14

I'm having a an issue compiling some unit tests in my cmake project. The idea is to add these boost unit tests as executables, so that I can then run them. Anyway I'm getting this error that I don't quit understand, which is saying that I cannot link my cpp unit tests which must be linked to test the library I built. The two unit tests I'm trying to link and add as executables are, DownloadTickers.cpp and GetTickersForLetter.cpp.

My directory structure is as follows:

> Algo
  > build (this is where I do: cmake .. which gives me errors)
  -CMakeLists.txt (top level cmake)
  -algo.h.ini
  -run.cpp
  > NetworkModule
   > CrawlTickers
    -CMakeLists.txt
    -CrawlTickers.cpp
    -CrawlTickers.hpp
    > tests
     -CMakeLists.txt
     -DownloadTickers.cpp
     -GetTickersForLetter.cpp

The CMakeLists.txt for Algo is:

cmake_minimum_required (VERSION 2.8)
project (Algo)

set (Algo_VERSION_MAJOR 0)
set (Algo_VERSION_MINOR 1)
set (CMAKE_CXX_COMPILER g++-4.8)
set (CMAKE_BUILD_TYPE Release)

add_definitions(
  -std=c++11
)

configure_file(
  "${PROJECT_SOURCE_DIR}/algo.h.in"
  "${PROJECT_BINARY_DIR}/algo.h"
)

include_directories("${PROJECT_BINARY_DIR}")

add_subdirectory(NetworkModule/CrawlTickers)

add_executable(Run run.cpp)

The CMakeLists.txt for CrawlTickers is:

find_package(Boost COMPONENTS system filesystem unit_test_framework REQUIRED)

add_library(CrawlTickers SHARED CrawlTickers.cpp)

add_subdirectory(tests)

target_link_libraries(
  CrawlTickers
  cpprest
)

target_link_libraries(
  DownloadTickers
  CrawlTickers
  ${Boost_FILESYSTEM_LIBRARY}
  ${Boost_SYSTEM_LIBRARY}
  ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
)

target_link_libraries(
  GetTickersForLetter
  CrawlTickers
  ${Boost_FILESYSTEM_LIBRARY}
  ${Boost_SYSTEM_LIBRARY}
  ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY}
)

The CMakeLists.txt for tests is:

add_executable( DownloadTickers DownloadTickers.cpp )

add_executable( GetTickersForLetter GetTickersForLetter.cpp )

My thinking is that cmake would naturally register DownloadTickers and GetTickersForLetter as executables in the CrawlTickers CMakeLists.txt and then know how to link it to the target, but I have no idea why I'm getting this error. Any help is greatly appreciated. Thanks.

Dr.Knowitall
  • 10,080
  • 23
  • 82
  • 133

2 Answers2

11

The target_link_libraries directive needs to be part of the same CMakeLists.txt as the add_executable directive. This also applies to libraries. Think of each directory and associated CMakeLists.txt as a subproject.

As pointed out in the comments, CMake 3.13 now allows the requested behavior.

Peter
  • 14,559
  • 35
  • 55
  • I got this issue but in a function defined in a custom .cmake-script... Any workaround? Trying to append coverage-flags for a target passed in as argument... – helmesjo Jun 25 '17 at 19:10
  • @helmesjo That sounds like a different question. Ask a new one? – Peter Jun 26 '17 at 01:23
  • Same error message but yes, it might be desirable to have it as a separate question. Thanks anyways! – helmesjo Jun 26 '17 at 05:52
  • This [policy](https://cmake.org/cmake/help/latest/policy/CMP0079.html#policy:CMP0079) is now disabled by default in CMake 3.13 and greater. – Kevin Jun 09 '20 at 13:35
0

The relevant policy (CMP0079) was already mentioned in the comments, but I suppose the actual solution need to be clearly stated. With CMake 3.13 and above you need to add the following line to your top-level CMakeLists.txt:

if(POLICY CMP0079 )
  cmake_policy(SET CMP0079 NEW)
endif()

This allows the use of target_link_libraries() with targets defined in other directories.

You could also increase the CMake minimum version instead:

cmake_minimum_required (VERSION 3.13)

But that will change a whole bunch of policies (essentially, everything from CPM0024 to CMP0081) to NEW which may not be desirable for existing projects.

Dmitry Grigoryev
  • 3,156
  • 1
  • 25
  • 53
  • are you sure you need to explcitly set it if you have CMake 3.13+? I thought `NEW` is the default for policies once they are defined? – starball Jul 08 '23 at 07:43
  • @starball, `NEW` is the default only if your project claims to be compatible with the new version of CMake using `cmake_minimum_required`. Otherwise `OLD` is the default until the policy is eventually removed from CMake, at which point only `NEW` behavior is available. – Dmitry Grigoryev Jul 17 '23 at 13:01