2011-12-27 17 views
12

Próbuję połączyć moduł C++ przy użyciu GCC, w zasadzie tak:Zmieniono kolejność łącza GCC?

gcc -c hello.c 
g++ -c world.cpp 
gcc -ohello -lstdc++ hello.o world.o 

pamiętać, że używanie -lstdc++ połączyć moduł C++ w, tak, że można używać gcc zamiast g++. Problem polega na tym, że ja dostaję błąd:

undefined reference to `operator new(unsigned long)' 

(Zakładając, że world.cpp zawiera co najmniej jedno połączenie do new).

Ten błąd jest ustalona jeśli kładę -lstdc++ na końcu linii łącznikowej , tak:

gcc -ohello hello.o world.o -lstdc++ 

Jestem świadomy, że to pytanie zostało zadane wiele razy tutaj, ale mam specjalny wymóg. Nie dzwonię bezpośrednio do GCC. Używam systemu kompilacji dla innego języka programowania (Mercury), który wywołuje GCC w moim imieniu i nie mogę łatwo zmienić sposobu, w jaki wywołuje GCC (chociaż mogę określić dodatkowe biblioteki przy użyciu zmiennej środowiskowej LDFLAGS). Więc mam dwa dodatkowe wymagania:

  • Nie mogę korzystać g++ połączyć (tylko gcc) - czyli dlaczego robię ten -lstdc++ sztuczkę powyższą zamiast po prostu powiązanie z g++).
  • Nie sądzę, żebym mógł kontrolować kolejność poleceń linkera - Mercury umieści pliki .o w wierszu poleceń po dowolnych bibliotekach.

Rozumiem podstawowy powód, dla którego kolejność jest istotna, ale co jest zaskakujący mnie jest dlaczego ten przerwę teraz? Właśnie zaktualizowałem Ubuntu do wersji 11.10/GCC 4.6.1. Od lat z powodzeniem kompiluję ten program przy użyciu dokładnie powyższej techniki (najpierw wprowadzając -lstdc++). Dopiero teraz pojawił się ten błąd. Niepowiązany program kopalni łączy się z OpenGL przy użyciu -lgl i to zbytnio się zepsuło po aktualizacji i musiałem przenieść -lgl na koniec wiersza polecenia. Prawdopodobnie odkryję, że dziesiątki moich programów nie są już kompilowane. Dlaczego to się zmieniło? Czy coś jest nie tak z moim nowym systemem, czy jest tak, jak jest teraz? Zauważ, że są to zwykłe biblioteki współdzielone, nie statycznie połączone.

Czy jest coś, co mogę zrobić, aby GCC powróciło na dawną drogę, gdzie kolejność bibliotek nie ma znaczenia? Czy jest jakiś inny sposób, aby przekonać GCC do poprawnego połączenia libstdc++ bez przenoszenia go po plikach .o w linii poleceń?

Odpowiedz

12

Jeśli Mercury umieści pliki obiektów po bibliotekach, Mercury zostanie zerwana. Biblioteki należą do plików obiektów - zawsze. Czasami możesz uciec z odwrotną kolejnością, ale niezawodnie. (Biblioteki statyczne muszą przechodzić za plikami obiektowymi, które odwołują się do symboli w bibliotece statycznej, czasami linker odnotowuje symbole zdefiniowane przez bibliotekę współdzieloną, nawet jeśli żaden z symboli nie jest używany, czasami linker odnotuje tylko symbole wspólnej biblioteki jeśli biblioteka współdzielona udostępnia co najmniej jeden symbol.)

+3

Więc w zasadzie ta "regresja" jest właśnie taka dla całej mojej kariery rozwojowej, polegam na tym, że "przypadkowo zadziałała" i teraz przestała działać? Wydaje się, że jest to dość poważna zmiana. Odkładałem biblioteki przed plikami obiektowymi przez większą część dekady, ponieważ nie miałem pojęcia, że ​​to był problem :(Dzięki za radę.Wygląda na to, że problemem nie jest Merkury umieszczanie obiektów po bibliotekach, ale w moim poleceniu LDFLAGS istnieją bardziej złożone zależności. Robię postępy, więc dam ci kleszcza. Dzięki. – mgiuca

+1

Hipoteza niepotwierdzona: być może zaszła zmiana w 'ld', która dotyczy ciebie. Celem może być uniknięcie ładowania nieużywanych bibliotek współdzielonych. Jeśli korzystasz z bibliotek statycznych, otrzymujesz tylko te rzeczy, których potrzebujesz. Zdarzyło się tak, że jeśli umieścisz bibliotekę współdzieloną na linii łącza, zostanie ona załadowana w środowisku wykonawczym, nawet jeśli biblioteka nie zawiera żadnych symboli. Tylko ładowanie biblioteki, jeśli spełnia co najmniej jeden symbol, może skrócić czas uruchamiania programu. Ale oznacza to również, że jeśli jedynym znakomitym symbolem podczas skanowania biblioteki jest 'main()', biblioteka nie zostanie załadowana. –

+0

Zobacz komentarze na temat '--as-needed' dla wersji 2.20' ld' w [NEWS] (http://sourceware.org/cgi-bin/cvsweb.cgi/~checkout~/src/ld/NEWS? plik rev = 1.121 i content-type = text/plain & cvsroot = src & only_with_tag = binutils-binutils-2_22). Zobacz także [manual] (http://sourceware.org/binutils/docs-2.22/ld/Options.html#Options) oraz '--copy-dt-needed-entries' oraz' --no-copy- Opcje dt-needed-entries'. Przypuszczam, że poprzednia nieudana hipoteza jest przynajmniej w pewnym stopniu udowodniona. –

Powiązane problemy