2009-04-30 8 views
25

मैंने देखा है कि --whole-archive लिंकर विकल्प का एकमात्र वास्तविक उपयोग स्थिर लोगों से साझा पुस्तकालय बनाने में है। हाल ही में मैं मेकफ़ाइल (ओं) में आया जो घर स्थिर पुस्तकालयों में लिंक करते समय हमेशा इस विकल्प का उपयोग करता है। यह निश्चित रूप से निष्पादन योग्य वस्तुओं को अनावश्यक रूप से बिना संदर्भित ऑब्जेक्ट कोड में खींचने का कारण बनता है। मेरी प्रतिक्रिया यह थी कि यह सादा गलत है, क्या मुझे यहां कुछ याद आ रही है?एलडी लिंकर प्रश्न: - व्हाहोल-संग्रह विकल्प

दूसरा प्रश्न मुझे पूरे संग्रह विकल्प के बारे में पढ़ने के साथ कुछ करना है लेकिन काफी पार्स नहीं कर सका। इस प्रभाव के लिए कुछ --whole-archive विकल्प का उपयोग स्थिर पुस्तकालय से लिंक करते समय किया जाना चाहिए यदि निष्पादन योग्य एक साझा लाइब्रेरी से भी लिंक करता है जो बदले में (उसी भाग में) स्थिर लाइब्रेरी के समान ऑब्जेक्ट कोड होता है। वह साझा लाइब्रेरी है और स्थैतिक पुस्तकालय ऑब्जेक्ट कोड के संदर्भ में ओवरलैप है। इस विकल्प का उपयोग निष्पादन योग्य में सभी प्रतीकों (उपयोग के बावजूद) को हल करने के लिए मजबूर करेगा। यह ऑब्जेक्ट कोड डुप्लिकेशन से बचने के लिए माना जाता है। यह भ्रमित है, अगर कार्यक्रम में एक प्रतीक को रेफरी किया जाता है तो इसे लिंक समय पर विशिष्ट रूप से हल किया जाना चाहिए, यह व्यवसाय नकल के बारे में क्या है? (मुझे माफ कर दो तो निम्न अनुच्छेद काफी स्पष्टता का प्रतीक नहीं है)

धन्यवाद

उत्तर

3

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

प्रश्न के आपके दूसरे भाग के रूप में। यदि एक निष्पादन योग्य एक स्थिर पुस्तकालय और गतिशील लाइब्रेरी दोनों को लिंक करता है जिसमें (भाग में) स्थिर लाइब्रेरी के समान ऑब्जेक्ट कोड है तो -whole-archive यह सुनिश्चित करेगा कि लिंक समय पर स्थिर लाइब्रेरी से कोड को प्राथमिकता दी जा सके । यह आमतौर पर वही होता है जब आप स्थिर लिंकिंग करते हैं।

50

स्थिर पुस्तकालयों के साथ निष्पादन योग्य लिंक करते समय --whole-archive के वैध उपयोग हैं।

main.cc

typedef void (*handler)(const char *protocol); 
typedef map<const char *, handler> M; 
M m; 

void register_handler(const char *protocol, handler) { 
    m[protocol] = handler; 
} 
int main(int argc, char *argv[]) 
{ 
    for (int i = 1; i < argc-1; i+= 2) { 
     M::iterator it = m.find(argv[i]); 
     if (it != m.end()) it.second(argv[i+1]); 
    } 
} 

http.cc (libhttp.a का हिस्सा)

: एक उदाहरण सी ++ कोड, जहां वैश्विक उदाहरणों उनके कंस्ट्रक्टर्स (: अपरीक्षित कोड चेतावनी) में खुद को "रजिस्टर" बनाने जा रहा है
class HttpHandler { 
    HttpHandler() { register_handler("http", &handle_http); } 
    static void handle_http(const char *) { /* whatever */ } 
}; 
HttpHandler h; // registers itself with main! 

ध्यान दें कि http.cc में main.cc की आवश्यकता नहीं है। आप आप के रूप में

g++ main.cc -lhttp 

इस लिंक करते हैं तो नहीं एक http हैंडलर मुख्य निष्पादन में लिंक मिल जाएगा, और नहीं handle_http() कॉल करने के लिए सक्षम हो जाएगा।

g++ main.cc -Wl,--whole-archive -lhttp -Wl,--no-whole-archive 

