1 # -*- Mode: Python; indent-tabs-mode: nil -*-
2 # ***** BEGIN LICENSE BLOCK *****
3 # Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
15 # The Original Code is [Open Source Virtual Machine].
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.
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.
36 # ***** END LICENSE BLOCK *****
43 def writeFileIfChanged(path
, contents
):
44 """Write some contents to a file. Avoids modifying the file timestamp if the file contents already match."""
45 print "Generating " + path
+ "...",
47 outf
= open(path
, "r")
48 oldcontents
= outf
.read()
51 if oldcontents
== contents
:
57 outf
= open(path
, "w")
62 # Figure out TARGET and CPU, a la config.guess
63 # Do cross-compilation in the future, which will require HOST_OS and perhaps
68 cputest
= build
.process
.run_for_output(['uname', '-m'])
69 return _configSub(ostest
, cputest
)
71 def _configSub(ostest
, cputest
):
72 if ostest
.startswith('win') or ostest
.startswith('cygwin'):
74 elif ostest
.startswith('darwin') or ostest
.startswith('apple-darwin'):
76 elif ostest
.startswith('linux') or ostest
.startswith('pc-linux'):
78 elif ostest
.startswith('sunos'):
81 raise Exception('Unrecognized OS: ' + ostest
)
83 if re
.search(r
'^i(\d86|86pc|x86)$', cputest
):
85 elif re
.search('^(x86_64|amd64)$', cputest
):
87 elif re
.search('^(ppc64|powerpc64)$', cputest
):
89 elif re
.search('^(ppc|powerpc|Power Macintosh)$', cputest
):
91 elif re
.search('sun', cputest
):
93 elif re
.search('arm', cputest
):
95 elif re
.search('mips', cputest
):
97 elif re
.search('sh4', cputest
):
100 raise Exception('Unrecognized CPU: ' + cputest
)
105 def __init__(self
, topsrcdir
, options
=None, sourcefile
=None, objdir
=None,
106 optimize
=True, debug
=False):
107 self
._topsrcdir
= topsrcdir
109 self
._objdir
= objdir
111 self
._objdir
= os
.getcwd()
113 self
._optimize
= optimize
115 self
._host
= _configGuess()
116 self
._target
= self
._host
119 srcfile
= self
._topsrcdir
+ "/" + sourcefile
120 if not os
.path
.exists(srcfile
):
121 raise Exception("Source file " + srcfile
+ " doesn't exist.")
123 objfile
= self
._objdir
+ "/" + sourcefile
124 if os
.path
.exists(objfile
):
125 raise Exception("It appears you're trying to build in the source directory. "
126 "(Source file " + objfile
+ " exists here.) "
127 "You must use an object directory to build Tamarin. "
128 "Create an empty directory, cd into it, and run this configure.py script from there.")
132 o
= options
.getStringArg("optimize")
137 d
= options
.getStringArg("debug")
142 hostcpu
, hostos
= options
.host
.split('-', 1)
143 self
._host
= _configSub(hostos
, hostcpu
)
146 targetcpu
, targetos
= options
.target
.split('-', 1)
147 self
._target
= _configSub(targetos
, targetcpu
)
150 'topsrcdir': self
._topsrcdir
,
151 'HOST_OS': self
._host
[0],
152 'TARGET_OS': self
._target
[0],
153 'TARGET_CPU': self
._target
[1]
156 if self
._host
[0] == 'windows':
157 self
._acvars
['topsrcdir'] = toMSYSPath(self
._topsrcdir
)
160 self
._acvars
['ENABLE_DEBUG'] = 1
163 self
._compiler
= 'GCC'
164 self
._acvars
.update({
171 'PROGRAM_SUFFIX': '',
172 'USE_COMPILER_DEPS': 1,
173 'EXPAND_LIBNAME' : '-l$(1)',
174 'EXPAND_DLLNAME' : '-l$(1)',
179 if self
._target
[0] == 'windows':
180 self
._compiler
= 'VS'
181 del self
._acvars
['USE_COMPILER_DEPS']
183 static_crt
= options
.getBoolArg('static-crt')
184 self
._acvars
.update({
185 'OBJ_SUFFIX' : 'obj',
187 'LIB_SUFFIX' : 'lib',
188 'DLL_SUFFIX' : 'dll',
189 'PROGRAM_SUFFIX': '.exe',
190 'CPPFLAGS' : (self
._debug
and '-MTd' or '-MT') or (self
._debug
and '-MDd' or '-MD'),
191 'CXX' : 'cl.exe -nologo',
193 'CC' : 'cl.exe -nologo',
196 'AR' : 'lib.exe -nologo',
197 'LD' : 'link.exe -nologo',
199 'MKSTATICLIB' : '$(AR) -OUT:$(1)',
200 'MKDLL' : '$(LD) -DLL -OUT:$(1)',
201 'MKPROGRAM' : '$(LD) -OUT:$(1)',
202 'EXPAND_LIBNAME' : '$(1).lib',
203 'EXPAND_DLLNAME' : '$(1).lib',
205 'LIBPATH' : '-LIBPATH:'
207 if self
._target
[1] == "arm":
208 self
._acvars
.update({'LDFLAGS' : '-NODEFAULTLIB:"oldnames.lib" -ENTRY:"mainWCRTStartup"'})
209 if sys
.platform
.startswith('cygwin'):
210 self
._acvars
.update({'ASM' : '$(topsrcdir)/build/cygwin-wrapper.sh armasm.exe -nologo -arch 5T'})
212 self
._acvars
.update({'ASM' : 'armasm.exe -nologo -arch 5T'})
214 if self
._target
[1] == "x86_64":
215 if sys
.platform
.startswith('cygwin'):
216 self
._acvars
.update({'MASM' : '$(topsrcdir)/build/cygwin-wrapper.sh ml64.exe -nologo -c '})
218 self
._acvars
.update({'MASM' : 'ml64.exe -nologo -c '})
220 if sys
.platform
.startswith('cygwin'):
221 self
._acvars
.update({'CXX' : '$(topsrcdir)/build/cygwin-wrapper.sh cl.exe -nologo'})
222 self
._acvars
.update({'CC' : '$(topsrcdir)/build/cygwin-wrapper.sh cl.exe -nologo'})
224 # Hackery! Make assumptions that we want to build with GCC 3.3 on MacPPC
225 # and GCC4 on MacIntel
226 elif self
._target
[0] == 'darwin':
227 self
._acvars
.update({
228 'DLL_SUFFIX' : 'dylib',
229 'CPPFLAGS' : '-pipe',
232 'DLL_CFLAGS' : '-fPIC',
233 'LDFLAGS' : '-framework CoreServices',
235 'MKSTATICLIB' : '$(AR) cr $(1)',
236 'MKDLL' : '$(CXX) -dynamiclib -single_module -install_name @executable_path/$(1) -o $(1)',
237 'MKPROGRAM' : '$(CXX) -o $(1)',
238 'POSTMKPROGRAM': 'dsymutil $(1)'
241 # -Wno-trigraphs -Wreturn-type -Wnon-virtual-dtor -Wmissing-braces -Wparentheses -Wunused-label -Wunused-parameter -Wunused-variable -Wunused-value -Wuninitialized
243 if 'CXX' in os
.environ
:
244 self
._acvars
['CXX'] = os
.environ
['CXX']
245 elif self
._target
[1] == 'i686':
246 self
._acvars
['CXX'] = 'g++'
247 self
._acvars
['CXXFLAGS'] += ' -arch i686 '
248 self
._acvars
['LDFLAGS'] += ' -arch i686 '
249 elif self
._target
[1] == 'x86_64':
250 self
._acvars
['CXX'] = 'g++'
251 self
._acvars
['CXXFLAGS'] += ' -arch x86_64 '
252 self
._acvars
['LDFLAGS'] += ' -arch x86_64 '
253 elif self
._target
[1] == 'powerpc':
254 self
._acvars
['CXX'] = 'g++'
255 self
._acvars
['CXXFLAGS'] += ' -arch ppc '
256 self
._acvars
['LDFLAGS'] += ' -arch ppc '
257 elif self
._target
[1] == 'ppc64':
258 self
._acvars
['CXX'] = 'g++'
259 self
._acvars
['CXXFLAGS'] += ' -arch ppc64 '
260 self
._acvars
['LDFLAGS'] += ' -arch ppc64 '
262 raise Exception("Unexpected Darwin processor.")
264 if 'CC' in os
.environ
:
265 self
._acvars
['CC'] = os
.environ
['CC']
266 elif self
._target
[1] == 'i686':
267 self
._acvars
['CC'] = 'gcc'
268 self
._acvars
['CFLAGS'] += ' -arch i686 '
269 elif self
._target
[1] == 'x86_64':
270 self
._acvars
['CC'] = 'gcc'
271 self
._acvars
['CFLAGS'] += ' -arch x86_64 '
272 elif self
._target
[1] == 'powerpc':
273 self
._acvars
['CC'] = 'gcc'
274 self
._acvars
['CFLAGS'] += ' -arch ppc '
275 elif self
._target
[1] == 'ppc64':
276 self
._acvars
['CC'] = 'gcc'
277 self
._acvars
['CFLAGS'] += ' -arch ppc64 '
279 raise Exception("Unexpected Darwin processor.")
281 elif self
._target
[0] == 'linux':
282 self
._acvars
.update({
283 'CPPFLAGS' : os
.environ
.get('CPPFLAGS', ''),
284 'CXX' : os
.environ
.get('CXX', 'g++'),
285 'CXXFLAGS' : os
.environ
.get('CXXFLAGS', ''),
286 'CC' : os
.environ
.get('CC', 'gcc'),
287 'CFLAGS' : os
.environ
.get('CFLAGS', ''),
288 'DLL_CFLAGS' : '-fPIC',
289 'LD' : os
.environ
.get('LD', 'ar'),
290 'LDFLAGS' : os
.environ
.get('LDFLAGS', ''),
291 'AR' : os
.environ
.get('AR', 'ar'),
292 'MKSTATICLIB' : '$(AR) cr $(1)',
293 'MKDLL' : '$(CXX) -shared -o $(1)',
294 'MKPROGRAM' : '$(CXX) -o $(1)'
296 if self
._target
[1] == "mips":
297 self
._acvars
.update({'CXXFLAGS' : ''})
298 self
._acvars
.update({'LDFLAGS' : ''})
299 self
._acvars
.update({'zlib_EXTRA_CFLAGS' : ''})
301 elif self
._target
[0] == 'sunos':
302 if options
.getBoolArg("gcc", False):
303 self
._acvars
.update({
304 'CPPFLAGS' : os
.environ
.get('CPPFLAGS', '') + "-DBROKEN_OFFSETOF",
305 'CXX' : os
.environ
.get('CXX', 'g++'),
306 'CXXFLAGS' : os
.environ
.get('CXXFLAGS', ''),
307 'CC' : os
.environ
.get('CC', 'gcc'),
308 'CFLAGS' : os
.environ
.get('CFLAGS', ''),
309 'DLL_CFLAGS' : '-fPIC',
312 'MKSTATICLIB' : '$(AR) cr $(1)',
313 'MKDLL' : '$(CXX) -shared -o $(1)',
314 'MKPROGRAM' : '$(CXX) -o $(1)'
317 self
._compiler
= 'SunStudio'
318 self
._acvars
.update({
328 'MKSTATICLIB' : '$(AR) cr $(1)',
329 'MKPROGRAM' : '$(CXX) -o $(1)'
331 self
._acvars
['COMPILER'] = self
._compiler
334 """Returns the build directory being configured."""
338 """Returns an (os, cpu) tuple of the host machine."""
342 """Returns an (os, cpu) tuple of the target machine."""
345 def getCompiler(self
):
346 """Returns the compiler in use, as a string.
348 - 'GCC': the GNU Compiler Collection, including GCC and G++
349 - 'VS': Microsoft Visual Studio
350 - 'SunStudio': Sun Studio"""
351 return self
._compiler
356 def subst(self
, name
, value
):
357 self
._acvars
[name
] = value
359 _confvar
= re
.compile("@([^@]+)@")
361 def generate(self
, makefile
):
362 outpath
= self
._objdir
+ "/" + makefile
365 "\n".join([k
+ "=" + str(v
) \
366 for (k
,v
) in self
._acvars
.iteritems()]) + \
367 "\n\ninclude $(topsrcdir)/build/config.mk\n" \
368 "include $(topsrcdir)/manifest.mk\n" \
369 "include $(topsrcdir)/build/rules.mk\n"
371 writeFileIfChanged(outpath
, contents
)
373 def toMSYSPath(path
):
374 if sys
.platform
.startswith('cygwin'):
377 raise ValueError("win32 path without drive letter! %s" % path
)
379 return '/%s%s' % (path
[0], path
[2:].replace('\\', '/'))