Pergunta

Eu tenho um pequeno pedaço de código que depende de muitas bibliotecas estáticas (A_1-A_N). Eu gostaria de empacotar esse código em uma biblioteca estática e disponibilizá -lo para outras pessoas.

Minha biblioteca estática, vamos chamá -la de x, compila bem.

Criei um programa de amostra simples que usa uma função de X, mas quando tento vinculá -lo a X, recebo muitos erros sobre os símbolos ausentes das bibliotecas A_1 - A_N.

Existe uma maneira de criar uma nova biblioteca estática, y que contém X e toda a funcionalidade necessária por x (bits selecionados de A_1 - A_N), para que eu possa distribuir apenas Y para as pessoas vincularem seus programas?


ATUALIZAR:

Eu olhei apenas despejando tudo com ar E fazendo um mega-lib, no entanto, que acaba incluindo muitos símbolos que não são necessários (todos os arquivos .O são de cerca de 700 MB, no entanto, um executável estaticamente vinculado é 7 MB). Existe uma boa maneira de incluir apenas o que é realmente necessário?


Isso parece intimamente relacionado a Como combinar várias bibliotecas C/C ++ em uma?.

Foi útil?

Solução

As bibliotecas estáticas não se conectam a outras bibliotecas estáticas. A única maneira de fazer isso é usar sua ferramenta de bibliotecário/arquiver (por exemplo ar no Linux) para criar uma única nova biblioteca estática concatenando as várias bibliotecas.

Editar: Em resposta à sua atualização, a única maneira que sei selecionar apenas os símbolos necessários é criar manualmente a biblioteca a partir do subconjunto dos arquivos .O que os contêm. Isso é difícil, demorado e propenso a erros. Não estou ciente de nenhuma ferramenta para ajudar a fazer isso (para não dizer que não existe), mas seria um projeto interessante para produzir um.

Outras dicas

Se você estiver usando o Visual Studio, então sim, você pode fazer isso.

A ferramenta Bibliotec Builder que vem com o Visual Studio permite unir bibliotecas na linha de comando. Eu não conheço nenhuma maneira de fazer isso no editor visual.

lib.exe /OUT:compositelib.lib  lib1.lib lib2.lib

No Linux ou Mingw, com a Chain de ferramentas GNU:

ar -M <<EOM
    CREATE libab.a
    ADDLIB liba.a
    ADDLIB libb.a
    SAVE
    END
EOM
ranlib libab.a

De se você não excluir liba.a e libb.a, você pode fazer um "arquivo fino":

ar crsT libab.a liba.a libb.a

No Windows, com MSVC Toolchain:

lib.exe /OUT:libab.lib liba.lib libb.lib

Uma biblioteca estática é apenas um arquivo de .o arquivos de objeto. Extraí -los com ar (assumindo o Unix) e leve -os de volta em uma grande biblioteca.

Alternativamente para Link Library Dependencies Nas propriedades do projeto, há outra maneira de vincular bibliotecas no Visual Studio.

  1. Abra o projeto da biblioteca (x) que você deseja ser combinado com outras bibliotecas.
  2. Adicione as outras bibliotecas que você deseja combinadas com x (clique com o botão direito do mouse, Add Existing Item...).
  3. Vá para suas propriedades e certifique -se de Item Type é Library

Isso incluirá as outras bibliotecas em X como se você corresse

lib /out:X.lib X.lib other1.lib other2.lib

Nota Antes de ler o resto: o script do shell mostrado aqui certamente não é seguro de usar e bem testado. Use por sua conta e risco!

Eu escrevi um script bash para realizar essa tarefa. Suponha que sua biblioteca seja lib1 e a que você precisa incluir alguns símbolos é lib2. O script agora é executado em um loop, onde primeiro verifica quais símbolos indefinidos do LIB1 podem ser encontrados no LIB2. Em seguida, ele extrai os arquivos de objeto correspondentes de Lib2 com ar, renomeie -os um pouco e os coloca no Lib1. Agora, pode haver mais símbolos ausentes, porque as coisas que você incluiu no Lib2 precisa de outras coisas do LIB2, que ainda não incluímos, então o loop precisa ser executado novamente. Se, depois de alguns passes do loop, não houver mais alterações, ou seja, nenhum arquivo de objeto do LIB2 adicionado ao LIB1, o loop poderá parar.

Observe que os símbolos incluídos ainda são relatados como indefinidos por nm, por isso, estou acompanhando os arquivos de objeto, que foram adicionados ao LIB1, eles mesmos, a fim de determinar se o loop pode ser interrompido.

#! /bin/bash

lib1="$1"
lib2="$2"

if [ ! -e $lib1.backup ]; then
    echo backing up
    cp $lib1 $lib1.backup
fi

remove_later=""

new_tmp_file() {
    file=$(mktemp)
    remove_later="$remove_later $file"
    eval $1=$file
}
remove_tmp_files() {
    rm $remove_later
}
trap remove_tmp_files EXIT

find_symbols() {
    nm $1 $2 | cut -c20- | sort | uniq 
}

new_tmp_file lib2symbols
new_tmp_file currsymbols

nm $lib2 -s --defined-only > $lib2symbols

prefix="xyz_import_"
pass=0
while true; do
    ((pass++))
    echo "Starting pass #$pass"
    curr=$lib1
    find_symbols $curr "--undefined-only" > $currsymbols
    changed=0
    for sym in $(cat $currsymbols); do
        for obj in $(egrep "^$sym in .*\.o" $lib2symbols | cut -d" " -f3); do
            echo "  Found $sym in $obj."
            if [ -e "$prefix$obj" ]; then continue; fi
            echo "    -> Adding $obj to $lib1"
            ar x $lib2 $obj
            mv $obj "$prefix$obj"
            ar -r -s $lib1 "$prefix$obj"
            remove_later="$remove_later $prefix$obj"
            ((changed=changed+1))
        done
    done
    echo "Found $changed changes in pass #$pass"

    if [[ $changed == 0 ]]; then break; fi
done

Eu nomeei aquele script libcomp, então você pode chamá -lo então, por exemplo, com

./libcomp libmylib.a libwhatever.a

de onde é o que você deseja incluir símbolos. No entanto, acho mais seguro copiar tudo em um diretório separado primeiro. Eu não confiaria tanto no meu script (no entanto, funcionou para mim; eu poderia incluir libgsl.a na minha biblioteca numérica com isso e deixar de fora esse switch -lgsl compilador).

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top