2012-01-08 18 views
77

सीएमके को निष्पादन योग्य को बाहरी साझा लाइब्रेरी में जोड़ने के लिए कैसे मिलता है जो एक ही सीएमके परियोजना के भीतर नहीं बनता है?बाहरी पुस्तकालय के लिए सीएमके लिंक

बस कर target_link_libraries(GLBall ${CMAKE_BINARY_DIR}/res/mylib.so) मैं द्विआधारी निर्देशिका bin/res में पुस्तकालय की नकल की बाद त्रुटि

make[2]: *** No rule to make target `res/mylib.so', needed by `GLBall'. Stop. 
make[1]: *** [CMakeFiles/GLBall.dir/all] Error 2 
make: *** [all] Error 2 
(GLBall is the executable) 

देता है।

मैं find_library(RESULT mylib.so PATHS ${CMAKE_BINARY_DIR}/res)

कौन सा RESULT-NOTFOUND के साथ विफल उपयोग करने की कोशिश।

उत्तर

67

सेट पुस्तकालयों खोज पहले पथ:

LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/res) 

और फिर बस

TARGET_LINK_LIBRARIES(GLBall mylib) 
+0

धन्यवाद! – Prime

+22

की [ 'link_directories'] (http://www.cmake.org/cmake/help/v2.8.10/cmake.html#command:link_directories) हतोत्साहित किया जाता है उपयोग करते हैं, यहां तक ​​कि अपने स्वयं के दस्तावेज में।मुझे लगता है कि मूल प्रश्न में विफल 'find_library' कॉल को हल करने के लिए बेहतर होगा, या @ आंद्रे के समाधान का उपयोग करें। – Fraser

+3

मुझे "आयातित" लाइब्रेरी लक्ष्य अधिक मजबूत होने के लिए मिलता है, क्योंकि यह विशेष लाइब्रेरी के स्थान को लक्षित करता है, बल्कि वैश्विक खोज पथ देता है। आंद्रे का जवाब देखें। –

79

arrowdodger के जवाब सही और कई अवसरों पर प्राथमिकता दी है। मैं बस अपने उत्तर में एक विकल्प जोड़ना चाहता हूं:

आप एक लिंक-निर्देशिका के बजाय "आयातित" लाइब्रेरी लक्ष्य जोड़ सकते हैं। कुछ की तरह:

# Your-external "mylib", add GLOBAL if the imported library is located in directories above the current. 
add_library(mylib SHARED IMPORTED) 
# You can define two import-locations: one for debug and one for release. 
set_target_properties(mylib PROPERTIES IMPORTED_LOCATION ${CMAKE_BINARY_DIR}/res/mylib.so) 

और फिर के रूप में लिंक अगर यह पुस्तकालय अपनी परियोजना द्वारा बनाया गया था: add_library() कमान और पर एक नज़र डालें:

TARGET_LINK_LIBRARIES(GLBall mylib) 

इस तरह के एक दृष्टिकोण आप थोड़ा और अधिक लचीलापन देना होगा many target-properties related to imported libraries

मुझे नहीं पता कि यह "libs के अद्यतन संस्करण" के साथ आपकी समस्या का समाधान करेगा या नहीं।

+2

कि शायद होगा ' add_library (mylib साझा आयातित) ' या आप एक' add_library आयातित तर्क है, लेकिन कोई पुस्तकालय type' त्रुटि – Marvin

+1

@Marvin के साथ बुलाया मिल उद्घाटन ब्रैकेट गलत है –

+4

@Andre:: मैं के बाद लगता है कि 'IMPORTED_LOCATION' – Ela782

3

एक और विकल्प, यदि आप ऐपस्टोर के साथ काम कर रहे हैं, तो "एंटाइटेलमेंट्स" की आवश्यकता है और ऐप्पल-फ्रेमवर्क से लिंक करने की आवश्यकता है।

पात्रता काम करने के लिए (उदाहरण के लिए GameCenter) आप जरूरत -buildstep एक "पुस्तकालय के साथ लिंक बाइनरी" है और उसके बाद के लिए "GameKit.framework" के साथ लिंक। सीएमके कमांडलाइन में "निम्न स्तर" पर पुस्तकालयों को इंजेक्ट करता है, इसलिए एक्सकोड वास्तव में इसके बारे में नहीं जानता है, और इस तरह आप क्षमता स्क्रीन में गेमकिट सक्षम नहीं करेंगे।

सीएमके का उपयोग करने के लिए एक तरीका है और "बैनरीज के साथ लिंक" है- बिल्डस्टेप सीएमके के साथ xcodeproj उत्पन्न करना है, और फिर 'sed' का उपयोग '& प्रतिस्थापित करें' पर करें और XCode को पसंद करते हुए गेमकिट जोड़ें। ..

स्क्रिप्ट इस तरह दिखता है (एक्सकोड 6.3.1 के लिए)।

s#\/\* Begin PBXBuildFile section \*\/#\/\* Begin PBXBuildFile section \*\/\ 
    26B12AA11C10544700A9A2BA \/\* GameKit.framework in Frameworks \*\/ = {isa = PBXBuildFile; fileRef = 26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/; };#g 

s#\/\* Begin PBXFileReference section \*\/#\/\* Begin PBXFileReference section \*\/\ 
    26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GameKit.framework; path = System\/Library\/Frameworks\/GameKit.framework; sourceTree = SDKROOT; };#g 

s#\/\* End PBXFileReference section \*\/#\/\* End PBXFileReference section \*\/\ 
\ 
\/\* Begin PBXFrameworksBuildPhase section \*\/\ 
    26B12A9F1C10543B00A9A2BA \/\* Frameworks \*\/ = {\ 
     isa = PBXFrameworksBuildPhase;\ 
     buildActionMask = 2147483647;\ 
     files = (\ 
      26B12AA11C10544700A9A2BA \/\* GameKit.framework in Frameworks xxx\*\/,\ 
     );\ 
     runOnlyForDeploymentPostprocessing = 0;\ 
    };\ 
\/\* End PBXFrameworksBuildPhase section \*\/\ 
#g 

s#\/\* CMake PostBuild Rules \*\/,#\/\* CMake PostBuild Rules \*\/,\ 
      26B12A9F1C10543B00A9A2BA \/\* Frameworks xxx\*\/,#g 
s#\/\* Products \*\/,#\/\* Products \*\/,\ 
      26B12AA01C10544700A9A2BA \/\* GameKit.framework xxx\*\/,#g 

"gamecenter.sed" को यह बचाने के लिए और उसके बाद इस तरह "लागू" यह (यह अपने xcodeproj बदलता!)

sed -i.pbxprojbak -f gamecenter.sed myproject.xcodeproj/project.pbxproj 

आप स्क्रिप्ट आदेशों को बदलने के लिए अपनी जरूरत फिट करने के लिए हो सकता है ।

चेतावनी: यह विभिन्न एक्सकोड-संस्करण के साथ तोड़ने की संभावना है क्योंकि प्रोजेक्ट-प्रारूप बदल सकता है, (हार्डकोडेड) अद्वितीय संख्या वास्तव में अद्वितीय नहीं हो सकती है - और आम तौर पर अन्य लोगों द्वारा समाधान बेहतर होते हैं - इसलिए जब तक आपको आवश्यकता नहीं होती Appstore + एंटाइटेलमेंट्स (और स्वचालित बिल्ड) का समर्थन करें, ऐसा मत करें।

यह एक CMake बग, देख http://cmake.org/Bug/view.php?id=14185 और http://gitlab.kitware.com/cmake/cmake/issues/14185

+0

