Compile glimmerhmm from source to dodge bioconda's AVX2 baseline (Rosetta 2 SIGILL) - #71
Merged
Merged
Conversation
The bioconda glimmerhmm 3.0.4 recipe (build 10, rebuilt Sep 2025)
compiles x86_64 builds with `-march=x86-64-v3`, the AVX2/BMI2 baseline.
Under Rosetta 2 on Apple Silicon (and on pre-Haswell x86_64) this
SIGILLs at the first call to `build1` during trainGlimmerHMM,
surfacing as `build1 exited funny: 4 at trainGlimmerHMM line 338`
(perl `$? = 4` == SIGILL). This is the same root cause we already
fixed for augustus and pytantan.
glimmerhmm is not packaged in Ubuntu apt, so this commit adds a new
Docker build stage that compiles glimmerhmm 3.0.4 from the upstream
tarball with `-march=x86-64 -mtune=generic` (the v1 baseline). The
build applies the same upstream fixes the bioconda recipe carries
(makefile typo fixes for the `escoreSTOP2` / `rfapp` targets, and
patching trainGlimmerHMM/glimmhmm.pl to use `#!/usr/bin/env perl`
and `FindBin qw($RealBin)` so they self-locate their support
binaries via `$RealBin/../share/glimmerhmm/train`).
The compiled tree is copied into the final stage at /opt/glimmerhmm
using bioconda's bin/ + share/glimmerhmm/{train,trained_dir} layout
so trainGlimmerHMM's self-location keeps working. /opt/glimmerhmm/bin
is prepended to PATH in both the final-stage `ENV PATH=...` and the
entrypoint.sh (the latter is necessary because `pixi shell-hook`
re-prepends /app/.pixi/envs/default/bin during activation and would
otherwise put the bioconda binary back in front).
A defense-in-depth check during the build stage scans the compiled
binaries with objdump for AVX/AVX2/AVX512 mnemonics (ymm/zmm refs,
vpbroadcast, vextracti128, vfmadd, etc.) and fails the build if any
appear. Same approach pytantan uses.
The bioconda glimmerhmm in the pixi env is left in place: on osx-arm64
it provides the arm64-native binary for outside-docker dev work, and
inside the docker image it sits behind /opt/glimmerhmm on PATH as a
shadowed fallback (belt-and-suspenders) — if /opt/glimmerhmm is ever
missing or the self-compiled binaries are unusable, the pixi-env
binary will be picked up automatically.
- Dockerfile: new `glimmerhmm-build` stage; final stage copies
/opt/glimmerhmm and prepends its bin to PATH; entrypoint.sh
re-prepends after the pixi shell-hook.
- pixi.toml: comment-only — documents why glimmerhmm is intentionally
kept in [dependencies] despite being shadowed in the docker image.
nextgenusfs
marked this pull request as ready for review
May 28, 2026 04:36
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Same root cause we already addressed for augustus (PR #70) and pytantan: bioconda's
glimmerhmm3.0.4 binary is compiled with-march=x86-64-v3(AVX2/BMI2 baseline), so it SIGILLs under Rosetta 2 on Apple Silicon and on pre-Haswell x86_64 hardware. In thelinux/amd64Docker image this surfaces as:(perl
$? = 4== SIGILL → illegal instruction →build1was compiled with instructions Rosetta 2 can't emulate.)Unlike augustus,
glimmerhmmis not packaged in Ubuntu apt, so the apt-substitution trick used in PR #70 isn't available. Instead, this PR adds a new Docker build stage that compilesglimmerhmm3.0.4 from the upstream tarball with-march=x86-64 -mtune=generic(the x86-64 v1 baseline) and layers it ontoPATHahead of the bioconda binary in the pixi env.Changes
Dockerfileglimmerhmm-buildstage (Ubuntu noble +build-essential) that:GlimmerHMM-3.0.4.tar.gzfromccb.jhu.edu(sha256-pinned).escoreSTOP2→scoreSTOP2,rfapp→erfapp, drop the nonexistenttrainGlimmerHMMmake-clean target) andtrainGlimmerHMM/glimmhmm.plpatched to#!/usr/bin/env perl+FindBin qw($RealBin)so they self-locate support binaries via$RealBin/../share/glimmerhmm/train.sources/andtrain/withCFLAGS/CXXFLAGS="-O3 -march=x86-64 -mtune=generic ..."./opt/glimmerhmmusing bioconda'sbin/ + share/glimmerhmm/{train,trained_dir}layout.objdumpscans the compiled binaries for AVX/AVX2/AVX512 mnemonics (ymm/zmm refs,vpbroadcast,vextracti128,vfmadd, …) and fails the build if any appear. Same approach pytantan uses.COPY --from=glimmerhmm-build /opt/glimmerhmm /opt/glimmerhmm.ENV PATH=/opt/glimmerhmm/bin:/app/.pixi/envs/default/bin:...so the self-compiled binary wins over the pixi-env bioconda binary.entrypoint.shre-prepends/opt/glimmerhmm/bintoPATHafter thepixi shell-hookactivation — necessary because the shell-hook re-prepends/app/.pixi/envs/default/binand would otherwise put the bioconda binary back in front.pixi.tomlglimmerhmm = "*"is intentionally kept in[dependencies]despite being shadowed in the docker image: onosx-arm64it provides the arm64-native binary for outside-docker dev work, and inside the image it sits behind/opt/glimmerhmmonPATHas a shadowed fallback.Why a fallback?
funannotate2 invokes glimmerhmm via PATH-resolved binary names (
trainGlimmerHMM,glimmerhmm,glimmhmm.pl) — confirmed by greppingfunannotate2/abinitio.py,train.py,predict.py. With/opt/glimmerhmm/binat the front ofPATH, the self-compiled v1-baseline binaries win. If/opt/glimmerhmmever goes missing (corrupted COPY, manual edit), the bioconda binary in the pixi env will be picked up automatically — at which point Rosetta 2 will SIGILL again, but on a native x86_64 host it'll just keep working.Verification
git diffconfirms onlyDockerfileandpixi.tomlchange;pixi.lockis untouched.trainGlimmerHMMrun under Rosetta 2) still needs to happen before merging.Related
Pull Request opened by Augment Code with guidance from the PR author