स्थैतिक पुस्तकालयों को अन्य स्थैतिक पुस्तकालयों से जोड़ना


138

मेरे पास कोड का एक छोटा सा टुकड़ा है जो कई स्थिर पुस्तकालयों (a_1-a_n) पर निर्भर करता है। मैं उस कोड को स्टैटिक लाइब्रेरी में पैकेज करना चाहता हूं और इसे अन्य लोगों के लिए उपलब्ध कराना चाहता हूं।

मेरा स्थिर पुस्तकालय, इसे एक्स को कॉल करने देता है, ठीक संकलन करता है।

मैंने एक साधारण नमूना कार्यक्रम बनाया है जो एक्स से एक फ़ंक्शन का उपयोग करता है, लेकिन जब मैं इसे एक्स से लिंक करने का प्रयास करता हूं, तो मुझे पुस्तकालयों a_1 - a_n से लापता प्रतीकों के बारे में कई त्रुटियां मिलती हैं।

क्या कोई ऐसा तरीका है जिससे मैं एक नई स्टैटिक लाइब्रेरी बना सकता हूँ, Y जिसमें X है और X द्वारा आवश्यक सभी कार्यक्षमता है (a से एक चयनित बिट्स - a_n), ताकि मैं लोगों को उनके प्रोग्राम को लिंक करने के लिए सिर्फ Y वितरित कर सकूं?


अपडेट करें:

मैं बस के साथ सब कुछ डंपिंग देखा है ए आर और एक मेगा lib बनाने, तथापि, प्रतीकों कि आवश्यक नहीं हैं की एक बहुत कुछ (सभी ओ फ़ाइलों के बारे में 700 एमबी हैं सहित समाप्त हो जाती है, हालांकि, एक स्थिर जुड़ा हुआ निष्पादन 7 कि एमबी)। क्या वास्तव में आवश्यक केवल वही शामिल करने का एक अच्छा तरीका है?


यह बारीकी से संबंधित लगता है कि एक में कई सी / सी ++ पुस्तकालयों को कैसे संयोजित किया जाए?

जवाबों:


76

स्थैतिक पुस्तकालय अन्य स्थैतिक पुस्तकालयों के साथ लिंक नहीं करते हैं। ऐसा करने का एकमात्र तरीका यह है कि आप अपने लाइब्रेरियन / आर्चीवर टूल (उदाहरण के लिए लिनक्स पर ए.आर. ) का उपयोग करके एक से अधिक नई लाइब्रेरी को एक साथ बनाकर कई लाइब्रेरी को समेट सकते हैं।

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


हाय नील, मैंने सवाल अपडेट किया है - क्या आपको केवल .o फ़ाइलों को शामिल करने का कोई तरीका पता है जो आवश्यक हैं?
जेसन सुंदरम

अद्यतन - यदि आप खुद को ऐसा करने के लिए इच्छुक पाते हैं, तो एक कदम पीछे ले जाएँ, और कुछ और आगे बढ़ाएँ (जब तक कि जॉन नूलेर बताते हैं, आप विज़ुअल स्टूडियो का उपयोग कर रहे हैं)। मैं इस दृष्टिकोण में बहुत समय तक डूब गया और कुछ भी उपयोगी नहीं मिला।
जेसन सुंदरम

GNU ld टूल एक विकल्प प्रदान करता है -rजिसके साथ आउटपुट का उपयोग ld के इनपुट के रूप में किया जा सकता है। यदि आप एक बार लिंक करते हैं, तो आपको एक रीकॉन्सेबल मिलना चाहिए जो आपके पुस्तकालयों को सरोगेट कर सकता है। (यह करने की कोशिश की थी)।
हार्पर

49

यदि आप विजुअल स्टूडियो का उपयोग कर रहे हैं तो हां, आप ऐसा कर सकते हैं।

विज़ुअल स्टूडियो के साथ आने वाला लाइब्रेरी बिल्डर टूल आपको कमांड लाइन पर एक साथ पुस्तकालयों से जुड़ने की अनुमति देता है। मैं दृश्य संपादक में यह करने के लिए किसी भी तरह का पता नहीं है, हालांकि।

lib.exe /OUT:compositelib.lib  lib1.lib lib2.lib

5
VS2008 में, लाइब्रेरियन / जनरल के तहत कंपोजिटेलिब के प्रोजेक्ट गुणों में, यदि आप [x] लिंक लाइब्रेरी डिपेंडेंसीज की जांच करते हैं, तो यह आपके लिए ऐसा करेगा यदि lib1 और lib2 कंपोजिटेलिब की निर्भरता हैं। यह थोड़ा छोटा लगता है, मैं प्रत्येक बिल्ड कॉन्फ़िगरेशन में अलग से चेकबॉक्स सेट करूँगा, एक बार 'सभी कॉन्फ़िगरेशन' में नहीं।
स्पाइकएक्सएक्सएफ

