Skip to content

Embed build/version info into spank_qrmi binary - #202

Merged
ohtanim merged 12 commits into
qiskit-community:mainfrom
ohtanim:version_info_in_binary
Aug 28, 2026
Merged

ohtanim merged 12 commits into
qiskit-community:mainfrom
ohtanim:version_info_in_binary

Conversation

@ohtanim

@ohtanim ohtanim commented Aug 27, 2026 •

Copy link
Copy Markdown
Collaborator

Description of Change

Review & Approve

Urgency: Not urgent. That said, a quick review would give us a chance to get this into the current customer upgrade window, so faster turnaround is appreciated if feasible.

Target date: Hoping to complete within one week.

Background

We recently ran into an issue during a cluster upgrade at one of our customers' data centers: quantum workloads stopped running due to a version mismatch between the deployed spank plugin binary and the QRMI Python package. While investigating, it became clear that being able to quickly determine

  • (a) which version of the spank plugin binary was actually deployed, and
  • (b) which version of QRMI it was linked against
    would have made this kind of issue much easier to diagnose.
    As described in this PR, I addressed this by embedding version information directly into the binary's ELF headers, making it possible to retrieve the relevant version information with standard Linux commands.

Summary

Currently there is no way to determine which version of spank_qrmi.so is actually deployed without rebuilding or running the plugin. This PR embeds that information as a plain string in the binary so it can be inspected
offline with strings / readelf, e.g.:

$ strings spank_qrmi.so | grep SPANK_QRMI
SPANK_QRMI_BUILD_VERSION=0.11.0;SPANK_QRMI_GIT_HASH=0dac1793b013

$ readelf -p .version_info spank_qrmi.so
String dump of section '.version_info':
  [     0]  SPANK_QRMI_BUILD_VERSION=0.11.0;SPANK_QRMI_GIT_HASH=0dac1793b013

QRMI will embed the same kind of marker into its own .version_info section (see the companion change in the QRMI crate), so the two show up side by side in the same linked .so:

$ strings spank_qrmi.so | grep -E "SPANK_QRMI|QRMI_BUILD"
SPANK_QRMI_BUILD_VERSION=0.11.0;SPANK_QRMI_GIT_HASH=0dac1793b013
QRMI_BUILD_VERSION:0.24.0;QRMI_GIT_HASH:7a9573703ac4

$ readelf -p .version_info spank_qrmi.so
String dump of section '.version_info':
  [     0]  SPANK_QRMI_BUILD_VERSION=0.11.0;SPANK_QRMI_GIT_HASH=0dac1793b013
  [    3b]  QRMI_BUILD_VERSION:0.24.0;QRMI_GIT_HASH:7a9573703ac4

This lets an operator answer "which spank_qrmi build, and which QRMI build, are actually linked into this .so?" directly from the deployed file, without rebuilding or invoking the plugin.

