Skip to content

Commit 974b2e8

Browse files
committed
fix: ensure wit-bindge test suite compiles
Signed-off-by Gordon Smith <GordonJSmith@gmail.com>
1 parent 3934d24 commit 974b2e8

23 files changed

Lines changed: 1943 additions & 93 deletions

include/cmcpp/string.hpp

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -34,10 +34,10 @@ namespace cmcpp
3434
auto encoded = cx.convert(&cx.opts.memory[ptr], worst_case_size, src, src_byte_len, src_encoding, Encoding::Utf8);
3535
if (worst_case_size > encoded.second)
3636
{
37-
ptr = cx.opts.realloc(ptr, worst_case_size, 1, encoded.second);
37+
ptr = cx.opts.realloc(ptr, worst_case_size, 1, static_cast<uint32_t>(encoded.second));
3838
assert(ptr + encoded.second <= cx.opts.memory.size());
3939
}
40-
return std::make_pair(ptr, encoded.second);
40+
return std::make_pair(ptr, static_cast<uint32_t>(encoded.second));
4141
}
4242

4343
inline std::pair<uint32_t, uint32_t> store_utf16_to_utf8(LiftLowerContext &cx, const void *src, uint32_t src_code_units)
@@ -62,7 +62,7 @@ namespace cmcpp
6262
auto encoded = cx.convert(&cx.opts.memory[ptr], worst_case_size, src, src_code_units, Encoding::Utf8, Encoding::Utf16);
6363
if (encoded.second < worst_case_size)
6464
{
65-
ptr = cx.opts.realloc(ptr, worst_case_size, 2, encoded.second);
65+
ptr = cx.opts.realloc(ptr, worst_case_size, 2, static_cast<uint32_t>(encoded.second));
6666
assert(ptr == align_to(ptr, 2));
6767
assert(ptr + encoded.second <= cx.opts.memory.size());
6868
}
@@ -103,7 +103,7 @@ namespace cmcpp
103103
const size_t src_byte_length = src_code_units * ValTrait<T>::char_size;
104104

105105
assert(src_code_units <= MAX_STRING_BYTE_LENGTH);
106-
uint32_t ptr = cx.opts.realloc(0, 0, 2, src_byte_length);
106+
uint32_t ptr = cx.opts.realloc(0, 0, 2, static_cast<uint32_t>(src_byte_length));
107107
trap_if(cx, ptr != align_to(ptr, 2));
108108
trap_if(cx, ptr + src_code_units > cx.opts.memory.size());
109109
uint32_t dst_byte_length = 0;
@@ -118,9 +118,9 @@ namespace cmcpp
118118
else
119119
{
120120
// If it doesn't, convert it to a UTF-16 sequence
121-
uint32_t worst_case_size = 2 * src_code_units;
121+
uint32_t worst_case_size = static_cast<uint32_t>(2 * src_code_units);
122122
trap_if(cx, worst_case_size > MAX_STRING_BYTE_LENGTH, "Worst case size exceeds maximum string byte length");
123-
ptr = cx.opts.realloc(ptr, src_byte_length, 2, worst_case_size);
123+
ptr = cx.opts.realloc(ptr, static_cast<uint32_t>(src_byte_length), 2, worst_case_size);
124124
trap_if(cx, ptr != align_to(ptr, 2), "Pointer misaligned");
125125
trap_if(cx, ptr + worst_case_size > cx.opts.memory.size(), "Out of bounds access");
126126

@@ -147,7 +147,7 @@ namespace cmcpp
147147
uint32_t destPtr = ptr + (2 * dst_byte_length);
148148
uint32_t destLen = worst_case_size - (2 * dst_byte_length);
149149
void *srcPtr = (char *)src + dst_byte_length * ValTrait<T>::char_size;
150-
uint32_t srcLen = (src_code_units - dst_byte_length) * ValTrait<T>::char_size;
150+
uint32_t srcLen = static_cast<uint32_t>((src_code_units - dst_byte_length) * ValTrait<T>::char_size);
151151
auto encoded = cx.convert(&cx.opts.memory[destPtr], destLen, srcPtr, srcLen, src_encoding, Encoding::Utf16);
152152

153153
// Add special tag to indicate the string is a UTF-16 string ---
@@ -158,7 +158,7 @@ namespace cmcpp
158158
}
159159
if (dst_byte_length < src_code_units)
160160
{
161-
ptr = cx.opts.realloc(ptr, src_code_units, 2, dst_byte_length);
161+
ptr = cx.opts.realloc(ptr, static_cast<uint32_t>(src_code_units), 2, dst_byte_length);
162162
trap_if(cx, ptr != align_to(ptr, 2), "Pointer misaligned");
163163
trap_if(cx, ptr + dst_byte_length > cx.opts.memory.size(), "Out of bounds access");
164164
}
@@ -179,18 +179,18 @@ namespace cmcpp
179179
if (src_tagged_code_units & UTF16_TAG)
180180
{
181181
src_simple_encoding = Encoding::Utf16;
182-
src_code_units = src_tagged_code_units ^ UTF16_TAG;
182+
src_code_units = static_cast<uint32_t>(src_tagged_code_units ^ UTF16_TAG);
183183
}
184184
else
185185
{
186186
src_simple_encoding = Encoding::Latin1;
187-
src_code_units = src_tagged_code_units;
187+
src_code_units = static_cast<uint32_t>(src_tagged_code_units);
188188
}
189189
}
190190
else
191191
{
192192
src_simple_encoding = src_encoding;
193-
src_code_units = src_tagged_code_units;
193+
src_code_units = static_cast<uint32_t>(src_tagged_code_units);
194194
}
195195

