La prueba de la caja recién instalada —`cargo build` en un proyecto nuevo, sin flags ni rutas a mano— falló con `linker `cc` not found`, y destapó que la pieza que había empaquetado era falsa: **cargo NO LEE `/etc/cargo/config.toml`**. Sólo lee `$CARGO_HOME/config.toml`, los `.cargo/config.toml` del proyecto y sus padres, y lo que se le pase con `--config` — que es lo que yo venía pasando a mano en cada prueba, y por eso «funcionaba». Y el arreglo no era mover el fichero: **el que enlaza es `rustc`, y rustc no lee la config de cargo**. Las flags van DENTRO del compilador, en el spec del triple: · `linker = "ld.lld"` + `linker_flavor = Gnu(Cc::No, Lld::Yes)` — sin esto rustc busca `cc`, que una caja takana no tiene. · `crt_static_default = true` — sin esto enlaza dinámico y pide `-lgcc`, que no existe (la distro se construye con zig, que trae compiler-rt). · `crt_static_allows_dylibs = true` — su pareja obligatoria: sin ella `crt-static` apaga los dylibs y con ellos los PROC-MACROS (serde_derive, clap_derive, las 44 recetas `cargo-*` con `derive`). El compilador en sí sigue dinámico: el `bootstrap.toml` fija `crt-static = false` para el build, y eso gana sobre el default del spec. ⇒ `cargo-config` (receta, árbol y copia en scripts/) se van enteros: un paquete que instala un fichero que nadie abre es peor que no tenerlo. Y de paso, `lld21` instala los cuatro alias como SYMLINKS y no como copias: cmake los duplicaba, 5 × 96 M = 478 M de artefacto para 97 M de enlazador. Ahora 108 M, y `ld.lld` sigue despachando por `argv[0]`, que es como upstream lo diseñó. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
85 lines
4.6 KiB
Diff
85 lines
4.6 KiB
Diff
Registra el triple de Alpine `x86_64-alpine-linux-musl` como target de rustc.
|
|
|
|
POR QUÉ (SDD 31 §4.bis). El build usa el triple de Alpine en todas partes porque el stage0 es el
|
|
rustc del LAB y Alpine RENOMBRA su triple: con el canónico, el stage0 no tiene la std
|
|
(`can't find crate for std`). Pero ese nombre lo conoce el rustc de Alpine y NO el de upstream, así
|
|
que en el stage 2 —cuando toma el relevo el compilador que acabamos de construir— el build muere:
|
|
|
|
error: error loading target specification: could not find specification for target
|
|
"x86_64-alpine-linux-musl"
|
|
|
|
O sea: el triple que hace falta para ARRANCAR el build es el que el PRODUCTO del build no tiene.
|
|
Esto lo mete DENTRO del compilador, que es lo que hace Alpine en su APKBUILD, y por eso vale en
|
|
todos los stages (un `.json` por `RUST_TARGET_PATH` no sirve para el triple del HOST).
|
|
|
|
La única diferencia real con el spec canónico es `crt_static_default = false`: es lo que habilita
|
|
dylibs y, con ellos, los PROC-MACROS. Un rustc con `crt-static` por default no puede compilar
|
|
`serde_derive` ni `clap_derive` — ni las 44 recetas `cargo-*` del corpus que usan `derive`.
|
|
|
|
--- /dev/null
|
|
+++ b/compiler/rustc_target/src/spec/targets/x86_64_alpine_linux_musl.rs
|
|
@@ -0,0 +1,53 @@
|
|
+use crate::spec::{
|
|
+ Arch, Cc, LinkerFlavor, Lld, SanitizerSet, StackProbeType, Target, TargetMetadata, base,
|
|
+};
|
|
+
|
|
+pub(crate) fn target() -> Target {
|
|
+ let mut base = base::linux_musl::opts();
|
|
+ base.cpu = "x86-64".into();
|
|
+ base.plt_by_default = false;
|
|
+ base.max_atomic_width = Some(64);
|
|
+ base.add_pre_link_args(LinkerFlavor::Gnu(Cc::Yes, Lld::No), &["-m64"]);
|
|
+ base.stack_probes = StackProbeType::Inline;
|
|
+ base.static_position_independent_executables = true;
|
|
+ base.supported_sanitizers = SanitizerSet::ADDRESS
|
|
+ | SanitizerSet::CFI
|
|
+ | SanitizerSet::LEAK
|
|
+ | SanitizerSet::MEMORY
|
|
+ | SanitizerSet::THREAD;
|
|
+ base.supports_xray = true;
|
|
+ // ── ESTÁTICO POR DEFECTO, PERO CON DYLIBS ─────────────────────────────────────────────────
|
|
+ // `crt_static_default = true` es lo que hace que un `rustc hola.rs` produzca un binario que
|
|
+ // CORRE en una caja takana: sin él, rustc enlaza dinámico y pide `-lgcc`, que no existe —la
|
|
+ // distro se construye con zig, que trae compiler-rt—, y el enlace muere en `cannot find -lgcc`.
|
|
+ // `crt_static_allows_dylibs = true` es su pareja obligatoria: sin ella, `crt-static` apaga los
|
|
+ // dylibs y con ellos los PROC-MACROS (`serde_derive`, `clap_derive` y las 44 recetas `cargo-*`
|
|
+ // del corpus que usan `derive`). Los dos juntos = binarios estáticos y proc-macros vivos.
|
|
+ // El compilador EN SÍ sigue siendo dinámico: el `bootstrap.toml` fija `crt-static = false` para
|
|
+ // el build, que gana sobre este default.
|
|
+ base.crt_static_default = true;
|
|
+ base.crt_static_allows_dylibs = true;
|
|
+
|
|
+ // ── EL ENLAZADOR, EN EL COMPILADOR Y NO EN UN FICHERO DE CONFIG ───────────────────────────
|
|
+ // Sin esto, `rustc` busca `cc` —que una caja takana NO TIENE— y falla con `linker \`cc\` not
|
|
+ // found`. Ponerlo acá y no en un `config.toml` de cargo es la diferencia entre «takana compila
|
|
+ // Rust» y «takana compila Rust si sabés tres flags»: el que compila es rustc, y rustc no lee la
|
|
+ // config de cargo. `ld.lld` lo publica `recipes/lld21.toml`, que va en el mismo perfil.
|
|
+ base.linker = Some("ld.lld".into());
|
|
+ base.linker_flavor = LinkerFlavor::Gnu(Cc::No, Lld::Yes);
|
|
+
|
|
+ Target {
|
|
+ llvm_target: "x86_64-alpine-linux-musl".into(),
|
|
+ metadata: TargetMetadata {
|
|
+ description: Some("64-bit Alpine Linux with musl (triple propio de Alpine)".into()),
|
|
+ tier: Some(3),
|
|
+ host_tools: Some(true),
|
|
+ std: Some(true),
|
|
+ },
|
|
+ pointer_width: 64,
|
|
+ data_layout:
|
|
+ "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(),
|
|
+ arch: Arch::X86_64,
|
|
+ options: base,
|
|
+ }
|
|
+}
|
|
--- a/compiler/rustc_target/src/spec/mod.rs
|
|
+++ b/compiler/rustc_target/src/spec/mod.rs
|
|
@@ -1506,6 +1506,7 @@
|
|
("aarch64-unknown-linux-musl", aarch64_unknown_linux_musl),
|
|
("aarch64_be-unknown-linux-musl", aarch64_be_unknown_linux_musl),
|
|
("x86_64-unknown-linux-musl", x86_64_unknown_linux_musl),
|
|
+ ("x86_64-alpine-linux-musl", x86_64_alpine_linux_musl),
|
|
("i686-unknown-linux-musl", i686_unknown_linux_musl),
|
|
("i586-unknown-linux-musl", i586_unknown_linux_musl),
|
|
("mips-unknown-linux-musl", mips_unknown_linux_musl),
|