29

我想运行一个解析整个源代码树的 cmake 命令,所以我无法在 cmake 的 add_custom_command/add_custom_target 命令中列出所有可能的依赖项。

是否可以告诉 cmake 只是在没有任何条件的情况下运行命令?我尝试了在网上找到的所有解决方案(包括 SO),但他们都认为该命令依赖于几个最新的已知文件。

我找到了一个解决方案,但它不能可靠地工作:

cmake_minimum_required(VERSION 2.6)

project(main)

add_custom_command(
   OUTPUT file1
   COMMAND echo touching file1
   COMMAND touch file1
   DEPENDS file2)
add_custom_target(dep ALL DEPENDS file1 file2)

# this command re-touches file2 after dep target is "built"
# and thus forces its rebuild
ADD_CUSTOM_COMMAND(TARGET dep
          POST_BUILD
          COMMAND echo touching file2
          COMMAND touch file2
)

这是输出:

queen3@queen3-home:~/testlib$ make
[100%] Generating file1
touching file1
touching file2
[100%] Built target dep
queen3@queen3-home:~/testlib$ make
[100%] Generating file1
touching file1
touching file2
[100%] Built target dep
queen3@queen3-home:~/testlib$ make
touching file2
[100%] Built target dep
queen3@queen3-home:~/testlib$ 

如您所见,在第三次运行时它没有生成 file1,即使之前已触及 file2。有时每 2 次运行一次,有时每 3 次,有时每 4 次。它是一个错误吗?是否有另一种方法可以在 cmake 中运行没有任何依赖关系的命令?

奇怪但是如果我添加两个命令来重新触摸file2,即只是复制粘贴构建后的命令,它可以可靠地工作。或者它可能每运行 1000 次就会失败,我还不确定 ;-)

4

4 回答 4

25

虽然我对这个解决方案一点也不满意,但自从我偶然发现这个页面并且没有看到它被提及后发布。

您可以添加引用丢失文件的自定义目标,

例如:

add_custom_target(
    my_custom_target_that_always_runs ALL
    DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/__header.h
)

add_custom_command(
    OUTPUT
        ${CMAKE_CURRENT_BINARY_DIR}/__header.h  # fake! ensure we run!
        ${CMAKE_CURRENT_BINARY_DIR}/header.h    # real header, we write.
    # this command must generate: ${CMAKE_CURRENT_BINARY_DIR}/header.h
    COMMAND some_command
)

这将继续运行自定义命令,因为__header.h未找到。

请参阅使用它的工作示例

于 2015-07-20T13:44:14.747 回答
18

关于ideaman42 的答案的一个转折是创建一个带有空回显语句的虚拟输出。优点是您可以有几个自定义命令取决于这个虚拟输出。

此外,cmake 构建系统将知道您的自定义命令的输出文件是什么,以便可以正确解决对该输出的任何依赖关系。

# Custom target will always cause its dependencies to be evaluated and is
# run by default
add_custom_target(dummy_target ALL
    DEPENDS
        custom_output
    )

# custom_output will always be rebuilt because it depends on always_rebuild
add_custom_command(
    OUTPUT custom_output
    COMMAND command_that_produces_custom_output
    DEPENDS
        always_rebuild
    )

# Dummy output which is never actually produced. Anything that depends on
# this will always be rebuilt.
add_custom_command(
    OUTPUT always_rebuild
    COMMAND cmake -E echo
    )

cmake -E echo与 cmake 一样接近无操作。

于 2015-08-18T03:08:09.133 回答
12

我搜索了完全相同的内容,最终找到了“notSoWorkaround”解决方案。

ADD_CUSTOM_TARGET(do_always ALL COMMAND yourCommandRegardlessOfAnyDependency)

这将添加一个将在 ALL 之后运行的目标。并且由于自定义目标始终被认为是过时的,它将始终运行。

您可能需要DEPENDS yourA.out在构建后运行

我的消息来源:

于 2017-04-04T11:55:20.320 回答
1

所以这是我的解决方案。我添加了一个假库:

add_subdirectory(fake)
add_dependencies(${PROJECT_NAME} fake)

我这样做:

cmake_minimum_required (VERSION 2.6)
project(fake CXX)
add_library(${PROJECT_NAME} SHARED fake.cpp)
add_custom_command(TARGET fake
    POST_BUILD
    COMMAND ./mycommand.sh
    COMMAND rm ${ROOT_BIN_DIR}/libfake.so
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})

如您所见,我只是在构建后删除了 .so 文件,这会导致每次重建假库,并执行 POST_BUILD,并且所有这些都在主 PROJECT_NAME 之前,因为它依赖于假。

于 2012-12-18T08:34:23.833 回答