您的位置:首页 > 产品设计 > UI/UE

Qt Framework 问题之 framework/Versions/A:bundle format unrecognized, invalid, or unsuitable

2019-11-23 23:23 3339 查看
在解决标题提到的问题之后,先来介绍下Qt Framework一些基本知识。 基于QT的Mac端工程,在打包时需要对所有需要嵌入到APP的framework及dylib文件进行手动签名处理。

一、签名处理的流程

1. 先编译工程生成APP。 2. 对所有framework/dylib进行签名,命令为:
codesign --force --verify --verbose --sign "Developer ID Application: XXXX. (XXXXXXX)" MMMMMM.framework

在终端输入即可,注意MMMMMM.framework 需要是绝对路径。

3. 对所有framework执行签名后,对app进行签名处理:
codesign --force --verify --verbose --sign "Developer ID Application: XXXXXX. (XXXXX)" NNNNNNN.app
在终端输入即可,注意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.prl移动到Resources(软连接的文件夹)文件夹中,此时进行签名OK,签名成功后,文件目录为:  

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的内容为:

#!/bin/sh

# WARNING: You may have to run Clean in Xcode after changing CODE_SIGN_IDENTITY!
# FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework" -or -name "*.dylib" -or -name "*.bundle")

echo "------start to process unseable files in framework ----"
ITEMS=""

echo "build dir:"
echo $TARGET_BUILD_DIR

FRAMEWORKS_DIR="${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"

echo "Framework path:"
echo $FRAMEWORKS_DIR

# Prefer the expanded name, if available.
CODE_SIGN_IDENTITY_FOR_ITEMS="${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
if [ "${CODE_SIGN_IDENTITY_FOR_ITEMS}" = "" ] ; then
# Fall back to old behavior.
CODE_SIGN_IDENTITY_FOR_ITEMS="${CODE_SIGN_IDENTITY}"
fi

echo "Identity:"
echo "${CODE_SIGN_IDENTITY_FOR_ITEMS}"

if [ -d "$FRAMEWORKS_DIR" ] ; then
# FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework")
FRAMEWORKS=$(find "${FRAMEWORKS_DIR}" -depth -type d -name "*.framework" -or -name "*.dylib" -or -name "*.bundle")
RESULT=$?
if [[ $RESULT != 0 ]] ; then
exit 1
fi
ITEMS="${FRAMEWORKS}"
fi

echo "Found:"
echo "${ITEMS}"

for ITEM in $ITEMS;
do

framework_filepath="${ITEM##*/}"

# 不带后缀的文件名
framework_filename="${framework_filepath%.*}"

# 带后缀名的文件名
current_framework_name="${framework_filepath##*/}"
echo "============================:"$current_framework_name

# 后缀名
extension=${ITEM##*.}

if [ "$extension" != "framework" ]
then
# 签名
codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${ITEM}"
continue
fi

zip_archive_framework="ZipArchive.framework"

#判断字符串是否相等
if [ "$zip_archive_framework" == "$current_framework_name" ]
then
#zip_archive_framework 需要单独处理
echo "[ process ZipArchive.framework ]"

headers_folder="${ITEM}/Headers"
modules_folder="${ITEM}/Modules"
resources_folder="${ITEM}/Resources"
current_folder="${ITEM}/Versions/Current"

rm -rf $headers_folder
rm -rf $modules_folder
rm -rf $resources_folder
rm -rf $current_folder
rm "${ITEM}/ZipArchive"

ln -s "${ITEM}/Versions/A" $current_folder
ln -s "${ITEM}/Versions/A/Headers" $headers_folder
ln -s "${ITEM}/Versions/A/Modules" $modules_folder
ln -s "${ITEM}/Versions/A/Resources" $resources_folder
ln -s "${ITEM}/Versions/A/ZipArchive" "${ITEM}/ZipArchive"

# 签名
codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${ITEM}/Versions/A"
else
# debug file
debug_name="${framework_filename}_debug"
framework_debug="${ITEM}/${debug_name}"

# debug prl file
debug_prl_name="${framework_filename}_debug.prl"
framework_debug_prl="${ITEM}/${debug_prl_name}"

echo "${framework_debug} deleting >>>"
echo "${framework_debug_prl} deleting >>>"

# delete two files
rm $framework_debug
rm $framework_debug_prl

# 移除A文件夹,否则APP签名失败
rm -rf "${ITEM}/Versions/A"

resources_folder="${ITEM}/Versions/5/Resources"
echo $resources_folder
release_prl_name="${framework_filename}.prl"
framework_release_prl="${ITEM}/${release_prl_name}"
echo $framework_release_prl
echo "move ${framework_release_prl} to Resources folder::"
mv $framework_release_prl $resources_folder

if [ "QtWebEngineCore" == "$framework_filename" ]
then
QtWebEngineProcess_app="${ITEM}/Versions/5/Helpers/QtWebEngineProcess.app"
codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${QtWebEngineProcess_app}"
fi
# 签名
codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${ITEM}"
fi
done

MacOS_DIR="${TARGET_BUILD_DIR}/${CONTENTS_FOLDER_PATH}/MacOS"
MacOS_ITEMS=""

if [ -d "$MacOS_DIR" ] ; then
MacOSLibs=$(find "${MacOS_DIR}" -depth -type d -name "*.framework" -or -name "*.dylib" -or -name "*.bundle")
RESULT=$?
if [[ $RESULT != 0 ]] ; then
exit 1
fi
MacOS_ITEMS="${MacOSLibs}"
fi

echo "MacOS_Found:"
echo "${MacOS_ITEMS}"

for MacOS_ITEM in $MacOS_ITEMS;
do
framework_filepath="${MacOS_ITEM##*/}"]
# 带后缀名的文件名
current_framework_name="${framework_filepath##*/}"
echo "============================:"$current_framework_name

# 签名
codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${MacOS_ITEM}"
done

# 特殊处理的 etcpack 和 convert
codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${MacOS_DIR}/etcpack"
codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${MacOS_DIR}/convert"

#app
PROJECT_NAME="${TARGET_BUILD_DIR}/${FULL_PRODUCT_NAME}"
echo "PROJECT_NAME:"
echo $PROJECT_NAME

#对APP签名
codesign --force --verify --verbose --sign "${CODE_SIGN_IDENTITY_FOR_ITEMS}" "${PROJECT_NAME}"

#用于判断APP及所有framework是否签名工程
codesign -v --strict --deep --verbose=2 "${PROJECT_NAME}"

注意:

1. 如果未使用ZipArchive.framework,则不需要特殊处理。

2.如果未使用etcpack和convert,也无需签名处理。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