В конце концов, все оказалось не так просто, как я думал. Это работает, но есть оговорки.
Основываясь на ответах Андона М. Коулмана и Александра Климетчека, вот функция сценария, которая берет имена dylib из Homebrew, копирует их в каталог Contents/Frameworks
пакета приложений и устанавливает соответствующий путь поиска исполняемого файла, используя install_name_tool
. Я заметил, что иногда фактическое местоположение .dylib отличается от того, что находит компоновщик Xcode при сборке исполняемого файла, и это также обрабатывается, запрашивая exe с помощью otool -L
.
Сценарий ниже копирует .dylib для библиотеки liblo в комплект приложения. Добавление новых библиотек должно быть таким же простым, как добавление новой строки copy lib ###.dlyib
в конец скрипта.
# exit on error
set -e
# paths
LOCALLIBS_PATH="$SRCROOT/libs"
HOMEBREW_PATH="/usr/local"
FRAMEWORKS_PATH="$BUILT_PRODUCTS_DIR/$FRAMEWORKS_FOLDER_PATH"
EXE_PATH="$BUILT_PRODUCTS_DIR/$EXECUTABLE_FOLDER_PATH/$EXECUTABLE_NAME"
# code signing identity
IDENTITY="$EXPANDED_CODE_SIGN_IDENTITY_NAME"
if [ "$IDENTITY" == "" ] ; then
IDENTITY="$CODE_SIGN_IDENTITY"
fi
# copy lib into Contents/Frameworks and set lib search path
# $1: library .dylib
# $2: optional path to libs folder, otherwise use Homebrew
copylib() {
LIB=$1
if [ "$2" == "" ] ; then
# use homebrew
LIB_PATH=$(find "$HOMEBREW_PATH" -type f -name $LIB)
else
# use given path
LIB_PATH="$2/$LIB"
fi
echo "$LIB:"
echo " $LIB_PATH -> $FRAMEWORKS_FOLDER_PATH/$LIB"
# copy lib, set permissions, and sign
mkdir -p "$FRAMEWORKS_PATH"
cp "$LIB_PATH" "$FRAMEWORKS_PATH/"
chmod 755 "$FRAMEWORKS_PATH/$LIB"
codesign --verify --force --sign "$IDENTITY" "$FRAMEWORKS_PATH/$LIB"
# set new path within executable
OLD=$(otool -L "$EXE_PATH" | grep $LIB | awk '{print $1}')
NEW="@executable_path/../Frameworks/$LIB"
install_name_tool -change "$OLD" "$NEW" "$EXE_PATH"
# print to confirm new path
otool -L "$EXE_PATH" | grep $LIB
}
##### GO
# use lib from homebrew
copy lib liblo.7.dylib
# or use local lib
#copylib liblo.7.dylib "$LOCALLIBS_PATH/liblo/lib"
Добавьте это как фазу сборки Run Script в проекте Xcode. Вы также можете сохранить его как внешний файл и вызвать его с помощью sh
на этапе запуска сценария с помощью:
sh $PROJECT_DIR/path-to/copy-libs.sh
Пример вывода отчета о сборке:
liblo.7.dylib:
/usr/local/Cellar/liblo/0.29/lib/liblo.7.dylib ->> YOURAPP.app/Contents/Frameworks/liblo.7.dylib
@executable_path/../Frameworks/liblo.7.dylib (compatibility version 11.0.0, current version 11.0.0)
Вероятно, $(find $HOMEBREW_PATH -type f -name $LIB)
можно было бы улучшить, перейдя вместо этого по символической ссылке .dylib в /usr/local/lib
.
ОБНОВЛЕНИЕ: Возможно, вам также потребуется убедиться, что новые dylibs подписаны, иначе шаг подписи кода завершится сбоем при сборке, по крайней мере, это в конечном итоге произошло для меня. После этого Опубликовать SO, добавив --deep
к параметру Другие флаги подписи кода в настройках сборки проекта.
Возможно, есть лучший способ подписать только те файлы, которые добавляет скрипт, но мне не хотелось копаться в запуске codesign
вручную. Однако из того, что я читал, Apple не предлагает --deep
ни для чего, кроме временных исправлений, так что это, вероятно, не лучшая практика.
ОБНОВЛЕНИЕ 2. Запуск --deep
на самом деле не решил проблему, и приложение по-прежнему не запускалось на других компьютерах. В конце концов, мне пришлось подписать код скопированного .dylib вручную, что оказалось относительно просто.
Одно примечание: я столкнулся с двусмысленной ошибкой идентификации «Mac Developer» при запуске кода, который, казалось, был сбит с толку двумя сертификатами с одинаковым именем в цепочке ключей: т.е. текущий сертификат разработчика и предыдущий сертификат разработчика с истекшим сроком действия. Открытие Keychain Access и удаление сертификата с истекшим сроком действия решили проблему.
ОБНОВЛЕНИЕ 3: Использование переменной пути в кавычках для исправления путей с пробелами.
ОБНОВЛЕНИЕ 4: это решение отлично подходит для создания приложений для последних систем, но я столкнулся с проблемой подписи кода при запуске приложения в macOS 10.10. Судя по этому сообщению SO, более старые версии macOS используют другой алгоритм хеширования кодового знака, и приложение будет нормально работать в системе 10.12, но с ошибкой подписи кода в 10.10. В обеих системах codesign подтвердил, что все было подписано правильно.
По сути, вам нужно собрать библиотеки с набором -mmacosx-version-min
, чтобы codesign мог сказать, какие алгоритмы использовать для поддержки минимальной и последних версий macOS. Я пытался передать пользовательские CFLAGS/LDFLAGS в Homebrew при сборке liblo из исходного кода, но это невозможно без редактирования формулы варева. В конце концов, я решил написать скрипт сборки для самостоятельной сборки liblo из исходного кода и модифицировал скрипт копирования, чтобы он также мог размещаться локально. Теперь все наконец-то работает.
TLDR: библиотеки Homebrew отлично подходят для первоначальной разработки и тестирования, но создание библиотек вручную лучше подходит для развертывания.
person
danomatika
schedule
10.04.2018
install_name_tool -change
, чтобы исправить эту проблему. - person Andon M. Coleman   schedule 06.10.2013install_name_tool -change
в двоичном файле в OS X, он используется для изменения расположения файлов .dylib при запуске из пакета .app. Обычно речь идет о чем-то вроде@executable_path/../Frameworks/MyLib.dylib
. Но если вы используете графический интерфейс Xcode, он должен делать это за вас, когда вы связываете свой .app. Посмотрите здесь. Это также обсуждалось на SO, но на данный момент я не могу найти актуальный вопрос. - person Andon M. Coleman   schedule 06.10.2013