genbindings-lua.py 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. #!/usr/bin/python
  2. # This script is used to generate luabinding glue codes.
  3. # Android ndk version must be ndk-r9b.
  4. import sys
  5. import os, os.path
  6. import shutil
  7. import ConfigParser
  8. import subprocess
  9. import re
  10. from contextlib import contextmanager
  11. import shutil
  12. import yaml
  13. import tempfile
  14. def _check_ndk_root_env():
  15. ''' Checking the environment NDK_ROOT, which will be used for building
  16. '''
  17. try:
  18. NDK_ROOT = os.environ['NDK_ROOT']
  19. except Exception:
  20. print "NDK_ROOT not defined. Please define NDK_ROOT in your environment."
  21. sys.exit(1)
  22. return NDK_ROOT
  23. def _check_python_bin_env():
  24. ''' Checking the environment PYTHON_BIN, which will be used for building
  25. '''
  26. try:
  27. PYTHON_BIN = os.environ['PYTHON_BIN']
  28. except Exception:
  29. print "PYTHON_BIN not defined, use current python."
  30. PYTHON_BIN = sys.executable
  31. return PYTHON_BIN
  32. class CmdError(Exception):
  33. pass
  34. @contextmanager
  35. def _pushd(newDir):
  36. previousDir = os.getcwd()
  37. os.chdir(newDir)
  38. yield
  39. os.chdir(previousDir)
  40. def _run_cmd(command):
  41. ret = subprocess.call(command, shell=True)
  42. if ret != 0:
  43. message = "Error running command"
  44. raise CmdError(message)
  45. def _edit_yaml(filePath):
  46. f = open(filePath, 'r')
  47. data = yaml.load(f)
  48. f.close()
  49. data['conversions']['ns_map']['cocos2d::plugin::'] = 'plugin.'
  50. data['conversions']['to_native']['TIAPDeveloperInfo'] = 'ok &= pluginx::luaval_to_TIAPDeveloperInfo(tolua_S, ${arg_idx}, &${out_value})'
  51. data['conversions']['to_native']['TAdsDeveloperInfo'] = 'ok &= pluginx::luaval_to_TAdsDeveloperInfo(tolua_S, ${arg_idx}, &${out_value})'
  52. data['conversions']['to_native']['TAdsInfo'] = 'ok &= pluginx::luaval_to_TAdsInfo(tolua_S, ${arg_idx}, &${out_value})'
  53. data['conversions']['to_native']['TShareDeveloperInfo'] = 'ok &= pluginx::luaval_to_TShareDeveloperInfo(tolua_S, ${arg_idx}, &${out_value})'
  54. data['conversions']['to_native']['TSocialDeveloperInfo'] = 'ok &= pluginx::luaval_to_TSocialDeveloperInfo(tolua_S, ${arg_idx}, &${out_value})'
  55. data['conversions']['to_native']['TUserDeveloperInfo'] = 'ok &= pluginx::luaval_to_TUserDeveloperInfo(tolua_S, ${arg_idx}, &${out_value})'
  56. f = open(filePath, 'w')
  57. f.write(yaml.dump(data))
  58. f.close()
  59. def main():
  60. cur_platform= '??'
  61. llvm_path = '??'
  62. ndk_root = _check_ndk_root_env()
  63. # del the " in the path
  64. ndk_root = re.sub(r"\"", "", ndk_root)
  65. python_bin = _check_python_bin_env()
  66. platform = sys.platform
  67. if platform == 'win32':
  68. cur_platform = 'windows'
  69. elif platform == 'darwin':
  70. cur_platform = platform
  71. elif 'linux' in platform:
  72. cur_platform = 'linux'
  73. else:
  74. print 'Your platform is not supported!'
  75. sys.exit(1)
  76. if platform == 'win32':
  77. x86_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.3/prebuilt', '%s' % cur_platform))
  78. if not os.path.exists(x86_llvm_path):
  79. x86_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.4/prebuilt', '%s' % cur_platform))
  80. else:
  81. x86_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.3/prebuilt', '%s-%s' % (cur_platform, 'x86')))
  82. if not os.path.exists(x86_llvm_path):
  83. x86_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.4/prebuilt', '%s-%s' % (cur_platform, 'x86')))
  84. x64_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.3/prebuilt', '%s-%s' % (cur_platform, 'x86_64')))
  85. if not os.path.exists(x64_llvm_path):
  86. x64_llvm_path = os.path.abspath(os.path.join(ndk_root, 'toolchains/llvm-3.4/prebuilt', '%s-%s' % (cur_platform, 'x86_64')))
  87. if os.path.isdir(x86_llvm_path):
  88. llvm_path = x86_llvm_path
  89. elif os.path.isdir(x64_llvm_path):
  90. llvm_path = x64_llvm_path
  91. else:
  92. print 'llvm toolchain not found!'
  93. print 'path: %s or path: %s are not valid! ' % (x86_llvm_path, x64_llvm_path)
  94. sys.exit(1)
  95. project_root = os.path.abspath(os.path.join(os.path.dirname(__file__), '..', '..', '..'))
  96. cocos_root = os.path.abspath(os.path.join(project_root, ''))
  97. cxx_generator_root = os.path.abspath(os.path.join(project_root, 'tools/bindings-generator'))
  98. pluginx_root = os.path.abspath(os.path.join(project_root, 'plugin'))
  99. # save config to file
  100. config = ConfigParser.ConfigParser()
  101. config.set('DEFAULT', 'androidndkdir', ndk_root)
  102. config.set('DEFAULT', 'clangllvmdir', llvm_path)
  103. config.set('DEFAULT', 'cocosdir', cocos_root)
  104. config.set('DEFAULT', 'cxxgeneratordir', cxx_generator_root)
  105. config.set('DEFAULT', 'extra_flags', '')
  106. config.set('DEFAULT', 'pluginxdir', pluginx_root)
  107. # To fix parse error on windows, we must difine __WCHAR_MAX__ and undefine __MINGW32__ .
  108. if platform == 'win32':
  109. config.set('DEFAULT', 'extra_flags', '-D__WCHAR_MAX__=0x7fffffff -U__MINGW32__')
  110. conf_ini_file = os.path.abspath(os.path.join(os.path.dirname(__file__), 'userconf.ini'))
  111. print 'generating userconf.ini...'
  112. with open(conf_ini_file, 'w') as configfile:
  113. config.write(configfile)
  114. # set proper environment variables
  115. if 'linux' in platform or platform == 'darwin':
  116. os.putenv('LD_LIBRARY_PATH', '%s/libclang' % cxx_generator_root)
  117. if platform == 'win32':
  118. path_env = os.environ['PATH']
  119. os.putenv('PATH', r'%s;%s\libclang;%s\tools\win32;' % (path_env, cxx_generator_root, cxx_generator_root))
  120. # edit conversions config for pluginx
  121. conversions_yaml = '%s/targets/lua/conversions.yaml' % cxx_generator_root
  122. conversions_backup = '%s.backup' % conversions_yaml
  123. shutil.copy(conversions_yaml, conversions_backup)
  124. _edit_yaml(conversions_yaml)
  125. try:
  126. tolua_root = '%s/plugin/tools/pluginx-bindings-generator/tolua' % project_root
  127. output_dir = '%s/plugin/luabindings/auto' % project_root
  128. cmd_args = {'cocos2dx_pluginx.ini' : ('cocos2dx_pluginx', 'lua_cocos2dx_pluginx_auto')}
  129. target = 'lua'
  130. generator_py = '%s/generator.py' % cxx_generator_root
  131. for key in cmd_args.keys():
  132. args = cmd_args[key]
  133. cfg = '%s/%s' % (tolua_root, key)
  134. print 'Generating bindings for %s...' % (key[:-4])
  135. command = '%s %s %s -s %s -t %s -o %s -n %s' % (python_bin, generator_py, cfg, args[0], target, output_dir, args[1])
  136. _run_cmd(command)
  137. if platform == 'win32':
  138. with _pushd(output_dir):
  139. _run_cmd('dos2unix *')
  140. # replace header file
  141. tmpfd,tmpname = tempfile.mkstemp(dir='.')
  142. input_file_name = '%s/%s.cpp' % (output_dir, args[1])
  143. try:
  144. output_file = os.fdopen(tmpfd, 'w')
  145. input_file = open(input_file_name)
  146. for line in input_file:
  147. output_file.write(line.replace('#include "LuaBasicConversions.h"', '#include "LuaBasicConversions.h"\n#include "lua_pluginx_basic_conversions.h"'))
  148. finally:
  149. output_file.close()
  150. input_file.close()
  151. shutil.move(tmpname, input_file_name)
  152. print '---------------------------------'
  153. print 'Generating lua bindings succeeds.'
  154. print '---------------------------------'
  155. except Exception as e:
  156. if e.__class__.__name__ == 'CmdError':
  157. print '---------------------------------'
  158. print 'Generating lua bindings fails.'
  159. print '---------------------------------'
  160. sys.exit(1)
  161. else:
  162. raise
  163. finally:
  164. shutil.move(conversions_backup, conversions_yaml)
  165. # -------------- main --------------
  166. if __name__ == '__main__':
  167. main()