node.js - 从 node-gyp 调用 make

标签 node.js gnu-make node-gyp gyp

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

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

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

但是,我喜欢做的是通过在共享库的 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,但没有任何区别)。

编辑:

在 shell 中指定 -d 的共享库上运行 GNU make(即在 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 依赖目标中操作 block 内的调用,相同的源文件得到这个:

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 设置回调用环境中的默认状态。

在不更改绑定(bind)操作的情况下,您可以通过抢先导出来实现此目的 在您的 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 中,make 将递归并使用 MAKEFLAGS=-w 运行:

$ 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 将只包含选项字符

关于node.js - 从 node-gyp 调用 make,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37926444/

相关文章:

r - 在 RStudio 中使用 Makefile

makefile - 如何在 makefile 中写入 'cd' 命令?

javascript - node-gyp 是否带有 npm?

electron - 如何打包具有 OCR 功能的 Electron 应用程序?

jquery - 检测是否使用 Node.js 进行 ajax 调用(刷新页面而不重新加载)

node.js - 在express js中转发查询

node.js - 在Node.js中使用MongoDB中的电子邮件模板

makefile - 如何防止 Webpack 从 Makefile 配方中多次运行

node.js - Npm install karma 在 node-gyp 重建时挂起

javascript - Node.js:从 Mongoose 查询返回正确的 JSON