विशेष रूप से - बाहरी लाइब्रेरी से लिंक करने के लिए सेमेक प्राप्त करना समस्या नहीं है (ऊपर कई समाधान हैं)। इसे स्वचालित तरीके से काम करने के लिए प्राप्त करना, ताकि यह ऐप्पल ऐपस्टोर * और * एंटाइटेलमेंट्स के साथ काम करता है एक चुनौती है। उस विशिष्ट मामले में, उपर्युक्त समाधान काम नहीं करते हैं क्योंकि एक्सकोड उस तरह से जुड़े पुस्तकालयों को 'नहीं देख पाएगा, और एंटाइटेलमेंट अभी काम नहीं करेगा। अफैक सेमेक मुक्ति को जोड़ नहीं सकता जिस तरह से एक्सकोड को 'एपस्टोर-संगत तरीके' में चाहिए, फिर से, मुझे प्रबुद्ध करने के लिए स्वतंत्र महसूस करें। – kalmiya

+1

यहां आप यहां जाएं: https://cmake.org/Bug/view.php?id=14185, मैंने एक साल पहले पोस्ट किया था। – kalmiya

+1

ओह, यह दुखद है। नए मुद्दे ट्रैकर के लिंक को पूरा करने के लिए, जिसमें वर्तमान में कोई कॉमनेट नहीं है: https://gitlab.kitware.com/cmake/cmake/issues/14185 – usr1234567

24

मुझे लगता है आप किसी लाइब्रेरी foo बुलाया लिंक करना चाहते है, इसका फ़ाइल नाम आमतौर पर कुछ लिंक foo.dll या libfoo.so है।

1. पुस्तकालय
आप पुस्तकालय खोजने के लिए का पता लगाएं। यह एक अच्छा विचार है, भले ही आप अपनी लाइब्रेरी के पथ को जानते हों। अगर पुस्तकालय गायब हो गया या नया नाम मिला तो सीएमके को गलती होगी। यह जल्दी त्रुटि को पहचानने में मदद करता है और उपयोगकर्ता को स्पष्ट करता है (स्वयं हो सकता है) किसी समस्या का कारण बनता है।
एक पुस्तकालय foo खोजने के लिए और FOO_LIB उपयोग

find_library(FOO_LIB foo) 

CMake बाहर ही समझ जाएगा कि वास्तविक फ़ाइल का नाम है में पथ में संग्रह करना। यह /usr/lib, /usr/lib64 की तरह सामान्य स्थानों और PATH में रास्तों की जाँच करता है।

आप पहले से ही अपनी लाइब्रेरी का स्थान पता है। जब आप सीएमके को कॉल करते हैं तो इसे CMAKE_PREFIX_PATH पर जोड़ें, फिर सीएमके भी पास की पथों में आपकी लाइब्रेरी की तलाश करेगा।

कभी-कभी आप जानकारी के लिए संकेत या पथ प्रत्यय जोड़ने के लिए, दस्तावेज़ देखें की जरूरत है: https://cmake.org/cmake/help/latest/command/find_library.html

2. लिंक पुस्तकालय 1. से आप FOO_LIB में पूरी लाइब्रेरी नाम होता है। आप

target_link_libraries(mylib "${FOO_LIB}") 

में के रूप में अपने लक्ष्य mylib के पुस्तकालय से जोड़ने के लिए इस का उपयोग आप पुस्तकालय, cf के सामने PRIVATE, PUBLIC, या INTERFACE जोड़ सकते हैं प्रलेखन: https://cmake.org/cmake/help/latest/command/target_link_libraries.html

3. जोड़ेंभी शामिल है (यह कदम अनिवार्य नहीं हो सकता है।)
आप भी हेडर फाइल शामिल find_path समान का उपयोग find_library के लिए और एक हेडर फाइल के लिए खोज करना चाहते हैं। फिर के साथ target_link_libraries के साथ निर्देशिका शामिल करें।

प्रलेखन: https://cmake.org/cmake/help/latest/command/find_path.html और https://cmake.org/cmake/help/latest/command/target_include_directories.html

तो बाहरी सॉफ्टवेयर के लिए उपलब्ध है, तो आप find_package द्वारा find_library और find_path बदल सकते हैं। बहुत ज्यादा

+2

IMHO यह सबसे अच्छा जवाब है। हालांकि, मुझे परेशानी थी क्योंकि मैं "add_executable" के बाद "प्रोजेक्ट" और "target_link_libraries" के बाद "find_library" को नहीं बुला रहा था। – smoothware

संबंधित मुद्दे