Как создать динамическую библиотеку (dylib) с помощью Xcode?

Я создаю несколько утилит командной строки в Xcode (plain C, no Cocoa). Я хочу, чтобы все они использовали мою настроенную версию libpng, и я хочу сэкономить место, разделив одну копию библиотеки среди всех исполняемых файлов (я не против перераспределения .dylib с ними). ​​

Нужно ли мне делать магию, чтобы получить символы экспорта libpng?

Создает ли ссылка Link Binary With Libraries статическую фазу?

Apple docs упоминает загрузку библиотек во время выполнения с помощью dlopen, но как я могу заставить Xcode создавать исполняемые файлы без жалоб на недостающие символы?


Думаю, я понял:

  • libpng не связывался правильно, потому что я создал 32/64-разрядные исполняемые файлы и 32-битную библиотеку. Параметры сборки библиотеки и исполняемых файлов должны соответствовать.

  • libpng config.h нуждается в тоннах таких как #define FEATURE_XXX_SUPPORTED

  • "Строка компоновки бинарных ссылок с библиотеками" отлично обрабатывает динамические библиотеки, а переменная окружения DYLD_FALLBACK_LIBRARY_PATH необходима для загрузки .dylib из пакета приложений.

Ответ 1

Вероятно, вам нужно убедиться, что вы создаете динамическую библиотеку с экспортированным символьным файлом, в котором указано, что должно быть экспортировано из библиотеки. Это просто плоский список символов, по одному на строку, для экспорта.

Кроме того, когда ваша динамическая библиотека построена, она получает встроенное в нее имя установки, по умолчанию это путь, по которому он построен. Впоследствии все, что связано с ним, будет искать его по указанному пути сначала и только после этого будет искать (маленький) набор путей по умолчанию, описанный в DYLD_FALLBACK_LIBRARY_PATH в dyld(1) справочная страница.

Если вы собираетесь разместить эту библиотеку рядом с вашими исполняемыми файлами, вы должны настроить ее имя для установки, чтобы ссылаться на нее. Просто выполните поиск Google для "установки имени", чтобы получить тонну информации об этом.

Ответ 2

Динамическая привязка к Mac OS X, крошечный пример

Шаги:

  • создать библиотеку libmylib.dylib, содержащую mymod.o
  • скомпилировать и связать "callmymod", который вызывает его
  • вызов mymod из callmymod, используя DYLD_LIBRARY_PATH и DYLD_PRINT_LIBRARIES

Проблема: вы просто хотите создать библиотеку для использования других модулей. Однако там сложная куча программ - gcc, ld, macosx libtool, dyld - с zillions опций, некоторый хорошо сгнивший компост и различия между MacOSX и Linux. Есть тонны страниц человека (я считаю 7679 + 1358 + 228 + 226 строк в 10.4.11 ppc) но не так много на примерах или программах с режимом "скажите мне, что вы делаете".

(Самое главное в понимании - упростить ОБЗОР для себя: нарисуйте несколько фотографий, запустите несколько небольших примеров, объясните это кому-то еще).

Справочная информация: apple OverviewOfDynamicLibraries, Wikipedia Dynamic_library


Шаг 1, создайте 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

Шаг 2, компиляция и ссылка 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

Шаг 3, запустите callmymod, ссылаясь на 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

Это заканчивается одним крошечным примером; надеюсь, что это поможет понять шаги.
(Если вы делаете это много, см. GNU Libtool который является glibtool на macs, и SCons.)
веселит
- denis

Ответ 3

К сожалению, по моему опыту документация Apple устарела, избыточна и отсутствует много общей информации, которую вам обычно нужно.

Я написал кучу вещей на этом сайте, где мне пришлось заставить FMOD (Sound API) работать с моей кросс-платформенной игрой, которую мы разработали на uni. Это странный процесс, и я удивлен тем, что Apple не добавляет больше информации о своих документах разработчиков.

К сожалению, как "зло", как Microsoft, они на самом деле делают гораздо лучшую работу по наблюдению за своими разработчиками с документацией (это исходит от евангелиста Apple).

Я думаю, в основном, что вы не делаете, ПОСЛЕ того, как вы скомпилировали ваш .app Bundle. Затем вам нужно запустить команду на исполняемом двоичном файле /MyApp.app/contents/MacOS/MyApp, чтобы изменить, где исполняемый файл ищет файл библиотеки. Вы должны создать новую фазу сборки, которая может запускать script. Я не буду объяснять этот процесс еще раз, я уже сделал это подробно:

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

Надеюсь, что это поможет.

Ответ 4

Знаете ли вы о справочной странице Apple Темы динамического программирования библиотек? Он должен покрывать большую часть того, что вам нужно. Имейте в виду, что общие библиотеки, которые загружаются безоговорочно при запуске программы и динамически загружаемых библиотеках (пачках, IIRC), которые загружаются по требованию, и два из них несколько отличаются от MacOS X от эквивалентов в Linux или Solaris.