awtk/scripts/compile_config.py
2024-01-13 17:16:47 +08:00

280 lines
12 KiB
Python

import os
import io
import sys
import json
import shutil
import importlib
import collections
global COMPILE_CONFIG
COMPILE_CONFIG = None
global APP_ROOT
APP_ROOT = ''
global WIN32_RES
WIN32_RES = ''
def get_curr_config() :
global COMPILE_CONFIG
return COMPILE_CONFIG
def set_curr_config(complie_config) :
global COMPILE_CONFIG
COMPILE_CONFIG = complie_config
def set_app_win32_res(dir_path) :
global WIN32_RES
WIN32_RES = dir_path
def set_curr_app_root(app_root) :
global APP_ROOT
APP_ROOT = app_root
def get_curr_app_root() :
global APP_ROOT
return APP_ROOT
def get_curr_config_for_awtk() :
global WIN32_RES
global COMPILE_CONFIG
if COMPILE_CONFIG != None :
return COMPILE_CONFIG
else :
COMPILE_CONFIG = complie_helper()
if not COMPILE_CONFIG.load_last_complie_argv() :
print('========================= Error ================================')
print('Please Recompile AWTK !!!!!')
sys.exit('Not found last complie argv config file !!!!!')
COMPILE_CONFIG.set_value('WIN32_RES', WIN32_RES)
return COMPILE_CONFIG;
def json_obj_load_file(file_path) :
obj = None;
if os.path.exists(file_path) :
try :
with io.open(file_path, 'r', encoding='utf-8') as file :
obj = json.load(file);
except Exception as e :
print(e)
return obj;
def json_obj_save_file(obj, file_path) :
dir = os.path.dirname(file_path);
if os.path.exists(dir) :
try :
with io.open(file_path, 'w', encoding='utf-8') as file :
if sys.version_info >= (3, 0):
json.dump(obj, file, indent=4, ensure_ascii=False)
else :
file.write(json.dumps(obj, indent=4, ensure_ascii=False).decode('utf-8'))
except Exception as e :
print(e)
else :
print(dir + ' is not exists')
class complie_helper :
DEFAULT_CONFIG_FILE = './awtk_config_define.py'
LAST_COMLIP_ARGV_FILE = './bin/last_complie_argv.json'
COMPILE_CMD_INFO = collections.OrderedDict({
'help' : { 'name': 'HELP', 'help_info' : 'show all usage'},
'userdefine' : { 'name' : 'DEFINE_FILE', 'help_info' : 'set user config define file, DEFINE_FILE=XXXXX'},
'save_file' : { 'name' : 'EXPORT_DEFINE_FILE', 'help_info' : 'current config define export to file, EXPORT_DEFINE_FILE=./awtk_config_define.py'},
})
config = collections.OrderedDict({
'OUTPUT_DIR' : { 'value' : None, 'type' : str.__name__, 'desc' : ['compiled export directory '], 'help_info' : 'set awtk compiled export directory, default value is \'\', \'\' is system\'s value'},
'TOOLS_NAME' : { 'value' : None, 'type' : str.__name__, 'str_enum' : ['mingw'], 'desc' : ['value is \'mingw\' or None'], 'help_info' : 'set awtk compile\'s name, default value is None, None is system\'s value'},
'INPUT_ENGINE' : { 'value' : None, 'type' : str.__name__, 'str_enum' : ['null', 'spinyin', 't9', 't9ext', 'pinyin'], 'desc' : ['value is null/spinyin/t9/t9ext/pinyin'], 'help_info' : 'set awtk use input engine, default value is None, None is system\'s value' },
'VGCANVAS' : { 'value' : None, 'type' : str.__name__, 'str_enum' : ['NANOVG', 'NANOVG_PLUS', 'CAIRO'], 'desc' : ['value is NANOVG/NANOVG_PLUS/CAIRO'], 'help_info' : 'set awtk use render vgcanvas type, default value is None, None is system\'s value' },
'NANOVG_BACKEND' : { 'value' : None, 'type' : str.__name__, 'str_enum' : ['GLES2', 'GLES3', 'GL3', 'AGG', 'AGGE'], 'desc' : ['if NANOVG_BACKEND is valid, VGCANVAS must be NANOVG or \'\'', 'if VGCANVAS is NANOVG_PLUS, NANOVG_BACKEND must be GLES2/GLES3/GL3 or None', 'NANOVG_BACKEND is GLES2/GLES3/GL3/AGG/AGGE'], 'help_info' : 'set awtk\'s nanovg use render model, default value is None, None is system\'s value'},
'LCD_COLOR_FORMAT' : { 'value' : None, 'type' : str.__name__, 'str_enum' : ['bgr565', 'bgra8888', 'mono'], 'desc' : ['if NANOVG_BACKEND is GLES2/GLES3/GL3, LCD_COLOR_FORMAT must be bgra8888 or \'\'', 'if NANOVG_BACKEND is AGG/AGGE, LCD_COLOR_FORMAT must be bgr565/bgra8888/mono or None', 'NANOVG_BACKEND is bgr565/bgra8888/mono'], 'help_info' : 'set awtk\'s lcd color format, default value is None, None is system\'s value'},
'DEBUG' : { 'value' : True, 'type' : bool.__name__, 'desc' : ['awtk\'s compile is debug'], 'help_info' : 'awtk\'s compile is debug, value is true or false, default value is true' },
'PDB' : { 'value' : True, 'type' : bool.__name__, 'desc' : ['export pdb file'], 'help_info' : 'export pdb file, value is true or false' },
'SDL_UBUNTU_USE_IME' : { 'value' : False, 'type' : bool.__name__, 'desc' : ['ubuntu use chinese input engine'], 'help_info' : 'ubuntu use ime, this sopt is ubuntu use chinese input engine, value is true or false, default value is false' },
'NATIVE_WINDOW_BORDERLESS' : { 'value' : False, 'type' : bool.__name__, 'desc' : ['pc desktop program no borerless'], 'help_info' : 'pc desktop program no borerless, value is true or false, default value is false' },
'NATIVE_WINDOW_NOT_RESIZABLE' : { 'value' : False, 'type' : bool.__name__, 'desc' : ['pc desktop program do not resize program'], 'help_info' : 'pc desktop program do not resize program\'s size, value is true or false, default value is false' },
'BUILD_TESTS' : { 'value' : True, 'type' : bool.__name__, 'desc' : ['build awtk\'s gtest demo'], 'help_info' : 'build awtk\'s gtest demo, value is true or false, default value is true' },
'BUILD_DEMOS' : { 'value' : True, 'type' : bool.__name__, 'desc' : ['build awtk\'s demo examples'], 'help_info' : 'build awtk\'s demo examples, value is true or false, default value is true' },
'BUILD_TOOLS' : { 'value' : True, 'type' : bool.__name__, 'desc' : ['build awtk\'s tools'], 'help_info' : 'build awtk\'s tools, value is true or false, default value is true' },
'WIN32_RES' : { 'value' : None, 'type' : str.__name__, 'save_file' : False, 'desc' : ['app\'s win32 res path'], 'help_info' : 'app\'s win32 res path, WIN32_RES=XXXXX, value\'s default=\'awtk/win32_res/awtk.res\' ' },
})
def try_load_default_config(self) :
if os.path.exists(self.DEFAULT_CONFIG_FILE) :
self.load_config(self.DEFAULT_CONFIG_FILE)
def set_compile_config(self, config) :
self.config = config
def load_config_by_sopt(self, ARGUMENTS) :
for key in ARGUMENTS :
if key.upper() == self.COMPILE_CMD_INFO['userdefine']['name'] :
file = ARGUMENTS[key]
if os.path.exists(file) :
self.load_config(file)
break;
else :
sys.exit('userdefine sopt is not found :' + file)
def check_config_legality(self) :
for key in self.config :
check = False
if not 'str_enum' in self.config[key] :
continue
if self.config[key]['value'] != '' and self.config[key]['value'] != None:
for str_enum in self.config[key]['str_enum'] :
if str_enum == self.config[key]['value'] :
check = True
break
if not check :
if self.config[key]['value'] == None:
sys.exit(key + ' \'s value is None, is not legality !')
else :
sys.exit(key + ' \'s value is ' + self.config[key]['value'] + ', is not legality !')
def scons_user_sopt(self, ARGUMENTS) :
EXPORT_USERDEFINE_FILE = None
def find_compile_cmd_info_by_name(name) :
for key in self.COMPILE_CMD_INFO :
if name == self.COMPILE_CMD_INFO[key]['name']:
return True
return False
for arg in sys.argv :
key = arg.upper()
if key == self.COMPILE_CMD_INFO['help']['name'] :
self.show_usage()
sys.exit()
self.load_config_by_sopt(ARGUMENTS)
for key in ARGUMENTS :
userdefine_key = key.upper()
if self.has_key(userdefine_key) :
value = ARGUMENTS[key]
self.set_value(userdefine_key, value)
elif not find_compile_cmd_info_by_name(userdefine_key):
print('awtk\'s default compiler list does not support {0} , so skip {0} !!!!!!'.format(key))
elif key.upper() == self.COMPILE_CMD_INFO['save_file']['name'] :
EXPORT_USERDEFINE_FILE = ARGUMENTS[key]
if EXPORT_USERDEFINE_FILE != None :
self.save_config(EXPORT_USERDEFINE_FILE)
sys.exit()
self.check_config_legality()
def show_usage(self) :
print('=========================================================')
for key in self.config :
print((key + ' : ').ljust(32) + self.config[key]['help_info'])
for desc in self.config[key]['desc'] :
print(''.ljust(32) + desc)
for key in self.COMPILE_CMD_INFO :
print((self.COMPILE_CMD_INFO[key]['name'] + ' : ').ljust(32) + self.COMPILE_CMD_INFO[key]['help_info'])
print('=========================================================')
def write_file(self, filename, s):
if sys.version_info >= (3, 0):
with open(filename, 'w', encoding='utf8') as f:
f.write(s)
else:
with open(filename, 'w') as f:
s = s.encode('utf8')
f.write(s)
def save_config(self, file) :
dir = os.path.dirname(file);
if os.path.exists(dir) :
save_data = ''
save_data += '# user set default configuration item \n'
save_data += '# if value is None, so value is default value \n'
save_data += '\n'
for key in self.config :
if 'save_file' in self.config[key] and not self.config[key]['save_file'] :
continue
for desc in self.config[key]['desc'] :
save_data += ('# ' + desc)
save_data += '\n'
if isinstance(self.config[key]['value'], str) :
save_data += (key + ' = r\'' + self.config[key]['value'] + '\'')
else :
save_data += (key + ' = ' + str(self.config[key]['value']))
save_data += '\n\n'
try :
self.write_file(file, save_data)
except Exception as e :
print(e)
else :
print(dir + ' is not exists')
def load_config(self, file) :
file = os.path.abspath(file)
if os.path.exists(file) :
script_dir = os.path.dirname(file)
file_name = os.path.basename(file)
module_name, ext = os.path.splitext(file_name)
sys.path.insert(0, script_dir)
config_script = importlib.import_module(module_name)
sys.path.remove(script_dir)
for key in self.config :
if hasattr(config_script, key) :
if not 'save_file' in self.config[key] or self.config[key]['save_file'] :
self.config[key]['value'] = getattr(config_script, key)
else :
sys.exit(file + ' is not found')
def has_key(self, name) :
return name in self.config
def get_value(self, name, default_value = None) :
return self.get_unique_value(name, default_value)
def get_unique_value(self, name, default_value) :
if name in self.config and self.config[name]['value'] != None :
return self.config[name]['value']
return default_value
def set_value(self, name, value) :
if name in self.config :
if isinstance(self.config[name]['value'], bool) and isinstance(value, bool):
self.config[name]['value'] = value
elif (isinstance(self.config[name]['value'], bool) and isinstance(value, str)) or ('type' in self.config[name] and self.config[name]['type'] == bool.__name__ and isinstance(value, str)):
try :
from utils import strtobool
self.config[name]['value'] = strtobool(value) == 1
except :
self.config[name]['value'] = value.lower() == 'true'
elif isinstance(self.config[name]['value'], list) and isinstance(value, str) :
self.config[name]['value'] = value.split(',')
elif self.config[name]['value'] == None and (not 'type' in self.config[name]):
self.config[name]['value'] = value
else:
self.config[name]['value'] = value
def save_last_complie_argv(self) :
json_obj_save_file(self.config, self.LAST_COMLIP_ARGV_FILE);
def load_last_complie_argv(self) :
if os.path.exists(self.LAST_COMLIP_ARGV_FILE) :
obj = json_obj_load_file(self.LAST_COMLIP_ARGV_FILE);
if obj != None :
self.config = collections.OrderedDict(obj);
return True
return False
def output_compile_data(self, awtk_root) :
output_dir = self.config['OUTPUT_DIR']['value']
if output_dir != '' and output_dir != None :
if os.path.exists(output_dir) :
shutil.rmtree(output_dir)
os.makedirs(output_dir)
shutil.copytree(awtk_root + '/bin', output_dir + '/bin')
shutil.copytree(awtk_root + '/lib', output_dir + '/lib')