您最多选择25个主题 主题必须以中文或者字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符
 
 
 
 
 
 

486 行
20 KiB

from genericpath import exists
from pathlib import Path
import os
import sys
import getopt
import shutil
import json
import re
work_path=os.getcwd()
engine_path=""
platform=""
gn_params=""
optimize=""
ninja_params=""
ninja_params1=""
ninja_params2=""
ninja_params3=""
runtime_mode=""
bitcode=""
flutter_root_path=""
visual_studio_path=""
def get_opts():
# get intput agrs
global engine_path
global gn_params
global runtime_mode
global bitcode
global visual_studio_path
global platform
if len(sys.argv) < 2:
show_help()
sys.exit()
options, args = getopt.getopt(sys.argv[1:], 'r:p:m:v:eh',["help"])
for opt, arg in options:
if opt == '-r':
engine_path = arg # set engine_path, depot_tools and flutter engine folder will be put into this path
elif opt == '-p':
platform = arg
if platform == "android" or platform == "ios":
gn_params += " --" + arg # set the target platform android/ios
elif opt == '-m':
runtime_mode = arg
gn_params += " --runtime-mode=" + runtime_mode # set runtime mode release/debug
elif opt == '-v':
visual_studio_path = arg
elif opt == '-e':
bitcode="-bitcode_bundle -bitcode_verify"
elif opt in ("-h","--help"):
show_help()
sys.exit()
if platform == "ios" and bitcode == "-bitcode_bundle -bitcode_verify":
gn_params += " --bitcode" # enable-bitcode switch
def engine_path_check():
global engine_path
if not os.path.exists(engine_path):
os.makedirs(engine_path)
def bitcode_conf():
global platform
global bitcode
if platform == "ios":
f = open("bitcode.conf",'w')
if bitcode == "-bitcode_bundle -bitcode_verify":
f.write("true")
else:
f.write("false")
f.close()
def set_params():
global output_path
global ninja_params
global ninja_params1
global ninja_params2
global ninja_params3
global gn_params
global visual_studio_path
global platform
global optimize
print("setting environment variable and other params...")
if platform == "windows":
visual_studio_path_env = os.getenv('GYP_MSVS_OVERRIDE_PATH', 'null')
if visual_studio_path == "":
if visual_studio_path_env == 'null':
assert False, "In func set_params(), visual_studio_path is not exist, please set the path by using \"-v\" param to set a engine path."
else:
os.environ["GYP_MSVS_OVERRIDE_PATH"] = visual_studio_path
if runtime_mode == "release" and (platform == "mac" or platform == "windows"):
optimize=""
output_path="host_release"
ninja_params1=" -C out/" +output_path + " flutter/third_party/txt:txt_lib"
ninja_params2=" -C out/" +output_path + " third_party/angle:angle_lib"
ninja_params3=" -C out/" +output_path + " third_party/angle:libEGL_static"
elif runtime_mode == "debug" and (platform == "mac" or platform == "windows"):
optimize="--unoptimized"
output_path="host_debug_unopt"
ninja_params1=" -C out/" +output_path + " flutter/third_party/txt:txt_lib"
ninja_params2=" -C out/" +output_path + " third_party/angle:angle_lib"
ninja_params3=" -C out/" +output_path + " third_party/angle:libEGL_static"
elif runtime_mode == "release" and platform == "android":
optimize=""
output_path="android_release"
elif runtime_mode == "debug" and platform == "android":
optimize="--unoptimized"
output_path="android_debug_unopt"
elif runtime_mode == "release" and platform == "ios":
optimize=""
output_path="ios_release"
elif runtime_mode == "debug" and platform == "ios":
optimize="--unoptimized"
output_path="ios_debug_unopt"
else:
assert False, "In func set_params(), unknown param"
ninja_params=" -C out/" + output_path + " flutter/third_party/txt:txt_lib"
gn_params=gn_params + " " + optimize
def set_env_verb():
global platform
global flutter_root_path
flutter_root_path = os.getenv('FLUTTER_ROOT_PATH', 'null')
if flutter_root_path == 'null':
os.environ["FLUTTER_ROOT_PATH"] = os.path.join(engine_path, "engine","src")
flutter_root_path = os.getenv('FLUTTER_ROOT_PATH')
else:
print("This environment variable has been set, skip")
env_path = os.getenv('PATH')
path_strings = re.split("[;:]", env_path)
for path in path_strings:
if path.endswith("depot_tools"):
print("This environment variable has been set, skip")
return
if platform == "windows":
os.environ["PATH"] = engine_path + "/depot_tools;" + os.environ["PATH"]
else:
os.environ["PATH"] = engine_path + "/depot_tools:" + os.environ["PATH"]
def get_depot_tools():
print("\nGetting Depot Tools...")
if not os.path.exists(engine_path):
assert False,"Flutter engine path is not exist, please set the path by using \"-r\" param to set a engine path."
if os.path.exists(Path(engine_path + "/depot_tools")) and os.path.exists(Path(engine_path + "/depot_tools/.git")):
print("depot_tools already installed, skip")
else:
os.chdir(engine_path)
os.system("git clone https://chromium.googlesource.com/chromium/tools/depot_tools.git")
os.system("gclient sync")
def get_flutter_engine():
global engine_path
global flutter_root_path
print("\nGetting flutter engine...")
if not os.path.exists(Path(engine_path + "/engine")):
os.makedirs(Path(engine_path + "/engine"))
content = '''
solutions = [
{
"managed": False,
"name": "src/flutter",
"url": "git@github.com:flutter/engine.git",
"custom_deps": {},
"deps_file": "DEPS",
"safesync_url": "",
},
]
'''
f = open(Path(engine_path + "/engine/.gclient"), "w")
f.write(content)
f.close()
os.chdir(Path(engine_path + "/engine"))
os.system("gclient sync")
os.chdir(Path(flutter_root_path + "/flutter"))
os.system("git checkout flutter-1.17-candidate.5")
os.system("gclient sync -D")
def compile_engine():
global flutter_root_path
global work_path
global gn_params
global output_path
global ninja_params1
global ninja_params2
global ninja_params3
global platform
print("\nSCompiling engine...")
if platform == "ios" or platform == "mac":
os.chdir(Path(flutter_root_path + "/flutter/third_party/txt"))
copy_file(Path(work_path + "/patches/BUILD.gn.patch"), Path(flutter_root_path + "/flutter/third_party/txt"))
os.system("patch < BUILD.gn.patch -N")
os.chdir(Path(flutter_root_path + "/build/mac"))
copy_file(Path(work_path + "/patches/find_sdk.patch"), Path(flutter_root_path + "/build/mac"))
os.system("patch < find_sdk.patch -N")
elif platform == "android":
os.chdir(Path(flutter_root_path + "/flutter/third_party/txt"))
copy_file(Path(work_path + "/patches/android/BUILD.gn.patch"), Path(flutter_root_path + "/flutter/third_party/txt"))
os.system("patch < BUILD.gn.patch -N")
os.chdir(Path(flutter_root_path + "/build/mac"))
copy_file(Path(work_path + "/patches/find_sdk.patch"), Path(flutter_root_path + "/build/mac"))
os.system("patch < find_sdk.patch -N")
os.chdir(Path(flutter_root_path + "/build/secondary/third_party/libcxxabi"))
copy_file(Path(work_path + "/patches/android/BUILD_2.gn.patch"), Path(flutter_root_path + "/build/secondary/third_party/libcxxabi"))
os.system("patch < BUILD_2.gn.patch -N")
elif platform == "windows":
os.chdir(Path(flutter_root_path + "/flutter/third_party/txt"))
copy_file(Path(work_path + "/patches/BUILD.gn.patch"), Path(flutter_root_path + "/flutter/third_party/txt"))
os.system("patch < BUILD.gn.patch -N")
os.chdir(Path(flutter_root_path + "/third_party/angle"))
copy_file(Path(work_path + "/patches/windows/BUILD.gn.patch"), Path(flutter_root_path + "/third_party/angle"))
os.system("patch < BUILD.gn.patch -N")
os.chdir(Path(flutter_root_path + "/third_party/angle/src/libANGLE/renderer/d3d/d3d11/"))
copy_file(Path(work_path + "/patches/windows/cpp.patch"), Path(flutter_root_path + "/third_party/angle/src/libANGLE/renderer/d3d/d3d11"))
os.system("patch < cpp.patch -N")
os.chdir(Path(flutter_root_path + "/third_party/skia/"))
copy_file(Path(work_path + "/patches/windows/BUILD_2.gn.patch"), Path(flutter_root_path + "/third_party/skia"))
os.system("patch < BUILD_2.gn.patch -N")
os.chdir(Path(flutter_root_path))
os.system("python ./flutter/tools/gn " + gn_params)
if platform == "mac":
f = open(Path(flutter_root_path + "/out/" + output_path + "/args.gn"), 'a')
f.write("icu_use_data_file = false")
f.close()
os.system("ninja " + ninja_params)
elif platform == "ios":
old_str = "bitcode_marker = true"
new_str = "bitcode_marker = false"
file_data = ""
with open(Path(flutter_root_path + "/out/" + output_path + "/args.gn"), "r") as f:
for line in f:
if old_str in line:
line = line.replace(old_str,new_str)
file_data += line
file_data += "icu_use_data_file = false"
with open(Path(flutter_root_path + "/out/" + output_path + "/args.gn"),"w") as f:
f.write(file_data)
os.system("ninja " + ninja_params)
elif platform == "windows":
f = open(Path(flutter_root_path + "/out/" + output_path + "/args.gn"), 'a')
f.write("skia_use_angle = true\nskia_use_egl = true")
f.close()
os.system("ninja " + ninja_params1)
os.system("ninja " + ninja_params2)
os.system("ninja " + ninja_params3)
os.chdir(Path(flutter_root_path + "/third_party/icu/flutter/"))
os.system("ld -r -b binary -o icudtl.o icudtl.dat")
elif platform == "android":
os.system("ninja " + ninja_params)
def build_engine():
global flutter_root_path
global work_path
global runtime_mode
global platform
global output_path
global bitcode
dest_folder=""
#delete SDKRoot env if any. It may conflict with the real sysroot path generated by Bee
if 'SDKROOT' in os.environ:
del os.environ['SDKROOT']
print("\nStarting build engine...")
if platform == "windows":
dest_folder = "x86_64"
elif platform == "mac":
dest_folder = "osx"
elif platform == "android":
dest_folder = "android"
os.chdir(work_path + "/../")
os.system("python " + flutter_root_path + "/flutter/sky/tools/objcopy.py --objcopy " + flutter_root_path + "/third_party/android_tools/ndk/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64/bin/arm-linux-androideabi-objcopy --input " + flutter_root_path + "/third_party/icu/flutter/icudtl.dat --output icudtl.o --arch arm")
elif platform == "ios":
dest_folder = "ios"
if not os.path.exists(Path(work_path + "/../../com.unity.uiwidgets/Runtime/Plugins/" + dest_folder)):
os.makedirs(Path(work_path + "/../../com.unity.uiwidgets/Runtime/Plugins/" + dest_folder))
os.chdir(Path(work_path + "/../"))
if runtime_mode == "release":
if os.path.exists(Path(work_path + "/../build_release")):
shutil.rmtree(Path(work_path + "/../build_release"))
if platform == "windows":
os.system("bee.exe win_release")
copy_file(Path(work_path + "/../build_release/"), Path(work_path + "/../../com.unity.uiwidgets/Runtime/Plugins/" + dest_folder))
else:
os.system("mono bee.exe " + platform +"_release")
copy_file(Path(work_path + "/../build_release/"), Path(work_path + "/../../com.unity.uiwidgets/Runtime/Plugins/" + dest_folder))
if platform == "android":
tundra_file=Path(work_path + "/../artifacts/tundra.dag.json")
rsp = get_rsp(tundra_file, runtime_mode)
if not os.path.exists(Path(work_path + "/../artifacts/rsp/backup")):
os.makedirs(Path(work_path + "/../artifacts/rsp/backup"))
copy_file(Path(work_path + "/../" + rsp), Path(work_path + "/../artifacts/rsp/backup"))
os.chdir(Path(work_path))
rsp_patch(rsp)
os.chdir(Path(work_path + "/../"))
os.system("artifacts/Stevedore/android-ndk-mac/toolchains/llvm/prebuilt/darwin-x86_64/bin/clang++ " + "@\"" + rsp + "\"")
os.system(flutter_root_path + "/buildtools/mac-x64/clang/bin/clang++ " + "@\"" + rsp + "\"")
copy_file(Path(work_path + "/../artifacts/libUIWidgets/release_Android_arm32/libUIWidgets.so"), Path(work_path + "/../../com.unity.uiwidgets/Runtime/Plugins/Android"))
elif platform == "ios":
print("\nStarting prlink library...")
os.chdir(Path(work_path + "/../"))
tundra_file=Path(work_path + "/../artifacts/tundra.dag.json")
prelinkfiles(tundra_file, runtime_mode, output_path, work_path, bitcode)
elif runtime_mode == "debug":
if os.path.exists(Path(work_path + "/../build_debug")):
shutil.rmtree(Path(work_path + "/../build_debug"))
if platform == "windows":
os.system("bee.exe win_debug")
else:
os.system("mono bee.exe " + platform +"_debug")
copy_file(Path(work_path + "/../build_debug/"), Path(work_path + "/../../com.unity.uiwidgets/Runtime/Plugins/" + dest_folder))
if platform == "ios":
print("\nStarting prlink library...")
os.chdir(Path(work_path + "/../"))
tundra_file=Path(work_path + "/../artifacts/tundra.dag.json")
prelinkfiles(tundra_file, runtime_mode, output_path, work_path, bitcode)
def revert_patches():
global flutter_root_path
print("\nRevert patches...")
os.chdir(Path(flutter_root_path + "/flutter/third_party/txt"))
os.system("patch -R < BUILD.gn.patch")
if platform == "ios" or platform == "mac":
os.chdir(Path(flutter_root_path + "/build/mac"))
os.system("patch -R < find_sdk.patch")
if platform == "ios":
os.chdir(Path(work_path))
if os.path.exists(Path(work_path + "/bitcode.conf")):
os.remove("bitcode.conf")
elif platform == "android":
os.chdir(Path(flutter_root_path + "/build/mac"))
os.system("patch -R < find_sdk.patch")
os.chdir(Path(flutter_root_path + "/build/secondary/third_party/libcxxabi"))
os.system("patch -R < BUILD_2.gn.patch")
elif platform == "windows":
os.chdir(Path(flutter_root_path + "/third_party/angle"))
os.system("patch -R < BUILD.gn.patch")
os.chdir(Path(flutter_root_path + "/third_party/angle/src/libANGLE/renderer/d3d/d3d11/"))
os.system("patch -R < cpp.patch")
os.chdir(Path(flutter_root_path + "/third_party/skia/"))
os.system("patch -R < BUILD_2.gn.patch")
def copy_file(source_path, target_path):
if not os.path.exists(target_path):
os.makedirs(target_path)
if os.path.exists(source_path):
if os.path.isfile(source_path):
shutil.copy(source_path, target_path)
elif os.path.isdir(source_path):
for root, dirs, files in os.walk(source_path):
for file in files:
src_file = os.path.join(root, file)
shutil.copy(src_file, target_path)
def rsp_patch(rsp_path):
global work_path
file_data = ""
file = Path(work_path + "/../" + rsp_path)
old_str = ',--icf-iterations=5'
with open(file, "r") as f:
for line in f:
if old_str in line:
line = line.replace(old_str,'')
file_data += line
with open(file,"w") as f:
f.write(file_data)
return "rsp modified"
def get_xcode_path():
res = os.popen('xcode-select -p')
return res.read()
def get_target_files(tundra_file, runtime_mode):
if not os.path.exists(tundra_file):
print('tundra.dag.json file not found')
return None
with open(tundra_file, 'r') as f:
temp = json.loads(f.read())
json_list = temp['Nodes']
target_files=''
for item in json_list:
if item['Annotation'].startswith('Lib_iOS_arm64') and item['Annotation'].find(runtime_mode) != -1:
action = item['Action']
o_file_list = action.split("\"")
for o in o_file_list:
if o.endswith('.o'):
target_files += ' '+o
return target_files
def prelinkfiles(tundra_file, runtime_mode, output_path, work_path, bitcode):
global flutter_root_path
target_files = get_target_files(tundra_file, runtime_mode)
if not target_files:
print("get prelink xxx.o files failed")
else:
os.system('nm -j ' + flutter_root_path + '/out/' + output_path + '/obj/flutter/third_party/txt/libtxt_lib.a > third.symbol')
xcode_path = get_xcode_path().strip()
os.system('\"' + xcode_path + '/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld" -r -arch arm64 ' + bitcode + ' -syslibroot ' + xcode_path + '/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS.sdk -unexported_symbols_list third.symbol ' + target_files + ' ' + flutter_root_path + '/out/' + output_path + '/obj/flutter/third_party/txt/libtxt_lib.a -o "libUIWidgets.o"')
os.system('\"' + xcode_path + '/Toolchains/XcodeDefault.xctoolchain/usr/bin/libtool" -arch_only arm64 -static "libUIWidgets.o" -o "libUIWidgets.a"')
if runtime_mode == "release":
os.system('\"' + xcode_path + '/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip" -x "libUIWidgets.a"')
copy_file(Path(work_path + "/../libUIWidgets.a"), Path(work_path + "/../../com.unity.uiwidgets/Runtime/Plugins/ios/libUIWidgets.a"))
def get_rsp(tundra_file, runtime_mode):
if not os.path.exists(tundra_file):
print('tundra.dag.json file not found')
return None
with open(tundra_file, 'r') as f:
temp = json.loads(f.read())
json_list = temp['Nodes']
target_files=''
for item in json_list:
if item['Annotation'].startswith('Link_Android_arm32') and item['Annotation'].find(runtime_mode) != -1:
action_list = item['Inputs']
for o in action_list:
if o.endswith('.rsp'):
return o
def show_help():
help_note = '''
SYNOPSIS
python3 lib_build.py <-p <android|ios|windows|mac>> <-r <engine_path>> <-m <debug|release>> [-v [visual_studio_path]] [-e] [-h] [--help].
NOTION
python3 is required to run this script. For windows, visual studio 2017 need to be installed. For mac, Xcode need to be installed and Mac version should be 10 or 11.
You can build for mac/ios/android platforms on Mac. You can only build for windows platform on Windows
DESCRIPTION
lib_build.py will setup the build environment and build UIWidgets' engine.
The following options are available:
required parameters:
-p Target platform, available values: android, windows, mac, ios
-m Build mode, available values: debug, release
-r The build target directory, third party dependencies (e.g., flutter engine) will be downloaded and built here
optional parameters:
-h, --help Show this help message
-e Enable bitcode for ios targets and can only be used when "-p ios" is specified
-v The visual studio path in your PC, e.g., "C:\Program Files (x86)/Microsoft Visual Studio/2017/Community". It is required if "-p window" is specified
'''
print(help_note)
def main():
get_opts()
engine_path_check()
bitcode_conf()
set_params()
set_env_verb()
get_depot_tools()
get_flutter_engine()
compile_engine()
build_engine()
revert_patches()
if __name__=="__main__":
main()