Changes

  • CMakeLists.txt:
    • Adds VERSION x.y.z to the existing project(spank_qrmi ...) declaration, so this plugin's own version is CMake's standard PROJECT_VERSION, bumped by hand as part of a release PR.
    • Resolves this repo's own short git commit hash (git rev-parse --short=12 HEAD), falling back to "unknown" when built outside a git checkout (e.g. a tarball/zip export).
    • Writes spank_qrmi_version.h under ${CMAKE_BINARY_DIR}/generated via file(WRITE ...). Both values are known at cmake .. configure time (unlike QRMI's own version, which is only available after its ExternalProject fetch step), so no extra build-time step, target dependency, or separate template file is needed here.
  • spank_qrmi.c: includes the generated spank_qrmi_version.h and embeds a version string in a dedicated .version_info ELF section via __attribute__((section(".version_info"), used)), readable with strings or readelf -p .version_info without executing the plugin.

Note: an earlier version of this PR also duplicated QRMI's own crate version/git-hash into this same string. That's been dropped now that QRMI embeds its own .version_info marker directly (see the companion QRMI PR),
so spank_qrmi.so's string only needs to describe itself.

Testing

  • Compiled with the project's existing strict flags (-Wall -Wextra -Werror -O2 -pedantic -Wconversion -Wwrite-strings -Wfloat-equal) with no new warnings.
  • Confirmed the embedded string is visible via both strings and readelf -p .version_info on the compiled object, and that it coexists correctly in the same section alongside QRMI's own marker once linked together (same section name, distinct symbol names — no collision).
  • Confirmed the full cmake .. && make build against the real QRMI ExternalProject fetch path (both default GitHub fetch and -DQRMI_ROOT=local-checkout path), and a check that the linked spank_qrmi.so still loads correctly under slurmd.

Notes / follow-ups

  • If a deployment pipeline runs strip -s (full strip) on the final .so, custom ELF sections like .version_info can be removed along with symbol tables. If binary stripping is part of the deploy process, either use strip --strip-debug instead, or add --keep-section=.version_info to whatever strip/objcopy invocation is used.
  • This plugin's own version needs to be bumped by hand in the project(...VERSION x.y.z) line as part of future release PRs; it isn't tied to git tags, and isn't currently overridable from the cmake command line
    (project(VERSION ...) always wins over any -D of the same name).
  • Requires the companion QRMI-side change (embedding QRMI's own .version_info marker) to get the full picture; this PR alone only covers the spank_qrmi side.
  • Not a behavior change to the plugin itself — purely additive metadata.

Related

qiskit-community/qrmi#225

Checklist ✅

  • Have you included a description of this change?
  • Have you updated the relevant documentation to reflect this change?
  • Have you made sure CI is passing before requesting a review?

Ticket

  • Fixes #
  • Is Part of #

@ohtanim ohtanim added the enhancement New feature or request label Aug 27, 2026
@ohtanim ohtanim self-assigned this Aug 27, 2026
@ohtanim
ohtanim marked this pull request as ready for review August 27, 2026 04:33

@badtst badtst left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Lgtm !

Comment thread docs/FAQ.md Resolved
Comment thread plugins/spank_qrmi/CMakeLists.txt Outdated
Comment on lines +96 to +103
# Version of this plugin itself: read from VERSION.txt, a plain one-line
# file checked into the repo (see VERSION.txt next to this CMakeLists.txt).
# This is deliberately NOT derived from `git describe`: it works the same
# way whether built from a full git clone, a release tarball, or a zip
# export with no .git directory, and a version bump shows up as a normal,
# reviewable one-line diff in the PR instead of depending on someone
# remembering to push a tag.
set(SPANK_QRMI_VERSION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/VERSION.txt")

@badtst badtst Aug 27, 2026 •

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I'd set the version directly in the cmake project() directly. Still as visible in git diffs as VERSION.txt imho and doesn't need all this extra cmake logic

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for comment.

I think people will probably have different preferences on this. Personally, I prefer this approach because I don't want to update the CMakeLists.txt file frequently. Another advantage is that if we introduce CI workflows in the future, a simple VERSION.txt file would be easier to integrate into those workflows. I'd also be interested in hearing other people's opinions on this point.

@ohtanim ohtanim Aug 27, 2026 •

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@awennersteen @MatthieuMoreau0 @yoonho @OkuyanBoga What do you think above?

There are 2 solutions for now. I'm open to switching the current implementation to project(spank_qrmi VERSION x.y.z) as I described:

VERSION.txt needs to be bumped by hand as part of future release PRs; it isn't tied to git tags. Open to switching this to project(spank_qrmi VERSION x.y.z) in CMakeLists.txt instead if that's preferred as the single source of truth — happy to adjust either way.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@badtst I implemented the alternative approach and committed it. Thinking about it further, I can see your point. It does seem simpler and closer to the conventional way of handling versioning in CMake. Regarding CI, I don't see a significant difference in effort between the two approaches. In either case, updating the version would amount to a straightforward one-line file replacement. Could you please take a look at the latest updates when you have time?

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll take a look. Sure both options work but I feel like the spank plugin does not iterate nearly as fast as the QRMI itself and versions bump do not happen this frequently

@badtst badtst left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works as expected on my side, lgtm

@ohtanim

ohtanim commented Aug 27, 2026 •

Copy link
Copy Markdown
Collaborator Author

After talking with @yoonho, I reconsidered the current implementation. At the moment, the SPANK plugin writes not only its own version information but also the version and Git hash of the statically linked QRMI library into .version_info. However, I now think that the QRMI-related information should be written by the QRMI library itself because libqrmi.so should also provide similar .version_info for diagnostics.
I am going to update this PR accordingly, including changes on the QRMI side. Please hold off on reviewing it for now.

@ohtanim
ohtanim marked this pull request as draft August 27, 2026 16:35
@ohtanim ohtanim changed the title Embed build/version info into spank_qrmi binary WIP - Embed build/version info into spank_qrmi binary Aug 27, 2026
@ohtanim ohtanim changed the title WIP - Embed build/version info into spank_qrmi binary Embed build/version info into spank_qrmi binary Aug 28, 2026
@ohtanim
ohtanim marked this pull request as ready for review August 28, 2026 00:58
@ohtanim

ohtanim commented Aug 28, 2026

Copy link
Copy Markdown
Collaborator Author

@badtst @awennersteen @MatthieuMoreau0 @yoonho @OkuyanBoga I have recreated this PR based on above post. I also opened QRMI side changes - qiskit-community/qrmi#225.

Could you please review and approve ?

@ohtanim
ohtanim requested a review from badtst August 28, 2026 00:59

@badtst badtst left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm ! looks great

Comment thread docs/FAQ.md Resolved
@ohtanim
ohtanim requested a review from badtst August 28, 2026 09:15
@ohtanim
ohtanim merged commit 5c94396 into qiskit-community:main Aug 28, 2026
2 checks passed
@ohtanim
ohtanim deleted the version_info_in_binary branch August 28, 2026 09:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants