cmake:复制boost-build"在Jamfile中构建所有内容"行为?

时间:2016-04-18 18:08:25

标签: c++ boost cmake boost-build

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

boost-build的一个功能是,您可以指定Jamfile的路径(相当于CMakeLists.txt文件),并且将构建其中指定的所有目标。

例如,使用以下项目结构:

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

如果输入以下命令:

$ b2 foo

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

boost-build示例

以下是使用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's Jamfile内有指令build-project test

这意味着,如果我输入b2 foo,那么lib/Jamfile中的所有内容都将被执行,从而导致foo foo/test被构建。< / p>

此外,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不会成功,并且测试会赢得&#39 ;运行。

问题:

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

1 个答案:

答案 0 :(得分:0)

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

这有点令人费解,因为它需要几个虚假的目标和依赖链接。

第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_targetfoo_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 - &gt; foo_test.run - &gt; foo_test.passed - &gt; foo_test依赖链。

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

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