Skip to content

feat(iotedge): update Azure IoT stack to 1.6.0 and rust toolchain to 1.97.1 - #687

Merged
mlilien merged 7 commits into
omnect:mainfrom
mlilien:iotedge_1.6.0
Aug 21, 2026
Merged

feat(iotedge): update Azure IoT stack to 1.6.0 and rust toolchain to 1.97.1#687
mlilien merged 7 commits into
omnect:mainfrom
mlilien:iotedge_1.6.0

Conversation

@mlilien

@mlilien mlilien commented Aug 18, 2026

Copy link
Copy Markdown
Contributor

Moves the Azure IoT stack to the 1.6.0 line, which forces a Rust toolchain bump.

Three commits, reviewable independently.

feat(rust): bump toolchain to 1.97.1

oe-core wrynose (OE 6.0.2) ships rustc 1.94.1, but iotedge 1.6.0's edgelet pulls sysinfo 0.39.x, whose MSRV is 1.95. Bumping the toolchain was preferred over downgrading the dependency.

The rust recipes are patched in oe-core in place via the kas patch mechanism rather than vendored into meta-omnect: oe-core's meta is first in BBPATH, so a vendored rust_*.bb's require recipes-devtools/rust/rust-source.inc would resolve back to oe-core's old copy.

The patch is derived from wrynose's own 1.94.1 recipe set, which is class-compatible. oe-core master's set is deliberately not used — it carries a work-shared source refactor (common-source.inc, rust-source_1.97.1.bb), the @LLVM_CONFIG_PATH@/STAGING_BINDIR_CROSS llvm-config rework, and cargo_common/rust-common/cargo class changes that would disrupt every Rust recipe in the build. It:

  • renames rust, cargo, libstd-rs and rust-cross-canadian from _1.94.1 to _1.97.1
  • updates the source sha256 and trims the patch list in rust-source.inc
  • moves the bootstrap snapshot from 1.93.0 to 1.96.0
  • replaces files/ with the 1.97.1 patch set

Upstream does its own bumps the same way — git mv plus rust-snapshot.inc/rust-source.inc metadata, with no content change to rust_*.bb (checked for the 1.95.0, 1.96.0 and 1.96.1 bumps). The 1.97.1 bump is the exception, so three content changes are taken from it as well:

  • rust_1.97.1.bb: delete vendored archives from the installed library sources in all three rust_do_install variants. Without it do_package fails — 1.97 vendors the library workspace into <src>/library/vendor, which the recipe copies into the package, and dwarfsrcfiles rejects wit-bindgen 0.57.1's non-ELF archive (oe/package.py, source_info(), exempts only clang+LTO).
  • meta/classes-recipe/rust-target-config.bbclass: the aarch64 AAPCS64 non-leaf frame pointer from the same commit, plus the arm/armv7 eabi/eabihf target ABI from the 1.96.0 bump. The arm half is not a breaker for us (rustc 1.97.1 permits hard-float with an unspecified cfg(target_abi), and every arm32 machine we build is hard-float), but it belongs to the same version-bump pair and a soft-float arm32 target would be rejected outright without it.
  • meta/recipes-devtools/clang/: 0043-LoopUnroll-Iterate-exit-fold-candidates-in-determini.patch plus its common.inc SRC_URI line — an LLVM backport making LoopUnroll and LoopPeel iterate deterministically. Version-coupled because rust links oe-core's LLVM rather than a bundled one (rust_1.97.1.bb sets download-ci-llvm = False and points llvm-config at ${STAGING_BINDIR}/${STAGING_BINDIR_NATIVE}), so every Rust recipe in the image draws its codegen from that tree. llvm-project-source.bb is the sole consumer of that patch list — it is the only recipe reaching common.inc through common-clang.inc without also requiring common-source.inc, which blanks SRC_URI. Upstream's 0043 number is kept: its 0042 comes from 789d416dd8 (clang-tools-extra: disable tests), which is not version-coupled and which wrynose does not carry, so keeping the number lines up on a later rebase instead of colliding.

Not adopted, deliberately: upstream's armv8a AArch32 Thumb fixes and MIPS ABI class changes (not tied to a version bump, and no machine we build needs them) and the snapshot self-contained-lld patchelf loop (only fails on build hosts without a /lib64 compat path).

LLVM needs no version change: wrynose already ships 22.1.3 and rust 1.97 requires only >= 20. RUSTVERSION is retargeted so the PREFERRED_VERSION_* values it feeds no longer point at the removed 1.94.1.

Per the one-p001-per-repo convention, kas/patches/oe.patch is regenerated as the concatenation of oe_layerdir.patch and the new oe_rust-1.97.1.patch.

feat(iotedge): update Azure IoT stack to 1.6.0

Crate manifests regenerated with cargo bitbake.

  • aziot-identityd moves from the 1.6.0-rc.1 commit pinned during the wrynose migration to the 1.6.0 release tag. Its crate list came out byte-identical to rc.1, so both recipe patches still apply unchanged.
  • iotedge / aziot-edged move to Azure/iotedge 1.6.0; version-specific includes renamed and generated recipes regenerated (crates.io set grew 226 → 306). iot_identity_service_rev stays at the aziot-identityd SRCREV, since iotedge 1.6.0's edgelet/Cargo.lock pins exactly that commit and its 26 git members are unchanged, so the remap paths in omnect_rust_aziot-identityd_deps.bbclass remain valid.

