22

おそらくこれは不可能であり、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.

確かに、「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は、実際のファイル出力が .xml ではないため、直感的でfoo_outないことbarです。

どうすればいいですか?

私の場合、オプションのリソースを ELF ファイルに挿入する、標準の実行可能ターゲットに対して特別な処理ステップを実行する必要があります。両方の実行可能ファイルを Makefile ターゲットとして使用できるようにしたいので、ネイキッド ELF 実行可能ファイルとリソースが注入された ELF 実行可能ファイルをビルドできます。

カスタムの Makefile を作成していた場合、これは簡単です。

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

foo_out: foo_in
    post_process $< > $@   

そして、私はすることができmake foo_inますmake foo_out

4

3 に答える 3

13

add_custom_command新しいターゲットを作成しません。によって明示的にターゲットを定義するか、make でターゲットを可視化する必要があります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 をお勧めします。

お役に立てれば!

于 2015-06-09T13:53:27.120 に答える
10

ドキュメンテーションが不明確

CMake のドキュメントはここでは不明確です。CMake の Makefile ジェネレーターは、メインの Makefile には表示されないサブ Makefile にソース ファイルの make ルールを作成します。メインの 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)

これは単なる例ですが、アイデアが得られることを願っています。make foo最終的な ELF 出力、make foo_inまたはmake foo_step1他のステップの 1 つを呼び出すことができます。そして、すべてのステップはユーザーと CMake にとって透過的だと思います。

ターゲットに出力の 1 つと同じ名前を付けることはできません

カスタム ターゲットに出力の 1 つと同じ名前を付けようとしている場合、たとえば次のようにします。

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)

無効なメイク ファイルが作成されます。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)

OUTPUTs自体を宣言することはできません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 ジェネレーターでのみ機能する1 つの最終バージョンで、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)

参考文献

于 2015-06-11T08:22:48.677 に答える
1

依存関係を回避し、 の2 番目の署名を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 を生成します。このターゲットを含むビルドは正しくありません。とにかく続ける

于 2016-09-06T08:42:38.193 に答える