问题
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