Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Codeblocks generation error #463

Closed
ovenpasta opened this issue Feb 14, 2019 · 9 comments
Closed

Codeblocks generation error #463

ovenpasta opened this issue Feb 14, 2019 · 9 comments

Comments

@ovenpasta
Copy link

Hi, having problems with clion... but also with others...

clion-2018.3.4/bin/cmake/linux/bin/cmake -DCMAKE_BUILD_TYPE=Debug -G "CodeBlocks - Unix Makefiles" /home/aldo/prova1/Projucer
CMake Error at /home/aldo/FRUT/cmake/Reprojucer.cmake:1540 (message):
  You must call jucer_export_target("Code::Blocks (Linux)") before calling
  jucer_project_end().
Call Stack (most recent call first):
  CMakeLists.txt:742 (jucer_project_end)

Where did the string "Code::Blocks (Linux)" came from?

here is the official string for the generators:
https://cmake.org/cmake/help/latest/generator/CodeBlocks.html#codeblocks

I saw that the code in Reprojucer.cmake improperly uses that string to check for the generator
but it should be "CodeBlocks - Unix Makefiles"...

I've even succeded cross compiling to mingw64 using mxe cmake toolchain with some hacks to the Reprojucer.cmake script. Much painful!

@McMartin
Copy link
Owner

McMartin commented Feb 14, 2019

Hi @ovenpasta,

Thanks for giving a try to FRUT!


Where did the string "Code::Blocks (Linux)" came from?

Code::Blocks (Linux) is one of the Projucer export targets (also called "exporters") that Reprojucer.cmake supports. Reprojucer.cmake supports two of these export targets on Linux: Linux Makefile and Code::Blocks (Linux).


I saw that the code in Reprojucer.cmake improperly uses that string to check for the generator
but it should be "CodeBlocks - Unix Makefiles"...

I think you misunderstood what Reprojucer.cmake is doing. Let's consider the following .jucer project file (created with Projucer 5.4.2):

<?xml version="1.0" encoding="UTF-8"?>

<JUCERPROJECT id="HgTYRQ" name="LinuxOnlyApp" projectType="consoleapp" jucerVersion="5.4.2">
  <MAINGROUP id="xkAArJ" name="LinuxOnlyApp">
    <GROUP id="{9B88DEC0-3AE7-1B81-3370-F41E4B94E9A3}" name="Source">
      <FILE id="fLvRxG" name="Main.cpp" compile="1" resource="0" file="Source/Main.cpp"/>
    </GROUP>
  </MAINGROUP>
  <EXPORTFORMATS>
    <LINUX_MAKE targetFolder="Builds/LinuxMakefile" extraDefs="BUILD_WITH_MAKE=1">
      <CONFIGURATIONS>
        <CONFIGURATION isDebug="1" name="Debug"/>
        <CONFIGURATION isDebug="0" name="Release"/>
      </CONFIGURATIONS>
      <MODULEPATHS/>
    </LINUX_MAKE>
    <CODEBLOCKS_LINUX targetFolder="Builds/CodeBlocksLinux" extraDefs="BUILD_WITH_CODEBLOCKS=1">
      <CONFIGURATIONS>
        <CONFIGURATION isDebug="1" name="Debug"/>
        <CONFIGURATION isDebug="0" name="Release"/>
      </CONFIGURATIONS>
      <MODULEPATHS/>
    </CODEBLOCKS_LINUX>
  </EXPORTFORMATS>
  <MODULES/>
  <LIVE_SETTINGS>
    <WINDOWS/>
  </LIVE_SETTINGS>
  <JUCEOPTIONS JUCE_STRICT_REFCOUNTEDPOINTER="1"/>
</JUCERPROJECT>

When we use Jucer2Reprojucer to convert this .jucer project into a CMakeLists.txt file, we get:

# This file was generated by Jucer2Reprojucer from "LinuxOnlyApp.jucer"

cmake_minimum_required(VERSION 3.4)

project("LinuxOnlyApp")


list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}/../../FRUT/cmake")
include(Reprojucer)


set(LinuxOnlyApp_jucer_FILE
  "${CMAKE_CURRENT_LIST_DIR}/LinuxOnlyApp.jucer"
)


jucer_project_begin(
  JUCER_VERSION "5.4.2"
  PROJECT_FILE "${LinuxOnlyApp_jucer_FILE}"
  PROJECT_ID "HgTYRQ"
)

jucer_project_settings(
  PROJECT_NAME "LinuxOnlyApp"
  PROJECT_VERSION "1.0.0"
  PROJECT_TYPE "Console Application"
  BUNDLE_IDENTIFIER "com.yourcompany.LinuxOnlyApp"
  CXX_LANGUAGE_STANDARD "C++14"
)

jucer_project_files("LinuxOnlyApp/Source"
# Compile   Xcode     Binary
#           Resource  Resource
  x         .         .         "Source/Main.cpp"
)

jucer_export_target(
  "Linux Makefile"
  EXTRA_PREPROCESSOR_DEFINITIONS
    "BUILD_WITH_MAKE=1"
)

jucer_export_target_configuration(
  "Linux Makefile"
  NAME "Debug"
  DEBUG_MODE ON
)

jucer_export_target_configuration(
  "Linux Makefile"
  NAME "Release"
  DEBUG_MODE OFF
)

jucer_export_target(
  "Code::Blocks (Linux)"
  EXTRA_PREPROCESSOR_DEFINITIONS
    "BUILD_WITH_CODEBLOCKS=1"
)

jucer_export_target_configuration(
  "Code::Blocks (Linux)"
  NAME "Debug"
  DEBUG_MODE ON
  ARCHITECTURE "64-bit (-m64)"
)

jucer_export_target_configuration(
  "Code::Blocks (Linux)"
  NAME "Release"
  DEBUG_MODE OFF
  ARCHITECTURE "64-bit (-m64)"
)

jucer_project_end()

Now, depending on the CMake generator (more precisely, the value of CMAKE_EXTRA_GENERATOR), Reprojucer.cmake will either consider the settings for the "Linux Makefile" export target or for the "Code::Blocks (Linux)" one. In your case, you are using the CodeBlocks - Unix Makefiles CMake generator, which sets CMAKE_EXTRA_GENERATOR to CodeBlocks, so Reprojucer.cmake only considers the settings for the "Code::Blocks (Linux)" export target. If your CMakeLists.txt file doesn't call jucer_export_target("Code::Blocks (Linux)" ...), then Reprojucer.cmake aborts.


I've even succeded cross compiling to mingw64 using mxe cmake toolchain with some hacks to the Reprojucer.cmake script. Much painful!

Reprojucer.cmake is meant, as its name suggests, to reproduce what Projucer does. It is not meant to be a generic CMake script that can handle any use cases. I guess you would be more interested in a FindJUCE.cmake module, that would allow you to do:

find_package(JUCE COMPONENTS juce_audio_utils)
add_executable(AudioPlayer ...)
target_link_libraries(AudioPlayer PRIVATE
  JUCE::juce_audio_basics::sources
  JUCE::juce_audio_devices::sources
  JUCE::juce_audio_formats::sources
  JUCE::juce_audio_processors::sources
  JUCE::juce_audio_utils::sources
  JUCE::juce_core::sources
  JUCE::juce_data_structures::sources
  JUCE::juce_events::sources
  JUCE::juce_graphics::sources
  JUCE::juce_gui_basics::sources
  JUCE::juce_gui_extra::sources
)

I am currently working on such a FindJUCE.cmake module, but it's not an easy task and it will take me quite some time until I can merge something like this in FRUT.

@McMartin
Copy link
Owner

McMartin commented Mar 1, 2020

(After more than a year, here is a better answer, which also closes this issue)

Since Reprojucer supports both "Linux Makefile" and "Code::Blocks (Linux)" exporters from Projucer, it needs to choose between the 2 when running on Linux. It roughly does:

if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux")
  if(CMAKE_EXTRA_GENERATOR STREQUAL "CodeBlocks")  # true when calling `cmake -G "CodeBlocks - *"`
    set(exporter "Code::Blocks (Linux)")
  else()
    set(exporter "Linux Makefile")
  endif()
endif()

The default CMake generator on Linux is Unix Makefiles, but CLion calls cmake -G "CodeBlocks - Unix Makefiles". To force the usage of the "Linux Makefile" exporter, you need to make CLion use another CMake generator (by adding -G "<generator-of-your-choice>" to the "CMake options" setting of CLion).

