detect.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281
  1. import methods
  2. import os
  3. import sys
  4. def is_active():
  5. return True
  6. def get_name():
  7. return "Windows"
  8. def can_build():
  9. if (os.name == "nt"):
  10. # building natively on windows!
  11. if (os.getenv("VCINSTALLDIR")):
  12. return True
  13. else:
  14. print("\nMSVC not detected, attempting MinGW.")
  15. mingw32 = ""
  16. mingw64 = ""
  17. if (os.getenv("MINGW32_PREFIX")):
  18. mingw32 = os.getenv("MINGW32_PREFIX")
  19. if (os.getenv("MINGW64_PREFIX")):
  20. mingw64 = os.getenv("MINGW64_PREFIX")
  21. test = "gcc --version > NUL 2>&1"
  22. if os.system(test) != 0 and os.system(mingw32 + test) != 0 and os.system(mingw64 + test) != 0:
  23. print("- could not detect gcc.")
  24. print("Please, make sure a path to a MinGW /bin directory is accessible into the environment PATH.\n")
  25. return False
  26. else:
  27. print("- gcc detected.")
  28. return True
  29. if (os.name == "posix"):
  30. mingw = "i586-mingw32msvc-"
  31. mingw64 = "x86_64-w64-mingw32-"
  32. mingw32 = "i686-w64-mingw32-"
  33. if (os.getenv("MINGW32_PREFIX")):
  34. mingw32 = os.getenv("MINGW32_PREFIX")
  35. mingw = mingw32
  36. if (os.getenv("MINGW64_PREFIX")):
  37. mingw64 = os.getenv("MINGW64_PREFIX")
  38. test = "gcc --version &>/dev/null"
  39. if (os.system(mingw + test) == 0 or os.system(mingw64 + test) == 0 or os.system(mingw32 + test) == 0):
  40. return True
  41. return False
  42. def get_opts():
  43. mingw = ""
  44. mingw32 = ""
  45. mingw64 = ""
  46. if (os.name == "posix"):
  47. mingw = "i586-mingw32msvc-"
  48. mingw32 = "i686-w64-mingw32-"
  49. mingw64 = "x86_64-w64-mingw32-"
  50. if os.system(mingw32 + "gcc --version &>/dev/null") != 0:
  51. mingw32 = mingw
  52. if (os.getenv("MINGW32_PREFIX")):
  53. mingw32 = os.getenv("MINGW32_PREFIX")
  54. mingw = mingw32
  55. if (os.getenv("MINGW64_PREFIX")):
  56. mingw64 = os.getenv("MINGW64_PREFIX")
  57. return [
  58. ('mingw_prefix', 'MinGW Prefix', mingw32),
  59. ('mingw_prefix_64', 'MinGW Prefix 64 bits', mingw64),
  60. ]
  61. def get_flags():
  62. return [
  63. ]
  64. def build_res_file(target, source, env):
  65. cmdbase = ""
  66. if (env["bits"] == "32"):
  67. cmdbase = env['mingw_prefix']
  68. else:
  69. cmdbase = env['mingw_prefix_64']
  70. CPPPATH = env['CPPPATH']
  71. cmdbase = cmdbase + 'windres --include-dir . '
  72. import subprocess
  73. for x in range(len(source)):
  74. cmd = cmdbase + '-i ' + str(source[x]) + ' -o ' + str(target[x])
  75. try:
  76. out = subprocess.Popen(cmd, shell=True, stderr=subprocess.PIPE).communicate()
  77. if len(out[1]):
  78. return 1
  79. except:
  80. return 1
  81. return 0
  82. def configure(env):
  83. env.Append(CPPPATH=['#platform/windows'])
  84. # Targeted Windows version: Vista (and later)
  85. winver = "0x0600" # Windows Vista is the minimum target for windows builds
  86. if (os.name == "nt" and os.getenv("VCINSTALLDIR")): # MSVC
  87. env['ENV']['TMP'] = os.environ['TMP']
  88. ## Build type
  89. if (env["target"] == "release"):
  90. env.Append(CCFLAGS=['/O2'])
  91. env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS'])
  92. env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup'])
  93. elif (env["target"] == "release_debug"):
  94. env.Append(CCFLAGS=['/O2', '/DDEBUG_ENABLED'])
  95. env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
  96. elif (env["target"] == "debug_release"):
  97. env.Append(CCFLAGS=['/Z7', '/Od'])
  98. env.Append(LINKFLAGS=['/DEBUG'])
  99. env.Append(LINKFLAGS=['/SUBSYSTEM:WINDOWS'])
  100. env.Append(LINKFLAGS=['/ENTRY:mainCRTStartup'])
  101. elif (env["target"] == "debug"):
  102. env.Append(CCFLAGS=['/Z7', '/DDEBUG_ENABLED', '/DDEBUG_MEMORY_ENABLED', '/DD3D_DEBUG_INFO', '/Od'])
  103. env.Append(LINKFLAGS=['/SUBSYSTEM:CONSOLE'])
  104. env.Append(LINKFLAGS=['/DEBUG'])
  105. ## Architecture
  106. # Note: this detection/override code from here onward should be here instead of in SConstruct because it's platform and compiler specific (MSVC/Windows)
  107. if (env["bits"] != "default"):
  108. print("Error: bits argument is disabled for MSVC")
  109. print("""
  110. Bits argument is not supported for MSVC compilation. Architecture depends on the Native/Cross Compile Tools Prompt/Developer Console
  111. (or Visual Studio settings) that is being used to run SCons. As a consequence, bits argument is disabled. Run scons again without bits
  112. argument (example: scons p=windows) and SCons will attempt to detect what MSVC compiler will be executed and inform you.
  113. """)
  114. sys.exit()
  115. # Forcing bits argument because MSVC does not have a flag to set this through SCons... it's different compilers (cl.exe's) called from the proper command prompt
  116. # that decide the architecture that is build for. Scons can only detect the os.getenviron (because vsvarsall.bat sets a lot of stuff for cl.exe to work with)
  117. env["bits"] = "32"
  118. env["x86_libtheora_opt_vc"] = True
  119. ## Compiler configuration
  120. env['ENV'] = os.environ
  121. # This detection function needs the tools env (that is env['ENV'], not SCons's env), and that is why it's this far bellow in the code
  122. compiler_version_str = methods.detect_visual_c_compiler_version(env['ENV'])
  123. print("Detected MSVC compiler: " + compiler_version_str)
  124. # If building for 64bit architecture, disable assembly optimisations for 32 bit builds (theora as of writting)... vc compiler for 64bit can not compile _asm
  125. if(compiler_version_str == "amd64" or compiler_version_str == "x86_amd64"):
  126. env["bits"] = "64"
  127. env["x86_libtheora_opt_vc"] = False
  128. print("Compiled program architecture will be a 64 bit executable (forcing bits=64).")
  129. elif (compiler_version_str == "x86" or compiler_version_str == "amd64_x86"):
  130. print("Compiled program architecture will be a 32 bit executable. (forcing bits=32).")
  131. else:
  132. print("Failed to detect MSVC compiler architecture version... Defaulting to 32bit executable settings (forcing bits=32). Compilation attempt will continue, but SCons can not detect for what architecture this build is compiled for. You should check your settings/compilation setup.")
  133. ## Compile flags
  134. env.Append(CCFLAGS=['/MT', '/Gd', '/GR', '/nologo'])
  135. env.Append(CXXFLAGS=['/TP'])
  136. env.Append(CPPFLAGS=['/DMSVC', '/GR', ])
  137. env.Append(CCFLAGS=['/I' + os.getenv("WindowsSdkDir") + "/Include"])
  138. env.Append(CCFLAGS=['/DWINDOWS_ENABLED'])
  139. env.Append(CCFLAGS=['/DOPENGL_ENABLED'])
  140. env.Append(CCFLAGS=['/DRTAUDIO_ENABLED'])
  141. env.Append(CCFLAGS=['/DTYPED_METHOD_BIND'])
  142. env.Append(CCFLAGS=['/DWIN32'])
  143. env.Append(CCFLAGS=['/DWINVER=%s' % winver, '/D_WIN32_WINNT=%s' % winver])
  144. if env["bits"] == "64":
  145. env.Append(CCFLAGS=['/D_WIN64'])
  146. LIBS = ['winmm', 'opengl32', 'dsound', 'kernel32', 'ole32', 'oleaut32', 'user32', 'gdi32', 'IPHLPAPI', 'Shlwapi', 'wsock32', 'Ws2_32', 'shell32', 'advapi32', 'dinput8', 'dxguid']
  147. env.Append(LINKFLAGS=[p + env["LIBSUFFIX"] for p in LIBS])
  148. env.Append(LIBPATH=[os.getenv("WindowsSdkDir") + "/Lib"])
  149. if (os.getenv("VCINSTALLDIR")):
  150. VC_PATH = os.getenv("VCINSTALLDIR")
  151. else:
  152. VC_PATH = ""
  153. env.Append(CCFLAGS=["/I" + p for p in os.getenv("INCLUDE").split(";")])
  154. env.Append(LIBPATH=[p for p in os.getenv("LIB").split(";")])
  155. # Incremental linking fix
  156. env['BUILDERS']['ProgramOriginal'] = env['BUILDERS']['Program']
  157. env['BUILDERS']['Program'] = methods.precious_program
  158. else: # MinGW
  159. # Workaround for MinGW. See:
  160. # http://www.scons.org/wiki/LongCmdLinesOnWin32
  161. env.use_windows_spawn_fix()
  162. ## Build type
  163. if (env["target"] == "release"):
  164. env.Append(CCFLAGS=['-msse2'])
  165. if (env["bits"] == "64"):
  166. env.Append(CCFLAGS=['-O3'])
  167. else:
  168. env.Append(CCFLAGS=['-O2'])
  169. env.Append(LINKFLAGS=['-Wl,--subsystem,windows'])
  170. elif (env["target"] == "release_debug"):
  171. env.Append(CCFLAGS=['-O2', '-DDEBUG_ENABLED'])
  172. elif (env["target"] == "debug"):
  173. env.Append(CCFLAGS=['-g', '-DDEBUG_ENABLED', '-DDEBUG_MEMORY_ENABLED'])
  174. ## Compiler configuration
  175. if (os.name == "nt"):
  176. env['ENV']['TMP'] = os.environ['TMP'] # way to go scons, you can be so stupid sometimes
  177. else:
  178. env["PROGSUFFIX"] = env["PROGSUFFIX"] + ".exe" # for linux cross-compilation
  179. mingw_prefix = ""
  180. if (env["bits"] == "default"):
  181. env["bits"] = "64" if "PROGRAMFILES(X86)" in os.environ else "32"
  182. if (env["bits"] == "32"):
  183. env.Append(LINKFLAGS=['-static'])
  184. env.Append(LINKFLAGS=['-static-libgcc'])
  185. env.Append(LINKFLAGS=['-static-libstdc++'])
  186. mingw_prefix = env["mingw_prefix"]
  187. else:
  188. env.Append(LINKFLAGS=['-static'])
  189. mingw_prefix = env["mingw_prefix_64"]
  190. nulstr = ""
  191. if (os.name == "posix"):
  192. nulstr = ">/dev/null"
  193. else:
  194. nulstr = ">nul"
  195. env["CC"] = mingw_prefix + "gcc"
  196. env['AS'] = mingw_prefix + "as"
  197. env['CXX'] = mingw_prefix + "g++"
  198. env['AR'] = mingw_prefix + "ar"
  199. env['RANLIB'] = mingw_prefix + "ranlib"
  200. env['LD'] = mingw_prefix + "g++"
  201. env["x86_libtheora_opt_gcc"] = True
  202. ## Compile flags
  203. env.Append(CCFLAGS=['-DWINDOWS_ENABLED', '-mwindows'])
  204. env.Append(CCFLAGS=['-DOPENGL_ENABLED'])
  205. env.Append(CCFLAGS=['-DRTAUDIO_ENABLED'])
  206. env.Append(CCFLAGS=['-DWINVER=%s' % winver, '-D_WIN32_WINNT=%s' % winver])
  207. env.Append(LIBS=['mingw32', 'opengl32', 'dsound', 'ole32', 'd3d9', 'winmm', 'gdi32', 'iphlpapi', 'shlwapi', 'wsock32', 'ws2_32', 'kernel32', 'oleaut32', 'dinput8', 'dxguid'])
  208. env.Append(CPPFLAGS=['-DMINGW_ENABLED'])
  209. # resrc
  210. env.Append(BUILDERS={'RES': env.Builder(action=build_res_file, suffix='.o', src_suffix='.rc')})