问答文章1 问答文章501 问答文章1001 问答文章1501 问答文章2001 问答文章2501 问答文章3001 问答文章3501 问答文章4001 问答文章4501 问答文章5001 问答文章5501 问答文章6001 问答文章6501 问答文章7001 问答文章7501 问答文章8001 问答文章8501 问答文章9001 问答文章9501

由npminstall报关于node-gyp的错引发的思考

发布网友 发布时间:2024-09-26 16:14

我来回答

1个回答

热心网友 时间:2024-11-16 15:25

最近在启动一个老旧的vue项目的时候,发现在npminstall的时候,node-sass在进行编译时报关于node-gyp的错,于是花了点时间来搞清楚node-gyp的作用和背后的机理。

javascript:一个跨平台脚本语言

我们知道,JavaScript脚本语言不依赖于操作系统,仅需要浏览器的支持。因此一个JavaScript脚本在编写后可以带到任意机器上使用,前提上机器上的浏览器支持JavaScript脚本语言。

像C/C++它把源程序由特定平台的编译器一次性编译为平台相关的机器码,是无法跨平台。像JavaScript它不直接面向底层,它使用特定的解释器(chrome或者nodejs),把代码一行行解释为机器码,类似于同声翻译,它的优点是可以跨平台,缺点是执行速度慢,暴露源程序。

所以,nodejs也是跨平台的,所以对于任何的nodejs模块理论也应该是跨平台的。然而,有些nodejs模块直接或间接使用原生C/C++代码,这些东西要跨平台,就需要使用源码根据实际的操作平台环境进行原生模块编译。除了nodejs模块外,还有一些Node插件,它们也是由C/C++编写的,所以在使用的时候也需要编译。

Node插件

Node插件是用C/C++语言编写的动态链接库,使用require()?加载到Node环境中,能够像普通Node模块一样使用。Node插件可以用于编写高性能C++算法,也可以用在Node环境与其他C/C++库之间提供接口封装,实现互相调用。

在早期的Node插件开发中,严重依赖V8引擎的API,可能都遇到过升级Node版本后插件不可用的情况,需要重新编译。这是因为Node版本升级,V8引擎的二进制ABI接口发生变化,导致之前编译的Node插件不可用。

为了解决这一问题,在Node8.0版本中发布了新的N-API接口。N-API并不是一种新的插件编写模式,N-API是对V8引擎API的封装,以C风格API提供对外接口,并且保证接口是ABI稳定的。使用N-API编写的Node插件能够一次编写、一次编译,跨多个Node版本运行。N-API接口在8.12.0以及更高版本中已经处于稳定状态(参见abi-stable-node),可以放心在生产环境投入使用。

编译Node插件使用node-gyp。下面我们尝试编译一个简单的hello-world插件。

在?github.com/nodejs/node…?中有官方提供的多个Node插件上手示例项目。其中多数小demo官方有提供了3种实现方式,分别是NAN,N-API以及node-addon-api。node-addon-api是对C形式的N-API的C++封装,同样是ABI兼容的。我个人推荐使用node-addon-api。NAN是早期的写插件使用的API,需要和V8API结合使用,现在已经不再推荐。

通过使用node-addon-api,插件代码比直接使用N-API更加简洁、易读。NODE_MODULE第一个参数是插件名称,第二个参数是Initialize注册函数。Initialize注册函数中,将?hello?绑定到函数?Method?上。

hello_world.cc

#include<node.h>voidMethod(constv8::FunctionCallbackInfo<v8::Value>&args){v8::Isolate*isolate=args.GetIsolate();args.GetReturnValue().Set(v8::String::NewFromUtf8(isolate,"world").ToLocalChecked());}voidInitialize(v8::Local<v8::Object>exports){NODE_SET_METHOD(exports,"hello",Method);}NODE_MODULE(NODE_GYP_MODULE_NAME,Initialize)

binding.gyp

{"targets":[{"target_name":"hello_world","sources":["hello_world.cc"]}]}

index.js

constbinding=require('./build/Release/hello_world');console.log(binding.hello());

package.json

"scripts":{"build":"node-gypconfigure&&node-gypbuild","dev":"nodeindex.js"}

执行npmrunbuild,生成hello_world.node文件,然后像引入其他js模块一样就可以正常使用了。

在javascript端,也可以使用bindings来加载模块。因为Node插件历史发展中,二进制文件会被编译产出到很多不同的位置,使用bindings可以解决寻找插件路径的问题,bindings检查所有可能的插件构建位置,返回第一个成功的加载位置。首先安装bindings

npminstallbindingsnode-gyp

在上面编译hello_world.cc的工具是node-gyp,要理解node-gyp首先要知道什么是gyp。

gyp其实是一个用来生成项目文件的工具,一开始是设计给chromium项目使用的,后来大家发现比较好用就用到了其他地方。生成项目文件后就可以调用GCC,vsbuild,xcode等编译平台来编译。至于为什么要有node-gyp,是由于node程序中需要调用一些其他语言编写的工具甚至是dll,需要先编译一下,否则就会有跨平台的问题,例如在windows上运行的软件copy到mac上就不能用了,但是如果源码支持,编译一下,在mac上还是可以用的。

