ld linker usuwający plik obiektowy ze statycznej biblioteki podczas tworzenia współdzielonego

Mam kilka statycznych bibliotek, które łączę w jedną wspólną bibliotekę. Jeden z nich, powiedzmy, że libUsefulFunc.a zawiera plik obiektowy przydatnychFunc.o z funkcją, użytecznyFunc (), który jest używany tylko z innej statycznej biblioteki, powiedzmy usingFunc (), rezydujący w usingFunc.c hostowanym w libUsingFunc.a

Problem polega na tym, że linker wyrzuca użyteczneFunc.o i otrzymuję błąd „niezdefiniowane odniesienie”. Próbowałem obu rzędów łączenia.

Odtworzyłem sytuację przy użyciu najprostszych plików, jakie mogłem wymyślić:

a.h

extern int foo();

a.c

#include "a.h"
int foo()
{
    return 13;
}

pne

#include "a.h"

extern int b()
{
  return print("a = %d\n", foo());
}

Buduj wszystko:

gcc -c a.c -o a.o
gcc -c b.c -o b.o
ar q b.a b.o
ar q a.a a.o
ld -shared -o test.so ./b.a ./a.a
nm ./test.so 
00001034 A __bss_start
00001034 A _edata
00001034 A _end

Jeśli udostępnię pliki obiektów zamiast archiwów:

ld -shared -o test.so ./a.o ./b.o
nm ./test.so 
00001220 a _DYNAMIC
00000000 a _GLOBAL_OFFSET_TABLE_
00001298 A __bss_start
00001298 A _edata
00001298 A _end
000001a0 T b
00000194 T foo
         U print

Czy istnieje sposób, aby powiedzieć linkerowi, aby nie wyrzucał plików obiektowych, które jego zdaniem są nieużywane, bez konieczności wyświetlania wszystkich plików obiektowych? Wiem, że istnieje opcja --whole-archive, ale tworzę bibliotekę jako część projektu Android NDK i nie znalazłem sposobu na przekazanie tej opcji dla konkretnej biblioteki.

Aktualizacja W pełni zrozumiałem swój pierwotny problem i znalazłem właściwe rozwiązanie. Najpierw mój przykład powyżej: linker zaczyna się od punktów wejścia i wyszukuje wszystkie używane symbole. Są one wyszukiwane w bieżącej bibliotece. Raz znaleziony dodaje symbole, których używa do swojej listy, a więc wymusza. Biblioteki są procesami tylko raz iw kolejności, w jakiej pojawiają się w linii poleceń. Jeśli więc druga biblioteka używa symbolu z pierwszego - symbol pozostanie niezdefiniowany, ponieważ linker nie wróci. W moim przykładzie powinienem był mu powiedzieć, że b () zostanie wywołany zewnętrznie, mógłbym to zrobić za pomocą --undefined = b:

ld -shared -o test.so --undefined=b ./b.a ./a.a

W pierwotnym problemie miałem do czynienia z kolistym odniesieniem między dwiema statycznymi bibliotekami. tak jakbym miał w archiwum b plik b1.c z funkcją foo_b (), która jest wywoływana z foo (). W takich przypadkach znalazłem 3 możliwe rozwiązania, które znalazłem:

Wyświetl dwa razy b: ld -shared -o test.so --undefined = b ./b.a ./a.a ./b.aUżyj - całe-archiwumUżyj opcji --start-group archives --end-group option. Określone archiwa są wyszukiwane wielokrotnie, dopóki nie zostaną utworzone nowe niezdefiniowane odwołania.

W przypadku bibliotek NDK na Androida dostępne są tylko pierwsze i drugie opcje, ponieważ pliki makefile NDK nie umożliwiają określenia grupy archiwum

Mam nadzieję, że będzie to przydatne także dla innych ludzi!

questionAnswers(3)

yourAnswerToTheQuestion