JUCE program won't compile

Okay, so I have a problem:
I want to use CMake.
Now one could ask why.
Well, it’s as simple as that every other project/dependency etc. uses CMake so it only makes sense to try and use CMake for the JUCE part.

Now onto the tricky part:
The project does compile just fine with the auto generated files by the Projucer

(insert) dustvoice@dustvoice-VirtualBox:~/Projects/Development/CommuniCare_eV/CommuniCare_Manager/Builds/Linux$ make
Compiling AddComponent.cpp
Compiling AddEntryComponent.cpp
Compiling AddUserComponent.cpp
Compiling CustomTableListBox.cpp
Compiling ExpandArea.cpp
Compiling ExpandEntryArea.cpp
Compiling ExpandUserArea.cpp
Compiling Main.cpp
Compiling PostFunctions.cpp
Compiling BinaryData.cpp
Compiling include_juce_core.cpp
Compiling include_juce_data_structures.cpp
Compiling include_juce_events.cpp
Compiling include_juce_graphics.cpp
Compiling include_juce_gui_basics.cpp
Compiling include_juce_gui_extra.cpp
Compiling include_juce_opengl.cpp
Linking ComminuCare e.V. Manager - App

but not with my CMake file. I’m sure there is some easy solution (as it only seems to be a linker error) and I would be very glad if someone could help me with this.

Ok, so my general CMakeLists.txt can be found here.
(it is worth noting that currently nothing resides in the Libraries directory)

Now I am getting errors, when I try to compile it under MinGW-w64 (log), MSVC with Visual Studio 2019 (log) or g++ under Ubuntu (log).

For linux I discovered that in the auto-generated Makefile a call to pkg-config is made. So I ran

pkg-config --libs freetype2 x11 xext xinerama webkit2gtk-4.0 gtk+-x11-3.0 libcurl

(copied from the auto-generated Linux makefile)
and got

-lfreetype -lX11 -lXext -lXinerama -lwebkit2gtk-4.0 -lgtk-3 -lsoup-2.4 -ljavascriptcoregtk-4.0 -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lcurl

as an output. So I added

target_link_libraries(${PROJECT_NAME} "freetype" "webkit2gtk-4.0" "gtk-3" "soup-2.4" "javascriptcoregtk-4.0" "gtk-3" "gdk-3" "pangocairo-1.0" "pango-1.0" "atk-1.0" "cairo-gobject" "cairo" "gdk_pixbuf-2.0" "gio-2.0" "gobject-2.0" "glib-2.0" "curl")

to the end of my CMakeLists.txt.

At least I now got to the point where the only error reported (on Linux) was

[0/1] Re-running CMake...
-- Configuring done
-- Generating done
-- Build files have been written to: /home/dustvoice/Projects/Development/CommuniCare_eV/CommuniCare_Manager/Builds/Linux
[1/1] Linking CXX executable CommuniCare_eV_Manager
FAILED: CommuniCare_eV_Manager 
: && /usr/bin/c++  -std=c++14 -std=c++14   CMakeFiles/CommuniCare_eV_Manager.dir/JuceLibraryCode/BinaryData.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/JuceLibraryCode/include_juce_core.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/JuceLibraryCode/include_juce_data_structures.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/JuceLibraryCode/include_juce_events.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/JuceLibraryCode/include_juce_graphics.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/JuceLibraryCode/include_juce_gui_basics.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/JuceLibraryCode/include_juce_gui_extra.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/JuceLibraryCode/include_juce_opengl.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/Source/AddComponent.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/Source/AddEntryComponent.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/Source/AddUserComponent.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/Source/CustomTableListBox.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/Source/ExpandArea.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/Source/ExpandEntryArea.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/Source/ExpandUserArea.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/Source/Main.cpp.o CMakeFiles/CommuniCare_eV_Manager.dir/Source/PostFunctions.cpp.o  -o CommuniCare_eV_Manager  -lfreetype -lX11 -lXext -lXinerama -lwebkit2gtk-4.0 -lgtk-3 -lsoup-2.4 -ljavascriptcoregtk-4.0 -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lcurl -lsoup-2.4 -ljavascriptcoregtk-4.0 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0 -lcurl && :
/usr/bin/ld: CMakeFiles/CommuniCare_eV_Manager.dir/JuceLibraryCode/include_juce_core.cpp.o: undefined reference to symbol 'dlclose@@GLIBC_2.2.5'
/usr/bin/ld: /lib/x86_64-linux-gnu/libdl.so.2: error adding symbols: DSO missing from command line
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.

