489 lines
12 KiB
Python
489 lines
12 KiB
Python
import json
|
|
import os
|
|
import glob
|
|
import subprocess
|
|
import multiprocessing
|
|
import platform
|
|
import shutil
|
|
import string
|
|
import sys
|
|
import hashlib
|
|
import argparse
|
|
|
|
############################################################################
|
|
def exitPy():
|
|
os.system('pause')
|
|
os._exit(0)
|
|
|
|
def getFiles(postfix):
|
|
fs = glob.glob(os.getcwd() + "\\" + postfix)
|
|
return fs
|
|
|
|
def getWindowsTargetPlatformVersion():
|
|
return ["10.0.19041.0"]
|
|
|
|
def getProjectList(projs):
|
|
print("选择要编译的工程:")
|
|
print("\t1.全部工程")
|
|
print("\t2.编译单个工程")
|
|
print("\t其它键退出")
|
|
no = input("选择要编译的工程:")
|
|
|
|
projectList = {}
|
|
if no == "1":
|
|
projectList = projs
|
|
elif no == "2":
|
|
idx = 1
|
|
prolst = list(projs.keys())
|
|
strPrj = "\t{}.{}"
|
|
print("选择要编译的工程:")
|
|
for prj in prolst:
|
|
print(strPrj.format(idx, prj))
|
|
idx += 1
|
|
no = input("选择要编译的工程,多个工程用空格分割:")
|
|
nolst = no.split(" ", -1)
|
|
for _no in nolst:
|
|
i = 0
|
|
try:
|
|
i = int(_no)
|
|
except:
|
|
continue
|
|
if i > len(prolst): continue
|
|
prjName = prolst[i - 1]
|
|
if prjName in projs:
|
|
projectList[prjName] = projs[prjName]
|
|
else:
|
|
os._exit(0)
|
|
return projectList
|
|
|
|
def startCompile(cmd):
|
|
compile = subprocess.Popen(cmd)
|
|
compile.wait()
|
|
|
|
def clearLogs(all):
|
|
logs = getFiles("*.log")
|
|
for f in logs:
|
|
if all == True:
|
|
os.remove(f)
|
|
else:
|
|
if os.path.getsize(f) == 0:
|
|
os.remove(f)
|
|
|
|
def printErrorList():
|
|
logs = getFiles("*.log")
|
|
i = 0
|
|
for f in logs:
|
|
if os.path.getsize(f) != 0:
|
|
print("compile failed : " + f)
|
|
i += 1
|
|
if i == 0: print("all success!")
|
|
return i != 0
|
|
|
|
def cleanDir(path):
|
|
if not os.path.exists(path):
|
|
os.makedirs(path)
|
|
return
|
|
shutil.rmtree(path)
|
|
os.mkdir(path)
|
|
|
|
def parseCommands(pathLst, argLst):
|
|
allcmds = list()
|
|
cmds = list()
|
|
_cmds = list()
|
|
for obj in pathLst:
|
|
cmds.clear()
|
|
_cmds.clear()
|
|
cmds.append(string.Template(obj["cmd"]))
|
|
for arg in obj["args"]:
|
|
_cmds.clear()
|
|
for x in argLst[arg]:
|
|
d = dict()
|
|
d[arg] = x
|
|
for cmd in cmds:
|
|
_cmds.append(string.Template(cmd.safe_substitute(d)))
|
|
cmds.clear()
|
|
cmds += _cmds
|
|
allcmds += cmds
|
|
paths = list()
|
|
for x in allcmds:
|
|
paths.append(x.safe_substitute())
|
|
return paths
|
|
|
|
def copyFile(cpy, args):
|
|
try:
|
|
argLst = cpy["arg-list"]
|
|
cleanLst = cpy["clean-list"]
|
|
copyLst = cpy["copy-list"]
|
|
except:
|
|
return False
|
|
argLst = {**argLst, **args}
|
|
pathLst = parseCommands(cleanLst, argLst)
|
|
for x in pathLst:
|
|
cleanDir(x)
|
|
|
|
pathLst.clear()
|
|
pathLst = parseCommands(copyLst, argLst)
|
|
for x in pathLst:
|
|
print(x)
|
|
os.system(x)
|
|
|
|
return True
|
|
|
|
def package(pk, product):
|
|
iscc = pk["iscc"]
|
|
iss = pk["iss-list"][product]
|
|
iss = os.path.abspath(iss)
|
|
os.system("\"{cc}\" {ss}".format(cc = iscc, ss = iss))
|
|
|
|
def md5File(path):
|
|
f = open(path, 'rb')
|
|
md5_obj = hashlib.md5()
|
|
while True:
|
|
d = f.read(8096)
|
|
if not d:
|
|
break
|
|
md5_obj.update(d)
|
|
hash_code = md5_obj.hexdigest()
|
|
f.close()
|
|
md5 = str(hash_code).lower()
|
|
return md5
|
|
|
|
def compileStartUp(startup, compiler, product):
|
|
prjPath = startup["path"]
|
|
iconPath = startup["iconPath"]
|
|
iconTarget = startup["iconName"]["targetIcon"]
|
|
iconSrc = startup["iconName"][product]
|
|
bt = 'rebuild'
|
|
|
|
#现在只需要copy环境即可
|
|
os.system("copy {pa}{na} {pa}{tn} /y".format(pa = iconPath, na = iconSrc, tn = iconTarget))
|
|
|
|
#判断两个文件是否相同,如果相同,说明不需要编译
|
|
|
|
#md5Target = md5File(iconPath + iconTarget)
|
|
#md5Src = md5File(iconPath + iconSrc)
|
|
#if md5Target == md5Src:
|
|
# bt = 'build'
|
|
|
|
'''
|
|
comp = startup["compiler"]
|
|
if comp not in compiler:
|
|
print("未找到编译嚣{}".format(comp))
|
|
os._exit(0)
|
|
vc2005 = compiler[comp]
|
|
'''
|
|
|
|
'''
|
|
不需要编译,在json文件中统一编译
|
|
prjPath = os.path.abspath(prjPath)
|
|
olddir = os.getcwd()
|
|
os.chdir(vc2005)
|
|
os.system("devenv.exe {pa} /{bt} \"release|win32\" /out \"{od}\\startup-win32.slog\"".format(pa = prjPath, od = olddir, bt = bt))
|
|
os.chdir(olddir)
|
|
'''
|
|
|
|
def printCompileInfomation():
|
|
print("**********************************************************")
|
|
print("编译机信息:")
|
|
for x in platform.uname():
|
|
print(x)
|
|
print("**********************************************************")
|
|
return
|
|
|
|
def getCompileProject(compileFile):
|
|
if os.path.exists(compileFile) == False:
|
|
print("未找到 {} 文件。".format(compileFile))
|
|
os.system("pause")
|
|
os._exit(0)
|
|
|
|
jsonstr = ""
|
|
|
|
try:
|
|
file = open(compileFile, "r", encoding="utf-8")
|
|
jsonstr = file.read()
|
|
file.close()
|
|
except Exception as e:
|
|
print("打开文件失败。")
|
|
print(type(e).__name__, e)
|
|
os.system("pause")
|
|
os._exit(0)
|
|
|
|
try:
|
|
project = json.loads(jsonstr)
|
|
except:
|
|
print("文件解析失败。")
|
|
os.system("pause")
|
|
os._exit(0)
|
|
|
|
return project
|
|
|
|
def getProperty(desc, propertyLst, getall):
|
|
print (desc)
|
|
|
|
#如果只有一个选项,直接用
|
|
if len(propertyLst) == 1:
|
|
return [propertyLst[0]]
|
|
|
|
delta = 1
|
|
if getall == True:
|
|
print('1.全部')
|
|
delta = 2
|
|
for idx, val in enumerate(propertyLst):
|
|
print('{i}.{v}'.format(i = idx + delta, v = val))
|
|
no = input('请选择序号(其它键退出):')
|
|
if not no.isdigit():
|
|
exitPy()
|
|
|
|
index = int(no)
|
|
if getall:
|
|
if index == 1:
|
|
return list(propertyLst)
|
|
|
|
index -= delta
|
|
if index >= 0 and index < len(propertyLst):
|
|
return [propertyLst[index]]
|
|
else:
|
|
exitPy()
|
|
|
|
def getYesOrNo(desc):
|
|
no = input(desc)
|
|
if no == "y" or no == "Y":
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def getArgs(desc, arg, _global, getall):
|
|
if len(_global) == 1:
|
|
return _global
|
|
if arg == None:
|
|
return getProperty(desc, _global, getall)
|
|
else:
|
|
return arg
|
|
|
|
############################################################################
|
|
if __name__ == '__main__':
|
|
|
|
if len(sys.argv) > 1 and os.path.exists(sys.argv[1]) == True:
|
|
project = getCompileProject(sys.argv[1])
|
|
del sys.argv[1]
|
|
else:
|
|
g_fs = getFiles("*.json")
|
|
fs = getProperty('请选择要编译的配置文件', g_fs, False)
|
|
project = getCompileProject(fs[0])
|
|
|
|
g_lm = []
|
|
if 'lockMode-list' in project:
|
|
g_lm = project['lockMode-list']
|
|
try:
|
|
g_pd = project['product-list']
|
|
g_bt = project['buildType-list']
|
|
g_pf = project['platform-list']
|
|
g_cf = project['config-list']
|
|
g_ts = project['toolset-list']
|
|
except:
|
|
print('''json文件丢失数据。请检查如下字段: 'product-list', 'lockMode-list', 'buildType-list', 'platform-list', 'config-list', 'toolset-list'。''')
|
|
exitPy()
|
|
|
|
argParse = argparse.ArgumentParser(description='收集参数')
|
|
|
|
if len(g_pd) != 0:
|
|
argParse.add_argument('--pd'
|
|
, help = '''产品名称:'EW2020'或'WF2020' '''
|
|
, type = str
|
|
, nargs = 1
|
|
, choices = g_pd)
|
|
|
|
if len(g_lm) != 0:
|
|
argParse.add_argument('--lm'
|
|
, help = '''加密方式:'BAL_LOCAL'或'BAL_REMOTE' '''
|
|
, type = str
|
|
, nargs = '*'
|
|
, choices = g_lm)
|
|
|
|
if len(g_pf) != 0:
|
|
argParse.add_argument('--pf'
|
|
, help = '''系统平台:'win32'或'x64' '''
|
|
, type = str
|
|
, nargs = '*'
|
|
, choices = g_pf)
|
|
|
|
if len(g_ts) != 0:
|
|
argParse.add_argument('--ts'
|
|
, help = '''vc平台,'v90'、'v100'、'v110'或'v140' '''
|
|
, type = str
|
|
, nargs = '*'
|
|
, choices = g_ts)
|
|
|
|
if len(g_cf) != 0:
|
|
argParse.add_argument('--cf'
|
|
, help = '''编译配置:'release'或'debug' '''
|
|
, type = str
|
|
, nargs = '*'
|
|
, choices = g_cf)
|
|
|
|
if len(g_bt) != 0:
|
|
argParse.add_argument('--bt'
|
|
, help = '''编译行为:'build'、'rebuild'或'clean' '''
|
|
, type = str
|
|
, nargs = '*'
|
|
, choices = g_bt)
|
|
|
|
argParse.add_argument('--autopk', help = '设置此标志,将会自动打包', nargs = '*')
|
|
argParse.add_argument('--svn', help = '设置此标志,将会自动更新代码', nargs = '*')
|
|
argParse.add_argument('--allcompile', help = '设置此标志,将会编译所有代码', nargs = '*')
|
|
|
|
#xx = argParse.parse_args('--pd WF2020 --lm BAL_LOCAL BAL_REMOTE --pf win32 x64 --ts v90 v100 v110 v140 --cf release --bt build'.split())
|
|
#args = argParse.parse_args('--pd WF2020 --lm BAL_LOCAL BAL_REMOTE --pf win32 x64 --ts v90 v100 v110 v140 --cf release --bt build --autopk --svn --allcompile'.split())
|
|
args = argParse.parse_args()
|
|
|
|
printCompileInfomation()
|
|
clearLogs(True)
|
|
|
|
pd = []
|
|
lm = []
|
|
bt = []
|
|
pf = []
|
|
cf = []
|
|
ts = []
|
|
#tsrv专门为copy命令构建,详细请查看配置文件
|
|
tsrv = []
|
|
|
|
if len(g_pd) != 0: pd = getArgs('请选择产品', args.pd, g_pd, False)
|
|
if len(g_lm) != 0: lm = getArgs('请选择加密方式', args.lm, g_lm, True)
|
|
if len(g_bt) != 0: bt = getArgs('请选择编译行为', args.bt, g_bt, False)
|
|
if len(g_pf) != 0: pf = getArgs('请选择系统平台', args.pf, g_pf, True)
|
|
if len(g_cf) != 0: cf = getArgs('请选择编译配置', args.cf, g_cf, True)
|
|
if len(g_ts) != 0: ts = getArgs('请选择VC器平台', args.ts, g_ts, True)
|
|
|
|
autoPK = False
|
|
if "copy-list" in project and "package" in project:
|
|
if args.autopk == None: autoPK = getYesOrNo("是否自动打包?(Y/N):")
|
|
elif (len(args.autopk) == 0 or args.autopk[0] == "Y" or args.autopk[0] == "y"): autoPK = True
|
|
else: autoPK = False
|
|
|
|
if "SVN" in project:
|
|
autoSVN = False
|
|
if args.svn == None: autoSVN = getYesOrNo("是否更新代码?(Y/N):")
|
|
elif (len(args.svn) == 0 or args.svn[0] == "Y" or args.svn[0] == "y"): autoSVN = True
|
|
else: autoSVN = False
|
|
if autoSVN:
|
|
os.system("svn update {pa}".format(pa = project["SVN"]))
|
|
|
|
prjLst = dict()
|
|
if args.allcompile == None:
|
|
prjLst = getProjectList(project["project-list"][pd[0]])
|
|
elif len(args.allcompile) > 0:
|
|
dic = project["project-list"][pd[0]]
|
|
for prjName in args.allcompile:
|
|
if dic.get(prjName) != None:
|
|
prjLst[prjName] = dic[prjName]
|
|
else:
|
|
prjLst = project["project-list"][pd[0]]
|
|
|
|
if len(prjLst) == 0:
|
|
print('没有需要编译的工程。')
|
|
exitPy()
|
|
|
|
if "compiler-list" not in project:
|
|
print("未找到编译器列表.")
|
|
os._exit()
|
|
|
|
compilerLst = project["compiler-list"]
|
|
|
|
''' 构造公共参数列表
|
|
其参数对应 json文件
|
|
'''
|
|
global_args = dict()
|
|
|
|
#编译器列表
|
|
for x, y in compilerLst.items():
|
|
lst = list()
|
|
lst.append(y)
|
|
global_args[x] = lst
|
|
#产品
|
|
if len(pd) != 0:
|
|
global_args["pd"] = pd
|
|
#编译类型
|
|
if len(bt) != 0:
|
|
global_args["bt"] = bt
|
|
#编译配置项
|
|
if len(cf) != 0:
|
|
global_args["cf"] = cf
|
|
#编译平台
|
|
if len(pf) != 0:
|
|
global_args["pf"] = pf
|
|
#加密方式
|
|
if len(lm) != 0:
|
|
global_args["lm"] = lm
|
|
# slm是为了给依赖earthwormcore的工程指名一个lib路径
|
|
# 原因是,earthwormcore.lib生成到了 LOCKMODE 宏指定的目录里,
|
|
# LOCKMODE可能会有多个值,但是没有关系,
|
|
# 只需要依赖任何一个LOCKMODE下的earthwormcore.lib就好
|
|
# 因为依赖earthowrmcore.lib的工程并不使用LOCKMODE宏
|
|
global_args["slm"] = [lm[0]]
|
|
#编译版本,注意,此版本可能还带有objectarx的版本信息以"v90;RVER=R18"的形式
|
|
#通过 ts 来解析出 tsrv
|
|
_ts = []
|
|
if len(ts) != 0:
|
|
for t in ts:
|
|
pr = t.split('+')
|
|
if len(pr) == 2:
|
|
_ts.append('{};RVER={}'.format(pr[0], pr[1]))
|
|
tsrv.append(pr[0] + pr[1])
|
|
else:
|
|
_ts.append(pr[0])
|
|
tsrv.append(pr[0])
|
|
if len(_ts) != 0:
|
|
global_args["ts"] = _ts
|
|
if len(tsrv) != 0:
|
|
global_args["tsrv"] = tsrv
|
|
|
|
#SDK版本
|
|
global_args["wtpv"] = getWindowsTargetPlatformVersion()
|
|
|
|
buildlines = dict()
|
|
argsLst = dict()
|
|
for na, prj in prjLst.items():
|
|
argsLst.clear()
|
|
argsLst["na"] = [na]
|
|
argsLst = {**argsLst, **global_args}
|
|
argsLst = {**argsLst, **prj["arg-list"]}
|
|
buildlines[na] = parseCommands([{'cmd': prj['cmd'], 'args': prj['args']}], argsLst)
|
|
|
|
# 在这里先处理一下命令行中的 log 文件名,由于 toolset 可能带有 objectarx版本信息,需要剔除
|
|
for na, cmds in buildlines.items():
|
|
for i in range(len(cmds)):
|
|
cmd = cmds[i]
|
|
if cmd.count(';RVER=') == 2:
|
|
cmd = cmd[::-1]
|
|
cmd = cmd.replace(str(';RVER=')[::-1], '', 1)
|
|
cmd = cmd[::-1]
|
|
cmds[i] = cmd
|
|
#buildlines[na] = cmd
|
|
|
|
#准备编译 先处理startup工程
|
|
if "startup" in project:
|
|
compileStartUp(project["startup"], compilerLst, pd[0])
|
|
|
|
for cmds in buildlines.values():
|
|
pool = multiprocessing.Pool(processes = 4)
|
|
for cmd in cmds:
|
|
pool.apply_async(startCompile, args = (cmd, ))
|
|
pool.close()
|
|
pool.join()
|
|
clearLogs(False)
|
|
|
|
clearLogs(False)
|
|
|
|
hasErr = printErrorList()
|
|
|
|
if hasErr == True:
|
|
os.system("pause")
|
|
os._exit(0)
|
|
|
|
if (autoPK == True) and ("copy-list" in project) and ("package" in project):
|
|
copyFile(project["copy-list"][pd[0]], global_args)
|
|
package(project["package"], pd[0])
|
|
|
|
|