129 votes

Liaison de bibliothèques statiques avec d'autres bibliothèques statiques

J'ai un petit morceau de code qui dépend de nombreuses bibliothèques statiques (a_1-a_n). J'aimerais regrouper ce code dans une bibliothèque statique et le mettre à la disposition d'autres personnes.

Ma bibliothèque statique, appelons-la X, compile bien.

J'ai créé un exemple de programme simple qui utilise une fonction de X, mais lorsque j'essaie de le lier à X, je reçois de nombreuses erreurs concernant des symboles manquants dans les bibliothèques a_1 - a_n.

Existe-t-il un moyen de créer une nouvelle bibliothèque statique, Y, qui contient X et toutes les fonctionnalités nécessaires à X (bits sélectionnés de a_1 à a_n), afin de pouvoir distribuer uniquement Y pour que les gens puissent y lier leurs programmes ?


UPDATE :

J'ai envisagé de tout vider avec ar et faire une méga-lib, cependant, cela finit par inclure beaucoup de symboles qui ne sont pas nécessaires (tous les fichiers .o font environ 700 Mo, cependant, un exécutable lié statiquement fait 7 Mo). Existe-t-il un moyen efficace d'inclure uniquement ce qui est réellement nécessaire ?


Cela semble étroitement lié à Comment combiner plusieurs bibliothèques C/C++ en une seule ? .

69voto

Les bibliothèques statiques ne se lient pas avec d'autres bibliothèques statiques. La seule façon de le faire est d'utiliser votre outil de bibliothécaire/archiviste (par exemple ar sur Linux) pour créer une seule nouvelle bibliothèque statique en concaténant les multiples bibliothèques.

Editar: En réponse à votre mise à jour, le seul moyen que je connaisse pour sélectionner uniquement les symboles nécessaires est de créer manuellement la bibliothèque à partir du sous-ensemble des fichiers .o qui les contiennent. Cette opération est difficile, longue et source d'erreurs. Je n'ai pas connaissance d'outils permettant de faire cela (je ne dis pas qu'ils n'existent pas), mais cela ferait un projet intéressant d'en produire un.

46voto

John Knoeller Points 20754

Si vous utilisez Visual Studio, alors oui, vous pouvez le faire.

L'outil de création de bibliothèques fourni avec Visual Studio vous permet d'assembler des bibliothèques en ligne de commande. Je ne connais pas de moyen de le faire dans l'éditeur visuel.

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

22voto

Star Brilliant Points 108

Sur Linux ou MingW, avec la chaîne d'outils GNU :

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

Si vous ne supprimez pas liba.a y libb.a vous pouvez créer une "archive mince" :

ar crsT libab.a liba.a libb.a

Sous Windows, avec la chaîne d'outils MSVC :

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

10voto

Nikolai N Fetissov Points 52093

Une bibliothèque statique est juste une archive de .o fichiers objets. Extrayez-les avec ar (en supposant qu'il s'agisse d'Unix) et de les regrouper dans une grande bibliothèque.

8voto

Elmar Zander Points 286

A noter avant de lire le reste : Le shell script présenté ici n'est certainement pas sûr à utiliser et bien testé. Utilisez-le à vos risques et périls !

J'ai écrit un bash script pour accomplir cette tâche. Supposons que votre bibliothèque soit lib1 et que celle dont vous devez inclure certains symboles soit lib2. Le script tourne maintenant dans une boucle, où il vérifie d'abord quels symboles non définis de lib1 peuvent être trouvés dans lib2. Il extrait ensuite les fichiers objets correspondants de la lib2 avec ar les renomme un peu, et les place dans lib1. Maintenant, il peut y avoir d'autres symboles manquants, parce que les éléments de la lib2 que vous avez inclus ont besoin d'autres éléments de la lib2, que nous n'avons pas encore inclus, donc la boucle doit être exécutée à nouveau. Si après quelques passages de la boucle, il n'y a plus de changements, c'est-à-dire aucun fichier objet de la lib2 ajouté à la lib1, la boucle peut s'arrêter.

Notez, que les symboles inclus sont toujours signalés comme non définis par nm Je suis donc en train de suivre les fichiers objets qui ont été ajoutés à la lib1, afin de déterminer si la boucle peut être arrêtée.

#! /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

J'ai nommé ce script libcomp vous pouvez donc l'appeler par exemple avec

./libcomp libmylib.a libwhatever.a

où libwhatever est l'endroit d'où vous voulez inclure les symboles. Cependant, je pense qu'il est plus sûr de tout copier d'abord dans un répertoire séparé. Je ne ferais pas tellement confiance à mon script (cependant, cela a fonctionné pour moi ; je pouvais inclure libgsl.a dans ma bibliothèque numérique avec cela et laisser de côté le commutateur de compilateur -lgsl).

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X