PageRenderTime 99ms CodeModel.GetById 21ms RepoModel.GetById 2ms app.codeStats 0ms

/build/configuration.py

https://github.com/changm/tessa
Python | 378 lines | 314 code | 24 blank | 40 comment | 31 complexity | 9827075cef3a0b755fc07f41274434a4 MD5 | raw file
  1. # -*- Mode: Python; indent-tabs-mode: nil -*-
  2. # ***** BEGIN LICENSE BLOCK *****
  3. # Version: MPL 1.1/GPL 2.0/LGPL 2.1
  4. #
  5. # The contents of this file are subject to the Mozilla Public License Version
  6. # 1.1 (the "License"); you may not use this file except in compliance with
  7. # the License. You may obtain a copy of the License at
  8. # http://www.mozilla.org/MPL/
  9. #
  10. # Software distributed under the License is distributed on an "AS IS" basis,
  11. # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
  12. # for the specific language governing rights and limitations under the
  13. # License.
  14. #
  15. # The Original Code is [Open Source Virtual Machine].
  16. #
  17. # The Initial Developer of the Original Code is
  18. # Adobe System Incorporated.
  19. # Portions created by the Initial Developer are Copyright (C) 2005-2006
  20. # the Initial Developer. All Rights Reserved.
  21. #
  22. # Contributor(s):
  23. #
  24. # Alternatively, the contents of this file may be used under the terms of
  25. # either the GNU General Public License Version 2 or later (the "GPL"), or
  26. # the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
  27. # in which case the provisions of the GPL or the LGPL are applicable instead
  28. # of those above. If you wish to allow use of your version of this file only
  29. # under the terms of either the GPL or the LGPL, and not to allow others to
  30. # use your version of this file under the terms of the MPL, indicate your
  31. # decision by deleting the provisions above and replace them with the notice
  32. # and other provisions required by the GPL or the LGPL. If you do not delete
  33. # the provisions above, a recipient may use your version of this file under
  34. # the terms of any one of the MPL, the GPL or the LGPL.
  35. #
  36. # ***** END LICENSE BLOCK *****
  37. import os
  38. import sys
  39. import build.process
  40. import re
  41. def writeFileIfChanged(path, contents):
  42. """Write some contents to a file. Avoids modifying the file timestamp if the file contents already match."""
  43. print "Generating " + path + "...",
  44. try:
  45. outf = open(path, "r")
  46. oldcontents = outf.read()
  47. outf.close()
  48. if oldcontents == contents:
  49. print "not changed"
  50. return
  51. except IOError:
  52. pass
  53. outf = open(path, "w")
  54. outf.write(contents)
  55. outf.close()
  56. print
  57. # Figure out TARGET and CPU, a la config.guess
  58. # Do cross-compilation in the future, which will require HOST_OS and perhaps
  59. # other settings
  60. def _configGuess():
  61. ostest = sys.platform
  62. cputest = build.process.run_for_output(['uname', '-m'])
  63. return _configSub(ostest, cputest)
  64. def _configSub(ostest, cputest):
  65. if ostest.startswith('win') or ostest.startswith('cygwin'):
  66. os = 'windows'
  67. elif ostest.startswith('darwin') or ostest.startswith('apple-darwin'):
  68. os = 'darwin'
  69. elif ostest.startswith('linux') or ostest.startswith('pc-linux'):
  70. os = 'linux'
  71. elif ostest.startswith('sunos'):
  72. os = 'sunos'
  73. else:
  74. raise Exception('Unrecognized OS: ' + ostest)
  75. if re.search(r'^i(\d86|86pc|x86)$', cputest):
  76. cpu = 'i686'
  77. elif re.search('^(x86_64|amd64)$', cputest):
  78. cpu = 'x86_64'
  79. elif re.search('^(ppc64|powerpc64)$', cputest):
  80. cpu = 'ppc64'
  81. elif re.search('^(ppc|powerpc|Power Macintosh)$', cputest):
  82. cpu = 'powerpc'
  83. elif re.search('sun', cputest):
  84. cpu = 'sparc'
  85. elif re.search('arm', cputest):
  86. cpu = 'arm'
  87. elif re.search('mips', cputest):
  88. cpu = 'mips'
  89. else:
  90. raise Exception('Unrecognized CPU: ' + cputest)
  91. return (os, cpu)
  92. class Configuration:
  93. def __init__(self, topsrcdir, options=None, sourcefile=None, objdir=None,
  94. optimize=True, debug=False):
  95. self._topsrcdir = topsrcdir
  96. if objdir:
  97. self._objdir = objdir
  98. else:
  99. self._objdir = os.getcwd()
  100. self._optimize = optimize
  101. self._debug = debug
  102. self._host = _configGuess()
  103. self._target = self._host
  104. if sourcefile:
  105. srcfile = self._topsrcdir + "/" + sourcefile
  106. if not os.path.exists(srcfile):
  107. raise Exception("Source file " + srcfile + " doesn't exist.")
  108. objfile = self._objdir + "/" + sourcefile
  109. if os.path.exists(objfile):
  110. raise Exception("It appears you're trying to build in the source directory. "
  111. "(Source file " + objfile + " exists here.) "
  112. "You must use an object directory to build Tamarin. "
  113. "Create an empty directory, cd into it, and run this configure.py script from there.")
  114. if options:
  115. o = options.getStringArg("optimize")
  116. if o != None:
  117. self._optimize = o
  118. d = options.getStringArg("debug")
  119. if d != None:
  120. self._debug = d
  121. if options.host:
  122. hostcpu, hostos = options.host.split('-', 1)
  123. self._host = _configSub(hostos, hostcpu)
  124. if options.target:
  125. targetcpu, targetos = options.target.split('-', 1)
  126. self._target = _configSub(targetos, targetcpu)
  127. self._acvars = {
  128. 'topsrcdir': self._topsrcdir,
  129. 'HOST_OS': self._host[0],
  130. 'TARGET_OS': self._target[0],
  131. 'TARGET_CPU': self._target[1]
  132. }
  133. if self._host[0] == 'windows':
  134. self._acvars['topsrcdir'] = toMSYSPath(self._topsrcdir)
  135. if self._debug:
  136. self._acvars['ENABLE_DEBUG'] = 1
  137. self._compiler = 'GCC'
  138. self._acvars.update({
  139. 'I_SUFFIX': 'i',
  140. 'II_SUFFIX': 'ii',
  141. 'OBJ_SUFFIX': 'o',
  142. 'LIB_PREFIX': 'lib',
  143. 'LIB_SUFFIX': 'a',
  144. 'DLL_SUFFIX': 'so',
  145. 'PROGRAM_SUFFIX': '',
  146. 'USE_COMPILER_DEPS': 1,
  147. 'EXPAND_LIBNAME' : '-l$(1)',
  148. 'EXPAND_DLLNAME' : '-l$(1)',
  149. 'OUTOPTION' : '-o ',
  150. 'LIBPATH': '-L'
  151. })
  152. if self._target[0] == 'windows':
  153. self._compiler = 'VS'
  154. del self._acvars['USE_COMPILER_DEPS']
  155. static_crt = options.getBoolArg('static-crt')
  156. self._acvars.update({
  157. 'OBJ_SUFFIX' : 'obj',
  158. 'LIB_PREFIX' : '',
  159. 'LIB_SUFFIX' : 'lib',
  160. 'DLL_SUFFIX' : 'dll',
  161. 'PROGRAM_SUFFIX': '.exe',
  162. 'CPPFLAGS' : (self._debug and '-MTd' or '-MT') or (self._debug and '-MDd' or '-MD'),
  163. 'CXX' : 'cl.exe -nologo',
  164. 'CXXFLAGS' : '-TP',
  165. 'CC' : 'cl.exe -nologo',
  166. 'CFLAGS' : '-TC',
  167. 'DLL_CFLAGS' : '',
  168. 'AR' : 'lib.exe -nologo',
  169. 'LD' : 'link.exe -nologo',
  170. 'LDFLAGS' : '',
  171. 'MKSTATICLIB' : '$(AR) -OUT:$(1)',
  172. 'MKDLL' : '$(LD) -DLL -OUT:$(1)',
  173. 'MKPROGRAM' : '$(LD) -OUT:$(1)',
  174. 'EXPAND_LIBNAME' : '$(1).lib',
  175. 'EXPAND_DLLNAME' : '$(1).lib',
  176. 'OUTOPTION' : '-Fo',
  177. 'LIBPATH' : '-LIBPATH:'
  178. })
  179. if self._target[1] == "arm":
  180. self._acvars.update({'LDFLAGS' : '-NODEFAULTLIB:"oldnames.lib" -ENTRY:"mainWCRTStartup"'})
  181. if sys.platform.startswith('cygwin'):
  182. self._acvars.update({'ASM' : '$(topsrcdir)/build/cygwin-wrapper.sh armasm.exe -nologo -arch 5T'})
  183. else:
  184. self._acvars.update({'ASM' : 'armasm.exe -nologo -arch 5T'})
  185. if self._target[1] == "x86_64":
  186. if sys.platform.startswith('cygwin'):
  187. self._acvars.update({'MASM' : '$(topsrcdir)/build/cygwin-wrapper.sh ml64.exe -nologo -c '})
  188. else:
  189. self._acvars.update({'MASM' : 'ml64.exe -nologo -c '})
  190. if sys.platform.startswith('cygwin'):
  191. self._acvars.update({'CXX' : '$(topsrcdir)/build/cygwin-wrapper.sh cl.exe -nologo'})
  192. self._acvars.update({'CC' : '$(topsrcdir)/build/cygwin-wrapper.sh cl.exe -nologo'})
  193. # Hackery! Make assumptions that we want to build with GCC 3.3 on MacPPC
  194. # and GCC4 on MacIntel
  195. elif self._target[0] == 'darwin':
  196. self._acvars.update({
  197. 'DLL_SUFFIX' : 'dylib',
  198. 'CPPFLAGS' : '-pipe',
  199. 'CXXFLAGS' : '',
  200. 'CFLAGS' : '',
  201. 'DLL_CFLAGS' : '-fPIC',
  202. 'LDFLAGS' : '-framework CoreServices',
  203. 'AR' : 'ar',
  204. 'MKSTATICLIB' : '$(AR) cr $(1)',
  205. 'MKDLL' : '$(CXX) -dynamiclib -single_module -install_name @executable_path/$(1) -o $(1)',
  206. 'MKPROGRAM' : '$(CXX) -o $(1)'
  207. })
  208. # -Wno-trigraphs -Wreturn-type -Wnon-virtual-dtor -Wmissing-braces -Wparentheses -Wunused-label -Wunused-parameter -Wunused-variable -Wunused-value -Wuninitialized
  209. if 'CXX' in os.environ:
  210. self._acvars['CXX'] = os.environ['CXX']
  211. elif self._target[1] == 'i686':
  212. self._acvars['CXX'] = 'g++'
  213. self._acvars['CXXFLAGS'] += ' -arch i686 '
  214. self._acvars['LDFLAGS'] += ' -arch i686 '
  215. elif self._target[1] == 'x86_64':
  216. self._acvars['CXX'] = 'g++'
  217. self._acvars['CXXFLAGS'] += ' -arch x86_64 '
  218. self._acvars['LDFLAGS'] += ' -arch x86_64 '
  219. elif self._target[1] == 'powerpc':
  220. self._acvars['CXX'] = 'g++'
  221. self._acvars['CXXFLAGS'] += ' -arch ppc '
  222. self._acvars['LDFLAGS'] += ' -arch ppc '
  223. elif self._target[1] == 'ppc64':
  224. self._acvars['CXX'] = 'g++'
  225. self._acvars['CXXFLAGS'] += ' -arch ppc64 '
  226. self._acvars['LDFLAGS'] += ' -arch ppc64 '
  227. else:
  228. raise Exception("Unexpected Darwin processor.")
  229. if 'CC' in os.environ:
  230. self._acvars['CC'] = os.environ['CC']
  231. elif self._target[1] == 'i686':
  232. self._acvars['CC'] = 'gcc'
  233. self._acvars['CFLAGS'] += ' -arch i686 '
  234. elif self._target[1] == 'x86_64':
  235. self._acvars['CC'] = 'gcc'
  236. self._acvars['CFLAGS'] += ' -arch x86_64 '
  237. elif self._target[1] == 'powerpc':
  238. self._acvars['CC'] = 'gcc'
  239. self._acvars['CFLAGS'] += ' -arch ppc '
  240. elif self._target[1] == 'ppc64':
  241. self._acvars['CC'] = 'gcc'
  242. self._acvars['CFLAGS'] += ' -arch ppc64 '
  243. else:
  244. raise Exception("Unexpected Darwin processor.")
  245. elif self._target[0] == 'linux':
  246. self._acvars.update({
  247. 'CPPFLAGS' : os.environ.get('CPPFLAGS', ''),
  248. 'CXX' : os.environ.get('CXX', 'g++'),
  249. 'CXXFLAGS' : os.environ.get('CXXFLAGS', ''),
  250. 'CC' : os.environ.get('CC', 'gcc'),
  251. 'CFLAGS' : os.environ.get('CFLAGS', ''),
  252. 'DLL_CFLAGS' : '-fPIC',
  253. 'LD' : os.environ.get('LD', 'ar'),
  254. 'LDFLAGS' : os.environ.get('LDFLAGS', ''),
  255. 'AR' : os.environ.get('AR', 'ar'),
  256. 'MKSTATICLIB' : '$(AR) cr $(1)',
  257. 'MKDLL' : '$(CXX) -shared -o $(1)',
  258. 'MKPROGRAM' : '$(CXX) -o $(1)'
  259. })
  260. if self._target[1] == "mips":
  261. self._acvars.update({'CXXFLAGS' : ''})
  262. self._acvars.update({'LDFLAGS' : ''})
  263. self._acvars.update({'zlib_EXTRA_CFLAGS' : ''})
  264. elif self._target[0] == 'sunos':
  265. if options.getBoolArg("gcc", False):
  266. self._acvars.update({
  267. 'CPPFLAGS' : os.environ.get('CPPFLAGS', '') + "-DBROKEN_OFFSETOF",
  268. 'CXX' : os.environ.get('CXX', 'g++'),
  269. 'CXXFLAGS' : os.environ.get('CXXFLAGS', ''),
  270. 'CC' : os.environ.get('CC', 'gcc'),
  271. 'CFLAGS' : os.environ.get('CFLAGS', ''),
  272. 'DLL_CFLAGS' : '-fPIC',
  273. 'LD' : 'ar',
  274. 'LDFLAGS' : '',
  275. 'MKSTATICLIB' : '$(AR) cr $(1)',
  276. 'MKDLL' : '$(CXX) -shared -o $(1)',
  277. 'MKPROGRAM' : '$(CXX) -o $(1)'
  278. })
  279. else:
  280. self._compiler = 'SunStudio'
  281. self._acvars.update({
  282. 'I_SUFFIX': 'i',
  283. 'II_SUFFIX': 'i',
  284. 'CPPFLAGS' : '',
  285. 'CXX' : 'CC',
  286. 'CXXFLAGS' : '',
  287. 'CC' : 'cc',
  288. 'CFLAGS' : '',
  289. 'LD' : 'ar',
  290. 'LDFLAGS' : '',
  291. 'MKSTATICLIB' : '$(AR) cr $(1)',
  292. 'MKPROGRAM' : '$(CXX) -o $(1)'
  293. })
  294. self._acvars['COMPILER'] = self._compiler
  295. def getObjDir(self):
  296. """Returns the build directory being configured."""
  297. return self._objdir
  298. def getHost(self):
  299. """Returns an (os, cpu) tuple of the host machine."""
  300. return self._host
  301. def getTarget(self):
  302. """Returns an (os, cpu) tuple of the target machine."""
  303. return self._target
  304. def getCompiler(self):
  305. """Returns the compiler in use, as a string.
  306. Possible values are:
  307. - 'GCC': the GNU Compiler Collection, including GCC and G++
  308. - 'VS': Microsoft Visual Studio
  309. - 'SunStudio': Sun Studio"""
  310. return self._compiler
  311. def getDebug(self):
  312. return self._debug
  313. def subst(self, name, value):
  314. self._acvars[name] = value
  315. _confvar = re.compile("@([^@]+)@")
  316. def generate(self, makefile):
  317. outpath = self._objdir + "/" + makefile
  318. contents = \
  319. "\n".join([k + "=" + str(v) \
  320. for (k,v) in self._acvars.iteritems()]) + \
  321. "\n\ninclude $(topsrcdir)/build/config.mk\n" \
  322. "include $(topsrcdir)/manifest.mk\n" \
  323. "include $(topsrcdir)/build/rules.mk\n"
  324. writeFileIfChanged(outpath, contents)
  325. def toMSYSPath(path):
  326. if sys.platform.startswith('cygwin'):
  327. return path
  328. elif path[1] != ':':
  329. raise ValueError("win32 path without drive letter! %s" % path)
  330. else:
  331. return '/%s%s' % (path[0], path[2:].replace('\\', '/'))