Skip to content

Commit bc470e7

Browse files
committed
app compile wasm (with external script)
1 parent c3177ee commit bc470e7

File tree

7 files changed

+151
-8
lines changed

7 files changed

+151
-8
lines changed

CircuitLib/procedural/cpp/adder.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ bool generateCircuit() {
1212

1313
BlockType BlockType_AND = getPrimitiveType("AND");
1414
BlockType BlockType_XOR = getPrimitiveType("XOR");
15-
BlockType BlockType_OR = getPrimitiveType("XOR");
15+
BlockType BlockType_OR = getPrimitiveType("OR");
1616
BlockType BlockType_SWITCH = getPrimitiveType("SWITCH");
1717
BlockType BlockType_LIGHT = getPrimitiveType("LIGHT");
1818

resources/wasmBuilder.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import pathlib
2+
import sys
3+
import os
4+
5+
def build(source: pathlib.Path, target: pathlib.Path):
6+
assert (source.suffix in [".zig", ".rs", ".c", ".cpp", ".cc"])
7+
assert (target.suffix == ".wasm")
8+
os.chdir(source.parent)
9+
res = 0
10+
if source.suffix == ".zig":
11+
res = os.system(f"zig build-exe {source} -target wasm32-freestanding -fno-entry -rdynamic -O ReleaseSmall -femit-bin={target}")
12+
elif source.suffix == ".rs":
13+
return False # Rust builds are currently disabled
14+
res = os.system(f"rustc {source} -target wasm32-unknown-unknown -O -o {target}")
15+
elif source.suffix in [".cc", ".c", ".cpp"]:
16+
res = os.system(f"emcc {source} -Os -flto -s STANDALONE_WASM -s EXPORTED_FUNCTIONS=\"['_generateCircuit', '_getUUID', '_getName', '_getDefaultParameters']\" --no-entry -o {target}")
17+
return res == 0
18+
19+
build(sys.argv[1], sys.argv[2])

resources/wasmBuilder.sh

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
if [ "$#" -ne 2 ]; then
6+
echo "Usage: $0 <source> <target>" >&2
7+
exit 1
8+
fi
9+
10+
source="$1"
11+
target="$2"
12+
13+
# Get file extension
14+
source_ext="${source##*.}"
15+
target_ext="${target##*.}"
16+
17+
# Validate extensions
18+
case "$source_ext" in
19+
zig|rs|c|cpp|cc) ;;
20+
*)
21+
echo "Error: Source file must have extension .zig, .rs, .c, .cpp, or .cc" >&2
22+
exit 1
23+
;;
24+
esac
25+
26+
if [ "$target_ext" != "wasm" ]; then
27+
echo "Error: Target file must have .wasm extension" >&2
28+
exit 1
29+
fi
30+
31+
# Get source directory and change to it
32+
source_dir="$(dirname "$source")"
33+
cd "$source_dir"
34+
35+
# Build based on extension
36+
case "$source_ext" in
37+
zig)
38+
zig build-exe "$source" -target wasm32-freestanding -fno-entry -rdynamic -O ReleaseSmall -femit-bin="$target"
39+
;;
40+
rs)
41+
echo "Error: Rust builds are currently disabled" >&2
42+
exit 1
43+
;;
44+
c|cpp|cc)
45+
emcc "$source" -Os -flto -s STANDALONE_WASM -s EXPORTED_FUNCTIONS="['_generateCircuit', '_getUUID', '_getName', '_getDefaultParameters']" --no-entry -o "$target"
46+
;;
47+
esac

resources/wasmCompileCommand.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"command": ["wasmBuilder.sh", "source", "target"]
3+
}

src/computerAPI/circuits/circuitFileManager.cpp

Lines changed: 23 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,27 @@
44
#include "backend/wasm/wasm.h"
55
#include "connectionMachineParser.h"
66
#include "scrapMechanicParser.h"
7+
#include "wasmCompiler.h"
78

89
CircuitFileManager::CircuitFileManager(CircuitManager& circuitManager) : circuitManager(circuitManager) { }
910

