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 предоставить способ указать группу архива

Надеюсь, что это будет полезно и другим людям!

Ответы на вопрос(3)

Ваш ответ на вопрос