node源码粗读(2):node编译过程详解及如何在本地进行源码修改和调试
发布于 6 年前 作者 xtx1130 5624 次浏览 来自 分享

上篇文章直接单刀直入讲述了node运行的一个整体流程,导致很多人在群里或者cnode中询问如何可以在本地断点调试node。因此献上这篇文章,让大家对node编译过程和开发有个整体的认知

c++编译三部曲

$ ./configure
$ make  
$ make install

相信看到这三个命令后,大家应该是十分熟悉。没错,node编译也就是这三步。

  • 第一步:配置。软件装到哪里、什么参数、什么os、装什么东西,全都是configure来确定的
  • 第二步:编译。make会读取makefile的配置,进行编译,生成可执行文件
  • 第三步:安装。make install 会根据设定好的路径,把软件安装到系统中

接下来,我们从这三个步骤入手,来串一下node整体的编译过程。

node 编译过程

./configure

目标很明确,我们直奔configure文件,来查看node的configure究竟都做了些什么。 issue9-1 额,原来关键代码就在这里,其中import了三个模块,分别为:nodedownload(下载模块)、getmoduleversion(获取版本)、以及gyp_node。大家知道,node其实是基于gyp进行编译的那么这个gyp_node模块具体是什么呢?让我们继续扒到tools/gyp_nodeissue9-2 通过gyp_node中的这段代码可以读出来,其实最后运行的是node.gyp,我们视线跳转到node.gyp,而node.gyp就是构建文件内容,即python的一个数据结构(类似一个json串)。通过筛查其中的target_name我们可以发现这个gyp_node做了有如下几件事情(只说比较重要的,有兴趣的同学可以自己翻看node.gyp):

  • 关联node可执行文件的sources
  • 定义node_js2c的输出文件为node_javascript.cc
  • node_dtrace动态跟踪框架一系列定义
  • cctest 测试相关定义

接下来视线回到gyp_node.py。下面有几行有意思的代码:

  if sys.platform != 'win32' and 'ninja' not in args:
    # Tell gyp to write the Makefiles into output_dir
    args.extend(['--generator-output', output_dir])

    # Tell make to write its output into the same dir
    args.extend(['-Goutput_dir=' + output_dir])

这几行代码会根据node.gyp中的target_name和type在./out文件夹中,生成Makefile和*.mk文件: issue9-3 回到./configure中,有几个配置参数需要我们注意一下:

parser.add_option('--prefix',
    action='store',
    dest='prefix',
    default='/usr/local',
    help='select the install prefix [default: %default]')
parser.add_option('--debug',
    action='store_true',
    dest='debug',
    help='also build debug build')

请大家注意下这两个参数,一个是–prefix,如果不设定prefix,默认路径相当于安装到了全局,不利于我们进行调试,–debug参数在运行configure的时候也是一定要加的。加了–debug,make的才会生成相应的/out/Debug文件夹。即,如果你想在本地调试的话,需要运行的第一个步骤的代码是:

$ ./configure --preifx=your repo --debug

make

入手make的话,我们直接切入到makefile就好了。然后我们就会发现如下代码:

ifeq ($(BUILDTYPE),Release)
all: out/Makefile $(NODE_EXE)
else
all: out/Makefile $(NODE_EXE) $(NODE_G_EXE)
endif

在这里,分为了两种情况,上面为Release的情况,下面是configure --debug的情况。可以看到debug多一个步骤$(NODE_G_EXE),经过查找其实是node_g,用于debug模式用的。$(NODE_EXE)就不过多介绍了,就是node的执行文件,下面主要看一下out/Makefile。不知道大家对out/文件夹还熟悉吗?没错,就是上一步./configure生成的。我们翻到out/Makefile中看一下这个makefile做了什么。 issue9-4 这里只做一段代码的截图,不过我们已经可以发现这里面引用了所有的mk文件,之后进行编译,因为他监听了所有的mk,相当于这里监听了所有的node相关的文件,只要include的关联文件有改动,在make的时候都会造成out/Makefile的重新编译,接下来我们回到主文件./Makefile:

.PHONY: $(NODE_EXE) $(NODE_G_EXE)
$(NODE_EXE): config.gypi out/Makefile
	$(MAKE) -C out BUILDTYPE=Release V=$(V)
	if [ ! -r $@ -o ! -L $@ ]; then ln -fs out/Release/$(NODE_EXE) $@; fi

$(NODE_G_EXE): config.gypi out/Makefile
	$(MAKE) -C out BUILDTYPE=Debug V=$(V)
	if [ ! -r $@ -o ! -L $@ ]; then ln -fs out/Debug/$(NODE_EXE) $@; fi

.PHONY的目标是$(NODE_EXE) $(NODE_G_EXE),说明在每次make的时候,这两个target一定会运行,看上面的代码这两个target都关联了 out/Makefile,而out/Makefile刚才已经讲过了,他可以监听到所有的node源码文件,只要有改动,在make的时候就会重新编译。通过这一套流程,其实可以实现如下的功能:

修改node源码文件->make重新编译->node重新编译生成

如果我们在调试的时候,如果一直用的是编译之后的node,那么我们其实在修改源码之后,只需要重新make一下就好了。

make install

如果只是本地做调试用,其实到第二步就可以了,make install 相当于把可执行文件安装到第一步定义的preifx中,在这里我建议大家,在git clone 代码的时候,直接clone到你心仪的目录下。

本地调试开发node源码

本地编译

在本地开发的时候,我选择的ide是cLion,除了开始生成的cMakefile比较坑爹外,还是不错的。
首先,把node代码 clone下来:

$ git clone https://github.com/nodejs/node.git

然后,进入到node中运行:

$ ./configure --prefix=your repo --debug 

然后进行make操作:

$ make

这样,相当于已经编译完成node了。

导入项目

我们打开cLion把这个项目到cLion中,导入进来之后会自动生成一个CMakeLists.txt,我们不需要管这个文件,在进行调试的时候,通过make就可以了。CMakeLists.txt由于是自动生成的,只是简单的遍历了一遍c++基础文件,没有相应的链接库,所以即使跑也是跑不通的。

关联node

在cLion顶部菜单run->Edit Configuration中,进行一下配置: issue9-5 一定要确保before launch中是空的,不要加build,如果加了build就会在运行前调用cmake读取CMakeLists.txt,这并不是我们所希望的。executable可执行文件,选择out/Debug/node。

断点调试

还是刚才那张图,在你的programming arguments中加上要调试的js文件地址,然后去node.cc中打断点,然后运行debug试一下,看看是否会走到你的断点中,不出意外的话,是完全ok的。

node源码修改调试

如果你想对node源码进行修改调试,认真看了上面的文章的同学应该已经想到了:在修改完代码之后,通过make进行编译,就会触发out/Makefile,从而重新生成out/Debug/node文件,注意一下make的控制台输出:

if [ ! -r node_g -o ! -L node_g ]; then ln -fs out/Debug/node node_g; fi

在这里,对out/Debug/node做了一个软链,如果是第一次编译,会建立一个软链,连接到node_g。

原文链接:https://github.com/xtx1130/blog/issues/9
如果您觉得文章写的对您来说有价值,欢迎star,如果其中有分析的不到位或者错误的地方,欢迎大佬在评论或者issue中指正 by小菜

5 回复

star了,额去试一下。

star



 

来自酷炫的 CNodeMD

回到顶部