# compiler-rt-profile — la runtime de PERFILADO de compiler-rt para el target nativo. # # QUÉ ES: `libclang_rt.profile.a`, la librería que implementa los `__llvm_profile_*` y que ESCRIBE # los ficheros `.profraw`. Sin ella, `-fprofile-generate` compila y no enlaza. # # ══ POR QUÉ EXISTE: EL LAB NO TRAE NINGUNA RUNTIME DE COMPILER-RT ══════════════════════════════ # Lo descubrió el build del firefox instrumentado, en el minuto 38:56: # # ld.lld: error: cannot open # /usr/lib/llvm22/lib/clang/22/lib/x86_64-alpine-linux-musl/libclang_rt.profile.a # # El lab trae clang 22.1.8 con su `include/` pero **el `lib/` del resource dir no existe** — es # exactamente lo que ya documentaba `recipes/wasi-compiler-rt.toml` para el caso wasm. Esta receta # es su HERMANA NATIVA: mismo tarball, mismo patrón, mismo sitio de aterrizaje; lo que cambia es el # target (x86_64 en vez de wasm32) y el componente (profile en vez de builtins). # # ⚠ LA VERSIÓN SIGUE A LA DEL LAB, igual que su hermana y por lo mismo: la runtime de perfilado es # un contrato con el clang que la va a usar (el formato del `.profraw` tiene versión). El tarball es # 22.1.8 y el lab trae llvm22 22.1.8-r1. Como `clang`/`llvm` son prefijos de `TOOLCHAIN_PREFIXES`, # un bump del lab mueve la huella y re-hashea esto solo: la alineación está vigilada, no confiada. # # DÓNDE ATERRIZA: `/usr/lib/llvm22/lib/clang/22/lib//`, que es donde clang la busca sin que # nadie le pase un flag — el layout "per-target runtime dir", que es el que nombra el error. En el # lab ese directorio no existe y las deps se apilan como overlay BAJO el rootfs, así que esta receta # lo CREA sin pisar nada. name = "compiler-rt-profile" version = "22.1.8" license = "Apache-2.0 WITH LLVM-exception" [source] tarball = "https://github.com/llvm/llvm-project/releases/download/llvmorg-22.1.8/llvm-project-22.1.8.src.tar.xz" sha256 = "922f1817a0df7b1489272d18134ee0087a8b068828f87ac63b9861b1a9965888" [build] compiler = "clang" [deps] # `python3` por lo mismo que en la hermana: el CMakeLists de compiler-rt busca Python3 y sin él cae # a un `find_package(Python2 ... REQUIRED)` que muere diciendo «Could NOT find Python2» — el mensaje # nombra el fallback, no la causa. build = ["cmake", "samurai", "python3"] [build.phases] configure = ''' set -e # Se apaga TODO menos profile. compiler-rt trae sanitizers, xray, memprof, orc… y ninguno hace falta # acá; construirlos multiplicaría el tiempo y ampliaría la superficie de fallo sin destinatario. unset CFLAGS CXXFLAGS LDFLAGS cmake -B build -G Ninja -S compiler-rt -Wno-dev \ -DCMAKE_BUILD_TYPE=MinSizeRel \ -DCMAKE_C_COMPILER=clang \ -DCMAKE_CXX_COMPILER=clang++ \ -DCMAKE_AR=/usr/bin/llvm-ar \ -DCMAKE_RANLIB=/usr/bin/llvm-ranlib \ -DCOMPILER_RT_DEFAULT_TARGET_ONLY=ON \ -DCMAKE_C_COMPILER_TARGET=x86_64-alpine-linux-musl \ -DCMAKE_CXX_COMPILER_TARGET=x86_64-alpine-linux-musl \ -DCMAKE_ASM_COMPILER_TARGET=x86_64-alpine-linux-musl \ -DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=ON \ -DCOMPILER_RT_BUILD_PROFILE=ON \ -DCOMPILER_RT_BUILD_BUILTINS=OFF \ -DCOMPILER_RT_BUILD_SANITIZERS=OFF \ -DCOMPILER_RT_BUILD_XRAY=OFF \ -DCOMPILER_RT_BUILD_LIBFUZZER=OFF \ -DCOMPILER_RT_BUILD_MEMPROF=OFF \ -DCOMPILER_RT_BUILD_ORC=OFF \ -DCOMPILER_RT_BUILD_CTX_PROFILE=OFF \ -DCOMPILER_RT_INCLUDE_TESTS=OFF \ -DCMAKE_INSTALL_PREFIX=/usr/lib/llvm22/lib/clang/22/ ''' compile = 'cmake --build build' install = ''' set -e DESTDIR=/out cmake --install build RES=/out/usr/lib/llvm22/lib/clang/22 # El `include/` del resource dir es del LAB (los headers de clang). Instalarlo desde acá lo taparía # con una copia del tarball — la misma trampa que su hermana wasm documenta y evita. rm -rf "$RES/include" # ── GUARDIÁN 1: el fichero EXACTO que el enlazador pidió ───────────────────────────────────── # No «alguna libclang_rt»: la ruta literal del error, porque el layout per-target es una opción de # cmake y equivocarla deja la librería instalada donde clang no mira. Es el mismo fallo que la # libstdc++ en /usr/lib64 de esta misma noche, un directorio más allá. A="$RES/lib/x86_64-alpine-linux-musl/libclang_rt.profile.a" test -s "$A" || { echo "!! no está $A — ¿cambió el layout del resource dir?" >&2 find /out -name 'libclang_rt*' >&2 exit 1 } echo "guardián: $A ($(stat -c%s "$A") bytes)" # ── GUARDIÁN 2: LA PRUEBA DEL CONSUMIDOR ───────────────────────────────────────────────────── # «Existe» no es «sirve». Se exige que DEFINA lo que un binario instrumentado va a buscar: la # función que vuelca el `.profraw` y el contador de versión del formato. Si el `.a` sale vacío o # con otro componente dentro, esto lo caza acá y no al final de una corrida de perfilado. falta="" for s in __llvm_profile_write_file __llvm_profile_get_version __llvm_profile_initialize_file; do llvm-nm --defined-only "$A" 2>/dev/null | grep -qE " $s(@|$)" || falta="$falta $s" done test -z "$falta" || { echo "!! el .a no define:$falta" >&2; exit 1; } echo "guardián: define los símbolos que emite -fprofile-generate" '''