3 # Copyright Joyent, Inc. and other Node contributors.
5 # Permission is hereby granted, free of charge, to any person obtaining a
6 # copy of this software and associated documentation files (the
7 # "Software"), to deal in the Software without restriction, including
8 # without limitation the rights to use, copy, modify, merge, publish,
9 # distribute, sublicense, and/or sell copies of the Software, and to permit
10 # persons to whom the Software is furnished to do so, subject to the
11 # following conditions:
13 # The above copyright notice and this permission notice shall be included
14 # in all copies or substantial portions of the Software.
16 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN
19 # NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
20 # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
21 # OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE
22 # USE OR OTHER DEALINGS IN THE SOFTWARE.
26 import sys, os, shutil, glob
28 from Utils import cmd_output
29 from os.path import join, dirname, abspath, normpath
30 from logging import fatal
35 # Use the directory that this file is found in to find the tools
36 # directory where the js2c.py file can be found.
37 sys.path.append(sys.argv[0] + '/tools');
40 if sys.platform.startswith("cygwin"):
41 print "cygwin not supported"
46 supported_archs = ('arm', 'ia32', 'x64') # 'mips' supported by v8, but not node
49 if os.environ.has_key('JOBS'):
50 jobs = int(os.environ['JOBS'])
53 return path.replace("\\", "/")
55 def canonical_cpu_type(arch):
56 m = {'x86': 'ia32', 'i386':'ia32', 'x86_64':'x64', 'amd64':'x64'}
57 if arch in m: arch = m[arch]
58 if not arch in supported_archs:
59 raise Exception("supported architectures are "+', '.join(supported_archs)+\
60 " but NOT '" + arch + "'.")
64 # the gcc module provides a --debug-level option
65 opt.tool_options('compiler_cxx')
66 opt.tool_options('compiler_cc')
67 opt.tool_options('misc')
68 opt.add_option( '--libdir'
72 , help='Install into this libdir [Release: ${PREFIX}/lib]'
74 opt.add_option( '--debug'
77 , help='Build debug variant [Release: False]'
80 opt.add_option( '--profile'
83 , help='Enable profiling [Release: False]'
86 opt.add_option( '--efence'
89 , help='Build with -lefence for debugging [Release: False]'
93 opt.add_option( '--without-snapshot'
96 , help='Build without snapshotting V8 libraries. You might want to set this for cross-compiling. [Release: False]'
97 , dest='without_snapshot'
100 opt.add_option( '--without-ssl'
101 , action='store_true'
103 , help='Build without SSL'
108 opt.add_option('--shared-v8'
109 , action='store_true'
111 , help='Link to a shared V8 DLL instead of static linking'
115 opt.add_option( '--shared-v8-includes'
118 , help='Directory containing V8 header files'
119 , dest='shared_v8_includes'
122 opt.add_option( '--shared-v8-libpath'
125 , help='A directory to search for the shared V8 DLL'
126 , dest='shared_v8_libpath'
129 opt.add_option( '--shared-v8-libname'
132 , help="Alternative lib name to link to (default: 'v8')"
133 , dest='shared_v8_libname'
136 opt.add_option( '--openssl-includes'
139 , help='A directory to search for the OpenSSL includes'
140 , dest='openssl_includes'
143 opt.add_option( '--openssl-libpath'
146 , help="A directory to search for the OpenSSL libraries"
147 , dest='openssl_libpath'
150 opt.add_option( '--no-ssl2'
151 , action='store_true'
153 , help="Disable OpenSSL v2"
154 , dest='openssl_nov2'
157 opt.add_option( '--gdb'
158 , action='store_true'
160 , help="add gdb support"
165 opt.add_option( '--shared-zlib'
166 , action='store_true'
168 , help='Link to a shared zlib DLL instead of static linking'
172 opt.add_option( '--shared-zlib-includes'
175 , help='Directory containing zlib header files'
176 , dest='shared_zlib_includes'
179 opt.add_option( '--shared-zlib-libpath'
182 , help='A directory to search for the shared zlib DLL'
183 , dest='shared_zlib_libpath'
187 opt.add_option( '--shared-cares'
188 , action='store_true'
190 , help='Link to a shared C-Ares DLL instead of static linking'
191 , dest='shared_cares'
194 opt.add_option( '--shared-cares-includes'
197 , help='Directory containing C-Ares header files'
198 , dest='shared_cares_includes'
201 opt.add_option( '--shared-cares-libpath'
204 , help='A directory to search for the shared C-Ares DLL'
205 , dest='shared_cares_libpath'
209 opt.add_option( '--with-dtrace'
210 , action='store_true'
212 , help='Build with DTrace (experimental)'
217 opt.add_option( '--product-type'
220 , help='What kind of product to produce (program, cstaticlib '\
221 'or cshlib) [default: %default]'
222 , dest='product_type'
225 opt.add_option( '--dest-cpu'
228 , help='CPU architecture to build for. Valid values are: '+\
229 ', '.join(supported_archs)
233 def get_node_version():
234 def get_define_value(lines, define):
237 return line.split()[-1] #define <NAME> <VALUE>
239 lines = open("src/node_version.h").readlines()
240 node_major_version = get_define_value(lines, 'NODE_MAJOR_VERSION')
241 node_minor_version = get_define_value(lines, 'NODE_MINOR_VERSION')
242 node_patch_version = get_define_value(lines, 'NODE_PATCH_VERSION')
243 node_is_release = get_define_value(lines, 'NODE_VERSION_IS_RELEASE')
245 return "%s.%s.%s%s" % ( node_major_version,
248 node_is_release == "0" and "-pre" or ""
254 conf.check_tool('compiler_cxx')
255 if not conf.env.CXX: conf.fatal('c++ compiler not found')
256 conf.check_tool('compiler_cc')
257 if not conf.env.CC: conf.fatal('c compiler not found')
262 conf.env['LIBDIR'] = o.libdir
264 conf.env['LIBDIR'] = conf.env['PREFIX'] + '/lib'
266 conf.env["USE_DEBUG"] = o.debug
267 # Snapshot building does noet seem to work on mingw32
268 conf.env["SNAPSHOT_V8"] = not o.without_snapshot and not sys.platform.startswith("win32")
269 if sys.platform.startswith("sunos"):
270 conf.env["SNAPSHOT_V8"] = False
271 conf.env["USE_PROFILING"] = o.profile
273 conf.env["USE_SHARED_V8"] = o.shared_v8 or o.shared_v8_includes or o.shared_v8_libpath or o.shared_v8_libname
274 conf.env["USE_SHARED_CARES"] = o.shared_cares or o.shared_cares_includes or o.shared_cares_libpath
275 conf.env["USE_SHARED_ZLIB"] = o.shared_zlib or o.shared_zlib_includes or o.shared_zlib_libpath
277 conf.env["USE_GDBJIT"] = o.use_gdbjit
279 if not conf.env["USE_SHARED_ZLIB"] and not sys.platform.startswith("win32"):
280 conf.env.append_value("LINKFLAGS", "-lz")
282 conf.check(lib='dl', uselib_store='DL')
283 if not sys.platform.startswith("sunos") and not sys.platform.startswith("win32"):
284 conf.env.append_value("CCFLAGS", "-rdynamic")
285 conf.env.append_value("LINKFLAGS_DL", "-rdynamic")
287 if sys.platform.startswith("freebsd") or sys.platform.startswith("openbsd"):
288 conf.check(lib='kvm', uselib_store='KVM')
290 #if Options.options.debug:
291 # conf.check(lib='profiler', uselib_store='PROFILER')
293 if Options.options.dtrace:
294 if not sys.platform.startswith("sunos"):
295 conf.fatal('DTrace support only currently available on Solaris')
297 conf.find_program('dtrace', var='DTRACE', mandatory=True)
298 conf.env["USE_DTRACE"] = True
299 conf.env.append_value("CXXFLAGS", "-DHAVE_DTRACE=1")
301 if Options.options.efence:
302 conf.check(lib='efence', libpath=['/usr/lib', '/usr/local/lib'], uselib_store='EFENCE')
304 if sys.platform.startswith("freebsd"):
305 if not conf.check(lib="execinfo",
306 includes=['/usr/include', '/usr/local/include'],
307 libpath=['/usr/lib', '/usr/local/lib'],
308 uselib_store="EXECINFO"):
309 conf.fatal("Install the libexecinfo port from /usr/ports/devel/libexecinfo.")
311 if not Options.options.without_ssl:
312 # Don't override explicitly supplied openssl paths with pkg-config results.
313 explicit_openssl = o.openssl_includes or o.openssl_libpath
315 # Disable ssl v2 methods
317 conf.env.append_value("CPPFLAGS", "-DOPENSSL_NO_SSL2=1")
319 if not explicit_openssl and conf.check_cfg(package='openssl',
320 args='--cflags --libs',
321 uselib_store='OPENSSL'):
322 Options.options.use_openssl = conf.env["USE_OPENSSL"] = True
323 conf.env.append_value("CPPFLAGS", "-DHAVE_OPENSSL=1")
325 if o.openssl_libpath:
326 openssl_libpath = [o.openssl_libpath]
327 elif not sys.platform.startswith('win32'):
328 openssl_libpath = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/usr/sfw/lib']
330 openssl_libpath = [normpath(join(cwd, '../openssl'))]
332 if o.openssl_includes:
333 openssl_includes = [o.openssl_includes]
334 elif not sys.platform.startswith('win32'):
335 openssl_includes = [];
337 openssl_includes = [normpath(join(cwd, '../openssl/include'))];
339 openssl_lib_names = ['ssl', 'crypto']
340 if sys.platform.startswith('win32'):
341 openssl_lib_names += ['ws2_32', 'gdi32']
343 libssl = conf.check_cc(lib=openssl_lib_names,
344 header_name='openssl/ssl.h',
345 function_name='SSL_library_init',
346 includes=openssl_includes,
347 libpath=openssl_libpath,
348 uselib_store='OPENSSL')
350 libcrypto = conf.check_cc(lib='crypto',
351 header_name='openssl/crypto.h',
352 includes=openssl_includes,
353 libpath=openssl_libpath,
354 uselib_store='OPENSSL')
356 if libcrypto and libssl:
357 conf.env["USE_OPENSSL"] = Options.options.use_openssl = True
358 conf.env.append_value("CPPFLAGS", "-DHAVE_OPENSSL=1")
359 elif sys.platform.startswith('win32'):
360 conf.fatal("Could not autodetect OpenSSL support. " +
361 "Use the --openssl-libpath and --openssl-includes options to set the search path. " +
362 "Use configure --without-ssl to disable this message.")
364 conf.fatal("Could not autodetect OpenSSL support. " +
365 "Make sure OpenSSL development packages are installed. " +
366 "Use configure --without-ssl to disable this message.")
368 Options.options.use_openssl = conf.env["USE_OPENSSL"] = False
370 conf.check(lib='util', libpath=['/usr/lib', '/usr/local/lib'],
373 # normalize DEST_CPU from --dest-cpu, DEST_CPU or built-in value
374 if Options.options.dest_cpu and Options.options.dest_cpu:
375 conf.env['DEST_CPU'] = canonical_cpu_type(Options.options.dest_cpu)
376 elif 'DEST_CPU' in os.environ and os.environ['DEST_CPU']:
377 conf.env['DEST_CPU'] = canonical_cpu_type(os.environ['DEST_CPU'])
378 elif 'DEST_CPU' in conf.env and conf.env['DEST_CPU']:
379 conf.env['DEST_CPU'] = canonical_cpu_type(conf.env['DEST_CPU'])
381 have_librt = conf.check(lib='rt', uselib_store='RT')
383 have_monotonic = False
389 clock_gettime(CLOCK_MONOTONIC, &now);
393 have_monotonic = conf.check_cc(lib="rt", msg="Checking for CLOCK_MONOTONIC", fragment=code)
396 conf.env.append_value('CPPFLAGS', '-DHAVE_MONOTONIC_CLOCK=1')
398 conf.env.append_value('CPPFLAGS', '-DHAVE_MONOTONIC_CLOCK=0')
400 if sys.platform.startswith("sunos"):
404 struct ifaddrs hello;
409 if conf.check_cc(msg="Checking for ifaddrs on solaris", fragment=code):
410 conf.env.append_value('CPPFLAGS', '-DSUNOS_HAVE_IFADDRS')
412 if not conf.check(lib='socket', uselib_store="SOCKET"):
413 conf.fatal("Cannot find socket library")
414 if not conf.check(lib='nsl', uselib_store="NSL"):
415 conf.fatal("Cannot find nsl library")
416 if not conf.check(lib='kstat', uselib_store="KSTAT"):
417 conf.fatal("Cannot find kstat library")
419 if conf.env['USE_SHARED_V8']:
421 if o.shared_v8_includes: v8_includes.append(o.shared_v8_includes);
424 if o.shared_v8_libpath: v8_libpath.append(o.shared_v8_libpath);
426 if not o.shared_v8_libname: o.shared_v8_libname = 'v8'
428 if not conf.check_cxx(lib=o.shared_v8_libname, header_name='v8.h',
430 includes=v8_includes,
432 conf.fatal("Cannot find v8")
435 if not conf.check_cxx(lib=o.shared_v8_libname + '_g', header_name='v8.h',
437 includes=v8_includes,
439 conf.fatal("Cannot find v8_g")
441 conf.define("HAVE_CONFIG_H", 1)
443 if sys.platform.startswith("sunos"):
444 conf.env.append_value ('CCFLAGS', '-threads')
445 conf.env.append_value ('CXXFLAGS', '-threads')
446 #conf.env.append_value ('LINKFLAGS', ' -threads')
447 elif not sys.platform.startswith("win32"):
448 threadflags='-pthread'
449 conf.env.append_value ('CCFLAGS', threadflags)
450 conf.env.append_value ('CXXFLAGS', threadflags)
451 conf.env.append_value ('LINKFLAGS', threadflags)
452 if sys.platform.startswith("darwin"):
453 # used by platform_darwin_*.cc
454 conf.env.append_value('LINKFLAGS', ['-framework','Carbon'])
455 # cross compile for architecture specified by DEST_CPU
456 if 'DEST_CPU' in conf.env:
457 arch = conf.env['DEST_CPU']
458 # map supported_archs to GCC names:
459 arch_mappings = {'ia32': 'i386', 'x64': 'x86_64'}
460 if arch in arch_mappings:
461 arch = arch_mappings[arch]
462 flags = ['-arch', arch]
463 conf.env.append_value('CCFLAGS', flags)
464 conf.env.append_value('CXXFLAGS', flags)
465 conf.env.append_value('LINKFLAGS', flags)
466 if 'DEST_CPU' in conf.env:
467 arch = conf.env['DEST_CPU']
468 # TODO: -m32 is only available on 64 bit machines, so check host type
473 conf.env.append_value('CCFLAGS', flags)
474 conf.env.append_value('CXXFLAGS', flags)
475 conf.env.append_value('LINKFLAGS', flags)
478 conf.env.append_value('CPPFLAGS', '-D_LARGEFILE_SOURCE')
479 conf.env.append_value('CPPFLAGS', '-D_FILE_OFFSET_BITS=64')
481 # Makes select on windows support more than 64 FDs
482 if sys.platform.startswith("win32"):
483 conf.env.append_value('CPPFLAGS', '-DFD_SETSIZE=1024');
485 ## needed for node_file.cc fdatasync
486 ## Strangely on OSX 10.6 the g++ doesn't see fdatasync but gcc does?
496 if conf.check_cxx(msg="Checking for fdatasync(2) with c++", fragment=code):
497 conf.env.append_value('CPPFLAGS', '-DHAVE_FDATASYNC=1')
499 conf.env.append_value('CPPFLAGS', '-DHAVE_FDATASYNC=0')
502 conf.env.append_value('CPPFLAGS', '-DARCH="' + conf.env['DEST_CPU'] + '"')
505 conf.env.append_value('CPPFLAGS', '-DPLATFORM="' + conf.env['DEST_OS'] + '"')
508 if not sys.platform.startswith('win'):
509 conf.env.append_value('CPPFLAGS', '-D__POSIX__=1')
511 platform_file = "src/platform_%s.cc" % conf.env['DEST_OS']
512 if os.path.exists(join(cwd, platform_file)):
513 Options.options.platform_file = True
514 conf.env["PLATFORM_FILE"] = platform_file
516 Options.options.platform_file = False
517 conf.env["PLATFORM_FILE"] = "src/platform_none.cc"
519 if conf.env['USE_PROFILING'] == True:
520 conf.env.append_value('CPPFLAGS', '-pg')
521 conf.env.append_value('LINKFLAGS', '-pg')
523 if sys.platform.startswith("win32"):
524 conf.env.append_value('LIB', 'psapi')
525 conf.env.append_value('LIB', 'winmm')
526 # This enforces ws2_32 to be linked after crypto, otherwise the linker
527 # will run into undefined references from libcrypto.a
528 if not Options.options.use_openssl:
529 conf.env.append_value('LIB', 'ws2_32')
531 conf.env.append_value('CPPFLAGS', '-Wno-unused-parameter');
532 conf.env.append_value('CPPFLAGS', '-D_FORTIFY_SOURCE=2');
534 # Split off debug variant before adding variant specific defines
535 debug_env = conf.env.copy()
536 conf.set_env_name('Debug', debug_env)
538 # Configure debug variant
540 debug_env.set_variant('Debug')
541 debug_env.append_value('CPPFLAGS', '-DDEBUG')
542 debug_compile_flags = ['-g', '-O0', '-Wall', '-Wextra']
543 debug_env.append_value('CCFLAGS', debug_compile_flags)
544 debug_env.append_value('CXXFLAGS', debug_compile_flags)
545 conf.write_config_header("config.h")
547 # Configure default variant
548 conf.setenv('Release')
549 default_compile_flags = ['-g', '-O3']
550 conf.env.append_value('CCFLAGS', default_compile_flags)
551 conf.env.append_value('CXXFLAGS', default_compile_flags)
552 conf.write_config_header("config.h")
555 def v8_cmd(bld, variant):
556 scons = join(cwd, 'tools/scons/scons.py')
557 deps_src = join(bld.path.abspath(),"deps")
558 v8dir_src = join(deps_src,"v8")
560 # NOTE: We want to compile V8 to export its symbols. I.E. Do not want
561 # -fvisibility=hidden. When using dlopen() it seems that the loaded DSO
562 # cannot see symbols in the executable which are hidden, even if the
563 # executable is statically linked together...
565 # XXX Change this when v8 defaults x86_64 to native builds
566 # Possible values are (arm, ia32, x64, mips).
568 if bld.env['DEST_CPU']:
569 arch = "arch="+bld.env['DEST_CPU']
573 if variant == "Release":
578 if bld.env["SNAPSHOT_V8"]:
579 snapshot = "snapshot=on"
583 cmd_R = sys.executable + ' "%s" -j %d -C "%s" -Y "%s" visibility=default mode=%s %s toolchain=%s library=static %s'
585 cmd = cmd_R % ( scons
586 , Options.options.jobs
587 , safe_path(bld.srcnode.abspath(bld.env_of_name(variant)))
588 , safe_path(v8dir_src)
595 if bld.env["USE_GDBJIT"]:
598 if sys.platform.startswith("sunos"):
599 cmd += ' toolchain=gcc strictaliasing=off'
603 return ("echo '%s' && " % cmd) + cmd
607 v8 = bld.new_task_gen(
608 source = 'deps/v8/SConstruct '
609 + bld.path.ant_glob('v8/include/*')
610 + bld.path.ant_glob('v8/src/*'),
611 target = bld.env["staticlib_PATTERN"] % "v8",
612 rule = v8_cmd(bld, "Release"),
616 v8.env.env = dict(os.environ)
617 v8.env.env['CC'] = sh_escape(bld.env['CC'][0])
618 v8.env.env['CXX'] = sh_escape(bld.env['CXX'][0])
620 v8.uselib = "EXECINFO"
621 bld.env["CPPPATH_V8"] = "deps/v8/include"
622 t = join(bld.srcnode.abspath(bld.env_of_name("Release")), v8.target)
623 bld.env_of_name('Release').append_value("LINKFLAGS_V8", t)
626 if bld.env["USE_DEBUG"]:
627 v8_debug = v8.clone("Debug")
628 v8_debug.rule = v8_cmd(bld, "Debug")
629 v8_debug.target = bld.env["staticlib_PATTERN"] % "v8_g"
630 v8_debug.uselib = "EXECINFO"
631 bld.env["CPPPATH_V8_G"] = "deps/v8/include"
632 t = join(bld.srcnode.abspath(bld.env_of_name("Debug")), v8_debug.target)
633 bld.env_of_name('Debug').append_value("LINKFLAGS_V8_G", t)
635 bld.install_files('${PREFIX}/include/node/', 'deps/v8/include/*.h')
638 if sys.platform.startswith('win32'):
641 return s.replace("\\", "\\\\").replace("(","\\(").replace(")","\\)").replace(" ","\\ ")
643 def uv_cmd(bld, variant):
644 srcdeps = join(bld.path.abspath(), "deps")
645 srcdir = join(srcdeps, "uv")
646 blddir = bld.srcnode.abspath(bld.env_of_name(variant)) + '/deps/uv'
648 # FIXME This is awful! We're copying the entire source directory into the
649 # build directory before each compile. This could be much improved by
650 # modifying libuv's build to send object files to a separate directory.
652 cmd = 'cp -r ' + sh_escape(srcdir) + '/* ' + sh_escape(blddir)
653 if not sys.platform.startswith('win32'):
654 cmd += ' && if [[ -z "$NODE_MAKE" ]]; then NODE_MAKE=make; fi; '
655 cmd += '$NODE_MAKE -C ' + sh_escape(blddir)
657 cmd += ' && make -C ' + sh_escape(blddir)
663 uv = bld.new_task_gen(
665 source = 'deps/uv/include/uv.h',
666 target = 'deps/uv/uv.a',
668 rule = uv_cmd(bld, 'Release')
671 uv.env.env = dict(os.environ)
672 uv.env.env['CC'] = sh_escape(bld.env['CC'][0])
673 uv.env.env['CXX'] = sh_escape(bld.env['CXX'][0])
675 t = join(bld.srcnode.abspath(bld.env_of_name("Release")), uv.target)
676 bld.env_of_name('Release').append_value("LINKFLAGS_UV", t)
678 if bld.env["USE_DEBUG"]:
679 uv_debug = uv.clone("Debug")
680 uv_debug.rule = uv_cmd(bld, 'Debug')
681 uv_debug.env.env = dict(os.environ)
683 t = join(bld.srcnode.abspath(bld.env_of_name("Debug")), uv_debug.target)
684 bld.env_of_name('Debug').append_value("LINKFLAGS_UV", t)
686 bld.install_files('${PREFIX}/include/node/', 'deps/uv/include/*.h')
687 bld.install_files('${PREFIX}/include/node/uv-private', 'deps/uv/include/uv-private/*.h')
688 bld.install_files('${PREFIX}/include/node/ev', 'deps/uv/src/ev/*.h')
689 bld.install_files('${PREFIX}/include/node/c-ares', """
690 deps/uv/include/ares.h
691 deps/uv/include/ares_version.h
696 ## This snippet is to show full commands as WAF executes
698 old = Build.BuildContext.exec_command
699 def exec_command(self, cmd, **kw):
700 if isinstance(cmd, list): print(" ".join(cmd))
701 return old(self, cmd, **kw)
702 Build.BuildContext.exec_command = exec_command
704 Options.options.jobs=jobs
705 product_type = Options.options.product_type
706 product_type_is_lib = product_type != 'program'
708 print "DEST_OS: " + bld.env['DEST_OS']
709 print "DEST_CPU: " + bld.env['DEST_CPU']
710 print "Parallel Jobs: " + str(Options.options.jobs)
711 print "Product type: " + product_type
715 if not bld.env['USE_SHARED_V8']: build_v8(bld)
719 http_parser = bld.new_task_gen("cc")
720 http_parser.source = "deps/http_parser/http_parser.c"
721 http_parser.includes = "deps/http_parser/"
722 http_parser.name = "http_parser"
723 http_parser.target = "http_parser"
724 http_parser.install_path = None
725 if bld.env["USE_DEBUG"]:
726 http_parser.clone("Debug")
727 if product_type_is_lib:
728 http_parser.ccflags = '-fPIC'
731 def make_macros(loc, content):
736 macros_loc_debug = join(
737 bld.srcnode.abspath(bld.env_of_name("Debug")),
741 macros_loc_default = join(
742 bld.srcnode.abspath(bld.env_of_name("Release")),
746 ### We need to truncate the macros.py file
747 f = open(macros_loc_debug, 'w')
749 f = open(macros_loc_default, 'w')
752 make_macros(macros_loc_debug, "") # leave debug(x) as is in debug build
753 # replace debug(x) with nothing in release build
754 make_macros(macros_loc_default, "macro debug(x) = ;\n")
755 make_macros(macros_loc_default, "macro assert(x) = ;\n")
757 if not bld.env["USE_DTRACE"]:
759 'DTRACE_HTTP_CLIENT_REQUEST',
760 'DTRACE_HTTP_CLIENT_RESPONSE',
761 'DTRACE_HTTP_SERVER_REQUEST',
762 'DTRACE_HTTP_SERVER_RESPONSE',
763 'DTRACE_NET_SERVER_CONNECTION',
764 'DTRACE_NET_STREAM_END',
765 'DTRACE_NET_SOCKET_READ',
766 'DTRACE_NET_SOCKET_WRITE'
770 make_macros(macros_loc_default, "macro %s(x) = ;\n" % probe)
771 make_macros(macros_loc_debug, "macro %s(x) = ;\n" % probe)
773 def javascript_in_c(task):
775 source = map(lambda x: x.srcpath(env), task.inputs)
776 targets = map(lambda x: x.srcpath(env), task.outputs)
777 source.append(macros_loc_default)
778 js2c.JS2C(source, targets)
780 def javascript_in_c_debug(task):
782 source = map(lambda x: x.srcpath(env), task.inputs)
783 targets = map(lambda x: x.srcpath(env), task.outputs)
784 source.append(macros_loc_debug)
785 js2c.JS2C(source, targets)
787 native_cc = bld.new_task_gen(
788 source='src/node.js ' + bld.path.ant_glob('lib/*.js'),
789 target="src/node_natives.h",
794 # Add the rule /after/ cloning the debug
795 # This is a work around for an error had in python 2.4.3 (I'll paste the
796 # error that was had into the git commit meessage. git-blame to find out
798 if bld.env["USE_DEBUG"]:
799 native_cc_debug = native_cc.clone("Debug")
800 native_cc_debug.rule = javascript_in_c_debug
802 native_cc.rule = javascript_in_c_debug
804 if bld.env["USE_DTRACE"]:
805 dtrace = bld.new_task_gen(
807 source = "src/node_provider.d",
808 target = "src/node_provider.h",
809 rule = "%s -x nolibs -h -o ${TGT} -s ${SRC}" % (bld.env.DTRACE),
813 if bld.env["USE_DEBUG"]:
814 dtrace_g = dtrace.clone("Debug")
816 bld.install_files('${LIBDIR}/dtrace', 'src/node.d')
818 if sys.platform.startswith("sunos"):
820 # The USDT DTrace provider works slightly differently on Solaris than on
821 # the Mac; on Solaris, any objects that have USDT DTrace probes must be
822 # post-processed with the DTrace command. (This is not true on the
823 # Mac, which has first-class linker support for USDT probes.) On
824 # Solaris, we must therefore post-process our object files. Waf doesn't
825 # seem to really have a notion for this, so we inject a task after
826 # compiling and before linking, and then find all of the node object
827 # files and shuck them off to dtrace (which will modify them in place
830 def dtrace_postprocess(task):
831 abspath = bld.srcnode.abspath(bld.env_of_name(task.env.variant()))
832 objs = glob.glob(abspath + 'src/*.o')
833 source = task.inputs[0].srcpath(task.env)
834 target = task.outputs[0].srcpath(task.env)
835 cmd = '%s -G -x nolibs -s %s -o %s %s' % (task.env.DTRACE,
839 Utils.exec_command(cmd)
841 dtracepost = bld.new_task_gen(
842 name = "dtrace-postprocess",
843 source = "src/node_provider.d",
844 target = "node_provider.o",
848 rule = dtrace_postprocess
851 t = join(bld.srcnode.abspath(bld.env_of_name("Release")), dtracepost.target)
852 bld.env_of_name('Release').append_value('LINKFLAGS', t)
855 # Note that for the same (mysterious) issue outlined above with respect
856 # to assigning the rule to native_cc/native_cc_debug, we must apply the
857 # rule to dtracepost/dtracepost_g only after they have been cloned. We
858 # also must put node_provider.o on the link line, but because we
859 # (apparently?) lack LINKFLAGS in debug, we (shamelessly) stowaway on
862 if bld.env["USE_DEBUG"]:
863 dtracepost_g = dtracepost.clone("Debug")
864 dtracepost_g.rule = dtrace_postprocess
865 t = join(bld.srcnode.abspath(bld.env_of_name("Debug")), dtracepost.target)
866 bld.env_of_name("Debug").append_value('LINKFLAGS_V8_G', t)
870 node = bld.new_task_gen("cxx", product_type)
873 node.uselib = 'RT OPENSSL ZLIB CARES EXECINFO DL KVM SOCKET NSL KSTAT UTIL OPROFILE'
874 node.add_objects = 'http_parser'
875 if product_type_is_lib:
876 node.install_path = '${LIBDIR}'
878 node.install_path = '${PREFIX}/bin'
883 src/node_javascript.cc
884 src/node_extensions.cc
885 src/node_http_parser.cc
886 src/node_constants.cc
903 src/v8_typed_array.cc
906 if not sys.platform.startswith("win32"):
907 node.source += " src/node_signal_watcher.cc "
908 node.source += " src/node_stat_watcher.cc "
909 node.source += " src/node_io_watcher.cc "
911 node.source += bld.env["PLATFORM_FILE"]
912 if not product_type_is_lib:
913 node.source = 'src/node_main.cc '+node.source
915 if bld.env["USE_OPENSSL"]: node.source += " src/node_crypto.cc "
925 if not bld.env["USE_SHARED_V8"]: node.includes += ' deps/v8/include '
927 if os.environ.has_key('RPATH'):
928 node.rpath = os.environ['RPATH']
930 if (sys.platform.startswith("win32")):
932 bld.env.append_value('LINKFLAGS', '-static-libgcc')
933 bld.env.append_value('LINKFLAGS', '-static-libstdc++')
935 def subflags(program):
936 x = { 'CCFLAGS' : " ".join(program.env["CCFLAGS"]).replace('"', '\\"')
937 , 'CPPFLAGS' : " ".join(program.env["CPPFLAGS"]).replace('"', '\\"')
938 , 'LIBFLAGS' : " ".join(program.env["LIBFLAGS"]).replace('"', '\\"')
939 , 'PREFIX' : safe_path(program.env["PREFIX"])
940 , 'VERSION' : get_node_version()
944 # process file.pc.in -> file.pc
946 node_conf = bld.new_task_gen('subst', before="cxx")
947 node_conf.source = 'src/node_config.h.in'
948 node_conf.target = 'src/node_config.h'
949 node_conf.dict = subflags(node)
950 node_conf.install_path = '${PREFIX}/include/node'
952 if bld.env["USE_DEBUG"]:
953 node_g = node.clone("Debug")
954 node_g.target = "node"
955 node_g.uselib += ' V8_G UV '
956 node_g.install_path = None
958 node_conf_g = node_conf.clone("Debug")
959 node_conf_g.dict = subflags(node_g)
960 node_conf_g.install_path = None
962 # After creating the debug clone, append the V8 dep
963 node.uselib += ' V8 UV '
965 bld.install_files('${PREFIX}/include/node/', """
968 src/node_object_wrap.h
973 # Only install the man page if it exists.
974 # Do 'make doc install' to build and install it.
975 if os.path.exists('doc/node.1'):
976 bld.install_files('${PREFIX}/share/man/man1/', 'doc/node.1')
978 bld.install_files('${PREFIX}/bin/', 'tools/node-waf', chmod=0755)
979 bld.install_files('${LIBDIR}/node/wafadmin', 'tools/wafadmin/*.py')
980 bld.install_files('${LIBDIR}/node/wafadmin/Tools', 'tools/wafadmin/Tools/*.py')
983 Options.options.debug
984 # HACK to get binding.node out of build directory.
985 # better way to do this?
986 if Options.commands['configure']:
987 if not Options.options.use_openssl:
988 print "WARNING WARNING WARNING"
989 print "OpenSSL not found. Will compile Node without crypto support!"
991 if not Options.options.platform_file:
992 print "WARNING: Platform not fully supported. Using src/platform_none.cc"
994 elif not Options.commands['clean']:
995 if sys.platform.startswith("win32"):
996 if os.path.exists('out/Release/node.exe'):
997 os.system('cp out/Release/node.exe .')
998 if os.path.exists('out/Debug/node.exe'):
999 os.system('cp out/Debug/node.exe node_g.exe')
1001 if os.path.exists('out/Release/node') and not os.path.islink('node'):
1002 os.symlink('out/Release/node', 'node')
1003 if os.path.exists('out/Debug/node') and not os.path.islink('node_g'):
1004 os.symlink('out/Debug/node', 'node_g')
1006 if sys.platform.startswith("win32"):
1007 if os.path.exists('node.exe'): os.unlink('node.exe')
1008 if os.path.exists('node_g.exe'): os.unlink('node_g.exe')
1010 if os.path.exists('node'): os.unlink('node')
1011 if os.path.exists('node_g'): os.unlink('node_g')