CMakeを使用してDLLファイルを実行可能ファイルと同じフォルダーにコピーする方法


98

CMakeを使用して、SVNでソースのVisual Studioファイルを生成します。現在、私のツールでは、いくつかのDLLファイルが実行可能ファイルと同じフォルダーにある必要があります。DLLファイルは、ソースと同じフォルダーにあります。

CMakeLists.txt生成されたVisual Studioプロジェクトがリリース/デバッグフォルダーに特定のDLLファイルを既に持っているか、コンパイル時にそれらをコピーするように変更するにはどうすればよいですか?

回答:


122

add_custom_command一緒にこれを達成するために使用しcmake -E copy_if_different...ます。完全な情報を実行するには

cmake --help-command add_custom_command
cmake -E


したがって、あなたの場合、次のディレクトリ構造がある場合:

/CMakeLists.txt
/src
/libs/test.dll

コマンドが適用されるCMakeターゲットがのMyTest場合、CMakeLists.txtに以下を追加できます。

add_custom_command(TARGET MyTest POST_BUILD        # Adds a post-build event to MyTest
    COMMAND ${CMAKE_COMMAND} -E copy_if_different  # which executes "cmake - E copy_if_different..."
        "${PROJECT_SOURCE_DIR}/libs/test.dll"      # <--this is in-file
        $<TARGET_FILE_DIR:MyTest>)                 # <--this is out-file path


/libs/ディレクトリの内容全体をコピーしたい場合は、次を使用しますcmake -E copy_directory

add_custom_command(TARGET MyTest POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
        "${PROJECT_SOURCE_DIR}/libs"
        $<TARGET_FILE_DIR:MyTest>)


構成(リリース、デバッグなど)に応じて異なるdllをコピーする必要がある場合、対応する構成で名前が付けられたサブディレクトリにこれらを含めることができます。 /libs/Release、と/libs/Debug。次に、次のように、構成タイプをadd_custom_command呼び出しのdllへのパスに挿入する必要があります。

add_custom_command(TARGET MyTest POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_directory
        "${PROJECT_SOURCE_DIR}/libs/$<CONFIGURATION>"
        $<TARGET_FILE_DIR:MyTest>)

3
それが将来誰かを助ける場合に備えて私のケースで何が機能したかについての簡単なメモ:メインの実行可能ファイルがオプションでリンクする静的ライブラリプロジェクトがあり、そのライブラリを追加する場合は、コピーするDLLが必要です。そのため、そのライブラリのCMakeLists.txtファイル${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$<CONFIG>で、ターゲットの宛先に使用しました。それ以外の場合は、ライブラリビルドパスにコピーされ、役に立たなかった。
AberrantWolf 2016

install()バイナリをアセンブルすることは、cmake ディレクティブの目標ではありませんか?それともcmake LIBRARYなのか?私はツールチェーンを本当に知りません。
サンドバーグ2018年

1
$<TARGET_FILE_DIR:MyTest>- それは何ですか?情報を印刷する方法、正確には何を意味するのか
ilw

コマンドを統合しているときに何かを見落とした場合を除き、このメソッドはで追加されたライブラリでは機能しませんIMPORTED_LIBRARIES。何もビルドされていない場合、ビルド後のコマンドを実行できないという不満があります。
ツァルメン

2
私のcmakeをテストして実行するとき:IMPORTEDライブラリを使用していて、DLLを再配置する必要がある場合は、バリアントコマンドを使用する必要があります。使用するようにIMPORTEDライブラリを追加した場合複数のビルド後コマンドを実行するには、それらすべてを1つのカスタムコマンドにバインドする必要MyImportedLibがあることにCOMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:MyImportedLib> $<TARGET_FILE_DIR:MyTest>注意してください。例add_custom_command(TARGET MyTest POST_BUILD COMMAND #your first command# COMMAND #Your second command#)
Tzalumen

24

これらの行を最上位のCMakeLists.txtファイルに入れました。CMakeによってコンパイルされたすべてのライブラリと実行可能ファイルは、実行可能ファイルがライブラリを見つけてすべてを簡単に実行できるように、ビルドディレクトリの最上位に配置されます。

set (CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})
set (CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR})

これは、プロジェクトのソースディレクトリからプリコンパイルされたバイナリをコピーするというOPの問題を解決しないことに注意してください。


7

私のプログラムのWindowsビルドを作成しようとしたときに、今日この問題が発生しました。そして、これらすべての答えが私を満足させなかったので、私はいくつかの研究をしてしまいました。主な問題は3つありました。

  • デバッグビルドをライブラリのデバッグバージョンにリンクし、リリースビルドをライブラリのリリースビルドにそれぞれリンクする必要がありました。

  • さらに、正しいバージョンのDLLファイル(デバッグ/リリース)を出力ディレクトリにコピーする必要がありました。

  • そして、複雑で壊れやすいスクリプトを記述せずに、これらすべてを実現したいと考えていました。

githubでいくつかのCMakeマニュアルといくつかのマルチプラットフォームプロジェクトを閲覧した後、私はこの解決策を見つけました:

「インポート済み」属性を使用してライブラリをターゲットとして宣言し、そのデバッグを参照して.libファイルと.dllファイルを解放します。

