Skip to content

import: a module's file for the target, <name>.<os>.ts, before <name>.ts - #552

Merged
ASDAlexander77 merged 1 commit into
mainfrom
import-os-suffix
Oct 11, 2026
Merged

ASDAlexander77 merged 1 commit into
mainfrom
import-os-suffix

Conversation

@ASDAlexander77

Copy link
Copy Markdown
Owner

Summary

An import with no extension now resolves to the target's own file first:

Target import "./m" resolves to (if it exists)
Windows m.win32.ts
Linux and Android m.linux.ts
Anything else m.<the triple's OS name>.ts

If that file doesn't exist, the import resolves to m.ts as before.

The names follow the default library, which builds lib.win32.ts or lib.linux.ts, using lib.linux.ts for Android.

Why: some modules need a different declaration per target, not just different function bodies. The motivating case is native_ts_graphics' NVRHI bindings, @cppvtable classes whose slot numbers and struct layouts follow the C++ ABI. MSVC has one destructor slot and Itanium has two, overloads are ordered differently, and std::string has a different layout in each C++ standard library.

A slot number is fixed where the call is compiled, so the default library's approach (one .d.ts, with the implementation picked at link time) can't switch these. With this change the importer names one module, import { nvrhi } from "../core/nvrhi", and the build compiles and links core/nvrhi.win32.ts or core/nvrhi.linux.ts beside it.

Change

  • includeFilePath (MLIRGenImpl.h) checks for the target's file first.
  • The new targetOSFileSuffix maps the target triple to win32, linux, or the triple's OS name.
  • Imports with an extension, and imports of shared libraries, are unchanged.

Tests

  • test-compile-export-import-os-suffix: import_os_suffix.ts imports ./export_os_suffix, and there is no export_os_suffix.ts. It is compiled and run with the host's file:
    • export_os_suffix.win32.ts calls GetCurrentProcessId;
    • export_os_suffix.linux.ts calls getpid.
  • test-compile-import-os-suffix-win32 / -linux: run on any host with --emit=mlir -mtriple=.... Each checks that the import picked up that target's OS function and not the other one.
  • Locally on Windows, the import, export-import and ownership-verifier tests pass: 297/297.

🤖 Generated with Claude Code

An import without an extension resolves to <name>.win32.ts on Windows, <name>.linux.ts on Linux and Android (<name>.<the triple's OS name>.ts elsewhere) when that file exists, else to <name>.ts. A module with code per target - a C++ ABI's vtables and struct layouts, for @cppvtable classes - is then picked as the default library picks lib.win32.ts or lib.linux.ts, while the importer names one module.

Tests: import_os_suffix.ts with export_os_suffix.win32.ts / .linux.ts, compiled and run on the host; and the import's declarations checked for each target triple (--emit=mlir), on any host.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant