Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Remove library added with link_libraries()

Tags:

cmake

How do I remove libraries added with link_libraries()?

Yes, I know I should use target_link_libraries(). I can`t because I must link a library to every future target. See this. The library is CMake built. This should be invisible to the C++/CMake developer. He should not have to worry about this lib. Example:

add_library(link-to-all a.cpp)
link_libraries(link-to-all)
add_executable(e1 e1.cpp) # with link-to-all
add_executable(e2 e2.cpp) # with link-to-all
unlink_libraries(link-to-all) #does not exist!
add_executable(e3 e3.cpp) # without link-to-all
# all further targets link without link-to-all!

In my case link-to-all is a library with implementation for coverage checking functions. It is enabled depending on a configuration option and should be implicitly used for all coming targets. Coverage analysis may be disabled for specific targets, so I want to be able to disable it.

The coverage is enabled by prepending CMAKE_<LANG>_COMPILE_OBJECT and disabled by removing the prefix. Afaik this cannot be done target specific, only global for coming targets. So unlink_libraries() would be a function that i can call symmetrically.

function(enable_coverage)
   prepend_compiler();
   link_libraries(cov);
   # alternative with loosing target information/dependency
   # prepend_system_libs(<path>/libcov.a)
endfunction()
function(disable_coverage)
   reset_compiler();
   unlink_libraries(cov);
   # reset_system_libs()
endfunction()

I could use CMAKE_<LANG>_STANDARD_LIBRARIES, (and also remove it there) but I would need the LOCATION of the library (generator expression: TARGET) in there. But I would also lose the interfaces of link-to-all. Also, that would probably remove the build dependencies.

like image 620
kuga Avatar asked Sep 12 '26 03:09

kuga


2 Answers

While I agree with @Guillaume, I'll combine the suggestions into an answer, as the linked answer is not very clear. As @Tsyvarev confirmed in the CMake source, the link_libraries() call sets the LINK_LIBRARIES target property; the target_link_libraries() call does the same. While your executable e3 will initially be set to link with all libraries, you can remove one (or multiple) libraries from the list using a combination of get_target_property() and set_property(). Here is an example to demonstrate how:

# Library to be linked to all targets.
add_library(link-to-all a.cpp)
# Library to be linked to (almost) all targets.
add_library(link-to-almost-all b.cpp)

link_libraries(link-to-all link-to-almost-all)
# Gets our link-everywhere libraries. Oops!
add_executable(e3 test.cpp)

# Get the LINK_LIBRARIES property for this target.
get_target_property(E3_LINKED_LIBS e3 LINK_LIBRARIES)
message("Libraries linked to e3: ${E3_LINKED_LIBS}")

# Remove one item from the list, and overwrite the previous LINK_LIBRARIES property for e3.
list(REMOVE_ITEM E3_LINKED_LIBS link-to-almost-all)
set_property(TARGET e3 PROPERTY LINK_LIBRARIES ${E3_LINKED_LIBS})

# Verify only one library is now linked.
get_target_property(E3_LINKED_LIBS_NEW e3 LINK_LIBRARIES)
message("Libraries linked to e3: ${E3_LINKED_LIBS_NEW}")

The messages printed here confirm the library was removed from the LINK_LIBRARIES target property for e3:

Libraries linked to e3: link-to-all;link-to-almost-all
Libraries linked to e3: link-to-all
like image 157
Kevin Avatar answered Sep 16 '26 22:09

Kevin


As an additonal answer I repeat what I commented on squarekittles answer (for future reference):

You should use the target property <LANG>_COMPILER_LAUNCHER instead of CMAKE_<LANG>_COMPILE_OBJECT. It can be set on target base.

like image 37
kuga Avatar answered Sep 16 '26 22:09

kuga



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!