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

Build fail at link stage: Linker can't find -ljack (libjack) #220

Open
terminator356 opened this issue Feb 7, 2025 · 14 comments
Open

Build fail at link stage: Linker can't find -ljack (libjack) #220

terminator356 opened this issue Feb 7, 2025 · 14 comments

Comments

@terminator356
Copy link

Hi. Hoping someone can help here.

[  0%] Linking CXX executable yoshimi
/usr/lib64/gcc/x86_64-suse-linux/14/../../../../x86_64-suse-linux/bin/ld : ne peut pas trouver -ljack : Aucun fichier ou dossier de ce nom
collect2: erreur: ld a retourné le statut de sortie 1
make[2]: *** [CMakeFiles/yoshimi.dir/build.make:1525: yoshimi] Error 1
make[1]: *** [CMakeFiles/Makefile2:112: CMakeFiles/yoshimi.dir/all] Error 2
make: *** [Makefile:136: all] Error 2

The linker says it can't find the jack library.
Here is the contents of build/CMakeFiles/yoshimi.dir/link.txt :

/usr/bin/c++ -march=native -mtune=native -Wall -O3 -rdynamic -Wl,--dependency-file=CMakeFiles/yoshimi.dir/link.d CMakeFiles/yoshimi.dir/Interface/InterChange.cpp.o CMakeFiles/yoshimi.dir/Interface/Data2Text.cpp.o CMakeFiles/yoshimi.dir/Interface/Text2Data.cpp.o CMakeFiles/yoshimi.dir/Interface/MidiLearn.cpp.o CMakeFiles/yoshimi.dir/Interface/MidiDecode.cpp.o CMakeFiles/yoshimi.dir/Interface/TextLists.cpp.o CMakeFiles/yoshimi.dir/CLI/CmdInterface.cpp.o CMakeFiles/yoshimi.dir/CLI/CmdInterpreter.cpp.o CMakeFiles/yoshimi.dir/Misc/CmdOptions.cpp.o CMakeFiles/yoshimi.dir/Misc/Config.cpp.o CMakeFiles/yoshimi.dir/Misc/SynthEngine.cpp.o CMakeFiles/yoshimi.dir/Misc/Bank.cpp.o CMakeFiles/yoshimi.dir/Misc/BuildScheduler.cpp.o CMakeFiles/yoshimi.dir/Misc/Microtonal.cpp.o CMakeFiles/yoshimi.dir/Misc/Part.cpp.o CMakeFiles/yoshimi.dir/Misc/Splash.cpp.o CMakeFiles/yoshimi.dir/Misc/WavFile.cpp.o CMakeFiles/yoshimi.dir/Misc/XMLwrapper.cpp.o CMakeFiles/yoshimi.dir/Params/ADnoteParameters.cpp.o CMakeFiles/yoshimi.dir/Params/EnvelopeParams.cpp.o CMakeFiles/yoshimi.dir/Params/FilterParams.cpp.o CMakeFiles/yoshimi.dir/Params/LFOParams.cpp.o CMakeFiles/yoshimi.dir/Params/SUBnoteParameters.cpp.o CMakeFiles/yoshimi.dir/Params/PADnoteParameters.cpp.o CMakeFiles/yoshimi.dir/Params/Controller.cpp.o CMakeFiles/yoshimi.dir/Params/ParamCheck.cpp.o CMakeFiles/yoshimi.dir/Params/UnifiedPresets.cpp.o CMakeFiles/yoshimi.dir/Params/OscilParameters.cpp.o CMakeFiles/yoshimi.dir/Synth/ADnote.cpp.o CMakeFiles/yoshimi.dir/Synth/Envelope.cpp.o CMakeFiles/yoshimi.dir/Synth/LFO.cpp.o CMakeFiles/yoshimi.dir/Synth/OscilGen.cpp.o CMakeFiles/yoshimi.dir/Synth/SUBnote.cpp.o CMakeFiles/yoshimi.dir/Synth/Resonance.cpp.o CMakeFiles/yoshimi.dir/Synth/PADnote.cpp.o CMakeFiles/yoshimi.dir/DSP/AnalogFilter.cpp.o CMakeFiles/yoshimi.dir/DSP/Filter.cpp.o CMakeFiles/yoshimi.dir/DSP/FormantFilter.cpp.o CMakeFiles/yoshimi.dir/DSP/SVFilter.cpp.o CMakeFiles/yoshimi.dir/DSP/Unison.cpp.o CMakeFiles/yoshimi.dir/Effects/Alienwah.cpp.o CMakeFiles/yoshimi.dir/Effects/Chorus.cpp.o CMakeFiles/yoshimi.dir/Effects/Echo.cpp.o CMakeFiles/yoshimi.dir/Effects/EffectLFO.cpp.o CMakeFiles/yoshimi.dir/Effects/EffectMgr.cpp.o CMakeFiles/yoshimi.dir/Effects/Effect.cpp.o CMakeFiles/yoshimi.dir/Effects/Phaser.cpp.o CMakeFiles/yoshimi.dir/Effects/Reverb.cpp.o CMakeFiles/yoshimi.dir/Effects/EQ.cpp.o CMakeFiles/yoshimi.dir/Effects/Distorsion.cpp.o CMakeFiles/yoshimi.dir/Effects/DynamicFilter.cpp.o CMakeFiles/yoshimi.dir/MusicIO/MusicClient.cpp.o CMakeFiles/yoshimi.dir/MusicIO/MusicIO.cpp.o CMakeFiles/yoshimi.dir/MusicIO/JackEngine.cpp.o CMakeFiles/yoshimi.dir/MusicIO/AlsaEngine.cpp.o CMakeFiles/yoshimi.dir/PresetsUI.cpp.o CMakeFiles/yoshimi.dir/EnvelopeUI.cpp.o CMakeFiles/yoshimi.dir/LFOUI.cpp.o CMakeFiles/yoshimi.dir/FilterUI.cpp.o CMakeFiles/yoshimi.dir/VirKeyboardUI.cpp.o CMakeFiles/yoshimi.dir/ConfigUI.cpp.o CMakeFiles/yoshimi.dir/SUBnoteUI.cpp.o CMakeFiles/yoshimi.dir/ResonanceUI.cpp.o CMakeFiles/yoshimi.dir/OscilGenUI.cpp.o CMakeFiles/yoshimi.dir/ADnoteUI.cpp.o CMakeFiles/yoshimi.dir/PADnoteUI.cpp.o CMakeFiles/yoshimi.dir/EffUI.cpp.o CMakeFiles/yoshimi.dir/BankUI.cpp.o CMakeFiles/yoshimi.dir/PartUI.cpp.o CMakeFiles/yoshimi.dir/MicrotonalUI.cpp.o CMakeFiles/yoshimi.dir/MasterUI.cpp.o CMakeFiles/yoshimi.dir/MasterMiscUI.cpp.o CMakeFiles/yoshimi.dir/ParametersUI.cpp.o CMakeFiles/yoshimi.dir/ConsoleUI.cpp.o CMakeFiles/yoshimi.dir/VectorUI.cpp.o CMakeFiles/yoshimi.dir/MidiLearnUI.cpp.o CMakeFiles/yoshimi.dir/UI/DynamicTooltip.cpp.o CMakeFiles/yoshimi.dir/UI/WidgetPDial.cpp.o CMakeFiles/yoshimi.dir/UI/WidgetCheckButton.cpp.o CMakeFiles/yoshimi.dir/UI/WidgetSpinner.cpp.o CMakeFiles/yoshimi.dir/UI/WidgetMWSlider.cpp.o CMakeFiles/yoshimi.dir/UI/YoshiWin.cpp.o CMakeFiles/yoshimi.dir/UI/MiscGui.cpp.o CMakeFiles/yoshimi.dir/main.cpp.o -o yoshimi -lfontconfig -lfreetype -lfltk_images -lfltk_forms -lfltk_gl -lfltk -lX11 -lXext -lm -lmxml -lasound -ljack -lfftw3f -lcairo -lncurses -lform -lreadline -lz -Wl,-Bstatic -ldl -Wl,-Bdynamic

