jwezorek
jwezorek

Reputation: 9525

How do you tell CMake to statically link to a library in a package found with find_package?

I am building a library from source and an executable that depends on the library. The library depends on a third-party library, libjpeg, which I would like to handle via static linking. libjpeg is installed on my system. I can see the .a file at /usr/lib/x86_64-linux-gnu/libjpeg.a(I am building on Ubuntu.)

When processing my library's CMakeLists.txt file, CMake successfully finds libjpeg but its output announces that is has found the dynamic version of libjpeg i.e. the output from CMake is

-- Found JPEG: /usr/lib/x86_64-linux-gnu/libjpeg.so (found version "80")

then later in the CMakeLists.txt I link my library to libjpeg via

target_link_libraries( my_library
    PRIVATE JPEG
)

and building is succesful. However when I then link to my_library from my_executable I get the following error:

[100%] Linking CXX executable my_executable
/usr/bin/ld: cannot find -lJPEG
collect2: error: ld returned 1 exit status

which I take to mean that the problem is that since my_library is linking to libjpeg dynamically I would need to target_link_libraries to libjpeg from the executable rather than the library. In any case what I want to do is completely hide my_library's dependency on libjpeg.

Is there some way to tell find_package to prefer static libraries?

Upvotes: 0

Views: 2994

Answers (2)

Artefacto
Artefacto

Reputation: 97805

You can indicate the name:

find_library(JPEGLIB REQUIRED NAMES libjpeg.a)
add_executable(myapp myapp.c)
target_link_libraries(myapp PRIVATE ${JPEGLIB})

Each library name given to the NAMES option is first considered as a library file name and then considered with platform-specific prefixes (e.g. lib) and suffixes (e.g. .so). Therefore one may specify library file names such as libfoo.a directly. This can be used to locate static libraries on UNIX-like systems.

Upvotes: 0

spectras
spectras

Reputation: 13542

Before anything, you should fix your script:

target_link_libraries(my_library PRIVATE JPEG::JPEG)

You have to give the imported target name to target_link_libraries.

That being said, no, not directly. find_package itself does nothing of the sort, it simply looks for the correct script and calls it. Thus the actual behavior is library-specific. For libjpeg, probably it finds a copy of this script and runs it.

For libjpeg in particular, FindJPEG.cmake provides no way to tell it to prefer static or dynamic version.

However, you can define JPEG_LIBRARY_RELEASE before calling find_package, to force it to find a specific version. For instance, if you do:

cmake -DJPEG_LIBRARY_RELEASE=/usr/lib/x86_64-linux-gnu/libjpeg.a .....

Then you should get a static build (replace with JPEG_LIBRARY_DEBUG to define the debug version). You can do the same with pretty much any detected thing where you want to force the detection of something else, as most script will not overwrite values defined on the command line.

If that suits your workflow, perfect. Otherwise, you won't have a clean solution with CMake alone, and you should add a dependency manager on top of that (vcpkg, conan.io).

Upvotes: 2

Related Questions