Build

记录之前用Shell和Python分别写的自动打包脚本。

Shell

语法

变量

1
2
3
4
5
6
7
8
# 字符串
projectName="ABC"

# Bool
isNeedPodInstall=true

# 字符串拼接
ipaPath="Result"/$projectName.ipa

条件语句

1
2
3
if $isNeedPodInstall; then
pod install
fi

函数

1
2
3
4
5
6
7
8
9
build()
{
if $isGetTimeWithBuilding; then
echo "打包并计算编译时间。。。"
xcodebuild -workspace $workspacePath -scheme $projectName clean archive -archivePath $archivePath OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" |grep .[0-9]ms | sort -nr > $resultPath/time.txt
else
xcodebuild -workspace $workspacePath -scheme $projectName clean archive -archivePath $archivePath
fi
}

写文件

1
2
3
4
5
6
7
8
9
10
11
12
echo "创建Plist文件"
cat << EOF > $configPlistDir
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>ad-hoc</string>
</dict>
</plist>
EOF
echo "创建Plist文件 Success"

执行参数

1
2
3
4
5
6
# ./build -c "修复已知问题"
log=""
if [ $1 == "-c" ]; then
log="$2"
fi
echo "打包说明: $log"

Python

语法

头文件

1
2
3
4
import sys, os
import plistlib
import gflags
import time

gflags是Google的参数解析库。

1
2
3
4
5
6
7
# 定义Python主入口
if __name__ == '__main__':
obj = Build()
startTime = time.time()
obj.start()
endTime = time.time()
print("\nUseing time:%d s" % (int(endTime - startTime)))

函数

1
2
def execuse(commond):
print("Excusing ->" + commond + "<- Commond\n")

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Build:

# 初始化方法
def __init__(self):
print("Build init.")

# 方法
def createConfigPlistFile(self):
p = open(configPlistDir, "w")
plistContent = """\
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>ad-hoc</string>
</dict>
</plist>
"""
p.write(plistContent)
p.flush()
p.close()
print("--->Create Config Plist Success!")

Archive

shell版本

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
#! /bin/bash
#任何一个语句返回非真则退出Bash
set -e
#显示每条执行语句
#set -x
######Start Config#####
projectName="CarLoan"
resultPath="Result"
configPlistDir="$resultPath/build.plist"
#directory
rootDir="../iOS"
infoPlistDir="$rootDir/$projectName/$projectName/Supporting Files/Info.plist"
ipaPath=$resultPath/$projectName.ipa
archivePath=$resultPath/$projectName.xcarchive
workspacePath=$rootDir/$projectName.xcworkspace
#Bool
isNeedPodInstall=true
isNeedAutoModifyVersion=true
isGetTimeWithBuilding=false
isUploadFirIm=true
isNeedAutoLogThisArchive=true
#isWorkSpace=true
#isQuiet=false
######End Config######

rm -rf $resultPath/
mkdir $resultPath/

##### fir Log ######
##### . ./build -c "测试版本"
changeLog=""
if [ $1 == "-c" ]; then
changeLog="$2"
fi
echo "Fir打包说明: $changeLog"


#####这里操作一些必须在主程序目录下的操作#####
cd ../iOS/

if $isNeedPodInstall; then
pod install
fi

cd ../docs/
#####这里操作一些必须在主程序目录下的操作#####

# 读取当前版本号
currentVersion=`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion" "$infoPlistDir"`
echo "当前版本号: $currentVersion"
# 版本号加1
newVersion=`expr $currentVersion + 1`

echo "创建Plist文件"
cat << EOF > $configPlistDir
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>ad-hoc</string>
</dict>
</plist>
EOF
echo "创建Plist文件 Success"

versionAdd()
{
# 设置新的版本号
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $newVersion" "$infoPlistDir"
echo "修改版本号:$currentVersion -> $newVersion"
}

baseBuild()
{
xcodebuild -workspace $workspacePath -scheme $projectName clean archive -archivePath $archivePath $1
#xcodebuild -project $projectName -scheme $projectName clean archive -archivePath $archivePath $1
}

build()
{
if $isGetTimeWithBuilding; then
echo "打包并计算编译时间。。。"
xcodebuild -workspace $workspacePath -scheme $projectName clean archive -archivePath $archivePath OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" |grep .[0-9]ms | sort -nr > $resultPath/time.txt
else
xcodebuild -workspace $workspacePath -scheme $projectName clean archive -archivePath $archivePath
fi
}

# 打包ipa文件
archive()
{
if [ -d $archivePath ]; then
echo "创建ipa文件。。。"
xcodebuild -exportArchive -archivePath $archivePath -exportPath $resultPath/ -exportOptionsPlist $configPlistDir
echo "创建ipa文件成功"
size=`ls -hl $ipaPath | awk '{print $5}'`
echo "ipa文件大小:$size"
else
echo "创建ipa文件失败,xcarchive文件不存在"
exit 1
fi
}

upload()
{
if [ -f $ipaPath ]; then
fir me
#fir i $ipaPath
fir p $ipaPath -c "$changeLog"
else
echo "上传到fir失败,ipa文件不存在"
exit 1
fi
}

#如果打包失败就将版本号改回去
##TODO:
goBack(){
git checkout -- $infoPlistDir
}

if $isNeedAutoModifyVersion; then
versionAdd
fi

echo "Building。。。"
build
echo "Archiving。。。"
archive
echo "上传至Fir。。。"
if $isUploadFirIm; then
upload
fi

if $isNeedAutoLogThisArchive; then
#给版本号一个新的Commit,表示一次发布版本。
echo "提交一个新Commit,记录此次打包。。。"
git add "$infoPlistDir"
git commit -m "New Packet: $currentVersion -> $newVersion"
git push
fi

python版本

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
#! /usr/bin/python
import sys, os
import plistlib
import gflags
import time
#import pdb

gflags.DEFINE_bool('test', False, 'Is Test')
gflags.DEFINE_string('log', '', 'ChangeLog for fir')
gflags.DEFINE_bool('version', True, 'Is Auto Change Version')
gflags.DEFINE_bool('clean', True, 'Clean WorkSpace before Archive')
gflags.DEFINE_bool('time', False, 'Get time with build')
gflags.DEFINE_bool('upload', True, 'Upload to fir')
gflags.DEFINE_bool('quiet', True, 'Do not print any output except for warnings and errors')
gflags.DEFINE_bool('commit', True, 'Auto Git Commit to log this Archive')
#Other Flags for Commond
gflags.DEFINE_string('build', '', 'Other Flags for build, Using \' replaced "')
gflags.DEFINE_string('archive', '', 'Other Flags for archive, Using \' replaced "')
gflags.DEFINE_string('fir', '', 'Other Flags for fir, Using \' replaced "')

#checking FLAGS
try : gflags.FLAGS(sys.argv)
except gflags.FlagsError, e :
print e
print("--->FLAGS Error!")
sys.exit(1)

rootDir = "../iOS"
resultDir = "../docs"
resultPath = "Result"
configPlistDir = resultPath + "/build.plist"
timePath = resultPath + "/time.txt"

def execuse(commond):
print("Excusing ->" + commond + "<- Commond\n")
if not gflags.FLAGS.test: os.system(commond)

# Init Build
# remove Result/
# ceate Result
def initBuild():
rmResultPath = "rm -rf " + resultPath
execuse(rmResultPath)
if not gflags.FLAGS.test: os.mkdir(resultPath)

# Auto get project name
def getProjectName():
os.chdir(rootDir)
filelist = os.listdir('./')
for item in filelist:
if item.endswith(".xcworkspace"):
os.chdir(resultDir)
return item.split(".", 1)[0]
else:
print("--->Can't Get Project Name!")
sys.exit(1)

if not gflags.FLAGS.test: initBuild()
projectName = getProjectName()

infoPlistDir = rootDir + ("/" + projectName) * 2 + '/Supporting Files/Info.plist'
ipaPath = resultPath + "/" + projectName + ".ipa"
archivePath = resultPath + "/" + projectName + ".xcarchive"
workspacePath = rootDir + "/" + projectName + ".xcworkspace"

class Build:

def __init__(self):
self.plist = plistlib.readPlist(infoPlistDir)
self.version = self.plist["CFBundleShortVersionString"]
self.bundleVersion = self.plist["CFBundleVersion"]
self.newVersion = self.bundleVersion
print("----------------------------------------------------")
print("--------- CurrentVersion is v" + self.version + " " + str(self.bundleVersion) + " ---------")

#Create Config plist file at resultPath
def createConfigPlistFile(self):
p = open(configPlistDir, "w")
plistContent = """\
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>method</key>
<string>ad-hoc</string>
</dict>
</plist>
"""
p.write(plistContent)
p.flush()
p.close()
print("--->Create Config Plist Success!")

def versionChange(self):
self.newVersion = str(int(self.bundleVersion) + 1)
self.plist["CFBundleVersion"] = self.newVersion
plistlib.writePlist(self.plist, infoPlistDir)
print("---------Update BundleVersion from " + self.bundleVersion + " -> " + self.newVersion + "---------")

#build new xcarchive
def build(self):
baseBuild = "xcodebuild"
#if self.isWorkSpace:
baseBuild += " -workspace " + workspacePath
baseBuild += " -scheme " + projectName
#else:
#baseBuild += " -project"
if gflags.FLAGS.clean: baseBuild += " clean"
else: print("--->Clean before Build is Closed!")
baseBuild += " archive -archivePath " + archivePath
if gflags.FLAGS.quiet: baseBuild += " -quiet"
if gflags.FLAGS.build != '': baseBuild += " " + gflags.FLAGS.build
if gflags.FLAGS.time:
baseBuild += ' OTHER_SWIFT_FLAGS="-Xfrontend -debug-time-function-bodies" |grep .[0-9]ms | sort -nr > ' + timePath
execuse(baseBuild)
print("------------------Build Success---------------------\n")

def archive(self):
print("------------------Start Archive---------------------\n")
baseArchive = "xcodebuild"
baseArchive += " -exportArchive -archivePath " + archivePath
baseArchive += " -exportPath " + resultPath
baseArchive += " -exportOptionsPlist " + configPlistDir
if gflags.FLAGS.quiet: baseArchive += " -quiet"
if gflags.FLAGS.archive != '': baseArchive += " " + gflags.FLAGS.archive
execuse(baseArchive)
print("------------------Archive Success-------------------\n")

def upload(self):
fir = "fir p " + ipaPath
log = gflags.FLAGS.log
if log != '':
fir += ' -c "' + log + '"'
if gflags.FLAGS.fir != '': fir += " " + gflags.FLAGS.fir
execuse(fir)
print("------------------Upload Success-------------------\n")

def commit(self):
os.chdir(rootDir)
commit = 'git commit -am "' + 'New Packet: ' + str(self.version) + " " + str(self.newVersion) + '"'
execuse(commit)
push = 'git push'
execuse(push)
print("----------------Git Commit Success------------------\n")
os.chdir(resultDir)

def start(self):
print("---------------Start Building " + projectName + "---------------\n")
self.createConfigPlistFile()
if gflags.FLAGS.version: self.versionChange()
self.build()
self.archive()
if gflags.FLAGS.upload: self.upload()
if gflags.FLAGS.commit: self.commit()


if __name__ == '__main__':
obj = Build()
startTime = time.time()
obj.start()
endTime = time.time()
print("\nUseing time:%d s" % (int(endTime - startTime)))