Node基于 GYP(Generate Your Projects)构建C\C++插件,在编译插件前需要编写一个.gyp配置文件,该文件相当于Node的 package.json
文件。
介绍
GYP(Generate Your Projects)是一个跨平台自动化项目构建工具,其由 Google 团队开发用于生成Chromium Web浏览器的原生IDE的项目文件。
node-gyp 是一个用 Node.js 编写的跨平台命令行工具,用于为 Node.js 编译本机插件模块。它包含 Chromium 团队以前使用的 gyp-next 项目的供应商副本,扩展以支持 Node.js 原生插件的开发。
流程
在通过node-gyp执行构建项目资源时,可以分解成两部分:
- 命令执行
- 执行配置文件
命令执行即通过node-gyp命令行工具,执行对于项目的配置文件,包含最基础的输出文件名称,配置各个平台的源文件,配置平台特有的编译器等信息。
node-gyp commands
通过node-gyp命令行工具,我们可以通过此构建node addon插件,和资源的清理、配置等操作,常用的命令有如下:
Command | Description |
---|---|
help | 显示帮助对话框 |
build | Invokes make/msbuild.exe and builds the native addon 调用 make/msbuild.exe 并构建本机插件 |
clean | Removes the build directory if it exists 删除构建目录(如果存在) |
configure | Generates project build files for the current platform 为当前平台生成项目构建文件 |
rebuild | Runs clean, configure and build all in a row 连续运行干净、配置和构建 |
install | Installs Node.js header files for the given version 安装给定版本的 Node.js 头文件 |
list | Lists the currently installed Node.js header versions 列出当前安装的 Node.js 标头版本 |
remove | Removes the Node.js header files for the given version 删除给定版本的 Node.js 头文件 |
node-gyp options
上文通过命令,我们可以执行不同的操作,但在操作时,可以通过指定不同的options来完成不同的运行时配置,例如指定Node版本、指定python版本等,所有可用的node-gyp配置参数如下:
Command | Description |
---|---|
-j n, —jobs n | Run make in parallel. The value max will use all available CPU cores |
—target=v6.2.1 | Node.js version to build for (default is process.version) |
—silly, —loglevel=silly | Log all progress to console |
—verbose, —loglevel=verbose | Log most progress to console |
—silent, —loglevel=silent | Don’t log anything to console |
debug, —debug | Make Debug build (default is Release) |
—release, —no-debug | Make Release build |
-C $dir, —directory=$dir | Run command in different directory |
—make=$make | Override make command (e.g. gmake) |
—thin=yes | Enable thin static libraries |
—arch=$arch | Set target architecture (e.g. ia32) |
—tarball=$path | Get headers from a local tarball |
—devdir=$path | SDK download directory (default is OS cache directory) |
—ensure | Don’t reinstall headers if already present |
—dist-url=$url | Download header tarball from custom URL |
—proxy=$url | Set HTTP(S) proxy for downloading header tarball |
—noproxy=$urls | Set urls to ignore proxies when downloading header tarball |
—cafile=$cafile | Override default CA chain (to download tarball) |
—nodedir=$path | Set the path to the node source code |
—python=$path | Set path to the Python binary |
—msvs_version=$version | Set Visual Studio version (Windows only) |
—solution=$solution | Set Visual Studio Solution version (Windows only) |
—force-process-config | Force using runtime’s process.config object to generate config.gypi file |
node-gyp配置文件
如下展示基础的node-gyp配置文件内容:
{
'variables': {},
'includes': [
'../build/common.gypi',
],
'target_defaults': {},
'targets': [
{
'target_name': 'target_1',
},
{
'target_name': 'target_2',
},
],
'conditions': [
['OS=="linux"', {
'targets': [
{
'target_name': 'linux_target_3',
},
],
}],
['OS=="win"', {
'targets': [
{
'target_name': 'windows_target_4',
},
],
}
],
],
}
整个文件就是一个Python字典,实际也是一个JSON文件,只有两点小区别:
- 使用#号做注释
- 在列表或字典最后一个元素之后使用,是合法的
gyp顶级属性介绍
variables
定义变量,可以在文件的其他部分内插和使用。includes
将包含在本文件中的其他文件列表。 按照惯例,包含文件的后缀名为.gypi(gyp include)。target_defaults
设置,将应用于本.gyp文件中定义的所有目标。targets
这个.gyp文件可以生成的目标列表。 其中每个目标都是一个字典,包含了描述构建目标所需的所有设置信息。conditions
条件规范列表,可以根据不同变量的值修改由该.gyp文件定义的全局字 典中项目内容。如上例中,顶级字典中conditions部分的最常见用法是将平台相关的特定的目标添加到targets列表。gyp targets 属性介绍
在 targets 中包含以下顶级设置:target_name
目标名,在所有的.gyp文件中应该是唯一的。此名称将用于所成生的不同IDE的项目名,如:Visual Studio解决方案中的项目名称、Xcode配置中的目标名称、SCons配置的命令行构建此目标的别名。type
设置为executablemsvs_guid
这只是过渡用法。用于将在生成的Visual Studio解决方案文件中使用的硬编码的GUID值,这使我们能够检查与gyp生成的项目文件互操作的chrome.sln文件。一旦Chromium中的所有内容都由gyp生成,GUID在调用中保持不变就不再重要了,我们就可以不在考虑这些设置,dependenciesdefines
这个目标所依赖的其他目标列表。gyp生成的文件将保证其他目标在这个目标之前建立。任何dependencies列表中的库目标都将与此目标链接。此列表中的目标的direct_dependent_settings部分中列出的各种设置(define、include_dirs等)将应用于此目标的构建和链接方式。详见下面direct_dependent_settings介绍。defines
将在编译命令行中传递的C预处理器定义(使用-D或/D选项)。include_dirs
包含头文件的目录。将传递给编译命令行(使用-I或/I选项)。sources
这个目标的源文件列表。
所添加的文件路径,是相对于.gyp文件的路径。除非真的需要,否则就应该字线顺序排序。conditions
将根据匹配条件更新目标字典中的不同设置。常用用例
将会介绍一些常用的GYP用例用法,这些用法是代码片段,不包含完整的配置文件,在实际使用中可能需要配合其他的配置,需要注意一下。添加新的源文件
这里面分两种情况,添加平台源文件和添加某个平台支持的源文件,添加方法相似但略有不同。添加某个平台的源文件
在添加某个平台特有的源文件时,只需要在target中的source添加文件地址即可:
所添加的文件路径,是相对于.gyp文件的路径。除非真的需要,否则就应该字线顺序排序。{
'targets': [
{
'target_name': 'target',
'sources': [
'file.cpp',
'file2.cpp',
],
},
],
},
添加一个平台相关的源文件
平台相关的问题被命名为:*_linux.{ext}
、*_mac.{ext}
、*_posix.{ext}
或*_win.{ext}
也就是说,你可以简单的使用以下标准后缀之一来添加特定于平台的源文件:
- _linux (如 foo_linux.cc)
- _mac (如 foo_mac.cc)
- _posix (如 foo_posix.cc)
- _win (如 foo_win.cc)
如,你可以像下面这样将文件添加到指定targets的sources列表中,即可添加平台相关的源文件:
{
'targets': [
{
'target_name': 'foo',
'type': 'executable',
'sources': [
'independent.cc',
'specific_win.cc',
],
},
],
},
Chromium .gyp
文件会进行过滤,将不适合当前平台的文件过滤掉。在上面的示例中,specific_win.cc文件将会从非Windows版本的源列表中自动删除。
添加平台特有的源文件
如果平台相关的文件名不包含 *_{linux,mac,posix,win}
字符串,但也不能修改文件名,可以通过以下两种模式来进行平台匹配:
方式一:
可以将文件添加到指定targets的sources列表中,并添加一个conditions节点来排除指定的文件名:
{
'targets': [
{
'target_name': 'foo',
'type': 'executable',
'sources': [
'linux_specific.cc',
],
'conditions': [
['OS == "linux"', {
'sources': [
# 仅仅支持linux系统配置
'linux_specific.cc',
]
}[,
],
},
],
},
方法二:
在conditions中的sources中添加平台相关的文件:
{
'targets': [
{
'target_name': 'foo',
'type': 'executable',
'sources': [],
['OS == "linux"', {
'sources': [
'linux_specific.cc',
]
}],
},
],
},
添加一个新的可执行目标
在构建addon插件时,可能会存在需要创建多个可执行目标,通常是每个可执行目标类型需要新的一组源文件列表,一些编译器/连接器。
适用于所有平台的可执行目标
讲定义新的可执行目标的字典添加到 .gyp
文件的targets 中,如:
{
'targets': [
{
'target_name': 'new_unit_tests',
'type': 'executable',
'defines': [
'FOO',
],
'include_dirs': [
'..',
],
'dependencies': [
'other_target_in_this_file',
'other_gyp2:target_in_other_gyp2',
],
'sources': [
'new_additional_source.cc',
'new_unit_tests.cc',
],
},
],
}
适用于特定平台的可执行目标
添加适用于特定平台的可执行目标时,所定义的新的可执行目标不是添加到targets列表中,而是与其同级的conditions 节点中:
{
'targets': [
],
'conditions': [
['OS=="win"', {
'targets': [
{
'target_name': 'new_unit_tests',
'type': 'executable',
'defines': [
'FOO',
],
'include_dirs': [
'..',
],
'dependencies': [
'other_target_in_this_file',
'other_gyp2:target_in_other_gyp2',
],
'sources': [
'new_additional_source.cc',
'new_unit_tests.cc',
],
},
],
}],
],
}
向目标中添加设置
添加新的预处理器定义(-D或/D标识)
新的预处理器定义可以通过defines设置:
{
'targets': [
{
'target_name': 'existing_target',
'defines': [
'BAR=some_value',
],
},
],
},
预处理器定义可以直接在targets设置中指定,也可以添加到conditions节点中;
添加新的包含目录(-I或/I标识)
添加新的目录可以通过 include_dirs
设置:
{
'targets': [
{
'target_name': 'existing_target',
'include_dirs': [
'..',
'include',
],
},
],
},
上例中可以通过 targets 设置指定目录,也可以包含在 conditions 语句中。
添加新的 compiler flags
添加指定的 compiler flags 时,可以通过 cflags 来设置:
{
'targets': [
{
'target_name': 'existing_target',
'conditions': [
['OS=="win"', {
'cflags': [
'/WX',
],
}, { # OS != "win"
'cflags': [
'-Werror',
],
}],
],
},
],
},
因为这些标识是因平台而定的,所以只能在conditions中设置。
gyp语法说明
参考:https://itbilu.com/nodejs/npm/By7L5p3ff.html
引用
User Documentation:https://gyp.gsrc.io/docs/UserDocumentation.md
译文:https://itbilu.com/nodejs/npm/Hklq5OweM.html
Input Format Reference:https://gyp.gsrc.io/docs/InputFormatReference.md