cmake的

也许这是不可能的,我误解了cmake 3.2文档,但是我通过创建自定义命令会在Makefile中创建一个自定义“目标”,以便通过调用输出文件的名称来构建目标。 CMake文档说:

在生成文件中,这将以下面的形式创建一个新目标:

 OUTPUT: MAIN_DEPENDENCY DEPENDS
    COMMAND

所以我想我可以运行make OUTPUT 。 也许这些文档让CMake目标与Makefile目标混淆?

例如,

 add_custom_command(OUTPUT foo_out
    COMMAND post_process foo_in > foo_out
    DEPENDS foo_in
 )

我想要做

 make foo_out

它会使foo_out 。 但是,如果我这样做,我会得到

make: **** No rule to make target `foo_out`. Stop.

果然,cmake二进制输出目录中的任何文件中都不存在“foo_out”这个词。 如果我改变它

add_custom_target(bar DEPENDS foo_out)
add_custom_command(OUTPUT foo_out COMMAND post_process foo_in > foo_out)

然后我可以做

make bar

我可以做

make foo_in

但我仍然做不到

make foo_out

make bar的问题在于它不直观,因为实际的文件输出是foo_out而不是bar

我该怎么做呢?

就我而言,我需要对标准可执行目标执行一个特殊的处理步骤,将可选资源插入到ELF文件中。 我希望能够将两个可执行文件作为Makefile目标,因此我可以构建裸ELF可执行文件以及资源注入的ELF可执行文件。

如果我正在编写一个自定义的Makefile,那么这是微不足道的!

foo_in: foo.c
    $(CC) $< -o $@

foo_out: foo_in
    post_process $< > $@   

我可以做make foo_inmake foo_out


add_custom_command 不会创建一个新的目标。 您必须通过add_executableadd_libraryadd_custom_target明确定义目标,以便使它们可见。

如果你必须解决部署问题,你可以

1.使用install命令(在CMakeLists.txt中的某个地方)像这样:

install(SCRIPT <dir>/post_install.cmake)

存储只有在单独的.cmake文件中运行make install时才执行的命令。 或者,如果安装目标已被预留用于其他事情,或者您有更复杂的事情发生:

2.手动定义一个部署目标。 一旦你得到了这个,你可以创建一个自定义的构建后命令,只有在你的deploy目标上明确运行make时才会执行该命令。 这使您可以通过单独的目标执行命令。

在您的CMakeLists.txt中,它可能如下所示:

cmake_minimum_required(VERSION 3.0)

add_executable("App" <sources>)

# option 1: do deployment stuff only when installing
install(SCRIPT <dir>/post_install.cmake)

# option 2: define a deploy target and add post-build commands
add_custom_target("deploy")
add_custom_command(TARGET "deploy" POST_BUILD <some command>)

这两种方法都可以让您将开发版本与昂贵的现成部署版本分开(如果我理解正确,那么这就是目标)。 我会推荐选项1,因为它只是更干净。

希望这可以帮助!


文档不清楚

CMake的文档在这里不清楚。 CMake的Makefiles生成器在子Makefiles中创建源文件make规则,这些规则在主Makefile中不可见。 在主要的Makefile中,你只能找到你的CMake目标的PHONY规则。 我知道的唯一例外是Ninja Makefiles生成器,它将所有构建规则放入单个文件中。

将后处理步骤转换为CMake

根据我的经验 - 如果post_process是一个脚本 - 你应该考虑用/在CMake脚本中重写你的后处理步骤,因为CMake应该知道用于后处理的所有文件依赖性和变量(然后它将例如处理所有必要的重建或清理步骤)。

以下是我所做的简化/修改版本:

function(my_add_elf _target)

    set(_source_list ${ARGN})
    add_executable(${_target}_in ${_source_list})

    set_target_properties(
        ${_target}_in
        PROPERTIES
            POSITION_INDEPENDENT_CODE   0
            SUFFIX                      .elf
    )

    add_custom_command(
        OUTPUT ${_target}_step1.elf
        COMMAND some_conversion_cmd $<TARGET_FILE:${_target}_in> > ${_target}_step1.elf
        DEPENDS ${_target}_in
    )

    add_custom_target(
        ${_target}_step1 
        DEPENDS 
            ${_target}_step1.elf
    )

    add_custom_command(
        OUTPUT ${_target}_out.elf
        COMMAND final_post_process_cmd ${_target}_step1.elf > ${_target}_out.elf
        DEPENDS ${_target}_step1
    )

    add_custom_target(
        ${_target}_out 
        DEPENDS 
            ${_target}_out.elf
    )

    # alias / PHONY target
    add_custom_target(${_target} DEPENDS ${_target}_out)

endfunction(my_add_elf)

然后打电话

my_add_elf(foo foo.c)

这只是一个例子,但我希望它给出了这样的想法:可以为最终的ELF输出调用make foomake foo_in或为其他步骤之一make foo_step1 。 我认为所有步骤对于用户和CMake都是透明的。

无法为您的目标指定与其中一个输出相同的名称

