Статически связать OpenSSL в XCode

Я пытаюсь связать статические библиотеки libssl.a и libcrypto.a в проекте командной строки XCode [в разделе Link Binary With Libraries]. Я включил файлы заголовков Openssl в путь поиска.

Компиляция завершается успешно, но выполнение завершается с ошибкой dyld: Library not loaded: /usr/local/ssl/lib/libcrypto.1.0.0.dylib.

Почему он ищет dylib, когда я связываю его статически? Как это можно исправить?

Любая помощь будет ценной.


person ZestyZest    schedule 19.06.2015    source источник
comment
Анил - это iOS, OS X или и то, и другое?   -  person jww    schedule 21.06.2015


Ответы (1)


Почему он ищет dylib, когда я связываю его статически? Как это можно исправить?

Компоновщик Apple использует dylib или общий объект, если он доступен, независимо от ваших флагов компоновщика, таких как -rpath и -Bstatic. Они делают это даже на iOS, где дилибы запрещены!

Это хорошо известная проблема, как только вы о ней узнаете :) См., например, Установка Crypto++ 5.6.2 в Mac OS X. Crypto++ имеет те же проблемы с инструментами Apple.

Исправление состоит в том, чтобы остановить с помощью параметров -L и -l и напрямую связать объектный файл или архив. Архив — это просто набор объектных файлов, поэтому вы можете использовать их взаимозаменяемо.

Чтобы указать объектные файлы или архивы для компоновщика, см. Ссылка на объектный файл. В Xcode вы добавляете полное имя архива (например, /usr/local/openssl-ios/lib/libcrypto.a) в список Другие флаги компоновщика (OTHER_LDFLAGS параметр Xcode).

При добавлении полного архива в OTHER_LDFLAGS, я полагаю, вы просто добавляете его дословно, без каких-либо переключателей, таких как -l или -L. Вам может понадобиться -Wl (-Wl,/usr/local/openssl-ios/lib/libcrypto.a), но вы не используете -l (-l/usr/local/openssl-ios/lib/libcrypto.a).

Вы используете -Wl, когда опция передается компоновщику через драйвер компилятора. Если компоновщик вызывается напрямую, вам не нужен -Wl и его не следует использовать.


Второй вариант — установить GCC_LINK_WITH_DYNAMIC_LIBRARIES на YES. Apple не документирует это в Xcode Справочник по настройкам сборки, но он явно под моей копией Xcode. См. Как связать статическую библиотеку для iOS в Stack Overflow.

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


Третий вариант — удалить dylib или общий объект из всех путей, используемых в Xcode, чтобы Xcode случайно не нашел его при использовании -lcrypto.


Четвертый вариант — разрешить динамическое связывание, но выполнить программу с ссылкой DYLD_LIBRARY_PATH. Его OS X эквивалентен LD_LIBRARY_PATH и гарантирует загрузку вашей копии OpenSSL (например, 1.0.2), а не системной версии OpenSSL (0.9.8).

Но мне не нравится этот вариант, потому что он требует, чтобы пользователи вашего программного обеспечения что-то делали.


Другая возможность, связанная с сообщением dyld: Library not loaded: /usr/local/ssl/lib/libcrypto.1.0.0.dylib, заключается в том, чтобы подписать вашу копию библиотеки. Немного странно, что он найден, но не загружен, поэтому я собираюсь выбросить это на случай, если его OS X Подписание кода или Служба привратника ...

Чтобы подписать код вашей копии библиотеки в рамках программы MAC Developer, просто:

codesign -fs "Johnny Developer" /usr/local/ssl/lib/libcrypto.so
person jww    schedule 21.06.2015
comment
Большое спасибо. 1) Это работает, если я использую -Wl,$path_to_lib.a в OTHER_LINKER_FLAGS, даже если я удаляю библиотеки из Link Binary With Library. Как это вообще возможно? Надеюсь предустановленный на MAC openssl не мешает? 2) Всегда ли openssl устанавливается на MAC-OSX по умолчанию? Если это так, будет ли иметь значение, если мы будем использовать его напрямую (используя NSTask), не вдаваясь в сложности статического или динамического связывания. - person ZestyZest; 22.06.2015
comment
Подбирает нужную версию. Я создал статическую библиотеку версии 1.0.2a, а вывод SSLeay_version — 1.0.2a 19 марта. Также имеет ли смысл, если openssl предустановлен всегда, мы можем напрямую вызывать функции openssl через NSTask, не связывая его с проектом? - person ZestyZest; 22.06.2015
comment
1.0.2a, 19 марта — последняя версия 1.0.2c, в ней исправлены ошибки безопасности. Имеет ли смысл предустанавливать openssl... — версия OpenSSL от Apple — 0.9.8. В нем отсутствует большая часть поддержки EC, TLS 1.1 и TLS 1.2 (среди прочего). Вероятно, вам следует избегать этого. - person jww; 22.06.2015
comment
Как это вообще возможно? - о, мой плохой... Да, это работает. Это работает, потому что вы указываете объектные файлы для ссылки на компоновщик. Архив — это просто набор объектных файлов. Даже если вы используете этот трюк, убедитесь, что вы используете -I... для указания файлов заголовков для этой конкретной библиотеки. - person jww; 22.06.2015
comment
У меня возникла аналогичная проблема после обновления с Xcode 9 до Xcode 10. Мое приложение для iOS создается и запускается, но при запуске openssl.framework image not found... ?? Я должен упомянуть, что для обновления Xcode 10 (Swift 4.2) потребовались pod repo update и pod install. - person jbm; 18.10.2018