从 node-gyp 调用 make

Invoking make from node-gyp

我正在使用 node-gyp 在 Linux 上构建一个用 C++ 编写的本机 Node.js 附加组件。

加载项依赖于另一个共享库。这个库目前不是用 gyp 构建的,它只有一个 makefile。

如果我先构建共享库,然后构建我的附加组件,在我的 binding.gyp 文件的主要目标中为 'libraries' 指定一个值,一切正常。

但是,我喜欢做的是通过在共享库的 makefile 上调用 make,从 node-gyp 进程中的源代码构建共享库。我尝试使用 'action' 属性 添加依赖目标到附加组件的 binding.gyp 并使主要目标依赖于它:

    {
        "target_name": "other_library",
        "type": "none",
        "actions": [
            {
                "action_name": "build_other_library",
                "inputs": [],
                "outputs": [ "/path/to/build/output/libother.so" ],
                "action": [ "make", "-C", "/path/to/makefile" ]
            }
        ]
    }

这并不完全有效。它 找到另一个 makefile 并且 make 正在启动(我可以通过设置 --verbose 看到这种情况),但是 makefile 没有正确执行。

当共享库的 makefile 运行时,GNU make 的隐式构建规则似乎被抑制了。这意味着 .cc 和 .cpp 文件不会被编译为 .o 文件。

我意识到 node-gyp 本身正在从 binding.gyp 中的目标为附加组件生成一组 makefile,并且共享库的 makefile 是从其中一个生成的。

是否继承了node-gyp的make设置,包括内置规则的抑制?

有解决办法吗? (除了向共享库的 makefile 添加显式构建规则之外)?

(我尝试用 $(MAKE) 替换 make,但没有任何区别)。

编辑:

运行 GNU make 在共享库上使用 shell 指定的 -d(即在 node-gyp 之外),搜索典型源文件的隐式规则如下所示:

   Considering target file `code.o'.
     File `code.o' does not exist.
     Looking for an implicit rule for `code.o'.
     Trying pattern rule with stem `code'.
     Trying implicit prerequisite `code.c'.
     Trying pattern rule with stem `code'.
     Trying implicit prerequisite `code.cc'.
     Trying pattern rule with stem `code'.
     Trying implicit prerequisite `code.C'.
     Trying pattern rule with stem `code'.
     Trying implicit prerequisite `code.cpp'.
     Found prerequisite `code.cpp' as VPATH `../Common/code.cpp'
     Found an implicit rule for `code.o'.

将 -d 添加到 node-gyp 相关目标的操作块中的调用,相同的源文件得到这个:

Considering target file `code.o'.
 File `code.o' does not exist.
 Looking for an implicit rule for `code.o'.
 No implicit rule found for `code.o'.

所以看起来隐式构建规则确实被抑制了 (?)

node-gyp 在其顶层 makefile 中设置 MAKEFLAGS=-r-r 是短的 --no-builtin-rules 的形式,默认情况下,它会传递给任何 子品牌。

但是,您将能够为您的子品牌重新启用内置规则 通过将 MAKEFLAGS 设置回调用环境中的默认状态。

在不更改绑定操作的情况下,您可以通过抢先导出来实现 在您的 makefile 中纠正 MAKEFLAGS,然后重新调用 $(MAKE)

为了说明,假设这是您的原始 makefile:

all: foo

foo: foo.o
    $(CC) -o $@ $<

其中您正在从一个源文件 foo.c 制作一个程序 foo(假设 存在于工作目录中)并依靠 %o: %c 的内置规则进行编译 foo.o 来自 foo.c。因此使用此 makefile 构建将失败:

*** No rule to make target 'foo.o', needed by 'foo'. Stop.

像这样更改 makefile:

ifneq ($(MAKEFLAGS),w)
all:
    export MAKEFLAGS=-w && $(MAKE)
else
all: foo

foo: foo.o
    $(CC) -o $@ $<

endif

现在,如果 -rMAKEFLAGS 和 运行 中,而 MAKEFLAGS=-w 则 make 将递归:

$ node-gyp build
gyp info it worked if it ends with ok
gyp info using node-gyp@3.0.3
gyp info using node@4.2.6 | linux | x64
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
make: Entering directory '/home/imk/develop/scrap/build'
  ACTION binding_gyp_prog_target_build_foo foo
make[1]: Entering directory '/home/imk/develop/scrap'
export MAKEFLAGS=-w && make
make[2]: Entering directory '/home/imk/develop/scrap'
cc    -c -o foo.o foo.c
cc -o foo foo.o
make[2]: Leaving directory '/home/imk/develop/scrap'
make[1]: Leaving directory '/home/imk/develop/scrap'
  TOUCH Release/obj.target/prog.stamp
make: Leaving directory '/home/imk/develop/scrap/build'
gyp info ok 

-w--print-directory的缩写)就是那个 在添加 node-gyp 之前有效的默认选项 -r.

注意测试ifneq ($(MAKEFLAGS),w)是正确的。它不应该是 ifneq ($(MAKEFLAGS),-w)。 如果 环境变量 MAKEFLAGS 包含 make 命令行选项 那么 GNU Make 特殊变量 MAKEFLAGS 将只包含 选项字符 .