Skip to content

Compile glimmerhmm from source to dodge bioconda's AVX2 baseline (Rosetta 2 SIGILL) - #71

Merged
nextgenusfs merged 1 commit into
mainfrom
fix-glimmerhmm-sigill
May 28, 2026
Merged

Compile glimmerhmm from source to dodge bioconda's AVX2 baseline (Rosetta 2 SIGILL)#71
nextgenusfs merged 1 commit into
mainfrom
fix-glimmerhmm-sigill

Conversation

@nextgenusfs

Copy link
Copy Markdown
Owner

Summary

Same root cause we already addressed for augustus (PR #70) and pytantan: bioconda's glimmerhmm 3.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 the linux/amd64 Docker image this surfaces as:

[May 27 03:17 PM] ERROR 43: /app/.pixi/envs/default/bin/../share/glimmerhmm/train/build1 exited funny: 4 at /app/.pixi/envs/default/bin/trainGlimmerHMM line 338.

(perl $? = 4 == SIGILL → illegal instruction → build1 was compiled with instructions Rosetta 2 can't emulate.)

Unlike augustus, glimmerhmm is 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 compiles glimmerhmm 3.0.4 from the upstream tarball with -march=x86-64 -mtune=generic (the x86-64 v1 baseline) and layers it onto PATH ahead of the bioconda binary in the pixi env.

Changes

  • Dockerfile

    • New glimmerhmm-build stage (Ubuntu noble + build-essential) that:
      • Downloads GlimmerHMM-3.0.4.tar.gz from ccb.jhu.edu (sha256-pinned).
      • Applies the same upstream patches the bioconda recipe carries — makefile typo fixes (escoreSTOP2scoreSTOP2, rfapperfapp, drop the nonexistent trainGlimmerHMM make-clean target) and trainGlimmerHMM / glimmhmm.pl patched to #!/usr/bin/env perl + FindBin qw($RealBin) so they self-locate support binaries via $RealBin/../share/glimmerhmm/train.
      • Compiles sources/ and train/ with CFLAGS/CXXFLAGS="-O3 -march=x86-64 -mtune=generic ...".
      • Installs into /opt/glimmerhmm using bioconda's bin/ + share/glimmerhmm/{train,trained_dir} layout.
      • Defense-in-depth check: objdump scans 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.
    • Final stage:
      • 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.sh re-prepends /opt/glimmerhmm/bin to PATH after the pixi shell-hook activation — necessary because the shell-hook re-prepends /app/.pixi/envs/default/bin and would otherwise put the bioconda binary back in front.
  • pixi.toml

    • Comment-only change explaining why glimmerhmm = "*" is intentionally kept in [dependencies] despite being shadowed in the docker image: on osx-arm64 it provides the arm64-native binary for outside-docker dev work, and inside the image it sits behind /opt/glimmerhmm on PATH as a shadowed fallback.

Why a fallback?

funannotate2 invokes glimmerhmm via PATH-resolved binary names (trainGlimmerHMM, glimmerhmm, glimmhmm.pl) — confirmed by grepping funannotate2/abinitio.py, train.py, predict.py. With /opt/glimmerhmm/bin at the front of PATH, the self-compiled v1-baseline binaries win. If /opt/glimmerhmm ever 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 diff confirms only Dockerfile and pixi.toml change; pixi.lock is untouched.
  • Smoke test (Docker build + trainGlimmerHMM run under Rosetta 2) still needs to happen before merging.

Related


Pull Request opened by Augment Code with guidance from the PR author

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
nextgenusfs marked this pull request as ready for review May 28, 2026 04:36
@nextgenusfs
nextgenusfs merged commit f80b5f8 into main May 28, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant