Search code examples
c++cmakecmakelists-optionscmake-language

Is it possible to get a list of linked libraries in CMake script as it will be pass to the linker?


I need to get a list of all linked libraries in form as they will be passed to the linker in my CMake script.

For example, in my CMake project file, I define the target, which represents the build of a dynamic library. I call the functions from another CMake file's to include in my target all necessary static libraries, and finally if I

set(CMAKE_VERBOSE_MAKEFILE ON)

I see the output something like this: "clang++ -o /path/to/program.p /path/to/library1.a /path/to/library2.a" and so on.

I need to get the string that will contain the list of all static libraries linked to my dynamic library in my CMake script. I tried to do that like:

get_target_property(l_libs2 ${target} LINK_LIBRARIES)
message("!!!LINK_LIBRARIES: ${l_libs2}")

But it contains the string in the format like a: "Library::Library1;Library::Library2". I tried to get the same information from the properties: INTERFACE_LINK_LIBRARIES, LDFLAGS, LIBS, LINK_FLAGS, LINK_WHAT_YOU_USE, LINK_OPTIONS,...

Is it possible in principle? How to CMake engine "build" this argument for the linker?

Why I need that:

I need to exclude export from all libraries except one. If I pass to the linker option

"-Wl,--exclude-libs,ALL" 

it leads to SEGFAULT when my dynamic library (python extension module) loads into python. I played with compiler flags and found that it happens because

"--exclude-libs,ALL" 

exclude export from "python.a" library. So if I set the exclusion list more precisely i.e.

"-Wl,--exclude-libs,library1.a -Wl,--exclude-libs,library2.a" 

and so on, i.e. all libraries except "python.a", the module load to python without any problem. So I decided to generate this compiler option dynamically to get the libraries list and then, process it with regex. The best way to solve that is if clang will have the opposite option to "--exclude-libs" for example "--exclude-libs-except" (or something like that) but unfortunately I do not find it in clang documentation.


Solution

  • Yes it is possible - I know of a way on how to get this once the files are generated, however I do not think it is possible (at least not in a straight forward way within the CMakeLists.txt file itself.).

    I was once debugging a link dependency issue and had to "figure out" what is being passed to the linker. This is what I did:

    • Generated build files through CMake via cmake -S. -Bbuild
    • Greped the build folder e.g. grep -Ri "[-]lmylibrary*" ./build

    The result was that only one specific file became of interest i.e.:

    ./build/CMakeFiles/target_name.dir/link.txt
    

    This one file will contain what is being fed to your linker/compiler.

    EDIT: I'll maybe also add that changing this file will truly affect the build. So if you want to make a "hack" to fix your issues you could always run a script on this file before building.

    However I do believe that CMake can handle your issues well if configured correctly. For example via set_target_properties