2010-05-04 24 views
11

का उपयोग करते हुए डुप्लिकेट क्लास नामों के साथ पुस्तकालयों को जोड़ना क्या जीसीसी के लिए एक ही नाम के साथ कक्षाओं वाले पुस्तकालयों को जोड़ने के दौरान चेतावनी उत्पन्न करने का कोई तरीका है? उदाहरण के लिएजीसीसी

Port.h

class Port { 
public: 
    std::string me(); 
}; 

Port.cpp

#include "Port.h" 
std::string Port::me() { return "Port"; } 

FakePort.h

class Port { 
public: 
    std::string me(); 
}; 

FakePort.cpp

#include "FakePort.h" 
std::string Port::me() { return "FakePort"; } 

main.cpp

#include "Port.h" 

int main() { 
    Port port; 
    std::cout << "Hello world from " << port.me() << std::endl; 
    return 0; 
} 

बिल्डिंग

# g++ -c -o Port.o Port.cpp 
# ar rc Port.a Port.o 
# g++ -c -o FakePort.o FakePort.cpp 
# ar rc FakePort.a FakePort.o 
# g++ -c -o main.o main.cpp 
# g++ main.o Port.a FakePort.a 
# ./a.out 
    Hello world from Port 

बदलें पुस्तकालय आदेश

01 जब तक दूसरा एक जो शामिल हो जाता है एक वस्तु फ़ाइल में शामिल है एक प्रतीक दो अलग पुस्तकालयों जीसीसी पहले एक यह पाता है का उपयोग करें और एक दूसरे पर ध्यान नहीं देगा में परिभाषित किया गया है

हैं:

# g++ main.o FakePort.a Port.a 
# ./a.out 
    Hello world from FakePort 

this page के अनुसार किसी अन्य कारण के लिए।

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

# g++ -Wl,--warnLibraryDupSymbols main.o FakePort.a Port.a 
    Warning: Duplicate symbol: Port 

लेकिन मुझे ऐसा करने के लिए जीसीसी लिंकर विकल्पों में कुछ भी नहीं मिला। क्या जीसीसी को स्वचालित रूप से ऐसे मामलों की पहचान और रिपोर्ट करना संभव है?

+0

संबंधित: http://stackoverflow.com/questions/10671956/same-class-name-in-different-c-files – oliver

उत्तर

3

निम्नलिखित एक कोशिश (मैं ईमानदारी से अगर यह तुम क्या चाहते करूँगा पता नहीं है) के लायक हो सकता है:

--whole-archive

प्रत्येक संग्रह के बाद कमांड लाइन पर उल्लेख के लिए - -होल-संग्रह विकल्प, आवश्यक ऑब्जेक्ट फ़ाइलों के लिए संग्रह खोजने के बजाय लिंक में संग्रह में प्रत्येक ऑब्जेक्ट फ़ाइल शामिल करें। इसका उपयोग आम तौर पर एक साझा लाइब्रेरी में एक संग्रह फ़ाइल को चालू करने के लिए किया जाता है, जिससे प्रत्येक ऑब्जेक्ट को परिणामी साझा लाइब्रेरी में शामिल किया जा सकता है। यह विकल्प एक से अधिक बार इस्तेमाल किया जा सकता है।

मैंने कोशिश नहीं की है, लेकिन ऐसा लगता है जैसे यह पुस्तकालय में सभी वस्तुओं को खींच देगा जैसे कि वे ऑब्जेक्ट फाइलें थे। आपको प्रत्येक पुस्तकालय के लिए विकल्प निर्दिष्ट करने की आवश्यकता होगी।

जैसा कि नील ने कहा था, यह आपको कक्षा-स्तर के संघर्ष नहीं देगा, लेकिन यदि समान हस्ताक्षर वाले वर्ग सदस्य हैं, तो यह लिंकर आपको बता सकता है।

+0

