CMake - Only link a library to an executable if it is needed

不羁岁月 提交于 2019-12-26 03:53:04

问题


I have a project that includes several source files, and I am using the GoogleTest library to create unit tests for some of these source files. The tests are all separate .cpp files and each includes the header of the respective source file to be tested.

I want to create a separate executable for each unit test. To do this I have a loop that creates an executable for each member in a test_sources list, and names it according to a test_names list.

The problem is that a couple of my unit tests require another 3rd party library. This library is defined inside the ${${PROJECT_NAME}_EXTERNAL_LIBRARIES}) list. I have tried to link this to my text executables, but I get the error:

Error: No rule to make target 'PocoNetExternal/Foundation/libPocoFoundationd.so', needed by 'StringExTest'.  Stop.

This is because StringExTest is one of the tests that does not need the POCO library. If I remove the link to POCO, I get an undefined reference error for the executable that does need POCO. Interestingly if I put the link back in and build again everything compiles and runs fine and without error. Unfortunately, this is not good enough as I need it to work the first time so it works on our continuous integration server.

Here is the code that links Gtest and Poco to the executables. How can I change this so it only links POCO if it is needed? This code also needs to be reusable without modification if other tests are added or removed.

##########################################################################
##### Loop over all the .cpp files and create separate executables

list(LENGTH test_sources len1)              #len1 is length of test_sources list
math(EXPR len2 "${len1} - 1")               #len2 is len1 - 1

foreach(val RANGE ${len2})              #for val = 0 to len2
  list(GET test_names ${val} name)          #name will change on every loop
  list(GET test_sources ${val} src)         #list(GET <list> <element index> <output variable>)
  add_executable("${name}" "${src}" "${test_files}")    #add_executable(<name> source1 [source2 ...])
endforeach()

##########################################################################
###### Link the libraries

makeLibPathsAbsolute()

foreach(val RANGE ${len2})                          #for val = 0 to len2
    list(GET test_names ${val} name)                    #name will change on every loop
    target_link_libraries(${name} gtest_main)               #link gtest libraries
    message(STATUS "LINKING: ${external_libraries_abs} to ${name}\n")
    target_link_libraries(${name} ${external_libraries_abs})    #link all other libraies (give the absolute path path)
endforeach()

回答1:


Pass full path to target_link_libraries(). You can make paths in ${PROJECT_NAME}_EXTERNAL_LIBRARIES absolute by using get_filename_component() with ABSOLUTE arg.



来源:https://stackoverflow.com/questions/46040574/cmake-only-link-a-library-to-an-executable-if-it-is-needed

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!