196196
switch (cx.opts.string_encoding)
@@ -300,7 +300,7 @@ namespace cmcpp
300300
retVal.encoding = encoding;
301301
}
302302
retVal.resize(host_byte_length);
303-
auto decoded = cx.convert(retVal.data(), host_byte_length, (void *)&cx.opts.memory[ptr], byte_length, encoding, ValTrait<T>::encoding == Encoding::Latin1_Utf16 ? encoding : ValTrait<T>::encoding);
303+
auto decoded = cx.convert(retVal.data(), host_byte_length, (void *)&cx.opts.memory[ptr], static_cast<uint32_t>(byte_length), encoding, ValTrait<T>::encoding == Encoding::Latin1_Utf16 ? encoding : ValTrait<T>::encoding);
304304
if ((decoded.second / char_size) < host_byte_length)
305305
{
306306
retVal.resize(decoded.second / char_size);

samples/wamr/CMakeLists.txt

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,7 +136,14 @@ target_include_directories(wamr
136136
)
137137

138138
if (MSVC)
139-
target_compile_options(wamr PRIVATE /EHsc /permissive-)
139+
target_compile_options(wamr PRIVATE
140+
/EHsc
141+
/permissive-
142+
/wd4244 # conversion from 'type1' to 'type2', possible loss of data
143+
/wd4267 # conversion from 'size_t' to 'type', possible loss of data
144+
/wd4305 # truncation from 'type1' to 'type2'
145+
/wd4309 # truncation of constant value
146+
)
140147
else()
141148
target_compile_options(wamr PRIVATE -Wno-error=maybe-uninitialized -Wno-error=jump-misses-init)
142149
endif()

samples/wamr/generated/sample_wamr.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
// Generated WAMR bindings for package: example:sample
77
// These symbol arrays can be used with wasm_runtime_register_natives_raw()
8-
// NOTE: You must implement the functions declared in the imports namespace
8+
// NOTE: You must implement the functions declared in the host namespace
99
// (See sample.hpp for declarations, provide implementations in your host code)
1010

1111
using namespace cmcpp;

test/CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,16 @@ elseif(CMAKE_CXX_COMPILER_ID MATCHES "Clang")
1111
add_link_options(-fprofile-instr-generate)
1212
endif()
1313

14+
# Suppress narrowing conversion warnings on MSVC for WebAssembly 32-bit ABI
15+
if(MSVC)
16+
add_compile_options(
17+
/wd4244 # conversion from 'type1' to 'type2', possible loss of data
18+
/wd4267 # conversion from 'size_t' to 'type', possible loss of data
19+
/wd4305 # truncation from 'type1' to 'type2'
20+
/wd4309 # truncation of constant value
21+
)
22+
endif()
23+
1424
find_package(doctest CONFIG REQUIRED)
1525
find_package(ICU REQUIRED COMPONENTS uc dt in io)
1626

test/generate_test_stubs.py

Lines changed: 20 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@
1111
from typing import List, Tuple
1212
import argparse
1313

14+
# Force UTF-8 encoding for stdout on Windows
15+
if sys.platform == 'win32':
16+
import io
17+
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8', errors='replace')
18+
sys.stderr = io.TextIOWrapper(sys.stderr.buffer, encoding='utf-8', errors='replace')
19+
1420
# ANSI color codes
1521
class Colors:
1622
RED = '\033[0;31m'
@@ -31,6 +37,16 @@ def color(cls, text: str, color_code: str) -> str:
3137
return f"{color_code}{text}{cls.NC}"
3238
return text
3339

40+
# Platform-specific symbols
41+
if sys.platform == 'win32':
42+
CHECKMARK = "OK"
43+
CROSSMARK = "FAIL"
44+
SKIPMARK = "SKIP"
45+
else:
46+
CHECKMARK = "✓"
47+
CROSSMARK = "✗"
48+
SKIPMARK = "⊘"
49+
3450
def find_wit_files(directory: Path) -> List[Path]:
3551
"""Recursively find all .wit files in a directory"""
3652
return sorted(directory.rglob("*.wit"))
@@ -174,15 +190,15 @@ def main():
174190
success, message = generate_stub(wit_file, output_prefix, codegen_tool, args.verbose)
175191

176192
if success:
177-
print(Colors.color("✓", Colors.GREEN))
193+
print(Colors.color(CHECKMARK, Colors.GREEN))
178194
if args.verbose and message:
179195
print(f" {message}")
180196
success_count += 1
181197
elif "No output files generated" in message:
182-
print(Colors.color("⊘ (no output)", Colors.YELLOW))
198+
print(Colors.color(f"{SKIPMARK} (no output)", Colors.YELLOW))
183199
skipped_count += 1
184200
else:
185-
print(Colors.color("✗", Colors.RED))
201+
print(Colors.color(CROSSMARK, Colors.RED))
186202
if args.verbose:
187203
print(f" Error: {message}")
188204
failure_count += 1
@@ -203,7 +219,7 @@ def main():
203219
if args.verbose:
204220
print(f" Error: {error}")
205221

206-
print(f"\n{Colors.color('✓', Colors.GREEN)} Stub generation complete!")
222+
print(f"\n{Colors.color(CHECKMARK, Colors.GREEN)} Stub generation complete!")
207223
print(f"Output directory: {output_dir}")
208224

209225
# Exit with 0 if we have successful generations, even with some failures

test/host-util.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ class Heap
3232
}
3333

3434
uint32_t ret = align_to(last_alloc, alignment);
35-
last_alloc = ret + new_size;
35+
last_alloc = static_cast<uint32_t>(ret + new_size);
3636
if (last_alloc > memory.size())
3737
{
3838
trap("oom");

test/validate_all_wit_bindgen.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,23 @@ def generate_stub(wit_path, stub_name):
6767
except Exception as e:
6868
return False, str(e)
6969

70+
def check_if_empty_stub(stub_name):
71+
"""Check if generated stub only contains empty namespaces"""
72+
stub_file = GENERATED_DIR / f"{stub_name}.hpp"
73+
74+
try:
75+
with open(stub_file, 'r') as f:
76+
content = f.read()
77+
# Check for the marker comment that indicates empty interfaces
78+
if "This WIT file contains no concrete interface definitions" in content:
79+
# Also verify it only has empty namespaces
80+
if "namespace host {}" in content and "namespace guest {}" in content:
81+
return True
82+
except Exception:
83+
pass
84+
85+
return False
86+
7087
def compile_stub(stub_name):
7188
"""Compile a generated stub"""
7289
stub_file = GENERATED_DIR / f"{stub_name}.hpp"
@@ -107,6 +124,10 @@ def process_wit_file(wit_path):
107124
gen_ok, gen_error = generate_stub(wit_path, stub_name)
108125

109126
if gen_ok:
127+
# Check if this generated an empty stub (references external packages only)
128+
if check_if_empty_stub(stub_name):
129+
return rel_path, 'empty_stub', 'Generated empty stub (references external packages only)'
130+
110131
# Compile stub
111132
compile_ok, compile_error = compile_stub(stub_name)
112133

@@ -142,11 +163,13 @@ def main():
142163
'gen_success': 0,
143164
'gen_failed': 0,
144165
'compile_success': 0,
145-
'compile_failed': 0
166+
'compile_failed': 0,
167+
'empty_stubs': 0
146168
}
147169

148170
failed_generation = []
149171
failed_compilation = []
172+
empty_stub_files = []
150173

151174
# Process files in parallel
152175
with ThreadPoolExecutor(max_workers=num_workers) as executor:
@@ -163,6 +186,11 @@ def main():
163186
stats['gen_success'] += 1
164187
stats['compile_success'] += 1
165188
status = f"{GREEN}{RESET}"
189+
elif result == 'empty_stub':
190+
stats['gen_success'] += 1
191+
stats['empty_stubs'] += 1
192+
status = f"{YELLOW}{RESET}"
193+
empty_stub_files.append((rel_path, error))
166194
elif result == 'compile_failed':
167195
stats['gen_success'] += 1
168196
stats['compile_failed'] += 1
@@ -191,9 +219,18 @@ def main():
191219
print(f" Total WIT files: {stats['total']}")
192220
print(f" Generation successful: {stats['gen_success']} ({stats['gen_success']/stats['total']*100:.1f}%)")
193221
print(f" Generation failed: {stats['gen_failed']}")
222+
print(f" Empty stubs (no types): {stats['empty_stubs']}")
194223
print(f" Compilation successful: {stats['compile_success']} ({stats['compile_success']/stats['total']*100:.1f}%)")
195224
print(f" Compilation failed: {stats['compile_failed']}")
196225

226+
if empty_stub_files:
227+
print(f"\n{YELLOW}Empty stubs ({len(empty_stub_files)} files):{RESET}")
228+
print(f"These files only reference external packages and contain no concrete definitions:")
229+
for rel_path, reason in empty_stub_files[:10]:
230+
print(f" - {rel_path}")
231+
if len(empty_stub_files) > 10:
232+
print(f" ... and {len(empty_stub_files) - 10} more")
233+
197234
if failed_generation:
198235
print(f"\n{YELLOW}Failed generation ({len(failed_generation)} files):{RESET}")
199236
for rel_path, error in failed_generation[:10]: # Show first 10

tools/wit-codegen/CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ add_executable(wit-codegen
4040
wit_parser.cpp
4141
code_generator.cpp
4242
type_mapper.cpp
43+
package_registry.cpp
44+
dependency_resolver.cpp
4345
${ANTLR_GENERATED_SOURCES}
4446
)
4547

0 commit comments

Comments
 (0)