优选cmake项目结构 [英] preferred cmake project structure
问题描述
我想有以下结构 A - > B - > C
,其中:
-
C
,第三方库的包装器,非常
的基本代码等。 -
B
是常见的类,函数和数据 -
- 由于所有三个项目都在进行中,我想有能力建立
C
,C + B
和C + B + A
一个镜头。 - 我宁愿静态链接超过动态,因此
C
和C + / code>将是静态库,
C + B + A
将是可执行文件 - cmake列表和配置文件简单干净。我在官方wiki和互联网上发现的例子都是相当大和怪异的。
- 如果它不需要改变多于几行,这将是巨大的更改
A
,B
或C
的位置文件系统。 - 所有这三个组件都使用google-test,但我不确定是否对项目布局很重要。
- CMake必须知道依赖关系的位置 - 相对或绝对 - by
- 有一个单一的源代码树(你不想要的那个)
- 具有多个可执行文件的CMake共享库
- < a href =http://stackoverflow.com/questions/31512485/cmake-how-to-setup-source-library-and-cmakelists-txt-dependencies> CMake:如何设置源,库和CMakeLists.txt依赖?
- 包含/ libraries /二进制文件的公共目录位置
- 通过配置文件/变量定义获取路径
- 在主机上提供
- 有一个单一的源代码树(你不想要的那个)
- 首选工具链文件
if(SomeCompiler)
语句 - 将共同/重复代码零件移动为
- 将复杂的非目标特定代码零件移动到自己的(CMake)脚本文件中
我想方便地重用 C
或 B(+ C)
在未来在我的其他项目。此外,我有以下要求:
我对cmake很新鲜,我甚至不明白是否更好写 XXXConfig.cmake
或 FindXXX.cmake
文件。另外,我不知道,我应该如何使用 X_INCLUDE_DIRS
传递从子组件到父组件的相对路径。
首先我必须承认我同意@Tsyvarev。您的CMake环境应适合您的流程/工作流程,并应考虑项目规模和团队结构。
因此,这个问题的这部分很难回答我将专注于技术部分:
为了使您的CMake文件尽可能简单,我建议将您的CMake代码分成单独的专用文件:
示例代码
请求 find_package()
变体,使用在CMake项目中使用CMake启用的库和上面列出的内容:
MyCommonCode.cmake
)
文件(
WRITE$ {CMAKE_CURRENT_BINARY_DIR} / $ {_ target} Config.cmake
include(\\ $ \ {CMAKE_CURRENT_LIST_DIR\} /${_target}Targets.cmake\)
set_property(
TARGET $ {_ target}
APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES \$ {_ include_dir} \
)
)
export(
TARGETS $ {_ target}
FILE$ {CMAKE_CURRENT_BINARY_DIR} / $ {_ target} Targets.cmake
EXPORT_LINK_INTERFACE_LIBRARIES
)
export(PACKAGE $ {_ target})
endfunction(my_export_target)
C / CMakeLists.txt
include(MyCommonCode。 cmake)
...
my_export_target(C$ {CMAKE_CURRENT_SOURCE_DIR} / include)
$ b b
B / CMakeLists.txt
include(MyCommonCode.cmake)
find_package(C REQUIRED)
...
target_link_libraries(BC)
my_export_target(B$ {CMAKE_CURRENT_SOURCE_DIR} / include)
A / CMakeLists.txt
code> include(MyCommonCode.cmake)
find_package(B REQUIRED)
...
target_link_libraries(AB)
这将保持所有3个构建环境分离,只共享相对静态的
MyCommonCode.cmake
文件。所以在这种方法中,我到目前为止还没有涵盖你的第一点,但建议使用外部脚本链接/触发您的A / B / C的构建步骤。I would like to have the following structure
A -> B -> C
, where:
C
is boilerplate code, wrappers for third-party libraries, very basic code etc.B
is the common classes, functions and data structures specific to the project's domain.A
is the project itself.
I would like to make it easy to reuse C
or B(+C)
in future in my other projects. In addition, I have the following requirements:
- As all three projects are in-progress, I would like to have an ability to build
C
,C+B
andC+B+A
in one shot. - I would prefer the static linkage over dynamic, so that
C
andC+B
would be static libraries, andC+B+A
would be the executable - I would like to keep cmake lists and config files simple and clean. Examples which I found in the official wiki and over the internet are pretty big and monstrous.
- It would be great if it won't require changing more than a couple of lines if I'd change the locations of
A
,B
orC
in the filesystem. - All these three components are using google-test, but I'm not sure if it is important for the project layout.
I am pretty new to cmake and I don't even understand is it better to write XXXConfig.cmake
or FindXXX.cmake
files. Also, I am not sure, how should I pass relative paths from subcomponent to the parent component using X_INCLUDE_DIRS
.
First I have to admit that I agree with @Tsyvarev. Your CMake environment should fit to your processes/workflow and should take project sizes and team structure into account. Or generally speaking the environment CMake will be used in. And this tends to be - in a positive way - very alive.
So this part of your question is difficult to answer and I'll concentrate on the technical part:
- CMake has to know the location of the dependencies - relative or absolute - by
- having a monolithic source tree (the one you don't want anymore)
- a common directory location for includes/libraries/binaries
- getting the paths via config files/variable definitions
- using registration in or installation from a database provided on the host
- To keep your CMake files as simple as possible I would recommend to group your CMake code into separate dedicated files:
- Prefer toolchain files over
if(SomeCompiler)
statements - Move common/repeating code parts as
function()
bodies into a shared CMake include file - Move complex non-target specific code parts into their own (CMake) script files
- Prefer toolchain files over
Example Code
Since you have specifically asked for the find_package()
variant, taking Use CMake-enabled libraries in your CMake project and the things listed above:
MyCommonCode.cmake
cmake_policy(SET CMP0022 NEW)
function(my_export_target _target _include_dir)
file(
WRITE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Config.cmake"
"
include(\"\$\{CMAKE_CURRENT_LIST_DIR\}/${_target}Targets.cmake\")
set_property(
TARGET ${_target}
APPEND PROPERTY
INTERFACE_INCLUDE_DIRECTORIES \"${_include_dir}\"
)
"
)
export(
TARGETS ${_target}
FILE "${CMAKE_CURRENT_BINARY_DIR}/${_target}Targets.cmake"
EXPORT_LINK_INTERFACE_LIBRARIES
)
export(PACKAGE ${_target})
endfunction(my_export_target)
C/CMakeLists.txt
include(MyCommonCode.cmake)
...
my_export_target(C "${CMAKE_CURRENT_SOURCE_DIR}/include")
B/CMakeLists.txt
include(MyCommonCode.cmake)
find_package(C REQUIRED)
...
target_link_libraries(B C)
my_export_target(B "${CMAKE_CURRENT_SOURCE_DIR}/include")
A/CMakeLists.txt
include(MyCommonCode.cmake)
find_package(B REQUIRED)
...
target_link_libraries(A B)
This keeps all 3 build environments separate, only sharing the relatively static MyCommonCode.cmake
file. So in this approach I have so far not covered your first point, but would recommend the use of a external script to chain/trigger your build steps for A/B/C.
这篇关于优选cmake项目结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!