Do some notes during the investigation of issues.
In CI tests, only MSVC build failed on two testcases. See this issue.
In the testcase, a module have a table of 2 external reference, but when setting or getting them, runtime reports that table access is out of bound.
(module $m
(table $t (export "table") 2 externref)
(func (export "get") (param $i i32) (result externref)
(table.get $t (local.get $i)))
(func (export "set") (param $i i32) (param $x externref)
(table.set $t (local.get $i) (local.get $x))))
(register "exporter" $m)
(assert_return (invoke $m "get" (i32.const 0)) (ref.null extern))
(assert_return (invoke $m "get" (i32.const 1)) (ref.null extern))
Previously, MSVC build have some quirks:
- not initialize some value to zero.
Start to debug it. Here is the debug config. PATH is required for the exe to find the dll. Because we use MSVC as the compiler, we use cppvsdbg to debug. The key is --gtest_filter=*TestSuites/16
.
{
"name": "spectest",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/build/test/aot/wasmedgeAOTCoreTests.exe",
"args": ["--gtest_filter=*TestSuites/16"],
"symbolSearchPath": "${workspaceFolder}/build/test/aot",
"logging": {
"moduleLoad": false,
"trace": true
},
"cwd": "${workspaceFolder}/build/test/aot",
"environment": [{"name": "PATH", "value": "%PATH%;${workspaceFolder}/build/lib/api"}],
"visualizerFile": "${workspaceFolder}/my.natvis",
"showDisplayString": true
}
The test log said it is a out of bounds table access
error, we search the code, and search TableOutOfBounds
again, and find WasmEdge\include\runtime\instance\table.h
. set breakpoint at those places where the error message is printed.
Then, we see that, at the inst, the table index is 0, correct. But the offset is 0xf1dd3560? The call stack showed elem.66.dll
, which means the code is JIT compiled to native code. Because it is JITed. Next we should print the LLVM IR to debug.
first use wasm2wat to build\test\spec\testSuites\core\elem\elem.66.wasm. Search for .ll"
, there are two places where the IR is printed. No need to recompile, just set the breakpoint at the if branch checking debug enabled, and execute in debug console: LLModule.printModuleToFile("wasm-opt.ll")
.
In the test, the program visits each line of the json file:
{"type": "register", "line": 661, "name": "$m", "as": "exporter"},
{"type": "assert_return", "line": 663, "action": {"type": "invoke", "module": "$m", "field": "get", "args": [{"type": "i32", "value": "0"}]}, "expected": [{"type": "externref", "value": "null"}]},
At the second line, it invokes the function in module "$m", with a single argument i32 0.
(module
(type (;0;) (func (param i32) (result externref)))
(type (;1;) (func (param i32 externref)))
(func (;0;) (type 0) (param i32) (result externref)
local.get 0
table.get 0)
(func (;1;) (type 1) (param i32 externref)
local.get 0
local.get 1
table.set 0)
(table (;0;) 2 externref)
(export "table" (table 0))
(export "get" (func 0))
(export "set" (func 1)))
The function fetches the table 0 with offset from the argument. In the following LLVM IR, it corresponds to %8 = tail call i64 %7(i32 0, i32 %4) #4
. In this call inst, the %7
is table_get function provided by the runtime. However, during the process, the offset becomes a extremely large value. This time, it is 0xff1b1020.
; Function Attrs: strictfp
define protected dllexport void @t0(ptr noalias readonly %0, ptr noalias %1, ptr noalias %2, ptr noalias %3) #1 {
entry:
%4 = getelementptr inbounds i8, ptr %2, i64 0
%5 = load i32, ptr %4, align 4
%6 = tail call i64 %1(ptr %0, i32 %5) #4
%7 = getelementptr inbounds i8, ptr %3, i64 0
store i64 %6, ptr %7, align 4
ret void
}
; Function Attrs: strictfp
define protected dllexport void @t1(ptr noalias readonly %0, ptr noalias %1, ptr noalias %2, ptr noalias %3) #1 {
entry:
%4 = getelementptr inbounds i8, ptr %2, i64 0
%5 = load i32, ptr %4, align 4
%6 = getelementptr inbounds i8, ptr %2, i64 16
%7 = load i64, ptr %6, align 4
tail call void %1(ptr %0, i32 %5, i64 %7) #4
ret void
}
; Function Attrs: strictfp
define protected dllexport i64 @f0(ptr noalias readonly %0, i32 %1) #1 {
entry:
%2 = load %ExecCtx, ptr %0, align 8
%3 = alloca i32, align 4
store i32 %1, ptr %3, align 4
%4 = load i32, ptr %3, align 4
%5 = load ptr, ptr @intrinsics, align 8, !invariant.group !1
%6 = getelementptr inbounds [23 x ptr], ptr %5, i64 0, i64 9
%7 = load ptr, ptr %6, align 8
%8 = tail call i64 %7(i32 0, i32 %4) #4
br label %ret
ret: ; preds = %entry
ret i64 %8
}
; Function Attrs: strictfp
define protected dllexport void @f1(ptr noalias readonly %0, i32 %1, i64 %2) #1 {
entry:
%3 = load %ExecCtx, ptr %0, align 8
%4 = alloca i32, align 4
store i32 %1, ptr %4, align 4
%5 = alloca i64, align 8
store i64 %2, ptr %5, align 4
%6 = load i32, ptr %4, align 4
%7 = load i64, ptr %5, align 4
%8 = load ptr, ptr @intrinsics, align 8, !invariant.group !1
%9 = getelementptr inbounds [23 x ptr], ptr %8, i64 0, i64 10
%10 = load ptr, ptr %9, align 8
%11 = tail call i64 %10(i32 0, i32 %6, i64 %7) #4
br label %ret
ret: ; preds = %entry
ret void
}
The following function is called. This is the proxy function in the intrinsics function pointers table.
template <typename RetT, typename... ArgsT>
struct Executor::ProxyHelper<Expect<RetT> (Executor::*)(Runtime::StackManager &,
ArgsT...) noexcept> {
template <Expect<RetT> (Executor::*Func)(Runtime::StackManager &,
ArgsT...) noexcept>
static auto proxy(ArgsT... Args)
#if !WASMEDGE_OS_WINDOWS
noexcept
#endif
{
Expect<RetT> Res = (This->*Func)(*CurrentStack, Args...);
if (unlikely(!Res)) {
Fault::emitFault(Res.error());
}
if constexpr (!std::is_void_v<RetT>) {
return *Res;
}
}
};
This code used C++ member function pointer in a template.
WasmEdge::RefVariant *__fastcall ___proxy__1_tableGet_Executor_2WasmEdge__QEAA_AV__expected_URefVariant_WasmEdge__VErrCode_2__cxx20__AEAVStackManager_Runtime_3_II_Z___ProxyHelper_P8Executor_1WasmEdge__EAA_AV__expected_URefVariant_WasmEdge__VErrCode_2__cxx20__AEAVStackManager_Runtime_2_II__E_Executor_1WasmEdge__SA_A_PII_Z(
WasmEdge::RefVariant *result,
unsigned int <Args_0>,
unsigned int <Args_1>)
{
__int64 *v3; // rdi
__int64 i; // rcx
WasmEdge::ErrCode *v5; // rax
__int64 v6; // rax
__int64 v8; // [rsp+0h] [rbp-78h] BYREF
__int64 v9; // [rsp+30h] [rbp-48h] BYREF
cxx20::expected<WasmEdge::RefVariant,WasmEdge::ErrCode> v10; // [rsp+38h] [rbp-40h] BYREF
char v11; // [rsp+54h] [rbp-24h] BYREF
char *v12; // [rsp+58h] [rbp-20h]
WasmEdge::Executor::Executor *v13; // [rsp+60h] [rbp-18h]
bool v14; // [rsp+68h] [rbp-10h]
v3 = &v9;
for ( i = 16i64; i; --i )
{
*(_DWORD *)v3 = -858993460;
v3 = (__int64 *)((char *)v3 + 4);
}
v13 = *(WasmEdge::Executor::Executor **)(*((_QWORD *)NtCurrentTeb()->Reserved1[11] + tls_index) + 344i64);
WasmEdge::Executor::Executor::tableGet(
v13,
&v10,
*(WasmEdge::Runtime::StackManager **)(*((_QWORD *)NtCurrentTeb()->Reserved1[11] + tls_index) + 336i64),
<Args_0>,
<Args_1>);
v14 = !cxx20::expected<WasmEdge::RefVariant,WasmEdge::ErrCode>::operator bool(&v10);
if ( WasmEdge::unlikely_19(v14) )
{
v12 = &v11;
v5 = cxx20::detail::expected_view_base<WasmEdge::RefVariant,WasmEdge::ErrCode>::error(&v10);
v6 = ((__int64 (__fastcall *)(char *, WasmEdge::ErrCode *))WasmEdge::ErrCode::ErrCode)(v12, v5);
((void (__fastcall *)(__int64))WasmEdge::Fault::emitFault)(v6);
}
result->Ptr = cxx20::expected<WasmEdge::RefVariant,WasmEdge::ErrCode>::operator*(&v10)->Ptr;
j__RTC_CheckStackVars(&v8, (_RTC_framedesc *)&unk_1435B7920);
return result;
}
Probably it is related to return value optimization or Copy Elision. C++ 17 enforces return value optimization. In MSVC, there is (Mandatory copy and move elision).
I'll keep this readme file up to date during the whole process of OSPP 2023.
There are two branches:
- OSPP (current branch) for notes and logs.
- am009/msvc_support for development
Guideline: While solving compiler errors, split modifications into many small commits. When trying to organize modifications, use git rebase interactive to move similar commits together, and optionally squash them.
2023-05-16 OSPP 2023 Challenge
2023-05-24 gtest,
OSPP feat: Enabling WasmEdge Compilation with MSVC Toolchain
- 2023-07-05 Start working on rewriting SIMD related parts. (MSVC: unroll SIMD to avoid gnu vector.)
- 2023-08-09 Finally leave the dilemma of SIMD.
- 2023-08-10 Find a bug in int128.h
(\w+\.size\(\))
=> static_cast<int>($1)
/\*\.(.+?) =\*/( ?)
=> /* $1 */
cmake automatically adds /EHsc and LLVM add /EHs-c-
-
Equivalent flag for
-Wall
-Wno-xxx
Reference: MSVC C++ Warning levels. Warning level 1 (severe), level 2 (significant), 3 (production quality), 4 (informational).
- For
-Wall
there is/Wall
. - For
-Wextra
, there seems no equivalent flag? - For
-Werror
, there is/WX
. However, MSVC/Wall
is too verbose, and should use/W4
. So I'll start with/W4
- For
-
Use
if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC")
orif(MSVC)
in cmake.Notice that, MSVC is also set using
clang-cl
. So Use . See this question
On x86_64 (especially MSVC), LLVM will generate SSE related instructions for accessing global variable, and many of these instructions requires alignment (16-bytes). The absence of alignment will trigger memory access error, and many AOT related test will fail.
AOTCoreTest TestSuites/69
failed (SIMD related), It reports memory out of bound access, but after checking, actually it's just general memory error, not necessarily out of bound access. (At lib\system\fault.cpp
vectoredExceptionHandler
windows part, it emits error according to the exception type, which is EXCEPTION_ACCESS_VIOLATION_
.) The JIT/AOT code error is hard to debug, the stack trace is not very useful. I tried to dump the generated IR by insert debug print code to precisely break at the test case. However, the IR turned out to be identical to the normal one.
Finally, I find that actually it is not about the code; The address being accessed is totally fine. the fault instruction uses movdqa
, and I realized that this instruction requires memory alignment. the address accessed is not 16-bytes aligned!!
In two test cases for f32.abs
,
- Input 2139156962 (hex 0x7f80f1e2, NAN) (), expected output is the same
- Input 4286640610 (hex 0xff80f1e2, -NAN) expected output is 2139156962 (hex 0x7f80f1e2, NAN), MSVC result 2143351266 (hex 0x7fc0f1e2 NAN). According to IEEE 754 fp, the highest bit of fraction
is set by std::fabs
.
This is confirmed by the following code:
#include<array>
#include<iostream>
#include<cmath>
int main() {
// 10000000000000ULL
uint32_t before = 0x7f80f1e2;
float before_f = reinterpret_cast<float&>(before);
std::cout << "before: " << before << ", (" << before_f << std::endl;
float after_f = std::fabs(before_f);
uint32_t after = reinterpret_cast<uint32_t&>(after_f);;
std::cout << "after: " << after << ", (" << after_f << std::endl;
return 0;
}
/* MSVC
before: 2139156962, (nan
after: 2143351266, (nan
*/
/* g++
before: 2139156962, (nan
after: 2139156962, (nan
*/
the failure of WasiTest.PollOneoffSocketV1
is caused by the timeout value is not big enough? I think.
Because of the uninitialized flags(include\host\wasi\inode.h
INode
__wasi_fdflags_t
), In MSVC, the non-block flag is not set properly and cause the failure of WasiTest.PollOneoffSocketV1.
Think this code:
int limit = std::numeric_limits<int>::max();
limit = (int) ((float) limit)
2147483647
-> 2.14748365e+09
-> -2147483648
Actually float is more imprecise around the edge of limit, so if the cast makes the number across the edge, it will overflow if casted back.
So if the float is at the limit (== 2.14748365e+09), directly use the limit.
At test\spec\spectest.cpp:468
(SpecTest::run
) set conditional breakpoint: _strcmpi(UnitName._Mydata, "float_misc") == 0
2023-08-10 test\api\APIUnitTest.cpp
a parenthesized type followed by an initializer list is a non-standard explicit type conversion syntax
https://stackoverflow.com/questions/33270731/error-c4576-in-vs2015-enterprise
Just remove the parentheses?
Because std::swap
is not marked as constexpr before c++20.
In MSVC, use __restrict
The restrict keyword can be considered an extension to the strict aliasing rule. It allows the programmer to declare that pointers which share the same type (or were otherwise validly created) do not alias eachother.
E:\OSPP\WasmEdge\lib\host\wasi\wasifunc.cpp(368): error C2734: '__restrict__': 'const' object must be initialized if not 'extern'
E:\OSPP\WasmEdge\lib\host\wasi\wasifunc.cpp(368): error C3531: '__restrict__': a symbol whose type contains 'auto' must have an initializer
E:\OSPP\WasmEdge\lib\host\wasi\wasifunc.cpp(368): error C2146: syntax error: missing ';' before identifier 'Argc'
E:\OSPP\WasmEdge\include\experimental/span.hpp(250): error C2872: 'byte': ambiguous symbol
C:\Program Files (x86)\Windows Kits\10\include\10.0.19041.0\shared\rpcndr.h(191): note: could be 'unsigned char byte'
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.34.31933\include\cstddef(28): note: or 'std::byte'
E:\OSPP\WasmEdge\include\host/wasi/environ.h(850): note: see reference to function template instantiation 'auto cxx20::as_writable_bytes<uint8_t,18446744073709551615>(cxx20::span<uint8_t,18446744073709551615>) noexcept' being compiled
E:\OSPP\WasmEdge\include\experimental/span.hpp(229): warning C4623: 'cxx20::span<const uint32_t,1>': default constructor was implicitly defined as deleted
E:\OSPP\WasmEdge\include\host/wasi/environ.h(854): note: see reference to class template instantiation 'cxx20::span<const uint32_t,1>' being compiled
I found another important issue that, MSVC does not support attribute [[gnu::vector_size(16)]]
, and there seems no direct replacement. I found this OpenMP SIMD Extension which is very different from the extension.
- For example, this code, MSVC first report a warning that the attribute
[[gnu::vector_size(16)]]
is unknown. Probablyint32x8_t
directly becomesint32_t
- the arithmetic of these vector types seems to be used a lot (
EV1 * EV2
in the above code, in the following code, and many more), which will do the arithmetic for each element in the array according to gcc vector extension. If MSVC equivalent cannot be found, probably we have to rewrite all these operations for MSVC? We can either rewrite these using loop and hope for the compiler to optimize it to use SIMD instructions, or implement a class (or structure) that override these operations support these operations? I don't know...
Background: Because MSVC does not support gnu::vector_size
or equivalent, we need to implement unrolled version of SIMD instructions. Many implementations are in *.ipp
files, and we can create MSVC version of these ipp files, use #ifdef
to include them.
According to the specification, rewrite each part of the instructions.
The first decision is to make these vector type using std::array. e.g., using int8x16_t = std::array<int8_t, 16>;
. The reason why not choose plain array type, is related to the implementation of ValVariant
. Using plain array type will cause some wired errors.
instruction | specification and reference |
---|---|
q15mulr_sat_s | q15mulr_sat_s |
replace_lane | replace_lane |
i8x16.popcnt | i8x16.popcnt and this answer |
The WasmEdge::Executor::detail::vectorSelect
also can not be used, because the ternary operator:
In C++, the ternary operator ?: is available. a?b:c, where b and c are vectors of the same type and a is an integer vector with the same number of elements of the same size as b and c, computes all three arguments and creates a vector {a[0]?b[0]:c[0], a[1]?b[1]:c[1], …}. (from https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html )
using vscode's replace to replace the definition of some type with gnu::vector_size
into std::array
:
using ([^\s]+) \[\[gnu::vector_size\(([0-9]+)\)\]\] = ([^\s;]+);
->using $1 = SIMDArray<$3, $2>
using ([^\s]+) \[\[gnu::vector_size\(([0-9]+)\)\]\] = ([^\s;]+);
->using $1 = std::array<$3, ($2 / sizeof($3))>;
std::array<([a-zA-Z0-9_]+), \(([0-9]+) / sizeof\(([a-zA-Z0-9_]+)\)\)>
->SIMDArray<$1, $2>
using ([^\s]+) \[\[gnu::vector_size\(([0-9]+)\)\]\] = ([^\s;]+);
->constexpr int32_t Len = $2 / sizeof($3);\n using $1 = std::array<$3, Len>;
There are a few places where we assume __x86_64__
is not defined under MSVC. (still defined when using clang-cl) (In MSVC, it seems to be _WIN64
or _M_X64
?).
lib/aot/compiler.cpp
. It will enable some llvm x86_64 intrinsics (likeLLVM::Core::X86SSE41RoundPs
) if__x86_64__
is defined.include\common\int128.h
so that the class version instead of__int128
version will be used. This might actually be a good thing because these code simulates int128 behavior using a class and MSVC does not have the int128 type.- P.S., Probably we should use
__SIZEOF_INT128__
to check for the existence of__int128
here?
- P.S., Probably we should use
Besides, clang-cl will also define _MSC_VER
unless a -fmsc-version=0
flag is provided.
array designator initializer is supported in clang-cl but not in MSVC
We can use the syntax of aggregate initialization by commenting out the member initializer, or write constructor for each union member.
In include\api\wasmedge\wasmedge.h
there is a WASMEDGE_CAPI_EXPORT that does basically the same thing. However, the macro WASMEDGE_COMPILE_LIBRARY
is only defined in the api directory (in lib\api\CMakeLists.txt:5
).
There is a gcc wiki talking about this. But the macro definition is too complex. According to this tutorial, __attribute__ ((dllimport))
seems not necessary. Here is a place where similar macro ATTRIBUTE_INTERFACE
like the following are used.
#ifdef _MSC_VER
#define WASMEDGE_EXPORT __declspec(dllexport)
#else
#define WASMEDGE_EXPORT [[gnu::visibility("default")]]
#endif
Somehow, the 32bit related logic in include\common\int128.h
is compiled, probably because the defined(__x86_64__)
is false. In MSVC, it seems to be _WIN64
or _M_X64
.
There seems no __int128 equivalent in MSVC
_MSC_VER is also defined by MSVC clang and
some unused code:
friend constexpr uint128_t operator*(uint128_t LHS, long long RHS) noexcept {
return LHS * uint128_t(RHS);
}
friend constexpr uint128_t operator*(long long LHS, uint128_t RHS) noexcept {
return uint128_t(LHS) * RHS;
}
The replacement seems to be __forceinline
You can't force the compiler to inline a particular function, even with the __forceinline keyword. When you compile with /clr, the compiler won't inline a function if there are security attributes applied to the function.
https://stackoverflow.com/questions/19191211/constructor-initialization-of-a-named-union-member
gtest have -WX
(regard all warning as error) in their compiler flags (in build\_deps\gtest-src\googletest\cmake\internal_utils.cmake:75
), but there are still many warnings (which become errors).
Current solution: supress many warnings in WasmEdge\test\CMakeLists.txt
.
In include/common/int128.h
clz()
, an intrinsic is used.
change according to thirdparty\blake3\blake3_impl.h
__assume(0)
can indicate unreachable code path
visual studio - likely/unlikely equivalent for MSVC - Stack Overflow
Temporarily use the solution here: https://blog.csdn.net/celestialwy/article/details/1352891
https://stackoverflow.com/a/42136453
https://github.com/getsentry/symsynd/blob/master/demangle/llvm/Support/Compiler.h
-
How to set MSVC output language to English?
Install and uninstall related language pack in visual studio installer.
According to here, Set environment variable
VSLANG=1033
-
How to debug cmake: use trace related flags
- Challenge1: Use Clang on Windows to build and run tests
- Challenge2: Try using MSVC to build.
To use MSVC to build, I installed MSVC 14.34.31933, and removed $Env:CC = "clang-cl"
and $Env:CXX = "clang-cl"
in the build script, and add -vcvars_ver=14.34.31933
.
# Remove-Item -LiteralPath "build" -Force -Recurse
$vsPath = (&"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath)
Import-Module (Join-Path $vsPath "Common7\Tools\Microsoft.VisualStudio.DevShell.dll")
Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation -DevCmdArguments "-arch=x64 -host_arch=x64 -winsdk=10.0.19041.0 -vcvars_ver=14.34.31933"
$llvm_dir = "C:\\Users\\warren\\my_programs\\LLVM-13.0.1-win64\\lib\\cmake\\llvm"
# $Env:CC = "cl.exe"
# $Env:CXX = "cl"
cmake -Bbuild -GNinja -DCMAKE_SYSTEM_VERSION="10.0.19041.0" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL "-DLLVM_DIR=$llvm_dir" -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_BUILD_PACKAGE="ZIP" .
cmake --build build
the first error encountered is:
cl : Command line error D8021 : invalid numeric argument '/Wextra'
TODO:
- When the compiler is MSVC, not add unsupported flags to
WASMEDGE_CFLAGS
, and find equivalent flags instead. - try to find equivalent code in MSVC for the
int128.h
issue
CMake is already installed on my computer.
- Install latest cmake and select the option that add cmake to path.
- Download the LLVM fork from https://github.com/WasmEdge/llvm-windows . Do not use llvm official release and do not add its
bin
to path. - Open
LLVM-13.0.1-win64\lib\cmake\llvm\LLVMExports.cmake
and search fordiaguids
, and change fromEnterprise
toCommunity
. - Use Visual Studio Installer to install Windows SDK and MSVC. Change Win 11 SDK to Win 10 SDK 10.0.19041.0. Select Clang 15 and use this as compiler!!
vswhere
seems to be already included in Visual Studio Installer. Change its occurrence to absolute path.
Clone the code and check out to 0.12.0
. Follow the instructions: https://wasmedge.org/book/en/contribute/build_from_src/windows.html but add some more cmake flags.
Build script below:
$vsPath = (&"C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath)
Import-Module (Join-Path $vsPath "Common7\Tools\Microsoft.VisualStudio.DevShell.dll")
Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation -DevCmdArguments "-arch=x64 -host_arch=x64 -winsdk=10.0.19041.0 -vcvars_ver=14.33.31629"
$llvm_dir = "C:\\Users\\warren\\my_programs\\LLVM-13.0.1-win64\\lib\\cmake\\llvm"
$Env:CC = "clang-cl"
$Env:CXX = "clang-cl"
cmake -Bbuild -GNinja -DCMAKE_SYSTEM_VERSION="10.0.19041.0" -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL "-DLLVM_DIR=$llvm_dir" -DWASMEDGE_BUILD_TESTS=ON -DWASMEDGE_BUILD_PACKAGE="ZIP" .
if ($?) {
cmake --build build
}
if ($?) {
$Env:PATH += ";$pwd\\build\\lib\\api"
cd build
ctest --output-on-failure
cd ..
}
the output saved using 2>&1 > out.txt
are uploaded as clang-build.txt
.
installing LLVM
during decompressing the llvm zip file, I notice that clang-cl.exe
clang++.exe
are actually symbolic links. If I use explorer to decompress the file, the symbolic links seems broken. I started 7zip file manager with administrator privilege to decompress it, and the result seems to replace the symlink with another copy of the target.
Follow https://wasmedge.org/book/en/contribute/build_from_src/windows.html#run-tests and all test passed.
tldr: Do not add the downloaded clang 13 to compile (do not add it to PATH), use clang 15 from Visual Studio Installer instead!!! (it will be automatically added to path when you enter dev shell.)
A few days ago, I can successfully compile, but when I come back to this today, this new error occurred. To debug cmake output, I added --debug-output
to cmake flags. I found a line in CMakeError.log.
In file included from C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\filesystem:9:
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\yvals_core.h(807,1): error: static_assert failed "Error in C++ Standard Library usage."
_EMIT_STL_ERROR(STL1000, "Unexpected compiler version, expected Clang 15.0.0 or newer.");
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.35.32215\include\yvals_core.h(462,5): note: expanded from macro '_EMIT_STL_ERROR'
static_assert(false, "Error in C++ Standard Library usage.")
^ ~~~~~
1 error generated.
ninja: build stopped: subcommand failed.
filesystem
header is actually found. I need to downgrade MSVC version. But uninstall latest version seems to introduce more problem, so keep the newer version and try to specify MSVC version used. Downgrade to MSVC v142 (2019) will trigger another error, so I tried several previous version of MSVC v143.
According to Get-Help Enter-VsDevShell
and VsDevCmd.bat /help
, add -vcvars_ver=14.29.30133
. Open C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC
to find out MSVC versions. Finally 14.33.31629
can work.
Enter-VsDevShell -VsInstallPath $vsPath -SkipAutomaticLocation -DevCmdArguments "-arch=x64 -host_arch=x64 -winsdk=10.0.19041.0 -vcvars_ver=14.33.31629"
However, Some tests failed.
The following tests FAILED:
8 - wasmedgeExecutorCoreTests (Failed)
11 - wasmedgeAPIVMCoreTests (Failed)
12 - wasmedgeAPIStepsCoreTests (Failed)
Errors while running CTest
MSVC Version | CMake | Build? | Test? | Errors |
---|---|---|---|---|
14.31.31103 | √ | × | - | undefined symbol: __std_init_once_link_alternate_names_and_abort |
14.32.31326 | √ | √ | × | ExecutorCoreTests APIVMCoreTests APIStepsCoreTests failed |
14.33.31629 | √ | √ | × | ExecutorCoreTests APIVMCoreTests APIStepsCoreTests failed |
14.34.31933 | × | - | - | Cannot Compile simple program using std::filesystem |
14.35.32215(latest) | × | - | - | Cannot Compile simple program using std::filesystem |
After A few days' trying and error, I finally find out that, I should't use the downloaded clang 13 to compile, use clang 15 from Visual Studio Installer instead!!!
WasmEdge\include\common/enum_errcode.hpp(79): error C7555: use of designated initializers requires at least '/std:c++20'
2023-05-24
- add
/std:c++17
toWASMEDGE_CFLAGS
- add
target_compile_features(${TARGET_NAME} PRIVATE cxx_std_17)
according to here set(CMAKE_CXX_STANDARD 17)
or-DCMAKE_CXX_STANDARD=17
TODO
2023-05-13 When I check out to latest tag: 0.12.1
, I got this error.
- The MSVC runtime library for LLVM should be the same with WasmEdge.
- There is an hard-coded library path for
diaguids.lib
in LLVM's cmake file. To solve these two issue without upgrading llvm version, it seems that forking llvm and recompile is the only way.
Previously my Visual Studio version is 2019. Upgrading to 2022 solves the issue.
According to here
it could not find this new function: __std_init_once_link_alternate_names_and_abort. This function is from STL's import library: msvcprt.lib and was only added in the VS 2022 version: 17.2.5.
ninja: error: 'C:/Program Files/Microsoft Visual Studio/2022/Enterprise/DIA SDK/lib/amd64/diaguids.lib', needed by 'test/aot/wasmedgeAOTCoreTests.exe', missing and no known rule to make it
Found a related issue: WasmEdge#1290
Edit C:\Users\warren\my_programs\LLVM-13.0.1-win64\lib\cmake\llvm\LLVMExports.cmake
and search for diaguids
, and change from Enterprise
to Community
.
tldr: this error disappeared after my environment changed, but if it exist, you can add the flags.
There is an error said: llvm-mt: error: no libxml2
. This issue,
Changing cmake version doesn't seems to work.
I decided to first upgrade my cmake (from 3.21.1) to latest(3.26.3).
Finally I think I have to add the following to cmake flags:
-DCMAKE_EXE_LINKER_FLAGS="/manifest:no" -DCMAKE_MODULE_LINKER_FLAGS="/manifest:no" -DCMAKE_SHARED_LINKER_FLAGS="/manifest:no"