跳到主要内容

静态编译node.js-v16踩坑记

· 阅读需 3 分钟
Skyone
科技爱好者

想静态编译一个 Node.js 打包成 Google Distroless 容器,但编译的时候遇到一些问题,不过为了照顾没有编译过源代码的同学,还是一步一步介绍。最终成果:

静态链接

注:本文仅面向Linux系统

今天七夕,来首歌

获取Nodejs源代码

我这里下载的是Nodejs v16,命令如下

# 下载源代码
wget https://nodejs.org/dist/v16.16.0/node-v16.16.0.tar.gz
# 解压
tar -zxf node-v16.16.0.tar.gz
# 进入文件夹
cd node-v16.16.0

编译

一般情况下,正常编译只需要:

./configure && make && make install

但是,我们需要将nodejs纯静态编译,参考这篇文章

首先查看 configure 的与 static 相关的帮助:

./configure --help | grep static

输出如下:

    --fully-static        Generate an executable without external dynamic
--partly-static Generate an executable with libgcc and libstdc++
--enable-static build as static library
link to a shared http_parser DLL instead of static
--shared-libuv link to a shared libuv DLL instead of static linking
--shared-nghttp2 link to a shared nghttp2 DLL instead of static linking
--shared-openssl link to a shared OpenSSl DLL instead of static linking
--shared-zlib link to a shared zlib DLL instead of static linking
--shared-cares link to a shared cares DLL instead of static linking

显然,我们需要 --fully-static--enable-static 参数

注意!这里有一个坑!

我们直接编译是不会通过的,显示编译失败!

我把错误信息 Google 了一下,找到了如下 Issue

nodejs/node#30180

里面的错误与我遇到的一样,也清晰的给出了原因和解决方案

原因:没有静态链接 pthread

解决方案:修改 configure.py 文件

diff --git a/configure.py b/configure.py
index 8790b3c13fcc..5f7fdb55aed9 100755
--- a/configure.py
+++ b/configure.py
@@ -1266,7 +1266,7 @@ def configure_static(o):
return

if options.fully_static:
- o['libraries'] += ['-static']
+ o['libraries'] += ['-static', '-Wl,--whole-archive', '-lpthread', '-Wl,--no-whole-archive']
elif options.partly_static:
o['libraries'] += ['-static-libgcc', '-static-libstdc++']
if options.enable_asan:

可以使用 sed 命令一键修改:

sed -i "s/'-static'/'-static', '-Wl,--whole-archive', '-lpthread', '-Wl,--no-whole-archive'/" configure.py

问题解决,可以正常编译了:

./configure --fully-static --enable-static
make && make install

对比一下

看看动态链接与静态链接的区别:

首先是动态链接版:

动态链接

然后是静态链接版:

静态链接

可以看到,仅仅变大了1M

【完】