封裝檔案

本主題說明如何封裝在載入頁面時用來填入Emscripten 虛擬檔案系統的檔案。

檔案封裝方式有兩種選擇:預載入內嵌。內嵌會將指定的檔案儲存在 wasm 檔案內,而預載入則會將它們封裝在側邊的套件中。內嵌檔案比預載入更有效率,因為不需要下載和複製單獨的檔案,但預載入可以選擇單獨託管資料。

Emcc 使用檔案封裝器來封裝檔案並產生檔案系統 API呼叫,以在執行階段建立和載入檔案系統。雖然建議使用 Emcc 作為封裝工具,但在某些情況下,手動執行檔案封裝器會比較合理。

使用 --use-preload-plugins,可以根據副檔名自動解碼檔案。請參閱預載入檔案以取得更多資訊。

使用 emcc 封裝

封裝檔案最簡單的方法是在編譯時使用emccpreloadembed 命令會選擇其各自的封裝方法。

下面的命令顯示如何封裝要預載入的檔案

emcc file.cpp -o file.html --preload-file asset_dir

此命令會產生 file.htmlfile.jsfile.data.data 檔案包含 asset_dir/ 中的所有檔案,並由 file.js 載入。

注意

教學課程示範如何使用 hello_world_file.cpp 測試程式碼進行預載入。

內嵌的命令如下所示。在這種情況下,emcc 會產生 file.htmlfile.jsasset_dir/ 的內容會直接內嵌到 file.js

emcc file.cpp -o file.html --embed-file asset_dir

依預設,要封裝的檔案應巢狀在編譯時命令提示字元目錄中或其下方。在執行階段,相同的巢狀檔案結構會對應到虛擬檔案系統,其中根目錄對應到命令提示字元目錄。

例如,考慮檔案結構 dir1/dir2/dir3/asset_dir/,其中專案是從 dir2 編譯的。當我們封裝 asset_dir 時,我們會指定其相對位置 dir3/asset_dir/

emcc file.cpp -o file.html --preload-file dir3/asset_dir

該資料夾在執行階段的虛擬檔案系統中位於相同的位置 dir3/asset_dir。同樣地,如果我們在 dir2 中封裝檔案,則該檔案將在執行階段的虛擬檔案系統根目錄中可用。

可以使用 @ 符號將本機檔案系統中任何位置的封裝檔案對應到虛擬檔案系統中的任何位置。這在下面的修改虛擬檔案系統中的檔案位置中討論。

使用檔案封裝器工具進行封裝

您也可以使用 file_packager 頂部的說明手動執行檔案封裝器

檔案封裝器會產生 .data 檔案和 .js 檔案。 .js 檔案包含使用資料檔案的程式碼,而且必須在載入主要編譯程式碼之前載入。(例如,在 --shell-file 的結尾處,在 {{{ SCRIPT }}}` 之前新增 <script> 標籤。)

注意

  • 使用檔案封裝器可讓您將檔案封裝與編譯程式碼分開執行。

  • 您可以對每個檔案執行檔案封裝器並載入 .js 輸出,來載入多個資料檔案。如需動態載入的範例,請參閱 BananaBreadcube2/js/game-setup.js)。

變更資料檔案位置

依預設,包含所有預載入檔案的 .data 檔案會從與 .js 檔案相同的 URL 載入。在某些情況下,將資料檔案放在與其他檔案不同的位置可能很有用 — 例如,如果您的 .html.js 變更頻繁,您可能會希望將資料檔案保留在其他地方的快速 CDN 上。

此模型透過指定 Module.locateFile 函式來傳回儲存資料檔案的 URL 來支援。該函式必須在載入資料檔案的 <script> 元素之前指定。

修改虛擬檔案系統中的檔案位置

預設的封裝方法是將編譯時的巢狀檔案結構(相對於編譯時的命令提示字元目錄)直接對應到虛擬檔案系統的根目錄。可以在建置時在路徑中使用 @ 符號,來明確指定資源在執行階段於虛擬檔案系統中的位置。

注意

需要 @ 符號,因為有時封裝並未巢狀在編譯時目錄下的檔案會很有用,因此無法將其預設對應到虛擬檔案系統中的位置。

例如,我們可以將預載入的資料夾 ../../asset_dir 對應到虛擬檔案系統的根目錄 (/),方法是使用

emcc file.cpp -o file.html --preload-file ../../asset_dir@/

我們也可以對應新的路徑和檔案名稱。例如,若要讓內嵌的檔案 ../res/gen123.png/main.png 的形式可用,我們可能會執行

emcc file.cpp -o file.html --embed-file ../res/gen123.png@main.png

有效字元集

以下字元可用於檔案名稱:A-Za-z0-9、空格字元以及任何以下字元:!#$%&'()+,-.;=@[]^_`{}~。此外,如果您的主機檔案系統支援,則可以使用以下字元:"*<>?| (Windows 不允許在檔案名稱中使用這些字元)。當在命令列上指定字元 @ 時,必須將其轉義為 @@ 的形式,以避免觸發 src@dst 的映射表示法 (請參閱上方)。字元 /\: 無法使用。

監控檔案使用情況

重要

為了減少下載大小並提高啟動速度,請僅打包您的應用程式實際需要的檔案。

有一個選項可以記錄執行時實際使用的檔案。要使用它,請定義 Module.logReadFiles 物件。每個讀取的檔案都會被記錄到 stderr。

另一種方法是查看您編譯後的 JavaScript 中的 FS.readFiles()。這是一個包含所有讀取檔案的鍵的物件。您可能會發現它比記錄更容易使用,因為它記錄的是檔案而不是潛在的多個檔案存取。

注意

您還可以修改 FS.readFiles() 物件或完全移除它。舉例來說,這對於查看應用程式中兩個時間點之間讀取了哪些檔案會很有用。

預先載入檔案

使用 --use-preload-plugins,檔案可以根據其副檔名自動解碼。也可以透過在每個檔案上呼叫 emscripten_run_preload_plugins() 手動完成。這些檔案仍以原始形式儲存在檔案系統中,但可以直接使用其解碼後的格式。

支援以下格式

  • 圖片 (.jpg.jpeg.png.bmp):這些檔案會使用瀏覽器的圖片解碼器解碼,然後可以由 IMG_Load 使用 (SDL1 和 SDL2 連接埠,它們依賴於 emscripten_get_preloaded_image_data())。(設定 Module.noImageDecodingtrue 以停用)。

  • 音訊 (.ogg.wav.mp3):這些檔案會使用瀏覽器的音訊解碼器解碼,然後可以使用 Mix_LoadWAV (僅限 SDL1)。(設定 Module.noAudioDecodingtrue 以停用)。

  • 動態程式庫 (.so):這些檔案會使用 WebAssembly.instantiate 預先編譯和實例化。這對於需要非同步編譯大型 WebAssembly 模組的瀏覽器 (例如 Chrome) 非常有用,如果您稍後想使用 dlopen 同步載入模組。(設定 Module.noWasmDecodingtrue 以停用)。

測試程式碼

測試套件 包含許多檔案打包範例,是搜尋可執行程式碼的好地方。