Ten post na blogu jest dość niedokładny.
O ile wiem, zmiany ABI w C ++ były wprowadzane z każdym głównym wydaniem GCC (tj. Z różnymi składnikami o numerze pierwszej lub drugiej wersji).
Nie prawda. Jedyne zmiany C ++ ABI wprowadzone od czasu GCC 3.4 były wstecznie kompatybilne, co oznacza, że C ++ ABI był stabilny przez prawie dziewięć lat.
Co gorsza, większość głównych dystrybucji Linuksa używa migawek GCC i / lub łatek do swoich wersji GCC, przez co praktycznie niemożliwe jest dokładne ustalenie, z jakimi wersjami GCC możesz mieć do czynienia podczas dystrybucji plików binarnych.
Różnice między poprawionymi wersjami GCC dystrybucji są niewielkie i nie zmieniają ABI, np. Fedora 4.6.3 20120306 (Red Hat 4.6.3-2) jest kompatybilna z ABI z oryginalnymi wydaniami FSF 4.6.x i prawie na pewno z każdym 4.6. x z dowolnej innej dystrybucji.
W bibliotekach uruchomieniowych GNU / Linux GCC używają wersji symboli ELF, więc łatwo jest sprawdzić wersje symboli wymagane przez obiekty i biblioteki, a jeśli masz plik, libstdc++.so
który zapewnia te symbole, zadziała, nie ma znaczenia, czy jest to nieco inna poprawiona wersja z innej wersji twojej dystrybucji.
ale żaden kod C ++ (ani żaden kod korzystający z obsługi środowiska uruchomieniowego C ++) nie może być łączony dynamicznie, jeśli ma to działać.
To też nie jest prawdą.
To powiedziawszy, statyczne linkowanie do libstdc++.a
jest jedną z opcji dla Ciebie.
Powodem, dla którego może to nie działać, jeśli dynamicznie ładujesz bibliotekę (używając dlopen
), jest to, że symbole libstdc ++, od których ona zależy, mogły nie być potrzebne twojej aplikacji, gdy ją (statycznie) łączysz, więc te symbole nie będą obecne w twoim pliku wykonywalnym. Można to rozwiązać, dynamicznie łącząc bibliotekę współdzieloną z libstdc++.so
(co i tak jest właściwe, jeśli to od niej zależy). Interpozycja symboli ELF oznacza, że symbole obecne w pliku wykonywalnym będą używane przez bibliotekę współdzieloną, ale inne nie. obecny w twoim pliku wykonywalnym zostanie znaleziony w miejscu libstdc++.so
, do którego prowadzi. Jeśli Twoja aplikacja nie używa dlopen
, nie musisz się tym przejmować.
Inną opcją (i tą, którą preferuję) jest wdrożenie nowszej libstdc++.so
wraz z aplikacją i upewnienie się, że zostanie ona znaleziona przed domyślnym systemem libstdc++.so
, co można zrobić, zmuszając dynamiczny linker do szukania we właściwym miejscu, używając $LD_LIBRARY_PATH
zmiennej środowiskowej w run- time lub ustawiając RPATH
plik wykonywalny w czasie łącza. Wolę używać, RPATH
ponieważ nie zależy to od prawidłowego ustawienia środowiska, aby aplikacja działała. Jeśli powiązanie aplikacji z '-Wl,-rpath,$ORIGIN'
(zwróć uwagę na apostrofów aby powłoka próbuje rozwinąć $ORIGIN
), a następnie plik wykonywalny będzie mieć RPATH
z$ORIGIN
których mówi linker dynamiczny szukać bibliotek dzielonych w tym samym katalogu co plik wykonywalny sama. Jeśli umieścisz nowszylibstdc++.so
w tym samym katalogu, w którym znajduje się plik wykonywalny, zostanie znaleziony w czasie wykonywania, problem rozwiązany. (Inną opcją jest umieszczenie pliku wykonywalnego w /some/path/bin/
i nowszej libstdc ++. Tak /some/path/lib/
i połączyć się z '-Wl,-rpath,$ORIGIN/../lib'
lub inną stałą lokalizacją względem pliku wykonywalnego i ustawić wartość RPATH względem $ORIGIN
)
-static-libstdc++
opcji, po prostu-static