- Node.js:来一打 C++ 扩展
- 死月
- 6746字
- 2020-08-27 17:13:37
1.4 C++扩展开发的准备工作
前面讲了一些概念性的内容,本节将介绍入手一个Node.js的C++扩展时要做的一些准备工作。
1.4.1 编辑器/IDE
“工欲善其事,必先利其器”,有一个称心的编辑器或者IDE是非常重要的事情。这里推荐几款比较强大的工具。
1.VIM/NeoVIM
VIM是从vi发展出来的一个文本编辑器,在配置完备、插件附体的情况下其功能可以媲美于一款IDE,在程序员中被广泛使用。其和Emacs并列成为类UNIX系统用户最喜欢的编辑器。VIM的第一个版本由Bram Moolenaar在1991年发布,最初是Vi IMitation的简称。不过随着后来其功能不断增加,正式的名称改成了Vi IMproved。
NeoVIM是对VIM的一个重构版本,也可以说是VIM的一个超集,它兼容VIM的配置,但是也有自己的一些配置策略。
该项目自2014年发起,就目前来说已经可以非常方便地使用了。
不过对于暂时还没有VIM基础的读者来说,一开始入门的学习曲线会比较陡峭,但是一旦学成之后就可以“肆无忌惮”了。其玩笑化的学习曲线如图1-12所示。
图1-12 网络上关于VIM学习曲线的玩笑
若想学习VIM,除了搜索网上的教程以外,还可以去阅读O’Reilly系列图书《学习vi和Vim编辑器》的原版或者中文版。
想要尝试NeoVIM的读者可以参考NeoVIM官网Wiki上的安装一节:https://github.com/neovim/neovim/wiki/Installing-Neovim。
在安装完VIM或者NeoVIM之后,你可能需要一款强大的VIM下的代码补全插件来助你在C++世界中厮杀,这个插件就是YouCompleteMe(https://github.com/Valloric/YouCompleteMe)。另外,你还需要一款语法检查插件——syntastic(https://github.com/vim-syntastic/syntastic)。
2.Emacs
Emacs(源自Editor MACroS,宏编辑器),是一个文本编辑器家族,具有强大的可扩展性,在程序员和其他以技术工作为主的计算机用户中广受欢迎。其最初由Richard Stallman于1975年在MIT协同Guy Lewis Steele Jr.共同完成。
网上广为流传的一句话“Emacs其实是一个操作系统”足以证明其很强大。人们用Emacs不仅可以写代码,还能管理文件系统、收发邮件、上网听音乐等。
想用Emacs开发的读者可以上它的官网(https://www.gnu.org/software/emacs/)了解更多的信息。
3.Sublime Text
Sublime Text是一款具有代码高亮、语法提升、自动补全等功能的编辑器,其界面美观,同样有着插件扩展机制,这套机制可以基于Python进行开发。经过一系列发展之后,Sublime Text已经由2升级至3。
Sublime具有下面的一些特性:
· 快速跳转(文件、符号或者行数);
· 指令框(快速输入指令);
· 多行选择;
· 基于Python的插件机制;
· 项目单独配置;
· JSON格式的配置文件;
· 跨平台。
在集成了一堆插件之后,其同样是一款功能强大的编辑器。图1-13为笔者从网络上摘录的一张Sublime Text截图。
图1-13 Sublime Text截图
想用Sublime Text开发的读者可以上它的官网(https://www.sublimetext.com/)了解更多信息。
4.Visual Studio Code
Visual Studio Code是一款比较新潮的编辑器,由Microsoft公司出品。其跨平台且开源,对Node.js(调试)、TypeScript、Go等语言的支持较好,并且性能非常高。
中国Node.js领域的布道者之一i5ting曾撰写了一份关于Visual Studio Code的指南(Visual Studio Code Guide,http://i5ting.github.io/vsc/),里面详细介绍了Visual Studio Code的各种用法。图1-14为笔者从网络上摘录的一张Visual Studio Code截图。
图1-14 Visual Studio Code截图
想用Visual Studio Code开发的读者可以上它的官网(https://code.visualstudio.com/)了解更多信息。
5.Atom
Atom是GitHub在2014年发布的一款基于Web技术构建的文本编辑器,其底层基于GitHub自己开源的Electron开发。
Atom有什么亮点呢?我总结了这样几点:
· 像Sublime Text一样开箱即用;
· 像Emacs一样允许开发者充分地定制;
· 基于JavaScript和Web技术构建;
· 开源且拥有一个活跃的社区。
——摘自jysperm博客的《Atom背后的故事》
详见https://jysperm.me/2016/11/behind-atom/
上面这段节选总结起来就是Atom易用、高可扩展。
想用Atom开发的读者可以上它的官网(https://atom.io/)了解更多信息。
6.Visual Studio
Visual Studio是由Microsoft公司开发的一款Windows系统下强大的IDE。它包含了整个软件生命周期中所需要的大部分工具,如UML、代码管控等。而且其对于C++的支持异常强大,可以说是世界上最好的IDE之一。
虽然Visual Studio已经非常老牌了,但是它一直与时俱进,其最新的版本照样有对于Node.js的支持。并且其还有一个令人兴奋的点是,Microsoft已经着手Visual Studio对于macOS系统的支持,目前已经有针对macOS的版本发布。
在Windows下用Visual Studio还有一个理由,就是如果用node-gyp形式管理Node.js C++模块的话,在Windows系统下Visual Studio是必要的依赖。在编译时的中间步骤中,node-gyp生成的中间目录中就有Visual Studio专用的项目文件(*.sln)。这个中间文件可以直接使用Visual Studio打开进行项目编写和调试。
如果读者觉得麻烦,也可以用其他的编辑器进行编码,只是Windows用户在编译C++模块的时候Visual Studio是必须要安装的,或者至少要安装其编译工具。图1-15为笔者从网络上摘录的一张Visual Studio截图。
图1-15 Visual Studio截图
想用Visual Studio开发的读者可以上它的官网(https://www.visualstudio.com/zh-hans/)了解更多信息。
1.4.2 node-gyp
node-gyp是Node.js下的C++扩展构建工具。几乎所有的Node.js C++扩展都是由它构建的。
它基于GYP来进行工作。GYP的全称为Generate Your Projects,它是谷歌出品的一套构建工具,通过一个*.gyp的描述文件生成不同系统所需要的项目文件(如Makefile或者Visual Studio项目文件)以供构建和编译。
使用node-gyp的C++扩展中主要由一个binding.gyp文件进行配置。
较新的Node.js版本中会自带node-gyp。当然,如果没有自带或者需要升级,我们也能自行安装。
1.依赖
在安装node-gyp之前,我们还需要安装一些它所需要的依赖,才能供其正常工作。其中每个平台都需要的依赖就是Python 2.7。
注意:一定是Python 2.7,因为node-gyp在Python 3.x下并不能很好地工作。
(1)如果读者用的是UNIX
在UNIX系列平台下工作的读者大概需要这三样东西:
· Python 2.7(通常系统自带);
· make;
· C++编译工具包(如GCC)。
以Ubuntu 14.04为例,从完全没有上述依赖的情况开始,大概需要通过下面的几条命令来安装。
· Git
在本书的讲解中,Git是比较重要的一个工具,所以推荐读者事先安装好Git。
· Python
在接下来的输入提示中看情况去区分Y或者N即可。通常情况下全部选Y选项。
不过通常对于像Ubuntu这类Linux发行版来说,Python 2.7是自带的,不需要再安装。
· make和gcc
在Ubuntu的最精简版本安装时,make和gcc是不随系统安装的。如果你的环境中已经存在着make和gcc,则可以略过本步骤。
我们可以一步安装这些与构建相关的程序集:
如果是其他的发行版,则可以单独安装这些程序。
(2)如果读者用的是macOS
在macOS下搭建node-gyp的环境依赖大体与UNIX下相同,只不过它的构建工具源于Xcode。
· Xcode
Xcode里面包含了各种构建所需要的工具,如GCC等。
首先需要从App Store下载安装Xcode。事先已经安装了Xcode的读者可以略过这一步。图1-16为Xcode在App Store中的安装界面。
图1-16 Xcode的安装界面
在安装好Xcode后,需要通过它的入口来安装命令行工具(Command Line Tools)。事先已经通过Xcode安装命令行工具的读者可以略过这一步。
打开Xcode,然后依次点击菜单栏的Xcode→Preferences→Downloads进行下载。
(3)如果读者用的是Windows
在Windows系统下,微软的Windows Build Tools是必备的前驱依赖。这些依赖可以通过安装Visual Studio 2015(或其他可用版本)、Visual C++Build Tools或者是NPM中的windows-build-tools来获得。
· Visual Studio
有些读者可能在先前的学习或者工作经验中就已经接触过Visual Studio,所以其计算机中已有这样的IDE,这样就可以略过本节以及与Windows Build Tools相关的章节。
如果你并没有Windows Builds Tools中的任意一项,并且想以安装Visual Studio的方式获取的话,就可以阅读一下本节。
首先前往https://www.visualstudio.com/zh-hans/或者通过搜索引擎下载到Visual Studio 2015(或其他可用版本),然后执行安装步骤。图1-17和图1-18分别为Visual Studio安装时不同步骤的界面。
图1-17 Visual Studio安装步骤1
图1-18 Visual Studio安装步骤2
然后在下一步的安装界面中选择与Visual C++相关的选项。
安装完毕重启即可。最后要在NPM中设置一下Visual Studio的版本号。执行下面的命令:
注意:如果你使用Visual Studio 2015进行安装,则上述命令后面的版本号不需要改;如果是其他node-gyp支持的版本,则只需要把后面的版本改成相应的版本即可。
· Visual C++Build Tools
如果开发者在开发过程中并不需要使用Visual Studio这么庞大的IDE,也可以使用稍微轻量一点的只包含Visual C++的构建工具包来完成依赖。
要安装Visual C++Build Tools,可以前往其相关的官网:http://landinghub.visualstudio.com/visual-cpp-build-tools。
图1-19为Visual C++Build Tools官网的截图,图1-20为其安装界面截图。
图1-19 Visual C++Build Tools官网
图1-20 Visual C++Build Tools的安装界面
点击了Download Visual C++Build Tools 2015之后就会跳出下载弹窗。等下载好之后就可以进行安装了。
根据安装界面上引导的步骤进行安装,安装完成,之后重启即可。然后在NPM中设置一下Visual Studio版本号:
· NPM的windows-build-tools
如果直接使用NPM,也可以安装在NPM官方仓库中的windows-build-tools依赖。其包名就是windows-build-tools,更多信息可以访问它在GitHub上的仓库进行了解:https://github.com/felixrieseberg/windows-build-tools。
在安装windows-build-tools之前需要保证你的计算机中已经安装了.NET Framework 4.5.1。若你的计算机尚未安装.NET Framework相应版本的话,可以前往https://www.microsoft.com/en-us/download/details.aspx?id=40773进行下载并且安装。
若要安装windows-build-tools,请打开你的Windows终端软件(如Command、PowerShell、Cygwin等),然后执行下面的命令:
可能出现的结果会跟下面的输出比较像。
由于上述命令要前往微软官网、Python官网等下载相应的程序,因此在国内的网络中下载会有速度缓慢或者丢包等现象,请耐心等待或重试。
执行了上述命令后,如果一切顺利,那么你就完成了node-gyp前驱依赖windows-build-tools的安装,里面包含了Visual C++Build Tools和Python 2.7。
· Python
node-gyp除了需要Visual C++的构建工具之外,还需要Python来支持其正常工作。如果你使用了NPM的windows-build-tools包安装方式来安装node-gyp前驱依赖的话,可以省去这一步,因为它自带了Python。但如果你使用另两种方式来安装Visual C++构建工具的话,还是要安装一下Python 2.7的。
首先,前往https://www.python.org/downloads/进行下载并安装。
注意:下载Python 2.7.*版本,node-gyp不支持Python 3+。
图1-21为在Windows下安装Python 2.7的界面截图。
图1-21 Windows Python 2.7的安装界面
注意要将python.exe添加到环境变量中。安装界面中有这一选项,选择就可以了。安装完成之后重启计算机。
然后在NPM中设置一下Python版本即可:
如果你的计算机中安装了多个版本的Python的话,可执行下面的命令指定相应的Python:
· Git
为了更方便地跟随本书的脚步,对于在Windows下开发的用户笔者推荐安装Git。如果本机没有安装Git环境,请读者自行前往https://git-scm.com下载Git并安装。图1-22为Windows下的Git Bash命令行。
图1-22 Windows下的Git Bash命令行
安装完之后,从未使用过Git的读者,可以打开初始安装后出现在“开始”菜单中的Git Bash项打开Git命令行,也可以在此使用Node.js之类的程序,或者直接在Windows的命令行中使用git命令。使用者可根据自己的个人习惯决定如何使用。此前在Windows中就会使用Git的读者按照自己以前的习惯使用即可。图1-23为在Windows下CMD中的Git命令行。
图1-23 CMD窗口中的Git命令行
· 其他问题
如果在Windows系统中安装node-gyp的前驱依赖时遇到一些问题,可以访问https://github.com/Microsoft/nodejs-guidelines/blob/master/windows-environment.md#compiling-native-addon-modules了解更多信息。
C++11
这里有比较重要的一点,即从io.js 3.0开始以及Node.js 4之后的版本,都需要使用C++11来对插件进行编译。所以,基本上现如今的Node.js下C++扩展开发和安装,都需要让计算机(或者服务器)上的C++编译器支持C++11了。
2.安装
node-gyp的安装非常简单。由于它是Node.js的一个常规包,因此可以直接通过NPM进行管理。跟平常的Node.js包一样,node-gyp只需要通过npm install就能安装了。
不过需要注意的是,node-gyp需要被全局安装,才能在安装一些Node.js下的C++扩展时被用到,也就是说在npm install时需要加上-g的参数。
另外需要注意,本书中如果没有特殊提示,所有命令行都是在类UNIX系统下执行的,在Windows系统中可能会有略微的出入,但出入不大。其中[sudo]表示有可能需要以sudo的形式执行该命令。$表示输入提示符,在Windows下这类似于D:\Workspace>。如果某一行没有该输入提示符带头,就说明该行是命令行可能的输出结果。
3.node-gyp命令
为了演示,推荐读者使用本书对应的代码“1.first build”目录下的代码。其代码可以从GitHub上克隆。
首先执行一遍node-gyp-h,看一下它的建议帮助文档。在本书编写之际当前node-gyp的版本为3.6.0。
从上面的简易文档中可以发现,node-gyp有下面几个子命令。
· node-gyp build:调用msbuild以构建模块(在Windows下是msbuild,若在UNIX下则会是make)。
· node-gyp clean:清理生成的构建文件以及out目录。
· node-gyp configure:为当前模块生成MSVC项目配置文件(在Windows下是MSVC,若在UNIX下则会是Makefile)。
· node-gyp rebuild:一次性依次执行clean/configure和build。
· node-gyp install:为指定版本的Node.js安装开发环境的文件。
· node-gyp list:输出当前安装的Node.js开发环境文件。
· node-gyp remove:移除指定版本的Node.js开发环境文件。
(1) node-gyp install
为了构建方便,我们先在当前开发环境中执行一遍install命令,将Node.js源码的一些头文件下载到本地目录。
若在Windows下,上述命令会把当前执行的Node.js相应版本的源码头文件、lib文件等下载解压到当前用户目录的.node-gyp目录下,如C:\Users\USER\.node-gyp;如果是Linux或者macOS的用户,则一样会下载解压到当前用户目录下,如/home/USER/.node-gyp目录。
我们会发现下面有相应的以版本号为名的目录,里面就是相关的文件了。图1-24为Windows下.node-gyp的目录结构示例;图1-25为macOS下该目录结构的示例。
图1-24 Windows下的.node-gyp目录结构
图1-25 macOS下的.node-gyp目录
扩展阅读:install命令有一个好玩的环境变量,叫NODEJS_ORG_MIRROR。由于在国内访问Node.js官方镜像的一些文件会非常慢,因此笔者推荐使用阿里巴巴维护的Node.js镜像。这个时候就可以设置NODEJS_ORG_MIRROR这个环境变量,在设置之后当我们执行node-gyp install时,就已经使用了该镜像。
阿里巴巴镜像的地址根目录如下:https://npm.taobao.org/mirrors/node。
在Windows下,该目录除了头文件以外还有库文件*.lib等,而在UNIX下只有头文件。有了这些文件,才能在构建代码的时候将它们包含进项目中。
· Windows
如果是Windows 7用户,笔者推荐右击“电脑”,选择“属性”一项,之后依次点击“高级系统设置”→“高级”→“环境变量”,添加用户环境变量或者系统环境变量。其变量名为NODEJS_ORG_MIRROR,其变量值为https://npm.taobao.org/mirrors/node,如图1-26所示。
图1-26 Windows下的NODEJS_ORG_MIRROR环境变量设置
· UNIX
如果是Linux或者macOS的用户,则可以在执行命令前加上NODEJS_ORG_MIRROR=https://npm.taobao.org/mirrors/node临时修改环境变量,如:
(2) node-gyp configure
在构建源码之前,必须先生成项目文件。在Windows下是Visual Studio所用的C++项目文件,而在UNIX系统下则是一个Makefile文件。
用命令行进入对应代码的“1.first build”目录,执行下面的命令:
为了使Windows开发者有一个更清晰的了解,这里给出在Windows下执行上述命令后可能出现的输出:
这个时候我们就能看到当前目录下多了一个build目录。在UNIX环境下生成的是Makefile文件和一些必要的配置文件;而在Windows下则是生成一个项目文件,里面有一个binding.sln文件可以直接用Visual Studio打开,如图1-27所示。
图1-27 用Visual Studio打开binding.sln的效果
(3) node-gyp build
build命令用于将当前所在目录的模块进行构建,将C++代码编译成二进制文件。我们可以在对应代码的“1.first build”目录下尝试一下该命令。
为了正确地编译,请使用相应的Node.js版本。这里可以上下偏差一些版本号,但不保证差别很大的版本能互相兼容。“1.first build”目录相应的Node.js版本号为6.9.4。
为了使Windows开发者有一个更清晰的了解,笔者这里给出Windows下执行上述命令后可能出现的输出:
我们发现执行了上述命令后,最后会在build/Release/目录下生成一个first.node。这就是我们构建的第一个Node.js的C++模块了。
为了看一下效果,我们可以在当前目录下打开Node.js命令行,并引入它执行Node.js代码:
看到了吧,成功了!
注意:要使用node-gyp build命令必须先生成构建配置,即执行node-gyp configure。
(4) node-gyp clean
clean命令清理生成的构建文件以及out目录,说白了就是将目录清干净,但是源码没动。
(5) node-gyp rebuild
这是一个懒人命令。它一次性依次执行了clean/configure和build。用通俗的语言来表达,就是先清理之前的构建记录,然后重新生成一份构建项目文件,最后进行构建编译。
(6)其他子命令
除了上述的子命令之外,还有就是list和remove了。
其中,node-gyp list会列出以版本为维度的当前你已安装的Node.js开发环境头文件。
上面的这个样例输出就说明了笔者的计算机中安装了0.10.38、0.12.2、0.12.7以及6.9.4等版本的Node.js开发环境头文件。
而node-gyp remove则是移除其中一个版本。比如笔者要移除0.10.38,就可以执行node-gyp remove 0.10.38了。
执行完这些之后我们再执行node-gyp list,就会发现0.10.38已经被除名了。
除此之外,还有以下两个参数供大家使用。
· node-gyp-h或者node-gyp--help:输出帮助文字。
· node-gyp-v或者node-gyp--version:输出当前node-gyp的版本号。
1.4.3 其他构建工具
本小节作为扩展阅读,并不在书中详细展开,有兴趣的读者可以到其各自工具的官网查询文档。
大千世界,物种繁多。天地不仁以万物为刍狗,码农不仁以各种构建工具为刍狗。除了最受欢迎(或者说受众最广)的node-gyp以外,Node.js中其实还有其他各种不同的构建工具。
node-gyp的原理就是在安装C++原生模块的时候,使用GYP通过一个binding.gyp文件来构建各系统所需的C++项目文件(如UNIX下是Makefile,Windows下是Visual Studio项目),然后再通过相应的构建工具(如Visual Studio)来进行构建。所以依照其原理,其他的构建工具大同小异,只不过node-gyp是官方支持,所以不需要嵌入任何脚本,而其他构建工具大多需要在package.json中的scripts字段加入诸如postinstall的脚本,使其在包安装阶段能够执行构建。
Node.js的C++模块构建工具其实有很多,读者甚至可以自己实现一套。下面列出两个构建工具供大家参考。
1.cmake-js
顾名思义,这个构建工具会使用CMake当前的C++源码生成一个项目文件。所以其本质上跟node-gyp一样,只是生成的项目文件(或者Makefile)会有所不同。
它对于开发者(以及安装这个包的用户)是有要求的,需要其在计算机上安装CMake。Windows用户一样需要Visual C++Build Tools,UNIX用户还需要GCC。不过UNIX用户还多了一个选择,就是Ninja。
有兴趣的读者可以访问其官网进行更进一步的了解,它的GitHub地址是https://github.com/cmake-js/cmake-js。
要使用cmake-js,则需要以全局依赖的方式安装它,并且配置项目package.json文件的postinstall字段,使其在安装阶段执行cmake-js以达到构建效果。
2.node-cmake
node-cmake是另一个以CMake为基础的构建工具。其原理与前面的cmake-js差不多,都是通过CMakeList.txt生成项目所需的文件,然后再通过postinstall字段进行构建和编译的。
有兴趣的读者可以访问其官方网站进行深入的了解,它的GitHub地址是https://github.com/cjntaylor/node-cmake。
1.4.4 小结
本节主要介绍了作为一个Node.js的C++扩展开发者所需要事先搭建好的开发环境。毕竟编辑器/IDE作为开发者的主要装备,还是有必要好好挑选和使用的,这也就是所谓的“磨刀不误砍柴工”。而node-gyp作为Node.js界中最流行的原生扩展构建工具,也作为本书中所用的原生扩展构建工具,在阅读本书前也是需要事先安装好的。
除此之外,本节还拓展阅读了其他的一些非GYP系的构建工具,如cmake-js和node-cmake。大家需要清楚,构建工具的本质就是通过一个配置文件和构建工具的程序本身来生成一个关于当前项目的Makefile或者Visual Studio项目文件,从而可以调用其相应的编译器对项目进行编译。
1.4.5 参考资料
[1]Neovim:https://neovim.io/.
[2](美)罗宾斯,(美)汉娜,(美)拉姆.学习vi和Vim编辑器[M].南京:东南大学出版社,2011.
[3]Emacs和Vim:神的编辑器和编辑器之神:http://os.51cto.com/art/201101/242518.htm.
[4]Sublime Text:学习资源篇:http://www.jianshu.com/p/d1b9a64e2e37.
[5]Visual Studio Code Guide:http://i5ting.github.io/vsc/.
[6]Atom背后的故事:https://jysperm.me/2016/11/behind-atom/.
[7]Visual Studio for Mac:https://www.visualstudio.com/zh-hans/vs/visual-studio-mac/.
[8]针对Visual Studio的Node.js工具:https://www.visualstudio.com/zh-hans/vs/node-js/.
[9]蒋鑫.Git权威指南[M].北京:机械工业出版社,2011.
[10]node-gyp/README.md at master:https://github.com/nodejs/node-gyp/blob/master/README.md.