CML का उपयोग करके निष्पादन योग्य के समान DLL फ़ाइलों को कॉपी कैसे करें?


98

हम अपने SVN में हमारे स्रोतों की विज़ुअल स्टूडियो फ़ाइलों को बनाने के लिए CMake का उपयोग करते हैं। अब मेरे टूल को निष्पादन योग्य के रूप में कुछ DLL फ़ाइलों को उसी फ़ोल्डर में रखने की आवश्यकता है। DLL फाइलें स्रोत के साथ एक फ़ोल्डर में हैं।

मैं अपनी CMakeLists.txtऐसी कैसे बदल सकता हूं कि उत्पन्न विज़ुअल स्टूडियो प्रोजेक्ट में या तो रिलीज़ / डीबग फ़ोल्डर में पहले से ही विशेष 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>)


यदि आपको कॉन्फ़िगरेशन (रिलीज़, डीबग, उदा) के आधार पर अलग-अलग डीएल को कॉपी करने की आवश्यकता है, तो आपके पास इन सबडायरेक्टरीज को संबंधित कॉन्फ़िगरेशन के साथ नामित किया जा सकता है: /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>लक्ष्य गंतव्य के लिए उपयोग किया । अन्यथा यह इसे लाइब्रेरी बिल्ड पथ पर कॉपी कर देगा, जो बेकार था।
अबरैंटवुल्फ़

क्या यह install()बायनेरिज़ को इकट्ठा करने के लिए सीमेक निर्देशों का लक्ष्य नहीं है ? या हो सकता है सीमेक LIBRARYचीजें? मैं वास्तव में टूलकिन नहीं जानता।
सेंडबर्ग

1
$<TARGET_FILE_DIR:MyTest>- यह क्या है? जानकारी कैसे प्रिंट करें, इसका क्या मतलब है
ilw

जब तक मैं कुछ याद नहीं करता जब मैं कमांड को एकीकृत कर रहा था यह विधि पुस्तकालयों के साथ काम नहीं करती है IMPORTED_LIBRARIES। यह शिकायत करता है कि जब कुछ भी नहीं बनाया गया है तो पोस्ट-बिल्ड कमांड चलाने में सक्षम नहीं है।
तज़ुल्मेन

2
मेरे cmake का परीक्षण करने और उसे बदलने पर: यदि आप IMPORTEDपुस्तकालयों का उपयोग कर रहे हैं , और DLL को स्थानांतरित करने की आवश्यकता है, तो आपको एक वेरिएंट कमांड का उपयोग करने की आवश्यकता है। यदि आपने अपनी IMPORTEDलाइब्रेरी को जोड़ा है, तो 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#)
बांधने की आवश्यकता है

24

मैंने इन पंक्तियों को अपने शीर्ष-स्तरीय CMakeLists.txt फ़ाइल में डाला। CMake द्वारा संकलित सभी पुस्तकालयों और निष्पादनों को बिल्ड डायरेक्टरी के शीर्ष स्तर पर रखा जाएगा, ताकि निष्पादक पुस्तकालयों को खोज सकें और सब कुछ चलाना आसान हो।

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

ध्यान दें कि यह परियोजना के स्रोत निर्देशिका से precompiled binaries को कॉपी करने की ओपी की समस्या को हल नहीं करता है।


7

मुझे आज यह समस्या आई है जब मैंने अपने प्रोग्राम का विंडोज बनाने की कोशिश की। और मैंने खुद ही कुछ शोध करना समाप्त कर दिया क्योंकि इन सभी उत्तरों ने मुझे संतुष्ट नहीं किया। तीन मुख्य मुद्दे थे:

  • मैं चाहता था कि डिबग का निर्माण पुस्तकालयों के डिबग संस्करणों के साथ जोड़ा जाए और रिलीज़ बिल्ड क्रमशः पुस्तकालयों के रिलीज़ बिल्ड के साथ जोड़ा जाए।

  • इसके अलावा, मैं चाहता था कि आउटपुट निर्देशिकाओं के लिए DLL फ़ाइलों (डीबग / रिलीज़) के सही संस्करणों को कॉपी किया जाए।

  • और मैं जटिल और नाजुक स्क्रिप्ट लिखे बिना यह सब हासिल करना चाहता था।

कुछ सीएमके मैनुअल और कुछ मल्टीप्लेट रिकॉर्डर प्रोजेक्ट्स को जीथब में ब्राउज़ करने के बाद मैंने इसका हल ढूंढा है:

अपनी लाइब्रेरी को "महत्वपूर्ण" विशेषता के साथ एक लक्ष्य के रूप में घोषित करें, इसके डिबग और रिलीज़ .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

स्वीकृत उत्तर के लिए एक परिशिष्ट, एक अलग उत्तर के रूप में जोड़ा गया ताकि मुझे कोड स्वरूपण मिल जाए:

यदि आप एक ही परियोजना में अपने dlls का निर्माण कर रहे हैं, तो वे आम तौर पर रिलीज़, डीबग, आदि निर्देशिकाओं में होंगे। आपको उन्हें ठीक से कॉपी करने के लिए Visual Studio वातावरण चर का उपयोग करना होगा। उदाहरण के लिए:

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

स्रोत के लिए और

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

गंतव्य के लिए। भागने पर ध्यान दें!

आप कॉन्फ़िगरेशन के लिए CMake CMAKE_BUILD_TYPE चर का उपयोग नहीं कर सकते क्योंकि यह वीएस प्रोजेक्ट जनरेशन समय पर हल हो गया है और हमेशा डिफ़ॉल्ट होगा।


8
स्वीकृत उत्तर का अंतिम भाग क्लीनर $<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

यह उनमें से एक के लिए उपयोगी है

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

आपको संभवतः कस्टम लक्ष्य जोड़ने और इसे अपने निष्पादन योग्य लक्ष्यों में से एक पर निर्भर करने की आवश्यकता है।

उपरोक्त फ़ंक्शन का उपयोग करके फ़ाइल की प्रतिलिपि बनाने के लिए:

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

0

मैं एक 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)

आपके जवाबों की बदौलत मैं इस पर सोच सका। सिर्फ एक लाइन है, इसलिए मुझे लगता है कि ठीक है। डिबग या रिलीज़ के$<CONFIG> दो मूल्य हो सकते हैं, यह इस बात पर निर्भर करता है कि प्रोजेक्ट कैसे बनाया गया है, मूल प्रश्न के रूप में आवश्यक है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.