Skip to content

openvmm: expose release and development build identity - #4137

Closed
Ben Hillis (benhillis) wants to merge 6 commits into
microsoft:mainfrom
benhillis:user/benhill/openvmm-build-visibility-final
Closed

openvmm: expose release and development build identity#4137
Ben Hillis (benhillis) wants to merge 6 commits into
microsoft:mainfrom
benhillis:user/benhill/openvmm-build-visibility-final

Conversation

@benhillis

Copy link
Copy Markdown
Member

Depends on #4135. Once the preceding version PRs merge, this diff reduces to the user-visible build classification.

This change makes the source shape explicit wherever build identity is inspected:

  • openvmm -V remains compact;
  • openvmm --version reports version, build kind, product version, revision, and target;
  • startup telemetry records the same identity once per VMM process;
  • Windows VERSIONINFO sets VS_FF_PRERELEASE for ordinary checkouts;
  • the exact openvmm-v<VERSION> checkout and an extracted source archive report release;
  • OPENVMM_PKGVERSION reports custom, rather than allowing a builder to claim official release status.

The compiled behavior is unchanged; these are identity and diagnostics only.

Ben Hillis added 6 commits July 31, 2026 11:55
`openvmm --version` did not exist, and there was nothing to report if it had:
the workspace set no `version`, so every crate in it was `0.0.0`.

OpenVMM ships as a source archive that packagers build themselves, which rules
out the usual approach of having CI inject a version at build time -- the
packager builds long after our pipeline has exited, from a tree with no git
history to recover a version from. The version therefore has to be committed to
the tree. QEMU, systemd, the kernel, cloud-hypervisor and rustc all do this, and
each falls back gracefully when `.git` is absent rather than deriving the
release version from a tag.

So: set `version` in `[workspace.package]`, inherit it in `openvmm` and
`openvmm_entry`, and wire up clap's `version`. `OPENVMM_PKGVERSION` lets a
packager append their own build identity, as QEMU's `-Dpkgversion` and
cloud-hypervisor's `CH_EXTRA_VERSION` do; an empty value is ignored, since build
systems routinely pass an undefined variable through as "".

Two things fall out of that:

- The Windows VERSIONINFO resource is a second version surface, stamped from
  `OPENVMM_MAJOR`/`MINOR`/`PATCH`/`REVISION` and defaulting to `0.0.0.0`. No
  in-repo caller sets those, so leaving it alone would have left one binary
  reporting `0.1.0-dev` from `--version` and `0.0.0.0` from its file properties.
  It now defaults to the crate version, with the env vars still overriding
  per-component so a pipeline can stamp a build number in.

- `cargo xtask fmt` deliberately strips `version` from `[package]`, partly
  because doing so also makes a crate unpublishable. The three crates on its
  exception list now set `publish = false` explicitly, restoring the property
  the lint was relying on.

Verified by building `openvmm` from an extracted archive with no `.git` anywhere
above it, which is the case that actually matters.
The workspace version advances only in the reviewed pull request that selects the next release. Development-build identity is added separately from the committed product version.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0ba1c0df-faf0-4a0e-b39d-c3eb0e363fce
Builds on the crate-based version by adding back the part of the tag-derived
scheme that is actually worth having: the commit a build came from.

`openvmm_build_info` resolves the version at build time. The version itself is
still a committed fact inherited from `[workspace.package]`, so it travels
inside the source archive and a packager building an extracted tree with no Git
history reports the right thing. Git is consulted only to append `+g<revision>`
to a build made from a checkout, as semver build metadata so it orders
identically to the plain version. `OPENVMM_PKGVERSION` still replaces the lot.

Deliberately omitted from the tag-derived design:

- No `.openvmm-release.json` and no tag parsing. Nothing has to stamp metadata
  into the archive, so there is no release step that can silently fail and
  leave a shipped tarball reporting `0.0.0-dev`, and no tag/manifest agreement
  to validate in CI.

- No dirty flag. Detecting a modified working tree means emitting a
  `rerun-if-changed` for every tracked file, which stats the entire repository
  on every build. The revision alone needs two files.

The Git lookup rejects a repository that does not start exactly where OpenVMM
does. Git searches parent directories, so an archive extracted inside an
unrelated checkout would otherwise report that checkout's HEAD, which is the
one failure mode here that is silent and wrong rather than merely absent.

`product_version` is exposed separately from `version` and is what the snapshot
manifest records, since a persisted field wants the upstream version rather
than a distribution's build string.

Verified from a checkout, from an archive extracted outside any repository, and
from one extracted inside an unrelated repository.
Keep enriching ordinary checkouts with +g<sha>, but report the plain product version when HEAD carries openvmm-v<VERSION>. A checkout without tags fails safely toward development identity, while an extracted source archive remains plain because it has no repository.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0ba1c0df-faf0-4a0e-b39d-c3eb0e363fce
The hybrid versioning scheme already orders correctly -- `0.1.0-dev` is a
semver prerelease, so it sorts below `0.1.0` -- but nothing said "this is
not an official build" in words, and nothing distinguished the two at all
on Windows.

Four additions, none of which invent a new source of truth:

- `BuildKind` (`Release | Development | Custom`), resolved at build time
  from facts already in hand: `Custom` when `OPENVMM_PKGVERSION` is set,
  `Development` when the version carries a prerelease component, else
  `Release`. It lands in the `OPENVMM_BUILD_INFO` link section, so it is
  extractable from a binary without running it.

  Deliberately not a boolean "official". OpenVMM ships as source that
  someone else builds, so a packager's binary is legitimately not ours and
  yet is a legitimate build of an official version. A boolean would be
  unverifiable and would invite lying; the real proof of officialness is
  the attestation on the tarball.

- A rustc-style long version. clap uses `version` for `-V` and
  `long_version` for `--version`, so this costs no new flag:

      openvmm 0.1.0-dev+g2d79d0685
      build:   development (not an official release)
      version: 0.1.0-dev
      commit:  2d79d06
      host:    x86_64-pc-windows-msvc

  Composed in the build script, because the parts are optional, and passed
  through a file in `OUT_DIR` rather than `cargo::rustc-env`: cargo parses
  build script output a line at a time and silently keeps only the first
  line of a multi-line value.

- One startup log line carrying the same identity, so every log bundle and
  bug report has it. `info`, not `warn`: development builds are the normal
  case for anyone working on OpenVMM, and a warning that always fires is
  one that gets filtered out and then ignored when it finally matters.
  Emitted after option parsing so `--version` and `--help` stay clean, and
  after the mesh host check so worker processes do not each repeat it.

- `VS_FF_PRERELEASE` in the Windows version resource, which is the
  idiomatic Win32 mechanism for exactly this and shows up in the file
  properties dialog. Set from `CARGO_PKG_VERSION_PRE`, so it tracks the
  same fact the rest of this does.

  `VS_FF_SPECIALBUILD` was considered for the `OPENVMM_PKGVERSION` case and
  skipped: it requires a matching `SpecialBuild` string, which needs
  RC-preprocessor conditionals to supply, and packager overrides on Windows
  are rare enough not to justify that.

Verified: `-V` and `--version` produce the short and long forms; the log
line appears once on a real run and not on `--version`; and the built
binary reports `IsPreRelease: True` with `FileVersion 0.1.0.0`.
Classify only an extracted released source tree or an exact release-tag checkout as a release. Ordinary checkouts remain development builds even though the committed product version is the most recently released version. Keep the long CLI output, startup telemetry, and Windows VS_FF_PRERELEASE flag consistent with that classification.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

Copilot-Session: 0ba1c0df-faf0-4a0e-b39d-c3eb0e363fce
Copilot AI review requested due to automatic review settings July 31, 2026 21:48
@github-actions github-actions Bot added the unsafe Related to unsafe code label Jul 31, 2026
@github-actions

Copy link
Copy Markdown

⚠️ Unsafe Code Detected

This PR modifies files containing unsafe Rust code. Extra scrutiny is required during review.

For more on why we check whole files, instead of just diffs, check out the Rustonomicon

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This pull request introduces a centralized “build identity” source (openvmm_build_info) and wires it into user-visible version reporting and telemetry, while also ensuring Windows VERSIONINFO reflects whether the build is a release vs development checkout.

Changes:

  • Add openvmm_build_info crate to provide a consistent version/kind/revision/target identity (including a multi-line --version form).
  • Update openvmm CLI version output, snapshot manifest stamping, and startup telemetry to use the resolved build identity.
  • Ensure versioned crates that must carry a version explicitly set publish = false, and extend the workspace to carry a canonical version.

Reviewed changes

Copilot reviewed 13 out of 14 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
xtask/src/tasks/fmt/lints/package_info.rs Expands version exception policy and documents why certain crates may carry a version.
vm/vmgs/vmgstool/Cargo.toml Adds publish = false to comply with the “versioned crate” exception policy.
openvmm/openvmm/resources.rc Adds Windows VERSIONINFO file flags plumbing for prerelease marking.
openvmm/openvmm/Cargo.toml Makes openvmm inherit the workspace version and prevents publishing.
openvmm/openvmm/build.rs Stamps Windows resource version from the crate version by default and sets prerelease flags based on Git tag identity.
openvmm/openvmm_entry/src/vm_controller.rs Persists the canonical product version into snapshot manifests.
openvmm/openvmm_entry/src/lib.rs Emits once-per-process build identity telemetry in logs.
openvmm/openvmm_entry/src/cli_args.rs Sets CLI name/version/long-version from openvmm_build_info and adds tests for -V/--version output.
openvmm/openvmm_entry/Cargo.toml Adds dependency on openvmm_build_info.
openvmm/openvmm_build_info/src/lib.rs Defines BuildInfo/BuildKind API and embeds build metadata in a discoverable linker section.
openvmm/openvmm_build_info/Cargo.toml Introduces the new crate with workspace version and publish = false.
openvmm/openvmm_build_info/build.rs Generates version/kind/revision/target env vars and long_version.txt at build time.
Cargo.toml Sets [workspace.package] version and adds openvmm_build_info to workspace dependencies.
Cargo.lock Updates resolved package versions and includes the new crate.

Comment on lines +150 to +158
let target = std::env::var("TARGET").unwrap_or_else(|_| "unknown".into());
let long_version = format!(
"{version}\n\
build: {kind_description}\n\
version: {product_version}\n\
commit: {}\n\
host: {target}",
revision.as_deref().unwrap_or("(not built from a checkout)"),
);
@benhillis

Copy link
Copy Markdown
Member Author

Superseded by the accepted direction in #4150 and the replacement product-version/build-identity implementation in #4162.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

unsafe Related to unsafe code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants