Skip to content

Unvendor bundled C++ deps (protobuf, abseil, onnx, re2, flatbuffers, coremltools)#183

Open
hmaarrfk wants to merge 14 commits into
conda-forge:mainfrom
hmaarrfk:coreml-libcoremltools
Open

Unvendor bundled C++ deps (protobuf, abseil, onnx, re2, flatbuffers, coremltools)#183
hmaarrfk wants to merge 14 commits into
conda-forge:mainfrom
hmaarrfk:coreml-libcoremltools

Conversation

@hmaarrfk

@hmaarrfk hmaarrfk commented May 17, 2026

Copy link
Copy Markdown
Contributor

I've been wanting to help unvendor lots of the stuff that this repo depends on.

The list is:

I'm not really sure how valuable this is, but it is in the spirit of conda-forge as a whole.

So i figured I would ask my AI tools to do the hardest parts of my OSS contributions.

  • I have reviewed AI's code
  • This code is ready to be read by other humans.
AI's details

Draft — not ready to merge

This branch unvendors several of the C++ dependencies that onnxruntime
bundles and builds from source, so the feedstock instead links the
conda-forge shared libraries.

Blocked on: libcoremltools and libonnx are not yet on conda-forge —
they currently live on the experimental mark.harfouche channel, which
recipe/conda_build_config.yaml adds to channel_sources temporarily. CI
on this PR will fail until those packages are published to conda-forge
proper. Opening as a draft to share the approach and gather feedback.

What this does

onnxruntime 1.26.0 FetchContent-builds and statically links its own copies
of many dependencies. This branch makes it use the conda-forge packages:

Dependency Change
libprotobuf host dep; find_package already supported — no patch
libabseil host dep + patch 0007 (onnxruntime pins an exact-version FIND_PACKAGE_ARGS; abseil's CMake config is ExactVersion, so the constraint must be dropped)
libcoremltools patch 0006 — CoreML EP links the prebuilt library instead of vendoring the coremltools sources
libonnx host dep + patch 0008; requires onnxruntime_USE_FULL_PROTOBUF=ON (the conda onnx is full-protobuf). The patch guards onnxruntime's schema registration with ONNX's IsOnnxStaticRegistrationDisabled() so an externally-linked onnx that statically registers schemas does not double-register
re2 host dep; find_package already supported — no patch
flatbuffers build + host dep; build.sh regenerates the schema headers with the conda flatc (the committed *.fbs.h carry a static_assert pinning the flatbuffers version)

Because onnxruntime_USE_FULL_PROTOBUF=ON is now set, the compiled C++ unit
tests are skipped — they need ONNX's .proto sources, which the libonnx
package does not ship. The recipe's own test section (Python import, CoreML
provider, the C++ consumer test, cmake-package-check) still runs.

Still vendored

cpuinfo (pytorch/cpuinfo) and kleidiai remain vendored and statically
linked — there is no conda-forge package for either yet.

Known limitations

  • The conda-forge libonnx does not carry onnxruntime's vendored patch that
    un-deprecates the opset-18 GroupNormalization operator, so models with an
    ai.onnx GroupNormalization node at opset 18–20 are rejected. opset ≥ 21
    is fine. In practice no mainstream exporter emits that operator (they
    decompose group norm), so the impact is minimal.
  • Only osx-arm64 has been build-verified locally (a full conda-build:
    both outputs build, link the conda shared libraries, and pass their
    tests). linux and win are unverified.

🤖 Generated with Claude Code

hmaarrfk added 9 commits May 16, 2026 21:51
<details><summary>Claude's draft</summary>

Wire the CoreML execution provider to link the conda-forge
libcoremltools package instead of vendoring and rebuilding the
coremltools sources via FetchContent.

- patches/0006: onnxruntime cmake locates the installed libcoremltools
  shared library and points coremltools_SOURCE_DIR at its installed
  headers/.proto tree, then links the library. coreml_proto is still
  compiled by onnxruntime itself.
- meta.yaml: add libcoremltools to host (osx-arm64); drop the explicit
  libprotobuf 3.21 pin so the build picks up the migrated global pin;
  update license metadata (coremltools is now a linked dependency).
- conda_build_config.yaml: temporarily add the mark.harfouche channel
  so libcoremltools can be pulled before it is on conda-forge.
