2012-05-20 35 views
65

Chúng tôi sử dụng CMake để tạo các tệp Visual Studio của các nguồn của chúng tôi trong SVN của chúng tôi. Bây giờ công cụ của tôi yêu cầu một số tệp DLL nằm trong cùng thư mục với tệp thực thi. Các tệp DLL nằm trong một thư mục bên cạnh nguồn.Làm thế nào để sao chép các tệp DLL vào cùng thư mục với tệp thực thi bằng CMake?

Làm cách nào để thay đổi CMakeLists.txt của mình sao cho dự án Visual Studio được tạo sẽ có tệp DLL cụ thể trong thư mục phát hành/gỡ lỗi hoặc sẽ sao chép chúng khi biên dịch?

Trả lời

79

Tôi muốn sử dụng add_custom_command để đạt được điều này cùng với cmake -E copy_if_different.... Để biết đầy đủ chạy

cmake --help-command add_custom_command 
cmake -E 


Vì vậy, trong trường hợp của bạn, nếu bạn có cấu trúc sau đây thư mục:

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

và mục tiêu CMake của bạn mà lệnh áp dụng là MyTest, sau đó bạn có thể thêm thông tin sau vào CMakeLists.txt của bạn:

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 


Nếu bạn chỉ muốn toàn bộ nội dung của thư mục /libs/ sao chép, sử dụng 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>) 


Nếu bạn cần phải sao chép dlls khác nhau tùy thuộc vào cấu hình (Release, Debug, ví dụ) sau đó bạn có thể có các thư mục con này được đặt tên theo cấu hình tương ứng: /libs/Release/libs/Debug. Sau đó bạn cần phải tiêm loại cấu hình vào đường dẫn đến dll trong add_custom_command cuộc gọi, như thế này:

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

Ghi chú nhanh về những gì đã hoạt động trong trường hợp của tôi trong trường hợp nó giúp người khác trong tương lai: Tôi có một dự án thư viện tĩnh mà thực thi chính liên kết tùy chọn chống lại, và thư viện đó yêu cầu một DLL được sao chép nếu được thêm vào. Vì vậy, trong tệp CMakeLists.txt của thư viện đó, tôi đã sử dụng '$ {CMAKE_RUNTIME_OUTPUT_DIRECTORY}/$ ' cho đích đích. Nếu không nó sẽ sao chép nó vào đường dẫn xây dựng thư viện, đó là vô ích. – AberrantWolf

1

Bạn có thể cần phải add custom target và làm cho nó phụ thuộc vào một trong các mục tiêu thực thi của bạn. Để sao chép tệp bằng cách sử dụng chức năng trên, hãy sử dụng

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

5

Một phụ lục cho câu trả lời được chấp nhận, thêm vào như là một câu trả lời riêng biệt vì vậy tôi nhận được mã định dạng:

Nếu bạn đang xây dựng các dll của mình trong cùng một dự án, chúng thường nằm trong các thư mục Release, Debug,…. Bạn sẽ phải sử dụng các biến môi trường Visual Studio để sao chép chính xác chúng. ví dụ .:

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

cho nguồn và

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

cho đến đích. Lưu ý thoát!

Bạn không thể sử dụng biến CMake CMAKE_BUILD_TYPE cho cấu hình vì nó được giải quyết tại thời gian tạo dự án VS và sẽ luôn là bất kỳ giá trị mặc định nào.

+5

Phần cuối cùng của câu trả lời được chấp nhận giải quyết vấn đề này theo cách thức CMake sạch hơn bằng cách sử dụng '$ ' –

1

này rất hữu ích cho một trong số họ

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) 
9

tôi đặt những dòng này trong tập tin CMakeLists.txt cấp cao nhất của tôi. Tất cả các thư viện và tệp thực thi sẽ được đặt ở cấp cao nhất của thư mục xây dựng để các tệp thực thi có thể tìm thấy các thư viện và rất dễ dàng để chạy mọi thứ.

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

Bạn cũng có thể sử dụng find_library lệnh:

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

Với EXECUTABLE_PATH xác định, ví dụ:

set(EXECUTABLE_OUTPUT_PATH ${PROJECT_BINARY_DIR}/bin) 

bạn có thể di chuyển các tập tin .dll đó cần thực thi của bạn, với

file(COPY ${<some_var>} 
    DESTINATION ${EXECUTABLE_OUTPUT_PATH}) 
Các vấn đề liên quan