but googling for over 2h yielded no results unfortunately.
Also (understandably) running that modified CMakeLists.txt file under windows produced only hot garbo:

[...]
D:/MSYS2/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.2.1/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lfreetype
D:/MSYS2/mingw64/bin/../lib/gcc/x86_64-w64-mingw32/8.2.1/../../../../x86_64-w64-mingw32/bin/ld.exe: cannot find -lwebkit2gtk-4.0
[...]

I’m completely lost as to what I have to do. As these are ONLY linker error, it shouldn’t be too difficult to get this sh*t to compile, right?

Any quick help is really appreciated.
Maybe someone with insight on the Projucer auto-generation for the individual platforms could help me out.

Thanks in advance,
David

Introduction

This doesn’t sound like a problem to me :smiley:

I’m always happy to help with issues related to building (even if it’s not with CMake). Let’s see what went wrong for each platform that you tried.

MinGW-64

When compiling under MinGW-w64, you are getting a lot of linker errors because you need to link against the Windows libraries that are listed in the header file of each JUCE module as mingwLibs. For instance, in juce_core.h:

Projucer parses the header file for each module:


and then adds the libraries to the linker settings:

Here is how I add these libraries to PListMerger, a very simple command line helper executable of FRUT:

MSVC with Visual Studio 2019

From https://cmake.org/cmake/help/latest/command/add_executable.html:

If WIN32 is given the property WIN32_EXECUTABLE will be set on the target created. See documentation of that target property for details.

and from https://cmake.org/cmake/help/latest/prop_tgt/WIN32_EXECUTABLE.html:

When this property is set to true the executable when linked on Windows will be created with a WinMain() entry point instead of just main().

Projucer does that by setting the proper value for the “SubSystem”:


which results in /SUBSYSTEM:CONSOLE or /SUBSYSTEM:WINDOWS being passed to the linker.
See https://docs.microsoft.com/en-us/cpp/build/reference/subsystem-specify-subsystem?view=vs-2019 for more details.

g++ under Ubuntu

This is similar to MinGW-64, you need to link against the Linux libraries that are listed in the header files of each JUCE module as linuxLibs. The call to pkg-config only applies to linuxPackages.

Projucer extract both linuxLibs and linuxPackages here:


but they are not handled in the same way.

linuxLibs are directly passed to the linker:

linuxPackages are passed through pkg-config to both the compiler and the linker:

Since some of the linuxPackages depend on the linuxLibs, you ended-up with only a single error left. From https://linux.die.net/man/3/dlclose:

Link with -ldl.

Conclusion

I hope all of this will help you.

As you can see building JUCE using CMake is not straightforward. This is why I created FRUT.

Don’t hesitate to ask me any question (here or on PM) about CMake/FRUT/Projucer or anything else related to building JUCE projects.

5 Likes

That’s why I tried using FRUT and will still try to make it work. Just a quick question: is a jucer file mandatory for FRUT? If yes, why is that? As I saw, every setting available in the projucer is expected to be provided by the custom cmake macros. If no, why do I have to provide a jucer file to work with FRUT then. Is the script writing to the jucer file (which would be ideal for generating for example android files) or read it (why would I have to provide the options then?)? You have to understand that we want as little as possible overhead and we are trying to scout out the possibilities. Of course writing our own handling for the different platforms would indeed provide massive overhead compared to using some sort of a library, but right now it just seems as if one would have to use the Projucer AND FRUT which would of course be the opposite of what we want (simplifying and integrating JUCE parts using Cmake [only in the best case])

Uuhh. Hellooo. Thx for pointing that out. I’ll try just so we can check if this helps us in any way. The more options the better!

No, you can use FRUT without a .jucer file.

However, FRUT currently only provides Reprojucer.cmake, which (as its name suggests) tries to reproduce the behavior of Projucer. So having an existing .jucer project file makes things easier. You can use Jucer2Reprojucer to convert this .jucer file into a read-to-use CMakeLists.txt file.

If you don’t have a .jucer file, it will take you a bit more time to get started (since you won’t benefit from Jucer2Reprojucer), but you can look at the CMakeLists.txt files that are in the generated/ folder of FRUT for examples. And I’m always happy to help!

In the near future, FRUT will also provide FindJUCE.cmake, which will allow you to build JUCE projects in a “pure” CMake way (using find_package(JUCE REQUIRED COMPONENTS ...) and then using almost only standard CMake commands). But in the meantime, FRUT only has Reprojucer.cmake to offer.