Как вы кодируете пакеты фреймворков для Mac App Store?

После недавнего представления я получил следующую ошибку:

Недействительная подпись - вложенный пакет приложений (FooBar.app/Contents/Frameworks/GData.framework) не подписан, подпись недопустима или не подписана с сертификатом подачи Apple. Для получения дополнительной информации см. Руководство по песочнице ввода кода и приложения.

Недействительная подпись - вложенный пакет приложений (FooBar.app/Contents/Frameworks/Growl.framework) не подписан, подпись недопустима или не подписана с сертификатом подачи Apple. Для получения дополнительной информации см. Руководство по песочнице ввода кода и приложения.

Недействительная подпись - вложенный пакет приложений libcurl (FooBar.app/Contents/Frameworks/libcurl.framework) не подписан, подпись недопустима или не подписана с сертификатом подачи Apple. Для получения дополнительной информации см. Руководство по песочнице ввода кода и приложения.

Итак, я подписал все пакеты фреймов в Technote 2206:

codesign -f -v -s "3rd Party Mac Developer Application: Name" ./libcurl.framework/Versions/A/libcurl
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./libcurl.framework/Versions/A/libssh2.1.dylib
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./Growl.framework/Versions/A/Growl
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./GData.framework/Versions/A/GData

Technote 2206 говорит:

Рамки подписи

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

# Это неправильный путь:

codeign -s my-signature-identity../FooBarBaz.framework

# Правильный путь:

codeign -s my-signature-identity../FooBarBaz.framework/Версии/A

И когда я пытаюсь проверить результаты, это выглядит хорошо:

% codesign -vvv FooBar.app/Contents/Frameworks/libcurl.framework
FooBar.app/Contents/Frameworks/libcurl.framework: valid on disk
FooBar.app/Contents/Frameworks/libcurl.framework: satisfies its Designated Requirement
% codesign -vvv FooBar.app/Contents/Frameworks/Growl.framework
FooBar.app/Contents/Frameworks/Growl.framework: valid on disk
FooBar.app/Contents/Frameworks/Growl.framework: satisfies its Designated Requirement

Для удовольствия я попытался напрямую подписать пакет фреймов, и он все еще был отклонен. Но это именно то, что сказано в документации.

Любые догадки, почему это считается недействительным? Я использую тот же сертификат, который я использую для кодового знака моего приложения - того, который работал в прошлом.

Мое единственное предположение было бы связано с существующими plists (мне нужно владеть идентификаторами в инфраструктуре Info.plists?) или права - любые предложения?

Ответ 1

На основе ответа baptrs я разработал эту оболочку script, которая координирует все мои фреймворки и другие двоичные ресурсы/вспомогательные исполняемые файлы (в настоящее время поддерживаемые типы: dylib, bundle и login):

#!/bin/sh

# WARNING: You may have to run Clean in Xcode after changing CODE_SIGN_IDENTITY! 

# Verify that $CODE_SIGN_IDENTITY is set
if [ -z "${CODE_SIGN_IDENTITY}" ] ; then
    echo "CODE_SIGN_IDENTITY needs to be set for framework code-signing!"

    if [ "${CONFIGURATION}" = "Release" ] ; then
        exit 1
    else
        # Code-signing is optional for non-release builds.
        exit 0
    fi
fi

if [ -z "${CODE_SIGN_ENTITLEMENTS}" ] ; then
    echo "CODE_SIGN_ENTITLEMENTS needs to be set for framework code-signing!"

    if [ "${CONFIGURATION}" = "Release" ] ; then
        exit 1
    else
        # Code-signing is optional for non-release builds.
        exit 0
    fi
fi

ITEMS=""

FRAMEWORKS_DIR="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
if [ -d "$FRAMEWORKS_DIR" ] ; then
    FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework" -or -name "*.dylib" -or -name "*.bundle" | sed -e "s/\(.*framework\)/\1\/Versions\/A\//")
    RESULT=$?
    if [[ $RESULT != 0 ]] ; then
        exit 1
    fi

    ITEMS="${FRAMEWORKS}"
fi

LOGINITEMS_DIR="${TARGET_BUILD_DIR}/${CONTENTS_FOLDER_PATH}/Library/LoginItems/"
if [ -d "$LOGINITEMS_DIR" ] ; then
    LOGINITEMS=$(find "${LOGINITEMS_DIR}" -depth -type d -name "*.app")
    RESULT=$?
    if [[ $RESULT != 0 ]] ; then
        exit 1
    fi

    ITEMS="${ITEMS}"$'\n'"${LOGINITEMS}"
fi

# Prefer the expanded name, if available.
CODE_SIGN_IDENTITY_FOR_ITEMS="${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
if [ "${CODE_SIGN_IDENTITY_FOR_ITEMS}" = "" ] ; then
    # Fall back to old behavior.
    CODE_SIGN_IDENTITY_FOR_ITEMS="${CODE_SIGN_IDENTITY}"
