cmake 用于具有通用代码的更大项目
cmake for bigger project with common code
我刚接触 cmake 是因为我开始从事一个更大的项目。我需要添加模块测试。
有几个嵌入式设备,每个都有自己的应用程序 运行。
这些应用程序中的大多数都共享代码。
所以代码被分成模块。问题是一些模块在大多数其他模块中使用。这些模块是通用的,common-net和log.
设备的简化项目(应用程序)具有以下结构:
.
|-- CMakeLists.txt (for app)
|-- LICENSE
|-- app
| |-- inc
| | |-- appfile1.hpp
| | `-- appfile2.hpp
| `-- src
| |-- appfile1.cpp
| |-- appfile2.cpp
| `-- main.cpp
|-- comp
| |-- comp1
| | |-- CMakeLists.txt (for test)
| | |-- comp
| | | |-- CMakeLists.txt (for lib)
| | | |-- intf
| | | | |-- comp1file.hpp
| | | | `-- comp1file.hpp
| | | `-- src
| | | |-- comp1file.cpp
| | | `-- comp1file.cpp
| | `-- test
| | `-- src
| | `-- comp1testfile.cpp
| |-- comp2
| | |-- CMakeLists.txt (for test)
| | |-- comp
| | | |-- CMakeLists.txt (for lib)
| | | |-- inc
| | | | `-- comp2file1.hpp
| | | |-- intf
| | | | |-- comp2file2.hpp
| | | | |-- comp2file3.hpp
| | | | |-- comp2file4.hpp
| | | `-- src
| | | |-- comp2file1.cpp
| | | |-- comp2file2.cpp
| | | `-- comp2file3.cpp
| | `-- test
| | |-- inc
| | | `-- comp2testfile.hpp
| | `-- src
| | `-- comp2testfile.cpp
| |-- common
| | |-- CMakeLists.txt (for test)
| | `-- comp
| | |-- inc
| | | |-- commonfile1.hpp
| | | `-- commonfile2.hpp
| | `-- src
| | `-- commonfile1.cpp
| |-- common-net
| | |-- CMakeLists.txt (for test)
| | |-- comp
| | | |-- inc
| | | | |-- netfile1.hpp
| | | | |-- netfile2.hpp
| | | | |-- netfile3.hpp
| | | | |-- netfile4.hpp
| | | | |-- netfile5.hpp
| | | `-- src
| | | |-- netfile1.cpp
| | | |-- netfile2.cpp
| | | |-- netfile3.cpp
| | | |-- netfile4.cpp
| | | |-- netfile5.cpp
| | `-- test
| | |-- inc
| | | |-- nettestfile1.hpp
| | `-- src
| | |-- nettestfile1.cpp
| | |-- nettestfile2.cpp
| | |-- nettestfile3.cpp
| |-- comp3
| | |-- CMakeLists.txt (for test)
| | |-- comp
| | | |-- CMakeLists.txt (for lib)
| | | |-- intf
| | | | |-- comp3file1.hpp
| | | | `-- comp3file2.hpp
| | | `-- src
| | | `-- comp3file1.cpp
| | `-- test
| | `-- src
| | `-- comp3testfile1.cpp
| |-- log
| | `-- comp
| | |-- inc
| | | |-- logfile1.hpp
| | | |-- logfile2.hpp
| | |-- intf
| | | |-- logfile3.hpp
| | | |-- logfile4.hpp
| | `-- src
| | |-- logfile1.cpp
| | |-- logfile2.cpp
| | |-- logfile3.cpp
| | `-- logfile4.cpp
| |-- comp4
| | |-- CMakeLists.txt (for test)
| | |-- comp
| | | |-- CMakeLists.txt (for lib)
| | | |-- intf
| | | | |-- comp4file1.hpp
| | | | |-- comp4file2.hpp
| | | | |-- comp4file3.hpp
| | | `-- src
| | | |-- comp4file1.cpp
| | | |-- comp4file2.cpp
| | | `-- comp4file3.cpp
| | `-- test
| | |-- inc
| | | |-- comp4testfile1.hpp
| | | `-- comp4testfile2.hpp
| | `-- src
| | |-- comp4testfile1.cpp
| | |-- comp4testfile2.cpp
| | |-- comp4testfile3.cpp
| | |-- comp4testfile4.cpp
| | `-- comp4testfile5.cpp
|-- gcc-4.8.cmake
|-- gcc-4.9.cmake
`-- gcc-default.cmake
我知道它里面有很多 "comp",但是这个命名不是我决定的..
每个 comp 有 2 个 CMakefiles:
顶层是创建一个单元测试可执行文件来测试模块。
comp中的一个是制作一个库。这样它就可以在应用程序 CMakefile.
中与 add_subdirectory 一起使用
问题是很多模块都依赖于 common、common-net 和 log。
目前这些部分没有构建为库。我猜如果在多个模块中使用 add_subdirectory 会出现问题?这个干净吗?
这导致:
每个依赖模块在 comp CMakefile 中包含公共 headers。
在顶层(app CMakefile),公共源被添加到可执行文件中。
但是对于每个模块测试,我还必须将公共源添加到测试可执行文件中。
这对我来说似乎很奇怪,我认为有什么地方不对劲。但是不知道怎么解决干净?
查看项目树,需要独立测试每个模块。
在顶层添加源的方法是否可行?
因此,如果我理解正确的话,您有两个不同的问题:必须向每个可执行文件添加公共源,以及必须为每个可执行文件包含公共 headers。
你真正应该做的是让每个公共代码库成为 CMake 静态库目标。 CMake 解决项目中库和可执行文件之间的依赖关系,这就是您所拥有的。只要您在使用该代码的内容之前添加带有公共代码(common、common-net 和 log)的子目录,您就可以执行类似
的操作
target_link_libraries(comp2 common common-net log)
在每个 comp 文件夹中,CMake 将处理依赖项和 linking。
此外,您可以将包含路径(以及其他内容)附加到目标,它们将自动应用于 link 指向它的任何内容。
因此,例如,对于日志库,您将使用
target_include_directories(log PUBLIC inc intf)
然后,link编辑到日志库的任何内容都会自动将 comp/log/comp/inc
和 comp/log/comp/intf
文件夹添加到其 header 路径。
最后,如果我理解正确的话,当您需要可执行测试时,您正在 add_subdirectory
-ing comp4/CMakeLists.txt
文件,而当您需要构建用于包含到应用程序中的库。更好的方法是让测试也 link 到库。
因此,总而言之,您的项目结构应如下所示:
Top-levelCMakeLists.txt
add_subdirectory(comp)
add_subdirectory(app)
comp/CMakeLists.txt
add_subdirectory(common)
add_subdirectory(common-net)
add_subdirectory(log)
add_subdirectory(comp1)
<and so on for the other comps>
comp/common-net/CMakeLists.txt
add_subdirectory(comp)
add_executable(test-common-net <source for test>)
target_link_libraries(test-common-net common-net)
comp/common-net/comp/CMakeLists.txt
add_library(common-net STATIC <source for common-net>)
target_include_directories(common-net PUBLIC inc)
# assuming common-net depends on common
target_link_libraries(common-net common)
comp/comp1/CMakeLists.txt
add_subdirectory(comp)
add_executable(test-comp1 <source for test>)
target_link_libraries(test-comp1 comp1)
comp/comp1/comp/CMakeLists.txt
add_library(comp1 STATIC <source for comp1>)
target_include_directories(comp1 PUBLIC inc)
target_link_libraries(comp1 common common-net log)
你现在可能明白了。您只需要创建一个相互依赖的库链。
我刚接触 cmake 是因为我开始从事一个更大的项目。我需要添加模块测试。 有几个嵌入式设备,每个都有自己的应用程序 运行。
这些应用程序中的大多数都共享代码。 所以代码被分成模块。问题是一些模块在大多数其他模块中使用。这些模块是通用的,common-net和log.
设备的简化项目(应用程序)具有以下结构:
.
|-- CMakeLists.txt (for app)
|-- LICENSE
|-- app
| |-- inc
| | |-- appfile1.hpp
| | `-- appfile2.hpp
| `-- src
| |-- appfile1.cpp
| |-- appfile2.cpp
| `-- main.cpp
|-- comp
| |-- comp1
| | |-- CMakeLists.txt (for test)
| | |-- comp
| | | |-- CMakeLists.txt (for lib)
| | | |-- intf
| | | | |-- comp1file.hpp
| | | | `-- comp1file.hpp
| | | `-- src
| | | |-- comp1file.cpp
| | | `-- comp1file.cpp
| | `-- test
| | `-- src
| | `-- comp1testfile.cpp
| |-- comp2
| | |-- CMakeLists.txt (for test)
| | |-- comp
| | | |-- CMakeLists.txt (for lib)
| | | |-- inc
| | | | `-- comp2file1.hpp
| | | |-- intf
| | | | |-- comp2file2.hpp
| | | | |-- comp2file3.hpp
| | | | |-- comp2file4.hpp
| | | `-- src
| | | |-- comp2file1.cpp
| | | |-- comp2file2.cpp
| | | `-- comp2file3.cpp
| | `-- test
| | |-- inc
| | | `-- comp2testfile.hpp
| | `-- src
| | `-- comp2testfile.cpp
| |-- common
| | |-- CMakeLists.txt (for test)
| | `-- comp
| | |-- inc
| | | |-- commonfile1.hpp
| | | `-- commonfile2.hpp
| | `-- src
| | `-- commonfile1.cpp
| |-- common-net
| | |-- CMakeLists.txt (for test)
| | |-- comp
| | | |-- inc
| | | | |-- netfile1.hpp
| | | | |-- netfile2.hpp
| | | | |-- netfile3.hpp
| | | | |-- netfile4.hpp
| | | | |-- netfile5.hpp
| | | `-- src
| | | |-- netfile1.cpp
| | | |-- netfile2.cpp
| | | |-- netfile3.cpp
| | | |-- netfile4.cpp
| | | |-- netfile5.cpp
| | `-- test
| | |-- inc
| | | |-- nettestfile1.hpp
| | `-- src
| | |-- nettestfile1.cpp
| | |-- nettestfile2.cpp
| | |-- nettestfile3.cpp
| |-- comp3
| | |-- CMakeLists.txt (for test)
| | |-- comp
| | | |-- CMakeLists.txt (for lib)
| | | |-- intf
| | | | |-- comp3file1.hpp
| | | | `-- comp3file2.hpp
| | | `-- src
| | | `-- comp3file1.cpp
| | `-- test
| | `-- src
| | `-- comp3testfile1.cpp
| |-- log
| | `-- comp
| | |-- inc
| | | |-- logfile1.hpp
| | | |-- logfile2.hpp
| | |-- intf
| | | |-- logfile3.hpp
| | | |-- logfile4.hpp
| | `-- src
| | |-- logfile1.cpp
| | |-- logfile2.cpp
| | |-- logfile3.cpp
| | `-- logfile4.cpp
| |-- comp4
| | |-- CMakeLists.txt (for test)
| | |-- comp
| | | |-- CMakeLists.txt (for lib)
| | | |-- intf
| | | | |-- comp4file1.hpp
| | | | |-- comp4file2.hpp
| | | | |-- comp4file3.hpp
| | | `-- src
| | | |-- comp4file1.cpp
| | | |-- comp4file2.cpp
| | | `-- comp4file3.cpp
| | `-- test
| | |-- inc
| | | |-- comp4testfile1.hpp
| | | `-- comp4testfile2.hpp
| | `-- src
| | |-- comp4testfile1.cpp
| | |-- comp4testfile2.cpp
| | |-- comp4testfile3.cpp
| | |-- comp4testfile4.cpp
| | `-- comp4testfile5.cpp
|-- gcc-4.8.cmake
|-- gcc-4.9.cmake
`-- gcc-default.cmake
我知道它里面有很多 "comp",但是这个命名不是我决定的..
每个 comp 有 2 个 CMakefiles: 顶层是创建一个单元测试可执行文件来测试模块。 comp中的一个是制作一个库。这样它就可以在应用程序 CMakefile.
中与 add_subdirectory 一起使用问题是很多模块都依赖于 common、common-net 和 log。 目前这些部分没有构建为库。我猜如果在多个模块中使用 add_subdirectory 会出现问题?这个干净吗?
这导致: 每个依赖模块在 comp CMakefile 中包含公共 headers。 在顶层(app CMakefile),公共源被添加到可执行文件中。 但是对于每个模块测试,我还必须将公共源添加到测试可执行文件中。
这对我来说似乎很奇怪,我认为有什么地方不对劲。但是不知道怎么解决干净?
查看项目树,需要独立测试每个模块。 在顶层添加源的方法是否可行?
因此,如果我理解正确的话,您有两个不同的问题:必须向每个可执行文件添加公共源,以及必须为每个可执行文件包含公共 headers。
你真正应该做的是让每个公共代码库成为 CMake 静态库目标。 CMake 解决项目中库和可执行文件之间的依赖关系,这就是您所拥有的。只要您在使用该代码的内容之前添加带有公共代码(common、common-net 和 log)的子目录,您就可以执行类似
的操作target_link_libraries(comp2 common common-net log)
在每个 comp 文件夹中,CMake 将处理依赖项和 linking。
此外,您可以将包含路径(以及其他内容)附加到目标,它们将自动应用于 link 指向它的任何内容。
因此,例如,对于日志库,您将使用
target_include_directories(log PUBLIC inc intf)
然后,link编辑到日志库的任何内容都会自动将 comp/log/comp/inc
和 comp/log/comp/intf
文件夹添加到其 header 路径。
最后,如果我理解正确的话,当您需要可执行测试时,您正在 add_subdirectory
-ing comp4/CMakeLists.txt
文件,而当您需要构建用于包含到应用程序中的库。更好的方法是让测试也 link 到库。
因此,总而言之,您的项目结构应如下所示:
Top-levelCMakeLists.txt
add_subdirectory(comp)
add_subdirectory(app)
comp/CMakeLists.txt
add_subdirectory(common)
add_subdirectory(common-net)
add_subdirectory(log)
add_subdirectory(comp1)
<and so on for the other comps>
comp/common-net/CMakeLists.txt
add_subdirectory(comp)
add_executable(test-common-net <source for test>)
target_link_libraries(test-common-net common-net)
comp/common-net/comp/CMakeLists.txt
add_library(common-net STATIC <source for common-net>)
target_include_directories(common-net PUBLIC inc)
# assuming common-net depends on common
target_link_libraries(common-net common)
comp/comp1/CMakeLists.txt
add_subdirectory(comp)
add_executable(test-comp1 <source for test>)
target_link_libraries(test-comp1 comp1)
comp/comp1/comp/CMakeLists.txt
add_library(comp1 STATIC <source for comp1>)
target_include_directories(comp1 PUBLIC inc)
target_link_libraries(comp1 common common-net log)
你现在可能明白了。您只需要创建一个相互依赖的库链。