2015-10-15 23 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配置文件。