【问题标题】:CMake: Linking a static library from a subdirectory to an executable in another subdirectoryCMake:将静态库从子目录链接到另一个子目录中的可执行文件
【发布时间】:2017-02-16 06:27:45
【问题描述】:

我有一个项目同时使用我自己的代码和需要编译的外部代码。我的文件树如下。

PROJECT_ROOT
 |--CMakeLists.txt
 |--src
     |--CMakeLists.txt
     |--B1.cpp
     |--B1.h
     |--B2.cpp
     |--B2.h
     |
     |--ext
     |   |--CMakeLists.txt
     |   |--outside_module
     |   |   |--CMakeLists.txt
     |   |   |--A1.h
     |   |   |--A1.cpp
     |
     |--exe
         |--CMakeLists.txt
         |--runnerA.cpp
         |--runnerB.cpp

我在下面粘贴了我的 CMakeList.txt 文件的结构。我遇到的问题是我的runnerA 可执行文件给了我一堆未定义的对A1.h 和A1.cpp 中定义的符号的引用错误。但是,由于某种原因,当尝试链接到可执行文件 runnerA 时,CMake 无法找到我的库 A。

我包含了其余的代码,因为它编译得很好。我能够毫无问题地构建可执行文件runnerB。我推断runnerB 有效,因为源文件位于我的src 文件夹中,该文件夹是我的exe 文件夹的父文件夹,因此B 库范围包括exe。

如何让 CMake 知道在哪里可以找到我的 A 库,以便在将其链接到 src/exe 中的 runnerA 时可以找到它?


PROJECT_ROOT

cmake_minimum_required(VERSION 2.8)
project(MyProject)

add_subdirectory(src)

PROJECT_ROOT/src

find_package(Module REQUIRED)

# CREATE LIBRARIES
add_library(
    B
    B1.cpp B1.h
    B2.cpp B2.h
)

# GROUP LIBRARIES TOGETHER
set(
    B_LIBS
    B
    ${Module_LIBS}
)


# INCLUDE DIRECTORIES
set(
    B_INCLUDES
    .
    ${Module_INCLUDE_DIRS}
)

# ASSIGN INCLUDES TO LIBRARY
target_include_directories(
    B PUBLIC
    ${B_INCLUDES}
)


add_subdirectory(ext)
add_subdirectory(exe)

PROJECT_ROOT/src/ext

add_subdirectory(outside_module)

PROJECT_ROOT/src/ext/outside_module

find_package(Boost COMPONENTS
    filesystem
    system
    log
    thread
    REQUIRED)

# ADD DEFINITIONS
add_definitions(-DBOOST_LOG_DYN_LINK) # Necessary to compile A with log shared libraries (instead of static)

# DEFINE LIBRARY
add_library(
    A
    A1.cpp A2.h
)

# LINK LIBRARIES
set(
    A_LIBS
    A
    ${Boost_FILESYSTEM_LIBRARY}
    ${Boost_LOG_LIBRARY}
    ${Boost_SYSTEM_LIBRARY}
    ${Boost_THREAD_LIBRARY}
)

# INCLUDE DIRECTORIES
set(
    A_INCLUDES
    ${Boost_INCLUDE_DIRS}
)

PROJECT_ROOT/src/exe

# DEFINE EXECUTABLES
add_executable(runnerB runnerB.cpp)
add_executable(runnerA runnerA.cpp)


##################
# LINK LIBRARIES
##################
target_link_libraries(
    runnerB
    ${B_LIBS}
)

target_link_libraries(
    runnerA
    ${A_LIBS}
)

target_include_directories(
    runnerA PUBLIC
    ${A_INCLUDES}
)

# INSTALLATION
install(TARGETS runnerB DESTINATION bin/)
install(TARGETS runnerA DESTINATION bin/)

【问题讨论】:

  • 您需要将您的可执行文件链接到 A:target_link_libraries(runnerA A)。
  • @arrowd:我做到了。在PROJECT_ROOT/src/exe 部分的代码中输入错误。现已修复
  • @arrowd:另外,话虽如此,我真的认为这是一个范围问题。由于我的 CMake 命令适用于 runnerB
  • 反对者——怎么了?它不是重复的,并且已经有一个接受的答案

标签: c++ cmake


【解决方案1】:

对,你在嵌套的 CMakeLists.txt 中设置了 ${A_LIBS} 变量。解决方案是使用set() command 和PARENT_SCOPE 或CACHE 关键字。

【讨论】:

  • 当我需要“祖父母”范围时会发生什么?
  • 使用CACHE,这将在CMakeCache.txt中创建一个条目,因此您的变量将是全局的。
  • 在这种情况下也不要忘记FORCE!
  • CACHE 使它工作。这似乎是不好的做法,不是吗?有没有比通过 CMakeCache.txt 文件传递​​这些组更优雅的方法?
  • 不一定。所有这些FindFoo.cmake 模块实际上都在这样做。只是它们通常在同一个CMakeLists.txt 中调用,其中使用${FOO_LIBRARIES},但在内部它们只是设置缓存变量。也可以看看cmake.org/cmake/help/latest/command/mark_as_advanced.html。
猜你喜欢
  • 2021-10-22
  • 2022-12-21
  • 2015-07-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-09
  • 2019-06-04
  • 1970-01-01
相关资源
最近更新 更多