长久以来linux的二进制分发一直是巨坑,npm为了方便干脆就直接源码分发,用户装的时候再现场编译。不过对另一些人二进制分发就比源码分发简单多了,所以还有个node-pre-gyp来干二进制扩展的分发。

node-pre-gyp

上面node-gyp固然相当方便了,但是每一次安装node原生模块的时候,都需要根据平台(Windows、Linux、macOS以及对应的x86、x64、arm64等等)进行源码编译,这样做费时费力。为什么不一开始就针对这些平台编译好了做成二进制制品发布呢?反正一般来说主流的平台架构就那么一些(Windows、Linux、macOS)。所以node-pre--gyp就帮我们做了这件事。原生模块开发者将代码编译生成各个平台架构的二进制包直接发布到node-pre-gyp上,当我们的node项目安装原生模块时候。处理流程就是首先去node-pre-gyp上找有没有当前平台的组件包,有的话直接拉取使用,如果没有则进行原生编译。下图是node-sqlite3的二进制包:

于是乎,当我们进行node原生模块安装的时候,一般会有如下的流程:

针对当前平台架构优先考虑node-pre-gyp方式进行安装,但是为了防止无法获取针对对应平台编译好的二进制包(网络原因、暂时没有对应平台的二进制包),进入第2步;

下载原生模块源码,然后使用node-gyp进行项目构建,得到与平台相关的源码项目文件(Windows则生成vcxproj项目,Linux下是Makefile);在这个过程,node-gyp会使用Python进行自动化构建操作,这也是为什么有些朋友安装node原生模块的时候,会报错找不到Python。

调用平台对应的编译工具进行编译。在Windows的环境下,node-gyp会查找本地的MSBuild/CL等编译工具,而这些编译工具又一般在VisualStudio安装的时候,也一并安装在了机器上。这就是为什么有些朋友没有安装VisualStudio的时候,会报错。

原文:https://juejin.cn/post/7101945682277171213
声明声明:本网页内容为用户发布,旨在传播知识,不代表本网认同其观点,若有侵权等问题请及时与本网联系,我们将在第一时间删除处理。E-MAIL:11247931@qq.com
分手后说过的话精选185句 分手说的精选113句 分手怎么挽回女朋友的句子精选162句 现在工作忙的要死,女朋友因为这跟我分手,我该怎么办? ...任意组成两个不同的两位小数,并把它们改写成以0.001为计数单位... m3/MW▪h怎么换算m3/s▪GW? 交通银行的刷卡金怎么使用呢? 什么时候刷卡金 ...突然前面两条腿好像断了一样 走路前面两腿都无法支撑 吃饭就坐着吃... 王者荣耀:伤害与回复兼备的杨戬,为何不受待见,真废了吗? vue项目启动报错? 金辉鹿鸣长滩为啥只有2栋楼 16.17世纪,除葡萄牙之外侵占中国的国家 高陵金辉鹿鸣长滩一共几期 大国兴起 16.17.18世纪分别是那个地方兴盛的时期 大国兴起的原因和条件... 16.17世纪的殖民国家有哪些? 西安金辉鹿鸣长滩带装修吗? 西安金辉鹿鸣长滩售楼处电话是多少? 滴滴王卡是专为司机推出的工作手机号吗? mt6873p5g是什么处理器? 联通滴滴王卡真实的吗 super junior的歌曲【why I like you喜欢你的理由】的歌词及中文... 德国曼格纳机油好不好?德国卡帕姆机油好嘛? vivo手机横屏竖屏该怎么调整? 德国机油品牌大全哪款可以降低噪声? 河北二建2024报名时间 怎么看电池是否健康? 河北二建考试最新消息2024年 怎么给手机测电池 易付宝是不是骗人的?? ...虫子吗,看看是看不出有虫子,可是就是感觉有虫子在爬 泰康人寿回访要保险人提供生日吗 Vue项目报错及解决方案集合 2021东莞植物园假日专线开通时间 东莞植物园游玩攻略 不锈钢炒锅用白布擦有黑是怎么回事 哪些盐是沉淀 老人留下来的三元钱人民币 现在能够值多少钱? 哪些碳酸盐沉淀 去扬州必游的十大景点都是哪里_北京到扬州自驾游沿途景点推荐 什么是单项式,什么是多项式。 从西宁到茶卡盐湖如何去 做剧烈运动,加速血液循坏后擦精油 有利于更好吸收?? 西宁怎么去青海湖和茶卡盐湖 我在济南现在到北京务工索要什么手术,老家是四川广元的,在济南干地铁... 怎么查询用过什么网贷 你如何看待专业的发展前景和专业的满意度呢? 如何用手机号搜索到对方的微信号码? 陌生人可以通过手机号码查到我吗 盐酸维拉帕米片药理毒理 盐酸维拉帕米缓释片作用机理