安装

以下所有说明适用于 Linux、macOS 和 Windows。

二进制文件

安装 LFortran 的推荐方法是使用 Conda。例如,按照你的平台的说明安装 Miniconda,安装 Conda。然后创建一个新环境(你可以选择任何名称,这里我们选择了lf)并激活它:

conda create -n lf
conda activate lf

然后通过以下方式安装 LFortran:

conda install lfortran -c conda-forge

现在 lf 环境有 lfortran 编译器可用,你可以通过执行 lfortran 启动交互式提示,或使用 lfortran -h 查看命令行选项。

Note about Conda Installation

When installing LFortran using Conda, multiple copies of the lfortran executable may be present in different locations (for example, in the package cache). Only the executable inside the active Conda environment should be used.

After activating a conda environment, the correct executable is typically located at: $CONDA_PREFIX/bin/lfortran

To verify which executable is being used, activate a conda environment and run: which lfortran

Other copies located in package directories may not run correctly and can be ignored.

Jupyter 内核是通过上面的命令自动安装的,所以在安装 Jupyter 本身之后:

conda install jupyter -c conda-forge

你可以通过执行以下命令来创建基于 Fortran 的 Jupyter 笔记本:

jupyter notebook

并选择 New->Fortran。

从源代码构建

如果你只想自己或在包管理器(Spack、Conda、Debian 等)中安装 LFortran,建议使用此方法。源代码包含所有生成的文件,并且具有最小的依赖关系。

The source tarball of LFortran depends on:

  • Python

  • cmake

  • LLVM 10-19

  • zstd-static

  • zlib

首先,我们必须安装依赖项,例如使用 Conda:

conda create -n lf python cmake llvmdev zstd-static zlib
conda activate lf

On a Linux system, we additionally need to install libunwind:

conda install libunwind

然后从 https://lfortran.org/download/ 下载源代码,例如:

wget https://github.com/lfortran/lfortran/releases/download/v0.42.0/lfortran-0.42.0.tar.gz
tar xzf lfortran-0.42.0.tar.gz
cd lfortran-0.42.0

并构建:

cmake -DWITH_LLVM=yes -DCMAKE_INSTALL_PREFIX=`pwd`/inst .
make -j8
make install

This will install lfortran into inst/bin. It assumes that c++ and cc are available, which on Linux are typically the GNU C++/C compilers.

从 Git 构建

我们假设你安装了 C++ 编译器,以及 git 和 wget。在 Ubuntu 中,你还可以为 stacktraces 安装 binutils-dev。

如果你没有安装 Conda,你可以在 Linux 上安装(在其他平台上类似):

wget --no-check-certificate https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh -O miniconda.sh
bash miniconda.sh -b -p $HOME/conda_root
export PATH="$HOME/conda_root/bin:$PATH"

克隆 LFortran git 存储库:

git clone https://github.com/lfortran/lfortran.git
cd lfortran

然后准备环境:

conda env create -f environment_linux.yml
conda activate lf

生成构建所需的文件(此步骤取决于 re2c、bison 和 python):

./build0.sh

Now you can use our script ./build1.sh to build in Debug mode:

./build1.sh

and can use ninja to rebuild.

To do a clean rebuild, you can use:

# NOTE: the below git command deletes all untracked files
git clean -dfx  # reset repository to a clean state by removing artifacts generated during the build process
./build0.sh
./build1.sh

运行交互式提示符:

./src/bin/lfortran

See how to run tests to make sure all tests pass

在 Windows 上使用 Visual Studio 从 Git 构建

安装 Visual Studio (MSVC),例如 2022 版本,可以免费下载社区版本:https://visualstudio.microsoft.com/downloads/ 。

使用来自 https://github.com/conda-forge/miniforge 的 Windows 安装程序安装 miniforge。

从桌面上启动 Miniforge Prompt。

在 shell 中,用以下方法初始化 MSVC 编译器:

call "C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\Tools\VsDevCmd" -arch=x64

你可以选择通过以下方式测试 MSVC 是否工作:

cl /?
link /?

这两个命令都必须打印帮助信息(若干页)。

现在你可以下载并建立 LFortran:

git clone https://github.com/lfortran/lfortran.git
cd lfortran
conda env create -f environment_win.yml
conda activate lf
build0.bat
build1.bat