- .ci_support/migrations: add the absl_grpc_proto_26Q1 migration so
  onnxruntime builds against libprotobuf 6.33.5 / libabseil 20260107,
  matching libcoremltools.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume cddc3bcd-9a3e-4dd2-ad9e-6ff54036dd64
```
</details>
…6.05.16.16.48.35

Other tools:
- conda-build 26.3.0
- rattler-build 0.64.1
- rattler-build-conda-compat 1.4.14
<details><summary>Claude's draft</summary>

onnxruntime 1.26.0 previously FetchContent-built and statically linked
its own protobuf (v21.12) and abseil (20250814). Link the conda-forge
libprotobuf and libabseil shared libraries instead.

- protobuf: onnxruntime already declares it with find_package support,
  so adding libprotobuf to host is enough for find_package to pick it
  up via CMAKE_PREFIX_PATH=$PREFIX.
- abseil: patch 0007 drops onnxruntime's explicit 20250814 version from
  FIND_PACKAGE_ARGS. Abseil's installed CMake config uses ExactVersion
  compatibility, so any version constraint there forces a vendored
  build regardless of which libabseil is installed.
- The onnxruntime-cpp output ships libonnxruntime, which now dynamically
  links these libraries, so libabseil/libprotobuf/libcoremltools are
  added to that output's host to propagate run_exports to its run deps.
- Vendored abseil/protobuf license_file entries removed; those licenses
  now ship with the conda-forge libabseil and libprotobuf packages.

Verified by a full local osx-arm64 conda-build: both the onnxruntime
and onnxruntime-cpp outputs build, link the conda-forge shared
libraries, and pass all tests (10/10 ctest, Python import + CoreML
provider, the C++ consumer test, and cmake-package-check).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume d80ad55e-ba07-4e9b-a8b1-63193a50dad3
```
</details>
<details><summary>Claude's draft</summary>

onnxruntime 1.26.0 previously FetchContent-built and statically linked
its own onnx 1.21.0. Link the conda-forge libonnx 1.21.0 shared library
instead. onnxruntime already declares onnx with find_package support
(FIND_PACKAGE_ARGS NAMES ONNX onnx), so adding libonnx to host is enough
for it to be discovered; it aliases ONNX::onnx / ONNX::onnx_proto.

- libonnx is a full-protobuf build, so build.sh now sets
  onnxruntime_USE_FULL_PROTOBUF=ON. onnxruntime consequently links the
  full libprotobuf instead of libprotobuf-lite, keeping onnx, onnxruntime
  and libcoremltools on one self-consistent full-protobuf stack.
- patch 0008 guards onnxruntime's RegisterOnnx{,ML,Training}OperatorSetSchema()
  calls with ONNX's IsOnnxStaticRegistrationDisabled(). An unvendored onnx
  is built with static schema registration enabled and registers the
  opsets itself at load time; calling them again threw duplicate-schema
  errors. The vendored onnx is built with __ONNX_DISABLE_STATIC_REGISTRATION
  so the guard is true and registration still happens -- the patch works
  for both the vendored and the unvendored onnx.
- The C++ unit tests build an onnx_test_data_proto target that needs
  ONNX's .proto source files, which libonnx does not ship. build.sh now
  skips the compiled unit tests; the recipe test section still exercises
  the Python package, the C++ consumer test and cmake-package-check.
- libonnx added to host of the onnxruntime and onnxruntime-cpp outputs;
  the vendored onnx-src license_file entry removed.

Verified by a full local osx-arm64 conda-build: both outputs build, link
libonnx.dylib and the full libprotobuf, import with zero schema-registration
errors, pass cmake-package-check, and run inference on CPU and CoreML.

Known limitation: onnxruntime's vendored onnx.patch un-deprecates the
opset-18 GroupNormalization op; the external libonnx does not carry that,
so opset-18 GroupNormalization models are rejected (opset-21 is fine).
Fixing it requires a patch in the libonnx feedstock.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume d80ad55e-ba07-4e9b-a8b1-63193a50dad3
```
</details>
<details><summary>Claude's draft</summary>

The unvendored onnx build uses the conda-forge libonnx, which does not
carry onnxruntime's vendored patch un-deprecating the opset-18
GroupNormalization operator. Document, next to the libonnx host
dependency, that models with an ai.onnx GroupNormalization node at opset
18-20 are rejected (INVALID_GRAPH) and should be version-converted or
re-exported to opset >= 21.

This is rare in practice: the PyTorch (TorchScript and dynamo) and
tf2onnx exporters all decompose group normalization into
Reshape/InstanceNormalization/Mul/Add rather than emitting the
ai.onnx GroupNormalization operator, so no mainstream export path is
affected. Documentation only; no build change.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume d80ad55e-ba07-4e9b-a8b1-63193a50dad3
```
</details>
<details><summary>Claude's draft</summary>

onnxruntime previously FetchContent-built and statically linked its own
re2 (2024-07-02). Add re2 to the host requirements of the onnxruntime
and onnxruntime-cpp outputs so onnxruntime links the conda-forge re2
shared library instead.

onnxruntime already declares re2 with find_package support
(FIND_PACKAGE_ARGS NAMES re2, no version constraint), so no patch is
needed -- adding re2 to host is enough for it to be discovered via
CMAKE_PREFIX_PATH=$PREFIX. re2's run dependency is supplied by its
run_exports. The vendored re2-src license_file entry is removed.

Verified by a local osx-arm64 build: re2 is no longer in _deps,
libonnxruntime links @rpath/libre2.11.dylib, and inference runs on the
CPU and CoreML execution providers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume d80ad55e-ba07-4e9b-a8b1-63193a50dad3
```
</details>
…6.05.16.16.48.35

<details><summary>Claude's draft</summary>

Re-render after adding libabseil, libprotobuf, libonnx and re2 to the
host requirements. conda-smithy pulls the libabseil and re2 pinned
versions into the .ci_support variant configs.

Other tools:
- conda-build 26.3.0
- rattler-build 0.64.1
- rattler-build-conda-compat 1.4.14

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume d80ad55e-ba07-4e9b-a8b1-63193a50dad3
```
</details>
<details><summary>Claude's draft</summary>

onnxruntime previously FetchContent-built and statically linked its own
flatbuffers (23.5.26). Add flatbuffers to the build and host
requirements so onnxruntime uses the conda-forge flatbuffers instead.

onnxruntime already declares flatbuffers with find_package support
(FIND_PACKAGE_ARGS 23.5.9 NAMES Flatbuffers flatbuffers); flatbuffers'
CMake config-version file is AnyNewerVersion, so the conda-forge
flatbuffers (25.x) satisfies the >= 23.5.9 request and no patch is
needed.

The flatbuffers schema headers checked into the onnxruntime source tree
(ort.fbs.h and friends) carry a static_assert pinning them to the exact
flatbuffers version they were generated with (23.5.26). build.sh now
regenerates them with the conda flatc (via the upstream compile_schema.py
helpers) before building, so the embedded version assert matches the
conda flatbuffers runtime.

flatbuffers is statically linked into libonnxruntime, so it is a
build/host dependency only -- there is no run dependency and the
onnxruntime-cpp output does not need it. flatbuffers is added to build
because flatc must run on the build platform when cross compiling. The
vendored flatbuffers-src license_file entry is removed.

Verified by a local osx-arm64 build: flatbuffers is no longer in _deps,
the regenerated ort.fbs.h asserts the conda flatbuffers version, and
inference runs on the CPU and CoreML execution providers.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume d80ad55e-ba07-4e9b-a8b1-63193a50dad3
```
</details>
…6.05.16.16.48.35

<details><summary>Claude's draft</summary>

Re-render after adding flatbuffers to the build and host requirements.
conda-smithy pulls the pinned flatbuffers version into the .ci_support
variant configs.

Other tools:
- conda-build 26.3.0
- rattler-build 0.64.1
- rattler-build-conda-compat 1.4.14

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume d80ad55e-ba07-4e9b-a8b1-63193a50dad3
```
</details>
@conda-forge-admin

conda-forge-admin commented May 17, 2026

Copy link
Copy Markdown
Contributor

Hi! This is the friendly automated conda-forge-linting service.

I just wanted to let you know that I linted all conda-recipes in your PR (recipe/meta.yaml) and found it was in an excellent condition.

I do have some suggestions for making it better though...

