1. 程式人生 > 實用技巧 >macOS(OSX10.14, Xcode10.3)釋出Qt(5.12.9)程式

macOS(OSX10.14, Xcode10.3)釋出Qt(5.12.9)程式

macOS(OSX10.14, Xcode10.3)釋出Qt(5.12.9)程式

1. 申請應用開發證書與釋出證書

https://developer.apple.com/

2. 應用的編譯、簽名、動態庫打包

2.1 設定Qt編譯環境

#檢視能否使用qmake
qmake -v
#如果不能執行qmake,則在/etc/profile增加以下內容
export QTDIR=/Applications/Qt5.12.9/5.12.9/clang_64
export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$QTDIR/lib
export PATH=$PATH:$QTDIR/bin

2.2 Qt工程轉化為Xcode工程(確保Qt工程編譯和執行都沒問題再做轉換)

  • 在Xcode上面編譯Qt工程可以設定簽名、沙盒還有其他釋出資訊,避免未知和繁瑣的命令列操作
qmake xxx.pro -spec macx-xcode
# 然後在.pro檔案目錄下可以看到Xcode工程配置檔案了

2.2 應用圖示設定

2.2.1 建立.iconset資料夾

2.2.2 使用Qt新增Icon

  • 將app.iconset裡面的圖片合成一個.icns圖片

    iconutil -c icns app.iconset -o app.icns
    
  • 在.pro檔案設定應用圖示

    # 這裡app.icns在同一個目錄
    ICON = app.icns
    

    這個方法Qt內編譯是有效的,但轉換成Xcode工程就不行了

2.2.3 使用Xcode新增Icon

  • 將app.iconset內的圖片複製到.pro檔案所在的目錄/專案名/Images.xcassets/AppIcon.appIconset/內
  • 在Xcode設定的General內找到App Icons,預設是Use asset Catalogs,點選它會提示Migrate app icons to an asset catalog
    ,再點選Migrate就可以看到左側Resource目錄多出一項Images.xcasset
  • 點選Images.xcasset,再點選AppIcon,就可以看到剛才放進去的圖片,現在要做的是把圖片拖拽到對應的位置,然後編譯就可以看到圖標出現在程式塢了

2.3 Xcode設定(點選螢幕左側的專案名)

PROJECT

  • 找到Packaging設定Product Bundle Identifier

    com.company_name.product_name

TARGETS

2.3.1 General

  • Identity

    在這裡可以填寫產品型別和版本資訊

    Bundle Identifier: com.company_name.product_name,必須要按這種格式,否則上傳應用報錯

    Version: 必須要填寫,否則上傳應用報錯

    Build: 必須要填寫,否則上傳應用報錯

  • Signing

    選擇Automatically manage signing,這樣Xcode會顯示這個應用需要哪些資訊,選擇team然後Xcode會自動幫你找到證書(前提是已安裝開發和釋出證書)

  • Deployment Info

    選擇最低的釋出平臺

  • App Icons

    見2.2.3

  • Linked Frameworks and Libraries

    在這裡可以新增macOS系統自帶的Frameworks,也可以新增Qt的framework

2.3.2 Capabilities

  • App Sandbox

    現在所有macOS應用都需要沙盒,都選應用需要獲取的訪問許可權。

    編譯之後會生成xxx.entitlements檔案,後面給第三方動態庫簽名會用到

2.3.3 Build Settings

  • Architextures

    選擇Release編譯模式,如果Qt工程沒有debug版本的動態庫最好設定scheme去掉debug編譯和執行(標題欄-->Product-->Scheme-->Edit Scheme)

2.3.4 Build Phases

如果不想每次編譯後手動執行指令碼,可以在Build Phases新增打包和簽名指令碼,個人推薦這麼做,因為編譯後手動操作打包簽名後上傳應用會莫名其妙地出現簽名錯誤問題

點選左上角+,新增Run Script

  • 新增Qt動態庫打包指令碼(在Link Binary With Libraries之後)

    /Applications/Qt5.12.9/clang_64/bin/macdeployqt $BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME
    
  • 新增Qt動態庫簽名指令碼(所有編譯操作之後)

    find $BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/Contents/PlugIns -name ".dylib" | xargs /usr/bin/codesign --force --sign xxcertificationsxx --entitlements xxx.entitlements --timestamp=none
    find $BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME/Contents/Frameworks -name ".framework" | xargs /usr/bin/codesign --force --sign xxcertificationsxx --entitlements xxx.entitlements --timestamp=none
    

添加了這個指令碼每次編譯前都清理一下(Product --> clean),另外這些簽名方法是在編譯資訊裡面找到的

2.3.5 Archive Post-actions (自定義生成Archive包操作)

使用Archive打包應用的優點在於比較容易在本地驗證應用是否存在問題,能夠在上傳應用之前排除一些規範問題

  • 設定Post-actions

    在Product找到Scheme選項,在Scheme選項找到Edit Scheme,在Edit Scheme找到Archive,點選Archive右側的三角形後會看到Post-actions,

    勾選Post-actions,新增Run Script,把打包和簽名的指令碼寫填上去

  • 執行Archive前必須清理工程,否則$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME可能不會生效,因為在Release Build之後$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME會指向Release目錄下的app

