mirror of https://github.com/axmolengine/axmol.git
353 lines
12 KiB
Python
353 lines
12 KiB
Python
#!/usr/bin/python
|
|
# ----------------------------------------------------------------------------
|
|
# generate the prebuilt Android.mk from source code Android.mk
|
|
#
|
|
# Copyright 2014 (C) zhangbin
|
|
#
|
|
# License: MIT
|
|
# ----------------------------------------------------------------------------
|
|
'''
|
|
generate the prebuilt Android.mk from source code Android.mk
|
|
'''
|
|
|
|
import os
|
|
import shutil
|
|
import re
|
|
|
|
from argparse import ArgumentParser
|
|
|
|
class MKGenerator(object):
|
|
|
|
SRC_FILE_CFG_PATTERN = r"^LOCAL_SRC_FILES[ \t]*[\:\+]*=[ \t]*.+"
|
|
INCLUDE_CFG_PATTERN = r"^include[ \t]+\$\(BUILD_STATIC_LIBRARY\)"
|
|
|
|
LIB_MODULE_PATTERN = r"^LOCAL_MODULE[ \t]*[\:]*=[ \t]*(.+)"
|
|
LIB_MODULE_FILENAME_PATTERN = r"^LOCAL_MODULE_FILENAME[ \t]*[\:]*=[ \t]*(.+)"
|
|
|
|
EXPORT_INCLUDE_PATTERN = r"^LOCAL_EXPORT_C_INCLUDES[ \t]*[\:\+]*=[ \t]*(.+)"
|
|
INCLUDE_MODULE_PATTERN = r"^\$\(call[ \t]*import-module,[ \t]*(.*)\)"
|
|
|
|
|
|
KEY_IS_MODULE = 'is_module'
|
|
KEY_MODULE_LINES = 'lines'
|
|
|
|
def __init__(self, src_mk_path, lib_file_path, dst_mk_path=None):
|
|
if os.path.isabs(src_mk_path):
|
|
self.src_mk_path = src_mk_path
|
|
else:
|
|
self.src_mk_path = os.path.abspath(src_mk_path)
|
|
|
|
if os.path.isabs(lib_file_path):
|
|
self.lib_file_path = lib_file_path
|
|
else:
|
|
self.lib_file_path = os.path.abspath(lib_file_path)
|
|
|
|
if dst_mk_path is None:
|
|
self.dst_mk_path = os.path.join(os.path.dirname(src_mk_path), "Android-prebuilt.mk")
|
|
else:
|
|
if os.path.isabs(dst_mk_path):
|
|
self.dst_mk_path = dst_mk_path
|
|
else:
|
|
self.dst_mk_path = os.path.abspath(dst_mk_path)
|
|
|
|
dst_mk_dir = os.path.dirname(self.dst_mk_path)
|
|
if not os.path.exists(dst_mk_dir):
|
|
os.makedirs(dst_mk_dir)
|
|
|
|
def get_lib_file_name(self, lines):
|
|
module_file_name = None
|
|
module_name = None
|
|
for line in lines:
|
|
trim_line = line.lstrip(" ")
|
|
trim_line = trim_line.rstrip(" ")
|
|
match1 = re.match(MKGenerator.LIB_MODULE_FILENAME_PATTERN, trim_line)
|
|
if match1 is not None:
|
|
module_file_name = match1.group(1)
|
|
|
|
match2 = re.match(MKGenerator.LIB_MODULE_PATTERN, trim_line)
|
|
if match2 is not None:
|
|
module_name = match2.group(1)
|
|
|
|
ret = None
|
|
if module_file_name is not None:
|
|
ret = "%s.a" % module_file_name
|
|
elif module_name is not None:
|
|
if module_name.startswith('lib'):
|
|
ret = "%s.a" % module_name
|
|
else:
|
|
ret = "lib%s.a" % module_name
|
|
|
|
return ret
|
|
|
|
def modidy_src_file(self, lines, new_src_file):
|
|
new_lines = []
|
|
|
|
src_file_begin_flag = False
|
|
added = False
|
|
found_src_file_cfg = False
|
|
for line in lines:
|
|
trim_line = line.lstrip(" ")
|
|
if re.match(MKGenerator.SRC_FILE_CFG_PATTERN, trim_line):
|
|
found_src_file_cfg = True
|
|
if not added:
|
|
new_lines.append("LOCAL_SRC_FILES := %s\n" % new_src_file)
|
|
added = True
|
|
if line.endswith("\\\n"):
|
|
src_file_begin_flag = True
|
|
elif src_file_begin_flag:
|
|
if not line.endswith("\\\n"):
|
|
src_file_begin_flag = False
|
|
else:
|
|
new_lines.append(line)
|
|
|
|
if not found_src_file_cfg:
|
|
ret_lines = []
|
|
for line in new_lines:
|
|
ret_lines.append(line)
|
|
if re.match(MKGenerator.LIB_MODULE_FILENAME_PATTERN, line):
|
|
ret_lines.append("LOCAL_SRC_FILES := %s\n" % new_src_file)
|
|
else:
|
|
ret_lines = new_lines
|
|
|
|
return ret_lines
|
|
|
|
def remove_config(self, lines, cfg_key):
|
|
new_lines = []
|
|
cfg_begin = False
|
|
line_pattern = r"^%s[ ]+[\+\:]=[ ]+.+" % cfg_key
|
|
for line in lines:
|
|
trim_line = line.lstrip(" ")
|
|
if re.match(line_pattern, trim_line):
|
|
if line.endswith("\\\n"):
|
|
cfg_begin = True
|
|
elif cfg_begin:
|
|
if not line.endswith("\\\n"):
|
|
cfg_begin = False
|
|
else:
|
|
new_lines.append(line)
|
|
|
|
return new_lines
|
|
|
|
def modify_export_c_include(self, lines):
|
|
if self.src_mk_path == self.dst_mk_path:
|
|
return lines
|
|
|
|
new_lines = []
|
|
insert_idx = -1
|
|
cur_idx = 0
|
|
include_paths = []
|
|
cfg_begin = False
|
|
for line in lines:
|
|
trim_line = line.lstrip(" ")
|
|
match = re.match(MKGenerator.EXPORT_INCLUDE_PATTERN, trim_line)
|
|
if match is not None:
|
|
if insert_idx == -1:
|
|
insert_idx = cur_idx
|
|
|
|
path_str = match.group(1)
|
|
if line.endswith("\\\n"):
|
|
cfg_begin = True
|
|
path_str = path_str.replace("\\", "")
|
|
include_paths += path_str.split()
|
|
elif cfg_begin:
|
|
path_str = trim_line
|
|
if line.endswith("\\\n"):
|
|
path_str = path_str.replace("\\\n", "")
|
|
else:
|
|
cfg_begin = False
|
|
|
|
include_paths += path_str.split()
|
|
else:
|
|
new_lines.append(line)
|
|
cur_idx += 1
|
|
|
|
src_dir = os.path.dirname(self.src_mk_path)
|
|
dst_dir = os.path.dirname(self.dst_mk_path)
|
|
rel_path = os.path.relpath(src_dir, dst_dir)
|
|
new_include_paths = []
|
|
for include_path in include_paths:
|
|
if include_path.startswith("$(LOCAL_PATH)"):
|
|
new_path = include_path.replace("$(LOCAL_PATH)", "$(LOCAL_PATH)/%s" % rel_path)
|
|
else:
|
|
new_path = "$(LOCAL_PATH)/%s/%s" % (rel_path, include_path)
|
|
new_include_paths.append(new_path)
|
|
|
|
if len(new_include_paths) > 0:
|
|
new_path_str = "LOCAL_EXPORT_C_INCLUDES := "
|
|
new_path_str += " \\\n".join(new_include_paths)
|
|
new_path_str += "\n"
|
|
if insert_idx >= 0:
|
|
new_lines.insert(insert_idx, new_path_str)
|
|
else:
|
|
new_lines.append(new_path_str)
|
|
|
|
return new_lines
|
|
|
|
def modify_include_cfg(self, lines):
|
|
new_lines = []
|
|
|
|
for line in lines:
|
|
trim_line = line.lstrip(" ")
|
|
if re.match(MKGenerator.INCLUDE_CFG_PATTERN, trim_line):
|
|
new_lines.append("include $(PREBUILT_STATIC_LIBRARY)\n")
|
|
else:
|
|
new_lines.append(line)
|
|
|
|
return new_lines
|
|
|
|
def modify_import_module(self, lines):
|
|
if self.src_mk_path == self.dst_mk_path:
|
|
return lines
|
|
|
|
new_lines = []
|
|
|
|
ignore_strs = [
|
|
"prebuilt", "cpufeatures"
|
|
]
|
|
for line in lines:
|
|
trim_line = line.lstrip(" ")
|
|
match = re.match(MKGenerator.INCLUDE_MODULE_PATTERN, trim_line)
|
|
if match is not None:
|
|
module = match.group(1)
|
|
need_modify = True
|
|
for str in ignore_strs:
|
|
if module.find(str) >= 0:
|
|
need_modify = False
|
|
break
|
|
|
|
if need_modify:
|
|
new_lines.append("$(call import-module, %s/prebuilt-mk)\n" % module)
|
|
else:
|
|
new_lines.append(line)
|
|
else:
|
|
new_lines.append(line)
|
|
|
|
return new_lines
|
|
|
|
def use_whole_lib(self, lines):
|
|
new_lines = []
|
|
for line in lines:
|
|
new_line = line.replace("LOCAL_STATIC_LIBRARIES", "LOCAL_WHOLE_STATIC_LIBRARIES")
|
|
new_lines.append(new_line)
|
|
|
|
ret_lines = []
|
|
is_first_time = True
|
|
pattern = r'LOCAL_WHOLE_STATIC_LIBRARIES[ \t]*:=.*'
|
|
for line in new_lines:
|
|
ret_line = line
|
|
if re.match(pattern, line):
|
|
if is_first_time:
|
|
is_first_time = False
|
|
else:
|
|
ret_line = line.replace(":=", "+=")
|
|
|
|
ret_lines.append(ret_line)
|
|
|
|
return ret_lines
|
|
|
|
def split_modules(self, origin_lines):
|
|
ret = []
|
|
cur_module = {}
|
|
cur_module[MKGenerator.KEY_MODULE_LINES] = []
|
|
cur_module[MKGenerator.KEY_IS_MODULE] = False
|
|
|
|
pattern_begin = r'include[ \t]+\$\(CLEAR_VARS\)'
|
|
pattern_end = r'include[ \t]+\$\(BUILD_STATIC_LIBRARY\)'
|
|
for line in origin_lines:
|
|
if re.match(pattern_begin, line):
|
|
if len(cur_module[MKGenerator.KEY_MODULE_LINES]) > 0:
|
|
ret.append(cur_module)
|
|
|
|
cur_module = {}
|
|
cur_module[MKGenerator.KEY_MODULE_LINES] = []
|
|
cur_module[MKGenerator.KEY_IS_MODULE] = True
|
|
|
|
cur_module[MKGenerator.KEY_MODULE_LINES].append(line)
|
|
|
|
if re.match(pattern_end, line):
|
|
if len(cur_module[MKGenerator.KEY_MODULE_LINES]) > 0:
|
|
ret.append(cur_module)
|
|
cur_module = {}
|
|
cur_module[MKGenerator.KEY_MODULE_LINES] = []
|
|
cur_module[MKGenerator.KEY_IS_MODULE] = False
|
|
|
|
if len(cur_module[MKGenerator.KEY_MODULE_LINES]) > 0:
|
|
ret.append(cur_module)
|
|
|
|
return ret
|
|
|
|
def handle_module(self, module_lines, relative_path):
|
|
# modify the LOCAL_SRC_FILES
|
|
lib_file_name = self.get_lib_file_name(module_lines)
|
|
if lib_file_name is None:
|
|
raise Exception("The mk file %s not specify module name." % self.src_mk_path)
|
|
relative_path = "%s/$(TARGET_ARCH_ABI)/%s" % (relative_path, lib_file_name)
|
|
dst_lines = self.modidy_src_file(module_lines, relative_path)
|
|
|
|
# remove the LOCAL_C_INCLUDES & LOCAL_LDLIBS
|
|
dst_lines = self.remove_config(dst_lines, "LOCAL_C_INCLUDES")
|
|
dst_lines = self.remove_config(dst_lines, "LOCAL_LDLIBS")
|
|
|
|
# modify the LOCAL_EXPORT_C_INCLUDES
|
|
dst_lines = self.modify_export_c_include(dst_lines)
|
|
|
|
# modify the line $(include BUILD_STATIC_LIBRARY)
|
|
dst_lines = self.modify_include_cfg(dst_lines)
|
|
|
|
# use whole libs
|
|
dst_lines = self.use_whole_lib(dst_lines)
|
|
|
|
return dst_lines
|
|
|
|
def do_generate(self):
|
|
src_mk_obj = open(self.src_mk_path)
|
|
|
|
# open the dst file
|
|
tmp_file = "%s-tmp" % self.src_mk_path
|
|
use_tmp_file = False
|
|
if self.dst_mk_path == self.src_mk_path:
|
|
use_tmp_file = True
|
|
dst_mk_obj = open(tmp_file, "w")
|
|
else:
|
|
dst_mk_obj = open(self.dst_mk_path, "w")
|
|
|
|
relative_path = os.path.relpath(self.lib_file_path, os.path.dirname(self.dst_mk_path))
|
|
|
|
# read the src file
|
|
src_lines = src_mk_obj.readlines()
|
|
|
|
modules = self.split_modules(src_lines)
|
|
dst_lines = []
|
|
for module in modules:
|
|
if module[MKGenerator.KEY_IS_MODULE]:
|
|
ret_lines = self.handle_module(module[MKGenerator.KEY_MODULE_LINES], relative_path)
|
|
else:
|
|
ret_lines = module[MKGenerator.KEY_MODULE_LINES]
|
|
|
|
for l in ret_lines:
|
|
dst_lines.append(l)
|
|
|
|
# modify the import-module
|
|
dst_lines = self.modify_import_module(dst_lines)
|
|
|
|
dst_mk_obj.writelines(dst_lines)
|
|
|
|
#close files
|
|
dst_mk_obj.close()
|
|
src_mk_obj.close()
|
|
|
|
# rename the file if temp file used
|
|
if use_tmp_file:
|
|
os.remove(self.src_mk_path)
|
|
os.rename(tmp_file, self.dst_mk_path)
|
|
|
|
if __name__ == "__main__":
|
|
parser = ArgumentParser(description="Generate prebuilt engine for Cocos Engine.")
|
|
parser.add_argument('-s', '--src-mk', dest='src_mk', help='The source Android.mk path.')
|
|
parser.add_argument('-d', "--dst-mk", dest='dst_mk', help='The output path of Android.mk. Default is beside the source mk with name \"Android-prebuilt.mk\".')
|
|
parser.add_argument('-l', "--lib-path", dest='lib_path', help='The lib file path.')
|
|
(args, unknown) = parser.parse_known_args()
|
|
|
|
gen_obj = MKGenerator(args.src_mk, args.lib_path, args.dst_mk)
|
|
gen_obj.do_generate()
|