C++ CMake - 同一项目中的应用程序/库之间的依赖项(标头)

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11216408/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-27 14:57:19  来源:igfitidea点击:

CMake - dependencies (headers) between apps/libraries in same project

c++visual-studio-2010dependenciescmakeheader-files

提问by Ela782

I have the following project structure:

我有以下项目结构:

  • CMakeLists.txt
    • lib1/CMakeLists.txt and all cpp and header files of the lib
    • lib2/CMakeLists.txt and all cpp and header files of the lib
    • app/CMakeLists.txt and all cpp and header files of the app
  • CMakeLists.txt
    • lib1/CMakeLists.txt 和 lib 的所有 cpp 和头文件
    • lib2/CMakeLists.txt 和 lib 的所有 cpp 和头文件
    • app/CMakeLists.txt 以及应用程序的所有 cpp 和头文件

The main CMakeLists.txt looks like:

主要的 CMakeLists.txt 看起来像:

PROJECT( ${PROJECT_NAME} )
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)

The lib1/CMakeLists.txt looks eg like (stripped):

lib1/CMakeLists.txt 看起来像(剥离):

SET(SOURCE
file.cpp
)
SET(HEADERS
    some_lib_header.h
)
add_library( lib1 ${SOURCE} ${HEADERS} )

and the one for the app looks the same except of ADD_EXECUTABLE:

除了 ADD_EXECUTABLE 之外,应用程序的那个看起来是一样的:

SET(SOURCE
main.cpp
)
SET(HEADERS
    some_header.h
)
add_library( lib1 ${SOURCE} ${HEADERS} )
ADD_EXECUTABLE( app ${SOURCE} ${HEADERS} )

I found the setup working well this way because out of this, I can generate one Visual Studio solution file which contains all those three projects. But my problem is that my app includes header files of lib1 (and also of lib2, which depends on lib1). When I do

我发现该设置以这种方式运行良好,因为由此,我可以生成一个包含所有这三个项目的 Visual Studio 解决方案文件。但我的问题是我的应用程序包含 lib1(以及依赖于 lib1 的 lib2)的头文件。当我做

$mkdir build
$cd build
$cmake -C ..\myproject

it generates out-of-source VS .sln file as I want it, but the app doesn't compile because it can't find the header files of lib1 (obviously).

它根据我的需要生成源外 VS .sln 文件,但该应用程序无法编译,因为它找不到 lib1 的头文件(显然)。

Now I read and tried many things, like TARGET_LINK_LIBRARIES( app lib1 )(which got the app to link with the lib1, but not solve the header include issue), and things like add_subdirectory( ../lib1 )in various variants in the CMakeLists.txt of app (which all throwed errors that I couldn't fix), and also find_package (which I guess is the wrong approach).

现在我阅读并尝试了很多东西,比如TARGET_LINK_LIBRARIES( app lib1 )(它让应用程序与 lib1 链接,但没有解决标题包含问题),以及add_subdirectory( ../lib1 )应用程序的 CMakeLists.txt 中的各种变体(所有这些都抛出了我无法做到的错误) 't fix),还有 find_package (我猜这是错误的方法)。

So how can I solve this (I guess simple...) problem?

那么我该如何解决这个(我想很简单......)问题呢?

回答by Fraser

Here's one possible solution:

这是一种可能的解决方案:

Root CMakeLists.txt:

根 CMakeLists.txt:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(${PROJECT_NAME})
add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)


lib1/CMakeLists.txt:


lib1/CMakeLists.txt:

project(Lib1)
add_library(lib1 lib1.cpp lib1.h)


lib2/CMakeLists.txt:


lib2/CMakeLists.txt:

project(Lib2)
add_library(lib2 lib2.cpp lib2.h)

# Add /lib1 to #include search path
include_directories(${Lib1_SOURCE_DIR})
# Specify lib2's dependency on lib1
target_link_libraries(lib2 lib1)


app/CMakeLists.txt:


应用程序/CMakeLists.txt:

project(App)
add_executable(app main.cpp some_header.h)

# Add /lib1 and /lib2 to #include search path
include_directories(${Lib1_SOURCE_DIR} ${Lib2_SOURCE_DIR})
# Specify app's dependency on lib2.
# lib2's dependency on lib1 is automatically added.
target_link_libraries(app lib2)


There are plenty of different ways to achieve the same end result here. For a relatively small project, I'd probably just use a single CMakeLists.txt:


这里有很多不同的方法可以实现相同的最终结果。对于一个相对较小的项目,我可能只使用一个 CMakeLists.txt:

cmake_minimum_required(VERSION 2.8 FATAL_ERROR)
project(Test)

add_library(lib1 lib1/lib1.cpp lib1/lib1.h)
add_library(lib2 lib2/lib2.cpp lib2/lib2.h)
add_executable(app app/main.cpp app/some_header.h)

include_directories(${CMAKE_SOURCE_DIR}/lib1 ${CMAKE_SOURCE_DIR}/lib2)

target_link_libraries(lib2 lib1)
target_link_libraries(app lib2)


For further info on the relevant commands and their rationale, run:


有关相关命令及其原理的更多信息,请运行:

cmake --help-command add_subdirectory
cmake --help-command include_directories
cmake --help-command target_link_libraries

回答by Mizux

Project
 CMakeLists.txt
 \-lib1
   CMakeLists.txt
   \- include \ lib1
   \- src
 \-lib2
   CMakeLists.txt
   \- include \ lib2
   \- src
 \-app
   CMakeLists.txt
   \- src

Suppose dependencies as follow:

假设依赖如下:

lib1 ---> lib2 ---> app 
   \--------------> app

Something like this:

像这样的东西:

CMakeLists.txt:

CMakeLists.txt:

add_subdirectory(lib1)
add_subdirectory(lib2)
add_subdirectory(app)

lib1/CMakeLists.txt:

lib1/CMakeLists.txt:

  file(GLOB_RECURSE _HDRS "include/*.hpp")
  file(GLOB_RECURSE _SRCS "src/*.[hc]pp")
  add_library(lib1 ${_HDRS} ${_SRCS})
  #target_link_libraries(lib1)
  target_include_directories(lib1 PUBLIC include)

  install(TARGETS lib1 DESTINATION lib)
  install(FILES ${_HDRS} DESTINATION include/lib1)

lib2/CMakeLists.txt:

lib2/CMakeLists.txt:

  file(GLOB_RECURSE _HDRS "include/*.hpp")
  file(GLOB_RECURSE _SRCS "src/*.[hc]pp")
  add_library(lib2 ${_HDRS} ${_SRCS})
  target_link_libraries(lib2 lib1)
  target_include_directories(lib2 PUBLIC include)

  install(TARGETS lib2 DESTINATION lib)
  install(FILES ${_HDRS} DESTINATION include/lib2)

so in lib2/src/file.cpp you could do #include <lib1/header.hpp>

所以在 lib2/src/file.cpp 你可以做 #include <lib1/header.hpp>

app/CMakeLists.txt:

应用程序/CMakeLists.txt:

  file(GLOB_RECURSE _SRCS "src/*.[hc]pp")
  add_executable(app ${_SRCS})
  target_link_libraries(app lib1 lib2)

  install(TARGETS app DESTINATION bin)

so in app/src/file.cpp you could do #include <lib1/header.hpp>and #include <lib2/header.hpp>

所以在 app/src/file.cpp 你可以做#include <lib1/header.hpp>#include <lib2/header.hpp>

The magic is target_include_directorieswhich attach the "include" directory to the target, so when linking with it you pull the include directory also ;)

神奇的是target_include_directories将“include”目录附加到目标,所以当与它链接时,你也拉包含目录;)