Подпишите рамки для OSX 10.9

После использования macdeployqt Я подписываю свое заявление, чтобы избежать проблем с привратником.

я могу использовать codesign на всех платформах и внутри пакета, но когда я прихожу, чтобы подписать пакет, я получаю сообщение об ошибке:

$ codesign --force --verify --verbose --sign "Developer ID Application: My ID" MyApplication.app
MyApplication.app: bundle format unrecognized, invalid, or unsuitable
In subcomponent: /Users/username/Dev/Apps/MyApplication/MyApplication.app/Contents/Frameworks/QtConcurrent.framework

Если я проверю подпись:

$codesign -vvv MyApplication.app/Contents/Frameworks/QtConcurrent.framework/Versions/5/QtConcurrent 
MyApplication.app/Contents/Frameworks/QtConcurrent.framework/Versions/5/QtConcurrent: valid on disk
MyApplication.app/Contents/Frameworks/QtConcurrent.framework/Versions/5/QtConcurrent: satisfies its Designated Requirement

Согласно http://furbo.org/2013/10/17/code-signing-and-mavericks/ кажется, что я должен подписать пакет фреймворка примерно так

$ codesign --force --verify --verbose --sign "Developer ID Application: My ID" MyApplication.app/Contents/Frameworks/QtConcurrent.framework/Versions/5

но это приводит к

MyApplication.app/Contents/Frameworks/QtConcurrent.framework/Versions/5: bundle format unrecognized, invalid, or unsuitable

6 ответов

Решение

Получил ту же ошибку этим утром. Кодовое приложение кажется более строгим в OSX 10.9

Проблема вызвана тем, что macdeployqt не копирует файл info.plist комплектов инфраструктуры Qt в комплект приложений.

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

например

$ cp ~/Qt5.2.0/5.2.0-beta1/clang_64/lib/QtCore.framework/Contents/Info.plist MyApplication.app/Contents/Frameworks/QtCore.framework/Resources/

Сделайте это для каждого из модулей qt, которые использует ваше приложение, ПОСЛЕ вызова macdeployqt*, но ДО вызова кодового знака. (* или mkdir каталоги назначения)

Кроме того, вызывайте кодовый знак в папках фреймворка, а не в подпапке версии.

т.е.

$ codesign --force --verify --verbose --sign "Developer ID Application: My ID" MyApplication.app/Contents/Frameworks/QtConcurrent.framework

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

Резюме

  1. Исправьте неверно сформированные фреймворки Qt, переместив Info.plist в папку Resources на текущем уровне версии в фреймворке.
  2. Используйте параметр codesign --deep, чтобы подписать все двоичные файлы в пакете, включая фреймворки и плагины.

подробности

Самый простой способ решить эту проблему - использовать опцию --deep codesign. Эта опция (которая, как я полагаю, была введена с Mavericks) подпишет все двоичные файлы в целевом пакете, включая двоичный файл основного приложения, а также его фреймворки и плагины.

Однако, прежде чем использовать эту опцию (или любую другую предложенную технику подписи), вы должны исправить каркасы Qt, как и в других публикациях в этой теме. По какой-то странной причине встроенные фреймворки Qt не соответствуют нормам фреймворка Apple и будут путать инструмент кодирования. Это, в свою очередь, может привести к плохому поведению, такому как замена символической ссылки верхнего уровня платформы дополнительной копией подписанного двоичного файла платформы.

Чтобы исправить фреймворки Qt, вы должны скопировать Info.plist в папку Resources в конкретной версии фреймворка, а не на верхний уровень фреймворка (как было предложено ранее). Кроме того, вы можете захотеть выбросить оригинальную копию Info.plist в инфраструктуру пакета приложения, поскольку она в основном не в том месте.

В частности, вы должны сделать что-то вроде этого, чтобы исправить каждую структуру по мере необходимости:

mkdir -p MyKillerApp.app/Contents/Frameworks/QtCore.framework/Versions/Current/Resources
cp lib/QtCore.framework/Contents/Info.plist MyKillerApp.app/Contents/Frameworks/QtCore.framework/Versions/Current/Resources
rm -rf MyKillerApp.app/Contents/Frameworks/QtCore.framework/Contents

Выше предполагается, что в платформе есть символьная ссылка "Версии / Текущий". Я думаю, что это относится ко всем встроенным библиотекам Qt. Но если это не так для вашей сборки, то вы можете использовать конкретное имя папки версии (например, "4") вместо символической ссылки "Текущая".

После нормализации фреймворков вы можете использовать опцию --deep, чтобы подписать все двоичные файлы в пакете приложения:

codesign --deep --force --verify --sign "Developer ID Application: My ID" MyKillerApp.app

В качестве альтернативы, если вы включили кодовое обозначение на уровне проекта для последующей обработки развертывания, вы можете просто передать параметр --deep в "Другие флаги подписи кода":

OTHER_CODE_SIGN_FLAGS = --deep

