// SPDX-License-Identifier: LGPL-3.0-only // SPDX-FileCopyrightText: Copyright (C) 2026 Catcrafts® export module Crafter.Build:Toolchain; import std; namespace fs = std::filesystem; export namespace Crafter { // The compiler crafter-build drives and what sits next to it, resolved // once per process by GetToolchain(). Every clang++, clang and llvm-ar // the tool spawns, the libclang the linter dlopens, the std module // source and the default sysroots come from here, so a toolchain // installed anywhere other than /usr (the Flatpak carries its own under // /app) needs no per-call-site knowledge. struct Toolchain { // LLVM install prefix. Empty when the tools are bare names on PATH. fs::path prefix; fs::path clangxx; fs::path clang; fs::path llvmAr; // Where clang-c/Index.h lives when it is not on the default include // path; empty otherwise. fs::path llvmIncludeDir; // The exact libclang to dlopen; nullopt means search the usual names. std::optional libclang; // A libc++ install other than the compiler's own // (CRAFTER_BUILD_LIBCXX_DIR); empty means clang finds its own. fs::path libcxxDir; // libc++'s std module source for host builds. fs::path stdCppm; fs::path wasiSysroot; // Holds include/c++//bits/std.cc for the mingw target. Passed to // clang as --sysroot only when it was set explicitly: clang's own // mingw discovery handles the distro layout, and a --sysroot pointing // at the triple directory would lose crtbegin.o and libgcc. fs::path mingwSysroot; bool mingwSysrootExplicit = false; // `clang++ -print-target-triple` and the first line of // `clang++ --version`; both empty when clang++ could not be run. std::string hostTriple; std::string clangVersion; // Why clang++ could not be resolved or run; empty when it could. std::string error; // Flags for compiling against libcxxDir; empty without one. std::string LibcxxCompileFlags() const; // Flags for linking against the libc++ the compiler will use: a -L // and an rpath for /lib when the prefix is not the system one // (clang searches only its per-target runtime directory and the // system paths, and a bundled toolchain's libc++.so.1 is on neither // the linker's nor the loader's default path), or for an explicit // libcxxDir. std::string LibcxxLinkFlags() const; // Names this toolchain for cache directory names: the clang version // followed by a hash of what decides which headers and libraries a // PCM is built against. Two toolchains with different keys never // share a PCM. std::string Key() const; }; // What ResolveToolchain reads, so a test can feed it a staged layout. struct ToolchainInputs { // The CRAFTER_* variables, present only when set and non-empty. std::map> env; // The of /share/crafter-build; empty when unknown. fs::path crafterPrefix; }; // Pure path resolution: an env override wins, then a toolchain installed // beside crafter-build (/bin/clang++), then bare names on // PATH. Never runs a process, so hostTriple and clangVersion stay empty. Toolchain ResolveToolchain(const ToolchainInputs& inputs); // ResolveToolchain over the real environment plus the two clang probes, // computed once and cached. Never throws. const Toolchain& GetToolchain(); // GetToolchain(), or a std::runtime_error carrying its error. const Toolchain& RequireToolchain(); // The version baked in when crafter-build was built; "0.0.0-dev" for a // build that was given none. std::string_view CrafterBuildVersion(); }