2015-10-15 55 views
17

是否有关于如何将第三方预编译的二进制文件像ImageMagick的成电子应用好的解决办法?有node.js模块,但它们都是封装或本地绑定到系统安装的库。我想知道是否有可能在发行版中捆绑预编译的二进制文件。捆绑预编译的二进制到电子应用

+0

看到我对这个其他答案[SO问题](http://stackoverflow.com/questions/38361996/how-can-i-bundle-a-precompiled-binary-with-electron/43389268#43389268) – gimenete

回答

9

我没有找到一个解决的办法,但我不知道,如果这被认为是最好的做法。我无法找到任何包含第三方预编译二进制文件的好文档,所以我只是一直弄弄它,直到它终于与我的ffmpeg二进制文件一起工作。这就是我所做的(从电子快速入门开始,节点。JS V6):

Mac OS X的方法

从app目录我跑在终端中输入以下命令,包括FFmpeg的二进制文件作为一个模块:

mkdir node_modules/ffmpeg 
cp /usr/local/bin/ffmpeg node_modules/ffmpeg/ 
cd node_modules/.bin 
ln -s ../ffmpeg/ffmpeg ffmpeg 

(替换为/usr/local/bin/ffmpeg您当前的二进制路径,从这里下载)放置链接允许electron-packager包含我保存到node_modules/ffmpeg/的二进制文件。

然后获取捆绑的应用程序路径(以便我可以使用我的二进制文件的绝对路径......无论我做了什么,相对路径似乎都不起作用)我安装了npm软件包app-root-dir通过运行以下命令:

npm i -S app-root-dir 

现在,我有根app目录,我只是追加的子文件夹为我的二进制文件,并从那里出来。这是我放在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}`); 
    }); 

窗口的方法

  1. 打开电子基础文件夹(电子快速启动是默认的名称),然后进入node_modules文件夹。在那里创建一个名为ffmpeg的文件夹,并将静态二进制文件复制到此目录中。注意:它必须是你的二进制文件的静态版本,因为ffmpeg我抓住了最新的Windows版本here
  2. 要获得捆绑的应用程序路径(以便我可以为我的二进制文件使用绝对路径......不管我做了什么,相对路径似乎都不起作用)我安装了npm包app-root-dir运行在我的应用程序目录中从命令提示符下面的命令:

    npm i -S app-root-dir 
    
  3. 在您node_modules文件夹,浏览到的.bin子文件夹。您需要在这里创建几个文本文件来告诉节点包含刚才复制的二进制exe文件。使用您喜欢的文本编辑器,并创建两个文件,一个名为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" "[email protected]" 
        ret=$? 
    else 
        node "$basedir/../ffmpeg/ffmpeg" "[email protected]" 
        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" %* 
    ) 
    

接下来,您可以运行的ffmpeg在你的Windows电子分布(在renderer.js中)如下(我也使用了app-root-dir节点模块)。请注意添加到二进制路径中的引号,如果您的应用程序安装到具有空格的目录(例如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}`); 
}); 
+0

要清楚,这个方法使用electron-packager应用程序和一个预编译的ffmpeg二进制文件。 [使用电子应用捆绑模块]方法。 – UltrasoundJelly

+0

你能解释一下'ln -s ../ffmpeg/ffmpeg node_modules/.bin/ffmpeg'你是否连接了你刚刚创建的'ffmpeg'副本? 'ln -s'之前改过目录了吗? – Jake

+1

对不起,代码不正确。我没有改变目录,然后创建链接。添加并更改了代码。 – UltrasoundJelly

6

TL;博士:

当然可以!但它需要你编写自己的自包含插件,它不会对系统库做任何假设。此外,在某些情况下,您必须确保您的插件已编译为所需的操作系统。


允许在几个部分打破这个问题:

- Addons(母语模块)

扩展中心是动态链接的共享对象。

换句话说,您可以编写自己的插件,而不依赖于系统范围库(例如,通过静态链接所需模块),其中包含所有您需要的代码。

你必须考虑这样的方法和具体的操作系统,这意味着你需要编译你的插件为要支持的每个操作系统! (这取决于其他库,你可以使用)

- Native modules为电子

的本地节点模块通过电子的支持,但由于电子是使用不同的V8版本,从官方的节点,你在构建本地模块时必须手动指定Electron头部的位置

这意味着已针对节点标头构建的本地模块必须重建以用于电子内部。你可以找到电子文档。

- 捆绑模块,电子应用

我想你想拥有你的应用程序作为一个独立的可执行文件,而不需要用户在他们的计算机上安装的电子。如果是这样,我可以建议使用electron-packager

+0

so我可以下载为每个操作系统预编译的imagemagick,将它打包到一个子文件夹中并针对它执行? – Tobias

+0

编辑:如在开关中,如果它是Windows我使用imagemagick.exe等 – Tobias

+0

@Tobias如果你得到可执行文件,你可以运行程序['child_process'](https://nodejs.org/api/child_process.html)模块。如果要访问库的函数,则需要使用整个本机插件方法。 –

5

下面是另一种方法,在Mac和Windows中测试到目前为止。需要'app-root-dir'包,不需要手动向node_modules dir添加任何内容。

  1. 将下资源/ $ OS文件 /,其中$ OS或者是“陆委会”“LINUX”,或“赢”。构建过程将根据构建目标OS从这些目录中复制文件。在构建CONFIGS

  2. extraFiles选项,如下所示:

的package.json

"build": { 
    "extraFiles": [ 
     { 
     "from": "resources/${os}", 
     "to": "Resources/bin", 
     "filter": ["**/*"] 
     } 
    ], 
  • 使用这样确定目前的平台。
  • GET-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和操作系统的可执行文件。在这里,我假设内置版本处于生产模式和其他模式下的源版本,但您可以创建自己的调用逻辑。
  • 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 
    }); 
    

    我想我是用electron-builder作为基地,ENV文件生成与它来。基本上它只是一个JSON配置文件。