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');
42 supported_archs = ('arm', 'ia32', 'x64') # 'mips' supported by v8, but not node
45 if os.environ.has_key('JOBS'):
46 jobs = int(os.environ['JOBS'])
49 return path.replace("\\", "/")
51 def canonical_cpu_type(arch):
52 m = {'x86': 'ia32', 'i386':'ia32', 'x86_64':'x64', 'amd64':'x64'}
53 if arch in m: arch = m[arch]
54 if not arch in supported_archs:
55 raise Exception("supported architectures are "+', '.join(supported_archs)+\
56 " but NOT '" + arch + "'.")
60 # the gcc module provides a --debug-level option
61 opt.tool_options('compiler_cxx')
62 opt.tool_options('compiler_cc')
63 opt.tool_options('misc')
64 opt.add_option( '--libdir'
68 , help='Install into this libdir [Default: ${PREFIX}/lib]'
70 opt.add_option( '--debug'
73 , help='Build debug variant [Default: False]'
76 opt.add_option( '--profile'
79 , help='Enable profiling [Default: False]'
82 opt.add_option( '--efence'
85 , help='Build with -lefence for debugging [Default: False]'
89 opt.add_option( '--without-snapshot'
92 , help='Build without snapshotting V8 libraries. You might want to set this for cross-compiling. [Default: False]'
93 , dest='without_snapshot'
96 opt.add_option( '--without-ssl'
99 , help='Build without SSL'
104 opt.add_option('--shared-v8'
105 , action='store_true'
107 , help='Link to a shared V8 DLL instead of static linking'
111 opt.add_option( '--shared-v8-includes'
114 , help='Directory containing V8 header files'
115 , dest='shared_v8_includes'
118 opt.add_option( '--shared-v8-libpath'
121 , help='A directory to search for the shared V8 DLL'
122 , dest='shared_v8_libpath'
125 opt.add_option( '--shared-v8-libname'
128 , help="Alternative lib name to link to (default: 'v8')"
129 , dest='shared_v8_libname'
132 opt.add_option( '--openssl-includes'
135 , help='A directory to search for the OpenSSL includes'
136 , dest='openssl_includes'
139 opt.add_option( '--openssl-libpath'
142 , help="A directory to search for the OpenSSL libraries"
143 , dest='openssl_libpath'
146 opt.add_option( '--gdb'
147 , action='store_true'
149 , help="add gdb support"
154 opt.add_option('--shared-cares'
155 , action='store_true'
157 , help='Link to a shared C-Ares DLL instead of static linking'
158 , dest='shared_cares'
161 opt.add_option( '--shared-cares-includes'
164 , help='Directory containing C-Ares header files'
165 , dest='shared_cares_includes'
168 opt.add_option( '--shared-cares-libpath'
171 , help='A directory to search for the shared C-Ares DLL'
172 , dest='shared_cares_libpath'
176 opt.add_option('--shared-libev'
177 , action='store_true'
179 , help='Link to a shared libev DLL instead of static linking'
180 , dest='shared_libev'
183 opt.add_option( '--shared-libev-includes'
186 , help='Directory containing libev header files'
187 , dest='shared_libev_includes'
190 opt.add_option( '--shared-libev-libpath'
193 , help='A directory to search for the shared libev DLL'
194 , dest='shared_libev_libpath'
197 opt.add_option( '--with-dtrace'
198 , action='store_true'
200 , help='Build with DTrace (experimental)'
205 opt.add_option( '--product-type'
208 , help='What kind of product to produce (program, cstaticlib '\
209 'or cshlib) [default: %default]'
210 , dest='product_type'
213 opt.add_option( '--dest-cpu'
216 , help='CPU architecture to build for. Valid values are: '+\
217 ', '.join(supported_archs)
225 conf.check_tool('compiler_cxx')
226 if not conf.env.CXX: conf.fatal('c++ compiler not found')
227 conf.check_tool('compiler_cc')
228 if not conf.env.CC: conf.fatal('c compiler not found')
233 conf.env['LIBDIR'] = o.libdir
235 conf.env['LIBDIR'] = conf.env['PREFIX'] + '/lib'
237 conf.env["USE_DEBUG"] = o.debug
238 # Snapshot building does noet seem to work on cygwin and mingw32
239 conf.env["SNAPSHOT_V8"] = not o.without_snapshot and not sys.platform.startswith("win32")
240 if sys.platform.startswith("sunos"):
241 conf.env["SNAPSHOT_V8"] = False
242 conf.env["USE_PROFILING"] = o.profile
244 conf.env["USE_SHARED_V8"] = o.shared_v8 or o.shared_v8_includes or o.shared_v8_libpath or o.shared_v8_libname
245 conf.env["USE_SHARED_CARES"] = o.shared_cares or o.shared_cares_includes or o.shared_cares_libpath
246 conf.env["USE_SHARED_LIBEV"] = o.shared_libev or o.shared_libev_includes or o.shared_libev_libpath
248 conf.env["USE_GDBJIT"] = o.use_gdbjit
250 conf.check(lib='dl', uselib_store='DL')
251 if not sys.platform.startswith("sunos") and not sys.platform.startswith("cygwin") and not sys.platform.startswith("win32"):
252 conf.env.append_value("CCFLAGS", "-rdynamic")
253 conf.env.append_value("LINKFLAGS_DL", "-rdynamic")
255 if sys.platform.startswith("freebsd") or sys.platform.startswith("openbsd"):
256 conf.check(lib='kvm', uselib_store='KVM')
258 #if Options.options.debug:
259 # conf.check(lib='profiler', uselib_store='PROFILER')
261 if Options.options.dtrace:
262 if not sys.platform.startswith("sunos"):
263 conf.fatal('DTrace support only currently available on Solaris')
265 conf.find_program('dtrace', var='DTRACE', mandatory=True)
266 conf.env["USE_DTRACE"] = True
267 conf.env.append_value("CXXFLAGS", "-DHAVE_DTRACE=1")
269 if Options.options.efence:
270 conf.check(lib='efence', libpath=['/usr/lib', '/usr/local/lib'], uselib_store='EFENCE')
272 if sys.platform.startswith("freebsd"):
273 if not conf.check(lib="execinfo",
274 includes=['/usr/include', '/usr/local/include'],
275 libpath=['/usr/lib', '/usr/local/lib'],
276 uselib_store="EXECINFO"):
277 conf.fatal("Install the libexecinfo port from /usr/ports/devel/libexecinfo.")
279 if not Options.options.without_ssl:
280 # Don't override explicitly supplied openssl paths with pkg-config results.
281 explicit_openssl = o.openssl_includes or o.openssl_libpath
282 if not explicit_openssl and conf.check_cfg(package='openssl',
283 args='--cflags --libs',
284 uselib_store='OPENSSL'):
285 Options.options.use_openssl = conf.env["USE_OPENSSL"] = True
286 conf.env.append_value("CPPFLAGS", "-DHAVE_OPENSSL=1")
288 if o.openssl_libpath:
289 openssl_libpath = [o.openssl_libpath]
290 elif not sys.platform.startswith('win32'):
291 openssl_libpath = ['/usr/lib', '/usr/local/lib', '/opt/local/lib', '/usr/sfw/lib']
293 openssl_libpath = [normpath(join(cwd, '../openssl'))]
295 if o.openssl_includes:
296 openssl_includes = [o.openssl_includes]
297 elif not sys.platform.startswith('win32'):
298 openssl_includes = [];
300 openssl_includes = [normpath(join(cwd, '../openssl/include'))];
302 openssl_lib_names = ['ssl', 'crypto']
303 if sys.platform.startswith('win32'):
304 openssl_lib_names += ['ws2_32', 'gdi32']
306 libssl = conf.check_cc(lib=openssl_lib_names,
307 header_name='openssl/ssl.h',
308 function_name='SSL_library_init',
309 includes=openssl_includes,
310 libpath=openssl_libpath,
311 uselib_store='OPENSSL')
313 libcrypto = conf.check_cc(lib='crypto',
314 header_name='openssl/crypto.h',
315 includes=openssl_includes,
316 libpath=openssl_libpath,
317 uselib_store='OPENSSL')
319 if libcrypto and libssl:
320 conf.env["USE_OPENSSL"] = Options.options.use_openssl = True
321 conf.env.append_value("CPPFLAGS", "-DHAVE_OPENSSL=1")
322 elif sys.platform.startswith('win32'):
323 conf.fatal("Could not autodetect OpenSSL support. " +
324 "Use the --openssl-libpath and --openssl-includes options to set the search path. " +
325 "Use configure --without-ssl to disable this message.")
327 conf.fatal("Could not autodetect OpenSSL support. " +
328 "Make sure OpenSSL development packages are installed. " +
329 "Use configure --without-ssl to disable this message.")
331 Options.options.use_openssl = conf.env["USE_OPENSSL"] = False
333 conf.check(lib='util', libpath=['/usr/lib', '/usr/local/lib'],
336 # normalize DEST_CPU from --dest-cpu, DEST_CPU or built-in value
337 if Options.options.dest_cpu and Options.options.dest_cpu:
338 conf.env['DEST_CPU'] = canonical_cpu_type(Options.options.dest_cpu)
339 elif 'DEST_CPU' in os.environ and os.environ['DEST_CPU']:
340 conf.env['DEST_CPU'] = canonical_cpu_type(os.environ['DEST_CPU'])
341 elif 'DEST_CPU' in conf.env and conf.env['DEST_CPU']:
342 conf.env['DEST_CPU'] = canonical_cpu_type(conf.env['DEST_CPU'])
344 have_librt = conf.check(lib='rt', uselib_store='RT')
346 have_monotonic = False
352 clock_gettime(CLOCK_MONOTONIC, &now);
356 have_monotonic = conf.check_cc(lib="rt", msg="Checking for CLOCK_MONOTONIC", fragment=code)
359 conf.env.append_value('CPPFLAGS', '-DHAVE_MONOTONIC_CLOCK=1')
361 conf.env.append_value('CPPFLAGS', '-DHAVE_MONOTONIC_CLOCK=0')
363 if sys.platform.startswith("sunos"):
364 if not conf.check(lib='socket', uselib_store="SOCKET"):
365 conf.fatal("Cannot find socket library")
366 if not conf.check(lib='nsl', uselib_store="NSL"):
367 conf.fatal("Cannot find nsl library")
368 if not conf.check(lib='kstat', uselib_store="KSTAT"):
369 conf.fatal("Cannot find kstat library")
371 conf.sub_config('deps/libeio')
373 if conf.env['USE_SHARED_V8']:
375 if o.shared_v8_includes: v8_includes.append(o.shared_v8_includes);
378 if o.shared_v8_libpath: v8_libpath.append(o.shared_v8_libpath);
380 if not o.shared_v8_libname: o.shared_v8_libname = 'v8'
382 if not conf.check_cxx(lib=o.shared_v8_libname, header_name='v8.h',
384 includes=v8_includes,
386 conf.fatal("Cannot find v8")
389 if not conf.check_cxx(lib=o.shared_v8_libname + '_g', header_name='v8.h',
391 includes=v8_includes,
393 conf.fatal("Cannot find v8_g")
395 if sys.platform.startswith("win32"):
396 # On win32 CARES is always static, so we can call internal functions like ares_inet_pton et al.
397 # CARES_STATICLIB must be defined or gcc will try to make DLL stub calls
398 conf.env.append_value('CPPFLAGS', '-DCARES_STATICLIB=1')
399 conf.sub_config('deps/c-ares')
400 elif conf.env['USE_SHARED_CARES']:
402 if o.shared_cares_includes: cares_includes.append(o.shared_cares_includes);
404 if o.shared_cares_libpath: cares_libpath.append(o.shared_cares_libpath);
405 if not conf.check_cxx(lib='cares',
406 header_name='ares.h',
407 uselib_store='CARES',
408 includes=cares_includes,
409 libpath=cares_libpath):
410 conf.fatal("Cannot find c-ares")
412 conf.sub_config('deps/c-ares')
415 if conf.env['USE_SHARED_LIBEV']:
417 if o.shared_libev_includes: libev_includes.append(o.shared_libev_includes);
419 if o.shared_libev_libpath: libev_libpath.append(o.shared_libev_libpath);
420 if not conf.check_cxx(lib='ev', header_name='ev.h',
422 includes=libev_includes,
423 libpath=libev_libpath):
424 conf.fatal("Cannot find libev")
426 conf.sub_config('deps/libev')
430 conf.define("HAVE_CONFIG_H", 1)
432 if sys.platform.startswith("sunos"):
433 conf.env.append_value ('CCFLAGS', '-threads')
434 conf.env.append_value ('CXXFLAGS', '-threads')
435 #conf.env.append_value ('LINKFLAGS', ' -threads')
436 elif not sys.platform.startswith("cygwin") and not sys.platform.startswith("win32"):
437 threadflags='-pthread'
438 conf.env.append_value ('CCFLAGS', threadflags)
439 conf.env.append_value ('CXXFLAGS', threadflags)
440 conf.env.append_value ('LINKFLAGS', threadflags)
441 if sys.platform.startswith("darwin"):
442 # used by platform_darwin_*.cc
443 conf.env.append_value('LINKFLAGS', ['-framework','Carbon'])
444 # cross compile for architecture specified by DEST_CPU
445 if 'DEST_CPU' in conf.env:
446 arch = conf.env['DEST_CPU']
447 # map supported_archs to GCC names:
448 arch_mappings = {'ia32': 'i386', 'x64': 'x86_64'}
449 if arch in arch_mappings:
450 arch = arch_mappings[arch]
451 flags = ['-arch', arch]
452 conf.env.append_value('CCFLAGS', flags)
453 conf.env.append_value('CXXFLAGS', flags)
454 conf.env.append_value('LINKFLAGS', flags)
455 if 'DEST_CPU' in conf.env:
456 arch = conf.env['DEST_CPU']
457 # TODO: -m32 is only available on 64 bit machines, so check host type
462 conf.env.append_value('CCFLAGS', flags)
463 conf.env.append_value('CXXFLAGS', flags)
464 conf.env.append_value('LINKFLAGS', flags)
466 # Needed for getaddrinfo in libeio
467 conf.env.append_value("CPPFLAGS", "-DX_STACKSIZE=%d" % (1024*64))
469 conf.env.append_value('CPPFLAGS', '-D_LARGEFILE_SOURCE')
470 conf.env.append_value('CPPFLAGS', '-D_FILE_OFFSET_BITS=64')
471 conf.env.append_value('CPPFLAGS', '-DEV_MULTIPLICITY=0')
473 # Makes select on windows support more than 64 FDs
474 if sys.platform.startswith("win32"):
475 conf.env.append_value('CPPFLAGS', '-DFD_SETSIZE=1024');
477 ## needed for node_file.cc fdatasync
478 ## Strangely on OSX 10.6 the g++ doesn't see fdatasync but gcc does?
488 if conf.check_cxx(msg="Checking for fdatasync(2) with c++", fragment=code):
489 conf.env.append_value('CPPFLAGS', '-DHAVE_FDATASYNC=1')
491 conf.env.append_value('CPPFLAGS', '-DHAVE_FDATASYNC=0')
494 conf.env.append_value('CPPFLAGS', '-DARCH="' + conf.env['DEST_CPU'] + '"')
497 conf.env.append_value('CPPFLAGS', '-DPLATFORM="' + conf.env['DEST_OS'] + '"')
500 if not sys.platform.startswith('win'):
501 conf.env.append_value('CPPFLAGS', '-D__POSIX__=1')
503 platform_file = "src/platform_%s.cc" % conf.env['DEST_OS']
504 if os.path.exists(join(cwd, platform_file)):
505 Options.options.platform_file = True
506 conf.env["PLATFORM_FILE"] = platform_file
508 Options.options.platform_file = False
509 conf.env["PLATFORM_FILE"] = "src/platform_none.cc"
511 if conf.env['USE_PROFILING'] == True:
512 conf.env.append_value('CPPFLAGS', '-pg')
513 conf.env.append_value('LINKFLAGS', '-pg')
515 if sys.platform.startswith("win32"):
516 conf.env.append_value('LIB', 'ws2_32')
517 conf.env.append_value('LIB', 'winmm')
519 conf.env.append_value('CPPFLAGS', '-Wno-unused-parameter');
520 conf.env.append_value('CPPFLAGS', '-D_FORTIFY_SOURCE=2');
522 # Split off debug variant before adding variant specific defines
523 debug_env = conf.env.copy()
524 conf.set_env_name('debug', debug_env)
526 if (sys.platform.startswith("win32")):
527 # Static pthread - crashes
528 #conf.env.append_value('LINKFLAGS', '../deps/pthreads-w32/libpthreadGC2.a')
529 #debug_env.append_value('LINKFLAGS', '../deps/pthreads-w32/libpthreadGC2d.a')
531 conf.env.append_value('LIB', 'pthread.dll')
533 # Configure debug variant
535 debug_env.set_variant('debug')
536 debug_env.append_value('CPPFLAGS', '-DDEBUG')
537 debug_compile_flags = ['-g', '-O0', '-Wall', '-Wextra']
538 debug_env.append_value('CCFLAGS', debug_compile_flags)
539 debug_env.append_value('CXXFLAGS', debug_compile_flags)
540 conf.write_config_header("config.h")
542 # Configure default variant
543 conf.setenv('default')
544 default_compile_flags = ['-g', '-O3']
545 conf.env.append_value('CCFLAGS', default_compile_flags)
546 conf.env.append_value('CXXFLAGS', default_compile_flags)
547 conf.write_config_header("config.h")
550 def v8_cmd(bld, variant):
551 scons = join(cwd, 'tools/scons/scons.py')
552 deps_src = join(bld.path.abspath(),"deps")
553 v8dir_src = join(deps_src,"v8")
555 # NOTE: We want to compile V8 to export its symbols. I.E. Do not want
556 # -fvisibility=hidden. When using dlopen() it seems that the loaded DSO
557 # cannot see symbols in the executable which are hidden, even if the
558 # executable is statically linked together...
560 # XXX Change this when v8 defaults x86_64 to native builds
561 # Possible values are (arm, ia32, x64, mips).
563 if bld.env['DEST_CPU']:
564 arch = "arch="+bld.env['DEST_CPU']
568 if variant == "default":
573 if bld.env["SNAPSHOT_V8"]:
574 snapshot = "snapshot=on"
578 cmd_R = sys.executable + ' "%s" -j %d -C "%s" -Y "%s" visibility=default mode=%s %s toolchain=%s library=static %s'
580 cmd = cmd_R % ( scons
581 , Options.options.jobs
582 , safe_path(bld.srcnode.abspath(bld.env_of_name(variant)))
583 , safe_path(v8dir_src)
590 if bld.env["USE_GDBJIT"]:
593 if sys.platform.startswith("sunos"):
594 cmd += ' toolchain=gcc strictaliasing=off'
598 return ("echo '%s' && " % cmd) + cmd
602 v8 = bld.new_task_gen(
603 source = 'deps/v8/SConstruct '
604 + bld.path.ant_glob('v8/include/*')
605 + bld.path.ant_glob('v8/src/*'),
606 target = bld.env["staticlib_PATTERN"] % "v8",
607 rule = v8_cmd(bld, "default"),
610 v8.uselib = "EXECINFO"
611 bld.env["CPPPATH_V8"] = "deps/v8/include"
612 t = join(bld.srcnode.abspath(bld.env_of_name("default")), v8.target)
613 bld.env_of_name('default').append_value("LINKFLAGS_V8", t)
617 if bld.env["USE_DEBUG"]:
618 v8_debug = v8.clone("debug")
619 v8_debug.rule = v8_cmd(bld, "debug")
620 v8_debug.target = bld.env["staticlib_PATTERN"] % "v8_g"
621 v8_debug.uselib = "EXECINFO"
622 bld.env["CPPPATH_V8_G"] = "deps/v8/include"
623 t = join(bld.srcnode.abspath(bld.env_of_name("debug")), v8_debug.target)
624 bld.env_of_name('debug').append_value("LINKFLAGS_V8_G", t)
626 bld.install_files('${PREFIX}/include/node/', 'deps/v8/include/*.h')
630 ## This snippet is to show full commands as WAF executes
632 old = Build.BuildContext.exec_command
633 def exec_command(self, cmd, **kw):
634 if isinstance(cmd, list): print(" ".join(cmd))
635 return old(self, cmd, **kw)
636 Build.BuildContext.exec_command = exec_command
638 Options.options.jobs=jobs
639 product_type = Options.options.product_type
640 product_type_is_lib = product_type != 'program'
642 print "DEST_OS: " + bld.env['DEST_OS']
643 print "DEST_CPU: " + bld.env['DEST_CPU']
644 print "Parallel Jobs: " + str(Options.options.jobs)
645 print "Product type: " + product_type
647 bld.add_subdirs('deps/libeio')
649 if not bld.env['USE_SHARED_V8']: build_v8(bld)
650 if not bld.env['USE_SHARED_LIBEV']: bld.add_subdirs('deps/libev')
651 if not bld.env['USE_SHARED_CARES']: bld.add_subdirs('deps/c-ares')
655 http_parser = bld.new_task_gen("cc")
656 http_parser.source = "deps/http_parser/http_parser.c"
657 http_parser.includes = "deps/http_parser/"
658 http_parser.name = "http_parser"
659 http_parser.target = "http_parser"
660 http_parser.install_path = None
661 if bld.env["USE_DEBUG"]:
662 http_parser.clone("debug")
663 if product_type_is_lib:
664 http_parser.ccflags = '-fPIC'
667 def make_macros(loc, content):
672 macros_loc_debug = join(
673 bld.srcnode.abspath(bld.env_of_name("debug")),
677 macros_loc_default = join(
678 bld.srcnode.abspath(bld.env_of_name("default")),
682 ### We need to truncate the macros.py file
683 f = open(macros_loc_debug, 'w')
685 f = open(macros_loc_default, 'w')
688 make_macros(macros_loc_debug, "") # leave debug(x) as is in debug build
689 # replace debug(x) with nothing in release build
690 make_macros(macros_loc_default, "macro debug(x) = ;\n")
691 make_macros(macros_loc_default, "macro assert(x) = ;\n")
693 if not bld.env["USE_DTRACE"]:
695 'DTRACE_HTTP_CLIENT_REQUEST',
696 'DTRACE_HTTP_CLIENT_RESPONSE',
697 'DTRACE_HTTP_SERVER_REQUEST',
698 'DTRACE_HTTP_SERVER_RESPONSE',
699 'DTRACE_NET_SERVER_CONNECTION',
700 'DTRACE_NET_STREAM_END',
701 'DTRACE_NET_SOCKET_READ',
702 'DTRACE_NET_SOCKET_WRITE'
706 make_macros(macros_loc_default, "macro %s(x) = ;\n" % probe)
707 make_macros(macros_loc_debug, "macro %s(x) = ;\n" % probe)
709 def javascript_in_c(task):
711 source = map(lambda x: x.srcpath(env), task.inputs)
712 targets = map(lambda x: x.srcpath(env), task.outputs)
713 source.append(macros_loc_default)
714 js2c.JS2C(source, targets)
716 def javascript_in_c_debug(task):
718 source = map(lambda x: x.srcpath(env), task.inputs)
719 targets = map(lambda x: x.srcpath(env), task.outputs)
720 source.append(macros_loc_debug)
721 js2c.JS2C(source, targets)
723 native_cc = bld.new_task_gen(
724 source='src/node.js ' + bld.path.ant_glob('lib/*.js'),
725 target="src/node_natives.h",
730 # Add the rule /after/ cloning the debug
731 # This is a work around for an error had in python 2.4.3 (I'll paste the
732 # error that was had into the git commit meessage. git-blame to find out
734 if bld.env["USE_DEBUG"]:
735 native_cc_debug = native_cc.clone("debug")
736 native_cc_debug.rule = javascript_in_c_debug
738 native_cc.rule = javascript_in_c_debug
740 if bld.env["USE_DTRACE"]:
741 dtrace = bld.new_task_gen(
743 source = "src/node_provider.d",
744 target = "src/node_provider.h",
745 rule = "%s -x nolibs -h -o ${TGT} -s ${SRC}" % (bld.env.DTRACE),
749 if bld.env["USE_DEBUG"]:
750 dtrace_g = dtrace.clone("debug")
752 bld.install_files('${LIBDIR}/dtrace', 'src/node.d')
754 if sys.platform.startswith("sunos"):
756 # The USDT DTrace provider works slightly differently on Solaris than on
757 # the Mac; on Solaris, any objects that have USDT DTrace probes must be
758 # post-processed with the DTrace command. (This is not true on the
759 # Mac, which has first-class linker support for USDT probes.) On
760 # Solaris, we must therefore post-process our object files. Waf doesn't
761 # seem to really have a notion for this, so we inject a task after
762 # compiling and before linking, and then find all of the node object
763 # files and shuck them off to dtrace (which will modify them in place
766 def dtrace_postprocess(task):
767 abspath = bld.srcnode.abspath(bld.env_of_name(task.env.variant()))
768 objs = glob.glob(abspath + 'src/*.o')
769 source = task.inputs[0].srcpath(task.env)
770 target = task.outputs[0].srcpath(task.env)
771 cmd = '%s -G -x nolibs -s %s -o %s %s' % (task.env.DTRACE,
775 Utils.exec_command(cmd)
777 dtracepost = bld.new_task_gen(
778 name = "dtrace-postprocess",
779 source = "src/node_provider.d",
780 target = "node_provider.o",
784 rule = dtrace_postprocess
787 t = join(bld.srcnode.abspath(bld.env_of_name("default")), dtracepost.target)
788 bld.env_of_name('default').append_value('LINKFLAGS', t)
791 # Note that for the same (mysterious) issue outlined above with respect
792 # to assigning the rule to native_cc/native_cc_debug, we must apply the
793 # rule to dtracepost/dtracepost_g only after they have been cloned. We
794 # also must put node_provider.o on the link line, but because we
795 # (apparently?) lack LINKFLAGS in debug, we (shamelessly) stowaway on
798 if bld.env["USE_DEBUG"]:
799 dtracepost_g = dtracepost.clone("debug")
800 dtracepost_g.rule = dtrace_postprocess
801 t = join(bld.srcnode.abspath(bld.env_of_name("debug")), dtracepost.target)
802 bld.env_of_name("debug").append_value('LINKFLAGS_V8_G', t)
806 node = bld.new_task_gen("cxx", product_type)
809 node.uselib = 'RT EV OPENSSL CARES EXECINFO DL KVM SOCKET NSL KSTAT UTIL OPROFILE'
810 node.add_objects = 'eio http_parser'
811 if product_type_is_lib:
812 node.install_path = '${LIBDIR}'
814 node.install_path = '${PREFIX}/bin'
819 src/node_javascript.cc
820 src/node_extensions.cc
821 src/node_http_parser.cc
823 src/node_io_watcher.cc
824 src/node_constants.cc
828 src/node_signal_watcher.cc
829 src/node_stat_watcher.cc
837 if sys.platform.startswith("win32"):
838 node.source += " src/node_stdio_win32.cc "
839 node.source += " src/node_child_process_win32.cc "
841 node.source += " src/node_stdio.cc "
842 node.source += " src/node_child_process.cc "
844 node.source += bld.env["PLATFORM_FILE"]
845 if not product_type_is_lib:
846 node.source = 'src/node_main.cc '+node.source
848 if bld.env["USE_OPENSSL"]: node.source += " src/node_crypto.cc "
856 if not bld.env["USE_SHARED_V8"]: node.includes += ' deps/v8/include '
858 if not bld.env["USE_SHARED_LIBEV"]:
859 node.add_objects += ' ev '
860 node.includes += ' deps/libev '
862 if not bld.env["USE_SHARED_CARES"]:
863 node.add_objects += ' cares '
864 node.includes += ' deps/c-ares deps/c-ares/' + bld.env['DEST_OS'] + '-' + bld.env['DEST_CPU']
866 if sys.platform.startswith('cygwin'):
867 bld.env.append_value('LINKFLAGS', '-Wl,--export-all-symbols')
868 bld.env.append_value('LINKFLAGS', '-Wl,--out-implib,default/libnode.dll.a')
869 bld.env.append_value('LINKFLAGS', '-Wl,--output-def,default/libnode.def')
870 bld.install_files('${LIBDIR}', "build/default/libnode.*")
872 def subflags(program):
873 x = { 'CCFLAGS' : " ".join(program.env["CCFLAGS"]).replace('"', '\\"')
874 , 'CPPFLAGS' : " ".join(program.env["CPPFLAGS"]).replace('"', '\\"')
875 , 'LIBFLAGS' : " ".join(program.env["LIBFLAGS"]).replace('"', '\\"')
876 , 'PREFIX' : safe_path(program.env["PREFIX"])
877 , 'VERSION' : '0.4.7' # FIXME should not be hard-coded, see NODE_VERSION_STRING in src/node_version.
881 # process file.pc.in -> file.pc
883 node_conf = bld.new_task_gen('subst', before="cxx")
884 node_conf.source = 'src/node_config.h.in'
885 node_conf.target = 'src/node_config.h'
886 node_conf.dict = subflags(node)
887 node_conf.install_path = '${PREFIX}/include/node'
889 if bld.env["USE_DEBUG"]:
890 node_g = node.clone("debug")
891 node_g.target = "node_g"
892 node_g.uselib += ' V8_G'
894 node_conf_g = node_conf.clone("debug")
895 node_conf_g.dict = subflags(node_g)
896 node_conf_g.install_path = None
898 # After creating the debug clone, append the V8 dep
901 bld.install_files('${PREFIX}/include/node/', """
904 src/node_object_wrap.h
910 # Only install the man page if it exists.
911 # Do 'make doc install' to build and install it.
912 if os.path.exists('doc/node.1'):
913 bld.install_files('${PREFIX}/share/man/man1/', 'doc/node.1')
915 bld.install_files('${PREFIX}/bin/', 'tools/node-waf', chmod=0755)
916 bld.install_files('${LIBDIR}/node/wafadmin', 'tools/wafadmin/*.py')
917 bld.install_files('${LIBDIR}/node/wafadmin/Tools', 'tools/wafadmin/Tools/*.py')
919 # create a pkg-config(1) file
920 node_conf = bld.new_task_gen('subst', before="cxx")
921 node_conf.source = 'tools/nodejs.pc.in'
922 node_conf.target = 'tools/nodejs.pc'
923 node_conf.dict = subflags(node)
925 bld.install_files('${LIBDIR}/pkgconfig', 'tools/nodejs.pc')
928 Options.options.debug
929 # HACK to get binding.node out of build directory.
930 # better way to do this?
931 if Options.commands['configure']:
932 if not Options.options.use_openssl:
933 print "WARNING WARNING WARNING"
934 print "OpenSSL not found. Will compile Node without crypto support!"
936 if not Options.options.platform_file:
937 print "WARNING: Platform not fully supported. Using src/platform_none.cc"
939 elif not Options.commands['clean']:
940 if sys.platform.startswith("win32"):
941 if os.path.exists('build/default/node.exe'):
942 os.system('cp build/default/node.exe .')
943 if os.path.exists('build/debug/node_g.exe'):
944 os.system('cp build/debug/node_g.exe .')
946 if os.path.exists('build/default/node') and not os.path.exists('node'):
947 os.symlink('build/default/node', 'node')
948 if os.path.exists('build/debug/node_g') and not os.path.exists('node_g'):
949 os.symlink('build/debug/node_g', 'node_g')
951 if sys.platform.startswith("win32"):
952 if os.path.exists('node.exe'): os.unlink('node.exe')
953 if os.path.exists('node_g.exe'): os.unlink('node_g.exe')
955 if os.path.exists('node'): os.unlink('node')
956 if os.path.exists('node_g'): os.unlink('node_g')