add_library(sdl2 SHARED IMPORTED GLOBAL)
set_property(TARGET sdl2 PROPERTY IMPORTED_IMPLIB_RELEASE "${SDL_ROOT_PATH}/lib/SDL2.lib")
set_property(TARGET sdl2 PROPERTY IMPORTED_LOCATION_RELEASE "${SDL_ROOT_PATH}/bin/SDL2.dll")
set_property(TARGET sdl2 PROPERTY IMPORTED_IMPLIB_DEBUG "${SDL_ROOT_PATH}/lib/SDL2d.lib")
set_property(TARGET sdl2 PROPERTY IMPORTED_LOCATION_DEBUG "${SDL_ROOT_PATH}/bin/SDL2d.dll")

通常どおり、このターゲットをプロジェクトにリンクします

target_link_libraries(YourProg sdl2 ...)

以前のビルド以降に何らかの方法で変更されている場合、dllファイルを宛先にコピーするカスタムビルドステップを作成する

add_custom_command ( TARGET YourProg POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    $<TARGET_FILE:sdl2> $<TARGET_FILE_DIR:YourProg>
)

5

受け入れられた回答の補遺。別の回答として追加されたので、コードのフォーマットを取得します。

同じプロジェクトでdllをビルドしている場合、それらは通常、Release、Debugなどのディレクトリにあります。それらを正しくコピーするには、Visual Studio環境変数を使用する必要があります。例えば:

"${PROJECT_BINARY_DIR}/your_library/\$\(Configuration\)/your_library.dll"

ソースと

"${CMAKE_CURRENT_BINARY_DIR}/\$\(Configuration\)/your_library.dll"

目的地のため。エスケープに注意してください!

CMake CMAKE_BUILD_TYPE変数は、VSプロジェクトの生成時に解決され、常にデフォルトのままであるため、構成に使用することはできません。


8
受け入れられた回答の最後の部分は、これを使用してより明確なCMakeの方法でこれに対処します$<CONFIGURATION>
チャッククランチ

4

コマンドfind_libraryを使用することもできます。

find_library(<some_var> NAMES <name_of_lib> PATHS "<path/to/lib>")

たとえば、EXECUTABLE_PATHを定義すると、次のようになります。

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin)

実行可能ファイルに必要な.dllファイルを移動できます。

file(COPY ${<some_var>}
    DESTINATION ${EXECUTABLE_OUTPUT_PATH})

2

これはそれらの1つに役立ちます

SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY
    ${PROJECT_SOURCE_DIR}/lib CACHE
    PATH "Directory where all the .lib files are dumped." FORCE)
SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY
    ${PROJECT_SOURCE_DIR}/bin CACHE
    PATH "Directory where .exe and .dll files are dumped." FORCE)

1

おそらくカスタムターゲット追加する必要があります、実行可能なターゲットの1つに依存させるあります。

上記の関数を使用してファイルをコピーするには、以下を使用します。

COMMAND ${CMAKE_PROGRAM} -E copy_if_different ${CMAKE_BINARY_DIR}/path/to/file.dll ${CMAKE_BINARY_DIR}/where/to/put/file.dll`

0

私はCMakeの初心者ですが、自分の経験を共有したかったのです。私の場合、すべてのバイナリが含まれるようにインストール後のコピーが必要でした。CMake内にインポートできるサードパーティのバイナリの場合、次のように機能します。

find_package( dependency REQUIRED )
if( MSVC ) 
    # If done properly and if the dependency has a correct config file, IMPORTED_LOCATION_RELEASE should be defined
    get_target_property( DEP_SHARED_LIB_PATH dependency IMPORTED_LOCATION_RELEASE )
    # Create a bin directory in the install folder
    add_custom_command(TARGET BGS POST_BUILD COMMAND ${CMAKE_COMMAND} -E make_directory  ${CMAKE_INSTALL_PREFIX}/bin/)
    # Copy the shared lib file
    add_custom_command(TARGET BGS POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${DEP_SHARED_LIB_PATH} ${CMAKE_INSTALL_PREFIX}/bin/)
endif()

明らかに、IMPORTED_LOCATION_RELEASEは、共有ライブラリがどのように構築/インストールされたかに応じて、バリアントを持つことができます。IMPORTED_LOCATION_DEBUGの可能性があります。

たぶん、そのプロパティ名を取得するためのより良い方法があるのか​​もしれません。


0

を使用してビルド中にファイルを移動する install

この問題は、ステップ9の CMake公式チュートリアルを実行しようとしたときに発生しました。これは、移動したいファイルの場所でした。

src
 |_build
    |_Debug
       - `MathFunctions.dll`

これは私がファイルを入れたい場所でした:

src
 |_build
    |_install
         |_bin
             - `MathFunctions.dll`

このDLLは、私がしたすべてはこの行を含めるようにし、共有ライブラリとして生成されたためCMakeLists.txt、サブディレクトリのライブラリのソースコードが含まれていsrc/Mathfunctions/CMakeLists.txt

install(FILES ${PROJECT_BINARY_DIR}/$<CONFIG>/MathFunctions.dll
DESTINATION bin)

あなたの答えのおかげで、私はこれについて考えることができました。1行だけなので大丈夫だと思います。には、プロジェクトの構築方法に応じて、元の質問で必要なように、デバッグまたはリリースの$<CONFIG> 2つの値を設定できます。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.