połącz dwa skompilowane przez GCC pliki obiektowe .o w trzeci plik .o

84

Jak połączyć dwa skompilowane przez GCC pliki obiektowe .o w trzeci plik .o?

$ gcc -c  a.c -o a.o
$ gcc -c  b.c -o b.o
$ ??? a.o b.o -o c.o
$ gcc c.o other.o -o executable

Jeśli masz dostęp do plików źródłowych, -combineflaga GCC połączy pliki źródłowe przed kompilacją:

$ gcc -c -combine a.c b.c -o c.o

Jednak działa to tylko dla plików źródłowych, a GCC nie akceptuje .oplików jako danych wejściowych dla tego polecenia.

Zwykle łączenie .oplików nie działa poprawnie, ponieważ nie można użyć danych wyjściowych konsolidatora jako danych wejściowych. Rezultatem jest biblioteka współdzielona, ​​która nie jest statycznie połączona z wynikowym plikiem wykonywalnym.

$ gcc -shared a.o b.o -o c.o
$ gcc c.o other.o -o executable
$ ./executable
./executable: error while loading shared libraries: c.o: cannot open shared object file: No such file or directory
$ file c.o
c.o: ELF 32-bit LSB shared object, Intel 80386, version 1 (SYSV), dynamically linked, not stripped
$ file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
Lucian Adrian Grijincu
źródło
1
gcc obecnie nie ma -combineopcji. Istnieje w gcc 4.1.2 i nie istnieje w gcc 6.3.0 (ktoś inny może dowiedzieć się, kiedy zostało usunięte).
Keith Thompson,

Odpowiedzi:

98

Przekazanie -relocatablelub -rdo ldspowoduje utworzenie obiektu odpowiedniego jako dane wejściowe ld.

$ ld -relocatable a.o b.o -o c.o
$ gcc c.o other.o -o executable
$ ./executable

Wygenerowany plik jest tego samego typu, co oryginalne .opliki.

$ file a.o
a.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
$ file c.o
c.o: ELF 32-bit LSB relocatable, Intel 80386, version 1 (SYSV), not stripped
Lucian Adrian Grijincu
źródło
2
Czy można wykonać operację odwrotną? tj. produkować ao i bo z co?
Bert Regelink
7
@BertRegelink nie, ponieważ nie ma unikalnej odwrotności, matematycznie nie tworzy grupy: P
Alec Teal
7
Ostrzeżenie: --relocatablewydaje się być mniej przenośny. Dysk twardy dostarczany z systemem Android NDK rozpoznaje tylko pliki -relocatable. Jeśli potrzebujesz przenośności, trzymaj się -r.
Martin Bonner wspiera Monikę
3
@matthijs Słowo jest takie samo; różnica wynosi jeden minus lub dwa.
Martin Bonner wspiera Monikę
1
Ach, nie widziałem tego. Tak więc Android NDK rozpoznaje tylko -relocatable i -r , ale nie --relocatable. Dzięki za wytłumaczenie!
Matthijs Kooijman
10

Jeśli chcesz utworzyć archiwum dwóch lub więcej plików .o (np. Bibliotekę statyczną), użyj arpolecenia:

ar rvs mylib.a file1.o file2.o

źródło
@Lucian Ale dlaczego chcesz to zrobić? Biblioteka statyczna jest znacznie wygodniejsza do łączenia niż plik .o.
5
Muszę uruchomić objcopyplik wynikowy i uczynić niektóre rodzaje symboli lokalnymi dla pliku, aby nie były widoczne na zewnątrz. Niektóre symbole, które muszą być zlokalizowane, znajdują się między plikami a.oi b.o. Nie mogę zlokalizować pojedynczych plików - ponieważ symbole nie zostałyby znalezione w czasie konsolidatora - i nie mogę również zlokalizować symboli z archiwum statycznego.
Lucian Adrian Grijincu