2012-01-22 15 views
14

पर पोर्ट सी/सी ++ अनुप्रयोगों को पोर्ट कैसे करें ठीक है, यह एक मजेदार अभ्यास है, लेकिन यह कुछ पुराने लिनक्स सिस्टम के लिए बहुत कठिन संकलन प्रोग्राम नहीं हो सकता है, या यह कर सकता है?विरासत लिनक्स कर्नेल संस्करणों

मेरे पास लिनक्स चलाने वाले कुछ प्राचीन सिस्टम तक पहुंच है और शायद यह देखना दिलचस्प होगा कि वे लोड के तहत कैसे प्रदर्शन करते हैं। एक उदाहरण के रूप में कहें हम Eigen का उपयोग करके कुछ रैखिक बीजगणित करना चाहते हैं जो एक अच्छा हेडर-केवल लाइब्रेरी है। लक्ष्य प्रणाली पर इसे संकलित करने का कोई मौका?

[email protected]:~ $ uname -a 
Linux local 2.2.16 #5 Sat Jul 8 20:36:25 MEST 2000 i586 unknown 
[email protected]:~ $ gcc --version 
egcs-2.91.66 

शायद नहीं ... तो चलो इसे एक मौजूदा सिस्टम पर संकलित करें। नीचे मेरे प्रयास हैं, मुख्य रूप से असफल लोग। कोई और विचार बहुत स्वागत है।

  1. संकलित -m32 -march=i386

    [email protected]:~ $ ./a.out 
    BUG IN DYNAMIC LINKER ld.so: dynamic-link.h: 53: elf_get_dynamic_info: Assertion `! "bad dynamic tag"' failed! 
    
  2. -m32 -march=i386 -static साथ संकलित साथ: सब काफी हाल ही में गिरी संस्करणों पर चलाता है लेकिन विफल रहता है अगर वे अच्छी तरह से ज्ञात त्रुटि संदेश

    [email protected]:~ $ ./a.out 
    FATAL: kernel too old 
    Segmentation fault 
    

    इस के साथ थोड़ा पुराने हैं एक glibc त्रुटि है जिसमें कम से कम कर्नेल संस्करण है जो इसका समर्थन करता है, उदाहरण के लिए अपने सिस्टम पर गिरी 2.6.4:

    $ file a.out 
    a.out: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), 
    statically linked, for GNU/Linux 2.6.4, not stripped 
    
  3. संकलित glibc अपने आप को सबसे पुराने गिरी संभव लिए समर्थन के साथ। This post और अधिक विस्तार में यह वर्णन लेकिन अनिवार्य रूप से यह इस

    wget ftp://ftp.gnu.org/gnu/glibc/glibc-2.14.tar.bz2 
    tar -xjf glibc-2.14.tar.bz2 
    cd glibc-2.14 
    mkdir build; cd build 
    ../configure --prefix=/usr/local/glibc_32 \ 
          --enable-kernel=2.0.0 \ 
          --with-cpu=i486 --host=i486-linux-gnu \ 
          CC="gcc -m32 -march=i486" CXX="g++ -m32 -march=i486" 
    make -j 4 
    make intall 
    

    सुनिश्चित नहीं हैं कि अगर --with-cpu और --host विकल्प कुछ भी करने की तरह हो जाता है, सबसे महत्वपूर्ण -m32 -march=i486 के लिए 32-बिट बनाता है (दुर्भाग्य से -march=i386 गिल्लियां संकलक झंडे के उपयोग कराने के लिए है पुराने कर्नेल के साथ लाइब्रेरी को संगत बनाने के लिए थोड़ी देर बाद त्रुटियों के साथ) और --enable-kernel=2.0.0। Incidentially, configure दौरान मैं चेतावनी

    WARNING: minimum kernel version reset to 2.0.10 
    

    जो अभी भी स्वीकार्य है मिल गया, मुझे लगता है। विभिन्न कर्नेल के साथ बदलती चीजों की एक सूची के लिए ./sysdeps/unix/sysv/linux/kernel-features.h देखें। नव संकलित glibc पुस्तकालय के खिलाफ

    ठीक है, तो चलो लिंक, थोड़ा गंदा लेकिन यहाँ यह जाता है:

    $ export LIBC_PATH=/usr/local/glibc_32 
    $ export LIBC_FLAGS=-nostdlib -L${LIBC_PATH} \ 
            ${LIBC_PATH}/crt1.o ${LIBC_PATH}/crti.o \ 
            -lm -lc -lgcc -lgcc_eh -lstdc++ -lc \ 
            ${LIBC_PATH}/crtn.o 
    
    $ g++ -m32 -static prog.o ${LIBC_FLAGS} -o prog 
    

    जब से हम एक स्थिर संकलन कर रहे हैं link order महत्वपूर्ण है और अच्छी तरह से कुछ परीक्षण और त्रुटि की आवश्यकता हो सकती

    $ g++ -m32 -static -Wl,-v file.o 
    

    ध्यान दें, crtbeginT.o और crtend.o भी जुड़े हुए हैं जिसके खिलाफ मैं मीटर के लिए जरूरत नहीं थी:, लेकिन मूल रूप से हम क्या विकल्प gcc लिंकर देता से सीख वाई कार्यक्रम तो मैंने उन्हें छोड़ दिया। आउटपुट में --start-group -lgcc -lgcc_eh -lc --end-group जैसी रेखा भी शामिल है जो पुस्तकालयों के बीच अंतर-निर्भरता को इंगित करती है, this post देखें। मैंने को gcc कमांड लाइन में दो बार उल्लेख किया है जो अंतर-निर्भरता को हल करता है।

    ठीक है, कड़ी मेहनत रंग लाए गया है और अब मैं

    $ file ./prog 
    ./prog: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), 
    statically linked, for GNU/Linux 2.0.10, not stripped 
    

    शानदार मैंने सोचा मिलता है, अब पुराने सिस्टम पर यह प्रयास करें:

    [email protected]:~ $ ./prog 
    set_thread_area failed when setting up thread-local storage 
    Segmentation fault 
    

    यह, फिर से, एक glibc त्रुटि है ./nptl/sysdeps/i386/tls.h से संदेश। मैं विवरण समझने और हारने में असफल रहा।

  4. संकलित नई प्रणाली g++ -c -m32 -march=i386 और पुराने पर लिंक पर। वाह, वास्तव में कम से कम कुछ परीक्षणों के लिए सी और सरल सी ++ प्रोग्राम (सी ++ ऑब्जेक्ट्स का उपयोग नहीं) के लिए काम करता है। यह बहुत आश्चर्यजनक नहीं है क्योंकि मुझे libc से printf (और शायद कुछ गणित) की आवश्यकता है, जिसमें इंटरफ़ेस नहीं बदला गया है लेकिन libstdc++ पर इंटरफ़ेस अब बहुत अलग है।

  5. सेटअप एक पुराने Linux सिस्टम और जीसीसी संस्करण 2.95 के साथ एक आभासी बॉक्स। फिर संकलन जीसीसी संस्करण 4.x.x ... खेद है, लेकिन अब यह सही करने के लिए बहुत आलसी ...

  6. ???

+0

संकलन? एक हेडर-केवल टेम्पलेट लाइब्रेरी? –

+0

इस टेम्पलेट लाइब्रेरी का उपयोग करने वाले एक परीक्षण प्रोग्राम को संकलित करें। यह केवल कुछ कोड का एक उदाहरण है जो पुराने जीसीसी संस्करण के कारण लक्ष्य मशीन पर संकलित नहीं होगा। – user1059432

+0

आह, ठीक है। क्षमा करें, बस गलत समझा। –

उत्तर

3

कारण आप मूल सिस्टम पर यह संकलन नहीं कर सकते हैं की संभावना कर्नेल संस्करण के साथ कोई संबंध नहीं है (यह हो सकता है, लेकिन आम तौर पर 2.2 वर्ष है कि सबसे कोड के लिए एक बड़ी बाधा के लिए पर्याप्त के लिए नहीं है) । समस्या यह है कि toolchain प्राचीन है (बहुत कम, संकलक पर) है। हालांकि, इंस्टॉल किए गए egcs के साथ G ++ के नए संस्करण को बनाने से आपको कुछ भी नहीं रोकता है। एक बार ऐसा करने के बाद आपको glibc के साथ समस्याएं भी आ सकती हैं, लेकिन आपको कम से कम इसे प्राप्त करना चाहिए।

आप कुछ इस तरह दिखेगा क्या करना चाहिए:

  • egcs
  • के साथ नवीनतम जीसीसी का निर्माण के साथ नवीनतम जीसीसी के पुनर्निर्माण gcc तुम सिर्फ बनाया
  • अपने नए संकलक
  • के साथ नवीनतम binutils और ld बिल्ड

अब आप एक अच्छी तरह से बनाया गया आधुनिक संकलक और है जिसके साथ अपने नमूना एपी निर्माण करने के लिए toolchain (एक के सबसे) तह। यदि भाग्य आपके पक्ष में नहीं है तो आपको glibc का एक नया संस्करण भी बनाने की आवश्यकता हो सकती है, लेकिन यह आपकी समस्या है - टूलचेन - कर्नेल नहीं।

8

त्रुटि संदेश का कारण मिल गया है:

[email protected] $ ./prog 
set_thread_area failed when setting up thread-local storage 
Segmentation fault 

यह क्योंकि glibc एक समारोह जो गिरी 2.4.20 के बाद से ही उपलब्ध है के लिए एक प्रणाली कॉल बनाता है। के रूप में यह गलत तरीके से गिरी 2.0.10 के साथ संगत होना करने के लिए जब यह कम से कम गिरी 2.4.20 की आवश्यकता है का दावा है एक तरह से यह glibc की एक बग के रूप में देखा जा सकता है।

विवरण:

./glibc-2.14/nptl/sysdeps/i386/tls.h 
[...] 
    /* Install the TLS. */             \ 
    asm volatile (TLS_LOAD_EBX            \ 
        "int $0x80\n\t"           \ 
        TLS_LOAD_EBX            \ 
        : "=a" (_result), "=m" (_segdescr.desc.entry_number)  \ 
        : "0" (__NR_set_thread_area),        \ 
        TLS_EBX_ARG (&_segdescr.desc), "m" (_segdescr.desc)); \ 
[...] 
    _result == 0 ? NULL              \ 
    : "set_thread_area failed when setting up thread-local storage\n"; }) 
[...] 

यहाँ मुख्य बात है, यह विधानसभा समारोह int 0x80 जो लिनक्स कर्नेल के लिए एक प्रणाली कॉल जो जो सेट कर दिया जाता eax के मूल्य के आधार पर क्या करना है फैसला करता है कॉल के __NR_set_thread_area इस मामले में और किसी भी पहले गिरी संस्करणों में

$ grep __NR_set_thread_area /usr/src/linux-2.4.20/include/asm-i386/unistd.h 
#define __NR_set_thread_area 243 

लेकिन नहीं में परिभाषित किया गया है।

तो अच्छी खबर यह है कि "--enable-kernel=2.0.0 के साथ ग्लिबल संकलित करना" शायद निष्पादन योग्य उत्पन्न करेगा जो सभी लिनक्स कर्नेल> = 2.4.20 पर चलता है।

तथ्य यह एक configure विकल्प के रूप में की पेशकश की है के बावजूद पुराने कर्नेल के साथ इस काम tls (धागे की स्थानीय भंडारण), लेकिन जो glibc 2.14 साथ संभव नहीं है निष्क्रिय करने के लिए किया जाएगा बनाने के लिए, केवल मौका।

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