Qtのクロスプラットフォームアプリケーション:Mac App Store

OS Xの開発が完了した後、不完全感が残る場合があります。完全な幸福のために、特にデスクトップアプリケーションを販売するのに最適なプラットフォームであるため、カタログにアプリケーションを表示したいと思います。 このテーマについては、公式ブログにQt 4.8の時点からの記事があり、 ハブではさらに古い記事あります。 幸いなことに、Qtを再構築する必要はもうありませんが、OS X 10.9の登場により、いくつかのバグが重大になり、脱出する必要があります。



開発者ステータスの取得、プロビジョニングプロファイルの作成、iTunes Connectでの新しいアプリケーションの登録など、些細で長い間考えられていたものについては説明しません。 このすべてがすでに構成されており、プログラムの準備ができており、ただ待っているだけだと想定しています。 このようにダウンロードできるApplication Loaderが必要な追加のソフトウェアがあるため、Xcodeを使用したくありませんでした。 iStodoの学生向けのオーガナイザーのファイルは例として示されていますが、抽象的なものではなく、現実に近いものです。



そのため、最初に3つの追加ファイルが必要です: *アイコン 、Info.plist、Entitlements.plist



Info.plist



このファイルには、アプリケーションに関するすべての情報が含まれています(推奨フィールドの表はこちらです )。



最小限のワイヤフレームを次に示します。

<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>CFBundleDevelopmentRegion</key> <string>Russian</string> <key>CFBundleDisplayName</key> <string>iStodo</string> <key>CFBundleExecutable</key> <string>iStodo</string> <key>CFBundleIconFile</key> <string>iStodo.icns</string> <key>CFBundleIdentifier</key> <string>ru.istodo.istodo</string> <key>CFBundleInfoDictionaryVersion</key> <string>6.0</string> <key>CFBundleName</key> <string>iStodo</string> <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> <string>1.1.0</string> <key>CFBundleSignature</key> <string>????</string> <key>NSPrincipalClass</key> <string>NSApplication</string> <key>LSApplicationCategoryType</key> <string>public.app-category.productivity</string> </dict> </plist>
      
      





非標準のplistを各アセンブリ中にバンドルに自動的に追加するには、プロジェクトファイルに追加する必要があります。

 QMAKE_INFO_PLIST= $${PWD}/Info.plist
      
      





同時に、デバッグ用に.proファイルに数行をすぐに追加します。

 QMAKE_CFLAGS += -gdwarf-2 QMAKE_CXXFLAGS += -gdwarf-2
      
      





Entitlements.plist



App Storeを介してインストールされたプログラムは、 サンドボックスで機能します。そのためには、いくつかの準備が必要です。 ルールに従って、QDesktopServices :: storageLocation()を使用して、 company_name / application_name (iTunes Connectで指定されている)の形式のフォルダーにアクセスできるため、これらのパラメーターを明示的に設定する必要があります。

 QApplication::setOrganizationName("MyCompany") QApplication::setApplicationName("MyApp")
      
      





実際、資格は許可ファイルであり、その中で指定されていない機能はブロックされます。 たとえば、ネットワークで何かをしたい場合は、フラグcom.apple.security.network.clientなどを設定します。 ここに説明がある可能なキー。



さて、完成したファイルの例:

 <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> <key>com.apple.security.app-sandbox</key> <true/> <key>com.apple.security.files.user-selected.read-write</key> <true/> </dict> </plist>
      
      





転記



そのため、次のキーポイントを強調できます。





コピー


Qt SDKがインストールされているシステムだけでなくプログラムを実行するには、必要なすべてのプラグインとフレームワークをアプリケーションバンドルにコピーする特別なユーティリティmacdeployqtを実行する必要があります。 残念ながら、このユーティリティのエラーにより、フレームワークのInfo.plistファイルはコピーされません。これは作業には問題ありませんが、これらがないとアプリケーションに正しく署名することはできません。 プログラムがQtSqlモジュールを使用する場合、利用可能なすべてのドライバーがコピーされることに注意してください。 すべては問題ありませんが、 libqsqlodbc.dylibのためアプリケーションは「プライベートメソッドを使用するため」という文言で拒否され、 libqsqlpsql.dylibのために、古いライブラリを使用することを誓います。 運命を誘惑しないために、公開する前に不必要なドライバーを破壊する必要があり、同時にパッケージサイズをわずかに小さくします。 また、サイズを小さくするために、不要な画像形式のプラグインなどを削除できます。



署名する


OS X 10.9以降では、アプリケーションだけでなく、すべてのフレームワーク、プラグインに署名する必要があります。 テクニカルノート2206には、正しいバージョンはフレームワークフォルダーに署名することではなく、バージョンカタログに署名するように書かれているという事実にもかかわらず、実際にはこれを行うことができず、レビューについて苦情はありませんでした。

コマンドの例:

 codesign -s "3rd Party Mac Developer Application: Developer Name" myApp.app/Contents/Frameworks/QtSql.framework/ codesign -s "3rd Party Mac Developer Application: Developer Name" myApp.app/Contents/PlugIns/platforms/libqcocoa.dylib
      
      





すべてのライブラリに署名すると、アプリケーションキュー全体が到着します。ここで、資格ファイルが使用されます。

 codesign --entitlements myAppEntitlements.plist -s "3rd Party Mac Developer Application: Developer Name" myApp.app
      
      





