一、签名处理的流程
codesign --force --verify --verbose --sign "Developer ID Application: XXXX. (XXXXXXX)" MMMMMM.framework
在终端输入即可,注意MMMMMM.framework 需要是绝对路径。
codesign --force --verify --verbose --sign "Developer ID Application: XXXXXX. (XXXXX)" NNNNNNN.app
二、验证APP是否签名成功
如果想验证下APP是否签名成功,可以输入下面任意一个命令:
(1)第一条命令:用于判断APP及所有framework是否签名工程
codesign -v --strict --deep --verbose=2 aaaaa.app
如果提示下面两行表示成功:
aaaaa.app: valid on disk aaaaa.app: satisfies its Designated Requirement
如果提示类似下面的提示,表示失败:
In subcomponent /XXXX/XXXX/XXXX/ff.framework
表示这个framework签名不合格,需要查看此framework内部文件结构是否正常等,完成之后重新进行签名,再对APP进行签名。
(2)第二条命令:用于查看APP签名信息及嵌入到APP的dylib和framework等
codesign -d --deep --verbose=2 -r- aaaaa.app
提示如下表示成功:

(3)第三条命令:
spctl --assess -vv NNNNN.app
提示如下表示成功:
aaaaa.app: accepted source=Developer ID origin=Developer ID Application: XXXXXXXXX. (XXXXXX)
三、Qt Framework/dylib文件签名失败问题
xcode 提示 " framework/Versions/A:bundle format unrecognized, invalid, or unsuitable" ,
说明当前framework不符合apple官方对framework这种bundle的格式要求。查看Versions/A文件夹下为空。
以QtConcurrent.framework(Qt 5.5.1版本)为例说明问题,提示的framework结构为:

由于发版时都是基于release版本编译,因此移除根目录下QtConcurrent_debug和QtConcurrent_debug.prl文件,然后重新对当前framework进行签名处理,
此时会提示“Unsealed contents present in the root directory of an embedded framework”,说明在framework的根目录下存在不符合要求的文件,
此时除了软连接文件,就剩余QtConcurrent.prl文件,经查阅发现此文件用于在链接时查找库的依赖关系,因此此文件不能删除。
那不删除又无法签名成功,该如何处理呢?

QtConcurrent.framework根目录下没有了QtConcurrent.prl,并且在/5/目录下生成了一个名为 _CodeSignature的文件夹,表示当前framework签名成功。
对于APP所依赖所有Qt的framework进行上述处理,而对于其他dylib文件则比较简单,直接输入签名命令进行签名即可。
需要特别注意的是QtWebEngineCore.framework,对此进行签名之前,需要先对/Versions/5/Helpers/QtWebEngineProcess.app进行签名。
等所有依赖的库签名成功后,再对APP进行签名:
codesign --force --verify --verbose --sign "Developer ID Application: XXXXX (XXXXX)" aaaaaa.app
其中aaaaa.app代表app的绝对路径如果app签名也成功,那么在APP/Contents根目录下会多出一个_CodeSignature文件夹和embedded.provisionfile文件。

四、处理脚本
为了方便编译,自己封装了一个脚本(codesign_framework_test.sh),在xcode的配置即可,如下图所示。

codesign_frameworks_test.sh的内容为:
1 #!/bin/sh
2
3 # WARNING: You may have to run Clean in Xcode after changing CODE_SIGN_IDENTITY!
4 # FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework" -or -name "*.dylib" -or -name "*.bundle")
5
6 echo "------start to process unseable files in framework ----"
7 ITEMS=""
8
9 echo "build dir:"
10 echo $TARGET_BUILD_DIR
11
12 FRAMEWORKS_DIR="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
13
14 echo "Framework path:"
15 echo $FRAMEWORKS_DIR
16
17 # Prefer the expanded name, if available.
18 CODE_SIGN_IDENTITY_FOR_ITEMS="${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
19 if [ "${CODE_SIGN_IDENTITY_FOR_ITEMS}" = "" ] ; then
20 # Fall back to old behavior.
21 CODE_SIGN_IDENTITY_FOR_ITEMS="${CODE_SIGN_IDENTITY}"
22 fi
23
24 echo "Identity:"
25 echo "${CODE_SIGN_IDENTITY_FOR_ITEMS}"
26
27 if [ -d "$FRAMEWORKS_DIR" ] ; then
28 # FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework")
29 FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework" -or -name "*.dylib" -or -name "*.bundle")
30 RESULT=$?
31 if [[ $RESULT != 0 ]] ; then
32 exit 1
33 fi
34 ITEMS="${FRAMEWORKS}"
35 fi
36
37 echo "Found:"
38 echo "${ITEMS}"
39
40 for ITEM in $ITEMS;
41 do
42
43 framework_filepath="${ITEM##*/}"
44
45 # 不带后缀的文件名
46 framework_filename="${framework_filepath%.*}"
47
48 # 带后缀名的文件名
49 current_framework_name="${framework_filepath##*/}"
50 echo "============================:"$current_framework_name
51
52 # 后缀名
53 extension=${ITEM##*.}
54
55 if [ "$extension" != "framework" ]
56 then
57 # 签名
58 codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${ITEM}"
59 continue
60 fi
61
62 zip_archive_framework="ZipArchive.framework"
63
64 #判断字符串是否相等
65 if [ "$zip_archive_framework" == "$current_framework_name" ]
66 then
67 #zip_archive_framework 需要单独处理
68 echo "[ process ZipArchive.framework ]"
69
70 headers_folder="${ITEM}/Headers"
71 modules_folder="${ITEM}/Modules"
72 resources_folder="${ITEM}/Resources"
73 current_folder="${ITEM}/Versions/Current"
74
75 rm -rf $headers_folder
76 rm -rf $modules_folder
77 rm -rf $resources_folder
78 rm -rf $current_folder
79 rm "${ITEM}/ZipArchive"
80
81 ln -s "${ITEM}/Versions/A" $current_folder
82 ln -s "${ITEM}/Versions/A/Headers" $headers_folder
83 ln -s "${ITEM}/Versions/A/Modules" $modules_folder
84 ln -s "${ITEM}/Versions/A/Resources" $resources_folder
85 ln -s "${ITEM}/Versions/A/ZipArchive" "${ITEM}/ZipArchive"
86
87 # 签名
88 codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${ITEM}/Versions/A"
89 else
90 # debug file
91 debug_name="${framework_filename}_debug"
92 framework_debug="${ITEM}/${debug_name}"
93
94 # debug prl file
95 debug_prl_name="${framework_filename}_debug.prl"
96 framework_debug_prl="${ITEM}/${debug_prl_name}"
97
98 echo "${framework_debug} deleting >>>"
99 echo "${framework_debug_prl} deleting >>>"
100
101 # delete two files
102 rm $framework_debug
103 rm $framework_debug_prl
104
105 # 移除A文件夹,否则APP签名失败
106 rm -rf "${ITEM}/Versions/A"
107
108 resources_folder="${ITEM}/Versions/5/Resources"
109 echo $resources_folder
110 release_prl_name="${framework_filename}.prl"
111 framework_release_prl="${ITEM}/${release_prl_name}"
112 echo $framework_release_prl
113 echo "move ${framework_release_prl} to Resources folder::"
114 mv $framework_release_prl $resources_folder
115
116 if [ "QtWebEngineCore" == "$framework_filename" ]
117 then
118 QtWebEngineProcess_app="${ITEM}/Versions/5/Helpers/QtWebEngineProcess.app"
119 codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${QtWebEngineProcess_app}"
120 fi
121 # 签名
122 codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${ITEM}"
123 fi
124 done
125
126 MacOS_DIR="${TARGET_BUILD_DIR}/${CONTENTS_FOLDER_PATH}/MacOS"
127 MacOS_ITEMS=""
128
129 if [ -d "$MacOS_DIR" ] ; then
130 MacOSLibs=$(find "${MacOS_DIR}" -depth -type d -name "*.framework" -or -name "*.dylib" -or -name "*.bundle")
131 RESULT=$?
132 if [[ $RESULT != 0 ]] ; then
133 exit 1
134 fi
135 MacOS_ITEMS="${MacOSLibs}"
136 fi
137
138 echo "MacOS_Found:"
139 echo "${MacOS_ITEMS}"
140
141 for MacOS_ITEM in $MacOS_ITEMS;
142 do
143 framework_filepath="${MacOS_ITEM##*/}"]
144 # 带后缀名的文件名
145 current_framework_name="${framework_filepath##*/}"
146 echo "============================:"$current_framework_name
147
148 # 签名
149 codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${MacOS_ITEM}"
150 done
151
152 # 特殊处理的 etcpack 和 convert
153 codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${MacOS_DIR}/etcpack"
154 codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${MacOS_DIR}/convert"
155
156 #app
157 PROJECT_NAME="${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}"
158 echo "PROJECT_NAME:"
159 echo $PROJECT_NAME
160
161 #对APP签名
162 codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${PROJECT_NAME}"
163
164 #用于判断APP及所有framework是否签名工程
165 codesign -v --strict --deep --verbose=2 "${PROJECT_NAME}"
注意:
1. 如果未使用ZipArchive.framework,则不需要特殊处理。
2.如果未使用etcpack和convert,也无需签名处理。