diff --git a/CHANGELOG.md b/CHANGELOG.md index 7a20787e..4039ae9e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,20 @@ > Each `## []` section is that release's notes. Entries are written in English > from 2026.9.28.3 on; earlier entries remain as written. +## [2026.10.16.3] - 2026-10-17 + +### Fixed + +- Keep the toolchain the configuration names for this machine's own target. + `[toolchain] default` with a `default_target` that is the host's triple (a + Luban system's `/etc/mcpp/config.toml`: its gcc on `aarch64-linux-gnu`) was + replaced by the target row's convention, and on aarch64 a first build + downloaded llvm instead of using the system's gcc. A cross target and a + capability pin are unchanged. +- `gcc` for a target that names glibc (`aarch64-linux-gnu`) is the glibc + payload, which `xim:gcc` publishes for aarch64 since 16.1.0; it was + answered with `musl-gcc`. With no target, aarch64 still takes `musl-gcc`. + ## [2026.10.16.2] - 2026-10-17 ### Changed diff --git a/mcpp.toml b/mcpp.toml index 3a889752..ca3ab795 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,6 +1,6 @@ [package] name = "mcpp" -version = "2026.10.16.2" +version = "2026.10.16.3" description = "Modern C++ build & package management tool" license = "Apache-2.0" authors = ["mcpp-community"] diff --git a/modules/versioning/src/version.cppm b/modules/versioning/src/version.cppm index 1ed319fa..eb85b4eb 100644 --- a/modules/versioning/src/version.cppm +++ b/modules/versioning/src/version.cppm @@ -31,6 +31,6 @@ import std; export namespace mcpp { -inline constexpr std::string_view MCPP_VERSION = "2026.10.16.2"; +inline constexpr std::string_view MCPP_VERSION = "2026.10.16.3"; } // namespace mcpp diff --git a/src/build/prepare.cppm b/src/build/prepare.cppm index b4a80290..fbad6fc0 100644 --- a/src/build/prepare.cppm +++ b/src/build/prepare.cppm @@ -85,6 +85,7 @@ import mcpp.toolchain.lifecycle; import mcpp.toolchain.stdmod; import mcpp.toolchain.post_install; import mcpp.toolchain.abi; +import mcpp.toolchain.triple; import mcpp.build.plan; import mcpp.build.flags; // compute_flags — the per-role contracts (#418) import mcpp.build.graph_shape; // #407: the graph says which mode wrote it @@ -279,6 +280,21 @@ export inline bool tc_origin_is_user_explicit(TcOrigin o) { || o == TcOrigin::BuildProgram; } +// IS THIS A PAIR THE CONFIGURATION STATES FOR THE MACHINE'S OWN TARGET? +// +// `[toolchain] default` with a `default_target` that is the host's triple +// names the compiler that serves this machine (a Luban system's +// /etc/mcpp/config.toml: its own gcc on aarch64-linux-gnu). A row's +// convention pin does not replace it: on aarch64 it replaced the system's gcc +// with a download of llvm. A cross target keeps the rule above (the +// windows-gnu regression), and a capability pin always applies. +export inline bool configured_native_pair(bool targetFromGlobalDefault, TcOrigin origin, + const mcpp::toolchain::triple::Triple& target, + const mcpp::toolchain::triple::Triple& host) { + return targetFromGlobalDefault && origin == TcOrigin::GlobalDefault + && !target.pin_is_capability() && target.str() == host.str(); +} + // MAY A BUILD THAT RESOLVED THIS WAY WRITE THE MACHINE'S DEFAULT? // // `GraphRequirement` is the one origin that must not: it is a property of a diff --git a/src/build/prepare/toolchain.cpp b/src/build/prepare/toolchain.cpp index eb81c534..ee4e20bc 100644 --- a/src/build/prepare/toolchain.cpp +++ b/src/build/prepare/toolchain.cpp @@ -464,6 +464,9 @@ struct TargetOverrideCtx { const mcpp::manifest::TargetEntry* sectionEntry = nullptr; bool hasExplicitSection = false; bool hasToolchainOverride = false; + // The target came from the configuration's `default_target`, beside its + // `[toolchain] default`: a pair the configuration states. + bool targetFromGlobalDefault = false; const mcpp::toolchain::triple::TargetInfo* known = nullptr; }; @@ -869,8 +872,13 @@ step1_target_row_pin_and_capability_check(PrepareState& state, TargetOverrideCtx state.targetRowPin = std::string(ctx.known->pin); state.targetRowName = ctx.parsed->str(); } + // A pair the configuration states for this machine's own target is kept + // (`configured_native_pair`). + const bool configuredNativePair = ctx.parsed + && configured_native_pair(ctx.targetFromGlobalDefault, state.tcOrigin, *ctx.parsed, + mcpp::toolchain::triple::host_triple()); if (ctx.known && !ctx.hasToolchainOverride && !ctx.known->pin.empty() - && !tc_origin_is_user_explicit(state.tcOrigin)) { + && !tc_origin_is_user_explicit(state.tcOrigin) && !configuredNativePair) { state.targetPinCandidate = std::string(ctx.known->pin); state.targetPinIsCapability = ctx.parsed && ctx.parsed->pin_is_capability(); } @@ -1012,6 +1020,7 @@ static std::expected step1_target_and_static_overrides(Prepar // override and the vocabulary-table convention (pin + default linkage). if (!state.overrides.target_triple.empty()) { TargetOverrideCtx ctx; + ctx.targetFromGlobalDefault = targetFromGlobalDefault; if (auto r = step1_resolve_target_triple_request(state, ctx); !r) return std::unexpected(r.error()); if (auto r = step1_validate_target_tier(state, ctx); !r) diff --git a/src/toolchain/registry.cppm b/src/toolchain/registry.cppm index c96c4879..d95b5446 100644 --- a/src/toolchain/registry.cppm +++ b/src/toolchain/registry.cppm @@ -695,6 +695,12 @@ bool gcc_native_payload_is_musl(std::string_view hostArch, bool isLinux, if (hostArch == "x86_64") return false; // the glibc payload exists here // "Native" = no explicit target, or one naming this same machine. A CROSS // target keeps its own payload rule (the `-gcc` packages above). + // + // A target that names glibc (`aarch64-linux-gnu`) asks for the glibc + // payload, which `xim:gcc` publishes for aarch64 since 16.1.0 (a Luban + // system's own gcc is that one): answering it with musl-gcc built for + // another C library than the one named. + if (target.env == "gnu") return false; return target.empty() || (target.os == "linux" && target.arch == hostArch); } diff --git a/tests/unit/test_toolchain_registry.cpp b/tests/unit/test_toolchain_registry.cpp index 32d59ac5..e3bd2855 100644 --- a/tests/unit/test_toolchain_registry.cpp +++ b/tests/unit/test_toolchain_registry.cpp @@ -222,9 +222,13 @@ TEST(ToolchainRegistry, NativeGccPayloadFollowsWhatTheArchActuallyPublishes) { EXPECT_FALSE(gcc_native_payload_is_musl( "x86_64", true, {"x86_64", "linux", "gnu"})); - // aarch64: the glibc package has no asset, musl-gcc does. + // aarch64 with no target: musl-gcc, the payload every version publishes. EXPECT_TRUE(gcc_native_payload_is_musl("aarch64", true, none)); EXPECT_TRUE(gcc_native_payload_is_musl( + "aarch64", true, {"aarch64", "linux", "musl"})); + // A target that names glibc asks for the glibc payload (xim:gcc publishes + // aarch64 since 16.1.0; a Luban system's own gcc is that one). + EXPECT_FALSE(gcc_native_payload_is_musl( "aarch64", true, {"aarch64", "linux", "gnu"})); // A CROSS target keeps its own payload rule — this is about the native diff --git a/tests/unit/test_windows_defaults.cpp b/tests/unit/test_windows_defaults.cpp index 3557e630..00202230 100644 --- a/tests/unit/test_windows_defaults.cpp +++ b/tests/unit/test_windows_defaults.cpp @@ -126,3 +126,22 @@ TEST(LinuxDefaults, NativeArm64UsesLlvmAndOtherDefaultsRemainStable) { EXPECT_EQ(row->pin, pins::kFirstRunLinuxAarch64); EXPECT_FALSE(target->pin_is_capability()); } + +// A Luban system's /etc/mcpp/config.toml names its own gcc on the host's +// triple (gcc@16.1.0 + aarch64-linux-gnu); the aarch64-linux-gnu row's llvm +// convention replaced it with a download (xim-pkgindex#986, editions CI on +// arm). The configured pair for the host's own target is kept; a cross target +// and a remembered default without a target are not this case. +TEST(LinuxDefaults, AConfiguredPairForTheHostsOwnTargetKeepsItsToolchain) { + namespace tr = mcpp::toolchain::triple; + using mcpp::build::TcOrigin; + using mcpp::build::configured_native_pair; + auto arm = tr::parse("aarch64-linux-gnu"); + auto x86 = tr::parse("x86_64-linux-gnu"); + auto winGnu = tr::parse("x86_64-windows-gnu"); + ASSERT_TRUE(arm && x86 && winGnu); + EXPECT_TRUE(configured_native_pair(true, TcOrigin::GlobalDefault, *arm, *arm)); + EXPECT_FALSE(configured_native_pair(false, TcOrigin::GlobalDefault, *arm, *arm)) << "--target names it"; + EXPECT_FALSE(configured_native_pair(true, TcOrigin::FirstRun, *arm, *arm)) << "mcpp's own guess"; + EXPECT_FALSE(configured_native_pair(true, TcOrigin::GlobalDefault, *winGnu, *x86)) << "a cross target"; +}