[重新认识cocos2dx---工具篇] 一 setup.py
2015-11-02 18:07
351 查看
拿到引擎源码后运行setup.py很必要,
该工具配置了引擎的环境变量的配置,并把他们添加到了path变量中
设置的变量包括:
COCOS_CONSOLE_ROOT
COCOS_TEMPLATES_ROOT
NDK_ROOT
ANDROID_SDK_ROOT
ANT_ROOT
重中之重------找到程序的入口:
代码可分为四部分来分析
1. 准备阶段-----判断版本
以Python 2.7.3为例,sys.version_info含有版本号信息如下,
2. 命令行参数设置
3. 主体部分 ---设置系统参数
函数set_environment_variables()中的关键部分是一下五行
第一步来看设置cocos命令的路径
第一个 获取环境变量的值。函数中对注册表的操作是该工具的核心步骤,辅助os.environ是在该工具中常见的搭配
第四个:删除Path中的变量,对字符串的操作还是值得注意的
第二步来看设置新建工程时模板的路径
代码与第一步类同,略去
第三步来看设置android相关的路径,三者雷同
小结:这一部分的结构很清晰,封装的函数恰到好处,类SetEnvVar 封装了大部分的操作
4. 结束部分
通知所有的顶层窗口,应用程序改变了系统参数
总结: python的相关用法:(没办法了太长了,只能另开了)
[python 补充] optparser
os.path
该工具配置了引擎的环境变量的配置,并把他们添加到了path变量中
设置的变量包括:
COCOS_CONSOLE_ROOT
COCOS_TEMPLATES_ROOT
NDK_ROOT
ANDROID_SDK_ROOT
ANT_ROOT
重中之重------找到程序的入口:
if __name__ == '__main__':
代码可分为四部分来分析
1. 准备阶段-----判断版本
if not _check_python_version(): exit() /**************************/ def _check_python_version(): major_ver = sys.version_info[0] if major_ver > 2: print ("The python version is %d.%d. But python 2.x is required. (Version 2.7 is well tested)\n" "Download it here: https://www.python.org/" % (major_ver, sys.version_info[1])) return False return True调用自定义的_check_python_version函数判断python的版本号,不是python 2.X的话退出,由于python 2.X 和python 3.X代码不兼容,判断版本号还是必须的
以Python 2.7.3为例,sys.version_info含有版本号信息如下,
>>> sys.version_info sys.version_info(major=2, minor=7, micro=3, releaselevel='final', serial=0)
2. 命令行参数设置
parser = OptionParser() parser.add_option( '-n', '--ndkroot', dest='ndk_root', help='directory of ndk root') parser.add_option('-a', '--androidsdkroot', dest='android_sdk_root', help='directory of android sdk root') parser.add_option( '-t', '--antroot', dest='ant_root', help='directory that contains ant/ant.bat') opts, args = parser.parse_args()
3. 主体部分 ---设置系统参数
env = SetEnvVar() env.set_environment_variables( opts.ndk_root, opts.android_sdk_root, opts.ant_root)
函数set_environment_variables()中的关键部分是一下五行
self.set_console_root() self.set_templates_root() ndk_ret = self.set_variable(NDK_ROOT, ndk_root) sdk_ret = self.set_variable(ANDROID_SDK_ROOT, android_sdk_root) ant_ret = self.set_variable(ANT_ROOT, ant_root)
第一步来看设置cocos命令的路径
def set_console_root(self): print("->Check environment variable %s" % COCOS_CONSOLE_ROOT) # 获取最新的路径 cocos_consle_root = os.path.join( self.current_absolute_path, 'tools', 'cocos2d-console', 'bin') # 获取已经设置的路径 old_dir = self._find_environment_variable(COCOS_CONSOLE_ROOT) if old_dir is None: # 首次设置时步骤 if self._isWindows(): self.set_windows_path(cocos_consle_root) self._set_environment_variable( COCOS_CONSOLE_ROOT, cocos_consle_root) else: if old_dir == cocos_consle_root: # is same with before, nothing to do return # 更新最新的环境变量 if self._isWindows(): self.remove_dir_from_win_path(old_dir) self.set_windows_path(cocos_consle_root) self._force_update_env(COCOS_CONSOLE_ROOT, cocos_consle_root)有几个重要的自定义函数
第一个 获取环境变量的值。函数中对注册表的操作是该工具的核心步骤,辅助os.environ是在该工具中常见的搭配
def _find_environment_variable(self, var): ''' 获取环境变量var的值,未找到返回None ''' print(" ->Search for environment variable %s..." % var) ret = None try: # os.environ 是一个字符串所对应环境的映像对象 # 当访问不存在的字段时python会抛异常 ret = os.environ[var] except Exception: if not self._isWindows(): file_list = self._get_unix_file_list() if file_list is not None: home = os.path.expanduser('~') for name in file_list: path = os.path.join(home, name) ret = self._search_unix_variable(var, path) if ret is not None: break else: ''' _winreg 修改windows注册表 _winreg.OpenKeyEx() 读取,打开特定的key _winreg.QueryValueEx() _winreg.CloseKey() ''' import _winreg try: env = None # 打开一个键 env = _winreg.OpenKeyEx(_winreg.HKEY_CURRENT_USER, 'Environment', 0, _winreg.KEY_READ) #注册表中检索一个键的路径 ret = _winreg.QueryValueEx(env, var)[0] _winreg.CloseKey(env) except Exception: if env: _winreg.CloseKey(env) ret = None if ret is None: print(" ->%s not found\n" % var) else: print(" ->%s is found : %s\n" % (var, ret)) return ret第二个: 添加变量到Path变量中
def set_windows_path(self, add_dir): ''' 将add_dir加到Path变量中 ''' ret = False import _winreg try: env = None path = None env = _winreg.OpenKeyEx(_winreg.HKEY_CURRENT_USER, 'Environment', 0, _winreg.KEY_SET_VALUE | _winreg.KEY_READ) path = _winreg.QueryValueEx(env, 'Path')[0] # add variable if can't find it in PATH # _winreg.SetValueEx() 设置一个值 # _winreg.FlushKey() 回写所有的键属性改变到注册表 path_lower = path.lower() add_dir_lower = add_dir.lower() if (path_lower.find(add_dir_lower) == -1): path = add_dir + ';' + path _winreg.SetValueEx(env, 'Path', 0, _winreg.REG_SZ, path) _winreg.FlushKey(env) _winreg.CloseKey(env) ret = True except Exception: if not path: path = add_dir _winreg.SetValueEx(env, 'Path', 0, _winreg.REG_SZ, path) _winreg.FlushKey(env) ret = True else: _winreg.SetValueEx(env, 'Path', 0, _winreg.REG_SZ, path) _winreg.FlushKey(env) ret = False if env: _winreg.CloseKey(env) if ret: print(" ->Add directory \"%s\" into PATH succeed!\n" % add_dir) else: print(" ->Add directory \"%s\" into PATH failed!\n" % add_dir)第三个: 根据不同的平台,分别添加环境变量
def _set_environment_variable(self, key, value): ''' 将key,value添加到环境变量中 ''' print(" -> Add %s environment variable..." % key) ret = False if self._isWindows(): ret = self._set_environment_variable_win32(key, value) else: ret = self._set_environment_variable_unix(key, value) if ret: print(" ->Added %s=%s\n" % (key, value)) else: print(" ->Add failed\n") return ret # modify registry table to add an environment variable on windows def _set_environment_variable_win32(self, key, value): ''' 在win32平台添加key,value的环境变量 ''' ret = False import _winreg try: env = None env = _winreg.OpenKeyEx(_winreg.HKEY_CURRENT_USER, 'Environment', 0, _winreg.KEY_SET_VALUE | _winreg.KEY_READ) _winreg.SetValueEx(env, key, 0, _winreg.REG_SZ, value) _winreg.FlushKey(env) _winreg.CloseKey(env) ret = True except Exception: if env: _winreg.CloseKey(env) ret = False return ret
第四个:删除Path中的变量,对字符串的操作还是值得注意的
def remove_dir_from_win_path(self, remove_dir): ''' 删除Path中的remove_dir ''' import _winreg try: env = None path = None env = _winreg.OpenKeyEx(_winreg.HKEY_CURRENT_USER, 'Environment', 0, _winreg.KEY_SET_VALUE | _winreg.KEY_READ) path = _winreg.QueryValueEx(env, 'Path')[0] path_lower = path.lower() remove_dir = remove_dir.replace('/', '\\') remove_dir_lower = remove_dir.lower() start_pos = path_lower.find(remove_dir_lower) if (start_pos >= 0): length = len(remove_dir_lower) need_remove = path[start_pos:(start_pos + length)] path = path.replace(need_remove, '') path = path.replace(';;', ';') _winreg.SetValueEx(env, 'Path', 0, _winreg.REG_SZ, path) _winreg.FlushKey(env) _winreg.CloseKey(env) print(' ->Remove directory \"%s\" from PATH!\n' % remove_dir) except Exception: print(' ->Remove directory \"%s\" from PATH failed!\n' % remove_dir)第五个: 更新环境变量
def _force_update_env(self, var_name, value): ret = False if self._isWindows(): print(" ->Force update environment variable %s" % var_name) ret = self._set_environment_variable_win32(var_name, value) if not ret: print(" ->Failed!") else: print(" ->Succeed : %s=%s" % (var_name, value)) else: ret = self._force_update_unix_env(var_name, value) return ret def _force_update_unix_env(self, var_name, value): ''' 有待分析 ''' import re home = os.path.expanduser('~') str_re = SetEnvVar.RE_FORMAT % var_name patten = re.compile(str_re) replace_str = 'export %s=%s\n' % (var_name, value) file_list = SetEnvVar.MAC_CHECK_FILES if self._isLinux(): file_list = SetEnvVar.LINUX_CHECK_FILES print(" ->Update variable %s in files %s" % (var_name, str(file_list))) variable_updated = False for file_name in file_list: path = os.path.join(home, file_name) if os.path.isfile(path): lines = [] # read files need_over_write = False file_obj = open(path, 'r') for line in file_obj: str_temp = line.lstrip(' \t') match = patten.match(str_temp) if match is not None: variable_updated = True need_over_write = True lines.append(replace_str) else: lines.append(line) file_obj.close() # rewrite file if need_over_write: file_obj = open(path, 'w') file_obj.writelines(lines) file_obj.close() print(" ->File %s updated!" % path) # nothing updated, should add variable if not variable_updated: print("\n ->No files updated, add variable %s instead!" % var_name) ret = self._set_environment_variable(var_name, value) else: ret = True return ret
第二步来看设置新建工程时模板的路径
代码与第一步类同,略去
第三步来看设置android相关的路径,三者雷同
def set_variable(self, var_name, value): ''' 在环境变量中添加或是更新var_name, value ''' print("->Check environment variable %s" % var_name) find_value = self._find_environment_variable(var_name) var_found = (find_value is not None) action_none = 0 action_add = 1 action_update = 2 # 根据不同情况得出操作类型:不做,添加,更新 need_action = action_none if var_found: if value and self._check_valid(var_name, value): # should update need_action = action_update else: # do nothing need_action = action_none else: if not value: # find the command path in system value = self._find_value_from_sys(var_name) if not value: value = self._get_input_value(var_name) if value and self._check_valid(var_name, value): # should add variable need_action = action_add else: # do nothing need_action = action_none # 开始操作 if need_action == action_none: # do nothing return SetEnvVar.RESULT_DO_NOTHING elif need_action == action_add: # add variable if self._set_environment_variable(var_name, value): return SetEnvVar.RESULT_ADDED else: return SetEnvVar.RESULT_ADD_FAILED elif need_action == action_update: # update variable if self._force_update_env(var_name, value): # update succeed return SetEnvVar.RESULT_UPDATED else: # update failed return SetEnvVar.RESULT_UPDATE_FAILED else: return SetEnvVar.RESULT_DO_NOTHING
小结:这一部分的结构很清晰,封装的函数恰到好处,类SetEnvVar 封装了大部分的操作
4. 结束部分
通知所有的顶层窗口,应用程序改变了系统参数
if env._isWindows(): import ctypes HWND_BROADCAST = 0xFFFF WM_SETTINGCHANGE = 0x1A SMTO_ABORTIFHUNG = 0x0002 result = ctypes.c_long() SendMessageTimeoutW = ctypes.windll.user32.SendMessageTimeoutW SendMessageTimeoutW(HWND_BROADCAST, WM_SETTINGCHANGE, 0, u'Environment', SMTO_ABORTIFHUNG, 5000, ctypes.byref(result))
总结: python的相关用法:(没办法了太长了,只能另开了)
[python 补充] optparser
os.path
相关文章推荐
- cocos2d-x改底层之动态改变UIListView中的某项在链表中的位置
- cocosjs显示跨域图片的办法
- cocos2d-x改底层之获取UIListView的实际内容大小
- 【Cocos2d-x】脚本生成资源头文件
- cocos2d-x Programmers Guide v3.3 译本和阅读笔记(1-2章)
- [cocos2dx]Android编译的一些注意事项
- Cocos2d-x多场景切换生命周期
- Touch Handling in Cocos2D 3.x(七)
- Touch Handling in Cocos2D 3.x(七)
- Touch Handling in Cocos2D 3.x(七)
- Cocos2d-x场景生命周期函数介绍
- Touch Handling in Cocos2D 3.x(六)
- Touch Handling in Cocos2D 3.x(六)
- Touch Handling in Cocos2D 3.x(六)
- Touch Handling in Cocos2D 3.x(五)
- Touch Handling in Cocos2D 3.x(五)
- Touch Handling in Cocos2D 3.x(五)
- Touch Handling in Cocos2D 3.x(四)
- Touch Handling in Cocos2D 3.x(四)
- Touch Handling in Cocos2D 3.x(四)