30 Stimmen

Wie erstelle ich eine dynamische Bibliothek (Dylib) mit Xcode?

Ich baue einige Befehlszeilen-Dienstprogramme in Xcode (plain C, keine Cocoa). Ich möchte, dass alle von ihnen meine angepasste Version von libpng verwenden, und ich möchte Platz sparen, indem Sie eine Kopie der Bibliothek unter allen ausführbaren Dateien teilen (ich habe nichts dagegen, neu zu verteilen .dylib mit ihnen).

Muss ich etwas zaubern, um libpng-Export-Symbole zu erhalten?

Hat "Binär mit Bibliotheken verknüpfen" Phasenverknüpfung statisch aufbauen?

Apples Dokumentationen erwähnen das Laden von Bibliotheken zur Laufzeit mit dlopen Aber wie kann ich Xcode dazu bringen, eine ausführbare Datei zu erstellen, ohne sich über fehlende Symbole zu beschweren?


Ich glaube, ich habe es herausgefunden:

  • libpng wurde nicht richtig gelinkt, weil ich 32/64-Bit-Programme und eine 32-Bit-Bibliothek erstellt habe. Die Build-Einstellungen der Bibliothek und der ausführbaren Dateien müssen übereinstimmen.

  • libpng's config.h muss tonnenweise Defines haben wie #define FEATURE_XXX_SUPPORTED

  • "Binär mit Bibliotheken verknüpfen" Build-Phase kommt mit dynamischen Bibliotheken gut zurecht, und DYLD_FALLBACK_LIBRARY_PATH Umgebungsvariable ist zum Laden erforderlich .dylib s aus dem Anwendungsbündel.

56voto

denis Punkte 20177

Dynamische Verknüpfung unter Mac OS X, ein kleines Beispiel

Schritte:

  1. eine Bibliothek libmylib.dylib erstellen, die mymod.o enthält
  2. einen "callmymod" kompilieren und linken, der ihn aufruft
  3. Aufruf von mymod aus callmymod, unter Verwendung von DYLD_LIBRARY_PATH und DYLD_PRINT_LIBRARIES

Problem: Sie wollen "nur" eine Bibliothek erstellen, die andere Module nutzen können. Es gibt jedoch einen entmutigenden Haufen von Programmen -- gcc, ld, macosx libtool, dyld -- mit Zillionen von Optionen, etwas verrottetem Kompost und Unterschieden zwischen MacOSX und Linux. Es gibt tonnenweise man-Seiten (ich zähle 7679 + 1358 + 228 + 226 Zeilen in 10.4.11 ppc) aber nicht viel in Form von Beispielen oder Programmen mit einem "Sag mir, was du tust"-Modus.

(Das Wichtigste beim Verstehen ist, eine vereinfachte ÜBERBLICK für sich selbst zu erstellen: zeichnen Sie einige Bilder, führen Sie einige kleine Beispiele durch, erklären Sie es einer anderen Person).

Hintergrund: apple ÜbersichtÜberDynamischeBibliotheken , Wikipedia Dynamische_Bibliothek


Schritt 1: libmylib.dylib erstellen --

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

Schritt 2, Kompilieren und Verknüpfen von 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

Schritt 3: Führen Sie callmymod aus, um libmylib.dylib zu verknüpfen.

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

Damit endet ein kleines Beispiel; ich hoffe, es hilft, die Schritte zu verstehen.
(Wenn Sie dies häufig tun, siehe GNU Libtool das ist Glibtool auf Macs, und SCons .)

7voto

Chris Hanson Punkte 53324

Sie müssen wahrscheinlich sicherstellen, dass die von Ihnen erstellte dynamische Bibliothek eine Datei mit exportierten Symbolen enthält, in der aufgelistet ist, was aus der Bibliothek exportiert werden soll. Es handelt sich dabei nur um eine flache Liste der zu exportierenden Symbole, eines pro Zeile.

Wenn Ihre dynamische Bibliothek erstellt wird, erhält sie außerdem eine Installationsname eingebettet, die standardmäßig der Pfad ist, unter dem sie erstellt wird. Anschließend wird alles, was darauf verlinkt, zuerst unter dem angegebenen Pfad suchen und erst danach einen (kleinen) Satz von Standardpfaden durchsuchen, die unter DYLD_FALLBACK_LIBRARY_PATH im dyld(1) Manpage .

Wenn Sie diese Bibliothek neben Ihre ausführbaren Dateien stellen wollen, sollten Sie ihren Installationsnamen so anpassen, dass er darauf verweist. Eine einfache Google-Suche nach "install name" sollte eine Menge Informationen dazu liefern.

7voto

Brock Woolf Punkte 45353

Leider ist die Dokumentation von Apple meiner Erfahrung nach veraltet, redundant und es fehlen viele Informationen, die man normalerweise braucht.

Ich habe auf meiner Website einiges darüber geschrieben, wie ich FMOD (Sound API) mit meinem plattformübergreifenden Spiel, das wir an der Uni entwickelt haben, zum Laufen bringe. Es ist ein seltsamer Prozess und ich bin überrascht, dass Apple nicht mehr Informationen auf ihre Entwickler Dokumente hinzufügen.

Unglücklicherweise, so "böse" wie Microsoft auch sein mag, leisten sie einen viel besseren Job, wenn es darum geht, ihre Entwickler mit Dokumentation zu versorgen (dies kommt von einem Apple-Evangelisten).

Ich denke, was Sie im Grunde nicht tun, ist NACH dem Kompilieren Ihres .app-Bündels. Sie müssen dann einen Befehl für die ausführbare Binärdatei /MyApp.app/contents/MacOS/MyApp ausführen, um zu ändern, wo die ausführbare Datei nach ihrer Bibliotheksdatei sucht. Sie müssen eine neue Build-Phase erstellen, die ein Skript ausführen kann. Ich werde diesen Prozess nicht noch einmal erklären, ich habe ihn hier bereits ausführlich beschrieben:

http://brockwoolf.com/blog/how-to-use-dynamic-libraries-in-xcode-31-using-fmod

Ich hoffe, das hilft.

4voto

Jonathan Leffler Punkte 694013

Kennen Sie die Apple-Referenzseite Themen der dynamischen Bibliotheksprogrammierung ? Es sollte das meiste abdecken, was Sie brauchen. Seien Sie sich bewusst, dass es gemeinsam genutzte Bibliotheken gibt, die beim Programmstart bedingungslos geladen werden, und dynamisch geladene Bibliotheken (Bundles, IIRC), die bei Bedarf geladen werden, und die beiden unterscheiden sich unter MacOS X etwas von den Entsprechungen unter Linux oder Solaris.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X