Search code examples
cmakecmake-custom-commandfind-package

CMake link library from find_package with system lib in wrong order


my CMakeLists.txt is as follows

find_pacakge(something)
add_executable(exe main.cc)
# libsomething depends on dlopen/dlsym... so I have to add dl here
target_link_libraries(run PRIVATE something::something dl)

results:

g++ -o exe -ldl path/to/libsomething.a
libsomething.c: undefined reference to `dlsym'

but CMake always put the -ldl flag before libsomething.a even I have tried:

target_link_libraries(run PRIVATE dl something::something dl something::something )

# produced output:
# g++ -o exe -ldl -ldl path/to/libsomething.a
# libsomething.c: undefined reference to `dlsym'

or

target_link_libraries(run PRIVATE dl)
target_link_libraries(run PRIVATE something::something)
target_link_libraries(run PRIVATE dl)

# produced output:
# g++ -o exe -ldl -ldl path/to/libsomething.a
# libsomething.c: undefined reference to `dlsym'

But the right way to build the program is

$ g++ -o exe path/to/libsomething.a -ldl

How can I resolve this issue?


Solution

  • Your comment

    # libsomething depends on dlopen/dlsym... so I have to add dl here

    reveals the core of the problem: It is libsomething needs linkage with dl, so its find_package(something) should care about that. The absence of that linkage is a deficiency (that is, a bug) in the library itself.

    If you are the author of the library, then fix it. If the author of the library accepts bugreports, then fill the one about given problem.

    If fixing the library is not an option for you, then you could "fix" result of find_package in your project:

    find_package(something)
    # Created imported target misses linkage with 'dl' library.
    # Add it here.
    target_link_libraries(something::something INTERFACE ${CMAKE_DL_LIBS})
    
    add_executable(exe main.cc)
    # Now we can use the library in a simple way
    target_link_libraries(exe PRIVATE something::something)
    

    The above code relies on the fact, that something::something, provided by find_package(something), is an IMPORTED target, denoting the library file. So we can add required linkage to it.