सुनिश्चित नहीं हैं कि अगर यह सबसे अच्छा है सामान्य मामला जवाब, लेकिन यह यहां काम करता है। # g ++ main.cpp -Wl, - संपूर्ण संग्रह FakePort.a Port.a -Wl, - नो-पूर्ण-संग्रह पोर्ट.ए (पोर्ट.ओ): पोर्ट.cpp :(। टेक्स्ट + 0x0) : 'पोर्ट :: मुझे()' FakePort.a (FakePort.o) की कई परिभाषा: FakePort.cpp :(। टेक्स्ट + 0x0): पहले यहां परिभाषित – joesdiner

+1

यदि मुझे कुछ भी याद नहीं है तो यह आपकी बाइनरी को काफी हद तक फहरा सकता है, इसलिए परीक्षण परीक्षण के लिए यह केवल उपयोगी है। या क्या वह सही जगह पर '- नो-पूर्ण-संग्रह' के साथ उसका ख्याल रख सकता है? @joesdiner –

+1

@gf: मुझे लगता है कि आप सही हैं; इस उत्तर का उद्देश्य एकीकरण चरण में समस्याओं (या संभावित समस्याओं) का निदान करने के लिए इसका उपयोग करना था - सामान्य निर्माण कॉन्फ़िगरेशन के रूप में नहीं। मुझे लगता है कि यह जोसेडरिन करना चाहता था। –

0

मुझे जो भी चाहिए वो करने के लिए मुझे कोई विकल्प नहीं दिख रहा है। शायद बाद में सोचें और अपने सभी वर्गों के लिए दस्तावेज़ीकरण उत्पन्न करने के लिए डॉक्सिजन जैसे कोड प्रलेखन टूल का उपयोग करें और मैन्युअल रूप से डुप्लिकेट

0

कोई नहीं है। इसका कारण यह है कि एक वर्ग का नाम एक प्रतीक नहीं है जहां तक ​​लिंकर का संबंध है। सी ++ कंपाइलर ने श्रेणीबद्ध फ़ंक्शन नामों का उत्पादन करने के लिए कक्षा का नाम उपयोग किया होगा, लेकिन लिंकर शामिल होने के समय कक्षा का नाम स्वयं ही चला जाता है।

1

वैकल्पिक रूप से आप उम्मीदवारों को खोजने के लिए nm का उपयोग कर एक स्क्रिप्ट का उपयोग कर सकते हैं, उदा। कुछ की तरह:

import collections, subprocess, os, re, sys 

def filt(s): 
    p = subprocess.Popen(['c++filt', s],stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
    return p.communicate()[0].strip() 

rx = re.compile('^[\\d\\w]+ T [\\w]+', re.MULTILINE) 
sym = collections.defaultdict(set) 

for file in sys.argv[1:]: 
    proc = subprocess.Popen(['nm', file], stdout=subprocess.PIPE, stderr=subprocess.PIPE) 
    for s in rx.findall(proc.communicate()[0]): 
    sym[s.split()[2]].add(file) 

for s in filter(lambda x: len(sym[x])>1, sym): 
    print 'Duplicate "%s" in %s' % (filt(s), str(sym[s])) 

foo:$ python dups.py *.a 
Duplicate "Port::me()" in set(['Port.a', 'FakePort.a']) 
+0

डुप्ली उम्मीदवारों की सूची बनाने के लिए इस तरह की एक स्क्रिप्ट का उपयोग करें और फिर अपने मेकफ़ाइल पर काम करें। मेकफ़ाइल टेम्पलेट्स बनाएं जो कक्षाओं के ज्ञात समूह पर ध्यान केंद्रित करते हैं, जिसमें वे पथ शामिल हैं, शामिल हैं। इस तरह ट्रैक रखना आसान है कि 'पोर्ट' को –

+0

अच्छी स्क्रिप्ट से जोड़ा जा रहा है। मेरे लिए काम करता है, लेकिन माइकल बोर द्वारा प्रदान किया गया लिंकर विकल्प स्वचालित रूप से – joesdiner

+0

@joesdiner का पता लगा रहा है: तब भी बेहतर। अफसोस की बात है '- व्हाहोल-संग्रह' ओएसएक्स पर मेरे लिए काम नहीं करता है। –