web-dev-qa-db-fra.com

Liaison de bibliothèques statiques à 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 rendre disponible à d'autres personnes.

Ma bibliothèque statique, appelons-le 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, de nombreuses erreurs sur les symboles manquants apparaissent dans les bibliothèques a_1 - a_n.

Existe-t-il un moyen de créer une nouvelle bibliothèque statique, Y contenant X et toutes les fonctionnalités nécessaires à X (bits sélectionnés de a_1 - a_n), de sorte que je ne puisse distribuer que Y pour que les utilisateurs puissent lier leurs programmes?


MISE À JOUR:

J'ai simplement envisagé de tout jeter avec ar et de créer un méga-lib, mais cela finit par inclure un grand nombre de symboles inutiles ( tous les fichiers .o font environ 700 Mo. Toutefois, un exécutable lié statiquement fait 7 Mo). Existe-t-il un bon moyen d’inclure uniquement ce qui est réellement nécessaire?


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

121
Jason Sundram

Les bibliothèques statiques ne sont pas liées à d'autres bibliothèques statiques. La seule façon de procéder consiste à utiliser votre outil librarian/archiver (par exemple ar sous Linux) pour créer une nouvelle bibliothèque statique unique en concaténant plusieurs bibliothèques.

Edit: En réponse à votre mise à jour, le seul moyen que je connaisse pour sélectionner uniquement les symboles requis est de créer manuellement la bibliothèque à partir du sous-ensemble des fichiers .o qui les contiennent. Ceci est difficile, prend du temps et est sujet aux erreurs. Je ne suis au courant d'aucun outil pour aider à faire cela (pour ne pas dire qu'ils n'existent pas), mais cela en ferait un projet assez intéressant.

63
anon

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 de joindre des bibliothèques sur la ligne de commande. Je ne sais pas comment faire cela dans l'éditeur visuel.

lib.exe /OUT:compositelib.lib  lib1.lib lib2.lib
42
John Knoeller

Sous Linux ou MingW, avec GNU chaîne d’outils:

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

De si vous ne supprimez pas liba.a et 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
19
Star Brilliant

Une bibliothèque statique est juste une archive de .o fichiers objets. Extrayez-les avec ar (en supposant Unix) et regroupez-les dans une grande bibliothèque.

8
Nikolai Fetissov

Alternativement à Link Library Dependencies _ Dans les propriétés du projet, il existe un autre moyen de lier des bibliothèques dans Visual Studio.

  1. Ouvrez le projet de la bibliothèque (X) que vous souhaitez combiner avec d'autres bibliothèques.
  2. Ajoutez les autres bibliothèques que vous voulez combiner avec X (clic droit, Add Existing Item...).
  3. Accédez à leurs propriétés et assurez-vous que Item Type est Library

Cela inclura les autres bibliothèques dans X comme si vous aviez exécuté

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

Remarque avant de lire la suite: Le script Shell présenté ici n'est certainement pas sûr à utiliser et a été testé. À utiliser à vos risques et périls!

J'ai écrit un script bash pour accomplir cette tâche. Supposons que votre bibliothèque est lib1 et que vous ayez besoin d'inclure des symboles à partir de lib2. Le script s'exécute maintenant en 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 lib2 avec ar, les renomme un peu et les met dans lib1. Il peut maintenant y avoir plus de symboles manquants, car les éléments que vous avez inclus dans lib2 ont besoin d’autres éléments de lib2, que nous n’avons pas encore inclus, de sorte que la boucle doit être exécutée à nouveau. Si après quelques passes de la boucle, il n'y a plus de modifications, c'est-à-dire qu'aucun fichier objet de lib2 ajouté à lib1, la boucle peut s'arrêter.

Notez que les symboles inclus sont toujours signalés comme non définis par nm, je garde donc une trace des fichiers objet, qui ont été ajoutés à 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 ensuite, par exemple. avec

./libcomp libmylib.a libwhatever.a

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

3
Elmar Zander