Land Cantrill's DTrace patch
only works on solaris
This commit is contained in:
parent
91cc2d8c4b
commit
068b733583
@ -599,6 +599,7 @@ OutgoingMessage.prototype.end = function(data, encoding) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
this.finished = true;
|
this.finished = true;
|
||||||
|
DTRACE_HTTP_SERVER_RESPONSE(this.connection);
|
||||||
|
|
||||||
// There is the first message on the outgoing queue, and we've sent
|
// There is the first message on the outgoing queue, and we've sent
|
||||||
// everything to the socket.
|
// everything to the socket.
|
||||||
@ -866,6 +867,7 @@ function connectionListener(socket) {
|
|||||||
var res = new ServerResponse(req);
|
var res = new ServerResponse(req);
|
||||||
debug('server response shouldKeepAlive: ' + shouldKeepAlive);
|
debug('server response shouldKeepAlive: ' + shouldKeepAlive);
|
||||||
res.shouldKeepAlive = shouldKeepAlive;
|
res.shouldKeepAlive = shouldKeepAlive;
|
||||||
|
DTRACE_HTTP_SERVER_REQUEST(req, socket);
|
||||||
|
|
||||||
if (socket._httpMessage) {
|
if (socket._httpMessage) {
|
||||||
// There are already pending outgoing res, append.
|
// There are already pending outgoing res, append.
|
||||||
|
@ -789,6 +789,7 @@ Socket.prototype._shutdown = function() {
|
|||||||
Socket.prototype.end = function(data, encoding) {
|
Socket.prototype.end = function(data, encoding) {
|
||||||
if (this.writable) {
|
if (this.writable) {
|
||||||
if (this._writeQueueLast() !== END_OF_FILE) {
|
if (this._writeQueueLast() !== END_OF_FILE) {
|
||||||
|
DTRACE_NET_STREAM_END(this);
|
||||||
if (data) this.write(data, encoding);
|
if (data) this.write(data, encoding);
|
||||||
this._writeQueue.push(END_OF_FILE);
|
this._writeQueue.push(END_OF_FILE);
|
||||||
if (!this._connecting) {
|
if (!this._connecting) {
|
||||||
@ -868,6 +869,7 @@ function Server(/* [ options, ] listener */) {
|
|||||||
s.server = self;
|
s.server = self;
|
||||||
s.resume();
|
s.resume();
|
||||||
|
|
||||||
|
DTRACE_NET_SERVER_CONNECTION(s);
|
||||||
self.emit('connection', s);
|
self.emit('connection', s);
|
||||||
|
|
||||||
// The 'connect' event probably should be removed for server-side
|
// The 'connect' event probably should be removed for server-side
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
#include <node.h>
|
#include <node.h>
|
||||||
|
|
||||||
#include <v8-debug.h>
|
#include <v8-debug.h>
|
||||||
|
#include <node_dtrace.h>
|
||||||
|
|
||||||
#include <locale.h>
|
#include <locale.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@ -2028,6 +2029,8 @@ static void Load(int argc, char *argv[]) {
|
|||||||
Local<Object> global = v8::Context::GetCurrent()->Global();
|
Local<Object> global = v8::Context::GetCurrent()->Global();
|
||||||
Local<Value> args[1] = { Local<Value>::New(process) };
|
Local<Value> args[1] = { Local<Value>::New(process) };
|
||||||
|
|
||||||
|
InitDTrace(global);
|
||||||
|
|
||||||
f->Call(global, 1, args);
|
f->Call(global, 1, args);
|
||||||
|
|
||||||
if (try_catch.HasCaught()) {
|
if (try_catch.HasCaught()) {
|
||||||
|
64
src/node.d
Normal file
64
src/node.d
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/*
|
||||||
|
* This is the DTrace library file for the node provider, which includes
|
||||||
|
* the necessary translators to get from the args[] to something useful.
|
||||||
|
* Be warned: the mechanics here are seriously ugly -- and one must always
|
||||||
|
* keep in mind that clean abstractions often require filthy systems.
|
||||||
|
*/
|
||||||
|
#pragma D depends_on library procfs.d
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t fd;
|
||||||
|
int32_t port;
|
||||||
|
uint32_t remote;
|
||||||
|
} node_dtrace_connection_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t fd;
|
||||||
|
int32_t port;
|
||||||
|
uint64_t remote;
|
||||||
|
} node_dtrace_connection64_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int fd;
|
||||||
|
string remoteAddress;
|
||||||
|
int remotePort;
|
||||||
|
} node_connection_t;
|
||||||
|
|
||||||
|
translator node_connection_t <node_dtrace_connection_t *nc> {
|
||||||
|
fd = *(int32_t *)copyin((uintptr_t)&nc->fd, sizeof (int32_t));
|
||||||
|
remotePort =
|
||||||
|
*(int32_t *)copyin((uintptr_t)&nc->port, sizeof (int32_t));
|
||||||
|
remoteAddress = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
|
||||||
|
copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)&nc->remote,
|
||||||
|
sizeof (int32_t))) :
|
||||||
|
copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t)
|
||||||
|
&((node_dtrace_connection64_t *)nc)->remote, sizeof (int64_t)));
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint32_t url;
|
||||||
|
uint32_t method;
|
||||||
|
} node_dtrace_http_request_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
uint64_t url;
|
||||||
|
uint64_t method;
|
||||||
|
} node_dtrace_http_request64_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
string url;
|
||||||
|
string method;
|
||||||
|
} node_http_request_t;
|
||||||
|
|
||||||
|
translator node_http_request_t <node_dtrace_http_request_t *nd> {
|
||||||
|
url = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
|
||||||
|
copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)&nd->url,
|
||||||
|
sizeof (int32_t))) :
|
||||||
|
copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t)
|
||||||
|
&((node_dtrace_http_request64_t *)nd)->url, sizeof (int64_t)));
|
||||||
|
method = curpsinfo->pr_dmodel == PR_MODEL_ILP32 ?
|
||||||
|
copyinstr((uintptr_t)*(uint32_t *)copyin((uintptr_t)&nd->method,
|
||||||
|
sizeof (int32_t))) :
|
||||||
|
copyinstr((uintptr_t)*(uint64_t *)copyin((uintptr_t)
|
||||||
|
&((node_dtrace_http_request64_t *)nd)->method, sizeof (int64_t)));
|
||||||
|
};
|
113
src/node_dtrace.cc
Normal file
113
src/node_dtrace.cc
Normal file
@ -0,0 +1,113 @@
|
|||||||
|
#include <node_dtrace.h>
|
||||||
|
|
||||||
|
#ifdef HAVE_DTRACE
|
||||||
|
#include "node_provider.h"
|
||||||
|
#else
|
||||||
|
#define NODE_HTTP_SERVER_REQUEST(arg0, arg1)
|
||||||
|
#define NODE_HTTP_SERVER_REQUEST_ENABLED() (0)
|
||||||
|
#define NODE_HTTP_SERVER_RESPONSE(arg0)
|
||||||
|
#define NODE_HTTP_SERVER_RESPONSE_ENABLED() (0)
|
||||||
|
#define NODE_NET_SERVER_CONNECTION(arg0)
|
||||||
|
#define NODE_NET_SERVER_CONNECTION_ENABLED() (0)
|
||||||
|
#define NODE_NET_STREAM_END(arg0)
|
||||||
|
#define NODE_NET_STREAM_END_ENABLED() (0)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
|
||||||
|
using namespace v8;
|
||||||
|
|
||||||
|
#define SLURP_STRING(obj, member, valp) \
|
||||||
|
String::Utf8Value _##member(obj->Get(String::New(#member))->ToString()); \
|
||||||
|
if ((*(const char **)valp = *_##member) == NULL) \
|
||||||
|
*(const char **)valp = "<unknown>";
|
||||||
|
|
||||||
|
#define SLURP_INT(obj, member, valp) \
|
||||||
|
*valp = obj->Get(String::New(#member))->ToInteger()->Value();
|
||||||
|
|
||||||
|
#define SLURP_CONNECTION(arg, conn) \
|
||||||
|
node_dtrace_connection_t conn; \
|
||||||
|
Local<Object> _##conn = Local<Object>::Cast(arg); \
|
||||||
|
SLURP_INT(_##conn, fd, &conn.fd); \
|
||||||
|
SLURP_STRING(_##conn, remoteAddress, &conn.remote); \
|
||||||
|
SLURP_INT(_##conn, remotePort, &conn.port);
|
||||||
|
|
||||||
|
Handle<Value> DTRACE_NET_SERVER_CONNECTION(const Arguments& args) {
|
||||||
|
if (!NODE_NET_SERVER_CONNECTION_ENABLED())
|
||||||
|
return Undefined();
|
||||||
|
|
||||||
|
HandleScope scope;
|
||||||
|
|
||||||
|
SLURP_CONNECTION(args[0], conn);
|
||||||
|
NODE_NET_SERVER_CONNECTION(&conn);
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<Value> DTRACE_NET_STREAM_END(const Arguments& args) {
|
||||||
|
if (!NODE_NET_STREAM_END_ENABLED())
|
||||||
|
return Undefined();
|
||||||
|
|
||||||
|
HandleScope scope;
|
||||||
|
|
||||||
|
SLURP_CONNECTION(args[0], conn);
|
||||||
|
NODE_NET_STREAM_END(&conn);
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<Value> DTRACE_HTTP_SERVER_REQUEST(const Arguments& args) {
|
||||||
|
node_dtrace_http_request_t req;
|
||||||
|
|
||||||
|
if (!NODE_HTTP_SERVER_REQUEST_ENABLED())
|
||||||
|
return Undefined();
|
||||||
|
|
||||||
|
HandleScope scope;
|
||||||
|
|
||||||
|
Local<Object> arg0 = Local<Object>::Cast(args[0]);
|
||||||
|
Local<Object> arg1 = Local<Object>::Cast(args[1]);
|
||||||
|
|
||||||
|
SLURP_STRING(arg0, url, &req.url);
|
||||||
|
SLURP_STRING(arg0, method, &req.method);
|
||||||
|
|
||||||
|
SLURP_CONNECTION(args[1], conn);
|
||||||
|
|
||||||
|
NODE_HTTP_SERVER_REQUEST(&req, &conn);
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
Handle<Value> DTRACE_HTTP_SERVER_RESPONSE(const Arguments& args) {
|
||||||
|
if (!NODE_HTTP_SERVER_RESPONSE_ENABLED())
|
||||||
|
return Undefined();
|
||||||
|
|
||||||
|
HandleScope scope;
|
||||||
|
|
||||||
|
SLURP_CONNECTION(args[0], conn);
|
||||||
|
NODE_HTTP_SERVER_RESPONSE(&conn);
|
||||||
|
|
||||||
|
return Undefined();
|
||||||
|
}
|
||||||
|
|
||||||
|
#define NODE_PROBE(name) #name, name
|
||||||
|
|
||||||
|
void InitDTrace(Handle<Object> target) {
|
||||||
|
static struct {
|
||||||
|
const char *name;
|
||||||
|
Handle<Value> (*func)(const Arguments&);
|
||||||
|
Persistent<FunctionTemplate> templ;
|
||||||
|
} tab[] = {
|
||||||
|
{ NODE_PROBE(DTRACE_NET_SERVER_CONNECTION) },
|
||||||
|
{ NODE_PROBE(DTRACE_NET_STREAM_END) },
|
||||||
|
{ NODE_PROBE(DTRACE_HTTP_SERVER_REQUEST) },
|
||||||
|
{ NODE_PROBE(DTRACE_HTTP_SERVER_RESPONSE) },
|
||||||
|
{ NULL }
|
||||||
|
};
|
||||||
|
|
||||||
|
for (int i = 0; tab[i].name != NULL; i++) {
|
||||||
|
tab[i].templ = Persistent<FunctionTemplate>::New(
|
||||||
|
FunctionTemplate::New(tab[i].func));
|
||||||
|
target->Set(String::NewSymbol(tab[i].name), tab[i].templ->GetFunction());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
28
src/node_dtrace.h
Normal file
28
src/node_dtrace.h
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#ifndef NODE_DTRACE_H_
|
||||||
|
#define NODE_DTRACE_H_
|
||||||
|
|
||||||
|
#include <node.h>
|
||||||
|
#include <v8.h>
|
||||||
|
|
||||||
|
extern "C" {
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t fd;
|
||||||
|
int32_t port;
|
||||||
|
char *remote;
|
||||||
|
} node_dtrace_connection_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char *url;
|
||||||
|
char *method;
|
||||||
|
} node_dtrace_http_request_t;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
namespace node {
|
||||||
|
|
||||||
|
void InitDTrace(v8::Handle<v8::Object> target);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
44
src/node_provider.d
Normal file
44
src/node_provider.d
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* DTrace provider for node.js.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In order to have the information we need here to create the provider,
|
||||||
|
* we must declare bogus definitions for our depended-upon structures. And
|
||||||
|
* yes, the fact that we need to do this represents a shortcoming in DTrace,
|
||||||
|
* one that would be resolved by that elusive El Dorado: dynamic translators.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int dummy;
|
||||||
|
} node_dtrace_connection_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int dummy;
|
||||||
|
} node_connection_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int dummy;
|
||||||
|
} node_dtrace_http_request_t;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int dummy;
|
||||||
|
} node_http_request_t;
|
||||||
|
|
||||||
|
provider node {
|
||||||
|
probe net__server__connection(node_dtrace_connection_t *c) :
|
||||||
|
(node_connection_t *c);
|
||||||
|
probe net__stream__end(node_dtrace_connection_t *c) :
|
||||||
|
(node_connection_t *c);
|
||||||
|
probe http__server__request(node_dtrace_http_request_t *h,
|
||||||
|
node_dtrace_connection_t *c) :
|
||||||
|
(node_http_request_t *h, node_connection_t *c);
|
||||||
|
probe http__server__response(node_dtrace_connection_t *c) :
|
||||||
|
(node_connection_t *c);
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma D attributes Evolving/Evolving/ISA provider node provider
|
||||||
|
#pragma D attributes Private/Private/Unknown provider node module
|
||||||
|
#pragma D attributes Private/Private/Unknown provider node function
|
||||||
|
#pragma D attributes Private/Private/ISA provider node name
|
||||||
|
#pragma D attributes Evolving/Evolving/ISA provider node args
|
@ -39,6 +39,13 @@ process.on('exit', function() {
|
|||||||
process,
|
process,
|
||||||
global];
|
global];
|
||||||
|
|
||||||
|
if (DTRACE_HTTP_SERVER_RESPONSE) {
|
||||||
|
knownGlobals.push(DTRACE_HTTP_SERVER_RESPONSE);
|
||||||
|
knownGlobals.push(DTRACE_HTTP_SERVER_REQUEST);
|
||||||
|
knownGlobals.push(DTRACE_NET_STREAM_END);
|
||||||
|
knownGlobals.push(DTRACE_NET_SERVER_CONNECTION);
|
||||||
|
}
|
||||||
|
|
||||||
for (var x in global) {
|
for (var x in global) {
|
||||||
var found = false;
|
var found = false;
|
||||||
|
|
||||||
|
97
wscript
97
wscript
@ -1,7 +1,8 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import re
|
import re
|
||||||
import Options
|
import Options
|
||||||
import sys, os, shutil
|
import sys, os, shutil, glob
|
||||||
|
import Utils
|
||||||
from Utils import cmd_output
|
from Utils import cmd_output
|
||||||
from os.path import join, dirname, abspath
|
from os.path import join, dirname, abspath
|
||||||
from logging import fatal
|
from logging import fatal
|
||||||
@ -158,6 +159,13 @@ def set_options(opt):
|
|||||||
, dest='shared_libev_libpath'
|
, dest='shared_libev_libpath'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
opt.add_option( '--with-dtrace'
|
||||||
|
, action='store_true'
|
||||||
|
, default=False
|
||||||
|
, help='Build with DTrace (experimental)'
|
||||||
|
, dest='dtrace'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
opt.add_option( '--product-type'
|
opt.add_option( '--product-type'
|
||||||
, action='store'
|
, action='store'
|
||||||
@ -214,6 +222,14 @@ def configure(conf):
|
|||||||
#if Options.options.debug:
|
#if Options.options.debug:
|
||||||
# conf.check(lib='profiler', uselib_store='PROFILER')
|
# conf.check(lib='profiler', uselib_store='PROFILER')
|
||||||
|
|
||||||
|
if Options.options.dtrace:
|
||||||
|
if not sys.platform.startswith("sunos"):
|
||||||
|
conf.fatal('DTrace support only currently available on Solaris')
|
||||||
|
|
||||||
|
conf.find_program('dtrace', var='DTRACE', mandatory=True)
|
||||||
|
conf.env["USE_DTRACE"] = True
|
||||||
|
conf.env.append_value("CXXFLAGS", "-DHAVE_DTRACE=1")
|
||||||
|
|
||||||
if Options.options.efence:
|
if Options.options.efence:
|
||||||
conf.check(lib='efence', libpath=['/usr/lib', '/usr/local/lib'], uselib_store='EFENCE')
|
conf.check(lib='efence', libpath=['/usr/lib', '/usr/local/lib'], uselib_store='EFENCE')
|
||||||
|
|
||||||
@ -562,7 +578,7 @@ def build(bld):
|
|||||||
|
|
||||||
### src/native.cc
|
### src/native.cc
|
||||||
def make_macros(loc, content):
|
def make_macros(loc, content):
|
||||||
f = open(loc, 'w')
|
f = open(loc, 'a')
|
||||||
f.write(content)
|
f.write(content)
|
||||||
f.close
|
f.close
|
||||||
|
|
||||||
@ -576,10 +592,27 @@ def build(bld):
|
|||||||
"macros.py"
|
"macros.py"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
### We need to truncate the macros.py file
|
||||||
|
f = open(macros_loc_debug, 'w')
|
||||||
|
f.close
|
||||||
|
f = open(macros_loc_default, 'w')
|
||||||
|
f.close
|
||||||
|
|
||||||
make_macros(macros_loc_debug, "") # leave debug(x) as is in debug build
|
make_macros(macros_loc_debug, "") # leave debug(x) as is in debug build
|
||||||
# replace debug(x) with nothing in release build
|
# replace debug(x) with nothing in release build
|
||||||
make_macros(macros_loc_default, "macro debug(x) = ;\n")
|
make_macros(macros_loc_default, "macro debug(x) = ;\n")
|
||||||
|
|
||||||
|
if not bld.env["USE_DTRACE"]:
|
||||||
|
make_macros(macros_loc_default, "macro DTRACE_HTTP_SERVER_RESPONSE(x) = ;\n");
|
||||||
|
make_macros(macros_loc_default, "macro DTRACE_HTTP_SERVER_REQUEST(x) = ;\n");
|
||||||
|
make_macros(macros_loc_default, "macro DTRACE_NET_SERVER_CONNECTION(x) = ;\n");
|
||||||
|
make_macros(macros_loc_default, "macro DTRACE_NET_STREAM_END(x) = ;\n");
|
||||||
|
make_macros(macros_loc_debug, "macro DTRACE_HTTP_SERVER_RESPONSE(x) = ;\n");
|
||||||
|
make_macros(macros_loc_debug, "macro DTRACE_HTTP_SERVER_REQUEST(x) = ;\n");
|
||||||
|
make_macros(macros_loc_debug, "macro DTRACE_NET_SERVER_CONNECTION(x) = ;\n");
|
||||||
|
make_macros(macros_loc_debug, "macro DTRACE_NET_STREAM_END(x) = ;\n");
|
||||||
|
|
||||||
|
|
||||||
def javascript_in_c(task):
|
def javascript_in_c(task):
|
||||||
env = task.env
|
env = task.env
|
||||||
source = map(lambda x: x.srcpath(env), task.inputs)
|
source = map(lambda x: x.srcpath(env), task.inputs)
|
||||||
@ -610,6 +643,65 @@ def build(bld):
|
|||||||
native_cc_debug.rule = javascript_in_c_debug
|
native_cc_debug.rule = javascript_in_c_debug
|
||||||
|
|
||||||
native_cc.rule = javascript_in_c
|
native_cc.rule = javascript_in_c
|
||||||
|
|
||||||
|
if bld.env["USE_DTRACE"]:
|
||||||
|
dtrace = bld.new_task_gen(
|
||||||
|
name = "dtrace",
|
||||||
|
source = "src/node_provider.d",
|
||||||
|
target = "src/node_provider.h",
|
||||||
|
rule = "%s -x nolibs -h -o ${TGT} -s ${SRC}" % (bld.env.DTRACE),
|
||||||
|
before = "cxx",
|
||||||
|
)
|
||||||
|
|
||||||
|
if bld.env["USE_DEBUG"]:
|
||||||
|
dtrace_g = dtrace.clone("debug")
|
||||||
|
|
||||||
|
bld.install_files('/usr/lib/dtrace', 'src/node.d')
|
||||||
|
|
||||||
|
if sys.platform.startswith("sunos"):
|
||||||
|
#
|
||||||
|
# The USDT DTrace provider works slightly differently on Solaris than on
|
||||||
|
# the Mac; on Solaris, any objects that have USDT DTrace probes must be
|
||||||
|
# post-processed with the DTrace command. (This is not true on the
|
||||||
|
# Mac, which has first-class linker support for USDT probes.) On
|
||||||
|
# Solaris, we must therefore post-process our object files. Waf doesn't
|
||||||
|
# seem to really have a notion for this, so we inject a task after
|
||||||
|
# compiling and before linking, and then find all of the node object
|
||||||
|
# files and shuck them off to dtrace (which will modify them in place
|
||||||
|
# as appropriate).
|
||||||
|
#
|
||||||
|
def dtrace_postprocess(task):
|
||||||
|
abspath = bld.srcnode.abspath(bld.env_of_name(task.env.variant()))
|
||||||
|
objs = glob.glob(abspath + 'src/*.o')
|
||||||
|
|
||||||
|
Utils.exec_command('%s -G -x nolibs -s %s %s' % (task.env.DTRACE,
|
||||||
|
task.inputs[0].srcpath(task.env), ' '.join(objs)))
|
||||||
|
|
||||||
|
dtracepost = bld.new_task_gen(
|
||||||
|
name = "dtrace-postprocess",
|
||||||
|
source = "src/node_provider.d",
|
||||||
|
always = True,
|
||||||
|
before = "cxx_link",
|
||||||
|
after = "cxx",
|
||||||
|
)
|
||||||
|
|
||||||
|
bld.env.append_value('LINKFLAGS', 'node_provider.o')
|
||||||
|
|
||||||
|
#
|
||||||
|
# Note that for the same (mysterious) issue outlined above with respect
|
||||||
|
# to assigning the rule to native_cc/native_cc_debug, we must apply the
|
||||||
|
# rule to dtracepost/dtracepost_g only after they have been cloned. We
|
||||||
|
# also must put node_provider.o on the link line, but because we
|
||||||
|
# (apparently?) lack LINKFLAGS in debug, we (shamelessly) stowaway on
|
||||||
|
# LINKFLAGS_V8_G.
|
||||||
|
#
|
||||||
|
if bld.env["USE_DEBUG"]:
|
||||||
|
dtracepost_g = dtracepost.clone("debug")
|
||||||
|
dtracepost_g.rule = dtrace_postprocess
|
||||||
|
bld.env_of_name("debug").append_value('LINKFLAGS_V8_G',
|
||||||
|
'node_provider.o')
|
||||||
|
|
||||||
|
dtracepost.rule = dtrace_postprocess
|
||||||
|
|
||||||
### node lib
|
### node lib
|
||||||
node = bld.new_task_gen("cxx", product_type)
|
node = bld.new_task_gen("cxx", product_type)
|
||||||
@ -639,6 +731,7 @@ def build(bld):
|
|||||||
src/node_timer.cc
|
src/node_timer.cc
|
||||||
src/node_script.cc
|
src/node_script.cc
|
||||||
src/node_os.cc
|
src/node_os.cc
|
||||||
|
src/node_dtrace.cc
|
||||||
"""
|
"""
|
||||||
|
|
||||||
if sys.platform.startswith("win32"):
|
if sys.platform.startswith("win32"):
|
||||||
|
Loading…
x
Reference in New Issue
Block a user