Notice there are no "-L" linker directory options there.
Now for example here is part of MusE's link line.
My IDE is using ninja to build, so it looks different but it would be the same without ninja:

...
...
build muse/libmuse_core.so: CXX_SHARED_LIBRARY_LINKER__core_Debug muse/CMakeFiles/core.dir/moc_app.cpp.o muse/CMakeFiles/  DEP_FILE = muse/CMakeFiles/core.dir/link.d
  LANGUAGE_COMPILE_FLAGS = -Werror=format-security -Wextra -Winvalid-pch -fexceptions -Wall -fPIC -O0 -g -g -DQT_DEBUG -Werror
  LINK_FLAGS = -Wl,--dependency-file=muse/CMakeFiles/core.dir/link.d
  LINK_LIBRARIES = -Wl,-rpath,/home/me/muse_20231126/lib/muse-4.2/modules  al/libmuse_al.so  muse/arranger/libmuse_arranger.so  muse/cliplist/libmuse_cliplist.so  
...
...
 -latomic  -llash  -lasound  -llo  muse/libmuse_lv2host_module.so  -L/usr/lib64/pipewire-0.3/jack  -ljack  -lrtaudio  
muse/ctrl/libmuse_ctrl.so  libs/plugin/libmuse_plugin_rdf_module.so  libs/plugin/libmuse_plugin_list_module.so 
...
...

