methods.py 27 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675
  1. import os
  2. import os.path
  3. import sys
  4. import re
  5. import glob
  6. import string
  7. import datetime
  8. import subprocess
  9. from compat import iteritems, isbasestring, decode_utf8
  10. def add_source_files(self, sources, filetype, lib_env=None, shared=False):
  11. if isbasestring(filetype):
  12. dir_path = self.Dir('.').abspath
  13. filetype = sorted(glob.glob(dir_path + "/" + filetype))
  14. for path in filetype:
  15. sources.append(self.Object(path))
  16. def disable_warnings(self):
  17. # 'self' is the environment
  18. if self.msvc:
  19. # We have to remove existing warning level defines before appending /w,
  20. # otherwise we get: "warning D9025 : overriding '/W3' with '/w'"
  21. warn_flags = ['/Wall', '/W4', '/W3', '/W2', '/W1', '/WX']
  22. self['CCFLAGS'] = [x for x in self['CCFLAGS'] if not x in warn_flags]
  23. self.Append(CCFLAGS=['/w'])
  24. else:
  25. self.Append(CCFLAGS=['-w'])
  26. def add_module_version_string(self,s):
  27. self.module_version_string += "." + s
  28. def update_version(module_version_string=""):
  29. build_name = "custom_build"
  30. if os.getenv("BUILD_NAME") != None:
  31. build_name = os.getenv("BUILD_NAME")
  32. print("Using custom build name: " + build_name)
  33. import version
  34. # NOTE: It is safe to generate this file here, since this is still executed serially
  35. f = open("core/version_generated.gen.h", "w")
  36. f.write("#define VERSION_SHORT_NAME \"" + str(version.short_name) + "\"\n")
  37. f.write("#define VERSION_NAME \"" + str(version.name) + "\"\n")
  38. f.write("#define VERSION_MAJOR " + str(version.major) + "\n")
  39. f.write("#define VERSION_MINOR " + str(version.minor) + "\n")
  40. if hasattr(version, 'patch'):
  41. f.write("#define VERSION_PATCH " + str(version.patch) + "\n")
  42. f.write("#define VERSION_STATUS \"" + str(version.status) + "\"\n")
  43. f.write("#define VERSION_BUILD \"" + str(build_name) + "\"\n")
  44. f.write("#define VERSION_MODULE_CONFIG \"" + str(version.module_config) + module_version_string + "\"\n")
  45. f.write("#define VERSION_YEAR " + str(version.year) + "\n")
  46. f.close()
  47. # NOTE: It is safe to generate this file here, since this is still executed serially
  48. fhash = open("core/version_hash.gen.h", "w")
  49. githash = ""
  50. gitfolder = ".git"
  51. if os.path.isfile(".git"):
  52. module_folder = open(".git", "r").readline().strip()
  53. if module_folder.startswith("gitdir: "):
  54. gitfolder = module_folder[8:]
  55. if os.path.isfile(os.path.join(gitfolder, "HEAD")):
  56. head = open(os.path.join(gitfolder, "HEAD"), "r").readline().strip()
  57. if head.startswith("ref: "):
  58. head = os.path.join(gitfolder, head[5:])
  59. if os.path.isfile(head):
  60. githash = open(head, "r").readline().strip()
  61. else:
  62. githash = head
  63. fhash.write("#define VERSION_HASH \"" + githash + "\"")
  64. fhash.close()
  65. def parse_cg_file(fname, uniforms, sizes, conditionals):
  66. fs = open(fname, "r")
  67. line = fs.readline()
  68. while line:
  69. if re.match(r"^\s*uniform", line):
  70. res = re.match(r"uniform ([\d\w]*) ([\d\w]*)")
  71. type = res.groups(1)
  72. name = res.groups(2)
  73. uniforms.append(name)
  74. if type.find("texobj") != -1:
  75. sizes.append(1)
  76. else:
  77. t = re.match(r"float(\d)x(\d)", type)
  78. if t:
  79. sizes.append(int(t.groups(1)) * int(t.groups(2)))
  80. else:
  81. t = re.match(r"float(\d)", type)
  82. sizes.append(int(t.groups(1)))
  83. if line.find("[branch]") != -1:
  84. conditionals.append(name)
  85. line = fs.readline()
  86. fs.close()
  87. def detect_modules():
  88. module_list = []
  89. includes_cpp = ""
  90. register_cpp = ""
  91. unregister_cpp = ""
  92. files = glob.glob("modules/*")
  93. files.sort() # so register_module_types does not change that often, and also plugins are registered in alphabetic order
  94. for x in files:
  95. if not os.path.isdir(x):
  96. continue
  97. if not os.path.exists(x + "/config.py"):
  98. continue
  99. x = x.replace("modules/", "") # rest of world
  100. x = x.replace("modules\\", "") # win32
  101. module_list.append(x)
  102. try:
  103. with open("modules/" + x + "/register_types.h"):
  104. includes_cpp += '#include "modules/' + x + '/register_types.h"\n'
  105. register_cpp += '#ifdef MODULE_' + x.upper() + '_ENABLED\n'
  106. register_cpp += '\tregister_' + x + '_types();\n'
  107. register_cpp += '#endif\n'
  108. unregister_cpp += '#ifdef MODULE_' + x.upper() + '_ENABLED\n'
  109. unregister_cpp += '\tunregister_' + x + '_types();\n'
  110. unregister_cpp += '#endif\n'
  111. except IOError:
  112. pass
  113. modules_cpp = """
  114. // modules.cpp - THIS FILE IS GENERATED, DO NOT EDIT!!!!!!!
  115. #include "register_module_types.h"
  116. """ + includes_cpp + """
  117. void register_module_types() {
  118. """ + register_cpp + """
  119. }
  120. void unregister_module_types() {
  121. """ + unregister_cpp + """
  122. }
  123. """
  124. # NOTE: It is safe to generate this file here, since this is still executed serially
  125. with open("modules/register_module_types.gen.cpp", "w") as f:
  126. f.write(modules_cpp)
  127. return module_list
  128. def win32_spawn(sh, escape, cmd, args, env):
  129. import subprocess
  130. newargs = ' '.join(args[1:])
  131. cmdline = cmd + " " + newargs
  132. startupinfo = subprocess.STARTUPINFO()
  133. for e in env:
  134. if type(env[e]) != type(""):
  135. env[e] = str(env[e])
  136. proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
  137. stderr=subprocess.PIPE, startupinfo=startupinfo, shell=False, env=env)
  138. data, err = proc.communicate()
  139. rv = proc.wait()
  140. if rv:
  141. print("=====")
  142. print(err)
  143. print("=====")
  144. return rv
  145. """
  146. def win32_spawn(sh, escape, cmd, args, spawnenv):
  147. import win32file
  148. import win32event
  149. import win32process
  150. import win32security
  151. for var in spawnenv:
  152. spawnenv[var] = spawnenv[var].encode('ascii', 'replace')
  153. sAttrs = win32security.SECURITY_ATTRIBUTES()
  154. StartupInfo = win32process.STARTUPINFO()
  155. newargs = ' '.join(map(escape, args[1:]))
  156. cmdline = cmd + " " + newargs
  157. # check for any special operating system commands
  158. if cmd == 'del':
  159. for arg in args[1:]:
  160. win32file.DeleteFile(arg)
  161. exit_code = 0
  162. else:
  163. # otherwise execute the command.
  164. hProcess, hThread, dwPid, dwTid = win32process.CreateProcess(None, cmdline, None, None, 1, 0, spawnenv, None, StartupInfo)
  165. win32event.WaitForSingleObject(hProcess, win32event.INFINITE)
  166. exit_code = win32process.GetExitCodeProcess(hProcess)
  167. win32file.CloseHandle(hProcess);
  168. win32file.CloseHandle(hThread);
  169. return exit_code
  170. """
  171. def android_add_flat_dir(self, dir):
  172. if (dir not in self.android_flat_dirs):
  173. self.android_flat_dirs.append(dir)
  174. def android_add_maven_repository(self, url):
  175. if (url not in self.android_maven_repos):
  176. self.android_maven_repos.append(url)
  177. def android_add_dependency(self, depline):
  178. if (depline not in self.android_dependencies):
  179. self.android_dependencies.append(depline)
  180. def android_add_java_dir(self, subpath):
  181. base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + subpath
  182. if (base_path not in self.android_java_dirs):
  183. self.android_java_dirs.append(base_path)
  184. def android_add_res_dir(self, subpath):
  185. base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + subpath
  186. if (base_path not in self.android_res_dirs):
  187. self.android_res_dirs.append(base_path)
  188. def android_add_asset_dir(self, subpath):
  189. base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + subpath
  190. if (base_path not in self.android_asset_dirs):
  191. self.android_asset_dirs.append(base_path)
  192. def android_add_aidl_dir(self, subpath):
  193. base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + subpath
  194. if (base_path not in self.android_aidl_dirs):
  195. self.android_aidl_dirs.append(base_path)
  196. def android_add_jni_dir(self, subpath):
  197. base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + subpath
  198. if (base_path not in self.android_jni_dirs):
  199. self.android_jni_dirs.append(base_path)
  200. def android_add_gradle_plugin(self, plugin):
  201. if (plugin not in self.android_gradle_plugins):
  202. self.android_gradle_plugins.append(plugin)
  203. def android_add_gradle_classpath(self, classpath):
  204. if (classpath not in self.android_gradle_classpath):
  205. self.android_gradle_classpath.append(classpath)
  206. def android_add_default_config(self, config):
  207. if (config not in self.android_default_config):
  208. self.android_default_config.append(config)
  209. def android_add_to_manifest(self, file):
  210. base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + file
  211. with open(base_path, "r") as f:
  212. self.android_manifest_chunk += f.read()
  213. def android_add_to_permissions(self, file):
  214. base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + file
  215. with open(base_path, "r") as f:
  216. self.android_permission_chunk += f.read()
  217. def android_add_to_attributes(self, file):
  218. base_path = self.Dir(".").abspath + "/modules/" + self.current_module + "/" + file
  219. with open(base_path, "r") as f:
  220. self.android_appattributes_chunk += f.read()
  221. def disable_module(self):
  222. self.disabled_modules.append(self.current_module)
  223. def use_windows_spawn_fix(self, platform=None):
  224. if (os.name != "nt"):
  225. return # not needed, only for windows
  226. # On Windows, due to the limited command line length, when creating a static library
  227. # from a very high number of objects SCons will invoke "ar" once per object file;
  228. # that makes object files with same names to be overwritten so the last wins and
  229. # the library looses symbols defined by overwritten objects.
  230. # By enabling quick append instead of the default mode (replacing), libraries will
  231. # got built correctly regardless the invocation strategy.
  232. # Furthermore, since SCons will rebuild the library from scratch when an object file
  233. # changes, no multiple versions of the same object file will be present.
  234. self.Replace(ARFLAGS='q')
  235. def mySubProcess(cmdline, env):
  236. startupinfo = subprocess.STARTUPINFO()
  237. startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
  238. proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
  239. stderr=subprocess.PIPE, startupinfo=startupinfo, shell=False, env=env)
  240. data, err = proc.communicate()
  241. rv = proc.wait()
  242. if rv:
  243. print("=====")
  244. print(err)
  245. print("=====")
  246. return rv
  247. def mySpawn(sh, escape, cmd, args, env):
  248. newargs = ' '.join(args[1:])
  249. cmdline = cmd + " " + newargs
  250. rv = 0
  251. env = {str(key): str(value) for key, value in iteritems(env)}
  252. if len(cmdline) > 32000 and cmd.endswith("ar"):
  253. cmdline = cmd + " " + args[1] + " " + args[2] + " "
  254. for i in range(3, len(args)):
  255. rv = mySubProcess(cmdline + args[i], env)
  256. if rv:
  257. break
  258. else:
  259. rv = mySubProcess(cmdline, env)
  260. return rv
  261. self['SPAWN'] = mySpawn
  262. def split_lib(self, libname, src_list = None, env_lib = None):
  263. env = self
  264. num = 0
  265. cur_base = ""
  266. max_src = 64
  267. list = []
  268. lib_list = []
  269. if src_list is None:
  270. src_list = getattr(env, libname + "_sources")
  271. if type(env_lib) == type(None):
  272. env_lib = env
  273. for f in src_list:
  274. fname = ""
  275. if type(f) == type(""):
  276. fname = env.File(f).path
  277. else:
  278. fname = env.File(f)[0].path
  279. fname = fname.replace("\\", "/")
  280. base = string.join(fname.split("/")[:2], "/")
  281. if base != cur_base and len(list) > max_src:
  282. if num > 0:
  283. lib = env_lib.add_library(libname + str(num), list)
  284. lib_list.append(lib)
  285. list = []
  286. num = num + 1
  287. cur_base = base
  288. list.append(f)
  289. lib = env_lib.add_library(libname + str(num), list)
  290. lib_list.append(lib)
  291. if len(lib_list) > 0:
  292. if os.name == 'posix' and sys.platform == 'msys':
  293. env.Replace(ARFLAGS=['rcsT'])
  294. lib = env_lib.add_library(libname + "_collated", lib_list)
  295. lib_list = [lib]
  296. lib_base = []
  297. env_lib.add_source_files(lib_base, "*.cpp")
  298. lib = env_lib.add_library(libname, lib_base)
  299. lib_list.insert(0, lib)
  300. env.Prepend(LIBS=lib_list)
  301. def save_active_platforms(apnames, ap):
  302. for x in ap:
  303. names = ['logo']
  304. if os.path.isfile(x + "/run_icon.png"):
  305. names.append('run_icon')
  306. for name in names:
  307. pngf = open(x + "/" + name + ".png", "rb")
  308. b = pngf.read(1)
  309. str = " /* AUTOGENERATED FILE, DO NOT EDIT */ \n"
  310. str += " static const unsigned char _" + x[9:] + "_" + name + "[]={"
  311. while len(b) == 1:
  312. str += hex(ord(b))
  313. b = pngf.read(1)
  314. if (len(b) == 1):
  315. str += ","
  316. str += "};\n"
  317. pngf.close()
  318. # NOTE: It is safe to generate this file here, since this is still executed serially
  319. wf = x + "/" + name + ".gen.h"
  320. with open(wf, "w") as pngw:
  321. pngw.write(str)
  322. def no_verbose(sys, env):
  323. colors = {}
  324. # Colors are disabled in non-TTY environments such as pipes. This means
  325. # that if output is redirected to a file, it will not contain color codes
  326. if sys.stdout.isatty():
  327. colors['cyan'] = '\033[96m'
  328. colors['purple'] = '\033[95m'
  329. colors['blue'] = '\033[94m'
  330. colors['green'] = '\033[92m'
  331. colors['yellow'] = '\033[93m'
  332. colors['red'] = '\033[91m'
  333. colors['end'] = '\033[0m'
  334. else:
  335. colors['cyan'] = ''
  336. colors['purple'] = ''
  337. colors['blue'] = ''
  338. colors['green'] = ''
  339. colors['yellow'] = ''
  340. colors['red'] = ''
  341. colors['end'] = ''
  342. compile_source_message = '%sCompiling %s==> %s$SOURCE%s' % (colors['blue'], colors['purple'], colors['yellow'], colors['end'])
  343. java_compile_source_message = '%sCompiling %s==> %s$SOURCE%s' % (colors['blue'], colors['purple'], colors['yellow'], colors['end'])
  344. compile_shared_source_message = '%sCompiling shared %s==> %s$SOURCE%s' % (colors['blue'], colors['purple'], colors['yellow'], colors['end'])
  345. link_program_message = '%sLinking Program %s==> %s$TARGET%s' % (colors['red'], colors['purple'], colors['yellow'], colors['end'])
  346. link_library_message = '%sLinking Static Library %s==> %s$TARGET%s' % (colors['red'], colors['purple'], colors['yellow'], colors['end'])
  347. ranlib_library_message = '%sRanlib Library %s==> %s$TARGET%s' % (colors['red'], colors['purple'], colors['yellow'], colors['end'])
  348. link_shared_library_message = '%sLinking Shared Library %s==> %s$TARGET%s' % (colors['red'], colors['purple'], colors['yellow'], colors['end'])
  349. java_library_message = '%sCreating Java Archive %s==> %s$TARGET%s' % (colors['red'], colors['purple'], colors['yellow'], colors['end'])
  350. env.Append(CXXCOMSTR=[compile_source_message])
  351. env.Append(CCCOMSTR=[compile_source_message])
  352. env.Append(SHCCCOMSTR=[compile_shared_source_message])
  353. env.Append(SHCXXCOMSTR=[compile_shared_source_message])
  354. env.Append(ARCOMSTR=[link_library_message])
  355. env.Append(RANLIBCOMSTR=[ranlib_library_message])
  356. env.Append(SHLINKCOMSTR=[link_shared_library_message])
  357. env.Append(LINKCOMSTR=[link_program_message])
  358. env.Append(JARCOMSTR=[java_library_message])
  359. env.Append(JAVACCOMSTR=[java_compile_source_message])
  360. def detect_visual_c_compiler_version(tools_env):
  361. # tools_env is the variable scons uses to call tools that execute tasks, SCons's env['ENV'] that executes tasks...
  362. # (see the SCons documentation for more information on what it does)...
  363. # in order for this function to be well encapsulated i choose to force it to receive SCons's TOOLS env (env['ENV']
  364. # and not scons setup environment (env)... so make sure you call the right environment on it or it will fail to detect
  365. # the proper vc version that will be called
  366. # There is no flag to give to visual c compilers to set the architecture, ie scons bits argument (32,64,ARM etc)
  367. # There are many different cl.exe files that are run, and each one compiles & links to a different architecture
  368. # As far as I know, the only way to figure out what compiler will be run when Scons calls cl.exe via Program()
  369. # is to check the PATH variable and figure out which one will be called first. Code below does that and returns:
  370. # the following string values:
  371. # "" Compiler not detected
  372. # "amd64" Native 64 bit compiler
  373. # "amd64_x86" 64 bit Cross Compiler for 32 bit
  374. # "x86" Native 32 bit compiler
  375. # "x86_amd64" 32 bit Cross Compiler for 64 bit
  376. # There are other architectures, but Godot does not support them currently, so this function does not detect arm/amd64_arm
  377. # and similar architectures/compilers
  378. # Set chosen compiler to "not detected"
  379. vc_chosen_compiler_index = -1
  380. vc_chosen_compiler_str = ""
  381. # Start with Pre VS 2017 checks which uses VCINSTALLDIR:
  382. if 'VCINSTALLDIR' in tools_env:
  383. # print("Checking VCINSTALLDIR")
  384. # find() works with -1 so big ifs below are needed... the simplest solution, in fact
  385. # First test if amd64 and amd64_x86 compilers are present in the path
  386. vc_amd64_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"] + "BIN\\amd64;")
  387. if(vc_amd64_compiler_detection_index > -1):
  388. vc_chosen_compiler_index = vc_amd64_compiler_detection_index
  389. vc_chosen_compiler_str = "amd64"
  390. vc_amd64_x86_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"] + "BIN\\amd64_x86;")
  391. if(vc_amd64_x86_compiler_detection_index > -1
  392. and (vc_chosen_compiler_index == -1
  393. or vc_chosen_compiler_index > vc_amd64_x86_compiler_detection_index)):
  394. vc_chosen_compiler_index = vc_amd64_x86_compiler_detection_index
  395. vc_chosen_compiler_str = "amd64_x86"
  396. # Now check the 32 bit compilers
  397. vc_x86_compiler_detection_index = tools_env["PATH"].find(tools_env["VCINSTALLDIR"] + "BIN;")
  398. if(vc_x86_compiler_detection_index > -1
  399. and (vc_chosen_compiler_index == -1
  400. or vc_chosen_compiler_index > vc_x86_compiler_detection_index)):
  401. vc_chosen_compiler_index = vc_x86_compiler_detection_index
  402. vc_chosen_compiler_str = "x86"
  403. vc_x86_amd64_compiler_detection_index = tools_env["PATH"].find(tools_env['VCINSTALLDIR'] + "BIN\\x86_amd64;")
  404. if(vc_x86_amd64_compiler_detection_index > -1
  405. and (vc_chosen_compiler_index == -1
  406. or vc_chosen_compiler_index > vc_x86_amd64_compiler_detection_index)):
  407. vc_chosen_compiler_index = vc_x86_amd64_compiler_detection_index
  408. vc_chosen_compiler_str = "x86_amd64"
  409. # and for VS 2017 and newer we check VCTOOLSINSTALLDIR:
  410. if 'VCTOOLSINSTALLDIR' in tools_env:
  411. # Newer versions have a different path available
  412. vc_amd64_compiler_detection_index = tools_env["PATH"].upper().find(tools_env['VCTOOLSINSTALLDIR'].upper() + "BIN\\HOSTX64\\X64;")
  413. if(vc_amd64_compiler_detection_index > -1):
  414. vc_chosen_compiler_index = vc_amd64_compiler_detection_index
  415. vc_chosen_compiler_str = "amd64"
  416. vc_amd64_x86_compiler_detection_index = tools_env["PATH"].upper().find(tools_env['VCTOOLSINSTALLDIR'].upper() + "BIN\\HOSTX64\\X86;")
  417. if(vc_amd64_x86_compiler_detection_index > -1
  418. and (vc_chosen_compiler_index == -1
  419. or vc_chosen_compiler_index > vc_amd64_x86_compiler_detection_index)):
  420. vc_chosen_compiler_index = vc_amd64_x86_compiler_detection_index
  421. vc_chosen_compiler_str = "amd64_x86"
  422. vc_x86_compiler_detection_index = tools_env["PATH"].upper().find(tools_env['VCTOOLSINSTALLDIR'].upper() + "BIN\\HOSTX86\\X86;")
  423. if(vc_x86_compiler_detection_index > -1
  424. and (vc_chosen_compiler_index == -1
  425. or vc_chosen_compiler_index > vc_x86_compiler_detection_index)):
  426. vc_chosen_compiler_index = vc_x86_compiler_detection_index
  427. vc_chosen_compiler_str = "x86"
  428. vc_x86_amd64_compiler_detection_index = tools_env["PATH"].upper().find(tools_env['VCTOOLSINSTALLDIR'].upper() + "BIN\\HOSTX86\\X64;")
  429. if(vc_x86_amd64_compiler_detection_index > -1
  430. and (vc_chosen_compiler_index == -1
  431. or vc_chosen_compiler_index > vc_x86_amd64_compiler_detection_index)):
  432. vc_chosen_compiler_index = vc_x86_amd64_compiler_detection_index
  433. vc_chosen_compiler_str = "x86_amd64"
  434. return vc_chosen_compiler_str
  435. def find_visual_c_batch_file(env):
  436. from SCons.Tool.MSCommon.vc import get_default_version, get_host_target, find_batch_file
  437. version = get_default_version(env)
  438. (host_platform, target_platform,req_target_platform) = get_host_target(env)
  439. return find_batch_file(env, version, host_platform, target_platform)[0]
  440. def generate_cpp_hint_file(filename):
  441. if os.path.isfile(filename):
  442. # Don't overwrite an existing hint file since the user may have customized it.
  443. pass
  444. else:
  445. try:
  446. with open(filename, "w") as fd:
  447. fd.write("#define GDCLASS(m_class, m_inherits)\n")
  448. except IOError:
  449. print("Could not write cpp.hint file.")
  450. def generate_vs_project(env, num_jobs):
  451. batch_file = find_visual_c_batch_file(env)
  452. if batch_file:
  453. def build_commandline(commands):
  454. common_build_prefix = ['cmd /V /C set "plat=$(PlatformTarget)"',
  455. '(if "$(PlatformTarget)"=="x64" (set "plat=x86_amd64"))',
  456. 'set "tools=yes"',
  457. '(if "$(Configuration)"=="release" (set "tools=no"))',
  458. 'call "' + batch_file + '" !plat!']
  459. result = " ^& ".join(common_build_prefix + [commands])
  460. return result
  461. env.AddToVSProject(env.core_sources)
  462. env.AddToVSProject(env.main_sources)
  463. env.AddToVSProject(env.modules_sources)
  464. env.AddToVSProject(env.scene_sources)
  465. env.AddToVSProject(env.servers_sources)
  466. env.AddToVSProject(env.editor_sources)
  467. # windows allows us to have spaces in paths, so we need
  468. # to double quote off the directory. However, the path ends
  469. # in a backslash, so we need to remove this, lest it escape the
  470. # last double quote off, confusing MSBuild
  471. env['MSVSBUILDCOM'] = build_commandline('scons --directory="$(ProjectDir.TrimEnd(\'\\\'))" platform=windows progress=no target=$(Configuration) tools=!tools! -j' + str(num_jobs))
  472. env['MSVSREBUILDCOM'] = build_commandline('scons --directory="$(ProjectDir.TrimEnd(\'\\\'))" platform=windows progress=no target=$(Configuration) tools=!tools! vsproj=yes -j' + str(num_jobs))
  473. env['MSVSCLEANCOM'] = build_commandline('scons --directory="$(ProjectDir.TrimEnd(\'\\\'))" --clean platform=windows progress=no target=$(Configuration) tools=!tools! -j' + str(num_jobs))
  474. # This version information (Win32, x64, Debug, Release, Release_Debug seems to be
  475. # required for Visual Studio to understand that it needs to generate an NMAKE
  476. # project. Do not modify without knowing what you are doing.
  477. debug_variants = ['debug|Win32'] + ['debug|x64']
  478. release_variants = ['release|Win32'] + ['release|x64']
  479. release_debug_variants = ['release_debug|Win32'] + ['release_debug|x64']
  480. variants = debug_variants + release_variants + release_debug_variants
  481. debug_targets = ['bin\\godot.windows.tools.32.exe'] + ['bin\\godot.windows.tools.64.exe']
  482. release_targets = ['bin\\godot.windows.opt.32.exe'] + ['bin\\godot.windows.opt.64.exe']
  483. release_debug_targets = ['bin\\godot.windows.opt.tools.32.exe'] + ['bin\\godot.windows.opt.tools.64.exe']
  484. targets = debug_targets + release_targets + release_debug_targets
  485. if not env.get('MSVS'):
  486. env['MSVS']['PROJECTSUFFIX'] = '.vcxproj'
  487. env['MSVS']['SOLUTIONSUFFIX'] = '.sln'
  488. env.MSVSProject(
  489. target=['#godot' + env['MSVSPROJECTSUFFIX']],
  490. incs=env.vs_incs,
  491. srcs=env.vs_srcs,
  492. runfile=targets,
  493. buildtarget=targets,
  494. auto_build_solution=1,
  495. variant=variants)
  496. else:
  497. print("Could not locate Visual Studio batch file for setting up the build environment. Not generating VS project.")
  498. def precious_program(env, program, sources, **args):
  499. program = env.ProgramOriginal(program, sources, **args)
  500. env.Precious(program)
  501. return program
  502. def add_shared_library(env, name, sources, **args):
  503. library = env.SharedLibrary(name, sources, **args)
  504. env.NoCache(library)
  505. return library
  506. def add_library(env, name, sources, **args):
  507. library = env.Library(name, sources, **args)
  508. env.NoCache(library)
  509. return library
  510. def add_program(env, name, sources, **args):
  511. program = env.Program(name, sources, **args)
  512. env.NoCache(program)
  513. return program
  514. def CommandNoCache(env, target, sources, command, **args):
  515. result = env.Command(target, sources, command, **args)
  516. env.NoCache(result)
  517. return result
  518. def detect_darwin_sdk_path(platform, env):
  519. sdk_name = ''
  520. if platform == 'osx':
  521. sdk_name = 'macosx'
  522. var_name = 'MACOS_SDK_PATH'
  523. elif platform == 'iphone':
  524. sdk_name = 'iphoneos'
  525. var_name = 'IPHONESDK'
  526. elif platform == 'iphonesimulator':
  527. sdk_name = 'iphonesimulator'
  528. var_name = 'IPHONESDK'
  529. else:
  530. raise Exception("Invalid platform argument passed to detect_darwin_sdk_path")
  531. if not env[var_name]:
  532. try:
  533. sdk_path = decode_utf8(subprocess.check_output(['xcrun', '--sdk', sdk_name, '--show-sdk-path']).strip())
  534. if sdk_path:
  535. env[var_name] = sdk_path
  536. except (subprocess.CalledProcessError, OSError) as e:
  537. print("Failed to find SDK path while running xcrun --sdk {} --show-sdk-path.".format(sdk_name))
  538. raise
  539. def get_compiler_version(env):
  540. version = decode_utf8(subprocess.check_output([env['CXX'], '--version']).strip())
  541. match = re.search('[0-9][0-9.]*', version)
  542. if match is not None:
  543. return match.group().split('.')
  544. else:
  545. return None
  546. def using_gcc(env):
  547. return 'gcc' in os.path.basename(env["CC"])
  548. def using_clang(env):
  549. return 'clang' in os.path.basename(env["CC"])