Estou compilando um modelo usando make
. O modelo possui um Makefile
que conecta o código-fonte com bibliotecas dependentes por meio de sinalizadores semelhantes a -L/lib1 -L/lib2
. Mas quando tento executar esse modelo, ele falha, a menos que eu também assegure a variável ambiental
export LD_LIBRARY_PATH=/lib1:/lib2
e aponta exatamente para as mesmas bibliotecas. Isso me parece redundante.
O que poderia estar acontecendo sob o capô aqui? Por que efetivamente preciso especificar a localização das bibliotecas antes da compilação e antes da execução?
Esta pode ser uma pergunta boba; Não tenho muita experiência em compilar para código de máquina, geralmente apenas uso linguagens de script.
Embora todos usem a compilação no sentido coloquial de transformar o código-fonte em um executável, é tecnicamente uma única etapa em um pipeline bastante longo:
[ Para ser pedante, não é necessário que as etapas sejam separadas e os compiladores modernos geralmente as combinam para eficiência. ]
Nossa preocupação é a etapa de vinculação, que combina seu código com as bibliotecas padrão do sistema. O vinculador copia objetos de bibliotecas estáticas diretamente para o executável. Para bibliotecas compartilhadas, no entanto, ele fornece apenas uma referência à biblioteca.
As bibliotecas compartilhadas têm muitas vantagens. Você pode atualizá-los sem recompilar programas e eles usam menos memória porque os programas podem compartilhar código comum. Eles também têm a desvantagem óbvia de que o código não está no executável.
A solução para isso é o carregador dinâmico, responsável por resolver todas as referências de bibliotecas compartilhadas em tempo de execução. O carregador é executado automaticamente; as instruções para fazer isso são algo que o vinculador inclui no executável. Claro que isso pressupõe que o carregador possa encontrar as bibliotecas.
As bibliotecas do sistema estão em diretórios padrão, o que é direto. Quando não for esse o caso, o carregador pesquisará LD_LIBRARY_PATH. Por que o vinculador simplesmente não coloca o caminho no executável? Porque então você não conseguiria mover ou alterar a biblioteca.
Na prática, você também não poderia mover o executável, pois a biblioteca está fora do caminho de pesquisa do sistema. Se ele foi executado apenas quando a biblioteca estava localizada em ~luke/lib, você não pode entregá-lo a Joe, a menos que ele possa ler seus arquivos. É péssimo para Joe se você mudar para um novo emprego.
Apenas FYI seria péssimo em uma infinidade de outras maneiras também. Isso tornaria a depuração um pesadelo eterno se você pudesse apenas especificar o local da biblioteca em tempo de compilação, entre outras coisas.