Je construis quelques utilitaires de ligne de commande dans Xcode (C simple, pas de cacao). Je veux que tous utilisent ma version personnalisée de libpng, et je veux économiser de l'espace en partageant une copie de la bibliothèque entre tous les exécutables (cela ne me dérange pas de redistribuer .dylib
avec eux).
Dois-je faire de la magie pour obtenir des symboles d'exportation libpng?
"Lier le binaire aux bibliothèques" créer un lien de phase statique?
Les documents d'Apple mentionnent le chargement des bibliothèques au moment de l'exécution avec dlopen
, mais comment puis-je faire en sorte que Xcode crée un exécutable sans se plaindre des symboles manquants?
Je pense que je l'ai compris:
libpng ne se liait pas correctement, car j'ai construit des exécutables 32/64 bits et une bibliothèque 32 bits. Les paramètres de construction de la bibliothèque et des exécutables doivent correspondre.
config.h de libpng doit avoir des tonnes de définitions comme #define FEATURE_XXX_SUPPORTED
"Link Binary With Libraries" phase de construction gère très bien les bibliothèques dynamiques, et DYLD_FALLBACK_LIBRARY_PATH
la variable d'environnement est nécessaire pour le chargement .dylib
s de l'ensemble d'applications.
Vous devez probablement vous assurer que la bibliothèque dynamique que vous créez a un fichier de symboles exporté qui répertorie ce qui doit être exporté à partir de la bibliothèque. C'est juste une liste plate des symboles, un par ligne, à exporter.
De plus, lorsque votre bibliothèque dynamique est construite, elle reçoit un nom d'installation qui y est intégré, qui est, par défaut, le chemin sur lequel elle est construite. Par la suite, tout ce qui s'y rattache le recherchera d'abord sur le chemin spécifié et ne recherchera ensuite qu'un (petit) ensemble de chemins par défaut décrits sous DYLD_FALLBACK_LIBRARY_PATH
Dans la page de manuel dyld(1)
.
Si vous allez placer cette bibliothèque à côté de vos exécutables, vous devez ajuster son nom d'installation pour y faire référence. Le simple fait de faire une recherche Google sur "nom d'installation" devrait générer une tonne d'informations à ce sujet.
Liaison dynamique sur Mac OS X, un petit exemple
Pas:
Problème: vous voulez "simplement" créer une bibliothèque pour les autres modules à utiliser. Cependant, il y a un tas de programmes intimidants - gcc, ld, macosx libtool, dyld - avec des millions d'options, du compost bien pourri et des différences entre MacOSX et Linux. Il y a des tonnes de pages de manuel (je compte 7679 + 1358 + 228 + 226 lignes en 10.4.11 ppc) mais pas beaucoup d'exemples ou de programmes avec un mode "dites-moi ce que vous faites".
(La chose la plus importante à comprendre est de vous faire un APERÇU simplifié: dessinez des images, exécutez quelques petits exemples, expliquez-le à quelqu'un d'autre).
Contexte: Apple OverviewOfDynamicLibraries , Wikipedia Dynamic_library
Étape 1, créez libmylib.dylib -
mymod.c:
#include <stdio.h>
void mymod( int x )
{
printf( "mymod: %d\n", x );
}
gcc -c mymod.c # -> mymod.o
gcc -dynamiclib -current_version 1.0 mymod.o -o libmylib.dylib
# calls libtool with many options -- see man libtool
# -compatibility_version is used by dyld, see also cmpdylib
file libmylib.dylib # Mach-O dynamically linked shared library ppc
otool -L libmylib.dylib # versions, refs /usr/lib/libgcc_s.1.dylib
Étape 2, compilez et liez callmymod -
callmymod.c:
extern void mymod( int x );
int main( int argc, char** argv )
{
mymod( 42 );
}
gcc -c callmymod.c
gcc -v callmymod.o ./libmylib.dylib -o callmymod
# == gcc callmymod.o -dynamic -L. -lmylib
otool -L callmymod # refs libmylib.dylib
nm -gpv callmymod # U undef _mymod: just a reference, not mymod itself
Étape 3, exécutez la liaison callmymod vers libmylib.dylib -
export DYLD_PRINT_LIBRARIES=1 # see what dyld does, for ALL programs
./callmymod
dyld: loaded: libmylib.dylib ...
mymod: 42
mv libmylib.dylib /tmp
export DYLD_LIBRARY_PATH=/tmp # dir:dir:...
./callmymod
dyld: loaded: /tmp/libmylib.dylib ...
mymod: 42
unset DYLD_PRINT_LIBRARIES
unset DYLD_LIBRARY_PATH
Cela termine un tout petit exemple; j'espère que cela aide à comprendre les étapes.
(Si vous faites souvent cela, voir GNU Libtool qui est glibtool sur macs et SCons .)
à votre santé
- denis
Malheureusement, d'après mon expérience, la documentation d'Apple est désuète, redondante et il manque BEAUCOUP d'informations communes dont vous auriez normalement besoin.
J'ai écrit un tas de choses à ce sujet sur mon site Web où j'ai dû faire fonctionner FMOD (Sound API) avec mon jeu multiplateforme que nous avons développé à uni. C'est un processus étrange et je suis surpris que Apple n'ajoute pas plus d'informations sur leurs documents de développement.
Malheureusement, aussi "diaboliques" que Microsoft, ils font en fait un bien meilleur travail pour s'occuper de leurs développeurs avec la documentation (cela vient d'un Apple évangéliste).
Je pense que ce que vous ne faites pas, c'est APRÈS avoir compilé votre bundle .app. Vous devez ensuite exécuter une commande sur l'exécutable binaire /MyApp.app/contents/MacOS/MyApp afin de changer où l'exécutable recherche son fichier de bibliothèque. Vous devez créer une nouvelle phase de construction pouvant exécuter un script. Je ne vais pas expliquer à nouveau ce processus, je l'ai déjà fait en profondeur ici:
http://brockwoolf.com/blog/how-to-use-dynamic-libraries-in-xcode-31-using-fmod
J'espère que cela t'aides.
Connaissez-vous la Apple Rubriques de programmation de bibliothèque dynamique ? Elle devrait couvrir la plupart de ce dont vous avez besoin. Sachez qu'il existe des bibliothèques partagées qui sont chargées inconditionnellement à démarrage du programme et bibliothèques chargées dynamiquement (bundles, IIRC) qui sont chargées à la demande, et les deux sont quelque peu différents sur MacOS X des équivalents sur Linux ou Solaris.