For recipe/meta.yaml:

  • ℹ️ The recipe is not parsable by parser conda-souschef (grayskull). This parser is not currently used by conda-forge, but may be in the future. We are collecting information to see which recipes are compatible with grayskull.
  • ℹ️ The recipe is not parsable by parser conda-recipe-manager. The recipe can only be automatically migrated to the new v1 format if it is parseable by conda-recipe-manager.
  • ℹ️ azure.settings_win.variables.MINIFORGE_HOME is deprecated, please use workflow_settings.tools_install_dir instead.
  • ℹ️ azure.settings_win.variables.CONDA_BLD_PATH is deprecated, please use workflow_settings.build_workspace_dir instead.

This message was generated by GitHub Actions workflow run https://github.com/conda-forge/conda-forge-webservices/actions/runs/26990129787. Examine the logs at this URL for more detail.

Comment thread recipe/build.sh Outdated
Comment on lines +13 to +20
# The C++ unit tests build an onnx_test_data_proto target that imports ONNX's
# .proto source files. The unvendored conda-forge libonnx package ships only
# the generated headers, not the .proto sources, so the unit tests cannot be
# built. Skip them; the recipe's own test section still exercises the Python
# package, the C++ consumer test and cmake-package-check.
echo "Compiled unit tests are disabled"
RUN_TESTS_BUILD_PY_OPTIONS=""
BUILD_UNIT_TESTS="OFF"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

this might be the biggest change. im pretty ok with this but i should triple check that the proto files arent shipped somewhere

Comment thread recipe/meta.yaml Outdated
Comment thread recipe/meta.yaml Outdated
Comment thread recipe/meta.yaml Outdated
Comment thread recipe/meta.yaml Outdated
Comment thread recipe/meta.yaml Outdated
Comment thread recipe/meta.yaml Outdated
Comment thread recipe/meta.yaml Outdated
Comment thread recipe/meta.yaml Outdated
Comment thread recipe/meta.yaml Outdated
Comment thread recipe/build.sh Outdated
Comment thread recipe/build.sh Outdated
Co-authored-by: Mark Harfouche <mark.harfouche@gmail.com>
hmaarrfk added a commit to hmaarrfk/onnxruntime-feedstock that referenced this pull request Jun 2, 2026
<details><summary>Claude's draft</summary>

The OpenVINO EP pulls libopenvino-onnx-frontend into the host prefix, which
hard-depends on the conda-forge global libprotobuf (6.x). onnxruntime's
vendored onnx must be generated and compiled against that same protobuf, or its
headers get shadowed by the 6.x ones in $PREFIX/include and onnx fails to
compile ("onnx::ModelProto is incomplete type"). So on linux-64:

- build: use the global libprotobuf (provides a 6.x protoc) instead of pinning
  3.21; keep 3.21 on other platforms (unchanged, proven).
- host: add libprotobuf so the vendored onnx is compiled against the same 6.x
  headers/protoc as libopenvino-dev. onnxruntime then find_package()s the conda
  protobuf and links it instead of vendoring 3.21.
- license_file: protobuf and its abseil dependency are no longer vendored on
  linux-64 (they come from the conda libprotobuf/libabseil packages), so their
  _deps source trees don't exist there -- gate those license entries to
  [not linux64].

onnxruntime 1.26 / onnx 1.21 compile cleanly under protobuf 6.x: the only
removed API (RepeatedPtrField::ReleaseCleared) is guarded for >=5.26, and onnx
1.21 already requires abseil-based protobuf >=4.25.1. This is the same direction
as the draft unvendoring PR conda-forge#183.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume 8959e104-fade-4e06-a903-ec84f609fa1c
```
</details>
hmaarrfk added a commit to hmaarrfk/onnxruntime-feedstock that referenced this pull request Jun 2, 2026
<details><summary>Claude's draft</summary>

The OpenVINO EP pulls libopenvino-onnx-frontend into the host prefix, which
hard-pins the conda libprotobuf it was built against (6.33). onnxruntime's
build protoc and vendored onnx must use that same protobuf, or the 6.x host
headers shadow the vendored 3.21 ones and onnx fails to compile
("onnx::ModelProto is incomplete type"). So on linux-64:

- build + host: pin libprotobuf 6.33.* to match OpenVINO 2026.1. The conda-forge
  global pin has already moved to 7.x, so an unpinned libprotobuf gives a 7.x
  protoc in build vs OpenVINO's 6.33 in host -- another skew; pin both to 6.33
  (bump when OpenVINO migrates to 7.x). Other platforms keep the proven 3.21.
- onnxruntime then find_package()s the conda protobuf and links it instead of
  vendoring 3.21.
- license_file: protobuf is no longer vendored on linux-64 (it comes from the
  conda libprotobuf package), so gate the protobuf-src license to [not linux64].

onnxruntime 1.26 / onnx 1.21 compile cleanly under protobuf 6.x: the only
removed API (RepeatedPtrField::ReleaseCleared) is guarded for >=5.26, and onnx
1.21 already requires abseil-based protobuf >=4.25.1. Same direction as the
draft unvendoring PR conda-forge#183.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume 8959e104-fade-4e06-a903-ec84f609fa1c
```
</details>
@hmaarrfk hmaarrfk marked this pull request as ready for review June 2, 2026 00:48
@hmaarrfk hmaarrfk requested a review from xhochy as a code owner June 2, 2026 00:48
@hmaarrfk