Если у вас есть другие требования кодового знака для вашего основного приложения, чем для ваших фреймворков или плагинов, вы можете использовать небольшой трюк. Сначала вы подпишитесь с опцией --deep, используя требования фреймворков / плагинов. Затем вы можете снова подписать с параметром --force, но без параметра --deep, указав требования уровня приложения. Результатом будет то, что основное приложение будет подписано с требованиями к приложению, а все вспомогательные файлы будут подписаны с требованиями к фреймворкам / плагинам.

Этот подход может считаться немного ленивым и расточительным, так как вы подписываете основное приложение дважды. Но это проще, чем альтернатива нахождения и подписи всех вспомогательных двоичных файлов отдельно от основного двоичного файла приложения.

Большое спасибо!

Вы также должны подписать все плагины, используемые вашим приложением

т.е.

$ codesign --force --verify --verbose --sign "Developer ID Application: My ID" MyApplication.app/Contents/PlugIns/imageformats/libqgif.dylib

С наилучшими пожеланиями,

Rainer

Согласно документации Apple, вы должны подписывать папки версий, а не сам фреймворк. Я попробовал это и столкнулся с двумя проблемами. Прежде всего, некоторые из файлов Info.plist фреймворков Qt имеют неверные имена исполняемых файлов (суффикс _debug). После исправления, мне удалось подписать все фреймворки "яблочным путем". Однако после этого я не смог подписать основное приложение и получил ошибки об инфраструктурах Qt, которые я только что подписал.

Поэтому странное, но работающее решение - подписывать папки фреймворка. Это работает даже с неверными именами исполняемых файлов в файлах Info.plist.

Я использую этот скрипт для исправления каркасов QT 4.8 перед кодированием. Надеюсь это поможет. Мне и коллеге потребовалось около 3-4 дней, чтобы понять это (это было до публикации в блоге QT).

# we need to massage qt frameworks so they get codesigned by the new codesign
# more information about this $#@$!@# piece of $@#$@$!
# http://blog.qt.digia.com/blog/2014/10/29/an-update-on-os-x-code-signing/

QT_LIB_DIR=$(qmake -query QT_INSTALL_LIBS)
for i in $(find "$APP/Contents/Frameworks/" -name Qt\*.framework); do
   FW_NAME=$(basename "$i")
   FW_SHORTNAME=$(basename -s ".framework" "$i")
   mv "$i/Resources" "$i/Versions/4"
   ln -s Versions/Current/Resources "$i/"
   ln -s Versions/Current/${FW_SHORTNAME} "$i/${FW_SHORTNAME}"
   ln -s 4 "$i/Versions/Current"
   cp "${QT_LIB_DIR}/${FW_NAME}/Contents/Info.plist" "$i/Resources"
   chmod u+w "$i/Resources/Info.plist"
   # now comes the real magic, we have to add CFBundleIdentifier and CFBundleVersion to the Info.plist
   awk "/<\/dict>/{print \"<key>CFBundleIdentifier</key>\n<string>org.qt-project.${FW_SHORTNAME}</string>\"}1" "$i/Resources/Info.plist" > "$i/Resources/Info.plist.tmp"
   mv "$i/Resources/Info.plist.tmp" "$i/Resources/Info.plist"
   awk '/<\/dict>/{print "<key>CFBundleVersion</key>\n<string>4.8</string>"}1' "$i/Resources/Info.plist" > "$i/Resources/Info.plist.tmp"
   mv "$i/Resources/Info.plist.tmp" "$i/Resources/Info.plist"
done

Я написал сценарий, основанный на ответе Бенуа, который исправляет файл.app: https://gist.github.com/kainjow/8059407

Код:

#!/usr/bin/env ruby

# Copies missing Info.plist files for a .app's Qt frameworks installed
# from macdeployqt. Without the plists, 'codesign' fails on 10.9 with
# "bundle format unrecognized, invalid, or unsuitable".
#
# Example usage:
# ruby macdeployqt_fix_frameworks.rb /Users/me/Qt5.2.0/5.2.0/clang_64/ MyProgram.app
#
# Links:
# https://bugreports.qt-project.org/browse/QTBUG-23268
# http://stackru.com/questions/19637131/sign-a-framework-for-osx-10-9
# http://qt-project.org/forums/viewthread/35312

require 'fileutils'

qtdir = ARGV.shift
dotapp = ARGV.shift

abort "Missing args." if !qtdir || !dotapp
abort "\"#{qtdir}\" invalid" if !File.exists?(qtdir) || !File.directory?(qtdir)
abort "\"#{dotapp}\" invalid" if !File.exists?(dotapp) || !File.directory?(dotapp)

frameworksDir = File.join(dotapp, 'Contents', 'Frameworks')
Dir.foreach(frameworksDir) do |framework|
next if !framework.match(/^Qt.*.framework$/)
fullPath = File.join(frameworksDir, framework)
destPlist = File.join(fullPath, 'Resources', 'Info.plist')
next if File.exists?(destPlist)
srcPlist = File.join(qtdir, 'lib', framework, 'Contents', 'Info.plist')
abort "Source plist not found: \"#{srcPlist}\"" if !File.exists?(srcPlist)
FileUtils.cp(srcPlist, destPlist)
end 
Другие вопросы по тегам