ही "आत्म पंजीकरण" शैली भी सादा-सी है, उदा संभव है: क्या होता है जब आप लिंक के रूप में के साथ इस कंट्रास्ट __attribute__((constructor)) जीएनयू एक्सटेंशन के साथ।

+1

russion तो libhttp.a बनाया जा सकता है तो यह साबित होता है register_handler समारोह है कि libhttp.a में ही अस्तित्व में है। तो यह फ़ंक्शन main.cc में register_handler का संदर्भ कैसे दे सकता है? तो इस मामले में हमें आपके विचार को लागू करने के लिए किसी अन्य तरीके का उपयोग करना होगा। – longbkit

9

--whole-archive के लिए एक और वैध उपयोग टूलकिट डेवलपर्स के लिए एक स्थिर पुस्तकालय में एकाधिक सुविधाओं वाले पुस्तकालयों को वितरित करने के लिए है। इस मामले में, प्रदाता को पता नहीं है कि पुस्तकालय के कौन से हिस्से उपभोक्ता द्वारा उपयोग किए जाएंगे और इसलिए सबकुछ शामिल होना चाहिए।

+4

एस/साझा/स्थिर / – Igor

1

पुरानी क्वेरी, लेकिन आपके पहले प्रश्न ("क्यों") पर, मैंने देखा है - इन पुस्तकालयों के बीच मुख्य रूप से सर्कुलर संदर्भों को छिपाने के लिए मुख्य रूप से इन-हाउस पुस्तकालयों के लिए भी उपयोग किया जाता है। यह पुस्तकालयों के गरीब वास्तुकला को छिपाने के लिए जाता है, तो मैं इसकी सलाह नहीं होगी। हालांकि यह एक त्वरित परीक्षण काम करने का एक तेज़ तरीका है।

अपने दूसरे प्रश्न के लिए, यदि एक ही प्रतीक एक साझा वस्तु और एक स्थिर पुस्तकालय में मौजूद था, लिंकर साथ जो भी पुस्तकालय यह पहली बार मिलता है संदर्भ को संतुष्ट करेगा।
साझा लाइब्रेरी और स्थिर पुस्तकालय कोड की एक सटीक बंटवारे है, तो यह सब सिर्फ काम कर सकते हैं। लेकिन जहां शेयर की गई लाइब्रेरी और स्थिर पुस्तकालय एक ही प्रतीकों के विभिन्न कार्यान्वयन है, अपने कार्यक्रम अभी भी संकलन होगा, लेकिन पुस्तकालयों के आदेश के आधार पर अलग ढंग से व्यवहार करेंगे।

सभी प्रतीकों स्थिर पुस्तकालय से लोड करने के लिए मजबूर क्या कहाँ से भरी हुई है को लेकर उलझन को दूर करने का एक तरीका है। लेकिन आम तौर पर यह गलत समस्या को हल करने की तरह लगता है; आप ज्यादातर अलग पुस्तकालयों में एक ही प्रतीक नहीं चाहते हैं।

0

एक अतिरिक्त अच्छा परिदृश्य जिसमें --whole-archive स्थिर पुस्तकालयों और वृद्धिशील लिंकिंग से निपटने पर अच्छी तरह से उपयोग किया जाता है।

हमें कि लगता है:

  1. libA लागू करता a() और b() कार्य करता है।
  2. कार्यक्रम के कुछ हिस्से को libA केवल, उदा के खिलाफ लिंक किया जाना है

    : कुछ समारोह रैपिंग --wrap का उपयोग कर की वजह से
  3. libCc() कार्यों को लागू करता है और a()
  4. अंतिम कार्यक्रम a() और c()

इंक्रीमेंटल जोड़ने चरणों का उपयोग करता है हो सकता है का उपयोग करता है (एक शास्त्रीय उदाहरण malloc है)

ld -r -o step1.o module1.o --wrap malloc --whole-archive -lA 
ld -r -o step2.o step1.o module2.o --whole-archive -lC 
cc step3.o module3.o -o program 

--whole-संग्रह समारोह c() पट्टी होगा डब्ल्यू सम्मिलित करने के लिए असफल hich किसी भी तरह program द्वारा किया जाता है, सही संकलन प्रक्रिया को रोकने।

बेशक, यह एक विशेष कोने केस है जिसमें सभी मॉड्यूल में malloc पर सभी कॉल लपेटने से बचने के लिए वृद्धिशील लिंकिंग की जानी चाहिए, लेकिन यह एक ऐसा मामला है जिसे --whole-archive द्वारा सफलतापूर्वक समर्थित किया गया है।

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