すべてが順調に進んだかどうかを確認します。

 codesign --display --verbose=4 myApp.app
      
      





パックする


ここではすべてが1つのチームによって行われますが、公式マニュアルの作成以降に変更されています。

 productbuild --component "myApp.app" /Applications --sign "3rd Party Mac Developer Installer: Developer Name" --product "myApp.app/Contents/Info.plist" myApp.pkg
      
      





サンプルの場合、結果のパッケージをすぐに実行できます。

 sudo installer -store -pkg myApp.pkg -target /
      
      





iTunes Connectに注ぐ




繰り返しますが、複雑なことはありません。アプリアイテムを配信するアプリケーションを選択し、パスを指定します。 pkg 。 多くの人々は、注ぐプロセスの間に問題(凍結)に直面します、実用的な解決策はここにあります。



スクリプト



その結果、多くの手作業が必要になります。フレームワークの.plistファイルをコピーし、各ライブラリに署名する...プロセスを完全に自動化するPythonスクリプトが作成されました。 スクリプトは、アセンブリディレクトリ(または少なくともプログラムバンドルと同じディレクトリ)にあると想定されています。 myApp_1.2という形式の別のフォルダーが作成されます。このフォルダーには、すべてが正常に実行されると、作業の結果(.pkgファイル)が表示されます。 設定するには、パラメーターを使用してブロックを編集する必要があります-アプリケーション名、バージョン、Qtの場所、アクセス許可を持つファイル名、開発者に関する情報を指定します。

 version = "1.2" appName = "myApp" devName = "Developer Name" pathToQt = "/Users/_USER_NAME_/Qt5.2.0/5.2.0/clang_64/" entitlements = "myAppEntitlements.plist"
      
      





スクリプト
 # -*- coding: utf-8 -*- import os import glob import shutil from subprocess import call # Setup app info (Don't forget to change the version in the Info.plist) version = "1.2" appName = "myApp" devName = "Developer Name" pathToQt = "/Users/_USER_/Qt5.2.0/5.2.0/clang_64/" entitlements = "myAppEntitlements.plist" fullApp = appName +".app" dirName = appName + "_" + version # if we need only libqsqlite.dylib sqliteOnly = True sqldriversDir = fullApp+"/Contents/PlugIns/sqldrivers/" frameworksDir = fullApp+"/Contents/Frameworks/" pluginsDir = fullApp+"/Contents/PlugIns/" print("Prepearing to deploy...") # Check files and paths if not os.path.exists(pathToQt) or not os.path.isdir(pathToQt): print("Incorrect path to Qt") exit() if not os.path.exists(fullApp) or not os.path.isdir(fullApp): print("App bundle not found") exit() if not os.path.exists(entitlements) or os.path.isdir(entitlements): print("Entitlements file not found") exit() #remove old build if os.path.exists(dirName): shutil.rmtree(dirName) os.makedirs(dirName) # Copy all necessary files to new folder shutil.copy(entitlements, dirName) shutil.copytree(fullApp, dirName+"/"+fullApp) # Copy Qt libs for create independent app os.chdir(os.getcwd()+"/"+dirName) print("\nDeploying Qt to .app bundle...") call([pathToQt+"bin/macdeployqt", fullApp]) print("...done\n") # Other libs in Qt 5.2(at least) will be rejected from Mac App Store anyway if sqliteOnly and os.path.exists(sqldriversDir): sqllibs = glob.glob(sqldriversDir+"*.dylib") for lib in sqllibs: if os.path.basename(lib) != "libqsqlite.dylib": os.remove(lib) # Copy plists for frameworks (it's fix macdeployqt bug) frameworks = os.listdir(frameworksDir) for framework in frameworks: shutil.copy(pathToQt+"lib/"+framework+"/Contents/Info.plist", frameworksDir+framework+"/Resources/") print("\nSigning frameworks, dylibs, and binary...") # Sign frameworks (it's strange, but we can't sign "Versions" folder) os.system('codesign -s "3rd Party Mac Developer Application: '+devName+'" '+frameworksDir+"*") # Sign plugins pluginGroups = os.listdir(pluginsDir) for group in pluginGroups: os.system('codesign -s "3rd Party Mac Developer Application: '+devName+'" '+pluginsDir+group+"/*") # Sign app os.system('codesign --entitlements '+entitlements+' -s "3rd Party Mac Developer Application: '+devName+'" '+fullApp) print("\nCheck signing:") os.system("codesign --display --verbose=4 "+fullApp) # - - - print("\nBuilding package...") os.system('productbuild --component "'+fullApp+'" /Applications --sign "3rd Party Mac Developer Installer: '+devName+'" --product "'+fullApp+'/Contents/Info.plist" '+appName+'.pkg') print("...done\n") print('\nFor test install, run follow command: sudo installer -store -pkg '+dirName+'/'+appName+'.pkg -target /')
      
      





Bitbucket



結果https://itunes.apple.com/en/app/istodo/id840850188?mt=12です

結論として、Mac App Storeでの公開のためにQtアプリケーションを準備することは特に難しいことではありませんが、すべてを手動で行うのは面倒です。



目次



公式ガイド:

developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/Introduction/Introduction.html

developer.apple.com/library/mac/documentation/IDEs/Conceptual/AppDistributionGuide/SubmittingYourApp/SubmittingYourApp.html



All Articles