Summary
Binaries produced by perry publish linux use CPU instructions that are absent on x86-64 CPUs without AVX-512 (e.g. AMD EPYC "Rome" / Zen2, which supports up to x86-64-v3/AVX2 but not AVX-512). The binary crashes with SIGILL (invalid opcode) at startup, before any application output.
The same binary runs fine on an AVX-512-capable CPU (Intel Xeon "Skylake-SP"), so this is a target-baseline problem, not a codegen bug — and it strongly implicates AVX-512.
Critically, there appears to be no working way to constrain the target CPU baseline for perry publish. The [build] knobs I tried are silently ignored, and the one env var that changes output produces a malformed artifact (details below).
Impact: Perry-native services can't be deployed to non-AVX-512 hosts, which includes a lot of older/cheaper cloud instances still in production.
Environment
perry --version: 0.5.1239 (CLI)
- Build server: Perry Publish v0.5.1239 (
hub.perryts.com)
- Target:
linux x86-64, glibc (default)
- App: a fastify HTTP server (uses
perry-ext-fastify well-known routing)
- Fails on: AMD EPYC "Rome" (Zen2) — has AVX2/BMI2 (
x86-64-v3), no AVX-512
- Runs on: Intel Xeon "Skylake" — has AVX-512
Reproduction
// src/main.ts
import Fastify from 'fastify';
const app = Fastify({ logger: false });
app.get('/health', async () => ({ ok: true }));
await app.listen({ port: 8095, host: '127.0.0.1' });
console.log('listening');
# perry.toml
[project]
name = "repro"
entry = "src/main.ts"
icons = { source = "assets/icon.png" } # required or appimagetool fails
[build]
out_dir = "dist"
opt_level = 2
perry publish linux --skip-verify -o dist
- Extract the ELF from the produced AppImage (
--appimage-extract; the binary is usr/bin/repro).
- Run it on a Zen2 / EPYC-Rome host:
$ ./repro
Illegal instruction (core dumped) # crashes BEFORE "listening" prints
dmesg:
traps: repro[...] trap invalid opcode ip:...:2d2 sp:... error:0 in repro[...+d5a000]
The fault is at a fixed module offset each run, before any stdout → it's in the Perry runtime/stdlib init, not app code.
- Run the same binary on a Skylake (AVX-512) host → boots fine, serves
{"ok":true} on /health. ✅
Things I tried to lower the baseline — all failed
| Attempt |
Result |
[build] native_tuning = false |
ignored — identical output (same size, same SIGILL) |
[build] march = "x86-64-v3" |
ignored — identical output (same size, same SIGILL) |
PERRY_NO_AUTO_OPTIMIZE=1 |
changed output, but the downloaded linux artifact is not a valid ELF (first bytes 00 00 40 00; unsquashfs reports "Can't find a valid SQUASHFS superblock") — separate packaging bug |
--libc musl |
link fails: undefined reference to js_fastify_reply_send / js_fastify_listen / js_fastify_get / js_fastify_add_hook / ... — perry-ext-fastify seems unavailable for the musl target |
So neither the documented-looking [build] keys nor the escape hatches yield a runnable binary on a non-AVX-512 host.
Asks
- Primary: make
perry publish linux default to a portable baseline (x86-64-v2 or -v3), or honor a documented [build] key (march / target-cpu / baseline) that constrains both app code and the prebuilt runtime/stdlib. Auto-optimize appears to tune the runtime to the build server's CPU (AVX-512), which is not portable.
- Related:
perry-ext-fastify fails to link under --libc musl (undefined js_fastify_*).
- Related:
PERRY_NO_AUTO_OPTIMIZE=1 produces a malformed (non-ELF) linux artifact.
Happy to provide the failing binary, full build logs, or /proc/cpuinfo from both hosts.
Summary
Binaries produced by
perry publish linuxuse CPU instructions that are absent on x86-64 CPUs without AVX-512 (e.g. AMD EPYC "Rome" / Zen2, which supports up tox86-64-v3/AVX2 but not AVX-512). The binary crashes withSIGILL(invalid opcode) at startup, before any application output.The same binary runs fine on an AVX-512-capable CPU (Intel Xeon "Skylake-SP"), so this is a target-baseline problem, not a codegen bug — and it strongly implicates AVX-512.
Critically, there appears to be no working way to constrain the target CPU baseline for
perry publish. The[build]knobs I tried are silently ignored, and the one env var that changes output produces a malformed artifact (details below).Impact: Perry-native services can't be deployed to non-AVX-512 hosts, which includes a lot of older/cheaper cloud instances still in production.
Environment
perry --version: 0.5.1239 (CLI)hub.perryts.com)linuxx86-64, glibc (default)perry-ext-fastifywell-known routing)x86-64-v3), no AVX-512Reproduction
perry publish linux --skip-verify -o dist--appimage-extract; the binary isusr/bin/repro).dmesg:The fault is at a fixed module offset each run, before any stdout → it's in the Perry runtime/stdlib init, not app code.
{"ok":true}on/health. ✅Things I tried to lower the baseline — all failed
[build] native_tuning = false[build] march = "x86-64-v3"PERRY_NO_AUTO_OPTIMIZE=100 00 40 00;unsquashfsreports "Can't find a valid SQUASHFS superblock") — separate packaging bug--libc muslundefined reference to js_fastify_reply_send / js_fastify_listen / js_fastify_get / js_fastify_add_hook / ...—perry-ext-fastifyseems unavailable for the musl targetSo neither the documented-looking
[build]keys nor the escape hatches yield a runnable binary on a non-AVX-512 host.Asks
perry publish linuxdefault to a portable baseline (x86-64-v2or-v3), or honor a documented[build]key (march/target-cpu/baseline) that constrains both app code and the prebuilt runtime/stdlib. Auto-optimize appears to tune the runtime to the build server's CPU (AVX-512), which is not portable.perry-ext-fastifyfails to link under--libc musl(undefinedjs_fastify_*).PERRY_NO_AUTO_OPTIMIZE=1produces a malformed (non-ELF) linux artifact.Happy to provide the failing binary, full build logs, or
/proc/cpuinfofrom both hosts.