工作中需要给不同的渠道出包,每次替换参数,资源文件很繁琐,故自己实现了一个ios批量打包,看起来比较简陋,但是可以满使用需求,自己记录下:(需要用到Xcodeproj 开源库),如何使用可参考:使用代码为 Xcode 工程添加文件
工程文件目录:
dd.ruby:根据不同平台添加渠道需要的库文件;
require 'xcodeproj'
require 'pathname'
channel_symbol=ARGV[0]
dir_path=Pathname.new(File.dirname(__FILE__)).realpath
puts(dir_path)
project_path = dir_path+"Test.xcodeproj"
# 工程的全路径
project = Xcodeproj::Project.open(project_path)
group = project.main_group.find_subpath(File.join('ios','channels'), true)
group.set_source_tree('SOURCE_ROOT')
# 获取全部的文件引用
file_ref_list = target.source_build_phase.files_references
# 设置文件引用是否存在标识
file_ref_mark = false
###########talkingdata#######
if channel_symbol!="talkingdata" then
if !file_ref_mark then
file_ref = group.new_reference('sdks/libTalkingDataAppCpa.a')
target.frameworks_build_phase.add_file_reference(file_ref,true)
else
puts '文件引用已存在'
end
end
###########gaoqu#######
project.save
puts '文件添加完成'
del.ruby:删除项目中指定group中的文件;
require 'xcodeproj'
require 'pathname'
dir_path=Pathname.new(File.dirname(__FILE__)).realpath
puts(dir_path)
project_path = dir_path+"Test.xcodeproj"
# 工程的全路径
project = Xcodeproj::Project.open(project_path)
# 1、显示所有的target
project.targets.each do |target|
puts target.name
end
# 从工程中删除文件
target = project.targets.first
group = project.main_group.find_subpath(File.join('ios/channels',''), true)
group.set_source_tree('SOURCE_ROOT')
def removeBuildPhaseFilesRecursively(aTarget, aGroup)
aGroup.files.each do |file|
if file.real_path.to_s.end_with?(".m", ".mm", ".cpp",".bundle",".framework",".a") then
aTarget.source_build_phase.remove_file_reference(file)
elsif file.real_path.to_s.end_with?(".plist") then
aTarget.resources_build_phase.remove_file_reference(file)
end
end
aGroup.groups.each do |group|
removeBuildPhaseFilesRecursively(aTarget, group)
end
end
#if group.empty? then
removeBuildPhaseFilesRecursively(target, group)
group.clear()
group.remove_from_project
#end
project.save
package.py:打包脚本
#!/usr/bin/python
# -*- coding:UTF-8 -*-
import os,os.path
import sys
import getopt
import json
#######functions##########
def separateStr(symbol):
temStr=''
channelList=[]
for c in symbol:
if c!=',':
temStr+=c
else:
channelList.append(temStr)
temStr=''
if len(temStr)>0:
channelList.append(temStr)
return channelList
def getChannels():
opts,args=getopt.getopt(sys.argv[1:],'m:o')
symbol=''
for op,value in opts:
if op == '-m':
symbol=value
return separateStr(symbol)
def getJsonData(filename):
with open(filename, 'r') as f:
js_data = json.load(f)
return js_data
#######functions##########
cur_dir=os.path.dirname(os.path.realpath(__file__))
project_name='Test.xcodeproj'
target_name='Test-mobile'
archive_path=cur_dir+'/build/'+target_name+'.xcarchive'
ipa_path=cur_dir+'/ipas/tmp'
keys=getChannels()
package_source_dir=cur_dir+'/packages/'
json_dir=package_source_dir+'peizhi/'
print(keys)
for key in keys:
filename=json_dir+key+'.json'
print key
if not os.path.exists(filename):
print('not find'+filename)
continue
data=getJsonData(filename)
# print(data)
channel_symbol=data['channel_symbol']
belong_to=data['belong_to']
ipa_name=cur_dir+"/ipas/"+data['ipa_name']+'.ipa'
product_identifier=data['product_bundle_identifier']
code_sign_identifity=data['code_sign_identifity']
provisioning_profile=data['provisioning_profile']
development_team=data['development_team']
plist_path=package_source_dir+'plists/'+data['ipa_type']+".plist"
config_name='packages/xcc/'+data['xcconfig_name']+'.xcconfig'
if not os.path.exists(cur_dir+'/'+config_name):
config_name='packages/xcc/'+'default.xcconfig'
#modify platform.txt
if channel_symbol!='':
dst_file=cur_dir+'/../Resources/xml/platform.txt'
f_p=open(dst_file,'w')
f_p.write(channel_symbol)
f_p.close()
tmp_ipa_name=ipa_path+'/'+target_name+'.ipa'
#del no use sdks
del_sdk_cmd='ruby del.ruby'
#add will use sdks
add_sdk_cmd='ruby add.ruby %s' %(belong_to)
#clean
clean_build_tmp='rm -r %s' %(cur_dir+'/build')
#clean ipa tmp floder
clean_tmp_ipa='rm -r %s' %(ipa_path)
#clean
clean_cmd='xcodebuild clean -project %s -scheme %s' %(project_name,target_name)
#cp channel resource
can_use_cmd='chmod a+x %scp.sh' %(package_source_dir)
cp_cmd='%scp.sh %s %s' %(package_source_dir,data['res_path'],belong_to)
#build
build_cmd='xcodebuild archive -project %s -scheme %s -archivePath %s \
-configuration Release -sdk iphoneos build PRODUCT_BUNDLE_IDENTIFIER=%s \
CODE_SIGN_IDENTITY=%s PROVISIONING_PROFILE_SPECIFIER=%s DEVELOPMENT_TEAM=%s -xcconfig %s \
' %(project_name,target_name,archive_path,product_identifier,code_sign_identifity,
provisioning_profile,development_team,config_name)
#export ipa
export_cmd='xcodebuild -exportArchive -archivePath %s -exportPath %s -exportOptionsPlist %s' %(archive_path,ipa_path,plist_path)
#move ipa
mv_cmd='mv -f %s %s' %(tmp_ipa_name,ipa_name)
command=can_use_cmd+';'+cp_cmd+';'+del_sdk_cmd+';'+add_sdk_cmd+';'+clean_build_tmp+';'+clean_tmp_ipa+';'+clean_cmd+';'+build_cmd+';'+export_cmd+';'+mv_cmd
os.system(command)
packages:打包需要的配置文件;
cp.sh:拷贝sdks_res目录下对应的渠道需要的资源文件(icon,闪屏...)
peizhi:目录下存放打包ipa的参数 *.Jon
{
"channel_symbol":"",
"belong_to":"渠道标识",
"ipa_name":"生成的ipa名称",
"ipa_type":"生成的ipa类型:dev/adhoc/inhouse",
"product_bundle_identifier":"包名",
"code_sign_identifity":"证书的 常用名称",
"provisioning_profile":"使用的.mobileprovision文件名称",
"development_team":"证书的 组织单位",
"res_path":"需要拷贝的资源目录名称",
"xcconfig_name":"xcconfig配置文件名称"
}
plist:此文件夹下是使用命令行导出ipa必须的文件,文件中包含了ipa的包名,签名文件,ipa类型
sdks_res:渠道需要的资源文件
xcc:渠道需要的参数(appid,appkey)
配置好了之后再工程目录下执行 ./package.py -m xx1,xx2,xx3(packages/peizhi目录下的文件名称) 即可实现批量打包