From 3336be73cb2a51039fecbbe0274dcce90dfa8334 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 20:19:26 +0000 Subject: [PATCH 01/18] Integrate ONNX 1.22.0rc1 version plumbing (T1) Pin ONNX to rel-1.22.0 HEAD commit bc3be77bec2f628788796dff60819186bacf49df (VERSION_NUMBER 1.22.0rc1): - cmake/deps.txt: commit-archive zip URL + SHA1 421e5a9afb6c41a54696e424e5b9a3796aab6821 - cmake/external/onnx: submodule -> bc3be77b - cmake/vcpkg-ports/onnx/vcpkg.json: version-semver 1.22.0, port-version 0 - cmake/vcpkg-ports/onnx/portfile.cmake: REF commit form + tar.gz SHA512 e0c526f5...3ce467 Rebase cmake/patches/onnx/onnx.patch to ONNX 1.22 and mirror byte-identically into binskim.patch: - Kept ONNX_MINIMAL_BUILD option (rebased context) - Restructured the minimal-build source-selection hunk for ONNX 1.22's new onnx_core OBJECT library / add_subdirectory(onnx) layout - Dropped the Utils.cmake protobuf_warnings hunk (already removed upstream in 1.22) - Kept the GroupNormalization-18 .Deprecate() removal (still present in 1.22) Agent-signed-off: Developer (8ac66e2a) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- cmake/deps.txt | 2 +- cmake/external/onnx | 2 +- cmake/patches/onnx/onnx.patch | 74 +++++++-------------------- cmake/vcpkg-ports/onnx/binskim.patch | 74 +++++++-------------------- cmake/vcpkg-ports/onnx/portfile.cmake | 4 +- cmake/vcpkg-ports/onnx/vcpkg.json | 2 +- 6 files changed, 43 insertions(+), 115 deletions(-) diff --git a/cmake/deps.txt b/cmake/deps.txt index 5a835e0c6fe9f..1337a0f663a17 100644 --- a/cmake/deps.txt +++ b/cmake/deps.txt @@ -34,7 +34,7 @@ microsoft_gsl;https://github.com/microsoft/GSL/archive/refs/tags/v4.2.1.zip;1094 microsoft_wil;https://github.com/microsoft/wil/archive/refs/tags/v1.0.250325.1.zip;826c8bd47c2258ec61b8b218e031e5b33d27f761 mimalloc;https://github.com/microsoft/mimalloc/archive/refs/tags/v2.1.1.zip;d5ee7d34223d0567892db5179849939c8769dc41 mp11;https://github.com/boostorg/mp11/archive/refs/tags/boost-1.82.0.zip;9bc9e01dffb64d9e0773b2e44d2f22c51aace063 -onnx;https://github.com/onnx/onnx/archive/refs/tags/v1.21.0.zip;321d4acc807c8e0fb0bbcc0424a143dffde1e846 +onnx;https://github.com/onnx/onnx/archive/bc3be77bec2f628788796dff60819186bacf49df.zip;421e5a9afb6c41a54696e424e5b9a3796aab6821 # Use the latest commit of 10.9-GA onnx_tensorrt;https://github.com/onnx/onnx-tensorrt/archive/d5dce67db7c2e64b07e055571f5ec06f7f254de2.zip;01114d3b67650857281fa50faa2e412130a63b69 protobuf;https://github.com/protocolbuffers/protobuf/archive/refs/tags/v21.12.zip;7cf2733949036c7d52fda017badcab093fe73bfa diff --git a/cmake/external/onnx b/cmake/external/onnx index be2b5fde82d9c..bc3be77bec2f6 160000 --- a/cmake/external/onnx +++ b/cmake/external/onnx @@ -1 +1 @@ -Subproject commit be2b5fde82d9c8874f3d19328bdfe3b6962dc67b +Subproject commit bc3be77bec2f628788796dff60819186bacf49df diff --git a/cmake/patches/onnx/onnx.patch b/cmake/patches/onnx/onnx.patch index 0a5680778790b..8de740c79e21c 100644 --- a/cmake/patches/onnx/onnx.patch +++ b/cmake/patches/onnx/onnx.patch @@ -1,33 +1,27 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 044996e..ded7e39 100644 +index 365af87..defe81a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -53,6 +53,7 @@ option(ONNX_USE_LITE_PROTO "Use lite protobuf instead of full." OFF) - option(ONNX_DISABLE_EXCEPTIONS "Disable exception handling." OFF) +@@ -46,6 +46,7 @@ option(ONNX_DISABLE_EXCEPTIONS "Disable exception handling." OFF) option(ONNX_DISABLE_STATIC_REGISTRATION "Disable static registration for ONNX operator schemas." OFF) option(ONNX_USE_UNITY_BUILD "Enable Unity (Jumbo) build for" OFF) + option(ONNX_PYODIDE_BUILD "Build ONNX for Pyodide/Emscripten (wasm32)." OFF) +option(ONNX_MINIMAL_BUILD "Build only essential ONNX components" OFF) option(ONNX_INSTALL "Install ONNX targets, headers, and CMake config files" ON) if(WIN32) - option(ONNX_USE_MSVC_STATIC_RUNTIME "Build with MSVC static runtime" OFF) -@@ -399,14 +400,28 @@ relative_protobuf_generate_cpp(ONNX_PROTO_SRCS - onnx/onnx-operators.in.proto - onnx/onnx-data.in.proto) - --file(GLOB_RECURSE __tmp_srcs "${ONNX_ROOT}/onnx/*.h" "${ONNX_ROOT}/onnx/*.cc") --file(GLOB_RECURSE onnx_gtests_src "${ONNX_ROOT}/onnx/test/cpp/*.h" -- "${ONNX_ROOT}/onnx/test/cpp/*.cc" -- "${ONNX_ROOT}/onnx/backend/test/cpp/*.cc" -- "${ONNX_ROOT}/onnx/backend/test/cpp/*.h") --list(REMOVE_ITEM __tmp_srcs "${ONNX_ROOT}/onnx/cpp2py_export.cc") --list(REMOVE_ITEM __tmp_srcs ${onnx_gtests_src} "${ONNX_ROOT}/onnx/test/cmake/main.cc") --list(APPEND ONNX_SRCS ${__tmp_srcs}) + option(ONNX_USE_MSVC_STATIC_RUNTIME "Build with MSVC static runtime. Ignored if CMAKE_MSVC_RUNTIME_LIBRARY is defined." OFF) +@@ -494,7 +495,22 @@ endfunction() + # target_sources. onnx_core is an OBJECT library consumed by both the onnx + # static library and the onnx_cpp2py_export Python extension module. + add_library(onnx_core OBJECT) +-add_subdirectory(onnx) +if(ONNX_MINIMAL_BUILD) + message(STATUS "Configuring ONNX minimal build") -+ set(ONNX_SRCS -+ "${ONNX_ROOT}/onnx/common/common.h" -+ "${ONNX_ROOT}/onnx/defs/data_type_utils.h" -+ "${ONNX_ROOT}/onnx/defs/data_type_utils.cc" ++ # ORT's minimal/WebAssembly builds only need ONNX's type utilities and the ++ # generated protobuf sources (added unconditionally below); skip globbing in ++ # the full operator/schema sources via add_subdirectory(onnx). ++ target_sources(onnx_core PRIVATE ++ "${ONNX_ROOT}/onnx/defs/data_type_utils.cc" + ) + # Ensure ONNX_ML is treated as ON for minimal build consistency with ORT's file + set(ONNX_ML ON CACHE BOOL "Enable traditional ML API." FORCE) @@ -35,46 +29,16 @@ index 044996e..ded7e39 100644 + set(ONNX_BUILD_PYTHON OFF CACHE BOOL "Build Python binaries" FORCE) + set(ONNX_BUILD_TESTS OFF CACHE BOOL "Build ONNX C++ APIs Tests" FORCE) +else() -+ file(GLOB_RECURSE __tmp_srcs "${ONNX_ROOT}/onnx/*.h" "${ONNX_ROOT}/onnx/*.cc") -+ file(GLOB_RECURSE onnx_gtests_src "${ONNX_ROOT}/onnx/test/cpp/*.h" -+ "${ONNX_ROOT}/onnx/test/cpp/*.cc" -+ "${ONNX_ROOT}/onnx/backend/test/cpp/*.cc" -+ "${ONNX_ROOT}/onnx/backend/test/cpp/*.h") -+ list(REMOVE_ITEM __tmp_srcs "${ONNX_ROOT}/onnx/cpp2py_export.cc") -+ list(REMOVE_ITEM __tmp_srcs ${onnx_gtests_src} "${ONNX_ROOT}/onnx/test/cmake/main.cc") -+ list(APPEND ONNX_SRCS ${__tmp_srcs}) ++ add_subdirectory(onnx) +endif() - set(LINKED_PROTOBUF_TARGET protobuf::libprotobuf) - if(ONNX_USE_LITE_PROTO) -diff --git a/cmake/Utils.cmake b/cmake/Utils.cmake -index 1987edd..04b3088 100644 ---- a/cmake/Utils.cmake -+++ b/cmake/Utils.cmake -@@ -103,18 +103,7 @@ endfunction() - - function(add_onnx_compile_options target) - if(MSVC) -- # For disabling Protobuf related warnings -- set(protobuf_warnings -- /wd4146 # unary minus operator applied to unsigned type, result still -- # unsigned -- /wd4244 # 'argument': conversion from 'google::protobuf::uint64' to -- # 'int', possible loss of data -- /wd4267 # Conversion from 'size_t' to 'int', possible loss of data -- /wd4141 # 'inline': used more than once -- /wd4047 # '=': 'uintptr_t' differs in levels of indirection from 'void *' -- ) - add_msvc_runtime_flag(${target}) -- target_compile_options(${target} PUBLIC ${protobuf_warnings}) - if(ONNX_WERROR) - target_compile_options(${target} PRIVATE "/WX") - endif() + relative_protobuf_generate_cpp(ONNX_PROTO_SRCS + onnx/onnx.in.proto diff --git a/onnx/defs/nn/old.cc b/onnx/defs/nn/old.cc -index a6a8a83..153da87 100644 +index 4dd6619..6187eb3 100644 --- a/onnx/defs/nn/old.cc +++ b/onnx/defs/nn/old.cc -@@ -4026,7 +4026,6 @@ ONNX_OPERATOR_SET_SCHEMA( +@@ -3995,7 +3995,6 @@ ONNX_OPERATOR_SET_SCHEMA( GroupNormalization, 18, OpSchema() diff --git a/cmake/vcpkg-ports/onnx/binskim.patch b/cmake/vcpkg-ports/onnx/binskim.patch index 0a5680778790b..8de740c79e21c 100644 --- a/cmake/vcpkg-ports/onnx/binskim.patch +++ b/cmake/vcpkg-ports/onnx/binskim.patch @@ -1,33 +1,27 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 044996e..ded7e39 100644 +index 365af87..defe81a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -53,6 +53,7 @@ option(ONNX_USE_LITE_PROTO "Use lite protobuf instead of full." OFF) - option(ONNX_DISABLE_EXCEPTIONS "Disable exception handling." OFF) +@@ -46,6 +46,7 @@ option(ONNX_DISABLE_EXCEPTIONS "Disable exception handling." OFF) option(ONNX_DISABLE_STATIC_REGISTRATION "Disable static registration for ONNX operator schemas." OFF) option(ONNX_USE_UNITY_BUILD "Enable Unity (Jumbo) build for" OFF) + option(ONNX_PYODIDE_BUILD "Build ONNX for Pyodide/Emscripten (wasm32)." OFF) +option(ONNX_MINIMAL_BUILD "Build only essential ONNX components" OFF) option(ONNX_INSTALL "Install ONNX targets, headers, and CMake config files" ON) if(WIN32) - option(ONNX_USE_MSVC_STATIC_RUNTIME "Build with MSVC static runtime" OFF) -@@ -399,14 +400,28 @@ relative_protobuf_generate_cpp(ONNX_PROTO_SRCS - onnx/onnx-operators.in.proto - onnx/onnx-data.in.proto) - --file(GLOB_RECURSE __tmp_srcs "${ONNX_ROOT}/onnx/*.h" "${ONNX_ROOT}/onnx/*.cc") --file(GLOB_RECURSE onnx_gtests_src "${ONNX_ROOT}/onnx/test/cpp/*.h" -- "${ONNX_ROOT}/onnx/test/cpp/*.cc" -- "${ONNX_ROOT}/onnx/backend/test/cpp/*.cc" -- "${ONNX_ROOT}/onnx/backend/test/cpp/*.h") --list(REMOVE_ITEM __tmp_srcs "${ONNX_ROOT}/onnx/cpp2py_export.cc") --list(REMOVE_ITEM __tmp_srcs ${onnx_gtests_src} "${ONNX_ROOT}/onnx/test/cmake/main.cc") --list(APPEND ONNX_SRCS ${__tmp_srcs}) + option(ONNX_USE_MSVC_STATIC_RUNTIME "Build with MSVC static runtime. Ignored if CMAKE_MSVC_RUNTIME_LIBRARY is defined." OFF) +@@ -494,7 +495,22 @@ endfunction() + # target_sources. onnx_core is an OBJECT library consumed by both the onnx + # static library and the onnx_cpp2py_export Python extension module. + add_library(onnx_core OBJECT) +-add_subdirectory(onnx) +if(ONNX_MINIMAL_BUILD) + message(STATUS "Configuring ONNX minimal build") -+ set(ONNX_SRCS -+ "${ONNX_ROOT}/onnx/common/common.h" -+ "${ONNX_ROOT}/onnx/defs/data_type_utils.h" -+ "${ONNX_ROOT}/onnx/defs/data_type_utils.cc" ++ # ORT's minimal/WebAssembly builds only need ONNX's type utilities and the ++ # generated protobuf sources (added unconditionally below); skip globbing in ++ # the full operator/schema sources via add_subdirectory(onnx). ++ target_sources(onnx_core PRIVATE ++ "${ONNX_ROOT}/onnx/defs/data_type_utils.cc" + ) + # Ensure ONNX_ML is treated as ON for minimal build consistency with ORT's file + set(ONNX_ML ON CACHE BOOL "Enable traditional ML API." FORCE) @@ -35,46 +29,16 @@ index 044996e..ded7e39 100644 + set(ONNX_BUILD_PYTHON OFF CACHE BOOL "Build Python binaries" FORCE) + set(ONNX_BUILD_TESTS OFF CACHE BOOL "Build ONNX C++ APIs Tests" FORCE) +else() -+ file(GLOB_RECURSE __tmp_srcs "${ONNX_ROOT}/onnx/*.h" "${ONNX_ROOT}/onnx/*.cc") -+ file(GLOB_RECURSE onnx_gtests_src "${ONNX_ROOT}/onnx/test/cpp/*.h" -+ "${ONNX_ROOT}/onnx/test/cpp/*.cc" -+ "${ONNX_ROOT}/onnx/backend/test/cpp/*.cc" -+ "${ONNX_ROOT}/onnx/backend/test/cpp/*.h") -+ list(REMOVE_ITEM __tmp_srcs "${ONNX_ROOT}/onnx/cpp2py_export.cc") -+ list(REMOVE_ITEM __tmp_srcs ${onnx_gtests_src} "${ONNX_ROOT}/onnx/test/cmake/main.cc") -+ list(APPEND ONNX_SRCS ${__tmp_srcs}) ++ add_subdirectory(onnx) +endif() - set(LINKED_PROTOBUF_TARGET protobuf::libprotobuf) - if(ONNX_USE_LITE_PROTO) -diff --git a/cmake/Utils.cmake b/cmake/Utils.cmake -index 1987edd..04b3088 100644 ---- a/cmake/Utils.cmake -+++ b/cmake/Utils.cmake -@@ -103,18 +103,7 @@ endfunction() - - function(add_onnx_compile_options target) - if(MSVC) -- # For disabling Protobuf related warnings -- set(protobuf_warnings -- /wd4146 # unary minus operator applied to unsigned type, result still -- # unsigned -- /wd4244 # 'argument': conversion from 'google::protobuf::uint64' to -- # 'int', possible loss of data -- /wd4267 # Conversion from 'size_t' to 'int', possible loss of data -- /wd4141 # 'inline': used more than once -- /wd4047 # '=': 'uintptr_t' differs in levels of indirection from 'void *' -- ) - add_msvc_runtime_flag(${target}) -- target_compile_options(${target} PUBLIC ${protobuf_warnings}) - if(ONNX_WERROR) - target_compile_options(${target} PRIVATE "/WX") - endif() + relative_protobuf_generate_cpp(ONNX_PROTO_SRCS + onnx/onnx.in.proto diff --git a/onnx/defs/nn/old.cc b/onnx/defs/nn/old.cc -index a6a8a83..153da87 100644 +index 4dd6619..6187eb3 100644 --- a/onnx/defs/nn/old.cc +++ b/onnx/defs/nn/old.cc -@@ -4026,7 +4026,6 @@ ONNX_OPERATOR_SET_SCHEMA( +@@ -3995,7 +3995,6 @@ ONNX_OPERATOR_SET_SCHEMA( GroupNormalization, 18, OpSchema() diff --git a/cmake/vcpkg-ports/onnx/portfile.cmake b/cmake/vcpkg-ports/onnx/portfile.cmake index 3450dcb2e80ce..d7343304e5466 100644 --- a/cmake/vcpkg-ports/onnx/portfile.cmake +++ b/cmake/vcpkg-ports/onnx/portfile.cmake @@ -3,8 +3,8 @@ vcpkg_check_linkage(ONLY_STATIC_LIBRARY) vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO onnx/onnx - REF "v${VERSION}" - SHA512 3cee4c0fbc9e260e360a62a59e324e0b127a5749f958e0704989b407a4c1179c637ef86e41a406e7868537a62a11a821e3433005eb0725f979145f8d514926bd + REF bc3be77bec2f628788796dff60819186bacf49df + SHA512 e0c526f50767f376b8ad2ac3dc6b109c65f5b3ed20418fd3c4260a954b796d828a30cb5141a23db9b4db8e4db391bfe5042ef99d141f60bdbdbb991b1f3ce467 PATCHES fix-cmakelists.patch fix-dependency-protobuf.patch diff --git a/cmake/vcpkg-ports/onnx/vcpkg.json b/cmake/vcpkg-ports/onnx/vcpkg.json index 5ad70ff409e05..c399d4c1ab087 100644 --- a/cmake/vcpkg-ports/onnx/vcpkg.json +++ b/cmake/vcpkg-ports/onnx/vcpkg.json @@ -1,6 +1,6 @@ { "name": "onnx", - "version-semver": "1.21.0", + "version-semver": "1.22.0", "port-version": 0, "description": "Open standard for machine learning interoperability", "homepage": "https://onnx.ai", From 93e582921852f517ea4d6608b3e75107f2386c00 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 20:21:06 +0000 Subject: [PATCH 02/18] T4: bump onnx pin 1.21.0 -> 1.22.0rc1 across CI requirements.txt files ONNX 1.22.0rc1 is published on PyPI (verified via pip index versions onnx --pre), so all 7 requirements files use the published wheel pin onnx==1.22.0rc1 rather than the git source pin. Agent-signed-off: Developer (0ede529c) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- onnxruntime/test/python/requirements.txt | 2 +- .../inference/aarch64/python/cpu/scripts/requirements.txt | 2 +- .../ci_build/github/linux/docker/scripts/lort/requirements.txt | 2 +- .../github/linux/docker/scripts/manylinux/requirements.txt | 2 +- tools/ci_build/github/linux/docker/scripts/requirements.txt | 2 +- tools/ci_build/github/linux/python/requirements.txt | 2 +- tools/ci_build/github/windows/python/requirements.txt | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/onnxruntime/test/python/requirements.txt b/onnxruntime/test/python/requirements.txt index 3ece2f39d4042..5c2f22b896dde 100644 --- a/onnxruntime/test/python/requirements.txt +++ b/onnxruntime/test/python/requirements.txt @@ -1,3 +1,3 @@ -onnx==1.21.0 +onnx==1.22.0rc1 pytest onnx-ir diff --git a/tools/ci_build/github/linux/docker/inference/aarch64/python/cpu/scripts/requirements.txt b/tools/ci_build/github/linux/docker/inference/aarch64/python/cpu/scripts/requirements.txt index 5a3f4e7a28dac..2165fa6b72773 100644 --- a/tools/ci_build/github/linux/docker/inference/aarch64/python/cpu/scripts/requirements.txt +++ b/tools/ci_build/github/linux/docker/inference/aarch64/python/cpu/scripts/requirements.txt @@ -7,4 +7,4 @@ wheel protobuf==5.29.6 sympy==1.14 flatbuffers -onnx==1.21.0 +onnx==1.22.0rc1 diff --git a/tools/ci_build/github/linux/docker/scripts/lort/requirements.txt b/tools/ci_build/github/linux/docker/scripts/lort/requirements.txt index eb52681341012..28e5b84b988ee 100644 --- a/tools/ci_build/github/linux/docker/scripts/lort/requirements.txt +++ b/tools/ci_build/github/linux/docker/scripts/lort/requirements.txt @@ -3,7 +3,7 @@ beartype==0.15.0 flatbuffers cerberus h5py -onnx==1.21.0 +onnx==1.22.0rc1 # Python dependencies required for pytorch development astunparse expecttest!=0.2.0 diff --git a/tools/ci_build/github/linux/docker/scripts/manylinux/requirements.txt b/tools/ci_build/github/linux/docker/scripts/manylinux/requirements.txt index 9a0a6d0f51900..53c5f0e1e1505 100644 --- a/tools/ci_build/github/linux/docker/scripts/manylinux/requirements.txt +++ b/tools/ci_build/github/linux/docker/scripts/manylinux/requirements.txt @@ -9,4 +9,4 @@ sympy==1.14 flatbuffers neural-compressor>=2.2.1 triton==3.5.0 -onnx==1.21.0 +onnx==1.22.0rc1 diff --git a/tools/ci_build/github/linux/docker/scripts/requirements.txt b/tools/ci_build/github/linux/docker/scripts/requirements.txt index e570d9d810ec4..5b402b4c4e431 100644 --- a/tools/ci_build/github/linux/docker/scripts/requirements.txt +++ b/tools/ci_build/github/linux/docker/scripts/requirements.txt @@ -12,4 +12,4 @@ protobuf==6.33.5 packaging onnxscript==0.6.2 onnx-ir==0.1.16 -onnx==1.21.0 +onnx==1.22.0rc1 diff --git a/tools/ci_build/github/linux/python/requirements.txt b/tools/ci_build/github/linux/python/requirements.txt index bfe9ab0d8a508..77e1c49619bc1 100644 --- a/tools/ci_build/github/linux/python/requirements.txt +++ b/tools/ci_build/github/linux/python/requirements.txt @@ -12,4 +12,4 @@ onnxscript==0.6.2 onnx-ir==0.1.16 jinja2 markupsafe -onnx==1.21.0 +onnx==1.22.0rc1 diff --git a/tools/ci_build/github/windows/python/requirements.txt b/tools/ci_build/github/windows/python/requirements.txt index 211932f8dfd3d..f6653009ab0c8 100644 --- a/tools/ci_build/github/windows/python/requirements.txt +++ b/tools/ci_build/github/windows/python/requirements.txt @@ -14,4 +14,4 @@ jinja2 markupsafe semver packaging -onnx==1.21.0 +onnx==1.22.0rc1 From 6d99b05f933f3de73293b37d327a0729683c9883 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 20:23:47 +0000 Subject: [PATCH 03/18] Enable ONNX opset 27 in ORT C++: bump transpose-optimizer max opset to 27 and register Range at opset 27 - optimizer_api.h: kMaxSupportedOpset 26 -> 27 - Range CPU kernel split into VERSIONED [11,26] + new non-versioned [27] reusing the existing kernel (Range-27 adds fp16/bf16 types and a stash_type attr; the existing common numeric types bind, fp16/bf16 is a deferred enhancement) - cpu_execution_provider.cc: versioned the Range forward-declare and BuildKernelCreateInfo entries and added the opset-27 Range registration Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../transpose_optimization/optimizer_api.h | 2 +- .../core/providers/cpu/cpu_execution_provider.cc | 11 +++++++++-- onnxruntime/core/providers/cpu/generator/range.cc | 14 +++++++++++++- 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/onnxruntime/core/optimizer/transpose_optimization/optimizer_api.h b/onnxruntime/core/optimizer/transpose_optimization/optimizer_api.h index df3eda39d9882..cd0094877657d 100644 --- a/onnxruntime/core/optimizer/transpose_optimization/optimizer_api.h +++ b/onnxruntime/core/optimizer/transpose_optimization/optimizer_api.h @@ -478,7 +478,7 @@ class GraphRef { } // namespace api constexpr int64_t kMinSupportedOpset = 7; -constexpr int64_t kMaxSupportedOpset = 26; +constexpr int64_t kMaxSupportedOpset = 27; // enum of results that a CostCheckFn can return. enum class CostCheckResult { diff --git a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc index fb854b19accfa..86200a92f4ff4 100644 --- a/onnxruntime/core/providers/cpu/cpu_execution_provider.cc +++ b/onnxruntime/core/providers/cpu/cpu_execution_provider.cc @@ -581,7 +581,7 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, uint64_t, BitShift); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, 12, Pad); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, 11, GatherND); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, Range); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, 26, Range); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, Unique); class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, 23, float, TopK); class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 11, 23, double, TopK); @@ -1519,6 +1519,9 @@ class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 26, uint32_t, CumProd); class ONNX_OPERATOR_TYPED_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 26, uint64_t, CumProd); +// Opset 27 +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCpuExecutionProvider, kOnnxDomain, 27, Range); + // !!PLEASE READ BELOW!! Following that, add new entries above this comment /* *** IMPORTANT! *** @@ -2289,7 +2292,8 @@ Status RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, @@ -3706,6 +3710,9 @@ Status RegisterOnnxOperatorKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + + // opset 27 + BuildKernelCreateInfo, }; for (auto& function_table_entry : function_table) { KernelCreateInfo info = function_table_entry(); diff --git a/onnxruntime/core/providers/cpu/generator/range.cc b/onnxruntime/core/providers/cpu/generator/range.cc index 01a06859e11cc..c7702a3a34bec 100644 --- a/onnxruntime/core/providers/cpu/generator/range.cc +++ b/onnxruntime/core/providers/cpu/generator/range.cc @@ -46,9 +46,21 @@ ONNX_OPERATOR_KERNEL_EX( #endif -ONNX_CPU_OPERATOR_KERNEL( +ONNX_CPU_OPERATOR_VERSIONED_KERNEL( Range, 11, + 26, + KernelDefBuilder() + .TypeConstraint("T", + BuildKernelDefConstraintsFromTypeList()), + Range); + +// Opset 27 added float16/bfloat16 to the type constraint and a stash_type attribute. +// The existing kernel continues to support the common numeric types; float16/bfloat16 +// support is a follow-up enhancement. +ONNX_CPU_OPERATOR_KERNEL( + Range, + 27, KernelDefBuilder() .TypeConstraint("T", BuildKernelDefConstraintsFromTypeList()), From 45f1aa7d5debd94187730268ce09698bb4acf306 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 20:30:34 +0000 Subject: [PATCH 04/18] Add opset-27 ONNX backend test filters and regenerate webgl operator doc (ONNX 1.22.0rc1, issue #28752) - onnx_backend_test_series_filters.jsonc: exclude deferred opset-27 ops CausalConvWithState and LinearAttention (whole families, base + _expanded), and the Range-27 float16/bfloat16 node tests (ORT CPU Range-27 reuses the existing kernel registration which supports only the common numeric types; fp16/bf16 is a tracked follow-up). float/int32 Range tests remain enabled. - js/web/docs/webgl-operators.md: regenerated via npm run build:doc; now lists CausalConvWithState and LinearAttention as unsupported WebGL ops, reflecting the opset-27 schemas pulled in by the submodule bump. Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- js/web/docs/webgl-operators.md | 2 ++ .../onnx_backend_test_series_filters.jsonc | 15 ++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/js/web/docs/webgl-operators.md b/js/web/docs/webgl-operators.md index 98a79de61727c..1a8a99b88b2e0 100644 --- a/js/web/docs/webgl-operators.md +++ b/js/web/docs/webgl-operators.md @@ -33,6 +33,7 @@ See [Compatibility](../README.md#Compatibility) for a list of the supported plat | [BlackmanWindow](https://github.com/onnx/onnx/blob/main/docs/Operators.md#BlackmanWindow) | | | [Cast](https://github.com/onnx/onnx/blob/main/docs/Operators.md#Cast) | [6-8](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Cast-6), [9-12](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Cast-9), [13-18](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Cast-13), [19-20](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Cast-19), [21-22](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Cast-21), [23](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Cast-23), [24](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Cast-24), [25+](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Cast-25) | | [CastLike](https://github.com/onnx/onnx/blob/main/docs/Operators.md#CastLike) | | +| [CausalConvWithState](https://github.com/onnx/onnx/blob/main/docs/Operators.md#CausalConvWithState) | | | [Ceil](https://github.com/onnx/onnx/blob/main/docs/Operators.md#Ceil) | [6-12](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Ceil-6), [13+](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Ceil-13) | | [Celu](https://github.com/onnx/onnx/blob/main/docs/Operators.md#Celu) | | | [CenterCropPad](https://github.com/onnx/onnx/blob/main/docs/Operators.md#CenterCropPad) | | @@ -97,6 +98,7 @@ See [Compatibility](../README.md#Compatibility) for a list of the supported plat | [LeakyRelu](https://github.com/onnx/onnx/blob/main/docs/Operators.md#LeakyRelu) | [6-15](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#LeakyRelu-6), [16+](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#LeakyRelu-16) | | [Less](https://github.com/onnx/onnx/blob/main/docs/Operators.md#Less) | [7-8](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Less-7), [9-12](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Less-9), [13+](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Less-13) | | [LessOrEqual](https://github.com/onnx/onnx/blob/main/docs/Operators.md#LessOrEqual) | | +| [LinearAttention](https://github.com/onnx/onnx/blob/main/docs/Operators.md#LinearAttention) | | | [Log](https://github.com/onnx/onnx/blob/main/docs/Operators.md#Log) | [6-12](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Log-6), [13+](https://github.com/onnx/onnx/blob/main/docs/Changelog.md#Log-13) | | [LogSoftmax](https://github.com/onnx/onnx/blob/main/docs/Operators.md#LogSoftmax) | | | [Loop](https://github.com/onnx/onnx/blob/main/docs/Operators.md#Loop) | | diff --git a/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc b/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc index bf5a2dfdf4c7e..f04ddf728629d 100644 --- a/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc +++ b/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc @@ -374,7 +374,20 @@ "^test_dft_rfft_opset19", "^test_dft_irfft_opset19", // ORT BitCast kernel does not support bool type. - "^test_bitcast_bool_to_uint8" + "^test_bitcast_bool_to_uint8", + // --- ONNX 1.22.0rc1 / opset 27 integration (issue #28752) --- + // CausalConvWithState and LinearAttention are new opset-27 ops whose CPU kernels + // are deferred to follow-up work; exclude their entire backend node-test families + // (base + _expanded) for this RC integration. + "^test_causal_conv_with_state", + "^test_linear_attention", + // Range was updated to opset 27, adding float16/bfloat16 to type-constraint T and a + // stash_type attribute. The ORT CPU Range-27 kernel reuses the existing registration, + // which supports the common numeric types (float/double/int16/int32/int64) only. + // float16/bfloat16 support is a tracked follow-up, so exclude those Range-27 node + // tests (base + _expanded). The float/int32 Range tests remain enabled. + "^test_range_float16_type", + "^test_range_bfloat16_type" ], "current_failing_tests_x86": [ "^test_vgg19", From 4acfeef53b840b92534f3b4714d253fc131d49f5 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 20:35:23 +0000 Subject: [PATCH 05/18] T6: opset-27 (ONNX 1.22) optimizer + EP guard updates for Range ONNX 1.22 re-registers Range with an opset-27 schema (adds stash_type attr, widens type constraints; signature unchanged: 3 scalar inputs -> 1-D output). - gather_fusion.cc: add 27 to GatherToSlice Range version list {1,11}->{1,11,27}; add opset-27 GatherToSliceFusion test. - embed_layer_norm_fusion.cc: add 27 to the two Range path matchers (parent_path_3/4) so the embedding fusion still matches opset-27 models. - coreml/nnapi/vsinpu/webnn base_op_builder.h: bump default GetMaxSupportedOpSet 25->27, matching the lockstep convention of prior ONNX-integration PRs (#26579, #25678, #24449) so opset-27 nodes are not spuriously rejected. qdq_util.cc / layout_transformation_potentially_added_ops.h / kernel_type_str_resolver_utils.cc were checked and need no change (none reference the opset-27 ops Range/CausalConvWithState/LinearAttention). Agent-signed-off: Developer (0ede529c) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- onnxruntime/core/optimizer/embed_layer_norm_fusion.cc | 4 ++-- .../core/providers/coreml/builders/impl/base_op_builder.h | 2 +- .../nnapi/nnapi_builtin/builders/impl/base_op_builder.h | 2 +- .../core/providers/vsinpu/builders/impl/base_op_builder.h | 2 +- .../core/providers/webnn/builders/impl/base_op_builder.h | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/onnxruntime/core/optimizer/embed_layer_norm_fusion.cc b/onnxruntime/core/optimizer/embed_layer_norm_fusion.cc index 606e91ce91bbb..2aed40885fc6b 100644 --- a/onnxruntime/core/optimizer/embed_layer_norm_fusion.cc +++ b/onnxruntime/core/optimizer/embed_layer_norm_fusion.cc @@ -256,7 +256,7 @@ static bool MatchPositionEmbeddingSubgraphsFromGather( std::vector parent_path_3{ {0, 1, "Expand", {8, 13}, kOnnxDomain}, {0, 0, "Unsqueeze", {1, 11, 13}, kOnnxDomain}, - {0, 0, "Range", {1, 11}, kOnnxDomain}, + {0, 0, "Range", {1, 11, 27}, kOnnxDomain}, {0, 1, "Cast", {9, 13}, kOnnxDomain}, {0, 0, "Gather", {1, 11, 13}, kOnnxDomain}, {0, 0, "Shape", {1, 13}, kOnnxDomain}}; @@ -264,7 +264,7 @@ static bool MatchPositionEmbeddingSubgraphsFromGather( std::vector parent_path_4{ {0, 1, "Expand", {8, 13}, kOnnxDomain}, {0, 0, "Unsqueeze", {1, 11, 13}, kOnnxDomain}, - {0, 0, "Range", {1, 11}, kOnnxDomain}, + {0, 0, "Range", {1, 11, 27}, kOnnxDomain}, {0, 1, "Gather", {1, 11, 13}, kOnnxDomain}, {0, 0, "Shape", {1, 13}, kOnnxDomain}}; // Match one of the three path patterns. diff --git a/onnxruntime/core/providers/coreml/builders/impl/base_op_builder.h b/onnxruntime/core/providers/coreml/builders/impl/base_op_builder.h index 0714ad08fb5fc..609a965fa5198 100644 --- a/onnxruntime/core/providers/coreml/builders/impl/base_op_builder.h +++ b/onnxruntime/core/providers/coreml/builders/impl/base_op_builder.h @@ -46,7 +46,7 @@ class BaseOpBuilder : public IOpBuilder { const logging::Logger& logger) const; virtual int GetMinSupportedOpSet(const Node& /*node*/) const { return 1; } - virtual int GetMaxSupportedOpSet(const Node& /*node*/) const { return 25; } + virtual int GetMaxSupportedOpSet(const Node& /*node*/) const { return 27; } bool HasSupportedOpSet(const Node& node, const logging::Logger& logger) const; bool HasSupportedInputs(const Node& node, const OpBuilderInputParams& input_params, diff --git a/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/impl/base_op_builder.h b/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/impl/base_op_builder.h index ca6ffb388cdc6..a573b73d2bbb5 100644 --- a/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/impl/base_op_builder.h +++ b/onnxruntime/core/providers/nnapi/nnapi_builtin/builders/impl/base_op_builder.h @@ -72,7 +72,7 @@ class BaseOpBuilder : public IOpBuilder { const OpSupportCheckParams& params) const; virtual int GetMinSupportedOpSet(const NodeUnit& /* node_unit */) const { return 1; } - virtual int GetMaxSupportedOpSet(const NodeUnit& /* node_unit */) const { return 25; } + virtual int GetMaxSupportedOpSet(const NodeUnit& /* node_unit */) const { return 27; } // Check if this node_unit's type is supported // SingleNode type NodeUnit is supported diff --git a/onnxruntime/core/providers/vsinpu/builders/impl/base_op_builder.h b/onnxruntime/core/providers/vsinpu/builders/impl/base_op_builder.h index 719a806376222..488581dbd0e97 100644 --- a/onnxruntime/core/providers/vsinpu/builders/impl/base_op_builder.h +++ b/onnxruntime/core/providers/vsinpu/builders/impl/base_op_builder.h @@ -49,7 +49,7 @@ class BaseOpBuilder : public IOpBuilder { virtual bool IsQuantizedOp(const NodeUnit& /* node_unit */) const { return false; } virtual int GetMinSupportedOpSet(const NodeUnit& /* node_unit */) const { return 1; } - virtual int GetMaxSupportedOpSet(const NodeUnit& /* node_unit */) const { return 25; } + virtual int GetMaxSupportedOpSet(const NodeUnit& /* node_unit */) const { return 27; } virtual bool HasSupportedInputOutputsImpl( const InitializedTensorSet& initializers, const NodeUnit& node_unit) const; diff --git a/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.h b/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.h index a765cd9cbca85..f4429fbb06457 100644 --- a/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.h +++ b/onnxruntime/core/providers/webnn/builders/impl/base_op_builder.h @@ -52,7 +52,7 @@ class BaseOpBuilder : public IOpBuilder { // We still set the minimal supported opset to 1 as we couldn't // get the model opset version at this stage. virtual int GetMinSupportedOpSet(const Node& /* node */) const { return 1; } - virtual int GetMaxSupportedOpSet(const Node& /* node */) const { return 25; } + virtual int GetMaxSupportedOpSet(const Node& /* node */) const { return 27; } private: bool HasSupportedOpSet(const Node& node, const logging::Logger& logger) const; From 5a7455d70521d41a2bba526c1523347d53b28bf6 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 20:37:42 +0000 Subject: [PATCH 06/18] T6: add Range opset-27 to GatherToSlice fusion + opset-27 test Completes the T6 opset-27 sweep that the prior commit (c6366eb) missed for these two files. ONNX 1.22 re-registers Range with an opset-27 schema (operator_sets.h line 1460); find_optimizer_opset_version_updates_required.py flagged: 'Newer opset found for kOnnxDomain.Range. Latest:27 Optimizer support ends at 11. File: gather_fusion.cc' - gather_fusion.cc:309: GatherToSlice Range version list {1,11}->{1,11,27}. Range-27's signature is unchanged (3 scalar inputs -> 1-D output; only adds stash_type attr and wider type constraints), and the fusion depends only on that signature, so extending the accepted SinceVersion list is safe. - graph_transform_test.cc: new OpSet-27 (int64) GatherToSliceFusion block mirroring the existing OpSet-12/OpSet-14 blocks, proving Range-27 -> Gather fuses to Slice. Agent-signed-off: Developer (0ede529c) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- onnxruntime/core/optimizer/gather_fusion.cc | 2 +- .../test/optimizer/graph_transform_test.cc | 39 +++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) diff --git a/onnxruntime/core/optimizer/gather_fusion.cc b/onnxruntime/core/optimizer/gather_fusion.cc index 32a45e548ca0a..1f0c0a6c4c6a9 100644 --- a/onnxruntime/core/optimizer/gather_fusion.cc +++ b/onnxruntime/core/optimizer/gather_fusion.cc @@ -306,7 +306,7 @@ Status GatherToSliceFusion::ApplyImpl(Graph& graph, bool& modified, int graph_le ORT_RETURN_IF_ERROR(Recurse(node, modified, graph_level, logger)); - if (!graph_utils::IsSupportedOptypeVersionAndDomain(node, "Range", {1, 11}) || + if (!graph_utils::IsSupportedOptypeVersionAndDomain(node, "Range", {1, 11, 27}) || !graph_utils::IsSupportedProvider(node, GetCompatibleExecutionProviders()) || node.GetOutputEdgesCount() != 1) { continue; } diff --git a/onnxruntime/test/optimizer/graph_transform_test.cc b/onnxruntime/test/optimizer/graph_transform_test.cc index 924ceaa19a47d..4e2ca4ce14108 100644 --- a/onnxruntime/test/optimizer/graph_transform_test.cc +++ b/onnxruntime/test/optimizer/graph_transform_test.cc @@ -10145,6 +10145,45 @@ TEST_F(GraphTransformationTests, GatherToSliceFusion) { ASSERT_STATUS_OK(TestGraphTransformer(build_test_case, 14, *logger_, std::move(transformer), TransformerLevel::Level1, 1, pre_graph_checker, post_graph_checker)); } + + // OpSet-27, Tind is int64. Range gained an opset-27 schema in ONNX 1.22; ensure the fusion still matches it. + { + auto build_test_case = [&](ModelTestBuilder& builder) { + auto* data_arg = builder.MakeInput({{8, 8, 8, 8}}); + auto* range_input_1 = builder.MakeInitializer({}, {static_cast(0)}); + auto* range_input_2 = builder.MakeInitializer({}, {static_cast(8)}); + auto* range_input_3 = builder.MakeInitializer({}, {static_cast(1)}); + auto* range_output = builder.MakeIntermediate(); + auto* gather_output = builder.MakeOutput(); + + builder.AddNode("Range", {range_input_1, range_input_2, range_input_3}, {range_output}); + builder.AddNode("Gather", {data_arg, range_output}, {gather_output}) + .AddAttribute("axis", static_cast(2)); + }; + + auto post_graph_checker = [&](Graph& graph) { + auto op_count_map = CountOpsInGraph(graph); + TEST_RETURN_IF_NOT(op_count_map["Range"] == 0); + TEST_RETURN_IF_NOT(op_count_map["Gather"] == 0); + TEST_RETURN_IF_NOT(op_count_map["Slice"] == 1); + for (auto& node : graph.Nodes()) { + if (node.OpType() == "Slice") { + const NodeArg& input_arg = *(node.InputDefs()[3]); + const ONNX_NAMESPACE::TensorProto* tensor_proto = + graph_utils::GetConstantInitializer(graph, input_arg.Name()); + TEST_RETURN_IF_NOT(tensor_proto != nullptr); + Initializer init_const{graph, *tensor_proto, graph.ModelPath()}; + TEST_RETURN_IF_NOT(tensor_proto->data_type() == ONNX_NAMESPACE::TensorProto_DataType_INT64); + TEST_RETURN_IF_NOT(2 == static_cast(*(init_const.data()))); + } + } + return Status::OK(); + }; + + std::unique_ptr transformer = std::make_unique(); + ASSERT_STATUS_OK(TestGraphTransformer(build_test_case, 27, *logger_, std::move(transformer), + TransformerLevel::Level1, 1, pre_graph_checker, post_graph_checker)); + } } #if !defined(DISABLE_CONTRIB_OPS) From 7297a735de757d9f9be6d24f1496c0263bdd1cb1 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 20:56:13 +0000 Subject: [PATCH 07/18] T7: regenerate docs/OperatorKernels.md for opset-27 Range (ONNX 1.22.0rc1) Update the CPU ai.onnx Range entry to reflect T2's split registration: a non-versioned opset-27 kernel (27+) plus the versioned [11, 26] kernel, matching the output of tools/python/gen_opkernel_doc.py against a fresh RelWithDebInfo build. The doc was updated surgically rather than via a full regen because this validation build is CPU-only (no CUDA/DML EPs available on this Linux host; DML is Windows-only). A full regen would have destructively dropped the CUDA and DmlExecutionProvider sections. The CPU-section delta was verified to be exactly this Range change by diffing the freshly generated CPU section against the committed doc. Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/OperatorKernels.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index f6ed4668bb36e..9681edf7f642d 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -341,7 +341,8 @@ The **OpSet Version** column uses the following notation: |RandomNormalLike|*in* input:**T1**
*out* output:**T2**|1+|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(double), tensor(float)| |RandomUniform|*out* output:**T**|1+|**T** = tensor(double), tensor(float)| |RandomUniformLike|*in* input:**T1**
*out* output:**T2**|1+|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(double), tensor(float)| -|Range|*in* start:**T**
*in* limit:**T**
*in* delta:**T**
*out* output:**T**|11+|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64)| +|Range|*in* start:**T**
*in* limit:**T**
*in* delta:**T**
*out* output:**T**|27+|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64)| +|||[11, 26]|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64)| |Reciprocal|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(double), tensor(float)| |||[6, 12]|**T** = tensor(double), tensor(float)| |ReduceL1|*in* data:**T**
*in* axes:**tensor(int64)**
*out* reduced:**T**

or

*in* data:**T**
*out* reduced:**T**|18+|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)| From e37ccf360e36354d2bdc12d84bae61e8054bb92f Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 21:08:24 +0000 Subject: [PATCH 08/18] Narrow opset-27 ONNX backend test filters: drop over-broad CausalConvWithState/LinearAttention/Range-fp16-bf16 exclusions (ONNX 1.22.0rc1, issue #28752) T7 validation showed all 62 opset-27 backend node tests (the complete set: base + _expanded, including fp16/bf16) pass on the CPU EP. These ops are ONNX function ops (and Range-27 carries a function body), so ORT expands them into primitive nodes at partition time and executes correctly despite no native kernel and the CPU Range-27 kernel registering only common numeric types. Verified via onnx_test_runner -e cpu (62/62 succeeded, output-compared) under ALLOW_RELEASED_ONNX_OPSET_ONLY=0. Removing the global filters restores backend-test coverage per design-review Minor-1. Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../onnx_backend_test_series_filters.jsonc | 25 +++++++++---------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc b/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc index f04ddf728629d..130122932b402 100644 --- a/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc +++ b/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc @@ -374,20 +374,19 @@ "^test_dft_rfft_opset19", "^test_dft_irfft_opset19", // ORT BitCast kernel does not support bool type. - "^test_bitcast_bool_to_uint8", + "^test_bitcast_bool_to_uint8" // --- ONNX 1.22.0rc1 / opset 27 integration (issue #28752) --- - // CausalConvWithState and LinearAttention are new opset-27 ops whose CPU kernels - // are deferred to follow-up work; exclude their entire backend node-test families - // (base + _expanded) for this RC integration. - "^test_causal_conv_with_state", - "^test_linear_attention", - // Range was updated to opset 27, adding float16/bfloat16 to type-constraint T and a - // stash_type attribute. The ORT CPU Range-27 kernel reuses the existing registration, - // which supports the common numeric types (float/double/int16/int32/int64) only. - // float16/bfloat16 support is a tracked follow-up, so exclude those Range-27 node - // tests (base + _expanded). The float/int32 Range tests remain enabled. - "^test_range_float16_type", - "^test_range_bfloat16_type" + // No opset-27 CPU exclusions are needed. The new opset-27 ops CausalConvWithState + // and LinearAttention are ONNX *function* ops, and the updated Range op (opset 27, + // which adds float16/bfloat16) also carries an ONNX function body. ORT expands these + // function bodies into primitive nodes at graph-partition time, so all 62 opset-27 + // backend node tests (base + _expanded, including fp16/bf16) pass on the CPU EP even + // though no native CausalConvWithState/LinearAttention kernel exists and the CPU + // Range-27 kernel registers only the common numeric types. Verified with + // onnx_test_runner -e cpu (62/62 succeeded, output-compared) under + // ALLOW_RELEASED_ONNX_OPSET_ONLY=0. If a non-CPU EP (e.g. CUDA/DML) surfaces a + // genuine failure in CI, add a narrowly-scoped EP-specific exclusion below rather + // than re-adding a global filter. ], "current_failing_tests_x86": [ "^test_vgg19", From 2df7ff56c8bb48c4a07e47fe5e8ceb3cd069b713 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 21:22:43 +0000 Subject: [PATCH 09/18] review-polish A4: clarify opset-27 Range comment that fp16/bf16 models work today via ONNX function-body expansion (ONNX 1.22.0rc1, issue #28752) The prior comment said float16/bfloat16 'support is a follow-up enhancement', which a maintainer could misread as fp16/bf16 Range being broken. Clarify that such models execute correctly today because Range-27 carries an ONNX function body that ORT expands at graph-partition time; the follow-up is an efficient native kernel, not a functional fix. Comment-only change; verified onnxruntime_providers recompiles and all 20 GatherToSliceFusion/EmbedLayerNormFusion optimizer tests pass. Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- onnxruntime/core/providers/cpu/generator/range.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/onnxruntime/core/providers/cpu/generator/range.cc b/onnxruntime/core/providers/cpu/generator/range.cc index c7702a3a34bec..fcd4abcf72f87 100644 --- a/onnxruntime/core/providers/cpu/generator/range.cc +++ b/onnxruntime/core/providers/cpu/generator/range.cc @@ -56,8 +56,11 @@ ONNX_CPU_OPERATOR_VERSIONED_KERNEL( Range); // Opset 27 added float16/bfloat16 to the type constraint and a stash_type attribute. -// The existing kernel continues to support the common numeric types; float16/bfloat16 -// support is a follow-up enhancement. +// This kernel continues to natively support the common numeric types only; a native +// float16/bfloat16 kernel is a follow-up enhancement. Note that float16/bfloat16 Range +// models still execute correctly today: Range-27 carries an ONNX function body that ORT +// expands into primitive ops at graph-partition time, so the follow-up is about adding an +// efficient native kernel, not about fixing broken functionality. ONNX_CPU_OPERATOR_KERNEL( Range, 27, From 3da8169dfcb618d8936108ec15a464e144790724 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 21:24:51 +0000 Subject: [PATCH 10/18] review-polish: make GPU/CUDA/DML-unverified status explicit in opset-27 filter comment (ONNX 1.22.0rc1, issue #28752) The opset-27 validation only exercised the CPU EP. That limitation was previously only implicit (via the 'if a non-CPU EP fails in CI' clause). Add an explicit NOTE so a future maintainer cannot miss that GPU/CUDA/DML EPs were not exercised in this validation env. Comment-only; JSONC still parses (302 entries unchanged). Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../test/testdata/onnx_backend_test_series_filters.jsonc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc b/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc index 130122932b402..5937001e3e3c6 100644 --- a/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc +++ b/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc @@ -384,7 +384,8 @@ // though no native CausalConvWithState/LinearAttention kernel exists and the CPU // Range-27 kernel registers only the common numeric types. Verified with // onnx_test_runner -e cpu (62/62 succeeded, output-compared) under - // ALLOW_RELEASED_ONNX_OPSET_ONLY=0. If a non-CPU EP (e.g. CUDA/DML) surfaces a + // ALLOW_RELEASED_ONNX_OPSET_ONLY=0. NOTE: GPU/CUDA/DML EPs were NOT exercised in + // this validation env -- CPU EP only. If a non-CPU EP (e.g. CUDA/DML) surfaces a // genuine failure in CI, add a narrowly-scoped EP-specific exclusion below rather // than re-adding a global filter. ], From d51661219a790ec54e189cb8574a91063656ffde Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 21:54:56 +0000 Subject: [PATCH 11/18] Add onnx-opset-bump-checklist skill doc Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../skills/onnx-opset-bump-checklist/SKILL.md | 427 ++++++++++++++++++ 1 file changed, 427 insertions(+) create mode 100644 .agents/skills/onnx-opset-bump-checklist/SKILL.md diff --git a/.agents/skills/onnx-opset-bump-checklist/SKILL.md b/.agents/skills/onnx-opset-bump-checklist/SKILL.md new file mode 100644 index 0000000000000..5e045b58a3792 --- /dev/null +++ b/.agents/skills/onnx-opset-bump-checklist/SKILL.md @@ -0,0 +1,427 @@ +--- +name: onnx-opset-bump-checklist +description: Step-by-step checklist for bumping the pinned ONNX dependency / opset in ONNX Runtime (e.g. ONNX 1.21 / opset 26 → 1.22 / opset 27). Use when integrating a new ONNX release or release-candidate, updating the cmake/deps.txt onnx pin or the cmake/external/onnx submodule, regenerating cmake/patches/onnx/onnx.patch, raising kMaxSupportedOpset, or adding a new opset's CPU kernels. Covers the file taxonomy, archive-hash procedures, patch rebase/mirror rules, the RC→formal strategy, and the optimizer/EP gotchas that the automated audit script misses. +--- + +# ONNX Opset / Version Bump Checklist for ONNX Runtime + +Repeatable process for upgrading the ONNX dependency in ONNX Runtime. Recurs on every ONNX +release. Canonical reference PRs: **#27601** (ONNX 1.21, incremental rc1→formal — best +example), #26579 (1.20.1), #25678 (1.19). See also `docs/How_To_Update_ONNX_Dev_Notes.md`. + +## 0. Strategy: RC → formal (incremental) + +ONNX partner-validates each release candidate against ORT **before** publishing the formal +release — that is the whole point of the integration issue. When the issue points at a +`rel-X.Y.0` branch: + +1. **Integrate the RC first.** Pin by the release-branch **HEAD commit** (the `vX.Y.0rcN` + git *tag* usually does not exist yet). Run the full build + tests; file ONNX bugs upstream + (tag the ONNX release manager) for any ONNX-side defects found. +2. **Re-pin per RC** (rc2, rc3, …). Usually only the Group-A version-plumbing files change. + **Drop any `onnx.patch` hunks that ONNX has merged upstream** in the new RC. +3. **Re-pin to the formal tag** `vX.Y.0` once the GitHub Release is published. Note the + release can sit as a **draft** (no git tag, `git/ref/tags/vX.Y.0` → 404) for a while. + +```bash +gh api repos/onnx/onnx/git/ref/heads/rel-X.Y.0 --jq '.object.sha' # RC branch HEAD +curl -sL https://raw.githubusercontent.com/onnx/onnx/rel-X.Y.0/VERSION_NUMBER # e.g. X.Y.0rcN +gh api 'repos/onnx/onnx/releases?per_page=5' --jq '.[].tag_name' # '' => draft +``` + +## 1. File taxonomy — what to change + +Grouped so parallel work is safe. **Group A must land first** (the tree must build before +B/C/D can be validated). Throughout this section, bold letters in parentheses (e.g. gotcha +**a**, **g**) refer to the lettered gotchas **a**–**i** defined in §4. + +### Group A — version plumbing (always required, mechanical) +| File | Note | +|---|---| +| `cmake/deps.txt` (`onnx;` line) | archive URL + **SHA1 of the `.zip`** (see §2) | +| `cmake/external/onnx` (submodule) | `git -C cmake/external/onnx fetch && git -C cmake/external/onnx reset --hard && git add cmake/external/onnx` | +| `cmake/vcpkg-ports/onnx/vcpkg.json` | `version-semver`; reset `port-version` to 0 on a real version bump | +| `cmake/vcpkg-ports/onnx/portfile.cmake` | `REF` + **SHA512 of the `.tar.gz`** (see §2). RC = bare commit as `REF`; formal = `REF "v${VERSION}"` | +| `cmake/vcpkg-ports/onnx/binskim.patch` | keep **byte-identical** to `onnx.patch` (see §3) | +| `cmake/patches/onnx/onnx.patch` | rebase to the new source (see §3) | +| `cmake/vcpkg-ports/onnx/fix-dependency-protobuf.patch`, `fix-cmakelists.patch` | re-`diff` only if they fail to apply | +| **The 7 `requirements.txt` files** with `onnx==X.Y.Z` | `onnxruntime/test/python/requirements.txt`; `tools/ci_build/github/linux/python/requirements.txt`; `tools/ci_build/github/windows/python/requirements.txt`; `tools/ci_build/github/linux/docker/scripts/{requirements.txt,manylinux/requirements.txt,lort/requirements.txt}`; `tools/ci_build/github/linux/docker/inference/aarch64/python/cpu/scripts/requirements.txt`. Confirm with `git grep -n "onnx=="` (e.g. `onnx==1.21`) — grep the **old** pin you are replacing, not bare `onnx==1`. ⚠️ **Do NOT bump all matches.** `git grep -n "onnx==1"` also lists 3 transformers-model files — `onnxruntime/python/tools/transformers/models/{llama,phi2,stable_diffusion}/requirements.txt` — that are **intentionally frozen at `onnx==1.18.0`**. Leave those alone; only the 7 CI files above get the new pin. | + +### Group B — opset enablement +| File | Change | +|---|---| +| `onnxruntime/core/optimizer/transpose_optimization/optimizer_api.h` | `kMaxSupportedOpset` → new max opset (e.g. 26 → 27) | +| `onnxruntime/core/providers/cpu/cpu_execution_provider.cc` | add `// Opset N` forward-declares + `BuildKernelCreateInfo<...>` entries for new/updated CPU kernels; mirror the previous opset block exactly | +| `onnxruntime/core/graph/contrib_ops/contrib_defs.h`, `dml_ops/dml_defs.h` | apply ONNX-header-driven `OpSchemaRegisterOnce` macro fixes **only if the build emits those errors** | + +> **IR version is NOT bumped manually.** ORT reads `ONNX_NAMESPACE::Version::IR_VERSION` from +> the ONNX headers (`onnxruntime/core/graph/model.cc`); it follows the submodule automatically. + +### Group C — docs & test data (mostly auto-generated) +| File | Change | +|---|---| +| `docs/OperatorKernels.md` | regenerate (see gotcha **e** — needs a built ORT module): `python tools/python/gen_opkernel_doc.py --output_path docs/OperatorKernels.md` | +| `js/web/docs/webgl-operators.md` | `cd js/web && npm install && npm run build:doc` (the WebAssembly CI "Check out of dated documents" stage fails otherwise) | +| `onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc` | exclude backend tests for ops whose kernels are deferred (gotcha **g**) | +| `onnxruntime/test/testdata/onnx_backend_test_series_overrides.jsonc` | tolerance overrides for new tests | +| `onnxruntime/test/onnx/TestCase.cc` | `broken_tests` entries for genuinely-unsupported cases | + +### Group D — conditional (touch only if build/tests flag it — but see §4 gotchas) +`onnxruntime/core/framework/kernel_type_str_resolver_utils.cc`, +`onnxruntime/core/optimizer/layout_transformation/layout_transformation_potentially_added_ops.h`, +`onnxruntime/core/optimizer/qdq_transformer/qdq_util.cc`, EP `base_op_builder.h` max-opset +guards (gotcha **b**), optimizer fusion path-matchers (gotcha **a**, **c**), and any CPU op +file hard-coding a `SinceVersion` ceiling for a changed op. + +## 2. Archive-hash procedures + +`cmake/deps.txt` 3rd field = **SHA1 of the downloaded `.zip`** (verified: `sha1sum` of +`v1.21.0.zip` equals the pinned `321d4acc...`): +```bash +URL="https://github.com/onnx/onnx/archive/.zip" +curl -sL -o onnx.zip "$URL" && sha1sum onnx.zip # paste: onnx;$URL; +``` +vcpkg `portfile.cmake` uses **SHA512 of the `.tar.gz`**: +```bash +curl -sL -o onnx.tgz "https://github.com/onnx/onnx/archive/.tar.gz" +sha512sum onnx.tgz +``` +Shortcut: pin a wrong hash and build — ORT/FetchContent prints the expected one. + +> The submodule field (a git commit SHA) and the deps.txt field (a SHA1 of the archive +> *contents*) are **different by design** — never interchange them. + +> **vcpkg artifact must be mirrored** to the Microsoft vcpkg store before `--use_vcpkg` +> builds can download it (Terrapin upload — see below). Not self-service; coordinate with +> infra. This is gotcha **f**. + +### Mirroring the ONNX archive to the MS vcpkg store (required before `--use_vcpkg` builds pass) + +The SHA512 in `portfile.cmake` references a `.tar.gz` that vcpkg downloads from the **Microsoft +vcpkg artifact mirror**, not from GitHub. Until that exact archive is uploaded to the mirror, +`--use_vcpkg` builds fail with a download/hash error. The upload is done with the **Terrapin +Retrieval Tool** and is a **Windows + `az` auth + internal-credential** step — it **cannot** run +from a generic Linux CI host. + +**Step 1 — auth (PowerShell):** +```powershell +$authScope = 'https://mspmecloud.onmicrosoft.com/RebuildManager.Web/.default' +$env:TRT_UPLOAD_AUTH_TOKEN = $(az account get-access-token --scope $authScope --query 'accessToken' --output tsv) +``` + +**Step 2a — commit-version (RC phase, archive keyed by commit SHA):** +```powershell +C:\local\Terrapin\TerrapinRetrievalTool.exe -b https://vcpkg.storage.devpackages.microsoft.io/artifacts/ ` + -a true -u Environment ` + -p https://github.com/onnx/onnx/archive/.tar.gz ` + -s ` + -d "\Windows\vcpkg\downloads\onnx-onnx-.tar.gz.part" +``` + +**Step 2b — tag-version (formal phase, archive keyed by release tag):** +```powershell +C:\local\Terrapin\TerrapinRetrievalTool.exe -b https://vcpkg.storage.devpackages.microsoft.io/artifacts/ ` + -a true -u Environment ` + -p https://github.com/onnx/onnx/archive/refs/tags/v.tar.gz ` + -s ` + -d "\Windows\vcpkg\downloads\onnx-onnx-v.tar.gz" +``` + +Key notes: +- **(a)** `-s ` **MUST equal** the `portfile.cmake` SHA512 (the `sha512sum` of the same + `.tar.gz` — see §2). A mismatch re-uploads the wrong blob and the hash check still fails. +- **(b)** This is *why* `--use_vcpkg` builds fail with a download error until the upload lands — + the mirror has no copy of the new archive yet. +- **(c)** Microsoft-internal infra step: coordinate with the infra owner (e.g. **@snnn**). + External / Linux CI **cannot** perform it (needs Windows, the Terrapin tool, and `az` creds). +- **(d)** The **`cmake/deps.txt` path does NOT need this** — that build fetches the `.zip` + straight from GitHub. Only the vcpkg (`--use_vcpkg`) path depends on the mirror. +- **(e)** The `.part` suffix on the 2a `-d` path is vcpkg's **in-progress-download** temp name + (vcpkg renames it to the final `.tar.gz` once the hash verifies). Match whatever the failing + `--use_vcpkg` build actually requests in its `downloads/` dir — the RC run wrote a `.part`; + the formal-tag run wrote the bare `.tar.gz`. When unsure, copy the exact path from the build's + download error. + +## 3. onnx.patch rebase + binskim.patch mirror + +For each hunk in `cmake/patches/onnx/onnx.patch`, against the **new** ONNX source: +- Applies cleanly → keep. +- Context shifted → rebase (regenerate line numbers/indices). +- Fixed upstream in the new ONNX → **drop the hunk** (#27601 added a Slice `dim_value==0` + hunk for rc1/rc2 then removed it at rc3 once ONNX merged it). +- ONNX restructured the region → **rewrite the hunk.** Example (1.21 → 1.22): ONNX replaced + the `file(GLOB_RECURSE __tmp_srcs ...)` source-gathering block with an + `add_library(onnx_core OBJECT)` + `add_subdirectory(onnx)` model, so the `ONNX_MINIMAL_BUILD` + hunk had to switch from editing `set(ONNX_SRCS ...)` to + `target_sources(onnx_core PRIVATE "${ONNX_ROOT}/onnx/defs/data_type_utils.cc")`. Note + `data_type_utils.cc` lives in `onnx/defs/` (not `onnx/common/`), and headers do **not** + belong in `target_sources` (they are not compile units). + > **Structural note (re-validate every bump):** in the `onnx_core` OBJECT-lib layout, + > minimal mode skips `add_subdirectory(onnx)`. That is only safe because + > `add_onnx_compile_options(onnx_core)` (include dirs + protobuf link) and + > `add_onnx_global_defines(onnx_core)` are **unconditional at the top-level CMakeLists**. + > If a future ONNX moves those into the `onnx/` subdirectory, minimal builds will fail to + > configure/link — so never *assume* the minimal hunk still works; re-run the minimal build + > (§5) on every bump. + +Then **mirror the final `onnx.patch` byte-for-byte into +`cmake/vcpkg-ports/onnx/binskim.patch`** — they must stay identical. Verify: +```bash +git apply --check cmake/patches/onnx/onnx.patch +patch --binary --ignore-whitespace -p1 --dry-run < cmake/patches/onnx/onnx.patch +sha1sum cmake/patches/onnx/onnx.patch cmake/vcpkg-ports/onnx/binskim.patch # must match +``` + +## 4. Gotchas (the expensive ones — hand-check these) + +These are not caught by the automated audit and have bitten real integrations: + +**(a) The optimizer audit script misses fusion path-matchers.** +`tools/python/find_optimizer_opset_version_updates_required.py` only inspects **direct kernel +registrations** — it does **not** see opset version lists embedded in optimizer +`graph_utils::EdgeEndToMatch` **path-matchers**. When an op's opset changes, hand-grep the +fusion files and extend the version list. Confirmed sites for **`Range` → 27**: +- `onnxruntime/core/optimizer/embed_layer_norm_fusion.cc` — `EdgeEndToMatch` entries + `{0, 0, "Range", {1, 11, 27}, kOnnxDomain}` (multiple `parent_path_*`). +- `onnxruntime/core/optimizer/gather_fusion.cc` — `IsSupportedOptypeVersionAndDomain(node, + "Range", {1, 11, 27})` (Range→Gather→Slice fusion). +```bash +grep -rn '' onnxruntime/core/optimizer/*fusion*.cc | grep -iE 'EdgeEndToMatch|IsSupportedOptypeVersionAndDomain|\{[0-9, ]+\}' +``` + +**(b) EP `base_op_builder.h` `GetMaxSupportedOpSet` must be bumped in lockstep.** +Each NPU/coreml/web EP caps the opset it will partition. Bump every one that returns the old +max: +- `onnxruntime/core/providers/coreml/builders/impl/base_op_builder.h` +- `onnxruntime/core/providers/nnapi/nnapi_builtin/builders/impl/base_op_builder.h` +- `onnxruntime/core/providers/vsinpu/builders/impl/base_op_builder.h` +- `onnxruntime/core/providers/webnn/builders/impl/base_op_builder.h` +```bash +grep -rn 'GetMaxSupportedOpSet' onnxruntime/core/providers/*/builders/impl/base_op_builder.h +# all should return the NEW max opset (e.g. 27) +``` + +**(c) Fusion `IsSupportedOptypeVersionAndDomain` version lists** (same root cause as **a**) — +grep all of `onnxruntime/core/optimizer/` for the changed op, not just `*fusion*` files. + +**(d) The audit script crashes on placeholder macros.** +`find_optimizer_opset_version_updates_required.py` has a pre-existing crash (a placeholder +`'ver'` token gets parsed as an `int`). Expect it to throw on a clean main; don't treat the +crash as a signal from your change. Run it, but rely on the manual greps in **a–c**. + +**(e) `OperatorKernels.md` regeneration needs a built ORT Python module.** +`gen_opkernel_doc.py` imports `onnxruntime`, so build + install the wheel first (or download +the regenerated markdown from a CI published-artifact, which the dev-notes recommend). + +**(f) vcpkg artifact mirroring** — see §2; `--use_vcpkg` builds fail to download until done. +Because the vcpkg path is mirror-gated (not self-service), **do not rely on it to validate the +`onnx.patch` rebase.** Use the minimal build instead — it is mirror-independent (see §5 and **(i)**). + +**(g) Defer-and-filter brand-new, unimplemented ops — and why it is safe.** +Do not block the version bump on full kernels for large new ops (e.g. stateful +attention/conv). Exclude them in `onnx_backend_test_series_filters.jsonc` and track kernels as +follow-up PRs (#25678 deferred `TensorScatter`/`Swish` this way). Keeps the bump PR reviewable. +This is safe because ORT failures here are **node-local, not model-load-blocking**: +- ORT kernel matching is per-`(op, type-set)`. Registering an updated op for only a **subset** + of the new schema's types (e.g. `Range`-27 with the 5 common numeric types, deferring + fp16/bf16) does **not** break model load — the ONNX schema validates the model; only the + specific unsupported-type node fails kernel lookup with a clear "kernel not found". +- Deferring a brand-new op entirely (no kernel) is likewise node-local: ORT advertises the new + opset because the **submodule** registers the schemas (`operator_sets.h` / + `DomainToVersionRange::Map()`), independent of the transpose-optimizer `kMaxSupportedOpset`. + The model **loads**; the unimplemented node fails at kernel-bind. Precedent: `TensorScatter` + (24), `LpNormalization` (22, test name `test_l2normalization`), `TreeEnsemble` all sit in the filters file as "not implemented". +- Optional new schema attributes whose default "has no effect for other types" (e.g. + `Range`-27 `stash_type`) can be ignored by the kernel for the registered types — safe to defer. + +**(h) Function-op test filters — don't over-filter the `_expanded` variant.** +Many new/updated ops are ONNX **functions** (have `SetContextDependentFunctionBodyBuilder`) — +e.g. `Range`-27, `CausalConvWithState`, `LinearAttention`. ONNX emits two backend-test +variants: `test_` and `test__expanded` (the decomposed primitive subgraph). ORT can +usually **run** `_expanded` via the primitive decomposition even when the fused kernel is +deferred. An **unanchored** filter like `^test_range_float16_type` also drops `_expanded`, +silently losing real coverage. When deferring an op, in §5/T7 run `onnx_test_runner` and check +whether the `_expanded` variants pass; if they do, **narrow the filter** (anchor it / exclude +only the bare name) to keep coverage. Over-filtering is CI-safe but hides working paths. + +**(i) On a shared multi-agent branch, read clean `main`, not the working tree.** +Another agent may already have rebased `onnx.patch`. Inspect with +`git show :cmake/patches/onnx/onnx.patch` rather than reading the file directly. + +## 5. Build & validate locally + +**The canonical build + test command set lives in §9 (verification gauntlet)** — run those to +define "done". This section keeps only the +*rationale* for the highest-risk gate (don't duplicate the command list here — it drifts): + +> **MERGE GATE for the patch rebase (gotcha a/i + §3):** the `ONNX_MINIMAL_BUILD` hunk in +> `onnx.patch`/`binskim.patch` is the single highest-risk change and is **only** exercised when +> `ONNX_MINIMAL_BUILD=ON` — set by `build.py --minimal_build` **and always by the vcpkg port** +> (`tools/python/util/vcpkg_helpers.py`). Since the vcpkg path is mirror-gated (gotcha f), the +> `--minimal_build extended` command (§9 step 2) is the **cheap, mirror-independent gate**: it +> pulls the ONNX archive from `cmake/deps.txt` (no vcpkg mirror needed) and proves the rebased +> minimal hunk **configures + compiles + links**. Make a green minimal build a required gate +> before merging any `onnx.patch` rebase. + +Then update `TestCase.cc` / `onnx_backend_test_series_*.jsonc` for newly-introduced failing +node tests. After the PR is up, manually queue every packaging pipeline on the branch, and ask +infra to deploy any new ONNX test data to CI machines (dev-notes). + +## 6. Quick checklist +- [ ] Group A: deps.txt (zip SHA1), submodule, vcpkg.json, portfile.cmake (tar.gz SHA512), onnx.patch rebased, binskim.patch mirrored byte-identical, all 7 requirements.txt (NOT the 3 transformers-model files frozen at onnx==1.18.0) +- [ ] Group B: `kMaxSupportedOpset`, cpu_execution_provider.cc opset block, (contrib/dml macros if build demands) +- [ ] **Safety invariant (§11): every new no-kernel op MUST carry an ONNX function body — else its native kernel is a BLOCKER this PR, not a follow-up** +- [ ] Gotchas: fusion path-matchers (embed_layer_norm_fusion.cc, gather_fusion.cc), all 4 EP `GetMaxSupportedOpSet`, run audit script (expect crash), defer-and-filter new ops (node-local & safe), narrow function-op `_expanded` filters +- [ ] Group C: OperatorKernels.md (built module), webgl-operators.md, backend test filters/overrides +- [ ] Validate: run the **§9 verification gauntlet** (full build, `--minimal_build extended` gate, onnxruntime_test_all, onnx_test_runner -e cpu; `--use_vcpkg` after artifact mirrored) + +## 7. Worked example — ONNX 1.21 → 1.22.0rc1 (a template to copy) + +The real values from this session's bump. **Replace every value in `<...>` for the next bump**; +the structure stays the same. + +| Field | This bump (1.21 → 1.22.0rc1) | Where it goes | +|---|---|---| +| Source pin | commit `bc3be77bec2f628788796dff60819186bacf49df` (`rel-1.22.0` HEAD; RC has **no git tag** yet) | submodule + deps.txt URL + portfile `REF` | +| deps.txt SHA1 | `421e5a9afb6c41a54696e424e5b9a3796aab6821` (**SHA1 of the `.zip`**) | `cmake/deps.txt` 3rd field | +| portfile SHA512 | `e0c526f50767f376b8ad2ac3dc6b109c65f5b3ed20418fd3c4260a954b796d828a30cb5141a23db9b4db8e4db391bfe5042ef99d141f60bdbdbb991b1f3ce467` (**SHA512 of the `.tar.gz`**) | `cmake/vcpkg-ports/onnx/portfile.cmake` | +| Opset | 26 → **27** | `kMaxSupportedOpset`, cpu_execution_provider.cc | +| IR version | **13 (unchanged)** — auto from headers, do not touch | — | +| New/updated ops | `Range`-27 (updated, function), `CausalConvWithState` + `LinearAttention` (new, functions) | see §11 safety invariant | + +**Exact files touched this bump** (26 files — use as a coverage checklist): +``` +cmake/deps.txt # zip SHA1 + URL +cmake/external/onnx # submodule -> bc3be77b +cmake/patches/onnx/onnx.patch # rebase: 2 files / 3 @@ hunks — CMakeLists.txt (option decl + ONNX_MINIMAL_BUILD src restructure) + onnx/defs/nn/old.cc (GroupNormalization-18 .Deprecate() removal). Utils.cmake NOT touched (upstream-merged protobuf hunk dropped this bump) +cmake/vcpkg-ports/onnx/binskim.patch # byte-identical mirror of onnx.patch +cmake/vcpkg-ports/onnx/portfile.cmake # REF bc3be77b + tar.gz SHA512 +cmake/vcpkg-ports/onnx/vcpkg.json # version-semver + port-version 0 +docs/OperatorKernels.md # CPU-only surgical update (full regen = follow-up) +js/web/docs/webgl-operators.md # npm run build:doc +onnxruntime/core/optimizer/embed_layer_norm_fusion.cc # Range path-matcher {1,11,27} (gotcha a) +onnxruntime/core/optimizer/gather_fusion.cc # Range {1,11,27} (gotcha c) +onnxruntime/core/optimizer/transpose_optimization/optimizer_api.h # kMaxSupportedOpset 26->27 +onnxruntime/core/providers/cpu/cpu_execution_provider.cc # opset-27 kernel block +onnxruntime/core/providers/cpu/generator/range.cc # Range-27 kernel +onnxruntime/core/providers/{coreml,nnapi,vsinpu,webnn}/.../base_op_builder.h # GetMaxSupportedOpSet ->27 (gotcha b) +onnxruntime/test/optimizer/graph_transform_test.cc # fusion test updates +onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc # defer-and-filter new ops +onnxruntime/test/python/requirements.txt + 6 CI requirements.txt # onnx==1.22.0rc1 (NOT the 3 frozen at 1.18.0) +``` + +## 8. Hash-recompute one-liners + +Both hashes are of the **GitHub source archive at the pinned ref**, but of **different archive +formats** — keep them straight: + +```bash +REF=bc3be77bec2f628788796dff60819186bacf49df # commit (RC) — or v1.22.0 (formal tag) + +# deps.txt 3rd field = SHA1 of the .ZIP: +curl -sL "https://github.com/onnx/onnx/archive/${REF}.zip" | sha1sum + +# portfile.cmake SHA512 = SHA512 of the .TAR.GZ: +curl -sL "https://github.com/onnx/onnx/archive/${REF}.tar.gz" | sha512sum +``` +> `.zip` → **SHA1** → deps.txt. `.tar.gz` → **SHA512** → portfile. Never cross them. +> For a formal release use `refs/tags/v` in place of the bare commit in both URLs. + +> ⚠️ **RC commit and formal tag produce DIFFERENT hashes — recompute is MANDATORY when you +> switch `REF`.** GitHub names the archive's top-level directory after the ref +> (`onnx-/` for a commit vs `onnx-/` for `refs/tags/v`), so the +> archive **bytes differ** even though the tree content is identical. **Never reuse the RC +> commit's SHA1/SHA512 for the formal tag** — re-run both one-liners above against the tag. + +## 9. Verification gauntlet — what "done" means + +Run all of these green before calling a bump complete: + +```bash +# 1. Full build (deps.txt path): +./build.sh --config RelWithDebInfo --build_wheel --parallel +# 2. Minimal-build gate (proves the rebased ONNX_MINIMAL_BUILD onnx.patch hunk; mirror-independent): +./build.sh --config RelWithDebInfo --minimal_build extended --parallel --skip_tests +# 3. ORT unit tests: +./build/Linux/RelWithDebInfo/onnxruntime_test_all +# 4. ONNX backend node tests for the new opset on CPU EP: +./build/Linux/RelWithDebInfo/onnx_test_runner -e cpu \ + build/Linux/RelWithDebInfo/_deps/onnx-src/onnx/backend/test/data/node +``` +- **(a)** `ALLOW_RELEASED_ONNX_OPSET_ONLY` is **ORT-side load-time validation** + (`onnxruntime/core/graph/model_load_utils.h`), **not** schema registration — the ONNX schemas + for the new opset are **always** compiled in from the submodule regardless. With the default + `=1`, ORT **rejects at model-load** any model whose opset is still "under development" (e.g. + opset 27 during the RC), so the new-opset node tests fail / report "not implemented". Build and + run the gauntlet with **`ALLOW_RELEASED_ONNX_OPSET_ONLY=0`** so ORT loads and runs those + under-development-opset models. (Consistent with §4 gotcha **g**: schemas come from the + submodule; this flag only governs whether ORT *accepts* the model at load.) +- **(b)** Expect the new-op node tests you intentionally deferred to be **filtered** in + `onnx_backend_test_series_filters.jsonc` — but confirm the `_expanded` variants still run + (gotcha **h**): a function op with no native kernel must still PASS via decomposition (§11). +- **(c)** `--use_vcpkg` build is **not** a merge gate until the artifact is mirrored (§2); the + minimal build (step 2) is the mirror-independent stand-in that proves the patch rebase. + +## 10. PR-body template (fill in the blanks) + +```markdown +### Bump ONNX to (opset ) + +Pin: onnx/onnx@. Opset . IR version . + +**Standing caveats** +- **EP `GetMaxSupportedOpSet` bumped to ** (coreml/nnapi/vsinpu/webnn). These EPs gain no + new op kernels in this PR; the bump only raises the support ceiling so existing ops on + opset- models partition. New-op kernels for these EPs are follow-ups. +- **`OperatorKernels.md` updated for CPU EP only** (surgical edit). A full multi-EP regen needs + a built ORT module per EP and is tracked as a follow-up (gotcha **e**). +- **Opset is under development** (RC): ORT load-time validation rejects opset- models + unless `ALLOW_RELEASED_ONNX_OPSET_ONLY=0` (schemas are always compiled in from the submodule + — see §9a/§4g). Brand-new ops without kernels are **deferred + filtered** + in `onnx_backend_test_series_filters.jsonc` (node-local, safe — see skill §4 gotcha g). +- **GPU EPs unverified**: only CPU EP was built/tested here. CUDA/DML/etc. opset- coverage + is a follow-up. + +**Validation:** full build ✅, `--minimal_build extended` ✅, onnxruntime_test_all ✅, +onnx_test_runner -e cpu (opset- node tests) ✅. +``` + +## 11. SAFETY INVARIANT — no-kernel ops MUST carry a function body + +> **🚨 For every new/updated opset op that you ship WITHOUT a native ORT kernel, confirm the +> op carries an ONNX FUNCTION BODY. If it has NO function body, a native kernel is MANDATORY in +> THIS PR — it cannot be a follow-up. Otherwise the model loads but the node fails at session +> initialization.** + +**"Native kernel" means** any registered kernel that **binds the opset-N node** — including an +**open-ended existing kernel** (e.g. one registered `SinceVersion(13)` with no upper bound) that +already covers opset N. Such an op is **already kernel-covered** and does **not** trigger the +blocker below; the blocker applies **only** when *no* registered kernel binds the new-opset node +**and** the op has no function body. + +**Why (the function-expansion mechanism):** an ONNX *function* op ships a reference +decomposition into primitive ops (`SetContextDependentFunctionBodyBuilder` / +`FunctionBodyHelper`). At graph-partition time ORT **inlines** (expands) any function-op node +that has no registered kernel into its primitive subgraph, which IS kernel-covered — so the op +runs with zero native code. A **non-function** op has no such fallback: with no binding kernel, +kernel binding fails at **session initialization** (fail-fast `kernel not found`), even though +the model loaded (schema came from the submodule — see §4 gotcha **g**). + +> ⚠️ **Scope: runtime function-inlining is a FULL-build behavior.** Minimal / mobile / +> ORT-format builds do **not** runtime-inline function ops. The §9 gauntlet only proves the +> minimal build **compiles** (`--skip_tests`); it never **runs** a function-op model in a +> minimal build. So do **not** assume the function-inlining fallback gives minimal-build runtime +> coverage — a function-only op with no native kernel will not execute in a minimal build. + +This is exactly why the 1.22 bump could defer native kernels for **`CausalConvWithState`**, +**`LinearAttention`**, and **`Range`-27 fp16/bf16** and still pass (in a full build): all three +are ONNX functions, so ORT inlined them. Decision rule per new op: + +| A binding kernel covers the opset-N node? | Op has ONNX function body? | Action | +|---|---|---| +| Yes (incl. open-ended existing kernel) | — | Already covered; done | +| No | **Yes** | Safe to defer kernel — ORT inlines (full build); verify the `_expanded` test passes | +| No | **No** | **BLOCKER — write the kernel in this PR** (op would load then fail at session init) | + +Quick check: grep the ONNX op's `defs.cc` for `SetContextDependentFunctionBodyBuilder` or +`FunctionBody`; if absent, it is not a function and needs a kernel. From 16720d1075d2a92b73b66217c07c6634684f4ec5 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 22:49:49 +0000 Subject: [PATCH 12/18] Bump CUDA Range kernel to opset 27 (mirror CPU) Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/OperatorKernels.md | 3 ++- .../providers/cuda/cuda_execution_provider.cc | 9 +++++-- .../core/providers/cuda/generator/range.cc | 25 ++++++++++++++++++- 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index 9681edf7f642d..584e1f04d1a15 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -901,7 +901,8 @@ The **OpSet Version** column uses the following notation: |||[1, 21]|**T** = tensor(double), tensor(float), tensor(float16)| |RandomUniformLike|*in* input:**T1**
*out* output:**T2**|22+|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |||[1, 21]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(double), tensor(float), tensor(float16)| -|Range|*in* start:**T**
*in* limit:**T**
*in* delta:**T**
*out* output:**T**|11+|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64)| +|Range|*in* start:**T**
*in* limit:**T**
*in* delta:**T**
*out* output:**T**|27+|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64)| +|||[11, 26]|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64)| |Reciprocal|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16)| |ReduceL1|*in* data:**T**
*in* axes:**tensor(int64)**
*out* reduced:**T**

or

*in* data:**T**
*out* reduced:**T**|18+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32)| diff --git a/onnxruntime/core/providers/cuda/cuda_execution_provider.cc b/onnxruntime/core/providers/cuda/cuda_execution_provider.cc index e9339956a387b..e70329b310b76 100755 --- a/onnxruntime/core/providers/cuda/cuda_execution_provider.cc +++ b/onnxruntime/core/providers/cuda/cuda_execution_provider.cc @@ -1009,7 +1009,7 @@ class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kO class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 11, 12, If); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 11, 12, Loop); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 11, NonMaxSuppression); -class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 11, Range); +class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 11, 26, Range); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 11, 15, Scan); class ONNX_OPERATOR_VERSIONED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 11, 12, ScatterElements); class ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 11, 12, int32_t, Slice); @@ -1873,6 +1873,9 @@ class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 25, S class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 25, Squeeze); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 25, Transpose); class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 25, Unsqueeze); + +// Opset 27. +class ONNX_OPERATOR_KERNEL_CLASS_NAME(kCudaExecutionProvider, kOnnxDomain, 27, Range); #endif static Status RegisterCudaKernels(KernelRegistry& kernel_registry) { @@ -2293,7 +2296,7 @@ static Status RegisterCudaKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, - BuildKernelCreateInfo, + BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, @@ -3153,6 +3156,8 @@ static Status RegisterCudaKernels(KernelRegistry& kernel_registry) { BuildKernelCreateInfo, BuildKernelCreateInfo, BuildKernelCreateInfo, + // Opset 27 + BuildKernelCreateInfo, #endif }; diff --git a/onnxruntime/core/providers/cuda/generator/range.cc b/onnxruntime/core/providers/cuda/generator/range.cc index d0746688eb193..f9952df6ece42 100644 --- a/onnxruntime/core/providers/cuda/generator/range.cc +++ b/onnxruntime/core/providers/cuda/generator/range.cc @@ -13,10 +13,33 @@ using namespace ONNX_NAMESPACE; namespace onnxruntime { namespace cuda { -ONNX_OPERATOR_KERNEL_EX( +ONNX_OPERATOR_VERSIONED_KERNEL_EX( Range, kOnnxDomain, 11, + 26, + kCudaExecutionProvider, + (*KernelDefBuilder::Create()) + .InputMemoryType(OrtMemTypeCPUInput, 0) // start + .InputMemoryType(OrtMemTypeCPUInput, 1) // limit + .InputMemoryType(OrtMemTypeCPUInput, 2) // delta + .TypeConstraint("T", {DataTypeImpl::GetTensorType(), + DataTypeImpl::GetTensorType(), + DataTypeImpl::GetTensorType(), + DataTypeImpl::GetTensorType(), + DataTypeImpl::GetTensorType()}), + Range); + +// Opset 27 added float16/bfloat16 to the type constraint and a stash_type attribute. +// This kernel continues to natively support the common numeric types only; a native +// float16/bfloat16 CUDA kernel (range_impl.cu specialization) is a follow-up enhancement. +// Note that float16/bfloat16 Range models still execute correctly today: Range-27 carries +// an ONNX function body that ORT expands into primitive ops at graph-partition time, so the +// follow-up is about adding an efficient native kernel, not about fixing broken functionality. +ONNX_OPERATOR_KERNEL_EX( + Range, + kOnnxDomain, + 27, kCudaExecutionProvider, (*KernelDefBuilder::Create()) .InputMemoryType(OrtMemTypeCPUInput, 0) // start From 06ced99cc1b85877a2a401656a242a61c6e59ff1 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Tue, 2 Jun 2026 22:52:09 +0000 Subject: [PATCH 13/18] onnx-opset-bump skill: encode 'bump ALL execution providers together' tradition MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an op's kernel set changes for the new opset (e.g. Range gaining fp16/bf16 at opset 27), version-split / bump that op's registration in EVERY EP that registers it (CPU and CUDA at minimum) in the SAME PR, so no EP silently lags behind CPU and the advertised opset boundaries stay consistent. Even an open-ended kernel that already binds the new opset (e.g. CUDA Range at SinceVersion(11)) should still be version-split for convention/clarity. Worked example cited: PR #28754 split Range [11,26]+27 in both CPU and CUDA (verified). - §1 Group B: added the all-EP tradition callout + an EP checklist (grep each provider dir; split cpu/cuda/js/rocm macro registrations; assess dml/webgpu/coreml/nnapi/etc. per their own systems; bump coreml/nnapi/vsinpu/webnn GetMaxSupportedOpSet ceilings). - §11: added a cross-EP consistency convention note distinguishing splitting (clarity) from binding-coverage (correctness). - §6 checklist: Group B line now calls out version-splitting in every EP. Agent-signed-off: Architect (bcad189c) [claude-opus-4.8 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Agent-signed-off: Architect (bcad189c) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../skills/onnx-opset-bump-checklist/SKILL.md | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/.agents/skills/onnx-opset-bump-checklist/SKILL.md b/.agents/skills/onnx-opset-bump-checklist/SKILL.md index 5e045b58a3792..28dcfe5628075 100644 --- a/.agents/skills/onnx-opset-bump-checklist/SKILL.md +++ b/.agents/skills/onnx-opset-bump-checklist/SKILL.md @@ -54,6 +54,22 @@ B/C/D can be validated). Throughout this section, bold letters in parentheses (e | `onnxruntime/core/providers/cpu/cpu_execution_provider.cc` | add `// Opset N` forward-declares + `BuildKernelCreateInfo<...>` entries for new/updated CPU kernels; mirror the previous opset block exactly | | `onnxruntime/core/graph/contrib_ops/contrib_defs.h`, `dml_ops/dml_defs.h` | apply ONNX-header-driven `OpSchemaRegisterOnce` macro fixes **only if the build emits those errors** | +> **🆕 Tradition: bump EVERY EP that registers the op, in the SAME PR.** When an op's kernel set +> changes for the new opset (e.g. `Range` gaining fp16/bf16 at opset 27), version-split / bump +> that op's registration in **every** EP that registers it — **CPU and CUDA at minimum** — so no +> EP silently lags behind CPU and the advertised opset boundaries stay consistent. **Even an +> open-ended kernel that already binds the new opset** (e.g. CUDA `Range` at `SinceVersion(11)`, +> which already matches opset-27 nodes) should still be **version-split** for convention/clarity +> and to keep the kernel's advertised boundary matching the schema. Worked example — **PR #28754** +> split `Range` into `[11,26]` + `27` in **both** CPU and CUDA (verified), keeping the same +> numeric type set and deferring fp16/bf16 to ONNX function-expansion. + +**EP checklist when an op's kernel set changes for the new opset:** +- [ ] For **each** EP, `grep -rn ")" onnxruntime/core/providers//` (and its `*_execution_provider.cc`) to find every registration of the changed op. +- [ ] EPs that register ONNX kernels via the `ONNX_OPERATOR_[VERSIONED_]KERNEL[_CLASS_NAME]` macros — **cpu**, **cuda**, **js**, and **rocm** if it registers the op (rocm is often hipified from cuda): version-split each into `[prev_start, N-1]` + a new `N` registration (class forward-declare **and** `BuildKernelCreateInfo` entry). +- [ ] EPs with their **own** registration systems assess per their conventions, not the macro split — **dml** (`REG_INFO(ver, Op, …)` in `OperatorRegistration.cpp`), **webgpu**, **coreml/nnapi/qnn/openvino/migraphx**. A partition/capability check (e.g. MIGraphX's `optype == "Range"`) is **not** a kernel registration and needs no split. +- [ ] Bump the EP `GetMaxSupportedOpSet` ceilings (**coreml/nnapi/vsinpu/webnn**) in lockstep — see §4 gotcha **b**. + > **IR version is NOT bumped manually.** ORT reads `ONNX_NAMESPACE::Version::IR_VERSION` from > the ONNX headers (`onnxruntime/core/graph/model.cc`); it follows the submodule automatically. @@ -269,7 +285,7 @@ infra to deploy any new ONNX test data to CI machines (dev-notes). ## 6. Quick checklist - [ ] Group A: deps.txt (zip SHA1), submodule, vcpkg.json, portfile.cmake (tar.gz SHA512), onnx.patch rebased, binskim.patch mirrored byte-identical, all 7 requirements.txt (NOT the 3 transformers-model files frozen at onnx==1.18.0) -- [ ] Group B: `kMaxSupportedOpset`, cpu_execution_provider.cc opset block, (contrib/dml macros if build demands) +- [ ] Group B: `kMaxSupportedOpset`, cpu_execution_provider.cc opset block, **version-split the changed op in EVERY EP that registers it (cpu+cuda+js, rocm if present) — §1 Group B all-EP tradition**, (contrib/dml macros if build demands) - [ ] **Safety invariant (§11): every new no-kernel op MUST carry an ONNX function body — else its native kernel is a BLOCKER this PR, not a follow-up** - [ ] Gotchas: fusion path-matchers (embed_layer_norm_fusion.cc, gather_fusion.cc), all 4 EP `GetMaxSupportedOpSet`, run audit script (expect crash), defer-and-filter new ops (node-local & safe), narrow function-op `_expanded` filters - [ ] Group C: OperatorKernels.md (built module), webgl-operators.md, backend test filters/overrides @@ -399,6 +415,14 @@ already covers opset N. Such an op is **already kernel-covered** and does **not* blocker below; the blocker applies **only** when *no* registered kernel binds the new-opset node **and** the op has no function body. +> **Convention (cross-EP consistency) — distinct from the binding-coverage rule above.** Even +> when an open-ended kernel already binds opset N (so it is *not* a blocker), still +> **version-split** it — and do so in **every** EP that registers the op (see the Group B all-EP +> tradition). PR #28754 split `Range` `[11,26]`+`27` in **both** CPU and CUDA even though CUDA's +> `SinceVersion(11)` kernel already bound opset 27, so the advertised boundary matches the schema +> and no EP lags behind CPU. Splitting is about **clarity/consistency**; binding-coverage is +> about **correctness** — keep the two concerns distinct. + **Why (the function-expansion mechanism):** an ONNX *function* op ships a reference decomposition into primitive ops (`SetContextDependentFunctionBodyBuilder` / `FunctionBodyHelper`). At graph-partition time ORT **inlines** (expands) any function-op node From 8fdb354a052885b0efa8003bbfe70efa47e08d34 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Wed, 3 Jun 2026 17:07:47 +0000 Subject: [PATCH 14/18] Update FunctionTest cycle-rejection assertions for ONNX 1.22 checker message Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- onnxruntime/test/framework/function_test.cc | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/onnxruntime/test/framework/function_test.cc b/onnxruntime/test/framework/function_test.cc index ee3b0a6ec2133..351bfb6e2b0a8 100644 --- a/onnxruntime/test/framework/function_test.cc +++ b/onnxruntime/test/framework/function_test.cc @@ -120,6 +120,16 @@ static Status LoadModel(const char* source) { return session_object.Load(sstr); } +// A recursive/cyclic chain of model-local functions can be rejected by either layer: +// ONNX 1.22+ detects the cycle in its own model checker ("Cycle detected in model-local +// function references"), which runs before ORT's equivalent check ("must not be recursive"). +// Older ONNX versions don't catch it, so ORT's check fires instead. Accept either message so +// the cycle-rejection tests pass regardless of which layer rejects the model. +static testing::Matcher HasCycleRejectionMessage() { + return testing::AnyOf(testing::HasSubstr("must not be recursive"), + testing::HasSubstr("Cycle detected in model-local function references")); +} + namespace { const char* basic_code = R"( < @@ -358,7 +368,7 @@ TEST(FunctionTest, RejectsSelfRecursiveLocalFunction) { const auto status = LoadModel(code); ASSERT_FALSE(status.IsOK()); - EXPECT_THAT(status.ErrorMessage(), testing::HasSubstr("must not be recursive")); + EXPECT_THAT(status.ErrorMessage(), HasCycleRejectionMessage()); } TEST(FunctionTest, RejectsMutuallyRecursiveLocalFunctions) { @@ -391,7 +401,7 @@ TEST(FunctionTest, RejectsMutuallyRecursiveLocalFunctions) { const auto status = LoadModel(code); ASSERT_FALSE(status.IsOK()); - EXPECT_THAT(status.ErrorMessage(), testing::HasSubstr("must not be recursive")); + EXPECT_THAT(status.ErrorMessage(), HasCycleRejectionMessage()); } TEST(FunctionTest, RejectsRecursionThroughSubgraph) { @@ -572,7 +582,7 @@ TEST(FunctionTest, RejectsLongerCycle) { const auto status = LoadModel(code); ASSERT_FALSE(status.IsOK()); - EXPECT_THAT(status.ErrorMessage(), testing::HasSubstr("must not be recursive")); + EXPECT_THAT(status.ErrorMessage(), HasCycleRejectionMessage()); } TEST(FunctionTest, AcceptsAcyclicDiamond) { @@ -697,7 +707,7 @@ TEST(FunctionTest, RejectsMultipleIndependentCycles) { const auto status = LoadModel(code); ASSERT_FALSE(status.IsOK()); - EXPECT_THAT(status.ErrorMessage(), testing::HasSubstr("must not be recursive")); + EXPECT_THAT(status.ErrorMessage(), HasCycleRejectionMessage()); } // Test use of attibute references, especially where source/target attribute From c7119310e7e580a91f0cba15b8819a1d6e628217 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Wed, 3 Jun 2026 18:04:40 +0000 Subject: [PATCH 15/18] Fix opset-27 GatherToSliceFusion test on strict ALLOW_RELEASED_ONNX_OPSET_ONLY legs Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- onnxruntime/test/optimizer/graph_transform_test.cc | 8 +++++++- .../test/unittest_util/graph_transform_test_builder.cc | 10 ++++++---- .../test/unittest_util/graph_transform_test_builder.h | 9 +++++++-- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/onnxruntime/test/optimizer/graph_transform_test.cc b/onnxruntime/test/optimizer/graph_transform_test.cc index 4e2ca4ce14108..a44a85373e516 100644 --- a/onnxruntime/test/optimizer/graph_transform_test.cc +++ b/onnxruntime/test/optimizer/graph_transform_test.cc @@ -10181,8 +10181,14 @@ TEST_F(GraphTransformationTests, GatherToSliceFusion) { }; std::unique_ptr transformer = std::make_unique(); + // Opset 27 is still under development in ONNX 1.22, so the default released-opset-only model load + // would throw on strict (ALLOW_RELEASED_ONNX_OPSET_ONLY!=0) legs. Allow the unreleased opset here so + // this sub-block exercises the opset-27 Range schema on every CI leg, not just the relaxed ones. + const ModelOptions allow_unreleased_opset{/*allow_released_opsets_only*/ false, + /*strict_shape_type_inference*/ false}; ASSERT_STATUS_OK(TestGraphTransformer(build_test_case, 27, *logger_, std::move(transformer), - TransformerLevel::Level1, 1, pre_graph_checker, post_graph_checker)); + TransformerLevel::Level1, 1, pre_graph_checker, post_graph_checker, + allow_unreleased_opset)); } } diff --git a/onnxruntime/test/unittest_util/graph_transform_test_builder.cc b/onnxruntime/test/unittest_util/graph_transform_test_builder.cc index 5caafa0f379d4..d0276a2c3b8a6 100644 --- a/onnxruntime/test/unittest_util/graph_transform_test_builder.cc +++ b/onnxruntime/test/unittest_util/graph_transform_test_builder.cc @@ -222,17 +222,19 @@ void TransformerTester(const std::function& buil Status TestGraphTransformer(const std::function& build_test_case, int opset_version, const logging::Logger& logger, std::unique_ptr transformer, TransformerLevel level, unsigned steps, const std::function& pre_graph_checker, - const std::function& post_graph_checker) { + const std::function& post_graph_checker, + const ModelOptions& model_options) { const std::vector opset_versions{opset_version}; return TestGraphTransformer(build_test_case, opset_versions, logger, std::move(transformer), - level, steps, pre_graph_checker, post_graph_checker); + level, steps, pre_graph_checker, post_graph_checker, model_options); } Status TestGraphTransformer(const std::function& build_test_case, const std::vector& opset_versions, const logging::Logger& logger, std::unique_ptr transformer, TransformerLevel level, unsigned steps, const std::function& pre_graph_checker, - const std::function& post_graph_checker) { + const std::function& post_graph_checker, + const ModelOptions& model_options) { onnxruntime::GraphTransformerManager graph_transformation_mgr{steps}; ORT_RETURN_IF_ERROR(graph_transformation_mgr.Register(std::move(transformer), level)); @@ -242,7 +244,7 @@ Status TestGraphTransformer(const std::function& domain_to_version[kOnnxDomain] = opset; domain_to_version[kMSDomain] = 1; Model model("TransformerTester", false, ModelMetaData(), PathString(), IOnnxRuntimeOpSchemaRegistryList(), - domain_to_version, {}, logger); + domain_to_version, {}, logger, model_options); Graph& graph = model.MainGraph(); ModelTestBuilder helper(graph); ORT_RETURN_IF_NOT(build_test_case, "build_test_case must be provided"); diff --git a/onnxruntime/test/unittest_util/graph_transform_test_builder.h b/onnxruntime/test/unittest_util/graph_transform_test_builder.h index bc3c9535a853a..8f0f5aeb238d2 100644 --- a/onnxruntime/test/unittest_util/graph_transform_test_builder.h +++ b/onnxruntime/test/unittest_util/graph_transform_test_builder.h @@ -12,6 +12,7 @@ #include "core/framework/framework_common.h" #include "core/framework/int4.h" #include "core/optimizer/graph_transformer_level.h" +#include "core/graph/model.h" #include "core/graph/onnx_protobuf.h" #include "core/framework/tensorprotoutils.h" #include "test/unittest_util/framework_test_utils.h" @@ -598,7 +599,8 @@ void TransformerTester(const std::function& buil Status TestGraphTransformer(const std::function& build_test_case, int opset_version, const logging::Logger& logger, std::unique_ptr transformer, TransformerLevel level, unsigned steps, const std::function& pre_graph_checker, - const std::function& post_graph_checker); + const std::function& post_graph_checker, + const ModelOptions& model_options = {}); /** * @brief Apply a GraphTransformer to a graph, and run graph checkers before and after applying the transformer. @@ -611,11 +613,14 @@ Status TestGraphTransformer(const std::function& * @param steps The step count of the GraphTransformerManager * @param pre_graph_checker The graph checker function before applying the transformer * @param post_graph_checker The graph checker function after applying the transformer + * @param model_options Options used when constructing the test model (e.g. to allow loading + * under-development/unreleased ONNX opsets). Defaults to released-opset-only. */ Status TestGraphTransformer(const std::function& build_test_case, const std::vector& opset_versions, const logging::Logger& logger, std::unique_ptr transformer, TransformerLevel level, unsigned steps, const std::function& pre_graph_checker, - const std::function& post_graph_checker); + const std::function& post_graph_checker, + const ModelOptions& model_options = {}); } // namespace test } // namespace onnxruntime From c256720f502706d1799c783570381eb03434018f Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Wed, 3 Jun 2026 18:07:13 +0000 Subject: [PATCH 16/18] Filter unimplemented ONNX 1.22 FlexAttention + dtype-256 backend tests Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../onnx_backend_test_series_filters.jsonc | 35 ++++++++++++------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc b/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc index 5937001e3e3c6..c69e403a91b82 100644 --- a/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc +++ b/onnxruntime/test/testdata/onnx_backend_test_series_filters.jsonc @@ -374,20 +374,29 @@ "^test_dft_rfft_opset19", "^test_dft_irfft_opset19", // ORT BitCast kernel does not support bool type. - "^test_bitcast_bool_to_uint8" + "^test_bitcast_bool_to_uint8", // --- ONNX 1.22.0rc1 / opset 27 integration (issue #28752) --- - // No opset-27 CPU exclusions are needed. The new opset-27 ops CausalConvWithState - // and LinearAttention are ONNX *function* ops, and the updated Range op (opset 27, - // which adds float16/bfloat16) also carries an ONNX function body. ORT expands these - // function bodies into primitive nodes at graph-partition time, so all 62 opset-27 - // backend node tests (base + _expanded, including fp16/bf16) pass on the CPU EP even - // though no native CausalConvWithState/LinearAttention kernel exists and the CPU - // Range-27 kernel registers only the common numeric types. Verified with - // onnx_test_runner -e cpu (62/62 succeeded, output-compared) under - // ALLOW_RELEASED_ONNX_OPSET_ONLY=0. NOTE: GPU/CUDA/DML EPs were NOT exercised in - // this validation env -- CPU EP only. If a non-CPU EP (e.g. CUDA/DML) surfaces a - // genuine failure in CI, add a narrowly-scoped EP-specific exclusion below rather - // than re-adding a global filter. + // Most opset-27 node tests pass on the CPU EP: CausalConvWithState and LinearAttention + // are ONNX *function* ops, and the float16 Range-27 op carries an ONNX function body, so + // ORT expands them into primitive nodes at graph-partition time (verified with + // onnx_test_runner -e cpu, output-compared, under ALLOW_RELEASED_ONNX_OPSET_ONLY=0). + // Two categories still need exclusions in the Python onnx_backend_test_series harness: + // + // 1. FlexAttention is a brand-new ONNX 1.22 op in the ai.onnx.preview domain. It DOES carry + // a (context-dependent) ONNX function body, but ORT does not register the ai.onnx.preview + // domain at all, so it has neither a native kernel nor function-body expansion -> the node + // cannot resolve on any EP yet ("ai.onnx.preview:FlexAttention is not a registered op"). + // Scope: exclude ONLY the base node tests (which contain the unresolved FlexAttention + // node). The 11 *_expanded_ver26 variants decompose to standard ai.onnx ops (no preview + // node; the ai.onnx.preview opset_import in their header is unused and harmless), so they + // load and pass -- the negative lookahead keeps them running to retain that coverage. + // Follow-up: register ai.onnx.preview / implement FlexAttention. + "^test_flexattention_(?!.*expanded)", + // 2. The bfloat16 Range-27 node tests feed bf16 tensors that the Python backend harness + // cannot materialize as numpy arrays ("Numpy_type 256 can't be converted to + // MLDataType"); the CPU/CUDA Range kernels also have no native bf16 specialization + // (deferred to ONNX function expansion). Covers both the base and _expanded variants. + "^test_range_bfloat16_type_positive_delta" ], "current_failing_tests_x86": [ "^test_vgg19", From 85a11f2a88439980abc51a478f43eea7b7c3d95f Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Wed, 3 Jun 2026 19:16:29 +0000 Subject: [PATCH 17/18] Pin released opset in symlink-data test to avoid ONNX 1.22 opset-27 default Agent-signed-off: Developer (d307842f) [claude-opus-4.6 via copilot] Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../onnxruntime_test_python_symlink_data.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/onnxruntime/test/python/onnxruntime_test_python_symlink_data.py b/onnxruntime/test/python/onnxruntime_test_python_symlink_data.py index ea3c0f9ca9904..1972134277e61 100644 --- a/onnxruntime/test/python/onnxruntime_test_python_symlink_data.py +++ b/onnxruntime/test/python/onnxruntime_test_python_symlink_data.py @@ -65,7 +65,10 @@ def test_symlink_model_and_data_under_same_directory(self): const_node = helper.make_node("Constant", [], ["const_out"], value=tensor) add_node = helper.make_node("Add", ["input", "const_out"], ["output"]) graph = helper.make_graph([const_node, add_node], "test_graph", [input_], [output]) - model = helper.make_model(graph) + # Model is opset-agnostic (Constant + Add); pin a released opset so ONNX 1.22 + # does not default to the under-development opset 27, which fails strict + # ALLOW_RELEASED_ONNX_OPSET_ONLY legs (ValidateOpsetForDomain throws). + model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 22)]) model_blob_path = os.path.join(blobs_dir, "guid1") save(model, model_blob_path) @@ -143,7 +146,10 @@ def test_symlink_with_data_in_model_sub_dir(self): const_node = helper.make_node("Constant", [], ["const_out"], value=tensor) add_node = helper.make_node("Add", ["input", "const_out"], ["output"]) graph = helper.make_graph([const_node, add_node], "test_graph", [input_], [output]) - model = helper.make_model(graph) + # Model is opset-agnostic (Constant + Add); pin a released opset so ONNX 1.22 + # does not default to the under-development opset 27, which fails strict + # ALLOW_RELEASED_ONNX_OPSET_ONLY legs (ValidateOpsetForDomain throws). + model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 22)]) model_blob_path = os.path.join(blobs_dir, "guid1") save(model, model_blob_path) @@ -222,7 +228,10 @@ def test_symlink_with_data_not_in_model_sub_dir(self): const_node = helper.make_node("Constant", [], ["const_out"], value=tensor) add_node = helper.make_node("Add", ["input", "const_out"], ["output"]) graph = helper.make_graph([const_node, add_node], "test_graph", [input_], [output]) - model = helper.make_model(graph) + # Model is opset-agnostic (Constant + Add); pin a released opset so ONNX 1.22 + # does not default to the under-development opset 27, which fails strict + # ALLOW_RELEASED_ONNX_OPSET_ONLY legs (ValidateOpsetForDomain throws). + model = helper.make_model(graph, opset_imports=[helper.make_opsetid("", 22)]) model_blob_path = os.path.join(model_dir, "guid1") save(model, model_blob_path) From dfab2e91da8f3d7abb37824c823d9a8b5e115dd2 Mon Sep 17 00:00:00 2001 From: Ti-Tai Wang Date: Fri, 5 Jun 2026 18:04:25 +0000 Subject: [PATCH 18/18] THROWAWAY: graft onnx#8056 Xcode CMake fix onto rc1 to validate via ORT iOS CI Adds onnx/onnx#8056's CMake restructure (remove onnx_core OBJECT lib; make onnx the core static lib consuming TARGET_OBJECTS:onnx_proto) on top of our pinned bc3be77b (rc1) tree, reconciled with ORT's ONNX_MINIMAL_BUILD hunk and the GroupNormalization .Deprecate removal. onnx.patch == binskim.patch (sha256 dc5a3294). NOT FOR MERGE - validation of #8056 against ORT iOS/Xcode CI only. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- cmake/patches/onnx/onnx.patch | 440 ++++++++++++++++++++++++++- cmake/vcpkg-ports/onnx/binskim.patch | 440 ++++++++++++++++++++++++++- 2 files changed, 860 insertions(+), 20 deletions(-) diff --git a/cmake/patches/onnx/onnx.patch b/cmake/patches/onnx/onnx.patch index 8de740c79e21c..0e592cacb1468 100644 --- a/cmake/patches/onnx/onnx.patch +++ b/cmake/patches/onnx/onnx.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 365af87..defe81a 100644 +index 365af8726..5f861a1c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ option(ONNX_DISABLE_EXCEPTIONS "Disable exception handling." OFF) @@ -10,17 +10,70 @@ index 365af87..defe81a 100644 option(ONNX_INSTALL "Install ONNX targets, headers, and CMake config files" ON) if(WIN32) option(ONNX_USE_MSVC_STATIC_RUNTIME "Build with MSVC static runtime. Ignored if CMAKE_MSVC_RUNTIME_LIBRARY is defined." OFF) -@@ -494,7 +495,22 @@ endfunction() - # target_sources. onnx_core is an OBJECT library consumed by both the onnx - # static library and the onnx_cpp2py_export Python extension module. - add_library(onnx_core OBJECT) +@@ -490,29 +491,13 @@ function(RELATIVE_PROTOBUF_GENERATE_CPP SRCS) + set(ONNX_GENERATED_PROTO_FILES ${GENERATED_FILES} PARENT_SCOPE) + endfunction() + +-# Sources are listed explicitly in subdirectory CMakeLists.txt files via +-# target_sources. onnx_core is an OBJECT library consumed by both the onnx +-# static library and the onnx_cpp2py_export Python extension module. +-add_library(onnx_core OBJECT) -add_subdirectory(onnx) +- + relative_protobuf_generate_cpp(ONNX_PROTO_SRCS + onnx/onnx.in.proto + onnx/onnx-operators.in.proto + onnx/onnx-data.in.proto) +-target_sources(onnx_core PRIVATE ${ONNX_PROTO_SRCS}) +- +-# Proto sources don't play well with unity builds. +-set_source_files_properties(${ONNX_PROTO_SRCS} +- TARGET_DIRECTORY onnx_core +- PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE +-) +- +-# Dedicated target for the gen_proto.py step only (produces .proto files). +-# Both onnx_core and onnx_proto run gen_proto.py in a parallel build, creating +-# a race where both write to the same generated .proto paths simultaneously. +-# Serialising only the generation step lets protoc and C++ compilation for both +-# targets proceed in parallel afterwards. ++ ++# Serialises the gen_proto.py step so parallel builds don't race writing the ++# generated .proto files; protoc and C++ compilation still overlap afterwards. + add_custom_target(onnx_proto_gen DEPENDS ${ONNX_GENERATED_PROTO_FILES}) + + set(LINKED_PROTOBUF_TARGET protobuf::libprotobuf) +@@ -521,24 +506,45 @@ if(ONNX_USE_LITE_PROTO) + set(LINKED_PROTOBUF_TARGET protobuf::libprotobuf-lite) + endif() + endif() ++ ++# Compile the generated .pb.cc sources in exactly one target: Xcode's build ++# system rejects a protoc custom command shared across several targets. + add_library(onnx_proto ${ONNX_PROTO_SRCS}) + add_onnx_global_defines(onnx_proto) + add_dependencies(onnx_proto onnx_proto_gen) + +-# onnx_core lists ONNX_PROTO_SRCS as sources alongside onnx_proto; without an +-# explicit ordering cmake schedules gen_proto.py for both concurrently, causing +-# a write/read race on the generated .proto files. Depending on onnx_proto_gen +-# (the dedicated gen_proto.py step) serialises only the generation, letting +-# protoc and C++ compilation for both targets overlap afterwards. +-add_dependencies(onnx_core onnx_proto_gen) +- +-add_library(onnx $) +-add_dependencies(onnx onnx_proto onnx_core) +-set_target_properties(onnx_core PROPERTIES CXX_VISIBILITY_PRESET hidden) +-add_onnx_global_defines(onnx_core) ++# Core library. Hand-written sources come from target_sources(onnx ...) in the ++# subdirectories; the protobuf objects are pulled in from onnx_proto. ++add_library(onnx $) +if(ONNX_MINIMAL_BUILD) + message(STATUS "Configuring ONNX minimal build") + # ORT's minimal/WebAssembly builds only need ONNX's type utilities and the -+ # generated protobuf sources (added unconditionally below); skip globbing in ++ # generated protobuf sources (linked via onnx_proto above); skip pulling in + # the full operator/schema sources via add_subdirectory(onnx). -+ target_sources(onnx_core PRIVATE ++ target_sources(onnx PRIVATE + "${ONNX_ROOT}/onnx/defs/data_type_utils.cc" + ) + # Ensure ONNX_ML is treated as ON for minimal build consistency with ORT's file @@ -31,11 +84,186 @@ index 365af87..defe81a 100644 +else() + add_subdirectory(onnx) +endif() ++add_dependencies(onnx onnx_proto) ++set_target_properties(onnx PROPERTIES CXX_VISIBILITY_PRESET hidden) + add_onnx_global_defines(onnx) - relative_protobuf_generate_cpp(ONNX_PROTO_SRCS - onnx/onnx.in.proto + if(ONNX_BUILD_PYTHON) ++ if(BUILD_SHARED_LIBS) ++ # The extension links ONNX internals not on the public ONNX_API surface, ++ # which a hidden-visibility shared libonnx does not export. The wheel always ++ # builds onnx statically; a shared libonnx is for C++ use only. ++ message(FATAL_ERROR ++ "ONNX_BUILD_PYTHON=ON requires a static onnx; do not combine it with " ++ "BUILD_SHARED_LIBS=ON. Use ONNX_BUILD_PYTHON=OFF to build a shared libonnx.") ++ endif() + # find system nanobind + if(NOT DEFINED nanobind_DIR OR "${nanobind_DIR}" STREQUAL "") + execute_process( +@@ -574,12 +580,15 @@ if(ONNX_BUILD_PYTHON) + nanobind_add_module( + onnx_cpp2py_export + NB_STATIC NB_DOMAIN onnx STABLE_ABI FREE_THREADED LTO +- "${ONNX_ROOT}/onnx/cpp2py_export.cc" $) +- add_dependencies(onnx_cpp2py_export onnx) ++ "${ONNX_ROOT}/onnx/cpp2py_export.cc") ++ # Force-load the whole (static) archive so the operator schemas' static ++ # initializers are not dropped as apparently-unused. $ ++ # is the portable --whole-archive / -force_load / /WHOLEARCHIVE spelling. ++ target_link_libraries(onnx_cpp2py_export PRIVATE ++ $) + endif() + + add_onnx_compile_options(onnx_proto) +-add_onnx_compile_options(onnx_core) + add_onnx_compile_options(onnx) + if(TARGET onnx_cpp2py_export) + add_onnx_global_defines(onnx_cpp2py_export) +@@ -627,15 +636,15 @@ if(ONNX_INSTALL) + endif() + + if(ONNX_USE_UNITY_BUILD) +- # If ONNX_USE_UNITY_BUILD is set to ON, set onnx_core to use Unity builds. +- set_target_properties(onnx_core ++ # If ONNX_USE_UNITY_BUILD is set to ON, set onnx to use Unity builds. ++ set_target_properties(onnx + PROPERTIES + UNITY_BUILD ON + ) + + # With unity build object file could get big, need this switch in MSVC. + if(MSVC) +- target_compile_options(onnx_core PRIVATE /bigobj) ++ target_compile_options(onnx PRIVATE /bigobj) + endif() + # should be enabled for onnx_proto when protobuf can support Unity builds + endif() +diff --git a/onnx/CMakeLists.txt b/onnx/CMakeLists.txt +index bd97077f4..1c7a7c6e7 100644 +--- a/onnx/CMakeLists.txt ++++ b/onnx/CMakeLists.txt +@@ -4,7 +4,7 @@ + # Sources directly in onnx/ + # Note: cpp2py_export.cc is excluded — it is compiled separately into the + # onnx_cpp2py_export Python extension module. +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + checker.cc + checker.h + onnx_pb.h +diff --git a/onnx/common/CMakeLists.txt b/onnx/common/CMakeLists.txt +index 1156aa8cf..d14e08e79 100644 +--- a/onnx/common/CMakeLists.txt ++++ b/onnx/common/CMakeLists.txt +@@ -7,7 +7,7 @@ configure_file( + @ONLY + ) + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + array_ref.h + assertions.cc + assertions.h +diff --git a/onnx/defs/CMakeLists.txt b/onnx/defs/CMakeLists.txt +index 6c5e76613..835b81537 100644 +--- a/onnx/defs/CMakeLists.txt ++++ b/onnx/defs/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + attr_proto_util.cc + attr_proto_util.h + data_propagators.h +@@ -49,6 +49,6 @@ add_subdirectory(training) + + # These files exhibit issues in unity builds, so we disable them. + set_source_files_properties(schema.cc tensor_proto_util.cc +- TARGET_DIRECTORY onnx_core ++ TARGET_DIRECTORY onnx + PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE + ) +diff --git a/onnx/defs/controlflow/CMakeLists.txt b/onnx/defs/controlflow/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/controlflow/CMakeLists.txt ++++ b/onnx/defs/controlflow/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/generator/CMakeLists.txt b/onnx/defs/generator/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/generator/CMakeLists.txt ++++ b/onnx/defs/generator/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/image/CMakeLists.txt b/onnx/defs/image/CMakeLists.txt +index b3a8a996f..ebc1561f5 100644 +--- a/onnx/defs/image/CMakeLists.txt ++++ b/onnx/defs/image/CMakeLists.txt +@@ -1,6 +1,6 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + ) +diff --git a/onnx/defs/logical/CMakeLists.txt b/onnx/defs/logical/CMakeLists.txt +index 8db7d6875..0804eec6d 100644 +--- a/onnx/defs/logical/CMakeLists.txt ++++ b/onnx/defs/logical/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + ) +diff --git a/onnx/defs/math/CMakeLists.txt b/onnx/defs/math/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/math/CMakeLists.txt ++++ b/onnx/defs/math/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/nn/CMakeLists.txt b/onnx/defs/nn/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/nn/CMakeLists.txt ++++ b/onnx/defs/nn/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc diff --git a/onnx/defs/nn/old.cc b/onnx/defs/nn/old.cc -index 4dd6619..6187eb3 100644 +index 4dd66197c..6187eb39e 100644 --- a/onnx/defs/nn/old.cc +++ b/onnx/defs/nn/old.cc @@ -3995,7 +3995,6 @@ ONNX_OPERATOR_SET_SCHEMA( @@ -46,3 +274,195 @@ index 4dd6619..6187eb3 100644 .SetDoc(GroupNormalization_ver18_doc) .Attr("epsilon", "The epsilon value to use to avoid division by zero.", AttributeProto::FLOAT, 1e-5f) .Attr( +diff --git a/onnx/defs/object_detection/CMakeLists.txt b/onnx/defs/object_detection/CMakeLists.txt +index 8db7d6875..0804eec6d 100644 +--- a/onnx/defs/object_detection/CMakeLists.txt ++++ b/onnx/defs/object_detection/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + ) +diff --git a/onnx/defs/optional/CMakeLists.txt b/onnx/defs/optional/CMakeLists.txt +index 8db7d6875..0804eec6d 100644 +--- a/onnx/defs/optional/CMakeLists.txt ++++ b/onnx/defs/optional/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + ) +diff --git a/onnx/defs/preview/CMakeLists.txt b/onnx/defs/preview/CMakeLists.txt +index b3a8a996f..ebc1561f5 100644 +--- a/onnx/defs/preview/CMakeLists.txt ++++ b/onnx/defs/preview/CMakeLists.txt +@@ -1,6 +1,6 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + ) +diff --git a/onnx/defs/quantization/CMakeLists.txt b/onnx/defs/quantization/CMakeLists.txt +index 8db7d6875..0804eec6d 100644 +--- a/onnx/defs/quantization/CMakeLists.txt ++++ b/onnx/defs/quantization/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + ) +diff --git a/onnx/defs/reduction/CMakeLists.txt b/onnx/defs/reduction/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/reduction/CMakeLists.txt ++++ b/onnx/defs/reduction/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/rnn/CMakeLists.txt b/onnx/defs/rnn/CMakeLists.txt +index 8db7d6875..0804eec6d 100644 +--- a/onnx/defs/rnn/CMakeLists.txt ++++ b/onnx/defs/rnn/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + ) +diff --git a/onnx/defs/sequence/CMakeLists.txt b/onnx/defs/sequence/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/sequence/CMakeLists.txt ++++ b/onnx/defs/sequence/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/tensor/CMakeLists.txt b/onnx/defs/tensor/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/tensor/CMakeLists.txt ++++ b/onnx/defs/tensor/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/text/CMakeLists.txt b/onnx/defs/text/CMakeLists.txt +index b3a8a996f..ebc1561f5 100644 +--- a/onnx/defs/text/CMakeLists.txt ++++ b/onnx/defs/text/CMakeLists.txt +@@ -1,6 +1,6 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + ) +diff --git a/onnx/defs/traditionalml/CMakeLists.txt b/onnx/defs/traditionalml/CMakeLists.txt +index 28a162e24..e27fa8dcd 100644 +--- a/onnx/defs/traditionalml/CMakeLists.txt ++++ b/onnx/defs/traditionalml/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.h +diff --git a/onnx/defs/training/CMakeLists.txt b/onnx/defs/training/CMakeLists.txt +index b3a8a996f..ebc1561f5 100644 +--- a/onnx/defs/training/CMakeLists.txt ++++ b/onnx/defs/training/CMakeLists.txt +@@ -1,6 +1,6 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + ) +diff --git a/onnx/inliner/CMakeLists.txt b/onnx/inliner/CMakeLists.txt +index fbb2d7b1a..dd1f4f0fa 100644 +--- a/onnx/inliner/CMakeLists.txt ++++ b/onnx/inliner/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + inliner.cc + inliner.h + ) +diff --git a/onnx/shape_inference/CMakeLists.txt b/onnx/shape_inference/CMakeLists.txt +index 493b24706..8938c98a4 100644 +--- a/onnx/shape_inference/CMakeLists.txt ++++ b/onnx/shape_inference/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + attribute_binder.h + implementation.cc + implementation.h +diff --git a/onnx/version_converter/CMakeLists.txt b/onnx/version_converter/CMakeLists.txt +index e6a5571b9..af8f9cb24 100644 +--- a/onnx/version_converter/CMakeLists.txt ++++ b/onnx/version_converter/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + BaseConverter.h + convert.cc + convert.h +diff --git a/onnx/version_converter/adapters/CMakeLists.txt b/onnx/version_converter/adapters/CMakeLists.txt +index ef41ddd49..d4afa967b 100644 +--- a/onnx/version_converter/adapters/CMakeLists.txt ++++ b/onnx/version_converter/adapters/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + adapter.h + Attention_24_23.h + axes_attribute_to_input.h diff --git a/cmake/vcpkg-ports/onnx/binskim.patch b/cmake/vcpkg-ports/onnx/binskim.patch index 8de740c79e21c..0e592cacb1468 100644 --- a/cmake/vcpkg-ports/onnx/binskim.patch +++ b/cmake/vcpkg-ports/onnx/binskim.patch @@ -1,5 +1,5 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index 365af87..defe81a 100644 +index 365af8726..5f861a1c7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -46,6 +46,7 @@ option(ONNX_DISABLE_EXCEPTIONS "Disable exception handling." OFF) @@ -10,17 +10,70 @@ index 365af87..defe81a 100644 option(ONNX_INSTALL "Install ONNX targets, headers, and CMake config files" ON) if(WIN32) option(ONNX_USE_MSVC_STATIC_RUNTIME "Build with MSVC static runtime. Ignored if CMAKE_MSVC_RUNTIME_LIBRARY is defined." OFF) -@@ -494,7 +495,22 @@ endfunction() - # target_sources. onnx_core is an OBJECT library consumed by both the onnx - # static library and the onnx_cpp2py_export Python extension module. - add_library(onnx_core OBJECT) +@@ -490,29 +491,13 @@ function(RELATIVE_PROTOBUF_GENERATE_CPP SRCS) + set(ONNX_GENERATED_PROTO_FILES ${GENERATED_FILES} PARENT_SCOPE) + endfunction() + +-# Sources are listed explicitly in subdirectory CMakeLists.txt files via +-# target_sources. onnx_core is an OBJECT library consumed by both the onnx +-# static library and the onnx_cpp2py_export Python extension module. +-add_library(onnx_core OBJECT) -add_subdirectory(onnx) +- + relative_protobuf_generate_cpp(ONNX_PROTO_SRCS + onnx/onnx.in.proto + onnx/onnx-operators.in.proto + onnx/onnx-data.in.proto) +-target_sources(onnx_core PRIVATE ${ONNX_PROTO_SRCS}) +- +-# Proto sources don't play well with unity builds. +-set_source_files_properties(${ONNX_PROTO_SRCS} +- TARGET_DIRECTORY onnx_core +- PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE +-) +- +-# Dedicated target for the gen_proto.py step only (produces .proto files). +-# Both onnx_core and onnx_proto run gen_proto.py in a parallel build, creating +-# a race where both write to the same generated .proto paths simultaneously. +-# Serialising only the generation step lets protoc and C++ compilation for both +-# targets proceed in parallel afterwards. ++ ++# Serialises the gen_proto.py step so parallel builds don't race writing the ++# generated .proto files; protoc and C++ compilation still overlap afterwards. + add_custom_target(onnx_proto_gen DEPENDS ${ONNX_GENERATED_PROTO_FILES}) + + set(LINKED_PROTOBUF_TARGET protobuf::libprotobuf) +@@ -521,24 +506,45 @@ if(ONNX_USE_LITE_PROTO) + set(LINKED_PROTOBUF_TARGET protobuf::libprotobuf-lite) + endif() + endif() ++ ++# Compile the generated .pb.cc sources in exactly one target: Xcode's build ++# system rejects a protoc custom command shared across several targets. + add_library(onnx_proto ${ONNX_PROTO_SRCS}) + add_onnx_global_defines(onnx_proto) + add_dependencies(onnx_proto onnx_proto_gen) + +-# onnx_core lists ONNX_PROTO_SRCS as sources alongside onnx_proto; without an +-# explicit ordering cmake schedules gen_proto.py for both concurrently, causing +-# a write/read race on the generated .proto files. Depending on onnx_proto_gen +-# (the dedicated gen_proto.py step) serialises only the generation, letting +-# protoc and C++ compilation for both targets overlap afterwards. +-add_dependencies(onnx_core onnx_proto_gen) +- +-add_library(onnx $) +-add_dependencies(onnx onnx_proto onnx_core) +-set_target_properties(onnx_core PROPERTIES CXX_VISIBILITY_PRESET hidden) +-add_onnx_global_defines(onnx_core) ++# Core library. Hand-written sources come from target_sources(onnx ...) in the ++# subdirectories; the protobuf objects are pulled in from onnx_proto. ++add_library(onnx $) +if(ONNX_MINIMAL_BUILD) + message(STATUS "Configuring ONNX minimal build") + # ORT's minimal/WebAssembly builds only need ONNX's type utilities and the -+ # generated protobuf sources (added unconditionally below); skip globbing in ++ # generated protobuf sources (linked via onnx_proto above); skip pulling in + # the full operator/schema sources via add_subdirectory(onnx). -+ target_sources(onnx_core PRIVATE ++ target_sources(onnx PRIVATE + "${ONNX_ROOT}/onnx/defs/data_type_utils.cc" + ) + # Ensure ONNX_ML is treated as ON for minimal build consistency with ORT's file @@ -31,11 +84,186 @@ index 365af87..defe81a 100644 +else() + add_subdirectory(onnx) +endif() ++add_dependencies(onnx onnx_proto) ++set_target_properties(onnx PROPERTIES CXX_VISIBILITY_PRESET hidden) + add_onnx_global_defines(onnx) - relative_protobuf_generate_cpp(ONNX_PROTO_SRCS - onnx/onnx.in.proto + if(ONNX_BUILD_PYTHON) ++ if(BUILD_SHARED_LIBS) ++ # The extension links ONNX internals not on the public ONNX_API surface, ++ # which a hidden-visibility shared libonnx does not export. The wheel always ++ # builds onnx statically; a shared libonnx is for C++ use only. ++ message(FATAL_ERROR ++ "ONNX_BUILD_PYTHON=ON requires a static onnx; do not combine it with " ++ "BUILD_SHARED_LIBS=ON. Use ONNX_BUILD_PYTHON=OFF to build a shared libonnx.") ++ endif() + # find system nanobind + if(NOT DEFINED nanobind_DIR OR "${nanobind_DIR}" STREQUAL "") + execute_process( +@@ -574,12 +580,15 @@ if(ONNX_BUILD_PYTHON) + nanobind_add_module( + onnx_cpp2py_export + NB_STATIC NB_DOMAIN onnx STABLE_ABI FREE_THREADED LTO +- "${ONNX_ROOT}/onnx/cpp2py_export.cc" $) +- add_dependencies(onnx_cpp2py_export onnx) ++ "${ONNX_ROOT}/onnx/cpp2py_export.cc") ++ # Force-load the whole (static) archive so the operator schemas' static ++ # initializers are not dropped as apparently-unused. $ ++ # is the portable --whole-archive / -force_load / /WHOLEARCHIVE spelling. ++ target_link_libraries(onnx_cpp2py_export PRIVATE ++ $) + endif() + + add_onnx_compile_options(onnx_proto) +-add_onnx_compile_options(onnx_core) + add_onnx_compile_options(onnx) + if(TARGET onnx_cpp2py_export) + add_onnx_global_defines(onnx_cpp2py_export) +@@ -627,15 +636,15 @@ if(ONNX_INSTALL) + endif() + + if(ONNX_USE_UNITY_BUILD) +- # If ONNX_USE_UNITY_BUILD is set to ON, set onnx_core to use Unity builds. +- set_target_properties(onnx_core ++ # If ONNX_USE_UNITY_BUILD is set to ON, set onnx to use Unity builds. ++ set_target_properties(onnx + PROPERTIES + UNITY_BUILD ON + ) + + # With unity build object file could get big, need this switch in MSVC. + if(MSVC) +- target_compile_options(onnx_core PRIVATE /bigobj) ++ target_compile_options(onnx PRIVATE /bigobj) + endif() + # should be enabled for onnx_proto when protobuf can support Unity builds + endif() +diff --git a/onnx/CMakeLists.txt b/onnx/CMakeLists.txt +index bd97077f4..1c7a7c6e7 100644 +--- a/onnx/CMakeLists.txt ++++ b/onnx/CMakeLists.txt +@@ -4,7 +4,7 @@ + # Sources directly in onnx/ + # Note: cpp2py_export.cc is excluded — it is compiled separately into the + # onnx_cpp2py_export Python extension module. +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + checker.cc + checker.h + onnx_pb.h +diff --git a/onnx/common/CMakeLists.txt b/onnx/common/CMakeLists.txt +index 1156aa8cf..d14e08e79 100644 +--- a/onnx/common/CMakeLists.txt ++++ b/onnx/common/CMakeLists.txt +@@ -7,7 +7,7 @@ configure_file( + @ONLY + ) + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + array_ref.h + assertions.cc + assertions.h +diff --git a/onnx/defs/CMakeLists.txt b/onnx/defs/CMakeLists.txt +index 6c5e76613..835b81537 100644 +--- a/onnx/defs/CMakeLists.txt ++++ b/onnx/defs/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + attr_proto_util.cc + attr_proto_util.h + data_propagators.h +@@ -49,6 +49,6 @@ add_subdirectory(training) + + # These files exhibit issues in unity builds, so we disable them. + set_source_files_properties(schema.cc tensor_proto_util.cc +- TARGET_DIRECTORY onnx_core ++ TARGET_DIRECTORY onnx + PROPERTIES SKIP_UNITY_BUILD_INCLUSION TRUE + ) +diff --git a/onnx/defs/controlflow/CMakeLists.txt b/onnx/defs/controlflow/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/controlflow/CMakeLists.txt ++++ b/onnx/defs/controlflow/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/generator/CMakeLists.txt b/onnx/defs/generator/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/generator/CMakeLists.txt ++++ b/onnx/defs/generator/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/image/CMakeLists.txt b/onnx/defs/image/CMakeLists.txt +index b3a8a996f..ebc1561f5 100644 +--- a/onnx/defs/image/CMakeLists.txt ++++ b/onnx/defs/image/CMakeLists.txt +@@ -1,6 +1,6 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + ) +diff --git a/onnx/defs/logical/CMakeLists.txt b/onnx/defs/logical/CMakeLists.txt +index 8db7d6875..0804eec6d 100644 +--- a/onnx/defs/logical/CMakeLists.txt ++++ b/onnx/defs/logical/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + ) +diff --git a/onnx/defs/math/CMakeLists.txt b/onnx/defs/math/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/math/CMakeLists.txt ++++ b/onnx/defs/math/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/nn/CMakeLists.txt b/onnx/defs/nn/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/nn/CMakeLists.txt ++++ b/onnx/defs/nn/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc diff --git a/onnx/defs/nn/old.cc b/onnx/defs/nn/old.cc -index 4dd6619..6187eb3 100644 +index 4dd66197c..6187eb39e 100644 --- a/onnx/defs/nn/old.cc +++ b/onnx/defs/nn/old.cc @@ -3995,7 +3995,6 @@ ONNX_OPERATOR_SET_SCHEMA( @@ -46,3 +274,195 @@ index 4dd6619..6187eb3 100644 .SetDoc(GroupNormalization_ver18_doc) .Attr("epsilon", "The epsilon value to use to avoid division by zero.", AttributeProto::FLOAT, 1e-5f) .Attr( +diff --git a/onnx/defs/object_detection/CMakeLists.txt b/onnx/defs/object_detection/CMakeLists.txt +index 8db7d6875..0804eec6d 100644 +--- a/onnx/defs/object_detection/CMakeLists.txt ++++ b/onnx/defs/object_detection/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + ) +diff --git a/onnx/defs/optional/CMakeLists.txt b/onnx/defs/optional/CMakeLists.txt +index 8db7d6875..0804eec6d 100644 +--- a/onnx/defs/optional/CMakeLists.txt ++++ b/onnx/defs/optional/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + ) +diff --git a/onnx/defs/preview/CMakeLists.txt b/onnx/defs/preview/CMakeLists.txt +index b3a8a996f..ebc1561f5 100644 +--- a/onnx/defs/preview/CMakeLists.txt ++++ b/onnx/defs/preview/CMakeLists.txt +@@ -1,6 +1,6 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + ) +diff --git a/onnx/defs/quantization/CMakeLists.txt b/onnx/defs/quantization/CMakeLists.txt +index 8db7d6875..0804eec6d 100644 +--- a/onnx/defs/quantization/CMakeLists.txt ++++ b/onnx/defs/quantization/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + ) +diff --git a/onnx/defs/reduction/CMakeLists.txt b/onnx/defs/reduction/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/reduction/CMakeLists.txt ++++ b/onnx/defs/reduction/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/rnn/CMakeLists.txt b/onnx/defs/rnn/CMakeLists.txt +index 8db7d6875..0804eec6d 100644 +--- a/onnx/defs/rnn/CMakeLists.txt ++++ b/onnx/defs/rnn/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + ) +diff --git a/onnx/defs/sequence/CMakeLists.txt b/onnx/defs/sequence/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/sequence/CMakeLists.txt ++++ b/onnx/defs/sequence/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/tensor/CMakeLists.txt b/onnx/defs/tensor/CMakeLists.txt +index a89ba3be7..0011f0548 100644 +--- a/onnx/defs/tensor/CMakeLists.txt ++++ b/onnx/defs/tensor/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.cc +diff --git a/onnx/defs/text/CMakeLists.txt b/onnx/defs/text/CMakeLists.txt +index b3a8a996f..ebc1561f5 100644 +--- a/onnx/defs/text/CMakeLists.txt ++++ b/onnx/defs/text/CMakeLists.txt +@@ -1,6 +1,6 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + ) +diff --git a/onnx/defs/traditionalml/CMakeLists.txt b/onnx/defs/traditionalml/CMakeLists.txt +index 28a162e24..e27fa8dcd 100644 +--- a/onnx/defs/traditionalml/CMakeLists.txt ++++ b/onnx/defs/traditionalml/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + old.cc + utils.h +diff --git a/onnx/defs/training/CMakeLists.txt b/onnx/defs/training/CMakeLists.txt +index b3a8a996f..ebc1561f5 100644 +--- a/onnx/defs/training/CMakeLists.txt ++++ b/onnx/defs/training/CMakeLists.txt +@@ -1,6 +1,6 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + defs.cc + ) +diff --git a/onnx/inliner/CMakeLists.txt b/onnx/inliner/CMakeLists.txt +index fbb2d7b1a..dd1f4f0fa 100644 +--- a/onnx/inliner/CMakeLists.txt ++++ b/onnx/inliner/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + inliner.cc + inliner.h + ) +diff --git a/onnx/shape_inference/CMakeLists.txt b/onnx/shape_inference/CMakeLists.txt +index 493b24706..8938c98a4 100644 +--- a/onnx/shape_inference/CMakeLists.txt ++++ b/onnx/shape_inference/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + attribute_binder.h + implementation.cc + implementation.h +diff --git a/onnx/version_converter/CMakeLists.txt b/onnx/version_converter/CMakeLists.txt +index e6a5571b9..af8f9cb24 100644 +--- a/onnx/version_converter/CMakeLists.txt ++++ b/onnx/version_converter/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + BaseConverter.h + convert.cc + convert.h +diff --git a/onnx/version_converter/adapters/CMakeLists.txt b/onnx/version_converter/adapters/CMakeLists.txt +index ef41ddd49..d4afa967b 100644 +--- a/onnx/version_converter/adapters/CMakeLists.txt ++++ b/onnx/version_converter/adapters/CMakeLists.txt +@@ -1,7 +1,7 @@ + # Copyright (c) ONNX Project Contributors + # SPDX-License-Identifier: Apache-2.0 + +-target_sources(onnx_core PRIVATE ++target_sources(onnx PRIVATE + adapter.h + Attention_24_23.h + axes_attribute_to_input.h