hmaarrfk commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

One huge advantage of this is that you can start to have openvino as a runtime (which requires libprotobuf)

… abseil, re2)

<details><summary>Claude's draft</summary>

Now that the bundled C++ deps are unvendored, libonnxruntime.so dynamically
links libonnx.so, libprotobuf.so, libabsl_*.so and libre2.so. The main
onnxruntime output gains run deps on these automatically (it compiles
libonnxruntime.so, so conda-build infers them), but the onnxruntime-cpp output
only repackages the prebuilt libraries via install-cpp.sh -- conda-build can't
infer the link, so the package shipped no run deps for them.

The result: the onnxruntime-cpp test env (and any downstream C++ consumer)
lacks libonnx/libprotobuf/etc, and linking against -lonnxruntime fails with
undefined onnx:: / google::protobuf:: symbols. This surfaces only now that a
libonnx package exists for the test to get that far.

Fix: add libonnx/libprotobuf/libabseil/re2 to the onnxruntime-cpp host so their
run_exports pin them into the package's run requirements.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume 8959e104-fade-4e06-a903-ec84f609fa1c
```
</details>
hmaarrfk added a commit to hmaarrfk/onnxruntime-feedstock that referenced this pull request Jun 2, 2026
<details><summary>Claude's draft</summary>

Builds on the unvendored-dependencies work (PR conda-forge#183), so onnxruntime already
links the conda-forge libprotobuf 6.33.5 / libabseil 20260107 that OpenVINO
2026.1 also uses -- no protobuf version skew.

build.sh: pass --use_openvino CPU on linux-64. The "CPU" argument is only the
default device; the resulting libonnxruntime_providers_openvino.so is a
separately loadable module and the device is chosen at runtime via
provider_options=[{"device_type": "CPU"|"GPU"|"NPU"|"AUTO:GPU,CPU"|...}].
onnxruntime finds OpenVINO via find_package(OpenVINO REQUIRED COMPONENTS
Runtime ONNX), satisfied by libopenvino-dev on CMAKE_PREFIX_PATH.

meta.yaml (all gated to linux64):
- host: libopenvino-dev for the OpenVINO CMake config + onnx frontend.
- OpenVINO stays a *soft* dependency: ignore_run_exports_from libopenvino-dev /
  libopenvino / libopenvino-onnx-frontend / libopenvino-ir-frontend (the only
  OpenVINO packages with run_exports), and express compatibility via
  run_constrained: pin_compatible('libopenvino'). Every OpenVINO frontend and
  device plugin depends on an exact libopenvino build, so constraining
  libopenvino alone transitively pins them all. OpenVINO is therefore installed
  only when the user asks for it, and the OpenVINO EP picks it up when present.
- test: assert OpenVINOExecutionProvider is advertised (in a bare env without
  OpenVINO, since the provider library is loaded lazily).

migrations: add libopenvino_dev20261 to pin libopenvino 2026.1.0 (the build the
EP is compiled against). The OpenVINO EP is Linux x86_64 only; mirrors how the
CoreML EP is baked into the default osx-arm64 build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume 8959e104-fade-4e06-a903-ec84f609fa1c
```
</details>
hmaarrfk added a commit to hmaarrfk/onnxruntime-feedstock that referenced this pull request Jun 2, 2026
<details><summary>Claude's draft</summary>