如果一切都编译好了,那么你就可以使用 LFortran,如下所示:

inst\bin\lfortran examples/expr2.f90
expr2.exe
inst\bin\lfortran

等等 。

注意:LFortran 目前使用 MSVC 的链接器程序(link),只有在运行上面的 MSVC bat 脚本时才能使用。如果你忘记激活它,LFortran 的链接就会失败。

注意:miniforge shell 似乎在运行某个版本的 git-bash(尽管它是cmd.exe),它有一些类似 unix 的文件系统挂载在 /usr,有几个命令可用,如ls、which、git、vim。 由于这个原因,Conda 构建的 environment_win.yml 包含了所有需要的东西,包括 git。

用 WSL 在 Windows上 从 Git 构建

  • 在 Windows 中搜索“打开或关闭 Windows 功能”。

  • 标记适用于Linux 的 Windows 子系统。

  • 按“确定”并重新启动计算机。

  • Go to Microsoft store and download Ubuntu (20.04 or 22.04 or 24.04), and launch it.

  • Now setup LFortran by running the following commands.

    wget  https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-Linux-x86_64.sh -O miniconda.sh
    bash miniconda.sh -b -p $HOME/conda_root
    echo "export PATH=$HOME/conda_root/bin:$PATH" >> ~/.bashrc
    
  • After that restart the Ubuntu terminal.

  • Now clone the LFortran git repository (you should clone it inside a linux owned directory like ~ or any of its sub-directories).

    cd ~
    git clone https://github.com/lfortran/lfortran.git
    cd lfortran
    
  • 运行以下内容

    conda env create -f environment_linux.yml
    conda init bash
    
  • Restart Ubuntu terminal again

    conda activate lf
    sudo apt update
    sudo apt-get install build-essential
    sudo apt-get install zlib1g-dev libzstd-dev
    sudo apt install clang
    
  • 运行以下命令

    conda activate lf
    ./build0.sh
    cmake -DCMAKE_BUILD_TYPE=Debug -DWITH_LLVM=yes -DCMAKE_INSTALL_PREFIX=`pwd`/inst .
    make -j8
    
  • 如果一切都能编译,你可以使用 LFortran,如下所示

    ./src/bin/lfortran ./examples/expr2.f90
    ./expr2.out
    
  • 运行交互式提示符

    ./src/bin/lfortran
    

See how to run tests to make sure all tests pass

启用 Jupyter 内核

要安装 Jupyter 内核,还要安装以下 Conda 软件包:

conda install xeus=6.0.0 xeus-zmq=4.0.0 nlohmann_json

并通过 -DWITH_XEUS=yes 启用内核,然后安装到 $CONDA_PREFIX。比如:

cmake \
    -DCMAKE_BUILD_TYPE=Debug \
    -DWITH_LLVM=yes \
    -DWITH_XEUS=yes \
    -DCMAKE_PREFIX_PATH="$CONDA_PREFIX" \
    -DCMAKE_INSTALL_PREFIX="$CONDA_PREFIX" \
    .
cmake --build . -j4 --target install

要使用它,请安装 Jupyter(conda install jupyter)并测试是否找到 LFortran 内核:

jupyter kernelspec list --json

然后启动 Jupyter notebook,如下所示:

jupyter notebook

单击 New - > Fortran。启动 jupyter LFortran 终端控制台:

jupyter console --kernel=fortran

使用 Nix 从 Git 构建

There’s a provided Nix shell for making a consistent build environment with the exact same dependency versions across users.

Using the Environment

Enter the development environment:

nix develop ./ci/nix

To change the compilation environment from gcc (default) to clang:

nix develop ./ci/nix#clangOnly

Depending on your system configuration, you might have to run nix develop with the following extra nix features explicitly enabled:

nix --extra-experimental-features "flakes nix-command" develop ./ci/nix

Building the Code

The build steps are the same as when building from git:

./build0.sh
./build1.sh

As of 2025-11-10, the environment passes the CI tests, provided you tell it where to install the Jupyter kernel:

LFORTRAN_CMAKE_GENERATOR=Ninja CONDA_PREFIX=$(pwd) JUPYTER_PATH=$(pwd)/share/jupyter bash ci/build.sh

(take note that the Nix shell does not use conda)

Give the same JUPYTER_PATH when running jupyter notebook / jupyter lab to use the same jupyter kernel.