2
VS2015 IDE - क्या आप लाइब्रेरियन / जनरल के तहत "अतिरिक्त आश्रितों" का उपयोग नहीं करते हैं जिससे आपकी परियोजना का निर्माण हो रहा है और लाइब्रेरी से सीधे जुड़े हुए अतिरिक्त पुस्तकालय मिलेंगे?
दाविदक

@davidbak मैं पिछले कुछ दिनों में इसका पता लगाने की कोशिश कर रहा हूं और जाहिर है कि यह विकल्प अप्रचलित है और कुछ भी नहीं करता है?
मोंटाल्डो

20

जीएनयू टूलकिन के साथ लिनक्स या मिंगडब्ल्यू पर:

ar -M <<EOM
    CREATE libab.a
    ADDLIB liba.a
    ADDLIB libb.a
    SAVE
    END
EOM
ranlib libab.a

यदि आप नहीं हटाते हैं liba.aऔर libb.a, आप "पतली संग्रह" बना सकते हैं:

ar crsT libab.a liba.a libb.a

MSVC टूलकिन के साथ विंडोज पर:

lib.exe /OUT:libab.lib liba.lib libb.lib

जानकर अच्छा लगा, लेकिन वास्तव में ओपी की समस्या का समाधान नहीं किया गया है, क्योंकि आप libb.a से सबकुछ संयुक्त कार्य में शामिल कर रहे हैं, जो कि बहुत बड़ी हो सकती है यदि आपको libb से केवल कुछ मॉड्यूल की आवश्यकता हो।
एल्मर जेंडर

1
@ElmarZander लेकिन आप उपयोग कर सकते हैं ar crsT, जो कॉपी करने के बजाय "सिमिलिंकिंग" जैसा कुछ करता है, तो आपको केवल डेटा की एक प्रति को शिप करने की आवश्यकता है।
स्टार ब्रिलियंट

लिनक्स कर्नेल v4.19 पर पतले अभिलेखों का विशेष रूप से उपयोग किया जाता है: unix.stackexchange.com/questions/5518/…
Ciro Santilli 郝海东 not not not not not

10

एक स्थिर लाइब्रेरी सिर्फ .oऑब्जेक्ट फ़ाइलों का एक संग्रह है । उन्हें ar(यूनिक्स मानकर) निकालें और उन्हें एक बड़े पुस्तकालय में वापस पैक करें।


6

वैकल्पिक रूप से Link Library Dependenciesप्रोजेक्ट प्रॉपर्टीज में विजुअल स्टूडियो में लाइब्रेरी को लिंक करने का एक और तरीका है।

  1. लाइब्रेरी (X) का प्रोजेक्ट खोलें जिसे आप अन्य लाइब्रेरीज़ के साथ जोड़ना चाहते हैं।
  2. एक्स (राइट क्लिक Add Existing Item...) के साथ आप जो अन्य पुस्तकालय चाहते हैं, उन्हें जोड़ें ।
  3. उनके गुणों पर जाएं और सुनिश्चित करें कि Item TypeहैLibrary

इसमें X में अन्य पुस्तकालय शामिल होंगे जैसे कि आप भाग गए

lib /out:X.lib X.lib other1.lib other2.lib

नमस्ते, मैं इंटेल आईपीपी का उपयोग कर रहा हूं और मैंने अपने स्वयं के कार्यों का निर्माण किया है जो मैं चाहता हूं कि सभी को एक (स्टेटिक) लिबास में लपेटा जाए। फिर भी जब मैं लिब बनाता हूं और तब प्रोजेक्ट को दूसरे कंप्यूटर पर भेजता हूं जिसे मैं केवल उस लिब का उपयोग करके प्रोजेक्ट को संकलित करने में सक्षम होना चाहता हूं जिसे मैंने बनाया है, मुझे यह कहते हुए त्रुटि मिलती है कि इंटेल आईपीपी लाइब्रेरी की एक .h फ़ाइल की आवश्यकता है। कोई उपाय?
रॉय

लीब फाइल आमतौर पर पर्याप्त नहीं है। यदि आप इसका उपयोग करना चाहते हैं, तो आपको हेडर फ़ाइलों को भी शामिल करना होगा। लेकिन यह विषय यहाँ है क्योंकि यह थ्रेड लिंकिंग के बारे में बात करता है और आपकी समस्या संकलन चरण में है।
शाम

ठीक है। आपकी सहायता के लिए मुझे अधिक जानकारी की आवश्यकता होगी। बिल्ड आउटपुट देखें या लॉग करें और देखें कि गुमशुदा .h फ़ाइल पर क्या शिकायत है। मुझे लगता है कि यह cl.exe है। यदि ऐसा है, तो यह आपको संकलित का उपयोग करने वाले संकलित .cpp / .cc / .c फ़ाइल का नाम देगा। उस .cpp फ़ाइल का नाम क्या है और वह किस परियोजना की है?
इम्पो

