Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 10 additions & 13 deletions .github/workflows/create-release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -240,7 +240,7 @@ jobs:
continue-on-error: false
working-directory: ${{github.workspace}}/__build/tslang/msbuild/x64/release
env:
TSLANG_ANDROID_DEFAULT_LIB_PATH: ${{github.workspace}}/TypeScriptCompilerDefaultLib/__build/android/x86_64
TSLANG_ANDROID_DEFAULT_LIB_PATH: ${{github.workspace}}/TypeScriptCompilerDefaultLib/__build
run: |
$out = ctest -C ${{ env.BUILD_TYPE }} -R "test-compile-android-" --output-on-failure 2>&1 | Out-String
$out
Expand All @@ -251,28 +251,24 @@ jobs:
- name: Create Zip of Windows Asset
working-directory: ${{github.workspace}}/__build
# Flatten the compiler/runtime binaries into the archive root, and add the
# default library as a whole tree so its per-build, per-memory-model subfolders
# are preserved:
# defaultlib/{dll,lib}/{debug,release}/{gc,rc,none},
# defaultlib/*.d.ts, defaultlib/generics/
# default library as a whole tree so its per-target, per-build, per-memory-model
# subfolders are preserved, Android's among them (tslang --print-default-lib-dir names one):
# defaultlib/{dll,lib}/<arch>/<vendor>/<os>/<env>/{debug,release}/{gc,rc,none},
# defaultlib/*.d.ts, defaultlib/generics/ (shared by every target)
# plus the shared collector in its own folder, because its import library is also named
# gc.lib: gcdll/gc.lib + gcdll/gc.dll, for programs that load a tslang shared library.
# tsbindgen looks for clang's resource directory next to itself as lib/clang/<major>
# (findResourceDir's "release package" candidate), so stage that layout too - its headers
# only: the official LLVM package also puts compiler-rt's libraries under
# lib/clang/<major>/lib, which neither tsbindgen nor tslang uses.
# Android, per ABI (arm64-v8a, x86_64): android/<abi>/defaultlib/... (--default-lib-path=
# android/<abi>) and android/<abi>/lib/{libgc.a,libTypeScriptAsyncRuntime.a} (--gc-lib-path
# and --tslang-lib-path).
# Android, per ABI (arm64-v8a, x86_64): android/<abi>/lib/{libgc.a,libTypeScriptAsyncRuntime.a}
# (--gc-lib-path and --tslang-lib-path); its default library is in the defaultlib tree above.
run: |
foreach ($abi in 'arm64-v8a', 'x86_64') {
$dest = ".\android_stage\android\$abi"
New-Item -ItemType Directory -Force -Path "$dest\lib" | Out-Null
# moved, not copied: the default library's __build, packaged whole below, would carry it twice
Move-Item -Path "..\TypeScriptCompilerDefaultLib\__build\android\$abi\defaultlib" -Destination $dest -ErrorAction Stop
Copy-Item -Path "..\3rdParty\gc\android\$abi\release\lib\libgc.a", ".\tslang-runtime\release\android\$abi\libTypeScriptAsyncRuntime.a" -Destination "$dest\lib" -ErrorAction Stop
}
Remove-Item -Recurse -Force -Path "..\TypeScriptCompilerDefaultLib\__build\android" -ErrorAction Stop
New-Item -ItemType Directory -Force -Path .\gcdll_stage\gcdll | Out-Null
Copy-Item -Path ..\3rdParty\gcdll\x64\release\lib\gc.lib, ..\3rdParty\gcdll\x64\release\bin\gc.dll -Destination .\gcdll_stage\gcdll -ErrorAction Stop
Get-ChildItem -Path ..\3rdParty\llvm\x64\release\lib\clang -Directory | ForEach-Object { $dest = ".\resourcedir_stage\lib\clang\$($_.Name)"; New-Item -ItemType Directory -Force -Path $dest | Out-Null; Copy-Item -Path (Join-Path $_.FullName "include") -Destination $dest -Recurse -ErrorAction Stop }
Expand Down Expand Up @@ -453,8 +449,9 @@ jobs:
cp ./gc/ninja/release/libgc.a ./__stage/
cp ./tslang/ninja/release/lib/libTypeScriptAsyncRuntime.a ./__stage/
cp ../3rdParty/llvm/release/bin/wasm-ld ./__stage/
# Add the default library as a whole tree so its per-build, per-memory-model
# subfolders are preserved: defaultlib/{dll,lib}/{debug,release}/{gc,rc,none},
# Add the default library as a whole tree so its per-target, per-build, per-memory-model
# subfolders are preserved:
# defaultlib/{dll,lib}/<arch>/<vendor>/<os>/<env>/{debug,release}/{gc,rc,none},
# defaultlib/*.d.ts, defaultlib/generics/
cp -r ../TypeScriptCompilerDefaultLib/__build/defaultlib ./__stage/
# tsbindgen looks for clang's resource directory next to itself as lib/clang/<major>
Expand Down
3 changes: 2 additions & 1 deletion docs/how/cmake_bgfx/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,8 @@ build matching the model it was compiled with. One variable drives both:
cmake --preset default -DTSLANG_MEMORY_MODEL=rc
```

It selects `defaultlib/lib/<debug|release>/<model>` as the link directory and adds `-mm=<model>`
It selects `defaultlib/lib/<arch>/<vendor>/<os>/<env>/<debug|release>/<model>` (as
`tslang --print-default-lib-dir=lib` names it) as the link directory and adds `-mm=<model>`
to the compile flags, so the two cannot disagree; configuring fails if that model has not been
built. Valid values are `gc` (default), `rc` and `none`; only `gc` links Boehm.

Expand Down
22 changes: 14 additions & 8 deletions docs/how/cmake_bgfx/cmake/LocateTSLang.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -113,18 +113,24 @@ function(setup_tslang_link_paths)
message(FATAL_ERROR "setup_tslang_link_paths: TSLANG_PREFIX is not set")
endif()

# The compiled default lib is split per build mode (debug/release) and then per memory
# model (gc/rc/none): a default lib built for one model allocates the way that model
# allocates, so linking it into a program built for another is the mismatch the compiler
# refuses to paper over. TSLANG_MEMORY_MODEL picks both this directory and the -mm= flag.
# The compiled default lib is split per target, then per build mode (debug/release), then
# per memory model (gc/rc/none): a default lib built for one model allocates the way that
# model allocates, so linking it into a program built for another is the mismatch the
# compiler refuses to paper over. TSLANG_MEMORY_MODEL picks both this directory and the -mm=
# flag; tslang names the directory (--print-default-lib-dir), so the layout is not spelled
# out here.
if(CMAKE_BUILD_TYPE STREQUAL "Release")
set(_defaultlib_config "release")
set(_defaultlib_build_flag "")
else()
set(_defaultlib_config "debug")
set(_defaultlib_build_flag "--di")
endif()

set(_defaultlib_dir
"${TSLANG_BIN_DIR}/defaultlib/lib/${_defaultlib_config}/${TSLANG_MEMORY_MODEL}")
execute_process(COMMAND "${CMAKE_TSLANG_COMPILER}" --print-default-lib-dir=lib ${_defaultlib_build_flag}
-mm=${TSLANG_MEMORY_MODEL}
OUTPUT_VARIABLE _defaultlib_subdir
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY)
set(_defaultlib_dir "${TSLANG_BIN_DIR}/${_defaultlib_subdir}")
if(NOT IS_DIRECTORY "${_defaultlib_dir}")
message(FATAL_ERROR
"No default library built for -mm=${TSLANG_MEMORY_MODEL}: ${_defaultlib_dir} "
Expand Down
20 changes: 13 additions & 7 deletions docs/how/cmake_dll/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,21 +11,27 @@ enable_language(TSLANG)
# Include folders
include_directories(${CMAKE_TSLANG_DIR}/defaultlib)

# The compiled default lib is split into per-build subfolders (debug/release) and then per
# memory model (gc/rc/none); pick the pair matching this build, so that the CRT, the allocator
# and the default-lib binaries all agree. A library built for one model cannot be linked into
# a program built for another.
# The compiled default lib is split per target, then per build (debug/release), then per memory
# model (gc/rc/none); pick the one matching this build, so that the CRT, the allocator and the
# default-lib binaries all agree. A library built for one model cannot be linked into a program
# built for another. tslang names the folder (--print-default-lib-dir), so this never spells out
# the layout.
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(TSLANG_DEFAULTLIB_BUILD "release")
set(TSLANG_DEFAULTLIB_BUILD_FLAG "")
else()
set(TSLANG_DEFAULTLIB_BUILD "debug")
set(TSLANG_DEFAULTLIB_BUILD_FLAG "--di")
endif()

set(TSLANG_MEMORY_MODEL "gc" CACHE STRING "Memory model of compiled code: gc, rc or none")
set_property(CACHE TSLANG_MEMORY_MODEL PROPERTY STRINGS gc rc none)

execute_process(COMMAND "${CMAKE_TSLANG_COMPILER}" --print-default-lib-dir=lib ${TSLANG_DEFAULTLIB_BUILD_FLAG} -mm=${TSLANG_MEMORY_MODEL}
OUTPUT_VARIABLE TSLANG_DEFAULTLIB_SUBDIR
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY)

# Lib folders
link_directories(${CMAKE_TSLANG_DIR} ${CMAKE_TSLANG_DIR}/defaultlib/lib/${TSLANG_DEFAULTLIB_BUILD}/${TSLANG_MEMORY_MODEL})
link_directories(${CMAKE_TSLANG_DIR} ${CMAKE_TSLANG_DIR}/${TSLANG_DEFAULTLIB_SUBDIR})

# set options
if (CMAKE_BUILD_TYPE STREQUAL "Release")
Expand Down
3 changes: 2 additions & 1 deletion docs/how/cmake_dll/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ the build matching the model it was compiled with. One variable drives both:
cmake --preset default -DTSLANG_MEMORY_MODEL=rc
```

It selects `defaultlib/lib/<debug|release>/<model>` as the link directory and adds `-mm=<model>`
It selects `defaultlib/lib/<arch>/<vendor>/<os>/<env>/<debug|release>/<model>` (as
`tslang --print-default-lib-dir=lib` names it) as the link directory and adds `-mm=<model>`
to the compile flags, so the two cannot disagree. Valid values are `gc` (default), `rc` and
`none`; only `gc` links Boehm.

Expand Down
20 changes: 13 additions & 7 deletions docs/how/cmake_tslang/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,15 @@ enable_language(TSLANG)
# Include folders
include_directories(${CMAKE_TSLANG_DIR}/defaultlib)

# The compiled default lib is split into per-build subfolders (debug/release) and then per
# memory model (gc/rc/none); pick the pair matching this build, so that the CRT, the allocator
# and the default-lib binaries all agree. A library built for one model cannot be linked into
# a program built for another.
# The compiled default lib is split per target, then per build (debug/release), then per memory
# model (gc/rc/none); pick the one matching this build, so that the CRT, the allocator and the
# default-lib binaries all agree. A library built for one model cannot be linked into a program
# built for another. tslang names the folder (--print-default-lib-dir), so this never spells out
# the layout.
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(TSLANG_DEFAULTLIB_BUILD "release")
set(TSLANG_DEFAULTLIB_BUILD_FLAG "")
else()
set(TSLANG_DEFAULTLIB_BUILD "debug")
set(TSLANG_DEFAULTLIB_BUILD_FLAG "--di")
endif()

set(TSLANG_MEMORY_MODEL "gc" CACHE STRING "Memory model of compiled code: gc, rc or none")
Expand All @@ -30,8 +31,13 @@ set_property(CACHE TSLANG_MEMORY_MODEL PROPERTY STRINGS gc rc none)
# Two collectors free each other's live objects. See docs/memory-models.md.
option(TSLANG_SHARED_GC "The program loads tslang shared libraries (gc: share one collector)" OFF)

execute_process(COMMAND "${CMAKE_TSLANG_COMPILER}" --print-default-lib-dir=lib ${TSLANG_DEFAULTLIB_BUILD_FLAG} -mm=${TSLANG_MEMORY_MODEL}
OUTPUT_VARIABLE TSLANG_DEFAULTLIB_SUBDIR
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY)

# Lib folders
link_directories(${CMAKE_TSLANG_DIR} ${CMAKE_TSLANG_DIR}/defaultlib/lib/${TSLANG_DEFAULTLIB_BUILD}/${TSLANG_MEMORY_MODEL})
link_directories(${CMAKE_TSLANG_DIR} ${CMAKE_TSLANG_DIR}/${TSLANG_DEFAULTLIB_SUBDIR})

# set options
if (CMAKE_BUILD_TYPE STREQUAL "Release")
Expand Down
5 changes: 3 additions & 2 deletions docs/how/cmake_tslang/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,8 @@ the build matching the model it was compiled with. One variable drives both:
cmake --preset default -DTSLANG_MEMORY_MODEL=rc
```

It selects `defaultlib/lib/<debug|release>/<model>` as the link directory and adds `-mm=<model>`
It selects `defaultlib/lib/<arch>/<vendor>/<os>/<env>/<debug|release>/<model>` (as
`tslang --print-default-lib-dir=lib` names it) as the link directory and adds `-mm=<model>`
to the compile flags, so the two cannot disagree. Valid values are `gc` (default), `rc` and
`none`; only `gc` links Boehm.

Expand All @@ -69,7 +70,7 @@ cmake --preset default -DTSLANG_SHARED_GC=ON

- Windows: links `gcdll/gc.lib` (gc.dll's import library) instead of the static `gc.lib`, and copies
`gc.dll` beside the program. Ship it with `TypeScriptDefaultLib.dll`
(`defaultlib/dll/<release|debug>/gc`) and your libraries.
(`defaultlib/dll/<arch>/<vendor>/<os>/<env>/<release|debug>/gc`) and your libraries.
- Linux: links the whole static collector and exports its `GC_*` symbols, so the shared library
uses the program's collector.

Expand Down
3 changes: 2 additions & 1 deletion docs/memory-models.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,8 @@ What to ship with a Windows program that loads a tslang shared library, all in o

- the program and its shared libraries,
- `gc.dll` (from `gcdll/` in the release package),
- `TypeScriptDefaultLib.dll` (from `defaultlib/dll/<release|debug>/gc`), which every shared library
- `TypeScriptDefaultLib.dll` (from `defaultlib/dll/x86_64/pc/windows/msvc/<release|debug>/gc`;
`tslang --print-default-lib-dir=dll [--di]` names it), which every shared library
built with the default library imports.

A shared library that was linked against the static `gc.lib` anyway — by an older `tslang`, or by
Expand Down
4 changes: 2 additions & 2 deletions tslang/build_tslang_defaultlib_debug.bat
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ pushd
cd ../../TypeScriptCompilerDefaultLib/
call build.bat

rem Copy the whole staged defaultlib tree so per-build subfolders are preserved:
rem defaultlib\dll\{debug,release}\{gc,rc,none}, defaultlib\lib\{debug,release}\{gc,rc,none},
rem Copy the whole staged defaultlib tree so every target's, build's and model's subfolders are
rem preserved: defaultlib\{dll,lib}\<arch>\<vendor>\<os>\<env>\{debug,release}\{gc,rc,none},
rem *.d.ts, generics\
xcopy __build\defaultlib\*.* "../TypeScriptCompiler/__build/tslang/windows-msbuild-2026-debug/bin/defaultlib/" /i /e /y

Expand Down
4 changes: 2 additions & 2 deletions tslang/build_tslang_defaultlib_release.bat
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ pushd
cd ../../TypeScriptCompilerDefaultLib/
call build.bat

rem Copy the whole staged defaultlib tree so per-build subfolders are preserved:
rem defaultlib\dll\{debug,release}\{gc,rc,none}, defaultlib\lib\{debug,release}\{gc,rc,none},
rem Copy the whole staged defaultlib tree so every target's, build's and model's subfolders are
rem preserved: defaultlib\{dll,lib}\<arch>\<vendor>\<os>\<env>\{debug,release}\{gc,rc,none},
rem *.d.ts, generics\
xcopy __build\defaultlib\*.* "../TypeScriptCompiler/__build/tslang/windows-msbuild-2026-release/bin/defaultlib/" /i /e /y

Expand Down
32 changes: 14 additions & 18 deletions tslang/include/TypeScript/Defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -318,27 +318,23 @@
// warns about, and it is the largest instance of it, since every program that does not pass
// `--no-default-lib` links this one.
//
// Layout: defaultlib/{lib,dll}/[x86/]{debug,release}/{gc,rc,none}/. The model name is exactly
// `memoryModelName()`, so the directory and the `-mm=` flag cannot drift apart.
// The model name is exactly `memoryModelName()`, so the directory and the `-mm=` flag cannot
// drift apart.
#define DEFAULT_LIB_KIND_STATIC "lib"
#define DEFAULT_LIB_KIND_SHARED "dll"

// ...and, for a Windows x86 target, per arch, outermost under lib/ or dll/ like every other x86
// library (spec "Arch in the library layout"). Every other target, x64 included, has no arch
// segment, so existing trees keep their shape. There is no fallback to the x64 tree: an x64
// library links into an x86 program only to fail on every symbol.
#define DEFAULT_LIB_ARCH_X86 "x86"

inline std::string getDefaultLibSubDir(bool shared, bool debugBuild, const char *memoryModel, const char *arch)
{
std::string subDir = std::string(DEFAULT_LIB_DIR "/") + (shared ? DEFAULT_LIB_KIND_SHARED : DEFAULT_LIB_KIND_STATIC) + "/";
if (arch && *arch)
{
subDir += std::string(arch) + "/";
}

return subDir + (debugBuild ? DEFAULT_LIB_BUILD_DIR_DEBUG : DEFAULT_LIB_BUILD_DIR_RELEASE) + "/" + memoryModel;
}
// ...and, outermost under lib/ or dll/, per target, as the LLVM triple names it: arch, vendor, OS
// and environment, each the canonical name LLVM gives the parsed component, so the spellings of
// one target (i686/i386, an Android API level, an MSVC version) share a tree. Every target is
// keyed this way, the host included. There is no fallback to another target's tree: a library
// built for one links into a program for another only to fail on every symbol.
//
// Layout: defaultlib/{lib,dll}/<arch>/<vendor>/<os>/<env>/{debug,release}/{gc,rc,none}/, e.g.
// defaultlib/lib/x86_64/pc/windows/msvc/release/gc or defaultlib/lib/aarch64/unknown/linux/android/
// release/gc. Everything else (*.d.ts, generics/, ...) stays at the defaultlib root, shared by
// every build. Composed in ONE place, getDefaultLibSubDir (tslang/tslang/defaultlib.cpp), which
// the linker, the JIT, --install-default-lib and --print-default-lib-dir all call; the build
// scripts ask --print-default-lib-dir rather than spelling the path out.

#define DEBUG_SCOPE "current"
#define CU_DEBUG_SCOPE "compileUnit"
Expand Down
23 changes: 15 additions & 8 deletions tslang/include/TypeScript/VSCodeTemplate/Files.h
Original file line number Diff line number Diff line change
Expand Up @@ -301,21 +301,27 @@ project(<<PROJECT>> CXX TSLANG)
# Include folders
include_directories(${CMAKE_TSLANG_DIR}/defaultlib)

# The compiled default lib is split into per-build subfolders (debug/release) and then per
# memory model (gc/rc/none); pick the pair matching this build, so that the CRT, the allocator
# and the default-lib binaries all agree. A library built for one model cannot be linked into
# a program built for another.
# The compiled default lib is split per target, then per build (debug/release), then per memory
# model (gc/rc/none); pick the one matching this build, so that the CRT, the allocator and the
# default-lib binaries all agree. A library built for one model cannot be linked into a program
# built for another. tslang names the folder (--print-default-lib-dir), so this never spells out
# the layout.
if (CMAKE_BUILD_TYPE STREQUAL "Release")
set(TSLANG_DEFAULTLIB_BUILD "release")
set(TSLANG_DEFAULTLIB_BUILD_FLAG "")
else()
set(TSLANG_DEFAULTLIB_BUILD "debug")
set(TSLANG_DEFAULTLIB_BUILD_FLAG "--di")
endif()

set(TSLANG_MEMORY_MODEL "gc" CACHE STRING "Memory model of compiled code: gc, rc or none")
set_property(CACHE TSLANG_MEMORY_MODEL PROPERTY STRINGS gc rc none)

execute_process(COMMAND "${CMAKE_TSLANG_COMPILER}" --print-default-lib-dir=lib ${TSLANG_DEFAULTLIB_BUILD_FLAG} -mm=${TSLANG_MEMORY_MODEL}
OUTPUT_VARIABLE TSLANG_DEFAULTLIB_SUBDIR
OUTPUT_STRIP_TRAILING_WHITESPACE
COMMAND_ERROR_IS_FATAL ANY)

# Lib folders
link_directories(${CMAKE_TSLANG_DIR} ${CMAKE_TSLANG_DIR}/defaultlib/lib/${TSLANG_DEFAULTLIB_BUILD}/${TSLANG_MEMORY_MODEL})
link_directories(${CMAKE_TSLANG_DIR} ${CMAKE_TSLANG_DIR}/${TSLANG_DEFAULTLIB_SUBDIR})

# set options
if (CMAKE_BUILD_TYPE STREQUAL "Release")
Expand Down Expand Up @@ -480,7 +486,8 @@ the build matching the model it was compiled with. One variable drives both:
cmake --preset default -DTSLANG_MEMORY_MODEL=rc
```

It selects `defaultlib/lib/<debug|release>/<model>` as the link directory and adds `-mm=<model>`
It selects `defaultlib/lib/<arch>/<vendor>/<os>/<env>/<debug|release>/<model>` (as
`tslang --print-default-lib-dir=lib` names it) as the link directory and adds `-mm=<model>`
to the compile flags, so the two cannot disagree. Valid values are `gc` (default), `rc` and
`none`; only `gc` links Boehm.

Expand Down
Loading
Loading