Apply the libopenvino_dev20261 migration to the linux-64 variant configs so the
OpenVINO EP is built against (and run_constrained to) libopenvino 2026.1.0,
which uses the same libprotobuf 6.33.5 / libabseil 20260107 onnxruntime already
links via PR conda-forge#183's absl_grpc_proto_26Q1 migration.

Only the .ci_support/*.yaml libopenvino_dev pins are included; the conda-smithy
scaffolding churn from a full rerender (this machine's conda-smithy is newer than
PR conda-forge#183's) is intentionally left out so this stacks cleanly on PR conda-forge#183. A normal
rerender at merge time regenerates the rest.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume 8959e104-fade-4e06-a903-ec84f609fa1c
```
</details>
@hmaarrfk

hmaarrfk commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

i think the biggest question is whether or not we want to try to unvendor onnx with libonnx. i think it will be worthwhile.

Comments indicating approval on conda-forge/onnx-feedstock#146 would be appreciated.

If we want to keep libonnx vendored, then i can make those changes too.

<details><summary>Claude's draft</summary>

The unit tests were disabled because onnxruntime's onnx_test_data_proto target
needs ONNX's .proto sources, which the unvendored libonnx package doesn't ship.
The conda `onnx` (Python) package does ship them, so point onnx_SOURCE_DIR at it
($PREFIX/lib/pythonX.Y/site-packages, located via find) and re-enable the tests
(restoring the original cross/cuda-only disable) -- no re-vendoring of onnx.

- build.sh: compute ONNX_PROTO_ROOT from the conda onnx .proto; enable
  BUILD_UNIT_TESTS + --test for native non-CUDA builds; pass onnx_SOURCE_DIR.
- meta.yaml: add `onnx` to host. The python test (onnxruntime_test_python.py)
  imports onnx alongside onnxruntime, so the onnx must link the SHARED libonnx
  (shares onnx-ml.proto) -- an onnx that statically embeds its own onnx
  registers the descriptors twice and aborts. conda-forge's onnx gains that with
  the libonnx split (onnx-feedstock PR conda-forge#146); pin `*_1` until it lands.

Verified locally: the C++ suite passes 100% (10/10 test executables), and with
PR conda-forge#146's shared-libonnx onnx, `import onnx` + `import onnxruntime` coexist and
the python test runs clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume 8959e104-fade-4e06-a903-ec84f609fa1c
```
</details>
hmaarrfk added a commit to hmaarrfk/onnxruntime-feedstock that referenced this pull request Jun 2, 2026
<details><summary>Claude's draft</summary>

Builds on the unvendored-dependencies work (PR conda-forge#183), so onnxruntime already
links the conda-forge libprotobuf 6.33.5 / libabseil 20260107 that OpenVINO
2026.1 also uses -- no protobuf version skew.

build.sh: pass --use_openvino CPU on linux-64. The "CPU" argument is only the
default device; the resulting libonnxruntime_providers_openvino.so is a
separately loadable module and the device is chosen at runtime via
provider_options=[{"device_type": "CPU"|"GPU"|"NPU"|"AUTO:GPU,CPU"|...}].
onnxruntime finds OpenVINO via find_package(OpenVINO REQUIRED COMPONENTS
Runtime ONNX), satisfied by libopenvino-dev on CMAKE_PREFIX_PATH.

meta.yaml (all gated to linux64):
- host: libopenvino-dev for the OpenVINO CMake config + onnx frontend.
- OpenVINO stays a *soft* dependency: ignore_run_exports_from libopenvino-dev /
  libopenvino / libopenvino-onnx-frontend / libopenvino-ir-frontend (the only
  OpenVINO packages with run_exports), and express compatibility via
  run_constrained: pin_compatible('libopenvino'). Every OpenVINO frontend and
  device plugin depends on an exact libopenvino build, so constraining
  libopenvino alone transitively pins them all. OpenVINO is therefore installed
  only when the user asks for it, and the OpenVINO EP picks it up when present.
- test: assert OpenVINOExecutionProvider is advertised (in a bare env without
  OpenVINO, since the provider library is loaded lazily).

migrations: add libopenvino_dev20261 to pin libopenvino 2026.1.0 (the build the
EP is compiled against). The OpenVINO EP is Linux x86_64 only; mirrors how the
CoreML EP is baked into the default osx-arm64 build.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume 8959e104-fade-4e06-a903-ec84f609fa1c
```
</details>
hmaarrfk added a commit to hmaarrfk/onnxruntime-feedstock that referenced this pull request Jun 2, 2026
<details><summary>Claude's draft</summary>

Apply the libopenvino_dev20261 migration to the linux-64 variant configs so the
OpenVINO EP is built against (and run_constrained to) libopenvino 2026.1.0,
which uses the same libprotobuf 6.33.5 / libabseil 20260107 onnxruntime already
links via PR conda-forge#183's absl_grpc_proto_26Q1 migration.

Only the .ci_support/*.yaml libopenvino_dev pins are included; the conda-smithy
scaffolding churn from a full rerender (this machine's conda-smithy is newer than
PR conda-forge#183's) is intentionally left out so this stacks cleanly on PR conda-forge#183. A normal
rerender at merge time regenerates the rest.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume 8959e104-fade-4e06-a903-ec84f609fa1c
```
</details>
<details><summary>Claude's draft</summary>

Refine the re-enabled tests: build and run the C++ ctest suite directly (passes
against the unvendored onnx) and do not invoke build.py's python test phase.
Those python suites are ONNX-conformance + onnxruntime.quantization tooling
tests, brittle against the external unvendored onnx 1.21 (the quantization
preprocess raises NotImplementedError on a BatchNormalization op shared across
the '' and 'com.ms.internal.nhwc' domains; onnx_backend_test_series expects
vendored test data). Revert the onnx host dep to plain `onnx` -- with the python
phase gone, the C++ tests don't import python onnx, so any onnx that supplies
the .proto sources for onnx_test_data_proto works.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume 8959e104-fade-4e06-a903-ec84f609fa1c
```
</details>
@cbourjau

cbourjau commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

i think the biggest question is whether or not we want to try to unvendor onnx with libonnx. i think it will be worthwhile.

Comments indicating approval on conda-forge/onnx-feedstock#146 would be appreciated.

If we want to keep libonnx vendored, then i can make those changes too.

I gave a small update concerning libonnx in the linked PR. Could/should we unvendor onnx/protobuf and the rest in two separate PRs? There was also work upstream to make the execution providers separate from the main package (e.g. the CUDA kernels don't have to be statically linked to libonnxruntime anymore). I think this would a great thing to make use of in this feedstock. Is it in scope of this exercise, too?

@hmaarrfk

hmaarrfk commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

to understand:

  • One PR for unvendoring libonnx
  • One PR for unvendoring protobuf and the rest

is that correct?

@hmaarrfk

hmaarrfk commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

(i was thinking about the cuda stuff too, its kinda strange that we have to rebuild the whole thing, but we would need to think about how we would support 12.X and 13.X and so it makes it quite distinct from this exact work for now)

@cbourjau

cbourjau commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

to understand:

* One PR for unvendoring libonnx

* One PR for unvendoring protobuf and the rest

is that correct?

I thought:

  • One PR for libonnx + protobuf
  • One PR for everything else

Might just be that I'm overthinking this, though! My thinking is:

  • Landing piece-meal might be faster / no need to block on the libonnx part
  • Unvendoring onnx without unvendoring protobuf or the other way around might create other issues (just a hunch)

@hmaarrfk

hmaarrfk commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

Unvendoring onnx without unvendoring protobuf or the other way around might create other issues (just a hunch)

I’m pretty sure I remember this being true.

Also. My AI had trouble with OpenVINO execution provider without working from this branch due to protobuf being vendored.

Will try to break it out into two

@hmaarrfk

hmaarrfk commented Jun 2, 2026

Copy link
Copy Markdown
Contributor Author

just fyi, the only thing that doesn't depend on absl or protobuf is flatbuffers.

so it will be

  • flatbuffers
  • everything else.

:/

@hmaarrfk

hmaarrfk commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

part 1: #186 (comment)

@xhochy

xhochy commented Jun 3, 2026

Copy link
Copy Markdown
Member

I tried to unvendor libprotobuf in the past, but ran into the issue that both onnxruntime and libonnx try to load the same protobuf definitions. You would probably need to make sure that they are only loaded once (you can only load them multiples times if you have multiple static libprotobuf linkages)

@hmaarrfk

hmaarrfk commented Jun 3, 2026

Copy link
Copy Markdown
Contributor Author

I have to admit I did not know about the "protobuf initialization challenges", but I have been validating this and using this on my machines. In fact, I believe i addressed the "dual" protobuf initialization is part of the validation I ended up doing this last week. It was admittedly a lot of patching. I think we have generally seen the challenges of "shared protobuf". Arguably there are likely more challenges of having both "shared protobuf" and "static protobuf" when it comes time to linking libraries together.

I believe i should be able to upload the full set of packages to my channel to allow you all to test, can we agree on:

  • osx-arm64
  • linux-64

As test platforms. My goal is really to enable more runtimes for onnxruntime in a way that is commensurate with the rest of the conda-forge stack, that is to say, we have "worked to unvendor protobuf".

<details><summary>Claude's draft</summary>

The recipe test previously only imported onnxruntime and ran `pip check` /
`onnxruntime_test --help`; nothing actually executed a model. Add a runtime
smoke test (recipe/test_onnxruntime_inference.py) wired into the top-level
test of the onnxruntime python output, on the always-available
CPUExecutionProvider so it runs on every CI runner.

The test deliberately imports `onnx` and `onnxruntime` into the same process
and then runs a small MatMul -> Relu -> Add model. That import pair is exactly
what the unvendored libonnx build must get right: onnxruntime links the shared
libonnx and relies on ONNX's own static schema registration (patch 0008). If
that wiring regresses, the test aborts with duplicate ONNX schema / protobuf
descriptor-pool registration before any op runs. `onnx` is added to the test
`requires` for this reason.

Verified locally on linux-64: built libonnx (onnx-feedstock win-shared-lib)
and this onnxruntime branch, then in a clean env confirmed libonnxruntime.so
has `NEEDED libonnx.so` (dynamically linked, not vendored), `pip check` is
clean, and the runtime test passes:

    onnx 1.21.0 / onnxruntime 1.26.0
    providers: ['CPUExecutionProvider']
    onnxruntime CPU inference OK, output shape (2, 4)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

Resume this Claude session:
```
claude --resume f83cea30-3bae-4875-99f3-99b8640fb5cf
```
</details>
@hmaarrfk

hmaarrfk commented Jun 5, 2026

Copy link
Copy Markdown
Contributor Author

@cbourjau while i think it would be nice to do it in stages, unvendoring "flatbuffers" is a little boring on itself, and the rest of the unvendoring all depend on absl so they must be done together.

Please find attached instructions and a test script that tests things.

I've uploaded the required packages to my feedstock.

run_all_backends.py

I've tested this on a 2XX series NPU, the 3XX series NPU still crashes for me.

Please let me know if you have concerns:

$ python run_all_backends.py 
reference output: [12.299315   6.9270134  6.7726903]

ONNX Runtime
  [✓] onnxruntime CPU                    PASS  max|diff|=9.54e-07
  [✓] onnxruntime + OpenVINO CPU         PASS  max|diff|=9.54e-07
  [✓] onnxruntime + OpenVINO NPU         PASS  max|diff|=2.67e-03
  [✓] onnxruntime + OpenVINO GPU         PASS  max|diff|=5.14e-03
  [✓] onnxruntime + NVIDIA CUDA          PASS  max|diff|=0.00e+00

OpenVINO (native API)
  [✓] OpenVINO CPU                       PASS  max|diff|=9.54e-07
  [✓] OpenVINO NPU                       PASS  max|diff|=2.67e-03
  [✓] OpenVINO GPU                       PASS  max|diff|=5.14e-03

Summary:
  PASS  onnxruntime CPU                    max|diff|=9.54e-07
  PASS  onnxruntime + OpenVINO CPU         max|diff|=9.54e-07
  PASS  onnxruntime + OpenVINO NPU         max|diff|=2.67e-03
  PASS  onnxruntime + OpenVINO GPU         max|diff|=5.14e-03
  PASS  onnxruntime + NVIDIA CUDA          max|diff|=0.00e+00
  PASS  OpenVINO CPU                       max|diff|=9.54e-07
  PASS  OpenVINO NPU                       max|diff|=2.67e-03
  PASS  OpenVINO GPU                       max|diff|=5.14e-03

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.

4 participants