[cococos 2 dx---ツール編を再認識]setup.py


エンジンのソースコードを取得してsetupを実行します.pyは必要ですが、
このツールはエンジンの環境変数の構成を構成し、path変数に追加します.
設定された変数は次のとおりです.
COCOS_CONSOLE_ROOT COCOS_TEMPLATES_ROOT NDK_ROOT ANDROID_SDK_ROOT ANT_ROOT 
重中の重------プログラムの入り口を見つけます:
if __name__ == '__main__':

コードは4つの部分に分けて分析することができます
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)
" "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()の重要な部分は次の5行です.
        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
" % var) else: print(" ->%s is found : %s
" % (var, ret)) return ret

2つ目: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!
" % add_dir) else: print(" ->Add directory \"%s\" into PATH failed!
" % add_dir)

3つ目:異なるプラットフォームに基づいて、それぞれ環境変数を追加する
    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
" % (key, value)) else: print(" ->Add failed
") 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

4つ目: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!
' % remove_dir) except Exception: print(' ->Remove directory \"%s\" from PATH failed!
' % remove_dir)

5つ目:環境変数の更新
   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
' % (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("
->No files updated, add variable %s instead!" % var_name) ret = self._set_environment_variable(var_name, value) else: ret = True return ret

2つ目は、新規工事時のテンプレートのパスを設定することです.
コードは最初のステップと同じで、省略します.
3つ目はandroid関連のパスを設定し、3つは同じです.
    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