APP=$BUILT_PRODUCTS_DIR/$FULL_PRODUCT_NAME
/Applications/Qt5.12.9/clang_64/bin/macdeployqt $APP
find $APP/Contents/PlugIns -name ".dylib" | xargs /usr/bin/codesign --force --sign xxcertificationsxx --entitlements xxx.entitlements --timestamp=none
find $APP/Contents/Frameworks -name ".framework" | xargs /usr/bin/codesign --force --sign xxcertificationsxx --entitlements xxx.entitlements --timestamp=none

2.3.6 Xcode提示的設定

如果Xcode提示設定就跟著提示設定

2.4 打包Qt動態庫與第三方動態庫

2.4.1 使用macdeployqt打包程式動態庫

#切換到macdeployqt所在的目錄,或者在qt工程中右擊Open With Terminal,選擇Build Enviroment,執行
macdeployqt xxx.app
#把其他第三方動態庫也複製過來,我放置的目錄是xxx.app/Content/Frameworks
#如果缺少rwx相關的許可權要記得補充

2.4.2 修改動態庫連結路徑

如果第三方動態庫路徑不在xxx.app/Content內,那麼應該要修改一下動態庫路徑

# 檢視可執行檔案的動態庫依賴路徑
otool -L xxx.app/Content/MacOS/xxx
# 檢視動態庫路徑
otool -D xxx.dylib
# 修改路徑(我的動態庫都放在Frameworks這個資料夾中,對應的標識是@rpath)
sudo install_name_tool -id @rpath/xxx.dylib xxx.dylib

2.4.3 動態庫簽名

安裝好證書以後,簽名可以在Xcode或者鑰匙串都能找到

  • Qt Frameworks簽名
#切換到Frameworks路徑,使用macdeployqt打包以後在xxx.app/Content/目錄下可找到
find . -name "*.framework" | codesign --entitlements xxx.entitlements -s “Mac Developer:xxxxxx"
  • 動態庫簽名
# 切換到動態庫目錄
find . -name "*.dylib" | codesign --entitlements xxx.entitlements -s “Mac Developer:xxxxxx"

2.4.4 檢查應用是否已簽名

如果應用已被Xcode編譯執行成功,一般來說已經完成簽名了,可執行以下命令檢查

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

如果輸出簽名信息,則說明簽名成功了

3. 應用釋出

3.1 準備工作

  • 確保已在https://deleloper.apple.com/account/resources/identifiers/list 增加Identifiers
  • 確保已在https://appstoreconnect.apple.com/apps增加app

3.2 使用Archive釋出

這個方法會另外編譯工程,所以在Release資料夾下執行macdeployqt、簽名動態庫無效,Archive釋出的優點是自動簽名與上傳應用之前驗證應用

  • 確保2.3.5的Post-actions指令碼能正確執行

  • 執行Archive (Xcode標題欄 --> product --> Archive)

  • 檢查Archive包

    Archives編譯生成的執行檔案在/Users/xxx/Library/Developer/Xcode/Archives

    • 檢視動態庫和framwork是否完全打包
    • 檢查Archive包內的程式能否正常啟動
  • 驗證Archive包

    找到app目錄執行macdeployqt打包然後給動態庫簽名,最後在Archives視窗使用Distribute App 下方的Validate App驗證app

  • 上傳Archive包

    生成Archive檔案之後,在螢幕右側可以看到 Distribute App ,填好描述內容,點選它可以看到釋出方法,第一個方法是可以直接釋出到Mac App Store

3.3 使用Application loader釋出

不清楚productbuild可以man productbuild,文件結尾有現成的例子

# 打包Release目錄下的app
productbuid --component build/Release/Sample.app /Applications --sign "3rd Party Mac Developer Installer: xxx" Product.pkg

然後使用Xcode的Application loader上傳

4. 遇到的問題

  • 第三方動態庫驗證不通過,Couldn't find platform family in Info.plist CFBundleSupportedPlatforms or Mach-O LC_VERSION_MIN for xxx.dylib

    我使用的libusb、quazip編譯出來動態庫都是隻有一個動態庫並沒有Info.plist等資訊,在本地使用這些動態庫執行程式沒問題,打包程式並在其他機器執行也沒有問題,問題就出現在應用驗證。在網上看了好多方法,感覺可行的方法是:不使用第三方動態庫,下載第三方庫的原始碼直接引入到程式中呼叫。應用上架App Store之後,偶然發現macOS的應用其實可以選擇不在App Store釋出,如果不打算在App Store 釋出用2.4和3.3的方法打包就足夠了,這樣就不會有動態庫驗證的問題。

  • 手動使用指令碼簽名程式啟動失敗

    在不知道Post-actions之前,我都是手動在Archive目錄下給程式執行打包簽名指令碼,在Contents/MacOS目錄下執行程式失敗了,但在應用驗證卻通過了。直接將Release目錄下已簽名能正常啟動的程式複製過來覆蓋Archive目錄原有的程式也不行。後來在Post-actions增加打包簽名的指令碼讓Xcode自己執行就沒問題了。

本人水平有限,也不是蘋果開發專業戶,此文僅作參考。

參考文章: