electron集成arm64架构的nodejs addon插件

随着macos M1芯片的发布,当前的electron PC应用要适配arm64架构(虽然低版本electron应用也可以在arm64架构上面运行(转译)但是这严重影响电脑性能)。

环境搭建

mac上面编译node需要安装xcode、node-gyp、python,node。可以根据下面链接查看到当前支持了M1架构的应用具体版本号。https://isapplesiliconready.com/zh

  • xcode-v12.2
    在这里插入图片描述

  • node-v15.1.0
    在这里插入图片描述

  • python-v3.9.1
    在这里插入图片描述

  • electron-v11.1.0

在这里插入图片描述

在这里插入图片描述
查看当前本机安装的环境:

nodelee@bijiewangluodeMac-mini m1_addon % npm -v
7.0.8
nodelee@bijiewangluodeMac-mini m1_addon % node -v
v15.1.0
nodelee@bijiewangluodeMac-mini m1_addon % node-gyp -v
v7.1.2

环境测试

addon编写

强烈建议使用napi实现addon,nan api适配性很差,不同版本的electron需要重新编译,并且有些高版本的electron还不支持。

addon.cc

#include <string>
#include <assert.h>
#include <stdio.h>
#include <ctime>

#define NAPI_EXPERIMENTAL
#include <node_api.h>

#define NAPI_DESC(name, func) \
  napi_property_descriptor { name, 0, func, 0, 0, 0, napi_default, 0 }

#define CHECK(expr)                                                    \
  {                                                                    \
    if ((expr == napi_ok) == 0)                                        \
    {                                                                  \
      fprintf(stderr, "[Err] %s:%d: %s\n", __FILE__, __LINE__, #expr); \
      fflush(stderr);                                                  \
      abort();                                                         \
    }                                                                  \
  }

napi_value get_value(napi_env env, napi_callback_info info)
{
    
    
    napi_value ret;
    CHECK(napi_create_int32(env, 1314, &ret));
    return ret;
}


napi_value Init(napi_env env, napi_value exports)
{
    
    
    napi_property_descriptor desc;
    desc = NAPI_DESC("getValue", get_value);
    CHECK(napi_define_properties(env, exports, 1, &desc));
    return exports;
}
NAPI_MODULE(addon, Init)

binding.gyp

{
    
    
    'targets': [
        {
    
    
            "target_name": "addon", 
            "sources": ["./addon.cc"]      
        }
    ]  
}

index.js

var addon= require('./build/Release/addon.node');
console.log("addon get value is ", addon.getValue());

分别在intel和arm64 环境下编译

node-gyp rebuild --arch=arm64
node-gyp rebuild --arch=x64

查看intel x86上面编译的node架构

macdeMacBook-Pro:mac mac$ lipo -info addon_x64.node 
Architectures in the fat file: addon_x64.node are: x86_64 

查看arm64上面编译的node架构

nodelee@bijiewangluodeMac-mini Release % lipo -info addon_arm64.node
Non-fat file: addon_arm64.node is architecture: arm64

正常情况下两种架构的运行结果:

nodelee@bijiewangluodeMac-mini m1_addon % node index.js
addon get value is  1314

合并node

为了调用方便我们可以把不同架构的node合并成一个,加载的时候根据不同的架构加载不同的node。

lipo -create addon_arm64.node addon_x64.node -output addon.node

查看合并后的node架构

nodelee@bijiewangluodeMac-mini Release % lipo -info addon.node
Architectures in the fat file: addon.node are: x86_64 arm64

electron集成addon

electron高版本为了安全性打包后contextIsolation默认为true

mian.js

const {
    
    
  app,
  BrowserWindow,
  dialog,
  ipcMain
} = require("electron");
const path = require("path");

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.

let win;
function createWindow() {
    
    
  // Create the browser window.
  win = new BrowserWindow({
    
    
    width: 800,
    height: 600,
    webPreferences: {
    
    
      nodeIntegration: false, // is default value after Electron v5
      contextIsolation: true, // protect against prototype pollution
      // enableRemoteModule: false, // turn off remote
      preload: path.join(__dirname, "./preload.js") // use a preload script
    }
  });

  // Load app
  win.loadFile(path.join(__dirname, "./index.html"));
}

app.on("ready", createWindow);

index.html

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<script>
    console.log("value is ", window.api.getValue()); //
</script>

<body>
    <h1>hello electron</h1>
</body>

</html>

package.json

{
    
    
    "name": "bjcast-demo",
    "version": "1.0.18",
    "description": "A minimal Electron application",
    "main": "./main.js",
    "scripts": {
    
    
        "dev": "electron .",
        "build:mac": "electron-builder --mac --arm64"
    },
    "build": {
    
    
        "appId": "com.bjnet.demo",
        "mac": {
    
    
            "target": {
    
    
                "target": "dir",
                "arch": "arm64"
            }
        },
    },
    "author": "GitHub",
    "license": "CC0-1.0",
    "devDependencies": {
    
    
        "electron": "^11.1.0",
        "electron-builder": "^22.9.1"
    }
}

preload.js

const {
    
    
    contextBridge,
} = require("electron");



var addon = require('./addon.node');

contextBridge.exposeInMainWorld(
    "api", {
    
    
    getValue: () => {
    
    
        return addon.getValue();
    },
}
);

运行

npm run dev

打包

npm run build:mac

Guess you like

Origin blog.csdn.net/weixin_43398820/article/details/112850400