首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >cmake:复制boost-build的“在Jamfile中构建一切”的行为?

cmake:复制boost-build的“在Jamfile中构建一切”的行为?
EN

Stack Overflow用户
提问于 2016-04-18 18:08:24
回答 1查看 571关注 0票数 1

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

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

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

代码语言:javascript
复制
root
|
+--- foo
|    |
|    +--- test
|
+--- bar
|    |
|    +--- test
|
+--- app

如果输入以下命令:

代码语言:javascript
复制
$ b2 foo

将执行root/foo下的root/foo,生成foo库,构建并运行test测试。

boost构建示例

下面是一个使用boost-build的简单构建配置

Jamroot**:**

代码语言:javascript
复制
using gcc ;

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

build-project foo ;

foo/Jamfile**:**

代码语言:javascript
复制
lib foo : [ glob *.cpp ] ;

build-project test ;

foo/test/Jamfile**:**

代码语言:javascript
复制
import testing ;

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

您会注意到,在foo's Jamfile中有一个指令build-project test

这意味着,如果我键入b2 foo,那么lib/Jamfile中的所有内容都将被执行,从而生成foo foo/test

而且,在Jamroot中有一个指令build-project foo

这意味着,如果我只键入b2,那么Jamroot中的所有内容都将被执行,从而生成foofoo/test

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

构建也很容易,只需一个子目录,只需要--它是源代码和测试生成的.

这就是我想复制的行为。

cmake实例

root/CMakeLists.txt**:**

代码语言:javascript
复制
cmake_minimum_required(VERSION 3.2.2)
project(proj CXX)

add_subdirectory(foo)

foo/CMakeLists.txt**:**

代码语言:javascript
复制
file(GLOB src "*.cpp")

add_library(foo STATIC ${src})

add_subdirectory(test)

foo/test/CMakeLists.txt**:**

代码语言:javascript
复制
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不会构建,测试也不会运行。

问题:

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

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-04-18 19:37:33

下面是一个实现需求的实现。

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

步骤1:

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

foo/CMakeLists.txt

代码语言:javascript
复制
# 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

代码语言:javascript
复制
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

代码语言:javascript
复制
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
    )

因此,目标foolibfoofoo_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库及其测试)

然而,它的工作,在没有一个更优雅的解决方案,将给我我想要的。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/36701286

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档