纸上得来终觉浅,绝知此事要躬行。

0%

iOS私有库模块产物化及托管服务器。

iOS 私有库模块产物化及托管服务器

目的

为减少编译时间和打包时间,将私有库模块预编译成framework包引入工程,并使用脚本实现模块自动升级、和产物化托管。

一、模块生成framework包

使用打包工具cocoapods-packager ,具体下载方法和使用方法点击链接可查看。

为了先保证打包成功之后,才更新版本到私有库,使用本地代码仓库进行打包。将打包所用podspec需要与私有库podspec区分开。

以EMPAppstore模块举例:私有库podspec:EMPAppStore.podspec;打包所需podspec:EMPAppStorePackage.podspec

EMPAppStorePackage.podspec内容:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
require 'etc'

Pod::Spec.new do |s|

s.name = "EMPAppStore"
s.version = "2.0.11"
s.summary = "EMPAppStore !!"
s.description = <<-DESC
EMPAppStore 通讯录模块!

DESC
s.homepage = "**"
s.license = "MIT"
s.author = { "**" }
s.platform = :ios, "8.0"
s.source = { :git => "/Users/#{Etc.getlogin}/.jenkins/workspace/EMPAppStore" }
s.resources = 'EMPAppStore/Resources/*.bundle'
s.frameworks = 'UIKit', 'Foundation'
s.requires_arc = true

s.source_files = 'EMPAppStore/Core/**/*.{h,m}'
s.prefix_header_file = 'EMPAppStore/Core/EMPAppStorePCH.pch'
s.module_name = 'EMPAppStore'
#s.static_framework = true

s.dependency 'MJExtension', '~> 3.0.13'
s.dependency 'Realm', '~> 2.6.2'
s.dependency 'SVProgressHUD', '~> 2.1.2'
s.dependency 'SDWebImage', '~> 4.0.0'
s.dependency 'LPActionSheet', '~> 1.0'
s.dependency 'SSZipArchive', '~> 2.0.3'
s.dependency 'UAProgressView', '~> 0.1.3'

s.dependency 'EMPHttpClient'
s.dependency 'EMPUtils'
s.dependency 'EMPAppService'
s.dependency 'EMPKit'

s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }

s.pod_target_xcconfig = { 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES' }
s.user_target_xcconfig = { 'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES' }

end

打包脚本package.h内容

1
pod package EMPAppStorePackage.podspec --force --embedded --no-mangle --exclude-deps --spec-sources=[私有库repo地址],https://github.com/CocoaPods/Specs.git
错误及解决方法
1
have the same architectures (arm64) and can't be in the same fat output file

原因:XCode12 编译的模拟器库新增支持架构arm64,和真机模拟器的arm64格式冲突。

解决方法:

  1. 在packagePodspec中增加target的配置:
1
2
s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }

仍然出现错误的话

  1. 修改cocoapods-packager的源码:

源码路径(注意gem版本和cocoapods-packager版本):

/Library/Ruby/Gems/2.6.0/gems/cocoapods-packager-1.5.0/lib/cocoapods-packager/

修改pod_utils.rb文件 添加一行

修改后的pod_utils.rb文件

二、模块产物化的托管

两种方案

  1. 生成的framework包直接放在源码仓库中

    问题:每次更新一个版本都会在源码仓库中增加一个framework包,导致源码仓库占用内存随版本更新不断增大,会导致两个问题:

    • 长此以往,gitee上仓库硬盘容量不足
    • 浪费组内成员更新仓库所需的时间
  2. 既然cocoapods支持zip包的下载方式。干脆把framework包压缩后托管在服务器上。

    但是我们现有的模块比较多,如果都在自己电脑上做升级打包,要手动打包、上传还要时刻盯着结果。那就在服务器上部署个jenkins来完成打包的任务,打包压缩完成之后借助nginx托管。

    jenkins配置上gitee仓库的webhook。

    jenkins配置如下

    jenkins配置

    自动更新版本打包的脚本如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    #自动打包frameWork并推送pod repo的脚本。可指定版本号,不指定版本号按照版本号自增1的规则更新。
    #流程如下:
    #更新代码
    #更改[moduleName]Package.podspec 版本号
    #执行打包命令
    #修改[moudule].podspec 版本号
    #git add、commit、push
    #git tag 、 git push --tags
    #执行更新命令xx

    #当前文件路径
    directory="$(pwd)"
    #当前模块名称
    mouduleName=${directory##*/}
    echo "当前模块名称 ${mouduleName}"

    #版本号递增函数
    increment_version ()
    {
    declare -a part=( ${1//\./ } )
    declare new
    declare -i carry=1
    CNTR=${#part[@]}-1
    len=${#part[CNTR]}
    new=$((part[CNTR]+carry))
    part[CNTR]=${new}
    new="${part[*]}"
    echo "${new// /.}"
    return ${new// /.}
    }

    echo "当前分支"
    git branch
    echo "更新当前分支代码"
    git pull origin
    echo "更新当前分支代码完成"

    #read -p "输入需要发布的版本号,按Enter默认版本最小位+1: " shouldToVersion
    #echo "输入版本号为:${shouldToVersion}"

    #read -p "输入tag的注释(当前版本更新内容),按Enter表示不需要tag注释: " tagComment
    #echo "输入版本更新内容:${tagComment}"

    shouldToVersion=""
    tagComment=""

    echo "获取podspec文件 begin"
    #podspec文件路径
    packagePodspec_file_path="../${mouduleName}Package.podspec"
    podpushPodspec_file_path="../${mouduleName}.podspec"
    packagePodspec_file_name="${mouduleName}Package.podspec"
    podpushPodspec_file_name="${mouduleName}.podspec"
    echo "packagePodspec_file_path: ${packagePodspec_file_path}"
    echo "podpushPodspec_file_path: ${podpushPodspec_file_path}"
    echo "获取podspec文件 end"

    echo "读取podspec文件内容 begin"
    # 定义pod文件名称
    pod_file_name=${packagePodspec_file_name}
    # 查找 podspec 的版本
    search_str="s.version"
    # 当前版本号
    currentVersion=""
    #版本号所在行内容
    versionLine=""
    while read line
    do
    #查找包含的内容,正则表达式以search_str开头的内容
    result=$(echo ${line} | grep "^${search_str}")
    if [ "$result" != "" ]
    then
    echo " ${line} 包含 ${search_str}"
    versionLine=${line}
    currentVersion=${result##* }
    #去掉双引号
    currentVersion=${currentVersion:1:${#currentVersion}-1}
    currentVersion=${currentVersion:0:${#currentVersion}-1}
    fi
    done < $pod_file_name

    echo "当前版本号: ${currentVersion}"
    if [ currentVersion == "" ]
    then
    echo "获取当前版本号错误"
    set -e
    exit 1
    fi

    if [ "$shouldToVersion" == "" ]
    then
    shouldToVersion=$(increment_version ${currentVersion})
    #shouldToVersion=${currentVersion}
    fi

    echo "更新版本号为:$shouldToVersion"
    updateVersionLine="s.version = \"${shouldToVersion}\""

    echo "修改packagePodspec版本号 begin"
    sed -i "" "s/${versionLine}/${updateVersionLine}/g" ${packagePodspec_file_name}
    echo "修改packagePodspec版本号 end"

    echo "打包 begin"
    sh package.sh
    if [ ! -d "${mouduleName}-$shouldToVersion/${mouduleName}.xcframework" ] && [ ! -d "${mouduleName}-${shouldToVersion}/ios/${mouduleName}.embeddedframework" ]
    then
    echo "打包失败"
    set -e
    exit 1
    fi
    echo "打包 end"

    #echo "删除build文件夹"
    #rm -rf "${mouduleName}-$shouldToVersion/build"

    zipVersion=${shouldToVersion//./_}
    zipName="${mouduleName}_v${zipVersion}"

    rm -rf ${zipName}/
    rm -f ${zipName}.zip
    mkdir ${zipName}

    mkdir ${zipName}/frameworks
    mkdir ${zipName}/libs

    echo " 创建压缩包"

    if [ -d "${mouduleName}-$shouldToVersion/${mouduleName}.xcframework" ]
    then
    echo "cocoapods-xcframework打包方式"

    cp -a -f ${mouduleName}-${shouldToVersion}/${mouduleName}.xcframework/ios-armv7_arm64/ ${zipName}/frameworks/
    # macmini not work , user find command
    # cp -rf ${mouduleName}/Core/Vendor/**/*.framework ${zipName}/frameworks/
    # cp -rf ${mouduleName}/Core/Vendor/**/*.a ${zipName}/libs/
    # cp -rf EMPASR/Resources/**/*.{bundle,dat,bin,caf} ${zipName}/
    find ${mouduleName}/Resources/ -name '*.bundle' -o -name '*.dat' -o -name '*.bin' -o -name '*.caf' -o -name '*.xml' -o -name '*.js' -o -name '*.plist' | xargs -I F cp -rf "F" ${zipName}/
    # 第三方库资源文件
    find ${mouduleName}/Core/Vendor -name '*.bundle' -o -name '*.dat' -o -name '*.bin' -o -name '*.caf' -o -name '*.xml' -o -name '*.js' -o -name '*.plist' | xargs -I F cp -rf "F" ${zipName}/
    else
    echo "cocoapods-packer打包方式"

    cp -a -f ${mouduleName}-${shouldToVersion}/ios/${mouduleName}.embeddedframework/*.framework ${zipName}/frameworks/
    #find ${mouduleName}/Resources/ -name '*.bundle' -o -name '*.dat' -o -name '*.bin' -o -name '*.caf' -o -name '*.xml' | xargs -I F cp -rf "F" ${zipName}/
    # 第三方库资源文件
    #find ${mouduleName}/Core/Vendor -name '*.bundle' -o -name '*.dat' -o -name '*.bin' -o -name '*.caf' -o -name '*.xml' -o -name '*.js' -o -name '*.plist' | xargs -I F cp -rf "F" ${zipName}/
    fi

    echo "导入依赖的第三方库"
    find ${mouduleName}/Core/Vendor/ -name '*.framework' | xargs -I F cp -rf "F" ${zipName}/frameworks/
    find ${mouduleName}/Core/Vendor/ -name '*.a' | xargs -I F cp -rf "F" ${zipName}/libs/

    zip -y -r ${zipName}.zip ${zipName}

    echo "上传压缩包"
    #sshpass -p 'cccc' ssh xiaofeixia@192.168.50.197
    #sshpass -p 'cccc' scp ${zipName}.zip xiaofeixia@192.168.50.197:/Users/xiaofeixia/ios_frameworks/${mouduleName}

    if [ ! -d "/Users/mac/Desktop/iOS/ios-frameworks/${mouduleName}" ]
    then
    mkdir /Users/mac/Desktop/iOS/ios-frameworks/${mouduleName}
    echo "创建模块文件夹"
    fi

    cp ${zipName}.zip /Users/mac/Desktop/iOS/ios-frameworks/${mouduleName}

    echo "删除包文件"
    rm -rf ${mouduleName}-${shouldToVersion}
    rm -rf ${zipName}/
    rm -f ${zipName}.zip

    echo "修改podspec版本号 begin"
    sed -i "" "s/${versionLine}/${updateVersionLine}/g" ${podpushPodspec_file_name}
    echo "修改podspec版本号 end"

    echo "git push"
    git add ${packagePodspec_file_name} ${podpushPodspec_file_name}
    git commit -m "version to $shouldToVersion"
    git push origin HEAD:master

    echo "git tag"
    git tag -f $shouldToVersion -m "$tagComment"
    git push origin -f $shouldToVersion

    echo "pod push"
    if ! sh podpush.sh; then
    echo "pod install错误"
    set -e
    exit 1
    fi

    echo "更新pod私有库"
    cd /Users/mac/.cocoapods/repos/EMPPrivateSpecs
    git pull

    三、总结

    本文章只是提供了iOS模块产物化、自动升级托管的一个大致流程及思路。具体实现细节视个人项目而定。