将预编译的二进制文件捆绑到电子应用中
有没有一个很好的解决scheme,如何将imagemagick等第三方预编译的二进制文件包含到电子应用程序中? 有node.js模块,但它们都是封装或本地绑定到系统安装的库。 我想知道是否有可能在发行版中捆绑预编译的二进制文件。
我确实find了解决办法,但我不知道这是否被认为是最佳做法。 我无法find任何包含第三方预编译二进制文件的好文档,所以我只是一直弄弄它,直到最终与我的ffmpeg二进制文件一起工作。 这是我做的(从电子快速入门开始,node.js v6):
Mac OS X方法
从app目录中,我在terminal中运行以下命令,将ffmpeg二进制文件作为模块包含在内:
mkdir node_modules/ffmpeg cp /usr/local/bin/ffmpeg node_modules/ffmpeg/ cd node_modules/.bin ln -s ../ffmpeg/ffmpeg ffmpeg
(用当前的二进制pathreplace/usr/local/bin/ffmpeg
,从这里下载)放置链接允许electron-packager包含我保存到node_modules/ffmpeg/
的二进制文件。
然后获得捆绑的应用程序path(以便我可以使用绝对path为我的二进制…相对path似乎没有工作,无论我做了什么)我安装了npm包app-root-dir运行以下命令:
npm i -S app-root-dir
现在我有了根应用程序目录,我只是追加了我的二进制文件的子文件夹,并从那里产生。 这是我放在renderer.js中的代码:
var appRootDir = require('app-root-dir').get(); var ffmpegpath=appRootDir+'/node_modules/ffmpeg/ffmpeg'; console.log(ffmpegpath); const spawn = require( 'child_process' ).spawn, ffmpeg = spawn( ffmpegpath, ['-i',clips_input[0]]); //add whatever switches you need here ffmpeg.stdout.on( 'data', data => { console.log( `stdout: ${data}` ); }); ffmpeg.stderr.on( 'data', data => { console.log( `stderr: ${data}` ); });
Windows方法
- 打开你的电子基础文件夹(电子快速启动是默认名称),然后进入node_modules文件夹。 在那里创build一个名为ffmpeg的文件夹,并将你的静态二进制文件复制到这个目录中。 注意:它必须是你的二进制文件的静态版本,因为ffmpeg我抓住了最新的Windows版本。
-
要获得捆绑的应用程序path(以便我可以使用绝对path为我的二进制文件…相对path似乎没有工作,不pipe我做了什么)我通过运行以下命令安装npm包app-root-dir从我的应用程序目录中的命令提示符:
npm i -S app-root-dir
-
在您的node_modules文件夹中,导航到.bin子文件夹。 您需要在这里创build几个文本文件来告诉节点包含刚刚复制的二进制exe文件。 使用你最喜欢的文本编辑器,并创build两个文件,一个名为
ffmpeg
与以下内容:#!/bin/sh basedir=$(dirname "$(echo "$0" | sed -e 's,\\,/,g')") case `uname` in *CYGWIN*) basedir=`cygpath -w "$basedir"`;; esac if [ -x "$basedir/node" ]; then "$basedir/node" "$basedir/../ffmpeg/ffmpeg" "$@" ret=$? else node "$basedir/../ffmpeg/ffmpeg" "$@" ret=$? fi exit $ret
而第二个文本文件名为
ffmpeg.cmd
:@IF EXIST "%~dp0\node.exe" ( "%~dp0\node.exe" "%~dp0\..\ffmpeg\ffmpeg" %* ) ELSE ( @SETLOCAL @SET PATHEXT=%PATHEXT:;.JS;=;% node "%~dp0\..\ffmpeg\ffmpeg" %* )
接下来,您可以在Windows电子分配(在renderer.js中)中运行ffmpeg,如下所示(我也使用了app-root-dir节点模块)。 请注意添加到二进制path的引号,如果您的应用程序安装到一个空格的目录(例如C:\Program Files\YourApp
),它将无法正常工作。
var appRootDir = require('app-root-dir').get(); var ffmpegpath = appRootDir + '\\node_modules\\ffmpeg\\ffmpeg'; const spawn = require( 'child_process' ).spawn; var ffmpeg = spawn( 'cmd.exe', ['/c', '"'+ffmpegpath+ '"', '-i', clips_input[0]]); //add whatever switches you need here, test on command line first ffmpeg.stdout.on( 'data', data => { console.log( `stdout: ${data}` ); }); ffmpeg.stderr.on( 'data', data => { console.log( `stderr: ${data}` ); });
TL;博士:
是的你可以! 但它需要你编写你自己的独立的插件,它不会对系统库做任何假设。 此外,在某些情况下,您必须确保您的插件是为所需的操作系统编译的。
让我们分几个部分来解决这个问题:
– 插件 (原生模块) :
插件是dynamic链接的共享对象。
换句话说,你可以编写你自己的插件,而不需要依赖于系统范围的库(例如,通过静态链接所需的模块)来包含所有你需要的代码。
你必须考虑这种方法是特定于操作系统的,这意味着你需要编译你想要支持的每个操作系统的插件! (取决于你可能使用的其他库)
– 电子本地模块 :
Electron支持本地节点模块,但是由于Electron使用与官方节点不同的V8版本,因此在构build本地模块时必须手动指定Electron头的位置
这意味着已经build立了针对节点头部的本地模块必须被重build以用于电子内部。 你可以find如何在电子文档。
– 与电子应用捆绑模块 :
我想你想要你的应用程序作为一个独立的可执行文件,而不需要用户在他们的机器上安装电子。 如果是这样,我可以build议使用电子打包器 。
这是另一种方法,到目前为止已经在Mac和Windows上进行了testing。 需要“app-root-dir”包,不需要手动向node_modules dir添加任何内容。
-
把你的文件放在资源/ $ os /下,其中$ os是“mac” , “linux”或“win” 。 构build过程将根据构build目标OS从这些目录中复制文件。
-
将
extraFiles
选项放置在您的构buildconfiguration中,如下所示:
的package.json
"build": { "extraFiles": [ { "from": "resources/${os}", "to": "Resources/bin", "filter": ["**/*"] } ],
- 使用这样的东西来确定当前的平台。
得到-platform.js
import { platform } from 'os'; export default () => { switch (platform()) { case 'aix': case 'freebsd': case 'linux': case 'openbsd': case 'android': return 'linux'; case 'darwin': case 'sunos': return 'mac'; case 'win32': return 'win'; } };
- 根据env和OS调用应用程序的可执行文件。 在这里,我假设内置版本是在生产模式和其他模式的源版本,但你可以创build自己的调用逻辑。
import { join as joinPath, dirname } from 'path'; import { exec } from 'child_process'; import appRootDir from 'app-root-dir'; import env from './env'; import getPlatform from './get-platform'; const execPath = (env.name === 'production') ? joinPath(dirname(appRootDir.get()), 'bin'): joinPath(appRootDir.get(), 'resources', getPlatform()); const cmd = `${joinPath(execPath, 'my-executable')}`; exec(cmd, (err, stdout, stderr) => { // do things });
我想我是用电子生成器作为基础的,env文件的生成伴随着它。 基本上它只是一个JSONconfiguration文件。