CMake:试图为未在此目录中构建的目标添加链接库

14

我在我的cmake项目中编译一些单元测试时遇到了问题。想法是将这些boost单元测试添加为可执行文件,以便我可以运行它们。无论如何,我得到了一个错误,我不太理解,它说我不能链接我的cpp单元测试,必须链接它们来测试我构建的库。我正在尝试链接和添加为可执行文件的两个单元测试是DownloadTickers.cpp和GetTickersForLetter.cpp。

我的目录结构如下:

> 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

Algo的CMakeLists.txt如下:

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)

CrawlTickers的CMakeLists.txt文件:

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}
)

测试的CMakeLists.txt为:

add_executable( DownloadTickers DownloadTickers.cpp )

add_executable( GetTickersForLetter GetTickersForLetter.cpp )

我的想法是cmake会自然地在CrawlTickers的CMakeLists.txt文件中注册DownloadTickers和GetTickersForLetter作为可执行文件,然后知道如何将其链接到目标,但我不知道为什么会出现这个错误。非常感谢任何帮助。谢谢。


3
target_link_libraries 的调用放在与 add_executable 相同的CMakeLists.txt文件中。 - Peter
@Peter - 为什么不把这个作为一个“答案”,这样我就可以投赞成票了?这个解决方案对我有用。 - jacknad
FWIW:https://gitlab.kitware.com/cmake/cmake/merge_requests/2370 - Nehal J Wani
2个回答

11

target_link_libraries指令需要与add_executable指令在同一个CMakeLists.txt文件中。对于库也是如此。可以把每个目录和对应的CMakeLists.txt看作是子项目。

正如评论中指出的,CMake 3.13现在允许所需的行为。


我遇到了这个问题,但是它出现在一个自定义的 .cmake 脚本中定义的函数中... 有什么解决方法吗?我试图为传递的目标附加覆盖标志... - helmesjo
@helmesjo 这听起来像是一个不同的问题。要不你提一个新的问题? - Peter
相同的错误信息,但是将其作为一个单独的问题可能是可取的。无论如何,谢谢! - helmesjo
CMake 3.13及以上版本默认情况下已禁用此策略 - Kevin

0
相关政策(CMP0079)已经在评论中提到,但我认为实际解决方案需要明确说明。使用CMake 3.13及以上版本,您需要将以下行添加到顶层的CMakeLists.txt文件中:
if(POLICY CMP0079 )
  cmake_policy(SET CMP0079 NEW)
endif()

这允许在其他目录中定义的目标中使用target_link_libraries()

您也可以增加CMake的最小版本:

cmake_minimum_required (VERSION 3.13)

但这将改变许多政策(从 CPM0024 到 CMP0081 的所有内容)为 NEW,这可能不适用于现有项目。


你确定如果你使用CMake 3.13+,你需要明确地设置它吗?我以为一旦定义了策略,NEW就是默认值。 - starball
@starball,只有当你的项目声称与使用cmake_minimum_required声明的新版本CMake兼容时,NEW才是默认值。否则,在CMake最终移除该策略之前,OLD将是默认值,届时只有NEW行为可用。 - Dmitry Grigoryev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接