Skip to content

Commit 6920b9c

Browse files
Static crt multithreaded (#179)
* Link AOT output against static CRT (/MT[d]) everywhere The generated exe/dll previously linked the dynamic CRT (ucrt[d] + msvcrt[d]) while the prebuilt LLVM/MLIR libs, the TypeScript runtime libs and gc.lib all use the static CRT (/MT[d]). Mixing the two gives the generated program a separate heap and stdout buffer from those libs, crashing at startup/teardown (0xC0000005), notably for -emit=dll/-shared and import tests. Switch the Windows AOT link to the static CRT import names (libucrt[d] + libcmt[d] + libvcruntime[d]) to match, and drop the msvcrt[d] DLL-resolution branch that is no longer needed once the GC/runtime libs are linked statically. NOTE: requires the 3rdParty gc and LLVM packages to be the /MT builds. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> * Update GC version to 8.2.12 in build scripts and download links * Isolate Windows shared tests in a per-test working directory The Windows shared-test bat wrote fixed-name artifacts (<stem>.obj, <stem>.dll, <stem>.lib) directly in the shared test/tester cwd, while the imported-module stem is not unique across test variants - e.g. decl_class.ts feeds the -shared, -compile-time and -jit variants, and export_vars2.ts feeds two variants. Under `ctest -j` these run concurrently and stomp/delete each other's artifacts, causing random failures (e.g. test-compile-shared-decl-emit-class, test-compile-shared-export-import-vars-2). Port the per-test WORKDIR isolation the Linux branch already uses: create a unique <tempname>_wd dir, cd into it, build/link/run there (the shared lib keeps its real <stem> name needed for import resolution but can no longer collide), write .txt/.err to the parent dir the runner reads from, then remove the dir. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
1 parent 04f7ea8 commit 6920b9c

9 files changed

Lines changed: 39 additions & 25 deletions

prepare_3rdParty.bat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,11 @@ IF EXIST ".\3rdParty\gc\x64\%BUILD%\lib\gc.lib" (
2929
) ELSE (
3030
cd %p%
3131
echo "Downloading BDWGC"
32-
curl -o gc-%GC_VER%.tar.gz https://github.com/bdwgc/bdwgc/releases/download/v%GC_VER%/gc-%GC_VER%.tar.gz
32+
curl -o gc-%GC_VER%.tar.gz -L https://github.com/bdwgc/bdwgc/releases/download/v%GC_VER%/gc-%GC_VER%.tar.gz
3333
echo "Opening TAR.GZ BDWGC"
3434
tar -xvzf gc-%GC_VER%.tar.gz -C ./3rdParty/
3535
echo "Downloading Libatomic_ops"
36-
curl -o libatomic_ops-%LIBATOMIC_OPS_VER%.tar.gz https://github.com/bdwgc/libatomic_ops/releases/download/v%LIBATOMIC_OPS_VER%/libatomic_ops-%LIBATOMIC_OPS_VER%.tar.gz
36+
curl -o libatomic_ops-%LIBATOMIC_OPS_VER%.tar.gz -L https://github.com/bdwgc/libatomic_ops/releases/download/v%LIBATOMIC_OPS_VER%/libatomic_ops-%LIBATOMIC_OPS_VER%.tar.gz
3737
echo "Opening TAR.GZ Libatomic_ops"
3838
tar -xvzf libatomic_ops-%LIBATOMIC_OPS_VER%.tar.gz -C ./3rdParty/
3939
echo "Copy to gc-%GC_VER%/libatomic_ops"

scripts/build_gc_debug.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
mkdir -p __build/gc/ninja/debug
33
mkdir -p 3rdParty/gc/debug
44
cd __build/gc/ninja/debug
5-
cmake ../../../../3rdParty/gc-8.2.8 -G "Ninja" -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF -Wno-dev -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=../../../../3rdParty/gc/debug -Denable_threads=ON -Denable_cplusplus=OFF
5+
cmake ../../../../3rdParty/gc-8.2.12 -G "Ninja" -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF -Wno-dev -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=../../../../3rdParty/gc/debug -Denable_threads=ON -Denable_cplusplus=OFF
66
cmake --build . --config Debug -j 16
77
cmake --install . --config Debug

scripts/build_gc_debug_ninja.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pushd
22
mkdir __build\gc\ninja\debug
33
cd __build\gc\ninja\debug
4-
cmake ../../../../3rdParty/gc-8.2.8 -G "Ninja" -DCMAKE_BUILD_TYPE=Debug -Wno-dev -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=../../../../3rdParty/gc/debug -Denable_threads=ON -Denable_cplusplus=OFF
4+
cmake ../../../../3rdParty/gc-8.2.12 -G "Ninja" -DCMAKE_BUILD_TYPE=Debug -Wno-dev -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=../../../../3rdParty/gc/debug -Denable_threads=ON -Denable_cplusplus=OFF
55
cmake --build . --config Debug -j 8
66
cmake --install . --config Debug
77
popd

scripts/build_gc_debug_vs.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pushd
22
mkdir __build\gc\msbuild\x64\debug
33
cd __build\gc\msbuild\x64\debug
4-
cmake ../../../../../3rdParty/gc-8.2.8 -G "Visual Studio 18 2026" -A x64 %EXTRA_PARAM% -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF -Wno-dev -DCMAKE_INSTALL_PREFIX=../../../../../3rdParty/gc/x64/debug -Denable_threads=ON -Denable_cplusplus=OFF -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebug
4+
cmake ../../../../../3rdParty/gc-8.2.12 -G "Visual Studio 18 2026" -A x64 %EXTRA_PARAM% -DCMAKE_BUILD_TYPE=Debug -DBUILD_SHARED_LIBS=OFF -Wno-dev -DCMAKE_INSTALL_PREFIX=../../../../../3rdParty/gc/x64/debug -Denable_threads=ON -Denable_cplusplus=OFF -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDebug
55
cmake --build . --config Debug -j 20
66
cmake --install . --config Debug
77
popd

scripts/build_gc_release.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,6 @@
22
mkdir -p __build/gc/ninja/release
33
mkdir -p 3rdParty/gc/release
44
cd __build/gc/ninja/release
5-
cmake ../../../../3rdParty/gc-8.2.8 -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -Wno-dev -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=../../../../3rdParty/gc/release -Denable_threads=ON -Denable_cplusplus=OFF
5+
cmake ../../../../3rdParty/gc-8.2.12 -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -Wno-dev -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=../../../../3rdParty/gc/release -Denable_threads=ON -Denable_cplusplus=OFF
66
cmake --build . --config Release -j 16
77
cmake --install . --config Release

scripts/build_gc_release_ninja.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pushd
22
mkdir __build\gc\ninja\release
33
cd __build\gc\ninja\release
4-
cmake ../../../../3rdParty/gc-8.2.8 -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -Wno-dev -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=../../../../3rdParty/gc/release -Denable_threads=ON -Denable_cplusplus=OFF
4+
cmake ../../../../3rdParty/gc-8.2.12 -G "Ninja" -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -Wno-dev -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_INSTALL_PREFIX=../../../../3rdParty/gc/release -Denable_threads=ON -Denable_cplusplus=OFF
55
cmake --build . --config Release -j 8
66
cmake --install . --config Release
77
popd

scripts/build_gc_release_vs.bat

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
pushd
22
mkdir __build\gc\msbuild\x64\release
33
cd __build\gc\msbuild\x64\release
4-
cmake ../../../../../3rdParty/gc-8.2.8 -G "Visual Studio 18 2026" -A x64 %EXTRA_PARAM% -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -Wno-dev -DCMAKE_INSTALL_PREFIX=../../../../../3rdParty/gc/x64/release -Denable_threads=ON -Denable_cplusplus=OFF -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded
4+
cmake ../../../../../3rdParty/gc-8.2.12 -G "Visual Studio 18 2026" -A x64 %EXTRA_PARAM% -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF -Wno-dev -DCMAKE_INSTALL_PREFIX=../../../../../3rdParty/gc/x64/release -Denable_threads=ON -Denable_cplusplus=OFF -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreaded
55
cmake --build . --config Release -j 8
66
cmake --install . --config Release
77
popd

tsc/test/tester/test-runner.cpp

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,16 @@ void createSharedMultiBatchFile(std::string tempOutputFileNameNoExt, std::vector
428428
batFile << "set TSC_LIB_PATH=" << TEST_TSC_LIBPATH << std::endl;
429429
batFile << "set GC_LIB_PATH=" << TEST_GCPATH << std::endl;
430430

431+
// run everything inside a unique per-test working directory: the shared lib must keep its
432+
// real name (<stem>.dll) for `import './<stem>'` to resolve, but that name is not unique
433+
// across tests reusing the same source file (e.g. decl_class.ts feeds the compile/compile-time/jit
434+
// variants) - isolating the cwd avoids parallel collisions under `ctest -j`. The .txt/.err output
435+
// is written to the parent dir where the runner reads it from.
436+
batFile << "set WORKDIR=" << tempOutputFileNameNoExt << "_wd" << std::endl;
437+
batFile << "if exist %WORKDIR% rmdir /s /q %WORKDIR%" << std::endl;
438+
batFile << "mkdir %WORKDIR%" << std::endl;
439+
batFile << "cd %WORKDIR%" << std::endl;
440+
431441
auto first = true;
432442
std::stringstream shared_objs;
433443
std::stringstream shared_libs;
@@ -472,7 +482,7 @@ void createSharedMultiBatchFile(std::string tempOutputFileNameNoExt, std::vector
472482

473483
if (jitRun)
474484
{
475-
batFile << "%TSCEXEPATH%\\tsc.exe --emit=jit " << tsc_opt << " --shared-libs=%TSCEXEPATH%/TypeScriptRuntime.dll " << *files.begin() << " 1> %FILENAME%.txt 2> %FILENAME%.err"
485+
batFile << "%TSCEXEPATH%\\tsc.exe --emit=jit " << tsc_opt << " --shared-libs=%TSCEXEPATH%/TypeScriptRuntime.dll " << *files.begin() << " 1> ..\\%FILENAME%.txt 2> ..\\%FILENAME%.err"
476486
<< std::endl;
477487

478488
batFile << "del " << shared_libs.str() << std::endl;
@@ -494,7 +504,7 @@ void createSharedMultiBatchFile(std::string tempOutputFileNameNoExt, std::vector
494504

495505
batFile << "del " << exec_objs.str() << std::endl;
496506

497-
batFile << "call " RUN_CMD "%FILENAME%.exe 1> %FILENAME%.txt 2> %FILENAME%.err" << std::endl;
507+
batFile << "call " RUN_CMD "%FILENAME%.exe 1> ..\\%FILENAME%.txt 2> ..\\%FILENAME%.err" << std::endl;
498508

499509
batFile << "echo off" << std::endl;
500510
batFile << "del " << shared_libs.str() << std::endl;
@@ -506,6 +516,12 @@ void createSharedMultiBatchFile(std::string tempOutputFileNameNoExt, std::vector
506516
batFile << "echo on" << std::endl;
507517
}
508518

519+
// leave and remove the per-test working directory (with the shared lib, exe, objs, etc.)
520+
batFile << "echo off" << std::endl;
521+
batFile << "cd .." << std::endl;
522+
batFile << "rmdir /s /q %WORKDIR%" << std::endl;
523+
batFile << "echo on" << std::endl;
524+
509525
batFile.close();
510526
#else
511527
std::ofstream batFile(tempOutputFileNameNoExt + BAT_NAME);

tsc/tsc/exe.cpp

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -437,29 +437,27 @@ int buildExe(int argc, char **argv, std::string objFileName, std::string additio
437437
// system
438438
if (win)
439439
{
440-
args.push_back("-luser32");
440+
args.push_back("-luser32");
441+
442+
// Link the static CRT (/MT[d]) to match the prebuilt static LLVM/MLIR libs,
443+
// the TypeScript runtime libs and gc.lib. Mixing the static and dynamic CRT
444+
// gives the generated program a separate heap/stdout buffer from those libs
445+
// and crashes at startup/teardown (0xC0000005). The release config uses the
446+
// non-debug import-name suffix; debug uses the 'd' suffix.
441447
if (enableOpt)
442448
{
443-
args.push_back("-lucrt");
449+
args.push_back("-llibucrt");
450+
args.push_back("-llibcmt");
451+
args.push_back("-llibvcruntime");
444452
}
445453
else
446454
{
447-
args.push_back("-lucrtd");
455+
args.push_back("-llibucrtd");
456+
args.push_back("-llibcmtd");
457+
args.push_back("-llibvcruntimed");
448458
}
449459

450460
args.push_back("-lntdll");
451-
if (shared || !disableGC)
452-
{
453-
// needed to resolve DLL ref
454-
if (enableOpt)
455-
{
456-
args.push_back("-lmsvcrt");
457-
}
458-
else
459-
{
460-
args.push_back("-lmsvcrtd");
461-
}
462-
}
463461
}
464462

465463
// tsc libs

0 commit comments

Comments
 (0)