如何在构建时始终运行命令而不管任何依赖?

时间:2012-12-17 18:38:59

标签: cmake

我想运行一个解析整个源代码树的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。有时它会在每次第二次运行时发生,有时每隔三次运行一次这是一个错误吗?有没有其他方法可以在cmake中运行没有任何依赖的命令?

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

4 个答案:

答案 0 :(得分:11)

虽然我对这个解决方案一点也不满意,但是因为我偶然发现了这个页面,并且没有看到它的提及。

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

例如:

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

查看使用此内容的working example

答案 1 :(得分:11)

关于ideasman42的回答是创建一个带有空回声的虚拟输出。优点是你可以有几个自定义命令取决于这个虚拟输出。

此外,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一样接近无操作。

答案 2 :(得分:7)

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

ADD_CUSTOM_TARGET(do_always ALL COMMAND yourCommandRegardlessOfAnyDependency)

这会添加一个将在ALL之后运行的目标。由于自定义目标始终被视为过时,因此它将始终运行。

构建

后,您可能需要DEPENDS yourA.out才能运行

我的消息来源:

答案 3 :(得分:0)

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

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文件,这导致每次重建假lib,POST_BUILD执行,所有这些都在主PROJECT_NAME之前,因为它依赖于假。