关于依赖性的说明

我们鼓励终端用户(和发行版)使用来自 https://lfortran.org/download/的tarball,它只依赖于LLVM、CMake和C++编译器。

这个 tarball 是由我们的 CI(持续集成)自动生成的,包含一些自动生成的文件:解析器、AST 和 ASR 节点,由 ASDL 翻译器生成(需要 Python)。

在开发 LFortran 本身时要使用来自 git 的指令。

不使用 Conda 的用户注意

以下是在开发模式下安装此版本库的必要依赖,

堆栈跟踪

LFortran 可以在出现未处理的异常时打印堆栈跟踪,也可以在任何编译器错误时使用 --show-stacktrace 选项。这对开发编译器本身很有帮助,可以看到 LFortran 中的问题所在。默认情况下,堆栈跟踪支持是关闭的,要启用它,需要在每个平台上按照下面的说明安装先决条件后,用-DWITH_STACKTRACE=yes cmake 选项编译 LFortran。

LLVM

In all platforms having LLVM, stacktraces can be shown with LLVM, so no additional prerequisites are required. If LLVM is not available, you can use the following instructions, depending on your platform.

Ubuntu

在 Ubuntu 系统,apt install binutils-dev。

macOS

如果你在 macOS 上使用默认的 Clang 编译器,那么堆栈跟踪应该正好在基于 Intel 和 M1 的 macOS 上工作(CMake 构建系统自动调用 dsymtuil 工具和我们的 Python 脚本来存储调试信息,更多细节见 src/bin/CMakeLists.txt)。如果不能工作,请报告一个错误。

如果你不喜欢默认的方式,另一个选择是使用bintutils。为此,首先安装 Spack,然后:

spack install binutils
spack find -p binutils

最后一条命令将显示已安装的 binutils 软件包的完整路径。把这个路径添加到你的 shell 配置文件中,例如:

export CMAKE_PREFIX_PATH_LFORTRAN=/Users/ondrej/repos/spack/opt/spack/darwin-catalina-broadwell/apple-clang-11.0.0/binutils-2.36.1-wy6osfm6bp2323g3jpv2sjuttthwx3gd

并使用 -DCMAKE_PREFIX_PATH="$CMAKE_PREFIX_PATH_LFORTRAN;$CONDA_PREFIX" cmake 选项编译 LFortran。$CONDA_PREFIX 是在你使用 Conda 安装了一些其他的依赖项(如 llvm)的情况下出现的,否则你可以把它删除。

Tests

运行测试:

ctest
./run_tests.py

Update test references:

./run_tests.py -u

Run integration tests

cd integration_tests
./run_tests.py

Speed up integration tests on macOS

Integration tests run slowly because Apple checks the hash of each executable online before running.

You can turn off that feature in the Privacy tab of the Security and Privacy item of System Preferences > Developer Tools > Terminal.app > “allow the apps below to run software locally that does not meet the system’s security policy.”

CI coverage

Pull requests normally run only Quick checks. Quick uses the same builds, test suites and selection rules on PRs, main pushes, release tags and manual runs. Publishing steps remain push-only. Main runs Quick plus Exhaustive. Exhaustive adds configurations and broader suites, never another invocation of Quick, and runs identically on main and on manual dispatch. Exhaustive never runs on PRs.

The shared native compiler workflow has two explicit coverage roles:

Role

Caller

Native LLVM matrix

quick

Quick on every event

Linux 7/11/23

exhaustive

Exhaustive on every event

Linux 7/8/10/11/15/17/18/19/21/22/23 and macOS 22

Full LLVM-WASM, no-LLVM and MLIR suites belong directly to Quick on every event. They are not declared in Exhaustive or its shared compiler workflow, so there are no duplicate or skipped Exhaustive copies of these jobs.

Quick distributes the full CPU modes over two existing builds rather than serializing them in one long job:

Compiler

Complete regression modes

Linux/LLVM 11 Debug

Normal, --fast, Fortran 2023 normal/fast, full references, small LLVM variants, submodules and single invocation

Linux/LLVM 21 Debug

Separate compilation, submodules with separate compilation, and leak detection