मैं बहुत उलझा हुआ हूं। इससे पहले कि मैं इसे पढ़ूं, ऐसा लगता है कि यह कभी काम नहीं किया (यह मेरी परियोजनाओं को पहले से ही कॉन्फ़िगर किया गया है)। लेकिन अब जब मैंने इसे पढ़ लिया है और अपनी परियोजनाओं को रीसेट कर रहा हूं, तो यह स्पष्ट रूप से काम कर रहा है। जाओ पता लगाओ! :(
मोर्दकै

1
@Mordachai नीचे इस हाइकु आपके अनुभव को पूरी तरह से बताता है: कल यह काम किया था आज यह काम नहीं कर रहा है विंडोज ऐसा है
6'18

5

बाकी पढ़ने से पहले ध्यान दें: यहां दिखाई गई शेल स्क्रिप्ट निश्चित रूप से उपयोग करने के लिए सुरक्षित नहीं है और अच्छी तरह से परीक्षण की गई है। अपने जोखिम पार इस्तेमाल करें!

मैंने उस कार्य को पूरा करने के लिए एक बैश स्क्रिप्ट लिखी। मान लीजिए कि आपकी लाइब्रेरी lib1 है और जिस पर आपको कुछ प्रतीकों को शामिल करना है, वह है lib2। स्क्रिप्ट अब एक लूप में चलती है, जहां यह पहली बार जांचती है कि lib1 से अपरिभाषित प्रतीकों को lib2 में पाया जा सकता है। यह तब lib2 से संगत ऑब्जेक्ट फ़ाइलों को निकालता है ar, उन्हें थोड़ा नाम देता है, और उन्हें lib1 में डालता है। अब और अधिक लापता प्रतीक हो सकते हैं, क्योंकि lib2 से आपके द्वारा शामिल किए गए सामान को lib2 से अन्य सामान की आवश्यकता होती है, जिसे हमने अभी तक शामिल नहीं किया है, इसलिए लूप को फिर से चलाने की आवश्यकता है। यदि लूप के कुछ पास होने के बाद अब कोई परिवर्तन नहीं होता है, यानी lib2 से कोई भी ऑब्जेक्ट lib1 में नहीं जोड़ा जाता है, तो लूप बंद हो सकता है।

ध्यान दें, कि शामिल किए गए प्रतीकों को अभी भी अपरिभाषित के रूप में सूचित किया गया है nm, इसलिए मैं ऑब्जेक्ट फ़ाइलों का ट्रैक रख रहा हूं, जो कि लूप को रोका जा सकता है, यह निर्धारित करने के लिए, lib1 में खुद को जोड़ा गया था।

#! /bin/bash

lib1="$1"
lib2="$2"

if [ ! -e $lib1.backup ]; then
    echo backing up
    cp $lib1 $lib1.backup
fi

remove_later=""

new_tmp_file() {
    file=$(mktemp)
    remove_later="$remove_later $file"
    eval $1=$file
}
remove_tmp_files() {
    rm $remove_later
}
trap remove_tmp_files EXIT

find_symbols() {
    nm $1 $2 | cut -c20- | sort | uniq 
}

new_tmp_file lib2symbols
new_tmp_file currsymbols

nm $lib2 -s --defined-only > $lib2symbols

prefix="xyz_import_"
pass=0
while true; do
    ((pass++))
    echo "Starting pass #$pass"
    curr=$lib1
    find_symbols $curr "--undefined-only" > $currsymbols
    changed=0
    for sym in $(cat $currsymbols); do
        for obj in $(egrep "^$sym in .*\.o" $lib2symbols | cut -d" " -f3); do
            echo "  Found $sym in $obj."
            if [ -e "$prefix$obj" ]; then continue; fi
            echo "    -> Adding $obj to $lib1"
            ar x $lib2 $obj
            mv $obj "$prefix$obj"
            ar -r -s $lib1 "$prefix$obj"
            remove_later="$remove_later $prefix$obj"
            ((changed=changed+1))
        done
    done
    echo "Found $changed changes in pass #$pass"

    if [[ $changed == 0 ]]; then break; fi
done

मैंने उस स्क्रिप्ट को नाम दिया है libcomp, इसलिए आप इसे तब जैसे उदाहरण के साथ कह सकते हैं

./libcomp libmylib.a libwhatever.a

जहाँ libwhatever है जहाँ से आप प्रतीकों को शामिल करना चाहते हैं। हालांकि, मुझे लगता है कि पहले सब कुछ एक अलग निर्देशिका में कॉपी करना सबसे सुरक्षित है। मुझे अपनी स्क्रिप्ट पर इतना भरोसा नहीं होगा (हालाँकि, इसने मेरे लिए काम किया; मैं libgsl.a को अपनी संख्यात्मक लाइब्रेरी में शामिल कर सकता हूं और उस -lgsl कंपाइलर स्विच को छोड़ सकता हूं)।

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