要实现混合开发的的自动构建过程,需要解决几个问题:
以window平台为例子
from git import Repo
...
def pull_remote(self):
print("start update git repo")
# 获取指定地址的仓库对象
repo = self.get_repo()
# 获取目标分支名
branchStr = self.get_cur_branch()
head = repo.head
try:
#检查本地分支
branch = repo.branches[branchStr]
except IndexError as e:
# 没有检出的话需要检出
remoteHead = repo.remote().refs[branchStr]
remoteHead.checkout(force=True, b=branchStr)
branch = repo.branches[branchStr]
try:
#要丢弃所有更改
head.reset(working_tree=True)
repo.git.clean("-df")
#尝试checkout
branch.checkout()
repo.remote().pull()
except Exception as e:
print("error on update repo")
exit(1)
print("update git repo finished")
#
namespace XXX {
public static void CommandLineCompileBuild(){
...
}
}
那么可以在cmd或者shell中使用如下语句调用该函数
xxx/xxx/unity.exe -projectPath your-unityproject-path -executeMethod XXX.CommandLineCompileBuild
其中-projectPath参数指定要打包的工程的绝对路径
在真正开始启动Unity打包之前,一般会有一段预处理的工作,比如清除中间文件,生成代码等,这些也可以在python脚本中操作。 其中最重要的是关闭正在占用该工程的Unity进程。核心函数是通过查找Unity的LockFile文件的持有进程来关闭该Unity进程。
import psutil
from distutils.dir_util import copy_tree, remove_tree
...
def close_unity_process(self):
# 获取工程Root路径
projPath = self.get_unity_project_path()
tempDir = (projPath + r"\Temp")
lockFile = tempDir + r"\UnityLockfile"
exists = os.path.exists(lockFile)
if not exists:
return
unity_name = 'Unity.exe'
for proc in psutil.process_iter():
try:
if proc.name() != unity_name:
continue
open_files = proc.open_files()
if not open_files:
continue
found = False
for open_file in open_files:
if os.path.abspath(open_file.path) != lockFile:
continue
found = True
print(f'Kill open Unity process: {proc.pid}')
sys.stdout.flush()
proc.kill()
time.sleep(10)
break
if found:
break
except psutil.NoSuchProcess as err:
print("****", err)
if os.path.isdir(tempDir):
remove_tree(tempDir)
启动Unity并且打包的过程,可以使用python中提供的os.system函数,该通过cmd启动一个新进程,并且阻塞等待进程退出, 返回进程的返回值。例如:
import os
...
statusCode = os.system("xxx/xxx/unity.exe -projectPath your-unityproject-path -executeMethod XXX.CommandLineCompileBuild")
if statusCode != 0:
print("error while building:{} ".format(statusCode))
exit(statusCode)
等待Unity输出完工程以后,需要使用Gradle进行打包编译(IL2Cpp),在pyhon中可以调用Gradlew工具进行打包,需要提前安装好gradle。
...
def build_gradle(self, asPath):
# gradle 运行文件的全路径
gradleExePath = "path to gradle executable file"
# 切换到传入的Android工程目录
os.chdir(asPath)
# 首先build gradle wrapper 产生gradlew
code = os.system("{} wrapper".format(gradleExePath))
if code != 0:
exit(1)
isRelease = self.isRelease()
cmd = "assembleRelease" if isRelease else "assembleDebug"
# 使用gradlew assembleXXX 打包
code = os.system("gradlew {}".format(cmd))
if code != 0:
exit(1)
打包完成后,可以根据项目的实际情况,复制Gradle打包输出的资源和库文件到目标Android工程中。这一步可能会遇到Gradle的各种参数不对, 比如Unity输出的SDK,NDK地址格式错误等等,这些需要在脚本里显式的修复,不然无法进行下一步。
最后在目标Android工程中,再次执行上面的Gradle打包,得到最终的包体。需要注意的是,如果输出release包,需要额外的资源对齐和签名操作, 如果嫌麻烦可以将jks文件密码写在build.gradle里,这样在assembleRelease时会自动进行这些操作。不过这样做的话需要严格限制此Android工程的权限, 或者不要将build.gradle放在版本控制里,不然每个人都能看到密码。
#
#