Notice the "-L" telling the linker where to find the jack library.

So then, by sheer coincidence, all of the libraries that Yoshimi wants to link to are found
in the default /usr/lib or /usr/lib64. So they don't need "-L" in the linker line.
Except for Jack.
The jack library is found in another directory. So "-L" is required.

And yet that is missing from the Yoshimi link.txt line.

So I'm trying to figure out why MusE would give different results.
We use the very same cmake lines that Yoshimi does to add the jack library to the target.
I can't seem to find anything else that would make that difference.
I could have sworn there were some kind of lines like "taget_add_library_directory" or something.
I must be missing something.
Maybe it's ninja?

The jack.pc packageconfig file is fine. It correctly points to the library and header and so on,
and is obviously working for MusE.

Thanks.
Tim.
The MusE Sequencer project.

@Ichthyostega
Copy link
Contributor

Ichthyostega commented Feb 7, 2025

Hi Tim,

as you've probably noticed, Yoshimi is using CMake. Not that anyone especially likes CMake, the build system just happened to be set up this way a long time ago. And on top of this comes that there is the old CMake way, the a-little-bit-more-modern way, and did I mention the modern CMake way?

The point to note from your MusE reference example is that seemingly you are using the Jack implementation or emulation provided by pipewire? The option -L/usr/lib64/pipewire-0.3/jack seems to imply that. And, as you've also pointed out correctly, the standard options like -ljack, which are issued by CMake do imply that a library can be located by the linker itself, either by looking into the search path built into the toolchain, or through the linker cache.

Regarding Jack, we do the following in the Yoshimi build system:

find_package (PkgConfig REQUIRED)
...
pkg_check_modules (JACK REQUIRED jack>=0.115.6)
...

include_directories (AFTER
...
    ${JACK_INCLUDE_DIRS}
...
)
set(ExternLibraries
...
    ${JACK_LIBRARIES}
...
)

add_executable (yoshimi ${ProgSources} main.cpp)

target_link_libraries (yoshimi ${ExternLibraries})

So in order to help tracking down the problem with your build we should look at the following steps

  • The PkgConfig macro of CMake will populate a set of variables with prefix JACK_XXX
  • you can find out what CMake has configured by looking into your CMakeCache.txt
  • please look up there what definitions were added for Jack
  • according to the CMake Documentation, especially relevant for your situation should be the variable JACK_LIBRARY_DIRS
  • on my system, this variable is empty, because I have a regular jack implementation installed from a debian package, and thus it can be found in the usual locations. If I understand correct, CMake would add a -L flag if this variable would contain a specific search patch
  • which of course brings us to the question what CMake actually gets as response from pkg-config
  • this means, you should look into your actual jack.pc file what is in there (and be sure this is actually the .pc file found by CMake...)

This all together should help us to spot the actual point where this whole chain of configuration passing somehow breaks

And, since I've mentioned »modern CMake«, there is — of course — a different, »modern« way of handling that, as can be seen in this Stackoverflow ☺☻☺

@terminator356
Copy link
Author

Inside CMakeCache.txt:

//Path to a library.
pkgcfg_lib_JACK_jack:FILEPATH=/usr/lib64/pipewire-0.3/jack/libjack.so

And:

JACK_CFLAGS:INTERNAL=-I/usr/include;-D_REENTRANT
JACK_CFLAGS_I:INTERNAL=
JACK_CFLAGS_OTHER:INTERNAL=-D_REENTRANT
JACK_FOUND:INTERNAL=1
JACK_INCLUDEDIR:INTERNAL=/usr/include
JACK_INCLUDE_DIRS:INTERNAL=/usr/include
JACK_LDFLAGS:INTERNAL=-L/usr/lib64/pipewire-0.3/jack;-ljack
JACK_LDFLAGS_OTHER:INTERNAL=
JACK_LIBDIR:INTERNAL=/usr/lib64
JACK_LIBRARIES:INTERNAL=jack
JACK_LIBRARY_DIRS:INTERNAL=/usr/lib64/pipewire-0.3/jack
JACK_LIBS:INTERNAL=
JACK_LIBS_L:INTERNAL=
JACK_LIBS_OTHER:INTERNAL=
JACK_LIBS_PATHS:INTERNAL=
JACK_MODULE_NAME:INTERNAL=jack
JACK_PREFIX:INTERNAL=/usr
JACK_STATIC_CFLAGS:INTERNAL=-I/usr/include;-D_REENTRANT
JACK_STATIC_CFLAGS_I:INTERNAL=
JACK_STATIC_CFLAGS_OTHER:INTERNAL=-D_REENTRANT
JACK_STATIC_INCLUDE_DIRS:INTERNAL=/usr/include
JACK_STATIC_LDFLAGS:INTERNAL=-L/usr/lib64/pipewire-0.3/jack;-ljack
JACK_STATIC_LDFLAGS_OTHER:INTERNAL=
JACK_STATIC_LIBDIR:INTERNAL=
JACK_STATIC_LIBRARIES:INTERNAL=jack
JACK_STATIC_LIBRARY_DIRS:INTERNAL=/usr/lib64/pipewire-0.3/jack
JACK_STATIC_LIBS:INTERNAL=
JACK_STATIC_LIBS_L:INTERNAL=
JACK_STATIC_LIBS_OTHER:INTERNAL=
JACK_STATIC_LIBS_PATHS:INTERNAL=
JACK_VERSION:INTERNAL=1.9.17
JACK_jack_INCLUDEDIR:INTERNAL=
JACK_jack_LIBDIR:INTERNAL=
JACK_jack_PREFIX:INTERNAL=
JACK_jack_VERSION:INTERNAL=

Inside jack.pc:

prefix=/usr
includedir=${prefix}/include
libdir=${prefix}/lib64

server_libs=-L${libdir} -ljackserver
jack_implementation=pipewire

Name: jack
Description: PipeWire JACK API
Version: 1.9.17
Libs: -L${prefix}/lib64/pipewire-0.3/jack -ljack
Cflags: -I${includedir} -D_REENTRANT

And in directory /usr/lib64/pipewire-0.3/jack there is indeed all the jack libraries.
libjack.so links to libjack.so.0 which links to libjack.so.0.3.1207

Strange.
The build system is supposed to pick up all this and fill in the -L but it's missing from Yoshimi.

There are no other jack.pc files found on the system.

MusE seems to have no trouble filling in all that info from the .pc file.
We've been using CMake for many years too.
Even previously before ninja came along things also built fine here as well.

@terminator356
Copy link
Author

Also here are the relevant lines from running ldconfig -p printout of the linker config cache.
All seems fine with here as well:

libjackserver.so.0 (libc6,x86-64) => /usr/lib64/pipewire-0.3/jack/libjackserver.so.0
libjackserver.so (libc6,x86-64) => /usr/lib64/pipewire-0.3/jack/libjackserver.so
libjacknet.so.0 (libc6,x86-64) => /usr/lib64/pipewire-0.3/jack/libjacknet.so.0
libjacknet.so (libc6,x86-64) => /usr/lib64/pipewire-0.3/jack/libjacknet.so
libjack.so.0 (libc6,x86-64) => /usr/lib64/pipewire-0.3/jack/libjack.so.0
libjack.so (libc6,x86-64) => /usr/lib64/pipewire-0.3/jack/libjack.so

@Ichthyostega
Copy link
Contributor

Ichthyostega commented Feb 7, 2025

Thanks.
Note especially that in your CMakeCache

JACK_LIBRARY_DIRS:INTERNAL=/usr/lib64/pipewire-0.3/jack

Thus our CMakeLists.txt is not properly set up to handle this case, since the necessary information was even picked up by CMake.

Maybe the Stackoverflow-answer I quoted above could give us a lead? I.e something like

