बाहरी पुस्तकालय के लिए सीएमके लिंक


126

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

बस करने target_link_libraries(GLBall ${CMAKE_BINARY_DIR}/res/mylib.so)से त्रुटि हो जाती है

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)

लाइब्रेरी को बाइनरी डायर में कॉपी करने के बाद bin/res

मैंने प्रयोग करने की कोशिश की find_library(RESULT mylib.so PATHS ${CMAKE_BINARY_DIR}/res)

जो असफल हो जाता है RESULT-NOTFOUND

जवाबों:


101

पहले लाइब्रेरी खोज पथ सेट करें:

LINK_DIRECTORIES(${CMAKE_BINARY_DIR}/res)

और फिर बस करो

TARGET_LINK_LIBRARIES(GLBall mylib)

44
के उपयोग link_directoriesको हतोत्साहित किया जाता है, यहां तक ​​कि अपने स्वयं के प्रलेखन में भी। मुझे लगता है find_libraryकि मूल प्रश्न में असफल कॉल को हल करने के लिए यहां बेहतर होगा , या @ आंद्रे के समाधान का उपयोग करें।
फ्रेजर

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

1
आपको हमेशा find_libraryकठिन कोडिंग के बजाय इस रास्ते का उपयोग और उपयोग करना चाहिए , सीएफ। मेरा जवाब है
usr1234567

121

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

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

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

और फिर लिंक करें जैसे कि यह पुस्तकालय आपकी परियोजना द्वारा बनाया गया था:

TARGET_LINK_LIBRARIES(GLBall mylib)

इस तरह का दृष्टिकोण आपको थोड़ा और लचीलापन देगा: add_library () कमांड और आयातित पुस्तकालयों से संबंधित कई लक्ष्य-गुणों पर एक नज़र डालें ।

मुझे नहीं पता कि यह आपकी समस्या को "अपडेट किए गए संस्करणों के साथ" हल करेगा।


2
यह शायद होगा add_library( mylib SHARED IMPORTED )या आपको एक add_library called with IMPORTED argument but no library typeत्रुटि मिलेगी
मार्विन

4
@Andre: मुझे लगता है IMPORTED_LOCATIONकि ओपनिंग ब्रैकेट के गलत होने के बाद
Ela782

5
आप जोड़ने की जरूरत है GLOBALके बाद IMPORTED: यदि आप वर्तमान ऊपर निर्देशिका में आयातित लाइब्रेरी का उपयोग करना चाहते हैंadd_library(breakpad STATIC IMPORTED GLOBAL)
रोमन क्रूगलोव

@Andre IMPORTED_LOCATION को फ़ाइल के डायरेक्टरी के बजाय फ़ाइल में पथ की आवश्यकता प्रतीत होती है
SOUser

1
@ उपयोगकर्ता: हाँ, IMPORTED_LOCATION को फ़ाइल को इंगित करना चाहिए, निर्देशिका को नहीं। मैंने तय किया है कि, लगता है कि लेखक शिकायत नहीं करेगा।
त्सेवेरेव

64

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

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

    find_library(FOO_LIB foo)

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

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

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

2. लाइब्रेरी को लिंक करें 1 से आपके पास पूरी लाइब्रेरी का नाम है FOO_LIB। आप अपने लक्ष्य को पुस्तकालय से जोड़ने के लिए इस का उपयोग GLBallके रूप में

  target_link_libraries(GLBall PRIVATE "${FOO_LIB}")

आप जोड़ना चाहिए PRIVATE, PUBLICया INTERFACEलक्ष्य, cf के बाद प्रलेखन: https://cmake.org/cmake/help/latest/command/target_link_lbooks.html

आप इन दृश्यता विनिर्देशक में से एक नहीं जोड़ते हैं तो, यह या तो की तरह व्यवहार करेगा PRIVATEया PUBLIC, CMake संस्करण और नीतियों सेट पर निर्भर करता है।

3. शामिल करें (यह कदम अनिवार्य नहीं हो सकता है।)
यदि आप हेडर फ़ाइलों को भी शामिल करना चाहते हैं, तो हेडर फ़ाइल के find_pathसमान find_libraryऔर खोज करें। फिर target_include_directoriesसमान के साथ शामिल निर्देशिका जोड़ें 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_libraryऔर find_pathद्वारा find_package


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

1
find_packageइतना इन चरणों का पालन से अधिक आसान है
activedecay

2
मुझे लगता है कि मैं चरण 2 को नहीं समझता हूं। एक साझा पुस्तकालय के लिए $ {FOO_LIB} /full /path/to/libfoo.dylib की तरह होगा। यह कैसे उपयोगी है? target_link_lbooks "-L / full / path / -lfoo" नहीं बना रहा है, इसलिए find_library कुछ भी उपयोगी नहीं दे रही है, यह सत्यापित करने के अलावा कि लाइब्रेरी उस स्थान पर है जहां मैं पहले से ही जानता हूं। मैं क्या खो रहा हूँ?
गुइमैक

target_link_libraries(mylib "${FOO_LIB}")? लक्ष्य mylibउसके वास्तविक लक्ष्य के बजाय है GLBall? मुझे इससे कोई मतलब नहीं है
बर्सन

5

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

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

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

स्क्रिप्ट इस तरह दिखती है (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

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

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

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


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

1
ओह दुख की बात है। नए इश्यू ट्रैकर के लिंक को पूर्णता के लिए, जिसमें वर्तमान में कोई भी कॉमनेट
usr1234567

समस्या 5 महीने पहले हल हो गई थी, इसलिए सीएमके के हालिया संस्करण के साथ इसे अब मौजूद नहीं होना चाहिए। देखें gitlab.kitware.com/cmake/cmake/issues/14185
usr1234567
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.