1011
std::vector<circuit_id_t> CircuitFileManager::loadFromFile(const std::string& path) {
1112
auto iter = filePathToFile.find(path);
1213
if (iter != filePathToFile.end()) {
13-
logInfo("Duplicate import detected. skipping file: " + path, "CircuitFileManager");
14-
std::vector<circuit_id_t> circuitIds;
15-
for (const std::string& uuid : iter->second.UUIDs) {
16-
SharedCircuit circuit = circuitManager.getCircuit(uuid);
17-
if (circuit) {
18-
circuitIds.push_back(circuit->getCircuitId());
14+
if (!(
15+
((path.size() >= 4 && path.substr(path.size() - 4) == ".wat") || (path.size() >= 5 && path.substr(path.size() - 5) == ".wasm")) ||
16+
((path.size() >= 4 && path.substr(path.size() - 4) == ".cpp") || (path.size() >= 4 && path.substr(path.size() - 4) == ".zig") || (path.size() >= 3 && path.substr(path.size() - 3) == ".rs"))
17+
)) {
18+
logInfo("Duplicate import detected. skipping file: " + path, "CircuitFileManager");
19+
std::vector<circuit_id_t> circuitIds;
20+
for (const std::string& uuid : iter->second.UUIDs) {
21+
SharedCircuit circuit = circuitManager.getCircuit(uuid);
22+
if (circuit) {
23+
circuitIds.push_back(circuit->getCircuitId());
24+
}
1925
}
26+
return circuitIds;
2027
}
21-
return circuitIds;
2228
}
2329

2430
if (path.size() >= 4 && path.substr(path.size() - 4) == ".cir") {
@@ -47,6 +53,16 @@ std::vector<circuit_id_t> CircuitFileManager::loadFromFile(const std::string& pa
4753
} else {
4854
logError("Failed to load wasm module", "CircuitFileManager");
4955
}
56+
} else if ((path.size() >= 4 && path.substr(path.size() - 4) == ".cpp") || (path.size() >= 4 && path.substr(path.size() - 4) == ".zig") || (path.size() >= 3 && path.substr(path.size() - 3) == ".rs")) {
57+
std::optional<wasmtime::Module> module = WasmCompiler::compileFile(path);
58+
if (module) {
59+
const std::string* UUID = circuitManager.getProceduralCircuitManager().createWasmProceduralCircuit(module.value());
60+
if (UUID) {
61+
setSaveFilePath(*UUID, std::filesystem::absolute(std::filesystem::path(path)).generic_string());
62+
}
63+
} else {
64+
logError("Failed to compile/load wasm module", "CircuitFileManager");
65+
}
5066
} else if (path.size() >= 5 && path.substr(path.size() - 5) == ".json") {
5167
// SM circuit file parser function
5268
ScrapMechanicParser parser(*this, circuitManager);
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
#include "wasmCompiler.h"
2+
3+
#include "backend/wasm/wasm.h"
4+
#include "computerAPI/directoryManager.h"
5+
6+
std::optional<wasmtime::Module> WasmCompiler::compileFile(const std::string& file) {
7+
std::filesystem::path wasmCompileCommandPath = std::filesystem::absolute(DirectoryManager::getResourceDirectory() / "wasmCompileCommand.json");
8+
std::ifstream wasmCompileCommand(wasmCompileCommandPath);
9+
if (wasmCompileCommand.is_open()) {
10+
try {
11+
nlohmann::json jsonData;
12+
wasmCompileCommand >> jsonData;
13+
if (jsonData.is_object() && jsonData.contains("command") && jsonData.at("command").is_array()) {
14+
nlohmann::json args = jsonData.at("command");
15+
const std::filesystem::path& compiledWasmPath = DirectoryManager::getConfigDirectory() / "compiled_wasm";
16+
std::filesystem::create_directories(compiledWasmPath);
17+
const std::filesystem::path& wasmFile = compiledWasmPath / (std::filesystem::path(file).stem().string() + ".wasm");
18+
std::string command;
19+
for (unsigned int i = 0; i < args.size(); i++) {
20+
if (i > 0) {
21+
command += " ";
22+
}
23+
if (args.at(i) == "source") {
24+
command += "\"" + file + "\"";
25+
} else if (args.at(i) == "target") {
26+
command += "\"" + wasmFile.string() + "\"";
27+
} else if (i == 0) {
28+
command += "\"" + wasmCompileCommandPath.parent_path().string() + "/" + args.at(i).get<std::string>() + "\"";
29+
} else {
30+
command += "\"" + args.at(i).get<std::string>() + "\"";
31+
}
32+
}
33+
logInfo(command);
34+
std::system(command.c_str());
35+
return Wasm::loadModule(wasmFile.string());
36+
}
37+
logError("Failed to load compile commands.", "WasmCompiler");
38+
} catch (const nlohmann::json::parse_error& e) {
39+
logError("Failed to load compile commands. Error: {}", "WasmCompiler", e.what());
40+
}
41+
} else {
42+
logError("Failed to open compile commands from \"{}\"", "WasmCompiler", wasmCompileCommandPath.string());
43+
}
44+
return std::nullopt;
45+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#ifndef wasmCompiler_h
2+
#define wasmCompiler_h
3+
4+
#include <wasmtime.hh>
5+
6+
class Environment;
7+
8+
class WasmCompiler {
9+
public:
10+
static std::optional<wasmtime::Module> compileFile(const std::string& file);
11+
};
12+
13+
#endif /* wasmCompiler_h */

0 commit comments

Comments
 (0)