Every registered LLVM test runs in each of these modes on its designated compiler. Both are Debug builds, so every full Quick suite runs with assertions and per-pass ASR verification. Both also use the platform C/C++ diagnostic and standard-library hardening flags, including -Werror, and WITH_INTERNAL_ALLOC_CHECK=yes. Splitting the modes across two jobs reduces the critical path without sampling those suites or adding another dependent job/queue.

The Linux/LLVM 11 platform build retains full reference coverage, platform smoke tests, and the full GFortran, C/C++, Fortran, direct-WASM, OpenMP and CUDA-on-CPU backend suites. Linux/LLVM 21 Debug also runs normal/fast smoke coverage, and Linux/LLVM 7/23 Release provide additional smoke coverage. macOS/LLVM 11 keeps platform smoke coverage and the full Metal and CUDA-on-CPU suites. Windows keeps its native Release build and supported compile/link/run checks. Caffeine/coarrays run on the LLVM 11 Debug compatibility compiler. The standalone compiler-to-WASM build is also retained.

Exhaustive runs the full compatibility suites on every LLVM version except 11 and 19, which run the application catalog instead, as does macOS LLVM 22; every compatibility job runs Caffeine/coarrays. Three supplemental platform builds also run full normal/fast suites on Linux LLVM 11/21 Debug and full normal/reference suites on macOS LLVM 11 Debug. These retain the full platform coverage that used to run only in main’s Quick. Quick and Exhaustive share .github/actions/build-platform so these compiler configurations cannot drift. The supplemental jobs do not rerun Quick’s GPU, alternate-backend or descriptor-mode suites; Linux references stay in Quick.

All native compatibility profiles enable runtime-stacktrace support, including the LLVM 11/19 and macOS application compilers. Caffeine removes LFortran -g from its defaults and GASNet linker flags; its --enable-debug build does not require disabling runtime stacktraces. Actual LFortran -g links invoke llvm-dwarfdump and dwarf_convert.py (also dsymutil on macOS); ordinary non--g links do not. The LLVM packages supply these debug tools. A separate application-compiler probe verifies the generated runtime-support define, executes the tools and checks both ordinary and -g links before the catalog. Missing/broken tools or failed links must fail the job, not disable support.

On Linux, runtime-stacktrace support uses the compiler’s <unwind.h> interface. It does not itself enable CMake’s separate WITH_LIBUNWIND option. LLVM >=12 requires that library independently, and the workflow retains its explicit libunwind installation (also kept in the existing Quick LLVM 11 environment). The LLVM 11 application compiler does not need an additional libunwind installation merely to enable runtime stacktraces. Application validation must exercise the runtime-enabled Release LLVM 11/19 and macOS LLVM 22 profiles; success with the former disabled-runtime flags is not evidence for this change.

The distinct Kokkos/out-of-source and custom-install configurations run full suites. Standalone C++ builds, documentation/kernel tests, the Docker build/tests, JupyterLite and source packaging remain additional checks.

PRs do not run the Exhaustive workflow at all. For a rare, explicitly requested extended check of a PR, dispatch it in a fork (see below).

Job timeouts

Every job sets timeout-minutes, about twice its slowest normal run (for example 60 minutes for the Windows platform build, 150 for macOS). Without it, a hung job holds a runner for GitHub’s 6-hour default; under the organization’s 20 concurrent-job limit, one hang in a test that runs on every PR can block CI for hours. When a job’s normal duration grows, raise its timeout in the same change.

Compiler caches

Every C/C++ build runs through ccache or sccache (hendrikmuhs/ccache-action), including both halves of the WASM build, which use ccache as the CMake compiler launcher for the native compiler and for em++. The action keeps the cache in the workspace (.ccache or .sccache), so a build that runs git clean must exclude it. Caches are saved only on main (save: ${{ github.ref == 'refs/heads/main' }}) and restored everywhere. A cache saved for a PR or tag can only be restored by that same ref, and the repository’s 10 GB cache limit evicts the least recently used caches first, so PR caches would push out the main caches that every run starts from. The Cleanup caches by a branch workflow also deletes a PR’s caches when it closes.

Keep compiler inputs identical between commits. The version comes from git describe and changes with every commit, so it must not appear in build paths: ci/build.sh unpacks the versioned source tarball into the fixed lfortran-src/ directory before building.

The action appends a timestamp to every saved key, so each save on main adds a new copy. After every Quick or Exhaustive run on main, Prune-Main-Caches-CI.yml (ci/prune_main_caches.py) deletes all but the newest copy of each key, keeping the total under the limit. This leaves room for a 1.5 GB ccache per platform build (max-size: 1500M in .github/actions/build-platform); the action’s 500 MB default is smaller than one Debug build, so ccache evicted objects it still needed.

Required checks

The main ruleset requires these eleven Quick checks directly, bound to the GitHub Actions app (app ID 15368). There is no aggregate status job.

LFortran CI (OS=macos-latest, LLVM=11)
LFortran CI (OS=ubuntu-latest, LLVM=11)
LFortran CI (OS=ubuntu-latest, LLVM=21)
LFortran CI (OS=windows-2025, LLVM=11)
Build LFortran to WASM
Compiler compatibility / Test LLVM 7 (ubuntu-latest)
Compiler compatibility / Test LLVM 11 (ubuntu-latest)
Compiler compatibility / Test LLVM 23 (ubuntu-latest)
Compiler compatibility / Test LLVM 19 WASM (ubuntu-latest)
Compiler compatibility / Test without LLVM Backend
Compiler compatibility / Test MLIR backend

Keep these job names stable. When a required Quick job is renamed or added, update the ruleset in the same rollout; a required check that is never reported leaves PRs blocked. A conditionally skipped job reports success and does not block merging even when required, so required jobs must not be skipped by conditions. Repository variables (vars) are not passed to workflows triggered by PRs from forks, so required jobs must not depend on them either. Exhaustive uses the distinct Extended compiler checks prefix, so an optional Exhaustive result cannot substitute for a required Quick result.

Third-party applications generate bugs for the integration suite; they are not part of ordinary PR checks. The application catalog runs in every Exhaustive run on main (coalesced, so always on the latest main), where it both finds coverage gaps and demonstrates compatibility with real applications, and in every explicitly requested Exhaustive run. There is no automatic exception for changes to serialization, finalization, I/O or GPU lowering.

Caffeine is different: it supplies the coarray runtime backend. Building it, running its own LFortran-compiled unit tests and running every registered coarray capability test remain part of Quick, just as Metal and CUDA-on-CPU integration tests validate particular backends and platforms. Toolchain/runtime dependencies are not the application catalog.

ci/test_caffeine.sh uses Caffeine and its generated run-fpm.sh wrapper, which selects LFortran and the GASNet runner. Unit tests use four images; the PRIF smoke test and integration tests keep their existing image settings. The missing-tool installer uses the same fpm=0.12.0 pin as the application harness. A failed installed tool or unit test is an error, not a reason to skip coverage or reinstall speculatively.

Only the Linux GFortran/OpenCoarrays reference validation is source-dependent in Quick. The shared workflow supplies LFORTRAN_COARRAY_BASE (the PR base SHA or push’s previous SHA) and LFORTRAN_COARRAY_HEAD (the actual checkout SHA). ci/coarray_tests.py shares the harness’s manifest parser and compares registered primary and EXTRAFILES sources, including edits, additions, renames and deletions. Changed coarray registrations, harness/environment inputs or relevant CMake dependencies also request reference validation. Other changed paths default to reference validation, including data files anywhere in the repository, unregistered sources, support files and unknown configuration. This does not depend on finding literal file names or particular I/O statements in the Fortran sources. Only regular compiler implementation files under src/ with the explicit suffixes in COMPILER_SUFFIXES, and simple standalone non-coarray .f90 programs with literal RUN(NAME ... LABELS ...) registrations, can skip this fallback. Both versions of a changed file must qualify; additions/deletions check the existing version. Module/procedure sources, preprocessing, continuations and more complex registrations are intentionally conservative, even when unrelated. Unrelated simple registrations in the manifest retain their fast path. The same comparison rule applies on every event; there is no reduced PR-only LFortran selection.

