Quelles sont les différences entre .so et .dylib sur osx?

214

.dylib est l'extension de bibliothèque dynamique sur OSX, mais il n'a jamais été clair pour moi quand je ne peux / ne dois pas utiliser un objet partagé unix .so traditionnel.

Certaines des questions que j'ai:

  • Au niveau conceptuel, quelles sont les principales différences entre .so et .dylib?
  • Quand puis-je / dois-je utiliser l'un au-dessus de l'autre?
  • Trucs et astuces de compilation (Par exemple, le remplacement de gcc -shared -fPIC, car cela ne fonctionne pas sur osx)
Trent Davies
la source

Réponses:

206

Le format de fichier objet Mach-O utilisé par Mac OS X pour les exécutables et les bibliothèques fait la distinction entre les bibliothèques partagées et les modules chargés dynamiquement . Utilisez otool -hv some_filepour voir le type de fichier de some_file.

Les bibliothèques partagées Mach-O ont le type de fichier MH_DYLIBet portent l'extension .dylib. Ils peuvent être liés avec les indicateurs de l'éditeur de liens statiques habituels, par exemple -lfoopour libfoo.dylib. Ils peuvent être créés en passant l' -dynamiclibindicateur au compilateur. ( -fPICest la valeur par défaut et n'a pas besoin d'être spécifiée.)

Les modules chargeables sont appelés "bundles" dans le langage Mach-O. Ils ont le type de fichier MH_BUNDLE. Ils peuvent porter n'importe quelle extension; l'extension .bundleest recommandée par Apple, mais la plupart des logiciels portés sont utilisés .sopour des raisons de compatibilité. En règle générale, vous utiliserez des ensembles de plug-ins qui étendent une application; dans de telles situations, le bundle sera lié au binaire de l'application pour accéder à l'API exportée de l'application. Ils peuvent être créés en passant l' -bundleindicateur au compilateur.

Les dylibs et les bundles peuvent être chargés dynamiquement à l'aide des dlAPI (par exemple dlopen, dlclose). Il n'est pas possible de se lier à des bundles comme s'ils étaient des bibliothèques partagées. Cependant, il est possible qu'un bundle soit lié à de vraies bibliothèques partagées; ceux-ci seront chargés automatiquement lorsque le bundle est chargé.

Historiquement, les différences étaient plus importantes. Dans Mac OS X 10.0, il n'y avait aucun moyen de charger dynamiquement des bibliothèques. Un ensemble d'API dyld (par exemple NSCreateObjectFileImageFromFile, NSLinkModule) a été introduit avec 10.1 pour charger et décharger les bundles, mais ils ne fonctionnaient pas pour les dylibs. Une dlopenbibliothèque de compatibilité qui fonctionnait avec les bundles a été ajoutée en 10.3; dans 10.4, a dlopenété réécrit pour être une partie native de dyld et un support supplémentaire pour le chargement (mais pas le déchargement) des dylibs. Enfin, 10.5 a ajouté la prise en charge de l'utilisation dlcloseavec dylibs et a déconseillé les API dyld.

Sur les systèmes ELF comme Linux, les deux utilisent le même format de fichier ; n'importe quel morceau de code partagé peut être utilisé comme bibliothèque et pour le chargement dynamique.

Enfin, sachez que sous Mac OS X, "bundle" peut également faire référence à des répertoires avec une structure standardisée qui contient le code exécutable et les ressources utilisées par ce code. Il y a un certain chevauchement conceptuel (en particulier avec les "bundles chargeables" comme les plugins, qui contiennent généralement du code exécutable sous la forme d'un bundle Mach-O), mais ils ne doivent pas être confondus avec les bundles Mach-O discutés ci-dessus.

Références supplémentaires:

Miles
la source
1
Merci pour ce commentaire détaillé :) Dois-je bien comprendre que si je charge un bundle à partir d'un autre bundle (c'est-à-dire que le chemin est app -> bundle A -> bundle B), alors le bundle B ne pourra pas en voir symboles dans le lot A? Et si oui, existe-t-il des moyens de résoudre ce problème? Je viens de le frapper, je pense: stackoverflow.com/questions/4193539/…
Mikhail Edoshin
4
@noloader: -dynamiclibest un drapeau GCC. Il fait passer le compilateur -dylibà ld.
Miles
URL mise à jour pour la page de manuel de ld sur Mac OSX: manpages.info/macosx/ld.1.html
netpoetica
18

Le fichier .so n'est pas une extension de fichier UNIX pour la bibliothèque partagée.

Il se trouve que c'est un problème courant.

Vérifiez la ligne 3b sur la page sharedlib d'ArnaudRecipes

Fondamentalement, .dylib est l'extension de fichier mac utilisée pour indiquer une bibliothèque partagée.

Martin York
la source
9
@ninefingers. Correct. Mais certains outils utiliseront des valeurs par défaut, sauf si quelque chose est très explicite. Par exemple, les compilateurs utiliseront l'extension de libray partagée spécifique à la plate-forme lorsque l'indicateur -l <lib> est utilisé (l'indicateur réel peut très bien sur tous les compilateurs).
Martin York
14

La différence entre .dylib et .so sur mac os x réside dans la façon dont ils sont compilés. Pour les fichiers .so, vous utilisez -shared et pour .dylib, vous utilisez -dynamiclib. Les fichiers .so et .dylib sont interchangeables en tant que fichiers de bibliothèque dynamique et ont un type DYLIB ou BUNDLE. Voici la lecture des différents fichiers qui le montrent.

libtriangle.dylib:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL  0x00       DYLIB    17       1368   NOUNDEFS DYLDLINK TWOLEVEL NO_REEXPORTED_DYLIBS



libtriangle.so:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL  0x00       DYLIB    17       1256   NOUNDEFS DYLDLINK TWOLEVEL NO_REEXPORTED_DYLIBS

triangle.so:
Mach header
      magic cputype cpusubtype  caps    filetype ncmds sizeofcmds      flags
MH_MAGIC_64  X86_64        ALL  0x00      BUNDLE    16       1696   NOUNDEFS DYLDLINK TWOLEVEL

La raison pour laquelle les deux sont équivalents sur Mac OS X est pour la compatibilité descendante avec d'autres programmes UNIX OS qui se compilent dans le type de fichier .so.

Notes de compilation: que vous compiliez un fichier .so ou un fichier .dylib, vous devez insérer le chemin correct dans la bibliothèque dynamique pendant l'étape de liaison. Pour ce faire, ajoutez -install_name et le chemin d'accès au fichier à la commande de liaison. Si vous ne le faites pas, vous rencontrerez le problème vu dans cet article: Mac Dynamic Library Craziness (peut être Fortran uniquement) .

Zachary Kraus
la source
comment puis-je faire ./configurepour générer des .dylibfichiers plutôt que des fichiers groupés .so? ./configure --enable-sharedne fait pas cette tâche.
Admia
d'après mon expérience, la plupart des fichiers de configuration sur mac créeront un fichier .so ou un fichier de bibliothèque statique car les fichiers de configuration utilisent des noms de fichiers standard unix / linux.
Zachary Kraus
4

Juste une observation que je viens de faire lors de la construction d'un code naïf sur OSX avec cmake:

cmake ... -DBUILD_SHARED_LIBS=OFF ...

crée des fichiers .so

tandis que

cmake ... -DBUILD_SHARED_LIBS=ON ...

crée des fichiers .dynlib .

Peut-être que cela aide n'importe qui.

user2996950
la source