fi

echo "Identity:"
echo "${CODE_SIGN_IDENTITY_FOR_ITEMS}"

echo "Entitlements:"
echo "${CODE_SIGN_ENTITLEMENTS}"

echo "Found:"
echo "${ITEMS}"

# Change the Internal Field Separator (IFS) so that spaces in paths will not cause problems below.
SAVED_IFS=$IFS
IFS=$(echo -en "\n\b")

# Loop through all items.
for ITEM in $ITEMS;
do
    echo "Signing '${ITEM}'"
    codesign --force --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" --entitlements "${CODE_SIGN_ENTITLEMENTS}" "${ITEM}"
    RESULT=$?
    if [[ $RESULT != 0 ]] ; then
        echo "Failed to sign '${ITEM}'."
        IFS=$SAVED_IFS
        exit 1
    fi
done

# Restore $IFS.
IFS=$SAVED_IFS
  • Сохраните файл в своем проекте. Я сохраняю свою копию в подкаталоге Scripts в моем проекте root.
    • Моя называется codesign-frameworks.sh.
  • Добавьте фазу сборки "Запуск Script" сразу после фазы сборки "Копирование встроенных фреймворков".
    • Вы можете назвать его "Codesign Embedded Frameworks".
  • Вставить ./codesign-frameworks.sh (или все, что вы назвали своим script выше) в текстовое поле редактора script. Используйте ./Scripts/codesign-frameworks.sh, если вы храните script в подкаталоге.
  • Создайте приложение. Все вложенные структуры будут закодированы.

Если вы все равно получите ошибку "Identity: twoiguous (matches:...", прокомментируйте ниже. Этого больше не должно быть.

Обновлено 2012-11-14: добавление поддержки фреймворков со специальными символами в их имени (это не включает одинарные кавычки) в "codesign-frameworks.sh".

Обновлено 2013-01-30: добавление поддержки специальных символов во всех путях (это должно включать одинарные кавычки) в "codesign-frameworks.sh".

Обновлено 2013-10-29: добавление экспериментальной поддержки dylib.

Обновлено 2013-11-28: добавление поддержки прав. Улучшение поддержки экспериментального дилиба.

Обновлено 2014-06-13: Устранение проблем с кодовыми именами с помощью фреймворков, содержащих (вложенные) фреймворки. Это было сделано добавлением опции -depth в find, что приводит к тому, что find выполняет обход глубины. Это стало необходимым из-за проблемы, описанной здесь. Короче: содержащий пакет может быть подписан только в том случае, если его вложенные пакеты уже подписаны.

Обновлено 2014-06-28: добавление поддержки экспериментальных пакетов.

Обновлено 2014-08-22: Улучшение кода и предотвращение отказа для восстановления IFS.

Обновлено 2014-09-26: добавление поддержки для элементов входа.

Обновлено 2014-10-26: проверка котировок. Это исправляет ошибки "строка 31/42: слишком много аргументов", а результирующая ошибка "кодовый объект вообще не подписан" для путей, включая специальные символы.

Обновлено 2014-11-07: Устранение неоднозначной ошибки идентификации (например, "Разработчик Mac: неоднозначный..." ) при использовании автоматического разрешения идентичности в Xcode. Вам больше не нужно явно устанавливать идентификатор и использовать "Mac Developer"!

Обновлено 2015-08-07: Улучшение семантики.

Усовершенствования приветствуются!

Ответ 2

В вашем комментарии показано, что вы подписали объекты в каталоге версии пакета. "Технота" показывает, чтобы подписать сам каталог.

Следующие сочетания Technote лучше:

codesign -f -v -s "3rd Party Mac Developer Application: Name" ./libcurl.framework/Versions/A
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./Growl.framework/Versions/A
codesign -f -v -s "3rd Party Mac Developer Application: Name" ./GData.framework/Versions/A

Ответ 3

Вот как я это исправил;

  • Войдите в настройки сборки вашей цели
  • Найдите строку "Другие флаги подписи кода"
  • Введите --deep значение параметра деблокирования
  • Закрыть XCode
  • Войдите в папку производных данных на вашем Mac и удалите старые производные данные (путь по умолчанию: /Users/YOUR_USER_NAME/Library/Developer/Xcode/DerivedData)
  • Откройте Xcode и постройте

После сборки архива и отправки приложения снова...

Ответ 4

Одна вещь, о которой я не упоминал здесь, заключается в том, что вам нужно иметь свой Info.plist внутри /Resources внутри каталога версий. В противном случае при попытке подписания каталога с версией вы получите недопустимую, недействительную или неподходящую ошибку формата пакета.

Я предоставил более расширенный ответ здесь: Как Codesign Growl.framework для Sandboxed Mac App