我正在将boost-build
构建系统转换为cmake。
boost-build的一个功能是,您可以指定Jamfile
的路径(相当于CMakeLists.txt
文件),并且将构建其中指定的所有目标。
例如,使用以下项目结构:
root
|
+--- foo
| |
| +--- test
|
+--- bar
| |
| +--- test
|
+--- app
如果输入以下命令:
$ b2 foo
Jamfile
下的root/foo
将被执行,导致正在构建foo
库,正在构建并运行test
个测试
以下是使用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
中的所有内容都会被执行,从而导致foo
和foo/test
被构建。
因此很容易构建整个项目并获得所有源代码和所有测试。
构建只是一个子目录也很容易,只有来源和测试才能构建。
正是这种行为我试图复制。
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
并建立foo
和foo_test
。
但是,如果我指定make foo
,则只构建 foo
,但foo_test
不会成功,并且测试会赢得&#39 ;运行。
问题:
foo/CMakeLists.txt
时,如何在make foo
内构建所有内容?foo_test.passed
作为更新目标foo
AND 构建的一部分,作为ALL
目标的一部分?答案 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_target
(foo_test.run
),这取决于哨兵(foo_test.passed
)foo
和foo_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
具有libfoo
和foo_test.run
作为依赖关系。
因此,make
和make foo
都构建libfoo
并构建并运行foo_test
(通过foo_test.run
和foo_test.passed
)
感知笨拙:
foo
- &gt; foo_test.run
- &gt; foo_test.passed
- &gt; foo_test
依赖链。
在boost-build
中,您可以为库foo
命名,而不会导致foo
虚假目标与foo
库之间发生冲突(以及b2 foo
构建foo
库及其测试)
然而,它有效,并且在没有更优雅的解决方案的情况下,会给我我想要的东西。