axmol/tools/console/plugins/plugin_generate/gen_templates.py

321 lines
11 KiB
Python

#!/usr/bin/python
#-*- coding: UTF-8 -*-
import os
import sys
import json
import utils
from . import modify_template
import re
import axmol
from MultiLanguage import MultiLanguage
from axmol import CCPluginError, Logging
from argparse import ArgumentParser
class TemplateGenerator(axmol.CCPlugin):
CONFIG_FILE = "configs/gen_templates_config.json"
KEY_COPY_FROM_ENGINE = 'copy_from_engine'
KEY_COPY_FROM_BIN_TEMP = 'copy_from_bin_templates'
KEY_WIN32_CFG = 'win32_cfg'
KEY_XCODE_PROJS = 'xcode_projs'
KEY_BUILD_CFG_FILES = 'build_cfg_files'
KEY_VS_PROJS = 'vs_projs'
KEY_RM_COPY_RES = 'rm_copy_res'
KEY_REPLACE_STRING = 'replace_string'
KEY_MODIFY_CFG = 'modify_files'
@staticmethod
def plugin_name():
return "gen-templates"
@staticmethod
def brief_description():
return MultiLanguage.get_string('GEN_TEMP_BRIEF')
def parse_args(self, argv):
parser = ArgumentParser(prog="cocos %s" % self.__class__.plugin_name(),
description=self.__class__.brief_description())
(args, unknown) = parser.parse_known_args()
self.init(args)
return args
def init(self, args):
if getattr(sys, 'frozen', None):
self.cur_dir = os.path.realpath(os.path.dirname(sys.executable))
self.engine_path = os.path.join(self.cur_dir, os.pardir, os.pardir, os.pardir)
else:
self.cur_dir = os.path.realpath(os.path.dirname(__file__))
self.engine_path = os.path.join(self.cur_dir, os.pardir, os.pardir, os.pardir, os.pardir)
self.engine_path = os.path.normpath(self.engine_path)
# get path variables
self.lib_dir = os.path.join(self.engine_path, 'prebuilt')
self.engine_template_dir = os.path.join(self.engine_path, "templates")
# get the template config info
self.config_json = self.getConfigJson()
# get engine version
self.version = self.get_version_from_source()
self.fw_version = self.version.replace(' ', '-')
self._verbose = True
def generate(self):
self.clean_template()
self.copy_template()
self.gen_templates()
def clean_template(self):
utils.rmdir(os.path.join(self.engine_template_dir, "cpp-template-binary"))
utils.rmdir(os.path.join(self.engine_template_dir, "lua-template-binary"))
utils.rmdir(os.path.join(self.engine_template_dir, "js-template-binary"))
def copy_template(self):
for item in self.config_json[TemplateGenerator.KEY_COPY_FROM_ENGINE]:
axmol.copy_files_with_config(item, self.engine_path, self.engine_template_dir)
for item in self.config_json[TemplateGenerator.KEY_COPY_FROM_BIN_TEMP]:
axmol.copy_files_with_config(item, os.path.join(self.cur_dir, 'bin-templates'), self.engine_template_dir)
def getConfigJson(self):
cfg_json_path = os.path.join(self.cur_dir, TemplateGenerator.CONFIG_FILE)
f = open(cfg_json_path)
config_json = json.load(f)
f.close()
return config_json
def gen_templates(self):
dst_dir = self.engine_template_dir
x_path = self.engine_path
lib_dir = self.lib_dir
version = self.fw_version
modifier = modify_template.TemplateModifier(x_path, lib_dir, version)
# modify the VS project file of templates
for proj_file in self.config_json[TemplateGenerator.KEY_VS_PROJS]:
proj_file_path = os.path.join(self.engine_template_dir, proj_file)
modifier.modify_vs_proj(proj_file_path)
# modify the main.cpp in proj.win32
self.modify_win32_maincpp()
# modify the xcode project file of templates
for proj_file in self.config_json[TemplateGenerator.KEY_XCODE_PROJS]:
proj_file_path = os.path.join(self.engine_template_dir, proj_file)
modifier.modify_xcode_proj(proj_file_path)
# modify the build-cfg.json for templates
self.modify_build_cfg()
self.modify_version_json(os.path.join(dst_dir, "lua-template-binary/.settings/version.json"))
self.gen_template_config(dst_dir, self.version)
# modify files in config file
self.modify_files()
def modify_win32_maincpp(self):
win32_cfg = self.config_json[TemplateGenerator.KEY_WIN32_CFG]
cpp_files = win32_cfg['main_cpps']
link_libs_cfg = win32_cfg['link_libs']
check_pattern1 = r'^int[\s]+APIENTRY[\s]+_tWinMain'
check_pattern2 = r'^int[\s]+WINAPI[\s]+_tWinMain'
for main_cpp in cpp_files:
cpp_full_path = os.path.join(self.engine_template_dir, main_cpp)
if main_cpp.find('lua-template') >= 0:
link_libs = link_libs_cfg['base'] + link_libs_cfg['lua']
elif main_cpp.find('js-template') >= 0:
link_libs = link_libs_cfg['base'] + link_libs_cfg['js']
else:
link_libs = link_libs_cfg['base']
f = open(cpp_full_path)
old_lines = f.readlines()
f.close()
new_lines = []
for line in old_lines:
strip_line = line.strip()
if re.match(check_pattern1, strip_line) or re.match(check_pattern2, strip_line):
new_lines.append('#if _MSC_VER > 1800\n')
for lib in link_libs:
new_lines.append('%s\n' % self.get_lib_str(lib, 2015))
new_lines.append('#else\n')
for lib in link_libs:
new_lines.append('%s\n' % self.get_lib_str(lib, 2013))
new_lines.append('#endif\n\n')
new_lines.append(line)
else:
new_lines.append(line)
f = open(cpp_full_path, 'w')
f.writelines(new_lines)
f.close()
def get_lib_str(self, lib_name, ver):
base, ext = os.path.splitext(lib_name)
ret = '#pragma comment(lib,"%s_%d%s")' % (base, ver, ext)
return ret
def modify_file(self, file_path, pattern, replace_str):
f = open(file_path)
lines = f.readlines()
f.close()
new_lines = []
for line in lines:
new_line = re.sub(pattern, replace_str, line)
new_lines.append(new_line)
f = open(file_path, "w")
f.writelines(new_lines)
f.close()
def modify_files(self):
modify_cfg = self.config_json[TemplateGenerator.KEY_MODIFY_CFG]
for cfg in modify_cfg:
file_path = cfg["file_path"]
if not os.path.isabs(file_path):
file_path = os.path.abspath(os.path.join(self.engine_template_dir, file_path))
if not os.path.isfile(file_path):
print("%s is not a file." % file_path)
continue
pattern = cfg["pattern"]
replace_str = cfg["replace_string"]
self.modify_file(file_path, pattern, replace_str)
def modify_version_json(self, file_path):
f = open(file_path)
version_info = json.load(f)
f.close()
version_info["engineVersion"] = self.version
f = open(file_path, "w")
json.dump(version_info, f, sort_keys=True, indent=4)
f.close()
def get_version_from_source(self):
src_engine_path = self.engine_path
version_file_path = os.path.join(src_engine_path, "core/axmol.cpp")
pattern = r".*return[ \t]+\"(.*)\";"
# restore the version of engine
ver = ""
f = open(version_file_path)
for line in f.readlines():
match = re.match(pattern, line)
if match:
ver = match.group(1)
break
f.close()
if len(ver) <= 0:
raise CCPluginError(MultiLanguage.get_string('GEN_TEMP_ERROR_VER_NOT_FOUND_FMT', version_file_path),
CCPluginError.ERROR_PARSE_FILE)
return ver
def gen_template_config(self, template_path, engine_ver):
for name in os.listdir(template_path):
fullPath = os.path.join(template_path, name)
if not os.path.isdir(fullPath):
continue
if not re.match(".*-template-binary", name):
continue
cfg_path = os.path.join(fullPath, ".axproj.json")
cfg_info = {}
if os.path.exists(cfg_path):
f = open(cfg_path)
cfg_info = json.load(f)
f.close()
cfg_info["engine_version"] = engine_ver
cfg_info["engine_type"] = "prebuilt"
f = open(cfg_path, "w")
json.dump(cfg_info, f, sort_keys=True, indent=4)
f.close()
def rm_copy_res(self, file_path, keyword):
f = open(file_path)
info = json.load(f)
f.close()
changed = False
for cpy_res in info['copy_resources']:
if cpy_res['from'].find(keyword) >= 0:
info['copy_resources'].remove(cpy_res)
changed = True
break
if changed:
f = open(file_path, 'w')
json.dump(info, f, indent=4)
f.close()
def modify_project_properties(self, cfg_path):
f = open(cfg_path)
lines = f.readlines()
f.close()
new_lines = []
pattern = r'android\.library\.reference.*'
for line in lines:
temp_str = line.strip()
if not re.match(pattern, temp_str):
new_lines.append(line)
f = open(cfg_path, 'w')
f.writelines(new_lines)
f.close()
def modify_build_cfg(self):
build_cfg_files = self.config_json[TemplateGenerator.KEY_BUILD_CFG_FILES]
fw_version_path = "${COCOS_X_ROOT}/%s" % self.fw_version
for build_cfg_file in build_cfg_files:
cfg_full_path = os.path.join(self.engine_template_dir, build_cfg_file)
file_cfg_info = build_cfg_files[build_cfg_file]
if file_cfg_info.has_key(TemplateGenerator.KEY_RM_COPY_RES):
rm_copy_cfg = file_cfg_info[TemplateGenerator.KEY_RM_COPY_RES]
for keyword in rm_copy_cfg:
self.rm_copy_res(cfg_full_path, keyword)
if file_cfg_info.has_key(TemplateGenerator.KEY_REPLACE_STRING):
replace_cfg = file_cfg_info[TemplateGenerator.KEY_REPLACE_STRING]
f = open(cfg_full_path)
file_content = f.read()
f.close()
for replace_cfg_info in replace_cfg:
src_str = replace_cfg_info['src_str']
dst_str = replace_cfg_info['dst_str']
dst_str = dst_str.replace('${FW_VERSION_PATH}', fw_version_path)
file_content = file_content.replace(src_str, dst_str)
f = open(cfg_full_path, "w")
f.write(file_content)
f.close()
def run(self, argv, dependencies):
self.parse_args(argv)
self.generate()
Logging.info('')
Logging.info(MultiLanguage.get_string('GEN_TEMP_SUCCESS_FMT', self.engine_template_dir))