gpt4 book ai didi

cmake - add_custom_command 没有生成目标

转载 作者:行者123 更新时间:2023-12-03 13:31:16 31 4
gpt4 key购买 nike

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

In makefile terms this creates a new target in the following form:

 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.

果然,“foo_out”这个词在 cmake 二进制输出目录的任何文件中都不存在。如果我把它改成这个
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 可执行文件以及注入(inject)资源的 ELF 可执行文件。

如果我正在编写自定义 Makefile,这很简单!
foo_in: foo.c
$(CC) $< -o $@

foo_out: foo_in
post_process $< > $@

我可以做 make foo_inmake foo_out .

最佳答案

文档不清楚

CMake 的文档在这里不清楚。 CMake 的 Makefiles 生成器确实在子 Makefile 中创建源文件 make 规则,这些规则在主 Makefile 中不可见。在主 Makefile 中,您只会找到 PHONY CMake 目标的规则。我知道的唯一异常(exception)是 NinjaMakefiles 生成器将所有构建规则放入单个文件中。

将后处理步骤转换为 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)

这只是一个示例,但我希望它给出了一个想法:您可以调用 make foo对于最终的 ELF 输出, make foo_inmake 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 文件。我有 raised an issue关于这一点,希望可以通过扩展 CMake 本身来解决可能的问题,并得到以下答复:

CMake is not intended to produce specific content in a Makefile. Top-level target names created by add_custom_target are always logical (i.e. phony) names. It is simply not allowed to have a file of the same name.



可能的解决方法

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

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)

你不能声明 OUTPUT s 在 add_custom_target()本身,但在这种情况下你不想(因为你不想有任何命名混淆)。但是如果你不声明任何输出:
  • 目标将始终被视为过期
  • 您需要添加“不可见”输出 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 的错误跟踪器上发布了这个问题:
    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 in different directories for cross-compilation
  • CMake: how do i depend on output from a custom target?
  • cmake add_custom_command
  • How do I use CMake to build LaTeX documents?
  • 关于cmake - add_custom_command 没有生成目标,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30719275/

    31 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com