Building Mixed C and C++ node.js Modules
I had some trouble getting node.js modules containing both C and C++ files to build. It took me some time to track down the problem, and the solution isn't especially obvious, so I'm posting this on the web in case anyone else runs into this.
The standard way to connect to node.js from C++ is via a module, which you typically build using the "node-waf" script that ships with node, and which is essentially a wrapper for for the waf build system. It's easy to get your C++ code compiling using the example
wscript build file.
However, most of our driver is written in pure C, and many source files have turned out not to be valid C++. In most cases, this is easily fixed by inserting explicit static casts where we were casting from
void* implicitly, but in some cases it's a little trickier. Instead of spending time picking apart perfectly good code, I decided to try to get waf to build our .c files with gcc, not g++. This turned out to be somewhat trickier than expected.
Attacking the Problem
The typical wscript file contains a bunch of settings with "cxx" in the name, so I started by adding "c" versions, which didn't work. Changing them to "cc" (for "C compiler") got rid of the errors:
def set_options(opt): opt.tool_options("compiler_cxx") opt.tool_options("compiler_cc") def configure(conf): conf.check_tool("compiler_cc") conf.check_tool("compiler_cxx") conf.check_tool("node_addon")
node-waf configure later, the files were still being compiled with g++. This line seemed the next obvious candidate:
obj = bld.new_task_gen("cxx", "shlib", "node_addon")
Unfortunately, simply inserting a strategically placed "cc" didn't quite have the intended effect. The .c files were now being compiled correctly, but the "shlib" task was suddenly no recognised:
feature 'shlib' does not exist - bind at least one method to it
Node modules are essentially dynamically linked (shared) libraries, and the shlib task links your object (.o) files into such a library.
After some frustrated experimentation, I finally discovered a report filed in the waf bug tracker by someone having a similar problem. It turns out you have specify both
cshlib to make it work. Waf also seems fussy about the order the features appear in.
Finally, if you're specifying any of your own compiler flags in
cxxflags, those won't be used for the C compiler - that uses
A mixed C and C++ node.js module example build script therefore looks something like this:
srcdir = "." blddir = "build" VERSION = "0.0.1" def set_options(opt): opt.tool_options("compiler_cc") opt.tool_options("compiler_cxx") def configure(conf): conf.check_tool("compiler_cc") conf.check_tool("compiler_cxx") conf.check_tool("node_addon") def build(bld): obj = bld.new_task_gen("cc", "cxx", "cxxshlib", "cshlib", "node_addon") obj.cxxflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE"] obj.cflags = ["-g", "-D_FILE_OFFSET_BITS=64", "-D_LARGEFILE_SOURCE"] obj.target = "example" obj.source = "example_cpp_file.cpp" obj.source = "example_c_file.c"
The waf bug tracker link I found uses the build task "c", not "cc". If you're on a different OS (we're currently only using our tool on Mac OS X), and you're having trouble, you might want to try that instead.