The data contained in this repository can be downloaded to your computer using one of several clients.
Please see the documentation of your version control software client for more information.
Please select the desired protocol below to get the URL.
This URL has Read-Only access.
main_repo / configure @ 148f5e65
History | View | Annotate | Download (14.5 KB)
1 |
#!/usr/bin/env python |
---|---|
2 |
import optparse |
3 |
import os |
4 |
import pprint |
5 |
import re |
6 |
import shlex |
7 |
import subprocess |
8 |
import sys |
9 |
|
10 |
CC = os.environ.get('CC', 'cc') |
11 |
|
12 |
root_dir = os.path.dirname(__file__) |
13 |
sys.path.insert(0, os.path.join(root_dir, 'deps', 'v8', 'tools')) |
14 |
|
15 |
# parse our options |
16 |
parser = optparse.OptionParser() |
17 |
|
18 |
parser.add_option("--debug", |
19 |
action="store_true", |
20 |
dest="debug", |
21 |
help="Also build debug build") |
22 |
|
23 |
parser.add_option("--prefix", |
24 |
action="store", |
25 |
dest="prefix", |
26 |
help="Select the install prefix (defaults to /usr/local)") |
27 |
|
28 |
parser.add_option("--without-npm", |
29 |
action="store_true", |
30 |
dest="without_npm", |
31 |
help="Don\'t install the bundled npm package manager") |
32 |
|
33 |
parser.add_option("--without-ssl", |
34 |
action="store_true", |
35 |
dest="without_ssl", |
36 |
help="Build without SSL") |
37 |
|
38 |
parser.add_option("--without-snapshot", |
39 |
action="store_true", |
40 |
dest="without_snapshot", |
41 |
help="Build without snapshotting V8 libraries. You might want to set" |
42 |
" this for cross-compiling. [Default: False]") |
43 |
|
44 |
parser.add_option("--shared-v8", |
45 |
action="store_true", |
46 |
dest="shared_v8", |
47 |
help="Link to a shared V8 DLL instead of static linking") |
48 |
|
49 |
parser.add_option("--shared-v8-includes", |
50 |
action="store", |
51 |
dest="shared_v8_includes", |
52 |
help="Directory containing V8 header files") |
53 |
|
54 |
parser.add_option("--shared-v8-libpath", |
55 |
action="store", |
56 |
dest="shared_v8_libpath", |
57 |
help="A directory to search for the shared V8 DLL") |
58 |
|
59 |
parser.add_option("--shared-v8-libname", |
60 |
action="store", |
61 |
dest="shared_v8_libname", |
62 |
help="Alternative lib name to link to (default: 'v8')") |
63 |
|
64 |
parser.add_option("--shared-openssl", |
65 |
action="store_true", |
66 |
dest="shared_openssl", |
67 |
help="Link to a shared OpenSSl DLL instead of static linking") |
68 |
|
69 |
parser.add_option("--shared-openssl-includes", |
70 |
action="store", |
71 |
dest="shared_openssl_includes", |
72 |
help="Directory containing OpenSSL header files") |
73 |
|
74 |
parser.add_option("--shared-openssl-libpath", |
75 |
action="store", |
76 |
dest="shared_openssl_libpath", |
77 |
help="A directory to search for the shared OpenSSL DLLs") |
78 |
|
79 |
parser.add_option("--shared-openssl-libname", |
80 |
action="store", |
81 |
dest="shared_openssl_libname", |
82 |
help="Alternative lib name to link to (default: 'crypto,ssl')") |
83 |
|
84 |
# deprecated |
85 |
parser.add_option("--openssl-use-sys", |
86 |
action="store_true", |
87 |
dest="shared_openssl", |
88 |
help=optparse.SUPPRESS_HELP) |
89 |
|
90 |
# deprecated |
91 |
parser.add_option("--openssl-includes", |
92 |
action="store", |
93 |
dest="shared_openssl_includes", |
94 |
help=optparse.SUPPRESS_HELP) |
95 |
|
96 |
# deprecated |
97 |
parser.add_option("--openssl-libpath", |
98 |
action="store", |
99 |
dest="shared_openssl_libpath", |
100 |
help=optparse.SUPPRESS_HELP) |
101 |
|
102 |
# TODO document when we've decided on what the tracing API and its options will |
103 |
# look like |
104 |
parser.add_option("--systemtap-includes", |
105 |
action="store", |
106 |
dest="systemtap_includes", |
107 |
help=optparse.SUPPRESS_HELP) |
108 |
|
109 |
parser.add_option("--no-ssl2", |
110 |
action="store_true", |
111 |
dest="no_ssl2", |
112 |
help="Disable OpenSSL v2") |
113 |
|
114 |
parser.add_option("--shared-zlib", |
115 |
action="store_true", |
116 |
dest="shared_zlib", |
117 |
help="Link to a shared zlib DLL instead of static linking") |
118 |
|
119 |
parser.add_option("--shared-zlib-includes", |
120 |
action="store", |
121 |
dest="shared_zlib_includes", |
122 |
help="Directory containing zlib header files") |
123 |
|
124 |
parser.add_option("--shared-zlib-libpath", |
125 |
action="store", |
126 |
dest="shared_zlib_libpath", |
127 |
help="A directory to search for the shared zlib DLL") |
128 |
|
129 |
parser.add_option("--shared-zlib-libname", |
130 |
action="store", |
131 |
dest="shared_zlib_libname", |
132 |
help="Alternative lib name to link to (default: 'z')") |
133 |
|
134 |
parser.add_option("--with-dtrace", |
135 |
action="store_true", |
136 |
dest="with_dtrace", |
137 |
help="Build with DTrace (default is true on sunos)") |
138 |
|
139 |
parser.add_option("--without-dtrace", |
140 |
action="store_true", |
141 |
dest="without_dtrace", |
142 |
help="Build without DTrace") |
143 |
|
144 |
parser.add_option("--with-etw", |
145 |
action="store_true", |
146 |
dest="with_etw", |
147 |
help="Build with ETW (default is true on Windows)") |
148 |
|
149 |
parser.add_option("--without-etw", |
150 |
action="store_true", |
151 |
dest="without_etw", |
152 |
help="Build without ETW") |
153 |
|
154 |
# CHECKME does this still work with recent releases of V8? |
155 |
parser.add_option("--gdb", |
156 |
action="store_true", |
157 |
dest="gdb", |
158 |
help="add gdb support") |
159 |
|
160 |
parser.add_option("--dest-cpu", |
161 |
action="store", |
162 |
dest="dest_cpu", |
163 |
help="CPU architecture to build for. Valid values are: arm, ia32, x64") |
164 |
|
165 |
parser.add_option("--dest-os", |
166 |
action="store", |
167 |
dest="dest_os", |
168 |
help="Operating system to build for. Valid values are: " |
169 |
"win, mac, solaris, freebsd, linux") |
170 |
|
171 |
parser.add_option("--no-ifaddrs", |
172 |
action="store_true", |
173 |
dest="no_ifaddrs", |
174 |
help="Use on deprecated SunOS systems that do not support ifaddrs.h") |
175 |
|
176 |
parser.add_option("--with-arm-float-abi", |
177 |
action="store", |
178 |
dest="arm_float_abi", |
179 |
help="Specifies which floating-point ABI to use. Valid values are: " |
180 |
"soft, softfp, hard") |
181 |
|
182 |
parser.add_option("--ninja", |
183 |
action="store_true", |
184 |
dest="use_ninja", |
185 |
help="Generate files for the ninja build system") |
186 |
|
187 |
# Using --unsafe-optimizations voids your warranty. |
188 |
parser.add_option("--unsafe-optimizations", |
189 |
action="store_true", |
190 |
dest="unsafe_optimizations", |
191 |
help=optparse.SUPPRESS_HELP) |
192 |
|
193 |
(options, args) = parser.parse_args() |
194 |
|
195 |
|
196 |
def b(value): |
197 |
"""Returns the string 'true' if value is truthy, 'false' otherwise.""" |
198 |
if value: |
199 |
return 'true' |
200 |
else: |
201 |
return 'false' |
202 |
|
203 |
|
204 |
def pkg_config(pkg): |
205 |
cmd = os.popen('pkg-config --libs %s' % pkg, 'r') |
206 |
libs = cmd.readline().strip() |
207 |
ret = cmd.close() |
208 |
if (ret): return None |
209 |
|
210 |
cmd = os.popen('pkg-config --cflags %s' % pkg, 'r') |
211 |
cflags = cmd.readline().strip() |
212 |
ret = cmd.close() |
213 |
if (ret): return None |
214 |
|
215 |
return (libs, cflags) |
216 |
|
217 |
|
218 |
def cc_macros(): |
219 |
"""Checks predefined macros using the CC command.""" |
220 |
|
221 |
try: |
222 |
p = subprocess.Popen(shlex.split(CC) + ['-dM', '-E', '-'], |
223 |
stdin=subprocess.PIPE, |
224 |
stdout=subprocess.PIPE, |
225 |
stderr=subprocess.PIPE) |
226 |
except OSError: |
227 |
print '''Node.js configure error: No acceptable C compiler found! |
228 |
|
229 |
Please make sure you have a C compiler installed on your system and/or |
230 |
consider adjusting the CC environment variable if you installed |
231 |
it in a non-standard prefix. |
232 |
''' |
233 |
sys.exit() |
234 |
|
235 |
p.stdin.write('\n') |
236 |
out = p.communicate()[0] |
237 |
|
238 |
out = str(out).split('\n') |
239 |
|
240 |
k = {} |
241 |
for line in out: |
242 |
lst = shlex.split(line) |
243 |
if len(lst) > 2: |
244 |
key = lst[1] |
245 |
val = lst[2] |
246 |
k[key] = val |
247 |
return k |
248 |
|
249 |
|
250 |
def is_arch_armv7(): |
251 |
"""Check for ARMv7 instructions""" |
252 |
cc_macros_cache = cc_macros() |
253 |
return ('__ARM_ARCH_7__' in cc_macros_cache or |
254 |
'__ARM_ARCH_7A__' in cc_macros_cache or |
255 |
'__ARM_ARCH_7R__' in cc_macros_cache or |
256 |
'__ARM_ARCH_7M__' in cc_macros_cache) |
257 |
|
258 |
|
259 |
def arm_hard_float_abi(): |
260 |
"""Check for hardfloat or softfloat eabi on ARM""" |
261 |
# GCC versions 4.6 and above define __ARM_PCS or __ARM_PCS_VFP to specify |
262 |
# the Floating Point ABI used (PCS stands for Procedure Call Standard). |
263 |
# We use these as well as a couple of other defines to statically determine |
264 |
# what FP ABI used. |
265 |
# GCC versions 4.4 and below don't support hard-fp. |
266 |
# GCC versions 4.5 may support hard-fp without defining __ARM_PCS or |
267 |
# __ARM_PCS_VFP. |
268 |
|
269 |
if compiler_version() >= (4, 6, 0): |
270 |
return '__ARM_PCS_VFP' in cc_macros() |
271 |
elif compiler_version() < (4, 5, 0): |
272 |
return False |
273 |
elif '__ARM_PCS_VFP' in cc_macros(): |
274 |
return True |
275 |
elif ('__ARM_PCS' in cc_macros() or |
276 |
'__SOFTFP' in cc_macros() or |
277 |
not '__VFP_FP__' in cc_macros()): |
278 |
return False |
279 |
else: |
280 |
print '''Node.js configure error: Your version of GCC does not report |
281 |
the Floating-Point ABI to compile for your hardware |
282 |
|
283 |
Please manually specify which floating-point ABI to use with the |
284 |
--with-arm-float-abi option. |
285 |
''' |
286 |
sys.exit() |
287 |
|
288 |
|
289 |
def host_arch_cc(): |
290 |
"""Host architecture check using the CC command.""" |
291 |
|
292 |
k = cc_macros() |
293 |
|
294 |
matchup = { |
295 |
'__x86_64__' : 'x64', |
296 |
'__i386__' : 'ia32', |
297 |
'__arm__' : 'arm', |
298 |
} |
299 |
|
300 |
rtn = 'ia32' # default |
301 |
|
302 |
for i in matchup: |
303 |
if i in k and k[i] != '0': |
304 |
rtn = matchup[i] |
305 |
break |
306 |
|
307 |
return rtn |
308 |
|
309 |
|
310 |
def host_arch_win(): |
311 |
"""Host architecture check using environ vars (better way to do this?)""" |
312 |
|
313 |
arch = os.environ.get('PROCESSOR_ARCHITECTURE', 'x86') |
314 |
|
315 |
matchup = { |
316 |
'AMD64' : 'x64', |
317 |
'x86' : 'ia32', |
318 |
'arm' : 'arm', |
319 |
} |
320 |
|
321 |
return matchup.get(arch, 'ia32') |
322 |
|
323 |
|
324 |
def compiler_version(): |
325 |
try: |
326 |
proc = subprocess.Popen(shlex.split(CC) + ['--version'], stdout=subprocess.PIPE) |
327 |
except WindowsError: |
328 |
return (0, False) |
329 |
|
330 |
is_clang = 'clang' in proc.communicate()[0].split('\n')[0] |
331 |
|
332 |
proc = subprocess.Popen(shlex.split(CC) + ['-dumpversion'], stdout=subprocess.PIPE) |
333 |
version = tuple(map(int, proc.communicate()[0].split('.'))) |
334 |
|
335 |
return (version, is_clang) |
336 |
|
337 |
|
338 |
def configure_arm(o): |
339 |
# V8 on ARM requires that armv7 is set. CPU Model detected by |
340 |
# the presence of __ARM_ARCH_7__ and the like defines in compiler |
341 |
if options.arm_float_abi: |
342 |
hard_float = options.arm_float_abi == 'hard' |
343 |
else: |
344 |
hard_float = arm_hard_float_abi() |
345 |
o['variables']['v8_use_arm_eabi_hardfloat'] = b(hard_float) |
346 |
|
347 |
armv7 = is_arch_armv7() |
348 |
if armv7: |
349 |
# CHECKME VFPv3 implies ARMv7+ but is the reverse true as well? |
350 |
o['variables']['arm_fpu'] = 'vfpv3' |
351 |
o['variables']['arm_neon'] = 0 |
352 |
o['variables']['armv7'] = int(armv7) |
353 |
|
354 |
|
355 |
def configure_node(o): |
356 |
o['variables']['v8_enable_gdbjit'] = 1 if options.gdb else 0 |
357 |
o['variables']['v8_no_strict_aliasing'] = 1 # work around compiler bugs |
358 |
o['variables']['node_prefix'] = os.path.expanduser(options.prefix or '') |
359 |
o['variables']['node_install_npm'] = b(not options.without_npm) |
360 |
o['variables']['node_unsafe_optimizations'] = ( |
361 |
1 if options.unsafe_optimizations else 0) |
362 |
o['default_configuration'] = 'Debug' if options.debug else 'Release' |
363 |
|
364 |
host_arch = host_arch_win() if os.name == 'nt' else host_arch_cc() |
365 |
target_arch = options.dest_cpu or host_arch |
366 |
o['variables']['host_arch'] = host_arch |
367 |
o['variables']['target_arch'] = target_arch |
368 |
|
369 |
if target_arch == 'arm': |
370 |
configure_arm(o) |
371 |
|
372 |
cc_version, is_clang = compiler_version() |
373 |
o['variables']['clang'] = 1 if is_clang else 0 |
374 |
|
375 |
if not is_clang and cc_version != 0: |
376 |
o['variables']['gcc_version'] = 10 * cc_version[0] + cc_version[1] |
377 |
|
378 |
# clang has always supported -fvisibility=hidden, right? |
379 |
if not is_clang and cc_version < (4,0,0): |
380 |
o['variables']['visibility'] = '' |
381 |
|
382 |
# By default, enable DTrace on SunOS systems. Don't allow it on other |
383 |
# systems, since it won't work. (The MacOS build process is different than |
384 |
# SunOS, and we haven't implemented it.) |
385 |
if sys.platform.startswith('sunos'): |
386 |
o['variables']['node_use_dtrace'] = b(not options.without_dtrace) |
387 |
elif sys.platform.startswith('linux'): |
388 |
o['variables']['node_use_dtrace'] = 'false' |
389 |
o['variables']['node_use_systemtap'] = b(options.with_dtrace) |
390 |
if options.systemtap_includes: |
391 |
o['include_dirs'] += [options.systemtap_includes] |
392 |
elif b(options.with_dtrace) == 'true': |
393 |
raise Exception( |
394 |
'DTrace is currently only supported on SunOS or Linux systems.') |
395 |
else: |
396 |
o['variables']['node_use_dtrace'] = 'false' |
397 |
o['variables']['node_use_systemtap'] = 'false' |
398 |
|
399 |
if options.no_ifaddrs: |
400 |
o['defines'] += ['SUNOS_NO_IFADDRS'] |
401 |
|
402 |
# By default, enable ETW on Windows. |
403 |
if sys.platform.startswith('win32'): |
404 |
o['variables']['node_use_etw'] = b(not options.without_etw); |
405 |
elif b(options.with_etw) == 'true': |
406 |
raise Exception('ETW is only supported on Windows.') |
407 |
else: |
408 |
o['variables']['node_use_etw'] = 'false' |
409 |
|
410 |
|
411 |
def configure_libz(o): |
412 |
o['variables']['node_shared_zlib'] = b(options.shared_zlib) |
413 |
|
414 |
# assume shared_zlib if one of these is set? |
415 |
if options.shared_zlib_libpath: |
416 |
o['libraries'] += ['-L%s' % options.shared_zlib_libpath] |
417 |
if options.shared_zlib_libname: |
418 |
o['libraries'] += ['-l%s' % options.shared_zlib_libname] |
419 |
elif options.shared_zlib: |
420 |
o['libraries'] += ['-lz'] |
421 |
if options.shared_zlib_includes: |
422 |
o['include_dirs'] += [options.shared_zlib_includes] |
423 |
|
424 |
|
425 |
def configure_v8(o): |
426 |
o['variables']['v8_use_snapshot'] = b(not options.without_snapshot) |
427 |
o['variables']['node_shared_v8'] = b(options.shared_v8) |
428 |
|
429 |
# assume shared_v8 if one of these is set? |
430 |
if options.shared_v8_libpath: |
431 |
o['libraries'] += ['-L%s' % options.shared_v8_libpath] |
432 |
if options.shared_v8_libname: |
433 |
o['libraries'] += ['-l%s' % options.shared_v8_libname] |
434 |
elif options.shared_v8: |
435 |
o['libraries'] += ['-lv8'] |
436 |
if options.shared_v8_includes: |
437 |
o['include_dirs'] += [options.shared_v8_includes] |
438 |
|
439 |
|
440 |
def configure_openssl(o): |
441 |
o['variables']['node_use_openssl'] = b(not options.without_ssl) |
442 |
o['variables']['node_shared_openssl'] = b(options.shared_openssl) |
443 |
|
444 |
if options.without_ssl: |
445 |
return |
446 |
|
447 |
if options.no_ssl2: |
448 |
o['defines'] += ['OPENSSL_NO_SSL2=1'] |
449 |
|
450 |
if options.shared_openssl: |
451 |
(libs, cflags) = pkg_config('openssl') or ('-lssl -lcrypto', '') |
452 |
|
453 |
if options.shared_openssl_libpath: |
454 |
o['libraries'] += ['-L%s' % options.shared_openssl_libpath] |
455 |
|
456 |
if options.shared_openssl_libname: |
457 |
libnames = options.shared_openssl_libname.split(',') |
458 |
o['libraries'] += ['-l%s' % s for s in libnames] |
459 |
else: |
460 |
o['libraries'] += libs.split() |
461 |
|
462 |
if options.shared_openssl_includes: |
463 |
o['include_dirs'] += [options.shared_openssl_includes] |
464 |
else: |
465 |
o['cflags'] += cflags.split() |
466 |
|
467 |
|
468 |
output = { |
469 |
'variables': {}, |
470 |
'include_dirs': [], |
471 |
'libraries': [], |
472 |
'defines': [], |
473 |
'cflags': [], |
474 |
} |
475 |
|
476 |
configure_node(output) |
477 |
configure_libz(output) |
478 |
configure_v8(output) |
479 |
configure_openssl(output) |
480 |
|
481 |
# variables should be a root level element, |
482 |
# move everything else to target_defaults |
483 |
variables = output['variables'] |
484 |
del output['variables'] |
485 |
output = { |
486 |
'variables': variables, |
487 |
'target_defaults': output |
488 |
} |
489 |
pprint.pprint(output, indent=2) |
490 |
|
491 |
def write(filename, data): |
492 |
filename = os.path.join(root_dir, filename) |
493 |
print "creating ", filename |
494 |
f = open(filename, 'w+') |
495 |
f.write(data) |
496 |
|
497 |
write('config.gypi', "# Do not edit. Generated by the configure script.\n" + |
498 |
pprint.pformat(output, indent=2) + "\n") |
499 |
|
500 |
config = { |
501 |
'BUILDTYPE': 'Debug' if options.debug else 'Release', |
502 |
'USE_NINJA': str(int(options.use_ninja or 0)), |
503 |
} |
504 |
config = '\n'.join(map('='.join, config.iteritems())) + '\n' |
505 |
|
506 |
write('config.mk', |
507 |
'# Do not edit. Generated by the configure script.\n' + config) |
508 |
|
509 |
if options.use_ninja: |
510 |
gyp_args = ['-f', 'ninja'] |
511 |
elif os.name == 'nt': |
512 |
gyp_args = ['-f', 'msvs', '-G', 'msvs_version=auto'] |
513 |
elif options.dest_os: |
514 |
gyp_args = ['-f', 'make-' + options.dest_os] |
515 |
else: |
516 |
gyp_args = ['-f', 'make'] |
517 |
|
518 |
subprocess.call([sys.executable, 'tools/gyp_node'] + gyp_args) |