common.py revision 1e71283ccee61aa5d774fdef6d7668d3376d3a6d
1#######################################################################
2# Common SCons code
3
4import os
5import os.path
6import sys
7import platform as _platform
8
9
10#######################################################################
11# Defaults
12
13_platform_map = {
14	'linux2': 'linux',
15	'win32': 'winddk',
16}
17
18default_platform = sys.platform
19default_platform = _platform_map.get(default_platform, default_platform)
20
21_machine_map = {
22	'x86': 'x86',
23	'i386': 'x86',
24	'i486': 'x86',
25	'i586': 'x86',
26	'i686': 'x86',
27	'x86_64': 'x86_64',
28}
29if 'PROCESSOR_ARCHITECTURE' in os.environ:
30	default_machine = os.environ['PROCESSOR_ARCHITECTURE']
31else:
32	default_machine = _platform.machine()
33default_machine = _machine_map.get(default_machine, 'generic')
34
35if default_platform in ('linux', 'freebsd', 'darwin'):
36	default_dri = 'yes'
37elif default_platform in ('winddk', 'windows'):
38	default_dri = 'no'
39else:
40	default_dri = 'no'
41
42
43#######################################################################
44# Common options
45
46def AddOptions(opts):
47	from SCons.Options.BoolOption import BoolOption
48	from SCons.Options.EnumOption import EnumOption
49	opts.Add(BoolOption('debug', 'build debug version', 'no'))
50	#opts.Add(BoolOption('quiet', 'quiet command lines', 'no'))
51	opts.Add(EnumOption('machine', 'use machine-specific assembly code', default_machine,
52											 allowed_values=('generic', 'x86', 'x86_64')))
53	opts.Add(EnumOption('platform', 'target platform', default_platform,
54											 allowed_values=('linux', 'cell', 'windows', 'winddk')))
55	opts.Add(BoolOption('llvm', 'use LLVM', 'no'))
56	opts.Add(BoolOption('dri', 'build DRI drivers', default_dri))
57
58
59#######################################################################
60# Quiet command lines
61#
62# See also http://www.scons.org/wiki/HidingCommandLinesInOutput
63
64def quietCommandLines(env):
65	env['CCCOMSTR'] = "Compiling $SOURCE ..."
66	env['CXXCOMSTR'] = "Compiling $SOURCE ..."
67	env['ARCOMSTR'] = "Archiving $TARGET ..."
68	env['RANLIBCOMSTR'] = ""
69	env['LINKCOMSTR'] = "Linking $TARGET ..."
70
71
72#######################################################################
73# Convenience Library Builder
74# based on the stock StaticLibrary and SharedLibrary builders
75
76import SCons.Action
77import SCons.Builder
78
79def createConvenienceLibBuilder(env):
80    """This is a utility function that creates the ConvenienceLibrary
81    Builder in an Environment if it is not there already.
82
83    If it is already there, we return the existing one.
84    """
85
86    try:
87        convenience_lib = env['BUILDERS']['ConvenienceLibrary']
88    except KeyError:
89        action_list = [ SCons.Action.Action("$ARCOM", "$ARCOMSTR") ]
90        if env.Detect('ranlib'):
91            ranlib_action = SCons.Action.Action("$RANLIBCOM", "$RANLIBCOMSTR")
92            action_list.append(ranlib_action)
93
94        convenience_lib = SCons.Builder.Builder(action = action_list,
95                                  emitter = '$LIBEMITTER',
96                                  prefix = '$LIBPREFIX',
97                                  suffix = '$LIBSUFFIX',
98                                  src_suffix = '$SHOBJSUFFIX',
99                                  src_builder = 'SharedObject')
100        env['BUILDERS']['ConvenienceLibrary'] = convenience_lib
101        env['BUILDERS']['Library'] = convenience_lib
102
103    return convenience_lib
104
105
106#######################################################################
107# Build
108
109def make_build_dir(env):
110	# Put build output in a separate dir, which depends on the current configuration
111	# See also http://www.scons.org/wiki/AdvancedBuildExample
112	build_topdir = 'build'
113	build_subdir = env['platform']
114	if env['dri']:
115		build_subdir += "-dri"
116	if env['llvm']:
117		build_subdir += "-llvm"
118	if env['machine'] != 'generic':
119		build_subdir += '-' + env['machine']
120	if env['debug']:
121		build_subdir += "-debug"
122	build_dir = os.path.join(build_topdir, build_subdir)
123	# Place the .sconsign file on the builddir too, to avoid issues with different scons
124	# versions building the same source file
125	env.SConsignFile(os.path.join(build_dir, '.sconsign'))
126	return build_dir
127
128
129#######################################################################
130# Common environment generation code
131
132def generate(env):
133	# FIXME: this is already too late
134	#if env.get('quiet', False):
135	#	quietCommandLines(env)
136
137	# shortcuts
138	debug = env['debug']
139	machine = env['machine']
140	platform = env['platform']
141	x86 = env['machine'] == 'x86'
142	gcc = env['platform'] in ('linux', 'freebsd', 'darwin')
143	msvc = env['platform'] in ('windows', 'winddk')
144
145	# C preprocessor options
146	cppdefines = []
147	if debug:
148		cppdefines += ['DEBUG']
149	else:
150		cppdefines += ['NDEBUG']
151	if platform == 'windows':
152		cppdefines += [
153			'WIN32',
154			'_WINDOWS',
155			'_UNICODE',
156			'UNICODE',
157			# http://msdn2.microsoft.com/en-us/library/6dwk3a1z.aspx,
158			'WIN32_LEAN_AND_MEAN',
159			'VC_EXTRALEAN',
160			'_CRT_SECURE_NO_DEPRECATE',
161		]
162		if debug:
163			cppdefines += ['_DEBUG']
164	if platform == 'winddk':
165		# Mimic WINDDK's builtin flags. See also:
166		# - WINDDK's bin/makefile.new i386mk.inc for more info.
167		# - buildchk_wxp_x86.log files, generated by the WINDDK's build
168		# - http://alter.org.ua/docs/nt_kernel/vc8_proj/
169		cppdefines += [
170			('_X86_', '1'),
171			('i386', '1'),
172			'STD_CALL',
173			('CONDITION_HANDLING', '1'),
174			('NT_INST', '0'),
175			('WIN32', '100'),
176			('_NT1X_', '100'),
177			('WINNT', '1'),
178			('_WIN32_WINNT', '0x0501'), # minimum required OS version
179			('WINVER', '0x0501'),
180			('_WIN32_IE', '0x0603'),
181			('WIN32_LEAN_AND_MEAN', '1'),
182			('DEVL', '1'),
183			('__BUILDMACHINE__', 'WinDDK'),
184			('FPO', '0'),
185		]
186		if debug:
187			cppdefines += [('DBG', 1)]
188	if platform == 'windows':
189		cppdefines += ['PIPE_SUBSYSTEM_USER']
190	if platform == 'winddk':
191		cppdefines += ['PIPE_SUBSYSTEM_KERNEL']
192	env.Append(CPPDEFINES = cppdefines)
193
194	# C compiler options
195	cflags = []
196	if gcc:
197		if debug:
198			cflags += ['-O0', '-g3']
199		else:
200			cflags += ['-O3', '-g3']
201		cflags += [
202			'-Wall',
203			'-Wmissing-prototypes',
204			'-Wno-long-long',
205			'-ffast-math',
206			'-pedantic',
207			'-fmessage-length=0', # be nice to Eclipse
208		]
209	if msvc:
210		# See also:
211		# - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
212		# - cl /?
213		if debug:
214			cflags += [
215			  '/Od', # disable optimizations
216			  '/Oi', # enable intrinsic functions
217			  '/Oy-', # disable frame pointer omission
218			]
219		else:
220			cflags += [
221			  '/Ox', # maximum optimizations
222			  '/Oi', # enable intrinsic functions
223			  '/Os', # favor code space
224			]
225		if platform == 'windows':
226			cflags += [
227				# TODO
228				#'/Wp64', # enable 64 bit porting warnings
229			]
230		if platform == 'winddk':
231			cflags += [
232				'/Zl', # omit default library name in .OBJ
233				'/Zp8', # 8bytes struct member alignment
234				'/Gy', # separate functions for linker
235				'/Gm-', # disable minimal rebuild
236				'/W3', # warning level
237				'/WX', # treat warnings as errors
238				'/Gz', # __stdcall Calling convention
239				'/GX-', # disable C++ EH
240				'/GR-', # disable C++ RTTI
241				'/GF', # enable read-only string pooling
242				'/GS', # enable security checks
243				'/G6', # optimize for PPro, P-II, P-III
244				'/Ze', # enable extensions
245				#'/Gi-', # ???
246				'/QIfdiv-', # disable Pentium FDIV fix
247				#'/hotpatch', # ???
248				#'/Z7', #enable old-style debug info
249			]
250		# Put debugging information in a separate .pdb file for each object file as
251		# descrived in the scons manpage
252		env['CCPDBFLAGS'] = '/Zi /Fd${TARGET}.pdb'
253	env.Append(CFLAGS = cflags)
254	env.Append(CXXFLAGS = cflags)
255
256	# Linker options
257	if platform == 'winddk':
258		# See also:
259		# - http://msdn2.microsoft.com/en-us/library/y0zzbyt4.aspx
260		env.Append(LINKFLAGS = [
261			'/merge:_PAGE=PAGE',
262			'/merge:_TEXT=.text',
263			'/section:INIT,d',
264			'/opt:ref',
265			'/opt:icf',
266			'/ignore:4198,4010,4037,4039,4065,4070,4078,4087,4089,4221',
267			'/incremental:no',
268			'/fullbuild',
269			'/release',
270			'/nodefaultlib',
271			'/wx',
272			'/debug',
273			'/debugtype:cv',
274			'/version:5.1',
275			'/osversion:5.1',
276			'/functionpadmin:5',
277			'/safeseh',
278			'/pdbcompress',
279			'/stack:0x40000,0x1000',
280			'/driver',
281			'/align:0x80',
282			'/subsystem:native,5.01',
283			'/base:0x10000',
284
285			'/entry:DrvEnableDriver',
286		])
287
288
289	createConvenienceLibBuilder(env)
290
291
292	# for debugging
293	#print env.Dump()
294
295