如何在构建可执行文件时自动编译CMake中的链接库?



我有几个项目(git repos),每个项目都依赖于一些库(也是git repos)。每个项目只有一个目标可执行文件,并链接来自其他repos的库。

文件结构:

├── libraries
│   ├── libraryX (git:master)
│   │   ├── build
│   │   │   └── libX.so
│   │   ├── CMakeLists.txt
│   │   ├── fileX.cpp
│   │   └── fileX.h
│   ├── libraryY (git:master)
│   │   ├── build
│   │   │   └── libY.so
│   │   ├── CMakeLists.txt
│   │   ├── fileY.cpp
│   │   └── fileY.h
│   └── libraryZ (git:master)
│       ├── build
│       │   └── libZ.so
│       ├── CMakeLists.txt
│       ├── fileZ.cpp
│       └── fileZ.h
└── projects
├── projectA (git:master)
│   ├── build
│   │   └── outA
│   ├── CMakeLists.txt
│   └── mainA.cpp
└── projectB (git:master)
├── build
│   └── outB
├── CMakeLists.txt
└── mainB.cpp

这是libraryXCMakeLists.txt文件的示例:

cmake_minimum_required(VERSION 3.6)
project(libraryX LANGUAGES CXX)
set(libraries $ENV{LIBRARIES})
set(projects $ENV{PROJECTS})
add_library(libX SHARED fileX.cpp)
target_include_directories(libX PUBLIC ${libraries}/libraryX/)

目前我正在手动构建每个库,生成*.so文件,然后我去项目并构建可执行文件。这是projectA内部的CMakeLists.txt示例:

cmake_minimum_required(VERSION 3.6)
project(projectA LANGUAGES CXX)
set(libraries $ENV{LIBRARIES})
set(projects $ENV{PROJECTS})
add_executable(outA mainA.cpp)
target_include_directories(outA
PUBLIC
${libraries}/libraryX/
${libraries}/libraryY/
${libraries}/libraryZ/
${projects}/projectA/
)
target_link_libraries(outA
${libraries}/libraryX/build/libX.so
${libraries}/libraryY/build/libY.so
${libraries}/libraryZ/build/libZ.so
)

我只对一次构建/运行一个项目(例如projectA/)感兴趣,但是我不想每次都手动预编译每个库我做改变。

另外,我不能在项目下移动libraries/(例如projectA/libraries/libraryX),因为projectB/也依赖于它们,我不喜欢在兄弟文件夹中的一台计算机中有相同存储库的两个克隆。我也不能更改和重新安排存储库的内容以适应自己的需要,因为不同的团队正在开发它们,并计划在将来将它们作为完整的包发布,可从apt-get安装。最后,我不想在工作区中使用单个顶级CMakeLists.txt,因为项目a和B彼此独立。

我尝试查看add_subdirectorytarget_sources,但无法理解如何目标源,如果我想要相同的库在projectAprojectB中由不同的可执行文件使用。

当然,我可以运行bash脚本在每个库中构建CMake,但我认为这是CMake的工作。我显然没有看到什么明显的解决办法。

谁能帮助我强迫CMake预编译库之前链接到目标?

谢谢!

注:我怎么能告诉CMake编译*.dll文件而不是*.so,和*.exe而不是Linux二进制文件?

我已经阅读和观看了很多教程,并阅读了很多关于CMake项目架构的stackoverflow答案。我试着在Windows上的Visual Studio中运行这个项目,希望它能自己解决这个问题——但并没有什么帮助。我写了一个bash脚本,在链接库之前编译它们,但感觉不对,因为我被承诺CMake实际上为我做了这件事。我也尝试使用子目录系统,正如在另一个stackoverflow回答中提到的,但它并没有真正成功。

您的libraryX/CMakeLists.txt应该是这样的:

cmake_minimum_required(VERSION 3.6)
project(libraryX LANGUAGES CXX)
add_library(libX SHARED fileX.cpp)
target_include_directories(
libX 
PUBLIC 
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
)

在所有子项目的根目录中,您可以添加CMakeLists.txt,它对所有库(第一个)和二进制文件(最后一个)执行add_subdirectory()

然后在projectX/CMakeLists.txt中链接到你需要的CMake目标:

cmake_minimum_required(VERSION 3.6)
project(projectX LANGUAGES CXX)
add_executable(outA mainA.cpp)
target_include_directories(
outA
PUBLIC
${CMAKE_CURRENT_SOURCE_DIR}
# NOTE No need for any other paths
)
target_link_libraries(
outA
PRIVATE
libX
libY
libZ
)

更新(在我发现这些是独立的git仓库之后):

您需要导出您的库目标(构建并安装到相同的前缀中),并在projectX/CMakeLists.txt中使用find_package(libX)来查找要链接的目标。拥有独立的库是很好的(与单一库相比;)。

最新更新