依存するファイルの管理を自動化
以前の記事 では JavaScript のコードで依存するデータ・ファイルを取得し管理した。
ここでは、--preload-file オプションを使いデータ・ファイルの管理を自動化する。
以下は実装したファイルの一覧となる。
C:\wasm\project\15-preload-file\.vscode\launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "chrome",
"request": "launch",
"name": "localhost:8080",
"url": "http://localhost:8080/",
}
]
}
C:\wasm\project\15-preload-file\CMakePresets.json
{
"version": 5,
"cmakeMinimumRequired": {
"major": 3,
"minor": 20,
"patch": 0
},
"configurePresets": [
{
"name": "wasm-config",
"hidden": true,
"generator": "Ninja Multi-Config",
"binaryDir": "${sourceDir}/build",
"cacheVariables": {
"CMAKE_CXX_STANDARD": "17",
"CMAKE_CXX_STANDARD_REQUIRED": "ON",
"CMAKE_CXX_EXTENSIONS": "OFF",
"CMAKE_TOOLCHAIN_FILE": "$env{EMSDK}/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake",
"CMAKE_EXPORT_COMPILE_COMMANDS": "ON",
"CMAKE_CONFIGURATION_TYPES": "Debug;Release"
}
},
{
"name": "wasm-config-debug",
"inherits": "wasm-config",
"cacheVariables": {
}
},
{
"name": "wasm-config-release",
"inherits": "wasm-config",
"cacheVariables": {
}
}
],
"buildPresets": [
{
"name": "wasm-build-debug",
"configurePreset": "wasm-config-debug",
"verbose": true,
"configuration": "Debug"
},
{
"name": "wasm-build-release",
"configurePreset": "wasm-config-release",
"verbose": true,
"configuration": "Release"
}
]
}
C:\wasm\project\15-preload-file\CMakeLists.txt
-- --preload-file では「実際のパス @ 仮想ファイルシステム上のパス」の形式で指定
cmake_minimum_required(VERSION 3.20)
project(15_preload_file LANGUAGES CXX)
add_executable(15_preload_file main.cpp)
target_link_options(15_preload_file PRIVATE
$<$<CONFIG:Debug>:-gsource-map -sASSERTIONS=1 -sSAFE_HEAP=1>
"-sEXPORTED_RUNTIME_METHODS=FS"
"-sEXPORT_ES6=1"
"--preload-file=${CMAKE_SOURCE_DIR}/data.txt@data.txt"
)
C:\wasm\project\15-preload-file\index.html
- データ・ファイルの fetch() などは不要
- .data の位置を locateFile() でグルーコードに伝える必要がある
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="utf-8"/>
<script type="module">
import Module from './build/Debug/15_preload_file.js';
let v = 0;
const monitorRunDependencies = left => console.log(`left ${left}`);
const locateFile = (path, prefix) => {
if (path.endsWith(".data")) {
return './build/Debug/' + path;
}
return prefix + path;
};
Module({ arguments: ['data.txt'], monitorRunDependencies, locateFile }).then(emsModule =>
{
v = emsModule._increment(v);
console.log(`return=${v}`);
});
</script>
</head>
<body>
</body>
</html>
C:\wasm\project\15-preload-file\data.txt
1000
1010
2100
C:\wasm\project\15-preload-file\main.cpp
// UTF-8N CRLF
#include <emscripten.h>
#include <iostream>
#include <fstream>
extern "C"
EMSCRIPTEN_KEEPALIVE
int increment(int v)
{
printf("-- increment(%d)\n", v);
return v + 1;
}
int main(int argc, char** argv)
{
std::cout << "C++ main(argc=" << argc << ", argv=[";
for (int i=0; i<argc; ++i)
{
if (i) {
std::cout << ",";
}
std::cout << "'" << argv[i] << "'";
}
std::cout << "])" << std::endl;
std::cout << "open: " << argv[1] << std::endl;
std::ifstream ifs{ argv[1] };
if (ifs)
{
std::string line;
while (std::getline(ifs, line))
{
std::cout << "DATA: " << line << std::endl;
}
}
else
{
std::cerr << "file open error" << std::endl;
}
return 0;
}
// EOF
ビルド後の確認
--preload-file で指定したファイルは *.data としてまとめられ wasm ファイルと同じディレクトリに配置され、実行時に locateFile() により解決したパスから自動的に取得される。
C:\wasm\project\15-preload-file>dir build\Debug\*.data
ドライブ C のボリューム ラベルは OS です
ボリューム シリアル番号は E886-5372 です
C:\wasm\project\15-preload-file\build\Debug のディレクトリ
2025/10/22 10:50 16 15_preload_file.data
1 個のファイル 16 バイト
0 個のディレクトリ 623,659,319,296 バイトの空き領域
実行結果
monitorRunDependencies() での監視を含め、手動でファイル管理をしていたものと結果に変わりはない。
left 1
left 2
left 1
left 0
C++ main(argc=2, argv=['./this.program','data.txt'])
open: data.txt
DATA: 1000
DATA: 1010
DATA: 2100
-- increment(0)
return=1
似たオプションに --embed-file があるが、こちらはビルド時にファイルをグルーコードに埋め込む。
次回 は One True Awk を wasm として動かしてみる。