gpt4 book ai didi

c++ - cmake:复制 boost-build 的 "build everything in Jamfile"行为?

转载 作者:太空宇宙 更新时间:2023-11-04 13:17:24 24 4
gpt4 key购买 nike

我正在转换 boost-build构建系统到 cmake。

boost-build 的一个特性是您可以指定一个路径到一个 Jamfile(相当于一个 CMakeLists.txt 文件)和指定的所有目标将在其中 build 。

例如,具有以下项目结构:

root
|
+--- foo
| |
| +--- test
|
+--- bar
| |
| +--- test
|
+--- app

如果输入以下命令:

$ b2 foo

root/foo 下的Jamfile 将被执行,导致foo 库被构建,test 正在构建和运行测试

boost 构建示例

这是一个使用 boost-build 的简单构建配置:

Jamroot:

using gcc ;

project proj : requirements
<link>static
<include>.
;

build-project foo ;

foo/Jamfile:

lib foo : [ glob *.cpp ] ;

build-project test ;

foo/test/Jamfile:

import testing ;

unit-test foo-tests
: [ glob *.cpp ]
..//foo
;

你会注意到在 foo 的 Jamfile 中有一个指令 build-project test

这意味着如果我键入 b2 foo 然后 lib/Jamfile 中的所有内容都将被执行,导致 foo foo/test 正在构建中。

此外,在 Jamroot 中有一个指令 build-project foo

这意味着如果我只输入 b2 那么 Jamroot 中的所有内容都会被执行,导致 foofoo/test 正在构建中。

因此很容易构建整个项目并获得构建的所有源和所有测试。

构建只是一个子目录只获取它的源代码和测试构建也很容易。

我正试图复制这种行为。

cmake 示例

root/CMakeLists.txt:

cmake_minimum_required(VERSION 3.2.2)
project(proj CXX)

add_subdirectory(foo)

foo/CMakeLists.txt:

file(GLOB src "*.cpp")

add_library(foo STATIC ${src})

add_subdirectory(test)

foo/test/CMakeLists.txt:

file(GLOB src "*.cpp")

add_executable(foo_test ${src})

add_test(foo_test foo_test foo)

# run tests if foo_test.passed is missing or outdated
add_custom_command(
OUTPUT foo_test.passed
COMMAND foo_test
COMMAND ${CMAKE_COMMAND} -E touch foo_test.passed
DEPENDS foo_test
)

# make tests run as part of ALL target
add_custom_target(run_foo_test
ALL
DEPENDS foo_test.passed)

上面的 CMakeLists.txt 结构允许我make 并同时构建了 foofoo_test

但是,如果我指定make foo只有 foo 会被构建,但是foo_test 不会是,测试将不会运行。

问题:

  • 如何在键入 make foo 时构建 foo/CMakeLists.txt 中的所有内容?
  • 或者,如何使目标 foo_test.passed 构建为更新目标 foo 的一部分 AND 构建为 ALL 目标?

最佳答案

这是一个实现要求的实现。

它有点复杂,因为它需要几个虚假目标和依赖链。

第 1 步:

  • 创建一个虚假目标,“模块”的所有其他目标都将收集在
  • 将虚假目标添加到ALL,以便将其构建为全局构建过程的一部分

foo/CMakeLists.txt:

# create a phony target which all 'foo' related items will be added to
add_custom_target(foo
ALL
)

第 2 步:

  • 将“模块”中的每个目标添加为对该虚假目标的依赖

libfoo:

  • 请注意,我已将 foo 重命名为 libfoo,因为我们现在已将 foo 用于我们之前的假目标。
  • (这实际上会导致生成的库被称为 liblibfoo.a,这有点难看)

foo/CMakeLists.txt:

add_library(libfoo STATIC ${src})

# add libfoo as a dependency of foo, so 'make foo' will build libfoo
add_dependencies(foo
libfoo)

foo_test:

让测试作为构建的一部分自动运行有点复杂。

你必须:

  • 创建测试可执行文件
  • 添加一个 custom_command 来运行测试并在测试通过时生成一个哨兵文件 (foo_test.passed)
  • 添加一个 custom_target (foo_test.run) 依赖于哨兵 (foo_test.passed)
  • foofoo_test.run 之间添加依赖关系>

foo_test/CMakeLists.txt:

add_executable       (foo_test main.cpp)
target_link_libraries(foo_test libfoo ${Boost_UNIT_TEST_FRAMEWORK_LIBRARY})

# create foo_test.passed command which generates the sentinel file when the tests pass
add_custom_command(
OUTPUT foo_test.passed
COMMAND foo_test
COMMAND ${CMAKE_COMMAND} -E touch foo_test.passed
DEPENDS foo_test
)

# create foo_test.run target which depends on foo_test.passed
add_custom_target(foo_test.run
DEPENDS foo_test.passed
)

# add foo_test.run as a dependency of foo, so 'make foo' will build foo_test.run
add_dependencies(foo
foo_test.run
)

因此,目标 foo 具有 libfoofoo_test.run 作为依赖项。

因此,makemake foo 都构建了 libfoo 并构建并运行了 foo_test(通过 foo_test.runfoo_test.passed)

感知笨拙:

  • foo -> foo_test.run -> foo_test.passed -> foo_test 依赖链。

  • boost-build 中,您可以将库命名为 foo 而不会导致 foo 虚假目标与 foo 库(b2 foo 构建了 foo 库及其测试)

但是,它有效,并且在没有更优雅的解决方案的情况下,会给我想要的东西。

关于c++ - cmake:复制 boost-build 的 "build everything in Jamfile"行为?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36701286/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com