ld linker удаляет объектный файл из статической библиотеки при создании общей
У меня есть несколько статических библиотек, которые я объединяю в одну общую библиотеку. Один из них, скажем, libUsefulFunc.a содержит объектный файл ПолезныйФункц.о с функцией полезныйФункция (), который используется только из другой статической библиотеки, пустьскажем, с помощью функции Func (), находящейся в файле usingFunc.c, размещенном в libUsingFunc.a
Проблема в том, что компоновщик выбрасывает полезный Func.o, и я получаю ошибку " неопределенные ссылки ", Я пробовал оба порядка связывания.
Мы воссоздали ситуацию, используя самые простые файлы, которые я мог себе представить:
хиджры
extern int foo();
a.c
#include "a.h"
int foo()
{
return 13;
}
До нашей эры
#include "a.h"
extern int b()
{
return print("a = %d\n", foo());
}
Строим все это:
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
Если я предоставлю объектные файлы вместо архивов:
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
Есть ли способ сказать компоновщику не выбрасывать объектные файлы, которые он считает неиспользованными, без необходимости перечисления всех объектных файлов? Я знаю, что есть опция --whole-archive, но я собираю библиотеку как часть проекта Android NDK и не нашел способа передать эту опцию для конкретной библиотеки.
Обновление яЯ полностью понял мою первоначальную проблему и нашел правильное решение. Сначала к моему примеру выше: компоновщик начинает с точек входа и ищет все символы, которые они используют. Они ищутся в текущей библиотеке. Когда он найден, он добавляет символы, которые они используют, в свой список и, таким образом, принудительно. Библиотеки являются процессами только один раз и в порядке их появления в командной строке. Так что, если вторая библиотека использует символ из первой - символ останется неопределенным, так как компоновщик не вернется. Так что в моем примере я должен был сказать ему, что b () будет вызываться извне, я мог бы сделать это, используя --undefined = b:
ld -shared -o test.so --undefined=b ./b.a ./a.a
В исходной задаче у меня была круговая ссылка между двумя статическими библиотеками. как будто у меня в архиве b был файл b1.c с функцией foo_b (), который вызывается из foo (). Для таких случаев есть 3 возможных решения, которые я нашел:
Перечислите b дважды: ld -shared -o test.so --undefined = b ./b.a ./a.a ./b.aИспользовать --whole-архивИспользуйте параметр --start-group archives --end-group. В указанных архивах выполняется повторный поиск, пока не будут созданы новые неопределенные ссылки.Для библиотек Android NDK, по-видимому, доступны только первый и второй варианты, так как NDK 'с makefiles не делайt предоставить способ указать группу архива
Надеюсь, что это будет полезно и другим людям!