target_link_libraries(yoshimi PUBLIC
        PkgConfig::JACK

We just recently upgraded the minimum CMake requirement to 3.12 (hope that is »modern« enough)

@Ichthyostega
Copy link
Contributor

what I am hinting at is that we're probably using one of that gazillion ways that at some time used to be "the way" how to use CMake....

Note especially that we're using ${JACK_LIBRARIES} in the statement set(ExternLibraries..., and your configuration from CMakeCache shows that this one is only defined to jack, which would translate into the -ljack flag allone — which seemingly is not enough to make it work in your situation.

@terminator356
Copy link
Author

For reference here are the relevant contents of MusE's CMakeCache.txt.
They are identical to Yoshimi's:

//Path to a library.
pkgcfg_lib_JACK_jack:FILEPATH=/usr/lib64/pipewire-0.3/jack/libjack.so
...
...
JACK_CFLAGS:INTERNAL=-I/usr/include;-D_REENTRANT
JACK_CFLAGS_I:INTERNAL=
JACK_CFLAGS_OTHER:INTERNAL=-D_REENTRANT
JACK_FOUND:INTERNAL=1
JACK_INCLUDEDIR:INTERNAL=/usr/include
JACK_INCLUDE_DIRS:INTERNAL=/usr/include
JACK_LDFLAGS:INTERNAL=-L/usr/lib64/pipewire-0.3/jack;-ljack
JACK_LDFLAGS_OTHER:INTERNAL=
JACK_LIBDIR:INTERNAL=/usr/lib64
JACK_LIBRARIES:INTERNAL=jack
JACK_LIBRARY_DIRS:INTERNAL=/usr/lib64/pipewire-0.3/jack
JACK_LIBS:INTERNAL=
JACK_LIBS_L:INTERNAL=
JACK_LIBS_OTHER:INTERNAL=
JACK_LIBS_PATHS:INTERNAL=
JACK_MODULE_NAME:INTERNAL=jack
JACK_PREFIX:INTERNAL=/usr
JACK_STATIC_CFLAGS:INTERNAL=-I/usr/include;-D_REENTRANT
JACK_STATIC_CFLAGS_I:INTERNAL=
JACK_STATIC_CFLAGS_OTHER:INTERNAL=-D_REENTRANT
JACK_STATIC_INCLUDE_DIRS:INTERNAL=/usr/include
JACK_STATIC_LDFLAGS:INTERNAL=-L/usr/lib64/pipewire-0.3/jack;-ljack
JACK_STATIC_LDFLAGS_OTHER:INTERNAL=
JACK_STATIC_LIBDIR:INTERNAL=
JACK_STATIC_LIBRARIES:INTERNAL=jack
JACK_STATIC_LIBRARY_DIRS:INTERNAL=/usr/lib64/pipewire-0.3/jack
JACK_STATIC_LIBS:INTERNAL=
JACK_STATIC_LIBS_L:INTERNAL=
JACK_STATIC_LIBS_OTHER:INTERNAL=
JACK_STATIC_LIBS_PATHS:INTERNAL=
JACK_VERSION:INTERNAL=1.9.17
JACK_jack_INCLUDEDIR:INTERNAL=
JACK_jack_LIBDIR:INTERNAL=
JACK_jack_PREFIX:INTERNAL=
JACK_jack_VERSION:INTERNAL=

@Ichthyostega
Copy link
Contributor

And? there is no difference, see that?

That's why I just stated that the problem is in Yoshimi's CMakeList.txt

@terminator356
Copy link
Author

I'm confused.
I get that the newer way might fix the issue here. I've not tried it yet but it should likely work.
My confusion comes from our cmake files:

PKG_CHECK_MODULES(JACK REQUIRED jack>=0.125.0)
include_directories(${JACK_INCLUDE_DIRS})

...

target_link_libraries ( driver
...
      ${JACK_LIBRARIES}
...
      )

So... Is MusE using the old way?
It looks identical to Yoshimi's.
What could be the difference?

I tried some of MusE's few cmake policies in Yoshimi. No luck.
One looked very promising:
CMP0003
It deals with this very subject of adding "-L" or not.
I expected setting the policy to OLD would have made it work.
But it did not work. Old or new. I wonder why. The build did acknowledge it with a message.
Still, no one wants to set a policy to OLD. CMP0003 OLD will be deprecated soon anyway, it said.
Ours sets it to NEW.

@abrolag
Copy link
Member

abrolag commented Feb 8, 2025 via email

@Stazed
Copy link

Stazed commented Feb 8, 2025

Hey, I seem to recall seeing this sort of issue with one of my projects, I think it was with Suse and pipewire as well.
Try using ${JACK_LINK_LIBRARIES} instead of ${JACK_LIBRARIES}.

@Ichthyostega
Copy link
Contributor

That's exactly why CMake is such an annoying mess. The original intention might have been honorable, but the design was inadequate from start. Which leads to a confusing plethora of ad-hoc fixes and amendments...

IMHO we should at least try to follow the currently recommended way, which seems to be what is shown in the Stackoverflow answer.

@abrolag
Copy link
Member

abrolag commented Feb 9, 2025 via email

@abrolag
Copy link
Member

abrolag commented Feb 9, 2025 via email

@abrolag
Copy link
Member

abrolag commented Feb 10, 2025 via email

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

4 participants