簡體   English   中英

add_custom_command未生成目標

[英]add_custom_command is not generating a target

也許這是不可能的,並且我誤讀了cmake 3.2文檔 ,但我雖然創建了一個自定義命令,但會在Makefile中創建一個自定義的“目標”,以便我可以通過調用輸出文件的名稱來構建目標。 CMake文檔說:

用makefile術語,它以以下形式創建一個新目標:

  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)

將僅當您運行make install時執行的命令存儲在單獨的.cmake文件中。 或者,如果安裝目標已經預留給其他用途,或者您正在執行更復雜的操作:

2.手動定義部署目標。 一旦了解了這一點,就可以創建一個自定義的生成后命令,該命令僅在您在部署目標上顯式運行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生成器會在子Makefile中創建源文件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 foo為其他步驟之一調用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文件。 提出了一個與此有關的問題 ,希望可以通過擴展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的錯誤跟蹤器中發布了該問題:

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)

一些參考

轉過來的依賴項,並使用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。 涉及此目標的構建將是不正確的; 反正繼續

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM