Подписать платформу для OSX 10.9

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

Я могу использовать 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

Ответы

Ответ 1

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

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

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

например.

$ 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

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

Ответ 2

Резюме

  • Исправьте искаженные структуры Qt, переместив Info.plist в папку "Ресурсы" на текущем уровне версии в рамках.
  • Используйте параметр codeign --deep для одновременного подписания всех двоичных файлов в пакете, включая фреймворки и плагины.

Подробнее

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

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

Чтобы исправить фреймворки Qt, скопируйте Info.plist в папку "Ресурсы" в конкретной версии фреймворка, а не на верхний уровень фреймворка (как было ранее предложено). Кроме того, вы можете захотеть выбросить оригинальную копию 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, используя требования frameworks/plugins. Затем вы можете снова подписать параметр --force, но без опции --deep, указав требования уровня приложения. Результатом будет то, что основное приложение будет подписано с требованиями приложения, и все подзадачи будут подписаны с требованиями к фреймворкам/плагину.

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

Ответ 3

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

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

то есть.

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

С уважением,

Райнер

Ответ 4

Я написал script на основе ответа Benoît, который выполняет работу по исправлению файла .app: https://gist.github.com/kainjow/8059407

Код:

#!/usr/bin/env ruby

# Copies missing Info.plist files for a .app 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://stackoverflow.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 

Ответ 5

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

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

Ответ 6

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

# we need to massage qt frameworks so they get codesigned by the new codesign
# more information about this $#@[email protected]# piece of [email protected]#[email protected]$!
# 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