正在显示
14 个修改的文件
包含
1278 行增加
和
0 行删除
binding.gyp
0 → 100644
build/Makefile
0 → 100644
| 1 | +# We borrow heavily from the kernel build setup, though we are simpler since | ||
| 2 | +# we don't have Kconfig tweaking settings on us. | ||
| 3 | + | ||
| 4 | +# The implicit make rules have it looking for RCS files, among other things. | ||
| 5 | +# We instead explicitly write all the rules we care about. | ||
| 6 | +# It's even quicker (saves ~200ms) to pass -r on the command line. | ||
| 7 | +MAKEFLAGS=-r | ||
| 8 | + | ||
| 9 | +# The source directory tree. | ||
| 10 | +srcdir := .. | ||
| 11 | +abs_srcdir := $(abspath $(srcdir)) | ||
| 12 | + | ||
| 13 | +# The name of the builddir. | ||
| 14 | +builddir_name ?= . | ||
| 15 | + | ||
| 16 | +# The V=1 flag on command line makes us verbosely print command lines. | ||
| 17 | +ifdef V | ||
| 18 | + quiet= | ||
| 19 | +else | ||
| 20 | + quiet=quiet_ | ||
| 21 | +endif | ||
| 22 | + | ||
| 23 | +# Specify BUILDTYPE=Release on the command line for a release build. | ||
| 24 | +BUILDTYPE ?= Release | ||
| 25 | + | ||
| 26 | +# Directory all our build output goes into. | ||
| 27 | +# Note that this must be two directories beneath src/ for unit tests to pass, | ||
| 28 | +# as they reach into the src/ directory for data with relative paths. | ||
| 29 | +builddir ?= $(builddir_name)/$(BUILDTYPE) | ||
| 30 | +abs_builddir := $(abspath $(builddir)) | ||
| 31 | +depsdir := $(builddir)/.deps | ||
| 32 | + | ||
| 33 | +# Object output directory. | ||
| 34 | +obj := $(builddir)/obj | ||
| 35 | +abs_obj := $(abspath $(obj)) | ||
| 36 | + | ||
| 37 | +# We build up a list of every single one of the targets so we can slurp in the | ||
| 38 | +# generated dependency rule Makefiles in one pass. | ||
| 39 | +all_deps := | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + | ||
| 43 | +CC.target ?= $(CC) | ||
| 44 | +CFLAGS.target ?= $(CPPFLAGS) $(CFLAGS) | ||
| 45 | +CXX.target ?= $(CXX) | ||
| 46 | +CXXFLAGS.target ?= $(CPPFLAGS) $(CXXFLAGS) | ||
| 47 | +LINK.target ?= $(LINK) | ||
| 48 | +LDFLAGS.target ?= $(LDFLAGS) | ||
| 49 | +AR.target ?= $(AR) | ||
| 50 | + | ||
| 51 | +# C++ apps need to be linked with g++. | ||
| 52 | +LINK ?= $(CXX.target) | ||
| 53 | + | ||
| 54 | +# TODO(evan): move all cross-compilation logic to gyp-time so we don't need | ||
| 55 | +# to replicate this environment fallback in make as well. | ||
| 56 | +CC.host ?= gcc | ||
| 57 | +CFLAGS.host ?= $(CPPFLAGS_host) $(CFLAGS_host) | ||
| 58 | +CXX.host ?= g++ | ||
| 59 | +CXXFLAGS.host ?= $(CPPFLAGS_host) $(CXXFLAGS_host) | ||
| 60 | +LINK.host ?= $(CXX.host) | ||
| 61 | +LDFLAGS.host ?= | ||
| 62 | +AR.host ?= ar | ||
| 63 | + | ||
| 64 | +# Define a dir function that can handle spaces. | ||
| 65 | +# http://www.gnu.org/software/make/manual/make.html#Syntax-of-Functions | ||
| 66 | +# "leading spaces cannot appear in the text of the first argument as written. | ||
| 67 | +# These characters can be put into the argument value by variable substitution." | ||
| 68 | +empty := | ||
| 69 | +space := $(empty) $(empty) | ||
| 70 | + | ||
| 71 | +# http://stackoverflow.com/questions/1189781/using-make-dir-or-notdir-on-a-path-with-spaces | ||
| 72 | +replace_spaces = $(subst $(space),?,$1) | ||
| 73 | +unreplace_spaces = $(subst ?,$(space),$1) | ||
| 74 | +dirx = $(call unreplace_spaces,$(dir $(call replace_spaces,$1))) | ||
| 75 | + | ||
| 76 | +# Flags to make gcc output dependency info. Note that you need to be | ||
| 77 | +# careful here to use the flags that ccache and distcc can understand. | ||
| 78 | +# We write to a dep file on the side first and then rename at the end | ||
| 79 | +# so we can't end up with a broken dep file. | ||
| 80 | +depfile = $(depsdir)/$(call replace_spaces,$@).d | ||
| 81 | +DEPFLAGS = -MMD -MF $(depfile).raw | ||
| 82 | + | ||
| 83 | +# We have to fixup the deps output in a few ways. | ||
| 84 | +# (1) the file output should mention the proper .o file. | ||
| 85 | +# ccache or distcc lose the path to the target, so we convert a rule of | ||
| 86 | +# the form: | ||
| 87 | +# foobar.o: DEP1 DEP2 | ||
| 88 | +# into | ||
| 89 | +# path/to/foobar.o: DEP1 DEP2 | ||
| 90 | +# (2) we want missing files not to cause us to fail to build. | ||
| 91 | +# We want to rewrite | ||
| 92 | +# foobar.o: DEP1 DEP2 \ | ||
| 93 | +# DEP3 | ||
| 94 | +# to | ||
| 95 | +# DEP1: | ||
| 96 | +# DEP2: | ||
| 97 | +# DEP3: | ||
| 98 | +# so if the files are missing, they're just considered phony rules. | ||
| 99 | +# We have to do some pretty insane escaping to get those backslashes | ||
| 100 | +# and dollar signs past make, the shell, and sed at the same time. | ||
| 101 | +# Doesn't work with spaces, but that's fine: .d files have spaces in | ||
| 102 | +# their names replaced with other characters. | ||
| 103 | +define fixup_dep | ||
| 104 | +# The depfile may not exist if the input file didn't have any #includes. | ||
| 105 | +touch $(depfile).raw | ||
| 106 | +# Fixup path as in (1). | ||
| 107 | +sed -e "s|^$(notdir $@)|$@|" $(depfile).raw >> $(depfile) | ||
| 108 | +# Add extra rules as in (2). | ||
| 109 | +# We remove slashes and replace spaces with new lines; | ||
| 110 | +# remove blank lines; | ||
| 111 | +# delete the first line and append a colon to the remaining lines. | ||
| 112 | +sed -e 's|\\||' -e 'y| |\n|' $(depfile).raw |\ | ||
| 113 | + grep -v '^$$' |\ | ||
| 114 | + sed -e 1d -e 's|$$|:|' \ | ||
| 115 | + >> $(depfile) | ||
| 116 | +rm $(depfile).raw | ||
| 117 | +endef | ||
| 118 | + | ||
| 119 | +# Command definitions: | ||
| 120 | +# - cmd_foo is the actual command to run; | ||
| 121 | +# - quiet_cmd_foo is the brief-output summary of the command. | ||
| 122 | + | ||
| 123 | +quiet_cmd_cc = CC($(TOOLSET)) $@ | ||
| 124 | +cmd_cc = $(CC.$(TOOLSET)) $(GYP_CFLAGS) $(DEPFLAGS) $(CFLAGS.$(TOOLSET)) -c -o $@ $< | ||
| 125 | + | ||
| 126 | +quiet_cmd_cxx = CXX($(TOOLSET)) $@ | ||
| 127 | +cmd_cxx = $(CXX.$(TOOLSET)) $(GYP_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< | ||
| 128 | + | ||
| 129 | +quiet_cmd_objc = CXX($(TOOLSET)) $@ | ||
| 130 | +cmd_objc = $(CC.$(TOOLSET)) $(GYP_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< | ||
| 131 | + | ||
| 132 | +quiet_cmd_objcxx = CXX($(TOOLSET)) $@ | ||
| 133 | +cmd_objcxx = $(CXX.$(TOOLSET)) $(GYP_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< | ||
| 134 | + | ||
| 135 | +# Commands for precompiled header files. | ||
| 136 | +quiet_cmd_pch_c = CXX($(TOOLSET)) $@ | ||
| 137 | +cmd_pch_c = $(CC.$(TOOLSET)) $(GYP_PCH_CFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< | ||
| 138 | +quiet_cmd_pch_cc = CXX($(TOOLSET)) $@ | ||
| 139 | +cmd_pch_cc = $(CC.$(TOOLSET)) $(GYP_PCH_CXXFLAGS) $(DEPFLAGS) $(CXXFLAGS.$(TOOLSET)) -c -o $@ $< | ||
| 140 | +quiet_cmd_pch_m = CXX($(TOOLSET)) $@ | ||
| 141 | +cmd_pch_m = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCFLAGS) $(DEPFLAGS) -c -o $@ $< | ||
| 142 | +quiet_cmd_pch_mm = CXX($(TOOLSET)) $@ | ||
| 143 | +cmd_pch_mm = $(CC.$(TOOLSET)) $(GYP_PCH_OBJCXXFLAGS) $(DEPFLAGS) -c -o $@ $< | ||
| 144 | + | ||
| 145 | +# gyp-mac-tool is written next to the root Makefile by gyp. | ||
| 146 | +# Use $(4) for the command, since $(2) and $(3) are used as flag by do_cmd | ||
| 147 | +# already. | ||
| 148 | +quiet_cmd_mac_tool = MACTOOL $(4) $< | ||
| 149 | +cmd_mac_tool = ./gyp-mac-tool $(4) $< "$@" | ||
| 150 | + | ||
| 151 | +quiet_cmd_mac_package_framework = PACKAGE FRAMEWORK $@ | ||
| 152 | +cmd_mac_package_framework = ./gyp-mac-tool package-framework "$@" $(4) | ||
| 153 | + | ||
| 154 | +quiet_cmd_infoplist = INFOPLIST $@ | ||
| 155 | +cmd_infoplist = $(CC.$(TOOLSET)) -E -P -Wno-trigraphs -x c $(INFOPLIST_DEFINES) "$<" -o "$@" | ||
| 156 | + | ||
| 157 | +quiet_cmd_touch = TOUCH $@ | ||
| 158 | +cmd_touch = touch $@ | ||
| 159 | + | ||
| 160 | +quiet_cmd_copy = COPY $@ | ||
| 161 | +# send stderr to /dev/null to ignore messages when linking directories. | ||
| 162 | +cmd_copy = rm -rf "$@" && cp -af "$<" "$@" | ||
| 163 | + | ||
| 164 | +quiet_cmd_alink = LIBTOOL-STATIC $@ | ||
| 165 | +cmd_alink = rm -f $@ && ./gyp-mac-tool filter-libtool libtool $(GYP_LIBTOOLFLAGS) -static -o $@ $(filter %.o,$^) | ||
| 166 | + | ||
| 167 | +quiet_cmd_link = LINK($(TOOLSET)) $@ | ||
| 168 | +cmd_link = $(LINK.$(TOOLSET)) $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) | ||
| 169 | + | ||
| 170 | +quiet_cmd_solink = SOLINK($(TOOLSET)) $@ | ||
| 171 | +cmd_solink = $(LINK.$(TOOLSET)) -shared $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o "$@" $(LD_INPUTS) $(LIBS) | ||
| 172 | + | ||
| 173 | +quiet_cmd_solink_module = SOLINK_MODULE($(TOOLSET)) $@ | ||
| 174 | +cmd_solink_module = $(LINK.$(TOOLSET)) -bundle $(GYP_LDFLAGS) $(LDFLAGS.$(TOOLSET)) -o $@ $(filter-out FORCE_DO_CMD, $^) $(LIBS) | ||
| 175 | + | ||
| 176 | + | ||
| 177 | +# Define an escape_quotes function to escape single quotes. | ||
| 178 | +# This allows us to handle quotes properly as long as we always use | ||
| 179 | +# use single quotes and escape_quotes. | ||
| 180 | +escape_quotes = $(subst ','\'',$(1)) | ||
| 181 | +# This comment is here just to include a ' to unconfuse syntax highlighting. | ||
| 182 | +# Define an escape_vars function to escape '$' variable syntax. | ||
| 183 | +# This allows us to read/write command lines with shell variables (e.g. | ||
| 184 | +# $LD_LIBRARY_PATH), without triggering make substitution. | ||
| 185 | +escape_vars = $(subst $$,$$$$,$(1)) | ||
| 186 | +# Helper that expands to a shell command to echo a string exactly as it is in | ||
| 187 | +# make. This uses printf instead of echo because printf's behaviour with respect | ||
| 188 | +# to escape sequences is more portable than echo's across different shells | ||
| 189 | +# (e.g., dash, bash). | ||
| 190 | +exact_echo = printf '%s\n' '$(call escape_quotes,$(1))' | ||
| 191 | + | ||
| 192 | +# Helper to compare the command we're about to run against the command | ||
| 193 | +# we logged the last time we ran the command. Produces an empty | ||
| 194 | +# string (false) when the commands match. | ||
| 195 | +# Tricky point: Make has no string-equality test function. | ||
| 196 | +# The kernel uses the following, but it seems like it would have false | ||
| 197 | +# positives, where one string reordered its arguments. | ||
| 198 | +# arg_check = $(strip $(filter-out $(cmd_$(1)), $(cmd_$@)) \ | ||
| 199 | +# $(filter-out $(cmd_$@), $(cmd_$(1)))) | ||
| 200 | +# We instead substitute each for the empty string into the other, and | ||
| 201 | +# say they're equal if both substitutions produce the empty string. | ||
| 202 | +# .d files contain ? instead of spaces, take that into account. | ||
| 203 | +command_changed = $(or $(subst $(cmd_$(1)),,$(cmd_$(call replace_spaces,$@))),\ | ||
| 204 | + $(subst $(cmd_$(call replace_spaces,$@)),,$(cmd_$(1)))) | ||
| 205 | + | ||
| 206 | +# Helper that is non-empty when a prerequisite changes. | ||
| 207 | +# Normally make does this implicitly, but we force rules to always run | ||
| 208 | +# so we can check their command lines. | ||
| 209 | +# $? -- new prerequisites | ||
| 210 | +# $| -- order-only dependencies | ||
| 211 | +prereq_changed = $(filter-out FORCE_DO_CMD,$(filter-out $|,$?)) | ||
| 212 | + | ||
| 213 | +# Helper that executes all postbuilds until one fails. | ||
| 214 | +define do_postbuilds | ||
| 215 | + @E=0;\ | ||
| 216 | + for p in $(POSTBUILDS); do\ | ||
| 217 | + eval $$p;\ | ||
| 218 | + E=$$?;\ | ||
| 219 | + if [ $$E -ne 0 ]; then\ | ||
| 220 | + break;\ | ||
| 221 | + fi;\ | ||
| 222 | + done;\ | ||
| 223 | + if [ $$E -ne 0 ]; then\ | ||
| 224 | + rm -rf "$@";\ | ||
| 225 | + exit $$E;\ | ||
| 226 | + fi | ||
| 227 | +endef | ||
| 228 | + | ||
| 229 | +# do_cmd: run a command via the above cmd_foo names, if necessary. | ||
| 230 | +# Should always run for a given target to handle command-line changes. | ||
| 231 | +# Second argument, if non-zero, makes it do asm/C/C++ dependency munging. | ||
| 232 | +# Third argument, if non-zero, makes it do POSTBUILDS processing. | ||
| 233 | +# Note: We intentionally do NOT call dirx for depfile, since it contains ? for | ||
| 234 | +# spaces already and dirx strips the ? characters. | ||
| 235 | +define do_cmd | ||
| 236 | +$(if $(or $(command_changed),$(prereq_changed)), | ||
| 237 | + @$(call exact_echo, $($(quiet)cmd_$(1))) | ||
| 238 | + @mkdir -p "$(call dirx,$@)" "$(dir $(depfile))" | ||
| 239 | + $(if $(findstring flock,$(word 2,$(cmd_$1))), | ||
| 240 | + @$(cmd_$(1)) | ||
| 241 | + @echo " $(quiet_cmd_$(1)): Finished", | ||
| 242 | + @$(cmd_$(1)) | ||
| 243 | + ) | ||
| 244 | + @$(call exact_echo,$(call escape_vars,cmd_$(call replace_spaces,$@) := $(cmd_$(1)))) > $(depfile) | ||
| 245 | + @$(if $(2),$(fixup_dep)) | ||
| 246 | + $(if $(and $(3), $(POSTBUILDS)), | ||
| 247 | + $(call do_postbuilds) | ||
| 248 | + ) | ||
| 249 | +) | ||
| 250 | +endef | ||
| 251 | + | ||
| 252 | +# Declare the "all" target first so it is the default, | ||
| 253 | +# even though we don't have the deps yet. | ||
| 254 | +.PHONY: all | ||
| 255 | +all: | ||
| 256 | + | ||
| 257 | +# make looks for ways to re-generate included makefiles, but in our case, we | ||
| 258 | +# don't have a direct way. Explicitly telling make that it has nothing to do | ||
| 259 | +# for them makes it go faster. | ||
| 260 | +%.d: ; | ||
| 261 | + | ||
| 262 | +# Use FORCE_DO_CMD to force a target to run. Should be coupled with | ||
| 263 | +# do_cmd. | ||
| 264 | +.PHONY: FORCE_DO_CMD | ||
| 265 | +FORCE_DO_CMD: | ||
| 266 | + | ||
| 267 | +TOOLSET := target | ||
| 268 | +# Suffix rules, putting all outputs into $(obj). | ||
| 269 | +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.c FORCE_DO_CMD | ||
| 270 | + @$(call do_cmd,cc,1) | ||
| 271 | +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD | ||
| 272 | + @$(call do_cmd,cxx,1) | ||
| 273 | +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cpp FORCE_DO_CMD | ||
| 274 | + @$(call do_cmd,cxx,1) | ||
| 275 | +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.cxx FORCE_DO_CMD | ||
| 276 | + @$(call do_cmd,cxx,1) | ||
| 277 | +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.m FORCE_DO_CMD | ||
| 278 | + @$(call do_cmd,objc,1) | ||
| 279 | +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.mm FORCE_DO_CMD | ||
| 280 | + @$(call do_cmd,objcxx,1) | ||
| 281 | +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.S FORCE_DO_CMD | ||
| 282 | + @$(call do_cmd,cc,1) | ||
| 283 | +$(obj).$(TOOLSET)/%.o: $(srcdir)/%.s FORCE_DO_CMD | ||
| 284 | + @$(call do_cmd,cc,1) | ||
| 285 | + | ||
| 286 | +# Try building from generated source, too. | ||
| 287 | +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.c FORCE_DO_CMD | ||
| 288 | + @$(call do_cmd,cc,1) | ||
| 289 | +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD | ||
| 290 | + @$(call do_cmd,cxx,1) | ||
| 291 | +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cpp FORCE_DO_CMD | ||
| 292 | + @$(call do_cmd,cxx,1) | ||
| 293 | +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.cxx FORCE_DO_CMD | ||
| 294 | + @$(call do_cmd,cxx,1) | ||
| 295 | +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.m FORCE_DO_CMD | ||
| 296 | + @$(call do_cmd,objc,1) | ||
| 297 | +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.mm FORCE_DO_CMD | ||
| 298 | + @$(call do_cmd,objcxx,1) | ||
| 299 | +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.S FORCE_DO_CMD | ||
| 300 | + @$(call do_cmd,cc,1) | ||
| 301 | +$(obj).$(TOOLSET)/%.o: $(obj).$(TOOLSET)/%.s FORCE_DO_CMD | ||
| 302 | + @$(call do_cmd,cc,1) | ||
| 303 | + | ||
| 304 | +$(obj).$(TOOLSET)/%.o: $(obj)/%.c FORCE_DO_CMD | ||
| 305 | + @$(call do_cmd,cc,1) | ||
| 306 | +$(obj).$(TOOLSET)/%.o: $(obj)/%.cc FORCE_DO_CMD | ||
| 307 | + @$(call do_cmd,cxx,1) | ||
| 308 | +$(obj).$(TOOLSET)/%.o: $(obj)/%.cpp FORCE_DO_CMD | ||
| 309 | + @$(call do_cmd,cxx,1) | ||
| 310 | +$(obj).$(TOOLSET)/%.o: $(obj)/%.cxx FORCE_DO_CMD | ||
| 311 | + @$(call do_cmd,cxx,1) | ||
| 312 | +$(obj).$(TOOLSET)/%.o: $(obj)/%.m FORCE_DO_CMD | ||
| 313 | + @$(call do_cmd,objc,1) | ||
| 314 | +$(obj).$(TOOLSET)/%.o: $(obj)/%.mm FORCE_DO_CMD | ||
| 315 | + @$(call do_cmd,objcxx,1) | ||
| 316 | +$(obj).$(TOOLSET)/%.o: $(obj)/%.S FORCE_DO_CMD | ||
| 317 | + @$(call do_cmd,cc,1) | ||
| 318 | +$(obj).$(TOOLSET)/%.o: $(obj)/%.s FORCE_DO_CMD | ||
| 319 | + @$(call do_cmd,cc,1) | ||
| 320 | + | ||
| 321 | + | ||
| 322 | +ifeq ($(strip $(foreach prefix,$(NO_LOAD),\ | ||
| 323 | + $(findstring $(join ^,$(prefix)),\ | ||
| 324 | + $(join ^,test.target.mk)))),) | ||
| 325 | + include test.target.mk | ||
| 326 | +endif | ||
| 327 | + | ||
| 328 | +quiet_cmd_regen_makefile = ACTION Regenerating $@ | ||
| 329 | +cmd_regen_makefile = cd $(srcdir); /usr/local/lib/node_modules/node-gyp/gyp/gyp_main.py -fmake --ignore-environment "--toplevel-dir=." -I/Users/fzy/project/koa2_Sequelize_project/build/config.gypi -I/usr/local/lib/node_modules/node-gyp/addon.gypi -I/Users/fzy/.node-gyp/8.2.1/include/node/common.gypi "--depth=." "-Goutput_dir=." "--generator-output=build" "-Dlibrary=shared_library" "-Dvisibility=default" "-Dnode_root_dir=/Users/fzy/.node-gyp/8.2.1" "-Dnode_gyp_dir=/usr/local/lib/node_modules/node-gyp" "-Dnode_lib_file=/Users/fzy/.node-gyp/8.2.1/<(target_arch)/node.lib" "-Dmodule_root_dir=/Users/fzy/project/koa2_Sequelize_project" "-Dnode_engine=v8" binding.gyp | ||
| 330 | +Makefile: $(srcdir)/../../.node-gyp/8.2.1/include/node/common.gypi $(srcdir)/build/config.gypi $(srcdir)/binding.gyp $(srcdir)/../../../../usr/local/lib/node_modules/node-gyp/addon.gypi | ||
| 331 | + $(call do_cmd,regen_makefile) | ||
| 332 | + | ||
| 333 | +# "all" is a concatenation of the "all" targets from all the included | ||
| 334 | +# sub-makefiles. This is just here to clarify. | ||
| 335 | +all: | ||
| 336 | + | ||
| 337 | +# Add in dependency-tracking rules. $(all_deps) is the list of every single | ||
| 338 | +# target in our tree. Only consider the ones with .d (dependency) info: | ||
| 339 | +d_files := $(wildcard $(foreach f,$(all_deps),$(depsdir)/$(f).d)) | ||
| 340 | +ifneq ($(d_files),) | ||
| 341 | + include $(d_files) | ||
| 342 | +endif |
| 1 | +cmd_Release/obj.target/test/test.o := c++ '-DNODE_GYP_MODULE_NAME=test' '-DUSING_UV_SHARED=1' '-DUSING_V8_SHARED=1' '-DV8_DEPRECATION_WARNINGS=1' '-D_DARWIN_USE_64_BIT_INODE=1' '-D_LARGEFILE_SOURCE' '-D_FILE_OFFSET_BITS=64' '-DBUILDING_NODE_EXTENSION' -I/Users/fzy/.node-gyp/8.2.1/include/node -I/Users/fzy/.node-gyp/8.2.1/src -I/Users/fzy/.node-gyp/8.2.1/deps/uv/include -I/Users/fzy/.node-gyp/8.2.1/deps/v8/include -Os -gdwarf-2 -mmacosx-version-min=10.7 -arch x86_64 -Wall -Wendif-labels -W -Wno-unused-parameter -std=gnu++0x -stdlib=libc++ -fno-rtti -fno-exceptions -fno-threadsafe-statics -fno-strict-aliasing -MMD -MF ./Release/.deps/Release/obj.target/test/test.o.d.raw -c -o Release/obj.target/test/test.o ../test.cc | ||
| 2 | +Release/obj.target/test/test.o: ../test.cc \ | ||
| 3 | + /Users/fzy/.node-gyp/8.2.1/include/node/node.h \ | ||
| 4 | + /Users/fzy/.node-gyp/8.2.1/include/node/v8.h \ | ||
| 5 | + /Users/fzy/.node-gyp/8.2.1/include/node/v8-version.h \ | ||
| 6 | + /Users/fzy/.node-gyp/8.2.1/include/node/v8config.h \ | ||
| 7 | + /Users/fzy/.node-gyp/8.2.1/include/node/node_version.h | ||
| 8 | +../test.cc: | ||
| 9 | +/Users/fzy/.node-gyp/8.2.1/include/node/node.h: | ||
| 10 | +/Users/fzy/.node-gyp/8.2.1/include/node/v8.h: | ||
| 11 | +/Users/fzy/.node-gyp/8.2.1/include/node/v8-version.h: | ||
| 12 | +/Users/fzy/.node-gyp/8.2.1/include/node/v8config.h: | ||
| 13 | +/Users/fzy/.node-gyp/8.2.1/include/node/node_version.h: |
build/Release/.deps/Release/test.node.d
0 → 100644
| 1 | +cmd_Release/test.node := c++ -bundle -undefined dynamic_lookup -Wl,-no_pie -Wl,-search_paths_first -mmacosx-version-min=10.7 -arch x86_64 -L./Release -stdlib=libc++ -o Release/test.node Release/obj.target/test/test.o |
build/Release/obj.target/test/test.o
0 → 100644
不能预览此文件类型
build/Release/test.node
0 → 100755
不能预览此文件类型
build/binding.Makefile
0 → 100644
build/config.gypi
0 → 100644
| 1 | +# Do not edit. File was generated by node-gyp's "configure" step | ||
| 2 | +{ | ||
| 3 | + "target_defaults": { | ||
| 4 | + "cflags": [], | ||
| 5 | + "default_configuration": "Release", | ||
| 6 | + "defines": [], | ||
| 7 | + "include_dirs": [], | ||
| 8 | + "libraries": [] | ||
| 9 | + }, | ||
| 10 | + "variables": { | ||
| 11 | + "asan": 0, | ||
| 12 | + "coverage": "false", | ||
| 13 | + "debug_devtools": "node", | ||
| 14 | + "force_dynamic_crt": 0, | ||
| 15 | + "host_arch": "x64", | ||
| 16 | + "icu_data_file": "icudt59l.dat", | ||
| 17 | + "icu_data_in": "../../deps/icu-small/source/data/in/icudt59l.dat", | ||
| 18 | + "icu_endianness": "l", | ||
| 19 | + "icu_gyp_path": "tools/icu/icu-generic.gyp", | ||
| 20 | + "icu_locales": "en,root", | ||
| 21 | + "icu_path": "deps/icu-small", | ||
| 22 | + "icu_small": "true", | ||
| 23 | + "icu_ver_major": "59", | ||
| 24 | + "llvm_version": 0, | ||
| 25 | + "node_byteorder": "little", | ||
| 26 | + "node_enable_d8": "false", | ||
| 27 | + "node_enable_v8_vtunejit": "false", | ||
| 28 | + "node_install_npm": "true", | ||
| 29 | + "node_module_version": 57, | ||
| 30 | + "node_no_browser_globals": "false", | ||
| 31 | + "node_prefix": "/", | ||
| 32 | + "node_release_urlbase": "https://nodejs.org/download/release/", | ||
| 33 | + "node_shared": "false", | ||
| 34 | + "node_shared_cares": "false", | ||
| 35 | + "node_shared_http_parser": "false", | ||
| 36 | + "node_shared_libuv": "false", | ||
| 37 | + "node_shared_openssl": "false", | ||
| 38 | + "node_shared_zlib": "false", | ||
| 39 | + "node_tag": "", | ||
| 40 | + "node_use_bundled_v8": "true", | ||
| 41 | + "node_use_dtrace": "true", | ||
| 42 | + "node_use_etw": "false", | ||
| 43 | + "node_use_lttng": "false", | ||
| 44 | + "node_use_openssl": "true", | ||
| 45 | + "node_use_perfctr": "false", | ||
| 46 | + "node_use_v8_platform": "true", | ||
| 47 | + "node_without_node_options": "false", | ||
| 48 | + "openssl_fips": "", | ||
| 49 | + "openssl_no_asm": 0, | ||
| 50 | + "shlib_suffix": "57.dylib", | ||
| 51 | + "target_arch": "x64", | ||
| 52 | + "uv_parent_path": "/deps/uv/", | ||
| 53 | + "uv_use_dtrace": "true", | ||
| 54 | + "v8_enable_gdbjit": 0, | ||
| 55 | + "v8_enable_i18n_support": 1, | ||
| 56 | + "v8_enable_inspector": 1, | ||
| 57 | + "v8_no_strict_aliasing": 1, | ||
| 58 | + "v8_optimized_debug": 0, | ||
| 59 | + "v8_promise_internal_field_count": 1, | ||
| 60 | + "v8_random_seed": 0, | ||
| 61 | + "v8_trace_maps": 0, | ||
| 62 | + "v8_use_snapshot": "false", | ||
| 63 | + "want_separate_host_toolset": 0, | ||
| 64 | + "want_separate_host_toolset_mkpeephole": 0, | ||
| 65 | + "xcode_version": "7.0", | ||
| 66 | + "nodedir": "/Users/fzy/.node-gyp/8.2.1", | ||
| 67 | + "standalone_static_library": 1 | ||
| 68 | + } | ||
| 69 | +} |
build/gyp-mac-tool
0 → 100755
| 1 | +#!/usr/bin/env python | ||
| 2 | +# Generated by gyp. Do not edit. | ||
| 3 | +# Copyright (c) 2012 Google Inc. All rights reserved. | ||
| 4 | +# Use of this source code is governed by a BSD-style license that can be | ||
| 5 | +# found in the LICENSE file. | ||
| 6 | + | ||
| 7 | +"""Utility functions to perform Xcode-style build steps. | ||
| 8 | + | ||
| 9 | +These functions are executed via gyp-mac-tool when using the Makefile generator. | ||
| 10 | +""" | ||
| 11 | + | ||
| 12 | +import fcntl | ||
| 13 | +import fnmatch | ||
| 14 | +import glob | ||
| 15 | +import json | ||
| 16 | +import os | ||
| 17 | +import plistlib | ||
| 18 | +import re | ||
| 19 | +import shutil | ||
| 20 | +import string | ||
| 21 | +import subprocess | ||
| 22 | +import sys | ||
| 23 | +import tempfile | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +def main(args): | ||
| 27 | + executor = MacTool() | ||
| 28 | + exit_code = executor.Dispatch(args) | ||
| 29 | + if exit_code is not None: | ||
| 30 | + sys.exit(exit_code) | ||
| 31 | + | ||
| 32 | + | ||
| 33 | +class MacTool(object): | ||
| 34 | + """This class performs all the Mac tooling steps. The methods can either be | ||
| 35 | + executed directly, or dispatched from an argument list.""" | ||
| 36 | + | ||
| 37 | + def Dispatch(self, args): | ||
| 38 | + """Dispatches a string command to a method.""" | ||
| 39 | + if len(args) < 1: | ||
| 40 | + raise Exception("Not enough arguments") | ||
| 41 | + | ||
| 42 | + method = "Exec%s" % self._CommandifyName(args[0]) | ||
| 43 | + return getattr(self, method)(*args[1:]) | ||
| 44 | + | ||
| 45 | + def _CommandifyName(self, name_string): | ||
| 46 | + """Transforms a tool name like copy-info-plist to CopyInfoPlist""" | ||
| 47 | + return name_string.title().replace('-', '') | ||
| 48 | + | ||
| 49 | + def ExecCopyBundleResource(self, source, dest, convert_to_binary): | ||
| 50 | + """Copies a resource file to the bundle/Resources directory, performing any | ||
| 51 | + necessary compilation on each resource.""" | ||
| 52 | + extension = os.path.splitext(source)[1].lower() | ||
| 53 | + if os.path.isdir(source): | ||
| 54 | + # Copy tree. | ||
| 55 | + # TODO(thakis): This copies file attributes like mtime, while the | ||
| 56 | + # single-file branch below doesn't. This should probably be changed to | ||
| 57 | + # be consistent with the single-file branch. | ||
| 58 | + if os.path.exists(dest): | ||
| 59 | + shutil.rmtree(dest) | ||
| 60 | + shutil.copytree(source, dest) | ||
| 61 | + elif extension == '.xib': | ||
| 62 | + return self._CopyXIBFile(source, dest) | ||
| 63 | + elif extension == '.storyboard': | ||
| 64 | + return self._CopyXIBFile(source, dest) | ||
| 65 | + elif extension == '.strings': | ||
| 66 | + self._CopyStringsFile(source, dest, convert_to_binary) | ||
| 67 | + else: | ||
| 68 | + shutil.copy(source, dest) | ||
| 69 | + | ||
| 70 | + def _CopyXIBFile(self, source, dest): | ||
| 71 | + """Compiles a XIB file with ibtool into a binary plist in the bundle.""" | ||
| 72 | + | ||
| 73 | + # ibtool sometimes crashes with relative paths. See crbug.com/314728. | ||
| 74 | + base = os.path.dirname(os.path.realpath(__file__)) | ||
| 75 | + if os.path.relpath(source): | ||
| 76 | + source = os.path.join(base, source) | ||
| 77 | + if os.path.relpath(dest): | ||
| 78 | + dest = os.path.join(base, dest) | ||
| 79 | + | ||
| 80 | + args = ['xcrun', 'ibtool', '--errors', '--warnings', '--notices', | ||
| 81 | + '--output-format', 'human-readable-text', '--compile', dest, source] | ||
| 82 | + ibtool_section_re = re.compile(r'/\*.*\*/') | ||
| 83 | + ibtool_re = re.compile(r'.*note:.*is clipping its content') | ||
| 84 | + ibtoolout = subprocess.Popen(args, stdout=subprocess.PIPE) | ||
| 85 | + current_section_header = None | ||
| 86 | + for line in ibtoolout.stdout: | ||
| 87 | + if ibtool_section_re.match(line): | ||
| 88 | + current_section_header = line | ||
| 89 | + elif not ibtool_re.match(line): | ||
| 90 | + if current_section_header: | ||
| 91 | + sys.stdout.write(current_section_header) | ||
| 92 | + current_section_header = None | ||
| 93 | + sys.stdout.write(line) | ||
| 94 | + return ibtoolout.returncode | ||
| 95 | + | ||
| 96 | + def _ConvertToBinary(self, dest): | ||
| 97 | + subprocess.check_call([ | ||
| 98 | + 'xcrun', 'plutil', '-convert', 'binary1', '-o', dest, dest]) | ||
| 99 | + | ||
| 100 | + def _CopyStringsFile(self, source, dest, convert_to_binary): | ||
| 101 | + """Copies a .strings file using iconv to reconvert the input into UTF-16.""" | ||
| 102 | + input_code = self._DetectInputEncoding(source) or "UTF-8" | ||
| 103 | + | ||
| 104 | + # Xcode's CpyCopyStringsFile / builtin-copyStrings seems to call | ||
| 105 | + # CFPropertyListCreateFromXMLData() behind the scenes; at least it prints | ||
| 106 | + # CFPropertyListCreateFromXMLData(): Old-style plist parser: missing | ||
| 107 | + # semicolon in dictionary. | ||
| 108 | + # on invalid files. Do the same kind of validation. | ||
| 109 | + import CoreFoundation | ||
| 110 | + s = open(source, 'rb').read() | ||
| 111 | + d = CoreFoundation.CFDataCreate(None, s, len(s)) | ||
| 112 | + _, error = CoreFoundation.CFPropertyListCreateFromXMLData(None, d, 0, None) | ||
| 113 | + if error: | ||
| 114 | + return | ||
| 115 | + | ||
| 116 | + fp = open(dest, 'wb') | ||
| 117 | + fp.write(s.decode(input_code).encode('UTF-16')) | ||
| 118 | + fp.close() | ||
| 119 | + | ||
| 120 | + if convert_to_binary == 'True': | ||
| 121 | + self._ConvertToBinary(dest) | ||
| 122 | + | ||
| 123 | + def _DetectInputEncoding(self, file_name): | ||
| 124 | + """Reads the first few bytes from file_name and tries to guess the text | ||
| 125 | + encoding. Returns None as a guess if it can't detect it.""" | ||
| 126 | + fp = open(file_name, 'rb') | ||
| 127 | + try: | ||
| 128 | + header = fp.read(3) | ||
| 129 | + except e: | ||
| 130 | + fp.close() | ||
| 131 | + return None | ||
| 132 | + fp.close() | ||
| 133 | + if header.startswith("\xFE\xFF"): | ||
| 134 | + return "UTF-16" | ||
| 135 | + elif header.startswith("\xFF\xFE"): | ||
| 136 | + return "UTF-16" | ||
| 137 | + elif header.startswith("\xEF\xBB\xBF"): | ||
| 138 | + return "UTF-8" | ||
| 139 | + else: | ||
| 140 | + return None | ||
| 141 | + | ||
| 142 | + def ExecCopyInfoPlist(self, source, dest, convert_to_binary, *keys): | ||
| 143 | + """Copies the |source| Info.plist to the destination directory |dest|.""" | ||
| 144 | + # Read the source Info.plist into memory. | ||
| 145 | + fd = open(source, 'r') | ||
| 146 | + lines = fd.read() | ||
| 147 | + fd.close() | ||
| 148 | + | ||
| 149 | + # Insert synthesized key/value pairs (e.g. BuildMachineOSBuild). | ||
| 150 | + plist = plistlib.readPlistFromString(lines) | ||
| 151 | + if keys: | ||
| 152 | + plist = dict(plist.items() + json.loads(keys[0]).items()) | ||
| 153 | + lines = plistlib.writePlistToString(plist) | ||
| 154 | + | ||
| 155 | + # Go through all the environment variables and replace them as variables in | ||
| 156 | + # the file. | ||
| 157 | + IDENT_RE = re.compile(r'[/\s]') | ||
| 158 | + for key in os.environ: | ||
| 159 | + if key.startswith('_'): | ||
| 160 | + continue | ||
| 161 | + evar = '${%s}' % key | ||
| 162 | + evalue = os.environ[key] | ||
| 163 | + lines = string.replace(lines, evar, evalue) | ||
| 164 | + | ||
| 165 | + # Xcode supports various suffices on environment variables, which are | ||
| 166 | + # all undocumented. :rfc1034identifier is used in the standard project | ||
| 167 | + # template these days, and :identifier was used earlier. They are used to | ||
| 168 | + # convert non-url characters into things that look like valid urls -- | ||
| 169 | + # except that the replacement character for :identifier, '_' isn't valid | ||
| 170 | + # in a URL either -- oops, hence :rfc1034identifier was born. | ||
| 171 | + evar = '${%s:identifier}' % key | ||
| 172 | + evalue = IDENT_RE.sub('_', os.environ[key]) | ||
| 173 | + lines = string.replace(lines, evar, evalue) | ||
| 174 | + | ||
| 175 | + evar = '${%s:rfc1034identifier}' % key | ||
| 176 | + evalue = IDENT_RE.sub('-', os.environ[key]) | ||
| 177 | + lines = string.replace(lines, evar, evalue) | ||
| 178 | + | ||
| 179 | + # Remove any keys with values that haven't been replaced. | ||
| 180 | + lines = lines.split('\n') | ||
| 181 | + for i in range(len(lines)): | ||
| 182 | + if lines[i].strip().startswith("<string>${"): | ||
| 183 | + lines[i] = None | ||
| 184 | + lines[i - 1] = None | ||
| 185 | + lines = '\n'.join(filter(lambda x: x is not None, lines)) | ||
| 186 | + | ||
| 187 | + # Write out the file with variables replaced. | ||
| 188 | + fd = open(dest, 'w') | ||
| 189 | + fd.write(lines) | ||
| 190 | + fd.close() | ||
| 191 | + | ||
| 192 | + # Now write out PkgInfo file now that the Info.plist file has been | ||
| 193 | + # "compiled". | ||
| 194 | + self._WritePkgInfo(dest) | ||
| 195 | + | ||
| 196 | + if convert_to_binary == 'True': | ||
| 197 | + self._ConvertToBinary(dest) | ||
| 198 | + | ||
| 199 | + def _WritePkgInfo(self, info_plist): | ||
| 200 | + """This writes the PkgInfo file from the data stored in Info.plist.""" | ||
| 201 | + plist = plistlib.readPlist(info_plist) | ||
| 202 | + if not plist: | ||
| 203 | + return | ||
| 204 | + | ||
| 205 | + # Only create PkgInfo for executable types. | ||
| 206 | + package_type = plist['CFBundlePackageType'] | ||
| 207 | + if package_type != 'APPL': | ||
| 208 | + return | ||
| 209 | + | ||
| 210 | + # The format of PkgInfo is eight characters, representing the bundle type | ||
| 211 | + # and bundle signature, each four characters. If that is missing, four | ||
| 212 | + # '?' characters are used instead. | ||
| 213 | + signature_code = plist.get('CFBundleSignature', '????') | ||
| 214 | + if len(signature_code) != 4: # Wrong length resets everything, too. | ||
| 215 | + signature_code = '?' * 4 | ||
| 216 | + | ||
| 217 | + dest = os.path.join(os.path.dirname(info_plist), 'PkgInfo') | ||
| 218 | + fp = open(dest, 'w') | ||
| 219 | + fp.write('%s%s' % (package_type, signature_code)) | ||
| 220 | + fp.close() | ||
| 221 | + | ||
| 222 | + def ExecFlock(self, lockfile, *cmd_list): | ||
| 223 | + """Emulates the most basic behavior of Linux's flock(1).""" | ||
| 224 | + # Rely on exception handling to report errors. | ||
| 225 | + fd = os.open(lockfile, os.O_RDONLY|os.O_NOCTTY|os.O_CREAT, 0o666) | ||
| 226 | + fcntl.flock(fd, fcntl.LOCK_EX) | ||
| 227 | + return subprocess.call(cmd_list) | ||
| 228 | + | ||
| 229 | + def ExecFilterLibtool(self, *cmd_list): | ||
| 230 | + """Calls libtool and filters out '/path/to/libtool: file: foo.o has no | ||
| 231 | + symbols'.""" | ||
| 232 | + libtool_re = re.compile(r'^.*libtool: file: .* has no symbols$') | ||
| 233 | + libtool_re5 = re.compile( | ||
| 234 | + r'^.*libtool: warning for library: ' + | ||
| 235 | + r'.* the table of contents is empty ' + | ||
| 236 | + r'\(no object file members in the library define global symbols\)$') | ||
| 237 | + env = os.environ.copy() | ||
| 238 | + # Ref: | ||
| 239 | + # http://www.opensource.apple.com/source/cctools/cctools-809/misc/libtool.c | ||
| 240 | + # The problem with this flag is that it resets the file mtime on the file to | ||
| 241 | + # epoch=0, e.g. 1970-1-1 or 1969-12-31 depending on timezone. | ||
| 242 | + env['ZERO_AR_DATE'] = '1' | ||
| 243 | + libtoolout = subprocess.Popen(cmd_list, stderr=subprocess.PIPE, env=env) | ||
| 244 | + _, err = libtoolout.communicate() | ||
| 245 | + for line in err.splitlines(): | ||
| 246 | + if not libtool_re.match(line) and not libtool_re5.match(line): | ||
| 247 | + print >>sys.stderr, line | ||
| 248 | + # Unconditionally touch the output .a file on the command line if present | ||
| 249 | + # and the command succeeded. A bit hacky. | ||
| 250 | + if not libtoolout.returncode: | ||
| 251 | + for i in range(len(cmd_list) - 1): | ||
| 252 | + if cmd_list[i] == "-o" and cmd_list[i+1].endswith('.a'): | ||
| 253 | + os.utime(cmd_list[i+1], None) | ||
| 254 | + break | ||
| 255 | + return libtoolout.returncode | ||
| 256 | + | ||
| 257 | + def ExecPackageFramework(self, framework, version): | ||
| 258 | + """Takes a path to Something.framework and the Current version of that and | ||
| 259 | + sets up all the symlinks.""" | ||
| 260 | + # Find the name of the binary based on the part before the ".framework". | ||
| 261 | + binary = os.path.basename(framework).split('.')[0] | ||
| 262 | + | ||
| 263 | + CURRENT = 'Current' | ||
| 264 | + RESOURCES = 'Resources' | ||
| 265 | + VERSIONS = 'Versions' | ||
| 266 | + | ||
| 267 | + if not os.path.exists(os.path.join(framework, VERSIONS, version, binary)): | ||
| 268 | + # Binary-less frameworks don't seem to contain symlinks (see e.g. | ||
| 269 | + # chromium's out/Debug/org.chromium.Chromium.manifest/ bundle). | ||
| 270 | + return | ||
| 271 | + | ||
| 272 | + # Move into the framework directory to set the symlinks correctly. | ||
| 273 | + pwd = os.getcwd() | ||
| 274 | + os.chdir(framework) | ||
| 275 | + | ||
| 276 | + # Set up the Current version. | ||
| 277 | + self._Relink(version, os.path.join(VERSIONS, CURRENT)) | ||
| 278 | + | ||
| 279 | + # Set up the root symlinks. | ||
| 280 | + self._Relink(os.path.join(VERSIONS, CURRENT, binary), binary) | ||
| 281 | + self._Relink(os.path.join(VERSIONS, CURRENT, RESOURCES), RESOURCES) | ||
| 282 | + | ||
| 283 | + # Back to where we were before! | ||
| 284 | + os.chdir(pwd) | ||
| 285 | + | ||
| 286 | + def _Relink(self, dest, link): | ||
| 287 | + """Creates a symlink to |dest| named |link|. If |link| already exists, | ||
| 288 | + it is overwritten.""" | ||
| 289 | + if os.path.lexists(link): | ||
| 290 | + os.remove(link) | ||
| 291 | + os.symlink(dest, link) | ||
| 292 | + | ||
| 293 | + def ExecCompileXcassets(self, keys, *inputs): | ||
| 294 | + """Compiles multiple .xcassets files into a single .car file. | ||
| 295 | + | ||
| 296 | + This invokes 'actool' to compile all the inputs .xcassets files. The | ||
| 297 | + |keys| arguments is a json-encoded dictionary of extra arguments to | ||
| 298 | + pass to 'actool' when the asset catalogs contains an application icon | ||
| 299 | + or a launch image. | ||
| 300 | + | ||
| 301 | + Note that 'actool' does not create the Assets.car file if the asset | ||
| 302 | + catalogs does not contains imageset. | ||
| 303 | + """ | ||
| 304 | + command_line = [ | ||
| 305 | + 'xcrun', 'actool', '--output-format', 'human-readable-text', | ||
| 306 | + '--compress-pngs', '--notices', '--warnings', '--errors', | ||
| 307 | + ] | ||
| 308 | + is_iphone_target = 'IPHONEOS_DEPLOYMENT_TARGET' in os.environ | ||
| 309 | + if is_iphone_target: | ||
| 310 | + platform = os.environ['CONFIGURATION'].split('-')[-1] | ||
| 311 | + if platform not in ('iphoneos', 'iphonesimulator'): | ||
| 312 | + platform = 'iphonesimulator' | ||
| 313 | + command_line.extend([ | ||
| 314 | + '--platform', platform, '--target-device', 'iphone', | ||
| 315 | + '--target-device', 'ipad', '--minimum-deployment-target', | ||
| 316 | + os.environ['IPHONEOS_DEPLOYMENT_TARGET'], '--compile', | ||
| 317 | + os.path.abspath(os.environ['CONTENTS_FOLDER_PATH']), | ||
| 318 | + ]) | ||
| 319 | + else: | ||
| 320 | + command_line.extend([ | ||
| 321 | + '--platform', 'macosx', '--target-device', 'mac', | ||
| 322 | + '--minimum-deployment-target', os.environ['MACOSX_DEPLOYMENT_TARGET'], | ||
| 323 | + '--compile', | ||
| 324 | + os.path.abspath(os.environ['UNLOCALIZED_RESOURCES_FOLDER_PATH']), | ||
| 325 | + ]) | ||
| 326 | + if keys: | ||
| 327 | + keys = json.loads(keys) | ||
| 328 | + for key, value in keys.iteritems(): | ||
| 329 | + arg_name = '--' + key | ||
| 330 | + if isinstance(value, bool): | ||
| 331 | + if value: | ||
| 332 | + command_line.append(arg_name) | ||
| 333 | + elif isinstance(value, list): | ||
| 334 | + for v in value: | ||
| 335 | + command_line.append(arg_name) | ||
| 336 | + command_line.append(str(v)) | ||
| 337 | + else: | ||
| 338 | + command_line.append(arg_name) | ||
| 339 | + command_line.append(str(value)) | ||
| 340 | + # Note: actool crashes if inputs path are relative, so use os.path.abspath | ||
| 341 | + # to get absolute path name for inputs. | ||
| 342 | + command_line.extend(map(os.path.abspath, inputs)) | ||
| 343 | + subprocess.check_call(command_line) | ||
| 344 | + | ||
| 345 | + def ExecMergeInfoPlist(self, output, *inputs): | ||
| 346 | + """Merge multiple .plist files into a single .plist file.""" | ||
| 347 | + merged_plist = {} | ||
| 348 | + for path in inputs: | ||
| 349 | + plist = self._LoadPlistMaybeBinary(path) | ||
| 350 | + self._MergePlist(merged_plist, plist) | ||
| 351 | + plistlib.writePlist(merged_plist, output) | ||
| 352 | + | ||
| 353 | + def ExecCodeSignBundle(self, key, resource_rules, entitlements, provisioning): | ||
| 354 | + """Code sign a bundle. | ||
| 355 | + | ||
| 356 | + This function tries to code sign an iOS bundle, following the same | ||
| 357 | + algorithm as Xcode: | ||
| 358 | + 1. copy ResourceRules.plist from the user or the SDK into the bundle, | ||
| 359 | + 2. pick the provisioning profile that best match the bundle identifier, | ||
| 360 | + and copy it into the bundle as embedded.mobileprovision, | ||
| 361 | + 3. copy Entitlements.plist from user or SDK next to the bundle, | ||
| 362 | + 4. code sign the bundle. | ||
| 363 | + """ | ||
| 364 | + resource_rules_path = self._InstallResourceRules(resource_rules) | ||
| 365 | + substitutions, overrides = self._InstallProvisioningProfile( | ||
| 366 | + provisioning, self._GetCFBundleIdentifier()) | ||
| 367 | + entitlements_path = self._InstallEntitlements( | ||
| 368 | + entitlements, substitutions, overrides) | ||
| 369 | + subprocess.check_call([ | ||
| 370 | + 'codesign', '--force', '--sign', key, '--resource-rules', | ||
| 371 | + resource_rules_path, '--entitlements', entitlements_path, | ||
| 372 | + os.path.join( | ||
| 373 | + os.environ['TARGET_BUILD_DIR'], | ||
| 374 | + os.environ['FULL_PRODUCT_NAME'])]) | ||
| 375 | + | ||
| 376 | + def _InstallResourceRules(self, resource_rules): | ||
| 377 | + """Installs ResourceRules.plist from user or SDK into the bundle. | ||
| 378 | + | ||
| 379 | + Args: | ||
| 380 | + resource_rules: string, optional, path to the ResourceRules.plist file | ||
| 381 | + to use, default to "${SDKROOT}/ResourceRules.plist" | ||
| 382 | + | ||
| 383 | + Returns: | ||
| 384 | + Path to the copy of ResourceRules.plist into the bundle. | ||
| 385 | + """ | ||
| 386 | + source_path = resource_rules | ||
| 387 | + target_path = os.path.join( | ||
| 388 | + os.environ['BUILT_PRODUCTS_DIR'], | ||
| 389 | + os.environ['CONTENTS_FOLDER_PATH'], | ||
| 390 | + 'ResourceRules.plist') | ||
| 391 | + if not source_path: | ||
| 392 | + source_path = os.path.join( | ||
| 393 | + os.environ['SDKROOT'], 'ResourceRules.plist') | ||
| 394 | + shutil.copy2(source_path, target_path) | ||
| 395 | + return target_path | ||
| 396 | + | ||
| 397 | + def _InstallProvisioningProfile(self, profile, bundle_identifier): | ||
| 398 | + """Installs embedded.mobileprovision into the bundle. | ||
| 399 | + | ||
| 400 | + Args: | ||
| 401 | + profile: string, optional, short name of the .mobileprovision file | ||
| 402 | + to use, if empty or the file is missing, the best file installed | ||
| 403 | + will be used | ||
| 404 | + bundle_identifier: string, value of CFBundleIdentifier from Info.plist | ||
| 405 | + | ||
| 406 | + Returns: | ||
| 407 | + A tuple containing two dictionary: variables substitutions and values | ||
| 408 | + to overrides when generating the entitlements file. | ||
| 409 | + """ | ||
| 410 | + source_path, provisioning_data, team_id = self._FindProvisioningProfile( | ||
| 411 | + profile, bundle_identifier) | ||
| 412 | + target_path = os.path.join( | ||
| 413 | + os.environ['BUILT_PRODUCTS_DIR'], | ||
| 414 | + os.environ['CONTENTS_FOLDER_PATH'], | ||
| 415 | + 'embedded.mobileprovision') | ||
| 416 | + shutil.copy2(source_path, target_path) | ||
| 417 | + substitutions = self._GetSubstitutions(bundle_identifier, team_id + '.') | ||
| 418 | + return substitutions, provisioning_data['Entitlements'] | ||
| 419 | + | ||
| 420 | + def _FindProvisioningProfile(self, profile, bundle_identifier): | ||
| 421 | + """Finds the .mobileprovision file to use for signing the bundle. | ||
| 422 | + | ||
| 423 | + Checks all the installed provisioning profiles (or if the user specified | ||
| 424 | + the PROVISIONING_PROFILE variable, only consult it) and select the most | ||
| 425 | + specific that correspond to the bundle identifier. | ||
| 426 | + | ||
| 427 | + Args: | ||
| 428 | + profile: string, optional, short name of the .mobileprovision file | ||
| 429 | + to use, if empty or the file is missing, the best file installed | ||
| 430 | + will be used | ||
| 431 | + bundle_identifier: string, value of CFBundleIdentifier from Info.plist | ||
| 432 | + | ||
| 433 | + Returns: | ||
| 434 | + A tuple of the path to the selected provisioning profile, the data of | ||
| 435 | + the embedded plist in the provisioning profile and the team identifier | ||
| 436 | + to use for code signing. | ||
| 437 | + | ||
| 438 | + Raises: | ||
| 439 | + SystemExit: if no .mobileprovision can be used to sign the bundle. | ||
| 440 | + """ | ||
| 441 | + profiles_dir = os.path.join( | ||
| 442 | + os.environ['HOME'], 'Library', 'MobileDevice', 'Provisioning Profiles') | ||
| 443 | + if not os.path.isdir(profiles_dir): | ||
| 444 | + print >>sys.stderr, ( | ||
| 445 | + 'cannot find mobile provisioning for %s' % bundle_identifier) | ||
| 446 | + sys.exit(1) | ||
| 447 | + provisioning_profiles = None | ||
| 448 | + if profile: | ||
| 449 | + profile_path = os.path.join(profiles_dir, profile + '.mobileprovision') | ||
| 450 | + if os.path.exists(profile_path): | ||
| 451 | + provisioning_profiles = [profile_path] | ||
| 452 | + if not provisioning_profiles: | ||
| 453 | + provisioning_profiles = glob.glob( | ||
| 454 | + os.path.join(profiles_dir, '*.mobileprovision')) | ||
| 455 | + valid_provisioning_profiles = {} | ||
| 456 | + for profile_path in provisioning_profiles: | ||
| 457 | + profile_data = self._LoadProvisioningProfile(profile_path) | ||
| 458 | + app_id_pattern = profile_data.get( | ||
| 459 | + 'Entitlements', {}).get('application-identifier', '') | ||
| 460 | + for team_identifier in profile_data.get('TeamIdentifier', []): | ||
| 461 | + app_id = '%s.%s' % (team_identifier, bundle_identifier) | ||
| 462 | + if fnmatch.fnmatch(app_id, app_id_pattern): | ||
| 463 | + valid_provisioning_profiles[app_id_pattern] = ( | ||
| 464 | + profile_path, profile_data, team_identifier) | ||
| 465 | + if not valid_provisioning_profiles: | ||
| 466 | + print >>sys.stderr, ( | ||
| 467 | + 'cannot find mobile provisioning for %s' % bundle_identifier) | ||
| 468 | + sys.exit(1) | ||
| 469 | + # If the user has multiple provisioning profiles installed that can be | ||
| 470 | + # used for ${bundle_identifier}, pick the most specific one (ie. the | ||
| 471 | + # provisioning profile whose pattern is the longest). | ||
| 472 | + selected_key = max(valid_provisioning_profiles, key=lambda v: len(v)) | ||
| 473 | + return valid_provisioning_profiles[selected_key] | ||
| 474 | + | ||
| 475 | + def _LoadProvisioningProfile(self, profile_path): | ||
| 476 | + """Extracts the plist embedded in a provisioning profile. | ||
| 477 | + | ||
| 478 | + Args: | ||
| 479 | + profile_path: string, path to the .mobileprovision file | ||
| 480 | + | ||
| 481 | + Returns: | ||
| 482 | + Content of the plist embedded in the provisioning profile as a dictionary. | ||
| 483 | + """ | ||
| 484 | + with tempfile.NamedTemporaryFile() as temp: | ||
| 485 | + subprocess.check_call([ | ||
| 486 | + 'security', 'cms', '-D', '-i', profile_path, '-o', temp.name]) | ||
| 487 | + return self._LoadPlistMaybeBinary(temp.name) | ||
| 488 | + | ||
| 489 | + def _MergePlist(self, merged_plist, plist): | ||
| 490 | + """Merge |plist| into |merged_plist|.""" | ||
| 491 | + for key, value in plist.iteritems(): | ||
| 492 | + if isinstance(value, dict): | ||
| 493 | + merged_value = merged_plist.get(key, {}) | ||
| 494 | + if isinstance(merged_value, dict): | ||
| 495 | + self._MergePlist(merged_value, value) | ||
| 496 | + merged_plist[key] = merged_value | ||
| 497 | + else: | ||
| 498 | + merged_plist[key] = value | ||
| 499 | + else: | ||
| 500 | + merged_plist[key] = value | ||
| 501 | + | ||
| 502 | + def _LoadPlistMaybeBinary(self, plist_path): | ||
| 503 | + """Loads into a memory a plist possibly encoded in binary format. | ||
| 504 | + | ||
| 505 | + This is a wrapper around plistlib.readPlist that tries to convert the | ||
| 506 | + plist to the XML format if it can't be parsed (assuming that it is in | ||
| 507 | + the binary format). | ||
| 508 | + | ||
| 509 | + Args: | ||
| 510 | + plist_path: string, path to a plist file, in XML or binary format | ||
| 511 | + | ||
| 512 | + Returns: | ||
| 513 | + Content of the plist as a dictionary. | ||
| 514 | + """ | ||
| 515 | + try: | ||
| 516 | + # First, try to read the file using plistlib that only supports XML, | ||
| 517 | + # and if an exception is raised, convert a temporary copy to XML and | ||
| 518 | + # load that copy. | ||
| 519 | + return plistlib.readPlist(plist_path) | ||
| 520 | + except: | ||
| 521 | + pass | ||
| 522 | + with tempfile.NamedTemporaryFile() as temp: | ||
| 523 | + shutil.copy2(plist_path, temp.name) | ||
| 524 | + subprocess.check_call(['plutil', '-convert', 'xml1', temp.name]) | ||
| 525 | + return plistlib.readPlist(temp.name) | ||
| 526 | + | ||
| 527 | + def _GetSubstitutions(self, bundle_identifier, app_identifier_prefix): | ||
| 528 | + """Constructs a dictionary of variable substitutions for Entitlements.plist. | ||
| 529 | + | ||
| 530 | + Args: | ||
| 531 | + bundle_identifier: string, value of CFBundleIdentifier from Info.plist | ||
| 532 | + app_identifier_prefix: string, value for AppIdentifierPrefix | ||
| 533 | + | ||
| 534 | + Returns: | ||
| 535 | + Dictionary of substitutions to apply when generating Entitlements.plist. | ||
| 536 | + """ | ||
| 537 | + return { | ||
| 538 | + 'CFBundleIdentifier': bundle_identifier, | ||
| 539 | + 'AppIdentifierPrefix': app_identifier_prefix, | ||
| 540 | + } | ||
| 541 | + | ||
| 542 | + def _GetCFBundleIdentifier(self): | ||
| 543 | + """Extracts CFBundleIdentifier value from Info.plist in the bundle. | ||
| 544 | + | ||
| 545 | + Returns: | ||
| 546 | + Value of CFBundleIdentifier in the Info.plist located in the bundle. | ||
| 547 | + """ | ||
| 548 | + info_plist_path = os.path.join( | ||
| 549 | + os.environ['TARGET_BUILD_DIR'], | ||
| 550 | + os.environ['INFOPLIST_PATH']) | ||
| 551 | + info_plist_data = self._LoadPlistMaybeBinary(info_plist_path) | ||
| 552 | + return info_plist_data['CFBundleIdentifier'] | ||
| 553 | + | ||
| 554 | + def _InstallEntitlements(self, entitlements, substitutions, overrides): | ||
| 555 | + """Generates and install the ${BundleName}.xcent entitlements file. | ||
| 556 | + | ||
| 557 | + Expands variables "$(variable)" pattern in the source entitlements file, | ||
| 558 | + add extra entitlements defined in the .mobileprovision file and the copy | ||
| 559 | + the generated plist to "${BundlePath}.xcent". | ||
| 560 | + | ||
| 561 | + Args: | ||
| 562 | + entitlements: string, optional, path to the Entitlements.plist template | ||
| 563 | + to use, defaults to "${SDKROOT}/Entitlements.plist" | ||
| 564 | + substitutions: dictionary, variable substitutions | ||
| 565 | + overrides: dictionary, values to add to the entitlements | ||
| 566 | + | ||
| 567 | + Returns: | ||
| 568 | + Path to the generated entitlements file. | ||
| 569 | + """ | ||
| 570 | + source_path = entitlements | ||
| 571 | + target_path = os.path.join( | ||
| 572 | + os.environ['BUILT_PRODUCTS_DIR'], | ||
| 573 | + os.environ['PRODUCT_NAME'] + '.xcent') | ||
| 574 | + if not source_path: | ||
| 575 | + source_path = os.path.join( | ||
| 576 | + os.environ['SDKROOT'], | ||
| 577 | + 'Entitlements.plist') | ||
| 578 | + shutil.copy2(source_path, target_path) | ||
| 579 | + data = self._LoadPlistMaybeBinary(target_path) | ||
| 580 | + data = self._ExpandVariables(data, substitutions) | ||
| 581 | + if overrides: | ||
| 582 | + for key in overrides: | ||
| 583 | + if key not in data: | ||
| 584 | + data[key] = overrides[key] | ||
| 585 | + plistlib.writePlist(data, target_path) | ||
| 586 | + return target_path | ||
| 587 | + | ||
| 588 | + def _ExpandVariables(self, data, substitutions): | ||
| 589 | + """Expands variables "$(variable)" in data. | ||
| 590 | + | ||
| 591 | + Args: | ||
| 592 | + data: object, can be either string, list or dictionary | ||
| 593 | + substitutions: dictionary, variable substitutions to perform | ||
| 594 | + | ||
| 595 | + Returns: | ||
| 596 | + Copy of data where each references to "$(variable)" has been replaced | ||
| 597 | + by the corresponding value found in substitutions, or left intact if | ||
| 598 | + the key was not found. | ||
| 599 | + """ | ||
| 600 | + if isinstance(data, str): | ||
| 601 | + for key, value in substitutions.iteritems(): | ||
| 602 | + data = data.replace('$(%s)' % key, value) | ||
| 603 | + return data | ||
| 604 | + if isinstance(data, list): | ||
| 605 | + return [self._ExpandVariables(v, substitutions) for v in data] | ||
| 606 | + if isinstance(data, dict): | ||
| 607 | + return {k: self._ExpandVariables(data[k], substitutions) for k in data} | ||
| 608 | + return data | ||
| 609 | + | ||
| 610 | +if __name__ == '__main__': | ||
| 611 | + sys.exit(main(sys.argv[1:])) |
build/test.target.mk
0 → 100644
| 1 | +# This file is generated by gyp; do not edit. | ||
| 2 | + | ||
| 3 | +TOOLSET := target | ||
| 4 | +TARGET := test | ||
| 5 | +DEFS_Debug := \ | ||
| 6 | + '-DNODE_GYP_MODULE_NAME=test' \ | ||
| 7 | + '-DUSING_UV_SHARED=1' \ | ||
| 8 | + '-DUSING_V8_SHARED=1' \ | ||
| 9 | + '-DV8_DEPRECATION_WARNINGS=1' \ | ||
| 10 | + '-D_DARWIN_USE_64_BIT_INODE=1' \ | ||
| 11 | + '-D_LARGEFILE_SOURCE' \ | ||
| 12 | + '-D_FILE_OFFSET_BITS=64' \ | ||
| 13 | + '-DBUILDING_NODE_EXTENSION' \ | ||
| 14 | + '-DDEBUG' \ | ||
| 15 | + '-D_DEBUG' \ | ||
| 16 | + '-DV8_ENABLE_CHECKS' | ||
| 17 | + | ||
| 18 | +# Flags passed to all source files. | ||
| 19 | +CFLAGS_Debug := \ | ||
| 20 | + -O0 \ | ||
| 21 | + -gdwarf-2 \ | ||
| 22 | + -mmacosx-version-min=10.7 \ | ||
| 23 | + -arch x86_64 \ | ||
| 24 | + -Wall \ | ||
| 25 | + -Wendif-labels \ | ||
| 26 | + -W \ | ||
| 27 | + -Wno-unused-parameter | ||
| 28 | + | ||
| 29 | +# Flags passed to only C files. | ||
| 30 | +CFLAGS_C_Debug := \ | ||
| 31 | + -fno-strict-aliasing | ||
| 32 | + | ||
| 33 | +# Flags passed to only C++ files. | ||
| 34 | +CFLAGS_CC_Debug := \ | ||
| 35 | + -std=gnu++0x \ | ||
| 36 | + -stdlib=libc++ \ | ||
| 37 | + -fno-rtti \ | ||
| 38 | + -fno-exceptions \ | ||
| 39 | + -fno-threadsafe-statics \ | ||
| 40 | + -fno-strict-aliasing | ||
| 41 | + | ||
| 42 | +# Flags passed to only ObjC files. | ||
| 43 | +CFLAGS_OBJC_Debug := | ||
| 44 | + | ||
| 45 | +# Flags passed to only ObjC++ files. | ||
| 46 | +CFLAGS_OBJCC_Debug := | ||
| 47 | + | ||
| 48 | +INCS_Debug := \ | ||
| 49 | + -I/Users/fzy/.node-gyp/8.2.1/include/node \ | ||
| 50 | + -I/Users/fzy/.node-gyp/8.2.1/src \ | ||
| 51 | + -I/Users/fzy/.node-gyp/8.2.1/deps/uv/include \ | ||
| 52 | + -I/Users/fzy/.node-gyp/8.2.1/deps/v8/include | ||
| 53 | + | ||
| 54 | +DEFS_Release := \ | ||
| 55 | + '-DNODE_GYP_MODULE_NAME=test' \ | ||
| 56 | + '-DUSING_UV_SHARED=1' \ | ||
| 57 | + '-DUSING_V8_SHARED=1' \ | ||
| 58 | + '-DV8_DEPRECATION_WARNINGS=1' \ | ||
| 59 | + '-D_DARWIN_USE_64_BIT_INODE=1' \ | ||
| 60 | + '-D_LARGEFILE_SOURCE' \ | ||
| 61 | + '-D_FILE_OFFSET_BITS=64' \ | ||
| 62 | + '-DBUILDING_NODE_EXTENSION' | ||
| 63 | + | ||
| 64 | +# Flags passed to all source files. | ||
| 65 | +CFLAGS_Release := \ | ||
| 66 | + -Os \ | ||
| 67 | + -gdwarf-2 \ | ||
| 68 | + -mmacosx-version-min=10.7 \ | ||
| 69 | + -arch x86_64 \ | ||
| 70 | + -Wall \ | ||
| 71 | + -Wendif-labels \ | ||
| 72 | + -W \ | ||
| 73 | + -Wno-unused-parameter | ||
| 74 | + | ||
| 75 | +# Flags passed to only C files. | ||
| 76 | +CFLAGS_C_Release := \ | ||
| 77 | + -fno-strict-aliasing | ||
| 78 | + | ||
| 79 | +# Flags passed to only C++ files. | ||
| 80 | +CFLAGS_CC_Release := \ | ||
| 81 | + -std=gnu++0x \ | ||
| 82 | + -stdlib=libc++ \ | ||
| 83 | + -fno-rtti \ | ||
| 84 | + -fno-exceptions \ | ||
| 85 | + -fno-threadsafe-statics \ | ||
| 86 | + -fno-strict-aliasing | ||
| 87 | + | ||
| 88 | +# Flags passed to only ObjC files. | ||
| 89 | +CFLAGS_OBJC_Release := | ||
| 90 | + | ||
| 91 | +# Flags passed to only ObjC++ files. | ||
| 92 | +CFLAGS_OBJCC_Release := | ||
| 93 | + | ||
| 94 | +INCS_Release := \ | ||
| 95 | + -I/Users/fzy/.node-gyp/8.2.1/include/node \ | ||
| 96 | + -I/Users/fzy/.node-gyp/8.2.1/src \ | ||
| 97 | + -I/Users/fzy/.node-gyp/8.2.1/deps/uv/include \ | ||
| 98 | + -I/Users/fzy/.node-gyp/8.2.1/deps/v8/include | ||
| 99 | + | ||
| 100 | +OBJS := \ | ||
| 101 | + $(obj).target/$(TARGET)/test.o | ||
| 102 | + | ||
| 103 | +# Add to the list of files we specially track dependencies for. | ||
| 104 | +all_deps += $(OBJS) | ||
| 105 | + | ||
| 106 | +# CFLAGS et al overrides must be target-local. | ||
| 107 | +# See "Target-specific Variable Values" in the GNU Make manual. | ||
| 108 | +$(OBJS): TOOLSET := $(TOOLSET) | ||
| 109 | +$(OBJS): GYP_CFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) | ||
| 110 | +$(OBJS): GYP_CXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) | ||
| 111 | +$(OBJS): GYP_OBJCFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_C_$(BUILDTYPE)) $(CFLAGS_OBJC_$(BUILDTYPE)) | ||
| 112 | +$(OBJS): GYP_OBJCXXFLAGS := $(DEFS_$(BUILDTYPE)) $(INCS_$(BUILDTYPE)) $(CFLAGS_$(BUILDTYPE)) $(CFLAGS_CC_$(BUILDTYPE)) $(CFLAGS_OBJCC_$(BUILDTYPE)) | ||
| 113 | + | ||
| 114 | +# Suffix rules, putting all outputs into $(obj). | ||
| 115 | + | ||
| 116 | +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(srcdir)/%.cc FORCE_DO_CMD | ||
| 117 | + @$(call do_cmd,cxx,1) | ||
| 118 | + | ||
| 119 | +# Try building from generated source, too. | ||
| 120 | + | ||
| 121 | +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj).$(TOOLSET)/%.cc FORCE_DO_CMD | ||
| 122 | + @$(call do_cmd,cxx,1) | ||
| 123 | + | ||
| 124 | +$(obj).$(TOOLSET)/$(TARGET)/%.o: $(obj)/%.cc FORCE_DO_CMD | ||
| 125 | + @$(call do_cmd,cxx,1) | ||
| 126 | + | ||
| 127 | +# End of this set of suffix rules | ||
| 128 | +### Rules for final target. | ||
| 129 | +LDFLAGS_Debug := \ | ||
| 130 | + -undefined dynamic_lookup \ | ||
| 131 | + -Wl,-no_pie \ | ||
| 132 | + -Wl,-search_paths_first \ | ||
| 133 | + -mmacosx-version-min=10.7 \ | ||
| 134 | + -arch x86_64 \ | ||
| 135 | + -L$(builddir) \ | ||
| 136 | + -stdlib=libc++ | ||
| 137 | + | ||
| 138 | +LIBTOOLFLAGS_Debug := \ | ||
| 139 | + -undefined dynamic_lookup \ | ||
| 140 | + -Wl,-no_pie \ | ||
| 141 | + -Wl,-search_paths_first | ||
| 142 | + | ||
| 143 | +LDFLAGS_Release := \ | ||
| 144 | + -undefined dynamic_lookup \ | ||
| 145 | + -Wl,-no_pie \ | ||
| 146 | + -Wl,-search_paths_first \ | ||
| 147 | + -mmacosx-version-min=10.7 \ | ||
| 148 | + -arch x86_64 \ | ||
| 149 | + -L$(builddir) \ | ||
| 150 | + -stdlib=libc++ | ||
| 151 | + | ||
| 152 | +LIBTOOLFLAGS_Release := \ | ||
| 153 | + -undefined dynamic_lookup \ | ||
| 154 | + -Wl,-no_pie \ | ||
| 155 | + -Wl,-search_paths_first | ||
| 156 | + | ||
| 157 | +LIBS := | ||
| 158 | + | ||
| 159 | +$(builddir)/test.node: GYP_LDFLAGS := $(LDFLAGS_$(BUILDTYPE)) | ||
| 160 | +$(builddir)/test.node: LIBS := $(LIBS) | ||
| 161 | +$(builddir)/test.node: GYP_LIBTOOLFLAGS := $(LIBTOOLFLAGS_$(BUILDTYPE)) | ||
| 162 | +$(builddir)/test.node: TOOLSET := $(TOOLSET) | ||
| 163 | +$(builddir)/test.node: $(OBJS) FORCE_DO_CMD | ||
| 164 | + $(call do_cmd,solink_module) | ||
| 165 | + | ||
| 166 | +all_deps += $(builddir)/test.node | ||
| 167 | +# Add target alias | ||
| 168 | +.PHONY: test | ||
| 169 | +test: $(builddir)/test.node | ||
| 170 | + | ||
| 171 | +# Short alias for building this executable. | ||
| 172 | +.PHONY: test.node | ||
| 173 | +test.node: $(builddir)/test.node | ||
| 174 | + | ||
| 175 | +# Add executable to "all" target. | ||
| 176 | +.PHONY: all | ||
| 177 | +all: $(builddir)/test.node | ||
| 178 | + |
demo/a.out
0 → 100755
不能预览此文件类型
demo/demo.cpp
0 → 100644
test.cc
0 → 100644
| 1 | +#include <node.h> | ||
| 2 | +#include <v8.h> | ||
| 3 | + | ||
| 4 | +using namespace v8; | ||
| 5 | + | ||
| 6 | +// 传入了两个参数,args[0] 字符串,args[1] 回调函数 | ||
| 7 | +void hello(const FunctionCallbackInfo<Value>& args) { | ||
| 8 | + // 使用 HandleScope 来管理生命周期 | ||
| 9 | + Isolate* isolate = Isolate::GetCurrent(); | ||
| 10 | + HandleScope scope(isolate); | ||
| 11 | + | ||
| 12 | + // 判断参数格式和格式 | ||
| 13 | + if (args.Length() < 2 || !args[0]->IsString()) { | ||
| 14 | + isolate->ThrowException(Exception::TypeError( | ||
| 15 | + String::NewFromUtf8(isolate, "Wrong arguments"))); | ||
| 16 | + return; | ||
| 17 | + } | ||
| 18 | + | ||
| 19 | + // callback, 使用Cast方法来转换 | ||
| 20 | + Local<Function> callback = Local<Function>::Cast(args[1]); | ||
| 21 | + Local<Value> argv[1] = { | ||
| 22 | + // 拼接String | ||
| 23 | + String::Concat(Local<String>::Cast(args[0]), String::NewFromUtf8(isolate, " world")) | ||
| 24 | + }; | ||
| 25 | + // 调用回调, 参数: 当前上下文,参数个数,参数列表 | ||
| 26 | + callback->Call(isolate->GetCurrentContext()->Global(), 1, argv); | ||
| 27 | +} | ||
| 28 | + | ||
| 29 | +// 相当于在 exports 对象中添加 { hello: hello } | ||
| 30 | +void init(Handle<Object> exports) { | ||
| 31 | + NODE_SET_METHOD(exports, "hello", hello); | ||
| 32 | +} | ||
| 33 | + | ||
| 34 | +// 将 export 对象暴露出去 | ||
| 35 | +// 原型 `NODE_MODULE(module_name, Initialize)` | ||
| 36 | +NODE_MODULE(test, init); | ||
| 37 | + |
test2c++.js
0 → 100644
-
请 注册 或 登录 后发表评论