当你试图给一个自定义目标和其输出的同名时,例如:

add_executable(foo_in foo.c)
add_custom_command(
    OUTPUT foo_out
    COMMAND post_process foo_in > foo_out
    DEPENDS foo_in
)
add_custom_target(foo_out DEPENDS foo_out)

最终会导致无效的make文件。 我提出了一个关于这个问题,希望可以通过扩展CMake来获得可能的解决方案,并得到以下回复:

CMake不打算在Makefile中生成特定的内容。 由add_custom_target创建的顶级目标名称始终是逻辑(即虚假)名称。 这是不允许有一个同名的文件。

可行的解决方法

所以有一些解决方法,但它们都有一个或另一个缺点。

1.最短版本:

macro(my_add_elf_we _target)
    add_executable(${_target}_in ${ARGN})
    add_custom_target(
        ${_target}_out 
        COMMAND post_process $<TARGET_FILE:${_target}_in> > ${_target}_out
        DEPENDS ${_target}_in
    ) 
    set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${_target}_out)
endmacro(my_add_elf_we)

你不能在add_custom_target()本身中声明OUTPUT ,但在这种情况下你不想(因为你不想有任何命名混淆)。 但是如果你没有声明任何输出:

  • 目标将始终视为过时
  • 您需要添加“不可见”输出clean构建规则
  • 2.强制输出名称版本

    以下是上述宏的一个版本,它强制将名称输出并输出给定​​值:

    macro(my_add_elf_in_out _target_in _target_out)
        add_executable(${_target_in} ${ARGN})
        set_target_properties(
            ${_target_in}
            PROPERTIES
                SUFFIX          ""
                OUTPUT_NAME     "${_target_in}"
        )
        add_custom_target(
            ${_target_out}
            COMMAND post_process ${_target_in} > ${_target_out}
            DEPENDS ${_target_in}
        ) 
        set_property(DIRECTORY APPEND PROPERTY ADDITIONAL_MAKE_CLEAN_FILES ${_target_out})
    endmacro(my_add_elf_in_out)
    

    你用以下方式称呼它:

    my_add_elf_in_out(foo_in.elf foo_out.elf foo.c)
    

    3.对象版本

    以下版本使用对象库,但系统不会重复使用foo_in目标链接:

    macro(my_add_elf_obj_in_out _target_in _target_out)
    
        add_library(${_target_in}_obj OBJECT ${ARGN})
    
        add_executable(${_target_in} $<TARGET_OBJECTS:${_target_in}_obj>)
        set_target_properties(
            ${_target_in}
            PROPERTIES
                SUFFIX          ""
                OUTPUT_NAME     "${_target_in}"
        )
    
        add_executable(${_target_out} $<TARGET_OBJECTS:${_target_in}_obj>)
        set_target_properties(
            ${_target_out}
            PROPERTIES
                SUFFIX              ""
                OUTPUT_NAME         "${_target_out}"
                EXCLUDE_FROM_ALL    1
        )
        add_custom_command(
            TARGET ${_target_out}
            POST_BUILD
            COMMAND post_process ${_target_in} > ${_target_out}
        )
    
    endmacro(my_add_elf_obj_in_out)
    

    4.最后和最终版本

    还有一个最终版本肯定只适用于Makefile生成器,这让我在CMake的bug跟踪器中发布了这个问题:

    macro(my_add_elf_ext_in_out _target_in _target_out)
    
        add_executable(${_target_in} ${ARGN})
        set_target_properties(
            ${_target_in}
            PROPERTIES
                SUFFIX          ""
                OUTPUT_NAME     "${_target_in}"
        )
        add_executable(${_target_out} NotExisting.c)
        set_source_files_properties(
            NotExisting.c
            PROPERTIES
                GENERATED           1
                HEADER_FILE_ONLY    1
        )
        set_target_properties(
            ${_target_out}
            PROPERTIES
                SUFFIX              ""
                OUTPUT_NAME         "${_target_out}"
                RULE_LAUNCH_LINK    "# "
        )
        add_custom_command(
            TARGET ${_target_out}
            POST_BUILD
            COMMAND post_process ${_target_in} > ${_target_out}
        )
        add_dependencies(${_target_out} ${_target_in})
    
    endmacro(my_add_elf_ext_in_out)
    

    一些参考

  • 在不同的目录下CMake add_custom_command / _target进行交叉编译
  • CMake:我如何依靠自定义目标的输出?
  • cmake add_custom_command
  • 我如何使用CMake构建LaTeX文档?

  • 改变依赖关系,并使用add_custom_command的第二个签名,这应该工作:

    add_custom_target(foo_out DEPENDS foo_in)
    add_custom_command(TARGET foo_out POST_BUILD COMMAND post_process foo_in > foo_out)
    

    注意:添加BYPRODUCTS foo_out将导致(例如)忍者说

    多条规则会生成foo_out。 涉及这个目标的构建将是不正确的; 无论如何

    链接地址: http://www.djcxy.com/p/31881.html

    上一篇: cmake

    下一篇: executable target name is reserved