ld linker removendo um arquivo de objeto de uma biblioteca estática ao criar um compartilhado

Eu tenho um número de bibliotecas estáticas que eu linko em uma biblioteca compartilhada. Um deles, digamos, libUsefulFunc.a contém um arquivo de objeto usefulFunc.o com uma função, usefulFunc () que é usada apenas de outra biblioteca estática, digamos usingFunc (), residindo em usingFunc.c hospedado em libUsingFunc.a

O problema é que o linker joga fora o usefulFunc.o e eu recebo o erro "referência indefinida". Eu tentei as duas ordens de vinculação.

Eu recriou a situação usando os arquivos mais simples que eu pude pensar:

a.h

extern int foo();

a.c

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

b.c

#include "a.h"

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

Construindo tudo:

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

Se eu fornecer os arquivos de objeto em vez de arquivos:

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

Existe uma maneira de dizer ao vinculador para não jogar fora os arquivos de objetos que ele acha que não estão sendo usados ​​sem precisar listar todos os arquivos de objeto? Eu sei que existe uma opção --whole-archive, mas eu construo a biblioteca como parte do projeto Android NDK e não encontrei uma maneira de passar essa opção para uma biblioteca específica.

Uma atualização Eu entendi completamente o meu problema original e encontrei a solução correta. Primeiro no meu exemplo acima: o linker inicia nos pontos de entrada e procura por todos os símbolos que eles usam. Estes são procurados na biblioteca atual. Uma vez encontrado, adiciona os símbolos que eles usam à sua lista e assim forçam. As bibliotecas são processadas apenas uma vez e na ordem em que aparecem na linha de comando. Portanto, se a segunda biblioteca usar um símbolo do primeiro, o símbolo permanecerá indefinido, pois o vinculador não voltará. Então, no meu exemplo, eu deveria ter dito a ele que b () será chamado externamente, eu poderia fazê-lo usando --undefined = b:

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

No problema original que tive, havia uma referência circular entre duas bibliotecas estáticas. como se eu tivesse no arquivo b um arquivo b1.c com a função foo_b () que é chamada de foo (). Para tais casos, existem 3 soluções possíveis que encontrei:

Liste o b duas vezes: ld -shared -o test.so --undefined = b ./b.a./a.a./b.aUse --whole-archiveUse --start-group archives --opção -end-group. Os arquivos especificados são pesquisados ​​repetidamente até que não sejam criadas novas referências indefinidas.

Para bibliotecas Android NDK, apenas a primeira e a segunda opção parecem estar disponíveis, já que os makefiles do NDK não fornecem uma maneira de especificar o grupo de arquivos.

Espero que isso seja útil para outras pessoas também!

questionAnswers(3)

yourAnswerToTheQuestion