RUSTFLAGS += "-D warnings" is kept, but four patches are dropped:

  • the three fix_linter_findings-* patches — upstream 1.6.0 absorbed all of them ([workspace.lints.rust] now declares the unexpected_cfgs check-cfg values, External carries #[allow(dead_code)], the dead Uid(u32) field is gone, and ossl110 is declared and set by openssl-build's build script)
  • fix_docker_engine_api_version.patch — upstream moved the Docker Engine API to v1.41, compatible with the v1.40 minimum of Docker 29.5, and deleted the swagger file the patch edited. Forcing v1.44 again would regress compatibility with older daemons.

docs(kas): document oe.patch generation

p001 for openembedded-core now points at the generated oe.patch, so nothing references oe_layerdir.patch by name any more and editing it has no effect and raises no error. A new kas/patches/README.md plus a comment at the p001 entry record the rule. The note is deliberately not a header inside oe.patch, which would break byte-equality with cat kas/patches/oe_*.patch.

Verification

  • oe.patch byte-equals cat kas/patches/oe_*.patch, and applies to a pristine 5d1aa5c806 worktree with git apply --check --whitespace=nowarn, exactly how kas applies it.
  • 0043-LoopUnroll-… is byte-identical to upstream's copy, and was test-applied against the llvm-project-22.1.3.src tarball ${BASEURI} resolves to: both hunks land at the line numbers in the patch header (LoopPeel.cpp 11 and 1122, LoopUnroll.cpp 17 and 516) with git apply --check clean, so no fuzz and no offset. None of the pinned clang/ patch files touch either source file, so its position after 0041 rather than upstream's 0042 is immaterial. After applying, common.inc differs from upstream master only by the SPDX license string, the 22.1.8 sha256sum and 0042.
  • Every file the patch produces was diffed against oe-core master's same-version file, and each residual hunk accounted for: rust-snapshot.inc is byte-identical, rust-source.inc differs only by the work-shared block, rust_1.97.1.bb and rust-target-config.bbclass only by the refactors and the deliberately-skipped hunks listed above.

@JanZachmann JanZachmann 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.

One likely build breaker in the rust 1.97.1 rename, plus two smaller things, all inline. One more finding cannot be inline because the file is not in the diff: doc/examples/iotedge-apparmor/deployment.json:18 still pins mcr.microsoft.com/azureiotedge-agent:1.5, while 1.6.0 ships image = "mcr.microsoft.com/azureiotedge-agent:1.6" in edgelet/contrib/config/linux/default.toml (installed as config.toml.default, and the same value is the commented default in config.toml.edge.template). Worth bumping the example in this PR.

What I checked and found correct: rust source and all snapshot checksums against static.rust-lang.org; the patch applies cleanly on wrynose and matches oe-core 1.97.1 file for file; RUSTVERSION ?= "1.97.1%" wins over tcmode-default.inc; both SRCREVs equal the upstream 1.6.0 tags and match edgelet/Cargo.lock; the generated manifests match the locks exactly (306 crates and 306 checksums each, plus the 26 git members the .inc files override); all retained patches still apply and every dropped-patch claim holds at the new revisions. Dropping fix_docker_engine_api_version.patch is safe: iotedge 1.6.0 asks for /v1.41 and docker-moby v29.3.0 has defaultMinAPIVersion = "1.40".

For the release note: the installed default edge agent image moves to mcr.microsoft.com/azureiotedge-agent:1.6.

Comment thread kas/patches/oe_rust-1.97.1.patch
Comment thread kas/patches/oe_rust-1.97.1.patch
Comment thread kas/distro/oe.yaml
@JanZachmann
JanZachmann self-requested a review August 18, 2026 21:10

@JanZachmann JanZachmann 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.

Round 2. Both round-1 blockers are fixed and I re-checked them against upstream rather than against the description: the generated oe.patch applies clean at the pinned oe-core commit 5d1aa5c8, and after applying, meta/recipes-devtools/rust/ matches upstream master except the later refactors that are not tied to the version bump, while rust-target-config.bbclass differs from master by exactly the two commits you named as skipped. Details in the threads; the vendor/*.a one is resolved.

Three things are still open, none of them a reason to hold the code as written:

The clang/LLVM 0043-LoopUnroll-… patch from the same upstream commit is still outside the patch scope, and it does reach this build through llvm-project-source. It fixes non-deterministic codegen, not wrong codegen, so it is a decision rather than a defect - see the scope thread.

doc/examples/iotedge-apparmor/deployment.json:18 still pins azureiotedge-agent:1.5 while 1.6.0 ships :1.6 as its default. Outside the diff, so there is no thread for it.

The branch is unbuilt. Both new rust hunks land in do_package and in the generated target JSON, so a build of one aarch64 and one arm32 machine is the verification that counts here. That is why this is a comment and not an approval - the code matches upstream, but nothing has executed it yet.

oe-core wrynose (OE 6.0.2) ships rustc 1.94.1, but iotedge 1.6.0's edgelet
pulls sysinfo 0.39.x, whose MSRV is 1.95. Bump the toolchain instead of
downgrading the dependency.

The rust recipes are patched in oe-core in place via the existing kas patch
mechanism rather than vendored into meta-omnect: oe-core's meta is first in
BBPATH, so a vendored rust_*.bb's "require recipes-devtools/rust/
rust-source.inc" would resolve back to oe-core's old copy.

The patch is derived from wrynose's own 1.94.1 recipe set, which is
class-compatible - oe-core master's set is not, it carries a work-shared
source refactor plus cargo_common/rust-common changes that would disrupt
every rust recipe in the build. It renames the four recipes rust, cargo,
libstd-rs and rust-cross-canadian from 1.94.1 to 1.97.1, updates the source
sha256 and the patch list in rust-source.inc, moves the bootstrap snapshot
from 1.93.0 to 1.96.0, and replaces files/ with the 1.97.1 patch set. LLVM
needs no version bump; wrynose already ships 22.1.3 and rust 1.97 requires
>= 20.

Three content changes are taken from upstream on top of the rename. The 1.97.1
bump also deletes vendored archives from the installed library sources in all
three rust_do_install variants; without it do_package fails, because 1.97
vendors the library workspace into <src>/library/vendor - which the recipe
copies into the package - and dwarfsrcfiles rejects wit-bindgen's non-ELF
archive. The two version-coupled rust-target-config.bbclass hunks come along
as well: the aarch64 AAPCS64 non-leaf frame pointer from the same commit, and
the arm/armv7 eabi/eabihf target ABI from the 1.96.0 bump. Upstream's armv8a
AArch32 and MIPS class changes are not tied to a version bump and no machine
we build needs them.

The third reaches outside recipes-devtools/rust: the same upstream commit adds
0043-LoopUnroll-Iterate-exit-fold-candidates-in-determini.patch to the clang
recipe's patch list, an LLVM backport that makes LoopUnroll and LoopPeel
iterate deterministically. It is version-coupled because rust links oe-core's
LLVM rather than a bundled one - rust_1.97.1.bb sets download-ci-llvm to false
and points llvm-config at STAGING_BINDIR - so every rust recipe in the image
draws its codegen from that tree. Upstream's 0043 number is kept because its
0042 comes from an unrelated commit that wrynose does not carry.

RUSTVERSION is retargeted so the PREFERRED_VERSION_* values it feeds no
longer point at the removed 1.94.1.

Since kas takes a single p001 per repo, oe.patch is regenerated as the
concatenation of oe_layerdir.patch and the new oe_rust-1.97.1.patch, and
p001 for openembedded-core now points at it.

Signed-off-by: Marcel Lilienthal <134974+mlilien@users.noreply.github.com>
Move iotedge, aziot-edged and aziot-identityd to the 1.6.0 line, with the
crate manifests regenerated by cargo-bitbake.

aziot-identityd goes from the 1.6.0-rc.1 commit that was pinned for the
wrynose migration to the 1.6.0 release tag. Its crate list came out
byte-identical to rc.1, so both recipe patches still apply unchanged.

iotedge and aziot-edged move to Azure/iotedge 1.6.0. The version-specific
includes are renamed and the generated recipes regenerated; the crates.io
dependency set grew from 226 to 306 entries. iot_identity_service_rev stays
at the aziot-identityd SRCREV above - iotedge 1.6.0's edgelet/Cargo.lock
pins exactly that commit, and its 26 git members are unchanged, so the
remap paths in omnect_rust_aziot-identityd_deps.bbclass remain valid.

RUSTFLAGS += "-D warnings" is kept, but the three fix_linter_findings
patches are dropped because upstream 1.6.0 absorbed all of them:
[workspace.lints.rust] now declares the unexpected_cfgs check-cfg values,
External carries #[allow(dead_code)], the dead Uid(u32) field is gone, and
ossl110 is declared and set by openssl-build's build script.

fix_docker_engine_api_version.patch is dropped as well. Upstream moved the
Docker Engine API to v1.41, which is compatible with the v1.40 minimum of
Docker 29.5, and deleted the swagger file the patch edited. Forcing v1.44
again would regress compatibility with older daemons.

Requires rustc >= 1.95 for sysinfo 0.39.x; see the preceding commit.

Signed-off-by: Marcel Lilienthal <134974+mlilien@users.noreply.github.com>
p001 for openembedded-core points at the generated oe.patch, so nothing
references oe_layerdir.patch by name any more and editing it has no effect
and raises no error. Record the rule where both readers look: a README next
to the patches and a comment at the p001 entry.

The note deliberately does not go into oe.patch itself - that would break
the byte-equality with the concatenation it is verified against.

Signed-off-by: Marcel Lilienthal <134974+mlilien@users.noreply.github.com>
The AppArmor example manifest still pinned the 1.5 runtime images while the
distro now ships iotedge 1.6.0. edgeAgent and edgeHub have to track the
installed IoT Edge line - Azure does not support running a 1.6 agent against
a 1.5 hub - so all three pins move together rather than only the agent:
azureiotedge-agent, azureiotedge-hub and the SimulatedTemperatureSensor
sample module.

Bare minor tags are kept, matching the existing style in the file. Example
material only: nothing here is built into the image, and the CI apparmor test
copies just the omnect-temp-sensor profile from this directory, not the
manifest.

Signed-off-by: Marcel Lilienthal <134974+mlilien@users.noreply.github.com>
The concatenation rule was documented but unchecked: editing an oe_*.patch and
forgetting to regenerate left kas applying a stale oe.patch with nothing
reporting it.

Add a pull-request job running the same cmp the README prescribes. LC_ALL is
set on the step environment rather than on cat, because the shell expands and
collates the glob before cat ever runs, and glob order is the order the hunks
apply in - C and en_US.UTF-8 sort oe_A/oe_a/oe_B differently.

Drop the README's source table: it restated `ls kas/patches/oe_*.patch` and
needed an edit whenever a patch was added or dropped. The retirement rule it
carried survives as prose, and the file reads as the example it is meant to be.

Signed-off-by: Marcel Lilienthal <134974+mlilien@users.noreply.github.com>
@mlilien

mlilien commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Round 2 items closed.

Builds. One aarch64 machine (raspberrypi4-64) and one arm32 machine (dehndetect, armv7 hard-float i.MX6) both build green, image included. Both pull in aziot-edged 1.6.0, aziot-identityd, iotedge 1.6.0 and omnect-device-service, so the iotedge half of the PR is covered and not just the toolchain. The split is deliberate: the aarch64 frame-pointer hunk and the arm/armv7 eabihf hunk each only show up in the target JSON of their own architecture, so one machine could not have exercised both.

One correction on your do_package point. "Both new rust hunks land in do_package" holds for the generated target JSON but not for the vendor/*.a deletion. Target rust is not built by our images at all - only rust-native, cargo-native and target libstd-rs. Nothing RDEPENDs on target rust, and meta-omnect ships no toolchain kas feature, so do_package for rust never runs and that hunk is not exercised by an image build.

It is still the right hunk to carry: library/vendor/wit-bindgen-0.57.1/src/rt/libwit_bindgen_cabi.a is present in the 1.97.1 source, inside the library/ tree that rust_do_install copies, so the hazard is real for anyone who builds target rust or an SDK. Treat that one as reasoned rather than executed - say so if you want it actually built.

deployment.json is fixed in f350428, and it was three pins rather than the one you cited: azureiotedge-agent, azureiotedge-hub and the SimulatedTemperatureSensor sample all sat at :1.5. agent and hub are the runtime pair and Azure does not support a 1.6 agent against a 1.5 hub, so changing only line 18 would have left the manifest worse than it was. Bare minor tags kept, matching the file; all three 1.6 tags exist in MCR.

Scope item: 0043 landed before this review, in 75efeaf. The stale "not adopted, deliberately" line and the two-vs-three count in the PR body were corrected in the same push.

The README and CI-enforcement points from the kas/distro/oe.yaml thread are answered there, in d8a4ce1.

One caveat on reproducing the arm32 result: dehndetect pulls meta-omnect-dehn @ 73c1eea and mlilien/meta-dehn @ 965ca1a, both still on personal forks pending omnect/meta-dehn#11 and omnect/meta-omnect-dehn#40.

The branch gate listed main, kirkstone and scarthgap, so pull requests
targeting wrynose skipped the conventional-commit check entirely.

Signed-off-by: Marcel Lilienthal <134974+mlilien@users.noreply.github.com>

@JanZachmann JanZachmann 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.

Approving. All three threads are resolved and nothing is open from my side.

What I checked against upstream rather than against the description, across the rounds: the generated oe.patch applies clean at the pinned oe-core commit 5d1aa5c8 and stays byte-identical to cat kas/patches/oe_*.patch; after applying, meta/recipes-devtools/rust/ matches upstream master except the refactors that are not tied to the version bump, rust-target-config.bbclass differs only by the two class commits you deliberately skipped, and common.inc only by the SPDX string, the 22.1.8 sha256sum and 0042. 0043-LoopUnroll-… is byte-identical to upstream and applies with no offset against the real llvmorg-22.1.3 sources. On the iotedge side, both SRCREVs equal the upstream 1.6.0 tags, the generated manifests match the locks exactly, every retained patch still applies and every dropped one is genuinely absorbed upstream, and all three example images have a 1.6 tag on MCR for amd64, arm32v7 and arm64v8.

The build result and the CI green are yours, not mine - I did not run the image build.

Comment thread .github/workflows/kas-patch-checker.yml Outdated
Signed-off-by: Marcel Lilienthal <134974+mlilien@users.noreply.github.com>
@mlilien
mlilien requested a review from HarryWaschkeit August 21, 2026 05:56
@mlilien
mlilien merged commit cd93e16 into omnect:main Aug 21, 2026
3 checks passed
@mlilien
mlilien deleted the iotedge_1.6.0 branch August 21, 2026 08:17
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.

3 participants