Skip to content

Instantly share code, notes, and snippets.

@awwright
Created March 5, 2014 08:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save awwright/9363269 to your computer and use it in GitHub Desktop.
Save awwright/9363269 to your computer and use it in GitHub Desktop.
Node.js Makefile Build
OUT_BINNAME ?= node
# Default target
all: $(OUT_BINNAME)
printall:
@echo $(NODE_OBJECTS)
# Specify BUILDTYPE=Release on the command line for a release build.
BUILDTYPE ?= Release
ifeq ($(BUILDTYPE), "Debug")
DEBUG=1
endif
SHARED_V8 ?= 1
SHARED_HTTP_PARSER ?= 0
SHARED_UV ?= 0
NODE_FLAGS =
NODE_FLAGS += '-DNODE_WANT_INTERNALS=1' '-DARCH="$(DESTCPU)"' '-DPLATFORM="$(PLATFORM)"' '-DNODE_TAG=""' '-DHAVE_OPENSSL=1'
NODE_FLAGS += '-D__POSIX__' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-D_POSIX_C_SOURCE=200112'
NODE_FLAGS += -I./src -I$(builddir)/src
NODE_FLAGS += -pthread -Wall -Wextra -Wno-unused-parameter -m64 -O2 -fno-strict-aliasing -fno-tree-vrp -fno-rtti -fno-exceptions
NODE_LDFLAGS := -lz -lcares -lssl -lcrypto -lm -ldl -lrt
NODE_OBJECTS = \
cares_wrap.o \
fs_event_wrap.o \
handle_wrap.o \
node.o \
node_buffer.o \
node_constants.o \
node_crypto.o \
node_crypto_bio.o \
node_extensions.o \
node_file.o \
node_http_parser.o \
node_javascript.o \
node_main.o \
node_os.o \
node_script.o \
node_stat_watcher.o \
node_string.o \
node_watchdog.o \
node_zlib.o \
pipe_wrap.o \
process_wrap.o \
signal_wrap.o \
smalloc.o \
stream_wrap.o \
string_bytes.o \
tcp_wrap.o \
timer_wrap.o \
tls_wrap.o \
tty_wrap.o \
udp_wrap.o \
ifeq ($(BUILD_WIN32), 1)
NODE_OBJECTS += \
node_win32_etw_provider.o \
node_win32_perfctr_provider.o
endif
NODE_LIBS :=
ifeq ($(SHARED_HTTP_PARSER), 1)
NODE_LDFLAGS += -lhttp_parser
else
NODE_LIBS += deps/http_parser/libhttp_parser.a
NODE_FLAGS += -I./deps/http_parser
clean: clean-deps-http_parser
endif
deps/http_parser/libhttp_parser.a:
cd deps/http_parser && $(MAKE) libhttp_parser.o
rm -f $@
$(AR) crs $@ deps/http_parser/libhttp_parser.o
.PHONY: clean-deps-http_parser
clean-deps-http_parser:
cd deps/http_parser && $(MAKE) clean
ifeq ($(SHARED_UV), 1)
NODE_LDFLAGS += -luv
else
NODE_LIBS += deps/uv/libuv.a
NODE_FLAGS += -I./deps/uv/include
clean: clean-deps-uv
endif
deps/uv/libuv.a:
cd deps/uv && $(MAKE) libuv.a
.PHONY: clean-deps-uv
clean-deps-uv:
cd deps/uv && $(MAKE) clean
ifeq ($(SHARED_V8), 1)
NODE_LDFLAGS += -lv8
else
V8_ARCH = x64.release
V8_BUILD_PATH = deps/v8/out/$(V8_ARCH)/obj.target/tools/gyp
NODE_LIBS += $(V8_BUILD_PATH)/libv8_base.x64.a
NODE_LIBS += $(V8_BUILD_PATH)/libv8_nosnapshot.x64.a
NODE_FLAGS += -Ideps/v8/include
endif
# This won't honor the cross-compiler settings, appearently
# <https://bugs.gentoo.org/show_bug.cgi?id=354601>
# Please fix your crap, Google.
$(V8_BUILD_PATH)/libv8_base.x64.a $(V8_BUILD_PATH)/libv8_nosnapshot.*.a $(V8_BUILD_PATH)/libv8_snapshot.*.a:
test -d deps/v8/build/gyp || cd deps/v8 && $(MAKE) dependencies
sed -i -e 's/"python"/"<\(python\)"/' deps/v8/DEPS || die
sed -i -e 's/python /python2 /' deps/v8/build/gyp/gyp || die
cd deps/v8 && $(MAKE) $(V8_ARCH)
ifdef DEBUG
NODE_FLAGS += -DDEBUG -D_DEBUG
endif
builddir ?= $(BUILDTYPE)
$(builddir) $(builddir)/src:
test -d $@ || mkdir $@
$(builddir)/src: | $(builddir)
$(OUT_BINNAME): $(builddir)/$(OUT_BINNAME)
ln -fs $< $@
$(builddir)/$(OUT_BINNAME): $(addprefix $(builddir)/,$(NODE_OBJECTS)) $(NODE_LIBS)
#$(LD) $(LDFLAGS) --start-group $^ $(NODE_LDFLAGS) --end-group -o $@
$(CXX) -o $@ -pthread -rdynamic $(LDFLAGS) -Wl,--start-group $^ -Wl,--end-group $(NODE_LDFLAGS)
$(addprefix $(builddir)/,$(NODE_OBJECTS)): $(builddir)/%.o: src/%.cc | $(builddir)
$(CXX) $(NODE_FLAGS) $(CXXFLAGS) $< -c -o $@
$(builddir)/node_javascript.o: $(builddir)/%.o: $(builddir)/src/node_natives.h
CJS_SRC = src/node.js
CJS_SRC_DIRS ?=
# Appearently src/macros.py and src/perfctr_macros.py are used for something?
$(builddir)/src/config.js: | $(builddir)/src
printf '\n{"target_defaults":{},"variables":{}}' > $@
$(builddir)/src/node_natives.h: $(CJS_SRC) $(wildcard lib/*.js) $(builddir)/src/config.js tools/js2c.sh | $(builddir)/src
#$(PYTHON) tools/js2c.py $@ $^
$(SH) tools/js2c.sh --variable node_native node src/node.js $(addprefix -I,$(CJS_SRC_DIRS)) -Ilib --variable config_native config $(builddir)/src/config.js -o$@
#!/bin/sh
TEMPLATE_FILE="src/node_natives.h.in"
OUTPUT_FILE="src/node_natives.h"
PATH_NAME=()
PATH_PATH=()
SCRIPT_NAME=()
SCRIPT_PATH=()
SCRIPT_VAR=()
SCRIPT_CONTENT=()
print_help() {
echo "js2c: Format ECMAScript files into a form suitable for embedding in a compiled application"
echo "Watch in amazement as we implement Node.js require lookups in bash!"
echo "Usage: $0 <options>"
echo "Options:"
echo " -I<dir> Add files in a directory"
echo " -o<filepath> Output to a file (default: '-' standard output)"
echo " --variable <varname> <modulename> <filepath> Add a single file with a custom variable name"
echo " --exclude <pattern> Ignore"
}
push_path() {
echo "push_path($1,$2)" 1>&2
PATH_NAME+=("$1")
PATH_PATH+=("$2")
}
push_script() {
local len=${#SCRIPT_NAME[@]}
local varname=${3:-native_${len}_$(echo -n "${1:1}"|tr -c [a-zA-Z0-9] _)}
for v in "${SCRIPT_VAR[@]}"; do
if [ "$v" == "$varname" ] ; then return; fi
done
if [ -L "$2" ]; then
local target=$(readlink "$2"|sed -e 's|^\(./\)*||g')
push_symlink "$1" "$(dirname $1)/$target"
else
echo "push_script($1, $2, $varname)"
SCRIPT_NAME+=("$1")
SCRIPT_PATH+=("$2")
SCRIPT_VAR+=($varname)
SCRIPT_CONTENT+=("")
fi
}
push_symlink() {
echo "push_symlink($1 -> $2)"
local len=${#SCRIPT_NAME[@]}
local varname=${3:-native_${len}_$(echo -n "${1:1}"|tr -c [a-zA-Z0-9] _)}
SCRIPT_NAME+=("$1")
SCRIPT_PATH+=("")
SCRIPT_VAR+=($varname)
SCRIPT_CONTENT+=("module.exports=require('${2:1}');")
}
get_main() {
# JSON should be pretty easy to parse with some regular expressions, but this works too
cat $1 | grep '"main"' | cut -d: -f2 | cut -d'"' -f2 | sed -e 's|^\(./\)*||g'
}
while (( "$#" )); do
case "$1" in
-?|-h|--help)
print_help; exit ;;
-I*)
push_path "" "$(realpath ${1:2})" ;;
-o*)
OUTPUT_FILE="${1:2}" ;;
--variable)
push_script "/$3" "$4" "$2"
shift; shift; shift;
;;
*)
echo "Unknown argument: $1"
exit 1
;;
esac
shift
done
i=0
while [ -n "${PATH_PATH[i]}" ]; do
D="${PATH_PATH[i]}"
N="${PATH_NAME[i]}"
let DLEN=${#PATH_PATH[i]}+1
#echo $D/*
for filepath in $D/*; do
filename="${filepath:(${DLEN})}"
if [ "${filename:0:1}" == . ]; then continue;
elif [ "${filename:(-4)}" == ".src" ]; then continue;
elif [ "${filename:0:4}" == "test" ]; then continue;
elif [ "${filename:0:7}" == "example" ]; then continue;
elif [ -d "$filepath" ]; then
push_path "$N/$filename" "$filepath"
push_symlink "$N/$filename" "$N/$filename/index"
elif [ "${filepath:(-13)}" == "/package.json" ]; then
push_symlink "$N" "$N/$(get_main $filepath)"
elif [ "${filepath:(-3)}" == ".js" ]; then
push_script "$N/${filename:0:(-3)}" "$filepath"
push_symlink "$N/$filename" "$N/${filename:0:(-3)}"
fi
done;
let i+=1
done
encode_scripts() {
echo "${SCRIPT_PATH[@]}" 1>&2
i=0
while [ -n "${SCRIPT_VAR[i]}" ]; do
MODULEPATH="${SCRIPT_PATH[i]}"
MODULENAME="${SCRIPT_NAME[i]}"
local MODULEDIR="$(echo $MODULENAME|sed -e 's|/[^/]*$|/|')"
echo -n "const char ${SCRIPT_VAR[i]}[] = "\"
if [ -n "$MODULEPATH" ]; then
#echo "$MODULENAME dir $MODULEDIR" 1>&2
#cat $MODULEPATH | sed -e 's|^[\t ]*//.*$||g'|tr '\n' '\r'|sed -e 's|/[\t ]*\*.*\*/[\t ]*|\r|g' -e 's/\r[\r\t ]*/\r/g' -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/\x00//g' -e 's/\r/\\n/g'
# Nuke DTrace support, too
cat $MODULEPATH |tr '\n' '\r' |sed -r -e "s|require\\((['\"])./([^'\"]*)(['\"])\\)|require\\(\1${MODULEDIR:1}\2\3\\)|g" |sed -e 's/\\/\\\\/g' -e 's/"/\\"/g' -e 's/\x00//g' -e 's/\r/\\n/g' -e 's/\(DTRACE\|COUNTER\)_\(HTTP\|NET\)_\(SERVER\|CLIENT\|STREAM\)_\(REQUEST\|RESPONSE\|CONNECTION\|END\|READ\|WRITE\|CONNECTION_CLOSE\)([^)]*)\(\|;\)//g'
fi
if [ -n "${SCRIPT_CONTENT[i]}" ]; then
#echo "$MODULENAME content ${SCRIPT_CONTENT[i]}" 1>&2
echo -n "${SCRIPT_CONTENT[i]}"
fi
echo '";'
let i+=1
done
}
list_scripts() {
i=0
while [ -n "${SCRIPT_VAR[i]}" ]; do
NAME=native_script_${i}_$(echo -n "${SCRIPT_NAME[i]:1}"|tr -c [a-zA-Z0-9] _)
echo "{ \"${SCRIPT_NAME[i]:1}\", ${SCRIPT_VAR[i]}, sizeof(${SCRIPT_VAR[i]})-1 }, "
let i+=1
done
}
cat <<TEXT >"$OUTPUT_FILE"
#ifndef node_natives_h
#define node_natives_h
namespace node {
$(encode_scripts)
// const char config_native[] = { 30, 0 };
struct _native {
const char* name;
const char* source;
size_t source_len;
};
static const struct _native natives[] = {
$(list_scripts)
// # { "config", config_native, sizeof(config_native)-1 },
{ NULL, NULL, 0 } /* sentinel */
};
}
#endif
TEXT
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment