Khan's Notebook GCC/GNU/Linux Delphi/Window Java/Anywhere

路漫漫,长修远,我们不能没有钱

Qt for Mac DeveloperId 打包 签名 公证 盖章


以下脚本根据QCreator for mac工程的输出二进制文件 进行打包 部署 签名 上传公证 签章
可在工程目录下新建一个 deployed目录, 并将脚本拷贝到该目录下执行, 执行需要root权限
支持cmake工程或qmake工程

此脚本不含编译部分, 需要自行编译, 编译成功后方可成功执行
cd $projectDir && mkdir deployed 
cd deployed
sudo ./notarization.sh [MinSizeRel | debug | release]

脚本需要两个证书, 分别是Developer ID Application , 对代码进行签名; Developer ID Installer 对pkg安装包进行签名, 这两个证书只有App开发者账户持有者才有权限生成. 
脚本依赖工程中的一个 info.h, 该文件描述程序版本, 内容如下: 
1 #ifndef INFO_H
2 #define INFO_H
3 
4 #define VERSION "0.10.4"
5 
6 #endif // INFO_H
7 


  1 #!/bin/bash
  2 
  3 ###########################################################################
  4     QDeployd="/Users/khan/Develop/Qt/5.15.2/clang_64/bin/macdeployqt"
  5     BUNLDE_ID="com.cc.dd.app"              # bundle id
  6     USER="aa@bb.com".                           # apple开发者账户
  7     PASSWORD="eeee-ffff-gggg-hhhh"     # apple开发者专属密码(specific password) 见: https://support.apple.com/zh-cn/HT204397
  8     CERTIFICATE="Developer ID Application:iiii(team id)"
  9     INSTALLER_CERTIFICATE="Developer ID Installer: iiii (team id)"
 10 ###########################################################################
 11 
 12 ###########################################################################
 13     COLOR_NORMAL="\033[0m"
 14     COLOR_BLACK="\033[1;30m"
 15     COLOR_RED="\033[1;31m"
 16     COLOR_GREEN="\033[1;32m"
 17     COLOR_YELLOW="\033[1;33m"
 18     COLOR_BLUE="\033[1;34m"
 19     COLOR_PURPLE="\033[1;35m"
 20     COLOR_WHITE="\033[1;37m"
 21 
 22     CMAKE="1"
 23     projectName=""
 24     targetPaths=""
 25     appVersion="0.0.0"
 26 
 27     FindRet=$(find ../ -iname "info.h")
 28     if [ -n "$FindRet" ] ; then
 29         appVersion=$(cat $FindRet |grep -i 'VERSION' |sed 's|.*\"\([0-9\.]*\)\".*|\1|g')
 30     fi;
 31 
 32 
 33     if [ -f "../CMakeLists.txt" ] ; then
 34         CMAKE="1"
 35         echo -e "$COLOR_PURPLE[CMake project]$COLOR_NORMAL"
 36     else
 37         CMAKE="0"
 38         echo -e "$COLOR_PURPLE[QMake project]$COLOR_NORMAL"
 39     fi;
 40 
 41 
 42 
 43     if [ "$CMAKE" -eq "1" ] ; then
 44         projectName=$(cat ../CMakeLists.txt |grep -i 'Project(' | sed 's|.*(\([a-zA-Z0-9]*\)\ .*|\1|g')
 45     else 
 46         projectName=$(ls ../*.pro)
 47         projectName=$(echo "$projectName" | sed 's|../||g' | sed 's|.pro||g' )
 48     fi; 
 49 
 50     echo -e "Project Name $COLOR_PURPLE[$projectName V $appVersion]$COLOR_NORMAL"
 51 
 52     printHelp() {
 53         echo -e "USAGE: $0 $COLOR_YELLOW[target]$COLOR_NORMAL"
 54         echo -e "  target: $COLOR_YELLOW[debug|release]$COLOR_NORMAL"
 55         echo -e "  example: $0 $COLOR_YELLOW release $COLOR_NORMAL"
 56     }
 57 
 58     # echo -e "$#"
 59     if [ "$#" -ne "1" ] ; then
 60         printHelp
 61         exit 1
 62     fi;
 63 
 64     target=$1
 65 
 66     if [ "$CMAKE" -eq "1" ] ; then
 67         data="$(cat ../CMakeLists.txt.user)"
 68         count=$(xmllint --xpath 'count(//data/valuemap/valuemap/value[@key="ProjectExplorer.BuildConfiguration.BuildDirectory"])' - <<< "$data")
 69         for((index=1$index<=$countindex++)) ; do
 70             tmp=$(xmllint --xpath "(//data/valuemap/valuemap/value[@key='ProjectExplorer.BuildConfiguration.BuildDirectory'])[$index]/text()" - <<< "$data")
 71             targetPaths="$targetPaths$tmp\n"
 72         done
 73     else 
 74         data="$(cat ../$projectName.pro.user)"
 75         count=$(xmllint --xpath 'count(//data/valuemap/valuemap/value[@key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir"])' - <<< "$data")
 76         for((index=1$index<=$countindex++)) ; do
 77             tmp=$(xmllint --xpath "(//data/valuemap/valuemap/value[@key='ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir'])[$index]/text()" - <<< "$data")
 78             targetPaths="$targetPaths$tmp\n"
 79         done
 80     fi;
 81 
 82 
 83     targetPath=$(echo -e "$targetPaths" |grep -E -i "$target" | head -n 1)
 84     if [ -z "$targetPath" ] ; then
 85         echo -e "$projectName target$COLOR_RED dir [$target] not found$COLOR_NORMAL"
 86         exit 2
 87     fi
 88 
 89     echo -e "Deployd $COLOR_PURPLE$targetPath$COLOR_NORMAL package"
 90 ###########################################################################
 91 
 92 ###########################################################################
 93     DST_NAME=${projectName}_V${appVersion}.pkg
 94     if [ -f $DST_NAME ] ; then
 95         rm -rf $DST_NAME
 96     fi 
 97 
 98     rm -rf ./$projectName.app
 99     cp -R $targetPath/$projectName.app ./
100 
101 
102     $QDeployd $projectName.app -appstore-compliant -always-overwrite -qmldir=../Resource
103 
104     find $projectName.app -name '*.dSYM'|xargs rm -rf
105 
106     # 对qt模块进行签名
107     FrameworksName=$(ls $projectName.app/Contents/Frameworks/ | cut -d '.' -f 1)
108     for Item in ${FrameworksName[@]}
109     do
110         codesign --force --timestamp --entitlements Entitlements.plist --sign "$CERTIFICATE" $projectName.app/Contents/Frameworks/$Item.framework/$Item
111     done
112 
113     # 对插件进行签名
114     DylibName=$(find $projectName.app/Contents/PlugIns/ -name *.dylib)
115     for Item in ${DylibName[@]}
116     do
117         codesign --force --timestamp --entitlements Entitlements.plist --sign "$CERTIFICATE" $Item
118     done
119 
120     codesign --sign "$CERTIFICATE" --verbose=4 --timestamp -o runtime --entitlements Entitlements.plist $projectName.app
121 
122     echo -e ""
123     codesign -dvvv $projectName.app
124     echo -e "$COLOR_PURPLE End codesign $COLOR_NORMAL\n\n"
125 ###########################################################################
126 
127 ###########################################################################
128     pkgbuild --component ${projectName}.app --install-location /Applications --sign "${INSTALLER_CERTIFICATE}" --identifier "${BUNLDE_ID}" --version ${appVersion} ${DST_NAME}
129     echo -e ""
130     pkgutil --check-signature ${DST_NAME}
131     echo -e ""
132 
133 
134     # get TEAM_ID
135     data=$(xcrun altool --list-providers -u "$USER" -p "$PASSWORD" --output-format xml)
136     TEAM_ID=$(xmllint --xpath "//dict/array/dict[key='ProviderShortname']/key[text()='ProviderShortname']/following-sibling::*[1]/text()" - <<< "$data")
137     if [ "$TEAM_ID" ]; then
138         # notarization
139         echo -e "$COLOR_PURPLE[TEAM ID: $TEAM_ID]$COLOR_NORMAL"
140         RESULT=$(xcrun altool --notarize-app --primary-bundle-id "$BUNLDE_ID" --username "$USER" --password "$PASSWORD" --asc-provider "$TEAM_ID" -t macos --file ${DST_NAME})
141         FILTER_RESULT=$(echo -e "$RESULT" | grep RequestUUID)
142         if [ "$FILTER_RESULT" ] ; then
143             RequestUUID=$(echo -e "$RESULT" |grep RequestUUID | awk '{print $3}')
144             echo -e "$projectName $COLOR_PURPLE[RequestUUID: $RequestUUID]$COLOR_NORMAL"
145 
146             sleep 150
147             xcrun altool --notarization-info "$RequestUUID" --username "$USER" --password "$PASSWORD"
148 
149             xcrun stapler staple ${DST_NAME}
150         else
151             echo -e "$projectName $COLOR_RED upload ERROR:$COLOR_NORMAL \n $RESULT"
152         fi
153     fi
154 # ###########################################################################
155 
156 echo 'Done.'
157 
158 exit
159 

签名时需要提供权限描述, 见 Entitlements.plist, 权限描述见: https://developer.apple.com/documentation/security/app_sandbox, 可自行根据程序的功能进行增减
 1 <?xml version="1.0" encoding="UTF-8"?>
 2 <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
 3 <plist version="1.0">
 4     <dict>
 5         <key>com.apple.security.app-sandbox</key>
 6         <true/>
 7         <key>com.apple.security.network.client</key>
 8         <true/>
 9         <key>com.apple.security.device.usb</key>
10         <true/>
11         <key>com.apple.security.files.user-selected.read-write</key>
12         <true/>
13         <key>com.apple.security.files.downloads.read-write</key>
14         <true/>
15     </dict>
16 </plist>
17 

脚本主要逻辑是 
- 判断工程文件类型是qmake 还是cmake
- 根据工程文件 和 脚本参数 确认当前要处理的待处理程序在哪个目录 [release | debug | MinSizeRel]
- 获取当前待处理程序的版本号
- 使用application证书对framework PlugIns 进行签名; 使用application证书对app目录进行签名
- 制作pkg安装包, 并使用installer证书进行签名
- 获取开发者账户下的team id, 上传pkg进行公证
- 等待150s, 查看公证结果
- 对已公证的程序进行签章


> 签名完成后 codesign -dvvv $projectName.app 可以查看签名信息; 但此时用 spctl -a -vvvv  $projectName.app 2>&1 |grep -v objc 检查应该是reject状态, 需要上传到苹果服务器进行公证
> 公证完成后在用spctl检查 才会是accepted 状态, 很多文章描述得比较粗糙. 导致有人认为签名就能accepted .
> 签章应该是用于离线认证, 非必要步骤.


整个流程的日志给大家参考一下: 
 1 khan@Khan-WorkMini deployd %sudo ./notarization.sh MinSizeRel
 2 Password:
 3 [CMake project]
 4 Project Name [DonnerSynths V 0.10.4]
 5 Deployd /Users/khan/Project/Cpp/build-donner-synths-Desktop_Qt_5_15_2_clang_64bit-MinSizeRel package
 6 DonnerSynths.app: signed app bundle with Mach-O thin (x86_64) [com.cc.dd.app]
 7 
 8 Executable=/Users/khan/Project/Cpp/donner-synths/deployd/DonnerSynths.app/Contents/MacOS/DonnerSynths
 9 Identifier=com.cc.dd.app
10 Format=app bundle with Mach-O thin (x86_64)
11 CodeDirectory v=20500 size=9219 flags=0x10000(runtime) hashes=277+7 location=embedded
12 Hash type=sha256 size=32
13 CandidateCDHash sha256=088f2a88da85775cd13b727ff82dc6397fe45bbd
14 CandidateCDHashFull sha256=088f2a88da85775cd13b727ff82dc6397fe45bbd167801a5438ba1256534b65a
15 Hash choices=sha256
16 CMSDigest=088f2a88da85775cd13b727ff82dc6397fe45bbd167801a5438ba1256534b65a
17 CMSDigestType=2
18 CDHash=088f2a88da85775cd13b727ff82dc6397fe45bbd
19 Signature size=9023
20 Authority=Developer ID Application: iiii (team id)
21 Authority=Developer ID Certification Authority
22 Authority=Apple Root CA
23 Timestamp=Jan 7, 2022 at 10:44:53 AM
24 Info.plist entries=14
25 TeamIdentifier=team id
26 Runtime Version=12.0.0
27 Sealed Resources version=2 rules=13 files=1196
28 Internal requirements count=1 size=184
29  End codesign 
30 
31 
32 pkgbuild: Adding component at /Users/khan/Project/Cpp/donner-synths/deployd/DonnerSynths.app
33 pkgbuild: Using timestamp authority for signature
34 pkgbuild: Signing package with identity "Developer ID Installer: iiii (team id)" from keychain /Users/khan/Library/Keychains/login.keychain-db
35 pkgbuild: Adding certificate "Developer ID Certification Authority"
36 pkgbuild: Adding certificate "Apple Root CA"
37 pkgbuild: Wrote package to DonnerSynths_V0.10.4.pkg
38 
39 Package "DonnerSynths_V0.10.4.pkg":
40    Status: signed by a developer certificate issued by Apple for distribution
41    Signed with a trusted timestamp on: 2022-01-07 02:44:56 +0000
42    Certificate Chain:
43     1. Developer ID Installer: iiii (team id)
44        Expires: 2027-01-08 01:57:26 +0000
45        SHA256 Fingerprint:
46            EA B7 AC 9A 93 E8 53 36 A2 C4 C2 05 3E 25 9E 03 E4 F1 47 EB CC 56 
47            A4 1A 50 81 25 7D 8E 68 4C D2
48        ------------------------------------------------------------------------
49     2. Developer ID Certification Authority
50        Expires: 2027-02-01 22:12:15 +0000
51        SHA256 Fingerprint:
52            7A FC 9D 01 A6 2F 03 A2 DE 96 37 93 6D 4A FE 68 09 0D 2D E1 8D 03 
53            F2 9C 88 CF B0 B1 BA 63 58 7F
54        ------------------------------------------------------------------------
55     3. Apple Root CA
56        Expires: 2035-02-09 21:40:36 +0000
57        SHA256 Fingerprint:
58            B0 B1 73 0E CB C7 FF 45 05 14 2C 49 F1 29 5E 6E DA 6B CA ED 7E 2C 
59            68 C5 BE 91 B5 A1 10 01 F0 24
60 
61 
62 [TEAM ID: 7FAP7F8RGQ]
63 DonnerSynths [RequestUUID: 7d500295-6fb9-42c9-9225-6392d90d79ac]
64 No errors getting notarization info.
65 
66           Date: 2022-01-07 02:52:14 +0000
67           Hash: 7e67a9c9ff19ac005118979c919ad2f1c455ce76c6367f1f004eb7a8fc813c9d
68     LogFileURL: https://osxapps-ssl.itunes.apple.com/itunes-assets/Enigma126/v4/88/86/48/88864802-9a8f-3298-dbb1-eca3bb5e0125/developer_log.json?accessKey=1641718489_3503811620240527835_%2Fx0eXAds4HsDELxjADZUUu%2BgPIcHlwg8Rjwix%2FUDtgq0EL0zekzWYRuqxVmxuMB77dWVSlrDIx8l8Tt2m%2BNS%2FFsbl5vpGv6bfKksg%2FErnX%2BI0YWo1yOVKECEBLIVS3%2B8Aeuh4zEl%2BXG1W4fddYy94YDlq6X8Jw7XnY3uDyJ1Kvw%3D
69    RequestUUID: 7d500295-6fb9-42c9-9225-6392d90d79ac
70         Status: success
71    Status Code: 0
72 Status Message: Package Approved
73 
74 Processing: /Users/khan/Project/Cpp/donner-synths/deployd/DonnerSynths_V0.10.4.pkg
75 Processing: /Users/khan/Project/Cpp/donner-synths/deployd/DonnerSynths_V0.10.4.pkg
76 The staple and validate action worked!
77 Done.




2. 附录: 
该脚本可根据参数选择打包成pkg 或 dmg , 并签名 公证 签章

USAGE: sudo ./deploy -t[target] -p[package] -s

 -t target: [debug|release|MinSizeRel]

 -p package: [dmg|pkg] 打包类型

 -s sign 是否需要签名, 如携带该参数, 会自动公证签章, 否则仅完成打包动作

  example: ./deploy -s -t release -p dmg


  1 #!/bin/bash
  2 
  3 ###########################################################################
  4     QDeployd="/Users/khan/Develop/Qt/5.15.2/clang_64/bin/macdeployqt"
  5     BUNLDE_ID="com.xxx.keyboard.app"        # bundle id
  6     USER="xxxx@xxx.com"                    # apple开发者账户
  7     PASSWORD="xxxx-dddd-xxx-xxxx"             # apple开发者专属密码(specific password) 见: https://support.apple.com/zh-cn/HT204397  在https://appleid.apple.com/ 申请
  8     CERTIFICATE="Developer ID Application: xxxx Co.,Ltd (7FAP7F8RGQ)"         # 代码签名证书, app 和 dmg需要
  9     INSTALLER_CERTIFICATE="Developer ID Installer: xxxx Co.,Ltd (7FAP7F8RGQ)" # 安装包签名证书, pkg需要
 10 ###########################################################################
 11 
 12 ###########################################################################
 13     COLOR_NORMAL="\033[0m"
 14     COLOR_BLACK="\033[1;30m"
 15     COLOR_RED="\033[1;31m"
 16     COLOR_GREEN="\033[1;32m"
 17     COLOR_YELLOW="\033[1;33m"
 18     COLOR_BLUE="\033[1;34m"
 19     COLOR_PURPLE="\033[1;35m"
 20     COLOR_WHITE="\033[1;37m"
 21 ###########################################################################
 22 
 23 
 24 getVersion(){
 25     local appVersion="0.0.0"
 26     local FindRet=$(find ../ -iname "info.h")
 27     if [ -n "$FindRet" ] ; then
 28         appVersion=$(cat $FindRet |grep -i 'VERSION' |sed 's|.*\"\([0-9\.]*\)\".*|\1|g');
 29     fi;
 30     echo "$appVersion"
 31 }
 32 
 33 getProjectType(){
 34     if [ -f "../CMakeLists.txt" ] ; then
 35         return 1;
 36     else
 37         return 0;
 38     fi;
 39 }
 40 
 41 getProjectName(){
 42     local CMAKE=$1
 43     local projectName=""
 44     if [ "$CMAKE" -eq "1" ] ; then
 45         projectName=$(cat ../CMakeLists.txt |grep -i 'Project(' | sed 's|.*(\([a-zA-Z0-9]*\)\ .*|\1|g');
 46     else 
 47         projectName=$(ls ../*.pro)
 48         projectName=$(echo "$projectName" | sed 's|../||g' | sed 's|.pro||g' );
 49     fi;
 50     echo "$projectName"
 51 }
 52 
 53 getAppPath(){
 54     local CMAKE=$1
 55     local projectName=$2
 56     local target=$3
 57     
 58     local targetPaths=""
 59     if [ "$CMAKE" -eq "1" ] ; then
 60         data="$(cat ../CMakeLists.txt.user)"
 61         count=$(xmllint --xpath 'count(//data/valuemap/valuemap/value[@key="ProjectExplorer.BuildConfiguration.BuildDirectory"])' - <<< "$data")
 62         for((index=1$index<=$countindex++)) ; do
 63             tmp=$(xmllint --xpath "(//data/valuemap/valuemap/value[@key='ProjectExplorer.BuildConfiguration.BuildDirectory'])[$index]/text()" - <<< "$data")
 64             targetPaths="$targetPaths$tmp\n"
 65         done;
 66     else 
 67         data="$(cat ../$projectName.pro.user)"
 68         count=$(xmllint --xpath 'count(//data/valuemap/valuemap/value[@key="ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir"])' - <<< "$data")
 69         for((index=1$index<=$countindex++)) ; do
 70             tmp=$(xmllint --xpath "(//data/valuemap/valuemap/value[@key='ProjectExplorer.BuildConfiguration.BuildDirectory.shadowDir'])[$index]/text()" - <<< "$data")
 71             targetPaths="$targetPaths$tmp\n"
 72         done;
 73     fi;
 74 
 75     local targetPath=$(echo -e "$targetPaths" |grep -E -i "$target" | head -n 1)
 76     echo "$targetPath";
 77 }
 78 
 79 printHelp() {
 80     echo -e "USAGE: $0 -t$COLOR_YELLOW[target]$COLOR_NORMAL -p$COLOR_YELLOW[package]$COLOR_NORMAL -s"
 81     echo -e " -t target: $COLOR_YELLOW[debug|release|MinSizeRel]$COLOR_NORMAL"
 82     echo -e " -p package: $COLOR_YELLOW[dmg|pkg|zip]$COLOR_NORMAL"
 83     echo -e " -s sign"
 84     echo -e "  example: $0 -s -t$COLOR_YELLOW release $COLOR_NORMAL-p$COLOR_YELLOW dmg$COLOR_NORMAL"
 85 }
 86 
 87 
 88 unMountDmg(){
 89     DMG_NAME=$1
 90     data=$(hdiutil info -plist)
 91     VOL_DEVICE=$(xmllint --xpath "//dict[contains(., '$DMG_NAME') and key='image-path']/array/dict[key='dev-entry' and contains(., 'GUID_partition_scheme')]/key[text()='dev-entry']/following-sibling::*[1]/text()" - 2>/dev/null <<< "$data")
 92     if [ "$VOL_DEVICE" ]; then
 93         echo -e "Unmount DMG$COLOR_PURPLE $VOL_DEVICE $COLOR_NORMAL"
 94         hdiutil detach $VOL_DEVICE;
 95     fi
 96 }
 97 
 98 signApp(){
 99     local appPath=$1
100     local certificate=$2
101     local entitlementsPath=$3
102     # 对qt模块进行签名
103     local FrameworksName=$(ls $appPath/Contents/Frameworks/ | cut -d '.' -f 1)
104     for Item in ${FrameworksName[@]}
105     do
106         codesign --force --timestamp --entitlements $entitlementsPath --sign "$certificate" $appPath/Contents/Frameworks/$Item.framework/$Item;
107     done;
108 
109     # 对插件进行签名
110     local DylibName=$(find $appPath/Contents/PlugIns/ -name *.dylib)
111     for Item in ${DylibName[@]}
112     do
113         codesign --force --timestamp --entitlements $entitlementsPath --sign "$CERTIFICATE" $Item;
114     done;
115 
116     codesign --sign "$CERTIFICATE" --verbose=4 --timestamp -o runtime --entitlements $entitlementsPath $appPath
117 
118     echo -e ""
119     codesign -dvvv $appPath
120     echo -e "${COLOR_PURPLE}End codesign ${COLOR_NORMAL}\n\n"
121 }
122 
123 makeDmg(){
124     local appName=$1
125     local certificate=$2
126     local bundleId=$3
127     local DMG_BACKGROUND_IMG=$4
128     
129 
130     local VOL_NAME="${appName}"
131     local APP_EXE="${appName}.app/Contents/MacOS/${appName}"
132 
133     local DMG_TMP="${appName}-rw.dmg"
134     local DMG_FINAL="${appName}.dmg"
135     local STAGING_DIR="./Install"
136     
137     
138     # Check the background image DPI and convert it if it isn't 72x72
139     local _BACKGROUND_IMAGE_DPI_H=`sips -g dpiHeight ${DMG_BACKGROUND_IMG} | grep -Eo '[0-9]+\.[0-9]+'`
140     local _BACKGROUND_IMAGE_DPI_W=`sips -g dpiWidth ${DMG_BACKGROUND_IMG} | grep -Eo '[0-9]+\.[0-9]+'`
141 
142 
143     if [ $(echo " $_BACKGROUND_IMAGE_DPI_H != 72.0 " | bc) -eq 1 -o $(echo " $_BACKGROUND_IMAGE_DPI_W != 72.0 " | bc) -eq 1 ]; then
144         echo "WARNING: The background image's DPI is not 72.  This will result in distorted backgrounds on Mac OS X 10.7+."
145         echo "         I will convert it to 72 DPI for you."
146 
147         local _DMG_BACKGROUND_TMP="${DMG_BACKGROUND_IMG%.*}"_dpifix."${DMG_BACKGROUND_IMG##*.}"
148         sips -s dpiWidth 72 -s dpiHeight 72 ${DMG_BACKGROUND_IMG} --out ${_DMG_BACKGROUND_TMP}
149         DMG_BACKGROUND_IMG="${_DMG_BACKGROUND_TMP}";
150     fi
151 
152     # clear out any old data
153     rm -rf "${STAGING_DIR}" "${DMG_TMP}" "${DMG_FINAL}"
154     
155     # copy over the stuff we want in the final disk image to our staging dir
156     mkdir -p "${STAGING_DIR}"
157     cp -Rpf "${projectName}.app" "${STAGING_DIR}"  # -R复制软链接 -p保留源文件修改时间和权限 -f强制覆盖
158 
159     # figure out how big our DMG needs to be
160     #  assumes our contents are at least 1M!
161     local SIZE=`du -sh "${STAGING_DIR}" | sed 's/\([0-9]*\)M\(.*\)/\1/'`
162     # echo -e "DMG size: ${SIZE}"
163     SIZE=`echo "${SIZE} + 1.0" | bc | awk '{print int($1*1.5)}'`
164     echo -e "DMG size: ${SIZE}"
165 
166     if [ $? -ne 0 ]; then
167         echo "Error: Cannot compute size of staging dir"
168         exit;
169     fi
170     
171     # create the temp DMG file
172     hdiutil create -srcfolder "${STAGING_DIR}" -volname "${VOL_NAME}" -fs HFS+ -fsargs "-c c=64,a=16,e=16" -format UDRW -size ${SIZE}M "${DMG_TMP}"
173     
174     echo "Created DMG: ${DMG_TMP}"
175     
176     # mount it and save the device
177     local DEVICE=$(hdiutil attach -readwrite -noverify "${DMG_TMP}" | egrep '^/dev/' | sed 1q | awk '{print $1}')
178     
179     sleep 3
180 
181     # add a link to the Applications dir
182     echo "Add link to /Applications"
183     pushd /Volumes/"${VOL_NAME}"
184     ln -s /Applications
185     popd
186     
187     # add a background image
188     mkdir /Volumes/"${VOL_NAME}"/.background
189     cp "${DMG_BACKGROUND_IMG}" /Volumes/"${VOL_NAME}"/.background/
190     
191     # tell the Finder to resize the window, set the background,
192     #  change the icon size, place the icons in the right position, etc.
193     echo '
194     tell application "Finder"
195         tell disk "'${VOL_NAME}'"
196             open
197             set current view of container window to icon view
198             set toolbar visible of container window to false
199             set statusbar visible of container window to false
200             set the bounds of container window to {400, 100, 920, 460}
201             set viewOptions to the icon view options of container window
202             set arrangement of viewOptions to not arranged
203             set icon size of viewOptions to 72
204             set background picture of viewOptions to file ".background:'${DMG_BACKGROUND_IMG}'"
205             set position of item "'${appName}'.app" of container window to {160, 205}
206             set position of item "Applications" of container window to {360, 205}
207             close
208             open
209             update without registering applications
210             delay 2
211         end tell
212     end tell
213     ' | osascript
214     
215     sync
216 
217     # unmount it
218     hdiutil detach "${DEVICE}"
219 
220     sleep 2
221     
222     # now make the final image a compressed disk image
223     echo "Creating compressed image"
224     hdiutil convert "${DMG_TMP}" -format UDZO -imagekey zlib-level=9 -o "${VOL_NAME}_V${appVersion}.dmg"
225     
226     codesign -s "${certificate}" "${VOL_NAME}_V${appVersion}.dmg" -i "${bundleId}" --options runtime
227 
228     # clean up
229     rm -rf "${DMG_TMP}"
230     rm -rf "${STAGING_DIR}"
231     rm -f Applications
232 }
233 
234 makePkg(){
235     local appName=$1
236     local certificate=$2
237     local bundleId=$3
238     local version=$4
239     local DST_NAME=$5
240     pkgbuild --component ${appName}.app --install-location /Applications --sign "${certificate}" --identifier "${bundleId}" --version ${version} ${DST_NAME}
241     echo -e ""
242     pkgutil --check-signature ${DST_NAME}
243     echo -e ""
244 }
245 
246 makeZip(){
247     local appName=$1
248     local certificate=$2
249     local bundleId=$3
250     local DST_NAME=$4
251     # -y 或 --symlinks 存储软链接; -r 压缩目录及子目录; -q 静默模式
252     zip --symlinks -q -r ${DST_NAME} ${appName}.app
253 
254     codesign -s "${certificate}" "${DST_NAME}" -i "${bundleId}" --options runtime
255 
256     echo -e ""
257     codesign -dvvv "${DST_NAME}"
258     echo -e "${COLOR_PURPLE}End codesign ${COLOR_NORMAL}\n\n"
259 }
260 
261 notarization(){
262     local appName=$1
263     local USER=$2
264     local PASSWORD=$3
265     local DST_NAME=$4
266     # get TEAM_ID
267     local data=$(xcrun altool --list-providers -u "$USER" -p "$PASSWORD" --output-format xml)
268     local TEAM_ID=$(xmllint --xpath "//dict/array/dict[key='ProviderShortname']/key[text()='ProviderShortname']/following-sibling::*[1]/text()" - <<< "$data")
269     if [ "$TEAM_ID" ]; then
270         # notarization
271         echo -e "$COLOR_PURPLE[TEAM ID: $TEAM_ID]$COLOR_NORMAL"
272         local RESULT=$(xcrun altool --notarize-app --primary-bundle-id "$BUNLDE_ID" --username "$USER" --password "$PASSWORD" --asc-provider "$TEAM_ID" -t macos --file ${DST_NAME})
273         local FILTER_RESULT=$(echo -e "$RESULT" | grep RequestUUID)
274         if [ "$FILTER_RESULT" ] ; then
275             local RequestUUID=$(echo -e "$RESULT" |grep RequestUUID | awk '{print $3}')
276             echo -e "$projectName $COLOR_PURPLE[RequestUUID: $RequestUUID]$COLOR_NORMAL"
277 
278             sleep 150
279             xcrun altool --notarization-info "$RequestUUID" --username "$USER" --password "$PASSWORD"
280             ## 文件名全部转成大写; 
281             local TMP01=$(echo "$DST_NAME" | tr '[:lower:]' '[:upper:]')
282             local TMP02=$( echo "$TMP01" | grep -E '\.ZIP$')
283             if [ "$TMP02" ]; then
284                 echo "The validate action worked!"
285             else
286                 xcrun stapler staple ${DST_NAME}
287                 xcrun stapler validate ${DST_NAME};
288             fi
289 
290         else
291             echo -e "$projectName $COLOR_RED upload ERROR:$COLOR_NORMAL \n $RESULT";
292         fi;
293     fi;
294 }
295 
296 ###########################################################################
297     isSign="no"  ## 是否需要签名 
298     FLAG="0"
299     package="dmg"
300     while getopts 't:p:vsh' OPT; do
301         case $OPT in
302             t)                    ## 打包目标 [debug|release|MinSizeRel]
303                 target="$OPTARG";;
304             p)                   ## 打包类型 [dmg|pkg|zip]
305                 package="$OPTARG";;
306             s)                      ## 是否签名, 默认不签名
307                 isSign="yes";;
308             v)
309                 echo -e $0$COLOR_PURPLE v$(getVersion)$COLOR_NORMAL;;
310             h)                      ## 帮助
311                 printHelp
312                 exit 0;;
313             ?)
314                 printHelp
315                 exit 1;;
316         esac
317         FLAG="1";
318     done
319     shift $(($OPTIND - 1))
320 
321     if [ "$FLAG" -eq "0" ]; then
322         printHelp
323         exit 1
324     fi;
325 ###########################################################################
326 
327 ###########################################################################
328     # 临时全局变量
329     getProjectType
330     projectType=$?                                                 # 工程类型 cmake 或 qmake
331     projectName=$(echo $(getProjectName $projectType))             # 项目名
332     appVersion=$(echo $(getVersion))                               # 版本号
333     targetPath=$(echo $(getAppPath $projectType $projectName $target))  # 工程二进制输出目录
334 ###########################################################################
335 
336 
337 if [ "$projectType" = 1 ] ; then
338     echo -e "$COLOR_PURPLE[CMake project]$COLOR_NORMAL";
339 else 
340     echo -e "$COLOR_PURPLE[QMake project]$COLOR_NORMAL";
341 fi
342 
343 echo -e "Deployd $COLOR_PURPLE${targetPath}$COLOR_NORMAL $COLOR_YELLOW${projectName} v${appVersion}$COLOR_NORMAL ${package} package"
344 
345 rm -rf ./$projectName.app
346 cp -R ${targetPath}/${projectName}.app ./
347 
348 $QDeployd $projectName.app -always-overwrite -appstore-compliant -qmldir=../Resource
349 find $projectName.app -name '*.dSYM'|xargs rm -rf
350 
351 if [ "$package" = "dmg" ] ; then
352     DST_NAME=${projectName}_V${appVersion}.dmg
353 
354     unMountDmg $DST_NAME
355     if [ -f $DST_NAME ] ; then
356         rm -rf $DST_NAME;
357     fi
358 
359     if [ "$isSign" = "yes" ] ; then
360         signApp "$projectName.app" "${CERTIFICATE}" "Entitlements.plist" ;
361     fi
362     makeDmg "$projectName" "${CERTIFICATE}" "${BUNLDE_ID}" "background.png" 
363 
364     # 已签名程序才可公证
365     if [ "$isSign" = "yes" ] ; then
366         notarization "$projectName" "${USER}" "${PASSWORD}" "${DST_NAME}";
367     fi
368 
369     echo 'Done.';
370 elif [ "$package" = "pkg" ] ; then
371     DST_NAME=${projectName}_V${appVersion}.pkg
372     if [ -f $DST_NAME ] ; then
373         rm -rf $DST_NAME;
374     fi
375 
376     if [ "$isSign" = "yes" ] ; then
377         signApp "$projectName.app" "${CERTIFICATE}" "Entitlements.plist" ;
378     fi;
379     makePkg "$projectName" "${INSTALLER_CERTIFICATE}" "${BUNLDE_ID}" "${appVersion}" "${DST_NAME}"
380 
381     # 已签名程序才可公证
382     if [ "$isSign" = "yes" ] ; then
383         notarization "$projectName" "${USER}" "${PASSWORD}" "${DST_NAME}";
384     fi
385 
386     echo 'Done.';
387 elif [ "$package" = "zip" ] ; then
388     DST_NAME=${projectName}_V${appVersion}.zip
389     if [ -f $DST_NAME ] ; then
390         rm -rf $DST_NAME;
391     fi
392     if [ "$isSign" = "yes" ] ; then
393         signApp "$projectName.app" "${CERTIFICATE}" "Entitlements.plist" ;
394     fi
395 
396     makeZip "$projectName" "${CERTIFICATE}" "${BUNLDE_ID}" "${DST_NAME}"
397     # 已签名程序才可公证
398     if [ "$isSign" = "yes" ] ; then
399         notarization "$projectName" "${USER}" "${PASSWORD}" "${DST_NAME}";
400     fi
401 
402     echo 'Done.';
403 else
404     printHelp
405     exit 1;
406 fi;

posted on 2022-01-07 12:14 Khan 阅读(611) 评论(0)  编辑 收藏 引用 所属分类: GCC/G++


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理


<2006年9月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

导航

统计

常用链接

留言簿(33)

随笔分类(225)

随笔档案(169)

相册

技术

友情链接

最新随笔

搜索

积分与排名

最新随笔

最新评论

阅读排行榜

评论排行榜