When those inputs are demonstrably unchanged, neither shared-workflow setup nor the Caffeine script installs OpenMPI/OpenCoarrays for Quick, and no caf/cafrun checks run. Caffeine uses GASNet’s SMP conduit, not MPI. Missing or inconsistent history (including manual runs, new refs or unavailable push bases), dirty checkouts and unresolved source dependencies log conservative reference validation, never an unexplained skip. Even the narrow source-change fast path requires ordinary free-form .f90 coarray sources and known source options; fixed-form/preprocessed/other-language support and unknown options always request reference validation. The additional source guard keeps quoted text and trailing comments rather than guessing where a Fortran comment starts. File I/O (including INQUIRE), foreign bindings, split tokens and continued character literals request reference validation; only explicit standard-output write(*, ...) is exempt. These guards can request extra work, but are not a general Fortran dependency parser and never exempt data or unknown changed paths. Invalid test registrations fail explicitly. Standalone/default and Exhaustive invocations always request full Linux reference validation. macOS retains its existing no-OpenCoarrays behavior; Caffeine unit, smoke and all LFortran integration tests still run. The OpenMPI availability probe uses mpifort --showme:version, which checks the wrapper without invoking its configured build-time compiler. OpenCoarrays’ CMake build still selects GFortran and checks that it can compile and link MPI; a missing or broken reference compiler remains an error.

When an application finds a compiler bug, reduce the failure to a registered integration regression in the relevant modes, fix the compiler, and verify the original application failure. Promptly fix or revert a regression on main. The lasting protection for future PRs is the integration test, not adding the whole application to Quick. Finding such a gap on main is an accepted trade-off, not a reason to silently ignore the failing application check.

Exhaustive on main runs the full LLVM matrix, full platform suites, application, documentation, packaging and JupyterLite checks. Main pushes share one concurrency group per workflow (Quick and Exhaustive), so for each workflow at most one main run is in progress and one is pending. A running main run is never cancelled; a newer push replaces the pending run. The latest main is therefore always tested, but when several pushes land while a run is in progress, the intermediate commits are not tested individually. Their changes are covered by the next run. To test a skipped commit, re-run its cancelled run (gh run rerun <run-id>), which tests exactly that commit; it rejoins the main concurrency group and waits behind the run in progress. workflow_dispatch accepts only a branch or tag, not a commit.

Releases require green main, including application validation. The commit selected for release must have its own green Quick and Exhaustive runs on main; re-run them if that commit was skipped by coalescing. A green Quick PR or extended compiler run is not a substitute. Release-tag workflows still run compiler, documentation and packaging checks; they do not repeat the application catalog already validated on main.

Running Exhaustive for a PR

Exhaustive does not run on PRs. Run it only for rare, explicitly requested extended coverage, for example a particular major refactor. It is not a normal condition for marking a PR ready, and automation must not request it based on the subsystem being changed.

workflow_dispatch accepts only a branch or tag, and PR branches live in forks, so dispatch the workflow in the fork that holds the branch:

gh workflow run Exhaustive-Checks-CI.yml --repo <fork-owner>/lfortran --ref <branch>
gh run list --repo <fork-owner>/lfortran --workflow Exhaustive-Checks-CI.yml \
    --branch <branch> --event workflow_dispatch --limit 1
gh run watch <run-id> --repo <fork-owner>/lfortran

For someone else’s PR, push its head to a branch in your own fork first:

gh pr checkout <PR> --repo lfortran/lfortran
git push <your-fork-remote> HEAD:exhaustive-pr-<PR>
gh workflow run Exhaustive-Checks-CI.yml --repo <your-login>/lfortran --ref exhaustive-pr-<PR>

注意:

  • Forks have GitHub Actions workflows disabled until enabled once in the fork’s Actions tab.

  • The run uses the fork owner’s runners, so it does not compete with lfortran/lfortran CI.

  • The result does not appear among the upstream PR’s checks. Post the run URL and the tested head SHA in the PR, and rerun after new pushes if needed.

  • Exhaustive never invokes Quick, and a green Exhaustive result does not imply a green Quick result. If the PR’s current revision has no successful Quick run, dispatch Quick-Checks-CI.yml the same way.

  • Manual runs do not publish or deploy.

To run the representative integration subset locally:

cd integration_tests
./run_tests.py -b llvm --smoke > smoke.log 2>&1
./run_tests.py -b llvm --smoke -f > smoke-fast.log 2>&1

The explicit list lives in integration_tests/smoke_tests.cmake. Selection happens before targets and configure-time compiler commands are created, including WASM and implicit-interface tests. Backend support labels and normal/fast/standard flags still apply. An empty selected backend is an error. Use the full suite for primary regression coverage; add representative tests to the list when introducing a new feature or platform-sensitive path.