Skip to content

Commit d1df1af

Browse files
committed
fix: wamr build on windows
Signed-off-by: Gordon Smith <GordonJSmith@gmail.com>
1 parent feb4155 commit d1df1af

File tree

5 files changed

+208
-23
lines changed

5 files changed

+208
-23
lines changed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ project(cmcpp LANGUAGES CXX)
55
# Determine default for BUILD_SAMPLES: OFF on Windows, ON elsewhere
66
set(_BUILD_SAMPLES_DEFAULT ON)
77
if (WIN32)
8-
set(_BUILD_SAMPLES_DEFAULT OFF)
8+
set(_BUILD_SAMPLES_DEFAULT ON)
99
endif()
1010
option(BUILD_SAMPLES "Build samples" ${_BUILD_SAMPLES_DEFAULT})
1111
option(BUILD_TESTING "Build tests" ON)

include/wamr.hpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
#include "wasm_export.h"
22
#include "cmcpp.hpp"
3+
#include <array>
34

45
namespace cmcpp
56
{
@@ -94,10 +95,11 @@ namespace cmcpp
9495
std::vector<wasm_val_t> inputs = wasmVal2wam_val_t(lowered_args);
9596

9697
constexpr size_t output_size = std::is_same<result_t, void>::value ? 0 : 1;
97-
wasm_val_t outputs[output_size];
98+
std::array<wasm_val_t, output_size> outputs{};
99+
wasm_val_t *output_ptr = output_size > 0 ? outputs.data() : nullptr;
98100

99101
bool success = wasm_runtime_call_wasm_a(exec_env, guest_func,
100-
output_size, outputs,
102+
output_size, output_ptr,
101103
inputs.size(), inputs.data());
102104

103105
if (!success)
@@ -109,11 +111,11 @@ namespace cmcpp
109111

110112
if constexpr (output_size > 0)
111113
{
112-
auto output = lift_flat_values<result_t>(liftLowerContext, MAX_FLAT_RESULTS, wam_val_t2wasmVal(output_size, outputs));
114+
auto output = lift_flat_values<result_t>(liftLowerContext, MAX_FLAT_RESULTS, wam_val_t2wasmVal(output_size, output_ptr));
113115

114116
if (guest_cleanup_func)
115117
{
116-
wasm_runtime_call_wasm_a(exec_env, guest_cleanup_func, 0, nullptr, output_size, outputs);
118+
wasm_runtime_call_wasm_a(exec_env, guest_cleanup_func, 0, nullptr, output_size, output_ptr);
117119
}
118120

119121
return output;

samples/CMakeLists.txt

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,17 +9,82 @@ if (WAMR_SAMPLE_AVAILABLE)
99
message(FATAL_ERROR "WASI_SDK_PREFIX is not set. Install wasi-sdk via vcpkg or set WASI_SDK_PREFIX manually before building the samples.")
1010
endif()
1111

12+
if (NOT DEFINED NINJA_EXECUTABLE)
13+
set(_ninja_hint_dirs)
14+
set(_ninja_candidate_files)
15+
16+
if (DEFINED VCPKG_INSTALLED_DIR AND DEFINED VCPKG_HOST_TRIPLET)
17+
set(_vcpkg_tool_root "${VCPKG_INSTALLED_DIR}/${VCPKG_HOST_TRIPLET}/tools")
18+
if (EXISTS "${_vcpkg_tool_root}")
19+
file(GLOB _vcpkg_fetched_ninja
20+
"${_vcpkg_tool_root}/ninja*/ninja.exe"
21+
"${_vcpkg_tool_root}/ninja*/ninja"
22+
"${_vcpkg_tool_root}/ninja*/bin/ninja.exe"
23+
"${_vcpkg_tool_root}/ninja*/bin/ninja"
24+
)
25+
list(APPEND _ninja_candidate_files ${_vcpkg_fetched_ninja})
26+
foreach(_file IN LISTS _vcpkg_fetched_ninja)
27+
get_filename_component(_dir "${_file}" DIRECTORY)
28+
list(APPEND _ninja_hint_dirs "${_dir}")
29+
endforeach()
30+
endif()
31+
endif()
32+
33+
set(_repo_vcpkg_dir "${CMAKE_SOURCE_DIR}/vcpkg")
34+
if (EXISTS "${_repo_vcpkg_dir}/downloads/tools")
35+
file(GLOB _repo_fetched_ninja
36+
"${_repo_vcpkg_dir}/downloads/tools/ninja*/ninja.exe"
37+
"${_repo_vcpkg_dir}/downloads/tools/ninja*/ninja"
38+
"${_repo_vcpkg_dir}/downloads/tools/ninja*/bin/ninja.exe"
39+
"${_repo_vcpkg_dir}/downloads/tools/ninja*/bin/ninja"
40+
)
41+
list(APPEND _ninja_candidate_files ${_repo_fetched_ninja})
42+
foreach(_file IN LISTS _repo_fetched_ninja)
43+
get_filename_component(_dir "${_file}" DIRECTORY)
44+
list(APPEND _ninja_hint_dirs "${_dir}")
45+
endforeach()
46+
list(APPEND _ninja_hint_dirs "${_repo_vcpkg_dir}/downloads/tools")
47+
endif()
48+
49+
if (_ninja_hint_dirs)
50+
list(REMOVE_DUPLICATES _ninja_hint_dirs)
51+
find_program(NINJA_EXECUTABLE ninja
52+
HINTS ${_ninja_hint_dirs}
53+
NO_DEFAULT_PATH
54+
)
55+
endif()
56+
57+
if (NOT NINJA_EXECUTABLE)
58+
foreach(_candidate IN LISTS _ninja_candidate_files)
59+
if (EXISTS "${_candidate}")
60+
set(NINJA_EXECUTABLE "${_candidate}")
61+
break()
62+
endif()
63+
endforeach()
64+
endif()
65+
endif()
66+
67+
if (NOT NINJA_EXECUTABLE)
68+
find_program(NINJA_EXECUTABLE ninja)
69+
endif()
70+
71+
if (NOT NINJA_EXECUTABLE)
72+
message(FATAL_ERROR "Ninja build tool not found. Run './vcpkg/vcpkg.exe fetch ninja' or set NINJA_EXECUTABLE manually to build the wasm guest sample.")
73+
endif()
74+
1275
ExternalProject_Add(wasm
1376
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/wasm
1477
BUILD_ALWAYS TRUE
1578
PREFIX wasm
16-
CMAKE_ARGS
79+
CMAKE_GENERATOR Ninja
80+
CMAKE_ARGS
1781
-DHPCC_WASM_ROOT=${HPCC_WASM_ROOT}
1882
-DWASI_SDK_PREFIX=${WASI_SDK_PREFIX}
1983
-DCMAKE_TOOLCHAIN_FILE=${WASI_SDK_PREFIX}/share/cmake/wasi-sdk.cmake
2084
-DCMAKE_SYSROOT=${WASI_SDK_PREFIX}/share/wasi-sysroot
2185
-DCMAKE_INSTALL_PREFIX=${CMAKE_CURRENT_BINARY_DIR}
2286
-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
87+
-DCMAKE_MAKE_PROGRAM=${NINJA_EXECUTABLE}
2388
)
2489

2590
add_dependencies(wamr wasm)

samples/wamr/main.cpp

Lines changed: 74 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,39 +1,76 @@
11
#include "wamr.hpp"
22
#include <algorithm>
33
#include <cfloat>
4+
#include <filesystem>
5+
#include <fstream>
46
#include <iostream>
7+
#include <limits>
8+
#include <system_error>
59
#include <tuple>
610

711
using namespace cmcpp;
812

913
// Configuration constants
1014
constexpr uint32_t DEFAULT_STACK_SIZE = 8192;
1115
constexpr uint32_t DEFAULT_HEAP_SIZE = 8192;
12-
constexpr const char *WASM_FILE_PATH = "../bin/sample.wasm";
16+
const std::filesystem::path WASM_RELATIVE_PATH = std::filesystem::path("bin") / "sample.wasm";
1317

14-
char *read_wasm_binary_to_buffer(const char *filename, uint32_t *size)
18+
std::filesystem::path resolve_wasm_path(const std::filesystem::path &start_dir)
1519
{
16-
FILE *file = fopen(filename, "rb");
20+
constexpr int MAX_ASCENT = 6;
21+
auto dir = start_dir;
22+
for (int depth = 0; depth < MAX_ASCENT && !dir.empty(); ++depth)
23+
{
24+
const auto candidate = dir / WASM_RELATIVE_PATH;
25+
if (std::filesystem::exists(candidate))
26+
{
27+
std::error_code ec;
28+
const auto normalized = std::filesystem::weakly_canonical(candidate, ec);
29+
return ec ? candidate : normalized;
30+
}
31+
if (!dir.has_parent_path())
32+
{
33+
break;
34+
}
35+
dir = dir.parent_path();
36+
}
37+
38+
return {};
39+
}
40+
41+
char *read_wasm_binary_to_buffer(const std::filesystem::path &filename, uint32_t *size)
42+
{
43+
std::ifstream file(filename, std::ios::binary | std::ios::ate);
1744
if (!file)
1845
{
1946
std::cerr << "Failed to open file: " << filename << std::endl;
2047
return nullptr;
2148
}
2249

23-
fseek(file, 0, SEEK_END);
24-
*size = ftell(file);
25-
fseek(file, 0, SEEK_SET);
50+
const auto file_size = file.tellg();
51+
if (file_size < 0)
52+
{
53+
std::cerr << "Failed to determine file size: " << filename << std::endl;
54+
return nullptr;
55+
}
56+
57+
if (file_size > static_cast<std::streamoff>(std::numeric_limits<uint32_t>::max()))
58+
{
59+
std::cerr << "File too large to load: " << filename << std::endl;
60+
return nullptr;
61+
}
62+
63+
*size = static_cast<uint32_t>(file_size);
64+
file.seekg(0, std::ios::beg);
2665

2766
char *buffer = new char[*size];
28-
if (fread(buffer, 1, *size, file) != *size)
67+
if (!file.read(buffer, static_cast<std::streamsize>(*size)))
2968
{
3069
std::cerr << "Failed to read file: " << filename << std::endl;
3170
delete[] buffer;
32-
fclose(file);
3371
return nullptr;
3472
}
3573

36-
fclose(file);
3774
return buffer;
3875
}
3976

@@ -84,12 +121,38 @@ NativeSymbol logging_symbol[] = {
84121
host_function("log-u32", log_u32),
85122
};
86123

87-
int main()
124+
int main(int argc, char **argv)
88125
{
126+
static_cast<void>(argc);
127+
89128
std::cout << "WAMR Component Model C++ Sample" << std::endl;
90129
std::cout << "===============================" << std::endl;
91130
std::cout << "Starting WAMR runtime initialization..." << std::endl;
92131

132+
std::filesystem::path exe_dir = std::filesystem::current_path();
133+
if (argv && argv[0])
134+
{
135+
const std::filesystem::path candidate = std::filesystem::absolute(argv[0]);
136+
if (std::filesystem::exists(candidate))
137+
{
138+
exe_dir = candidate.parent_path();
139+
}
140+
}
141+
142+
std::filesystem::path wasm_path = resolve_wasm_path(exe_dir);
143+
if (wasm_path.empty())
144+
{
145+
wasm_path = resolve_wasm_path(std::filesystem::current_path());
146+
}
147+
148+
if (wasm_path.empty())
149+
{
150+
std::cerr << "Unable to locate sample.wasm relative to " << exe_dir << std::endl;
151+
return 1;
152+
}
153+
154+
std::cout << "Using WASM file: " << wasm_path << std::endl;
155+
93156
char *buffer, error_buf[128];
94157
wasm_module_t module;
95158
wasm_module_inst_t module_inst;
@@ -102,7 +165,7 @@ int main()
102165
std::cout << "WAMR runtime initialized successfully" << std::endl;
103166

104167
/* read WASM file into a memory buffer */
105-
buffer = read_wasm_binary_to_buffer(WASM_FILE_PATH, &size);
168+
buffer = read_wasm_binary_to_buffer(wasm_path, &size);
106169
if (!buffer)
107170
{
108171
std::cerr << "Failed to read WASM file" << std::endl;

samples/wasm/CMakeLists.txt

Lines changed: 61 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,53 @@
11
cmake_minimum_required(VERSION 3.10)
22

3+
if(WIN32)
4+
if(DEFINED ENV{USERPROFILE} AND NOT "$ENV{USERPROFILE}" STREQUAL "")
5+
set(_cargo_bin_root "$ENV{USERPROFILE}")
6+
else()
7+
set(_cargo_bin_root "$ENV{HOME}")
8+
endif()
9+
if(NOT "${_cargo_bin_root}" STREQUAL "")
10+
set(_cargo_bin "${_cargo_bin_root}\\.cargo\\bin")
11+
else()
12+
set(_cargo_bin "")
13+
endif()
14+
if(DEFINED ENV{PATH})
15+
string(REPLACE ";" "\\;" _escaped_env_path "$ENV{PATH}")
16+
else()
17+
set(_escaped_env_path "")
18+
endif()
19+
if(NOT "${_cargo_bin}" STREQUAL "")
20+
if(NOT "${_escaped_env_path}" STREQUAL "")
21+
set(CARGO_BIN_ENV "PATH=${_cargo_bin}\\;${_escaped_env_path}")
22+
else()
23+
set(CARGO_BIN_ENV "PATH=${_cargo_bin}")
24+
endif()
25+
else()
26+
set(CARGO_BIN_ENV "PATH=${_escaped_env_path}")
27+
endif()
28+
else()
29+
set(_cargo_bin "$ENV{HOME}/.cargo/bin")
30+
if(DEFINED ENV{PATH})
31+
set(_escaped_env_path "$ENV{PATH}")
32+
else()
33+
set(_escaped_env_path "")
34+
endif()
35+
if(NOT "${_cargo_bin}" STREQUAL "")
36+
if(NOT "${_escaped_env_path}" STREQUAL "")
37+
set(CARGO_BIN_ENV "PATH=${_cargo_bin}:${_escaped_env_path}")
38+
else()
39+
set(CARGO_BIN_ENV "PATH=${_cargo_bin}")
40+
endif()
41+
else()
42+
set(CARGO_BIN_ENV "PATH=${_escaped_env_path}")
43+
endif()
44+
endif()
45+
346
function(wit2code witFile)
447
add_custom_command(
548
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${witFile}/${witFile}.c ${CMAKE_CURRENT_BINARY_DIR}/${witFile}/${witFile}.h ${CMAKE_CURRENT_BINARY_DIR}/${witFile}/${witFile}_component_type.o
649
# COMMAND wit-bindgen markdown ${CMAKE_CURRENT_SOURCE_DIR}/${witFile}.wit
7-
COMMAND ${CMAKE_COMMAND} -E env PATH=$ENV{HOME}/.cargo/bin:$ENV{PATH} wit-bindgen c --out-dir "${CMAKE_CURRENT_BINARY_DIR}/${witFile}" "${CMAKE_CURRENT_SOURCE_DIR}/${witFile}.wit"
50+
COMMAND ${CMAKE_COMMAND} -E env "${CARGO_BIN_ENV}" wit-bindgen c --out-dir "${CMAKE_CURRENT_BINARY_DIR}/${witFile}" "${CMAKE_CURRENT_SOURCE_DIR}/${witFile}.wit"
851
# COMMAND wit-bindgen rust --ownership owning --out-dir ${CMAKE_CURRENT_BINARY_DIR}/${witFile}/rust ${CMAKE_CURRENT_SOURCE_DIR}/${witFile}.wit
952
# COMMAND wit-bindgen teavm-java --out-dir ${CMAKE_CURRENT_BINARY_DIR}/${witFile}/java ${CMAKE_CURRENT_SOURCE_DIR}/${witFile}.wit
1053
# COMMAND wit-bindgen tiny-go --out-dir ${CMAKE_CURRENT_BINARY_DIR}/${witFile}/go ${CMAKE_CURRENT_SOURCE_DIR}/${witFile}.wit
@@ -50,11 +93,23 @@ target_link_libraries(sample
5093
${CMAKE_CURRENT_BINARY_DIR}/sample/sample_component_type.o
5194
)
5295

53-
add_custom_command(
54-
TARGET sample POST_BUILD
55-
COMMAND ${CMAKE_COMMAND} -E env PATH=$ENV{HOME}/.cargo/bin:$ENV{PATH} wasm-tools component new ${CMAKE_CURRENT_BINARY_DIR}/sample.wasm -o ${CMAKE_CURRENT_BINARY_DIR}/sample-component.wasm
56-
# COMMAND npx jco transpile ${CMAKE_CURRENT_BINARY_DIR}/test.component.wasm -o ${CMAKE_CURRENT_BINARY_DIR}/js --wasi-shim --map wasi-*=@bytecodealliance/preview2-shim/* --map print=../../../../src-components/test/logger.js
57-
)
96+
if (NOT DEFINED WASM_TOOLS_EXECUTABLE)
97+
if (WIN32)
98+
find_program(WASM_TOOLS_EXECUTABLE wasm-tools HINTS "${_cargo_bin}")
99+
else()
100+
find_program(WASM_TOOLS_EXECUTABLE wasm-tools HINTS "${_cargo_bin}")
101+
endif()
102+
endif()
103+
104+
if (WASM_TOOLS_EXECUTABLE)
105+
add_custom_command(
106+
TARGET sample POST_BUILD
107+
COMMAND ${WASM_TOOLS_EXECUTABLE} component new ${CMAKE_CURRENT_BINARY_DIR}/sample.wasm -o ${CMAKE_CURRENT_BINARY_DIR}/sample-component.wasm
108+
# COMMAND npx jco transpile ${CMAKE_CURRENT_BINARY_DIR}/test.component.wasm -o ${CMAKE_CURRENT_BINARY_DIR}/js --wasi-shim --map wasi-*=@bytecodealliance/preview2-shim/* --map print=../../../../src-components/test/logger.js
109+
)
110+
else()
111+
message(WARNING "wasm-tools not found; skipping component conversion. Install via 'cargo install wasm-tools' to produce sample-component.wasm.")
112+
endif()
58113
# set_property(SOURCE main.cpp APPEND PROPERTY OBJECT_DEPENDS ${HPCC_WASM_ROOT}/build/guest/cpp/wit/test.c)
59114

60115
# Install the target and export the target information

0 commit comments

Comments
 (0)