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ć (tylkogcc
) - czyli dlaczego robię ten-lstdc++
sztuczkę powyższą zamiast po prostu powiązanie zg++
). - 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ń?
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
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. –
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. –