Upgrading to CLion 2019.3 might also solve the problem. See https://blog.jetbrains.com/clion/2019/10/clion-2019-3-eap-ninja-cmake-generators/ for more details.

@eyalamirmusic
Copy link

just to keep consistency, as mentioned in another thread, updating CLion does not solve the problem fully (not even using 2020.1 EAP, which I also have installed).

Even though CLion does support other exporters in terms of loading the project and building the targets, it doesn't know how to correctly do code parsing/refactoring with those exports, and debugger support is also not complete.

So even though this is a CLion-related bug, it could be fixed for all IDEs in present or future by not associating build instructions for a particular OS (Mac, iOS, Linux) with a generator/IDE - that 'coupling' was one of my main reasons to get away from the Projucer.

@McMartin
Copy link
Owner

McMartin commented Mar 1, 2020

If a project does both jucer_export_target("Linux Makefile" ...) and jucer_export_target("Code::Blocks (Linux)" ...), Reprojucer needs a way to decide where to get the settings from when building on Linux. Currently it checks whether CMAKE_EXTRA_GENERATOR STREQUAL "CodeBlocks", because that's what makes the most sense.

If you have a better solution to decide between the "Linux Makefile" and "Code::Blocks (Linux)" exporters, then please let me know, I'll be very happy to implement it right away.

@eyalamirmusic
Copy link

Definitely, if you decouple the step of setting linux-related variables into the targets from the part where you parse the projucer project, you can make it work regardless of which default target you choose for Linux, and even make it work manually if no such target exist.

Pseudo code:

#can be called by user, or at the point of configuring from JUCER file
macro set_linux_variables(...)
endmacro()

#Jucer file parsing:
if (CODE_BLOCKS)
    set_linux_variables(...)
else if(LINUX_MAKEFILE)
    set_linux_variables(...)
endif()

#Later, not worrying about particular generators at all, we can configure the targets:
if(LINUX)
    configure_from_predefined_linux_variables(...)
endif()

@McMartin
Copy link
Owner

McMartin commented Mar 1, 2020

This will be super confusing for people who are expecting Reprojucer to reproduce Projucer.

Imagine I have a project that only supports the "Code::Blocks (Linux)" exporter and that does:

jucer_export_target(
  "Code::Blocks (Linux)"
  EXTRA_PREPROCESSOR_DEFINITIONS
    "ENABLE_SECRET_FEATURE=1"
)

and I run cmake -G "Unix Makefiles" on Linux.

With your solution, Reprojucer will not complain about this project not supporting the "Linux Makefile" exporter and this will lead to my project building but without ENABLE_SECRET_FEATURE=1 defined. Then I'll spend hours and days figuring out why my app doesn't work as I expect.

@eyalamirmusic
Copy link

I think you misunderstood my intention, no current behaviour should be changed for people using FRUT on projucer project.

The actual logic of picking which target to draw from just needs to happen before adding the cmake targets. No need to add secret features or anything like that.

The logic should like that, roughly:

  1. Parse Projucer project.
    If the currently used generator can help us with defining a template (such as Linux Makefiles) - great.
    If it can't, we fall back to some default template of your choosing.

  2. Create CMake target - that part knows nothing about projucer exports, and can be configured even if a projucer file never existed.

@eyalamirmusic
Copy link

Just to be clear, if your projucer project didn't have any linux targets at all, those variables will never be filled and a target won't be added at all, which is how I'd expect it to work (you can show a message about that... but not fail since it's possible having no linux targets for some sub project is the desired behavior.

@McMartin
Copy link
Owner

McMartin commented Mar 1, 2020

The actual logic of picking which target to draw from just needs to happen before adding the cmake targets.

"You need to choose what to add before adding it". Seems a bit tautological, but makes sense. Unless you are using "target" to mean two different things and then I don't know what you actually mean.

Parse Projucer project.

Reprojucer doesn't do that.

we fall back to some default template of your choosing.

Whose choosing? Where is it defined? How can users of Reprojucer know about that?

if your projucer project didn't have any linux targets at all, those variables will never be filled and a target won't be added at all

This contradicts with the peudo code you wrote in #463 (comment), which would always add a target on Linux. This makes it hard for me to understand what you want.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants