diff --git a/.agents/skills/cuda-attention-kernel-patterns/SKILL.md b/.agents/skills/cuda-attention-kernel-patterns/SKILL.md new file mode 100644 index 0000000000000..5c074a50fc294 --- /dev/null +++ b/.agents/skills/cuda-attention-kernel-patterns/SKILL.md @@ -0,0 +1,267 @@ +--- +name: cuda-attention-kernel-patterns +description: Patterns and pitfalls for the ONNX domain Attention operator (opset 23/24) CUDA implementation. Use when modifying the dispatch cascade in core/providers/cuda/llm/attention.cc, writing mask/bias CUDA kernels, debugging attention test routing, or adding features to the ONNX Attention op. NOT for contrib domain MultiHeadAttention/GroupQueryAttention. +--- + +# ONNX Domain Attention (Opset 23/24) CUDA Patterns + +Reusable knowledge from ONNX Attention CUDA development in ORT. + +> **Scope**: This skill covers the **ONNX domain** `Attention` operator (opset 23/24) +> implemented at `core/providers/cuda/llm/attention.cc`. This is **separate from** the +> contrib domain `MultiHeadAttention` / `GroupQueryAttention` at `contrib_ops/cuda/bert/`. +> They share some underlying kernels (CUTLASS FMHA, Flash Attention) and infrastructure +> (`attention_softmax.h`) but have **different dispatch logic, parameter structs, and eligibility checks**. +> +> - **Shared infrastructure**: CUTLASS FMHA kernel, Flash kernel, unified unfused kernel +> (`unfused_attention.cu`), `attention_softmax.h`, `attention_impl.cu` (contrib only) +> - **ONNX-specific**: Dispatch cascade in `attention.cc`, `ConvertAttnMaskToBias`, +> `mask_filter_value` cap, parameter bridge to contrib structs, `attention_mask_impl.cu` +> - **Contrib-specific**: Own dispatch in contrib MHA/GQA ops, uses `contrib::AttentionParameters` +> directly, has XQA kernel, past-present buffer sharing + +## 1. Runner Dispatch Cascade + +CUDA attention dispatches in priority order: **Flash → MEA (Memory Efficient) → Unified Unfused Attention**. + +``` +// onnxruntime/core/providers/cuda/llm/attention.cc — ComputeInternal() +Flash eligible? → RunFlashAttention() + ↓ no +MEA eligible? → RunMemoryEfficientAttention() + ↓ no +Unified Unfused → RunUnfusedAttention() + (handles both MHA and GQA via reshape-Q trick) +``` + +**Flash eligibility**: fp16/bf16 only, SM≥8.0 (Ampere+), `head_size == v_head_size`, `head_size <= 256`, no `output_qk`, `attn_mask == nullptr`. Uses `mha_fwd` / `mha_fwd_kvcache`. + +**MEA eligibility**: SM50+/53+/80+ by dtype, `head_size <= 1024` and divisible by 8 (enforced by `has_memory_efficient_attention`), no `output_qk`. GQA additionally requires `head_size == v_head_size` (for `LaunchUngroup`); decode also requires it (for `LaunchConcatNewToPastKV`). Bias stride must satisfy `total_sequence_length % 4 == 0`. GQA with FP32 is excluded (LaunchUngroup only has fp16/bf16 instantiations). Supports `softcap + attn_mask` — CUTLASS applies softcap before bias in kernel tiles, matching ONNX spec ordering (onnx/onnx#7867, supersedes the now-closed onnx/onnx#7865 issue). + +**Unified Unfused Attention**: Always available as the final fallback. Handles both MHA (`num_heads == kv_num_heads`, group=1) and GQA (`num_heads != kv_num_heads`, group>1) via a reshape-Q trick with stride-based cuBLAS batched GEMM (no K/V head replication). Uses FP32 QK scratch for precision. Supports all features: +- softcap + attn_mask (spec-correct ordering) +- output_qk (kQK mode: copies raw QK before softcap/mask mutations) +- past_key + past_value with `head_size != v_head_size` (separate K/V concat) +- causal masking, nonpad_kv_seqlen, all dtypes (fp16/bf16/fp32) + +## 2. CUTLASS kLog2e Overflow + +CUTLASS `iterative_softmax` multiplies all attention scores by `kLog2e ≈ 1.4427` internally (for `exp2f` instead of `expf`). For float/bf16: + +``` +mask_filter_value = std::numeric_limits::lowest() ≈ -3.40e+38 +-3.40e+38 × 1.4427 ≈ -4.91e+38 → overflows fp32 → -inf +``` + +When all values become `-inf`, CUTLASS's special-case path produces `s_prime=0` → `1/s_prime=inf` → `0 × inf = NaN`. + +**Fix**: Cap `mask_filter_value` to `-1.0e+30f` in `ConvertAttnMaskToBias`. This value is safe: `1e30 × 1.4427 ≈ 1.4e30 << FLT_MAX`, and `exp(-1e30) ≈ 0` (effectively masked). + +**fp16 is NOT affected**: `lowest() = -65504`, and `-65504 × 1.4427 ≈ -94500` stays within fp32 range. + +This cap is ONLY applied in MEA paths. The unfused path uses `lowest()` directly (its softmax subtracts max first, avoiding overflow). + +**Subtlety**: When bias is present (`kSupportsBias=true`), CUTLASS pre-applies `p.scale` to QK (line 858) and uses `scaling=1.0f` in the softmax loop (line 981). So the full `kLog2e` multiplier hits the bias-dominated values — the overflow is head_size-independent. Without bias, `scaling = p.scale * kLog2e = kLog2e/sqrt(head_size)`, which is much smaller. + +## 3. Bias Alignment + +CUTLASS FMHA requires the attention bias row stride to satisfy minimum alignment. The bias has shape `[B, H, S, T]` where `T = total_sequence_length` is the row stride. + +```cpp +constexpr int min_bias_align = 4; // elements, not bytes +if (parameters.total_sequence_length % min_bias_align != 0) { + mea_eligible = false; // fall through to unfused +} +``` + +**Impact on tests**: If a test uses `total_sequence_length` not divisible by 4 (e.g., past=5 + new=6 = 11), MEA is rejected and unfused handles it. To test MEA with bias, ensure `total_sequence_length % 4 == 0`. + +## 4. Softcap Ordering + +ONNX Attention opset 23/24 spec ordering (per onnx/onnx#7867, which superseded +the now-closed onnx/onnx#7865 issue, and onnx/onnx#7913 which swapped +`qk_matmul_output_mode` values 1 and 2 to align with the corrected pipeline): + +``` +scale * (Q @ K^T) # stage 0: raw scaled QK + | +softcap (if > 0) # stage 1: tanh(qk / softcap) * softcap + | ++ attn_bias / + attn_mask # stage 2: additive (mask -inf survives to stage 3) + | +softmax # stage 3 + | +@ V +``` + +`qk_matmul_output_mode` integer values follow pipeline stage order: +0 = raw scale*QK, 1 = post-softcap (pre-mask), 2 = post-mask/bias (pre-softmax), +3 = post-softmax. + +CUDA implementation status (all spec-correct): +- **MEA (CUTLASS)**: `kernel_forward.h` applies softcap inside the score-compute + tile loop BEFORE `attn_bias` is added. +- **Flash**: `mha_fwd` / `mha_fwd_kvcache` handle softcap natively; reject + explicit `attn_mask`, so ordering with float mask is moot for this path. +- **Unfused**: `UnfusedSoftmaxKernel` does `QK -> scale -> softcap -> add bias -> softmax` + (all fused). + +CPU implementation status: `core/providers/cpu/llm/attention.cc::ComputeAttentionProbs` +applies softcap BEFORE the mask add (post-fix; pre-fix it inverted the order +and leaked probability through masked positions). + +Why this ordering matters: a -inf in `attn_mask` must survive to softmax. If +softcap were applied AFTER the mask-add, then `tanh(-inf/softcap) * softcap = -softcap` +(a finite value), and softmax would assign non-zero weight to the masked +position — leaking poison V values into the output. The CUDA-side guard tests +at `test_onnx_attention/test_gqa.py:1501` and `:1761`, and the CPU-side guards +at `TestONNXAttentionCPUSoftcapMaskOrdering` in the same file, exercise this +property by combining small softcap, a -inf mask entry, and a poison V value. + +## 5. Grid-Stride Loops for CUDA Kernels + +Always cap grid size to prevent exceeding `gridDim.x` limits, and use grid-stride loops for large workloads: + +```cpp +constexpr int64_t kMaxGridDimX = 65535; +int threads = static_cast(std::min(static_cast(max_threads_per_block), total)); +int64_t blocks = (total + threads - 1) / threads; +unsigned int grid_size = static_cast(std::min(blocks, kMaxGridDimX)); + +MyKernel<<>>(...); + +// Inside the kernel: +for (int64_t idx = blockIdx.x * blockDim.x + threadIdx.x; + idx < total; + idx += static_cast(gridDim.x) * blockDim.x) { + // work +} +``` + +**Never** cast `int64_t` block count directly to `unsigned int` without capping — it silently truncates. + +Always call `CUDA_CALL(cudaGetLastError())` after kernel launches in standalone helper functions. This is the established pattern in the file (see `ConcatPastToPresent`, `PastPresentBufferShare`). + +## 6. Fully-Masked Batches + +All-false bool masks or `seqlens_k=0` produce NaN in CUTLASS MEA. + +**Additive-bias path** (bool mask converted to bias): Fixed by capping `mask_filter_value` to `-1e+30f` (see section 2). CUTLASS then naturally computes uniform softmax → mean(V). + +**Nonpad path** (`seqlens_k=0`): CUTLASS skips all K/V positions → `s_prime=0` → NaN. Fixed by `ZeroOutputForFullyMaskedBatches` kernel which zeros output for batches where `seqlens_k[b] == 0`. Note: this produces zeros, not mean(V) — a cross-EP consistency TODO exists. + +**CPU/Unfused behavior**: `mask_filter_value = lowest()` (not `-inf`). All masked values are equal → `softmax(equal) = 1/N` → output = mean(V). This is the spec reference. + +## 7. Test Runner Targeting + +Use `ScopedEnvironmentVariables` to force specific CUDA runners: + +```cpp +// Force MEA (disable Flash) +ScopedEnvironmentVariables scoped_env({ + {"ORT_DISABLE_FLASH_ATTENTION", "1"}, +}); + +// Force Unfused (disable both Flash and MEA) +ScopedEnvironmentVariables scoped_env({ + {"ORT_DISABLE_FLASH_ATTENTION", "1"}, + {"ORT_DISABLE_MEMORY_EFFICIENT_ATTENTION", "1"}, +}); +``` + +**Always verify which runner a test actually hits.** A test designed for MEA may silently fall to unfused if: +- `total_sequence_length % 4 != 0` (bias alignment) +- `head_size != v_head_size` (decode path) +- fp32 dtype with GQA (LaunchUngroup fp16/bf16 only) +- fp32 dtype on SM < 80 + +Enable verbose logging to confirm: `LOGS_DEFAULT(VERBOSE) << "ONNX Attention: using ..."`. + +## 8. Cross-EP Consistency + +CPU is the spec reference implementation. CUDA outputs should match CPU for all valid inputs. + +- CPU uses `mask_filter_value = std::numeric_limits::lowest()` (finite, not `-inf`) +- CPU softmax: subtract-max-first → works correctly with extreme finite values +- CPU handles fully-masked batches naturally (uniform softmax → mean(V)) + +Run tests with `disable_cpu=false` to always validate against CPU. The C++ test framework (`RunTest4D`) supports `disable_cpu`, `disable_cuda`, `disable_dml` flags. + +## 9. File Locations + +### ONNX Domain (this op's code) + +| File | Purpose | +|------|---------| +| `core/providers/cuda/llm/attention.cc` | ONNX Attention CUDA dispatch: Flash/MEA/Unfused cascade, `ConvertAttnMaskToBias`, parameter setup | +| `core/providers/cuda/llm/attention_mask_impl.cu` | ONNX-specific mask/bias CUDA kernels: bool→bias, nonpad→seqlens_k, ZeroOutput, bias composition | +| `core/providers/cuda/llm/attention_mask_impl.h` | Declarations for ONNX mask/bias kernels | +| `core/providers/cpu/llm/attention.cc` | CPU reference implementation (ONNX domain) | +| `core/providers/cpu/llm/attention_helper.h` | ONNX parameter validation and shape computation | +| `test/providers/cpu/llm/attention_op_test.cc` | C++ attention tests (all EPs) | +| `test/python/transformers/test_onnx_attention/test_mha.py` | Python parity tests | +| `test/python/transformers/test_onnx_attention/common.py` | Python test utilities and reference `attention_ref()` | + +### Shared Infrastructure (used by both ONNX and contrib ops) + +| File | Purpose | +|------|---------| +| `contrib_ops/cuda/bert/unfused_attention.cu` | Unified unfused attention: QK GEMM (FP32), fused softmax kernel (scale+softcap+bias+causal), V GEMM. Handles MHA and GQA. | +| `contrib_ops/cuda/bert/unfused_attention.h` | `UnfusedAttentionParams`, `LaunchUnfusedAttention`, workspace size | +| `contrib_ops/cuda/bert/attention_impl.cu` | Legacy unfused `QkvToContext` (contrib MHA only). Also `ApplySoftcap`, `ConcatPastToPresent` | +| `contrib_ops/cuda/bert/attention_softmax.h` | CUDA softmax kernels (`ComputeSoftmax`, `ComputeSoftmaxWithRawMask`) — used by legacy contrib path | +| `contrib_ops/cuda/bert/cutlass_fmha/` | CUTLASS FMHA (Memory Efficient Attention) kernels | +| `contrib_ops/cuda/bert/flash_attention/` | Flash Attention kernels | + +### Contrib Domain (separate ops, NOT covered by this skill) + +| File | Purpose | +|------|---------| +| `contrib_ops/cuda/bert/multihead_attention.cu` | Contrib `MultiHeadAttention` — own dispatch, uses `contrib::AttentionParameters` directly | +| `contrib_ops/cuda/bert/group_query_attention.cu` | Contrib `GroupQueryAttention` — has XQA kernel, past-present buffer sharing | + +## 10. Parameter Bridge (ONNX → Contrib) + +The ONNX Attention op uses `attention_helper::AttentionParameters` (in `core/providers/cpu/llm/attention_parameters.h`). The unified unfused kernel (`LaunchUnfusedAttention`) uses its own `UnfusedAttentionParams` struct populated directly from ONNX parameters in `RunUnfusedAttention`. + +The contrib `QkvToContext` function (used by contrib MHA, NOT by ONNX Attention) uses `contrib::AttentionParameters`. ONNX Attention does **not** bridge to `contrib::AttentionParameters` — it routes through the unified unfused kernel instead. + +## 11. Causal Alignment + +The ONNX spec defines two causal alignment modes based on where query positions sit in the full attention matrix: + +- **Upper-left**: `q_i` attends to `kv[0..i]`. Query positions start at 0 in the full matrix. +- **Lower-right**: `q_i` attends to `kv[kv_len - q_len + i..kv_len - 1]`. Query positions are at the end. + +**ONNX spec rule**: `is_causal=1` always means upper-left in the full matrix. When `past_key` provides context, `past_sequence_length` shifts the query start position forward — the resulting `[S_q × total_kv]` sub-matrix effectively has lower-right alignment. + +### Per-kernel behavior + +| Kernel | Alignment | Mechanism | +|--------|-----------|-----------| +| **Flash** | Lower-right only | `is_causal` flag → `seqlen_k - seqlen_q` offset in kernel. No top-left option. | +| **MEA (CUTLASS)** | Both | `causal_from_top_left` flag in `MemoryEfficientAttentionParams`. `true` → `CausalFromTopLeft` (offset=0). `false` → `CausalFromBottomRight` (offset = num_keys - num_queries). | +| **Unfused** | Both | `past_kv_length` param. `0` → upper-left. `total_kv - S_q` → lower-right. | + +### Dispatch logic in attention.cc + +```cpp +// Flash cannot do upper-left → guarded by causal_cross_no_past +bool causal_cross_no_past = parameters.is_causal && + parameters.q_sequence_length != parameters.total_sequence_length && + parameters.past_sequence_length == 0; + +// Flash: skip when causal_cross_no_past (no top-left support) +// MEA: NOT skipped — handles it via causal_from_top_left = (past_sequence_length == 0) +// Unfused: always correct via past_kv_length = parameters.past_sequence_length +``` + +### When S_q == S_kv + +Upper-left and lower-right produce **identical** results when `S_q == S_kv` (the offset is 0 either way). The alignment distinction only matters for cross-attention shapes (`S_q != S_kv`). + +### TensorScatter decode (opset 24 external KV cache) + +TensorScatter manages KV cache externally — `past_key` is nullptr but K/V already contain the full sequence. Per the ONNX spec, `is_causal` with `S_q != S_kv` and no `past_key` means upper-left (q[0] sees only kv[0]), which is **not meaningful for decode**. + +**Correct pattern**: TensorScatter decode must use `is_causal=0` and rely on `nonpad_kv_seqlen` to bound the active KV range. Models using `is_causal=1` with TensorScatter decode have a spec-invalid combination. diff --git a/.agents/skills/ort-build/SKILL.md b/.agents/skills/ort-build/SKILL.md new file mode 100644 index 0000000000000..185d56d20c360 --- /dev/null +++ b/.agents/skills/ort-build/SKILL.md @@ -0,0 +1,85 @@ +--- +name: ort-build +description: Build ONNX Runtime from source. Use this skill when asked to build, compile, or generate CMake files for ONNX Runtime. +--- + +# Building ONNX Runtime + +The build scripts `build.sh` (Linux/macOS) and `build.bat` (Windows) delegate to `tools/ci_build/build.py`. + +## Build phases + +Three phases, controlled by flags: + +- `--update` — generate CMake build files +- `--build` — compile (add `--parallel` to speed this up) +- `--test` — run tests + +For native builds, if none are specified (and `--skip_tests` is not passed), **all three run by default**. For cross-compiled builds, the default is `--update` + `--build` only. + +### When to use `--update` + +You need `--update` when: +- First build in a new build directory +- New source files are added (some CMake targets use glob patterns, others use explicit file lists — re-run to pick up new files either way) +- CMake configuration changes (new flags, updated CMakeLists.txt) + +You do **not** need `--update` when only modifying existing `.cc`/`.h` files — just use `--build`. Skipping it saves time. + +## Examples + +```bash +# Full build (update + build + test) +./build.sh --config Release --parallel +.\build.bat --config Release --parallel # Windows + +# Just regenerate CMake files +./build.sh --config Release --update + +# Just compile (skip CMake regeneration and tests) +./build.sh --config Release --build --parallel + +# Just run tests (after a prior build) +./build.sh --config Release --test + +# Build with CUDA execution provider +./build.sh --config Release --parallel --use_cuda --cuda_home /usr/local/cuda --cudnn_home /usr/local/cuda + +# Build Python wheel +./build.sh --config Release --parallel --build_wheel + +# Build a specific CMake target (much faster than a full build) +./build.sh --config Release --build --parallel --target onnxruntime_common + +# Load flags from an option file (one flag per line) +./build.sh "@./custom_options.opt" --build --parallel +``` + +## Key flags + +| Flag | Description | +|------|-------------| +| `--config` | `Debug`, `MinSizeRel`, `Release`, or `RelWithDebInfo` | +| `--parallel` | Enable parallel compilation (recommended) | +| `--skip_tests` | Skip running tests after build | +| `--build_wheel` | Build the Python wheel package | +| `--use_cuda` | Enable CUDA EP. Requires `--cuda_home`/`--cudnn_home` or `CUDA_HOME`/`CUDNN_HOME` env vars. On Windows, only `cuda_home`/`CUDA_HOME` is validated. | +| `--target T` | Build a specific CMake target (requires `--build`; e.g., `onnxruntime_common`, `onnxruntime_test_all`) | +| `--build_dir` | Build output directory | + +## Build output path + +Default: `build///` where Platform is `Linux`, `MacOS`, or `Windows`. + +With Visual Studio multi-config generators, the config name appears twice (e.g., `build/Windows/Release/Release/`). + +It may be customized with `--build_dir`. + +## Agent tips + +- **Activate a Python virtual environment** before building. See "Python > Virtual environment" in `AGENTS.md`. +- **Prefer `python tools/ci_build/build.py` directly** over `build.bat`/`build.sh` when redirecting output. The `.bat` wrapper runs in `cmd.exe`, which breaks PowerShell redirection. +- **Redirect output to a file** (e.g., `> build_log.txt 2>&1`). Build output is large and will overflow terminal buffers. +- **Run builds in the background** — a full build can take tens of minutes to over an hour. Poll the log for `"Build complete"` or errors. +- **Use `--parallel`** by default unless the user says otherwise. +- Ask the user what they want to build (config, execution providers, wheel, etc.) if not clear from their prompt. diff --git a/.agents/skills/ort-lint/SKILL.md b/.agents/skills/ort-lint/SKILL.md new file mode 100644 index 0000000000000..7799219ef9134 --- /dev/null +++ b/.agents/skills/ort-lint/SKILL.md @@ -0,0 +1,43 @@ +--- +name: ort-lint +description: Lint and format ONNX Runtime code. Use this skill when asked to lint, format, or check code style for C++ or Python files in ONNX Runtime. +--- + +# Linting and Formatting ONNX Runtime Code + +ONNX Runtime uses [lintrunner](https://github.com/suo/lintrunner) for both C++ (clang-format) and Python (ruff). + +## Setup (one-time) + +```bash +pip install -r requirements-lintrunner.txt +lintrunner init +``` + +## Commands + +```bash +lintrunner -a # auto-fix changed files +lintrunner -a --all-files # auto-fix all files +lintrunner -a path/to/file.py path/to/other_file.cc # auto-fix specific files +lintrunner f --all-files # format Python files only +lintrunner # check without fixing (dry run) +``` + +## Style rules + +### C++ +- Google C++ Style with modifications (see `docs/Coding_Conventions_and_Standards.md` for full details) +- Max line length: 120 characters, but **aim for 80** when possible +- Configured in `.clang-format` and `.clang-tidy` + +### Python +- Google Python Style Guide (extension of PEP 8) +- Max line length: 120 characters +- Configured in `pyproject.toml` + +## Agent tips + +- **Activate a Python virtual environment** before installing dependencies. See "Python > Virtual environment" in `AGENTS.md`. +- If lintrunner is not yet set up, install and initialize first (see [Setup](#setup-one-time)). +- Prefer `lintrunner -a` (changed files only) over `--all-files` unless the user asks for a full sweep. diff --git a/.agents/skills/ort-test/SKILL.md b/.agents/skills/ort-test/SKILL.md new file mode 100644 index 0000000000000..bfefa955103f5 --- /dev/null +++ b/.agents/skills/ort-test/SKILL.md @@ -0,0 +1,81 @@ +--- +name: ort-test +description: Run ONNX Runtime tests. Use this skill when asked to run tests, debug test failures, or find and execute specific test cases in ONNX Runtime. +--- + +# Running ONNX Runtime Tests + +ONNX Runtime uses **Google Test** for C++ and **unittest** (preferred) / **pytest** for Python. + +## C++ tests + +### Test executables + +| Executable | What it tests | +|---|---| +| `onnxruntime_test_all` | Core framework, graph, optimizer, session tests | +| `onnxruntime_provider_test` | Operator/kernel tests (Conv, MatMul, etc.) across execution providers | + +Use `--gtest_filter` to select specific tests: + +```bash +./onnxruntime_provider_test --gtest_filter="*Conv3D*" +``` + +### Running tests + +**Always run from the build output directory** — tests may fail to find dependencies otherwise. + +```bash +# Linux +cd build/Linux/Release +./onnxruntime_provider_test --gtest_filter="*TestName*" + +# macOS +cd build/MacOS/Release +./onnxruntime_provider_test --gtest_filter="*TestName*" + +# Windows +cd build\Windows\Release +.\onnxruntime_provider_test.exe --gtest_filter="*TestName*" +``` + +You can also run all tests via the build script (assumes a prior successful build): + +```bash +./build.sh --config Release --test +.\build.bat --config Release --test # Windows +``` + +### Locating the build output directory + +The default path follows the pattern `build///` where Platform is `Linux`, `MacOS`, or `Windows`. With Visual Studio multi-config generators on Windows, the config may appear twice (e.g., `build/Windows/Release/Release/`). The path can also be customized via `--build_dir`. + +If you can't find a test binary, search for it: + +```powershell +# Windows +Get-ChildItem -Path build -Recurse -Filter "onnxruntime_provider_test.exe" | Select-Object -ExpandProperty FullName + +# Linux/macOS +find build -name "onnxruntime_provider_test" -type f +``` + +## Python tests + +Use `pytest` as the test runner: + +```bash +pytest onnxruntime/test/python/test_specific.py # entire file +pytest onnxruntime/test/python/test_specific.py::TestClass::test_method # specific test +pytest -k "test_keyword" onnxruntime/test/python/ # by keyword +``` + +Python test naming convention: `test___[when_]` + +## Agent tips + +- **Activate a Python virtual environment** before running tests. See "Python > Virtual environment" in `AGENTS.md`. +- **Redirect test output to a file** (e.g., `> test_output.txt 2>&1`) — output can be large. +- For C++ tests, verify the build directory exists and a prior build completed before running. +- Use `--gtest_filter` to run a targeted subset when the full suite takes too long. diff --git a/.agents/skills/python-kwargs-setattr-security/SKILL.md b/.agents/skills/python-kwargs-setattr-security/SKILL.md new file mode 100644 index 0000000000000..d31d9d9cac3fa --- /dev/null +++ b/.agents/skills/python-kwargs-setattr-security/SKILL.md @@ -0,0 +1,59 @@ +--- +name: python-kwargs-setattr-security +description: When reviewing or fixing Python code that uses setattr() with user-controlled kwargs to configure C++ extension objects (SessionOptions, RunOptions, etc.) in ONNX Runtime. Use this to apply the allowlist pattern that prevents arbitrary file writes and other attacks via reflected property access. +--- + +## Problem Pattern + +Using `hasattr(obj, k) / setattr(obj, k, v)` with user-controlled kwargs is insecure. The `hasattr` check is NOT a security guard — it returns True for ALL exposed properties including dangerous ones. + +```python +# INSECURE — do not use +for k, v in kwargs.items(): + if hasattr(options, k): + setattr(options, k, v) +``` + +## Fix: Explicit Allowlist + +Define a module-level frozenset of safe attribute names. Raise RuntimeError for known-but-blocked attrs; silently ignore unknown keys. + +```python +# Define at module level, before the class +_ALLOWED_SESSION_OPTIONS = frozenset({ + "enable_cpu_mem_arena", + "enable_mem_pattern", + # ... only explicitly reviewed safe attrs +}) + +# In the method +for k, v in kwargs.items(): + if k in _ALLOWED_SESSION_OPTIONS: + setattr(options, k, v) + elif hasattr(options, k): # reuse the existing instance, don't create new + raise RuntimeError( + f"SessionOptions attribute '{k}' is not permitted via the backend API. " + f"Allowed attributes: {', '.join(sorted(_ALLOWED_SESSION_OPTIONS))}" + ) + # else: silently ignore (may be kwargs for a different config object) +``` + +## Key Rules + +1. **Use the existing object** in `hasattr(options, k)` — never `hasattr(ClassName(), k)` (creates throwaway C++ objects per iteration) +2. **RuntimeError** is the ORT convention for API misuse errors (not ValueError) +3. **Silent ignore for one path is OK when kwargs are forwarded to both paths**: `run_model()` passes the same kwargs dict to both `prepare()` (validates SessionOptions) and `rep.run()` (validates RunOptions). A RunOptions kwarg unknown to SessionOptions is silently ignored by `prepare()` — this is correct because `rep.run()` will validate it. Only raise RuntimeError when the attr exists on the target object but is blocked. +4. **Frozenset constant naming**: `_ALLOWED_` — ALL_CAPS, Google Style +5. **No type annotations** on module-level constants (ORT Python convention) + +## Dangerous SessionOptions Properties (never allowlist) + +- `optimized_model_filepath` — triggers Model::Save(), overwrites arbitrary files +- `profile_file_prefix` + `enable_profiling` — writes profiling JSON to arbitrary path +- `register_custom_ops_library` — loads arbitrary shared libraries (method, not property) + +## Files in ONNX Runtime + +- `onnxruntime/python/backend/backend.py` — `_ALLOWED_SESSION_OPTIONS` +- `onnxruntime/python/backend/backend_rep.py` — `_ALLOWED_RUN_OPTIONS` +- Tests: `onnxruntime/test/python/onnxruntime_test_python_backend.py` — `TestBackendKwargsAllowlist` diff --git a/.config/1espt/PipelineAutobaseliningConfig.yml b/.config/1espt/PipelineAutobaseliningConfig.yml index 183d52d5c1d44..f59528797405e 100644 --- a/.config/1espt/PipelineAutobaseliningConfig.yml +++ b/.config/1espt/PipelineAutobaseliningConfig.yml @@ -14,6 +14,13 @@ pipelines: lastModifiedDate: 2024-10-25 armory: lastModifiedDate: 2024-10-25 + binary: + credscan: + lastModifiedDate: 2025-02-06 + binskim: + lastModifiedDate: 2025-04-25 + spotbugs: + lastModifiedDate: 2025-02-06 usedNonDefaultBranch: true 1299: retail: @@ -32,7 +39,7 @@ pipelines: credscan: lastModifiedDate: 2024-10-25 binskim: - lastModifiedDate: 2024-10-25 + lastModifiedDate: 2025-04-25 spotbugs: lastModifiedDate: 2024-10-25 1625: @@ -52,7 +59,7 @@ pipelines: credscan: lastModifiedDate: 2024-11-13 binskim: - lastModifiedDate: 2024-11-13 + lastModifiedDate: 2025-04-25 spotbugs: lastModifiedDate: 2024-11-13 1626: @@ -75,3 +82,117 @@ pipelines: lastModifiedDate: 2024-11-13 spotbugs: lastModifiedDate: 2024-11-13 + 995: + retail: + source: + credscan: + lastModifiedDate: 2025-02-12 + eslint: + lastModifiedDate: 2025-02-12 + psscriptanalyzer: + lastModifiedDate: 2025-02-12 + armory: + lastModifiedDate: 2025-02-12 + 1313: + retail: + source: + credscan: + lastModifiedDate: 2025-02-27 + eslint: + lastModifiedDate: 2025-02-27 + psscriptanalyzer: + lastModifiedDate: 2025-02-27 + armory: + lastModifiedDate: 2025-02-27 + binary: + credscan: + lastModifiedDate: 2025-02-27 + binskim: + lastModifiedDate: 2025-04-25 + spotbugs: + lastModifiedDate: 2025-02-27 + 1312: + retail: + source: + credscan: + lastModifiedDate: 2025-02-27 + eslint: + lastModifiedDate: 2025-02-27 + psscriptanalyzer: + lastModifiedDate: 2025-02-27 + armory: + lastModifiedDate: 2025-02-27 + 841: + retail: + source: + credscan: + lastModifiedDate: 2025-04-24 + eslint: + lastModifiedDate: 2025-04-24 + psscriptanalyzer: + lastModifiedDate: 2025-04-24 + armory: + lastModifiedDate: 2025-04-24 + policheck: + lastModifiedDate: 2025-07-25 + binary: + credscan: + lastModifiedDate: 2025-04-25 + binskim: + lastModifiedDate: 2025-07-25 + spotbugs: + lastModifiedDate: 2025-04-25 + usedBinskimScanAllExtensions: true + 1757: + retail: + source: + credscan: + lastModifiedDate: 2025-04-25 + eslint: + lastModifiedDate: 2025-04-25 + psscriptanalyzer: + lastModifiedDate: 2025-04-25 + armory: + lastModifiedDate: 2025-04-25 + policheck: + lastModifiedDate: 2025-07-23 + binary: + credscan: + lastModifiedDate: 2025-04-25 + binskim: + lastModifiedDate: 2025-07-24 + spotbugs: + lastModifiedDate: 2025-04-25 + usedBinskimScanAllExtensions: true + 1234: + retail: + source: + credscan: + lastModifiedDate: 2025-04-25 + eslint: + lastModifiedDate: 2025-04-25 + psscriptanalyzer: + lastModifiedDate: 2025-04-25 + armory: + lastModifiedDate: 2025-04-25 + policheck: + lastModifiedDate: 2025-07-23 + binary: + credscan: + lastModifiedDate: 2025-04-25 + binskim: + lastModifiedDate: 2025-07-24 + spotbugs: + lastModifiedDate: 2025-04-25 + usedBinskimScanAllExtensions: true + 1311: + retail: + source: + credscan: + lastModifiedDate: 2025-07-18 + eslint: + lastModifiedDate: 2025-07-18 + psscriptanalyzer: + lastModifiedDate: 2025-07-18 + armory: + lastModifiedDate: 2025-07-18 diff --git a/.config/guardian/.gdnbaselines b/.config/guardian/.gdnbaselines index a7ee2a4b69dda..18a9250059134 100644 --- a/.config/guardian/.gdnbaselines +++ b/.config/guardian/.gdnbaselines @@ -38,6 +38,437 @@ "createdDate": "2024-11-13 11:20:17Z", "expirationDate": "2025-05-02 11:55:15Z", "justification": "This error is baselined with an expiration date of 180 days from 2024-11-13 11:55:15Z" + }, + "6f6606e50e82b2d3c823c435151f4b69c1fbde92f274753b793d948856cfc462": { + "signature": "6f6606e50e82b2d3c823c435151f4b69c1fbde92f274753b793d948856cfc462", + "alternativeSignatures": [], + "target": "ScanTelemetry_20250206154816289.json", + "line": 1, + "memberOf": [ + "default" + ], + "tool": "credscan", + "ruleId": "CSCAN-AZURE0130", + "createdDate": "2025-02-06 15:53:46Z", + "expirationDate": "2025-07-26 16:26:55Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-02-06 16:26:55Z" + }, + "4a0e83898f2607b442b095973eed78a44648024954e8ef2188e6ba3786771620": { + "signature": "4a0e83898f2607b442b095973eed78a44648024954e8ef2188e6ba3786771620", + "alternativeSignatures": [ + "68a14c0d46c7eb93178e545e06454f12e9d1c98e4e9ecbe009e11cd3eff4f682" + ], + "target": "file:///D:/a/_work/_temp/RelWithDebInfo/RelWithDebInfo/dxcompiler.dll", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2007", + "createdDate": "2025-04-25 11:09:32Z", + "expirationDate": "2025-10-12 11:33:39Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 11:33:39Z" + }, + "b3a97d9c774e372e8204bdd6abe8e5bc5fdd46799adaeb0f666838042fdd8f99": { + "signature": "b3a97d9c774e372e8204bdd6abe8e5bc5fdd46799adaeb0f666838042fdd8f99", + "alternativeSignatures": [ + "79f7ba0d65b89c586e684239b8488e9d8cf58c53ce9fedb323dbee5096378e08" + ], + "target": "file:///D:/a/_work/_temp/RelWithDebInfo/RelWithDebInfo/onnxruntime.dll", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2007", + "createdDate": "2025-04-25 11:09:32Z", + "expirationDate": "2025-10-12 11:33:39Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 11:33:39Z" + }, + "9836b7915d2d6019bd245fd42935c164e0f9db8c867c8fe26cd6c2f576927aa2": { + "signature": "9836b7915d2d6019bd245fd42935c164e0f9db8c867c8fe26cd6c2f576927aa2", + "alternativeSignatures": [ + "1081cda6083ef05dfe233be730c16c300ef887ba2b0bd8908b2f255ba666f3be" + ], + "target": "file:///D:/a/_work/_temp/RelWithDebInfo/RelWithDebInfo/onnxruntime_autoep_test.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2007", + "createdDate": "2025-04-25 11:09:32Z", + "expirationDate": "2025-10-12 11:33:39Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 11:33:39Z" + }, + "5d44b5ab5f1d37e0368a85b56bf7460c97e329d626954edd761ace4890e5b6d9": { + "signature": "5d44b5ab5f1d37e0368a85b56bf7460c97e329d626954edd761ace4890e5b6d9", + "alternativeSignatures": [ + "acaec6efd0587a90c9d9ae4dc9893cd8ae4cec325f0263eb710444ca16f76e86" + ], + "target": "file:///D:/a/_work/_temp/RelWithDebInfo/RelWithDebInfo/onnxruntime_perf_test.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2007", + "createdDate": "2025-04-25 11:09:32Z", + "expirationDate": "2025-10-12 11:33:39Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 11:33:39Z" + }, + "55ad483be6385b220d416d13e2815669297a2e9abb23fb12c4c8057cba628808": { + "signature": "55ad483be6385b220d416d13e2815669297a2e9abb23fb12c4c8057cba628808", + "alternativeSignatures": [ + "64e9ad74cf4e0c10e1bc5c07140f0b8ed101b123a96565b112ee81ccaa3a942a" + ], + "target": "file:///D:/a/_work/_temp/RelWithDebInfo/RelWithDebInfo/onnxruntime_test_all.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2007", + "createdDate": "2025-04-25 11:09:32Z", + "expirationDate": "2025-10-12 11:33:39Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 11:33:39Z" + }, + "20edb5d58ae9fe1784a826b3cd03ec897234691bcb117b076ee0b1da3c4c4468": { + "signature": "20edb5d58ae9fe1784a826b3cd03ec897234691bcb117b076ee0b1da3c4c4468", + "alternativeSignatures": [ + "dc64851ea95bd49082445a0f63dd2eb843410d661388ff5b64303f71aed44ad4" + ], + "target": "file:///D:/a/_work/_temp/RelWithDebInfo/RelWithDebInfo/onnx_test_runner.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2007", + "createdDate": "2025-04-25 11:09:32Z", + "expirationDate": "2025-10-12 11:33:39Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 11:33:39Z" + }, + "6a04730bbf5429b2a82eec02edf9a10199d16a2956ef3bc4b11795318e44d7b3": { + "signature": "6a04730bbf5429b2a82eec02edf9a10199d16a2956ef3bc4b11795318e44d7b3", + "alternativeSignatures": [ + "fae795cbfb44b883a7ef789394c107474257e3256a60fc4f8142634875d2df47" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-arm64/native/onnxruntime_perf_test.exe", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "6b12997cff49c14a6472fa08cd6aae83767f6fea72aa2654caca0a7afbe1e8aa": { + "signature": "6b12997cff49c14a6472fa08cd6aae83767f6fea72aa2654caca0a7afbe1e8aa", + "alternativeSignatures": [ + "4349b8b6474089bf80e75d9ef3e41d904f91caac91fb5b64914ccbad1758e874" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-arm64/native/onnx_test_runner.exe", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "5e3b583bf904b2985056f9b98153ac5be048864ce31c78219e143727c834d988": { + "signature": "5e3b583bf904b2985056f9b98153ac5be048864ce31c78219e143727c834d988", + "alternativeSignatures": [ + "0edba8b6930210ec72d5d7ae32f20150656e16110734e5325665571f873b8787" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-arm64/native/QnnCpu.dll", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "32c1e4332e93d446403d313dee13b68d84e9ae65b45dd624bb07bea27c211b03": { + "signature": "32c1e4332e93d446403d313dee13b68d84e9ae65b45dd624bb07bea27c211b03", + "alternativeSignatures": [ + "55642f7417832dd59f767472b0d50492e273411880395c8fb16ccff013022271" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-arm64/native/QnnGpu.dll", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "79ad215ffb5f1a3c51f4061b877f5d1d65eb71a5c1acedd9fe0410b20f797df1": { + "signature": "79ad215ffb5f1a3c51f4061b877f5d1d65eb71a5c1acedd9fe0410b20f797df1", + "alternativeSignatures": [ + "570709e99467a902da4d446c6dbda5cebc52f84e6272834ec813204060d76188" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-arm64/native/QnnHtp.dll", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "00e3517a665b3fc013745cb76d0aad5d6091828c0325d5a3230fdae837f8f971": { + "signature": "00e3517a665b3fc013745cb76d0aad5d6091828c0325d5a3230fdae837f8f971", + "alternativeSignatures": [ + "f40aab5b7b16c3fbd0562d4d395897370f5409befabb9cb10be9c4a5116001ed" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-arm64/native/QnnHtpPrepare.dll", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "341396cfcbf2cd00c8b505c6fdd4fd56cd45c2466e548c6bfca2ded31ebbc371": { + "signature": "341396cfcbf2cd00c8b505c6fdd4fd56cd45c2466e548c6bfca2ded31ebbc371", + "alternativeSignatures": [ + "0515e21e0cc4f70161d08fe02bf41a1f7818db8ee22a152c550eb75019db2eee" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-arm64/native/QnnHtpV68Stub.dll", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "2fba96257861f1ba2b702bc8c1e9242ef9c71e90529d6dd830e78ae0280b5a50": { + "signature": "2fba96257861f1ba2b702bc8c1e9242ef9c71e90529d6dd830e78ae0280b5a50", + "alternativeSignatures": [ + "e0f5edd83dd731f4774d381587a99f7aa7bbff367931474d2a03d2fd0c284888" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-arm64/native/QnnHtpV73Stub.dll", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "f92f8f9eab05869e80b374408af4f30697bc49c6ff79511e6833cc5dcc0eaf9c": { + "signature": "f92f8f9eab05869e80b374408af4f30697bc49c6ff79511e6833cc5dcc0eaf9c", + "alternativeSignatures": [ + "48b6850d8ea65e1dc6028afba9530341e22be187eb497c791f06c592e06b070e" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-arm64/native/QnnSaver.dll", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "688b86bbaa9d662204784f37c9c184e532a5005429eb654dd31221b27affa28a": { + "signature": "688b86bbaa9d662204784f37c9c184e532a5005429eb654dd31221b27affa28a", + "alternativeSignatures": [ + "42fc3288553ee6bed51b3c0d5e1010b0d7d2efbaf805bc467b99e9b472fb5382" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-arm64/native/QnnSystem.dll", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "0c8d7037690ad318b1d094798d596dba3882a310dc68f97b3815a89d80c540a7": { + "signature": "0c8d7037690ad318b1d094798d596dba3882a310dc68f97b3815a89d80c540a7", + "alternativeSignatures": [ + "b450b5782f69aae532807936726d9c4af88806b0f49ae0ae33cd38a76bdc8a16" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-x64/native/onnxruntime_perf_test.exe", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "16744137fb39b77c89d7a4770f34e8ff4de6a0b94a080be2930daff16a4e4728": { + "signature": "16744137fb39b77c89d7a4770f34e8ff4de6a0b94a080be2930daff16a4e4728", + "alternativeSignatures": [ + "d6b6fc769d11c6c5998c3f7a4ad9aa0458f4ec7d83ed4e633f66a0f605820536" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-x64/native/onnx_test_runner.exe", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "17f65b2847b5e2d9db98da9877df029306d696896a7792cc307d3cd9db05d1b2": { + "signature": "17f65b2847b5e2d9db98da9877df029306d696896a7792cc307d3cd9db05d1b2", + "alternativeSignatures": [ + "bc5561d1f532f05ea310e9086f4755cbc3f30e8d7aa28ae62b127fd6d8332850" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-x64/native/QnnCpu.dll", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "6eab05d067b751e37396a947650b38645d3b18c54065e9fba45c39c140e829b5": { + "signature": "6eab05d067b751e37396a947650b38645d3b18c54065e9fba45c39c140e829b5", + "alternativeSignatures": [ + "c8a0788fe4624f8c8c5e81f6adfb2ef29b4d801fe7d970fc3961aa6958f7f0f3" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-x64/native/QnnHtp.dll", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "dee40d055d13313aec18920bc2f0a0a72bfc6deb836fd7a0a92245fc501bb73c": { + "signature": "dee40d055d13313aec18920bc2f0a0a72bfc6deb836fd7a0a92245fc501bb73c", + "alternativeSignatures": [ + "70da4f93be9acc7617d47270be9c790c970f0c12d6eaa642739d0d1b413eb7b5" + ], + "target": "Microsoft.ML.OnnxRuntime.QNN.1.23.0-dev-20250425-0443-1e118d6/runtimes/win-x64/native/QnnSaver.dll", + "memberOf": [ + "default" + ], + "tool": "codesign", + "ruleId": "CodeSign.MissingSigningCert", + "createdDate": "2025-04-25 17:06:52Z", + "expirationDate": "2025-10-12 17:09:03Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 17:09:03Z" + }, + "568199e534a7aaaa1f2f1395eba1edad215e4a4b1f71457c84868644ca2b5997": { + "signature": "568199e534a7aaaa1f2f1395eba1edad215e4a4b1f71457c84868644ca2b5997", + "alternativeSignatures": [], + "target": "ScanTelemetry_20250425220821141.json", + "line": 1, + "memberOf": [ + "default" + ], + "tool": "credscan", + "ruleId": "CSCAN-AZURE0130", + "createdDate": "2025-04-25 22:25:47Z", + "expirationDate": "2025-10-12 23:01:19Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 23:01:19Z" + }, + "46cd93fda3b6f7eec5d6c3f72169c3ad1092216fa6c9630177d7f2d6e940e555": { + "signature": "46cd93fda3b6f7eec5d6c3f72169c3ad1092216fa6c9630177d7f2d6e940e555", + "alternativeSignatures": [], + "target": "ScanTelemetry_20250425220811012.json", + "line": 1, + "memberOf": [ + "default" + ], + "tool": "credscan", + "ruleId": "CSCAN-AZURE0130", + "createdDate": "2025-04-25 22:25:52Z", + "expirationDate": "2025-10-12 23:01:19Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 23:01:19Z" + }, + "919e797b88639882a09d577e57832df0158ac312a221697faf9fc9a40021d8a0": { + "signature": "919e797b88639882a09d577e57832df0158ac312a221697faf9fc9a40021d8a0", + "alternativeSignatures": [], + "target": "ScanTelemetry_20250425220803349.json", + "line": 1, + "memberOf": [ + "default" + ], + "tool": "credscan", + "ruleId": "CSCAN-AZURE0130", + "createdDate": "2025-04-25 22:25:55Z", + "expirationDate": "2025-10-12 23:01:19Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-04-25 23:01:19Z" + }, + "67acaef0adebeee9ddcb2ff2630fa3051c0c8e7083f36f64ac0040d9a22b73b5": { + "signature": "67acaef0adebeee9ddcb2ff2630fa3051c0c8e7083f36f64ac0040d9a22b73b5", + "alternativeSignatures": [ + "2f5e8344c6d8ffa32a8a54c363d0c480380320a6c0a3fd3e4ca1ff2aafe6dbcf" + ], + "target": "file:///E:/_work/_temp/RelWithDebInfo/RelWithDebInfo/dxcompiler.dll", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2007", + "createdDate": "2025-07-24 10:13:44Z", + "expirationDate": "2026-01-10 11:03:50Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-07-24 11:03:50Z" + }, + "7a02b29f8870bfd4cc770281dd860421523a3aac51ea96332e25696ca1f5570e": { + "signature": "7a02b29f8870bfd4cc770281dd860421523a3aac51ea96332e25696ca1f5570e", + "alternativeSignatures": [ + "1229412e0db78558feac3bc51ea9eed6ae2311e60298dc1f2d3366bd12544c88" + ], + "target": "file:///E:/_work/_temp/RelWithDebInfo/RelWithDebInfo/onnxruntime_perf_test.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2007", + "createdDate": "2025-07-24 10:13:44Z", + "expirationDate": "2026-01-10 11:03:50Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-07-24 11:03:50Z" + }, + "68b657f6d9dd9386bd43f0716cb424c196f7da4559eb1c3f3f26a1297b211239": { + "signature": "68b657f6d9dd9386bd43f0716cb424c196f7da4559eb1c3f3f26a1297b211239", + "alternativeSignatures": [ + "e026012915cda24b9e85a1d1fa38607d09effa532b40a1c0f0740eb3855f9599" + ], + "target": "file:///E:/_work/_temp/RelWithDebInfo/RelWithDebInfo/onnxruntime_test_all.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2007", + "createdDate": "2025-07-24 10:13:44Z", + "expirationDate": "2026-01-10 11:03:50Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-07-24 11:03:50Z" + }, + "8222fbb019a791fa0541084854a0bf7bf723ce7ffaa4a0e1e5ca5cb76acb48bb": { + "signature": "8222fbb019a791fa0541084854a0bf7bf723ce7ffaa4a0e1e5ca5cb76acb48bb", + "alternativeSignatures": [ + "5e0bdc06af73864bdb480aceaf154a35e0774ab7f8490e7d9f8b5a36b7c19619" + ], + "target": "file:///E:/_work/_temp/RelWithDebInfo/RelWithDebInfo/onnx_test_runner.exe", + "memberOf": [ + "default" + ], + "tool": "binskim", + "ruleId": "BA2007", + "createdDate": "2025-07-24 10:13:44Z", + "expirationDate": "2026-01-10 11:03:50Z", + "justification": "This error is baselined with an expiration date of 180 days from 2025-07-24 11:03:50Z" } } } \ No newline at end of file diff --git a/.gdn/.gdntsa b/.gdn/.gdntsa deleted file mode 100644 index e49848d116d90..0000000000000 --- a/.gdn/.gdntsa +++ /dev/null @@ -1,3 +0,0 @@ -{ - "codebaseName": "onnxruntime_main" -} \ No newline at end of file diff --git a/.gitattributes b/.gitattributes index 8bfd419922d6b..10cff89899f11 100644 --- a/.gitattributes +++ b/.gitattributes @@ -11,3 +11,6 @@ # make sure build.sh retains Unix line endings, even when checked out on windows. *.sh text eol=lf + +# Git hooks must have Unix line endings to work on all platforms +.githooks/* text eol=lf diff --git a/.githooks/pre-commit b/.githooks/pre-commit new file mode 100755 index 0000000000000..d0eb94432f156 --- /dev/null +++ b/.githooks/pre-commit @@ -0,0 +1,17 @@ +#!/bin/sh +# Pre-commit hook: runs lintrunner on files being committed. +# Skip with: git commit --no-verify + +if ! command -v lintrunner >/dev/null 2>&1; then + echo "Warning: lintrunner not found - skipping pre-commit lint." + echo " Install: pip install -r requirements-lintrunner.txt && lintrunner init" + exit 0 +fi + +lintrunner --paths-cmd='git diff --cached --name-only --diff-filter=ACMR' + +if [ $? -ne 0 ]; then + echo "" + echo "Lint failed. Run 'lintrunner -a' to auto-fix, re-stage, and commit again." + exit 1 +fi diff --git a/.github/ISSUE_TEMPLATE/03-mobile.yml b/.github/ISSUE_TEMPLATE/03-mobile.yml index 7c6de5aad523d..07bb40ff94a2e 100644 --- a/.github/ISSUE_TEMPLATE/03-mobile.yml +++ b/.github/ISSUE_TEMPLATE/03-mobile.yml @@ -131,6 +131,6 @@ body: id: ep-version attributes: label: Execution Provider Library Version - placeholder: ex. CUDA 11.6 or ROCm 5.1.1 + placeholder: ex. CUDA 12.2 or ROCm 5.1.1 validations: required: false diff --git a/.github/ISSUE_TEMPLATE/05-performance.yml b/.github/ISSUE_TEMPLATE/05-performance.yml index da0e6c7ada7a7..1da2f3d3eefc8 100644 --- a/.github/ISSUE_TEMPLATE/05-performance.yml +++ b/.github/ISSUE_TEMPLATE/05-performance.yml @@ -113,7 +113,6 @@ body: - TensorRT - NNAPI - ACL - - ArmNN - MIGraphX - Rockchip NPU - SNPE @@ -127,7 +126,7 @@ body: id: ep-version attributes: label: Execution Provider Library Version - placeholder: ex. CUDA 11.6 or ROCm 5.1.1 + placeholder: ex. CUDA 12.2 or ROCm 5.1.1 validations: required: false - type: textarea diff --git a/.github/ISSUE_TEMPLATE/06-training.yml b/.github/ISSUE_TEMPLATE/06-training.yml index 790d64dac0051..fec2ab3a1b285 100644 --- a/.github/ISSUE_TEMPLATE/06-training.yml +++ b/.github/ISSUE_TEMPLATE/06-training.yml @@ -72,6 +72,6 @@ body: id: ep-version attributes: label: Execution Provider Library Version - placeholder: ex. CUDA 11.6 or ROCm 5.1.1 + placeholder: ex. CUDA 12.2 or ROCm 5.1.1 validations: required: false diff --git a/.github/ISSUE_TEMPLATE/08-general.yml b/.github/ISSUE_TEMPLATE/08-general.yml index 241be0044fe7d..d2802616dbed4 100644 --- a/.github/ISSUE_TEMPLATE/08-general.yml +++ b/.github/ISSUE_TEMPLATE/08-general.yml @@ -111,7 +111,6 @@ body: - TensorRT - NNAPI - ACL - - ArmNN - MIGraphX - Rockchip NPU - SNPE @@ -125,6 +124,6 @@ body: id: ep-version attributes: label: Execution Provider Library Version - placeholder: ex. CUDA 11.6 or ROCm 5.1.1 + placeholder: ex. CUDA 12.2 or ROCm 5.1.1 validations: required: false diff --git a/.github/actions/install-onnxruntime-wheel/action.yml b/.github/actions/install-onnxruntime-wheel/action.yml new file mode 100644 index 0000000000000..07f9a00a1dbcf --- /dev/null +++ b/.github/actions/install-onnxruntime-wheel/action.yml @@ -0,0 +1,18 @@ +name: 'Install ONNX Runtime Wheel' +description: 'Uninstalls existing ONNX Runtime packages and installs a wheel from a specified directory.' +inputs: + whl-directory: + description: 'The directory containing the ONNX Runtime wheel files.' + required: true +runs: + using: 'composite' + steps: + - name: Uninstall onnxruntime packages + shell: pwsh + run: | + python -m pip uninstall -y onnxruntime onnxruntime-gpu onnxruntime-training onnxruntime-directml -qq + + - name: Install onnxruntime wheel from specified directory + shell: pwsh + run: | + Get-ChildItem -Path ${{ inputs.whl-directory }}/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} \ No newline at end of file diff --git a/.github/actions/linux-web-init-and-check/action.yml b/.github/actions/linux-web-init-and-check/action.yml new file mode 100644 index 0000000000000..41216e8c2860b --- /dev/null +++ b/.github/actions/linux-web-init-and-check/action.yml @@ -0,0 +1,71 @@ +name: "Web Build Initialize and Check on Linux" +description: "Initializes and checks the ONNX Runtime Web build on Linux." +runs: + using: "composite" + steps: + - name: Setup Node.js + uses: actions/setup-node@v5 + with: + node-version: "22.x" + + - name: npm ci /js/ + run: npm ci + shell: bash + working-directory: ${{ github.workspace }}/js + + - name: npm ci /js/common/ + run: npm ci + shell: bash + working-directory: ${{ github.workspace }}/js/common + + - name: run onnxruntime-common tests + run: npm test + shell: bash + working-directory: ${{ github.workspace }}/js/common + + - name: run onnxruntime-common tests (enable Float16Array) + run: npm run test:f16 + shell: bash + working-directory: ${{ github.workspace }}/js/common + + - name: npm ci /js/web/ + run: npm ci + shell: bash + working-directory: ${{ github.workspace }}/js/web + + - name: run TypeScript type check in /js/web/ + run: npm run prebuild + shell: bash + working-directory: ${{ github.workspace }}/js/web + + - name: run ESLint + run: npm run lint + shell: bash + working-directory: ${{ github.workspace }}/js + + - name: Format code + run: npm run format + shell: bash + working-directory: ${{ github.workspace }}/js + + - name: Check unformatted files + run: | + node -e "a=require('child_process').execSync('git diff --name-only -- .').toString();if(a)throw new Error('Following source files are not formatted: (did you run \"npm run format\"?)\n'+a)" + shell: bash + working-directory: ${{ github.workspace }}/js + + - name: TypeDoc Validation + run: npx typedoc --emit none --treatWarningsAsErrors + shell: bash + working-directory: ${{ github.workspace }}/js/common + + - name: Generating documents + run: npm run build:doc + shell: bash + working-directory: ${{ github.workspace }}/js/web + + - name: Check out of dated documents + run: | + node -e "a=require('child_process').execSync('git diff --name-only -- .').toString();if(a)throw new Error('Following documents are not up-to-date: (did you run \"npm run build:doc\"?)\n'+a)" + shell: bash + working-directory: ${{ github.workspace }}/js/web diff --git a/.github/actions/locate-vcvarsall-and-setup-env/action.yml b/.github/actions/locate-vcvarsall-and-setup-env/action.yml new file mode 100644 index 0000000000000..fba855f14b487 --- /dev/null +++ b/.github/actions/locate-vcvarsall-and-setup-env/action.yml @@ -0,0 +1,80 @@ +name: 'Locate vcvarsall and Setup Environment' +description: 'Locates vcvarsall.bat, sets up the environment, and handles PATH updates.' +inputs: + architecture: + description: 'Target architecture (x64 or x86)' + required: true + default: 'x64' +outputs: + vcvarsall_path: + description: "Path to vcvarsall.bat" + value: ${{ steps.find-vcvarsall.outputs.vcvarsall_path }} +runs: + using: "composite" + steps: + + - name: Setup VCPKG + uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.9 + with: + vcpkg-version: '2025.08.27' + vcpkg-hash: '9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079' + cmake-version: '3.31.6' + cmake-hash: '0f1584e8666cf4a65ec514bd02afe281caabf1d45d2c963f3151c41484f457386aa03273ab25776a670be02725354ce0b46f3a5121857416da37366342a833a0' + add-cmake-to-path: 'true' + disable-terrapin: 'false' + + - name: Verify vcpkg setup + shell: pwsh # Use powershell to easily access env var + run: | + Write-Host "VCPKG_INSTALLATION_ROOT is set to: $env:VCPKG_INSTALLATION_ROOT" + & "$env:VCPKG_INSTALLATION_ROOT/vcpkg" version + + - name: Find vcvarsall.bat + id: find-vcvarsall + shell: python # Use Python shell + run: | + import os + import subprocess + + vswhere_path = os.path.join(os.environ["ProgramFiles(x86)"], "Microsoft Visual Studio", "Installer", "vswhere.exe") + + try: + process = subprocess.run([vswhere_path, "-latest", "-property", "installationPath"], capture_output=True, text=True, check=True) + vs_install_path = process.stdout.strip() + vcvarsall_path = os.path.join(vs_install_path, "VC", "Auxiliary", "Build", "vcvarsall.bat") + + if os.path.exists(vcvarsall_path): + print(f"vcvarsall found at: {vcvarsall_path}") + # Use GITHUB_OUTPUT environment variable + with open(os.environ['GITHUB_OUTPUT'], 'a') as f: + f.write(f"vcvarsall_path={vcvarsall_path}\n") + else: + print(f"vcvarsall.bat not found at expected path: {vcvarsall_path}") + # Use 'exit(1)' for Python to properly signal failure to GitHub Actions + exit(1) + + + except subprocess.CalledProcessError as e: + print(f"Error running vswhere.exe: {e}") + print(f"vswhere output: {e.stdout}") + print(f"vswhere stderr: {e.stderr}") + exit(1) # Exit with a non-zero code on error + except FileNotFoundError: + print(f"vswhere.exe not found at: {vswhere_path}") + exit(1) + + + - name: Setup Environment + shell: cmd + run: | + REM Get initial environment variables + set > initial_env.txt + + REM Call vcvarsall.bat using the output from the previous step + call "${{ steps.find-vcvarsall.outputs.vcvarsall_path }}" ${{ inputs.architecture }} + + REM Get environment variables after calling vcvarsall.bat + set > final_env.txt + + REM Call the Python script to update the GitHub Actions environment + python ${{ github.action_path }}\update_environment.py diff --git a/.github/actions/locate-vcvarsall-and-setup-env/locate_vcvarsall.bat b/.github/actions/locate-vcvarsall-and-setup-env/locate_vcvarsall.bat new file mode 100644 index 0000000000000..df900e5cd0995 --- /dev/null +++ b/.github/actions/locate-vcvarsall-and-setup-env/locate_vcvarsall.bat @@ -0,0 +1,30 @@ +@echo off +setlocal + +set vswherepath="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" +set vcvarsall_arch=%1 +if "%vcvarsall_arch%" == "x86" ( + set vcvarsall_arch=x86 +) else ( + set vcvarsall_arch=x64 +) + +for /f "usebackq delims=" %%i in (`%vswherepath% -latest -property installationPath`) do ( + if exist "%%i\VC\Auxiliary\Build\vcvars%vcvarsall_arch%.bat" ( + set "vcvarsall=%%i\VC\Auxiliary\Build\vcvars%vcvarsall_arch%.bat" + ) +) + +echo "Get initial environment variables" +set > initial_env.txt + +echo "Call vcvarsall.bat" +call "%vcvarsall%" + +echo "Get environment variables after calling vcvarsall.bat" +set > final_env.txt + +echo "Call the Python script to update the GitHub Actions environment" +python "%~dp0\update_environment.py" + +endlocal \ No newline at end of file diff --git a/.github/actions/locate-vcvarsall-and-setup-env/update_environment.py b/.github/actions/locate-vcvarsall-and-setup-env/update_environment.py new file mode 100644 index 0000000000000..9b63b26042562 --- /dev/null +++ b/.github/actions/locate-vcvarsall-and-setup-env/update_environment.py @@ -0,0 +1,37 @@ +import os +import re + + +def read_env_file(filepath): + env_vars = {} + with open(filepath) as f: + for line in f: + match = re.match(r"^(.*?)=(.*)$", line.strip()) + if match: + env_vars[match.group(1).upper()] = match.group(2) + return env_vars + + +initial_env = read_env_file("initial_env.txt") +final_env = read_env_file("final_env.txt") + +for key, value in final_env.items(): + if key not in initial_env or initial_env[key] != value: + if key.startswith("_"): + continue + if key.upper() == "PATH": + new_paths = value.split(";") + initial_paths = initial_env.get("PATH", "").split(";") + added_paths = [p for p in new_paths if p not in initial_paths and p] + + if added_paths: + print("Adding paths") + with open(os.environ["GITHUB_PATH"], "a") as f: + for path in added_paths: + print(f"Adding PATH: {path}") + f.write(path + os.linesep) + else: + # Use GITHUB_ENV + with open(os.environ["GITHUB_ENV"], "a") as f: + print(f"Setting {key}={value}\n") + f.write(f"{key}={value}\n") diff --git a/.github/actions/macos-ci-setup/action.yml b/.github/actions/macos-ci-setup/action.yml new file mode 100644 index 0000000000000..054676d301820 --- /dev/null +++ b/.github/actions/macos-ci-setup/action.yml @@ -0,0 +1,70 @@ +name: "macOS CI pipeline setup steps" +description: "Common setup steps for macOS CI pipelines" + +inputs: + platform_machine: + required: true + type: string + python_version: + required: false + type: string + default: "3.14" + node_version: + required: false + type: string + default: "20.x" + java_version: + required: false + type: string + default: "17" + xcode_version: + required: false + type: string + default: "16" + use_cache: + required: false + type: boolean + default: false + +runs: + using: "composite" + steps: + - name: Use Python + uses: actions/setup-python@v6 + with: + python-version: ${{ inputs.python_version }} + + - name: Verify machine architecture + shell: python + run: | + import platform + print(f"Running on {platform.machine()}") + assert platform.machine().lower() == "${{ inputs.platform_machine}}", "This job expects to be run on an ${{ inputs.platform_machine}} machine." + + - name: Use Node.js + uses: actions/setup-node@v5 + with: + node-version: ${{ inputs.node_version }} + + - name: Install coreutils and ninja + shell: bash + run: brew install coreutils ninja + + - name: Install Java + uses: actions/setup-java@v5 + with: + distribution: "temurin" + java-version: ${{ inputs.java_version }} + + - name: Use Xcode ${{ inputs.xcode_version }} + shell: bash + run: | + XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ inputs.xcode_version }}.app/Contents/Developer" + sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" + + - name: Install python dependencies + shell: bash + working-directory: ${{ github.workspace }} + run: | + python -m pip install --upgrade pip + python -m pip install -r requirements-dev.txt diff --git a/.github/actions/setup-android-ndk/action.yml b/.github/actions/setup-android-ndk/action.yml new file mode 100644 index 0000000000000..4eefc3642cd92 --- /dev/null +++ b/.github/actions/setup-android-ndk/action.yml @@ -0,0 +1,98 @@ +# .github/actions/setup-android-ndk/action.yml +name: 'Setup Android NDK' +description: 'Installs and configures a specific version of the Android NDK' +inputs: + ndk-version: + description: 'The version of the Android NDK to install (e.g., 27.2.12479018)' + required: true + default: '27.2.12479018' + android-sdk-root: + description: 'The root directory of the Android SDK' + required: true + default: '/usr/local/lib/android/sdk' + +runs: + using: "composite" # Use a composite action for multiple shell commands + steps: + - name: Install coreutils and ninja + shell: bash + run: sudo apt-get update -y && sudo apt-get install -y coreutils ninja-build + + - name: Install Android NDK + shell: bash + run: | + set -e + "${{ inputs.android-sdk-root }}/cmdline-tools/latest/bin/sdkmanager" --install "ndk;${{ inputs.ndk-version }}" + + NDK_PATH="${{ inputs.android-sdk-root }}/ndk/${{ inputs.ndk-version }}" + if [[ ! -d "${NDK_PATH}" ]]; then + echo "NDK directory is not in expected location: ${NDK_PATH}" + exit 1 + fi + + # Use standard environment variable setting in bash and add to GITHUB_ENV + echo "ANDROID_NDK_HOME=${NDK_PATH}" >> $GITHUB_ENV + echo "ANDROID_NDK_ROOT=${NDK_PATH}" >> $GITHUB_ENV + echo "ANDROID_NDK_HOME: ${NDK_PATH}" + echo "ANDROID_NDK_ROOT: ${NDK_PATH}" + + - name: Check if emulator are installed and add to PATH + shell: bash + run: | + if [[ ":$PATH:" == *":${ANDROID_SDK_ROOT}/emulator:"* ]]; then + echo "${ANDROID_SDK_ROOT}/emulator is in PATH" + else + ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install "emulator" + echo "${ANDROID_SDK_ROOT}/emulator" >> $GITHUB_PATH + fi + + - name: Check if platform tools are installed and add to PATH + shell: bash + run: | + if [[ ":$PATH:" == *":${ANDROID_SDK_ROOT}/platform-tools:"* ]]; then + echo "${ANDROID_SDK_ROOT}/platform-tools is in PATH" + else + ${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/sdkmanager --install "platform-tools" + echo "${ANDROID_SDK_ROOT}/platform-tools" >> $GITHUB_PATH + fi + ls -R "${ANDROID_SDK_ROOT}/platform-tools" + + - name: Create Android Emulator + shell: bash + env: + ANDROID_AVD_HOME: ${{ runner.temp }}/android-avd + run: | + python3 tools/python/run_android_emulator.py \ + --android-sdk-root "${ANDROID_SDK_ROOT}" \ + --create-avd --system-image "system-images;android-31;default;x86_64" + + - name: List Android AVDs + shell: bash + env: + ANDROID_AVD_HOME: ${{ runner.temp }}/android-avd + run: | + "${ANDROID_SDK_ROOT}/cmdline-tools/latest/bin/avdmanager" list avd + + - name: Check emulator.pid does not exist + shell: bash + run: | + if test -f ./emulator.pid; then + echo "Emulator PID file was not expected to exist but does and has pid: `cat ./emulator.pid`" + exit 1 + fi + + - name: Start Android Emulator + shell: bash + env: + ANDROID_AVD_HOME: ${{ runner.temp }}/android-avd + run: | + set -e -x + python3 tools/python/run_android_emulator.py \ + --android-sdk-root "${ANDROID_SDK_ROOT}" \ + --start --emulator-extra-args="-partition-size 2047 -memory 5120" \ + --emulator-pid-file ./emulator.pid + echo "Emulator PID: `cat ./emulator.pid`" + + - name: View Android ENVs + shell: bash + run: env | grep ANDROID diff --git a/.github/actions/webgpu-validate-shader-key/action.yml b/.github/actions/webgpu-validate-shader-key/action.yml new file mode 100644 index 0000000000000..86406a2e91877 --- /dev/null +++ b/.github/actions/webgpu-validate-shader-key/action.yml @@ -0,0 +1,29 @@ +name: "WebGPU Validate Shader Key" +description: "Validate if the shader key is consistent for WebGPU shaders." + +inputs: + log_file_path: + required: true + type: string + is_chromium_log: + required: false + type: boolean + default: false + +runs: + using: "composite" + steps: + - name: Validate shader keys (chromium log) + # GitHub Actions treats all inputs as strings even if it's specified as a boolean. + if: ${{ inputs.is_chromium_log == 'true' }} + shell: cmd + run: | + node parse-chromium-debug-log.js < "${{ inputs.log_file_path }}" | node validate-shader-key.js + working-directory: ${{ github.action_path }} + + - name: Validate shader keys (native log) + if: ${{ inputs.is_chromium_log != 'true' }} + shell: cmd + run: | + node validate-shader-key.js < "${{ inputs.log_file_path }}" + working-directory: ${{ github.action_path }} diff --git a/.github/actions/webgpu-validate-shader-key/parse-chromium-debug-log.js b/.github/actions/webgpu-validate-shader-key/parse-chromium-debug-log.js new file mode 100644 index 0000000000000..d34ff95192089 --- /dev/null +++ b/.github/actions/webgpu-validate-shader-key/parse-chromium-debug-log.js @@ -0,0 +1,30 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +"use strict"; + +const { EOL } = require("os"); +const readline = require("readline"); + +// This script is used to parse the Chromium debug log and extract the raw log data. + +async function processChromiumDebugLog() { + const rl = readline.createInterface({ + input: process.stdin, + crlfDelay: Infinity, + }); + + for await (const line of rl) { + const result = + /^\[.+INFO:CONSOLE.+?]\ "(?.+)",\ source:\ [^"]+?\(\d+\)$/.exec( + line + ); + if (!result) { + continue; + } + const rawLogData = result.groups.raw_log_data; + process.stdout.write(`${rawLogData}${EOL}`); + } +} + +processChromiumDebugLog(); diff --git a/.github/actions/webgpu-validate-shader-key/validate-shader-key.js b/.github/actions/webgpu-validate-shader-key/validate-shader-key.js new file mode 100644 index 0000000000000..aae689c17552a --- /dev/null +++ b/.github/actions/webgpu-validate-shader-key/validate-shader-key.js @@ -0,0 +1,122 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +"use strict"; + +const { EOL } = require("os"); +const readline = require("readline"); + +// This script is used to parse the raw log data and check if there are inconsistent shader. +// When the shader key is the same, the shader code should be the same. + +const shaderMap = new Map(); + +const regexStartingProgram = + /onnxruntime::webgpu::WebGpuContext::Run.+Starting program \"(?.+)\"/; +const regexShaderStart = + /^===\ WebGPU\ Shader\ code\ \[.+?(Key=\"(?.+)\")?]\ Start\ ===$/; +const regexShaderEnd = + /^===\ WebGPU\ Shader\ code\ \[.+?(Key=\"(?.+)\")?]\ End\ ===$/; + +async function processVerboseLog() { + const rl = readline.createInterface({ + input: process.stdin, + crlfDelay: Infinity, + }); + + let lastProgramKey = null; + let currentShaderKey = null; + let currentShaderCode = null; + + for await (const line of rl) { + const startingProgram = regexStartingProgram.exec(line); + if (startingProgram) { + lastProgramKey = startingProgram.groups.key; + continue; + } + + const resultStart = regexShaderStart.exec(line); + if (resultStart) { + if (currentShaderKey) { + throw new Error( + `Found incomplete shader code for key "${currentShaderKey}".` + ); + } + + const key = resultStart.groups.key ?? lastProgramKey; + if (!key) { + throw new Error( + 'No shader key is found in the log. Please use debug build or enable verbose logging in session options in release build.' + ); + } + if (lastProgramKey && key !== lastProgramKey) { + throw new Error( + `Found incorrect shader key from log. Expected "${lastProgramKey}", but got "${key}".` + ); + } + currentShaderKey = key; + currentShaderCode = ""; + continue; + } + + const resultEnd = regexShaderEnd.exec(line); + if (resultEnd) { + if (!currentShaderKey) { + throw new Error( + `Found unexpected shader end for key "${resultEnd.groups.key}".` + ); + } + + const key = resultEnd.groups.key ?? lastProgramKey; + if (!key) { + throw new Error( + 'No shader key is found in the log. Please use debug build or enable verbose logging in session options in release build.' + ); + } + if (lastProgramKey && key !== lastProgramKey) { + throw new Error( + `Found incorrect shader key from log. Expected "${lastProgramKey}", but got "${key}".` + ); + } + + if (shaderMap.has(currentShaderKey)) { + if (shaderMap.get(currentShaderKey) !== currentShaderCode) { + throw new Error(`Found inconsistent shader code for key "${currentShaderKey}". +=== Previous Shader Start === +${shaderMap.get(currentShaderKey)} +=== Previous Shader End === + +=== Current Shader Start === +${currentShaderCode} +=== Current Shader End ===`); + } + } else { + shaderMap.set(currentShaderKey, currentShaderCode); + } + + currentShaderKey = null; + currentShaderCode = null; + continue; + } + + if (currentShaderKey) { + currentShaderCode += line + EOL; + } + } + + if (currentShaderKey) { + throw new Error( + `Found incomplete shader code for key "${currentShaderKey}".` + ); + } + + if (shaderMap.size === 0) { + throw new Error("No shader code found."); + } + + console.log( + `All shader code is consistent. Total ${shaderMap.size} shader keys found.` + ); +} + +processVerboseLog(); diff --git a/.github/labeler.yml b/.github/labeler.yml index c14e2a213bc60..1b5ae695e98a3 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -2,7 +2,6 @@ api:CSharp: '/(\bc\s*sharp\b|\bc#)/i' api:java: '/\bjava\b/i' api:javascript: '/\bjavascript\b/i' ep:ACL: '/\bacl\b/i' -ep:ArmNN: '/\barmnn\b/i' ep:CANN: '/\bcann\b/i' ep:CoreML: '/\bcore\s*ml\b/i' ep:DML: '/(\bdirect\s*ml\b|\bdml\b)/i' @@ -11,7 +10,6 @@ ep:oneDNN: '/\bone\s*dnn\b/i' ep:OpenVINO: '/\bopen\s*vino\b/i' ep:QNN: '/\bqnn\b/i' ep:RockchipNPU: '/\brockchip(?:npu)?\b/i' -ep:ROCm: '/\brocm\b/i' ep:SNPE: '/\bsnpe\b/i' ep:tvm: '/\btvm\b/i' ep:VitisAI: '/\bvitis(?:ai)?\b/i' diff --git a/.github/policies/updateStaleIssues.yml b/.github/policies/updateStaleIssues.yml new file mode 100644 index 0000000000000..573e1ff2aeaeb --- /dev/null +++ b/.github/policies/updateStaleIssues.yml @@ -0,0 +1,58 @@ +name: Update Stale Issues +description: Update stale issues +resource: repository +configuration: + resourceManagementConfiguration: + scheduledSearches: + - description: Apply stale label to open, unassigned issues that have not been updated in the last 30 days + frequencies: + - daily: + time: 15:00 + filters: + - isIssue + - isOpen + - isNotAssigned + - isNotLabeledWith: + label: contributions welcome + - isNotLabeledWith: + label: documentation + - isNotLabeledWith: + label: feature request + - isNotLabeledWith: + label: regression + - isNotLabeledWith: + label: no stale + - noActivitySince: + days: 30 + actions: + - addReply: + reply: "Applying stale label due to no activity in 30 days. Please react to the issue by assigning it or labeling it as 'contributions welcome', 'documentation', 'feature request', 'regression', or 'no stale'." + - addLabel: + label: stale + - description: Close open, unassigned issues labeled stale that have not been updated in the last 30 days + frequencies: + - daily: + time: 15:00 + filters: + - hasLabel: + label: stale + - isIssue + - isOpen + - isNotAssigned + - isNotLabeledWith: + label: no stale + - noActivitySince: + days: 30 + actions: + - addReply: + reply: "Closing issue due to no activity in 30 days" + - closeIssue + eventResponderTasks: + - description: Remove stale label if open stale issue is commented on + if: + - payloadType: Issue_Comment + - hasLabel: + label: stale + then: + - removeLabel: + label: stale diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml new file mode 100644 index 0000000000000..252ea7281d981 --- /dev/null +++ b/.github/workflows/android.yml @@ -0,0 +1,317 @@ +name: Android CI +# This workflow is used to build and test on Android Emulator on Linux + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +permissions: + contents: read + packages: write + attestations: write + id-token: write + +jobs: + AndroidBinarySizeCheckJob_MinimalBaseline: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=AndroidBinarySizeCheckJob_MinimalBaseline-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + env: + CCACHE_DIR: ~/.cache/ccache # explicitly set to prevent any fallback to `~/.ccache` + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: Setup Android NDK + uses: ./.github/actions/setup-android-ndk + with: + ndk-version: 28.0.13004108 + + - name: Get Docker Image using Action + uses: microsoft/onnxruntime-github-actions/build-docker-image@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + id: build_docker_image_step + with: + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimecpubuildcix64 + push: true + azure-container-registry-name: onnxruntimebuildcache + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Set variables from config file + id: set_vars + run: | + import json, os + + config_file_path = "tools/ci_build/github/linux/ort_minimal/build_check_binsize_config/android_minimal_baseline.config" + with open(config_file_path, mode="r") as config_file: + config = json.load(config_file) + + def set_var(name, value): + print(f"Setting variable: {name} = '{value}'") + # Use GITHUB_ENV for setting environment variables + with open(os.environ['GITHUB_ENV'], 'a') as f: + f.write(f"{name}={value}\n") + + set_var("BuildConfigType", config["type"]) + set_var("BuildConfigOs", config["os"]) + shell: python + working-directory: ${{ github.workspace }} + + # FUTURE WORK: ccache, vcpkg cache + - name: 1a. Build onnxruntime + run: | + set -e -x + BINARY_SIZE_THRESHOLD_ARGS="" + echo "Binary size threshold in bytes: 1436672" + BINARY_SIZE_THRESHOLD_ARGS="--threshold_size_in_bytes 1436672" + + # Ensure ANDROID_NDK_HOME is available and get its real path + if [ -z "$ANDROID_NDK_HOME" ]; then + echo "ANDROID_NDK_HOME is not set." + exit 1 + fi + NDK_HOME_REALPATH=$(realpath $ANDROID_NDK_HOME) + + # Ensure ANDROID_HOME is available + if [ -z "$ANDROID_HOME" ]; then + echo "ANDROID_HOME is not set. Using default /usr/local/lib/android/sdk" + export ANDROID_HOME=/usr/local/lib/android/sdk + fi + + docker run -e SYSTEM_COLLECTIONURI --rm \ + --volume ${{ github.workspace }}:/onnxruntime_src \ + --volume ${{ runner.temp }}:/build \ + --volume $ANDROID_HOME:/android_home \ + --volume $NDK_HOME_REALPATH:/ndk_home \ + -w /onnxruntime_src \ + -e ALLOW_RELEASED_ONNX_OPSET_ONLY=1 \ + -e NIGHTLY_BUILD=1 \ + -e BUILD_BUILDNUMBER=${{ github.run_number }} \ + -e BUILD_SOURCEVERSION=${{ github.sha }} \ + -e BUILD_ID=${{ github.run_id }} \ + -e BUILD_REASON=${{ github.event_name }} \ + -e BUILD_BRANCH=${{ github.ref }} \ + -e RUNNER_TEMP=/build \ + ${{ steps.build_docker_image_step.outputs.full-image-name }} \ + bash -c "python3 -m pip install -r /onnxruntime_src/tools/ci_build/requirements/pybind/requirements.txt && \ + python3 tools/ci_build/github/linux/ort_minimal/build_ort_and_check_binary_size.py \ + --build_dir /build/1a \ + ${BINARY_SIZE_THRESHOLD_ARGS} \ + tools/ci_build/github/linux/ort_minimal/build_check_binsize_config/android_minimal_baseline.config" + shell: bash + + android_nnapi_ep: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=android_nnapi_ep-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + env: + CCACHE_DIR: ~/.cache/ccache # explicitly set to prevent any fallback to `~/.ccache` + steps: + - uses: actions/checkout@v6 + + - name: Use jdk 17 + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + ccache-version: 4.13.1 + ccache-hash: 626407a9b81dd86f8ec9867bff396b32dd1f00344f5b323526579a64f6d4104927f83e8d7a05ad9806fd78f4491e0adb4cff73388000a62050cb1b00766214ee + vcpkg-version: '2025.08.27' + vcpkg-hash: '9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079' + cmake-version: '3.31.6' + cmake-hash: '42395e20b10a8e9ef3e33014f9a4eed08d46ab952e02d2c1bbc8f6133eca0d7719fb75680f9bbff6552f20fcd1b73d86860f7f39388d631f98fb6f622b37cf04' + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: Setup Android NDK + uses: ./.github/actions/setup-android-ndk + with: + ndk-version: 28.0.13004108 + + - name: Setup CCache + uses: actions/cache@v5 + with: + # Fully qualify by workflow. `actions/cache` does not isolate by workflow, unlike ADO cache actions. + key: ccache | android.yml | android_nnapi_ep + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | android.yml | android_nnapi_ep + path: ~/.cache/vcpkg + + - name: CCache reset stats + run: ccache --zero-stats + shell: bash + + - name: NNAPI EP, Build, Test on Android Emulator + run: >- + python3 tools/ci_build/build.py + --enable_lto + --android + --build_dir build_nnapi + --android_sdk_path "$ANDROID_HOME" + --android_ndk_path "$ANDROID_NDK_HOME" + --android_abi=x86_64 + --android_api=29 + --skip_submodule_sync + --parallel + --use_cache + --use_vcpkg + --use_vcpkg_ms_internal_asset_cache + --use_nnapi + --build_shared_lib + --cmake_generator=Ninja + --build_java + --update --build --test + shell: bash + + - name: Build Minimal ORT with NNAPI and run tests + run: + tools/ci_build/github/linux/ort_minimal/nnapi_minimal_build_minimal_ort_and_run_tests.sh + "$(pwd)" + shell: bash + + - name: CCache stats + run: ccache --show-stats -vv + shell: bash + + - name: Install psutil for emulator shutdown by run_android_emulator.py + if: always() + run: python3 -m pip install psutil + shell: bash + + - name: Stop Android Emulator + if: always() + run: | + env | grep ANDROID + if test -f ${{ github.workspace }}/emulator.pid; then + echo "Emulator PID:"`cat ${{ github.workspace }}/emulator.pid` + python3 tools/python/run_android_emulator.py \ + --android-sdk-root "${ANDROID_SDK_ROOT}" \ + --stop \ + --emulator-pid-file ${{ github.workspace }}/emulator.pid + rm ${{ github.workspace }}/emulator.pid + else + echo "Emulator PID file was expected to exist but does not." + fi + shell: bash + + android_cpu_ep: + name: Android CI Pipeline + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=android_cpu_ep-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + env: + CCACHE_DIR: ~/.cache/ccache # explicitly set to prevent any fallback to `~/.ccache` + steps: + - uses: actions/checkout@v6 + + - name: Use jdk 17 + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + ccache-version: 4.13.1 + ccache-hash: 626407a9b81dd86f8ec9867bff396b32dd1f00344f5b323526579a64f6d4104927f83e8d7a05ad9806fd78f4491e0adb4cff73388000a62050cb1b00766214ee + vcpkg-version: '2025.08.27' + vcpkg-hash: '9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079' + cmake-version: '3.31.6' + cmake-hash: '42395e20b10a8e9ef3e33014f9a4eed08d46ab952e02d2c1bbc8f6133eca0d7719fb75680f9bbff6552f20fcd1b73d86860f7f39388d631f98fb6f622b37cf04' + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: Setup Android NDK + uses: ./.github/actions/setup-android-ndk + with: + ndk-version: 28.0.13004108 + + - name: Setup CCache + uses: actions/cache@v5 + with: + # Fully qualify by workflow. `actions/cache` does not isolate by workflow, unlike ADO cache actions. + key: ccache | android.yml | android_cpu_ep + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | android.yml | android_cpu_ep + path: ~/.cache/vcpkg + + - name: CCache reset stats + run: ccache --zero-stats + shell: bash + + - name: CPU EP, Build and Test + run: >- + python3 tools/ci_build/build.py + --enable_lto + --android + --build_dir build + --android_sdk_path $ANDROID_HOME + --android_ndk_path $ANDROID_NDK_HOME + --android_abi=x86_64 + --android_api=30 + --skip_submodule_sync + --parallel + --use_cache + --use_vcpkg + --use_vcpkg_ms_internal_asset_cache + --cmake_generator=Ninja + --build_java + --update --build --test + shell: bash + + - name: CCache stats + run: ccache --show-stats -vv + shell: bash + + - name: Install psutil for emulator shutdown by run_android_emulator.py + if: always() + run: python3 -m pip install psutil + shell: bash + + - name: Stop Android Emulator + if: always() + run: | + if test -f ${{ github.workspace }}/emulator.pid; then + echo "Emulator PID:"`cat ${{ github.workspace }}/emulator.pid` + python3 tools/python/run_android_emulator.py \ + --android-sdk-root "${ANDROID_SDK_ROOT}" \ + --stop \ + --emulator-pid-file ${{ github.workspace }}/emulator.pid + rm ${{ github.workspace }}/emulator.pid + else + echo "Emulator PID file was expected to exist but does not." + fi + shell: bash diff --git a/.github/workflows/cffconvert.yml b/.github/workflows/cffconvert.yml index 0cbaf24059390..d02fbfa018473 100644 --- a/.github/workflows/cffconvert.yml +++ b/.github/workflows/cffconvert.yml @@ -4,14 +4,19 @@ on: push: paths: - CITATION.cff + workflow_dispatch: jobs: validate: name: "validate" - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=cffconvert-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] steps: - name: Check out a copy of the repository - uses: actions/checkout@v4 + uses: actions/checkout@v6 - name: Check whether the citation metadata from CITATION.cff is valid uses: citation-file-format/cffconvert-github-action@2.0.0 diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml index d1dc717c2a9c9..a41fd3c2163c9 100644 --- a/.github/workflows/codeql.yml +++ b/.github/workflows/codeql.yml @@ -8,21 +8,26 @@ name: "CodeQL" on: push: - branches: [ "main", nuget_pkg, rel-* ] + branches: ["main", nuget_pkg, rel-*] pull_request: # The branches below must be a subset of the branches above - branches: [ "main" ] + branches: ["main"] schedule: - cron: '41 13 * * 0' + workflow_dispatch: concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} cancel-in-progress: true jobs: analyze: name: Analyze - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=codeql-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}-${{ matrix.language}}" + ] permissions: actions: read contents: read @@ -31,44 +36,44 @@ jobs: strategy: fail-fast: false matrix: - language: [ 'java', 'javascript', 'python' ] + language: ['java', 'javascript', 'python'] # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support steps: - - name: Checkout repository - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v6 # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - languages: ${{ matrix.language }} + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} # If you wish to specify custom queries, you can do so here or in a config file. # By default, queries listed here will override any specified in a config file. # Prefix the list here with "+" to use these queries and those in the config file. - + # Details on CodeQL's query packs refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - queries: security-extended,security-and-quality + queries: security-extended,security-and-quality # Setup Java to use a version that is not too old for the project - - if: ${{ matrix.language == 'java' }} - name: Setup Java 11 - uses: actions/setup-java@v4 - with: - java-version: '11' - distribution: 'microsoft' + - if: ${{ matrix.language == 'java' }} + name: Setup Java 11 + uses: actions/setup-java@v5 + with: + java-version: '11' + distribution: 'microsoft' - - if: ${{ matrix.language == 'javascript' }} - uses: actions/setup-node@v4 - with: - node-version: 20 + - if: ${{ matrix.language == 'javascript' }} + uses: actions/setup-node@v6 + with: + node-version: 20 # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # If this step fails, then you should remove it and run the build manually (see below) - - if: ${{ matrix.language != 'cpp' }} - name: Autobuild - uses: github/codeql-action/autobuild@v3 + - if: ${{ matrix.language != 'cpp' }} + name: Autobuild + uses: github/codeql-action/autobuild@v3 - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 diff --git a/.github/workflows/generate-xcframework-maccatalyst.yml b/.github/workflows/generate-xcframework-maccatalyst.yml new file mode 100644 index 0000000000000..774dc977032b2 --- /dev/null +++ b/.github/workflows/generate-xcframework-maccatalyst.yml @@ -0,0 +1,110 @@ +name: "Build XCFramework for MacCatalyst" + +on: + workflow_dispatch: + push: + #workflow_dispatch: + # branches: [main, develop] + +env: + python_version: 3.11 + +jobs: + build_macabi_xcf: + runs-on: macos-14 + env: + xcode_version: 15 + steps: + - name: install Python 3.10 + uses: actions/setup-python@v5 + with: + python-version: ${{ env.python_version }} + + - name: check Xcode version and Python 3 + run: | + /usr/bin/xcodebuild -version + python3 --version + python --version + which python3 + + # - name: Use Xcode ${{ env.xcode_version }} + # shell: bash + # run: | + # XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ env.xcode_version }}.app/Contents/Developer" + # sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" + + - name: checkout repository + uses: actions/checkout@v4 + + # - name: install protoc + # run : | + # mkdir -p $HOME/Downloads + # cd $HOME/Downloads + # curl -LJO https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-osx-universal_binary.zip + # unzip protoc-21.12-osx-universal_binary.zip -d protoc-21.12-osx-universal_binary + # mv protoc-21.12-osx-universal_binary/bin/protoc /usr/local/bin/protoc-3.21.12.0 + # mv protoc-21.12-osx-universal_binary/include/* /usr/local/include/ + + - name: create directory to store the library + run: mkdir -p $HOME/onnxlibrary/macabi_release_v20230327_2320 + + # - name: create release build + # run: | + # # Since Python 3.12, distutils is removed + # # pip3 install setuptools + # export PYTHONPATH=${{ github.workspace }}/tools/python:$PYTHONPATH + # cd ${{ github.workspace }}/tools/python + # ls ${{ github.workspace }}/tools/python + # # pip install -r ${{ github.workspace }}/requirements-dev.txt + # # pip install -r ${{ github.workspace }}/tools/ci_build/requirements.txt + # #Deal with lSystem + # export SDKROOT=$(xcrun --sdk macosx --show-sdk-path) + # export LIBRARY_PATH="$LIBRARY_PATH:$SDKROOT/usr/lib" + # #Build command + # python tools/ci_build/github/apple/build_apple_framework.py --config Release --build_dir /Users/goodnotesci/onnxlibrary/ios_release_v20240405_onnx116 --include_ops_by_config tools/ci_build/github/apple/hws_mobile_package.required_operators.config tools/ci_build/github/apple/default_full_ios_framework_build_settings.json + + # python ${{ github.workspace }}/tools/ci_build/github/apple/build_apple_framework.py --config=Release --build_dir=$HOME/onnxlibrary/macabi_release_v20230327_2320 \ + # --include_ops_by_config=${{ github.workspace }}/tools/ci_build/github/apple/hws_mobile_package.required_operators.config \ + # --path_to_protoc_exe=/usr/local/bin/protoc-3.21.12.0 ${{ github.workspace }}/tools/ci_build/github/apple/hws_mobile_package.required_operators.config + + - name: create releae build + run: | + export PYTHONPATH=${{ github.workspace }}/tools/python:$PYTHONPATH + pip install -r ${{ github.workspace }}/requirements-dev.txt + python3 ${{ github.workspace }}/tools/ci_build/github/apple/build_apple_framework.py --config Release --build_dynamic_framework --build_dir=$HOME/onnxlibrary/macabi_release_v20230327_2320 \ + --include_ops_by_config=${{ github.workspace }}/tools/ci_build/github/apple/hws_mobile_package.required_operators.config \ + ${{ github.workspace }}/tools/ci_build/github/apple/default_full_ios_framework_build_settings.json + + # python ./tools/ci_build/build.py \ + # --build_dir $HOME/onnxlibrary/macabi_release_v20230327_2320 \ + # --update \ + # --build --parallel \ + # --test \ + # --build_shared_lib \ + # --build_objc \ + # --use_coreml \ + # --use_xnnpack \ + # --use_binskim_compliant_compile_flags \ + # --include_ops_by_config=${{ github.workspace }}/tools/ci_build/github/apple/default_full_macabi_framework_build_settings.json + + + - name: create release build 2 + run: | + python ./tools/ci_build/build.py \ + --build_dir $HOME/onnxlibrary/macabi_release_v20230327_2320 \ + --update \ + --build --parallel \ + --skip_tests \ + --build_apple_framework \ + --use_xcode \ + --use_coreml \ + --use_xnnpack \ + --use_binskim_compliant_compile_flags \ + --ios \ + --apple_deploy_target=16.0 \ + --apple_sysroot=iphonesimulator \ + --osx_arch=x86_64 \ + --cmake_extra_defines=onnxruntime_BUILD_UNIT_TESTS=OFF \ + --cmake_extra_defines=CMAKE_POLICY_VERSION_MINIMUM=3.5 \ + --include_ops_by_config=${{ github.workspace }}/tools/ci_build/github/apple/hws_mobile_package.required_operators.config + diff --git a/.github/workflows/gradle-wrapper-validation.yml b/.github/workflows/gradle-wrapper-validation.yml index cf3bc598d02bb..cadddd0d7653d 100644 --- a/.github/workflows/gradle-wrapper-validation.yml +++ b/.github/workflows/gradle-wrapper-validation.yml @@ -3,12 +3,24 @@ # This workflow was copied from the link above. name: "Validate Gradle Wrapper" -on: [push, pull_request] +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main, 'rel-*'] + workflow_dispatch: jobs: validation: name: "Validation" - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=gradle-wrapper-validation-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] steps: - - uses: actions/checkout@v4 - - uses: gradle/actions/wrapper-validation@v4 + - uses: actions/checkout@v6 + - uses: gradle/actions/wrapper-validation@v5 +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true diff --git a/.github/workflows/ios.yml b/.github/workflows/ios.yml new file mode 100644 index 0000000000000..18ffc4c88b1e7 --- /dev/null +++ b/.github/workflows/ios.yml @@ -0,0 +1,65 @@ +name: iOS_CI_on_Mac + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + iOS_CI_on_Mac: + runs-on: macos-14 + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.9 + with: + vcpkg-version: '2025.08.27' + vcpkg-hash: 9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079 + cmake-version: '3.31.8' + cmake-hash: 99cc9c63ae49f21253efb5921de2ba84ce136018abf08632c92c060ba91d552e0f6acc214e9ba8123dee0cf6d1cf089ca389e321879fd9d719a60d975bcffcc8 + add-cmake-to-path: 'true' + disable-terrapin: 'true' + - name: Use Xcode ${{ env.XCODE_VERSION }} + shell: bash + run: | + set -e -x + XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ env.XCODE_VERSION }}.app/Contents/Developer" + sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" + + - name: (CPU, CoreML, XNNPACK EPs) Build onnxruntime for iOS x86_64 and run tests using simulator + shell: bash + run: | + python3 ${{ github.workspace }}/tools/ci_build/build.py \ + --skip_submodule_sync \ + --build_dir ${{ github.workspace }}/iOS \ + --build_shared_lib \ + --use_coreml \ + --use_xnnpack \ + --ios \ + --apple_sysroot iphonesimulator \ + --osx_arch x86_64 \ + --apple_deploy_target=15.1 \ + --use_xcode \ + --config RelWithDebInfo \ + --build_apple_framework \ + --parallel \ + --use_binskim_compliant_compile_flags + env: + ORT_GET_SIMULATOR_DEVICE_INFO_REQUESTED_RUNTIME_VERSION: ${{ env.IOS_SIMULATOR_RUNTIME_VERSION }} + + timeout-minutes: 150 + env: + XCODE_VERSION: 15.3.0 + IOS_SIMULATOR_RUNTIME_VERSION: 17.4 diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml index 00960c848b107..3ede5919feedf 100644 --- a/.github/workflows/labeler.yml +++ b/.github/workflows/labeler.yml @@ -8,7 +8,11 @@ permissions: jobs: triage: - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=labeler-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] steps: - uses: github/issue-labeler@v3.4 with: diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 8d966d358de01..023a3ceb92126 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -6,9 +6,10 @@ on: - main - rel-* pull_request: + workflow_dispatch: concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name == 'workflow_dispatch' }} + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} cancel-in-progress: true jobs: @@ -16,7 +17,7 @@ jobs: name: Optional Lint runs-on: ubuntu-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: misspell # Check spellings as well uses: reviewdog/action-misspell@v1 with: @@ -26,7 +27,7 @@ jobs: level: info filter_mode: diff_context - name: shellcheck # Static check shell scripts - uses: reviewdog/action-shellcheck@v1 + uses: reviewdog/action-shellcheck@v1.31.0 with: github_token: ${{ secrets.github_token }} reporter: github-pr-check @@ -36,14 +37,18 @@ jobs: lint-python-format: # Required workflow name: Python format - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=lint-python-format-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] permissions: contents: read security-events: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: # Use the version configured in target-version of [tool.black] section in pyproject.toml. python-version: "3.10" @@ -86,7 +91,7 @@ jobs: name: Optional Lint C++ runs-on: ubuntu-latest steps: - - uses: actions/checkout@master + - uses: actions/checkout@v6 - name: Update PATH run: | echo "$HOME/.local/bin" >> "$GITHUB_PATH" @@ -108,32 +113,5 @@ jobs: github_token: ${{ secrets.github_token }} reporter: github-pr-check level: info - flags: --linelength=120 - --exclude=java/src/main/native/*.c - --exclude=onnxruntime/core/mlas/inc/* - --exclude=onnxruntime/core/mlas/lib/* - --exclude=onnxruntime/contrib_ops/cuda/bert/flash_attention/* - --exclude=build/Debug/* - --exclude=cmake/* - --exclude=csharp/test/* - --exclude=onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/GeneratedShaders/* - --exclude=orttraining/orttraining/test/* - --exclude=onnxruntime/test/* - --exclude=winml/* + flags: --linelength=120 --exclude=java/src/main/native/*.c --exclude=onnxruntime/core/mlas/inc/* --exclude=onnxruntime/core/mlas/lib/* --exclude=onnxruntime/contrib_ops/cuda/bert/flash_attention/* --exclude=build/Debug/* --exclude=cmake/* --exclude=csharp/test/* --exclude=onnxruntime/core/providers/dml/DmlExecutionProvider/src/Operators/GeneratedShaders/* --exclude=orttraining/orttraining/test/* --exclude=onnxruntime/test/* --exclude=winml/* filter: "-runtime/references" - - lint-js: - name: Lint JavaScript - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-node@v4 - with: - node-version: 20 - - uses: reviewdog/action-eslint@v1 - with: - reporter: github-pr-check - level: error - filter_mode: file - eslint_flags: "--ext .ts --ext .tsx" - workdir: "js/" diff --git a/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml b/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml new file mode 100644 index 0000000000000..57c70e97fc4bb --- /dev/null +++ b/.github/workflows/linux-wasm-ci-build-and-test-workflow.yml @@ -0,0 +1,211 @@ +name: "Linux WASM CI Reusable Workflow for build and test" +description: "This is a reusable workflow for Linux WASM CI pipelines to build and test" + +on: + workflow_call: + inputs: + job_name: # workflow-scope unique key + required: true + type: string + build_config: + required: true + type: string + extra_build_args: + required: false + type: string + default: "" + skip_publish: + required: false + type: boolean + default: false + use_vcpkg: + required: false + type: boolean + default: true + enable_wasm_threads: + required: false + type: boolean + default: true + build_jsep: + required: false + type: boolean + default: false + build_webgpu: + required: false + type: boolean + default: false + +jobs: + build-wasm: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-linux-large", + "JobId=build-wasm-${{inputs.job_name}}-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + env: + buildArch: x64 + common_build_args: >- + --parallel + --use_cache + ${{ inputs.use_vcpkg == true && '--use_vcpkg --use_vcpkg_ms_internal_asset_cache' || '' }} + --config ${{ inputs.build_config }} + --skip_submodule_sync + --build_wasm + --enable_wasm_simd + ${{ inputs.enable_wasm_threads == true && '--enable_wasm_threads' || '' }} + ${{ inputs.extra_build_args }} + reduced_size_build_args: >- + --disable_ml_ops + --disable_generation_ops + --disable_types string float4 float8 optional sparsetensor + --include_ops_by_config onnxruntime/wasm/reduced_types.config + --enable_reduced_operator_type_support + + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + submodules: recursive + + - name: Set up Node.js + uses: actions/setup-node@v6 + with: + node-version: "22" + + - name: Set up Python + uses: actions/setup-python@v6 + with: + python-version: "3.12" + architecture: ${{ env.buildArch }} + + - name: Install python dependencies + run: python -m pip install flatbuffers + + - name: Setup CCache + uses: actions/cache@v5 + with: + # Fully qualify by workflow. `actions/cache` does not isolate by workflow, unlike ADO cache actions. + key: ccache | web.yml | ${{ inputs.job_name }} + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | web.yml | ${{ inputs.job_name }} + path: ~/.cache/vcpkg + + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + ccache-version: 4.13.1 + ccache-hash: 626407a9b81dd86f8ec9867bff396b32dd1f00344f5b323526579a64f6d4104927f83e8d7a05ad9806fd78f4491e0adb4cff73388000a62050cb1b00766214ee + vcpkg-version: '2025.08.27' + vcpkg-hash: '9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079' + cmake-version: '3.31.6' + cmake-hash: '42395e20b10a8e9ef3e33014f9a4eed08d46ab952e02d2c1bbc8f6133eca0d7719fb75680f9bbff6552f20fcd1b73d86860f7f39388d631f98fb6f622b37cf04' + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: Build (simd + threads) + run: | + python ./tools/ci_build/build.py \ + ${{ env.common_build_args }} \ + --build_dir ${{ github.workspace }}/build/wasm_inferencing \ + ${{ inputs.build_config == 'Release' && '--enable_wasm_api_exception_catching' || '' }} \ + --skip_tests + working-directory: ${{ github.workspace }} + + - name: Build (simd + threads + JSEP) + if: ${{ inputs.build_jsep == true }} + run: | + python ./tools/ci_build/build.py \ + ${{ env.common_build_args }} \ + --build_dir ${{ github.workspace }}/build/wasm_inferencing_jsep \ + --use_jsep \ + --use_webnn \ + --target onnxruntime_webassembly \ + ${{ inputs.build_config == 'Release' && '--enable_wasm_api_exception_catching' || '' }} \ + --skip_tests + working-directory: ${{ github.workspace }} + + - name: Build (simd + threads + WebGPU experimental) + if: ${{ inputs.build_webgpu == true }} + run: | + python ./tools/ci_build/build.py \ + ${{ env.common_build_args }} \ + --build_dir ${{ github.workspace }}/build/wasm_inferencing_webgpu \ + --use_webgpu \ + --use_webnn \ + --target onnxruntime_webassembly \ + ${{ inputs.build_config == 'Release' && '--enable_wasm_api_exception_catching' || '' }} \ + ${{ env.reduced_size_build_args }} \ + --skip_tests + working-directory: ${{ github.workspace }} + + - name: Build (simd + threads + WebGPU experimental, JSPI) + if: ${{ inputs.build_webgpu == true }} + run: | + python ./tools/ci_build/build.py \ + ${{ env.common_build_args }} \ + --build_dir ${{ github.workspace }}/build/wasm_inferencing_webgpu_jspi \ + --use_webgpu \ + --use_webnn \ + --enable_wasm_jspi \ + --target onnxruntime_webassembly \ + ${{ env.reduced_size_build_args }} \ + --skip_tests + working-directory: ${{ github.workspace }} + + - name: Create Artifacts + if: ${{ inputs.skip_publish != true }} + run: | + mkdir -p ${{ github.workspace }}/artifacts/wasm/ + cp ${{ github.workspace }}/build/wasm_inferencing/${{ inputs.build_config }}/ort-wasm-simd-threaded.wasm ${{ github.workspace }}/artifacts/wasm/ + cp ${{ github.workspace }}/build/wasm_inferencing/${{ inputs.build_config }}/ort-wasm-simd-threaded.mjs ${{ github.workspace }}/artifacts/wasm/ + if [ -d ${{ github.workspace }}/build/wasm_inferencing_jsep ]; then + cp ${{ github.workspace }}/build/wasm_inferencing_jsep/${{ inputs.build_config }}/ort-wasm-simd-threaded.jsep.wasm ${{ github.workspace }}/artifacts/wasm/ + cp ${{ github.workspace }}/build/wasm_inferencing_jsep/${{ inputs.build_config }}/ort-wasm-simd-threaded.jsep.mjs ${{ github.workspace }}/artifacts/wasm/ + fi + if [ -d ${{ github.workspace }}/build/wasm_inferencing_webgpu ]; then + cp ${{ github.workspace }}/build/wasm_inferencing_webgpu/${{ inputs.build_config }}/ort-wasm-simd-threaded.asyncify.wasm ${{ github.workspace }}/artifacts/wasm/ + cp ${{ github.workspace }}/build/wasm_inferencing_webgpu/${{ inputs.build_config }}/ort-wasm-simd-threaded.asyncify.mjs ${{ github.workspace }}/artifacts/wasm/ + fi + if [ -d ${{ github.workspace }}/build/wasm_inferencing_webgpu_jspi ]; then + cp ${{ github.workspace }}/build/wasm_inferencing_webgpu_jspi/${{ inputs.build_config }}/ort-wasm-simd-threaded.jspi.wasm ${{ github.workspace }}/artifacts/wasm/ + cp ${{ github.workspace }}/build/wasm_inferencing_webgpu_jspi/${{ inputs.build_config }}/ort-wasm-simd-threaded.jspi.mjs ${{ github.workspace }}/artifacts/wasm/ + fi + + - name: Upload WASM artifacts + if: ${{ inputs.skip_publish != true }} + uses: actions/upload-artifact@v6 + with: + name: ${{ inputs.build_config }}_wasm + path: ${{ github.workspace }}/artifacts/wasm + + - name: Test (Node.js) (simd + threads) + # unit tests are currently only supported in Debug builds because they require exceptions, which are disabled in Release builds. + if: ${{ inputs.build_config == 'Debug' }} + run: | + python ./tools/ci_build/build.py \ + ${{ env.common_build_args }} \ + --build_dir ${{ github.workspace }}/build/wasm_inferencing \ + --test + working-directory: ${{ github.workspace }} + + - name: Test (browser) (simd + threads) + # unit tests are currently only supported in Debug builds because they require exceptions, which are disabled in Release builds. + if: ${{ inputs.build_config == 'Debug' }} + run: | + python ./tools/ci_build/build.py \ + ${{ env.common_build_args }} \ + --build_dir ${{ github.workspace }}/build/wasm_inferencing \ + --wasm_run_tests_in_browser \ + --targets onnxruntime_test_all onnxruntime_provider_test \ + --update --build --test + working-directory: ${{ github.workspace }} + + - name: Publish test results + if: ${{ always() && inputs.build_config == 'Debug' }} + uses: actions/upload-artifact@v6 + with: + name: test-results + path: ${{ github.workspace }}/build/**/*.results.xml diff --git a/.github/workflows/linux_ci.yml b/.github/workflows/linux_ci.yml new file mode 100644 index 0000000000000..8801042492ecb --- /dev/null +++ b/.github/workflows/linux_ci.yml @@ -0,0 +1,130 @@ +# This workflow builds and tests the ONNX Runtime for Linux on multiple architectures and configurations. +# It leverages a reusable workflow (`reusable_linux_build.yml`) to handle the core build and test logic +# within Docker containers, ensuring a consistent environment. +# +# The workflow consists of five parallel jobs targeting different combinations: +# - build-linux-x64-debug: Builds/tests Debug config on Linux x64 (AMD CPU pool), enables AddressSanitizer. +# - build-linux-x64-release: Builds/tests Release config on Linux x64 (AMD CPU pool), includes wheel/nuget/benchmark flags. +# - orttraining-linux-ci-pipeline: Builds/tests Release config with Training enabled (--enable_training) on Linux x64 (AMD CPU pool). +# - build-linux-arm64-debug: Builds/tests Debug config on Linux arm64 (ARM CPU pool); ASan is disabled due to excessive runtime. Includes wheel build. +# - build-linux-arm64-release: Builds/tests Release config on Linux arm64 (ARM CPU pool), includes wheel/benchmark flags. +# +# Each job calls the reusable workflow, passing specific parameters: +# - target architecture (x64 or arm64) +# - build configuration (Debug or Release) +# - runner pool name +# - path to the appropriate Dockerfile +# - Docker image name for caching/use +# - configuration-specific build flags (e.g., --enable_address_sanitizer, --enable_training, --build_wheel) + +name: Linux CI + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main, 'rel-*'] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +permissions: + contents: read + packages: write + attestations: write + id-token: write + +jobs: + # --- x64 Builds --- + build-linux-x64-debug: + name: Build Linux x64 Debug (ASan) + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" + build_config: Debug + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile + docker_image_repo: onnxruntimecpubuildcix64 + extra_build_flags: '--enable_address_sanitizer' + job_identifier: build-linux-x64-debug + # python_path_prefix: '' # Default empty string is fine, no prefix needed + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + build-linux-x64-release: + name: Build Linux x64 Release + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu + docker_image_repo: onnxruntimecpubuildpythonx64 + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --build_nuget --enable_transformers_tool_test --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' # $ needs escaping in single quotes + job_identifier: build-linux-x64-release + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + build-linux-x64-release-py314: + name: Build Linux x64 Release (Python 3.14) + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu + docker_image_repo: onnxruntimecpubuildpythonx64 + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --build_nuget --enable_transformers_tool_test --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON' + python_path_prefix: 'PATH=/opt/python/cp314-cp314/bin:$PATH' # $ needs escaping in single quotes + job_identifier: build-linux-x64-release-py314 + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + orttraining-linux-ci-pipeline: + name: Build Linux x64 Release with training + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cpu + docker_image_repo: onnxruntimecpubuildpythonx64 # Shares image with standard x64 release + extra_build_flags: '--enable_training --use_binskim_compliant_compile_flags --build_wheel --build_nuget --enable_transformers_tool_test --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' # $ needs escaping in single quotes + job_identifier: orttraining-linux-ci-pipeline + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # --- arm64 Builds --- + build-linux-arm64-debug: + name: Build Linux arm64 Debug + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-ARM-CPU" + build_config: Debug + architecture: arm64 + dockerfile_path: tools/ci_build/github/linux/docker/inference/aarch64/default/cpu/Dockerfile + docker_image_repo: onnxruntimecpubuildciaarch64 + # ASan disabled due to excessive runtime (>4hr). Includes wheel build for basic checks. + extra_build_flags: '--use_binskim_compliant_compile_flags --build_shared_lib --enable_arm_neon_nchwc' + job_identifier: build-linux-arm64-debug + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + build-linux-arm64-release: + name: Build Linux arm64 Release + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-ARM-CPU" + build_config: Release + architecture: arm64 + dockerfile_path: tools/ci_build/github/linux/docker/inference/aarch64/python/cpu/Dockerfile + docker_image_repo: onnxruntimecpubuildpythonaarch64 + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --cmake_extra_defines onnxruntime_BUILD_BENCHMARKS=ON' + python_path_prefix: 'PATH=/opt/python/cp314-cp314/bin:$PATH' # $ needs escaping in single quotes + job_identifier: build-linux-arm64-release + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/linux_cuda_ci.yml b/.github/workflows/linux_cuda_ci.yml new file mode 100644 index 0000000000000..cae7a84f49442 --- /dev/null +++ b/.github/workflows/linux_cuda_ci.yml @@ -0,0 +1,106 @@ +name: Linux CUDA CI + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main, 'rel-*'] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +permissions: + contents: read + packages: write + attestations: write + id-token: write + +jobs: + build-linux-cuda-x64-release: + name: Build Linux CUDA x64 Release + # This job runs on a CPU node using the reusable build workflow + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" # Build pool + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + docker_build_args: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_almalinux8_gcc14:20251017.1' + docker_image_repo: onnxruntimecuda12manylinuxbuild + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --parallel --nvcc_threads 1 --cuda_version=12.8 --cuda_home=/usr/local/cuda-12.8 --cudnn_home=/usr/local/cuda-12.8 --enable_cuda_profiling --build_java --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 onnxruntime_BUILD_UNIT_TESTS=ON onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' + run_tests: false # <<< Do not run tests in this job + upload_build_output: true # <<< Upload the build/Release directory + execution_providers: 'cuda' + job_identifier: build-linux-cuda-x64-release + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token for reusable workflow needs (e.g., docker build action) + + test-linux-cuda-x64-release: + name: Test Linux CUDA x64 Release + needs: build-linux-cuda-x64-release + runs-on: + - self-hosted + - "1ES.Pool=onnxruntime-github-linux-a10" + - "1ES.ImageOverride=onnxruntime-ubuntu2204-CUDA-A10-Test" + - "JobId=test-linux-cuda-x64-release-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + permissions: + contents: read + packages: read + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - uses: microsoft/onnxruntime-github-actions/build-docker-image@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + id: build_docker_image_step + with: + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimecuda12manylinuxbuild + build-args: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_almalinux8_gcc14:20251017.1' + push: true + azure-container-registry-name: onnxruntimebuildcache + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token to action + + # --- Download Build Artifact to Runner Temp Directory --- + - name: Download Build Artifact + uses: actions/download-artifact@v7 + with: + name: build-output-x64-Release # Must match the upload name + path: ${{ runner.temp }}/Release # Download contents into temp dir structure + + # --- Restore Permissions in the Temp Directory --- + - name: Restore Executable Permissions + if: success() # Only run if download succeeded + working-directory: ${{ runner.temp }}/Release + run: | + if [ -f perms.txt ]; then + echo "Restoring executable permissions in ${{ runner.temp }}/Release ..." + while IFS= read -r file; do + # Check relative path existence within the current directory + if [ -f "$file" ]; then + chmod +x "$file" + else + echo "Warning: File '$file' listed in perms.txt not found." + fi + done < perms.txt + echo "Permissions restored." + else + echo "Warning: perms.txt not found in artifact." + fi + + # --- Run Tests using the downloaded build --- + # The run-build-script-in-docker action mounts ${{ runner.temp }} to /onnxruntime_src/build + # So build.py --build_dir build/Release inside the container correctly finds the artifacts. + - name: Test ONNX Runtime + id: test_step + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: Release + mode: 'test' # Set mode to test + execution_providers: 'cuda' + extra_build_flags: '--use_binskim_compliant_compile_flags --cuda_version=12.8 --cuda_home=/usr/local/cuda-12.8 --cudnn_home=/usr/local/cuda-12.8 --enable_cuda_profiling --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 onnxruntime_BUILD_UNIT_TESTS=ON onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' diff --git a/.github/workflows/linux_cuda_plugin_ci.yml b/.github/workflows/linux_cuda_plugin_ci.yml new file mode 100644 index 0000000000000..3b532c486cdfc --- /dev/null +++ b/.github/workflows/linux_cuda_plugin_ci.yml @@ -0,0 +1,127 @@ +name: CUDA Plugin Linux CI + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main, 'rel-*'] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +permissions: + contents: read + packages: write + attestations: write + id-token: write + +jobs: + build-linux-cuda-plugin-x64-release: + name: Build Linux CUDA Plugin EP x64 Release + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + docker_build_args: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_almalinux8_gcc14:20251017.1' + docker_image_repo: onnxruntimecuda12manylinuxbuild + extra_build_flags: >- + --use_binskim_compliant_compile_flags + --build_wheel + --parallel + --nvcc_threads 1 + --cuda_version=12.8 + --cuda_home=/usr/local/cuda-12.8 + --cudnn_home=/usr/local/cuda-12.8 + --enable_cuda_profiling + --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 + --cmake_extra_defines onnxruntime_BUILD_CUDA_EP_AS_PLUGIN=ON + python_path_prefix: 'PATH=/opt/python/cp312-cp312/bin:$PATH' + run_tests: false + upload_build_output: true + execution_providers: 'cuda' + job_identifier: build-linux-cuda-plugin-x64-release + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + test-linux-cuda-plugin-x64-release: + name: Test Linux CUDA Plugin EP x64 Release + needs: build-linux-cuda-plugin-x64-release + runs-on: + - self-hosted + - "1ES.Pool=onnxruntime-github-linux-a10" + - "JobId=test-linux-cuda-plugin-x64-release-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + permissions: + contents: read + packages: read + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - uses: microsoft/onnxruntime-github-actions/build-docker-image@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + id: build_docker_image_step + with: + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimecuda12manylinuxbuild + build-args: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_almalinux8_gcc14:20251017.1' + push: true + azure-container-registry-name: onnxruntimebuildcache + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + # --- Download Build Artifact to Runner Temp Directory --- + - name: Download Build Artifact + uses: actions/download-artifact@v7 + with: + name: build-output-x64-Release + path: ${{ runner.temp }}/Release + + # --- Restore Permissions in the Temp Directory --- + - name: Restore Executable Permissions + if: success() + working-directory: ${{ runner.temp }}/Release + run: | + if [ -f perms.txt ]; then + echo "Restoring executable permissions in ${{ runner.temp }}/Release ..." + while IFS= read -r file; do + if [ -f "$file" ]; then + chmod +x "$file" + else + echo "Warning: File '$file' listed in perms.txt not found." + fi + done < perms.txt + echo "Permissions restored." + else + echo "Warning: perms.txt not found in artifact." + fi + + # --- Install the ORT wheel and run CUDA plugin EP tests --- + - name: Run CUDA Plugin EP Python Tests + run: | + docker run --rm --gpus all \ + -v ${{ github.workspace }}:/onnxruntime_src \ + -v ${{ runner.temp }}/Release:/build/Release \ + -e NVIDIA_VISIBLE_DEVICES=all \ + ${{ steps.build_docker_image_step.outputs.full-image-name }} \ + bash -c " + set -ex + export PATH=/opt/python/cp312-cp312/bin:\$PATH + + # Install the ORT wheel + python -m pip install /build/Release/Release/dist/onnxruntime*.whl + + # Install test dependencies + python -m pip install numpy onnx + python -m pip install torch --index-url https://download.pytorch.org/whl/cpu + + # Set plugin path and run tests + export ORT_CUDA_PLUGIN_PATH=/build/Release/Release/libonnxruntime_providers_cuda_plugin.so + echo \"ORT_CUDA_PLUGIN_PATH=\$ORT_CUDA_PLUGIN_PATH\" + ls -la \$ORT_CUDA_PLUGIN_PATH + + cd /onnxruntime_src/onnxruntime/test/python/transformers + python test_cuda_plugin_ep.py + " diff --git a/.github/workflows/linux_minimal_build.yml b/.github/workflows/linux_minimal_build.yml new file mode 100644 index 0000000000000..d2d31cb5d77e1 --- /dev/null +++ b/.github/workflows/linux_minimal_build.yml @@ -0,0 +1,783 @@ +name: Linux CPU Minimal Build E2E + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +env: + BUILD_SOURCES_DIRECTORY: ${{ github.workspace }} + +jobs: + # Job 1: Build full onnxruntime and generate ORT format test files + build_full_ort: + name: 1. Build Full ORT and Generate ORT Files + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=build_full_ort-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + permissions: + contents: read + packages: write + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - uses: actions/setup-node@v6 + with: + node-version: 20 + + - name: Setup CCache + uses: actions/cache@v5 + with: + # Fully qualify by workflow. `actions/cache` does not isolate by workflow, unlike ADO cache actions. + key: ccache | linux_minimal_build.yml | build_full_ort + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + # ostensibly should be able to use the same cache for most of these, but in practice the hash does not match. + key: vcpkg-cache | linux_minimal_build.yml | build_full_ort + path: ~/.cache/vcpkg + + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + ccache-version: 4.13.1 + ccache-hash: 626407a9b81dd86f8ec9867bff396b32dd1f00344f5b323526579a64f6d4104927f83e8d7a05ad9806fd78f4491e0adb4cff73388000a62050cb1b00766214ee + vcpkg-version: '2025.08.27' + vcpkg-hash: '9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079' + cmake-version: '3.31.6' + cmake-hash: '42395e20b10a8e9ef3e33014f9a4eed08d46ab952e02d2c1bbc8f6133eca0d7719fb75680f9bbff6552f20fcd1b73d86860f7f39388d631f98fb6f622b37cf04' + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: Build Full ORT and Prepare Test Files + uses: microsoft/onnxruntime-github-actions/build-and-prep-ort-files@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + + - name: Upload Test Data Artifact + uses: actions/upload-artifact@v6 + with: + name: test_data + path: ${{ runner.temp }}/minimal_build_test_data/ + if-no-files-found: error # Fail if test data wasn't generated + + # Job 2: Build minimal onnxruntime [exceptions DISABLED, type reduction DISABLED, training ops ENABLED] + build_minimal_exceptions_disabled: + name: 2. Build Minimal (Exceptions Disabled) + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=build_minimal_exceptions_disabled-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + permissions: # Permissions needed for build-docker-image + contents: read + packages: write + id-token: write # If using OIDC for ACR login + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + - uses: actions/setup-node@v6 + with: + node-version: 20 + + - name: Setup CCache + uses: actions/cache@v5 + with: + key: ccache | linux_minimal_build.yml | build_minimal_exceptions_disabled + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | linux_minimal_build.yml | build_minimal_exceptions_disabled + path: ~/.cache/vcpkg + + - name: Get Docker Image using Action + uses: microsoft/onnxruntime-github-actions/build-docker-image@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + id: build_docker_image_step + with: + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimecpubuildcix64 + push: true + azure-container-registry-name: onnxruntimebuildcache + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Run Build 2 (Update) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: Debug # From original --config Debug + mode: 'update' # CMake configure step + extra_build_flags: >- + --cmake_generator Ninja + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --skip_tests + --minimal_build + --disable_exceptions + --enable_training_ops + + - name: Run Build 2 (Build) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: Debug # From original --config Debug + mode: 'build' # Actual build step + extra_build_flags: >- + --cmake_generator Ninja + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --skip_tests + --minimal_build + --disable_exceptions + --enable_training_ops + + # Job 3a: Build minimal onnxruntime [exceptions ENABLED, type reduction DISABLED, custom ops ENABLED] and run tests + build_minimal_custom_ops: + name: 3a. Build Minimal (Custom Ops) + needs: build_full_ort # Depends on Job 1 for test data + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=build_minimal_custom_ops-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + permissions: # Permissions needed for build-docker-image + contents: read + packages: write + id-token: write # If using OIDC for ACR login + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + - uses: actions/setup-node@v6 + with: + node-version: 20 + + - name: Setup CCache + uses: actions/cache@v5 + with: + key: ccache | linux_minimal_build.yml | build_minimal_custom_ops + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | linux_minimal_build.yml | build_minimal_custom_ops + path: ~/.cache/vcpkg + + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + ccache-version: 4.13.1 + ccache-hash: 626407a9b81dd86f8ec9867bff396b32dd1f00344f5b323526579a64f6d4104927f83e8d7a05ad9806fd78f4491e0adb4cff73388000a62050cb1b00766214ee + vcpkg-version: '2025.08.27' + vcpkg-hash: '9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079' + cmake-version: '3.31.6' + cmake-hash: '42395e20b10a8e9ef3e33014f9a4eed08d46ab952e02d2c1bbc8f6133eca0d7719fb75680f9bbff6552f20fcd1b73d86860f7f39388d631f98fb6f622b37cf04' + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: Build Full ORT and Prepare Test Files + uses: microsoft/onnxruntime-github-actions/build-minimal-ort-and-run-tests@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + reduced-ops-config-file: required_ops.ort_models.config + enable-custom-ops: 'true' + binary-size-report-name-prefix: "3a" + + # Job 3b: Build minimal onnxruntime [exceptions ENABLED, type reduction ENABLED] and run tests + build_minimal_type_reduction: + name: 3b. Build Minimal (Type Reduction) + needs: build_full_ort # Depends on Job 1 for test data + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=build_minimal_type_reduction-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + permissions: # Permissions needed for build-docker-image + contents: read + packages: write + id-token: write # If using OIDC for ACR login + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + - uses: actions/setup-node@v6 + with: + node-version: 20 + + - name: Setup CCache + uses: actions/cache@v5 + with: + key: ccache | linux_minimal_build.yml | build_minimal_type_reduction + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | linux_minimal_build.yml | build_minimal_type_reduction + path: ~/.cache/vcpkg + + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + ccache-version: 4.13.1 + ccache-hash: 626407a9b81dd86f8ec9867bff396b32dd1f00344f5b323526579a64f6d4104927f83e8d7a05ad9806fd78f4491e0adb4cff73388000a62050cb1b00766214ee + vcpkg-version: '2025.08.27' + vcpkg-hash: '9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079' + cmake-version: '3.31.6' + cmake-hash: '42395e20b10a8e9ef3e33014f9a4eed08d46ab952e02d2c1bbc8f6133eca0d7719fb75680f9bbff6552f20fcd1b73d86860f7f39388d631f98fb6f622b37cf04' + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: Build Full ORT and Prepare Test Files + uses: microsoft/onnxruntime-github-actions/build-minimal-ort-and-run-tests@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + reduced-ops-config-file: required_ops_and_types.ort_models.config + enable-type-reduction: 'true' + binary-size-report-name-prefix: "3b" + + # Job 4: Build minimal onnxruntime [exceptions ENABLED, type reduction ENABLED (globally allowed types)] and run tests + build_minimal_globally_allowed_types: + name: 4. Build Minimal (Globally Allowed Types) + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=build_minimal_globally_allowed_types-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + permissions: # Permissions needed for build-docker-image + contents: read + packages: write + id-token: write # If using OIDC for ACR login + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + - uses: actions/setup-node@v6 + with: + node-version: 20 + + - name: Setup CCache + uses: actions/cache@v5 + with: + key: ccache | linux_minimal_build.yml | build_minimal_globally_allowed_types + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | linux_minimal_build.yml | build_minimal_globally_allowed_types + path: ~/.cache/vcpkg + + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + ccache-version: 4.13.1 + ccache-hash: 626407a9b81dd86f8ec9867bff396b32dd1f00344f5b323526579a64f6d4104927f83e8d7a05ad9806fd78f4491e0adb4cff73388000a62050cb1b00766214ee + vcpkg-version: '2025.08.27' + vcpkg-hash: '9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079' + cmake-version: '3.31.6' + cmake-hash: '42395e20b10a8e9ef3e33014f9a4eed08d46ab952e02d2c1bbc8f6133eca0d7719fb75680f9bbff6552f20fcd1b73d86860f7f39388d631f98fb6f622b37cf04' + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: Build Full ORT and Prepare Test Files + uses: microsoft/onnxruntime-github-actions/build-minimal-ort-and-run-tests@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + globally_allowed_types: 'bool,float,int8_t,uint8_t' + enable-type-reduction: 'true' + skip-model-tests: 'true' + binary-size-report-name-prefix: "4" + + # Job 5: Build extended minimal onnxruntime and run tests + build_extended_minimal: + name: 5. Build Extended Minimal + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=build_extended_minimal-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + permissions: # Permissions needed for build-docker-image + contents: read + packages: write + id-token: write # If using OIDC for ACR login + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + - uses: actions/setup-node@v6 + with: + node-version: 20 + + - name: Setup CCache + uses: actions/cache@v5 + with: + key: ccache | linux_minimal_build.yml | build_extended_minimal + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | linux_minimal_build.yml | build_extended_minimal + path: ~/.cache/vcpkg + + - name: Get Docker Image using Action + uses: microsoft/onnxruntime-github-actions/build-docker-image@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + id: build_docker_image_step + with: + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimecpubuildcix64 + push: true + azure-container-registry-name: onnxruntimebuildcache + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + + - name: Run Build 5 (Update) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: Debug + mode: 'update' + extra_build_flags: >- + --cmake_generator Ninja + --build_shared_lib + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --minimal_build extended + + - name: Run Build 5 (Build) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: Debug + mode: 'build' + extra_build_flags: >- + --cmake_generator Ninja + --build_shared_lib + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --minimal_build extended + + - name: Run Build 5 (Test) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: Debug + mode: 'test' + extra_build_flags: >- + --cmake_generator Ninja + --build_shared_lib + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --minimal_build extended + + # Job 6a: Regular build with python and all optional features disabled. + build_regular_no_optional: + name: 6a. Build Regular (No Optional Features) + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=build_regular_no_optional-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + permissions: # Permissions needed for build-docker-image + contents: read + packages: write + id-token: write # If using OIDC for ACR login + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: Get Docker Image using Action + uses: microsoft/onnxruntime-github-actions/build-docker-image@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + id: build_docker_image_step + with: + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimecpubuildcix64 + push: true + azure-container-registry-name: onnxruntimebuildcache + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: gen config + shell: bash + run: | + mkdir -p ${{ runner.temp }}/.test_data + touch ${{ runner.temp }}/.test_data/include_no_operators.config + + - name: Setup CCache + uses: actions/cache@v5 + with: + key: ccache | linux_minimal_build.yml | build_regular_no_optional + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | linux_minimal_build.yml | build_regular_no_optional + path: ~/.cache/vcpkg + + - name: Run Build 6a (Update) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: MinSizeRel + mode: 'update' + extra_build_flags: >- + --cmake_generator Ninja + --build_wheel + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --disable_ml_ops + --disable_types string sparsetensor float4 float8 optional + --include_ops_by_config /onnxruntime_src/build/.test_data/include_no_operators.config + --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF + + - name: Run Build 6a (Build) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: MinSizeRel + mode: 'build' + extra_build_flags: >- + --cmake_generator Ninja + --build_wheel + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --disable_ml_ops + --disable_types string sparsetensor float4 float8 optional + --include_ops_by_config /onnxruntime_src/build/.test_data/include_no_operators.config + --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF + + - name: Run Build 6a (Test) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: MinSizeRel + mode: 'test' + extra_build_flags: >- + --cmake_generator Ninja + --build_wheel + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --disable_ml_ops + --disable_types string sparsetensor float4 float8 optional + --include_ops_by_config /onnxruntime_src/build/.test_data/include_no_operators.config + --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF + + # Job 6b: Minimal build with all optional features disabled. + build_minimal_no_optional: + name: 6b. Build Minimal (No Optional Features) + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=build_minimal_no_optional-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + permissions: # Permissions needed for build-docker-image + contents: read + packages: write + id-token: write # If using OIDC for ACR login + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: gen config + shell: bash + run: | + mkdir -p ${{ runner.temp }}/.test_data + touch ${{ runner.temp }}/.test_data/include_no_operators.config + + - name: Get Docker Image using Action + uses: microsoft/onnxruntime-github-actions/build-docker-image@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + id: build_docker_image_step + with: + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimecpubuildcix64 + push: true + azure-container-registry-name: onnxruntimebuildcache + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup CCache + uses: actions/cache@v5 + with: + key: ccache | linux_minimal_build.yml | build_minimal_no_optional + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | linux_minimal_build.yml | build_minimal_no_optional + path: ~/.cache/vcpkg + + - name: Run Build 6b (Update) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: MinSizeRel # From original --config MinSizeRel + mode: 'update' + extra_build_flags: >- + --cmake_generator Ninja + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --minimal_build + --disable_exceptions + --disable_ml_ops + --skip_tests + --enable_reduced_operator_type_support + --disable_types string sparsetensor optional float4 float8 + --include_ops_by_config /onnxruntime_src/build/.test_data/include_no_operators.config + --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF + + - name: Run Build 6b (Build) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: MinSizeRel # From original --config MinSizeRel + mode: 'build' + extra_build_flags: >- + --cmake_generator Ninja + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --minimal_build + --disable_exceptions + --disable_ml_ops + --skip_tests + --enable_reduced_operator_type_support + --disable_types string sparsetensor optional float4 float8 + --include_ops_by_config /onnxruntime_src/build/.test_data/include_no_operators.config + --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF + + # Job 6c: Extended minimal build with all optional features disabled. + build_extended_minimal_no_optional: + name: 6c. Build Extended Minimal (No Optional Features) + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=build_extended_minimal_no_optional-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + permissions: # Permissions needed for build-docker-image + contents: read + packages: write + id-token: write # If using OIDC for ACR login + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: gen config + shell: bash + run: | + mkdir -p ${{ runner.temp }}/.test_data + touch ${{ runner.temp }}/.test_data/include_no_operators.config + + - name: Get Docker Image using Action + uses: microsoft/onnxruntime-github-actions/build-docker-image@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + id: build_docker_image_step + with: + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimecpubuildcix64 + push: true + azure-container-registry-name: onnxruntimebuildcache + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: gen config + shell: bash + run: | + mkdir -p ${{ runner.temp }}/.test_data + touch ${{ runner.temp }}/.test_data/include_no_operators.config + + - name: Setup CCache + uses: actions/cache@v5 + with: + key: ccache | linux_minimal_build.yml | build_extended_minimal_no_optional + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | linux_minimal_build.yml | build_extended_minimal_no_optional + path: ~/.cache/vcpkg + + - name: Run Build 6c (Update) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: MinSizeRel # From original --config MinSizeRel + mode: 'update' + extra_build_flags: >- + --cmake_generator Ninja + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --minimal_build extended + --disable_exceptions + --disable_ml_ops + --skip_tests + --enable_reduced_operator_type_support + --disable_types string sparsetensor optional float4 float8 + --include_ops_by_config /onnxruntime_src/build/.test_data/include_no_operators.config + --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF + + - name: Run Build 6c (Build) + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: MinSizeRel # From original --config MinSizeRel + mode: 'build' + extra_build_flags: >- + --cmake_generator Ninja + --parallel + --use_binskim_compliant_compile_flags + --use_cache + --minimal_build extended + --disable_exceptions + --disable_ml_ops + --skip_tests + --enable_reduced_operator_type_support + --disable_types string sparsetensor optional float4 float8 + --include_ops_by_config /onnxruntime_src/build/.test_data/include_no_operators.config + --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF + + # Job 7: Extended minimal build with NNAPI EP for Android(arm64-v8a) and skip tests. + # NOTE: Keeping this as direct docker run due to custom volume mounts needed for Android SDK/NDK + build_extended_minimal_android: + name: 7. Build Extended Minimal (Android NNAPI) + needs: build_full_ort # Depends on Job 1 for test data + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=build_extended_minimal_android-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + permissions: # Permissions needed for build-docker-image + contents: read + packages: write + id-token: write # If using OIDC for ACR login + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + - uses: actions/setup-node@v6 + with: + node-version: 20 + - name: Download Test Data Artifact + uses: actions/download-artifact@v7 + with: + name: test_data + path: ${{ runner.temp }}/.test_data/ + + - name: Get Docker Image using Action + uses: microsoft/onnxruntime-github-actions/build-docker-image@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + id: build_docker_image_step + with: + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/inference/x86_64/default/cpu/Dockerfile + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimecpubuildcix64 + push: true + azure-container-registry-name: onnxruntimebuildcache + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - name: Setup Android NDK + uses: ./.github/actions/setup-android-ndk + with: + ndk-version: 28.0.13004108 + # Use default android-sdk-root if not specified + + - name: Setup CCache + uses: actions/cache@v5 + with: + key: ccache | linux_minimal_build.yml | build_extended_minimal_android + path: ~/.cache/ccache + + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: vcpkg-cache | linux_minimal_build.yml | build_extended_minimal_android + path: ~/.cache/vcpkg + + - name: Run Build 7 (Using docker run) + shell: bash + run: | + # Create the target dir for build output inside the runner's temp dir first + mkdir -p ${{ runner.temp }}/7 + + # Ensure ANDROID_NDK_HOME is available and get its real path + if [ -z "$ANDROID_NDK_HOME" ]; then + echo "ANDROID_NDK_HOME is not set." + exit 1 + fi + NDK_HOME_REALPATH=$(realpath $ANDROID_NDK_HOME) + + # Ensure ANDROID_HOME is available + if [ -z "$ANDROID_HOME" ]; then + echo "ANDROID_HOME is not set. Using default /usr/local/lib/android/sdk" + export ANDROID_HOME=/usr/local/lib/android/sdk + fi + + # mount `~/.cache` inside docker. assume `onnxruntimedev` is the container user (should match the docker-file specified earlier) + mkdir -p ~/.cache/vcpkg + + docker run --rm \ + --volume ~/.cache:/home/onnxruntimedev/.cache \ + --volume ${{ env.BUILD_SOURCES_DIRECTORY }}:/onnxruntime_src \ + --volume ${{ runner.temp }}:/build \ + --volume $ANDROID_HOME:/android_home \ + --volume $NDK_HOME_REALPATH:/ndk_home \ + -e ALLOW_RELEASED_ONNX_OPSET_ONLY=1 \ + -e NIGHTLY_BUILD=1 -e RUNNER_TEMP=/build \ + ${{ steps.build_docker_image_step.outputs.full-image-name }} \ + bash -c "python3 -m pip install -r /onnxruntime_src/tools/ci_build/requirements/pybind/requirements.txt \ + && python3 /onnxruntime_src/tools/ci_build/build.py \ + --build_dir /build/7 \ + --cmake_generator Ninja \ + --config MinSizeRel \ + --skip_submodule_sync \ + --parallel \ + --use_binskim_compliant_compile_flags \ + --use_cache \ + --android \ + --android_sdk_path /android_home \ + --android_ndk_path /ndk_home \ + --android_abi=arm64-v8a \ + --android_api=29 \ + --use_nnapi \ + --minimal_build extended \ + --build_shared_lib \ + --disable_ml_ops \ + --disable_exceptions \ + --skip_tests" + working-directory: ${{ env.BUILD_SOURCES_DIRECTORY }} diff --git a/.github/workflows/linux_openvino_ci.yml b/.github/workflows/linux_openvino_ci.yml new file mode 100644 index 0000000000000..e04bd6fd7d7af --- /dev/null +++ b/.github/workflows/linux_openvino_ci.yml @@ -0,0 +1,46 @@ +name: Linux OpenVINO CI + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main, 'rel-*'] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +permissions: + contents: read + packages: write # Needed if the reusable workflow pushes images + attestations: write # Optional: for artifact attestations if enabled + id-token: write # Optional: may be needed for OIDC authentication (e.g., ACR) + +jobs: + build_test_openvino: + name: Build and Test OpenVINO EP (AlamLinux8, Py3.12) + # Use the reusable workflow as the other Linux CI pipelines + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" + build_config: Release + # Architecture: OpenVino only supports Intel X64 + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/inference/x86_64/python/openvino/Dockerfile + docker_image_repo: onnxruntimeopenvino + + execution_providers: 'openvino' + + extra_build_flags: '--use_openvino CPU --enable_generic_interface --build_shared_lib' + + # Python Path Prefix: Set the correct Python 3.12 path inside the manylinux container + python_path_prefix: 'PATH=/opt/python/cp312-cp312/bin:$PATH' + + run_tests: true + upload_build_output: false + job_identifier: build_test_openvino + + # Secrets: Pass the necessary GitHub token + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/linux_tensorrt_ci.yml b/.github/workflows/linux_tensorrt_ci.yml new file mode 100644 index 0000000000000..263d9a98f0bb6 --- /dev/null +++ b/.github/workflows/linux_tensorrt_ci.yml @@ -0,0 +1,128 @@ +name: Linux TensorRT CI + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main, 'rel-*'] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +permissions: + contents: read + packages: write + attestations: write + id-token: write + +jobs: + build-linux-TensorRT-x64-release: + name: Build Linux TensorRT x64 Release + # This job runs on a CPU node using the reusable build workflow + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" # Build pool + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + docker_build_args: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_almalinux8_gcc14:20251017.1 --build-arg TRT_VERSION=10.14.1.48-1.cuda12.9 --network=host' + docker_image_repo: onnxruntimetensorrt86gpubuild + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --cuda_version=12.8 --cuda_home=/usr/local/cuda-12.8 --cudnn_home=/usr/local/cuda-12.8 --use_tensorrt --tensorrt_home /usr --build_java --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 onnxruntime_BUILD_UNIT_TESTS=ON onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' + run_tests: false # <<< Do not run tests in this job + upload_build_output: true # <<< Upload the build/Release directory + execution_providers: 'cuda tensorrt' + job_identifier: build-linux-TensorRT-x64-release + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token for reusable workflow needs (e.g., docker build action) + + build-linux-TensorRT-CUDA-Minimal-x64-release: + name: Build Linux TensorRT CUDA Minimal x64 Release + # Build-only job for CUDA minimal build (no tests, no unit tests) + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + docker_build_args: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_almalinux8_gcc14:20251017.1 --build-arg TRT_VERSION=10.14.1.48-1.cuda12.9 --network=host' + docker_image_repo: onnxruntimetensorrt86gpubuild + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --cuda_version=12.8 --cuda_home=/usr/local/cuda-12.8 --cudnn_home=/usr/local/cuda-12.8 --use_tensorrt --tensorrt_home /usr --build_java --enable_cuda_minimal_build --disable_generation_ops --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 onnxruntime_BUILD_UNIT_TESTS=OFF' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' + run_tests: false + upload_build_output: false + execution_providers: 'cuda tensorrt' + job_identifier: build-linux-TensorRT-CUDA-Minimal-x64-release + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + test-linux-TensorRT-x64-release: + name: Test Linux TensorRT x64 Release + needs: build-linux-TensorRT-x64-release + runs-on: + - self-hosted + - "1ES.Pool=onnxruntime-github-linux-a10" + - "1ES.ImageOverride=onnxruntime-ubuntu2204-CUDA-A10-Test" + - "JobId=test-linux-TensorRT-x64-release-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + permissions: + contents: read + packages: read + steps: + - name: Checkout code + uses: actions/checkout@v6 + + # --- Build the Docker image needed for testing --- + - name: Build Docker Image for Testing + uses: microsoft/onnxruntime-github-actions/build-docker-image@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + id: build_docker_image_step + with: + dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_cuda + image-name: ghcr.io/microsoft/onnxruntime/onnxruntimetensorrt86gpubuild + build-args: '--build-arg BASEIMAGE=onnxruntimebuildcache.azurecr.io/internal/azureml/onnxruntime/build/cuda12_x64_almalinux8_gcc14:20251017.1 --build-arg TRT_VERSION=10.14.1.48-1.cuda12.9 --network=host' + push: true + azure-container-registry-name: onnxruntimebuildcache + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token to action + + # --- Download Build Artifact to Runner Temp Directory --- + - name: Download Build Artifact + uses: actions/download-artifact@v7 + with: + name: build-output-x64-Release # Must match the upload name + path: ${{ runner.temp }}/Release # Download contents into temp dir structure + + # --- Restore Permissions in the Temp Directory --- + - name: Restore Executable Permissions + if: success() # Only run if download succeeded + working-directory: ${{ runner.temp }}/Release + run: | + if [ -f perms.txt ]; then + echo "Restoring executable permissions in ${{ runner.temp }}/Release ..." + while IFS= read -r file; do + # Check relative path existence within the current directory + if [ -f "$file" ]; then + chmod +x "$file" + else + echo "Warning: File '$file' listed in perms.txt not found." + fi + done < perms.txt + echo "Permissions restored." + else + echo "Warning: perms.txt not found in artifact." + fi + + # --- Run Tests using the downloaded build --- + # The run-build-script-in-docker action mounts ${{ runner.temp }} to /onnxruntime_src/build + # So build.py --build_dir build/Release inside the container correctly finds the artifacts. + - name: Test ONNX Runtime + id: test_step + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: Release + mode: 'test' # Set mode to test + execution_providers: 'cuda tensorrt' + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --cuda_version=12.8 --cuda_home=/usr/local/cuda-12.8 --cudnn_home=/usr/local/cuda-12.8 --use_tensorrt --tensorrt_home /usr --build_java --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 onnxruntime_BUILD_UNIT_TESTS=ON onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' diff --git a/.github/workflows/linux_training.yml b/.github/workflows/linux_training.yml deleted file mode 100644 index d382cdf476283..0000000000000 --- a/.github/workflows/linux_training.yml +++ /dev/null @@ -1,55 +0,0 @@ -name: orttraining-linux-ci-pipeline -on: - push: - branches: - - main - - rel-* - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.ref }} - cancel-in-progress: true - -jobs: - orttraining-linux-ci-pipeline: - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] - permissions: - actions: read - contents: read - security-events: write - steps: - - uses: actions/checkout@v4 - - run: | - python3 -m pip install --user -r tools/ci_build/github/linux/python/requirements.txt - - name: Initialize CodeQL - uses: github/codeql-action/init@v3 - with: - config-file: ./.github/codeql/codeql-config.yml - languages: 'cpp' - - run: | - set -e -x - rm -rf build - python3 tools/ci_build/build.py --build_dir build --config Release --enable_training --skip_submodule_sync --parallel --update --build - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@v3 - with: - category: "/language:cpp" - output: sarif-results - upload: failure-only - - - name: filter-sarif - uses: advanced-security/filter-sarif@v1 - with: - patterns: | - +**/*.cc - +**/*.h - -tests/**/*.* - -build/**/*.* - input: sarif-results/cpp.sarif - output: sarif-results/cpp.sarif - - - name: Upload SARIF - uses: github/codeql-action/upload-sarif@v3 - with: - sarif_file: sarif-results/cpp.sarif \ No newline at end of file diff --git a/.github/workflows/linux_webgpu.yml b/.github/workflows/linux_webgpu.yml new file mode 100644 index 0000000000000..28cf9fbf8f6ff --- /dev/null +++ b/.github/workflows/linux_webgpu.yml @@ -0,0 +1,102 @@ +name: Linux WebGPU CI + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main, 'rel-*'] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +permissions: + contents: read + packages: write + attestations: write + id-token: write + +jobs: + build-linux-webgpu-x64-release: + name: Build Linux WebGPU x64 Release + # This job runs on a CPU node using the reusable build workflow + uses: ./.github/workflows/reusable_linux_build.yml + with: + pool_name: "onnxruntime-github-Ubuntu2204-AMD-CPU" # Build pool + build_config: Release + architecture: x64 + dockerfile_path: tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_webgpu + docker_image_repo: onnxruntimecpubuildpythonx64 + extra_build_flags: '--use_binskim_compliant_compile_flags --build_wheel --use_webgpu --build_java --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=ON' + python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' + run_tests: false + upload_build_output: true + execution_providers: 'webgpu' + job_identifier: build-linux-webgpu-x64-release + secrets: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token for reusable workflow needs (e.g., docker build action) + + # TODO: the following test step is currently failing. Need to fix and re-enable it + + # test-linux-webgpu-x64-release: + # name: Test Linux WebGPU x64 Release + # needs: build-linux-webgpu-x64-release + # runs-on: + # - self-hosted + # - "1ES.Pool=Onnxruntime-github-Linux-GPU-A100-WUS3" + # permissions: + # contents: read + # packages: read + # steps: + # - name: Checkout code + # uses: actions/checkout@v4 + + # - uses: microsoft/onnxruntime-github-actions/build-docker-image@v0.0.9 + # id: build_docker_image_step + # with: + # dockerfile: ${{ github.workspace }}/tools/ci_build/github/linux/docker/Dockerfile.manylinux2_28_webgpu + # image-name: ghcr.io/microsoft/onnxruntime/onnxruntimecpubuildcix64 + # push: true + # azure-container-registry-name: onnxruntimebuildcache + # env: + # GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} # Pass token to action + + # # --- Download Build Artifact to Runner Temp Directory --- + # - name: Download Build Artifact + # uses: actions/download-artifact@v4 + # with: + # name: build-output-x64-Release # Must match the upload name + # path: ${{ runner.temp }}/Release # Download contents into temp dir structure + + # # --- Restore Permissions in the Temp Directory --- + # - name: Restore Executable Permissions + # if: success() # Only run if download succeeded + # working-directory: ${{ runner.temp }}/Release + # shell: bash + # run: | + # if [ -f perms.txt ]; then + # echo "Restoring executable permissions in ${{ runner.temp }}/Release ..." + # while IFS= read -r file; do + # # Check relative path existence within the current directory + # if [ -f "$file" ]; then + # chmod +x "$file" + # else + # echo "Warning: File '$file' listed in perms.txt not found." + # fi + # done < perms.txt + # echo "Permissions restored." + # else + # echo "Warning: perms.txt not found in artifact." + # fi + + # - name: Test ONNX Runtime + # id: test_step + # uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@v0.0.9 + # with: + # docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + # build_config: Release + # mode: 'test' # Set mode to test + # execution_providers: 'webgpu' + # extra_build_flags: '--use_binskim_compliant_compile_flags --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=ON' + # python_path_prefix: 'PATH=/opt/python/cp310-cp310/bin:$PATH' diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml index e99f16afe700c..0f8b4a42f48ae 100644 --- a/.github/workflows/mac.yml +++ b/.github/workflows/mac.yml @@ -1,208 +1,122 @@ -name: Mac_CI +name: "MacOS CI Pipeline" on: push: branches: - - main - - rel-* + - main + - rel-* pull_request: branches: - - main - - rel-* + - main + - rel-* workflow_dispatch: concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} cancel-in-progress: true env: - python_version: 3.11 + python_version: "3.14" jobs: - ARM64-Xcode16: + cpu: + uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml + with: + # Only build arm64 for CPU + matrix_include: >- + [ + {"machine": "arm64", "target": "arm64", "build_config": "Debug"}, + {"machine": "arm64", "target": "arm64", "build_config": "Release"} + ] + python_version: "3.14" + + coreml: + uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml + with: + use_coreml: true + matrix_include: >- + [ + {"machine": "arm64", "target": "x86_64", "build_config": "Release"}, + {"machine": "arm64", "target": "arm64", "build_config": "Debug"}, + {"machine": "arm64", "target": "arm64", "build_config": "Release"} + ] + python_version: "3.14" + + xnnpack: + uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml + with: + use_xnnpack: true + # only build arm64/Debug for XNNPack + matrix_include: >- + [ + {"machine": "arm64", "target": "arm64", "build_config": "Debug"} + ] + python_version: "3.14" + + webgpu: + uses: ./.github/workflows/macos-ci-build-and-test-workflow.yml + with: + use_webgpu: true + matrix_include: >- + [ + {"machine": "arm64", "target": "x86_64", "build_config": "Release"}, + {"machine": "arm64", "target": "arm64", "build_config": "Debug"}, + {"machine": "arm64", "target": "arm64", "build_config": "Release"} + ] + python_version: "3.14" + + iphone_simulator: runs-on: macos-15 env: - xcode_version: 16 - - timeout-minutes: 60 - - steps: - - uses: actions/setup-python@v5 - with: - python-version: ${{ env.python_version }} - - - name: Verify ARM64 machine - shell: python - run: | - import platform - assert platform.machine() == "arm64", "This job expects to be run on an ARM64 machine." - - - name: Use Xcode ${{ env.xcode_version }} - shell: bash - run: | - XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ env.xcode_version }}.app/Contents/Developer" - sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" - - - uses: actions/checkout@v4 - - - name: Build and test - shell: bash - run: | - python ./tools/ci_build/build.py \ - --build_dir ./build \ - --update \ - --build --parallel \ - --test \ - --build_shared_lib \ - --build_objc \ - --use_coreml \ - --use_xnnpack \ - --use_binskim_compliant_compile_flags - - ARM64-Xcode16-targeting-iphonesimulator: - runs-on: macos-15 - - env: - xcode_version: 16 + xcode_version: 16.4 + simulator_runtime_version: 18.5 strategy: matrix: target_arch: [x86_64, arm64] - timeout-minutes: 60 + timeout-minutes: 120 steps: - - uses: actions/setup-python@v5 - with: - python-version: ${{ env.python_version }} - - - name: Verify ARM64 machine - shell: python - run: | - import platform - assert platform.machine() == "arm64", "This job expects to be run on an ARM64 machine." - - - name: Use Xcode ${{ env.xcode_version }} - shell: bash - run: | - XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ env.xcode_version }}.app/Contents/Developer" - sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" - - - uses: actions/checkout@v4 - - - name: Build for iphonesimulator ${{ matrix.target_arch }} - shell: bash - run: | - python ./tools/ci_build/build.py \ - --build_dir ./build \ - --update \ - --build --parallel \ - --test \ - --build_apple_framework \ - --use_xcode \ - --use_coreml \ - --use_xnnpack \ - --use_binskim_compliant_compile_flags \ - --ios \ - --apple_deploy_target=15.1 \ - --apple_sysroot=iphonesimulator \ - --osx_arch=${{ matrix.target_arch }} - - Vcpkg: - runs-on: macos-13 - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: ${{ env.python_version }} - - - name: "Run Homebrew" - run: brew install autoconf automake autoconf-archive - - - name: "Run vcpkg(x64-osx)" - uses: lukka/run-vcpkg@v11 - with: - vcpkgDirectory: "${{ runner.temp }}/vcpkg" - vcpkgGitCommitId: "b322364f06308bdd24823f9d8f03fe0cc86fd46f" # 2024.12.16 - runVcpkgInstall: true # vcpkg install --x-manifest-root cmake --x-install-root .build --overlay-triplets cmake/vcpkg-triplets/default - vcpkgJsonGlob: "cmake/vcpkg.json" - vcpkgConfigurationJsonGlob: "cmake/vcpkg-configuration.json" - env: - VCPKG_INSTALLED_DIR: "${{ github.workspace }}/.build" - VCPKG_DEFAULT_TRIPLET: "x64-osx" - VCPKG_OVERLAY_TRIPLETS: "${{ github.workspace }}/cmake/vcpkg-triplets/default" - # VCPKG_BINARY_SOURCES: "default" # https://learn.microsoft.com/en-us/vcpkg/reference/binarycaching - - - name: "Run compile_schema.py" - run: | - set -e -x - # Runner's host triplet should be x64-osx or arm64-osx - export FLATC_DIR="${{ github.workspace }}/.build/${{ runner.arch }}-osx/tools/flatbuffers" - export PATH="$FLATC_DIR:$PATH" - flatc --version - python onnxruntime/core/flatbuffers/schema/compile_schema.py --flatc "$(which flatc)" - python onnxruntime/lora/adapter_format/compile_schema.py --flatc "$(which flatc)" - - - name: "Detect protoc" - id: protoc-detect - run: | - export PROTOC_DIR="${{ github.workspace }}/.build/${{ runner.arch }}-osx/tools/protobuf" - export PATH="$PROTOC_DIR:$PATH" - protoc --version - echo "protoc_path=$(which protoc)" >> "$GITHUB_OUTPUT" - - - name: "Run build.py(x64-osx)" - run: | - python ./tools/ci_build/build.py \ - --build_dir "build/x64-osx" \ - --skip_submodule_sync \ - --skip_tests \ - --compile_no_warning_as_error \ - --parallel \ - --path_to_protoc_exe "${{ steps.protoc-detect.outputs.protoc_path }}" \ - --osx_arch x86_64 \ - --use_vcpkg \ - --cmake_extra_defines "CMAKE_TOOLCHAIN_FILE:FILEPATH=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" \ - --cmake_extra_defines "VCPKG_TARGET_TRIPLET=x64-osx" \ - --cmake_extra_defines "VCPKG_INSTALLED_DIR:PATH=${{ github.workspace }}/.build" \ - --cmake_extra_defines "VCPKG_INSTALL_OPTIONS=--x-feature=tests" - env: - VCPKG_OVERLAY_TRIPLETS: "${{ github.workspace }}/cmake/vcpkg-triplets/default" - shell: bash - - - name: "Run vcpkg(arm64-osx)" - uses: lukka/run-vcpkg@v11 - with: - vcpkgDirectory: "${{ runner.temp }}/vcpkg" - doNotUpdateVcpkg: true - runVcpkgInstall: true # vcpkg install --x-manifest-root cmake --x-install-root .build --overlay-triplets cmake/vcpkg-triplets/default - vcpkgJsonGlob: "cmake/vcpkg.json" - vcpkgConfigurationJsonGlob: "cmake/vcpkg-configuration.json" - env: - VCPKG_INSTALLED_DIR: "${{ github.workspace }}/.build" - VCPKG_DEFAULT_TRIPLET: "arm64-osx" - VCPKG_OVERLAY_TRIPLETS: "${{ github.workspace }}/cmake/vcpkg-triplets/default" - # VCPKG_BINARY_SOURCES: "default" # https://learn.microsoft.com/en-us/vcpkg/reference/binarycaching - - - name: "Run build.py(arm64-osx)" - run: | - python ./tools/ci_build/build.py \ - --build_dir "build/arm64-osx" \ - --skip_submodule_sync \ - --skip_tests \ - --compile_no_warning_as_error \ - --parallel \ - --path_to_protoc_exe "${{ steps.protoc-detect.outputs.protoc_path }}" \ - --osx_arch arm64 \ - --use_vcpkg \ - --cmake_extra_defines "CMAKE_TOOLCHAIN_FILE:FILEPATH=${VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake" \ - --cmake_extra_defines "VCPKG_TARGET_TRIPLET=arm64-osx" \ - --cmake_extra_defines "VCPKG_INSTALLED_DIR:PATH=${{ github.workspace }}/.build" \ - --cmake_extra_defines "VCPKG_INSTALL_OPTIONS=--x-feature=tests" - env: - VCPKG_OVERLAY_TRIPLETS: "${{ github.workspace }}/cmake/vcpkg-triplets/default" - shell: bash + - name: Checkout code + uses: actions/checkout@v6 + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.9 + with: + vcpkg-version: '2025.08.27' + vcpkg-hash: 9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079 + cmake-version: '3.31.8' + cmake-hash: 99cc9c63ae49f21253efb5921de2ba84ce136018abf08632c92c060ba91d552e0f6acc214e9ba8123dee0cf6d1cf089ca389e321879fd9d719a60d975bcffcc8 + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: macOS CI pipeline prepare steps + uses: ./.github/actions/macos-ci-setup + with: + platform_machine: "arm64" + python_version: ${{ env.python_version }} + xcode_version: ${{ env.xcode_version }} + use_cache: false + + - name: Build for iphonesimulator ${{ matrix.target_arch }} + shell: bash + run: | + python ./tools/ci_build/build.py \ + --build_dir ./build \ + --update \ + --build --parallel \ + --test \ + --build_apple_framework \ + --use_xcode \ + --use_coreml \ + --use_xnnpack \ + --use_binskim_compliant_compile_flags \ + --ios \ + --apple_deploy_target=15.1 \ + --apple_sysroot=iphonesimulator \ + --osx_arch=${{ matrix.target_arch }} + env: + ORT_GET_SIMULATOR_DEVICE_INFO_REQUESTED_RUNTIME_VERSION: ${{ env.simulator_runtime_version }} Objective-C-StaticAnalysis: runs-on: macos-14 @@ -213,45 +127,52 @@ jobs: timeout-minutes: 30 steps: - - uses: actions/setup-python@v5 - with: - python-version: ${{ env.python_version }} - - - name: Use Xcode ${{ env.xcode_version }} - shell: bash - run: | - XCODE_DEVELOPER_DIR="/Applications/Xcode_${{ env.xcode_version }}.app/Contents/Developer" - sudo xcode-select --switch "${XCODE_DEVELOPER_DIR}" - - - uses: actions/checkout@v4 - - - name: Generate compile_commands.json and ONNX protobuf files - shell: bash - run: | - python ./tools/ci_build/build.py \ - --build_dir ./build \ - --cmake_generator "Unix Makefiles" \ - --config Debug \ - --build_shared_lib \ - --use_coreml \ - --build_objc \ - --enable_training_apis \ - --cmake_extra_defines CMAKE_EXPORT_COMPILE_COMMANDS=ON \ - --use_binskim_compliant_compile_flags \ - --update \ - --build --parallel \ - --target onnx_proto - - - name: Analyze Objective-C/C++ source code - shell: bash - run: | - CLANG_TIDY_CHECKS="-*,clang-analyzer-*" - - "$(brew --prefix llvm@15)/bin/clang-tidy" \ - -p=./build/Debug \ - --checks="${CLANG_TIDY_CHECKS}" \ - --warnings-as-errors="${CLANG_TIDY_CHECKS}" \ - --header-filter="objectivec/include|objectivec|onnxruntime/core" \ - ./objectivec/*.mm \ - ./onnxruntime/core/platform/apple/logging/apple_log_sink.mm \ - ./onnxruntime/core/providers/coreml/model/*.mm + - name: Checkout code + uses: actions/checkout@v6 + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.9 + with: + vcpkg-version: '2025.08.27' + vcpkg-hash: 9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079 + cmake-version: '3.31.8' + cmake-hash: 99cc9c63ae49f21253efb5921de2ba84ce136018abf08632c92c060ba91d552e0f6acc214e9ba8123dee0cf6d1cf089ca389e321879fd9d719a60d975bcffcc8 + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: macOS CI pipeline prepare steps + uses: ./.github/actions/macos-ci-setup + with: + platform_machine: "arm64" + python_version: ${{ env.python_version }} + xcode_version: ${{ env.xcode_version }} + use_cache: false + + - name: Generate compile_commands.json and ONNX protobuf files + shell: bash + run: | + python ./tools/ci_build/build.py \ + --build_dir ./build \ + --cmake_generator "Unix Makefiles" \ + --config Debug \ + --build_shared_lib \ + --use_coreml \ + --build_objc \ + --enable_training_apis \ + --cmake_extra_defines CMAKE_EXPORT_COMPILE_COMMANDS=ON \ + --use_binskim_compliant_compile_flags \ + --update \ + --build --parallel \ + --target onnx_proto + + - name: Analyze Objective-C/C++ source code + shell: bash + run: | + CLANG_TIDY_CHECKS="-*,clang-analyzer-*" + + "$(brew --prefix llvm@15)/bin/clang-tidy" \ + -p=./build/Debug \ + --checks="${CLANG_TIDY_CHECKS}" \ + --warnings-as-errors="${CLANG_TIDY_CHECKS}" \ + --header-filter="objectivec/include|objectivec|onnxruntime/core" \ + ./objectivec/*.mm \ + ./onnxruntime/core/platform/apple/logging/apple_log_sink.mm \ + ./onnxruntime/core/providers/coreml/model/*.mm diff --git a/.github/workflows/macos-ci-build-and-test-workflow.yml b/.github/workflows/macos-ci-build-and-test-workflow.yml new file mode 100644 index 0000000000000..76198c7f5c1ce --- /dev/null +++ b/.github/workflows/macos-ci-build-and-test-workflow.yml @@ -0,0 +1,138 @@ +name: "macOS CI Reusable Workflow for build and test" +description: "This is a reusable workflow for macOS CI pipelines to build and test" + +on: + workflow_call: + inputs: + use_webgpu: + required: false + type: boolean + default: false + use_xnnpack: + required: false + type: boolean + default: false + use_coreml: + required: false + type: boolean + default: false + python_version: + required: false + type: string + default: "3.14" + matrix_include: + required: false + type: string + description: "JSON string specifying combinations to include in the matrix" + # we do not have enough resources to run all combinations + # Include arm64 + Debug combination by default + default: >- + [ + {"machine": "arm64", "target": "arm64", "build_config": "Debug"} + ] + +jobs: + build-and-test: + strategy: + matrix: + # To avoid creating too many jobs, we explicitly specify the combinations to run. + # + # # Specify the machine architecture to run the build on. + # machine: ["x86_64", "arm64"] + # + # # Specify the target architecture for the build. + # target: ["x86_64", "arm64"] + # + # # Specify the build configuration for the build. + # build_config: ["Debug", "Release"] + # + include: ${{ fromJSON(inputs.matrix_include) }} + + # "macos-13" is a x86_64 image, and "macos-15" is an arm64 image. + # see also: https://github.com/actions/runner-images/blob/main/README.md + runs-on: ${{ matrix.machine == 'x86_64' && 'macos-13' || 'macos-15' }} + env: + build_flags: > + --build_dir ./build + --skip_submodule_sync + --parallel + --use_binskim_compliant_compile_flags + --build_shared_lib + --build_nodejs + --build_objc + --build_java + --build_wheel + ${{ matrix.target == 'arm64' && '--enable_arm_neon_nchwc' || '' }} + ${{ inputs.use_webgpu && '--use_webgpu' || '' }} + ${{ inputs.use_xnnpack && '--use_xnnpack' || '' }} + ${{ inputs.use_coreml && '--use_coreml --skip_onnx_tests' || '' }} + --use_vcpkg --use_vcpkg_ms_internal_asset_cache + --config ${{ matrix.build_config }} + --osx_arch ${{ matrix.target }} + + # xCode version needs to match the "runs-on" configuration. + xcode_version: ${{ matrix.machine == 'x86_64' && '14.3.1' || '16' }} + + steps: + - name: Checkout code + uses: actions/checkout@v6 + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.9 + with: + vcpkg-version: '2025.08.27' + vcpkg-hash: 9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079 + cmake-version: '3.31.8' + cmake-hash: 99cc9c63ae49f21253efb5921de2ba84ce136018abf08632c92c060ba91d552e0f6acc214e9ba8123dee0cf6d1cf089ca389e321879fd9d719a60d975bcffcc8 + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: macOS CI pipeline prepare steps + uses: ./.github/actions/macos-ci-setup + with: + platform_machine: ${{ matrix.machine }} + python_version: ${{ inputs.python_version }} + xcode_version: ${{ env.xcode_version }} + use_cache: true + + - uses: actions/cache@v5 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + + - name: Setup environment variables + shell: bash + run: | + set -e -x + export PATH=${{ github.workspace }}/build/installed/bin:$PATH + export ONNX_ML=1 + export CMAKE_ARGS="-DONNX_GEN_PB_TYPE_STUBS=ON -DONNX_WERROR=OFF" + python -m pip install -r '${{ github.workspace }}/tools/ci_build/github/linux/docker/scripts/requirements.txt' + + - name: Configure Build (build.py --update) + shell: bash + working-directory: ${{ github.workspace }} + run: | + rm -rf ${{ github.workspace }}/build/${{ matrix.build_config }} + python ./tools/ci_build/build.py --update ${{ env.build_flags }} + + - name: Build (build.py --build) + shell: bash + working-directory: ${{ github.workspace }} + run: | + python ./tools/ci_build/build.py --build ${{ env.build_flags }} + + - name: Install + shell: bash + run: | + set -e -x + rm -rf ${{ github.workspace }}/build/installed + cd ${{ github.workspace }}/build/${{ matrix.build_config }} + make install DESTDIR=${{ github.workspace }}/build/installed + + - name: Running Tests (build.py --test) + # Skip tests when cross-compiling + if: ${{ matrix.machine == matrix.target }} + shell: bash + working-directory: ${{ github.workspace }} + run: | + python ./tools/ci_build/build.py --test ${{ env.build_flags }} diff --git a/.github/workflows/pr_checks.yml b/.github/workflows/pr_checks.yml index af890d88995be..e4fb442869616 100644 --- a/.github/workflows/pr_checks.yml +++ b/.github/workflows/pr_checks.yml @@ -13,20 +13,24 @@ permissions: # set top-level default permissions as security best practice contents: read concurrency: - group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name == 'workflow_dispatch' }} + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} cancel-in-progress: true jobs: auto-apply-fixes: name: Suggest fixes - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=pr-auto-apply-fixes-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] permissions: contents: read pull-requests: write steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup Python - uses: actions/setup-python@v5 + uses: actions/setup-python@v6 with: python-version: "3.10" - name: Setup Rust @@ -47,6 +51,6 @@ jobs: set +e lintrunner f --all-files -v exit 0 - - uses: parkerbxyz/suggest-changes@v2 + - uses: parkerbxyz/suggest-changes@v3 with: comment: 'You can commit the suggested changes from lintrunner.' diff --git a/.github/workflows/publish-c-apidocs.yml b/.github/workflows/publish-c-apidocs.yml index 6d3e593d8694e..9f65f801ad528 100644 --- a/.github/workflows/publish-c-apidocs.yml +++ b/.github/workflows/publish-c-apidocs.yml @@ -1,6 +1,8 @@ name: Update C/C++ API Docs -# Run when the C API changes or every month so that the artifact does not expire +# Run when the C API changes or every week so that the artifact does not expire. +# Also runs on pull requests that touch relevant files so doc generation errors +# are caught early. The artifact is only published on the main branch. on: push: branches: @@ -8,13 +10,19 @@ on: paths: - include/onnxruntime/core/session/** - orttraining/orttraining/training_api/include/** + - docs/c_cxx/** + pull_request: + paths: + - include/onnxruntime/core/session/** + - orttraining/orttraining/training_api/include/** + - docs/c_cxx/** schedule: - - cron: '0 0 1,15 * *' + - cron: '0 0 * * 0' workflow_dispatch: concurrency: - group: "apidocs-c" - cancel-in-progress: false + group: "apidocs-c-${{ github.ref }}" + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} permissions: contents: write @@ -22,9 +30,13 @@ permissions: jobs: build: name: Generate C/C++ API docs - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=apidocs-c-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install doxygen and dependencies run: | sudo apt update @@ -42,11 +54,12 @@ jobs: - name: Move C/C++ docs into site run: | mkdir -p _site/docs/api - rm -rf site/docs/api/c + rm -rf _site/docs/api/c mv build/doxygen/html _site/docs/api/c - name: Upload new site - uses: actions/upload-artifact@v4 + if: github.ref == 'refs/heads/main' + uses: actions/upload-artifact@v6 with: name: onnxruntime-c-apidocs path: _site - retention-days: 30 + retention-days: 10 diff --git a/.github/workflows/publish-csharp-apidocs.yml b/.github/workflows/publish-csharp-apidocs.yml index 7cca0969a168b..ac9d9a88a2144 100644 --- a/.github/workflows/publish-csharp-apidocs.yml +++ b/.github/workflows/publish-csharp-apidocs.yml @@ -1,30 +1,39 @@ name: Update C# API Docs -# Run when the C# API changes or every month so that the artifact does not expire +# Run when the C# API changes or every week so that the artifact does not expire. +# Also runs on pull requests that touch relevant files so doc generation errors +# are caught early. The artifact is only published on the main branch. on: push: branches: - main paths: - csharp/** + pull_request: + paths: + - csharp/** schedule: - - cron: '0 0 1,15 * *' + - cron: '0 0 * * 0' workflow_dispatch: concurrency: - group: "apidocs-csharp" - cancel-in-progress: false + group: "apidocs-csharp-${{ github.ref }}" + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} permissions: contents: write jobs: build: - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=publish-csharp-apidocs-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] env: DOCFXVERSION: 2.62.2 steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install DocFX run: | dotnet tool update -g docfx @@ -56,8 +65,9 @@ jobs: if (Test-Path $OutputDirectory) { Remove-Item -Recurse -Force $OutputDirectory } Move-Item -Path csharp\ApiDocs\csharp -Destination $OutputDirectory - name: Upload docs artifact - uses: actions/upload-artifact@v4 + if: github.ref == 'refs/heads/main' + uses: actions/upload-artifact@v6 with: name: onnxruntime-csharp-apidocs path: _site - retention-days: 30 + retention-days: 10 diff --git a/.github/workflows/publish-gh-pages.yml b/.github/workflows/publish-gh-pages.yml index 11745ce24f9e5..d8f53f8dd698b 100644 --- a/.github/workflows/publish-gh-pages.yml +++ b/.github/workflows/publish-gh-pages.yml @@ -8,7 +8,11 @@ on: jobs: placeholder: - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=publish-gh-pages-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] steps: - name: Placeholder step to have workflow included in the GitHub web UI run: | diff --git a/.github/workflows/publish-java-apidocs.yml b/.github/workflows/publish-java-apidocs.yml index d04669a13aab7..e62f85873881e 100644 --- a/.github/workflows/publish-java-apidocs.yml +++ b/.github/workflows/publish-java-apidocs.yml @@ -1,19 +1,24 @@ name: Update Java API Docs -# Run when the Java API changes or every month so that the artifact does not expire +# Run when the Java API changes or every week so that the artifact does not expire. +# Also runs on pull requests that touch relevant files so doc generation errors +# are caught early. The artifact is only published on the main branch. on: push: branches: - main paths: - java/** + pull_request: + paths: + - java/** schedule: - - cron: '0 0 1,15 * *' + - cron: '0 0 * * 0' workflow_dispatch: concurrency: - group: "apidocs-java" - cancel-in-progress: false + group: "apidocs-java-${{ github.ref }}" + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} permissions: contents: write @@ -21,11 +26,15 @@ permissions: jobs: build: name: Generate Java docs - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=apidocs-java-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Set up JDK 11 - uses: actions/setup-java@v4 + uses: actions/setup-java@v5 with: java-version: '11' distribution: 'adopt' @@ -43,8 +52,9 @@ jobs: mkdir -p _site/docs/api mv java/build/docs/javadoc _site/docs/api/java - name: Upload new site - uses: actions/upload-artifact@v4 + if: github.ref == 'refs/heads/main' + uses: actions/upload-artifact@v6 with: name: onnxruntime-java-apidocs path: _site - retention-days: 30 + retention-days: 10 diff --git a/.github/workflows/publish-js-apidocs.yml b/.github/workflows/publish-js-apidocs.yml index a6749b42adc35..49961caf575aa 100644 --- a/.github/workflows/publish-js-apidocs.yml +++ b/.github/workflows/publish-js-apidocs.yml @@ -1,19 +1,24 @@ name: Update JS API Docs -# Run when the JS API changes or every month so that the artifact does not expire +# Run when the JS API changes or every week so that the artifact does not expire. +# Also runs on pull requests that touch relevant files so doc generation errors +# are caught early. The artifact is only published on the main branch. on: push: branches: - main paths: - js/common/** + pull_request: + paths: + - js/common/** schedule: - - cron: '0 0 1,15 * *' + - cron: '0 0 * * 0' workflow_dispatch: concurrency: - group: "apidocs-js" - cancel-in-progress: false + group: "apidocs-js-${{ github.ref }}" + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} permissions: contents: write @@ -21,14 +26,18 @@ permissions: jobs: build: name: Generate JS API docs - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=apidocs-js-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Setup Node.js - uses: actions/setup-node@v4 + uses: actions/setup-node@v6 with: node-version: 18 - - name: Generate JS docs + - name: Generate JS docs run: | cd js/ npm ci @@ -43,8 +52,9 @@ jobs: mkdir -p _site/docs/api mv js/common/docs _site/docs/api/js - name: Upload docs artifact - uses: actions/upload-artifact@v4 + if: github.ref == 'refs/heads/main' + uses: actions/upload-artifact@v6 with: name: onnxruntime-node-apidocs path: _site - retention-days: 30 + retention-days: 10 diff --git a/.github/workflows/publish-objectivec-apidocs.yml b/.github/workflows/publish-objectivec-apidocs.yml index deef64f73f15a..d21efc329f864 100644 --- a/.github/workflows/publish-objectivec-apidocs.yml +++ b/.github/workflows/publish-objectivec-apidocs.yml @@ -1,19 +1,24 @@ name: Update Objective-C API Docs -# Run when the Objective-C API changes or every month so that the artifact does not expire +# Run when the Objective-C API changes or every week so that the artifact does not expire. +# Also runs on pull requests that touch relevant files so doc generation errors +# are caught early. The artifact is only published on the main branch. on: push: branches: - main paths: - objectivec/** + pull_request: + paths: + - objectivec/** schedule: - - cron: '0 0 1,15 * *' + - cron: '0 0 * * 0' workflow_dispatch: concurrency: - group: "apidocs-objectivec" - cancel-in-progress: false + group: "apidocs-objectivec-${{ github.ref }}" + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} permissions: contents: write @@ -23,7 +28,15 @@ jobs: name: Generate Objective-C API docs runs-on: macos-latest steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.9 + with: + vcpkg-version: '2025.08.27' + vcpkg-hash: 9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079 + cmake-version: '3.31.8' + cmake-hash: 99cc9c63ae49f21253efb5921de2ba84ce136018abf08632c92c060ba91d552e0f6acc214e9ba8123dee0cf6d1cf089ca389e321879fd9d719a60d975bcffcc8 + add-cmake-to-path: 'true' + disable-terrapin: 'true' - name: Install Jazzy run: | @@ -44,8 +57,9 @@ jobs: shell: bash - name: Upload new site - uses: actions/upload-artifact@v4 + if: github.ref == 'refs/heads/main' + uses: actions/upload-artifact@v6 with: name: onnxruntime-objectivec-apidocs path: ./_site - retention-days: 30 + retention-days: 10 diff --git a/.github/workflows/publish-python-apidocs.yml b/.github/workflows/publish-python-apidocs.yml index adc2346d1bf1b..dfa370802edaf 100644 --- a/.github/workflows/publish-python-apidocs.yml +++ b/.github/workflows/publish-python-apidocs.yml @@ -1,6 +1,8 @@ name: Update Python API Docs -# Run when the Python API changes or every month so that the artifact does not expire +# Run when the Python API changes or every week so that the artifact does not expire. +# Also runs on pull requests that touch relevant files so doc generation errors +# are caught early. The artifact is only published on the main branch. on: push: branches: @@ -8,13 +10,17 @@ on: paths: - onnxruntime/python/** - docs/python/** + pull_request: + paths: + - onnxruntime/python/** + - docs/python/** schedule: - - cron: '0 0 1,15 * *' + - cron: '0 0 * * 0' workflow_dispatch: concurrency: - group: "apidocs-python" - cancel-in-progress: true + group: "apidocs-python-${{ github.ref }}" + cancel-in-progress: ${{ github.ref != 'refs/heads/main' }} permissions: contents: write @@ -22,9 +28,13 @@ permissions: jobs: build: name: Generate Python API docs - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=apidocs-python-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] steps: - - uses: actions/checkout@v4 + - uses: actions/checkout@v6 - name: Install tools run: | sudo apt-get update @@ -40,6 +50,7 @@ jobs: - name: Generate Python docs with Sphinx run: | cd tools/doc + chmod +x * ./builddoc.sh /usr/bin ../.. ../../build - name: Log source commit run: git rev-parse --short HEAD > build/docs/html/source-version.txt @@ -49,8 +60,9 @@ jobs: mkdir -p _site/docs/api/ mv build/docs/html _site/docs/api/python - name: Upload docs artifact - uses: actions/upload-artifact@v4 + if: github.ref == 'refs/heads/main' + uses: actions/upload-artifact@v6 with: name: onnxruntime-python-apidocs path: _site - retention-days: 30 + retention-days: 10 diff --git a/.github/workflows/react_native.yml b/.github/workflows/react_native.yml new file mode 100644 index 0000000000000..f93f7d7c2d08b --- /dev/null +++ b/.github/workflows/react_native.yml @@ -0,0 +1,294 @@ +name: React Native CI Pipeline + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main, 'rel-*'] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + build_android_packages: + name: Build Android AAR Packages + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=react_build_android_packages-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 120 + outputs: + aar_path: ${{ runner.temp }}/.artifacts + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: Set version number variables + id: set_versions + run: | + echo "OnnxRuntimeVersion=$(head -1 VERSION_NUMBER)" >> $GITHUB_ENV + echo "OnnxRuntimeGitCommitHash=$(git rev-parse HEAD)" >> $GITHUB_ENV + echo "OnnxRuntimeGitCommitHashShort=$(git rev-parse --short=8 HEAD)" >> $GITHUB_ENV + + - name: Setup Android NDK + uses: ./.github/actions/setup-android-ndk + with: + ndk-version: 28.0.13004108 + + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.9 + with: + vcpkg-version: '2025.08.27' + vcpkg-hash: '9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079' + cmake-version: '3.31.6' + cmake-hash: '42395e20b10a8e9ef3e33014f9a4eed08d46ab952e02d2c1bbc8f6133eca0d7719fb75680f9bbff6552f20fcd1b73d86860f7f39388d631f98fb6f622b37cf04' + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: Build Android AAR Packages + run: | + set -e -x + mkdir -p ${{ runner.temp }}/.build_settings + mkdir -p ${{ runner.temp }}/artifacts + cp tools/ci_build/github/js/react_native_e2e_full_aar_build_settings.json ${{ runner.temp }}/.build_settings/build_settings.json + + python3 -m pip install --user -r ${{ github.workspace }}/tools/ci_build/requirements/pybind/requirements.txt + + python3 ${{ github.workspace }}/tools/ci_build/github/android/build_aar_package.py --build_dir ${{ runner.temp }} --config Release --android_sdk_path $ANDROID_SDK_ROOT --android_ndk_path $ANDROID_NDK_ROOT ${{ runner.temp }}/.build_settings/build_settings.json + + # Copy the built artifacts to give folder for publishing + cp -r ${{ runner.temp }}/aar_out/Release/com ${{ runner.temp }}/artifacts + + - name: Upload Android AAR Artifact + uses: actions/upload-artifact@v6 + with: + name: onnxruntime-android-full-aar + path: ${{ runner.temp }}/artifacts + + react_native_ci_android: + name: React Native CI Android + needs: build_android_packages + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=react_native_ci_android-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 90 + steps: + - name: Set ANDROID_AVD_HOME environment variable + run: echo "ANDROID_AVD_HOME=${{ runner.temp }}/android-avd" >> $GITHUB_ENV + + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Use Python 3.12 + uses: actions/setup-python@v6 + with: + python-version: "3.12" + architecture: "x64" + + - name: Use Java 17 (Temurin) + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: Use Node.js 22.x + uses: actions/setup-node@v6 + with: + node-version: '22.x' + + - name: Install ninja + run: sudo apt-get update && sudo apt-get install -y ninja-build + + - name: Download Android AAR artifacts + uses: actions/download-artifact@v7 + with: + name: onnxruntime-android-full-aar + path: ${{ runner.temp }}/android-full-aar + + - name: Copy AAR to React Native and E2E directories + run: | + mkdir -p ${{ github.workspace }}/js/react_native/e2e/android/app/libs + cp -r ${{ runner.temp }}/android-full-aar/com ${{ github.workspace }}/js/react_native/e2e/android/app/libs + + - name: Install dependencies and bootstrap + run: | + npm install -g detox-cli + npm ci + working-directory: ${{ github.workspace }}/js + - run: npm ci + working-directory: ${{ github.workspace }}/js/common + - run: | + npm ci + npm run bootstrap-no-pods + working-directory: ${{ github.workspace }}/js/react_native + + - name: Generate a debug keystore + run: | + keytool -genkey -v -keystore debug.keystore -alias androiddebugkey -storepass android \ + -keypass android -keyalg RSA -keysize 2048 -validity 999999 -dname "CN=Android Debug,O=Android,C=US" + working-directory: ${{ github.workspace }}/js/react_native/e2e/android + + - name: Build React Native Detox Android e2e Tests + run: detox build --configuration android.emu.release + working-directory: ${{ github.workspace }}/js/react_native/e2e + + - name: Setup Android Emulator + uses: ./.github/actions/setup-android-ndk + with: + ndk-version: 28.0.13004108 + + - name: Run React Native Detox Android e2e Tests + run: | + JEST_JUNIT_OUTPUT_FILE=${{ github.workspace }}/js/react_native/e2e/android-test-results.xml \ + detox test --record-logs all \ + --configuration android.emu.release \ + --loglevel trace \ + --take-screenshots failing + working-directory: ${{ github.workspace }}/js/react_native/e2e + + - name: Install psutil and Stop Android Emulator + if: always() + run: | + python3 -m pip install psutil + if test -f ./emulator.pid; then + echo "Emulator PID: $(cat ./emulator.pid)" + python3 tools/python/run_android_emulator.py \ + --android-sdk-root "${ANDROID_SDK_ROOT}" \ + --stop \ + --emulator-pid-file ./emulator.pid + rm ./emulator.pid + else + echo "Emulator PID file was expected to exist but does not." + fi + + - name: Upload Android Test Results + if: always() + uses: actions/upload-artifact@v6 + with: + name: android-test-results + path: | + ${{ github.workspace }}/js/react_native/e2e/android-test-results.xml + ${{ github.workspace }}/js/react_native/e2e/artifacts + + react_native_ci_ios_build: + name: React Native CI iOS Build + runs-on: macos-14 + timeout-minutes: 120 + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Use Xcode 15.3.0 + run: sudo xcode-select --switch /Applications/Xcode_15.3.0.app/Contents/Developer + + - name: Use Python 3.12 + uses: actions/setup-python@v6 + with: + python-version: "3.12" + architecture: "x64" + + - name: Install Python requirements + run: pip install -r tools/ci_build/github/apple/ios_packaging/requirements.txt + + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.9 + with: + vcpkg-version: '2025.08.27' + vcpkg-hash: 9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079 + cmake-version: '3.31.8' + cmake-hash: 99cc9c63ae49f21253efb5921de2ba84ce136018abf08632c92c060ba91d552e0f6acc214e9ba8123dee0cf6d1cf089ca389e321879fd9d719a60d975bcffcc8 + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: Build iOS package and assemble pods + run: | + python ${{ github.workspace }}/tools/ci_build/github/apple/build_and_assemble_apple_pods.py \ + --build-dir "${{ runner.temp }}/ios_framework_full" \ + --staging-dir "${{ runner.temp }}/ios_pod" \ + --build-settings-file ${{ github.workspace }}/tools/ci_build/github/js/react_native_e2e_full_ios_framework_build_settings_arm64.json + + - name: Upload iOS Pod Artifact + uses: actions/upload-artifact@v6 + with: + name: ios_pod + path: ${{ runner.temp }}/ios_pod + + react_native_ci_ios_e2e_tests: + name: React Native CI iOS E2E Tests + needs: react_native_ci_ios_build + runs-on: macos-14 + timeout-minutes: 90 + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Download iOS pod artifact + uses: actions/download-artifact@v7 + with: + name: ios_pod + path: ${{ runner.temp }}/ios_pod + + - name: Use Xcode 15.3.0 + run: sudo xcode-select --switch /Applications/Xcode_15.3.0.app/Contents/Developer + + - name: Use Node.js 22.x + uses: actions/setup-node@v6 + with: + node-version: '22.x' + + - uses: microsoft/onnxruntime-github-actions/setup-build-tools@v0.0.9 + with: + vcpkg-version: '2025.08.27' + vcpkg-hash: 9a4b32849792e13bee1d24726f073b3881acae4165206ddf1a6378e44a4ddd05b3ee93f55ff46d8e8873b3cbcd06606212989e248f0bd615a5bf365070074079 + cmake-version: '3.31.8' + cmake-hash: 99cc9c63ae49f21253efb5921de2ba84ce136018abf08632c92c060ba91d552e0f6acc214e9ba8123dee0cf6d1cf089ca389e321879fd9d719a60d975bcffcc8 + add-cmake-to-path: 'true' + disable-terrapin: 'true' + + - name: Install dependencies and bootstrap + run: | + set -e -x + npm install -g detox-cli + brew tap wix/brew + brew install applesimutils + npm ci + working-directory: ${{ github.workspace }}/js + - run: npm ci + working-directory: ${{ github.workspace }}/js/common + - run: | + set -e -x + npm ci + npm run bootstrap-no-pods + working-directory: ${{ github.workspace }}/js/react_native + + - name: Pod install for e2e tests + run: | + set -e -x + ls ${{ runner.temp }}/ios_pod/onnxruntime-c + ORT_C_LOCAL_POD_PATH=${{ runner.temp }}/ios_pod/onnxruntime-c pod install --verbose + working-directory: ${{ github.workspace }}/js/react_native/e2e/ios + + - name: Build and Run Detox iOS e2e Tests + run: | + detox build --configuration ios.sim.release + JEST_JUNIT_OUTPUT_FILE=${{ github.workspace }}/js/react_native/e2e/ios-test-results.xml \ + detox test --record-logs all \ + --configuration ios.sim.release \ + --loglevel verbose \ + --take-screenshots failing + working-directory: ${{ github.workspace }}/js/react_native/e2e + + - name: Upload iOS Test Results + if: always() + uses: actions/upload-artifact@v6 + with: + name: ios-test-results + path: | + ${{ github.workspace }}/js/react_native/e2e/ios-test-results.xml + ${{ github.workspace }}/js/react_native/e2e/artifacts diff --git a/.github/workflows/reusable_linux_build.yml b/.github/workflows/reusable_linux_build.yml new file mode 100644 index 0000000000000..ad68d2b388fca --- /dev/null +++ b/.github/workflows/reusable_linux_build.yml @@ -0,0 +1,198 @@ +name: Reusable Linux CPU/GPU Build and Test + +on: + workflow_call: + inputs: + pool_name: + description: 'The specific 1ES pool name (e.g., onnxruntime-github-Ubuntu2204-AMD-CPU)' + required: true + type: string + build_config: + description: 'Build configuration (Debug or Release)' + required: true + type: string + architecture: + description: 'Target architecture (x64 or arm64)' + required: true + type: string + dockerfile_path: + description: 'Path to the Dockerfile relative to the workspace root' + required: true + type: string + docker_image_repo: + description: 'Name for the Docker image repository' + required: true + type: string + docker_build_args: + description: 'Arguments to pass to the docker image build command' + required: false + type: string + default: '' + execution_providers: + description: 'Space-separated list of execution providers to enable (passed to build.py)' + required: false + type: string + default: '' + extra_build_flags: + description: 'Additional flags for the build.py script (appended after EP flags)' + required: false + type: string + default: '' + python_path_prefix: + description: 'Optional prefix to add to the PATH for python command (e.g., PATH=/opt/python/cp310-cp310/bin:$PATH)' + required: false + type: string + default: '' + python_version: + description: 'Python version to set up on the runner host' + required: false + type: string + default: '3.x' + run_tests: + description: 'Whether to execute the test suite after building' + required: false + type: boolean + default: true + upload_build_output: + description: 'Whether to upload the build output directory as an artifact (used when tests are skipped)' + required: false + type: boolean + default: false + job_identifier: + description: 'A unique identifier for the job, used for hosted pool tracking' + required: true + type: string + secrets: + GH_TOKEN: + description: 'GitHub token for accessing actions/packages' + required: true + +jobs: + build_test_pipeline: + runs-on: + - self-hosted + - "1ES.Pool=${{ inputs.pool_name }}" + - "JobId=${{ inputs.job_identifier }}-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + permissions: + contents: read + packages: write + attestations: write + id-token: write + steps: + - name: Checkout code + uses: actions/checkout@v6 + + - name: Set up Python ${{ inputs.python_version }} + if: inputs.architecture != 'arm64' + uses: actions/setup-python@v6 + with: + python-version: ${{ inputs.python_version }} + + - name: Build Docker Image (${{ inputs.architecture }} / ${{ inputs.build_config }}) + uses: microsoft/onnxruntime-github-actions/build-docker-image@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + id: build_docker_image_step + with: + dockerfile: ${{ github.workspace }}/${{ inputs.dockerfile_path }} + image-name: ghcr.io/microsoft/onnxruntime/${{ inputs.docker_image_repo }} + build-args: ${{ inputs.docker_build_args }} + push: true + azure-container-registry-name: onnxruntimebuildcache + env: + GITHUB_TOKEN: ${{ secrets.GH_TOKEN }} + + - name: Setup CCache + uses: actions/cache@v5 + with: + key: 'ccache | "${{ inputs.job_identifier }}" | "${{ inputs.architecture }}" | "${{ inputs.build_config }}"' + path: ~/.cache/cache + + # same idea as ccache, but for vcpkg artifacts. ideally we'd use vcpkg's nuget remote cache facility instead. + - name: Setup VCPKG Cache + uses: actions/cache@v5 + with: + key: '"vcpkg-cache" | "${{ inputs.job_identifier }}" | "${{ inputs.architecture }}" | "${{ inputs.build_config }}"' + path: ~/.cache/vcpkg + + # ------------- Update Step (CMake Generation) ------------- + - name: Generate Build Files (CMake) (${{ inputs.architecture }} / ${{ inputs.build_config }}) + id: update_step + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: ${{ inputs.build_config }} + mode: 'update' + execution_providers: ${{ inputs.execution_providers }} # Pass down EP list + extra_build_flags: ${{ inputs.extra_build_flags }} --use_cache + python_path_prefix: ${{ inputs.python_path_prefix }} + + # ------------- Build Step (Compilation) ------------- + - name: Build ONNX Runtime (${{ inputs.architecture }} / ${{ inputs.build_config }}) + id: build_step + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: ${{ inputs.build_config }} + mode: 'build' + execution_providers: ${{ inputs.execution_providers }} # Pass down EP list + extra_build_flags: ${{ inputs.extra_build_flags }} --use_cache + python_path_prefix: ${{ inputs.python_path_prefix }} + + # ------------- Test Step ------------- + - name: Test ONNX Runtime (${{ inputs.architecture }} / ${{ inputs.build_config }}) + id: test_step + if: inputs.run_tests == true + uses: microsoft/onnxruntime-github-actions/run-build-script-in-docker@8bad63a3c05d448311dfa8e5f531171c97471aa1 # v0.0.12 + with: + docker_image: ${{ steps.build_docker_image_step.outputs.full-image-name }} + build_config: ${{ inputs.build_config }} + mode: 'test' + execution_providers: ${{ inputs.execution_providers }} # Pass down EP list + extra_build_flags: ${{ inputs.extra_build_flags }} --use_cache + python_path_prefix: ${{ inputs.python_path_prefix }} + + # ------------- Prepare Artifact Step ------------- + - name: Prepare Build Output for Upload + if: inputs.upload_build_output == true + shell: bash + run: | + #!/bin/bash + set -e -x + BUILD_DIR="${{ runner.temp }}/${{ inputs.build_config }}" + if [ ! -d "${BUILD_DIR}" ]; then + echo "Error: Build directory ${BUILD_DIR} not found. Cannot prepare artifact." + exit 1 + fi + echo "--- Cleaning build directory: ${BUILD_DIR} ---" + rm -rf "${BUILD_DIR}/onnxruntime" || true + rm -rf "${BUILD_DIR}/pybind11" || true + rm -rf "${BUILD_DIR}/vcpkg_installed" || true + rm -f "${BUILD_DIR}/models" || true + DEPS_DIR="${BUILD_DIR}/_deps" + if [ -d "${DEPS_DIR}" ]; then + echo "Cleaning ${DEPS_DIR}, keeping onnx-src..." + find "${DEPS_DIR}" -mindepth 1 ! -regex "^${DEPS_DIR}/onnx-src\(/.*\)?$" -delete + else + echo "${DEPS_DIR} does not exist, skipping deps cleanup." + fi + echo "--- Saving executable permissions ---" + cd "${BUILD_DIR}" + find . -executable -type f -printf '%p\n' > perms.txt + echo "--- Cleanup and permission saving complete for ${BUILD_DIR} ---" + + # ------------- Upload Build Output Step ------------- + - name: Upload Build Output Artifact + if: inputs.upload_build_output == true + uses: actions/upload-artifact@v6 + with: + name: build-output-${{ inputs.architecture }}-${{ inputs.build_config }} + path: ${{ runner.temp }}/${{ inputs.build_config }} + if-no-files-found: error + + # ------------- Upload Log on Build Failure Step ------------- + - name: Upload VCPKG Manifest Install Log on Update or Build Failure + if: steps.update_step.outcome == 'failure' || steps.build_step.outcome == 'failure' + uses: actions/upload-artifact@v6 + with: + name: vcpkg-manifest-install-log-${{ inputs.architecture }}-${{ inputs.build_config }} + path: ${{ runner.temp }}/${{ inputs.build_config }}/${{ inputs.build_config }}/vcpkg-manifest-install.log + if-no-files-found: ignore diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml deleted file mode 100644 index 14cf0825873a0..0000000000000 --- a/.github/workflows/stale.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Close stale issues -on: - # Allows you to dictate when you want this workflow to run using cron syntax (times in UTC) - schedule: - - cron: "0 15 * * *" - # Allows you to run this workflow manually from the Actions tab - # workflow_dispatch: - -jobs: - close-stale-issues: - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] - permissions: - issues: write - pull-requests: write - steps: - - uses: actions/stale@v8 - with: - # Comma separated list of labels that can be assigned to issues to exclude them from being marked as stale - exempt-issue-labels: contributions welcome, feature request, regression - # Override exempt-all-assignees but only to exempt the issues with an assignee to be marked as stale automatically - exempt-all-issue-assignees: true - # Used to ignore the issues and pull requests created before the start date - # Start date should be April 19, 2022 - corresponds to the day previous stale bot stopped working - start-date: '2022-04-19T00:00:00Z' - # Number of days without activity before the actions/stale action labels an issue - days-before-issue-stale: 30 - # Number of days without activity before the actions/stale action closes an issue - days-before-issue-close: 30 - # Label you want to apply to issues that have been inactive for the amount of time specified by days-before-issue-stale - stale-issue-label: "stale" - # Comment that you want to add to issues that are labeled by the actions/stale action - stale-issue-message: "This issue has been automatically marked as stale due to inactivity and will be closed in 30 days if no further activity occurs. If further support is needed, please provide an update and/or more details." - # Comment that you want to add to issues that are closed by the actions/stale action - close-issue-message: "This issue has been automatically closed due to inactivity. Please reactivate if further support is needed." - # If you never want this action to label PRs, set this value to -1 - days-before-pr-stale: -1 - # If you never want this action to close PRs, set this value to -1 - days-before-pr-close: -1 - repo-token: ${{ secrets.GITHUB_TOKEN }} diff --git a/.github/workflows/title-only-labeler.yml b/.github/workflows/title-only-labeler.yml index 7ee9f3917a901..e27337440aad3 100644 --- a/.github/workflows/title-only-labeler.yml +++ b/.github/workflows/title-only-labeler.yml @@ -8,7 +8,11 @@ permissions: jobs: triage: - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU"] + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Ubuntu2204-AMD-CPU", + "JobId=title-only-labeler-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] steps: - uses: github/issue-labeler@v3.4 with: diff --git a/.github/workflows/web.yml b/.github/workflows/web.yml new file mode 100644 index 0000000000000..e9974fc66de4d --- /dev/null +++ b/.github/workflows/web.yml @@ -0,0 +1,86 @@ +name: Web CI Pipeline + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + precheck: + runs-on: ubuntu-latest + outputs: + commit_sha: ${{ steps.extract_commit.outputs.commit_sha }} + steps: + - name: Checkout code + uses: actions/checkout@v6 + with: + submodules: true + + - name: Init and Precheck + uses: ./.github/actions/linux-web-init-and-check + + - name: Extract commit SHA + id: extract_commit + run: echo "commit_sha=${{ github.sha }}" >> $GITHUB_OUTPUT + shell: bash + + wasm_Debug: + needs: precheck + uses: ./.github/workflows/linux-wasm-ci-build-and-test-workflow.yml + with: + job_name: wasm_Debug + build_config: Debug + extra_build_args: "--enable_wasm_profiling" + build_jsep: true + build_webgpu: true + + wasm_Release: + needs: precheck + uses: ./.github/workflows/linux-wasm-ci-build-and-test-workflow.yml + with: + job_name: wasm_Release + build_config: Release + extra_build_args: "--target onnxruntime_webassembly --skip_tests --disable_rtti" + build_jsep: true + build_webgpu: true + + wasm_Release_static_library: + needs: precheck + uses: ./.github/workflows/linux-wasm-ci-build-and-test-workflow.yml + with: + job_name: wasm_Release_static_library + build_config: Release + extra_build_args: "--skip_tests --disable_rtti --build_wasm_static_lib" + use_vcpkg: false + enable_wasm_threads: false + skip_publish: true + + web_Debug: + needs: + - precheck + - wasm_Debug + uses: ./.github/workflows/windows-web-ci-workflow.yml + with: + job_name: web_Debug + commit_override: ${{ needs.precheck.outputs.commit_sha }} + build_config: Debug + + web_Release: + needs: + - precheck + - wasm_Release + uses: ./.github/workflows/windows-web-ci-workflow.yml + with: + job_name: web_Release + commit_override: ${{ needs.precheck.outputs.commit_sha }} + build_config: Release diff --git a/.github/workflows/windows-web-ci-workflow.yml b/.github/workflows/windows-web-ci-workflow.yml new file mode 100644 index 0000000000000..9b40f8ee1dc17 --- /dev/null +++ b/.github/workflows/windows-web-ci-workflow.yml @@ -0,0 +1,228 @@ +name: "Windows Web CI Workflow" +description: "Windows Web CI pipeline for building and testing ONNX Runtime Web" + +on: + workflow_call: + inputs: + job_name: # workflow-scope unique key + required: true + type: string + commit_override: + type: string + default: "" + build_config: + type: string + default: "Debug" + npm_packaging_mode: + type: string + default: "dev" + package_name: + type: string + default: "NPM_packages" + +jobs: + build_onnxruntime_web: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Win2022-WEBGPU-A10", + "JobId=build_onnxruntime_web-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + + env: + webgpu_commandline_extra_flags: "--chromium-flags=--ignore-gpu-blocklist --chromium-flags=--gpu-vendor-id=0x10de" + CHROME_BIN: 'C:\Program Files\Google\Chrome\Application\chrome.exe' + + timeout-minutes: 60 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: Read commit SHA and checkout + if: ${{ inputs.commit_override != '' }} + shell: cmd + run: | + git fetch origin +${{ inputs.commit_override }}:refs/remotes/origin/${{ inputs.commit_override }} + git checkout --force ${{ inputs.commit_override }} + + - name: Write commit SHA to __commit.txt + if: ${{ inputs.commit_override == '' }} + shell: cmd + run: | + echo.${{ github.sha }}>${{ github.workspace }}/__commit.txt + + - name: Checkout submodule onnx + shell: cmd + run: | + git submodule sync -- cmake\external\onnx + git submodule update --init -- cmake\external\onnx + + - name: Force EOL to LF on windows for /js/** + shell: cmd + run: | + echo.>>.gitattributes + echo /js/** text=auto eol=lf>>.gitattributes + rd /s /q js + git checkout -- js/** + git checkout -- .gitattributes + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: "20.x" + + - name: Download WebAssembly artifacts + uses: actions/download-artifact@v7 + with: + name: ${{ inputs.build_config }}_wasm + path: ${{ github.workspace }}/artifacts_wasm + + - name: Binplace dist files (.wasm) + shell: cmd + run: | + mkdir ${{ github.workspace }}\js\web\dist + copy ${{ github.workspace }}\artifacts_wasm\ort-*.wasm ${{ github.workspace }}\js\web\dist\ + + - name: Binplace dist files (.mjs) + shell: cmd + run: | + copy ${{ github.workspace }}\artifacts_wasm\ort-*.mjs ${{ github.workspace }}\js\web\dist\ + + - name: npm ci for /js/ + run: npm ci + working-directory: ${{ github.workspace }}/js + + - name: npm ci for /js/common/ + run: npm ci + working-directory: ${{ github.workspace }}/js/common + + - name: npm ci for /js/web/ + run: npm ci + working-directory: ${{ github.workspace }}/js/web + + - uses: actions/cache@v5 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + + - name: Pack NPM packages + shell: pwsh + run: | + . ${{ github.workspace }}\tools\ci_build\github\js\pack-npm-packages.ps1 ${{ inputs.npm_packaging_mode }} ${{ github.workspace }} web + + - name: Check active Chrome processes (before test) + if: ${{ runner.debug == '1' }} + shell: pwsh + run: | + Get-WmiObject Win32_Process -Filter "name = 'chrome.exe'" | Format-List CommandLine + + - name: Run ort-web tests (ALL backends) + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\02 + dir ${{ runner.temp }}\web\test\02 + npm test -- -e=chrome -b=webgl,wasm,webgpu ${{ env.webgpu_commandline_extra_flags }} --user-data-dir=${{ runner.temp }}\web\test\02 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + - name: Run ort-web tests (Suite1, webgpu, IO-binding=gpu-tensor) + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\03 + dir ${{ runner.temp }}\web\test\03 + npm test -- suite1 -e=chrome -b=webgpu --io-binding=gpu-tensor ${{ env.webgpu_commandline_extra_flags }} --user-data-dir=${{ runner.temp }}\web\test\03 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + - name: Run ort-web tests (Suite1, webgpu, IO-binding=gpu-location) + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\04 + dir ${{ runner.temp }}\web\test\04 + npm test -- suite1 -e=chrome -b=webgpu --io-binding=gpu-location ${{ env.webgpu_commandline_extra_flags }} --user-data-dir=${{ runner.temp }}\web\test\04 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + - name: Run ort-web tests - WebGL packed mode + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\05 + dir ${{ runner.temp }}\web\test\05 + npm test -- --webgl.pack -b=webgl -e=chrome --user-data-dir=${{ runner.temp }}\web\test\05 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + - name: Run ort-web tests - WebAssembly proxy + if: ${{ inputs.build_config == 'Release' }} + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\06 + dir ${{ runner.temp }}\web\test\06 + npm test -- --wasm.proxy -b=wasm -e=chrome --user-data-dir=${{ runner.temp }}\web\test\06 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + # WebGPU EP tests + - name: Run ort-web tests - WebGPU EP + continue-on-error: true + shell: cmd + run: | + mkdir ${{ runner.temp }}\web\test\07 + dir ${{ runner.temp }}\web\test\07 + npm test --webgpu-ep -- suite1 ${{ inputs.build_config == 'Debug' && '--log-verbose' || '' }} -b=webgpu -e=chrome ${{ env.webgpu_commandline_extra_flags }} --user-data-dir=${{ runner.temp }}\web\test\07 --chromium-flags=--enable-logging --chromium-flags=--v=1 + working-directory: ${{ github.workspace }}\js\web + + - name: Validate shader keys - WebGPU EP + if: ${{ inputs.build_config == 'Debug' }} + uses: ./.github/actions/webgpu-validate-shader-key + with: + log_file_path: ${{ runner.temp }}\web\test\07\chrome_debug.log + is_chromium_log: true + + # this step is added to help investigate the shader validation failure which is hard to reproduce + - name: Upload WebGPU shader validation log on failure + if: ${{ failure() && inputs.build_config == 'Debug' }} + uses: actions/upload-artifact@v6 + with: + name: webgpu-shader-validation-logs + path: ${{ runner.temp }}\web\test\07\chrome_debug.log + + - name: E2E package consuming test + if: ${{ inputs.build_config == 'Release' }} + run: npm run test:e2e -- --browser=Chrome_default + working-directory: ${{ github.workspace }}\js\web + + - name: Create artifacts directory + if: ${{ inputs.build_config == 'Release' }} + shell: cmd + run: mkdir ${{ github.workspace }}\artifacts_npm + + - name: Copy onnxruntime-common artifacts + if: ${{ inputs.build_config == 'Release' }} + shell: cmd + run: | + if exist ${{ github.workspace }}\js\common\onnxruntime-common-*.tgz ( + copy ${{ github.workspace }}\js\common\onnxruntime-common-*.tgz ${{ github.workspace }}\artifacts_npm\ + ) + + - name: Copy onnxruntime-web artifacts + if: ${{ inputs.build_config == 'Release' }} + shell: cmd + run: copy ${{ github.workspace }}\js\web\onnxruntime-web-*.tgz ${{ github.workspace }}\artifacts_npm\ + + - name: Upload NPM packages + if: ${{ inputs.build_config == 'Release' }} + uses: actions/upload-artifact@v6 + with: + name: ${{ inputs.package_name }} + path: ${{ github.workspace }}\artifacts_npm + + - name: Log Chrome processes (after test) + if: ${{ always() && runner.debug == '1' }} + shell: cmd + run: | + for %%i in (01 02 03 04 05 06 07) do ( + if exist ${{ runner.temp }}\web\test\%%i ( + echo ------------------- BEGIN %%i ------------------- + type ${{ runner.temp }}\web\test\%%i\chrome_debug.log + echo ------------------- END %%i ------------------- + ) + ) diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100644 index 5adfad63093bc..0000000000000 --- a/.github/workflows/windows.yml +++ /dev/null @@ -1,138 +0,0 @@ -name: Windows_CI -on: - push: - branches: - - main - - rel-* - pull_request: - -concurrency: - group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }} - cancel-in-progress: true - -env: - AZCOPY_AUTO_LOGIN_TYPE: MSI - AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 - -jobs: - Windows-CUDA-12: - runs-on: ["self-hosted", "1ES.Pool=onnxruntime-github-vs2022-mms"] - steps: - - uses: actions/checkout@v4 - with: - submodules: false - - uses: actions/setup-python@v5 - with: - python-version: '3.11.x' - architecture: 'x64' - - - uses: actions/setup-node@v4 - with: - node-version: 18 - - - name: Download cuda - run: azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v12.2" cuda_sdk - - - - name: Delete build folder - run: | - if (Test-Path D:\b) { Remove-Item -Recurse -Force D:\b } - - - # The build machine doesn't have a GPU. So the value of CMAKE_CUDA_ARCHITECTURES doesn't matter. - - name: Build code - run: python tools\ci_build\build.py --windows_sdk_version 10.0.22621.0 --enable_training --build_java --config Debug --build_dir D:\b --skip_submodule_sync --build_csharp --update --build --parallel --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_pybind --use_cuda --cuda_home=${{ github.workspace }}\cuda_sdk\v12.2 --enable_cuda_profiling --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=75 - - Vcpkg: - runs-on: "windows-latest" - steps: - - uses: actions/checkout@v4 - - uses: actions/setup-python@v5 - with: - python-version: '3.11.x' - architecture: 'x64' - - - name: "Run vcpkg(x64-windows)" - uses: lukka/run-vcpkg@v11 - with: - vcpkgDirectory: "C:/vcpkg" # use VCPKG_INSTALLATION_ROOT of the image - vcpkgGitCommitId: "b322364f06308bdd24823f9d8f03fe0cc86fd46f" # 2024.12.16 - runVcpkgInstall: true # vcpkg install --x-manifest-root cmake --x-install-root .build --overlay-triplets cmake/vcpkg-triplets/default - vcpkgJsonGlob: "cmake/vcpkg.json" - vcpkgConfigurationJsonGlob: "cmake/vcpkg-configuration.json" - env: - VCPKG_INSTALLED_DIR: "${{ github.workspace }}/.build" - VCPKG_DEFAULT_TRIPLET: "x64-windows" - VCPKG_OVERLAY_TRIPLETS: "${{ github.workspace }}/cmake/vcpkg-triplets/default" - # VCPKG_BINARY_SOURCES: "default" # https://learn.microsoft.com/en-us/vcpkg/reference/binarycaching - - - name: "Run compile_schema.py" - run: | - # Runner's host triplet should be x64-windows or arm64-windows - $FLATC_DIR="${{ github.workspace }}/.build/${{ runner.arch }}-windows/tools/flatbuffers" - $env:PATH="$FLATC_DIR;$env:PATH" - flatc --version - $FLATC_PATH = Join-Path "$FLATC_DIR" "flatc.exe" - python onnxruntime/core/flatbuffers/schema/compile_schema.py --flatc "$FLATC_PATH" - python onnxruntime/lora/adapter_format/compile_schema.py --flatc "$FLATC_PATH" - shell: pwsh - - - name: "Detect protoc" - id: protoc-detect - run: | - $PROTOC_DIR="${{ github.workspace }}/.build/${{ runner.arch }}-windows/tools/protobuf" - $env:PATH="$PROTOC_DIR;$env:PATH" - protoc --version - $PROTOC_PATH = Join-Path "$PROTOC_DIR" "protoc.exe" - "protoc_path=$PROTOC_PATH" >> $env:GITHUB_OUTPUT - shell: pwsh - - - name: "Run build.py(x64-windows)" - run: | - python tools\ci_build\build.py ` - --build_dir "cmake_build/x64-windows" ` - --skip_submodule_sync ` - --skip_tests ` - --compile_no_warning_as_error ` - --parallel ` - --path_to_protoc_exe "${{ steps.protoc-detect.outputs.protoc_path }}" ` - --use_vcpkg ` - --cmake_extra_defines "CMAKE_TOOLCHAIN_FILE:FILEPATH=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" ` - --cmake_extra_defines "VCPKG_TARGET_TRIPLET=x64-windows" ` - --cmake_extra_defines "VCPKG_INSTALLED_DIR:PATH=${{ github.workspace }}/.build" ` - --cmake_extra_defines "VCPKG_INSTALL_OPTIONS=--x-feature=tests" - env: - VCPKG_OVERLAY_TRIPLETS: "${{ github.workspace }}/cmake/vcpkg-triplets/default" - shell: pwsh - - - name: "Run vcpkg(arm64-windows)" - uses: lukka/run-vcpkg@v11 - with: - vcpkgDirectory: "C:/vcpkg" # use VCPKG_INSTALLATION_ROOT of the image - doNotUpdateVcpkg: true - runVcpkgInstall: true # vcpkg install --x-manifest-root cmake --x-install-root .build --overlay-triplets cmake/vcpkg-triplets/default - vcpkgJsonGlob: "cmake/vcpkg.json" - vcpkgConfigurationJsonGlob: "cmake/vcpkg-configuration.json" - env: - VCPKG_INSTALLED_DIR: "${{ github.workspace }}/.build" - VCPKG_DEFAULT_TRIPLET: "arm64-windows" - VCPKG_OVERLAY_TRIPLETS: "${{ github.workspace }}/cmake/vcpkg-triplets/default" - # VCPKG_BINARY_SOURCES: "default" # https://learn.microsoft.com/en-us/vcpkg/reference/binarycaching - - - name: "Run build.py(arm64-windows)" - run: | - python tools\ci_build\build.py ` - --build_dir "cmake_build/arm64-windows" --arm64 ` - --skip_submodule_sync ` - --skip_tests ` - --compile_no_warning_as_error ` - --parallel ` - --path_to_protoc_exe "${{ steps.protoc-detect.outputs.protoc_path }}" ` - --use_vcpkg ` - --cmake_extra_defines "CMAKE_TOOLCHAIN_FILE:FILEPATH=C:/vcpkg/scripts/buildsystems/vcpkg.cmake" ` - --cmake_extra_defines "VCPKG_TARGET_TRIPLET=arm64-windows" ` - --cmake_extra_defines "VCPKG_INSTALLED_DIR:PATH=${{ github.workspace }}/.build" ` - --cmake_extra_defines "VCPKG_INSTALL_OPTIONS=--x-feature=tests" - env: - VCPKG_OVERLAY_TRIPLETS: "${{ github.workspace }}/cmake/vcpkg-triplets/default" - shell: pwsh diff --git a/.github/workflows/windows_build_x64_asan.yml b/.github/workflows/windows_build_x64_asan.yml new file mode 100644 index 0000000000000..265ea2bf8dcab --- /dev/null +++ b/.github/workflows/windows_build_x64_asan.yml @@ -0,0 +1,47 @@ +# .github/workflows/build_x64_asan.yml +name: windows_x64_asan + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + build_x64: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-mms", + "JobId=windows-build-x64-asan-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env # Use the composite action + with: + architecture: x64 + + - name: Build and Test (Combined) + shell: cmd + run: | + @echo off + echo %PATH% + python -m pip install -r "%GITHUB_WORKSPACE%\tools\ci_build/github/windows\python\requirements.txt" + python "%GITHUB_WORKSPACE%\tools\ci_build\build.py" --config Debug --build_dir "%RUNNER_TEMP%\build" --skip_submodule_sync --parallel --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_generator "Visual Studio 17 2022" --disable_memleak_checker --enable_address_sanitizer diff --git a/.github/workflows/windows_cuda.yml b/.github/workflows/windows_cuda.yml new file mode 100644 index 0000000000000..852d0164083c4 --- /dev/null +++ b/.github/workflows/windows_cuda.yml @@ -0,0 +1,256 @@ +name: ONNX Runtime CUDA Builds + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +#TODO: enable --build_nodejs +jobs: + build: + name: Windows GPU CUDA CI Pipeline + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=windows-cuda-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: 'none' + + - uses: actions/setup-python@v6 + with: + python-version: '3.14' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r .\tools\ci_build\github\windows\python\requirements.txt + working-directory: ${{ github.workspace }} + shell: cmd + + - name: Download CUDA SDK v12.8 + working-directory: ${{ runner.temp }} + run: | + azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v12.8" . + dir + shell: pwsh + + - name: Add CUDA to PATH + shell: powershell + run: | + Write-Host "Adding CUDA to PATH" + Write-Host "CUDA Path: $env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\extras\CUPTI\lib64" + + - uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - uses: actions/cache@v5 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + + - name: API Documentation Check and generate + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + shell: cmd + + - uses: actions/setup-dotnet@v5 + env: + PROCESSOR_ARCHITECTURE: x64 + with: + dotnet-version: '8.x' + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + run: nuget restore ${{ github.workspace }}\packages.config -ConfigFile ${{ github.workspace }}\NuGet.config -PackagesDirectory ${{ runner.temp }}\build\RelWithDebInfo + shell: cmd + + - name: Set OnnxRuntimeBuildDirectory + shell: pwsh + run: | + $buildDir = Join-Path ${{ runner.temp }} "build" + echo "OnnxRuntimeBuildDirectory=$buildDir" >> $env:GITHUB_ENV + + - name: Build and Clean Binaries + working-directory: ${{ runner.temp }} + run: | + npm install -g typescript + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + # Execute the build process + python.exe ${{ github.workspace }}\tools\ci_build\build.py --update --build --config RelWithDebInfo --build_dir build --skip_submodule_sync --build_csharp --parallel --nvcc_threads 1 --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --build_wheel --build_java --use_cuda --cuda_home="$env:RUNNER_TEMP\v12.8" --enable_cuda_profiling --use_vcpkg --use_vcpkg_ms_internal_asset_cache --enable_transformers_tool_test --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 --cmake_extra_defines onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + + # Clean up the output directory before uploading artifacts + $outputDir = "${{ runner.temp }}\build\RelWithDebInfo" + Write-Host "Cleaning up files from $outputDir..." + + Remove-Item -Path "$outputDir\onnxruntime" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\pybind11" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\models" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\vcpkg_installed" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\_deps" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\CMakeCache.txt" -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\CMakeFiles" -Recurse -Force -ErrorAction SilentlyContinue + # Remove intermediate object files as in the original script + Remove-Item -Path $outputDir -Include "*.obj" -Recurse + shell: pwsh + + - name: Upload build artifacts + uses: actions/upload-artifact@v6 + with: + name: build-artifacts + path: ${{ runner.temp }}\build + env: + OrtPackageId: Microsoft.ML.OnnxRuntime.Gpu + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: false + ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 + + test: + name: Windows GPU CUDA CI Pipeline Test Job + needs: build + timeout-minutes: 300 + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Win2022-GPU-A10", + "JobId=windows-cuda-test-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: 'none' + + - name: Download build artifacts + uses: actions/download-artifact@v7 + with: + name: build-artifacts + path: ${{ runner.temp }}\build + + - uses: actions/setup-python@v6 + with: + python-version: '3.14' + architecture: x64 + + - uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r .\tools\ci_build\github\windows\python\requirements.txt + working-directory: ${{ github.workspace }} + shell: cmd + + - name: Download CUDA SDK v12.8 + working-directory: ${{ runner.temp }} + run: | + azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v12.8" . + dir + shell: pwsh + + - name: Add CUDA to PATH + shell: powershell + run: | + Write-Host "Adding CUDA to PATH" + Write-Host "CUDA Path: $env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\extras\CUPTI\lib64" + + - name: Set OnnxRuntimeBuildDirectory + shell: pwsh + run: | + $buildDir = Join-Path ${{ runner.temp }} "build" + echo "OnnxRuntimeBuildDirectory=$buildDir" >> $env:GITHUB_ENV + + - name: Install ONNX Runtime Wheel + uses: ./.github/actions/install-onnxruntime-wheel + with: + whl-directory: ${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo\dist + + - name: Run Tests + working-directory: ${{ runner.temp }} + run: | + npm install -g typescript + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + + python.exe ${{ github.workspace }}\tools\python\update_ctest_path.py "${{ runner.temp }}\build\RelWithDebInfo\CTestTestfile.cmake" "${{ runner.temp }}\build\RelWithDebInfo" + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + + python.exe ${{ github.workspace }}\tools\ci_build\build.py --test --config RelWithDebInfo --build_dir build --skip_submodule_sync --build_csharp --parallel --nvcc_threads 1 --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --build_wheel --build_java --use_cuda --cuda_home="$env:RUNNER_TEMP\v12.8" --enable_cuda_profiling --use_vcpkg --use_vcpkg_ms_internal_asset_cache --enable_transformers_tool_test --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 --cmake_extra_defines onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS=ON + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + shell: pwsh + + - name: Validate C# native delegates + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\csharp + shell: cmd + env: + OrtPackageId: Microsoft.ML.OnnxRuntime.Gpu + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: false + ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 diff --git a/.github/workflows/windows_cuda_plugin.yml b/.github/workflows/windows_cuda_plugin.yml new file mode 100644 index 0000000000000..07083a5caa08a --- /dev/null +++ b/.github/workflows/windows_cuda_plugin.yml @@ -0,0 +1,208 @@ +name: CUDA Plugin Windows CI + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + build: + name: Windows CUDA Plugin EP Build + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=windows-cuda-plugin-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: 'none' + + - uses: actions/setup-python@v6 + with: + python-version: '3.14' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r .\tools\ci_build\github\windows\python\requirements.txt + working-directory: ${{ github.workspace }} + shell: cmd + + - name: Download CUDA SDK v12.8 + working-directory: ${{ runner.temp }} + run: | + azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v12.8" . + dir + shell: pwsh + + - name: Add CUDA to PATH + shell: powershell + run: | + Write-Host "Adding CUDA to PATH" + Write-Host "CUDA Path: $env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\extras\CUPTI\lib64" + + - name: Set OnnxRuntimeBuildDirectory + shell: pwsh + run: | + $buildDir = Join-Path ${{ runner.temp }} "build" + echo "OnnxRuntimeBuildDirectory=$buildDir" >> $env:GITHUB_ENV + + - name: Build ONNX Runtime with CUDA Plugin EP + working-directory: ${{ runner.temp }} + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py ` + --update --build --config Release ` + --build_dir build ` + --skip_submodule_sync ` + --parallel ` + --nvcc_threads 1 ` + --use_binskim_compliant_compile_flags ` + --cmake_generator "Visual Studio 17 2022" ` + --build_shared_lib ` + --build_wheel ` + --use_cuda ` + --cuda_home="$env:RUNNER_TEMP\v12.8" ` + --skip_tests ` + --use_vcpkg ` + --use_vcpkg_ms_internal_asset_cache ` + --enable_cuda_profiling ` + --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 ` + --cmake_extra_defines onnxruntime_BUILD_CUDA_EP_AS_PLUGIN=ON + + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + + # Clean up intermediate files before uploading artifacts + $outputDir = "${{ runner.temp }}\build\Release" + Write-Host "Cleaning up files from $outputDir..." + + Remove-Item -Path "$outputDir\onnxruntime" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\pybind11" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\models" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\vcpkg_installed" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\_deps" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\CMakeCache.txt" -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\CMakeFiles" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path $outputDir -Include "*.obj" -Recurse + shell: pwsh + + - name: Upload build artifacts + uses: actions/upload-artifact@v6 + with: + name: cuda-plugin-build-artifacts + path: ${{ runner.temp }}\build + env: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 + + test: + name: Windows CUDA Plugin EP Test + needs: build + timeout-minutes: 120 + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Win2022-GPU-A10", + "JobId=windows-cuda-plugin-test-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: 'none' + + - name: Download build artifacts + uses: actions/download-artifact@v7 + with: + name: cuda-plugin-build-artifacts + path: ${{ runner.temp }}\build + + - uses: actions/setup-python@v6 + with: + python-version: '3.14' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r .\tools\ci_build\github\windows\python\requirements.txt + working-directory: ${{ github.workspace }} + shell: cmd + + - name: Install torch for CPU only + run: python -m pip install torch + working-directory: ${{ github.workspace }} + shell: cmd + + - name: Download CUDA SDK v12.8 + working-directory: ${{ runner.temp }} + run: | + azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v12.8" . + dir + shell: pwsh + + - name: Add CUDA to PATH + shell: powershell + run: | + Write-Host "Adding CUDA to PATH" + Write-Host "CUDA Path: $env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\extras\CUPTI\lib64" + + - name: Set OnnxRuntimeBuildDirectory + shell: pwsh + run: | + $buildDir = Join-Path ${{ runner.temp }} "build" + echo "OnnxRuntimeBuildDirectory=$buildDir" >> $env:GITHUB_ENV + + - name: Install ONNX Runtime Wheel + uses: ./.github/actions/install-onnxruntime-wheel + with: + whl-directory: ${{ runner.temp }}\build\Release\Release\dist + + - name: Run CUDA Plugin EP Python Tests + working-directory: ${{ github.workspace }}\onnxruntime\test\python\transformers + shell: pwsh + run: | + $env:ORT_CUDA_PLUGIN_PATH = "${{ runner.temp }}\build\Release\Release\onnxruntime_providers_cuda_plugin.dll" + Write-Host "ORT_CUDA_PLUGIN_PATH=$env:ORT_CUDA_PLUGIN_PATH" + if (-not (Test-Path $env:ORT_CUDA_PLUGIN_PATH)) { + Write-Error "CUDA plugin EP library not found at $env:ORT_CUDA_PLUGIN_PATH" + exit 1 + } + python test_cuda_plugin_ep.py + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + env: + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 diff --git a/.github/workflows/windows_dml.yml b/.github/workflows/windows_dml.yml new file mode 100644 index 0000000000000..de5eebdc86da0 --- /dev/null +++ b/.github/workflows/windows_dml.yml @@ -0,0 +1,113 @@ +name: ONNX Runtime DirectML Builds + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + build_x64_RelWithDebInfo: + name: Windows GPU DML CI Pipeline + env: + OrtPackageId: Microsoft.ML.OnnxRuntime.DirectML + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: false + ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Win2022-GPU-A10", + "JobId=windows-dml-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 # Fetch all history for all tags and branches + submodules: 'none' + + - uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r .\tools\ci_build\github\windows\python\requirements.txt + working-directory: ${{ github.workspace }} + shell: cmd + + - uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + shell: cmd + + - uses: actions/setup-dotnet@v5 + env: + PROCESSOR_ARCHITECTURE: x64 + with: + dotnet-version: '8.x' + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + run: nuget restore ${{ github.workspace }}\packages.config -ConfigFile ${{ github.workspace }}\NuGet.config -PackagesDirectory ${{ github.workspace }}\RelWithDebInfo + shell: cmd + + - name: Set OnnxRuntimeBuildDirectory + shell: pwsh + run: | + $buildDir = Join-Path ${{ runner.temp }} "build" + echo "OnnxRuntimeBuildDirectory=$buildDir" >> $env:GITHUB_ENV + + - name: Build and Test + working-directory: ${{ runner.temp }} + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir build --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --skip_onnx_tests --build_wheel --use_dml --enable_wcos --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + Remove-Item "${{ github.workspace }}\RelWithDebInfo" -Include "*.obj" -Recurse + shell: pwsh + + - name: Validate C# native delegates + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\csharp + shell: cmd + + - name: Install ONNX Runtime Wheel + uses: ./.github/actions/install-onnxruntime-wheel + with: + whl-directory: ${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo\dist diff --git a/.github/workflows/windows_gpu_doc_gen.yml b/.github/workflows/windows_gpu_doc_gen.yml new file mode 100644 index 0000000000000..5e50a970875fc --- /dev/null +++ b/.github/workflows/windows_gpu_doc_gen.yml @@ -0,0 +1,167 @@ +name: ONNX Runtime Windows GPU Doc Gen CI + +on: + push: + branches: + - main + - rel-* + paths: + - '**' + - '!docs/**' + - 'docs/OperatorKernels.md' + - 'docs/ContribOperators.md' + - '!README.md' + - '!CONTRIBUTING.md' + - '!BUILD.md' + - '!js/web/**' + - '!onnxruntime/core/providers/js/**' + pull_request: + branches: + - main + - rel-* + paths: + - '**' + - '!docs/**' + - 'docs/OperatorKernels.md' + - 'docs/ContribOperators.md' + - '!README.md' + - '!CONTRIBUTING.md' + - '!BUILD.md' + - '!js/web/**' + - '!onnxruntime/core/providers/js/**' + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + kernel_documentation: + name: Windows GPU Kernel Documentation Validation + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Win2022-GPU-A10", + "JobId=windows-gpu-doc-gen-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 300 + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: 'none' + + - uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r .\tools\ci_build\github\windows\python\requirements.txt + working-directory: ${{ github.workspace }} + shell: cmd + + - name: Download CUDA SDK v12.8 + working-directory: ${{ runner.temp }} + run: | + azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v12.8" . + dir + shell: pwsh + + - name: Add CUDA to PATH + shell: powershell + run: | + Write-Host "Adding CUDA to PATH" + Write-Host "CUDA Path: $env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\extras\CUPTI\lib64" + + - uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + shell: cmd + + - uses: actions/setup-dotnet@v5 + env: + PROCESSOR_ARCHITECTURE: x64 + with: + dotnet-version: '8.x' + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + run: nuget restore ${{ github.workspace }}\packages.config -ConfigFile ${{ github.workspace }}\NuGet.config -PackagesDirectory ${{ runner.temp }}\build\RelWithDebInfo + shell: cmd + + - name: Set OnnxRuntimeBuildDirectory + shell: pwsh + run: | + $buildDir = Join-Path ${{ runner.temp }} "build" + echo "OnnxRuntimeBuildDirectory=$buildDir" >> $env:GITHUB_ENV + + - name: Build + working-directory: ${{ runner.temp }} + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir build --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --update --build --gen_doc validate --skip_tests --build_wheel --use_dml --use_cuda --cuda_home="$env:RUNNER_TEMP\v12.8" --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + Remove-Item "${{ runner.temp }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + shell: pwsh + + - name: Validate C# native delegates + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\csharp + shell: cmd + + - name: Install ONNX Runtime Wheel + uses: ./.github/actions/install-onnxruntime-wheel + with: + whl-directory: ${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo\dist + + - name: Generate and validate documentation + working-directory: ${{ runner.temp }}\build + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir ${{ runner.temp }}\build --gen_doc validate + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + shell: pwsh + + - name: Upload updated documentation + if: failure() + uses: actions/upload-artifact@v6 + with: + name: updated-docs + path: | + ${{ github.workspace }}/docs/OperatorKernels.md + ${{ github.workspace }}/docs/ContribOperators.md diff --git a/.github/workflows/windows_openvino.yml b/.github/workflows/windows_openvino.yml new file mode 100644 index 0000000000000..52581c7d0a5f5 --- /dev/null +++ b/.github/workflows/windows_openvino.yml @@ -0,0 +1,169 @@ +name: Windows OpenVINO CI Pipeline + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + BUILD_OPENVINO_EP: + name: Windows OpenVINO CI Pipeline + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=BUILD_OPENVINO_EP-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 240 + env: + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 + OnnxRuntimeBuildDirectory: ${{ github.workspace }} + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '1' + BuildConfig: RelWithDebInfo + buildArch: x64 + + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: none + + - name: Setup Python 3.12 + uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 #Keep x64, because the original pipeline is for x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Download OpenVINO Toolkit v2026.1.0 + env: + OpenVINOVersion: 2026.1.0 + shell: pwsh + run: | + $Url ="https://storage.openvinotoolkit.org/repositories/openvino/packages/2026.1/windows_vc_mt/openvino_toolkit_windows_vc_mt_2026.1.0.21367.63e31528c62_x86_64.zip" + $OutputPath = "$env:RUNNER_TEMP\openvino.zip" + $ExtractPath = "$env:RUNNER_TEMP\openvino-v$env:OpenVINOVersion" + $TempExtractPath = "$env:RUNNER_TEMP\openvino_temp" + + # Ensure directories exist + if (Test-Path $ExtractPath) { + Remove-Item -Recurse -Force $ExtractPath + } + New-Item -ItemType Directory -Path $ExtractPath | Out-Null + New-Item -ItemType Directory -Path $TempExtractPath | Out-Null + + # Download OpenVINO ZIP + Write-Output "Downloading OpenVINO" + Invoke-WebRequest -Uri $Url -OutFile $OutputPath + + # Extract to temporary directory first + Write-Output "Extracting OpenVINO to a temporary directory" + Expand-Archive -Path $OutputPath -DestinationPath $TempExtractPath -Force + + # Locate the nested subdirectory + $InnerFolder = Get-ChildItem -Path $TempExtractPath -Directory | Select-Object -First 1 + + if ($InnerFolder) { + Write-Output "Moving extracted files to final destination" + Move-Item -Path "$($InnerFolder.FullName)\*" -Destination $ExtractPath -Force + } else { + Write-Error "Extraction failed: No expected subdirectory found in $TempExtractPath." + Write-Error "The archive may not have extracted correctly, or its structure is different than expected." + exit 1 + } + + # Clean up temporary files + Remove-Item -Recurse -Force $TempExtractPath + Remove-Item -Force $OutputPath + + # Confirm success + Write-Output "OpenVINO extracted to $ExtractPath" + + - name: Set OpenVINORootDir + shell: pwsh + # Use $GITHUB_ENV to set the variable for subsequent steps + run: | + $openVinoRootDir = Join-Path $env:RUNNER_TEMP "openvino-v2026.1.0" + echo "OpenVINORootDir=$openVinoRootDir" >> $env:GITHUB_ENV + + - name: Print OpenVINORootDir after downloading OpenVINO + shell: cmd + run: 'echo %OpenVINORootDir%' + + - name: Print contents of OpenVINO Toolkit + shell: cmd + run: 'dir %OpenVINORootDir%' + + - name: Set up OpenVINO environment + shell: pwsh + run: | + Write-Output "Setting up OpenVINO environment variables" + . "$env:OpenVINORootDir\setupvars.ps1" + + Write-Output "Exporting selected environment variables to pipeline" + + $vars = @( + "INTEL_OPENVINO_DIR", + "OpenVINO_DIR", + "OpenVINOGenAI_DIR", + "OPENVINO_LIB_PATHS", + "TBB_DIR", + "PATH", + "PYTHONPATH" + ) + + foreach ($var in $vars) { + if (Test-Path "Env:$var") { + $value = [System.Environment]::GetEnvironmentVariable($var, "Process") + Write-Output "Setting $var=$value" + echo "$var=$value" >> $env:GITHUB_ENV # Append to GITHUB_ENV + } else { + Write-Output "Warning: $var is not set." + } + } + + Write-Output "Selected environment variables exported successfully" + + + + - name: Generate onnxruntime.sln + shell: pwsh + working-directory: ${{ runner.temp }} + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config ${{ env.BuildConfig }} --build_dir build --cmake_generator "Visual Studio 17 2022" --build_shared_lib --use_openvino CPU --use_binskim_compliant_compile_flags --update --parallel + + - name: Build + shell: pwsh + working-directory: ${{ runner.temp }} + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config ${{ env.BuildConfig }} --build_dir build --cmake_generator "Visual Studio 17 2022" --build_shared_lib --use_openvino CPU --use_binskim_compliant_compile_flags --build --parallel + + + - name: Run unit tests + shell: pwsh + working-directory: ${{ runner.temp }} + run: | + python "${{ github.workspace }}\tools\ci_build\build.py" ` + --config "${{ env.BuildConfig }}" ` + --build_dir build ` + --cmake_generator "Visual Studio 17 2022" ` + --build_shared_lib ` + --use_openvino CPU ` + --use_binskim_compliant_compile_flags ` + --test --enable_onnx_tests diff --git a/.github/workflows/windows_qnn_x64.yml b/.github/workflows/windows_qnn_x64.yml new file mode 100644 index 0000000000000..35c620ca6f650 --- /dev/null +++ b/.github/workflows/windows_qnn_x64.yml @@ -0,0 +1,86 @@ +name: Windows x64 QNN CI Pipeline + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + build_test_qnn_ep: + name: Windows x64 QNN CI Pipeline (${{ matrix.QnnLibKind }}) + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=build_test_qnn_ep-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}-${{matrix.QnnLibKind}}" + ] + timeout-minutes: 120 + strategy: + matrix: + QnnLibKind: [shared_lib, static_lib] + env: + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '1' + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Download QNN SDK + working-directory: ${{ runner.temp }} + run: | + azcopy.exe cp --recursive https://lotusscus.blob.core.windows.net/models/qnnsdk/qnn-v2.42.0.251225 . + dir + shell: pwsh + + - name: Set QNN_SDK_ROOT environment variable + shell: pwsh + run: | + $qnn_sdk_path = Join-Path $env:RUNNER_TEMP "qnn-v2.42.0.251225" + echo "QNN_SDK_ROOT=$qnn_sdk_path" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append + echo "QNN SDK Root: $qnn_sdk_path" + dir $qnn_sdk_path + + - name: Build and Test + shell: cmd + run: | + python ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir ${{ runner.temp }}\build --cmake_generator "Visual Studio 17 2022" --build_java --build_shared_lib --use_qnn ${{ matrix.QnnLibKind }} --qnn_home %QNN_SDK_ROOT% --use_binskim_compliant_compile_flags --update --build --test --enable_onnx_tests --parallel + + - name: Run ONNX Tests + shell: cmd + working-directory: ${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo + run: | + .\onnx_test_runner -j 1 -e qnn -i "backend_path|%QNN_SDK_ROOT%\lib\x86_64-windows-msvc\QnnCpu.dll" ${{ github.workspace }}\cmake\external\onnx\onnx\backend\test\data\node + + - name: Run float32 model tests + shell: cmd + working-directory: ${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo + run: | + rem This step assumes the model data exists at C:\data\float32_models on the runner + if exist C:\data\float32_models ( + .\onnx_test_runner -j 1 -e qnn -i "backend_path|%QNN_SDK_ROOT%\lib\x86_64-windows-msvc\QnnCpu.dll" C:\data\float32_models + ) else ( + echo "Skipping float32 model tests: C:\data\float32_models not found." + ) diff --git a/.github/workflows/windows_tensorrt.yml b/.github/workflows/windows_tensorrt.yml new file mode 100644 index 0000000000000..0a47f46aa8516 --- /dev/null +++ b/.github/workflows/windows_tensorrt.yml @@ -0,0 +1,268 @@ +name: Windows GPU TensorRT CI Pipeline + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +#TODO: enable --build_nodejs +jobs: + build: + name: Windows GPU TensorRT CI Pipeline + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=windows-tensorrt-build-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: 'none' + + - uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r .\tools\ci_build\github\windows\python\requirements.txt + working-directory: ${{ github.workspace }} + shell: cmd + + - name: Download CUDA SDK v12.8 + working-directory: ${{ runner.temp }} + run: | + azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v12.8" . + dir + shell: pwsh + + - name: Download TensorRT-10.14.1.48.Windows.win10.cuda-12.9 + run: 'azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/local/TensorRT-10.14.1.48.Windows.win10.cuda-12.9" ${{ runner.temp }}' + shell: pwsh + + - name: Add CUDA to PATH + shell: powershell + run: | + Write-Host "Adding CUDA to PATH" + Write-Host "CUDA Path: $env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\extras\CUPTI\lib64" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\TensorRT-10.14.1.48.Windows.win10.cuda-12.9\lib" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\TensorRT-10.14.1.48.Windows.win10.cuda-12.9\bin" + + - uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - uses: actions/cache@v5 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + + - name: API Documentation Check and generate + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + shell: cmd + + - uses: actions/setup-dotnet@v5 + env: + PROCESSOR_ARCHITECTURE: x64 + with: + dotnet-version: '8.x' + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + run: nuget restore ${{ github.workspace }}\packages.config -ConfigFile ${{ github.workspace }}\NuGet.config -PackagesDirectory ${{ runner.temp }}\build\RelWithDebInfo + shell: cmd + + - name: Set OnnxRuntimeBuildDirectory + shell: pwsh + run: | + $buildDir = Join-Path ${{ runner.temp }} "build" + echo "OnnxRuntimeBuildDirectory=$buildDir" >> $env:GITHUB_ENV + + - name: Build and Clean Binaries + working-directory: ${{ runner.temp }} + run: | + npm install -g typescript + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + # Execute the build process + python ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --parallel --nvcc_threads 1 --use_binskim_compliant_compile_flags --build_dir build --skip_submodule_sync --build_shared_lib --build --update --cmake_generator "Visual Studio 17 2022" --build_wheel --enable_onnx_tests --use_tensorrt --tensorrt_home="${{ runner.temp }}\TensorRT-10.14.1.48.Windows.win10.cuda-12.9" --cuda_home="${{ runner.temp }}\v12.8" --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + + # Clean up the output directory before uploading artifacts + $outputDir = "${{ runner.temp }}\build\RelWithDebInfo" + Write-Host "Cleaning up files from $outputDir..." + + Remove-Item -Path "$outputDir\onnxruntime" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\pybind11" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\models" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\vcpkg_installed" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\_deps" -Recurse -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\CMakeCache.txt" -Force -ErrorAction SilentlyContinue + Remove-Item -Path "$outputDir\CMakeFiles" -Recurse -Force -ErrorAction SilentlyContinue + # Remove intermediate object files as in the original script + Remove-Item -Path $outputDir -Include "*.obj" -Recurse + shell: pwsh + + - name: Upload build artifacts + uses: actions/upload-artifact@v6 + with: + name: build-artifacts + path: ${{ runner.temp }}\build + env: + OrtPackageId: Microsoft.ML.OnnxRuntime.Gpu + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: false + ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 + + test: + name: Windows GPU TensorRT CI Pipeline Test Job + needs: build + timeout-minutes: 300 + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Win2022-GPU-A10", + "JobId=windows-tensorrt-test-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: 'none' + + - name: Download build artifacts + uses: actions/download-artifact@v7 + with: + name: build-artifacts + path: ${{ runner.temp }}\build + + - uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 + + - uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r .\tools\ci_build\github\windows\python\requirements.txt + working-directory: ${{ github.workspace }} + shell: cmd + + - name: Download CUDA SDK v12.8 + working-directory: ${{ runner.temp }} + run: | + azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/cuda_sdk/v12.8" . + dir + shell: pwsh + + - name: Download TensorRT-10.14.1.48.Windows.win10.cuda-12.9 + run: 'azcopy.exe cp --recursive "https://lotusscus.blob.core.windows.net/models/local/TensorRT-10.14.1.48.Windows.win10.cuda-12.9" ${{ runner.temp }}' + shell: pwsh + + - name: Add CUDA to PATH + shell: powershell + run: | + Write-Host "Adding CUDA to PATH" + Write-Host "CUDA Path: $env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\bin" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\v12.8\extras\CUPTI\lib64" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\TensorRT-10.14.1.48.Windows.win10.cuda-12.9\lib" + Add-Content -Path $env:GITHUB_PATH -Value "$env:RUNNER_TEMP\TensorRT-10.14.1.48.Windows.win10.cuda-12.9\bin" + + - name: Set OnnxRuntimeBuildDirectory + shell: pwsh + run: | + $buildDir = Join-Path ${{ runner.temp }} "build" + echo "OnnxRuntimeBuildDirectory=$buildDir" >> $env:GITHUB_ENV + + - name: Install ONNX Runtime Wheel + uses: ./.github/actions/install-onnxruntime-wheel + with: + whl-directory: ${{ runner.temp }}\build\RelWithDebInfo\RelWithDebInfo\dist + + - name: Run Tests + working-directory: ${{ runner.temp }} + run: | + npm install -g typescript + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + + python.exe ${{ github.workspace }}\tools\python\update_ctest_path.py "${{ runner.temp }}\build\RelWithDebInfo\CTestTestfile.cmake" "${{ runner.temp }}\build\RelWithDebInfo" + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + + python ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --use_binskim_compliant_compile_flags --parallel --nvcc_threads 1 --build_dir build --skip_submodule_sync --build_shared_lib --test --cmake_generator "Visual Studio 17 2022" --build_wheel --enable_onnx_tests --use_tensorrt --tensorrt_home="${{ runner.temp }}\TensorRT-10.14.1.48.Windows.win10.cuda-12.9" --cuda_home="${{ runner.temp }}\v12.8" --use_vcpkg --use_vcpkg_ms_internal_asset_cache --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES=86 + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + shell: pwsh + + - name: Validate C# native delegates + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\csharp + shell: cmd + env: + OrtPackageId: Microsoft.ML.OnnxRuntime.Gpu + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: false + ONNXRUNTIME_TEST_GPU_DEVICE_ID: '0' + AZCOPY_AUTO_LOGIN_TYPE: MSI + AZCOPY_MSI_CLIENT_ID: 63b63039-6328-442f-954b-5a64d124e5b4 diff --git a/.github/workflows/windows_webgpu.yml b/.github/workflows/windows_webgpu.yml new file mode 100644 index 0000000000000..92eca56507d46 --- /dev/null +++ b/.github/workflows/windows_webgpu.yml @@ -0,0 +1,377 @@ +name: ONNX Runtime WebGPU Builds + +on: + push: + branches: + - main + - rel-* + pull_request: + branches: + - main + - rel-* + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + webgpu_build_x64_RelWithDebInfo: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Win2022-GPU-A10", + "JobId=webgpu_build_x64_RelWithDebInfo-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}-${{ matrix.vcpkg_option }}-${{ matrix.wgsl_template }}" + ] + timeout-minutes: 300 + strategy: + matrix: + vcpkg_option: [novcpkg, vcpkg] + wgsl_template: [static, dynamic] + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }} + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: "0" + DocUpdateNeeded: false + NVIDIA_TF32_OVERRIDE: "0" + ONNXRUNTIME_TEST_GPU_DEVICE_ID: "0" + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: none + + - name: Setup Python 3.12 + uses: actions/setup-python@v6 + with: + python-version: "3.12" + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r tools\ci_build\github\windows\python\requirements.txt + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: "20.x" + + - name: Setup Java + uses: actions/setup-java@v5 + with: + distribution: "temurin" + java-version: "17" + architecture: x64 + + - name: API Documentation Check and generate + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + env: + PROCESSOR_ARCHITECTURE: x64 + with: + dotnet-version: "8.x" + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: "6.x" + + - name: NuGet restore + run: | + nuget restore packages.config -ConfigFile NuGet.config -PackagesDirectory ${{ github.workspace }}\RelWithDebInfo + shell: cmd + working-directory: ${{ github.workspace }} + + - uses: actions/cache@v5 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + + - name: Build and Test + shell: pwsh + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py ` + --config RelWithDebInfo ` + --build_dir ${{ github.workspace }} ` + --skip_submodule_sync ` + --build_csharp ` + --parallel ` + --use_binskim_compliant_compile_flags ` + --cmake_generator "Visual Studio 17 2022" ` + --build_shared_lib ` + --enable_onnx_tests ` + --build_nodejs ` + --build_java ` + --use_webgpu ` + --wgsl_template ${{ matrix.wgsl_template }} ` + ${{ matrix.vcpkg_option == 'vcpkg' && '--use_vcpkg --use_vcpkg_ms_internal_asset_cache' || '' }} ` + --cmake_extra_defines ` + onnxruntime_BUILD_UNIT_TESTS=ON ` + onnxruntime_BUILD_DAWN_SHARED_LIBRARY=ON + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + Remove-Item "${{ github.workspace }}\RelWithDebInfo" -Include "*.obj" -Recurse + + - name: Run tests (onnxruntime_test_all, onnxruntime_provider_test) with verbose logging + shell: pwsh + run: | + $env:ORT_UNIT_TEST_MAIN_LOG_LEVEL = "0" + .\onnxruntime_test_all.exe 2> .\onnxruntime_test_stderr.log + .\onnxruntime_provider_test.exe 2>> .\onnxruntime_test_stderr.log + working-directory: ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + + - name: Check log file + shell: cmd + run: | + dir ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo\onnxruntime_test_stderr.log + + - name: Validate shader keys + uses: ./.github/actions/webgpu-validate-shader-key + with: + log_file_path: ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo\onnxruntime_test_stderr.log + + - name: Validate C# native delegates + run: python tools\ValidateNativeDelegateAttributes.py + shell: cmd + working-directory: ${{ github.workspace }}\csharp + continue-on-error: true + + webgpu_plugin_build_x64_RelWithDebInfo: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Win2022-GPU-A10", + "JobId=webgpu_plugin_build_x64_RelWithDebInfo-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 300 + env: + OnnxRuntimeBuildDirectory: ${{ github.workspace }} + setVcvars: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: "0" + DocUpdateNeeded: false + NVIDIA_TF32_OVERRIDE: "0" + ONNXRUNTIME_TEST_GPU_DEVICE_ID: "0" + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: none + + - name: Setup Python 3.12 + uses: actions/setup-python@v6 + with: + python-version: "3.12" + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r tools\ci_build\github\windows\python\requirements.txt + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: "20.x" + + - uses: actions/cache@v5 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + + - name: Build and Test + shell: pwsh + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py ` + --config RelWithDebInfo ` + --build_dir ${{ github.workspace }} ` + --skip_submodule_sync ` + --parallel ` + --use_binskim_compliant_compile_flags ` + --cmake_generator "Visual Studio 17 2022" ` + --enable_onnx_tests ` + --use_webgpu shared_lib ` + --wgsl_template static ` + --use_vcpkg --use_vcpkg_ms_internal_asset_cache ` + --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=ON onnxruntime_ENABLE_DAWN_BACKEND_D3D12=1 onnxruntime_ENABLE_DAWN_BACKEND_VULKAN=1 ` + --disable_rtti ` + --enable_lto + + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + + - name: Publish artifacts + uses: actions/upload-artifact@v4 + with: + name: webgpu-plugin-binaries + path: | + ${{ github.workspace }}/RelWithDebInfo/RelWithDebInfo/onnxruntime_providers_webgpu.dll + ${{ github.workspace }}/RelWithDebInfo/RelWithDebInfo/onnxruntime_providers_webgpu.pdb + ${{ github.workspace }}/RelWithDebInfo/RelWithDebInfo/dxcompiler.dll + ${{ github.workspace }}/RelWithDebInfo/RelWithDebInfo/dxil.dll + + webgpu_external_dawn_build_x64_RelWithDebInfo: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Win2022-GPU-A10", + "JobId=webgpu_external_dawn_build_x64_RelWithDebInfo-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 300 + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: none + + - name: Setup Python 3.12 + uses: actions/setup-python@v6 + with: + python-version: "3.12" + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r tools\ci_build\github\windows\python\requirements.txt + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Generate onnxruntime.sln + shell: pwsh + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir ${{ github.workspace }} --skip_submodule_sync --update --parallel --cmake_generator "Visual Studio 17 2022" --use_webgpu --use_external_dawn --skip_tests --target onnxruntime_webgpu_external_dawn_test + + - name: Build + shell: pwsh + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir ${{ github.workspace }} --skip_submodule_sync --build --parallel --cmake_generator "Visual Studio 17 2022" --use_webgpu --use_external_dawn --skip_tests --target onnxruntime_webgpu_external_dawn_test + + - name: Run tests (onnxruntime_webgpu_external_dawn_test) + run: onnxruntime_webgpu_external_dawn_test.exe + shell: cmd + working-directory: ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + + - name: Run tests (onnxruntime_webgpu_external_dawn_test) - no_proc_table + run: onnxruntime_webgpu_external_dawn_test.exe --no_proc_table + shell: cmd + working-directory: ${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + + webgpu_minimal_build_edge_build_x64_RelWithDebInfo: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-Win2022-GPU-A10", + "JobId=webgpu_minimal_build_edge_build_x64_RelWithDebInfo-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 300 + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }} + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true + ALLOW_RELEASED_ONNX_OPSET_ONLY: "0" + DocUpdateNeeded: false + ONNXRUNTIME_TEST_GPU_DEVICE_ID: "0" + steps: + - name: Checkout + uses: actions/checkout@v6 + with: + fetch-depth: 0 + submodules: none + + - name: Setup Python 3.12 + uses: actions/setup-python@v6 + with: + python-version: "3.12" + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + run: python -m pip install -r tools\ci_build\github\windows\python\requirements.txt + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: "20.x" + + - name: Setup Java + uses: actions/setup-java@v5 + with: + distribution: "temurin" + java-version: "17" + architecture: x64 + + - name: API Documentation Check and generate + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Setup .NET + uses: actions/setup-dotnet@v5 + env: + PROCESSOR_ARCHITECTURE: x64 + with: + dotnet-version: "8.x" + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: "6.x" + + - name: NuGet restore + run: | + nuget restore packages.config -ConfigFile NuGet.config -PackagesDirectory ${{ github.workspace }}\RelWithDebInfo + shell: cmd + working-directory: ${{ github.workspace }} + + - name: Build + shell: pwsh + run: | + python.exe ${{ github.workspace }}\tools\ci_build\build.py --config RelWithDebInfo --build_dir ${{ github.workspace }} --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --update --build --build_shared_lib --disable_exceptions --disable_rtti --enable_msvc_static_runtime --enable_reduced_operator_type_support --skip_tests --use_binskim_compliant_compile_flags --cmake_extra_defines onnxruntime_BUILD_UNIT_TESTS=OFF onnxruntime_DISABLE_SPARSE_TENSORS=ON onnxruntime_DISABLE_OPTIONAL_TYPE=ON --minimal_build extended --use_webgpu + if ($lastExitCode -ne 0) { + exit $lastExitCode + } + Remove-Item "${{ github.workspace }}\RelWithDebInfo" -Include "*.obj" -Recurse + + - name: Validate C# native delegates + run: python tools\ValidateNativeDelegateAttributes.py + shell: cmd + working-directory: ${{ github.workspace }}\csharp diff --git a/.github/workflows/windows_x64_debug_build_x64_debug.yml b/.github/workflows/windows_x64_debug_build_x64_debug.yml new file mode 100644 index 0000000000000..134326b8f57de --- /dev/null +++ b/.github/workflows/windows_x64_debug_build_x64_debug.yml @@ -0,0 +1,133 @@ +name: windows_x64_debug + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + build_x64_debug: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=windows-x64-debug-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env # Use the composite action + with: + architecture: x64 + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\Debug\Debug + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x64 + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 # Use the official NuGet setup action + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\Debug -ConfigFile ${{ github.workspace }}\NuGet.config + + - uses: actions/cache@v5 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + + - name: Build and Test + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --config Debug --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --build_java --build_nodejs --build_wheel --disable_memleak_checker --msbuild_extra_options "IncludeMobileTargets=false" --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\Debug" -Include "*.obj" -Recurse + env: # Set environment variables here, applies to this step only + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: 'false' # Can be set dynamically based on build output if needed + + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + + - name: Install onnxruntime wheel + shell: pwsh + run: | + python -m pip uninstall -y onnxruntime onnxruntime-gpu onnxruntime-training onnxruntime-directml -qq + Get-ChildItem -Path dist/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} + working-directory: "${{ github.workspace }}\\build\\Debug\\Debug" + + # Publish artifacts only on failure and if DocUpdateNeeded is true (example) + - name: Publish OperatorKernels.md (Conditional) + uses: actions/upload-artifact@v6 + if: failure() && env.DocUpdateNeeded == 'true' # Use env. for step-level vars + with: + name: OperatorKernels.md + path: ${{ github.workspace }}/docs/OperatorKernels.md + + - name: Publish ContribOperators.md (Conditional) + uses: actions/upload-artifact@v6 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: ContribOperators.md + path: ${{ github.workspace }}/docs/ContribOperators.md + + # These variables will persist for the entire job + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/.github/workflows/windows_x64_release_build_x64_release.yml b/.github/workflows/windows_x64_release_build_x64_release.yml new file mode 100644 index 0000000000000..7acbdcd404ad3 --- /dev/null +++ b/.github/workflows/windows_x64_release_build_x64_release.yml @@ -0,0 +1,158 @@ +name: windows_x64_release + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + build_x64_release: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=windows-x64-release-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x64 + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + + - uses: actions/cache@v5 + id: onnx-node-tests-cache + with: + path: ${{ github.workspace }}/js/test/ + key: onnxnodetests-${{ hashFiles('js/scripts/prepare-onnx-node-tests.ts') }} + + - name: Build and Test + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --config RelWithDebInfo --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --build_wheel --build_java --build_nodejs --msbuild_extra_options "IncludeMobileTargets=false" --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: 'false' + + - name: Run onnxruntime_provider_test with example_plugin_ep + shell: pwsh + run: | + # Note on skipped tests: + # The skipped tests are either: + # - relying on CPU EP fallback for BFloat16 which is not supported + # - testing the LayerNormalization contrib op with mixed input/output types (only supported by a few EPs) + # Some other hardcoded EP types are skipped in these tests. For a plugin EP, we skip these tests by + # specifying them in the dynamic plugin EP configuration. + + $env:ORT_UNIT_TEST_MAIN_DYNAMIC_PLUGIN_EP_CONFIG_JSON = @" + { + "ep_library_registration_name": "example_ep", + "ep_library_path": "./example_plugin_ep.dll", + "selected_ep_name": "example_ep", + "tests_to_skip": [ + "LayerNormTest.LayerNorm_BFloat16Input", + "LayerNormTest.LayerNorm_Scale_Float16Input", + "LayerNormTest.LayerNorm_Scale_Float16ScaleOutput", + "LayerNormTest.LayerNorm_Scale_Bias_Float16Input", + "LayerNormTest.LayerNorm_Scale_Bias_Float16ScaleBiasOutput" + ] + } + "@ + + .\onnxruntime_provider_test.exe + working-directory: ${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + + - name: Install onnxruntime wheel + shell: pwsh + run: | + python -m pip uninstall -y onnxruntime onnxruntime-gpu onnxruntime-training onnxruntime-directml -qq + Get-ChildItem -Path dist/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} + working-directory: "${{ github.workspace }}\\build\\RelWithDebInfo\\RelWithDebInfo" + + - name: Publish OperatorKernels.md (Conditional) + uses: actions/upload-artifact@v6 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: OperatorKernels.md + path: ${{ github.workspace }}/docs/OperatorKernels.md + + - name: Publish ContribOperators.md (Conditional) + uses: actions/upload-artifact@v6 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: ContribOperators.md + path: ${{ github.workspace }}/docs/ContribOperators.md + + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/.github/workflows/windows_x64_release_ep_generic_interface_build_x64_release_ep_generic_interface.yml b/.github/workflows/windows_x64_release_ep_generic_interface_build_x64_release_ep_generic_interface.yml new file mode 100644 index 0000000000000..8cb5bad664921 --- /dev/null +++ b/.github/workflows/windows_x64_release_ep_generic_interface_build_x64_release_ep_generic_interface.yml @@ -0,0 +1,115 @@ +name: windows_x64_release_ep_generic_interface + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + build_x64_release_ep_generic_interface: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=build_x64_release_ep_generic_interface-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x64 + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + + - name: Build and test + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --config RelWithDebInfo --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --update --build --test --enable_generic_interface --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + - name: Publish OperatorKernels.md (Conditional) + uses: actions/upload-artifact@v6 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: OperatorKernels.md + path: ${{ github.workspace }}/docs/OperatorKernels.md + + - name: Publish ContribOperators.md (Conditional) + uses: actions/upload-artifact@v6 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: ContribOperators.md + path: ${{ github.workspace }}/docs/ContribOperators.md + + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml b/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml new file mode 100644 index 0000000000000..a3200b21cf658 --- /dev/null +++ b/.github/workflows/windows_x64_release_vitisai_build_x64_release.yml @@ -0,0 +1,111 @@ +name: windows_x64_release_vitisai + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + build_x64_release_vitisai: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=build_x64_release_vitisai-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x64 + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + + - name: Build + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --config RelWithDebInfo --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --update --build --build_wheel --use_vitisai --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + + - name: Install onnxruntime wheel + shell: pwsh + run: | + python -m pip uninstall -y onnxruntime onnxruntime-gpu onnxruntime-training onnxruntime-directml -qq + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Get-ChildItem -Path dist/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} + working-directory: "${{ github.workspace }}\\build\\RelWithDebInfo\\RelWithDebInfo" + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/.github/workflows/windows_x64_release_xnnpack.yml b/.github/workflows/windows_x64_release_xnnpack.yml new file mode 100644 index 0000000000000..1e55bd376a7e5 --- /dev/null +++ b/.github/workflows/windows_x64_release_xnnpack.yml @@ -0,0 +1,117 @@ +name: windows_x64_release_xnnpack + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + build_x64_release_xnnpack: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=build_x64_release_xnnpack-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x64 + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x64 + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '20.x' + + - name: Setup Java + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x64 + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x64 + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + + - name: Build and Test + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --use_xnnpack --config RelWithDebInfo --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --disable_rtti --msbuild_extra_options "IncludeMobileTargets=false" --build_nuget --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: 'false' + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + + - name: Publish OperatorKernels.md (Conditional) + uses: actions/upload-artifact@v6 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: OperatorKernels.md + path: ${{ github.workspace }}/docs/OperatorKernels.md + + - name: Publish ContribOperators.md (Conditional) + uses: actions/upload-artifact@v6 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: ContribOperators.md + path: ${{ github.workspace }}/docs/ContribOperators.md + + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/.github/workflows/windows_x86.yml b/.github/workflows/windows_x86.yml new file mode 100644 index 0000000000000..897b4f712ffdd --- /dev/null +++ b/.github/workflows/windows_x86.yml @@ -0,0 +1,164 @@ +name: Windows CPU CI Pipeline + +on: + push: + branches: [main, 'rel-*'] + pull_request: + branches: [main] + workflow_dispatch: + +concurrency: + group: ${{ github.workflow }}-${{ github.event_name == 'pull_request' && github.ref || github.sha }} + cancel-in-progress: true + +jobs: + build_x86_release: + runs-on: [ + "self-hosted", + "1ES.Pool=onnxruntime-github-vs2022-latest", + "JobId=windows-x86-release-${{ github.run_id }}-${{ github.run_number }}-${{ github.run_attempt }}" + ] + timeout-minutes: 300 + + steps: + - name: Checkout repository + uses: actions/checkout@v6 + with: + submodules: false + + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: '3.12' + architecture: x86 # x86 Python + + - name: Locate vcvarsall and Setup Env + uses: ./.github/actions/locate-vcvarsall-and-setup-env + with: + architecture: x86 # x86 architecture for vcvarsall + + - name: Install python modules + shell: cmd + run: python -m pip install -r "${{ github.workspace }}\tools\ci_build\github\windows\python\requirements.txt" + + - name: Setup Node.js + uses: actions/setup-node@v6 + with: + node-version: '20.x' + architecture: x86 #Add architecture + + - name: Setup Java + uses: actions/setup-java@v5 + with: + distribution: 'temurin' + java-version: '17' + architecture: x86 # x86 Java + + - name: API Documentation Check and generate + shell: cmd + run: | + set ORT_DOXY_SRC=${{ github.workspace }} + set ORT_DOXY_OUT=${{ github.workspace }}\build\RelWithDebInfo\RelWithDebInfo + mkdir %ORT_DOXY_SRC% + mkdir %ORT_DOXY_OUT% + "C:\Program Files\doxygen\bin\doxygen.exe" ${{ github.workspace }}\tools\ci_build\github\Doxyfile_csharp.cfg + working-directory: ${{ github.workspace }} + + - name: Use .NET 8.x + uses: actions/setup-dotnet@v5 + with: + dotnet-version: '8.x' + env: + PROCESSOR_ARCHITECTURE: x86 # x86 .NET + + - name: Prefer x86 dotnet on PATH + shell: pwsh + run: | + $x86DotnetDir = 'C:\Program Files (x86)\dotnet' + $x64DotnetDir = 'C:\Program Files\dotnet' + $machinePath = [Environment]::GetEnvironmentVariable('Path', 'Machine') + Write-Host "Machine PATH: $machinePath" + + $pathEntries = @($env:PATH -split ';' | Where-Object { $_ }) + $reorderedPathEntries = @( + $x86DotnetDir + $pathEntries | Where-Object { $_ -ne $x86DotnetDir } + ) + + $env:PATH = ($reorderedPathEntries -join ';') + + # Only add the x86 dotnet directory to GITHUB_PATH if it is not already on PATH (after normalization) + $normalizedX86DotnetDir = $x86DotnetDir.TrimEnd('\') + $normalizedPathEntries = $pathEntries | ForEach-Object { $_.TrimEnd('\') } + if (-not ($normalizedPathEntries -contains $normalizedX86DotnetDir)) { + Add-Content -Path $env:GITHUB_PATH -Value $x86DotnetDir + } + $dotnetPaths = @(Get-Command dotnet -All | Select-Object -ExpandProperty Source -Unique) + Write-Host 'Resolved dotnet executables:' + $dotnetPaths | ForEach-Object { Write-Host $_ } + + $x86DotnetExe = "$x86DotnetDir\dotnet.exe" + $x64DotnetExe = "$x64DotnetDir\dotnet.exe" + $x86Index = $dotnetPaths.IndexOf($x86DotnetExe) + $x64Index = $dotnetPaths.IndexOf($x64DotnetExe) + + if ($x86Index -lt 0) { + throw "Expected x86 dotnet executable was not found: $x86DotnetExe" + } + + if ($x64Index -ge 0 -and $x86Index -gt $x64Index) { + throw "x86 dotnet must appear before x64 dotnet on PATH. Found $x86DotnetExe after $x64DotnetExe." + } + + - name: Use Nuget 6.x + uses: nuget/setup-nuget@v2 + with: + nuget-version: '6.x' + + - name: NuGet restore + shell: cmd + run: | + nuget restore ${{ github.workspace }}\packages.config -PackagesDirectory ${{ github.workspace }}\build\RelWithDebInfo -ConfigFile ${{ github.workspace }}\NuGet.config + + - name: Build and Test + shell: pwsh + run: | + python.exe "${{ github.workspace }}\tools\ci_build\build.py" --config RelWithDebInfo --build_dir "${{ github.workspace }}\build" --skip_submodule_sync --build_csharp --parallel --use_binskim_compliant_compile_flags --cmake_generator "Visual Studio 17 2022" --build_shared_lib --enable_onnx_tests --build_wheel --msbuild_extra_options "IncludeMobileTargets=false" --build_nuget --compile_no_warning_as_error --use_vcpkg --use_vcpkg_ms_internal_asset_cache + if ($LASTEXITCODE -ne 0) { + exit $LASTEXITCODE + } + Remove-Item "${{ github.workspace }}\build\RelWithDebInfo" -Include "*.obj" -Recurse + env: + ALLOW_RELEASED_ONNX_OPSET_ONLY: '0' + DocUpdateNeeded: 'false' + + - name: Validate C# native delegates + shell: cmd + run: python tools\ValidateNativeDelegateAttributes.py + working-directory: ${{ github.workspace }}\\csharp + + - name: Install onnxruntime wheel + shell: pwsh + run: | + python -m pip uninstall -y onnxruntime onnxruntime-gpu onnxruntime-training onnxruntime-directml -qq + Get-ChildItem -Path dist/*.whl | foreach {pip --disable-pip-version-check install --upgrade $_.fullname} + working-directory: "${{ github.workspace }}\\build\\RelWithDebInfo\\RelWithDebInfo" + + - name: Publish OperatorKernels.md (Conditional) + uses: actions/upload-artifact@v6 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: OperatorKernels.md + path: ${{ github.workspace }}/docs/OperatorKernels.md + + - name: Publish ContribOperators.md (Conditional) + uses: actions/upload-artifact@v6 + if: failure() && env.DocUpdateNeeded == 'true' + with: + name: ContribOperators.md + path: ${{ github.workspace }}/docs/ContribOperators.md + + env: + OrtPackageId: Microsoft.ML.OnnxRuntime + OnnxRuntimeBuildDirectory: ${{ github.workspace }}\build + DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 'true' diff --git a/.gitignore b/.gitignore index 4d0a1205b7c19..b25763334f227 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ # build, distribute, and bins (+ python proto bindings) +build.*/ build build_*/ .build_debug/* diff --git a/.gitmodules b/.gitmodules index 29ca8821f8eb8..2864085bf85bf 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,4 +7,4 @@ [submodule "cmake/external/emsdk"] path = cmake/external/emsdk url = https://github.com/emscripten-core/emsdk.git - branch = 3.1.59 + branch = 4.0.23 diff --git a/.ignore b/.ignore new file mode 100644 index 0000000000000..7dd9d36d350d4 --- /dev/null +++ b/.ignore @@ -0,0 +1,4 @@ +!/.config +!/.devcontainer +!/.github +!/.pipelines diff --git a/.lintrunner.toml b/.lintrunner.toml index 74744277fa1e3..7f6f61df59f3b 100644 --- a/.lintrunner.toml +++ b/.lintrunner.toml @@ -91,22 +91,6 @@ init_command = [ ] is_formatter = true -[[linter]] -code = 'RUSTFMT' -include_patterns = ['**/*.rs'] -command = [ - 'python', - '-m', - 'lintrunner_adapters', - 'run', - 'rustfmt_linter', - '--binary=rustfmt', - '--config-path=rust/rustfmt.toml', - '--', - '@{{PATHSFILE}}' -] -is_formatter = true - [[linter]] code = 'CLANGFORMAT' include_patterns = [ @@ -114,12 +98,15 @@ include_patterns = [ '**/*.cc', '**/*.hpp', '**/*.cpp', + '**/*.cuh', + '**/*.cu', '**/*.m', '**/*.mm', ] exclude_patterns = [ 'java/**', # FIXME: Enable clang-format for java 'onnxruntime/contrib_ops/cuda/bert/tensorrt_fused_multihead_attention/**', # Contains data chunks + 'onnxruntime/contrib_ops/cuda/llm/fpA_intB_gemm/launchers/*.generated.cu', # Generated code 'onnxruntime/core/flatbuffers/schema/*.fbs.h', # Generated code 'onnxruntime/test/flatbuffers/*.fbs.h', # Generated code 'onnxruntime/core/graph/contrib_ops/quantization_defs.cc', diff --git a/.pipelines/OneBranch.Nuget-WindowsAI-Pipeline.Official.yml b/.pipelines/OneBranch.Nuget-WindowsAI-Pipeline.Official.yml deleted file mode 100644 index 909e3dc753cff..0000000000000 --- a/.pipelines/OneBranch.Nuget-WindowsAI-Pipeline.Official.yml +++ /dev/null @@ -1,355 +0,0 @@ -parameters: -- name: UploadSymbols - displayName: Upload Symbols to Microsoft symbol server? - type: boolean - default: false - -trigger: none - -variables: - CDP_DEFINITION_BUILD_COUNT: $[counter('', 0)] - DEBIAN_FRONTEND: noninteractive - ComponentDetection.Timeout: 1200 - -resources: - repositories: - - repository: templates - type: git - name: OneBranch.Pipelines/GovernedTemplates - ref: refs/heads/main - -extends: - template: v2/OneBranch.Official.CrossPlat.yml@templates - parameters: - nugetPublishing: - feeds: - - name: PublicPackages/ORT-Nightly - files_to_publish: '*.nupkg;!*.symbols.nupkg' - continueOnConflict: true - git: - submodules: false - globalSdl: # https://aka.ms/obpipelines/sdl - asyncSdl: - enabled: false - tsa: - enabled: true - prefast: - enabled: false - cg: - failOnAlert: false - policheck: - break: true # always break the build on policheck issues. You can disable it by setting to 'false' - exclusionsFile: '$(Build.SourcesDirectory)\tools\ci_build\policheck_exclusions.xml' - # suppression: - # suppressionFile: $(Build.SourcesDirectory)\.gdn\global.gdnsuppress - - stages: - - stage: Windows_Build - jobs: - - template: .pipelines/windowsai-steps.yml@self - parameters: - BuildArch: x64 - - - template: .pipelines/windowsai-steps.yml@self - parameters: - BuildArch: x86 - PythonPackageName: pythonx86 - - - template: .pipelines/windowsai-steps.yml@self - parameters: - BuildArch: arm64 - - - template: .pipelines/windowsai-steps.yml@self - parameters: - BuildArch: x64 - Runtime: static - - - template: .pipelines/windowsai-steps.yml@self - parameters: - BuildArch: x86 - PythonPackageName: pythonx86 - Runtime: static - - - template: .pipelines/windowsai-steps.yml@self - parameters: - BuildArch: arm64 - Runtime: static - - - - job: NuGet_Packaging - pool: - type: windows - variables: - ob_outputDirectory: '$(Build.ArtifactStagingDirectory)' - ob_sdl_binskim_break: false - ob_symbolsPublishing_enabled: ${{ parameters.UploadSymbols }} - ob_symbolsPublishing_symbolsFolder: $(Build.SourcesDirectory)/unzipped - dependsOn: - - Windows_Packaging_x64_dynamic - - Windows_Packaging_x86_dynamic - - Windows_Packaging_arm64_dynamic - - Windows_Packaging_x64_static - - Windows_Packaging_x86_static - - Windows_Packaging_arm64_static - condition: succeeded() - steps: - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet DirectML x64' - inputs: - artifactName: 'drop_Windows_Build_Windows_Packaging_x64_dynamic' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact-x64' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet DirectML x86' - inputs: - artifactName: 'drop_Windows_Build_Windows_Packaging_x86_dynamic' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact-x86' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet DirectML arm64' - inputs: - artifactName: 'drop_Windows_Build_Windows_Packaging_arm64_dynamic' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact-arm64' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet DirectML x64 StaticRuntime' - inputs: - artifactName: 'drop_Windows_Build_Windows_Packaging_x64_static' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact-x64-static-runtime' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet DirectML x86 StaticRuntime' - inputs: - artifactName: 'drop_Windows_Build_Windows_Packaging_x86_static' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact-x86-static-runtime' - - - task: DownloadPipelineArtifact@0 - displayName: 'Download Pipeline Artifact - NuGet DirectML arm64 StaticRuntime' - inputs: - artifactName: 'drop_Windows_Build_Windows_Packaging_arm64_static' - targetPath: '$(Build.BinariesDirectory)/nuget-artifact-arm64-static-runtime' - - - task: PowerShell@2 - displayName: 'Bundle NuGet and other binaries' - inputs: - targetType: 'inline' - script: | - Add-Type -AssemblyName "System.IO.Compression.FileSystem" - - $nupkgs = (Get-ChildItem -Filter Microsoft.AI.MachineLearning*.nupkg -Recurse) - $x64_nuget_package_name = $nupkgs[0].Name - $x64_nuget_package = $nupkgs[0].FullName - $x64_nupkg_unzipped_directory_root = $nupkgs[0].Directory.FullName - $x64_nupkg_unzipped_directory = [System.IO.Path]::Combine($x64_nupkg_unzipped_directory_root, 'binaries', [System.IO.Path]::GetFileNameWithoutExtension($x64_nuget_package)) - [System.IO.Compression.ZipFile]::ExtractToDirectory($x64_nuget_package, $x64_nupkg_unzipped_directory) - - $nupkgs = (Get-ChildItem ..\nuget-artifact-x64-static-runtime -Filter Microsoft.AI.MachineLearning*.nupkg -Recurse) - $x64_static_runtime_nuget_package = $nupkgs[0].FullName - $x64_static_runtime_nupkg_unzipped_directory_root = $nupkgs[0].Directory.FullName - $x64_static_runtime_nupkg_unzipped_directory = [System.IO.Path]::Combine($x64_static_runtime_nupkg_unzipped_directory_root, 'binaries', [System.IO.Path]::GetFileNameWithoutExtension($x64_static_runtime_nuget_package)) - [System.IO.Compression.ZipFile]::ExtractToDirectory($x64_static_runtime_nuget_package, $x64_static_runtime_nupkg_unzipped_directory) - - $nupkgs = (Get-ChildItem ..\nuget-artifact-x86 -Filter Microsoft.AI.MachineLearning*.nupkg -Recurse) - $x86_nuget_package = $nupkgs[0].FullName - $x86_nupkg_unzipped_directory_root = $nupkgs[0].Directory.FullName - $x86_nupkg_unzipped_directory = [System.IO.Path]::Combine($x86_nupkg_unzipped_directory_root, 'binaries', [System.IO.Path]::GetFileNameWithoutExtension($x86_nuget_package)) - [System.IO.Compression.ZipFile]::ExtractToDirectory($x86_nuget_package, $x86_nupkg_unzipped_directory) - - $nupkgs = (Get-ChildItem ..\nuget-artifact-x86-static-runtime -Filter Microsoft.AI.MachineLearning*.nupkg -Recurse) - $x86_static_runtime_nuget_package = $nupkgs[0].FullName - $x86_static_runtime_nupkg_unzipped_directory_root = $nupkgs[0].Directory.FullName - $x86_static_runtime_nupkg_unzipped_directory = [System.IO.Path]::Combine($x86_static_runtime_nupkg_unzipped_directory_root, 'binaries', [System.IO.Path]::GetFileNameWithoutExtension($x86_static_runtime_nuget_package)) - [System.IO.Compression.ZipFile]::ExtractToDirectory($x86_static_runtime_nuget_package, $x86_static_runtime_nupkg_unzipped_directory) - - $nupkgs = (Get-ChildItem ..\nuget-artifact-arm64 -Filter Microsoft.AI.MachineLearning*.nupkg -Recurse) - $arm64_nuget_package = $nupkgs[0].FullName - $arm64_nupkg_unzipped_directory_root = $nupkgs[0].Directory.FullName - $arm64_nupkg_unzipped_directory = [System.IO.Path]::Combine($arm64_nupkg_unzipped_directory_root, 'binaries', [System.IO.Path]::GetFileNameWithoutExtension($arm64_nuget_package)) - [System.IO.Compression.ZipFile]::ExtractToDirectory($arm64_nuget_package, $arm64_nupkg_unzipped_directory) - - $nupkgs = (Get-ChildItem ..\nuget-artifact-arm64-static-runtime -Filter Microsoft.AI.MachineLearning*.nupkg -Recurse) - $arm64_static_runtime_nuget_package = $nupkgs[0].FullName - $arm64_static_runtime_nupkg_unzipped_directory_root = $nupkgs[0].Directory.FullName - $arm64_static_runtime_nupkg_unzipped_directory = [System.IO.Path]::Combine($arm64_static_runtime_nupkg_unzipped_directory_root, 'binaries', [System.IO.Path]::GetFileNameWithoutExtension($arm64_static_runtime_nuget_package)) - [System.IO.Compression.ZipFile]::ExtractToDirectory($arm64_static_runtime_nuget_package, $arm64_static_runtime_nupkg_unzipped_directory) - - - - $x64_static_runtime_path_old = [System.IO.Path]::Combine($x64_static_runtime_nupkg_unzipped_directory, 'runtimes', 'win-x64', '_native') - $x64_static_runtime_path_new = [System.IO.Path]::Combine($x64_nupkg_unzipped_directory, 'runtimes', 'win-x64', '_native', 'static') - $x86_runtime_path_old = [System.IO.Path]::Combine($x86_nupkg_unzipped_directory, 'runtimes', 'win-x86', '_native') - $x86_runtime_path_new = [System.IO.Path]::Combine($x64_nupkg_unzipped_directory, 'runtimes', 'win-x86', '_native') - $x86_static_runtime_path_old = [System.IO.Path]::Combine($x86_static_runtime_nupkg_unzipped_directory, 'runtimes', 'win-x86', '_native') - $x86_static_runtime_path_new = [System.IO.Path]::Combine($x64_nupkg_unzipped_directory, 'runtimes', 'win-x86', '_native', 'static') - $arm64_runtime_path_old = [System.IO.Path]::Combine($arm64_nupkg_unzipped_directory, 'runtimes', 'win-arm64', '_native') - $arm64_runtime_path_new = [System.IO.Path]::Combine($x64_nupkg_unzipped_directory, 'runtimes', 'win-arm64', '_native') - $arm64_static_runtime_path_old = [System.IO.Path]::Combine($arm64_static_runtime_nupkg_unzipped_directory, 'runtimes', 'win-arm64', '_native') - $arm64_static_runtime_path_new = [System.IO.Path]::Combine($x64_nupkg_unzipped_directory, 'runtimes', 'win-arm64', '_native', 'static') - - $uap_build_path_old = [System.IO.Path]::Combine($x64_static_runtime_nupkg_unzipped_directory, 'build', 'native') - $uap_build_path_new = [System.IO.Path]::Combine($x64_nupkg_unzipped_directory, 'build', 'uap10.0') - - New-Item -Path $x64_static_runtime_path_new -ItemType Directory - New-Item -Path $x86_runtime_path_new -ItemType Directory - New-Item -Path $x86_static_runtime_path_new -ItemType Directory - New-Item -Path $arm64_runtime_path_new -ItemType Directory - New-Item -Path $arm64_static_runtime_path_new -ItemType Directory - - Copy-Item ([System.IO.Path]::Combine($x86_runtime_path_old, 'onnxruntime.dll')) $x86_runtime_path_new - Copy-Item ([System.IO.Path]::Combine($x86_runtime_path_old, 'onnxruntime.lib')) $x86_runtime_path_new - Copy-Item ([System.IO.Path]::Combine($x86_runtime_path_old, 'microsoft.ai.machinelearning.dll')) $x86_runtime_path_new - Copy-Item ([System.IO.Path]::Combine($x86_runtime_path_old, 'microsoft.ai.machinelearning.lib')) $x86_runtime_path_new - - Copy-Item ([System.IO.Path]::Combine($arm64_runtime_path_old, 'onnxruntime.dll')) $arm64_runtime_path_new - Copy-Item ([System.IO.Path]::Combine($arm64_runtime_path_old, 'onnxruntime.lib')) $arm64_runtime_path_new - Copy-Item ([System.IO.Path]::Combine($arm64_runtime_path_old, 'microsoft.ai.machinelearning.dll')) $arm64_runtime_path_new - Copy-Item ([System.IO.Path]::Combine($arm64_runtime_path_old, 'microsoft.ai.machinelearning.lib')) $arm64_runtime_path_new - - Copy-Item ([System.IO.Path]::Combine($x64_static_runtime_path_old, 'onnxruntime.dll')) ([System.IO.Path]::Combine($x64_static_runtime_path_new, 'onnxruntime.dll')) - Copy-Item ([System.IO.Path]::Combine($x64_static_runtime_path_old, 'onnxruntime.lib')) ([System.IO.Path]::Combine($x64_static_runtime_path_new, 'onnxruntime.lib')) - Copy-Item ([System.IO.Path]::Combine($x64_static_runtime_path_old, 'microsoft.ai.machinelearning.dll')) ([System.IO.Path]::Combine($x64_static_runtime_path_new, 'microsoft.ai.machinelearning.dll')) - Copy-Item ([System.IO.Path]::Combine($x64_static_runtime_path_old, 'microsoft.ai.machinelearning.lib')) ([System.IO.Path]::Combine($x64_static_runtime_path_new, 'microsoft.ai.machinelearning.lib')) - - Copy-Item ([System.IO.Path]::Combine($x86_static_runtime_path_old, 'onnxruntime.dll')) ([System.IO.Path]::Combine($x86_static_runtime_path_new, 'onnxruntime.dll')) - Copy-Item ([System.IO.Path]::Combine($x86_static_runtime_path_old, 'onnxruntime.lib')) ([System.IO.Path]::Combine($x86_static_runtime_path_new, 'onnxruntime.lib')) - Copy-Item ([System.IO.Path]::Combine($x86_static_runtime_path_old, 'microsoft.ai.machinelearning.dll')) ([System.IO.Path]::Combine($x86_static_runtime_path_new, 'microsoft.ai.machinelearning.dll')) - Copy-Item ([System.IO.Path]::Combine($x86_static_runtime_path_old, 'microsoft.ai.machinelearning.lib')) ([System.IO.Path]::Combine($x86_static_runtime_path_new, 'microsoft.ai.machinelearning.lib')) - - Copy-Item ([System.IO.Path]::Combine($arm64_static_runtime_path_old, 'onnxruntime.dll')) ([System.IO.Path]::Combine($arm64_static_runtime_path_new, 'onnxruntime.dll')) - Copy-Item ([System.IO.Path]::Combine($arm64_static_runtime_path_old, 'onnxruntime.lib')) ([System.IO.Path]::Combine($arm64_static_runtime_path_new, 'onnxruntime.lib')) - Copy-Item ([System.IO.Path]::Combine($arm64_static_runtime_path_old, 'microsoft.ai.machinelearning.dll')) ([System.IO.Path]::Combine($arm64_static_runtime_path_new, 'microsoft.ai.machinelearning.dll')) - Copy-Item ([System.IO.Path]::Combine($arm64_static_runtime_path_old, 'microsoft.ai.machinelearning.lib')) ([System.IO.Path]::Combine($arm64_static_runtime_path_new, 'microsoft.ai.machinelearning.lib')) - - Copy-Item -Recurse $uap_build_path_old $uap_build_path_new - - $merged_nuget_path = [System.IO.Path]::Combine($Env:BUILD_ARTIFACTSTAGINGDIRECTORY, 'merged') - if (!(Test-Path $merged_nuget_path)) { - New-Item -Path $merged_nuget_path -ItemType Directory - } - - $merged_nuget = [System.IO.Path]::Combine($merged_nuget_path, $x64_nuget_package_name) - Start-Process -FilePath "7z" -ArgumentList "-tzip a -r $merged_nuget ." -WorkingDirectory $x64_nupkg_unzipped_directory -NoNewWindow -Wait - - workingDirectory: $(Build.BinariesDirectory)\nuget-artifact-x64 - - - task: PowerShell@2 - displayName: 'Bundle Symbols NuGet' - inputs: - targetType: 'inline' - script: | - Add-Type -AssemblyName "System.IO.Compression.FileSystem" - - $nupkgs = (Get-ChildItem -Filter Microsoft.AI.MachineLearning*.snupkg -Recurse) - $x64_nuget_package_name = $nupkgs[0].Name - $x64_nuget_package = $nupkgs[0].FullName - $x64_nupkg_unzipped_directory_root = $nupkgs[0].Directory.FullName - $x64_nupkg_unzipped_directory = [System.IO.Path]::Combine($x64_nupkg_unzipped_directory_root, 'symbols', [System.IO.Path]::GetFileNameWithoutExtension($x64_nuget_package)) - [System.IO.Compression.ZipFile]::ExtractToDirectory($x64_nuget_package, $x64_nupkg_unzipped_directory) - - $nupkgs = (Get-ChildItem ..\nuget-artifact-x86 -Filter Microsoft.AI.MachineLearning*.snupkg -Recurse) - $x86_nuget_package = $nupkgs[0].FullName - $x86_nupkg_unzipped_directory_root = $nupkgs[0].Directory.FullName - $x86_nupkg_unzipped_directory = [System.IO.Path]::Combine($x86_nupkg_unzipped_directory_root, 'symbols', [System.IO.Path]::GetFileNameWithoutExtension($x86_nuget_package)) - [System.IO.Compression.ZipFile]::ExtractToDirectory($x86_nuget_package, $x86_nupkg_unzipped_directory) - - $nupkgs = (Get-ChildItem ..\nuget-artifact-arm64 -Filter Microsoft.AI.MachineLearning*.snupkg -Recurse) - $arm64_nuget_package = $nupkgs[0].FullName - $arm64_nupkg_unzipped_directory_root = $nupkgs[0].Directory.FullName - $arm64_nupkg_unzipped_directory = [System.IO.Path]::Combine($arm64_nupkg_unzipped_directory_root, 'symbols', [System.IO.Path]::GetFileNameWithoutExtension($arm64_nuget_package)) - [System.IO.Compression.ZipFile]::ExtractToDirectory($arm64_nuget_package, $arm64_nupkg_unzipped_directory) - - $x86_runtime_path_old = [System.IO.Path]::Combine($x86_nupkg_unzipped_directory, 'runtimes', 'win-x86', '_native') - $x86_runtime_path_new = [System.IO.Path]::Combine($x64_nupkg_unzipped_directory, 'runtimes', 'win-x86', '_native') - $arm64_runtime_path_old = [System.IO.Path]::Combine($arm64_nupkg_unzipped_directory, 'runtimes', 'win-arm64', '_native') - $arm64_runtime_path_new = [System.IO.Path]::Combine($x64_nupkg_unzipped_directory, 'runtimes', 'win-arm64', '_native') - - New-Item -Path $x86_runtime_path_new -ItemType Directory - New-Item -Path $arm64_runtime_path_new -ItemType Directory - - Copy-Item ([System.IO.Path]::Combine($x86_runtime_path_old, 'onnxruntime.pdb')) $x86_runtime_path_new - Copy-Item ([System.IO.Path]::Combine($x86_runtime_path_old, 'microsoft.ai.machinelearning.pdb')) $x86_runtime_path_new - - Copy-Item ([System.IO.Path]::Combine($arm64_runtime_path_old, 'onnxruntime.pdb')) $arm64_runtime_path_new - Copy-Item ([System.IO.Path]::Combine($arm64_runtime_path_old, 'microsoft.ai.machinelearning.pdb')) $arm64_runtime_path_new - - $merged_nuget_path = [System.IO.Path]::Combine($Env:BUILD_ARTIFACTSTAGINGDIRECTORY, 'merged') - if (!(Test-Path $merged_nuget_path)) { - New-Item -Path $merged_nuget_path -ItemType Directory - } - - $merged_nuget = [System.IO.Path]::Combine($merged_nuget_path, $x64_nuget_package_name) - - Start-Process -FilePath "7z" -ArgumentList "-tzip a -r $merged_nuget ." -WorkingDirectory $x64_nupkg_unzipped_directory -NoNewWindow -Wait - - $merged_nuget_without_pdb = [System.IO.Path]::ChangeExtension($merged_nuget, '.nupkg') - - # Now we combine the DLLs and PDBs together, put them back in a folder under $(Build.SourcesDirectory) - # We won't upload the unzipped folder. We will just feed it to BinSkim. - 7z x -o$(Build.SourcesDirectory)\unzipped $merged_nuget - 7z -y x -o$(Build.SourcesDirectory)\unzipped $merged_nuget_without_pdb - - workingDirectory: $(Build.BinariesDirectory)\nuget-artifact-x64 - - - script: | - dir $(Build.SourcesDirectory)\unzipped\runtimes\win-x64\_native - - - task: SFP.build-tasks.custom-build-task-1.EsrpCodeSigning@5 - displayName: "Sign Nuget package" - inputs: - ConnectedServiceName: 'OnnxrunTimeCodeSign_20240611' - AppRegistrationClientId: '53d54d02-978d-4305-8572-583cf6711c4f' - AppRegistrationTenantId: '72f988bf-86f1-41af-91ab-2d7cd011db47' - AuthAKVName: 'buildkeyvault' - AuthCertName: '53d54d02-SSL-AutoRotate' - AuthSignCertName: '53d54d02-978d-4305-8572-583cf6711c4f' - - FolderPath: $(Build.ArtifactStagingDirectory) - Pattern: '*.nupkg' - SessionTimeout: 90 - ServiceEndpointUrl: 'https://api.esrp.microsoft.com/api/v2' - MaxConcurrency: 25 - signConfigType: inlineSignParams - inlineOperation: | - [ - { - "keyCode": "CP-401405", - "operationSetCode": "NuGetSign", - "parameters": [ ], - "toolName": "sign", - "toolVersion": "6.2.9304.0" - }, - { - "keyCode": "CP-401405", - "operationSetCode": "NuGetVerify", - "parameters": [ ], - "toolName": "sign", - "toolVersion": "6.2.9304.0" - } - ] - - - job: NuGet_Publishing - pool: - type: windows - variables: - ob_outputDirectory: '$(Build.BinariesDirectory)' - ob_sdl_binskim_enabled: false - ob_pipelineartifacts_enabled: false - ${{ if eq(variables['Build.SourceBranch'], 'refs/heads/main') }}: - ob_nugetPublishing_enabled: true - dependsOn: - - NuGet_Packaging - condition: succeeded() - steps: - - task: DownloadPipelineArtifact@2 - displayName: 'Download Pipeline Artifact' - inputs: - buildType: 'current' - artifactName: 'drop_Windows_Build_NuGet_Packaging' - itemPattern: 'merged/**' - targetPath: '$(Build.BinariesDirectory)' - - - powershell: | - Rename-Item -Path merged packages - - workingDirectory: '$(Build.BinariesDirectory)' - displayName: 'Rename nuget folder' diff --git a/.pipelines/nuget_config/x64/packages.config b/.pipelines/nuget_config/x64/packages.config deleted file mode 100644 index b9932eb563b83..0000000000000 --- a/.pipelines/nuget_config/x64/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/.pipelines/nuget_config/x86/packages.config b/.pipelines/nuget_config/x86/packages.config deleted file mode 100644 index 37fe2d378b7fd..0000000000000 --- a/.pipelines/nuget_config/x86/packages.config +++ /dev/null @@ -1,6 +0,0 @@ - - - - - - diff --git a/.pipelines/windowsai-steps.yml b/.pipelines/windowsai-steps.yml deleted file mode 100644 index 855573de753b0..0000000000000 --- a/.pipelines/windowsai-steps.yml +++ /dev/null @@ -1,180 +0,0 @@ -parameters: -- name: BuildArch - displayName: BuildArch - type: string - default: 'x64' - -- name: Runtime - displayName: MSVC Runtime, should be 'dynamic' or 'static'. - type: string - default: 'dynamic' - -- name: PythonPackageName - displayName: PythonPackageName on nuget.org to use - type: string - default: 'python' - -jobs: -- job: Windows_Packaging_${{ parameters.BuildArch }}_${{ parameters.Runtime }} - pool: - type: windows - - variables: - ob_outputDirectory: '$(Build.ArtifactStagingDirectory)' - ob_sdl_binskim_break: true - ob_sdl_binskim_scanOutputDirectoryOnly: true - steps: - - task: UseDotNet@2 - inputs: - version: '5.x' - - - template: ../tools/ci_build/github/azure-pipelines/templates/telemetry-steps.yml@self - - - task: NuGetCommand@2 - displayName: 'NuGet restore' - inputs: - feedsToUse: config - nugetConfigPath: NuGet.config - restoreDirectory: '$(Build.BinariesDirectory)' - ${{ if eq(parameters.BuildArch, 'x64') }}: - restoreSolution: $(Build.SourcesDirectory)\.pipelines\nuget_config\x64\packages.config - ${{ if eq(parameters.BuildArch, 'x86') }}: - restoreSolution: $(Build.SourcesDirectory)\.pipelines\nuget_config\x86\packages.config - ${{ if eq(parameters.BuildArch, 'arm') }}: - restoreSolution: $(Build.SourcesDirectory)\.pipelines\nuget_config\x64\packages.config - ${{ if eq(parameters.BuildArch, 'arm64') }}: - restoreSolution: $(Build.SourcesDirectory)\.pipelines\nuget_config\x64\packages.config - - - script: | - @echo off - set vswherepath="%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" - for /f "usebackq delims=" %%i in (`%vswherepath% -latest -property installationPath`) do ( - set vslatest="%%i" - if exist "%%i\Common7\Tools\vsdevcmd.bat" ( - set vsdevcmd="%%i\Common7\Tools\vsdevcmd.bat" - ) - ) - - @echo vslatest %vslatest% - @echo vsdevcmd %vsdevcmd% - - @echo ##vso[task.setvariable variable=vslatest]%vslatest% - @echo ##vso[task.setvariable variable=vsdevcmd]%vsdevcmd% -arch=${{ parameters.BuildArch }} - displayName: 'locate vsdevcmd via vswhere' - - - powershell: | - Write-Host "##vso[task.setvariable variable=BuildFlags]" - Write-Host "##vso[task.setvariable variable=ArtifactName]Microsoft.AI.MachineLearning.${{ parameters.BuildArch }}" - displayName: Initialize build flags - - - powershell: | - Write-Host "##vso[task.setvariable variable=BuildFlags]$(BuildFlags) --${{ parameters.BuildArch }}" - displayName: Add cross compilation flags for ARM - condition: and(ne('${{ parameters.BuildArch }}', 'x64'), ne('${{ parameters.BuildArch }}', 'x86')) - - - powershell: | - Write-Host "##vso[task.setvariable variable=BuildFlags]$(BuildFlags) --enable_msvc_static_runtime" - Write-Host "##vso[task.setvariable variable=ArtifactName]$(ArtifactName).StaticRuntime" - displayName: Add static runtime flags - condition: eq('${{ parameters.Runtime }}', 'static') - - # must call vsdevcmd first to add cmake to PATH - - script: | - curl -O -L https://github.com/Kitware/CMake/releases/download/v3.28.3/cmake-3.28.3-windows-x86_64.zip - 7z x cmake-3.28.3-windows-x86_64.zip - set PYTHONHOME=$(Build.BinariesDirectory)\${{ parameters.PythonPackageName }}.3.9.7\tools - set PYTHONPATH=$(Build.BinariesDirectory)\${{ parameters.PythonPackageName }}.3.9.7\tools - $(Build.BinariesDirectory)\${{ parameters.PythonPackageName }}.3.9.7\tools\python.exe "$(Build.SourcesDirectory)\tools\ci_build\build.py" --build_dir $(Build.BinariesDirectory) --parallel --use_binskim_compliant_compile_flags --build_shared_lib --enable_onnx_tests --ms_experimental --use_dml --use_winml --cmake_generator "Visual Studio 17 2022" --update --config RelWithDebInfo --enable_lto --use_telemetry --disable_rtti --enable_wcos --windows_sdk_version "10.0.22621.0" $(BuildFlags) --cmake_extra_defines "CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO=/PROFILE" "CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO=/PROFILE" --cmake_path $(Build.BinariesDirectory)\cmake-3.28.3-windows-x86_64\bin\cmake.exe --ctest_path $(Build.BinariesDirectory)\cmake-3.28.3-windows-x86_64\bin\ctest.exe - workingDirectory: '$(Build.BinariesDirectory)' - displayName: 'Generate cmake config' - - - task: VSBuild@1 - displayName: 'Build' - inputs: - solution: '$(Build.BinariesDirectory)\RelWithDebInfo\onnxruntime.sln' - ${{ if ne(parameters.BuildArch, 'x86') }}: - platform: ${{ parameters.BuildArch }} - ${{ if eq(parameters.BuildArch, 'x86') }}: - platform: 'Win32' - configuration: RelWithDebInfo - msbuildArchitecture: ${{ parameters.BuildArch }} - maximumCpuCount: true - logProjectEvents: true - workingFolder: '$(Build.BinariesDirectory)\RelWithDebInfo' - createLogFile: true - - - ${{ if eq(parameters.Runtime, 'dynamic') }}: - - script: | - xcopy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\winml_test_api.exe $(Build.ArtifactStagingDirectory)\test_artifact\ - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\winml_test_scenario.exe $(Build.ArtifactStagingDirectory)\test_artifact\ - copy $(Build.SourcesDirectory)\winml\test\api\models\*.onnx $(Build.ArtifactStagingDirectory)\test_artifact\ - copy $(Build.SourcesDirectory)\winml\test\scenario\cppwinrt\*.onnx $(Build.ArtifactStagingDirectory)\test_artifact\ - copy $(Build.SourcesDirectory)\winml\test\scenario\models\*.onnx $(Build.ArtifactStagingDirectory)\test_artifact\ - copy $(Build.SourcesDirectory)\winml\test\common\testdata\squeezenet\* $(Build.ArtifactStagingDirectory)\test_artifact\ - copy $(Build.SourcesDirectory)\winml\test\collateral\models\*.onnx $(Build.ArtifactStagingDirectory)\test_artifact\ - xcopy $(Build.SourcesDirectory)\winml\test\collateral\models\ModelSubdirectory $(Build.ArtifactStagingDirectory)\test_artifact\ModelSubdirectory\ /i - copy $(Build.SourcesDirectory)\winml\test\collateral\images\*.png $(Build.ArtifactStagingDirectory)\test_artifact\ - copy $(Build.SourcesDirectory)\winml\test\collateral\images\*.jpg $(Build.ArtifactStagingDirectory)\test_artifact\ - copy $(Build.SourcesDirectory)\onnxruntime\test\testdata\sequence_length.onnx $(Build.ArtifactStagingDirectory)\test_artifact\ - copy $(Build.SourcesDirectory)\onnxruntime\test\testdata\sequence_construct.onnx $(Build.ArtifactStagingDirectory)\test_artifact\ - displayName: 'Copy WinML test collateral to artifact directory' - - - - ${{ if eq(parameters.BuildArch, 'x64') }}: - - script: | - call $(vsdevcmd) - msbuild Microsoft.AI.MachineLearning.Interop.csproj /p:Configuration=RelWithDebInfo /p:Platform="Any CPU" /p:OnnxRuntimeBuildDirectory=$(Build.BinariesDirectory) -restore - workingDirectory: '$(Build.SourcesDirectory)\csharp\src\Microsoft.AI.MachineLearning.Interop' - displayName: 'Build Microsoft.AI.MachineLearning.Interop.dll' - - - task: onebranch.pipeline.signing@1 - inputs: - command: 'sign' - signing_profile: 'external_distribution' - files_to_sign: '**/*.exe;**/*.dll' - search_root: '$(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo' - displayName: 'Sign runtime DLLs' - - - ${{ if eq(parameters.BuildArch, 'x64') }}: - - script: | - call $(vsdevcmd) - msbuild $(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj /p:Configuration=RelWithDebInfo /t:CreateWindowsAIPackage /p:OnnxRuntimeBuildDirectory=$(Build.BinariesDirectory) /p:OnnxRuntimeSourceDirectory=$(Build.SourcesDirectory) - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\*.nupkg $(Build.ArtifactStagingDirectory) - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\*.snupkg $(Build.ArtifactStagingDirectory) - workingDirectory: '$(Build.SourcesDirectory)\csharp' - displayName: 'Create NuGet Package' - - - ${{ if eq(parameters.BuildArch, 'x86') }}: - - script: | - call $(vsdevcmd) - msbuild $(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj /p:Configuration=RelWithDebInfo /t:CreateWindowsAIPackage /p:OnnxRuntimeBuildDirectory=$(Build.BinariesDirectory) /p:OnnxRuntimeSourceDirectory=$(Build.SourcesDirectory) /p:TargetArchitecture=x86 - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\*.nupkg $(Build.ArtifactStagingDirectory) - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\*.snupkg $(Build.ArtifactStagingDirectory) - workingDirectory: '$(Build.SourcesDirectory)\csharp' - displayName: 'Create NuGet Package' - - - ${{ if eq(parameters.BuildArch, 'arm64') }}: - - script: | - call $(vsdevcmd) - msbuild $(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj /p:Configuration=RelWithDebInfo /t:CreateWindowsAIPackage /p:OnnxRuntimeBuildDirectory=$(Build.BinariesDirectory) /p:OnnxRuntimeSourceDirectory=$(Build.SourcesDirectory) /p:TargetArchitecture=arm64 /p:ProtocDirectory=$(Build.BinariesDirectory)\host_protoc\Release - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\*.nupkg $(Build.ArtifactStagingDirectory) - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\*.snupkg $(Build.ArtifactStagingDirectory) - workingDirectory: '$(Build.SourcesDirectory)\csharp' - displayName: 'Create NuGet Package' - - - ${{ if eq(parameters.BuildArch, 'arm') }}: - - script: | - call $(vsdevcmd) - msbuild $(Build.SourcesDirectory)\csharp\OnnxRuntime.CSharp.proj /p:Configuration=RelWithDebInfo /t:CreateWindowsAIPackage /p:OnnxRuntimeBuildDirectory=$(Build.BinariesDirectory) /p:OnnxRuntimeSourceDirectory=$(Build.SourcesDirectory) /p:TargetArchitecture=arm /p:ProtocDirectory=$(Build.BinariesDirectory)\host_protoc\Release - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\*.nupkg $(Build.ArtifactStagingDirectory) - copy $(Build.BinariesDirectory)\RelWithDebInfo\RelWithDebInfo\*.snupkg $(Build.ArtifactStagingDirectory) - workingDirectory: '$(Build.SourcesDirectory)\csharp' - displayName: 'Create NuGet Package' - - - task: onebranch.pipeline.signing@1 - inputs: - command: 'sign' - signing_profile: 'external_distribution' - files_to_sign: '**/*.exe;**/*.dll' - search_root: '$(Build.ArtifactStagingDirectory)\test_artifact' - displayName: 'Sign test_artifact' diff --git a/.vscode/settings.json b/.vscode/settings.json index dabb6416afa7f..9074103775bc0 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -8,19 +8,29 @@ ], "[python]": { "editor.tabSize": 4, - // Auto sort imports - "editor.formatOnSave": true, - "editor.codeActionsOnSave": { - "source.organizeImports": "explicit" - }, - "editor.defaultFormatter": "ms-python.black-formatter" }, - // Enable Python linting and Pylance type checking - "python.analysis.typeCheckingMode": "basic", "cpplint.lineLength": 120, "cpplint.filters": [ "-build/include_subdir", "-runtime/references" ], - "C_Cpp.autoAddFileAssociations": false + "C_Cpp.autoAddFileAssociations": false, + + // Exclude build directories and non-essential folders from C++ parsing + "C_Cpp.files.exclude": { + "**/build/**": true, + "**/build_*/**": true, + "**/cmake/external/**": true, + "**/node_modules/**": true, + "**/.git/**": true + }, + + // Exclude from search but keep in explorer + "search.exclude": { + "**/build/**": true, + "**/build_*/**": true, + "**/cmake/external/**": true, + "**/node_modules/**": true, + "**/.git/**": true + } } diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 0000000000000..18c5a8dd88a1d --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,112 @@ +# Agent Instructions for ONNX Runtime + +## Build, Test, and Lint + +See the `/ort-build`, `/ort-test`, and `/ort-lint` skills (in `.agents/skills/`) for detailed instructions. + +## Architecture Overview + +ONNX Runtime is a cross-platform inference and training engine for ONNX models. The core pipeline is: **Load model → Build graph → Optimize graph → Partition across Execution Providers → Execute**. + +### Key layers (`onnxruntime/core/`) + +- **`graph/`** — ONNX model/graph IR. `Model` wraps a `Graph` of `Node`s. `GraphViewer` provides read-only traversal. +- **`optimizer/`** — Graph transformations (fusion, elimination, constant folding, layout transforms). Organized by optimization level (Level1–Level4). +- **`framework/`** — Execution machinery: `OpKernel`, `Tensor`, `KernelRegistry`, allocators, executors. +- **`session/`** — `InferenceSession`: `Load()` → `Initialize()` (optimize + assign kernels) → `Run()`. +- **`providers/`** — Execution Provider (EP) implementations. Each EP implements `IExecutionProvider`. CPU EP is the default fallback. 20+ EPs exist (CUDA, TensorRT, DirectML, CoreML, OpenVINO, WebGPU, QNN, etc.). +- **`common/`** — Utilities, status/error types, logging, threading. +- **`platform/`** — OS abstraction (file I/O, threading). + +### Contrib ops (`onnxruntime/contrib_ops/`) + +Custom operators not in the ONNX standard, organized by EP (`cpu/`, `cuda/`, `js/`, `webgpu/`). Each EP has its own contrib kernel registration file (e.g., `cpu_contrib_kernels.cc`, `cuda_contrib_kernels.cc`, `js_contrib_kernels.cc`, `webgpu_contrib_kernels.cc`). + +### Training (`orttraining/`) + +Training-specific code (gradient ops, loss functions, optimizers, `TrainingSession`) layered on top of the inference framework. + +### Language bindings + +`csharp/`, `java/`, `js/`, `objectivec/`, `rust/` — each wraps the C API (`include/onnxruntime/core/session/onnxruntime_c_api.h`). + +## C++ Conventions + +**Style**: Google C++ Style with modifications. Max line length 120 (aim for 80). See `docs/Coding_Conventions_and_Standards.md` for full details. + +### Error handling + +Functions that can fail return `onnxruntime::common::Status`. Key macros from `core/common/common.h`: + +- `ORT_RETURN_IF_ERROR(expr)` — early-return if `expr` returns non-OK Status +- `ORT_THROW_IF_ERROR(expr)` — throw if `expr` returns non-OK Status +- `ORT_RETURN_IF(cond, ...)` / `ORT_RETURN_IF_NOT(cond, ...)` — conditional early-return with message +- `ORT_ENFORCE(cond, ...)` — assert-like; throws `OnnxRuntimeException` on failure +- `ORT_MAKE_STATUS(category, code, ...)` — construct a Status object + +Exceptions may be disabled in a build, in which case, the throwing macros will call `abort()` instead. + +At the C API boundary, use `API_IMPL_BEGIN` / `API_IMPL_END` to catch exceptions — C++ exceptions must never cross the C API boundary. + +### Container types + +Use these instead of `std::vector` / `std::unordered_map`: + +- `InlinedVector` — small-buffer-optimized vector (64 bytes inline) +- `InlinedHashSet`, `InlinedHashMap` — flat hash containers +- `NodeHashSet`, `NodeHashMap` — when pointer stability is needed +- `TensorShapeVector` — for shape dimensions + +Use `reserve()` not `resize()`. Do not use `absl::` directly — use the ORT typedefs. + +### Other conventions + +- `#pragma once` for header guards +- `ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE` for new classes until copy/move is proven necessary +- Prefer `gsl::span` over `const std::vector&` for input parameters +- Prefer `std::string_view` by value over `const std::string&` +- `SafeInt` (from `core/common/safeint.h`) for memory size arithmetic +- Don't use `else` after `return` +- Avoid `long` (ambiguous width) — use `int64_t` for dimensions, `size_t` for counts +- `using namespace` allowed in limited scope but never at global scope in headers +- `std::make_unique()` for heap allocations; prefer `std::optional` over `unique_ptr` for optional/delayed construction + +## Python + +### Virtual environment + +Build and test processes may install Python packages. Create and activate an isolated virtual environment first: + +```bash +python -m venv .venv # one-time setup +source .venv/bin/activate # Linux/macOS +.\.venv\Scripts\Activate.ps1 # Windows (PowerShell) +``` + +If a virtual environment already exists (e.g., `.venv/`), activate it rather than creating a new one. + +### Conventions + +- Follow [Google Python Style Guide](https://google.github.io/styleguide/pyguide.html) (extension of PEP 8) +- Max line length: 120 characters +- Formatter: ruff (configured in `pyproject.toml`) +- Static type checking: pyright/pylance +- Test framework: `unittest` (preferred) with `pytest` as runner + +## C API Conventions + +The main public C API header is `include/onnxruntime/core/session/onnxruntime_c_api.h`. Other public headers are in `include/onnxruntime/core/session/` and `orttraining/orttraining/training_api/include/`. + +- Functions that may fail return `OrtStatus*` (`nullptr` on success); release/cleanup functions return `void` +- Object lifecycle: `OrtCreateXxx` / `OrtReleaseXxx` +- All strings are UTF-8 encoded +- Use `int64_t` for dimensions, `size_t` for counts and memory sizes +- APIs requiring allocation take an `OrtAllocator*` parameter +- Failed calls must not modify out-parameters + +## PR Guidelines + +- Keep PRs small (aim for ≤10 files; separate cosmetic changes from functional ones) +- All changes must have unit tests, unless documentation-only or already adequately covered +- Build and test locally on at least one platform before submitting +- PR author is responsible for merging after approval diff --git a/CODEOWNERS b/CODEOWNERS index a55067ed798d8..3ce36ef57524a 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -3,12 +3,6 @@ # Mobile /onnxruntime/core/flatbuffers/schema/ort.fbs @microsoft/onnxruntime-mobile -# MLAS and related contrib ops -/onnxruntime/core/graph/contrib_ops/nhwc_schema_defs.cc @microsoft/onnxruntime-mlas -/onnxruntime/core/graph/contrib_ops/nchwc_schema_defs.cc @microsoft/onnxruntime-mlas -/onnxruntime/core/graph/contrib_ops/quantization_defs.* @microsoft/onnxruntime-mlas -/onnxruntime/core/mlas/** @microsoft/onnxruntime-mlas - # Dependencies requirements-dev.txt @microsoft/onnxruntime-admin requirements-doc.txt @microsoft/onnxruntime-admin diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 2bd7a470f501e..9e1e7b9aa4f78 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -9,6 +9,18 @@ We're always looking for your help to improve the product (bug fixes, new featur * Make sure your PR adheres to the [PR Guidelines](./docs/PR_Guidelines.md) and [Coding Conventions and Standards](./docs/Coding_Conventions_and_Standards.md) established by the team. * If you're unsure about any of the above and want to contribute, you're welcome to [start a discussion](https://github.com/microsoft/onnxruntime/discussions) with the team. +## Git hooks (recommended) + +Enable the repo's pre-commit hook to run [lintrunner](https://github.com/suo/lintrunner) automatically before each commit: + +```sh +git config core.hooksPath .githooks +``` + +If lint issues are found, the commit is blocked. Run `lintrunner -a` to auto-fix, re-stage, and commit again. Use `git commit --no-verify` to bypass. + +> **Note:** `core.hooksPath` replaces Git's default hook directory (`.git/hooks/`). If you have existing custom hooks, you may need to integrate them manually. + ## Propose a new public API ONNX Runtime has a collection of [public APIs](./README.md#api-documentation). Some of these APIs make their way back into the Windows OS. We make compatibility commitments for these APIs and follow a structured process when adding to them. Please use the [Feature Request issue template](https://github.com/microsoft/onnxruntime/issues/new?template=feature_request.md) before starting any PRs that affect any of the public APIs. diff --git a/README.md b/README.md index f1817282b61a0..bae7c5f70531b 100644 --- a/README.md +++ b/README.md @@ -20,25 +20,8 @@ - ONNX Runtime Inferencing: [microsoft/onnxruntime-inference-examples](https://github.com/microsoft/onnxruntime-inference-examples) - ONNX Runtime Training: [microsoft/onnxruntime-training-examples](https://github.com/microsoft/onnxruntime-training-examples) -## Builtin Pipeline Status - -|System|Inference|Training| -|---|---|---| -|Windows|[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/Windows%20CPU%20CI%20Pipeline?label=Windows+CPU)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=9)
[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/Windows%20GPU%20CUDA%20CI%20Pipeline?label=Windows+GPU+CUDA)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=218)
[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/Windows%20GPU%20TensorRT%20CI%20Pipeline?label=Windows+GPU+TensorRT)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=47)
[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/Windows%20GPU%20WebGPU%20CI%20Pipeline?label=Windows+GPU+WebGPU)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=228)|| -|Linux|[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/Linux%20CPU%20CI%20Pipeline?label=Linux+CPU)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=11)
[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/Linux%20CPU%20Minimal%20Build%20E2E%20CI%20Pipeline?label=Linux+CPU+Minimal+Build)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=64)
[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/Linux%20GPU%20CI%20Pipeline?label=Linux+GPU)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=12)
[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/Linux%20GPU%20TensorRT%20CI%20Pipeline?label=Linux+GPU+TensorRT)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=45)
[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/Linux%20OpenVINO%20CI%20Pipeline?label=Linux+OpenVINO)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=55)|[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/orttraining-linux-ci-pipeline?label=Linux+CPU+Training)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=86)
[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/orttraining-linux-gpu-ci-pipeline?label=Linux+GPU+Training)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=84)| -|Mac|[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/MacOS%20CI%20Pipeline?label=MacOS+CPU)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=13)|| -|Android|[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/Android%20CI%20Pipeline?label=Android)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=53)|| -|iOS|[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/iOS%20CI%20Pipeline?label=iOS)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=134)|| -|Web|[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/ONNX%20Runtime%20Web%20CI%20Pipeline?label=Web)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=161)|| -|Other|[![Build Status](https://dev.azure.com/onnxruntime/onnxruntime/_apis/build/status/onnxruntime-binary-size-checks-ci-pipeline?repoName=microsoft%2Fonnxruntime&label=Binary+Size+Check)](https://dev.azure.com/onnxruntime/onnxruntime/_build/latest?definitionId=187&repoName=microsoft%2Fonnxruntime)|| - -This project is tested with [BrowserStack](https://www.browserstack.com/home). - -## Third-party Pipeline Status - -|System|Inference|Training| -|---|---|---| -|Linux|[![Build Status](https://github.com/Ascend/onnxruntime/actions/workflows/build-and-test.yaml/badge.svg)](https://github.com/Ascend/onnxruntime/actions/workflows/build-and-test.yaml)|| +* **Plugin EP repositories**: + - ONNX Runtime QNN Plugin EP: [onnxruntime/onnxruntime-qnn](https://github.com/onnxruntime/onnxruntime-qnn) ## Releases @@ -67,3 +50,18 @@ or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any addi ## License This project is licensed under the [MIT License](LICENSE). + +## Build for Goodnotes +``` +python3 tools/ci_build/github/apple/build_apple_framework.py --config Release --build_dynamic_framework --build_dir ~/Downloads/onnat/onnxlibrary/mac_release_v20230327_2320 --include_ops_by_config tools/ci_build/github/apple/hws_mobile_package.required_operators.config --path_to_protoc_exe /usr/local/bin/protoc tools/ci_build/github/apple/default_full_ios_framework_build_settings.json +``` +(note there’s a --build_dynamic_framework arg) + +Now you can check +``` +onnxruntime.framework % file onnxruntime +onnxruntime: Mach-O universal binary with 2 architectures: [x86_64:Mach-O 64-bit dynamically linked shared library x86_64] [arm64] +onnxruntime (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64 +onnxruntime (for architecture arm64): Mach-O 64-bit dynamically linked shared library arm64 +``` + diff --git a/SECURITY.md b/SECURITY.md index 869fdfe2b2469..d8e8bb9ca18a3 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -1,20 +1,18 @@ - + ## Security -Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations. -If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below. +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/security.md/definition), please report it to us as described below. ## Reporting Security Issues **Please do not report security vulnerabilities through public GitHub issues.** -Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report). +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report). -If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey). - -You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc). +You should receive a response within 24 hours. If for some reason you do not, please follow up using the messaging functionality found at the bottom of the Activity tab on your vulnerability report on [https://msrc.microsoft.com/report/vulnerability](https://msrc.microsoft.com/report/vulnerability/) or via email as described in the instructions at the bottom of [https://msrc.microsoft.com/create-report](https://aka.ms/security.md/msrc/create-report). Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc) or on MSRC's [FAQ page for reporting an issue](https://www.microsoft.com/en-us/msrc/faqs-report-an-issue). Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: @@ -28,7 +26,7 @@ Please include the requested information listed below (as much as you can provid This information will help us triage your report more quickly. -If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs. +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/security.md/msrc/bounty) page for more details about our active programs. ## Preferred Languages @@ -36,6 +34,6 @@ We prefer all communications to be in English. ## Policy -Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd). +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/security.md/cvd). diff --git a/SUPPORT.md b/SUPPORT.md new file mode 100644 index 0000000000000..a3d47db2c4e13 --- /dev/null +++ b/SUPPORT.md @@ -0,0 +1,13 @@ +# Support + +## How to file issues and get help + +This project uses [GitHub Issues](https://github.com/Microsoft/onnxruntime/issues) to track bugs and feature requests. Please search the existing +issues before filing new issues to avoid duplicates. For new issues, file your bug or +feature request as a new Issue. + +For help and questions about using this project, please use [GitHub Discussions](https://github.com/microsoft/onnxruntime/discussions). + +## Microsoft Support Policy + +Support for this project is limited to the resources listed above. diff --git a/ThirdPartyNotices.txt b/ThirdPartyNotices.txt index 26084ab42ec1c..fbd9f9a95f601 100644 --- a/ThirdPartyNotices.txt +++ b/ThirdPartyNotices.txt @@ -5806,41 +5806,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. _____ -composable_kernel - -https://github.com/ROCmSoftwarePlatform/composable_kernel - -Copyright (c) 2018- , Advanced Micro Devices, Inc. (Chao Liu, Jing Zhang) -Copyright (c) 2019- , Advanced Micro Devices, Inc. (Letao Qin, Qianfeng Zhang, Liang Huang, Shaojie Wang) -Copyright (c) 2022- , Advanced Micro Devices, Inc. (Anthony Chang, Chunyu Lai, Illia Silin, Adam Osewski, Poyen Chen, Jehandad Khan) -Copyright (c) 2019-2021, Advanced Micro Devices, Inc. (Hanwen Chang) -Copyright (c) 2019-2020, Advanced Micro Devices, Inc. (Tejash Shah) -Copyright (c) 2020 , Advanced Micro Devices, Inc. (Xiaoyan Zhou) -Copyright (c) 2021-2022, Advanced Micro Devices, Inc. (Jianfeng Yan) - -SPDX-License-Identifier: MIT -Copyright (c) 2018-2023, Advanced Micro Devices, Inc. All rights reserved. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - -_____ - neural-speed https://github.com/intel/neural-speed @@ -6045,3 +6010,112 @@ https://github.com/intel/neural-speed terms, and open source software license terms. These separate license terms govern your use of the third party programs as set forth in the "THIRD-PARTY-PROGRAMS" file. + +_____ + +dawn + +https://dawn.googlesource.com/dawn + + BSD 3-Clause License + + Copyright 2017-2023 The Dawn & Tint Authors + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions are met: + + 1. Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + + 2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + + 3. Neither the name of the copyright holder nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE + FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +_____ + +KleidiAI + +https://gitlab.arm.com/kleidi/kleidiai + +Apache License +Version 2.0, January 2004 +http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + +"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. + +"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. + +"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. + +"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. + +"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. + +"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. + +"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). + +"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. + +"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." + +"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: + + (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. + + You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +Copyright 2024-2025 Arm Limited and/or its affiliates + +Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/VERSION_NUMBER b/VERSION_NUMBER index 3500250a4b05b..5db08bf2dc579 100644 --- a/VERSION_NUMBER +++ b/VERSION_NUMBER @@ -1 +1 @@ -1.21.0 +1.27.0 diff --git a/cgmanifests/README.md b/cgmanifests/README.md index fcd15232f9251..a7d816a401a95 100644 --- a/cgmanifests/README.md +++ b/cgmanifests/README.md @@ -1,30 +1,3 @@ # CGManifest Files This directory contains CGManifest (cgmanifest.json) files. -See [here](https://docs.opensource.microsoft.com/tools/cg/cgmanifest.html) for details. - -## `cgmanifests/generated/cgmanifest.json` -This file contains generated CGManifest entries. - -It covers these dependencies: -- git submodules -- dependencies from the Dockerfile `tools/ci_build/github/linux/docker/Dockerfile.manylinux2014_cuda11` -- the entries in [../cmake/deps.txt](../cmake/deps.txt) - -If any of these dependencies change, this file should be updated. -**When updating, please regenerate instead of editing manually.** - -### How to Generate -1. Change to the repository root directory. -2. Ensure the git submodules are checked out and up to date. For example, with: - ``` - $ git submodule update --init --recursive - ``` -3. Run the generator script: - ``` - $ python cgmanifests/generate_cgmanifest.py --username --token - ``` - -Please supply your github username and access token to the script. If you don't have a token, you can generate one at https://github.com/settings/tokens. This is for authenticating with Github REST API so that you would not hit the rate limit. - -## `cgmanifests/cgmanifest.json` -This file contains non-generated CGManifest entries. Please edit directly as needed. +See [here](https://docs.opensource.microsoft.com/tools/cg/cgmanifest.html) for details. \ No newline at end of file diff --git a/cgmanifests/cgmanifest.json b/cgmanifests/cgmanifest.json index 46349f43923e2..bf889e9fb61a8 100644 --- a/cgmanifests/cgmanifest.json +++ b/cgmanifests/cgmanifest.json @@ -1,15 +1,6 @@ { "$schema": "https://json.schemastore.org/component-detection-manifest.json", "Registrations": [ - { - "component": { - "type": "git", - "git": { - "commitHash": "215105818dfde3174fe799600bb0f3cae233d0bf", - "repositoryUrl": "https://github.com/abseil/abseil-cpp.git" - } - } - }, { "component": { "Type": "maven", @@ -27,7 +18,7 @@ "maven": { "GroupId": "com.google.protobuf", "ArtifactId": "protobuf-java", - "Version": "3.21.7" + "Version": "3.25.5" }, "DevelopmentDependency": true } @@ -45,7 +36,7 @@ "component": { "type": "git", "git": { - "commitHash": "bee4d1dd8dc1ee4a1fd8fa6a96476c2f8b7492a3", + "commitHash": "5c210da409e7f1e51ddf445134a4376fdbd70d7d", "repositoryUrl": "https://github.com/dmlc/dlpack.git" } } @@ -131,16 +122,6 @@ } } }, - { - "component": { - "type": "git", - "git": { - "commitHash": "b31f58de6fa8bbda5353b3c77d9be4914399724d", - "repositoryUrl": "https://github.com/pytorch/pytorch.git" - }, - "comments": "pytorch 1.6 used by onnxruntime training image" - } - }, { "component": { "type": "git", @@ -189,15 +170,6 @@ } } }, - { - "component": { - "git": { - "commitHash": "02a2a458ac15912d7d87cc1171e811b0c5219ece", - "repositoryUrl": "https://github.com/grpc/grpc" - }, - "type": "git" - } - }, { "component": { "git": { @@ -324,116 +296,6 @@ "comments": "For Nodejs binding" } }, - { - "component": { - "type": "git", - "git": { - "commitHash": "aead4d751c2101e23336aa73f2380df83e7a13f3", - "repositoryUrl": "https://github.com/pypa/manylinux" - }, - "comments": "For building our CI build docker image" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "c974557598645360fbabac71352b083117e3cc17", - "repositoryUrl": "https://gitlab.kitware.com/cmake/cmake" - }, - "comments": "CMake 3.24.3. For building our CI build docker image" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "1e5d33e9b9b8631b36f061103a30208b206fd03a", - "repositoryUrl": "https://github.com/python/cpython" - }, - "comments": "Python 3.9.1" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "6503f05dd59e26a9986bdea097b3da9b3546f45b", - "repositoryUrl": "https://github.com/python/cpython" - }, - "comments": "Python 3.8.7" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "13c94747c74437e594b7fc242ff7da668e81887c", - "repositoryUrl": "https://github.com/python/cpython" - }, - "comments": "Python 3.7.9" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "c0a9afe2ac1820409e6173bd1893ebee2cf50270", - "repositoryUrl": "https://github.com/python/cpython" - }, - "comments": "Python 3.6.12" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "426b022776672fdf3d71ddd98d89af341c88080f", - "repositoryUrl": "https://github.com/python/cpython" - }, - "comments": "Python 3.5.10" - } - }, - { - "component": { - "type": "pip", - "pip": { - "Name": "transformers", - "Version": "4.38.0" - }, - "comments": "Installed in the training docker image" - } - }, - { - "component": { - "type": "pip", - "pip": { - "Name": "msgpack", - "Version": "1.0.0" - }, - "comments": "Installed in the training docker image" - } - }, - { - "component": { - "type": "pip", - "pip": { - "Name": "tensorboardX", - "Version": "1.8" - }, - "comments": "Installed in the training docker image" - } - }, - { - "component": { - "type": "pip", - "pip": { - "Name": "tensorboard", - "Version": "2.3.0" - }, - "comments": "Installed in the training docker image" - } - }, { "component": { "type": "git", @@ -454,16 +316,6 @@ "comments": "gtest-ios-framework" } }, - { - "component": { - "type": "git", - "git": { - "commitHash": "277508879878e0a5b5b43599b1bea11f66eb3c6c", - "repositoryUrl": "https://github.com/dmlc/dlpack.git" - }, - "comments": "dlpack" - } - }, { "component": { "Type": "other", @@ -493,15 +345,6 @@ }, "comments": "python-pillow. Implementation logic for anti-aliasing copied by Resize CPU kernel." } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "e7248b26a1ed53fa030c5c459f7ea095dfd276ac", - "repositoryUrl": "https://gitlab.com/libeigen/eigen.git" - } - } } ], "Version": 1 diff --git a/cgmanifests/generate_cgmanifest.py b/cgmanifests/generate_cgmanifest.py deleted file mode 100644 index b2e8f6816a2ef..0000000000000 --- a/cgmanifests/generate_cgmanifest.py +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/env python3 - -import argparse -import csv -import json -import os -import re -import subprocess -import sys -from dataclasses import dataclass -from pathlib import PurePosixPath -from urllib.parse import urlparse - -import requests - - -def parse_arguments(): - parser = argparse.ArgumentParser() - parser.add_argument("--username", required=True, help="Github username") - parser.add_argument("--token", required=True, help="Github access token") - - return parser.parse_args() - - -args = parse_arguments() - -SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__)) -REPO_DIR = os.path.normpath(os.path.join(SCRIPT_DIR, "..")) - -package_name = None -package_filename = None -package_url = None - -registrations = [] - - -@dataclass(frozen=True) -class GitDep: - commit: str - url: str - - -git_deps = {} - - -def add_github_dep(name, parsed_url): - segments = parsed_url.path.split("/") - org_name = segments[1] - repo_name = segments[2] - if segments[3] != "archive": - print("unrecognized github url path:" + parsed_url.path) - return - git_repo_url = f"https://github.com/{org_name}/{repo_name}.git" - # For example, the path might be like '/myorg/myrepo/archive/5a5f8a5935762397aa68429b5493084ff970f774.zip' - # The last segment, segments[4], is '5a5f8a5935762397aa68429b5493084ff970f774.zip' - if len(segments) == 5 and re.match(r"[0-9a-f]{40}", PurePosixPath(segments[4]).stem): - commit = PurePosixPath(segments[4]).stem - dep = GitDep(commit, git_repo_url) - if dep not in git_deps: - git_deps[dep] = name - else: - # TODO: support urls like: https://github.com/onnx/onnx-tensorrt/archive/refs/tags/release/7.1.zip - if len(segments) == 5: - tag = PurePosixPath(segments[4]).stem - if tag.endswith(".tar"): - tag = PurePosixPath(tag).stem - elif segments[4] == "refs" and segments[5] == "tags": - tag = PurePosixPath(segments[6]).stem - if tag.endswith(".tar"): - tag = PurePosixPath(tag).stem - else: - print("unrecognized github url path:" + parsed_url.path) - return - # Make a REST call to convert to tag to a git commit - url = f"https://api.github.com/repos/{org_name}/{repo_name}/git/refs/tags/{tag}" - print(f"requesting {url} ...") - res = requests.get(url, auth=(args.username, args.token)) - response_json = res.json() - tag_object = response_json["object"] - if tag_object["type"] == "commit": - commit = tag_object["sha"] - elif tag_object["type"] == "tag": - res = requests.get(tag_object["url"], auth=(args.username, args.token)) - commit = res.json()["object"]["sha"] - else: - print("unrecognized github url path:" + parsed_url.path) - return - dep = GitDep(commit, git_repo_url) - if dep not in git_deps: - git_deps[dep] = name - - -def normalize_path_separators(path): - return path.replace(os.path.sep, "/") - - -proc = subprocess.run( - [ - "git", - "submodule", - "foreach", - "--quiet", - "'{}' '{}' $toplevel/$sm_path".format( - normalize_path_separators(sys.executable), - normalize_path_separators(os.path.join(SCRIPT_DIR, "print_submodule_info.py")), - ), - ], - check=True, - cwd=REPO_DIR, - capture_output=True, - text=True, -) - - -submodule_lines = proc.stdout.splitlines() -for submodule_line in submodule_lines: - (absolute_path, url, commit) = submodule_line.split(" ") - git_deps[GitDep(commit, url)] = ( - f"git submodule at {normalize_path_separators(os.path.relpath(absolute_path, REPO_DIR))}" - ) - -with open(os.path.join(SCRIPT_DIR, "..", "cmake", "deps.txt")) as f: - depfile_reader = csv.reader(f, delimiter=";") - for row in depfile_reader: - if len(row) < 3: - continue - name = row[0] - # Lines start with "#" are comments - if name.startswith("#"): - continue - url = row[1] - parsed_url = urlparse(url) - # TODO: add support for gitlab - if parsed_url.hostname == "github.com": - add_github_dep(name, parsed_url) - else: - print("unrecognized url:" + url) - -for git_dep, comment in git_deps.items(): - registration = { - "component": { - "type": "git", - "git": { - "commitHash": git_dep.commit, - "repositoryUrl": git_dep.url, - }, - "comments": comment, - } - } - registrations.append(registration) - -cgmanifest = { - "$schema": "https://json.schemastore.org/component-detection-manifest.json", - "Version": 1, - "Registrations": registrations, -} - -with open(os.path.join(SCRIPT_DIR, "generated", "cgmanifest.json"), mode="w") as generated_cgmanifest_file: - print(json.dumps(cgmanifest, indent=2), file=generated_cgmanifest_file) diff --git a/cgmanifests/generated/README.md b/cgmanifests/generated/README.md deleted file mode 100644 index 299ce4bc82299..0000000000000 --- a/cgmanifests/generated/README.md +++ /dev/null @@ -1,2 +0,0 @@ -`cgmanifests/generated/cgmanifest.json` is a generated file. Please do not edit it directly. -More info [here](../README.md). diff --git a/cgmanifests/generated/cgmanifest.json b/cgmanifests/generated/cgmanifest.json deleted file mode 100644 index 46f8c8891dda5..0000000000000 --- a/cgmanifests/generated/cgmanifest.json +++ /dev/null @@ -1,356 +0,0 @@ -{ - "$schema": "https://json.schemastore.org/component-detection-manifest.json", - "Version": 1, - "Registrations": [ - { - "component": { - "type": "git", - "git": { - "commitHash": "d52c46520124845b1e0e0525f2759299d840143f", - "repositoryUrl": "https://github.com/emscripten-core/emsdk.git" - }, - "comments": "git submodule at cmake/external/emsdk" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "7a2ed51a6b682a83e345ff49fc4cfd7ca47550db", - "repositoryUrl": "https://github.com/google/libprotobuf-mutator.git" - }, - "comments": "git submodule at cmake/external/libprotobuf-mutator" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "b8baa8446686496da4cc8fda09f2b6fe65c2a02c", - "repositoryUrl": "https://github.com/onnx/onnx.git" - }, - "comments": "git submodule at cmake/external/onnx" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "4447c7562e3bc702ade25105912dce503f0c4010", - "repositoryUrl": "https://github.com/abseil/abseil-cpp.git" - }, - "comments": "abseil_cpp" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "dbb0094fd0cb936469e35320bf37e866ef7a1da4", - "repositoryUrl": "https://github.com/apple/coremltools.git" - }, - "comments": "coremltools" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "3c73d91c0b04e2b59462f0a741be8c07024c1bc0", - "repositoryUrl": "https://github.com/jarro2783/cxxopts.git" - }, - "comments": "cxxopts" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "6e921e1b1d21e84a5c82416ba7ecd98e33a436d0", - "repositoryUrl": "https://github.com/HowardHinnant/date.git" - }, - "comments": "date" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "277508879878e0a5b5b43599b1bea11f66eb3c6c", - "repositoryUrl": "https://github.com/dmlc/dlpack.git" - }, - "comments": "dlpack" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "0100f6a5779831fa7a651e4b67ef389a8752bd9b", - "repositoryUrl": "https://github.com/google/flatbuffers.git" - }, - "comments": "flatbuffers" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "0a92994d729ff76a58f692d3028ca1b64b145d91", - "repositoryUrl": "https://github.com/Maratyszcza/FP16.git" - }, - "comments": "fp16" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "63058eff77e11aa15bf531df5dd34395ec3017c8", - "repositoryUrl": "https://github.com/Maratyszcza/FXdiv.git" - }, - "comments": "fxdiv" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "a6ad7fbbdc2e14fab82bb8a6d27760d700198cbf", - "repositoryUrl": "https://github.com/google/benchmark.git" - }, - "comments": "google_benchmark" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "e39786088138f2749d64e9e90e0f9902daa77c40", - "repositoryUrl": "https://github.com/google/googletest.git" - }, - "comments": "googletest" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "fe98e0b93565382648129271381c14d6205255e3", - "repositoryUrl": "https://github.com/google/XNNPACK.git" - }, - "comments": "googlexnnpack" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "4f8fba14066156b73f1189a2b8bd568bde5284c5", - "repositoryUrl": "https://github.com/nlohmann/json.git" - }, - "comments": "json" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "a3534567187d2edc428efd3f13466ff75fe5805c", - "repositoryUrl": "https://github.com/microsoft/GSL.git" - }, - "comments": "microsoft_gsl" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "55f373e164d3f092dd6c7a56e3de6f90c4c6f3dc", - "repositoryUrl": "https://github.com/microsoft/wil.git" - }, - "comments": "microsoft_wil" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "3e313478d91c04ac5821743688ce55fc27432c4f", - "repositoryUrl": "https://github.com/microsoft/mimalloc.git" - }, - "comments": "mimalloc" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "0a0b5fb001ce0233ae3a6f99d849c0649e5a7361", - "repositoryUrl": "https://github.com/boostorg/mp11.git" - }, - "comments": "mp11" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "9c69a24bc2e20c8a511a4e6b06fd49639ec5300a", - "repositoryUrl": "https://github.com/onnx/onnx-tensorrt.git" - }, - "comments": "onnx_tensorrt" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "f0dc78d7e6e331b8c6bb2d5283e06aa26883ca7c", - "repositoryUrl": "https://github.com/protocolbuffers/protobuf.git" - }, - "comments": "protobuf" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "072586a71b55b7f8c584153d223e95687148a900", - "repositoryUrl": "https://github.com/Maratyszcza/psimd.git" - }, - "comments": "psimd" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "4e80ca24521aa0fb3a746f9ea9c3eaa20e9afbb0", - "repositoryUrl": "https://github.com/google/pthreadpool.git" - }, - "comments": "pthreadpool" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "941f45bcb51457884fa1afd6e24a67377d70f75c", - "repositoryUrl": "https://github.com/pybind/pybind11.git" - }, - "comments": "pybind11" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "8a1772a0c5c447df2d18edf33ec4603a8c9c04a6", - "repositoryUrl": "https://github.com/pytorch/cpuinfo.git" - }, - "comments": "pytorch_cpuinfo" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "6dcd83d60f7944926bfd308cc13979fc53dd69ca", - "repositoryUrl": "https://github.com/google/re2.git" - }, - "comments": "re2" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "4cafc9196c4da9c817992b20f5253ef967685bf8", - "repositoryUrl": "https://github.com/dcleblanc/SafeInt.git" - }, - "comments": "safeint" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "373eb09e4c5d2b3cc2493f0949dc4be6b6a45e81", - "repositoryUrl": "https://github.com/tensorflow/tensorboard.git" - }, - "comments": "tensorboard" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "f7b19de32c5d1f3cedfc735c2849f12b537522ee", - "repositoryUrl": "https://github.com/NVIDIA/cutlass.git" - }, - "comments": "cutlass" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "72c943dea2b9240cd09efde15191e144bc7c7d38", - "repositoryUrl": "https://github.com/protocolbuffers/utf8_range.git" - }, - "comments": "utf8_range" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "f3f6caa6e8adb420e005ec41c6fefc8d75affb6e", - "repositoryUrl": "https://github.com/microsoft/onnxruntime-extensions.git" - }, - "comments": "extensions" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "204da9c522cebec5220bba52cd3542ebcaf99e7a", - "repositoryUrl": "https://github.com/ROCmSoftwarePlatform/composable_kernel.git" - }, - "comments": "composable_kernel" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "de28d93dfa9ebf3e473127c1c657e1920a5345ee", - "repositoryUrl": "https://github.com/microsoft/DirectX-Headers.git" - }, - "comments": "directx_headers" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "de355c7094af70467f2b264f531ab5c5f4401c42", - "repositoryUrl": "https://github.com/NVIDIA/cudnn-frontend.git" - }, - "comments": "cudnn_frontend" - } - }, - { - "component": { - "type": "git", - "git": { - "commitHash": "b9b4a37041dec3dd62ac92014a6cc1aece48d9f3", - "repositoryUrl": "https://github.com/google/dawn.git" - }, - "comments": "dawn" - } - } - ] -} diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt index 962b42c1906d8..83d1751e55543 100644 --- a/cmake/CMakeLists.txt +++ b/cmake/CMakeLists.txt @@ -3,23 +3,23 @@ # Licensed under the MIT License. # Minimum CMake required -cmake_minimum_required(VERSION 3.26) +cmake_minimum_required(VERSION 3.28) -cmake_policy(SET CMP0069 NEW) -set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) - -cmake_policy(SET CMP0092 NEW) -cmake_policy(SET CMP0091 NEW) -cmake_policy(SET CMP0117 NEW) # Don't let cmake set a default value for CMAKE_CUDA_ARCHITECTURES cmake_policy(SET CMP0104 OLD) - -# Enable Hot Reload for MSVC compilers if supported. -cmake_policy(SET CMP0141 NEW) - # Project project(onnxruntime C CXX ASM) +include(onnxruntime_language_standard_versions.cmake) + +# We don't use C++20 modules yet. +# There are some known issues to address first: +# - Android builds from Linux Docker containers have trouble finding clang-scan-deps. +# - The MSVC /permissive option is needed for compiling some of the CUDA EP code which uses CUTLASS. +# This option is not compatible with C++20 modules. +# So we will skip module scanning for now. +set(CMAKE_CXX_SCAN_FOR_MODULES OFF) + # Disable fast-math for Intel oneAPI compiler if("${CMAKE_CXX_COMPILER_ID}" MATCHES "IntelLLVM") if("${CMAKE_CXX_COMPILER_ID}" MATCHES "MSVC-like") @@ -31,45 +31,33 @@ if("${CMAKE_CXX_COMPILER_ID}" MATCHES "IntelLLVM") endif() endif() -# Needed for Java -set(CMAKE_C_STANDARD 99) - include(CheckCXXCompilerFlag) include(CheckLanguage) include(CMakeDependentOption) include(FetchContent) include(CheckFunctionExists) +include(CheckSymbolExists) include(GNUInstallDirs) # onnxruntime_providers_* require CMAKE_INSTALL_* variables -# TODO: update this once all system adapt c++20 -if(CMAKE_SYSTEM_NAME STREQUAL "Darwin") -set(CMAKE_CXX_STANDARD 20) -else() -set(CMAKE_CXX_STANDARD 17) -endif() - if (MSVC) # Make sure Visual Studio sets __cplusplus macro correctly: https://learn.microsoft.com/en-us/cpp/build/reference/zc-cplusplus set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /Zc:__cplusplus") + + # Prevents CMake from injecting '#pragma system_header', which results in warnings being disabled in projects that + # use precompiled headers. + set(CMAKE_PCH_PROLOGUE "") endif() set_property(GLOBAL PROPERTY USE_FOLDERS ON) # NOTE: POSITION INDEPENDENT CODE hurts performance, and it only make sense on POSIX systems set(CMAKE_POSITION_INDEPENDENT_CODE ON) -# Enable CTest enable_testing() -include(Dart) - if (NOT CMAKE_BUILD_TYPE) message(STATUS "Build type not set - using RelWithDebInfo") set(CMAKE_BUILD_TYPE "RelWithDebInfo" CACHE STRING "Choose build type: Debug Release RelWithDebInfo MinSizeRel." FORCE) endif() -if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 9) - message(FATAL_ERROR "GCC version must be greater than or equal to 9") -endif() - # Options option(onnxruntime_USE_VCPKG "Build with the vcpkg package manager" OFF) option(onnxruntime_RUN_ONNX_TESTS "Enable ONNX Compatibility Testing" OFF) @@ -77,9 +65,10 @@ option(onnxruntime_GENERATE_TEST_REPORTS "Enable test report generation" OFF) option(onnxruntime_ENABLE_STATIC_ANALYSIS "Enable static analysis" OFF) option(onnxruntime_USE_CUSTOM_STATIC_ANALYSIS_RULES "Use a custom SDL Rule. It is mainly for our CI build" OFF) option(onnxruntime_REDIRECT_STATIC_ANALYSIS_OUTPUTS_TO_FILE "Use a custom SDL Rule. It is mainly for our CI build" OFF) -option(onnxruntime_ENABLE_PYTHON "Enable python buildings" OFF) +option(onnxruntime_ENABLE_PYTHON "Enable python bindings" OFF) # Enable it may cause LNK1169 error option(onnxruntime_ENABLE_MEMLEAK_CHECKER "Experimental: Enable memory leak checker in Windows debug build" OFF) +option(onnxruntime_ENABLE_CONVSYMKERNELAVX2_SAT_CHECKER "Experimental: Enable ConvSymKernelAvx2 assembly saturation checker in build" OFF) option(onnxruntime_USE_CUDA "Build with CUDA support" OFF) # Enable ONNX Runtime CUDA EP's internal unit tests that directly access the EP's internal functions instead of through # OpKernels. When the option is ON, we will have two copies of GTest library in the same process. It is not a typical @@ -87,6 +76,7 @@ option(onnxruntime_USE_CUDA "Build with CUDA support" OFF) cmake_dependent_option(onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS "Build with CUDA unit tests" OFF "onnxruntime_USE_CUDA;onnxruntime_BUILD_UNIT_TESTS" OFF) cmake_dependent_option(onnxruntime_USE_CUDA_NHWC_OPS "Build CUDA with NHWC op support" ON "onnxruntime_USE_CUDA" OFF) +cmake_dependent_option(onnxruntime_BUILD_CUDA_EP_AS_PLUGIN "Build CUDA EP as a separate plugin shared library" OFF "onnxruntime_USE_CUDA" OFF) option(onnxruntime_CUDA_MINIMAL "Build CUDA without any operations apart from memcpy ops. Usefuel for a very minial TRT build" OFF) option(onnxruntime_ENABLE_CUDA_LINE_NUMBER_INFO "When building with CUDA support, generate device code line number information." OFF) option(onnxruntime_USE_OPENVINO "Build with OpenVINO support" OFF) @@ -98,6 +88,12 @@ option(onnxruntime_USE_SNPE "Build with SNPE support" OFF) option(onnxruntime_USE_RKNPU "Build with RKNPU support" OFF) option(onnxruntime_USE_DNNL "Build with DNNL support" OFF) option(onnxruntime_USE_JSEP "Build with JavaScript implemented kernels support" OFF) +option(onnxruntime_USE_SVE "Build with SVE support in MLAS" OFF) +option(onnxruntime_USE_RVV "Build with RISC-V Vector support in MLAS" OFF) +option(onnxruntime_USE_ARM_NEON_NCHWC "Build with ARM Neon NCHWc kernels in MLAS" OFF) + +option(onnxruntime_USE_KLEIDIAI "Build with KleidiAI integration in MLAS" OFF) +option(onnxruntime_USE_QMX_KLEIDIAI_COEXIST "Build with QMX and Arm KLEIDIAI libraries" OFF) option(onnxruntime_BUILD_UNIT_TESTS "Build ONNXRuntime unit tests" ON) option(onnxruntime_BUILD_CSHARP "Build C# library" OFF) option(onnxruntime_BUILD_OBJC "Build Objective-C library" OFF) @@ -106,8 +102,12 @@ option(onnxruntime_BUILD_BENCHMARKS "Build ONNXRuntime micro-benchmarks" OFF) option(onnxruntime_USE_VSINPU "Build with VSINPU support" OFF) cmake_dependent_option(onnxruntime_USE_FLASH_ATTENTION "Build flash attention kernel for scaled dot product attention" ON "onnxruntime_USE_CUDA" OFF) -cmake_dependent_option(onnxruntime_USE_LEAN_ATTENTION "Build lean attention kernel for scaled dot product attention" ON "onnxruntime_USE_CUDA; NOT WIN32" OFF) -option(onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION "Build memory efficient attention kernel for scaled dot product attention" ON) +option(onnxruntime_USE_LEAN_ATTENTION "Build lean attention kernel for scaled dot product attention" OFF) +cmake_dependent_option(onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION "Build memory efficient attention kernel for scaled dot product attention" ON "onnxruntime_USE_CUDA" OFF) +option(onnxruntime_USE_FPA_INTB_GEMM "Build FpA IntB gemm cuda kernels" OFF) +option(onnxruntime_USE_INT4_KV_CACHE "Build cuda kernels for int4 kv cache" OFF) +option(onnxruntime_USE_FP8_KV_CACHE "Build cuda kernels for fp8 kv cache" ON) +option(onnxruntime_QUICK_BUILD "Speed up build by skipping some kernels for faster development" OFF) option(onnxruntime_BUILD_FOR_NATIVE_MACHINE "Enable this option for turning on optimization specific to this machine" OFF) option(onnxruntime_USE_AVX "Use AVX instructions" OFF) @@ -121,6 +121,7 @@ option(onnxruntime_ENABLE_MICROSOFT_INTERNAL "Use this option to enable/disable option(onnxruntime_USE_VITISAI "Build with Vitis-AI" OFF) option(onnxruntime_USE_TENSORRT "Build with TensorRT support" OFF) option(onnxruntime_USE_TENSORRT_BUILTIN_PARSER "Use TensorRT builtin parser" OFF) +option(onnxruntime_USE_NV "Build with TensorRT support" OFF) option(onnxruntime_ENABLE_LTO "Enable link time optimization" OFF) option(onnxruntime_CROSS_COMPILING "Cross compiling onnx runtime" OFF) option(onnxruntime_GCOV_COVERAGE "Compile with options necessary to run code coverage" OFF) @@ -128,6 +129,7 @@ option(onnxruntime_DONT_VECTORIZE "Do not vectorize operations in Eigen" OFF) option(onnxruntime_USE_FULL_PROTOBUF "Link to libprotobuf instead of libprotobuf-lite when this option is ON" OFF) option(onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS "Dump debug information about node inputs and outputs when executing the model." OFF) +option(onnxruntime_DUMP_TENSOR "Dump tensor inside kernel." OFF) cmake_dependent_option(onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS_ENABLE_DUMP_TO_SQLDB "Build dump debug information about node inputs and outputs with support for sql database." OFF "onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS" OFF) # When loading a delay loaded DLL, Windows searches the main EXE's folder first. @@ -136,20 +138,19 @@ option(onnxruntime_USE_DML "Build with DirectML support" OFF) option(onnxruntime_USE_MIGRAPHX "Build with AMDMIGraphX support" OFF) option(onnxruntime_USE_WINML "Build with WinML support" OFF) option(onnxruntime_USE_ACL "Build with ACL support" OFF) -option(onnxruntime_USE_ARMNN "Build with ArmNN support" OFF) -option(onnxruntime_ARMNN_RELU_USE_CPU "Use the CPU implementation for the Relu operator for the ArmNN EP" ON) -option(onnxruntime_ARMNN_BN_USE_CPU "Use the CPU implementation for the Batch Normalization operator for the ArmNN EP" ON) option(onnxruntime_ENABLE_INSTRUMENT "Enable Instrument with Event Tracing for Windows (ETW)" OFF) option(onnxruntime_USE_TELEMETRY "Build with Telemetry" OFF) cmake_dependent_option(onnxruntime_USE_MIMALLOC "Override new/delete and arena allocator with mimalloc" OFF "WIN32;NOT onnxruntime_USE_CUDA;NOT onnxruntime_USE_OPENVINO" OFF) option(onnxruntime_USE_CANN "Build with CANN support" OFF) -option(onnxruntime_USE_ROCM "Build with AMD GPU support" OFF) option(onnxruntime_USE_XNNPACK "Build with XNNPACK support. Provides an alternative math library on ARM, WebAssembly and x86." OFF) option(onnxruntime_USE_WEBNN "Build with WebNN support. Enable hardware acceleration in web browsers." OFF) option(onnxruntime_USE_WEBGPU "Build with WebGPU support. Enable WebGPU via C/C++ interface." OFF) +option(onnxruntime_USE_EP_API_ADAPTERS "Build EP (e.g. WebGPU) as a plugin EP shared library using EP API adapters" OFF) +option(onnxruntime_WGSL_TEMPLATE "Specify the code generator for WGSL template. Default is static." "static") option(onnxruntime_USE_EXTERNAL_DAWN "Build with treating Dawn as external dependency. Will not link Dawn at build time." OFF) option(onnxruntime_CUSTOM_DAWN_SRC_PATH "Path to custom Dawn src dir.") -option(onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY "Build Dawn as a monolithic library" OFF) +option(onnxruntime_BUILD_DAWN_SHARED_LIBRARY "Build Dawn as a shared library" OFF) +option(onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP "Adding frame present for PIX to capture a frame" OFF) # The following 2 options are only for Windows option(onnxruntime_ENABLE_DAWN_BACKEND_VULKAN "Enable Vulkan backend for Dawn (on Windows)" OFF) option(onnxruntime_ENABLE_DAWN_BACKEND_D3D12 "Enable D3D12 backend for Dawn (on Windows)" ON) @@ -158,10 +159,15 @@ option(onnxruntime_ENABLE_DAWN_BACKEND_D3D12 "Enable D3D12 backend for Dawn (on # XNNPACK EP requires the internal NHWC contrib ops to be available, so this option must be OFF when onnxruntime_USE_XNNPACK is ON cmake_dependent_option(onnxruntime_DISABLE_CONTRIB_OPS "Disable contrib ops" OFF "NOT onnxruntime_USE_XNNPACK" OFF) option(onnxruntime_DISABLE_ML_OPS "Disable traditional ML ops" OFF) +option(onnxruntime_DISABLE_GENERATION_OPS "Disable generation contrib ops (BeamSearch, WhisperBeamSearch, GreedySearch, Sampling)" OFF) option(onnxruntime_DISABLE_SPARSE_TENSORS "Disable sparse tensors data types" OFF) option(onnxruntime_DISABLE_OPTIONAL_TYPE "Disable optional type" OFF) option(onnxruntime_DISABLE_FLOAT8_TYPES "Disable float 8 types" OFF) +option(onnxruntime_DISABLE_FLOAT4_TYPES "Disable float 4 types" OFF) +option(onnxruntime_DISABLE_STRING_TYPE "Disable string type" OFF) option(onnxruntime_MINIMAL_BUILD "Exclude as much as possible from the build. Support ORT format models. No support for ONNX format models." OFF) +option(onnxruntime_CLIENT_PACKAGE_BUILD "Enables default settings that are more appropriate for client/on-device workloads." OFF) +option(onnxruntime_ENABLE_SESSION_THREADPOOL_CALLBACKS "Enable per-session thread pool work callbacks." OFF) cmake_dependent_option(onnxruntime_DISABLE_RTTI "Disable RTTI" ON "NOT onnxruntime_ENABLE_PYTHON;NOT onnxruntime_USE_CUDA" OFF) # For now onnxruntime_DISABLE_EXCEPTIONS will only work with onnxruntime_MINIMAL_BUILD, more changes (ONNX, non-CPU EP, ...) are required to run this standalone cmake_dependent_option(onnxruntime_DISABLE_EXCEPTIONS "Disable exception handling. Requires onnxruntime_MINIMAL_BUILD currently." ON "onnxruntime_MINIMAL_BUILD;NOT onnxruntime_ENABLE_PYTHON" OFF) @@ -193,10 +199,10 @@ option(onnxruntime_ENABLE_TRAINING_OPS "Include training operators but no traini option(onnxruntime_ENABLE_TRAINING_E2E_TESTS "Enable training end-to-end tests." OFF) option(onnxruntime_ENABLE_CPU_FP16_OPS "Build with advanced instruction sets" ON) option(onnxruntime_USE_NCCL "Build with NCCL support" OFF) -option(onnxruntime_USE_MPI "Build with MPI support" OFF) # WebAssembly options option(onnxruntime_BUILD_WEBASSEMBLY_STATIC_LIB "Enable this option to create WebAssembly static library" OFF) +option(onnxruntime_ENABLE_WEBASSEMBLY_JSPI "Enable WebAssembly JavaScript Promise Integration" OFF) option(onnxruntime_ENABLE_WEBASSEMBLY_THREADS "Enable this option to create WebAssembly byte codes with multi-threads support" OFF) option(onnxruntime_ENABLE_WEBASSEMBLY_EXCEPTION_CATCHING "Enable this option to turn on exception catching" OFF) option(onnxruntime_ENABLE_WEBASSEMBLY_API_EXCEPTION_CATCHING "Enable this option to turn on api exception catching" OFF) @@ -205,7 +211,7 @@ option(onnxruntime_WEBASSEMBLY_RUN_TESTS_IN_BROWSER "Enable this option to run t option(onnxruntime_ENABLE_WEBASSEMBLY_DEBUG_INFO "Enable this option to turn on DWARF format debug info" OFF) option(onnxruntime_ENABLE_WEBASSEMBLY_PROFILING "Enable this option to turn on WebAssembly profiling and preserve function names" OFF) option(onnxruntime_ENABLE_WEBASSEMBLY_OUTPUT_OPTIMIZED_MODEL "Enable this option to allow WebAssembly to output optimized model" OFF) -option(onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64 "Enable this option to allow WebAssembly to use 64bit memory" OFF) +option(onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD "Enable WebAssembly Relaxed SIMD" OFF) # Enable bitcode for iOS option(onnxruntime_ENABLE_BITCODE "Enable bitcode for iOS only" OFF) @@ -234,7 +240,6 @@ option(onnxruntime_PREBUILT_PYTORCH_PATH "Path to pytorch installation dir") option(onnxruntime_EXTERNAL_TRANSFORMER_SRC_PATH "Path to external transformer src dir") option(onnxruntime_ENABLE_CUDA_PROFILING "Enable CUDA kernel profiling" OFF) -option(onnxruntime_ENABLE_ROCM_PROFILING "Enable ROCM kernel profiling" OFF) option(onnxruntime_ENABLE_CPUINFO "Enable cpuinfo" ON) @@ -243,31 +248,32 @@ option(onnxruntime_ENABLE_ATEN "Enable ATen fallback" OFF) # dlpack support cmake_dependent_option(onnxruntime_ENABLE_DLPACK "Enable dlpack" ON "onnxruntime_ENABLE_TRAINING OR onnxruntime_ENABLE_ATEN OR onnxruntime_ENABLE_PYTHON" OFF) - -# Triton support -option(onnxruntime_ENABLE_TRITON "Enable Triton" OFF) - -# composable kernel is managed automatically, unless user want to explicitly disable it, it should not be manually set -option(onnxruntime_USE_COMPOSABLE_KERNEL "Enable composable kernel for ROCm EP" ON) -cmake_dependent_option(onnxruntime_USE_COMPOSABLE_KERNEL_CK_TILE "Enable ck_tile for composable kernel" ON "onnxruntime_USE_COMPOSABLE_KERNEL" OFF) -option(onnxruntime_USE_ROCBLAS_EXTENSION_API "Enable rocblas tuning for ROCm EP" OFF) -option(onnxruntime_USE_TRITON_KERNEL "Enable triton compiled kernel" OFF) -option(onnxruntime_BUILD_KERNEL_EXPLORER "Build Kernel Explorer for testing and profiling GPU kernels" OFF) - -option(onnxruntime_BUILD_CACHE "onnxruntime build with cache" OFF) -# https://zeux.io/2010/11/22/z7-everything-old-is-new-again/ -cmake_dependent_option(MSVC_Z7_OVERRIDE "replacing /Zi and /ZI with /Z7 when using MSVC with CCache" ON "onnxruntime_BUILD_CACHE; MSVC" OFF) - option(onnxruntime_USE_AZURE "Build with azure inferencing support" OFF) option(onnxruntime_USE_LOCK_FREE_QUEUE "Build with lock-free task queue for threadpool." OFF) option(onnxruntime_FORCE_GENERIC_ALGORITHMS "Disable optimized arch-specific algorithms. Use only for testing and debugging generic algorithms." OFF) +# DX interop feature option +option(onnxruntime_USE_DX_INTEROP "Build with the DX Interop feature for graphics API synchronization." OFF) + +if (onnxruntime_USE_DX_INTEROP) + add_compile_definitions(USE_DX_INTEROP=1) +else() + add_compile_definitions(USE_DX_INTEROP=0) +endif() + option(onnxruntime_USE_TENSORRT_INTERFACE "Build ONNXRuntime shared lib which is compatible with TensorRT EP interface" OFF) +option(onnxruntime_USE_NV_INTERFACE "Build ONNXRuntime shared lib which is compatible with NV EP interface" OFF) option(onnxruntime_USE_CUDA_INTERFACE "Build ONNXRuntime shared lib which is compatible with Cuda EP interface" OFF) option(onnxruntime_USE_OPENVINO_INTERFACE "Build ONNXRuntime shared lib which is compatible with OpenVINO EP interface" OFF) option(onnxruntime_USE_VITISAI_INTERFACE "Build ONNXRuntime shared lib which is compatible with Vitis-AI EP interface" OFF) option(onnxruntime_USE_QNN_INTERFACE "Build ONNXRuntime shared lib which is compatible with QNN EP interface" OFF) +if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" AND CMAKE_C_COMPILER_VERSION VERSION_LESS 11.1) + message(FATAL_ERROR "GCC version must be greater than or equal to 11.1") +endif() + +include(detect_onnxruntime_target_platform.cmake) + # ENABLE_TRAINING includes all training functionality # The following 2 entry points # 1. ORTModule @@ -298,181 +304,14 @@ if (onnxruntime_ENABLE_TRAINING_APIS) endif() endif() -if (onnxruntime_USE_ROCM) - if (WIN32) - message(FATAL_ERROR "ROCM does not support build in Windows!") - endif() - if (onnxruntime_USE_CUDA) - message(FATAL_ERROR "ROCM does not support build with CUDA!") - endif() - - # replicate strategy used by pytorch to get ROCM_VERSION - # https://github.com/pytorch/pytorch/blob/5c5b71b6eebae76d744261715231093e62f0d090/cmake/public/LoadHIP.cmake - # with modification - if (EXISTS "${onnxruntime_ROCM_HOME}/.info/version") - message("\n***** ROCm version from ${onnxruntime_ROCM_HOME}/.info/version ****\n") - file(READ "${onnxruntime_ROCM_HOME}/.info/version" ROCM_VERSION_DEV_RAW) - string(REGEX MATCH "^([0-9]+)\.([0-9]+)\.([0-9]+)-.*$" ROCM_VERSION_MATCH ${ROCM_VERSION_DEV_RAW}) - elseif (EXISTS "${onnxruntime_ROCM_HOME}/include/rocm_version.h") - message("\n***** ROCm version from ${onnxruntime_ROCM_HOME}/include/rocm_version.h ****\n") - file(READ "${onnxruntime_ROCM_HOME}/include/rocm_version.h" ROCM_VERSION_H_RAW) - string(REGEX MATCH "\"([0-9]+)\.([0-9]+)\.([0-9]+).*\"" ROCM_VERSION_MATCH ${ROCM_VERSION_H_RAW}) - elseif (EXISTS "${onnxruntime_ROCM_HOME}/include/rocm-core/rocm_version.h") - message("\n***** ROCm version from ${onnxruntime_ROCM_HOME}/include/rocm-core/rocm_version.h ****\n") - file(READ "${onnxruntime_ROCM_HOME}/include/rocm-core/rocm_version.h" ROCM_VERSION_H_RAW) - string(REGEX MATCH "\"([0-9]+)\.([0-9]+)\.([0-9]+).*\"" ROCM_VERSION_MATCH ${ROCM_VERSION_H_RAW}) - endif() - - if (ROCM_VERSION_MATCH) - set(ROCM_VERSION_DEV_MAJOR ${CMAKE_MATCH_1}) - set(ROCM_VERSION_DEV_MINOR ${CMAKE_MATCH_2}) - set(ROCM_VERSION_DEV_PATCH ${CMAKE_MATCH_3}) - set(ROCM_VERSION_DEV "${ROCM_VERSION_DEV_MAJOR}.${ROCM_VERSION_DEV_MINOR}.${ROCM_VERSION_DEV_PATCH}") - math(EXPR ROCM_VERSION_DEV_INT "(${ROCM_VERSION_DEV_MAJOR}*10000) + (${ROCM_VERSION_DEV_MINOR}*100) + ${ROCM_VERSION_DEV_PATCH}") - - message("ROCM_VERSION_DEV: ${ROCM_VERSION_DEV}") - message("ROCM_VERSION_DEV_MAJOR: ${ROCM_VERSION_DEV_MAJOR}") - message("ROCM_VERSION_DEV_MINOR: ${ROCM_VERSION_DEV_MINOR}") - message("ROCM_VERSION_DEV_PATCH: ${ROCM_VERSION_DEV_PATCH}") - message("ROCM_VERSION_DEV_INT: ${ROCM_VERSION_DEV_INT}") - else() - message(FATAL_ERROR "Cannot determine ROCm version string") - endif() - - - if (NOT CMAKE_HIP_COMPILER) - set(CMAKE_HIP_COMPILER "${onnxruntime_ROCM_HOME}/llvm/bin/clang++") - endif() - if (NOT CMAKE_HIP_ARCHITECTURES) - if (ROCM_VERSION_DEV VERSION_LESS "6.2") - message(FATAL_ERROR "CMAKE_HIP_ARCHITECTURES is not set when ROCm version < 6.2") - else() - set(CMAKE_HIP_ARCHITECTURES "gfx908;gfx90a;gfx1030;gfx1100;gfx1101;gfx940;gfx941;gfx942;gfx1200;gfx1201") - endif() - endif() - - file(GLOB rocm_cmake_components ${onnxruntime_ROCM_HOME}/lib/cmake/*) - list(APPEND CMAKE_PREFIX_PATH ${rocm_cmake_components}) - # Force cmake to accept the configured HIP compiler. Because the configured CMAKE_PREFIX_PATH does not work during - # enable_language(HIP), we might need to move configuring of CMAKE_PREFIX_PATH to build.py (in the future). - set(CMAKE_HIP_COMPILER_FORCED ON) - - enable_language(HIP) - # NOTE: Flags -mllvm -amdgpu-early-inline-all=true are critical for gpu kernel code performance. -mllvm passes the - # next flag to underlying LLVM instead of clang and -amdgpu-early-inline-all=true is the optimization flag for LLVM. - # With CMake's enable_language(HIP), additional flags including the proceeding one are propagated from - # hip-lang::device library. But in some weird cases, the hip-lang::device target may not be properly configured, for - # example, the CMAKE_PREFIX_PATH might be improperly configured. - if(NOT DEFINED _CMAKE_HIP_DEVICE_RUNTIME_TARGET) - message(FATAL_ERROR "HIP Language is not properly configured.") - endif() - add_compile_options("$<$:SHELL:-x hip>") - - if (NOT onnxruntime_HIPIFY_PERL) - find_path(HIPIFY_PERL_PATH - NAMES hipify-perl - HINTS - ${onnxruntime_ROCM_HOME}/bin - ${onnxruntime_ROCM_HOME}/hip/bin) - if (HIPIFY_PERL_PATH-NOTFOUND) - MESSAGE(FATAL_ERROR "hipify-perl not found") - endif() - set(onnxruntime_HIPIFY_PERL ${HIPIFY_PERL_PATH}/hipify-perl) - endif() - - # replicate strategy used by pytorch to get ROCM_VERSION - # https://github.com/pytorch/pytorch/blob/1a10751731784942dcbb9c0524c1369a29d45244/cmake/public/LoadHIP.cmake#L45-L109 - # with modification - set(ROCM_INCLUDE_DIRS "${onnxruntime_ROCM_HOME}/include") - set(PROJECT_RANDOM_BINARY_DIR "${CMAKE_BINARY_DIR}") - set(file "${CMAKE_BINARY_DIR}/detect_rocm_version.cc") - - # Find ROCM version for checks - # ROCM 5.0 and later will have header api for version management - if(EXISTS ${ROCM_INCLUDE_DIRS}/rocm_version.h) - file(WRITE ${file} "" - "#include \n" - ) - elseif(EXISTS ${ROCM_INCLUDE_DIRS}/rocm-core/rocm_version.h) - file(WRITE ${file} "" - "#include \n" - ) - else() - message(FATAL_ERROR "********************* rocm_version.h couldnt be found ******************\n") - endif() - - file(APPEND ${file} "" - "#include \n" - - "#ifndef ROCM_VERSION_PATCH\n" - "#define ROCM_VERSION_PATCH 0\n" - "#endif\n" - "#define STRINGIFYHELPER(x) #x\n" - "#define STRINGIFY(x) STRINGIFYHELPER(x)\n" - "int main() {\n" - " printf(\"%d.%d.%s\", ROCM_VERSION_MAJOR, ROCM_VERSION_MINOR, STRINGIFY(ROCM_VERSION_PATCH));\n" - " return 0;\n" - "}\n" - ) - - try_run(run_result compile_result ${PROJECT_RANDOM_BINARY_DIR} ${file} - CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${ROCM_INCLUDE_DIRS}" - RUN_OUTPUT_VARIABLE rocm_version_from_header - COMPILE_OUTPUT_VARIABLE output_var - ) - # We expect the compile to be successful if the include directory exists. - if(NOT compile_result) - message(FATAL_ERROR "ROCM: Couldn't determine version from header: " ${output_var}) - endif() - message(STATUS "ROCM: Header version is: " ${rocm_version_from_header}) - set(ROCM_VERSION_DEV_RAW ${rocm_version_from_header}) - - string(REGEX MATCH "^([0-9]+)\.([0-9]+)\.([0-9]+).*$" ROCM_VERSION_DEV_MATCH ${ROCM_VERSION_DEV_RAW}) - - if (ROCM_VERSION_DEV_MATCH) - set(ROCM_VERSION_DEV_MAJOR ${CMAKE_MATCH_1}) - set(ROCM_VERSION_DEV_MINOR ${CMAKE_MATCH_2}) - set(ROCM_VERSION_DEV_PATCH ${CMAKE_MATCH_3}) - set(ROCM_VERSION_DEV "${ROCM_VERSION_DEV_MAJOR}.${ROCM_VERSION_DEV_MINOR}.${ROCM_VERSION_DEV_PATCH}") - math(EXPR ROCM_VERSION_DEV_INT "(${ROCM_VERSION_DEV_MAJOR}*10000) + (${ROCM_VERSION_DEV_MINOR}*100) + ${ROCM_VERSION_DEV_PATCH}") - else() - message(FATAL_ERROR "Cannot determine ROCm version string") - endif() - message("\n***** ROCm version from rocm_version.h ****\n") - message("ROCM_VERSION_DEV: ${ROCM_VERSION_DEV}") - message("ROCM_VERSION_DEV_MAJOR: ${ROCM_VERSION_DEV_MAJOR}") - message("ROCM_VERSION_DEV_MINOR: ${ROCM_VERSION_DEV_MINOR}") - message("ROCM_VERSION_DEV_PATCH: ${ROCM_VERSION_DEV_PATCH}") - message("ROCM_VERSION_DEV_INT: ${ROCM_VERSION_DEV_INT}") - message("\n***** HIP LANGUAGE CONFIG INFO ****\n") - message("CMAKE_HIP_COMPILER: ${CMAKE_HIP_COMPILER}") - message("CMAKE_HIP_ARCHITECTURES: ${CMAKE_HIP_ARCHITECTURES}") - message("CMAKE_HIP_FLAGS: ${CMAKE_HIP_FLAGS}") - string(TOUPPER ${CMAKE_BUILD_TYPE} BUILD_TYPE) - message("CMAKE_HIP_FLAGS_${BUILD_TYPE}: ${CMAKE_HIP_FLAGS_${BUILD_TYPE}}") - add_definitions(-DROCM_VERSION=${ROCM_VERSION_DEV_INT}) - - if (onnxruntime_USE_COMPOSABLE_KERNEL AND ROCM_VERSION_DEV VERSION_LESS "5.3") - message(WARNING "composable kernel is only supported on ROCm >= 5.3") - set(onnxruntime_USE_COMPOSABLE_KERNEL OFF) - set(onnxruntime_USE_COMPOSABLE_KERNEL_CK_TILE OFF) - endif() - if (onnxruntime_USE_COMPOSABLE_KERNEL_CK_TILE AND ROCM_VERSION_DEV VERSION_LESS "6.0") - message(WARNING "ck_tile can only be enabled on ROCm >= 6.0 due to compatibility and compilation speed, disable automatically") - set(onnxruntime_USE_COMPOSABLE_KERNEL_CK_TILE OFF) - endif() - if (onnxruntime_USE_COMPOSABLE_KERNEL_CK_TILE AND CMAKE_BUILD_TYPE STREQUAL "Debug") - message(WARNING "ck_tile hits compiler error in Debug build, disable automatically") - set(onnxruntime_USE_COMPOSABLE_KERNEL_CK_TILE OFF) - endif() -endif() - - - -# Single output director for all binaries +# Single output directory for all binaries set(RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin CACHE PATH "Single output directory for all binaries.") +# Local mirror directory of cmake dependencies +set(REPO_ROOT ${PROJECT_SOURCE_DIR}/..) +set(onnxruntime_CMAKE_DEPS_MIRROR_DIR ${REPO_ROOT}/mirror CACHE PATH "Path to the local mirror of cmake dependencies") + include(FetchContent) @@ -567,6 +406,11 @@ if (onnxruntime_ENABLE_TRITON) endif() endif() +# Building plugin EPs that depend on EP API adapters. +if(onnxruntime_USE_EP_API_ADAPTERS) + add_compile_definitions(ORT_USE_EP_API_ADAPTERS=1) +endif() + # General C# properties if (onnxruntime_BUILD_CSHARP) check_language(CSharp) @@ -608,21 +452,12 @@ if (onnxruntime_EXTENDED_MINIMAL_BUILD AND NOT onnxruntime_MINIMAL_BUILD) set(onnxruntime_MINIMAL_BUILD ON) endif() -set(REPO_ROOT ${PROJECT_SOURCE_DIR}/..) set(ONNXRUNTIME_ROOT ${PROJECT_SOURCE_DIR}/../onnxruntime) set(ORTTRAINING_ROOT ${PROJECT_SOURCE_DIR}/../orttraining) set(ORTTRAINING_SOURCE_DIR ${ORTTRAINING_ROOT}/orttraining) include(adjust_global_compile_flags.cmake) -if (APPLE) - if (NOT CMAKE_OSX_ARCHITECTURES) - message("Building ONNX Runtime for ${CMAKE_HOST_SYSTEM_PROCESSOR} CPU ARCH") - endif() -elseif (NOT WIN32 AND NOT APPLE) - message("Building ONNX Runtime for ${onnxruntime_target_platform} CPU ARCH") -endif() - # We need to link with libatomic on systems that do not have built-in atomics, or # don't have built-in support for 8 byte atomics # Derived from https://github.com/protocolbuffers/protobuf/blob/master/cmake/CMakeLists.txt @@ -681,16 +516,65 @@ endif() if (onnxruntime_BUILD_SHARED_LIB OR onnxruntime_ENABLE_PYTHON) if (onnxruntime_ENABLE_PYTHON) if (onnxruntime_REQUIRE_PYTHON_EMBED_LIB) - find_package(Python 3.8 COMPONENTS Interpreter Development NumPy) + find_package(Python 3.10 COMPONENTS Interpreter Development NumPy) else() - find_package(Python 3.8 COMPONENTS Interpreter Development.Module NumPy) + find_package(Python 3.10 COMPONENTS Interpreter Development.Module NumPy) endif() message("Numpy version: ${Python_NumPy_VERSION}") if(Python_NumPy_VERSION VERSION_LESS "2.0.0") message(WARNING "The build binary will not be compatible with NumPy 2.0 because the NumPy installed on this machine is too low.") endif() else() - find_package(Python 3.8 COMPONENTS Interpreter) + find_package(Python 3.10 COMPONENTS Interpreter) + endif() +endif() + +if (onnxruntime_USE_ARM_NEON_NCHWC) + message(STATUS "Building MLAS with ARM Neon NCHWc kernels") +endif() + +if(onnxruntime_USE_SVE) + if(LINUX AND onnxruntime_target_platform STREQUAL "aarch64") + check_cxx_compiler_flag("-march=armv8.2-a+sve" HAS_ARM64_SVE) + if(HAS_ARM64_SVE) + message(STATUS "Compiler supports SVE!") + else() + message(WARNING "onnxruntime_USE_SVE was set but compiler does not support SVE. It will be disabled.") + set(onnxruntime_USE_SVE OFF) + endif() + else() + message(WARNING "onnxruntime_USE_SVE was set but it is not supported on this platform. It will be disabled.") + set(onnxruntime_USE_SVE OFF) + endif() +endif() + +if(onnxruntime_USE_KLEIDIAI) + function(is_kleidiai_supported is_supported_var) + # check for supported target platforms + if(NOT (onnxruntime_target_platform STREQUAL "aarch64" OR + onnxruntime_target_platform STREQUAL "ARM64" OR + onnxruntime_target_platform STREQUAL "arm64")) + message(WARNING "KleidiAI is not supported on this platform.") + + set(${is_supported_var} FALSE PARENT_SCOPE) + return() + endif() + + if(MSVC AND CMAKE_CXX_COMPILER_ID STREQUAL "MSVC" AND MSVC_VERSION VERSION_LESS 1940) + message(WARNING "KleidiAI requires MSVC compiler version 19.40 or newer, KleidiAI will be disabled in this build.") + + set(${is_supported_var} FALSE PARENT_SCOPE) + return() + endif() + + set(${is_supported_var} TRUE PARENT_SCOPE) + endfunction() + + is_kleidiai_supported(is_kleidiai_supported_result) + + if(NOT is_kleidiai_supported_result) + message(WARNING "onnxruntime_USE_KLEIDIAI was set but it is not supported. It will be disabled.") + set(onnxruntime_USE_KLEIDIAI OFF) endif() endif() @@ -744,11 +628,16 @@ if (WIN32) endif() else() + # Check for compiler flags check_cxx_compiler_flag(-Wambiguous-reversed-operator HAS_AMBIGUOUS_REVERSED_OPERATOR) + # -Winterference-size was added in GCC 13 + check_cxx_compiler_flag(-Winterference-size HAS_INTERFERENCE_SIZE) + check_cxx_compiler_flag(-Warray-bounds HAS_ARRAY_BOUNDS) check_cxx_compiler_flag(-Wbitwise-instead-of-logical HAS_BITWISE_INSTEAD_OF_LOGICAL) check_cxx_compiler_flag(-Wcast-function-type HAS_CAST_FUNCTION_TYPE) check_cxx_compiler_flag(-Wcatch-value HAS_CATCH_VALUE) check_cxx_compiler_flag(-Wclass-memaccess HAS_CLASS_MEMACCESS) + check_cxx_compiler_flag(-Wcharacter-conversion HAS_CHARACTER_CONVERSION) check_cxx_compiler_flag(-Wdangling-reference HAS_DANGLING_REFERENCE) check_cxx_compiler_flag(-Wdeprecated-anon-enum-enum-conversion HAS_DEPRECATED_ANON_ENUM_ENUM_CONVERSION) check_cxx_compiler_flag(-Wdeprecated-builtins HAS_DEPRECATED_BUILTINS) @@ -765,7 +654,6 @@ else() check_cxx_compiler_flag(-Wparentheses HAS_PARENTHESES) check_cxx_compiler_flag(-Wshorten-64-to-32 HAS_SHORTEN_64_TO_32) check_cxx_compiler_flag(-Wstrict-aliasing HAS_STRICT_ALIASING) - check_nvcc_compiler_flag(-Wstrict-aliasing NVCC_HAS_STRICT_ALIASING) check_cxx_compiler_flag(-Wstringop-overflow HAS_STRINGOP_OVERFLOW) check_cxx_compiler_flag(-Wtautological-pointer-compare HAS_TAUTOLOGICAL_POINTER_COMPARE) check_cxx_compiler_flag(-Wundefined-var-template HAS_UNDEFINED_VAR_TEMPLATE) @@ -790,6 +678,7 @@ else() message(FATAL_ERROR "The compiler doesn't support FLOAT16!!!") endif() endif() + if (HAS_TAUTOLOGICAL_POINTER_COMPARE) #we may have extra null pointer checkings in debug build, it's not an issue list(APPEND ORT_WARNING_FLAGS -Wno-tautological-pointer-compare) @@ -804,6 +693,7 @@ else() endif() if (HAS_DEPRECATED_ANON_ENUM_ENUM_CONVERSION) list(APPEND ORT_WARNING_FLAGS -Wno-deprecated-anon-enum-enum-conversion) + list(APPEND ORT_WARNING_FLAGS -Wno-deprecated-enum-enum-conversion) endif() if (HAS_UNDEFINED_VAR_TEMPLATE) list(APPEND ORT_WARNING_FLAGS -Wno-undefined-var-template) @@ -825,6 +715,12 @@ else() endif() endif() + if(HAS_INTERFERENCE_SIZE) + # The warning was from Eigen. Since we do not use Eigen in the public API, we can ignore it. + # However, it also means that part of our code was compiled based on the build machine's hardware spec. + # Specifically, the code was tuned based on the build machine's CPU cache line size, which can vary a lot. + list(APPEND ORT_WARNING_FLAGS -Wno-interference-size) + endif() # enable warning(s) that may not be on by default if (HAS_SHORTEN_64_TO_32) list(APPEND ORT_WARNING_FLAGS -Wshorten-64-to-32) @@ -838,9 +734,12 @@ endif() set(ONNXRUNTIME_PROVIDER_NAMES cpu) set(ORT_PROVIDER_FLAGS) -set(ORT_PROVIDER_CMAKE_FLAGS) if (onnxruntime_USE_CUDA) + include(cuda_configuration) + setup_cuda_compiler() + setup_cuda_architectures() + enable_language(CUDA) message( STATUS "CMAKE_CUDA_COMPILER_VERSION: ${CMAKE_CUDA_COMPILER_VERSION}") @@ -848,21 +747,9 @@ if (onnxruntime_USE_CUDA) set(onnxruntime_USE_FLASH_ATTENTION OFF) set(onnxruntime_USE_LEAN_ATTENTION OFF) set(onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION OFF) + set(onnxruntime_USE_FPA_INTB_GEMM OFF) endif() - if (CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 11.6) - message( STATUS "Turn off flash attention since CUDA compiler version < 11.6") - set(onnxruntime_USE_FLASH_ATTENTION OFF) - set(onnxruntime_USE_LEAN_ATTENTION OFF) - set(onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION OFF) - elseif(WIN32 AND CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 12) - message( STATUS "Flash-Attention unsupported in Windows with CUDA compiler version < 12.0") - set(onnxruntime_USE_FLASH_ATTENTION OFF) - endif() - - if (CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 11.4) - message( FATAL_ERROR "Failed build due to CUDA compiler version < 11.4") - endif() if (WIN32) message( STATUS "Lean Attention unsupported in Windows") set(onnxruntime_USE_LEAN_ATTENTION OFF) @@ -873,74 +760,116 @@ else() set(onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION OFF) endif() -if (onnxruntime_USE_CUDA OR onnxruntime_USE_CUDA_INTERFACE) +if (onnxruntime_USE_CUDA) list(APPEND ORT_PROVIDER_FLAGS -DUSE_CUDA=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_CUDA=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES cuda) if (onnxruntime_USE_FLASH_ATTENTION) message( STATUS "Enable flash attention for CUDA EP") list(APPEND ORT_PROVIDER_FLAGS -DUSE_FLASH_ATTENTION=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_FLASH_ATTENTION=1) endif() if (onnxruntime_USE_LEAN_ATTENTION) message( STATUS "Enable lean attention for CUDA EP") list(APPEND ORT_PROVIDER_FLAGS -DUSE_LEAN_ATTENTION=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_LEAN_ATTENTION=1) endif() if (onnxruntime_USE_MEMORY_EFFICIENT_ATTENTION) message( STATUS "Enable memory efficient attention for CUDA EP") list(APPEND ORT_PROVIDER_FLAGS -DUSE_MEMORY_EFFICIENT_ATTENTION=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_MEMORY_EFFICIENT_ATTENTION=1) + endif() + + if (onnxruntime_USE_FPA_INTB_GEMM) + message( STATUS "Enable FpA IntB Gemm for CUDA EP") + list(APPEND ORT_PROVIDER_FLAGS -DUSE_FPA_INTB_GEMM=1) + endif() + + if (onnxruntime_QUICK_BUILD) + message( STATUS "Quick build mode: Flash attention limited to head dimension 128 only") + list(APPEND ORT_PROVIDER_FLAGS -DORT_QUICK_BUILD=1) + endif() + + if (onnxruntime_USE_INT4_KV_CACHE) + message( STATUS "Enable int4 kv cache for CUDA EP") + list(APPEND ORT_PROVIDER_FLAGS -DUSE_INT4_KV_CACHE=1) + endif() + + if (onnxruntime_USE_FP8_KV_CACHE) + message( STATUS "Enable fp8 kv cache for CUDA EP") + list(APPEND ORT_PROVIDER_FLAGS -DUSE_FP8_KV_CACHE=1) endif() endif() -if (onnxruntime_USE_VITISAI OR onnxruntime_USE_VITISAI_INTERFACE) +if (onnxruntime_USE_CUDA_INTERFACE AND (NOT onnxruntime_USE_CUDA)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_CUDA_PROVIDER_INTERFACE=1) +endif() + +if (onnxruntime_USE_VITISAI) list(APPEND ORT_PROVIDER_FLAGS -DUSE_VITISAI=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_VITISAI=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES vitisai) endif() + +if (onnxruntime_USE_VITISAI_INTERFACE AND (NOT onnxruntime_USE_VITISAI)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_VITISAI_PROVIDER_INTERFACE=1) +endif() + if (onnxruntime_USE_DNNL) list(APPEND ORT_PROVIDER_FLAGS -DUSE_DNNL=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES dnnl) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_DNNL=1) endif() -if (onnxruntime_USE_OPENVINO OR onnxruntime_USE_OPENVINO_INTERFACE) + +if (onnxruntime_USE_OPENVINO) list(APPEND ORT_PROVIDER_FLAGS -DUSE_OPENVINO=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES openvino) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_OPENVINO=1) endif() -if (onnxruntime_USE_TENSORRT OR onnxruntime_USE_TENSORRT_INTERFACE) + +if (onnxruntime_USE_OPENVINO_INTERFACE AND (NOT onnxruntime_USE_OPENVINO)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_OPENVINO_PROVIDER_INTERFACE=1) +endif() + +if (onnxruntime_USE_TENSORRT) list(APPEND ORT_PROVIDER_FLAGS -DUSE_TENSORRT=1) #TODO: remove the following line and change the test code in onnxruntime_shared_lib_test to use the new EP API. list(APPEND ONNXRUNTIME_PROVIDER_NAMES tensorrt) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_TENSORRT=1) endif() + +if (onnxruntime_USE_TENSORRT_INTERFACE AND (NOT onnxruntime_USE_TENSORRT)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_TENSORRT_PROVIDER_INTERFACE=1) +endif() + +if (onnxruntime_USE_NV) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_NV=1) + list(APPEND ONNXRUNTIME_PROVIDER_NAMES nv_tensorrt_rtx) +endif() + +if (onnxruntime_USE_NV_INTERFACE AND (NOT onnxruntime_USE_NV)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_NV_PROVIDER_INTERFACE=1) +endif() + if (onnxruntime_USE_RKNPU) list(APPEND ORT_PROVIDER_FLAGS -DUSE_RKNPU=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_RKNPU=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES rknpu) endif() if (onnxruntime_USE_VSINPU) list(APPEND ORT_PROVIDER_FLAGS -DUSE_VSINPU=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_VSINPU=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES vsinpu) endif() if (onnxruntime_USE_NNAPI_BUILTIN) list(APPEND ORT_PROVIDER_FLAGS -DUSE_NNAPI=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_NNAPI_BUILTIN=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES nnapi) endif() if (onnxruntime_USE_JSEP) list(APPEND ORT_PROVIDER_FLAGS -DUSE_JSEP=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_JSEP=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES js) endif() if (onnxruntime_USE_QNN OR onnxruntime_USE_QNN_INTERFACE) - list(APPEND ORT_PROVIDER_FLAGS -DUSE_QNN=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_QNN=1) + + if(onnxruntime_USE_QNN) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_QNN=1) + else() + list(APPEND ORT_PROVIDER_FLAGS -DUSE_QNN_PROVIDER_INTERFACE=1) + endif() + list(APPEND ONNXRUNTIME_PROVIDER_NAMES qnn) if (NOT QNN_ARCH_ABI) string(TOLOWER ${onnxruntime_target_platform} GEN_PLATFORM) @@ -966,16 +895,20 @@ if (onnxruntime_USE_QNN OR onnxruntime_USE_QNN_INTERFACE) endif() endif() - if ((NOT onnxruntime_USE_QNN_INTERFACE) AND (MSVC OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")) + if (onnxruntime_USE_QNN AND (MSVC OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux")) file(GLOB QNN_LIB_FILES LIST_DIRECTORIES false "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/libQnn*.so" - "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/Qnn*.dll" + "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/Qnn*.dll" "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/libHtpPrepare.so" "${onnxruntime_QNN_HOME}/lib/${QNN_ARCH_ABI}/HtpPrepare.dll") if (${QNN_ARCH_ABI} STREQUAL "aarch64-windows-msvc" OR ${QNN_ARCH_ABI} STREQUAL "arm64x-windows-msvc") file(GLOB EXTRA_HTP_LIB LIST_DIRECTORIES false "${onnxruntime_QNN_HOME}/lib/hexagon-v68/unsigned/libQnnHtpV68Skel.so" - "${onnxruntime_QNN_HOME}/lib/hexagon-v73/unsigned/libQnnHtpV73Skel.so" - "${onnxruntime_QNN_HOME}/lib/hexagon-v73/unsigned/libqnnhtpv73.cat") + "${onnxruntime_QNN_HOME}/lib/hexagon-v73/unsigned/libQnnHtpV73Skel.so" + "${onnxruntime_QNN_HOME}/lib/hexagon-v73/unsigned/libqnnhtpv73.cat" + "${onnxruntime_QNN_HOME}/lib/hexagon-v81/unsigned/libQnnHtpV81Skel.so" + "${onnxruntime_QNN_HOME}/lib/hexagon-v81/unsigned/libqnnhtpv81.cat") list(APPEND QNN_LIB_FILES ${EXTRA_HTP_LIB}) + elseif(${QNN_ARCH_ABI} STREQUAL "aarch64-ubuntu-gcc9.4") + list(APPEND QNN_LIB_FILES "${onnxruntime_QNN_HOME}/lib/hexagon-v68/unsigned/libQnnHtpV68Skel.so") endif() message(STATUS "QNN lib files: " ${QNN_LIB_FILES}) endif() @@ -983,21 +916,17 @@ endif() if (onnxruntime_USE_SNPE) list(APPEND ORT_PROVIDER_FLAGS -DUSE_SNPE=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES snpe) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_SNPE=1) endif() if (onnxruntime_USE_WINML) list(APPEND ORT_PROVIDER_FLAGS -DUSE_WINML=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_WINML=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES winml) endif() if (onnxruntime_USE_ACL) list(APPEND ORT_PROVIDER_FLAGS -DUSE_ACL=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_ACL=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES acl) endif() if (onnxruntime_USE_DML) list(APPEND ORT_PROVIDER_FLAGS -DUSE_DML=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_DML=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES dml) if(onnxruntime_ENABLE_NPU_ADAPTER_ENUMERATION) list(APPEND ORT_PROVIDER_FLAGS -DENABLE_NPU_ADAPTER_ENUMERATION=1) @@ -1005,59 +934,88 @@ if (onnxruntime_USE_DML) endif() if (onnxruntime_USE_MIGRAPHX) list(APPEND ORT_PROVIDER_FLAGS -DUSE_MIGRAPHX=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_MIGRAPHX=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES migraphx) endif() -if (onnxruntime_USE_ARMNN) - list(APPEND ORT_PROVIDER_FLAGS -DUSE_ARMNN=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_ARMNN=1) - list(APPEND ONNXRUNTIME_PROVIDER_NAMES armnn) -endif() -if (onnxruntime_USE_ROCM) - list(APPEND ORT_PROVIDER_FLAGS -DUSE_ROCM=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_ROCM=1) - list(APPEND ONNXRUNTIME_PROVIDER_NAMES rocm) + +if (onnxruntime_USE_MIGRAPHX_INTERFACE AND (NOT onnxruntime_USE_MIGRAPHX)) + list(APPEND ORT_PROVIDER_FLAGS -DUSE_MIGRAPHX_PROVIDER_INTERFACE=1) endif() + if (onnxruntime_USE_COREML) list(APPEND ORT_PROVIDER_FLAGS -DUSE_COREML=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_COREML=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES coreml) endif() if (onnxruntime_USE_XNNPACK) list(APPEND ORT_PROVIDER_FLAGS -DUSE_XNNPACK=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_XNNPACK=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES xnnpack) endif() if (onnxruntime_USE_WEBNN) list(APPEND ORT_PROVIDER_FLAGS -DUSE_WEBNN=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_WEBNN=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES webnn) endif() if (onnxruntime_USE_WEBGPU) list(APPEND ORT_PROVIDER_FLAGS -DUSE_WEBGPU=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_WEBGPU=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES webgpu) - if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) - list(APPEND ORT_PROVIDER_FLAGS -DBUILD_DAWN_MONOLITHIC_LIBRARY=1) + + # TODO: the following code is used to disable building Dawn using vcpkg temporarily + # until we figure out how to resolve the packaging pipeline failures + # + # if (onnxruntime_USE_VCPKG AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + if (FALSE) + if (onnxruntime_BUILD_DAWN_SHARED_LIBRARY) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with onnxruntime_BUILD_DAWN_SHARED_LIBRARY=ON") + endif() + if (onnxruntime_USE_EXTERNAL_DAWN) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with onnxruntime_USE_EXTERNAL_DAWN=ON") + endif() + if (onnxruntime_CUSTOM_DAWN_SRC_PATH) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with a custom dawn source path") + endif() + if (WIN32) + if (onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with onnxruntime_ENABLE_DAWN_BACKEND_VULKAN=ON") + endif() + if (NOT onnxruntime_ENABLE_DAWN_BACKEND_D3D12) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with onnxruntime_ENABLE_DAWN_BACKEND_D3D12=OFF") + endif() + if (onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP) + message(FATAL_ERROR "onnxruntime_USE_VCPKG is not supported with onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP=ON") + endif() + endif() endif() + + if (onnxruntime_BUILD_DAWN_SHARED_LIBRARY) + if (NOT onnxruntime_USE_EP_API_ADAPTERS) + list(APPEND ORT_PROVIDER_FLAGS -DBUILD_DAWN_SHARED_LIBRARY=1) + else() + message(FATAL_ERROR "onnxruntime_USE_EP_API_ADAPTERS=ON is not supported with onnxruntime_BUILD_DAWN_SHARED_LIBRARY=ON") + endif() + endif() + if (onnxruntime_USE_EXTERNAL_DAWN) list(APPEND ORT_PROVIDER_FLAGS -DUSE_EXTERNAL_DAWN=1) endif() - if (onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) + if ((onnxruntime_ENABLE_DAWN_BACKEND_VULKAN AND WIN32) OR LINUX OR ANDROID) list(APPEND ORT_PROVIDER_FLAGS -DDAWN_ENABLE_VULKAN=1) endif() - if (onnxruntime_ENABLE_DAWN_BACKEND_D3D12) + if (onnxruntime_ENABLE_DAWN_BACKEND_D3D12 AND WIN32) list(APPEND ORT_PROVIDER_FLAGS -DDAWN_ENABLE_D3D12=1) endif() + if (onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP) + if (NOT onnxruntime_ENABLE_DAWN_BACKEND_D3D12 OR NOT WIN32) + message( + FATAL_ERROR + "Option onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP can only be set on windows with onnxruntime_ENABLE_DAWN_BACKEND_D3D12 is enabled.") + endif() + add_compile_definitions(ENABLE_PIX_FOR_WEBGPU_EP) + endif() endif() if (onnxruntime_USE_CANN) list(APPEND ORT_PROVIDER_FLAGS -DUSE_CANN=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_CANN=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES cann) endif() if (onnxruntime_USE_AZURE) list(APPEND ORT_PROVIDER_FLAGS -DUSE_AZURE=1) - list(APPEND ORT_PROVIDER_CMAKE_FLAGS -Donnxruntime_USE_AZURE=1) list(APPEND ONNXRUNTIME_PROVIDER_NAMES azure) endif() if (onnxruntime_USE_LOCK_FREE_QUEUE) @@ -1087,6 +1045,16 @@ function(onnxruntime_set_compile_flags target_name) endif() if(onnxruntime_ENABLE_LAZY_TENSOR) target_compile_definitions(${target_name} PRIVATE ENABLE_LAZY_TENSOR) + endif() + # Enable stream for all the non-minimal build + if (NOT onnxruntime_MINIMAL_BUILD) + target_compile_definitions(${target_name} PRIVATE ORT_ENABLE_STREAM) + endif() + if (onnxruntime_REDUCED_OPS_BUILD) + target_compile_definitions(${target_name} PRIVATE REDUCED_OPS_BUILD) + endif() + if (onnxruntime_DISABLE_EXTERNAL_INITIALIZERS) + target_compile_definitions(${target_name} PRIVATE DISABLE_EXTERNAL_INITIALIZERS) endif() if (onnxruntime_ENABLE_CPU_FP16_OPS) target_compile_definitions(${target_name} PRIVATE ENABLE_CPU_FP16_TRAINING_OPS) @@ -1106,6 +1074,10 @@ function(onnxruntime_set_compile_flags target_name) target_compile_definitions(${target_name} PRIVATE DISABLE_ML_OPS) endif() + if (onnxruntime_DISABLE_GENERATION_OPS) + target_compile_definitions(${target_name} PRIVATE DISABLE_GENERATION_OPS) + endif() + if (onnxruntime_DISABLE_SPARSE_TENSORS) target_compile_definitions(${target_name} PRIVATE DISABLE_SPARSE_TENSORS) endif() @@ -1118,21 +1090,35 @@ function(onnxruntime_set_compile_flags target_name) target_compile_definitions(${target_name} PRIVATE DISABLE_FLOAT8_TYPES) endif() + if (onnxruntime_DISABLE_FLOAT4_TYPES) + target_compile_definitions(${target_name} PRIVATE DISABLE_FLOAT4_TYPES) + endif() + + if (onnxruntime_DISABLE_STRING_TYPE) + target_compile_definitions(${target_name} PRIVATE DISABLE_STRING_TYPE) + endif() + if (onnxruntime_ENABLE_ATEN) target_compile_definitions(${target_name} PRIVATE ENABLE_ATEN) endif() + # TODO: Narrow scope for Kleidiai compile + if (onnxruntime_USE_KLEIDIAI) + target_compile_definitions(${target_name} PRIVATE USE_KLEIDIAI) + endif() set_target_properties(${target_name} PROPERTIES COMPILE_WARNING_AS_ERROR ON) if (onnxruntime_USE_CUDA) # Suppress a "conversion_function_not_usable" warning in gsl/span target_compile_options(${target_name} PRIVATE "$<$:SHELL:-Xcudafe \"--diag_suppress=conversion_function_not_usable\">") - target_compile_definitions(${target_name} PRIVATE -DDISABLE_CUSPARSE_DEPRECATED) endif() if (MSVC) foreach(CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORY ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) target_compile_options(${target_name} PRIVATE "$<$:/external:I${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORY}>") endforeach() - + if(VCPKG_INSTALLED_DIR) + cmake_path(NATIVE_PATH VCPKG_INSTALLED_DIR NORMALIZE VCPKG_INSTALLED_DIR_native) + target_compile_options(${target_name} PRIVATE "$<$:SHELL:/external:I ${VCPKG_INSTALLED_DIR_native}>") + endif() foreach(onnxruntime_external_lib IN LISTS onnxruntime_EXTERNAL_LIBRARIES) #TODO: the list contains cmake keywords like "debug". We should exclude them. if(TARGET ${onnxruntime_external_lib}) @@ -1162,7 +1148,9 @@ function(onnxruntime_set_compile_flags target_name) # We do not treat warnings from 3rd-party libraries as errors. In order to do that, we need to add their header files locations to /external:I. target_compile_options(${target_name} PRIVATE "$<$:/experimental:external>" "$<$:SHELL:--compiler-options /experimental:external>") target_compile_options(${target_name} PRIVATE "$<$:/external:W0>" "$<$:SHELL:--compiler-options /external:W0>") - target_compile_options(${target_name} PRIVATE "$<$:/external:templates->" "$<$:SHELL:--compiler-options /external:templates->") + #if(NOT onnxruntime_USE_VCPKG) + # target_compile_options(${target_name} PRIVATE "$<$:/external:templates->" "$<$:SHELL:--compiler-options /external:templates->") + #endif() target_compile_options(${target_name} PRIVATE "$<$:/external:I${CMAKE_CURRENT_SOURCE_DIR}>" "$<$:SHELL:--compiler-options /external:I${CMAKE_CURRENT_SOURCE_DIR}>") target_compile_options(${target_name} PRIVATE "$<$:/external:I${CMAKE_CURRENT_BINARY_DIR}>" "$<$:SHELL:--compiler-options /external:I${CMAKE_CURRENT_BINARY_DIR}>") if (onnxruntime_ENABLE_STATIC_ANALYSIS) @@ -1191,6 +1179,7 @@ function(onnxruntime_set_compile_flags target_name) foreach(ORT_FLAG ${ORT_PROVIDER_FLAGS}) target_compile_definitions(${target_name} PRIVATE ${ORT_FLAG}) endforeach() + if (HAS_DEPRECATED_COPY) #too many such errors in eigen target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options -Wno-deprecated-copy>" "$<$:-Wno-deprecated-copy>") @@ -1203,7 +1192,9 @@ function(onnxruntime_set_compile_flags target_name) endif() if (onnxruntime_USE_CUDA) foreach(FLAG ${ORT_WARNING_FLAGS}) - target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options ${FLAG}>") + if (NOT "${FLAG}" STREQUAL "-Wshorten-64-to-32") + target_compile_options(${target_name} PRIVATE "$<$:SHELL:--compiler-options ${FLAG}>") + endif() endforeach() if (NVCC_HAS_STRICT_ALIASING AND "${target_name}" MATCHES "cuda") target_compile_options(${target_name} PRIVATE "$<$:-Wno-strict-aliasing>") @@ -1212,31 +1203,6 @@ function(onnxruntime_set_compile_flags target_name) target_compile_options(${target_name} PRIVATE "$<$:-Wno-strict-aliasing>") endif() endif() - if (onnxruntime_USE_ROCM) - # flags are detected with CXX language mode, some flags are not supported with hipclang - # because we may mix gcc and hipclang - set(ORT_HIP_WARNING_FLAGS ${ORT_WARNING_FLAGS}) - list(REMOVE_ITEM ORT_HIP_WARNING_FLAGS -Wno-nonnull-compare) - # Unsupported by Clang 18 yet. - list(REMOVE_ITEM ORT_HIP_WARNING_FLAGS -Wno-dangling-reference) - - # float16.h:90:12: error: ‘tmp’ is used uninitialized - list(APPEND ORT_HIP_WARNING_FLAGS -Wno-uninitialized) - list(APPEND ORT_HIP_WARNING_FLAGS -Wno-deprecated-copy) - - # some #pragma unroll will fail, do not treat them as error - # #warning must not be treated as error - list(APPEND ORT_HIP_WARNING_FLAGS -Wno-error=pass-failed "-Wno-error=#warnings") - - # otherwise error: builtin __has_trivial_assign is deprecated; use __is_trivially_assignable instead - if (ROCM_VERSION_DEV VERSION_GREATER_EQUAL "5.4") - list(APPEND ORT_HIP_WARNING_FLAGS "-Wno-deprecated-builtins") - endif() - - foreach(FLAG ${ORT_HIP_WARNING_FLAGS}) - target_compile_options(${target_name} PRIVATE "$<$:SHELL:${FLAG}>") - endforeach() - endif() endfunction() function(onnxruntime_set_source_file_properties target_name) @@ -1255,7 +1221,7 @@ function(onnxruntime_configure_target target_name) if(WIN32 AND onnxruntime_ENABLE_STATIC_ANALYSIS AND onnxruntime_USE_CUSTOM_STATIC_ANALYSIS_RULES) set_target_properties(${target_name} PROPERTIES VS_USER_PROPS ${PROJECT_SOURCE_DIR}/EnableVisualStudioCodeAnalysis.props) endif() - target_include_directories(${target_name} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${abseil_cpp_SOURCE_DIR}) + target_include_directories(${target_name} PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT}) if (onnxruntime_ENABLE_TRAINING_OPS) target_include_directories(${target_name} PRIVATE ${ORTTRAINING_ROOT}) endif() @@ -1265,19 +1231,16 @@ function(onnxruntime_configure_target target_name) set_target_properties(${target_name} PROPERTIES INTERPROCEDURAL_OPTIMIZATION_MINSIZEREL TRUE) endif() - if (onnxruntime_BUILD_KERNEL_EXPLORER) - get_target_property(target_type ${target_name} TYPE) - if (target_type STREQUAL "MODULE_LIBRARY" OR target_type STREQUAL "SHARED_LIBRARY") - set_property(TARGET ${target_name} - APPEND_STRING PROPERTY LINK_FLAGS " -Xlinker --version-script=${ONNXRUNTIME_ROOT}/python/tools/kernel_explorer/version_script.lds ") - endif() - endif() - # Keep BinSkim happy if(MSVC AND NOT onnxruntime_target_platform MATCHES "ARM") - target_link_options(${target_name} PRIVATE "/CETCOMPAT") + target_link_options(${target_name} PRIVATE "$<$:/CETCOMPAT>") endif() + # Add compile features for minimum required language standard versions. + # Wrap in $ so the requirement is not exported to consumers of installed ORT targets. + target_compile_features(${target_name} PUBLIC + $ + $) endfunction() function(onnxruntime_add_shared_library target_name) @@ -1366,37 +1329,6 @@ if (onnxruntime_USE_ACL) endif() -# ArmNN -if (onnxruntime_USE_ARMNN) - if (NOT onnxruntime_ARMNN_RELU_USE_CPU) - add_definitions(-DRELU_ARMNN=1) - endif() - if (NOT onnxruntime_ARMNN_BN_USE_CPU) - add_definitions(-DBN_ARMNN=1) - endif() - - if (NOT onnxruntime_USE_ACL AND NOT ${onnxruntime_ACL_LIBS} STREQUAL "") - add_library(arm_compute SHARED IMPORTED) - set_target_properties(arm_compute PROPERTIES - IMPORTED_NO_SONAME 1 - IMPORTED_LOCATION "${onnxruntime_ACL_LIBS}/libarm_compute.so") - - add_library(arm_compute_graph SHARED IMPORTED) - set_target_properties(arm_compute_graph PROPERTIES - IMPORTED_NO_SONAME 1 - IMPORTED_LOCATION "${onnxruntime_ACL_LIBS}/libarm_compute_graph.so") - endif() - - if (NOT ${onnxruntime_ARMNN_LIBS} STREQUAL "") - add_library(armnn SHARED IMPORTED) - set_target_properties(armnn PROPERTIES - IMPORTED_NO_SONAME 1 - IMPORTED_LOCATION "${onnxruntime_ARMNN_LIBS}/libarmnn.so") - endif() - - list(APPEND onnxruntime_EXTERNAL_LIBRARIES armnn arm_compute arm_compute_graph) -endif() - if (onnxruntime_USE_DNNL) include(dnnl) add_compile_definitions(DNNL_OPENMP) @@ -1425,7 +1357,7 @@ if (onnxruntime_ENABLE_TRAINING_APIS) ) endif() -if (onnxruntime_USE_OPENVINO OR onnxruntime_USE_OPENVINO_INTERFACE) +if (onnxruntime_USE_OPENVINO) add_definitions(-DUSE_OPENVINO=1) @@ -1438,7 +1370,7 @@ if (onnxruntime_USE_OPENVINO OR onnxruntime_USE_OPENVINO_INTERFACE) add_definitions(-DOPENVINO_CONFIG_GPU=1) endif() - if (onnxruntime_USE_OPENVINO_CPU OR onnxruntime_USE_OPENVINO_INTERFACE) # OpenVino CPU interface is default built. + if (onnxruntime_USE_OPENVINO_CPU) add_definitions(-DOPENVINO_CONFIG_CPU=1) endif() @@ -1498,54 +1430,63 @@ if (Git_FOUND) OUTPUT_VARIABLE ORT_GIT_BRANCH) string(STRIP "${ORT_GIT_BRANCH}" ORT_GIT_BRANCH) string(APPEND ORT_BUILD_INFO "git-branch=${ORT_GIT_BRANCH}, git-commit-id=${ORT_GIT_COMMIT}, ") + if (onnxruntime_QUICK_BUILD) + string(APPEND ORT_BUILD_INFO "quick-build=1, ") + endif() + if (onnxruntime_USE_INT4_KV_CACHE) + string(APPEND ORT_BUILD_INFO "int4-kv-cache=1, ") + endif() + if (onnxruntime_USE_FP8_KV_CACHE) + string(APPEND ORT_BUILD_INFO "fp8-kv-cache=1, ") + endif() + if (onnxruntime_USE_CUDA AND onnxruntime_BUILD_CUDA_EP_AS_PLUGIN) + string(APPEND ORT_BUILD_INFO "cuda-plugin-ep=1, ") + endif() + if (onnxruntime_DUMP_TENSOR) + string(APPEND ORT_BUILD_INFO "dump-tensor=1, ") + endif() + if (onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS) + string(APPEND ORT_BUILD_INFO "dump-node=1, ") + endif() endif() string(APPEND ORT_BUILD_INFO "build type=${CMAKE_BUILD_TYPE}") -string(APPEND ORT_BUILD_INFO ", cmake cxx flags: ${CMAKE_CXX_FLAGS}") configure_file(onnxruntime_config.h.in ${CMAKE_CURRENT_BINARY_DIR}/onnxruntime_config.h) get_property(onnxruntime_GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) if (onnxruntime_USE_CUDA) - set(CMAKE_CUDA_RUNTIME_LIBRARY Shared) - set(CMAKE_CUDA_STANDARD 17) + set(CMAKE_CUDA_STANDARD ${CMAKE_CXX_STANDARD}) if(onnxruntime_CUDA_HOME) - file(TO_CMAKE_PATH CUDAToolkit_ROOT ${onnxruntime_CUDA_HOME}) + file(TO_CMAKE_PATH ${onnxruntime_CUDA_HOME} CUDAToolkit_ROOT) endif() find_package(CUDAToolkit REQUIRED) - if (NOT CMAKE_CUDA_ARCHITECTURES) - if (CMAKE_LIBRARY_ARCHITECTURE STREQUAL "aarch64-linux-gnu") - # Support for Jetson/Tegra ARM devices - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_53,code=sm_53") # TX1, Nano - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_62,code=sm_62") # TX2 - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_72,code=sm_72") # AGX Xavier, NX Xavier - if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_87,code=sm_87") # AGX Orin, NX Orin - endif() - else() - # the following compute capabilities are removed in CUDA 11 Toolkit - if (CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 11) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_30,code=sm_30") # K series - endif() - if (CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 12) - # 37, 50 still work in CUDA 11 but are marked deprecated and will be removed in future CUDA version. - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_37,code=sm_37") # K80 - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_50,code=sm_50") # M series - endif() - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_52,code=sm_52") # M60 - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_60,code=sm_60") # P series - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_70,code=sm_70") # V series - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_75,code=sm_75") # T series - if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_80,code=sm_80") # A series - endif() - if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -gencode=arch=compute_90,code=sm_90") # H series - endif() - endif() + + # Note: The minimum required CUDA version is greater than 11.8. + add_definitions("-DENABLE_BF16") + message(STATUS "CUDA Toolkit version is greater or equal than 11.8, enable -DENABLE_BF16 flag") + add_definitions("-DENABLE_FP8") + message(STATUS "CUDA Toolkit version is greater or equal than 11.8, enable -DENABLE_FP8 flag") + + if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.8) + add_definitions("-DENABLE_FP4") + message(STATUS "CUDA Toolkit version is greater or equal than 12.8, enable -DENABLE_FP4 flag") endif() + + if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL "13.0") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xfatbin=-compress-all -compress-mode=size") + else() + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -Xfatbin=-compress-all") + endif() + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --expt-relaxed-constexpr") - if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11) - set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --Werror default-stream-launch") + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} --Werror default-stream-launch") + + if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0) + if (UNIX) + # Suppress deprecation errors (e.g., long4 in CUDA 13) + add_compile_options(-Wno-deprecated-declarations) + endif() endif() + if (NOT WIN32) list(APPEND CUDA_NVCC_FLAGS --compiler-options -fPIC) endif() @@ -1593,10 +1534,6 @@ if (onnxruntime_ENABLE_CUDA_PROFILING) add_compile_definitions(ENABLE_CUDA_PROFILING) endif() -if (onnxruntime_ENABLE_ROCM_PROFILING) - add_compile_definitions(ENABLE_ROCM_PROFILING) -endif() - if (onnxruntime_ENABLE_TRAINING) add_compile_definitions(ENABLE_TRAINING_CORE) add_compile_definitions(ENABLE_STRIDED_TENSORS) @@ -1610,35 +1547,16 @@ if (onnxruntime_ENABLE_DLPACK) add_compile_definitions(ENABLE_DLPACK) endif() -if (UNIX OR onnxruntime_USE_NCCL) - # MPI is INDEPENDENT of NCCL for now. You can build NCLL without MPI and launch multi-GPU with your own launcher. - if (onnxruntime_USE_MPI) - if (EXISTS "${onnxruntime_MPI_HOME}") - set(MPI_HOME "${onnxruntime_MPI_HOME}") - elseif (EXISTS "/bert_ort/openmpi") - set(MPI_HOME "/bert_ort/openmpi") - endif() - find_package(MPI) - - if (MPI_CXX_FOUND) - message( STATUS "MPI Version: ${MPI_CXX_VERSION}") - message( STATUS "MPI (include: ${MPI_CXX_INCLUDE_DIRS}, library: ${MPI_CXX_LIBRARIES})" ) - mark_as_advanced(MPI_CXX_INCLUDE_DIRS MPI_CXX_LIBRARIES) - list(APPEND onnxruntime_EXTERNAL_LIBRARIES ${MPI_CXX_LIBRARIES} ${MPI_CXX_LINK_FLAGS}) - else () - message( - FATAL_ERROR - "MPI is not found. Please define onnxruntime_MPI_HOME to specify the path of MPI. Otherwise, NCCL will be disabled." - "or you can remove --use_mpi from build args to disable MPI." - ) - endif() - endif() +if (onnxruntime_CALLER_FRAMEWORK) + add_definitions(-DORT_CALLER_FRAMEWORK="${onnxruntime_CALLER_FRAMEWORK}") +endif() +if (UNIX OR onnxruntime_USE_NCCL) # Find NCCL if (onnxruntime_USE_NCCL) if (onnxruntime_USE_CUDA) set(NCCL_LIBNAME "nccl") - elseif (onnxruntime_USE_ROCM OR onnxruntime_USE_MIGRAPHX) + elseif (onnxruntime_USE_MIGRAPHX) set(NCCL_LIBNAME "rccl") endif() find_path(NCCL_INCLUDE_DIR @@ -1703,13 +1621,9 @@ if (UNIX OR onnxruntime_USE_NCCL) endif() else() set(onnxruntime_USE_NCCL OFF) - set(onnxruntime_USE_MPI OFF) - message( WARNING "MPI and NCCL are disabled because build is on Windows or USE_NCCL is set to OFF." ) + message( WARNING "NCCL is disabled because build is on Windows or USE_NCCL is set to OFF." ) endif() -if (onnxruntime_USE_MPI) - add_definitions(-DUSE_MPI=1) -endif() # Default version parts for Microsoft.AI.MachineLearning.dll, onnxruntime.dll, onnxruntime_providers_openvino.dll and onnxruntime_providers_shared.dll in non-ADO pipeline local builds set(VERSION_MAJOR_PART 0 CACHE STRING "First part of numeric file/product version.") @@ -1722,11 +1636,14 @@ if(VERSION_MAJOR_PART STREQUAL "0" AND VERSION_MINOR_PART STREQUAL "0" AND VERSI list(GET ORT_VERSION_STRING_LIST 0 VERSION_MAJOR_PART) list(GET ORT_VERSION_STRING_LIST 1 VERSION_MINOR_PART) list(GET ORT_VERSION_STRING_LIST 2 VERSION_BUILD_PART) - set(VERSION_STRING ORT_VERSION) + set(VERSION_STRING ${ORT_VERSION}) endif() if (WIN32) + if (onnxruntime_USE_MIMALLOC) + list(APPEND onnxruntime_EXTERNAL_LIBRARIES mimalloc-static) + endif() list(APPEND onnxruntime_EXTERNAL_LIBRARIES ${SYS_PATH_LIB}) list(APPEND onnxruntime_EXTERNAL_LIBRARIES debug Dbghelp) # In a onecore build the umbrella libs already contains references to the APIs in advapi32, so in onecore build we do not need to link to advapi32 @@ -1759,10 +1676,25 @@ if ("${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") endif() endif() - -#Now the 'onnxruntime_EXTERNAL_LIBRARIES' variable should be sealed. It will be used in onnxruntime.cmake which will be included in the next. -#The order of the following targets matters. Right depends on left. If target A appears before target B. Then A.cmake can not use variables defined in B.cmake. -set(ONNXRUNTIME_CMAKE_FILES onnxruntime_flatbuffers onnxruntime_common onnxruntime_mlas onnxruntime_graph onnxruntime_lora onnxruntime_framework onnxruntime_util onnxruntime_providers onnxruntime_optimizer onnxruntime_session ${ONNXRUNTIME_EAGER_CMAKE_FILE_NAME}) +# From this point on, onnxruntime_EXTERNAL_LIBRARIES should be no longer be modified. It will be used in +# onnxruntime.cmake which will be included next. + +# The order of the CMake file names (which exclude the ".cmake" suffix) in ONNXRUNTIME_CMAKE_FILES matters. Later CMake +# files may depend on earlier ones but earlier ones cannot depend on later ones. For example, if A appears before B, +# then A.cmake cannot use variables defined in B.cmake. +set(ONNXRUNTIME_CMAKE_FILES + onnxruntime_flatbuffers + onnxruntime_common + onnxruntime_mlas + onnxruntime_graph + onnxruntime_lora + onnxruntime_framework + onnxruntime_util + onnxruntime_providers + onnxruntime_optimizer + onnxruntime_session + ${ONNXRUNTIME_EAGER_CMAKE_FILE_NAME} + ) if (onnxruntime_USE_WINML) # WINML uses and depends on the shared lib. Note: You can build WINML without DML and you will get a @@ -1775,12 +1707,7 @@ if (onnxruntime_USE_WINML) list(APPEND ONNXRUNTIME_CMAKE_FILES winml) endif() # if (onnxruntime_USE_WINML) -if (onnxruntime_BUILD_SHARED_LIB OR onnxruntime_BUILD_APPLE_FRAMEWORK) - if (onnxruntime_BUILD_APPLE_FRAMEWORK AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS") - message(FATAL_ERROR "onnxruntime_BUILD_APPLE_FRAMEWORK can only be enabled for macOS or iOS or visionOS.") - endif() - list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime) -endif() +list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime) if (onnxruntime_BUILD_JAVA) message(STATUS "Java Build is enabled") @@ -1834,11 +1761,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") endif() endif() -if(onnxruntime_BUILD_KERNEL_EXPLORER) - message(STATUS "Kernel Explorer Build is enabled") - list(APPEND ONNXRUNTIME_CMAKE_FILES onnxruntime_kernel_explorer) -endif() - # When GDK_PLATFORM is set then WINAPI_FAMILY is defined in gdk_toolchain.cmake (along with other relevant flags/definitions). if (WIN32 AND NOT GDK_PLATFORM AND NOT CMAKE_CROSSCOMPILING) if (NOT CMAKE_CXX_STANDARD_LIBRARIES MATCHES kernel32.lib) @@ -1849,9 +1771,14 @@ if (WIN32 AND NOT GDK_PLATFORM AND NOT CMAKE_CROSSCOMPILING) endif() endif() -foreach(target_name ${ONNXRUNTIME_CMAKE_FILES}) - include(${target_name}.cmake) +foreach(onnxruntime_cmake_file ${ONNXRUNTIME_CMAKE_FILES}) + include(${onnxruntime_cmake_file}.cmake) endforeach() + +# CUDA EP Plugin build (independent shared library) +if (onnxruntime_USE_CUDA AND onnxruntime_BUILD_CUDA_EP_AS_PLUGIN) + include(onnxruntime_providers_cuda_plugin.cmake) +endif() if (UNIX) option(BUILD_PKGCONFIG_FILES "Build and install pkg-config files" ON) else() @@ -1873,6 +1800,10 @@ if (onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS) add_compile_definitions(DEBUG_NODE_INPUTS_OUTPUTS) endif() +if (onnxruntime_DUMP_TENSOR) + add_compile_definitions(DUMP_TENSOR_LEVEL=1) +endif() + if (onnxruntime_ENABLE_EXTERNAL_CUSTOM_OP_SCHEMAS) if (NOT CMAKE_SYSTEM_NAME STREQUAL "Linux") message(FATAL_ERROR "External custom operator schemas feature is only supported on Linux") @@ -1895,18 +1826,53 @@ if (onnxruntime_ENABLE_EXTERNAL_CUSTOM_OP_SCHEMAS) ) endif() -if(TARGET onnxruntime) -# Install - include(GNUInstallDirs) +if (NOT onnxruntime_BUILD_SHARED_LIB AND + (onnxruntime_USE_WEBGPU OR (CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND onnxruntime_USE_XNNPACK))) + message(WARNING + "CMake target files will not be generated for static onnxruntime builds " + "with WebGPU or Emscripten+XNNPACK support") +else() + # Install include(CMakePackageConfigHelpers) + set(PROJECT_CONFIG_CONTENT "@PACKAGE_INIT@\n") + + if (NOT onnxruntime_BUILD_SHARED_LIB) + string(APPEND PROJECT_CONFIG_CONTENT + "include(CMakeFindDependencyMacro)\n\ + find_dependency(absl)\n\ + find_dependency(date)\n\ + find_dependency(Eigen3)\n\ + find_dependency(nlohmann_json)\n\ + find_dependency(ONNX)\n\ + find_dependency(re2)\n\ + find_dependency(flatbuffers)\n\ + find_dependency(cpuinfo)\n\ + find_dependency(protobuf)\n\ + find_dependency(Boost COMPONENTS mp11)\n\ + find_dependency(Microsoft.GSL 4.0)\n\ + if(NOT WIN32 AND NOT CMAKE_SYSTEM_NAME STREQUAL \"Android\")\n\ + find_dependency(Iconv)\n\ + endif()\n\ + if(WIN32)\n\ + find_dependency(wil)\n\ + endif()\n\ + find_path(safeint_SOURCE_DIR NAMES \"SafeInt.hpp\" REQUIRED)\n\ + add_library(safeint_interface IMPORTED INTERFACE)\n\ + target_include_directories(safeint_interface INTERFACE ${safeint_SOURCE_DIR})\n\ + ") + endif() + string(APPEND PROJECT_CONFIG_CONTENT - "include(\"\${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}Targets.cmake\")") + "include(\"\${CMAKE_CURRENT_LIST_DIR}/${PROJECT_NAME}Targets.cmake\")\n") + + file(WRITE "${CMAKE_CURRENT_BINARY_DIR}/PROJECT_CONFIG_FILE" ${PROJECT_CONFIG_CONTENT}) install(EXPORT ${PROJECT_NAME}Targets NAMESPACE ${PROJECT_NAME}:: DESTINATION ${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}) -# Create config for find_package() + + # Create config for find_package() configure_package_config_file( "${CMAKE_CURRENT_BINARY_DIR}/PROJECT_CONFIG_FILE" ${PROJECT_NAME}Config.cmake INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") @@ -1921,9 +1887,25 @@ if(TARGET onnxruntime) "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}") + + if(DEFINED BUILD_AS_ARM64X) + set(ARM64X_TARGETS onnxruntime) + + # Add additional ARM64X build targets + if (onnxruntime_USE_QNN AND NOT onnxruntime_BUILD_QNN_EP_STATIC_LIB) + list(APPEND ARM64X_TARGETS onnxruntime_providers_shared) + list(APPEND ARM64X_TARGETS onnxruntime_providers_qnn) + endif() + + include("${CMAKE_CURRENT_SOURCE_DIR}/arm64x.cmake") + endif() +endif() + +if(onnxruntime_BUILD_UNIT_TESTS) + include("${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime_test_pch.cmake") endif() -if(DEFINED BUILD_AS_ARM64X) - set(ARM64X_TARGETS onnxruntime) - include("${CMAKE_CURRENT_SOURCE_DIR}/arm64x.cmake") +# Include precompiled header configuration for providers +if(TARGET onnxruntime_providers) + include("${CMAKE_CURRENT_SOURCE_DIR}/onnxruntime_providers_pch.cmake") endif() diff --git a/cmake/CMakePresets.json b/cmake/CMakePresets.json index 4987edaf85513..8d63912f6eaee 100644 --- a/cmake/CMakePresets.json +++ b/cmake/CMakePresets.json @@ -109,6 +109,29 @@ "rhs": "Darwin" } }, + { + "name": "arm64-osx", + "inherits": [ + "unit-test" + ], + "generator": "Xcode", + "binaryDir": "${sourceParentDir}/cmake_build/arm64-osx", + "installDir": "${sourceParentDir}/cmake_build/out", + "cacheVariables": { + "CMAKE_OSX_ARCHITECTURES": "arm64", + "onnxruntime_BUILD_SHARED_LIB": true, + "onnxruntime_USE_XNNPACK": false, + "onnxruntime_USE_COREML": true, + "onnxruntime_BUILD_OBJC": true, + "onnxruntime_BUILD_APPLE_FRAMEWORK": true, + "CMAKE_CONFIGURATION_TYPES": "Debug;Release" + }, + "condition": { + "type": "equals", + "lhs": "${hostSystemName}", + "rhs": "Darwin" + } + }, { "name": "x64-osx-vcpkg", "inherits": [ diff --git a/cmake/Info.plist.in b/cmake/Info.plist.in index f84bd250c8d66..de2c9938648d5 100644 --- a/cmake/Info.plist.in +++ b/cmake/Info.plist.in @@ -16,5 +16,6 @@ ???? CFBundlePackageType FMWK - + MinimumOSVersion + @CMAKE_OSX_DEPLOYMENT_TARGET@ diff --git a/cmake/adjust_global_compile_flags.cmake b/cmake/adjust_global_compile_flags.cmake index 8b5a744e497a6..8e45924db4d6d 100644 --- a/cmake/adjust_global_compile_flags.cmake +++ b/cmake/adjust_global_compile_flags.cmake @@ -1,15 +1,11 @@ -# work around Android NDK bug which doesn't include -O flag for Release configuration -# https://github.com/android/ndk/issues/1740 -# TODO: remove this when the NDK version(s) we support get fixed -if (ANDROID) - # NB: attempting to match the effects of this fix: https://android-review.googlesource.com/c/platform/ndk/+/2168845 - string(APPEND CMAKE_C_FLAGS_RELEASE " -O3") - string(APPEND CMAKE_CXX_FLAGS_RELEASE " -O3") - string(APPEND CMAKE_ASM_FLAGS_RELEASE " -O3") +# The flags set by this file are applied to 3rd-party libraries(e.g. protobuf) as well. If you want to set something that is only for ORT's code, please put it in the main CMakeLists.txt file. +if (ANDROID) # Build shared libraries with support for 16 KB ELF alignment # https://source.android.com/docs/core/architecture/16kb-page-size/16kb#build-lib-16kb-alignment set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384") + # Also apply to MODULE libraries (like libonnxruntime4j_jni.so) + set(CMAKE_MODULE_LINKER_FLAGS "${CMAKE_MODULE_LINKER_FLAGS} -Wl,-z,max-page-size=16384") endif() # Enable space optimization for gcc/clang @@ -41,21 +37,23 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") set(CMAKE_CXX_FLAGS_DEBUG "-g2") endif() - if (onnxruntime_ENABLE_WEBASSEMBLY_SIMD) + if (onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD) + string(APPEND CMAKE_C_FLAGS " -msimd128 -mrelaxed-simd") + string(APPEND CMAKE_CXX_FLAGS " -msimd128 -mrelaxed-simd") + elseif (onnxruntime_ENABLE_WEBASSEMBLY_SIMD) string(APPEND CMAKE_C_FLAGS " -msimd128") string(APPEND CMAKE_CXX_FLAGS " -msimd128") endif() - if (onnxruntime_ENABLE_WEBASSEMBLY_EXCEPTION_CATCHING) + # Enable WebAssembly exception catching. + if (onnxruntime_ENABLE_WEBASSEMBLY_JSPI) + string(APPEND CMAKE_C_FLAGS " -fwasm-exceptions -s WASM_LEGACY_EXCEPTIONS=0") + string(APPEND CMAKE_CXX_FLAGS " -fwasm-exceptions -s WASM_LEGACY_EXCEPTIONS=0") + elseif (onnxruntime_ENABLE_WEBASSEMBLY_EXCEPTION_CATCHING) string(APPEND CMAKE_C_FLAGS " -s DISABLE_EXCEPTION_CATCHING=0") string(APPEND CMAKE_CXX_FLAGS " -s DISABLE_EXCEPTION_CATCHING=0") endif() - if (onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64) - string(APPEND CMAKE_C_FLAGS " -DORT_WASM64") - string(APPEND CMAKE_CXX_FLAGS " -DORT_WASM64") - endif() - # Build WebAssembly with multi-threads support. if (onnxruntime_ENABLE_WEBASSEMBLY_THREADS) string(APPEND CMAKE_C_FLAGS " -pthread -Wno-pthreads-mem-growth") @@ -101,28 +99,36 @@ if (onnxruntime_MINIMAL_BUILD) endif() endif() -# Enable stream for all the non-minimal build -if (NOT onnxruntime_MINIMAL_BUILD) - add_compile_definitions(ORT_ENABLE_STREAM) +# ORT build with default settings more appropriate for client/on-device workloads. +if (onnxruntime_CLIENT_PACKAGE_BUILD) + add_compile_definitions(ORT_CLIENT_PACKAGE_BUILD) +endif() + +# Enable optional callbacks around per-session thread pool work execution. +if (onnxruntime_ENABLE_SESSION_THREADPOOL_CALLBACKS) + add_compile_definitions(ORT_ENABLE_SESSION_THREADPOOL_CALLBACKS) endif() if (onnxruntime_ENABLE_LTO) include(CheckIPOSupported) check_ipo_supported(RESULT ipo_enabled OUTPUT ipo_output) if (NOT ipo_enabled) - message(WARNING "IPO is not supported by this compiler") + message(WARNING "Interprocedural optimization (IPO) is not supported by this compiler. ${ipo_output}") set(onnxruntime_ENABLE_LTO OFF) else() set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ON) - endif() -endif() -if (onnxruntime_REDUCED_OPS_BUILD) - add_compile_definitions(REDUCED_OPS_BUILD) -endif() - -if (onnxruntime_DISABLE_EXTERNAL_INITIALIZERS) - add_definitions(-DDISABLE_EXTERNAL_INITIALIZERS=1) + # See https://cmake.org/cmake/help/latest/policy/CMP0069.html. + # + # "The OLD behavior for this policy is to add IPO flags only for Intel compiler on Linux. + # The NEW behavior for this policy is to add IPO flags for the current compiler or produce an error if CMake does + # not know the flags." + # + # CMake versions 3.8 and lower use the OLD behavior. This project requires CMake version > 3.8. + # However, some dependencies may specify a lower required CMake version and default to the OLD behavior. + # Ensure that CMake also uses the NEW behavior for such dependencies. + set(CMAKE_POLICY_DEFAULT_CMP0069 NEW) + endif() endif() if (onnxruntime_DISABLE_RTTI) @@ -160,6 +166,7 @@ if (onnxruntime_DISABLE_EXCEPTIONS) add_compile_definitions("ORT_NO_EXCEPTIONS") add_compile_definitions("MLAS_NO_EXCEPTION") add_compile_definitions("ONNX_NO_EXCEPTIONS") + # The following line of code probably is not needed because the same effect can be achieved by setting the compiler flag -fno-exceptions. add_compile_definitions("JSON_NOEXCEPTION") # https://json.nlohmann.me/api/macros/json_noexception/ if (MSVC) @@ -196,17 +203,9 @@ if (onnxruntime_CROSS_COMPILING) endif() endif() -if (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 9.0) - check_cxx_compiler_flag(-Wno-error HAS_NOERROR) - if (HAS_NOERROR) - string(APPEND CMAKE_CXX_FLAGS " -Wno-error=attributes") - string(APPEND CMAKE_C_FLAGS " -Wno-error=attributes") - endif() -endif() - -# Mark symbols to be invisible, for macOS/iOS/visionOS target only +# Mark symbols to be invisible, for macOS/iOS/visionOS/tvOS target only # Due to many dependencies have different symbol visibility settings, set global compile flags here. -if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS") +if (${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS|tvOS") foreach(flags CMAKE_CXX_FLAGS CMAKE_OBJC_FLAGS CMAKE_OBJCXX_FLAGS) string(APPEND ${flags} " -fvisibility=hidden -fvisibility-inlines-hidden") endforeach() @@ -214,10 +213,8 @@ endif() macro(check_nvcc_compiler_flag _FLAG _RESULT) - execute_process(COMMAND ${CUDAToolkit_BIN_DIR}/nvcc "${_FLAG}" RESULT_VARIABLE NVCC_OUT ERROR_VARIABLE NVCC_ERROR) - message("NVCC_ERROR = ${NVCC_ERROR}") - message("NVCC_OUT = ${NVCC_OUT}") - if ("${NVCC_OUT}" MATCHES "0") + execute_process(COMMAND ${CMAKE_CUDA_COMPILER} --compiler-options "${_FLAG}" -c ${REPO_ROOT}/cmake/empty.c -o ${CMAKE_CURRENT_BINARY_DIR}/empty.o RESULT_VARIABLE NVCC_OUT ERROR_QUIET OUTPUT_QUIET) + if (NVCC_OUT EQUAL 0) set(${_RESULT} 1) else() set(${_RESULT} 0) @@ -227,33 +224,22 @@ endmacro() #Set global compile flags for all the source code(including third_party code like protobuf) #This section must be before any add_subdirectory, otherwise build may fail because /MD,/MT mismatch if (MSVC) - if (CMAKE_VS_PLATFORM_NAME) - # Multi-platform generator - set(onnxruntime_target_platform ${CMAKE_VS_PLATFORM_NAME}) - else() - set(onnxruntime_target_platform ${CMAKE_SYSTEM_PROCESSOR}) - endif() - if (onnxruntime_target_platform STREQUAL "ARM64") - set(onnxruntime_target_platform "ARM64") - enable_language(ASM_MARMASM) - elseif (onnxruntime_target_platform STREQUAL "ARM64EC") - enable_language(ASM_MARMASM) - elseif (onnxruntime_target_platform STREQUAL "ARM" OR CMAKE_GENERATOR MATCHES "ARM") - set(onnxruntime_target_platform "ARM") + if (onnxruntime_target_platform STREQUAL "ARM64" OR + onnxruntime_target_platform STREQUAL "ARM64EC" OR + onnxruntime_target_platform STREQUAL "ARM") enable_language(ASM_MARMASM) - elseif (onnxruntime_target_platform STREQUAL "x64" OR onnxruntime_target_platform STREQUAL "x86_64" OR onnxruntime_target_platform STREQUAL "AMD64" OR CMAKE_GENERATOR MATCHES "Win64") - set(onnxruntime_target_platform "x64") + elseif (onnxruntime_target_platform STREQUAL "x64" OR + onnxruntime_target_platform STREQUAL "x86") enable_language(ASM_MASM) - elseif (onnxruntime_target_platform STREQUAL "Win32" OR onnxruntime_target_platform STREQUAL "x86" OR onnxruntime_target_platform STREQUAL "i386" OR onnxruntime_target_platform STREQUAL "i686") - set(onnxruntime_target_platform "x86") - enable_language(ASM_MASM) - message("Enabling SAFESEH for x86 build") - set(CMAKE_ASM_MASM_FLAGS "${CMAKE_ASM_MASM_FLAGS} /safeseh") + + if (onnxruntime_target_platform STREQUAL "x86") + message("Enabling SAFESEH for x86 build") + set(CMAKE_ASM_MASM_FLAGS "${CMAKE_ASM_MASM_FLAGS} /safeseh") + endif() else() - message(FATAL_ERROR "Unknown CMAKE_SYSTEM_PROCESSOR: ${CMAKE_SYSTEM_PROCESSOR}") + message(FATAL_ERROR "Unsupported onnxruntime_target_platform value: ${onnxruntime_target_platform}") endif() - #Always enable exception handling, even for Windows ARM if (NOT onnxruntime_DISABLE_EXCEPTIONS) string(APPEND CMAKE_CXX_FLAGS " /EHsc") @@ -280,34 +266,6 @@ if (MSVC) set(CMAKE_CXX_FLAGS_MINSIZEREL "${CMAKE_CXX_FLAGS_MINSIZEREL} /Gw /GL") endif() else() - if (NOT APPLE) - #XXX: Sometimes the value of CMAKE_SYSTEM_PROCESSOR is set but it's wrong. For example, if you run an armv7 docker - #image on an aarch64 machine with an aarch64 Ubuntu host OS, in the docker instance cmake may still report - # CMAKE_SYSTEM_PROCESSOR as aarch64 by default. Given compiling this code may need more than 2GB memory, we do not - # support compiling for ARM32 natively(only support cross-compiling), we will ignore this issue for now. - if(NOT CMAKE_SYSTEM_PROCESSOR) - message(WARNING "CMAKE_SYSTEM_PROCESSOR is not set. Please set it in your toolchain cmake file.") - # Try to detect it - if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") - execute_process( - COMMAND "${CMAKE_C_COMPILER}" -dumpmachine - OUTPUT_VARIABLE GCC_DUMP_MACHINE_OUT OUTPUT_STRIP_TRAILING_WHITESPACE - ERROR_VARIABLE _err - RESULT_VARIABLE _res - ) - if(NOT _res EQUAL 0) - message(SEND_ERROR "Failed to run 'gcc -dumpmachine':\n ${_res}") - endif() - string(REPLACE "-" ";" GCC_DUMP_MACHINE_OUT_LIST "${GCC_DUMP_MACHINE_OUT}") - list(LENGTH GCC_DUMP_MACHINE_OUT_LIST GCC_TRIPLET_LEN) - if(GCC_TRIPLET_LEN EQUAL 4) - list(GET GCC_DUMP_MACHINE_OUT_LIST 0 CMAKE_SYSTEM_PROCESSOR) - message("Setting CMAKE_SYSTEM_PROCESSOR to ${CMAKE_SYSTEM_PROCESSOR}") - endif() - endif() - endif() - set(onnxruntime_target_platform ${CMAKE_SYSTEM_PROCESSOR}) - endif() if (onnxruntime_BUILD_FOR_NATIVE_MACHINE) string(APPEND CMAKE_CXX_FLAGS " -march=native -mtune=native") string(APPEND CMAKE_C_FLAGS " -march=native -mtune=native") @@ -326,9 +284,6 @@ else() string(APPEND CMAKE_C_FLAGS " -g -O0 --coverage ") endif() if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU") - # suppress warnings from flatbuffers - string(APPEND CMAKE_CXX_FLAGS " -Wno-restrict ") - string(APPEND CMAKE_C_FLAGS " -Wno-restrict ") if(onnxruntime_USE_XNNPACK) # https://github.com/google/XNNPACK/issues/7650 string(APPEND CMAKE_C_FLAGS " -Wno-incompatible-pointer-types ") @@ -372,4 +327,4 @@ endif() if (onnxruntime_USE_EXTENSIONS) include_directories(${REPO_ROOT}/include/onnxruntime/core/session) -endif() \ No newline at end of file +endif() diff --git a/cmake/deps.txt b/cmake/deps.txt index c73d9a4e3532f..fa37238bbb82e 100644 --- a/cmake/deps.txt +++ b/cmake/deps.txt @@ -9,35 +9,34 @@ #since the file contains a version string: "lts_20230802". However, the file is for debugging purposes only and would #not affect built binaries. # -# NOTE: You must run deps_update_and_upload.py and generate_cgmanifest.py when ready to test your changes in a CI. -# See https://microsoft.sharepoint.com/teams/ONNX2/_layouts/OneNote.aspx?id=%2Fteams%2FONNX2%2FShared%20Documents%2FNotebooks%2FONNX%20Ecosystem%20Team%20Notebook&wd=target%28Development.one%7C63D3AB47-51D1-4A62-9965-66882234BD44%2FAdd%20or%20update%20a%20dependency%20in%20deps.txt%7C0E9ED71D-89D5-40FA-B05F-C0123289C591%2F%29 -# -abseil_cpp;https://github.com/abseil/abseil-cpp/archive/refs/tags/20240722.0.zip;36ee53eb1466fb6e593fc5c286680de31f8a494a +abseil_cpp;https://github.com/abseil/abseil-cpp/archive/refs/tags/20250814.0.zip;a9eb1d648cbca4d4d788737e971a6a7a63726b07 coremltools;https://github.com/apple/coremltools/archive/refs/tags/7.1.zip;f1bab0f30966f2e217d8e01207d518f230a1641a cxxopts;https://github.com/jarro2783/cxxopts/archive/3c73d91c0b04e2b59462f0a741be8c07024c1bc0.zip;6c6ca7f8480b26c8d00476e0e24b7184717fe4f0 date;https://github.com/HowardHinnant/date/archive/refs/tags/v3.0.1.zip;2dac0c81dc54ebdd8f8d073a75c053b04b56e159 -dlpack;https://github.com/dmlc/dlpack/archive/refs/tags/v0.6.zip;4d565dd2e5b31321e5549591d78aa7f377173445 +dlpack;https://github.com/dmlc/dlpack/archive/5c210da409e7f1e51ddf445134a4376fdbd70d7d.zip;e499c86e4e5c5268a87661d7ea39c27fae10907c # This Eigen commit id matches the eigen archive being consumed from https://gitlab.com/libeigen/eigen/-/archive/3.4/eigen-3.4.zip # prior to the 3.4.1 RC changing the bits and invalidating the hash. # it contains changes on top of 3.4.0 which are required to fix build issues. # Until the 3.4.1 release this is the best option we have. # Issue link: https://gitlab.com/libeigen/eigen/-/issues/2744 -eigen;https://gitlab.com/libeigen/eigen/-/archive/e7248b26a1ed53fa030c5c459f7ea095dfd276ac/eigen-e7248b26a1ed53fa030c5c459f7ea095dfd276ac.zip;be8be39fdbc6e60e94fa7870b280707069b5b81a +# Moved to github mirror to avoid gitlab issues. +# Issue link: https://github.com/bazelbuild/bazel-central-registry/issues/4355 +eigen;https://github.com/eigen-mirror/eigen/archive/1d8b82b0740839c0de7f1242a3585e3390ff5f33/eigen-1d8b82b0740839c0de7f1242a3585e3390ff5f33.zip;05b19b49e6fbb91246be711d801160528c135e34 flatbuffers;https://github.com/google/flatbuffers/archive/refs/tags/v23.5.26.zip;59422c3b5e573dd192fead2834d25951f1c1670c fp16;https://github.com/Maratyszcza/FP16/archive/0a92994d729ff76a58f692d3028ca1b64b145d91.zip;b985f6985a05a1c03ff1bb71190f66d8f98a1494 fxdiv;https://github.com/Maratyszcza/FXdiv/archive/63058eff77e11aa15bf531df5dd34395ec3017c8.zip;a5658f4036402dbca7cebee32be57fb8149811e1 google_benchmark;https://github.com/google/benchmark/archive/refs/tags/v1.8.5.zip;cd47d3d272faf353600c8cc2fdec2b52d6f69177 -googletest;https://github.com/google/googletest/archive/refs/tags/v1.15.0.zip;9d2d0af8d77ac726ea55d44a8fa727ec98311349 -#xnnpack 2024.09.04 -googlexnnpack;https://github.com/google/XNNPACK/archive/fe98e0b93565382648129271381c14d6205255e3.zip;14f61dcf17cec2cde34ba2dcf61d6f24bf6059f3 -json;https://github.com/nlohmann/json/archive/refs/tags/v3.10.5.zip;f257f8dc27c5b8c085dc887b40cddd18ae1f725c +googletest;https://github.com/google/googletest/archive/refs/tags/v1.17.0.zip;f638fa0e724760e2ba07ff8cfba32cd644e1ce28 +#xnnpack 2025.06.22 +googlexnnpack;https://github.com/google/XNNPACK/archive/3cf85e705098622d59056dcb8f5f963ea7bb0a00.zip;6f6bbba627241f89463ca845febaf063982b34fe +json;https://github.com/nlohmann/json/archive/refs/tags/v3.11.3.zip;5e88795165cc8590138d1f47ce94ee567b85b4d6 microsoft_gsl;https://github.com/microsoft/GSL/archive/refs/tags/v4.0.0.zip;cf368104cd22a87b4dd0c80228919bb2df3e2a14 -microsoft_wil;https://github.com/microsoft/wil/archive/refs/tags/v1.0.230629.1.zip;e4a542a323c070376f7c2d1973d0f7ddbc1d2fa5 +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.17.0.zip;13a60ac5217c104139ce0fd024f48628e7bcf5bc -# Use the latest commit of 10.7-GA -onnx_tensorrt;https://github.com/onnx/onnx-tensorrt/archive/9c69a24bc2e20c8a511a4e6b06fd49639ec5300a.zip;ff1fe9af78eb129b4a4cdcb7450b7390b4436dd3 +onnx;https://github.com/onnx/onnx/archive/refs/tags/v1.21.0.zip;321d4acc807c8e0fb0bbcc0424a143dffde1e846 +# 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 protoc_win64;https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-win64.zip;b4521f7ada5b260380f94c4bd7f1b7684c76969a protoc_win32;https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-win32.zip;3688010318192c46ce73213cdfb6b3e5656da874 @@ -46,17 +45,20 @@ protoc_linux_x86;https://github.com/protocolbuffers/protobuf/releases/download/v protoc_linux_aarch64;https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-linux-aarch_64.zip;df9d45470b0b8cf939dd2f0ec6b88e9cafc4d617 protoc_mac_universal;https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-osx-universal_binary.zip;23710c3d1c2036d8d65a6a22234372fa2d7af9ef psimd;https://github.com/Maratyszcza/psimd/archive/072586a71b55b7f8c584153d223e95687148a900.zip;1f5454b01f06f9656b77e4a5e2e31d7422487013 -pthreadpool;https://github.com/google/pthreadpool/archive/4e80ca24521aa0fb3a746f9ea9c3eaa20e9afbb0.zip;bd4ea65c8292801e9555b527a0ecbb2e0092c917 -pybind11;https://github.com/pybind/pybind11/archive/refs/tags/v2.13.1.zip;9255d5c8568debcc329dd42ed8f410ee139ac7b1 -pytorch_cpuinfo;https://github.com/pytorch/cpuinfo/archive/8a1772a0c5c447df2d18edf33ec4603a8c9c04a6.zip;85bf8a60dae026b99b6ccd78606c85ed83bfb2cd +pthreadpool;https://github.com/google/pthreadpool/archive/dcc9f28589066af0dbd4555579281230abbf74dd.zip;533a77943203ef15ca608bcd9dbe2c94da7451d2 +pybind11;https://github.com/pybind/pybind11/archive/refs/tags/v3.0.2.zip;a064e663b4d7a337ac291d1bef7337ef4e60a1ae +pytorch_cpuinfo;https://github.com/pytorch/cpuinfo/archive/403d652dca4c1046e8145950b1c0997a9f748b57.zip;30b2a07fe4bae8574f89176e56274cacdd6d135b re2;https://github.com/google/re2/archive/refs/tags/2024-07-02.zip;646e1728269cde7fcef990bf4a8e87b047882e88 safeint;https://github.com/dcleblanc/SafeInt/archive/refs/tags/3.0.28.zip;23f252040ff6cb9f1fd18575b32fa8fb5928daac tensorboard;https://github.com/tensorflow/tensorboard/archive/373eb09e4c5d2b3cc2493f0949dc4be6b6a45e81.zip;67b833913605a4f3f499894ab11528a702c2b381 -cutlass;https://github.com/NVIDIA/cutlass/archive/refs/tags/v3.5.1.zip;e49b2b964163d27765a5002d210a2f3c73771835 -utf8_range;https://github.com/protocolbuffers/utf8_range/archive/72c943dea2b9240cd09efde15191e144bc7c7d38.zip;9925739c9debc0efa2adcb194d371a35b6a03156 -extensions;https://github.com/microsoft/onnxruntime-extensions/archive/f3f6caa6e8adb420e005ec41c6fefc8d75affb6e.zip;cec2e164f1a00e7d80fd94df65e4e8d2daead70d -composable_kernel;https://github.com/ROCmSoftwarePlatform/composable_kernel/archive/204da9c522cebec5220bba52cd3542ebcaf99e7a.zip;1827348efd47831c13074245274d41b7cae8a557 +cutlass;https://github.com/NVIDIA/cutlass/archive/refs/tags/v4.4.2.zip;4b0bae4428b84370407c0a71778b13dc2eee5be1 +extensions;https://github.com/microsoft/onnxruntime-extensions/archive/c24b7bab0c12f53da76d0c31b03b9f0f8ec8f3b4.zip;239063aee4946a9af147b473a4c3da78ba7413b4 directx_headers;https://github.com/microsoft/DirectX-Headers/archive/refs/tags/v1.613.1.zip;47653509a3371eabb156360f42faf582f314bf2e -cudnn_frontend;https://github.com/NVIDIA/cudnn-frontend/archive/refs/tags/v1.7.0.zip;d0753d8d5b39947ca0729d7773cb84653a129eb1 -dawn;https://github.com/google/dawn/archive/b9b4a37041dec3dd62ac92014a6cc1aece48d9f3.zip;e8b8c2ebabdedb7c57d931fc4a19ae22146d31e1 -kleidiai;https://gitlab.arm.com/kleidi/kleidiai/-/archive/d15722976120710080ca098fe8ddabf4556cb40f/kleidiai-d15722976120710080ca098fe8ddabf4556cb40f.zip;d6c840d00c3b05aedf06e957ddaece1013d1f40b +cudnn_frontend;https://github.com/NVIDIA/cudnn-frontend/archive/refs/tags/v1.12.0.zip;7e733cfdc410d777b76122d64232499205589a96 +dawn;https://github.com/google/dawn/archive/ec7b457e5bb1fcec6f59733c4f3dd84d2f885a38.zip;d4d64d1729104b61e654073566f1a376e16cad92 +kleidiai;https://github.com/ARM-software/kleidiai/archive/refs/tags/v1.20.0.tar.gz;6895e72b3d5cf1173358164cb3d64c9d7d33cc84 +# kleidiai-qmx is pinned to a specific commit as there are no tagged releases. When an appropriate tagged release becomes available, +# this entry will be updated to use refs/tags/ instead of the raw commit hash. +kleidiai-qmx;https://github.com/qualcomm/kleidiai/archive/2f10c9a8d32f81ffeeb6d4885a29cc35d2b0da87.zip;5e855730a2d69057a569f43dd7532db3b2d2a05c +duktape;https://github.com/svaarala/duktape/releases/download/v2.7.0/duktape-2.7.0.tar.xz;8200c8e417dbab7adcc12c4dbdef7651cfc55794 +vulkan_headers;https://codeload.github.com/KhronosGroup/Vulkan-Headers/tar.gz/refs/tags/v1.4.344;57bc528ef7c4a3f7bfbb59e64a187e3734bd29d8 diff --git a/cmake/deps_update_and_upload.py b/cmake/deps_update_and_upload.py deleted file mode 100644 index 63df3f6f03869..0000000000000 --- a/cmake/deps_update_and_upload.py +++ /dev/null @@ -1,109 +0,0 @@ -# If deps.txt is updated, run this file to update and upload the dependencies so that CI can use them. -# -# Before running the script, find the latest version number at: -# https://aiinfra.visualstudio.com/Lotus/_artifacts/feed/Lotus/UPack/onnxruntime_build_dependencies/versions -# Increment it to obtain a new version number to use. -# -# Run without --do-upload once to verify downloading. Use --do-upload when you are ready to publish. -# E.g.: -# python cmake/deps_update_and_upload.py --root-path C:/temp/onnxruntime_deps --version 1.0.82 -# # check contents of C:/temp/onnxruntime_deps -# python cmake/deps_update_and_upload.py --root-path C:/temp/onnxruntime_deps --version 1.0.82 --no-download --do-upload -# -# Next, update the version number in tools/ci_build/github/azure-pipelines/templates/download-deps.yml. - -import argparse -import contextlib -import pathlib -import re -import subprocess -import tempfile - -script_dir = pathlib.Path(__file__).parent - -parser = argparse.ArgumentParser(description="Update dependencies and publish to Azure Artifacts") -parser.add_argument( - "--root-path", - type=pathlib.Path, - help="Target root path for downloaded files. If not provided, a temporary directory is used.", -) -parser.add_argument( - "--version", - type=str, - help="Package version to publish", -) -parser.add_argument( - "--do-upload", - action="store_true", - dest="upload", - help="Upload the package to Azure Artifacts", -) -parser.add_argument( - "--no-download", - action="store_false", - dest="download", - help="Skip downloading the dependency files. " - "Use with '--do-upload' and '--root-path' to upload the package from existing dependency files.", -) -args = parser.parse_args() - -if args.upload: - assert args.version is not None, "'--version' must be specified if uploading." - -if args.upload != args.download: - assert args.root_path is not None, "'--root-path' must be specified if only downloading or uploading." - -deps_path = script_dir / "deps.txt" -with open(deps_path) as file: - text = file.read() - -lines = [line for line in text.split("\n") if not line.startswith("#") and ";" in line] - -with contextlib.ExitStack() as context_stack: - if args.root_path is not None: - root_path = args.root_path.resolve() - root_path.mkdir(parents=True, exist_ok=True) - else: - temp_dir_name = context_stack.enter_context(tempfile.TemporaryDirectory()) - root_path = pathlib.Path(temp_dir_name) - - if args.download: - print(f"Downloading dependencies to directory: {root_path}") - - dep_pattern = re.compile(r"^[^;]+;https://([^;]+);.*$") - - for line in lines: - match = dep_pattern.fullmatch(line) - if match is None: - continue - - dep_path = match[1] - url = f"https://{dep_path}" - full_path = root_path / dep_path - - subprocess.run(["curl", "-sSL", "--create-dirs", "-o", str(full_path), url], check=True) - - package_name = "onnxruntime_build_dependencies" - version = args.version if args.version is not None else "VERSION_PLACEHOLDER" - - if args.upload: - # Check if the user is logged in to Azure - result = subprocess.run("az account show", shell=True, capture_output=True, text=True, check=False) - if "No subscriptions found" in result.stderr: - # Prompt the user to log in to Azure - print("You are not logged in to Azure. Please log in to continue.") - subprocess.run("az login", shell=True, check=True) - - # Publish the package to Azure Artifacts if --do-upload is specified - - cmd = f'az artifacts universal publish --organization https://dev.azure.com/onnxruntime --feed onnxruntime --name {package_name} --version {version} --description "onnxruntime build time dependencies" --path {root_path}' - if args.upload: - subprocess.run(cmd, shell=True, check=True) - else: - print("would have run: " + cmd) - - cmd = f'az artifacts universal publish --organization https://dev.azure.com/aiinfra --feed Lotus --name {package_name} --version {version} --description "onnxruntime build time dependencies" --path {root_path}' - if args.upload: - subprocess.run(cmd, shell=True, check=True) - else: - print("would have run: " + cmd) diff --git a/cmake/detect_onnxruntime_target_platform.cmake b/cmake/detect_onnxruntime_target_platform.cmake new file mode 100644 index 0000000000000..2f5f6ee9ca80c --- /dev/null +++ b/cmake/detect_onnxruntime_target_platform.cmake @@ -0,0 +1,80 @@ +# This file will set the onnxruntime_target_platform variable, if applicable. +# onnxruntime_target_platform identifies the platform to compile for. +block(PROPAGATE onnxruntime_target_platform) + +unset(onnxruntime_target_platform) + +if (MSVC) + if (CMAKE_VS_PLATFORM_NAME) + # Multi-platform generator + set(onnxruntime_target_platform ${CMAKE_VS_PLATFORM_NAME}) + else() + set(onnxruntime_target_platform ${CMAKE_SYSTEM_PROCESSOR}) + endif() + + if (onnxruntime_target_platform STREQUAL "ARM64" OR + onnxruntime_target_platform STREQUAL "ARM64EC") + # Do nothing. We'll just use the current value of onnxruntime_target_platform. + elseif (onnxruntime_target_platform STREQUAL "ARM" OR + CMAKE_GENERATOR MATCHES "ARM") + set(onnxruntime_target_platform "ARM") + elseif (onnxruntime_target_platform STREQUAL "x64" OR + onnxruntime_target_platform STREQUAL "x86_64" OR + onnxruntime_target_platform STREQUAL "AMD64" OR + CMAKE_GENERATOR MATCHES "Win64") + set(onnxruntime_target_platform "x64") + elseif (onnxruntime_target_platform STREQUAL "Win32" OR + onnxruntime_target_platform STREQUAL "x86" OR + onnxruntime_target_platform STREQUAL "i386" OR + onnxruntime_target_platform STREQUAL "i686") + set(onnxruntime_target_platform "x86") + else() + message(FATAL_ERROR "Unknown target platform: ${onnxruntime_target_platform}") + endif() +elseif(APPLE) + if(DEFINED CMAKE_OSX_ARCHITECTURES) + # We'll only set onnxruntime_target_platform when CMAKE_OSX_ARCHITECTURES specifies a single architecture. + list(LENGTH CMAKE_OSX_ARCHITECTURES CMAKE_OSX_ARCHITECTURES_LEN) + if(CMAKE_OSX_ARCHITECTURES_LEN EQUAL 1) + set(onnxruntime_target_platform ${CMAKE_OSX_ARCHITECTURES}) + endif() + else() + set(onnxruntime_target_platform ${CMAKE_SYSTEM_PROCESSOR}) + endif() +else() + #XXX: Sometimes the value of CMAKE_SYSTEM_PROCESSOR is set but it's wrong. For example, if you run an armv7 docker + #image on an aarch64 machine with an aarch64 Ubuntu host OS, in the docker instance cmake may still report + # CMAKE_SYSTEM_PROCESSOR as aarch64 by default. Given compiling this code may need more than 2GB memory, we do not + # support compiling for ARM32 natively(only support cross-compiling), we will ignore this issue for now. + if(NOT CMAKE_SYSTEM_PROCESSOR) + message(WARNING "CMAKE_SYSTEM_PROCESSOR is not set. Please set it in your toolchain cmake file.") + # Try to detect it + if("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang") + execute_process( + COMMAND "${CMAKE_C_COMPILER}" -dumpmachine + OUTPUT_VARIABLE GCC_DUMP_MACHINE_OUT + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_VARIABLE _err + RESULT_VARIABLE _res + ) + if(NOT _res EQUAL 0) + message(SEND_ERROR "Failed to run 'gcc -dumpmachine':\n ${_res}") + endif() + string(REPLACE "-" ";" GCC_DUMP_MACHINE_OUT_LIST "${GCC_DUMP_MACHINE_OUT}") + list(LENGTH GCC_DUMP_MACHINE_OUT_LIST GCC_TRIPLET_LEN) + if(GCC_TRIPLET_LEN EQUAL 4) + list(GET GCC_DUMP_MACHINE_OUT_LIST 0 CMAKE_SYSTEM_PROCESSOR) + message("Setting CMAKE_SYSTEM_PROCESSOR to ${CMAKE_SYSTEM_PROCESSOR}") + endif() + endif() + endif() + set(onnxruntime_target_platform ${CMAKE_SYSTEM_PROCESSOR}) +endif() + +if(DEFINED onnxruntime_target_platform) + message(STATUS "onnxruntime_target_platform = ${onnxruntime_target_platform}") +else() + message(WARNING "onnxruntime_target_platform is not set") +endif() + +endblock() diff --git a/cmake/empty.c b/cmake/empty.c new file mode 100644 index 0000000000000..af2cf319bdf79 --- /dev/null +++ b/cmake/empty.c @@ -0,0 +1,2 @@ +// This file is used by the check_nvcc_compiler_flag macro in adjust_global_compile_flags.cmake to test nvcc compiler flags. +void empty() {} diff --git a/cmake/external/abseil-cpp.cmake b/cmake/external/abseil-cpp.cmake index 6b4404a124926..a8e925cab51bf 100644 --- a/cmake/external/abseil-cpp.cmake +++ b/cmake/external/abseil-cpp.cmake @@ -9,34 +9,41 @@ set(BUILD_TESTING 0) set(ABSL_BUILD_TESTING OFF) set(ABSL_BUILD_TEST_HELPERS OFF) set(ABSL_USE_EXTERNAL_GOOGLETEST ON) -if(Patch_FOUND AND WIN32) - set(ABSL_PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/abseil/absl_windows.patch) + +# Both abseil and xnnpack create a target called memory, which +# results in a duplicate target if ABSL_ENABLE_INSTALL is on. +if (NOT CMAKE_SYSTEM_NAME MATCHES "AIX") + set(ABSL_ENABLE_INSTALL ON) +endif() + +if(Patch_FOUND) + if (WIN32) + set(ABSL_PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/abseil/absl_windows.patch && + ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/abseil/absl_cuda_warnings.patch) + else() + set(ABSL_PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/abseil/absl_cuda_warnings.patch) + endif() else() set(ABSL_PATCH_COMMAND "") endif() -if(WIN32 AND NOT Patch_FOUND) - #see https://github.com/google/re2/issues/425 and https://github.com/google/re2/issues/436 - set(ABSL_ENABLE_INSTALL ON) -endif() + # NB! Advancing Abseil version changes its internal namespace, -# currently absl::lts_20240116 which affects abseil-cpp.natvis debugger +# currently absl::lts_20250512 which affects abseil-cpp.natvis debugger # visualization file, that must be adjusted accordingly, unless we eliminate # that namespace at build time. -FetchContent_Declare( +onnxruntime_fetchcontent_declare( abseil_cpp URL ${DEP_URL_abseil_cpp} URL_HASH SHA1=${DEP_SHA1_abseil_cpp} + EXCLUDE_FROM_ALL PATCH_COMMAND ${ABSL_PATCH_COMMAND} - FIND_PACKAGE_ARGS 20240722 NAMES absl + FIND_PACKAGE_ARGS 20250814 NAMES absl ) onnxruntime_fetchcontent_makeavailable(abseil_cpp) FetchContent_GetProperties(abseil_cpp) if(abseil_cpp_SOURCE_DIR) set(ABSEIL_SOURCE_DIR ${abseil_cpp_SOURCE_DIR}) - if(onnxruntime_USE_WEBGPU) - set(DAWN_ABSEIL_DIR ${abseil_cpp_SOURCE_DIR}) - endif() endif() # abseil_cpp_SOURCE_DIR is non-empty if we build it from source @@ -55,97 +62,87 @@ endif() # TODO: since multiple ORT's dependencies depend on Abseil, the list below would vary from version to version. # We'd better to not manually manage the list. +# This list is generated using tools/python/resolve_absl_deps_dynamic.py for Abseil version 20250814.0 +# The libraries are topologically sorted for correct static linking order. set(ABSEIL_LIBS -absl::absl_log -absl::log_internal_log_impl -absl::log_internal_strip -absl::log_internal_message -absl::log_internal_format absl::synchronization -absl::str_format -absl::flags -absl::log_internal_globals -absl::kernel_timeout_internal -absl::str_format_internal -absl::hash -absl::log_internal_append_truncated -absl::absl_vlog_is_on -absl::flags_commandlineflag +absl::tracing_internal absl::time +absl::time_zone +absl::civil_time absl::symbolize -absl::graphcycles_internal -absl::log_internal_conditions -absl::strings -absl::malloc_internal absl::demangle_internal -absl::optional -absl::stacktrace -absl::base absl::demangle_rust -absl::bad_optional_access -absl::strings_internal +absl::stacktrace absl::debugging_internal -absl::int128 -absl::spinlock_wait -absl::decode_rust_punycode -absl::raw_logging_internal +absl::malloc_internal +absl::kernel_timeout_internal +absl::graphcycles_internal +absl::str_format +absl::str_format_internal absl::flat_hash_set absl::flat_hash_map -absl::node_hash_map -absl::node_hash_set -absl::compare -absl::base_internal -absl::nullability -absl::bounded_utf8_length_sequence -absl::log_severity -absl::type_traits -absl::atomic_hook -absl::bits -absl::flags_commandlineflag_internal +absl::algorithm_container +absl::raw_hash_map +absl::raw_hash_set +absl::prefetch +absl::hashtablez_sampler +absl::hashtable_debug_hooks +absl::hashtable_control_bytes +absl::hash_policy_traits +absl::common_policy_traits absl::hash_container_defaults -absl::numeric_representation -absl::node_slot_policy -absl::core_headers -absl::dynamic_annotations -absl::utf8_for_code_point -absl::errno_saver -absl::absl_check absl::hash_function_defaults +absl::cord +absl::inlined_vector +absl::inlined_vector_internal +absl::span +absl::crc_cord_state +absl::crc32c +absl::cordz_update_tracker +absl::cordz_update_scope +absl::cordz_info +absl::cordz_functions +absl::cord_internal +absl::container_common +absl::container_memory +absl::hash +absl::variant +absl::optional +absl::strings +absl::charset +absl::strings_internal +absl::string_view +absl::int128 +absl::compare absl::function_ref +absl::any_invocable absl::city -absl::low_level_hash +absl::bits +absl::endian +absl::flags absl::fixed_array -absl::variant +absl::weakly_mixed_integer +absl::memory absl::meta -absl::log_internal_voidify -absl::log_sink -absl::log_internal_log_sink_set -absl::log_sink_registry -absl::log_entry -absl::log_globals -absl::log_internal_nullguard -absl::examine_stack -absl::inlined_vector -absl::log_internal_proto -absl::strerror -absl::log_internal_config -absl::raw_hash_map -absl::raw_hash_set -absl::container_memory -absl::algorithm_container -absl::span -absl::log_internal_nullstream -absl::vlog_config_internal -absl::flags_reflection -absl::flags_internal -absl::flags_config -absl::fast_type_id -absl::utility -absl::time_zone -absl::civil_time -absl::string_view absl::throw_delegate -absl::memory -absl::charset -absl::endian -absl::config) +absl::iterator_traits_internal +absl::algorithm +absl::compressed_tuple +absl::utility +absl::base +absl::type_traits +absl::spinlock_wait +absl::raw_logging_internal +absl::errno_saver +absl::nullability +absl::log_severity +absl::dynamic_annotations +absl::base_internal +absl::atomic_hook +absl::core_headers +absl::config +absl::absl_log +absl::log_internal_log_impl +absl::absl_check +absl::log_internal_check_impl) diff --git a/cmake/external/abseil-cpp.natvis b/cmake/external/abseil-cpp.natvis index e995e215432a2..9c858ece449cd 100644 --- a/cmake/external/abseil-cpp.natvis +++ b/cmake/external/abseil-cpp.natvis @@ -1,79 +1,77 @@ - - - + + + + + + + - {{ size={ _size() }}} + + + + + + size={_size()} cap={_capacity()} (heap) + size={_size()} cap={_capacity()} (inline) + - $T2 - storage_.data_.allocated.allocated_capacity - $T2 + _size() - _is_allocated() - storage_.metadata_ - - _size() - _inlined_data()[$i] - - + _capacity() + _inline_capacity() + "heap" + "inline" + "empty" + _data() + _data()[0] + _data()[_size()-1] + "CORRUPT: size > capacity" + + + _size() - _allocated_data()[$i] + _data()[$i] - - - - - - - - size={ _size() } - size=({_size()}) - - _size() - _capacity() - - - _size() - - - - _slots()[nslot] - - nslot++ - - - - - - - - *($T1 *){value} - (*($T1 *){value}) - - *($T1 *){value} - - + + + + + + + + + + + - - - *($T1 *)this - (*($T1 *)this) - - *($T1 *)this - - + size={_size()} cap={_capacity()} (heap) + size={_size()} cap={_capacity()} (inline) - - {value.first}, {value.second} - ({value.first}, {value.second}) - value.first - value.second + _size() + _capacity() + _inline_capacity() + + "heap" + "inline" + "empty" + _data() + _data()[0] + _data()[_size()-1] + "CORRUPT: size > capacity" + + + + _size() + _data()[$i] + diff --git a/cmake/external/composable_kernel.cmake b/cmake/external/composable_kernel.cmake deleted file mode 100644 index b388a01209f4e..0000000000000 --- a/cmake/external/composable_kernel.cmake +++ /dev/null @@ -1,65 +0,0 @@ -set(PATCH_CLANG ${PROJECT_SOURCE_DIR}/patches/composable_kernel/Fix_Clang_Build.patch) -set(PATCH_GFX12X ${PROJECT_SOURCE_DIR}/patches/composable_kernel/Add_gfx12x_support.patch) - -include(FetchContent) -FetchContent_Declare(composable_kernel - URL ${DEP_URL_composable_kernel} - URL_HASH SHA1=${DEP_SHA1_composable_kernel} - PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PATCH_CLANG} && - ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PATCH_GFX12X} -) - -FetchContent_GetProperties(composable_kernel) -if(NOT composable_kernel_POPULATED) - FetchContent_Populate(composable_kernel) - set(GPU_TARGETS ${CMAKE_HIP_ARCHITECTURES}) - set(BUILD_DEV OFF CACHE BOOL "Disable -Weverything, otherwise, error: 'constexpr' specifier is incompatible with C++98 [-Werror,-Wc++98-compat]" FORCE) - # Exclude i8 device gemm instances due to excessive long compilation time and not being used - set(DTYPES fp32 fp16 bf16 fp8) - set(INSTANCES_ONLY ON) - add_subdirectory(${composable_kernel_SOURCE_DIR} ${composable_kernel_BINARY_DIR} EXCLUDE_FROM_ALL) - - add_library(onnxruntime_composable_kernel_includes INTERFACE) - target_include_directories(onnxruntime_composable_kernel_includes INTERFACE - ${composable_kernel_SOURCE_DIR}/include - ${composable_kernel_BINARY_DIR}/include - ${composable_kernel_SOURCE_DIR}/library/include) - target_compile_definitions(onnxruntime_composable_kernel_includes INTERFACE __fp32__ __fp16__ __bf16__) - - execute_process( - COMMAND ${Python3_EXECUTABLE} ${composable_kernel_SOURCE_DIR}/example/ck_tile/01_fmha/generate.py - --list_blobs ${composable_kernel_BINARY_DIR}/blob_list.txt - COMMAND_ERROR_IS_FATAL ANY - ) - file(STRINGS ${composable_kernel_BINARY_DIR}/blob_list.txt generated_fmha_srcs) - add_custom_command( - OUTPUT ${generated_fmha_srcs} - COMMAND ${Python3_EXECUTABLE} ${composable_kernel_SOURCE_DIR}/example/ck_tile/01_fmha/generate.py --output_dir ${composable_kernel_BINARY_DIR} - DEPENDS ${composable_kernel_SOURCE_DIR}/example/ck_tile/01_fmha/generate.py ${composable_kernel_BINARY_DIR}/blob_list.txt - ) - set_source_files_properties(${generated_fmha_srcs} PROPERTIES LANGUAGE HIP GENERATED TRUE) - add_custom_target(gen_fmha_srcs DEPENDS ${generated_fmha_srcs}) # dummy target for dependencies - # code generation complete - - set(fmha_srcs - ${generated_fmha_srcs} - ${composable_kernel_SOURCE_DIR}/example/ck_tile/01_fmha/fmha_fwd.cpp - ${composable_kernel_SOURCE_DIR}/example/ck_tile/01_fmha/fmha_fwd.hpp - ${composable_kernel_SOURCE_DIR}/example/ck_tile/01_fmha/bias.hpp - ${composable_kernel_SOURCE_DIR}/example/ck_tile/01_fmha/mask.hpp - ) - add_library(onnxruntime_composable_kernel_fmha STATIC EXCLUDE_FROM_ALL ${generated_fmha_srcs}) - target_link_libraries(onnxruntime_composable_kernel_fmha PUBLIC onnxruntime_composable_kernel_includes) - target_include_directories(onnxruntime_composable_kernel_fmha PUBLIC ${composable_kernel_SOURCE_DIR}/example/ck_tile/01_fmha) - add_dependencies(onnxruntime_composable_kernel_fmha gen_fmha_srcs) - - # ck tile only supports MI200+ GPUs at the moment - get_target_property(archs onnxruntime_composable_kernel_fmha HIP_ARCHITECTURES) - string(REPLACE "," ";" archs "${archs}") - set(original_archs ${archs}) - list(FILTER archs INCLUDE REGEX "(gfx942|gfx90a)") - if (NOT original_archs EQUAL archs) - message(WARNING "ck tile only supports archs: ${archs} among the originally specified ${original_archs}") - endif() - set_target_properties(onnxruntime_composable_kernel_fmha PROPERTIES HIP_ARCHITECTURES "${archs}") -endif() diff --git a/cmake/external/cuDNN.cmake b/cmake/external/cuDNN.cmake index f416b207676cf..2c755649d1360 100644 --- a/cmake/external/cuDNN.cmake +++ b/cmake/external/cuDNN.cmake @@ -3,7 +3,7 @@ add_library(CUDNN::cudnn_all INTERFACE IMPORTED) find_path( CUDNN_INCLUDE_DIR cudnn.h HINTS $ENV{CUDNN_PATH} ${CUDNN_PATH} ${Python_SITEARCH}/nvidia/cudnn ${CUDAToolkit_INCLUDE_DIRS} - PATH_SUFFIXES include + PATH_SUFFIXES include include/${onnxruntime_CUDA_VERSION} REQUIRED ) @@ -15,7 +15,7 @@ function(find_cudnn_library NAME) find_library( ${NAME}_LIBRARY ${NAME} "lib${NAME}.so.${CUDNN_MAJOR_VERSION}" HINTS $ENV{CUDNN_PATH} ${CUDNN_PATH} ${Python_SITEARCH}/nvidia/cudnn ${CUDAToolkit_LIBRARY_DIR} - PATH_SUFFIXES lib64 lib/x64 lib + PATH_SUFFIXES lib64 lib/x64 lib lib/${onnxruntime_CUDA_VERSION}/x64 REQUIRED ) @@ -67,43 +67,3 @@ target_link_libraries( INTERFACE CUDNN::cudnn ) - -if(CUDNN_MAJOR_VERSION EQUAL 8) - find_cudnn_library(cudnn_adv_infer) - find_cudnn_library(cudnn_adv_train) - find_cudnn_library(cudnn_cnn_infer) - find_cudnn_library(cudnn_cnn_train) - find_cudnn_library(cudnn_ops_infer) - find_cudnn_library(cudnn_ops_train) - - target_link_libraries( - CUDNN::cudnn_all - INTERFACE - CUDNN::cudnn_adv_train - CUDNN::cudnn_ops_train - CUDNN::cudnn_cnn_train - CUDNN::cudnn_adv_infer - CUDNN::cudnn_cnn_infer - CUDNN::cudnn_ops_infer - ) -elseif(CUDNN_MAJOR_VERSION EQUAL 9) - find_cudnn_library(cudnn_cnn) - find_cudnn_library(cudnn_adv) - find_cudnn_library(cudnn_graph) - find_cudnn_library(cudnn_ops) - find_cudnn_library(cudnn_engines_runtime_compiled) - find_cudnn_library(cudnn_engines_precompiled) - find_cudnn_library(cudnn_heuristic) - - target_link_libraries( - CUDNN::cudnn_all - INTERFACE - CUDNN::cudnn_adv - CUDNN::cudnn_ops - CUDNN::cudnn_cnn - CUDNN::cudnn_graph - CUDNN::cudnn_engines_runtime_compiled - CUDNN::cudnn_engines_precompiled - CUDNN::cudnn_heuristic - ) -endif() diff --git a/cmake/external/cuda_configuration.cmake b/cmake/external/cuda_configuration.cmake new file mode 100644 index 0000000000000..df180d185a268 --- /dev/null +++ b/cmake/external/cuda_configuration.cmake @@ -0,0 +1,207 @@ +# +# SPDX-FileCopyrightText: Copyright (c) 1993-2022 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# SPDX-License-Identifier: Apache-2.0 +# +# Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with +# the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the +# specific language governing permissions and limitations under the License. +# + +macro(setup_cuda_compiler) + # Determine CUDA version before enabling the language extension check_language(CUDA) clears CMAKE_CUDA_HOST_COMPILER + # if CMAKE_CUDA_COMPILER is not set + include(CheckLanguage) + if(NOT CMAKE_CUDA_COMPILER AND CMAKE_CUDA_HOST_COMPILER) + set(CMAKE_CUDA_HOST_COMPILER_BACKUP ${CMAKE_CUDA_HOST_COMPILER}) + endif() + check_language(CUDA) + if(CMAKE_CUDA_HOST_COMPILER_BACKUP) + set(CMAKE_CUDA_HOST_COMPILER ${CMAKE_CUDA_HOST_COMPILER_BACKUP}) + check_language(CUDA) + endif() + if(CMAKE_CUDA_COMPILER) + message(STATUS "CUDA compiler: ${CMAKE_CUDA_COMPILER}") + if(NOT WIN32) # Linux + execute_process( + COMMAND "bash" "-c" "${CMAKE_CUDA_COMPILER} --version | grep -E -o 'V[0-9]+.[0-9]+.[0-9]+' | cut -c2-" + RESULT_VARIABLE _BASH_SUCCESS + OUTPUT_VARIABLE CMAKE_CUDA_COMPILER_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE) + + if(NOT _BASH_SUCCESS EQUAL 0) + message(FATAL_ERROR "Failed to determine CUDA version") + endif() + + else() # Windows + execute_process( + COMMAND ${CMAKE_CUDA_COMPILER} --version + OUTPUT_VARIABLE versionString + RESULT_VARIABLE versionResult) + + if(versionResult EQUAL 0 AND versionString MATCHES "V[0-9]+\\.[0-9]+\\.[0-9]+") + string(REGEX REPLACE "V" "" version ${CMAKE_MATCH_0}) + set(CMAKE_CUDA_COMPILER_VERSION "${version}") + else() + message(FATAL_ERROR "Failed to determine CUDA version") + endif() + endif() + else() + message(FATAL_ERROR "No CUDA compiler found") + endif() + + set(CUDA_REQUIRED_VERSION 12.0) + if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS CUDA_REQUIRED_VERSION) + message(FATAL_ERROR "CUDA version ${CMAKE_CUDA_COMPILER_VERSION} must be at least ${CUDA_REQUIRED_VERSION}") + endif() + + # For CUDA 13+, explicitly set the compiler front-end to Clang to handle + # MSVC-specific pragmas correctly in device code. + if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0 AND NOT DEFINED CMAKE_CUDA_COMPILER_FRONTEND_VARIANT) + message(STATUS "Setting CUDA compiler front-end to Clang by default for CUDA 13+.") + set(CMAKE_CUDA_COMPILER_FRONTEND_VARIANT "CLANG") + endif() + + if(CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0) + set(CMAKE_CUDA_RUNTIME_LIBRARY "Hybrid") + else() + set(CMAKE_CUDA_RUNTIME_LIBRARY "Shared") + endif() +endmacro() + +macro(setup_cuda_architectures) + # cmake-format: off + # Initialize and normalize CMAKE_CUDA_ARCHITECTURES before enabling CUDA. + # Special values: + # (1) `native` is resolved to HIGHEST available architecture. Fallback to `all` if detection failed. + # (2) `all` / `all-major` / unset is resolved to a default set of architectures we optimized and compiler supports. + # Numerical architectures: + # * For `-virtual` architectures, the last one is kept as it is, and the others are ignored. + # * `-real` suffix is automatically added for other cases. + # * Always use accelerated (`-a` suffix) target for supported real architectures. + # cmake-format: on + + # Allow override via CUDAARCHS environment variable (standard CMake variable) + if(NOT CMAKE_CUDA_ARCHITECTURES AND DEFINED ENV{CUDAARCHS}) + set(CMAKE_CUDA_ARCHITECTURES "$ENV{CUDAARCHS}") + endif() + + if(CMAKE_CUDA_ARCHITECTURES STREQUAL "native") + # Detect highest available compute capability + set(OUTPUTFILE ${PROJECT_BINARY_DIR}/detect_cuda_arch) + set(CUDAFILE ${CMAKE_SOURCE_DIR}/utils/detect_cuda_arch.cu) + execute_process(COMMAND ${CMAKE_CUDA_COMPILER} -lcuda ${CUDAFILE} -o ${OUTPUTFILE}) + message(VERBOSE "Detecting native CUDA compute capability") + execute_process( + COMMAND ${OUTPUTFILE} + RESULT_VARIABLE CUDA_RETURN_CODE + OUTPUT_VARIABLE CUDA_ARCH_OUTPUT) + if(NOT ${CUDA_RETURN_CODE} EQUAL 0) + message(WARNING "Detecting native CUDA compute capability - fail") + message(WARNING "CUDA compute capability detection failed, compiling for all optimized architectures") + unset(CMAKE_CUDA_ARCHITECTURES) + else() + message(STATUS "Detecting native CUDA compute capability - done") + set(CMAKE_CUDA_ARCHITECTURES "${CUDA_ARCH_OUTPUT}") + endif() + elseif(CMAKE_CUDA_ARCHITECTURES STREQUAL "all") + unset(CMAKE_CUDA_ARCHITECTURES) + message(STATUS "Setting CMAKE_CUDA_ARCHITECTURES to all enables a list of architectures OnnxRuntime optimized for, " + "not all architectures CUDA compiler supports.") + elseif(CMAKE_CUDA_ARCHITECTURES STREQUAL "all-major") + unset(CMAKE_CUDA_ARCHITECTURES) + message( + STATUS "Setting CMAKE_CUDA_ARCHITECTURES to all-major enables a list of architectures OnnxRuntime optimized for, " + "not all major architectures CUDA compiler supports.") + else() + message(STATUS "Original CMAKE_CUDA_ARCHITECTURES : ${CMAKE_CUDA_ARCHITECTURES}") + endif() + + if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES) + if(CMAKE_LIBRARY_ARCHITECTURE STREQUAL "aarch64-linux-gnu") + # Support for Jetson/Tegra ARM devices + set(CMAKE_CUDA_ARCHITECTURES "53;62;72;87") # TX1/Nano, TX2, Xavier, Orin + else() + if(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 12.8) + set(CMAKE_CUDA_ARCHITECTURES "52;60;70;75;80;86;89;90") + elseif(CMAKE_CUDA_COMPILER_VERSION VERSION_LESS 13.0) + set(CMAKE_CUDA_ARCHITECTURES "60;70;75;80;86;89;90;100;120") + else() + # 13.x drops support for 60 and 70 + set(CMAKE_CUDA_ARCHITECTURES "75;80;86;89;90;100;120") + endif() + endif() + endif() + + unset(CMAKE_CUDA_ARCHITECTURES_CLEAN) + unset(CMAKE_CUDA_ARCHITECTURES_LAST_VIRTUAL) + foreach(CUDA_ARCH IN LISTS CMAKE_CUDA_ARCHITECTURES) + if(CUDA_ARCH STREQUAL "") + continue() + endif() + + if(CUDA_ARCH MATCHES "^([1-9])([0-9])+[af]?-virtual$") + set(CMAKE_CUDA_ARCHITECTURES_LAST_VIRTUAL ${CUDA_ARCH}) + elseif(CUDA_ARCH MATCHES "^(([1-9])([0-9])+)[af]?-real$") + list(APPEND CMAKE_CUDA_ARCHITECTURES_CLEAN ${CMAKE_MATCH_1}) + elseif(CUDA_ARCH MATCHES "^(([1-9])([0-9])+)([af]?)$") + list(APPEND CMAKE_CUDA_ARCHITECTURES_CLEAN ${CMAKE_MATCH_1}${CMAKE_MATCH_4}) + else() + message(FATAL_ERROR "Unrecognized CUDA architecture: ${CUDA_ARCH}") + endif() + endforeach() + list(REMOVE_DUPLICATES CMAKE_CUDA_ARCHITECTURES_CLEAN) + set(CMAKE_CUDA_ARCHITECTURES ${CMAKE_CUDA_ARCHITECTURES_CLEAN}) + + # CMAKE_CUDA_ARCHITECTURES_ORIG contains all architectures enabled, without automatically added -real or -a suffix. + set(CMAKE_CUDA_ARCHITECTURES_ORIG "${CMAKE_CUDA_ARCHITECTURES}") + message(STATUS "GPU architectures: ${CMAKE_CUDA_ARCHITECTURES_ORIG}") + + unset(ORT_HAS_SM80_OR_LATER) + foreach(CUDA_ARCH IN LISTS CMAKE_CUDA_ARCHITECTURES_ORIG) + if(CUDA_ARCH MATCHES "^([0-9]+)") + if(CMAKE_MATCH_1 GREATER_EQUAL 80) + set(ORT_HAS_SM80_OR_LATER ON) + break() + endif() + endif() + endforeach() + + if(ORT_HAS_SM80_OR_LATER) + add_definitions("-DHAS_SM80_OR_LATER") + endif() + + set(ARCHITECTURES_WITH_KERNELS "80" "86" "89" "90" "100" "110" "120") + foreach(CUDA_ARCH IN LISTS ARCHITECTURES_WITH_KERNELS) + if(NOT "${CUDA_ARCH}" IN_LIST CMAKE_CUDA_ARCHITECTURES_ORIG) + add_definitions("-DEXCLUDE_SM_${CUDA_ARCH}") + message(STATUS "Excluding SM ${CUDA_ARCH}") + endif() + endforeach() + + # Enable accelerated features (like WGMMA, TMA and setmaxnreg) for SM >= 90. + set(ARCHITECTURES_WITH_ACCEL "90" "100" "101" "110" "120") + unset(CMAKE_CUDA_ARCHITECTURES_NORMALIZED) + foreach(CUDA_ARCH IN LISTS CMAKE_CUDA_ARCHITECTURES) + if(CUDA_ARCH MATCHES "^([0-9]+)f$") + # Family code, no -real suffix + list(APPEND CMAKE_CUDA_ARCHITECTURES_NORMALIZED "${CUDA_ARCH}") + elseif("${CUDA_ARCH}" IN_LIST ARCHITECTURES_WITH_ACCEL) + list(APPEND CMAKE_CUDA_ARCHITECTURES_NORMALIZED "${CUDA_ARCH}a-real") + else() + list(APPEND CMAKE_CUDA_ARCHITECTURES_NORMALIZED "${CUDA_ARCH}-real") + endif() + endforeach() + + if(DEFINED CMAKE_CUDA_ARCHITECTURES_LAST_VIRTUAL) + list(APPEND CMAKE_CUDA_ARCHITECTURES_NORMALIZED "${CMAKE_CUDA_ARCHITECTURES_LAST_VIRTUAL}") + endif() + + set(CMAKE_CUDA_ARCHITECTURES ${CMAKE_CUDA_ARCHITECTURES_NORMALIZED}) + + message(STATUS "CMAKE_CUDA_ARCHITECTURES: ${CMAKE_CUDA_ARCHITECTURES}") +endmacro() diff --git a/cmake/external/cudnn_frontend.cmake b/cmake/external/cudnn_frontend.cmake index 7ac51deaf93bc..d89ab0f669f35 100644 --- a/cmake/external/cudnn_frontend.cmake +++ b/cmake/external/cudnn_frontend.cmake @@ -1,12 +1,15 @@ -include(FetchContent) -FetchContent_Declare( + +onnxruntime_fetchcontent_declare( cudnn_frontend URL ${DEP_URL_cudnn_frontend} URL_HASH SHA1=${DEP_SHA1_cudnn_frontend} + EXCLUDE_FROM_ALL ) -set(CUDNN_FRONTEND_BUILD_SAMPLES OFF) -set(CUDNN_FRONTEND_BUILD_UNIT_TESTS OFF) -set(CUDNN_FRONTEND_BUILD_PYTHON_BINDINGS OFF) +set(CUDNN_FRONTEND_SKIP_JSON_LIB OFF CACHE BOOL "" FORCE) +set(CUDNN_FRONTEND_BUILD_SAMPLES OFF CACHE BOOL "" FORCE) +set(CUDNN_FRONTEND_BUILD_TESTS OFF CACHE BOOL "" FORCE) +set(CUDNN_FRONTEND_BUILD_PYTHON_BINDINGS OFF CACHE BOOL "" FORCE) set(CUDNN_PATH ${onnxruntime_CUDNN_HOME}) -FetchContent_MakeAvailable(cudnn_frontend) + +onnxruntime_fetchcontent_makeavailable(cudnn_frontend) diff --git a/cmake/external/cutlass.cmake b/cmake/external/cutlass.cmake index f04f4bec76cd5..62187fd0ca63f 100644 --- a/cmake/external/cutlass.cmake +++ b/cmake/external/cutlass.cmake @@ -1,8 +1,10 @@ include(FetchContent) -FetchContent_Declare( +onnxruntime_fetchcontent_declare( cutlass URL ${DEP_URL_cutlass} URL_HASH SHA1=${DEP_SHA1_cutlass} + EXCLUDE_FROM_ALL + PATCH_COMMAND ${Patch_EXECUTABLE} --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/cutlass/cutlass_4.4.2.patch ) FetchContent_GetProperties(cutlass) diff --git a/cmake/external/dml.cmake b/cmake/external/dml.cmake index 3cfcdd4b04c62..1a62695e1f18e 100644 --- a/cmake/external/dml.cmake +++ b/cmake/external/dml.cmake @@ -100,13 +100,17 @@ else() endif() endif() -FetchContent_Declare( +if (onnxruntime_USE_VCPKG) + find_package(directx-headers CONFIG REQUIRED) +else() + onnxruntime_fetchcontent_declare( directx_headers URL ${DEP_URL_directx_headers} URL_HASH SHA1=${DEP_SHA1_directx_headers} -) - -FetchContent_Populate(directx_headers) -set(directx_headers_INCLUDE_DIRS "${directx_headers_SOURCE_DIR}/include") + EXCLUDE_FROM_ALL + ) -include_directories(BEFORE ${directx_headers_INCLUDE_DIRS}) + FetchContent_Populate(directx_headers) + set(directx_headers_INCLUDE_DIRS "${directx_headers_SOURCE_DIR}/include") + include_directories(BEFORE ${directx_headers_INCLUDE_DIRS}) +endif() \ No newline at end of file diff --git a/cmake/external/eigen.cmake b/cmake/external/eigen.cmake index 95dd438702a18..2f55860f34c70 100644 --- a/cmake/external/eigen.cmake +++ b/cmake/external/eigen.cmake @@ -1,24 +1,18 @@ -if (onnxruntime_USE_PREINSTALLED_EIGEN) - add_library(eigen INTERFACE) - file(TO_CMAKE_PATH ${eigen_SOURCE_PATH} eigen_INCLUDE_DIRS) - target_include_directories(eigen INTERFACE ${eigen_INCLUDE_DIRS}) -else () - if(CMAKE_SYSTEM_NAME MATCHES "AIX") - FetchContent_Declare( - eigen - URL ${DEP_URL_eigen} - URL_HASH SHA1=${DEP_SHA1_eigen} - PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/eigen/eigen-aix.patch - ) - else() - FetchContent_Declare( - eigen - URL ${DEP_URL_eigen} - URL_HASH SHA1=${DEP_SHA1_eigen} - PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/eigen/eigen-edge.patch - ) - endif() +set(EIGEN_BUILD_DOC OFF CACHE BOOL "" FORCE) +set(EIGEN_BUILD_BLAS OFF CACHE BOOL "" FORCE) +set(EIGEN_BUILD_LAPACK OFF CACHE BOOL "" FORCE) +set(EIGEN_BUILD_PKGCONFIG OFF CACHE BOOL "" FORCE) +set(EIGEN_BUILD_CMAKE_PACKAGE ON CACHE BOOL "" FORCE) - FetchContent_Populate(eigen) - set(eigen_INCLUDE_DIRS "${eigen_SOURCE_DIR}") -endif() +set(PATCH_EIGEN_S390X ${PROJECT_SOURCE_DIR}/patches/eigen/s390x-build.patch) +set(PATCH_EIGEN_S390X_WERROR ${PROJECT_SOURCE_DIR}/patches/eigen/s390x-build-werror.patch) + +onnxruntime_fetchcontent_declare( + Eigen3 + URL ${DEP_URL_eigen} + URL_HASH SHA1=${DEP_SHA1_eigen} + PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PATCH_EIGEN_S390X} && + ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PATCH_EIGEN_S390X_WERROR} + EXCLUDE_FROM_ALL +) +onnxruntime_fetchcontent_makeavailable(Eigen3) diff --git a/cmake/external/emsdk b/cmake/external/emsdk index d52c465201248..c0bb220cb6e6f 160000 --- a/cmake/external/emsdk +++ b/cmake/external/emsdk @@ -1 +1 @@ -Subproject commit d52c46520124845b1e0e0525f2759299d840143f +Subproject commit c0bb220cb6e6f4e0fabb6f6db9efd53390ef5e56 diff --git a/cmake/external/extensions.cmake b/cmake/external/extensions.cmake index 68796ad02d982..bd3c47d53f53d 100644 --- a/cmake/external/extensions.cmake +++ b/cmake/external/extensions.cmake @@ -38,10 +38,11 @@ endif() # onnxruntime-extensions if (NOT onnxruntime_EXTENSIONS_OVERRIDDEN) - FetchContent_Declare( + onnxruntime_fetchcontent_declare( extensions URL ${DEP_URL_extensions} URL_HASH SHA1=${DEP_SHA1_extensions} + EXCLUDE_FROM_ALL ) onnxruntime_fetchcontent_makeavailable(extensions) else() @@ -51,9 +52,24 @@ else() add_subdirectory(${onnxruntime_EXTENSIONS_PATH} ${CMAKE_BINARY_DIR}/_deps/extensions-subbuild EXCLUDE_FROM_ALL) endif() +# move internal includes generated by onnxruntime-extensions as PUBLIC +# from INTERFACE_INCLUDE_DIRECTORIES to INTERFACE_DIRECTORIES for the +# targets that we will link to +get_target_property(ocos_operators_INTERFACE_INCLUDES ocos_operators INTERFACE_INCLUDE_DIRECTORIES) +target_include_directories(ocos_operators PRIVATE ${ocos_operators_INTERFACE_INCLUDES}) +set_target_properties(ocos_operators PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "") + +get_target_property(noexcep_operators_INTERFACE_INCLUDES noexcep_operators INTERFACE_INCLUDE_DIRECTORIES) +target_include_directories(noexcep_operators PRIVATE ${noexcep_operators_INTERFACE_INCLUDES}) +set_target_properties(noexcep_operators PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "") + +get_target_property(ortcustomops_INTERFACE_INCLUDES ortcustomops INTERFACE_INCLUDE_DIRECTORIES) +target_include_directories(ortcustomops PRIVATE ${ortcustomops_INTERFACE_INCLUDES} ${ONNXRUNTIME_INCLUDE_DIR}/core/session) +set_target_properties(ortcustomops PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "") + # target library or executable are defined in CMakeLists.txt of onnxruntime-extensions target_include_directories(ocos_operators PRIVATE ${RE2_INCLUDE_DIR} ${json_SOURCE_DIR}/include) -target_include_directories(ortcustomops PUBLIC ${onnxruntime_EXTENSIONS_PATH}/includes) +target_include_directories(ortcustomops PUBLIC $) if(OCOS_ENABLE_SPM_TOKENIZER) onnxruntime_add_include_to_target(sentencepiece-static ${PROTOBUF_LIB} ${ABSEIL_LIBS}) endif() @@ -63,3 +79,10 @@ onnxruntime_add_include_to_target(noexcep_operators ${PROTOBUF_LIB} ${ABSEIL_LIB add_dependencies(ocos_operators ${onnxruntime_EXTERNAL_DEPENDENCIES}) add_dependencies(ortcustomops ${onnxruntime_EXTERNAL_DEPENDENCIES}) +if (NOT onnxruntime_BUILD_SHARED_LIB) + install(TARGETS ocos_operators ortcustomops noexcep_operators EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/cmake/external/helper_functions.cmake b/cmake/external/helper_functions.cmake index e3f2211f96158..e8044411e4201 100644 --- a/cmake/external/helper_functions.cmake +++ b/cmake/external/helper_functions.cmake @@ -1,223 +1,47 @@ -# Distributed under the OSI-approved BSD 3-Clause License. See accompanying -# file Copyright.txt or https://cmake.org/licensing for details. - -# Recursively set the folder for all targets in the subdirectories of the given source directory. -function(set_folder_for_subdir_targets srcDir folderName) - get_property(subdirs DIRECTORY "${srcDir}" PROPERTY SUBDIRECTORIES) - foreach(subdir ${subdirs}) - get_property(subdir_import_targets DIRECTORY "${subdir}" PROPERTY BUILDSYSTEM_TARGETS) - foreach(subdir_target ${subdir_import_targets}) - set_target_properties(${subdir_target} PROPERTIES FOLDER ${folderName}) - endforeach() - - set_folder_for_subdir_targets(${subdir} ${folderName}) - endforeach() -endfunction() - -# This file was copied from cmake source with modifications: -# 1. Add the EXCLUDE_FROM_ALL keyword when this function calls add_subdirectory. It will also resolve the -# 'make install' issue. -# 2. Group the VC projects into the "external" folder. We can do it at there in a centralized way instead +# This file contains some wrappers for cmake's FetchContent functions. The wrappers added the following functionalities: +# 1. Group the VC projects into the "external" folder. We can do it at there in a centralized way instead # of doing it one by one. -# 3. Set the cmake property COMPILE_WARNING_AS_ERROR to OFF for these external projects. - -macro(onnxruntime_fetchcontent_makeavailable) - - # We must append an item, even if the variable is unset, so prefix its value. - # We will strip that prefix when we pop the value at the end of the macro. - list(APPEND __cmake_fcCurrentVarsStack - "__fcprefix__${CMAKE_VERIFY_INTERFACE_HEADER_SETS}" - ) - set(CMAKE_VERIFY_INTERFACE_HEADER_SETS FALSE) - - get_property(__cmake_providerCommand GLOBAL PROPERTY - __FETCHCONTENT_MAKEAVAILABLE_SERIAL_PROVIDER - ) - foreach(__cmake_contentName IN ITEMS ${ARGV}) - string(TOLOWER ${__cmake_contentName} __cmake_contentNameLower) - - # If user specified FETCHCONTENT_SOURCE_DIR_... for this dependency, that - # overrides everything else and we shouldn't try to use find_package() or - # a dependency provider. - string(TOUPPER ${__cmake_contentName} __cmake_contentNameUpper) - if("${FETCHCONTENT_SOURCE_DIR_${__cmake_contentNameUpper}}" STREQUAL "") - # Dependency provider gets first opportunity, but prevent infinite - # recursion if we are called again for the same thing - if(NOT "${__cmake_providerCommand}" STREQUAL "" AND - NOT DEFINED __cmake_fcProvider_${__cmake_contentNameLower}) - message(VERBOSE - "Trying FETCHCONTENT_MAKEAVAILABLE_SERIAL dependency provider for " - "${__cmake_contentName}" - ) - # It's still valid if there are no saved details. The project may have - # been written to assume a dependency provider is always set and will - # provide dependencies without having any declared details for them. - __FetchContent_getSavedDetails(${__cmake_contentName} __cmake_contentDetails) - set(__cmake_providerArgs - "FETCHCONTENT_MAKEAVAILABLE_SERIAL" - "${__cmake_contentName}" - ) - # Empty arguments must be preserved because of things like - # GIT_SUBMODULES (see CMP0097) - foreach(__cmake_item IN LISTS __cmake_contentDetails) - string(APPEND __cmake_providerArgs " [==[${__cmake_item}]==]") - endforeach() - - # This property might be defined but empty. As long as it is defined, - # find_package() can be called. - get_property(__cmake_addfpargs GLOBAL PROPERTY - _FetchContent_${contentNameLower}_find_package_args - DEFINED - ) - if(__cmake_addfpargs) - get_property(__cmake_fpargs GLOBAL PROPERTY - _FetchContent_${contentNameLower}_find_package_args - ) - string(APPEND __cmake_providerArgs " FIND_PACKAGE_ARGS") - foreach(__cmake_item IN LISTS __cmake_fpargs) - string(APPEND __cmake_providerArgs " [==[${__cmake_item}]==]") - endforeach() - endif() - - # Calling the provider could lead to onnxruntime_fetchcontent_makeavailable() being - # called for a nested dependency. That nested call may occur in the - # current variable scope. We have to save and restore the variables we - # need preserved. - list(APPEND __cmake_fcCurrentVarsStack - ${__cmake_contentName} - ${__cmake_contentNameLower} - ) - - set(__cmake_fcProvider_${__cmake_contentNameLower} YES) - cmake_language(EVAL CODE "${__cmake_providerCommand}(${__cmake_providerArgs})") - - list(POP_BACK __cmake_fcCurrentVarsStack - __cmake_contentNameLower - __cmake_contentName - ) - - unset(__cmake_fcProvider_${__cmake_contentNameLower}) - unset(__cmake_providerArgs) - unset(__cmake_addfpargs) - unset(__cmake_fpargs) - unset(__cmake_item) - unset(__cmake_contentDetails) - - FetchContent_GetProperties(${__cmake_contentName}) - if(${__cmake_contentNameLower}_POPULATED) - continue() - endif() - endif() - - # Check if we've been asked to try find_package() first, even if we - # have already populated this dependency. If we previously tried to - # use find_package() for this and it succeeded, those things might - # no longer be in scope, so we have to do it again. - get_property(__cmake_haveFpArgs GLOBAL PROPERTY - _FetchContent_${__cmake_contentNameLower}_find_package_args DEFINED - ) - if(__cmake_haveFpArgs) - unset(__cmake_haveFpArgs) - message(VERBOSE "Trying find_package(${__cmake_contentName} ...) before FetchContent") - get_property(__cmake_fpArgs GLOBAL PROPERTY - _FetchContent_${__cmake_contentNameLower}_find_package_args - ) - - # This call could lead to onnxruntime_fetchcontent_makeavailable() being called for - # a nested dependency and it may occur in the current variable scope. - # We have to save/restore the variables we need to preserve. - list(APPEND __cmake_fcCurrentNameStack - ${__cmake_contentName} - ${__cmake_contentNameLower} - ) - find_package(${__cmake_contentName} ${__cmake_fpArgs}) - list(POP_BACK __cmake_fcCurrentNameStack - __cmake_contentNameLower - __cmake_contentName - ) - unset(__cmake_fpArgs) - - if(${__cmake_contentName}_FOUND) - FetchContent_SetPopulated(${__cmake_contentName}) - FetchContent_GetProperties(${__cmake_contentName}) - continue() - endif() - endif() - else() - unset(__cmake_haveFpArgs) +# 2. Set the cmake property COMPILE_WARNING_AS_ERROR to OFF for these external projects. + +function(onnxruntime_fetchcontent_declare contentName) + cmake_parse_arguments(PARSE_ARGV 1 ARG "" "URL;SOURCE_SUBDIR" "") + message(STATUS "Fetch ${contentName} from ${ARG_URL}") + FetchContent_Declare(${ARGV}) + string(TOLOWER ${contentName} contentNameLower) + if(NOT "${ARG_SOURCE_SUBDIR}" STREQUAL "") + set(onnxruntime_${contentNameLower}_cmake_src_dir "${ARG_SOURCE_SUBDIR}" PARENT_SCOPE) endif() +endfunction() - FetchContent_GetProperties(${__cmake_contentName}) - if(NOT ${__cmake_contentNameLower}_POPULATED) - FetchContent_Populate(${__cmake_contentName}) - __FetchContent_setupFindPackageRedirection(${__cmake_contentName}) - - # Only try to call add_subdirectory() if the populated content - # can be treated that way. Protecting the call with the check - # allows this function to be used for projects that just want - # to ensure the content exists, such as to provide content at - # a known location. We check the saved details for an optional - # SOURCE_SUBDIR which can be used in the same way as its meaning - # for ExternalProject. It won't matter if it was passed through - # to the ExternalProject sub-build, since it would have been - # ignored there. - set(__cmake_srcdir "${${__cmake_contentNameLower}_SOURCE_DIR}") - __FetchContent_getSavedDetails(${__cmake_contentName} __cmake_contentDetails) - if("${__cmake_contentDetails}" STREQUAL "") - message(FATAL_ERROR "No details have been set for content: ${__cmake_contentName}") - endif() - cmake_parse_arguments(__cmake_arg "SYSTEM" "SOURCE_SUBDIR" "" ${__cmake_contentDetails}) - if(NOT "${__cmake_arg_SOURCE_SUBDIR}" STREQUAL "") - string(APPEND __cmake_srcdir "/${__cmake_arg_SOURCE_SUBDIR}") - endif() - - if(EXISTS ${__cmake_srcdir}/CMakeLists.txt) - set(CMAKE_SKIP_INSTALL_RULES TRUE) - if (__cmake_arg_SYSTEM) - add_subdirectory(${__cmake_srcdir} ${${__cmake_contentNameLower}_BINARY_DIR} SYSTEM) - else() - add_subdirectory(${__cmake_srcdir} ${${__cmake_contentNameLower}_BINARY_DIR} EXCLUDE_FROM_ALL) - endif() - - get_property(subdir_import_targets DIRECTORY "${__cmake_srcdir}" PROPERTY BUILDSYSTEM_TARGETS) - - foreach(subdir_target ${subdir_import_targets}) +macro(onnxruntime_fetchcontent_makeavailable) + set(ONNXRUNTIME_CMAKE_SKIP_INSTALL_RULES_OLD_VALUE + "${CMAKE_SKIP_INSTALL_RULES}") + # If we don't skip the install rules we will hit errors from re2 like: + # CMake Error: install(EXPORT "re2Targets" ...) includes target "re2" which requires target "absl_base" that is not in any export set. + set(CMAKE_SKIP_INSTALL_RULES TRUE) + FetchContent_MakeAvailable(${ARGV}) + foreach(contentName IN ITEMS ${ARGV}) + string(TOLOWER ${contentName} contentNameLower) + set(content_src_dir "${${contentNameLower}_SOURCE_DIR}") + if(NOT "${onnxruntime_${contentNameLower}_cmake_src_dir}" STREQUAL "") + string(APPEND content_src_dir "/${onnxruntime_${contentNameLower}_cmake_src_dir}") + get_property(subdir_import_targets DIRECTORY "${content_src_dir}" PROPERTY BUILDSYSTEM_TARGETS) + foreach(subdir_target ${subdir_import_targets}) if(TARGET ${subdir_target}) - get_target_property(subdir_target_type ${subdir_target} TYPE) - if(subdir_target_type STREQUAL "EXECUTABLE") - get_target_property(subdir_target_osx_arch ${subdir_target} OSX_ARCHITECTURES) - if (subdir_target_osx_arch) - if (NOT ${CMAKE_HOST_SYSTEM_PROCESSOR} IN_LIST subdir_target_osx_arch) - message("Added an executable target ${subdir_target} but it can not run natively on ${CMAKE_HOST_SYSTEM_PROCESSOR}, we will try to modify it") + get_target_property(subdir_target_type ${subdir_target} TYPE) + if(subdir_target_type STREQUAL "EXECUTABLE") + get_target_property(subdir_target_osx_arch ${subdir_target} OSX_ARCHITECTURES) + if (subdir_target_osx_arch) + if (NOT ${CMAKE_HOST_SYSTEM_PROCESSOR} IN_LIST subdir_target_osx_arch) + message("Added an executable target ${subdir_target} but it can not run natively on ${CMAKE_HOST_SYSTEM_PROCESSOR}, we will try to modify it") + endif() endif() endif() - endif() - set_target_properties(${subdir_target} PROPERTIES FOLDER "External/${__cmake_contentName}") - set_target_properties(${subdir_target} PROPERTIES COMPILE_WARNING_AS_ERROR OFF) + set_target_properties(${subdir_target} PROPERTIES FOLDER "External") + set_target_properties(${subdir_target} PROPERTIES COMPILE_WARNING_AS_ERROR OFF) endif() - endforeach() - set(CMAKE_SKIP_INSTALL_RULES FALSE) - - # set the FOLDER property for all targets contained in source directory and subfolders - set_folder_for_subdir_targets(${__cmake_srcdir} "External/${__cmake_contentName}") + endforeach() endif() - - unset(__cmake_srcdir) - unset(__cmake_contentDetails) - unset(__cmake_arg_SOURCE_SUBDIR) - endif() - endforeach() - # Prefix will be "__fcprefix__" - list(POP_BACK __cmake_fcCurrentVarsStack __cmake_original_verify_setting) - string(SUBSTRING "${__cmake_original_verify_setting}" - 12 -1 __cmake_original_verify_setting - ) - set(CMAKE_VERIFY_INTERFACE_HEADER_SETS ${__cmake_original_verify_setting}) - - # clear local variables to prevent leaking into the caller's scope - unset(__cmake_contentName) - unset(__cmake_contentNameLower) - unset(__cmake_contentNameUpper) - unset(__cmake_providerCommand) - unset(__cmake_original_verify_setting) + endforeach() + set(CMAKE_SKIP_INSTALL_RULES ${ONNXRUNTIME_CMAKE_SKIP_INSTALL_RULES_OLD_VALUE}) endmacro() diff --git a/cmake/external/mimalloc.cmake b/cmake/external/mimalloc.cmake deleted file mode 100644 index 8738324d8a243..0000000000000 --- a/cmake/external/mimalloc.cmake +++ /dev/null @@ -1,7 +0,0 @@ -add_definitions(-DUSE_MIMALLOC) - -set(MI_OVERRIDE OFF CACHE BOOL "" FORCE) -set(MI_BUILD_TESTS OFF CACHE BOOL "" FORCE) -set(MI_DEBUG_FULL OFF CACHE BOOL "" FORCE) -set(MI_BUILD_SHARED OFF CACHE BOOL "" FORCE) -onnxruntime_fetchcontent_makeavailable(mimalloc) \ No newline at end of file diff --git a/cmake/external/onnx b/cmake/external/onnx index b8baa84466864..be2b5fde82d9c 160000 --- a/cmake/external/onnx +++ b/cmake/external/onnx @@ -1 +1 @@ -Subproject commit b8baa8446686496da4cc8fda09f2b6fe65c2a02c +Subproject commit be2b5fde82d9c8874f3d19328bdfe3b6962dc67b diff --git a/cmake/external/onnx_minimal.cmake b/cmake/external/onnx_minimal.cmake deleted file mode 100644 index 65ff3fb148b11..0000000000000 --- a/cmake/external/onnx_minimal.cmake +++ /dev/null @@ -1,89 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - -# -# Setup onnx and onnx_protobuf for a build with onnxruntime_MINIMAL_BUILD enabled. -# We exclude everything but the essentials from the onnx library. -# - -if(NOT onnxruntime_MINIMAL_BUILD) - message(FATAL_ERROR "This file should only be included in a minimal build") -endif() - -#TODO: if protobuf is a shared lib and onnxruntime_USE_FULL_PROTOBUF is ON, then onnx_proto should be built as a shared lib instead of a static lib. Otherwise any code outside onnxruntime.dll can't use onnx protobuf definitions if they share the protobuf.dll with onnxruntime. For example, if protobuf is a shared lib and onnx_proto is a static lib then onnxruntime_perf_test won't work. - - - -FetchContent_Populate(onnx) -set(ONNX_SOURCE_ROOT ${onnx_SOURCE_DIR}) - - - -add_library(onnx_proto ${ONNX_SOURCE_ROOT}/onnx/onnx-ml.proto ${ONNX_SOURCE_ROOT}/onnx/onnx-operators-ml.proto ${ONNX_SOURCE_ROOT}/onnx/onnx-data.proto) - -target_include_directories(onnx_proto PUBLIC $ "${CMAKE_CURRENT_BINARY_DIR}") -target_compile_definitions(onnx_proto PUBLIC $) - -set(_src_prefix "onnx/") -onnxruntime_protobuf_generate(NO_SRC_INCLUDES GEN_SRC_PREFIX ${_src_prefix} IMPORT_DIRS ${ONNX_SOURCE_ROOT} TARGET onnx_proto) - -# For reference, this would be the full ONNX source include. We only need data_type_utils in this build. -# file(GLOB_RECURSE onnx_src CONFIGURE_DEPENDS -# "${ONNX_SOURCE_ROOT}/onnx/*.h" -# "${ONNX_SOURCE_ROOT}/onnx/*.cc" -# ) -# file(GLOB_RECURSE onnx_exclude_src CONFIGURE_DEPENDS -# "${ONNX_SOURCE_ROOT}/onnx/py_utils.h" -# "${ONNX_SOURCE_ROOT}/onnx/proto_utils.h" -# "${ONNX_SOURCE_ROOT}/onnx/backend/test/cpp/*" -# "${ONNX_SOURCE_ROOT}/onnx/test/*" -# "${ONNX_SOURCE_ROOT}/onnx/cpp2py_export.cc" -# ) -# list(REMOVE_ITEM onnx_src ${onnx_exclude_src}) -set(onnx_src - "${ONNX_SOURCE_ROOT}/onnx/common/common.h" - "${ONNX_SOURCE_ROOT}/onnx/defs/data_type_utils.h" - "${ONNX_SOURCE_ROOT}/onnx/defs/data_type_utils.cc" -) - -add_library(onnx ${onnx_src}) -add_dependencies(onnx onnx_proto) -target_include_directories(onnx PUBLIC "${ONNX_SOURCE_ROOT}") -target_include_directories(onnx PUBLIC $) -if (onnxruntime_USE_FULL_PROTOBUF) - target_compile_definitions(onnx PUBLIC "ONNX_ML" "ONNX_NAMESPACE=onnx") -else() - target_compile_definitions(onnx PUBLIC "ONNX_ML" "ONNX_NAMESPACE=onnx" "ONNX_USE_LITE_PROTO") -endif() - -if (WIN32) - target_compile_options(onnx PRIVATE - /wd4800 # 'type' : forcing value to bool 'true' or 'false' (performance warning) - /wd4125 # decimal digit terminates octal escape sequence - /wd4100 # 'param' : unreferenced formal parameter - /wd4244 # 'argument' conversion from 'google::protobuf::int64' to 'int', possible loss of data - /wd4996 # 'argument' Using double parameter version instead of single parameter version of SetTotalBytesLimit(). The second parameter is ignored. - ) - if (NOT onnxruntime_DISABLE_EXCEPTIONS) - target_compile_options(onnx PRIVATE - /EHsc # exception handling - C++ may throw, extern "C" will not - ) - endif() - - target_compile_options(onnx_proto PRIVATE - /wd4244 # 'argument' conversion from 'google::protobuf::int64' to 'int', possible loss of data - ) - - set(onnx_static_library_flags - -IGNORE:4221 # LNK4221: This object file does not define any previously undefined public symbols, so it will not be used by any link operation that consumes this library - ) - set_target_properties(onnx PROPERTIES - STATIC_LIBRARY_FLAGS "${onnx_static_library_flags}") -else() - if(HAS_UNUSED_PARAMETER) - target_compile_options(onnx PRIVATE "-Wno-unused-parameter") - endif() - if(HAS_UNUSED_BUT_SET_VARIABLE) - target_compile_options(onnx PRIVATE "-Wno-unused-but-set-variable") - endif() -endif() diff --git a/cmake/external/onnxruntime_external_deps.cmake b/cmake/external/onnxruntime_external_deps.cmake index a811855395c1e..be0abc980bda6 100644 --- a/cmake/external/onnxruntime_external_deps.cmake +++ b/cmake/external/onnxruntime_external_deps.cmake @@ -1,3 +1,6 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + message(STATUS "Loading Dependencies URLs ...") include(external/helper_functions.cmake) @@ -17,7 +20,7 @@ foreach(ONNXRUNTIME_DEP IN LISTS ONNXRUNTIME_DEPS_LIST) if(ONNXRUNTIME_DEP_URL MATCHES "^https://") # Search a local mirror folder - string(REGEX REPLACE "^https://" "${REPO_ROOT}/mirror/" LOCAL_URL "${ONNXRUNTIME_DEP_URL}") + string(REGEX REPLACE "^https://" "${onnxruntime_CMAKE_DEPS_MIRROR_DIR}/" LOCAL_URL "${ONNXRUNTIME_DEP_URL}") if(EXISTS "${LOCAL_URL}") cmake_path(ABSOLUTE_PATH LOCAL_URL) @@ -35,10 +38,11 @@ include(external/abseil-cpp.cmake) set(RE2_BUILD_TESTING OFF CACHE BOOL "" FORCE) -FetchContent_Declare( +onnxruntime_fetchcontent_declare( re2 URL ${DEP_URL_re2} URL_HASH SHA1=${DEP_SHA1_re2} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES re2 ) onnxruntime_fetchcontent_makeavailable(re2) @@ -62,10 +66,11 @@ if (onnxruntime_BUILD_UNIT_TESTS) set(GTEST_HAS_ABSL ON CACHE BOOL "" FORCE) endif() # gtest and gmock - FetchContent_Declare( + onnxruntime_fetchcontent_declare( googletest URL ${DEP_URL_googletest} URL_HASH SHA1=${DEP_SHA1_googletest} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS 1.14.0...<2.0.0 NAMES GTest ) FetchContent_MakeAvailable(googletest) @@ -77,10 +82,11 @@ if (onnxruntime_BUILD_BENCHMARKS) # We will not need to install benchmark since we link it statically. set(BENCHMARK_ENABLE_INSTALL OFF CACHE BOOL "Disable benchmark install to avoid overwriting vendor install.") - FetchContent_Declare( + onnxruntime_fetchcontent_declare( google_benchmark URL ${DEP_URL_google_benchmark} URL_HASH SHA1=${DEP_SHA1_google_benchmark} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES benchmark ) onnxruntime_fetchcontent_makeavailable(google_benchmark) @@ -88,33 +94,24 @@ endif() if(onnxruntime_USE_MIMALLOC) - FetchContent_Declare( + add_definitions(-DUSE_MIMALLOC) + + set(MI_OVERRIDE OFF CACHE BOOL "" FORCE) + set(MI_BUILD_TESTS OFF CACHE BOOL "" FORCE) + set(MI_DEBUG_FULL OFF CACHE BOOL "" FORCE) + set(MI_BUILD_SHARED OFF CACHE BOOL "" FORCE) + onnxruntime_fetchcontent_declare( mimalloc URL ${DEP_URL_mimalloc} URL_HASH SHA1=${DEP_SHA1_mimalloc} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES mimalloc ) FetchContent_MakeAvailable(mimalloc) endif() -#Protobuf depends on utf8_range -FetchContent_Declare( - utf8_range - URL ${DEP_URL_utf8_range} - URL_HASH SHA1=${DEP_SHA1_utf8_range} - FIND_PACKAGE_ARGS NAMES utf8_range -) - -set(utf8_range_ENABLE_TESTS OFF CACHE BOOL "Build test suite" FORCE) -set(utf8_range_ENABLE_INSTALL OFF CACHE BOOL "Configure installation" FORCE) - -# The next line will generate an error message "fatal: not a git repository", but it is ok. It is from flatbuffers -onnxruntime_fetchcontent_makeavailable(utf8_range) -# protobuf's cmake/utf8_range.cmake has the following line -include_directories(${utf8_range_SOURCE_DIR}) - # Download a protoc binary from Internet if needed -if(NOT ONNX_CUSTOM_PROTOC_EXECUTABLE) +if(NOT ONNX_CUSTOM_PROTOC_EXECUTABLE AND NOT onnxruntime_USE_VCPKG) # This part of code is only for users' convenience. The code couldn't handle all cases. Users always can manually # download protoc from Protobuf's Github release page and pass the local path to the ONNX_CUSTOM_PROTOC_EXECUTABLE # variable. @@ -122,7 +119,7 @@ if(NOT ONNX_CUSTOM_PROTOC_EXECUTABLE) # Using CMAKE_CROSSCOMPILING is not recommended for Apple target devices. # https://cmake.org/cmake/help/v3.26/variable/CMAKE_CROSSCOMPILING.html # To keep it simple, just download and use the universal protoc binary for all Apple host builds. - FetchContent_Declare(protoc_binary URL ${DEP_URL_protoc_mac_universal} URL_HASH SHA1=${DEP_SHA1_protoc_mac_universal}) + onnxruntime_fetchcontent_declare(protoc_binary URL ${DEP_URL_protoc_mac_universal} URL_HASH SHA1=${DEP_SHA1_protoc_mac_universal} EXCLUDE_FROM_ALL) FetchContent_Populate(protoc_binary) if(protoc_binary_SOURCE_DIR) message(STATUS "Use prebuilt protoc") @@ -133,10 +130,13 @@ if(NOT ONNX_CUSTOM_PROTOC_EXECUTABLE) message(STATUS "CMAKE_HOST_SYSTEM_NAME: ${CMAKE_HOST_SYSTEM_NAME}") if(CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") if(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "AMD64") - FetchContent_Declare(protoc_binary URL ${DEP_URL_protoc_win64} URL_HASH SHA1=${DEP_SHA1_protoc_win64}) + onnxruntime_fetchcontent_declare(protoc_binary URL ${DEP_URL_protoc_win64} URL_HASH SHA1=${DEP_SHA1_protoc_win64} EXCLUDE_FROM_ALL) FetchContent_Populate(protoc_binary) elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "x86") - FetchContent_Declare(protoc_binary URL ${DEP_URL_protoc_win32} URL_HASH SHA1=${DEP_SHA1_protoc_win32}) + onnxruntime_fetchcontent_declare(protoc_binary URL ${DEP_URL_protoc_win32} URL_HASH SHA1=${DEP_SHA1_protoc_win32} EXCLUDE_FROM_ALL) + FetchContent_Populate(protoc_binary) + elseif(CMAKE_HOST_SYSTEM_PROCESSOR STREQUAL "ARM64") + onnxruntime_fetchcontent_declare(protoc_binary URL ${DEP_URL_protoc_win64} URL_HASH SHA1=${DEP_SHA1_protoc_win64} EXCLUDE_FROM_ALL) FetchContent_Populate(protoc_binary) endif() @@ -147,13 +147,13 @@ if(NOT ONNX_CUSTOM_PROTOC_EXECUTABLE) endif() elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL "Linux") if(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64)$") - FetchContent_Declare(protoc_binary URL ${DEP_URL_protoc_linux_x64} URL_HASH SHA1=${DEP_SHA1_protoc_linux_x64}) + onnxruntime_fetchcontent_declare(protoc_binary URL ${DEP_URL_protoc_linux_x64} URL_HASH SHA1=${DEP_SHA1_protoc_linux_x64} EXCLUDE_FROM_ALL) FetchContent_Populate(protoc_binary) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86?)$") - FetchContent_Declare(protoc_binary URL ${DEP_URL_protoc_linux_x86} URL_HASH SHA1=${DEP_SHA1_protoc_linux_x86}) + onnxruntime_fetchcontent_declare(protoc_binary URL ${DEP_URL_protoc_linux_x86} URL_HASH SHA1=${DEP_SHA1_protoc_linux_x86} EXCLUDE_FROM_ALL) FetchContent_Populate(protoc_binary) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^aarch64.*") - FetchContent_Declare(protoc_binary URL ${DEP_URL_protoc_linux_aarch64} URL_HASH SHA1=${DEP_SHA1_protoc_linux_aarch64}) + onnxruntime_fetchcontent_declare(protoc_binary URL ${DEP_URL_protoc_linux_aarch64} URL_HASH SHA1=${DEP_SHA1_protoc_linux_aarch64} EXCLUDE_FROM_ALL) FetchContent_Populate(protoc_binary) endif() @@ -185,17 +185,20 @@ endif() # for cross-compiling #2. if ONNX_CUSTOM_PROTOC_EXECUTABLE is not set, Compile everything(including protoc) from source code. if(Patch_FOUND) - set(ONNXRUNTIME_PROTOBUF_PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/protobuf/protobuf_cmake.patch) + set(ONNXRUNTIME_PROTOBUF_PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/protobuf/protobuf_cmake.patch && + ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/protobuf/protobuf_android_log.patch && + ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/protobuf/protobuf_s390x.patch) else() set(ONNXRUNTIME_PROTOBUF_PATCH_COMMAND "") endif() #Protobuf depends on absl and utf8_range -FetchContent_Declare( +onnxruntime_fetchcontent_declare( Protobuf URL ${DEP_URL_protobuf} URL_HASH SHA1=${DEP_SHA1_protobuf} PATCH_COMMAND ${ONNXRUNTIME_PROTOBUF_PATCH_COMMAND} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES Protobuf protobuf ) @@ -220,13 +223,8 @@ include(protobuf_function) onnxruntime_fetchcontent_makeavailable(Protobuf) if(Protobuf_FOUND) - message(STATUS "Protobuf version: ${Protobuf_VERSION}") + message(STATUS "Using protobuf from find_package(or vcpkg). Protobuf version: ${Protobuf_VERSION}") else() - if(protobuf_SOURCE_DIR) - if(onnxruntime_USE_WEBGPU) - set(DAWN_PROTOBUF_DIR ${protobuf_SOURCE_DIR}) - endif() - endif() # Adjust warning flags if (TARGET libprotoc) if (NOT MSVC) @@ -271,36 +269,45 @@ endif() set(ENABLE_DATE_TESTING OFF CACHE BOOL "" FORCE) set(USE_SYSTEM_TZ_DB ON CACHE BOOL "" FORCE) -FetchContent_Declare( +onnxruntime_fetchcontent_declare( date URL ${DEP_URL_date} URL_HASH SHA1=${DEP_SHA1_date} + EXCLUDE_FROM_ALL + PATCH_COMMAND + ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/date/date.patch FIND_PACKAGE_ARGS 3...<4 NAMES date ) onnxruntime_fetchcontent_makeavailable(date) -FetchContent_Declare( - mp11 - URL ${DEP_URL_mp11} - URL_HASH SHA1=${DEP_SHA1_mp11} - FIND_PACKAGE_ARGS NAMES Boost -) -onnxruntime_fetchcontent_makeavailable(mp11) if(NOT TARGET Boost::mp11) if(onnxruntime_USE_VCPKG) - find_package(Boost REQUIRED) + find_package(Boost REQUIRED) + message(STATUS "Aliasing Boost::headers to Boost::mp11") + add_library(Boost::mp11 ALIAS Boost::headers) + else() + onnxruntime_fetchcontent_declare( + mp11 + URL ${DEP_URL_mp11} + EXCLUDE_FROM_ALL + FIND_PACKAGE_ARGS NAMES Boost + ) + FetchContent_Populate(mp11) + if(NOT TARGET Boost::mp11) + add_library(Boost::mp11 IMPORTED INTERFACE) + target_include_directories(Boost::mp11 INTERFACE $) + endif() endif() - message(STATUS "Aliasing Boost::headers to Boost::mp11") - add_library(Boost::mp11 ALIAS Boost::headers) endif() set(JSON_BuildTests OFF CACHE INTERNAL "") -set(JSON_Install OFF CACHE INTERNAL "") +set(JSON_Install ON CACHE INTERNAL "") -FetchContent_Declare( +onnxruntime_fetchcontent_declare( nlohmann_json URL ${DEP_URL_json} URL_HASH SHA1=${DEP_SHA1_json} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS 3.10 NAMES nlohmann_json ) onnxruntime_fetchcontent_makeavailable(nlohmann_json) @@ -309,35 +316,32 @@ onnxruntime_fetchcontent_makeavailable(nlohmann_json) if (onnxruntime_ENABLE_CPUINFO) # Adding pytorch CPU info library # TODO!! need a better way to find out the supported architectures - list(LENGTH CMAKE_OSX_ARCHITECTURES CMAKE_OSX_ARCHITECTURES_LEN) - if (APPLE) - if (CMAKE_OSX_ARCHITECTURES_LEN LESS_EQUAL 1) + set(CPUINFO_SUPPORTED FALSE) + if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + # if xnnpack is enabled in a wasm build it needs clog from cpuinfo, but we won't internally use cpuinfo. + if (onnxruntime_USE_XNNPACK) set(CPUINFO_SUPPORTED TRUE) - elseif (onnxruntime_BUILD_APPLE_FRAMEWORK) - # We stitch multiple static libraries together when onnxruntime_BUILD_APPLE_FRAMEWORK is true, - # but that would not work for universal static libraries - message(FATAL_ERROR "universal binary is not supported for apple framework") endif() - else() - # if xnnpack is enabled in a wasm build it needs clog from cpuinfo, but we won't internally use cpuinfo - # so we don't set CPUINFO_SUPPORTED in the CXX flags below. - if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND NOT onnxruntime_USE_XNNPACK) - set(CPUINFO_SUPPORTED FALSE) - else() + elseif (APPLE) + list(LENGTH CMAKE_OSX_ARCHITECTURES CMAKE_OSX_ARCHITECTURES_LEN) + if (CMAKE_OSX_ARCHITECTURES_LEN LESS_EQUAL 1) set(CPUINFO_SUPPORTED TRUE) + else() + message(WARNING "cpuinfo is not supported when CMAKE_OSX_ARCHITECTURES has more than one value.") endif() - if (WIN32) + elseif (WIN32) + set(CPUINFO_SUPPORTED TRUE) + else() + if (onnxruntime_target_platform MATCHES "^(i[3-6]86|AMD64|x86(_64)?|armv[5-8].*|aarch64|arm64)$") set(CPUINFO_SUPPORTED TRUE) - elseif (NOT ${onnxruntime_target_platform} MATCHES "^(i[3-6]86|AMD64|x86(_64)?|armv[5-8].*|aarch64|arm64)$") - message(WARNING - "Target processor architecture \"${onnxruntime_target_platform}\" is not supported in cpuinfo. " - "cpuinfo not included." - ) - set(CPUINFO_SUPPORTED FALSE) + else() + message(WARNING "Target processor architecture \"${onnxruntime_target_platform}\" is not supported in cpuinfo.") endif() endif() -else() - set(CPUINFO_SUPPORTED FALSE) + + if(NOT CPUINFO_SUPPORTED) + message(WARNING "onnxruntime_ENABLE_CPUINFO was set but cpuinfo is not supported.") + endif() endif() if (CPUINFO_SUPPORTED) @@ -348,31 +352,50 @@ if (CPUINFO_SUPPORTED) # if this is a wasm build with xnnpack (only type of wasm build where cpuinfo is involved) # we do not use cpuinfo in ORT code, so don't define CPUINFO_SUPPORTED. - if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") - string(APPEND CMAKE_CXX_FLAGS " -DCPUINFO_SUPPORTED") + if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND onnxruntime_USE_XNNPACK) + else() + add_compile_definitions(CPUINFO_SUPPORTED) endif() - set(CPUINFO_BUILD_TOOLS OFF CACHE INTERNAL "") set(CPUINFO_BUILD_UNIT_TESTS OFF CACHE INTERNAL "") set(CPUINFO_BUILD_MOCK_TESTS OFF CACHE INTERNAL "") set(CPUINFO_BUILD_BENCHMARKS OFF CACHE INTERNAL "") if (onnxruntime_target_platform STREQUAL "ARM64EC" OR onnxruntime_target_platform STREQUAL "ARM64") - message(STATUS "Applying a patch for Windows ARM64/ARM64EC in cpuinfo") - FetchContent_Declare( - pytorch_cpuinfo - URL ${DEP_URL_pytorch_cpuinfo} - URL_HASH SHA1=${DEP_SHA1_pytorch_cpuinfo} - PATCH_COMMAND ${Patch_EXECUTABLE} -p1 < ${PROJECT_SOURCE_DIR}/patches/cpuinfo/9bb12d342fd9479679d505d93a478a6f9cd50a47.patch - FIND_PACKAGE_ARGS NAMES cpuinfo - ) + message(STATUS "Applying patches for Windows ARM64/ARM64EC in cpuinfo") + onnxruntime_fetchcontent_declare( + pytorch_cpuinfo + URL ${DEP_URL_pytorch_cpuinfo} + URL_HASH SHA1=${DEP_SHA1_pytorch_cpuinfo} + EXCLUDE_FROM_ALL + PATCH_COMMAND + ${Patch_EXECUTABLE} -p1 < ${PROJECT_SOURCE_DIR}/patches/cpuinfo/patch_cpuinfo_h_for_arm64ec.patch && + # https://github.com/pytorch/cpuinfo/pull/324 + ${Patch_EXECUTABLE} -p1 < ${PROJECT_SOURCE_DIR}/patches/cpuinfo/patch_vcpkg_arm64ec_support.patch && + # https://github.com/pytorch/cpuinfo/pull/348 + ${Patch_EXECUTABLE} -p1 < ${PROJECT_SOURCE_DIR}/patches/cpuinfo/win_arm_fp16_detection_fallback.patch + FIND_PACKAGE_ARGS NAMES cpuinfo + ) + elseif(CMAKE_SYSTEM_NAME STREQUAL "Linux") + message(STATUS "Applying sysfs fallback patch for cpuinfo on Linux") + onnxruntime_fetchcontent_declare( + pytorch_cpuinfo + URL ${DEP_URL_pytorch_cpuinfo} + URL_HASH SHA1=${DEP_SHA1_pytorch_cpuinfo} + EXCLUDE_FROM_ALL + PATCH_COMMAND + # https://github.com/microsoft/onnxruntime/issues/10038 + ${Patch_EXECUTABLE} -p1 < ${PROJECT_SOURCE_DIR}/patches/cpuinfo/fix_missing_sysfs_fallback.patch + FIND_PACKAGE_ARGS NAMES cpuinfo + ) else() - FetchContent_Declare( - pytorch_cpuinfo - URL ${DEP_URL_pytorch_cpuinfo} - URL_HASH SHA1=${DEP_SHA1_pytorch_cpuinfo} - FIND_PACKAGE_ARGS NAMES cpuinfo - ) + onnxruntime_fetchcontent_declare( + pytorch_cpuinfo + URL ${DEP_URL_pytorch_cpuinfo} + URL_HASH SHA1=${DEP_SHA1_pytorch_cpuinfo} + EXCLUDE_FROM_ALL + FIND_PACKAGE_ARGS NAMES cpuinfo + ) endif() set(ONNXRUNTIME_CPUINFO_PROJ pytorch_cpuinfo) onnxruntime_fetchcontent_makeavailable(${ONNXRUNTIME_CPUINFO_PROJ}) @@ -382,42 +405,21 @@ if (CPUINFO_SUPPORTED) endif() endif() -# xnnpack depends on clog -# Android build should use the system's log library instead of clog -if ((CPUINFO_SUPPORTED OR onnxruntime_USE_XNNPACK) AND NOT ANDROID) - set(CLOG_BUILD_TESTS OFF CACHE BOOL "" FORCE) - FetchContent_Declare( - pytorch_clog - URL ${DEP_URL_pytorch_cpuinfo} - URL_HASH SHA1=${DEP_SHA1_pytorch_cpuinfo} - SOURCE_SUBDIR deps/clog - FIND_PACKAGE_ARGS NAMES cpuinfo - ) - set(ONNXRUNTIME_CLOG_PROJ pytorch_clog) - onnxruntime_fetchcontent_makeavailable(${ONNXRUNTIME_CLOG_PROJ}) - set(ONNXRUNTIME_CLOG_TARGET_NAME clog) - # if cpuinfo is from find_package, use it with imported name - if(TARGET cpuinfo::clog) - set(ONNXRUNTIME_CLOG_TARGET_NAME cpuinfo::clog) - elseif(onnxruntime_USE_VCPKG) - # however, later cpuinfo versions may not contain clog. use cpuinfo - set(ONNXRUNTIME_CLOG_TARGET_NAME cpuinfo::cpuinfo) - endif() -endif() - if(onnxruntime_USE_CUDA) - FetchContent_Declare( + onnxruntime_fetchcontent_declare( GSL URL ${DEP_URL_microsoft_gsl} URL_HASH SHA1=${DEP_SHA1_microsoft_gsl} PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/gsl/1064.patch + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS 4.0 NAMES Microsoft.GSL ) else() - FetchContent_Declare( + onnxruntime_fetchcontent_declare( GSL URL ${DEP_URL_microsoft_gsl} URL_HASH SHA1=${DEP_SHA1_microsoft_gsl} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS 4.0 NAMES Microsoft.GSL ) endif() @@ -425,29 +427,40 @@ set(GSL_TARGET "Microsoft.GSL::GSL") set(GSL_INCLUDE_DIR "$") onnxruntime_fetchcontent_makeavailable(GSL) +if (NOT GSL_FOUND AND NOT onnxruntime_BUILD_SHARED_LIB) + install(TARGETS GSL EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() + find_path(safeint_SOURCE_DIR NAMES "SafeInt.hpp") if(NOT safeint_SOURCE_DIR) unset(safeint_SOURCE_DIR) - FetchContent_Declare( + onnxruntime_fetchcontent_declare( safeint URL ${DEP_URL_safeint} URL_HASH SHA1=${DEP_SHA1_safeint} + EXCLUDE_FROM_ALL ) # use fetch content rather than makeavailable because safeint only includes unconditional test targets FetchContent_Populate(safeint) endif() -add_library(safeint_interface INTERFACE) +add_library(safeint_interface IMPORTED INTERFACE) target_include_directories(safeint_interface INTERFACE ${safeint_SOURCE_DIR}) # Flatbuffers +if(onnxruntime_USE_VCPKG) + find_package(flatbuffers REQUIRED) +else() # We do not need to build flatc for iOS or Android Cross Compile -if (CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android" OR CMAKE_SYSTEM_NAME STREQUAL "Emscripten") +if (CMAKE_SYSTEM_NAME STREQUAL "iOS" OR CMAKE_SYSTEM_NAME STREQUAL "tvOS" OR CMAKE_SYSTEM_NAME STREQUAL "visionOS" OR CMAKE_SYSTEM_NAME STREQUAL "Android" OR CMAKE_SYSTEM_NAME STREQUAL "Emscripten") set(FLATBUFFERS_BUILD_FLATC OFF CACHE BOOL "FLATBUFFERS_BUILD_FLATC" FORCE) endif() set(FLATBUFFERS_BUILD_TESTS OFF CACHE BOOL "FLATBUFFERS_BUILD_TESTS" FORCE) -set(FLATBUFFERS_INSTALL OFF CACHE BOOL "FLATBUFFERS_INSTALL" FORCE) +set(FLATBUFFERS_INSTALL ON CACHE BOOL "FLATBUFFERS_INSTALL" FORCE) set(FLATBUFFERS_BUILD_FLATHASH OFF CACHE BOOL "FLATBUFFERS_BUILD_FLATHASH" FORCE) set(FLATBUFFERS_BUILD_FLATLIB ON CACHE BOOL "FLATBUFFERS_BUILD_FLATLIB" FORCE) if(Patch_FOUND) @@ -457,11 +470,12 @@ else() endif() #flatbuffers 1.11.0 does not have flatbuffers::IsOutRange, therefore we require 1.12.0+ -FetchContent_Declare( +onnxruntime_fetchcontent_declare( flatbuffers URL ${DEP_URL_flatbuffers} URL_HASH SHA1=${DEP_SHA1_flatbuffers} PATCH_COMMAND ${ONNXRUNTIME_FLATBUFFERS_PATCH_COMMAND} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS 23.5.9 NAMES Flatbuffers flatbuffers ) @@ -491,6 +505,7 @@ namespace std { using ::getenv; } endif() endif() endif() +endif() # ONNX if (NOT onnxruntime_USE_FULL_PROTOBUF) @@ -505,18 +520,31 @@ else() set(ONNXRUNTIME_ONNX_PATCH_COMMAND "") endif() -FetchContent_Declare( +if(onnxruntime_ENABLE_PYTHON) + if(onnxruntime_USE_VCPKG) + find_package(pybind11 CONFIG REQUIRED) + else() + include(pybind11) + endif() +if(TARGET pybind11::module) + message("Setting pybind11_lib") + set(pybind11_lib pybind11::module) +else() + message("Setting pybind11_dep") + set(pybind11_dep pybind11::pybind11) +endif() + +endif() +onnxruntime_fetchcontent_declare( onnx URL ${DEP_URL_onnx} URL_HASH SHA1=${DEP_SHA1_onnx} PATCH_COMMAND ${ONNXRUNTIME_ONNX_PATCH_COMMAND} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES ONNX onnx ) -if (NOT onnxruntime_MINIMAL_BUILD) - onnxruntime_fetchcontent_makeavailable(onnx) -else() - include(onnx_minimal) -endif() + +onnxruntime_fetchcontent_makeavailable(onnx) if(TARGET ONNX::onnx AND NOT TARGET onnx) message(STATUS "Aliasing ONNX::onnx to onnx") @@ -526,14 +554,19 @@ if(TARGET ONNX::onnx_proto AND NOT TARGET onnx_proto) message(STATUS "Aliasing ONNX::onnx_proto to onnx_proto") add_library(onnx_proto ALIAS ONNX::onnx_proto) endif() - -include(external/eigen.cmake) - if(onnxruntime_USE_VCPKG) - find_package(wil CONFIG REQUIRED) - set(WIL_TARGET "WIL::WIL") + find_package(Eigen3 CONFIG REQUIRED) else() - include(wil) # FetchContent + include(external/eigen.cmake) +endif() + +if(WIN32) + if(onnxruntime_USE_VCPKG) + find_package(wil CONFIG REQUIRED) + set(WIL_TARGET "WIL::WIL") + else() + include(wil) # FetchContent + endif() endif() # XNNPACK EP @@ -542,23 +575,27 @@ if (onnxruntime_USE_XNNPACK) message(FATAL_ERROR "XNNPACK EP requires the internal NHWC contrib ops to be available " "but onnxruntime_DISABLE_CONTRIB_OPS is ON") endif() - include(xnnpack) -endif() - -if (onnxruntime_USE_MIMALLOC) - add_definitions(-DUSE_MIMALLOC) - - set(MI_OVERRIDE OFF CACHE BOOL "" FORCE) - set(MI_BUILD_TESTS OFF CACHE BOOL "" FORCE) - set(MI_DEBUG_FULL OFF CACHE BOOL "" FORCE) - set(MI_BUILD_SHARED OFF CACHE BOOL "" FORCE) - onnxruntime_fetchcontent_makeavailable(mimalloc) + if(onnxruntime_USE_VCPKG) + FIND_PATH(XNNPACK_HDR xnnpack.h PATH_SUFFIXES include) + IF(NOT XNNPACK_HDR) + MESSAGE(FATAL_ERROR "Cannot find xnnpack") + ENDIF() + ADD_LIBRARY(xnnpack STATIC IMPORTED) + find_library(xnnpack_LIBRARY NAMES XNNPACK) + find_library(microkernels_prod_LIBRARY NAMES xnnpack-microkernels-prod) + find_package(unofficial-pthreadpool CONFIG REQUIRED) + + target_include_directories(xnnpack INTERFACE "${XNNPACK_HDR}") + set(XNNPACK_INCLUDE_DIR ${XNNPACK_DIR}/include) + set(onnxruntime_EXTERNAL_LIBRARIES_XNNPACK ${xnnpack_LIBRARY} ${microkernels_prod_LIBRARY} unofficial::pthreadpool unofficial::pthreadpool_interface) + else() + include(xnnpack) + endif() endif() set(onnxruntime_EXTERNAL_LIBRARIES ${onnxruntime_EXTERNAL_LIBRARIES_XNNPACK} ${WIL_TARGET} nlohmann_json::nlohmann_json onnx onnx_proto ${PROTOBUF_LIB} re2::re2 Boost::mp11 safeint_interface - flatbuffers::flatbuffers ${GSL_TARGET} ${ABSEIL_LIBS} date::date - ${ONNXRUNTIME_CLOG_TARGET_NAME}) + flatbuffers::flatbuffers ${GSL_TARGET} ${ABSEIL_LIBS} date::date Eigen3::Eigen) # The source code of onnx_proto is generated, we must build this lib first before starting to compile the other source code that uses ONNX protobuf types. # The other libs do not have the problem. All the sources are already there. We can compile them in any order. @@ -571,31 +608,27 @@ if(NOT (onnx_FOUND OR ONNX_FOUND)) # building ONNX from source endif() endif() -if (onnxruntime_RUN_ONNX_TESTS) - add_definitions(-DORT_RUN_EXTERNAL_ONNX_TESTS) -endif() - - if(onnxruntime_ENABLE_DLPACK) message(STATUS "dlpack is enabled.") - FetchContent_Declare( + + onnxruntime_fetchcontent_declare( dlpack URL ${DEP_URL_dlpack} URL_HASH SHA1=${DEP_SHA1_dlpack} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES dlpack ) - # We can't use onnxruntime_fetchcontent_makeavailable since some part of the the dlpack code is Linux only. - # For example, dlpackcpp.h uses posix_memalign. - FetchContent_Populate(dlpack) + onnxruntime_fetchcontent_makeavailable(dlpack) endif() if(onnxruntime_ENABLE_TRAINING OR (onnxruntime_ENABLE_TRAINING_APIS AND onnxruntime_BUILD_UNIT_TESTS)) # Once code under orttraining/orttraining/models dir is removed "onnxruntime_ENABLE_TRAINING" should be removed from # this conditional - FetchContent_Declare( + onnxruntime_fetchcontent_declare( cxxopts URL ${DEP_URL_cxxopts} URL_HASH SHA1=${DEP_SHA1_cxxopts} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES cxxopts ) set(CXXOPTS_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE) @@ -603,120 +636,186 @@ if(onnxruntime_ENABLE_TRAINING OR (onnxruntime_ENABLE_TRAINING_APIS AND onnxrunt onnxruntime_fetchcontent_makeavailable(cxxopts) endif() -if (onnxruntime_USE_COREML) - FetchContent_Declare( - coremltools - URL ${DEP_URL_coremltools} - URL_HASH SHA1=${DEP_SHA1_coremltools} - PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/coremltools/crossplatformbuild.patch - ) - # we don't build directly so use Populate. selected files are built from onnxruntime_providers_coreml.cmake - FetchContent_Populate(coremltools) -endif() if (onnxruntime_USE_WEBGPU) - if (onnxruntime_CUSTOM_DAWN_SRC_PATH) - # use the custom dawn source path if provided - # - # specified as: - # build.py --use_webgpu --cmake_extra_defines "onnxruntime_CUSTOM_DAWN_SRC_PATH=" - FetchContent_Declare( - dawn - SOURCE_DIR ${onnxruntime_CUSTOM_DAWN_SRC_PATH} - ) + # TODO: the following code is used to disable building Dawn using vcpkg temporarily + # until we figure out how to resolve the packaging pipeline failures + # + # if (onnxruntime_USE_VCPKG AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + if (FALSE) + # vcpkg does not support Emscripten yet + find_package(dawn REQUIRED) else() - FetchContent_Declare( - dawn - URL ${DEP_URL_dawn} - URL_HASH SHA1=${DEP_SHA1_dawn} - # All previous patches are merged into the upstream dawn project. We don't need to apply any patches right now. - # if we need to apply patches in the future, we can uncomment the following line. - # PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/dawn/dawn.patch - ) - endif() - - set(DAWN_BUILD_SAMPLES OFF CACHE BOOL "" FORCE) - set(DAWN_ENABLE_NULL OFF CACHE BOOL "" FORCE) - set(DAWN_FETCH_DEPENDENCIES ON CACHE BOOL "" FORCE) - - if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") - set(DAWN_EMSCRIPTEN_TOOLCHAIN "${REPO_ROOT}/cmake/external/emsdk/upstream/emscripten" CACHE STRING "" FORCE) - - # Add the missing files from the emsdk installation # - # For a "standard" emscripten build, the folder "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/maint/" is not used. This is the - # reason why EMSDK installation does not include it. - # However, currently the WebGPU support in Emscripten is still being developed and the Dawn project is maintaining - # a fork of the Emscripten toolchain. As an extra build step, Dawn needs to generate some files using the file - # "${DAWN_EMSCRIPTEN_TOOLCHAIN}/tools/maint/gen_struct_info.py" from emscripten, which is missing in the emscripten - # installed by emsdk. + # Please keep the following in sync with cmake/vcpkg-ports/dawn/portfile.cmake # - # We keep a copy of the missing file(s) in ${PROJECT_SOURCE_DIR}/patches/emscripten/, and now we extract them to the - # emscripten toolchain folder. - execute_process(COMMAND ${CMAKE_COMMAND} -E tar x "${PROJECT_SOURCE_DIR}/patches/emscripten/patch_3.1.74.tgz" - WORKING_DIRECTORY ${DAWN_EMSCRIPTEN_TOOLCHAIN}) - else() - if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) - set(DAWN_BUILD_MONOLITHIC_LIBRARY ON CACHE BOOL "" FORCE) - set(DAWN_ENABLE_INSTALL ON CACHE BOOL "" FORCE) - - if (onnxruntime_USE_EXTERNAL_DAWN) - message(FATAL_ERROR "onnxruntime_USE_EXTERNAL_DAWN and onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY cannot be enabled at the same time.") + set(DAWN_BUILD_SAMPLES OFF CACHE BOOL "" FORCE) + set(DAWN_ENABLE_NULL OFF CACHE BOOL "" FORCE) + set(DAWN_BUILD_PROTOBUF OFF CACHE BOOL "" FORCE) + set(DAWN_BUILD_TESTS OFF CACHE BOOL "" FORCE) + if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + if (onnxruntime_BUILD_DAWN_SHARED_LIBRARY) + set(DAWN_BUILD_MONOLITHIC_LIBRARY SHARED CACHE BOOL "" FORCE) + set(DAWN_ENABLE_INSTALL ON CACHE BOOL "" FORCE) + + if (onnxruntime_USE_EXTERNAL_DAWN) + message(FATAL_ERROR "onnxruntime_USE_EXTERNAL_DAWN and onnxruntime_BUILD_DAWN_SHARED_LIBRARY cannot be enabled at the same time.") + endif() + else() + # use dawn::dawn_native and dawn::dawn_proc instead of the monolithic dawn::webgpu_dawn to minimize binary size + set(DAWN_BUILD_MONOLITHIC_LIBRARY OFF CACHE BOOL "" FORCE) + set(DAWN_ENABLE_INSTALL OFF CACHE BOOL "" FORCE) + + # use the same protobuf/abseil for ORT and Dawn when static linking + if(abseil_cpp_SOURCE_DIR) + set(DAWN_ABSEIL_DIR ${abseil_cpp_SOURCE_DIR}) + endif() + if(protobuf_SOURCE_DIR) + set(DAWN_PROTOBUF_DIR ${protobuf_SOURCE_DIR}) + endif() endif() - else() - # use dawn::dawn_native and dawn::dawn_proc instead of the monolithic dawn::webgpu_dawn to minimize binary size - set(DAWN_BUILD_MONOLITHIC_LIBRARY OFF CACHE BOOL "" FORCE) - set(DAWN_ENABLE_INSTALL OFF CACHE BOOL "" FORCE) - endif() - # disable things we don't use - set(DAWN_DXC_ENABLE_ASSERTS_IN_NDEBUG OFF) - set(DAWN_ENABLE_DESKTOP_GL OFF CACHE BOOL "" FORCE) - set(DAWN_ENABLE_OPENGLES OFF CACHE BOOL "" FORCE) - set(DAWN_SUPPORTS_GLFW_FOR_WINDOWING OFF CACHE BOOL "" FORCE) - set(DAWN_USE_GLFW OFF CACHE BOOL "" FORCE) - set(DAWN_USE_WINDOWS_UI OFF CACHE BOOL "" FORCE) - set(DAWN_USE_X11 OFF CACHE BOOL "" FORCE) - - set(TINT_BUILD_TESTS OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_CMD_TOOLS OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_GLSL_WRITER OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_GLSL_VALIDATOR OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_IR_BINARY OFF CACHE BOOL "" FORCE) - set(TINT_BUILD_SPV_READER OFF CACHE BOOL "" FORCE) # don't need. disabling is a large binary size saving - set(TINT_BUILD_WGSL_WRITER ON CACHE BOOL "" FORCE) # needed to create cache key. runtime error if not enabled. - - # SPIR-V validation shouldn't be required given we're using Tint to create the SPIR-V. - set(DAWN_ENABLE_SPIRV_VALIDATION OFF CACHE BOOL "" FORCE) - - if (WIN32) - # building this requires the HLSL writer to be enabled in Tint. TBD if that we need either of these to be ON. - set(DAWN_USE_BUILT_DXC ON CACHE BOOL "" FORCE) - set(TINT_BUILD_HLSL_WRITER ON CACHE BOOL "" FORCE) - - if ((NOT onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) AND (NOT onnxruntime_ENABLE_DAWN_BACKEND_D3D12)) - message(FATAL_ERROR "At least one of onnxruntime_ENABLE_DAWN_BACKEND_VULKAN or onnxruntime_ENABLE_DAWN_BACKEND_D3D12 must be enabled when using Dawn on Windows.") - endif() - if (onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) - set(DAWN_ENABLE_VULKAN ON CACHE BOOL "" FORCE) - set(TINT_BUILD_SPV_WRITER ON CACHE BOOL "" FORCE) + if (onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP) + set(DAWN_ENABLE_DESKTOP_GL ON CACHE BOOL "" FORCE) + set(DAWN_ENABLE_OPENGLES ON CACHE BOOL "" FORCE) + set(DAWN_SUPPORTS_GLFW_FOR_WINDOWING ON CACHE BOOL "" FORCE) + set(DAWN_USE_GLFW ON CACHE BOOL "" FORCE) + set(DAWN_USE_WINDOWS_UI ON CACHE BOOL "" FORCE) + set(TINT_BUILD_GLSL_WRITER ON CACHE BOOL "" FORCE) + set(TINT_BUILD_GLSL_VALIDATOR ON CACHE BOOL "" FORCE) else() - set(DAWN_ENABLE_VULKAN OFF CACHE BOOL "" FORCE) + set(DAWN_ENABLE_DESKTOP_GL OFF CACHE BOOL "" FORCE) + set(DAWN_ENABLE_OPENGLES OFF CACHE BOOL "" FORCE) + set(DAWN_SUPPORTS_GLFW_FOR_WINDOWING OFF CACHE BOOL "" FORCE) + set(DAWN_USE_GLFW OFF CACHE BOOL "" FORCE) + set(DAWN_USE_WINDOWS_UI OFF CACHE BOOL "" FORCE) + set(TINT_BUILD_GLSL_WRITER OFF CACHE BOOL "" FORCE) + set(TINT_BUILD_GLSL_VALIDATOR OFF CACHE BOOL "" FORCE) endif() - if (onnxruntime_ENABLE_DAWN_BACKEND_D3D12) - set(DAWN_ENABLE_D3D12 ON CACHE BOOL "" FORCE) - else() - set(DAWN_ENABLE_D3D12 OFF CACHE BOOL "" FORCE) + + # disable things we don't use + set(DAWN_DXC_ENABLE_ASSERTS_IN_NDEBUG OFF) + set(DAWN_USE_X11 OFF CACHE BOOL "" FORCE) + + set(TINT_BUILD_TESTS OFF CACHE BOOL "" FORCE) + set(TINT_BUILD_CMD_TOOLS OFF CACHE BOOL "" FORCE) + set(TINT_BUILD_IR_BINARY OFF CACHE BOOL "" FORCE) + set(TINT_BUILD_SPV_READER OFF CACHE BOOL "" FORCE) # don't need. disabling is a large binary size saving + set(TINT_BUILD_WGSL_WRITER ON CACHE BOOL "" FORCE) # needed to create cache key. runtime error if not enabled. + + # SPIR-V validation shouldn't be required given we're using Tint to create the SPIR-V. + set(DAWN_ENABLE_SPIRV_VALIDATION OFF CACHE BOOL "" FORCE) + + if (WIN32) + # building this requires the HLSL writer to be enabled in Tint. TBD if that we need either of these to be ON. + set(DAWN_USE_BUILT_DXC ON CACHE BOOL "" FORCE) + set(TINT_BUILD_HLSL_WRITER ON CACHE BOOL "" FORCE) + + if ((NOT onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) AND (NOT onnxruntime_ENABLE_DAWN_BACKEND_D3D12)) + message(FATAL_ERROR "At least one of onnxruntime_ENABLE_DAWN_BACKEND_VULKAN or onnxruntime_ENABLE_DAWN_BACKEND_D3D12 must be enabled when using Dawn on Windows.") + endif() + if (onnxruntime_ENABLE_DAWN_BACKEND_VULKAN) + set(DAWN_ENABLE_VULKAN ON CACHE BOOL "" FORCE) + set(TINT_BUILD_SPV_WRITER ON CACHE BOOL "" FORCE) + else() + set(DAWN_ENABLE_VULKAN OFF CACHE BOOL "" FORCE) + endif() + if (onnxruntime_ENABLE_DAWN_BACKEND_D3D12) + set(DAWN_ENABLE_D3D12 ON CACHE BOOL "" FORCE) + else() + set(DAWN_ENABLE_D3D12 OFF CACHE BOOL "" FORCE) + endif() + # We are currently always using the D3D12 backend. + set(DAWN_ENABLE_D3D11 OFF CACHE BOOL "" FORCE) endif() - # We are currently always using the D3D12 backend. - set(DAWN_ENABLE_D3D11 OFF CACHE BOOL "" FORCE) endif() - endif() - onnxruntime_fetchcontent_makeavailable(dawn) + if (onnxruntime_CUSTOM_DAWN_SRC_PATH) + set(DAWN_FETCH_DEPENDENCIES OFF CACHE BOOL "" FORCE) + # use the custom dawn source path if provided + # + # specified as: + # build.py --use_webgpu --cmake_extra_defines "onnxruntime_CUSTOM_DAWN_SRC_PATH=" + onnxruntime_fetchcontent_declare( + dawn + SOURCE_DIR ${onnxruntime_CUSTOM_DAWN_SRC_PATH} + EXCLUDE_FROM_ALL + ) + else() + set(DAWN_FETCH_DEPENDENCIES ON CACHE BOOL "" FORCE) + set(ONNXRUNTIME_Dawn_PATCH_COMMAND + # The dawn_destroy_buffer_on_destructor.patch contains the following changes: + # + # - (private) Allow WGPUBufferImpl class to destroy the buffer in the destructor + # In native implementation, wgpuBufferRelease will trigger the buffer destroy (if refcount decreased to 0). But + # in emwgpu implementation, the buffer destroy won't happen. This change adds a destructor to the buffer class + # to destroy the buffer when the refcount is 0 for non-external buffers. + # + ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/dawn/dawn_destroy_buffer_on_destructor.patch && + + # The dawn_binskim.patch contains the following changes: + # + # - (private) Fulfill the BinSkim requirements + # Some build warnings are not allowed to be disabled in project level. + ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/dawn/dawn_binskim.patch && + + # The safari_polyfill.patch contains the following changes: + # + # - (private) Fix compatibility issues with Safari. Contains the following changes: + # - Polyfill for `device.AdapterInfo` (returns `undefined` in Safari v26.0) + # + ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/dawn/safari_polyfill.patch && + + # The dawn_device_lost_keepalive.patch contains the following changes: + # + # - (private) Fix premature ABORT when device.lost fires in callUserCallback + # The device.lost handler was wrapped in callUserCallback without runtimeKeepalivePush/Pop, + # causing maybeExit() to trigger _exit(0) and set ABORT=true when runtimeKeepaliveCounter + # was 0. This silently dropped all subsequent WebGPU callbacks (e.g. requestAdapter), + # breaking session re-creation after device destruction. + # + ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/dawn/dawn_device_lost_keepalive.patch && + + # The dawn_dxc_output_dir.patch contains the following changes: + # + # - (private) Fix DXC output directory for RelWithDebInfo and MinSizeRel configs + # Dawn only overrides the DXC output directory for Debug and Release configs. This causes + # build failures when using multi-config generators (like Visual Studio) with RelWithDebInfo + # because dxcompiler.dll ends up in the default output path instead of CMAKE_BINARY_DIR/$, + # and the copy_dxil_dll target copies dxil.dll to a different location. + # + ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/dawn/dawn_dxc_output_dir.patch && + + # The dawn_buffer_fix_injection.patch contains the following changes: + # + # - (private) Fix importJsBuffer calling wrong WGPUBufferImpl constructor + # Without this patch, importJsBuffer calls emwgpuCreateBuffer which invokes the + # (source, mappedAtCreation=false) constructor instead of the injection constructor + # tagged with kImportedFromJS. This patch adjusts the injection constructor signature + # to disambiguate it from the (source, mappedAtCreation) overload so emwgpuCreateBuffer + # reliably selects the injection constructor and imported buffers are properly tagged + # as kImportedFromJS. + # + ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/dawn/dawn_buffer_fix_injection.patch && + + # Remove the test folder to speed up potential file scan operations (70k+ files not needed for build). + # Using token ensures the correct absolute path regardless of working directory. + ${CMAKE_COMMAND} -E rm -rf /test) + + onnxruntime_fetchcontent_declare( + dawn + URL ${DEP_URL_dawn} + URL_HASH SHA1=${DEP_SHA1_dawn} + PATCH_COMMAND ${ONNXRUNTIME_Dawn_PATCH_COMMAND} + EXCLUDE_FROM_ALL + ) + endif() + + onnxruntime_fetchcontent_makeavailable(dawn) + endif() if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") - if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) + if (onnxruntime_BUILD_DAWN_SHARED_LIBRARY) list(APPEND onnxruntime_EXTERNAL_LIBRARIES dawn::webgpu_dawn) else() if (NOT onnxruntime_USE_EXTERNAL_DAWN) @@ -725,18 +824,84 @@ if (onnxruntime_USE_WEBGPU) list(APPEND onnxruntime_EXTERNAL_LIBRARIES dawn::dawn_proc) endif() endif() + + if (onnxruntime_ENABLE_PIX_FOR_WEBGPU_EP) + list(APPEND onnxruntime_EXTERNAL_LIBRARIES webgpu_glfw glfw) + endif() + + if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND onnxruntime_WGSL_TEMPLATE STREQUAL "dynamic") + if(onnxruntime_USE_VCPKG) + find_package(unofficial-duktape CONFIG REQUIRED) + add_library(duktape_static ALIAS unofficial::duktape::duktape) + else() + onnxruntime_fetchcontent_declare( + duktape + URL ${DEP_URL_duktape} + URL_HASH SHA1=${DEP_SHA1_duktape} + EXCLUDE_FROM_ALL + ) + onnxruntime_fetchcontent_makeavailable(duktape) + + if(NOT TARGET duktape_static) + add_library(duktape_static STATIC "${duktape_SOURCE_DIR}/src/duktape.c") + target_compile_features(duktape_static PRIVATE c_std_99) + target_include_directories(duktape_static INTERFACE $) + endif() + endif() + endif() +endif() + +if(onnxruntime_USE_COREML) + # Setup coremltools fp16 and json dependencies for creating an mlpackage. + # + # fp16 depends on psimd + onnxruntime_fetchcontent_declare(psimd URL ${DEP_URL_psimd} URL_HASH SHA1=${DEP_SHA1_psimd} EXCLUDE_FROM_ALL) + onnxruntime_fetchcontent_makeavailable(psimd) + set(PSIMD_SOURCE_DIR ${psimd_SOURCE_DIR}) + onnxruntime_fetchcontent_declare(fp16 URL ${DEP_URL_fp16} URL_HASH SHA1=${DEP_SHA1_fp16} EXCLUDE_FROM_ALL) + set(FP16_BUILD_TESTS OFF CACHE INTERNAL "") + set(FP16_BUILD_BENCHMARKS OFF CACHE INTERNAL "") + onnxruntime_fetchcontent_makeavailable(fp16) + + onnxruntime_fetchcontent_declare( + coremltools + URL ${DEP_URL_coremltools} + URL_HASH SHA1=${DEP_SHA1_coremltools} + PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/coremltools/crossplatformbuild.patch + EXCLUDE_FROM_ALL + ) + # we don't build directly so use Populate. selected files are built from onnxruntime_providers_coreml.cmake + FetchContent_Populate(coremltools) + +endif() + +if(onnxruntime_USE_KLEIDIAI) + # Disable the KleidiAI tests + set(KLEIDIAI_BUILD_TESTS OFF) + + onnxruntime_fetchcontent_declare(kleidiai URL ${DEP_URL_kleidiai} URL_HASH SHA1=${DEP_SHA1_kleidiai} EXCLUDE_FROM_ALL) + onnxruntime_fetchcontent_makeavailable(kleidiai) + # Fetch Qualcomm's kleidiai library + if(onnxruntime_USE_QMX_KLEIDIAI_COEXIST) + onnxruntime_fetchcontent_declare(kleidiai-qmx URL ${DEP_URL_kleidiai-qmx} URL_HASH SHA1=${DEP_SHA1_kleidiai-qmx} + EXCLUDE_FROM_ALL) + onnxruntime_fetchcontent_makeavailable(kleidiai-qmx) + endif() endif() set(onnxruntime_LINK_DIRS) if (onnxruntime_USE_CUDA) find_package(CUDAToolkit REQUIRED) - if(onnxruntime_CUDNN_HOME) - file(TO_CMAKE_PATH ${onnxruntime_CUDNN_HOME} onnxruntime_CUDNN_HOME) - set(CUDNN_PATH ${onnxruntime_CUDNN_HOME}) - endif() + # cuDNN is not needed for minimal CUDA builds (e.g., TensorRT-only builds) + if(NOT onnxruntime_CUDA_MINIMAL) + if(onnxruntime_CUDNN_HOME) + file(TO_CMAKE_PATH ${onnxruntime_CUDNN_HOME} onnxruntime_CUDNN_HOME) + set(CUDNN_PATH ${onnxruntime_CUDNN_HOME}) + endif() - include(cuDNN) + include(cuDNN) + endif() endif() if(onnxruntime_USE_SNPE) diff --git a/cmake/external/pybind11.cmake b/cmake/external/pybind11.cmake index 2c9e3cf4540c2..ba14667bc3c88 100644 --- a/cmake/external/pybind11.cmake +++ b/cmake/external/pybind11.cmake @@ -1,13 +1,11 @@ -FetchContent_Declare( +set(PYBIND11_NOPYTHON ON CACHE BOOL "" FORCE) +set(PYBIND11_INSTALL OFF CACHE BOOL "" FORCE) +set(PYBIND11_TEST OFF CACHE BOOL "" FORCE) +onnxruntime_fetchcontent_declare( pybind11_project URL ${DEP_URL_pybind11} - URL_HASH SHA1=${DEP_SHA1_pybind11} - FIND_PACKAGE_ARGS 2.6 NAMES pybind11 + URL_HASH SHA1=${DEP_SHA1_pybind11} + EXCLUDE_FROM_ALL + FIND_PACKAGE_ARGS 3.0 NAMES pybind11 ) onnxruntime_fetchcontent_makeavailable(pybind11_project) - -if(TARGET pybind11::module) - set(pybind11_lib pybind11::module) -else() - set(pybind11_dep pybind11::pybind11) -endif() diff --git a/cmake/external/wil.cmake b/cmake/external/wil.cmake index 120e986ebb552..290497af14b1f 100644 --- a/cmake/external/wil.cmake +++ b/cmake/external/wil.cmake @@ -3,10 +3,11 @@ set(WIL_BUILD_PACKAGING OFF CACHE BOOL "" FORCE) set(WIL_BUILD_TESTS OFF CACHE BOOL "" FORCE) -FetchContent_Declare( +onnxruntime_fetchcontent_declare( microsoft_wil URL ${DEP_URL_microsoft_wil} URL_HASH SHA1=${DEP_SHA1_microsoft_wil} + EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES wil ) diff --git a/cmake/external/xnnpack.cmake b/cmake/external/xnnpack.cmake index 0be2c7082bcc8..571283c33c713 100644 --- a/cmake/external/xnnpack.cmake +++ b/cmake/external/xnnpack.cmake @@ -17,11 +17,11 @@ if(CMAKE_ANDROID_ARCH_ABI STREQUAL armeabi-v7a) endif() # pthreadpool depends on fxdiv -FetchContent_Declare(fxdiv URL ${DEP_URL_fxdiv} URL_HASH SHA1=${DEP_SHA1_fxdiv}) +onnxruntime_fetchcontent_declare(fxdiv URL ${DEP_URL_fxdiv} URL_HASH SHA1=${DEP_SHA1_fxdiv} EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES fxdiv) onnxruntime_fetchcontent_makeavailable(fxdiv) set(FXDIV_SOURCE_DIR ${fxdiv_SOURCE_DIR}) -FetchContent_Declare(pthreadpool URL ${DEP_URL_pthreadpool} URL_HASH SHA1=${DEP_SHA1_pthreadpool}) +onnxruntime_fetchcontent_declare(pthreadpool URL ${DEP_URL_pthreadpool} URL_HASH SHA1=${DEP_SHA1_pthreadpool} EXCLUDE_FROM_ALL FIND_PACKAGE_ARGS NAMES unofficial-pthreadpool) onnxruntime_fetchcontent_makeavailable(pthreadpool) # --- Determine target processor @@ -62,6 +62,8 @@ ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "aarch64") SET(ORT_TARGET_PROCESSOR "arm64") ELSEIF(CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc64le") SET(ORT_TARGET_PROCESSOR "ppc64") +ELSEIF(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + SET(ORT_TARGET_PROCESSOR "wasm") ELSEIF(NOT ORT_TARGET_PROCESSOR MATCHES "^(x86(_64)?|arm64|riscv(32|64|128)|Hexagon|ppc64)$") SET(ORT_TARGET_PROCESSOR "${CMAKE_SYSTEM_PROCESSOR}") ELSE() @@ -75,23 +77,28 @@ if(ORT_TARGET_PROCESSOR MATCHES "^arm64.*" AND NOT CMAKE_C_COMPILER_ID STREQUAL # kleidiAI use CMAKE_SYSTEM_PROCESSOR to determine whether includes aarch64/arm64 ukernels # https://gitlab.arm.com/kleidi/kleidiai/-/blob/main/CMakeLists.txt#L134 set(CMAKE_SYSTEM_PROCESSOR arm64) - FetchContent_Declare(kleidiai URL ${DEP_URL_kleidiai} URL_HASH SHA1=${DEP_SHA1_kleidiai}) + onnxruntime_fetchcontent_declare(kleidiai URL ${DEP_URL_kleidiai} URL_HASH SHA1=${DEP_SHA1_kleidiai} EXCLUDE_FROM_ALL) onnxruntime_fetchcontent_makeavailable(kleidiai) set(KLEIDIAI_SOURCE_DIR ${kleidiai_SOURCE_DIR}) endif() -FetchContent_Declare(googlexnnpack URL ${DEP_URL_googlexnnpack} URL_HASH SHA1=${DEP_SHA1_googlexnnpack} +onnxruntime_fetchcontent_declare(googlexnnpack URL ${DEP_URL_googlexnnpack} URL_HASH SHA1=${DEP_SHA1_googlexnnpack} PATCH_COMMAND ${Patch_EXECUTABLE} --binary --ignore-whitespace -p1 < ${PROJECT_SOURCE_DIR}/patches/xnnpack/AddEmscriptenAndIosSupport.patch + EXCLUDE_FROM_ALL + FIND_PACKAGE_ARGS NAMES xnnpack ) onnxruntime_fetchcontent_makeavailable(googlexnnpack) set(XNNPACK_DIR ${googlexnnpack_SOURCE_DIR}) set(XNNPACK_INCLUDE_DIR ${XNNPACK_DIR}/include) -set(onnxruntime_EXTERNAL_LIBRARIES_XNNPACK XNNPACK microkernels-prod pthreadpool) +set(onnxruntime_EXTERNAL_LIBRARIES_XNNPACK XNNPACK pthreadpool) if(ORT_TARGET_PROCESSOR MATCHES "^arm64.*" AND NOT CMAKE_C_COMPILER_ID STREQUAL "MSVC") list(APPEND onnxruntime_EXTERNAL_LIBRARIES_XNNPACK kleidiai) endif() +if(NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + list(APPEND onnxruntime_EXTERNAL_LIBRARIES_XNNPACK xnnpack-microkernels-prod) +endif() # the XNNPACK CMake setup doesn't include the WASM kernels so we have to manually set those up if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") @@ -99,7 +106,7 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") message("Adding WebAssembly Source Files to XNNPACK") set(wasm_srcs "") - file(READ "${XNNPACK_DIR}/BUILD.bazel" xnnpack_bazel_config) + file(READ "${XNNPACK_DIR}/build_srcs.bzl" xnnpack_bazel_config) # Replace newlines with semicolon so that it is treated as a list by CMake # Also replace '[' and ']' so the bazel source lists don't get parsed as a nested list by cmake @@ -137,14 +144,26 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") GetSrcListFromBazel("TABLE_SRCS" table_srcs) list(APPEND wasm_srcs ${operator_srcs} ${table_srcs}) - # kernels - list(APPEND wasm_srcs ${XNNPACK_DIR}/src/amalgam/gen/scalar.c) - list(APPEND wasm_srcs ${XNNPACK_DIR}/src/amalgam/gen/wasm.c) + set(microkernel_src "") + + include(${XNNPACK_DIR}/cmake/gen/scalar_microkernels.cmake) + list(APPEND microkernel_src ${PROD_SCALAR_MICROKERNEL_SRCS}) + list(APPEND microkernel_src ${PROD_WASM_MICROKERNEL_SRCS}) - if(onnxruntime_ENABLE_WEBASSEMBLY_SIMD) - list(APPEND wasm_srcs ${XNNPACK_DIR}/src/amalgam/gen/wasmsimd.c) + if(onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD) + include(${XNNPACK_DIR}/cmake/gen/wasmsimd_microkernels.cmake) + include(${XNNPACK_DIR}/cmake/gen/wasmrelaxedsimd_microkernels.cmake) + list(APPEND microkernel_src ${PROD_WASMSIMD_MICROKERNEL_SRCS}) + list(APPEND microkernel_src ${PROD_WASMRELAXEDSIMD_MICROKERNEL_SRCS}) + target_compile_options(XNNPACK PRIVATE "-msimd128") + target_compile_options(XNNPACK PRIVATE "-mrelaxed-simd") + elseif(onnxruntime_ENABLE_WEBASSEMBLY_SIMD) + include(${XNNPACK_DIR}/cmake/gen/wasmsimd_microkernels.cmake) + list(APPEND microkernel_src ${PROD_WASMSIMD_MICROKERNEL_SRCS}) target_compile_options(XNNPACK PRIVATE "-msimd128") endif() + list(TRANSFORM microkernel_src PREPEND "${XNNPACK_DIR}/") + list(APPEND wasm_srcs ${microkernel_src}) message(DEBUG "wasm_srcs: ${wasm_srcs}\n") target_sources(XNNPACK PRIVATE ${wasm_srcs}) diff --git a/cmake/node_helper.cmake b/cmake/node_helper.cmake new file mode 100644 index 0000000000000..1d394629b75f8 --- /dev/null +++ b/cmake/node_helper.cmake @@ -0,0 +1,114 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +cmake_minimum_required(VERSION 3.25) + +# Function to get NPM path from Node.js path +function(get_npm_path_from_node result_var node_path) + get_filename_component(NODE_DIR ${node_path} DIRECTORY) + if(CMAKE_HOST_WIN32) + set(NPM_CLI_CANDIDATE "${NODE_DIR}/npm.cmd") + if(NOT EXISTS ${NPM_CLI_CANDIDATE}) + set(NPM_CLI_CANDIDATE "${NODE_DIR}/npm") + endif() + else() + set(NPM_CLI_CANDIDATE "${NODE_DIR}/npm") + endif() + + set(${result_var} ${NPM_CLI_CANDIDATE} PARENT_SCOPE) +endfunction() + +# Validator function for Node.js installation (checks both Node.js and NPM versions) +function(validate_nodejs_installation result_var node_path) + # First validate Node.js version + execute_process( + COMMAND ${node_path} --version + OUTPUT_VARIABLE NODE_VERSION_OUTPUT + ERROR_VARIABLE NODE_VERSION_ERROR + RESULT_VARIABLE NODE_VERSION_RESULT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(NODE_VERSION_RESULT EQUAL 0) + # Node version output starts with 'v', e.g., "v20.10.0" + string(REGEX MATCH "^v([0-9]+)\\.([0-9]+)\\.([0-9]+)" NODE_VERSION_MATCH ${NODE_VERSION_OUTPUT}) + if(NODE_VERSION_MATCH) + set(NODE_VERSION_MAJOR ${CMAKE_MATCH_1}) + + if(NODE_VERSION_MAJOR LESS 20) + message(STATUS "Node.js at ${node_path} version ${NODE_VERSION_OUTPUT} is too old. Required: >= v20.0.0") + set(${result_var} FALSE PARENT_SCOPE) + return() + endif() + + message(STATUS "Found Node.js at ${node_path} with version: ${NODE_VERSION_OUTPUT}") + else() + message(STATUS "Could not parse Node.js version from ${node_path}: ${NODE_VERSION_OUTPUT}") + set(${result_var} FALSE PARENT_SCOPE) + return() + endif() + else() + message(STATUS "Failed to get Node.js version from ${node_path}: ${NODE_VERSION_ERROR}") + set(${result_var} FALSE PARENT_SCOPE) + return() + endif() + + # Now validate NPM from the same installation directory + get_npm_path_from_node(NPM_CLI_CANDIDATE ${node_path}) + + if(NOT EXISTS ${NPM_CLI_CANDIDATE}) + get_filename_component(NODE_DIR ${node_path} DIRECTORY) + message(STATUS "Could not find NPM in the same directory as Node.js: ${NODE_DIR}") + set(${result_var} FALSE PARENT_SCOPE) + return() + endif() + + # Validate NPM version + execute_process( + COMMAND ${NPM_CLI_CANDIDATE} --version + OUTPUT_VARIABLE NPM_VERSION_OUTPUT + ERROR_VARIABLE NPM_VERSION_ERROR + RESULT_VARIABLE NPM_VERSION_RESULT + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + + if(NPM_VERSION_RESULT EQUAL 0) + string(REGEX MATCH "^([0-9]+)\\.([0-9]+)\\.([0-9]+)" NPM_VERSION_MATCH ${NPM_VERSION_OUTPUT}) + if(NPM_VERSION_MATCH) + set(NPM_VERSION_MAJOR ${CMAKE_MATCH_1}) + + if(NPM_VERSION_MAJOR LESS 10) + message(STATUS "NPM at ${NPM_CLI_CANDIDATE} version ${NPM_VERSION_OUTPUT} is too old. Required: >= 10.0.0") + set(${result_var} FALSE PARENT_SCOPE) + return() + endif() + + message(STATUS "Found NPM at ${NPM_CLI_CANDIDATE} with version: ${NPM_VERSION_OUTPUT}") + set(${result_var} TRUE PARENT_SCOPE) + else() + message(STATUS "Could not parse NPM version from ${NPM_CLI_CANDIDATE}: ${NPM_VERSION_OUTPUT}") + set(${result_var} FALSE PARENT_SCOPE) + endif() + else() + message(STATUS "Failed to get NPM version from ${NPM_CLI_CANDIDATE}: ${NPM_VERSION_ERROR}") + set(${result_var} FALSE PARENT_SCOPE) + endif() +endfunction() + +# Check if both Node.js and NPM are already provided +if((NOT NPM_CLI) OR (NOT NODE_EXECUTABLE)) + # Find node executable with combined Node.js + NPM validation + find_program(NODE_EXECUTABLE + NAMES "node.exe" "node" + DOC "Node.js executable" + VALIDATOR validate_nodejs_installation + REQUIRED + ) + + # Set NPM_CLI from the validated Node.js installation + get_npm_path_from_node(NPM_CLI ${NODE_EXECUTABLE}) + set(NPM_CLI ${NPM_CLI} CACHE FILEPATH "NPM command line client" FORCE) + message(STATUS "Using Node.js and NPM from the same validated installation:") + message(STATUS " Node.js: ${NODE_EXECUTABLE}") + message(STATUS " NPM: ${NPM_CLI}") +endif() diff --git a/cmake/nuget_helpers.cmake b/cmake/nuget_helpers.cmake index 22143ac422e9f..b066d1e9fb50e 100644 --- a/cmake/nuget_helpers.cmake +++ b/cmake/nuget_helpers.cmake @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.5) # Determines the version of a native nuget package from the root packages.config. # diff --git a/cmake/onnxruntime.cmake b/cmake/onnxruntime.cmake index 78edb4179fafd..8f2234070d15d 100644 --- a/cmake/onnxruntime.cmake +++ b/cmake/onnxruntime.cmake @@ -1,10 +1,13 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. +include(CMakePrintHelpers) if(UNIX) set(SYMBOL_FILE ${CMAKE_CURRENT_BINARY_DIR}/onnxruntime.lds) if(APPLE) set(OUTPUT_STYLE xcode) + elseif(CMAKE_SYSTEM_NAME MATCHES "AIX") + set(OUTPUT_STYLE aix) else() set(OUTPUT_STYLE gcc) endif() @@ -24,10 +27,13 @@ function(get_c_cxx_api_headers HEADERS_VAR) "${REPO_ROOT}/include/onnxruntime/core/session/onnxruntime_c_api.h" "${REPO_ROOT}/include/onnxruntime/core/session/onnxruntime_cxx_api.h" "${REPO_ROOT}/include/onnxruntime/core/session/onnxruntime_cxx_inline.h" + "${REPO_ROOT}/include/onnxruntime/core/session/onnxruntime_ep_c_api.h" + "${REPO_ROOT}/include/onnxruntime/core/session/onnxruntime_ep_device_ep_metadata_keys.h" "${REPO_ROOT}/include/onnxruntime/core/session/onnxruntime_float16.h" + "${REPO_ROOT}/include/onnxruntime/core/session/onnxruntime_lite_custom_op.h" + "${REPO_ROOT}/include/onnxruntime/core/session/onnxruntime_env_config_keys.h" "${REPO_ROOT}/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h" "${REPO_ROOT}/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h" - "${REPO_ROOT}/include/onnxruntime/core/session/onnxruntime_lite_custom_op.h" ) if (onnxruntime_ENABLE_TRAINING_APIS) @@ -40,7 +46,7 @@ function(get_c_cxx_api_headers HEADERS_VAR) foreach(f ${ONNXRUNTIME_PROVIDER_NAMES}) # The header files in include/onnxruntime/core/providers/cuda directory cannot be flattened to the same directory # with onnxruntime_c_api.h . Most other EPs probably also do not work in this way. - if((NOT f STREQUAL cuda) AND (NOT f STREQUAL rocm)) + if(NOT f STREQUAL cuda) file(GLOB _provider_headers CONFIGURE_DEPENDS "${REPO_ROOT}/include/onnxruntime/core/providers/${f}/*.h" ) @@ -53,138 +59,141 @@ endfunction() get_c_cxx_api_headers(ONNXRUNTIME_PUBLIC_HEADERS) -#If you want to verify if there is any extra line in symbols.txt, run -# nm -C -g --defined libonnxruntime.so |grep -v '\sA\s' | cut -f 3 -d ' ' | sort -# after build - -list(APPEND SYMBOL_FILES "${REPO_ROOT}/tools/ci_build/gen_def.py") -foreach(f ${ONNXRUNTIME_PROVIDER_NAMES}) - list(APPEND SYMBOL_FILES "${ONNXRUNTIME_ROOT}/core/providers/${f}/symbols.txt") -endforeach() - -if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") -add_custom_command(OUTPUT ${SYMBOL_FILE} ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c - COMMAND ${Python_EXECUTABLE} "${REPO_ROOT}/tools/ci_build/gen_def.py" - --version_file "${ONNXRUNTIME_ROOT}/../VERSION_NUMBER" --src_root "${ONNXRUNTIME_ROOT}" - --config ${ONNXRUNTIME_PROVIDER_NAMES} --style=${OUTPUT_STYLE} --output ${SYMBOL_FILE} - --output_source ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c - DEPENDS ${SYMBOL_FILES} - WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) - -add_custom_target(onnxruntime_generate_def ALL DEPENDS ${SYMBOL_FILE} ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c) -endif() -if(WIN32) - onnxruntime_add_shared_library(onnxruntime - ${SYMBOL_FILE} - "${ONNXRUNTIME_ROOT}/core/dll/dllmain.cc" - "${ONNXRUNTIME_ROOT}/core/dll/delay_load_hook.cc" - "${ONNXRUNTIME_ROOT}/core/dll/onnxruntime.rc" - ) -elseif(onnxruntime_BUILD_APPLE_FRAMEWORK) - # apple framework requires the header file be part of the library - onnxruntime_add_shared_library(onnxruntime - ${ONNXRUNTIME_PUBLIC_HEADERS} - "${CMAKE_CURRENT_BINARY_DIR}/generated_source.c" - ) +if(onnxruntime_BUILD_SHARED_LIB) + #If you want to verify if there is any extra line in symbols.txt, run + # nm -C -g --defined libonnxruntime.so |grep -v '\sA\s' | cut -f 3 -d ' ' | sort + # after build - # create Info.plist for the framework and podspec for CocoaPods (optional) - set(MACOSX_FRAMEWORK_NAME "onnxruntime") - set(MACOSX_FRAMEWORK_IDENTIFIER "com.microsoft.onnxruntime") + list(APPEND SYMBOL_FILES "${REPO_ROOT}/tools/ci_build/gen_def.py") + foreach(f ${ONNXRUNTIME_PROVIDER_NAMES}) + list(APPEND SYMBOL_FILES "${ONNXRUNTIME_ROOT}/core/providers/${f}/symbols.txt") + endforeach() - # Setup weak frameworks for macOS/iOS. 'weak' as the CoreML or WebGPU EPs are optionally enabled. - if(onnxruntime_USE_COREML) - list(APPEND _weak_frameworks "\\\"CoreML\\\"") - endif() + add_custom_command(OUTPUT ${SYMBOL_FILE} ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c + COMMAND ${Python_EXECUTABLE} "${REPO_ROOT}/tools/ci_build/gen_def.py" + --version_file "${ONNXRUNTIME_ROOT}/../VERSION_NUMBER" --src_root "${ONNXRUNTIME_ROOT}" + --config ${ONNXRUNTIME_PROVIDER_NAMES} --style=${OUTPUT_STYLE} --output ${SYMBOL_FILE} + --output_source ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c + DEPENDS ${SYMBOL_FILES} + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + + add_custom_target(onnxruntime_generate_def ALL DEPENDS ${SYMBOL_FILE} ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c) + if(WIN32) + onnxruntime_add_shared_library(onnxruntime + ${SYMBOL_FILE} + "${ONNXRUNTIME_ROOT}/core/dll/dllmain.cc" + "${ONNXRUNTIME_ROOT}/core/dll/delay_load_hook.cc" + "${ONNXRUNTIME_ROOT}/core/dll/onnxruntime.rc" + ) + elseif(onnxruntime_BUILD_APPLE_FRAMEWORK) + # apple framework requires the header file be part of the library + onnxruntime_add_shared_library(onnxruntime + ${ONNXRUNTIME_PUBLIC_HEADERS} + "${CMAKE_CURRENT_BINARY_DIR}/generated_source.c" + ) + + # create Info.plist for the framework and podspec for CocoaPods (optional) + set(MACOSX_FRAMEWORK_NAME "onnxruntime") + set(MACOSX_FRAMEWORK_IDENTIFIER "com.microsoft.onnxruntime") + + # Setup weak frameworks for macOS/iOS. 'weak' as the CoreML or WebGPU EPs are optionally enabled. + if(onnxruntime_USE_COREML) + list(APPEND _weak_frameworks "\\\"CoreML\\\"") + endif() - if(onnxruntime_USE_WEBGPU) - list(APPEND _weak_frameworks "\\\"QuartzCore\\\"") - list(APPEND _weak_frameworks "\\\"IOSurface\\\"") - list(APPEND _weak_frameworks "\\\"Metal\\\"") - endif() + if(onnxruntime_USE_WEBGPU) + list(APPEND _weak_frameworks "\\\"QuartzCore\\\"") + list(APPEND _weak_frameworks "\\\"IOSurface\\\"") + list(APPEND _weak_frameworks "\\\"Metal\\\"") + endif() - if (_weak_frameworks) - string(JOIN ", " APPLE_WEAK_FRAMEWORK ${_weak_frameworks}) - endif() + if (_weak_frameworks) + string(JOIN ", " APPLE_WEAK_FRAMEWORK ${_weak_frameworks}) + endif() - set(INFO_PLIST_PATH "${CMAKE_CURRENT_BINARY_DIR}/Info.plist") - configure_file(${REPO_ROOT}/cmake/Info.plist.in ${INFO_PLIST_PATH}) - configure_file( - ${REPO_ROOT}/tools/ci_build/github/apple/framework_info.json.template - ${CMAKE_CURRENT_BINARY_DIR}/framework_info.json) - set_target_properties(onnxruntime PROPERTIES - FRAMEWORK TRUE - FRAMEWORK_VERSION A - MACOSX_FRAMEWORK_INFO_PLIST ${INFO_PLIST_PATH} - # Note: The PUBLIC_HEADER and VERSION properties for the 'onnxruntime' target will be set later in this file. - ) -else() - if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") - onnxruntime_add_shared_library(onnxruntime ${ONNXRUNTIME_ROOT}/core/session/onnxruntime_c_api.cc) + set(INFO_PLIST_PATH "${CMAKE_CURRENT_BINARY_DIR}/Info.plist") + configure_file(${REPO_ROOT}/cmake/Info.plist.in ${INFO_PLIST_PATH}) + configure_file( + ${REPO_ROOT}/tools/ci_build/github/apple/framework_info.json.template + ${CMAKE_CURRENT_BINARY_DIR}/framework_info.json) + set_target_properties(onnxruntime PROPERTIES + FRAMEWORK TRUE + FRAMEWORK_VERSION A + MACOSX_FRAMEWORK_INFO_PLIST ${INFO_PLIST_PATH} + # Note: The PUBLIC_HEADER and VERSION properties for the 'onnxruntime' target will be set later in this file. + ) else() - onnxruntime_add_shared_library(onnxruntime ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c ) - endif() - if(NOT APPLE) - include(CheckLinkerFlag) - check_linker_flag(CXX "LINKER:-rpath=\$ORIGIN" LINKER_SUPPORT_RPATH) - if(LINKER_SUPPORT_RPATH) - target_link_options(onnxruntime PRIVATE "LINKER:-rpath=\$ORIGIN") + onnxruntime_add_shared_library(onnxruntime ${CMAKE_CURRENT_BINARY_DIR}/generated_source.c) + if(NOT APPLE) + include(CheckLinkerFlag) + check_linker_flag(CXX "LINKER:-rpath=\$ORIGIN" LINKER_SUPPORT_RPATH) + if(LINKER_SUPPORT_RPATH) + target_link_options(onnxruntime PRIVATE "LINKER:-rpath=\$ORIGIN") + endif() endif() endif() -endif() -if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") - add_dependencies(onnxruntime ${onnxruntime_EXTERNAL_DEPENDENCIES}) -else() add_dependencies(onnxruntime onnxruntime_generate_def ${onnxruntime_EXTERNAL_DEPENDENCIES}) -endif() -target_include_directories(onnxruntime PRIVATE ${ONNXRUNTIME_ROOT} PUBLIC "$") + target_include_directories(onnxruntime PRIVATE ${ONNXRUNTIME_ROOT} PUBLIC "$") -target_compile_definitions(onnxruntime PRIVATE FILE_NAME=\"onnxruntime.dll\") + target_compile_definitions(onnxruntime PRIVATE FILE_NAME=\"onnxruntime.dll\") -if(UNIX) - if (APPLE) - target_link_options(onnxruntime PRIVATE "LINKER:-dead_strip") - elseif(NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") - target_link_options(onnxruntime PRIVATE "LINKER:--version-script=${SYMBOL_FILE}" "LINKER:--no-undefined" "LINKER:--gc-sections") + if(UNIX) + if (APPLE) + target_link_options(onnxruntime PRIVATE "LINKER:-dead_strip") + elseif(CMAKE_SYSTEM_NAME MATCHES "AIX") + set_property(TARGET onnxruntime PROPERTY AIX_EXPORT_ALL_SYMBOLS OFF) + target_link_options(onnxruntime PRIVATE "LINKER:-bE:${SYMBOL_FILE}") + else() + target_link_options(onnxruntime PRIVATE "LINKER:--version-script=${SYMBOL_FILE}" "LINKER:--no-undefined" "LINKER:--gc-sections" "LINKER:-z,noexecstack") + endif() + else() + target_link_options(onnxruntime PRIVATE "-DEF:${SYMBOL_FILE}") endif() -else() - target_link_options(onnxruntime PRIVATE "-DEF:${SYMBOL_FILE}") -endif() -if (APPLE OR ${CMAKE_SYSTEM_NAME} MATCHES "^iOS") + if (APPLE) target_link_options(onnxruntime PRIVATE "LINKER:-exported_symbols_list,${SYMBOL_FILE}") - if (${CMAKE_SYSTEM_NAME} STREQUAL "iOS") - set_target_properties(onnxruntime PROPERTIES - MACOSX_RPATH TRUE - INSTALL_RPATH_USE_LINK_PATH FALSE - BUILD_WITH_INSTALL_NAME_DIR TRUE - INSTALL_NAME_DIR @rpath) - else() - set_target_properties(onnxruntime PROPERTIES INSTALL_RPATH "@loader_path") - endif() -endif() + set_target_properties(onnxruntime PROPERTIES + MACOSX_RPATH TRUE + BUILD_WITH_INSTALL_RPATH TRUE + INSTALL_RPATH "@loader_path" + BUILD_WITH_INSTALL_NAME_DIR TRUE + INSTALL_NAME_DIR @rpath) + endif() -if(CMAKE_SYSTEM_NAME STREQUAL "Android" AND onnxruntime_MINIMAL_BUILD) - # target onnxruntime is a shared library, the dummy __cxa_demangle is only attach to it to avoid - # affecting downstream ort library users with the behavior of dummy __cxa_demangle. So the dummy - # __cxa_demangle must not expose to libonnxruntime_common.a. It works as when the linker is - # creating the DSO, our dummy __cxa_demangle always comes before libc++abi.a so the - # __cxa_demangle in libc++abi.a is discarded, thus, huge binary size reduction. - target_sources(onnxruntime PRIVATE "${ONNXRUNTIME_ROOT}/core/platform/android/cxa_demangle.cc") - target_compile_definitions(onnxruntime PRIVATE USE_DUMMY_EXA_DEMANGLE=1) -endif() + if(CMAKE_SYSTEM_NAME STREQUAL "Android" AND onnxruntime_MINIMAL_BUILD) + # target onnxruntime is a shared library, the dummy __cxa_demangle is only attach to it to avoid + # affecting downstream ort library users with the behavior of dummy __cxa_demangle. So the dummy + # __cxa_demangle must not expose to libonnxruntime_common.a. It works as when the linker is + # creating the DSO, our dummy __cxa_demangle always comes before libc++abi.a so the + # __cxa_demangle in libc++abi.a is discarded, thus, huge binary size reduction. + target_sources(onnxruntime PRIVATE "${ONNXRUNTIME_ROOT}/core/platform/android/cxa_demangle.cc") + target_compile_definitions(onnxruntime PRIVATE USE_DUMMY_EXA_DEMANGLE=1) + endif() -# strip binary on Android, or for a minimal build on Unix -if(CMAKE_SYSTEM_NAME STREQUAL "Android" OR (onnxruntime_MINIMAL_BUILD AND UNIX)) - if (onnxruntime_MINIMAL_BUILD AND ADD_DEBUG_INFO_TO_MINIMAL_BUILD) - # don't strip - else() - set_target_properties(onnxruntime PROPERTIES LINK_FLAGS_RELEASE -s) - set_target_properties(onnxruntime PROPERTIES LINK_FLAGS_MINSIZEREL -s) + # strip binary on Android, or for a minimal build on Unix + if(CMAKE_SYSTEM_NAME STREQUAL "Android" OR (onnxruntime_MINIMAL_BUILD AND UNIX)) + if (onnxruntime_MINIMAL_BUILD AND ADD_DEBUG_INFO_TO_MINIMAL_BUILD) + # don't strip + else() + set_target_properties(onnxruntime PROPERTIES LINK_FLAGS_RELEASE -s) + set_target_properties(onnxruntime PROPERTIES LINK_FLAGS_MINSIZEREL -s) + endif() + endif() + + # we need to copy C/C++ API headers to be packed into Android AAR package + if(CMAKE_SYSTEM_NAME STREQUAL "Android" AND onnxruntime_BUILD_JAVA) + set(ANDROID_HEADERS_DIR ${CMAKE_CURRENT_BINARY_DIR}/android/headers) + file(MAKE_DIRECTORY ${ANDROID_HEADERS_DIR}) + # copy the header files one by one + foreach(h_ ${ONNXRUNTIME_PUBLIC_HEADERS}) + get_filename_component(HEADER_NAME_ ${h_} NAME) + add_custom_command(TARGET onnxruntime POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different ${h_} ${ANDROID_HEADERS_DIR}/${HEADER_NAME_}) + endforeach() endif() endif() @@ -199,9 +208,12 @@ if(CMAKE_SYSTEM_NAME STREQUAL "Android" AND onnxruntime_BUILD_JAVA) endforeach() endif() +if (NOT onnxruntime_BUILD_SHARED_LIB) + add_library(onnxruntime INTERFACE) +endif() + set(onnxruntime_INTERNAL_PROVIDER_LIBRARIES ${PROVIDERS_ACL} - ${PROVIDERS_ARMNN} ${PROVIDERS_COREML} ${PROVIDERS_DML} ${PROVIDERS_NNAPI} @@ -209,7 +221,6 @@ set(onnxruntime_INTERNAL_PROVIDER_LIBRARIES ${PROVIDERS_RKNPU} ${PROVIDERS_VSINPU} ${PROVIDERS_XNNPACK} - ${PROVIDERS_WEBGPU} ${PROVIDERS_WEBNN} ${PROVIDERS_AZURE} ${PROVIDERS_INTERNAL_TESTING} @@ -219,6 +230,10 @@ if (onnxruntime_BUILD_QNN_EP_STATIC_LIB) list(APPEND onnxruntime_INTERNAL_PROVIDER_LIBRARIES onnxruntime_providers_qnn) endif() +if (onnxruntime_USE_WEBGPU AND NOT onnxruntime_USE_EP_API_ADAPTERS) + list(APPEND onnxruntime_INTERNAL_PROVIDER_LIBRARIES onnxruntime_providers_webgpu) +endif() + # This list is a reversed topological ordering of library dependencies. # Earlier entries may depend on later ones. Later ones should not depend on earlier ones. set(onnxruntime_INTERNAL_LIBRARIES @@ -237,7 +252,7 @@ set(onnxruntime_INTERNAL_LIBRARIES onnxruntime_flatbuffers ) -if (${CMAKE_SYSTEM_NAME} MATCHES "AIX") +if (CMAKE_SYSTEM_NAME MATCHES "AIX") list(APPEND onnxruntime_INTERNAL_LIBRARIES iconv) endif() @@ -251,32 +266,31 @@ endif() # If you are linking a new library, please add it to the list onnxruntime_INTERNAL_LIBRARIES or onnxruntime_EXTERNAL_LIBRARIES, # Please do not add a library directly to the target_link_libraries command -target_link_libraries(onnxruntime PRIVATE +if (onnxruntime_BUILD_SHARED_LIB) + target_link_libraries(onnxruntime PRIVATE + ${onnxruntime_INTERNAL_LIBRARIES} + ${onnxruntime_EXTERNAL_LIBRARIES} + ) +else() + target_link_libraries(onnxruntime INTERFACE ${onnxruntime_INTERNAL_LIBRARIES} ${onnxruntime_EXTERNAL_LIBRARIES} -) + ) +endif() if(WIN32) target_link_options(onnxruntime PRIVATE ${onnxruntime_DELAYLOAD_FLAGS}) endif() #See: https://cmake.org/cmake/help/latest/prop_tgt/SOVERSION.html -if(NOT APPLE AND NOT WIN32) - if(${CMAKE_SYSTEM_NAME} MATCHES "AIX") - set_target_properties(onnxruntime PROPERTIES - PUBLIC_HEADER "${ONNXRUNTIME_PUBLIC_HEADERS}" - VERSION ${ORT_VERSION} - SOVERSION 1 - FOLDER "ONNXRuntime") - else() - set_target_properties(onnxruntime PROPERTIES - PUBLIC_HEADER "${ONNXRUNTIME_PUBLIC_HEADERS}" - LINK_DEPENDS ${SYMBOL_FILE} - VERSION ${ORT_VERSION} - SOVERSION 1 - FOLDER "ONNXRuntime") - endif() +if(NOT WIN32) + set_target_properties(onnxruntime PROPERTIES + PUBLIC_HEADER "${ONNXRUNTIME_PUBLIC_HEADERS}" + LINK_DEPENDS ${SYMBOL_FILE} + VERSION ${ORT_VERSION} + SOVERSION 1 + FOLDER "ONNXRuntime") else() - # Omit the SOVERSION setting in Windows/macOS/iOS/.. build + # Omit the SOVERSION setting in Windows build set_target_properties(onnxruntime PROPERTIES PUBLIC_HEADER "${ONNXRUNTIME_PUBLIC_HEADERS}" LINK_DEPENDS ${SYMBOL_FILE} @@ -327,8 +341,19 @@ if (winml_is_inbox) endif() endif() -# Assemble the Apple static framework (iOS and macOS) +# Assemble the Apple static framework if(onnxruntime_BUILD_APPLE_FRAMEWORK) + if (NOT CMAKE_SYSTEM_NAME MATCHES "Darwin|iOS|visionOS|tvOS") + message(FATAL_ERROR "onnxruntime_BUILD_APPLE_FRAMEWORK can only be enabled for macOS or iOS or visionOS or tvOS.") + endif() + + list(LENGTH CMAKE_OSX_ARCHITECTURES CMAKE_OSX_ARCHITECTURES_LEN) + if (CMAKE_OSX_ARCHITECTURES_LEN GREATER 1) + # We stitch multiple static libraries together when onnxruntime_BUILD_APPLE_FRAMEWORK is true, + # but that would not work for universal static libraries + message(FATAL_ERROR "universal binary is not supported for apple framework") + endif() + # when building for mac catalyst, the CMAKE_OSX_SYSROOT is set to MacOSX as well, to avoid duplication, # we specify as `-macabi` in the name of the output static apple framework directory. if (PLATFORM_NAME STREQUAL "macabi") @@ -484,3 +509,30 @@ if(onnxruntime_BUILD_APPLE_FRAMEWORK) endforeach() endif() + +# message(STATUS "++++++++ Paco START 2") +# #print_target_properties(onnxruntime) +# MESSAGE( STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS} ) +# MESSAGE( STATUS "CMAKE_CXX_COMPILER_TARGET: " ${CMAKE_CXX_COMPILER_TARGET} ) +# MESSAGE( STATUS "CMAKE_CXX_COMPILER: " ${CMAKE_CXX_COMPILER} ) +# MESSAGE( STATUS "CMAKE_CXX_FLAGS_RELEASE: " ${CMAKE_CXX_FLAGS_RELEASE} ) +# MESSAGE( STATUS "CMAKE_CXX_FLAGS_RELEASE_INIT: " ${CMAKE_CXX_FLAGS_RELEASE_INIT} ) +# MESSAGE( STATUS "CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN: " ${CMAKE_CXX_COMPILER_EXTERNAL_TOOLCHAIN} ) + +# message(STATUS "++++++++ Paco START 3") +# print_target_properties(onnxruntime) +# MESSAGE( STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS} ) + +# get_cmake_property(_variableNames VARIABLES) +# list (SORT _variableNames) +# foreach (_variableName ${_variableNames}) +# message(STATUS "${_variableName}=${${_variableName}}") +# endforeach() +# message(STATUS "++++++++ Paco END 3") +# #message(FATAL_ERROR get_property(target_names DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY BUILDSYSTEM_TARGETS)) + +# message(STATUS "++++++++ Paco END 2") +# #message(FATAL_ERROR get_property(target_names DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY BUILDSYSTEM_TARGETS)) + +# #set(CMAKE_XCODE_ATTRIBUTE_ONLY_ACTIVE_ARCH NO) #Paco +# #set(CMAKE_OSX_SYSROOT, "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.0.sdk") diff --git a/cmake/onnxruntime_common.cmake b/cmake/onnxruntime_common.cmake index 896379d743441..b081e22e8b3f4 100644 --- a/cmake/onnxruntime_common.cmake +++ b/cmake/onnxruntime_common.cmake @@ -11,6 +11,10 @@ set(onnxruntime_common_src_patterns "${ONNXRUNTIME_ROOT}/core/common/logging/*.cc" "${ONNXRUNTIME_ROOT}/core/common/logging/sinks/*.h" "${ONNXRUNTIME_ROOT}/core/common/logging/sinks/*.cc" + "${ONNXRUNTIME_ROOT}/core/platform/check_intel.h" + "${ONNXRUNTIME_ROOT}/core/platform/check_intel.cc" + "${ONNXRUNTIME_ROOT}/core/platform/device_discovery.h" + "${ONNXRUNTIME_ROOT}/core/platform/device_discovery_common.cc" "${ONNXRUNTIME_ROOT}/core/platform/env.h" "${ONNXRUNTIME_ROOT}/core/platform/env.cc" "${ONNXRUNTIME_ROOT}/core/platform/env_time.h" @@ -28,18 +32,30 @@ set(onnxruntime_common_src_patterns if(WIN32) list(APPEND onnxruntime_common_src_patterns - "${ONNXRUNTIME_ROOT}/core/platform/windows/*.h" - "${ONNXRUNTIME_ROOT}/core/platform/windows/*.cc" + "${ONNXRUNTIME_ROOT}/core/platform/windows/debug_alloc.cc" + "${ONNXRUNTIME_ROOT}/core/platform/windows/debug_alloc.h" + "${ONNXRUNTIME_ROOT}/core/platform/windows/dll_load_error.cc" + "${ONNXRUNTIME_ROOT}/core/platform/windows/dll_load_error.h" + "${ONNXRUNTIME_ROOT}/core/platform/windows/env_time.cc" + "${ONNXRUNTIME_ROOT}/core/platform/windows/env.cc" + "${ONNXRUNTIME_ROOT}/core/platform/windows/env.h" + "${ONNXRUNTIME_ROOT}/core/platform/windows/hardware_core_enumerator.cc" + "${ONNXRUNTIME_ROOT}/core/platform/windows/hardware_core_enumerator.h" + "${ONNXRUNTIME_ROOT}/core/platform/windows/stacktrace.cc" + "${ONNXRUNTIME_ROOT}/core/platform/windows/telemetry.cc" + "${ONNXRUNTIME_ROOT}/core/platform/windows/telemetry.h" "${ONNXRUNTIME_ROOT}/core/platform/windows/logging/*.h" "${ONNXRUNTIME_ROOT}/core/platform/windows/logging/*.cc" ) else() list(APPEND onnxruntime_common_src_patterns - "${ONNXRUNTIME_ROOT}/core/platform/posix/*.h" - "${ONNXRUNTIME_ROOT}/core/platform/posix/*.cc" + "${ONNXRUNTIME_ROOT}/core/platform/posix/env_time.cc" + "${ONNXRUNTIME_ROOT}/core/platform/posix/env.cc" + "${ONNXRUNTIME_ROOT}/core/platform/posix/stacktrace.cc" ) + # logging files if (onnxruntime_USE_SYSLOG) list(APPEND onnxruntime_common_src_patterns "${ONNXRUNTIME_ROOT}/core/platform/posix/logging/*.h" @@ -47,7 +63,7 @@ else() ) endif() - if (CMAKE_SYSTEM_NAME STREQUAL "Android") + if (ANDROID) list(APPEND onnxruntime_common_src_patterns "${ONNXRUNTIME_ROOT}/core/platform/android/logging/*.h" "${ONNXRUNTIME_ROOT}/core/platform/android/logging/*.cc" @@ -62,18 +78,34 @@ else() endif() endif() +# platform-specific device discovery files +if (WIN32) + list(APPEND onnxruntime_common_src_patterns + "${ONNXRUNTIME_ROOT}/core/platform/windows/device_discovery.cc") +elseif (LINUX) + list(APPEND onnxruntime_common_src_patterns + "${ONNXRUNTIME_ROOT}/core/platform/linux/device_discovery.cc" + "${ONNXRUNTIME_ROOT}/core/platform/linux/pci_device_discovery.h") +elseif (APPLE) + list(APPEND onnxruntime_common_src_patterns + "${ONNXRUNTIME_ROOT}/core/platform/apple/device_discovery.cc") +else() + list(APPEND onnxruntime_common_src_patterns + "${ONNXRUNTIME_ROOT}/core/platform/device_discovery_default.cc") +endif() + if(onnxruntime_target_platform STREQUAL "ARM64EC") if (MSVC) link_directories("$ENV{VCINSTALLDIR}/Tools/MSVC/$ENV{VCToolsVersion}/lib/ARM64EC") link_directories("$ENV{VCINSTALLDIR}/Tools/MSVC/$ENV{VCToolsVersion}/ATLMFC/lib/ARM64EC") link_libraries(softintrin.lib) - add_compile_options("/bigobj") + add_compile_options("$<$>:/bigobj>") endif() endif() if(onnxruntime_target_platform STREQUAL "ARM64") if (MSVC) - add_compile_options("/bigobj") + add_compile_options("$<$>:/bigobj>") endif() endif() @@ -98,6 +130,14 @@ if(WIN32) target_compile_options(onnxruntime_common PRIVATE "/Zc:char8_t-") endif() endif() + +if(NOT WIN32 AND NOT APPLE AND NOT ANDROID AND CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64") + set_source_files_properties( + ${ONNXRUNTIME_ROOT}/core/common/spin_pause.cc + PROPERTIES COMPILE_FLAGS "-mwaitpkg" + ) +endif() + if (onnxruntime_USE_TELEMETRY) set_target_properties(onnxruntime_common PROPERTIES COMPILE_FLAGS "/FI${ONNXRUNTIME_INCLUDE_DIR}/core/platform/windows/TraceLoggingConfigPrivate.h") endif() @@ -108,16 +148,14 @@ if (onnxruntime_USE_MIMALLOC) target_link_libraries(onnxruntime_common PRIVATE onnxruntime_mimalloc_shim) endif() -if(NOT onnxruntime_DISABLE_ABSEIL) - target_include_directories(onnxruntime_common PRIVATE ${ABSEIL_SOURCE_DIR}) - if (MSVC) - set(ABSEIL_NATVIS_FILE "abseil-cpp.natvis") - target_sources( - onnxruntime_common - INTERFACE $) - endif() +if (MSVC) + set(ABSEIL_NATVIS_FILE "abseil-cpp.natvis") + target_sources( + onnxruntime_common + INTERFACE $) endif() + if (MSVC) set(EIGEN_NATVIS_FILE ${eigen_SOURCE_DIR}/debug/msvc/eigen.natvis) if (EXISTS ${EIGEN_NATVIS_FILE}) @@ -127,9 +165,9 @@ if (MSVC) endif() endif() -onnxruntime_add_include_to_target(onnxruntime_common date::date ${WIL_TARGET}) +onnxruntime_add_include_to_target(onnxruntime_common date::date ${WIL_TARGET} Eigen3::Eigen) target_include_directories(onnxruntime_common - PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} # propagate include directories of dependencies that are part of public interface PUBLIC ${OPTIONAL_LITE_INCLUDE_DIR}) @@ -157,68 +195,15 @@ if(APPLE) target_link_libraries(onnxruntime_common PRIVATE "-framework Foundation") endif() - -if(MSVC) - if(onnxruntime_target_platform STREQUAL "ARM64") - set(ARM64 TRUE) - elseif (onnxruntime_target_platform STREQUAL "ARM") - set(ARM TRUE) - elseif(onnxruntime_target_platform STREQUAL "x64") - set(X64 TRUE) - elseif(onnxruntime_target_platform STREQUAL "x86") - set(X86 TRUE) - endif() -elseif(APPLE) - if(CMAKE_OSX_ARCHITECTURES_LEN LESS_EQUAL 1) - set(X64 TRUE) - endif() -elseif(NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") - if (CMAKE_SYSTEM_NAME STREQUAL "Android") - if (CMAKE_ANDROID_ARCH_ABI STREQUAL "armeabi-v7a") - set(ARM TRUE) - elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a") - set(ARM64 TRUE) - elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86_64") - set(X86_64 TRUE) - elseif (CMAKE_ANDROID_ARCH_ABI STREQUAL "x86") - set(X86 TRUE) - endif() - else() - execute_process( - COMMAND ${CMAKE_C_COMPILER} -dumpmachine - OUTPUT_VARIABLE dumpmachine_output - ERROR_QUIET - ) - if(dumpmachine_output MATCHES "^arm64.*") - set(ARM64 TRUE) - elseif(dumpmachine_output MATCHES "^arm.*") - set(ARM TRUE) - elseif(dumpmachine_output MATCHES "^aarch64.*") - set(ARM64 TRUE) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^riscv64.*") - set(RISCV64 TRUE) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i.86|x86?)$") - set(X86 TRUE) - elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64)$") - set(X86_64 TRUE) - endif() - endif() -endif() - - -if (RISCV64 OR ARM64 OR ARM OR X86 OR X64 OR X86_64) - # Link cpuinfo if supported - # Using it mainly in ARM with Android. - # Its functionality in detecting x86 cpu features are lacking, so is support for Windows. - if (CPUINFO_SUPPORTED) - onnxruntime_add_include_to_target(onnxruntime_common cpuinfo::cpuinfo) - list(APPEND onnxruntime_EXTERNAL_LIBRARIES cpuinfo::cpuinfo ${ONNXRUNTIME_CLOG_TARGET_NAME}) - endif() +if(CPUINFO_SUPPORTED) + # Link cpuinfo if supported + onnxruntime_add_include_to_target(onnxruntime_common cpuinfo::cpuinfo) + list(APPEND onnxruntime_EXTERNAL_LIBRARIES cpuinfo::cpuinfo) endif() if (NOT onnxruntime_BUILD_SHARED_LIB) install(DIRECTORY ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/common DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/core) - install(TARGETS onnxruntime_common + install(TARGETS onnxruntime_common EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/cmake/onnxruntime_compile_triton_kernel.cmake b/cmake/onnxruntime_compile_triton_kernel.cmake deleted file mode 100644 index 9ecb8cf93265c..0000000000000 --- a/cmake/onnxruntime_compile_triton_kernel.cmake +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - -find_package(Python3 COMPONENTS Interpreter REQUIRED) - -# set all triton kernel ops that need to be compiled -if(onnxruntime_USE_ROCM) - set(triton_kernel_scripts - "onnxruntime/core/providers/rocm/math/softmax_triton.py" - "onnxruntime/contrib_ops/rocm/diffusion/group_norm_triton.py" - ) -endif() - -function(compile_triton_kernel out_triton_kernel_obj_file out_triton_kernel_header_dir) - # compile triton kernel, generate .a and .h files - set(triton_kernel_compiler "${REPO_ROOT}/tools/ci_build/compile_triton.py") - set(out_dir "${CMAKE_CURRENT_BINARY_DIR}/triton_kernels") - set(out_obj_file "${out_dir}/triton_kernel_infos.a") - set(header_file "${out_dir}/triton_kernel_infos.h") - - list(TRANSFORM triton_kernel_scripts PREPEND "${REPO_ROOT}/") - - add_custom_command( - OUTPUT ${out_obj_file} ${header_file} - COMMAND Python3::Interpreter ${triton_kernel_compiler} - --header ${header_file} - --script_files ${triton_kernel_scripts} - --obj_file ${out_obj_file} - DEPENDS ${triton_kernel_scripts} ${triton_kernel_compiler} - COMMENT "Triton compile generates: ${out_obj_file}" - ) - add_custom_target(onnxruntime_triton_kernel DEPENDS ${out_obj_file} ${header_file}) - set(${out_triton_kernel_obj_file} ${out_obj_file} PARENT_SCOPE) - set(${out_triton_kernel_header_dir} ${out_dir} PARENT_SCOPE) -endfunction() diff --git a/cmake/onnxruntime_config.h.in b/cmake/onnxruntime_config.h.in index f82a23bf4026b..e5f759b9d705f 100644 --- a/cmake/onnxruntime_config.h.in +++ b/cmake/onnxruntime_config.h.in @@ -3,6 +3,7 @@ #pragma once +#cmakedefine HAS_ARRAY_BOUNDS #cmakedefine HAS_BITWISE_INSTEAD_OF_LOGICAL #cmakedefine HAS_CAST_FUNCTION_TYPE #cmakedefine HAS_CATCH_VALUE @@ -19,6 +20,7 @@ #cmakedefine HAS_PARENTHESES #cmakedefine HAS_REALLOCARRAY #cmakedefine HAS_SHORTEN_64_TO_32 +#cmakedefine HAS_STRINGOP_OVERFLOW #cmakedefine HAS_TAUTOLOGICAL_POINTER_COMPARE #cmakedefine HAS_UNUSED_BUT_SET_PARAMETER #cmakedefine HAS_UNUSED_BUT_SET_VARIABLE diff --git a/cmake/onnxruntime_csharp.cmake b/cmake/onnxruntime_csharp.cmake index 39533429e181c..cbd435cecf034 100644 --- a/cmake/onnxruntime_csharp.cmake +++ b/cmake/onnxruntime_csharp.cmake @@ -34,10 +34,6 @@ if (onnxruntime_USE_OPENVINO) STRING(APPEND CSHARP_PREPROCESSOR_DEFINES "USE_OPENVINO;") endif() -if (onnxruntime_USE_ROCM) - STRING(APPEND CSHARP_PREPROCESSOR_DEFINES "USE_ROCM;") -endif() - if (onnxruntime_USE_TENSORRT) STRING(APPEND CSHARP_PREPROCESSOR_DEFINES "USE_TENSORRT;") endif() diff --git a/cmake/onnxruntime_flatbuffers.cmake b/cmake/onnxruntime_flatbuffers.cmake index 3ab4c19122ba1..066fb561de57d 100644 --- a/cmake/onnxruntime_flatbuffers.cmake +++ b/cmake/onnxruntime_flatbuffers.cmake @@ -22,10 +22,9 @@ if (FLATBUFFERS_BUILD_FLATC) add_dependencies(onnxruntime_flatbuffers flatc) endif() if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_flatbuffers + install(TARGETS onnxruntime_flatbuffers EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() - diff --git a/cmake/onnxruntime_framework.cmake b/cmake/onnxruntime_framework.cmake index 9f8d807fad8f4..15f3105b34ecb 100644 --- a/cmake/onnxruntime_framework.cmake +++ b/cmake/onnxruntime_framework.cmake @@ -36,10 +36,7 @@ elseif(onnxruntime_ENABLE_TRITON) endif() if (onnxruntime_MINIMAL_BUILD) - set(onnxruntime_framework_src_exclude - "${ONNXRUNTIME_ROOT}/core/framework/fallback_cpu_capability.h" - "${ONNXRUNTIME_ROOT}/core/framework/fallback_cpu_capability.cc" - ) + set(onnxruntime_framework_src_exclude) # custom ops support must be explicitly enabled in a minimal build. exclude if not. if (NOT onnxruntime_MINIMAL_BUILD_CUSTOM_OPS) @@ -66,34 +63,28 @@ endif() if(onnxruntime_ENABLE_INSTRUMENT) target_compile_definitions(onnxruntime_framework PRIVATE ONNXRUNTIME_ENABLE_INSTRUMENT) endif() -if(onnxruntime_USE_TENSORRT OR onnxruntime_USE_NCCL) +if(onnxruntime_USE_TENSORRT OR onnxruntime_USE_NCCL OR onnxruntime_USE_NV) # TODO: for now, core framework depends on CUDA. It should be moved to TensorRT EP # TODO: provider_bridge_ort.cc should not include nccl.h -target_include_directories(onnxruntime_framework PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS} PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) +target_include_directories(onnxruntime_framework PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} PUBLIC ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) else() -target_include_directories(onnxruntime_framework PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS} PUBLIC ${CMAKE_CURRENT_BINARY_DIR}) +target_include_directories(onnxruntime_framework PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR}) endif() # Needed for the provider interface, as it includes training headers when training is enabled if (onnxruntime_ENABLE_TRAINING_OPS) target_include_directories(onnxruntime_framework PRIVATE ${ORTTRAINING_ROOT}) if (onnxruntime_ENABLE_TRAINING_TORCH_INTEROP OR onnxruntime_ENABLE_TRITON) - onnxruntime_add_include_to_target(onnxruntime_framework Python::Module) - target_include_directories(onnxruntime_framework PRIVATE ${dlpack_SOURCE_DIR}/include) + onnxruntime_add_include_to_target(onnxruntime_framework Python::Module dlpack::dlpack) endif() endif() -if (onnxruntime_USE_MPI) - target_include_directories(onnxruntime_framework PUBLIC ${MPI_CXX_INCLUDE_DIRS}) -endif() if (onnxruntime_ENABLE_ATEN) - # DLPack is a header-only dependency - set(DLPACK_INCLUDE_DIR ${dlpack_SOURCE_DIR}/include) - target_include_directories(onnxruntime_framework PRIVATE ${DLPACK_INCLUDE_DIR}) + onnxruntime_add_include_to_target(onnxruntime_framework dlpack::dlpack) endif() -onnxruntime_add_include_to_target(onnxruntime_framework onnxruntime_common onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers safeint_interface Boost::mp11 nlohmann_json::nlohmann_json) +onnxruntime_add_include_to_target(onnxruntime_framework onnxruntime_common onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers safeint_interface Boost::mp11 nlohmann_json::nlohmann_json Eigen3::Eigen) if (onnxruntime_USE_MIMALLOC) - target_link_libraries(onnxruntime_framework mimalloc-static) + onnxruntime_add_include_to_target(onnxruntime_framework mimalloc-static) endif() if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") @@ -108,7 +99,7 @@ add_dependencies(onnxruntime_framework ${onnxruntime_EXTERNAL_DEPENDENCIES}) # For the shared onnxruntime library, this is set in onnxruntime.cmake through CMAKE_SHARED_LINKER_FLAGS # But our test files don't use the shared library so this must be set for them. # For Win32 it generates an absolute path for shared providers based on the location of the executable/onnxruntime.dll -if (UNIX AND NOT APPLE AND NOT onnxruntime_MINIMAL_BUILD AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") +if (UNIX AND NOT APPLE AND NOT onnxruntime_MINIMAL_BUILD AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND NOT CMAKE_SYSTEM_NAME MATCHES "AIX") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'") endif() @@ -127,7 +118,7 @@ if (onnxruntime_BUILD_SHARED_LIB) install(FILES ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/framework/provider_options.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/) else() install(DIRECTORY ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/framework DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/core) - install(TARGETS onnxruntime_framework + install(TARGETS onnxruntime_framework EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/cmake/onnxruntime_fuzz_test.cmake b/cmake/onnxruntime_fuzz_test.cmake index eea411d938176..2935b58ffa61a 100644 --- a/cmake/onnxruntime_fuzz_test.cmake +++ b/cmake/onnxruntime_fuzz_test.cmake @@ -60,7 +60,7 @@ if (onnxruntime_FUZZ_ENABLED) # compile the executables onnxruntime_add_executable(onnxruntime_security_fuzz ${SEC_FUZ_SRC}) - # compile with c++17 + # compile with at least c++17 target_compile_features(onnxruntime_security_fuzz PUBLIC cxx_std_17) # Security fuzzing engine header file reference diff --git a/cmake/onnxruntime_graph.cmake b/cmake/onnxruntime_graph.cmake index 4d51325b8414e..fba1a680bb62a 100644 --- a/cmake/onnxruntime_graph.cmake +++ b/cmake/onnxruntime_graph.cmake @@ -157,7 +157,7 @@ endif() if (NOT onnxruntime_BUILD_SHARED_LIB) install(DIRECTORY ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/graph DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/core) - install(TARGETS onnxruntime_graph + install(TARGETS onnxruntime_graph EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/cmake/onnxruntime_java.cmake b/cmake/onnxruntime_java.cmake index 1227264e595ed..7da63b523be70 100644 --- a/cmake/onnxruntime_java.cmake +++ b/cmake/onnxruntime_java.cmake @@ -58,6 +58,15 @@ file(GLOB onnxruntime4j_native_src onnxruntime_add_shared_library_module(onnxruntime4j_jni ${onnxruntime4j_native_src}) set_property(TARGET onnxruntime4j_jni PROPERTY C_STANDARD 11) +if (APPLE) + set_target_properties(onnxruntime4j_jni PROPERTIES + MACOSX_RPATH TRUE + SKIP_BUILD_RPATH TRUE + INSTALL_RPATH_USE_LINK_PATH FALSE + BUILD_WITH_INSTALL_NAME_DIR TRUE + INSTALL_NAME_DIR @rpath) +endif() + # depend on java sources. if they change, the JNI should recompile add_dependencies(onnxruntime4j_jni onnxruntime4j) onnxruntime_add_include_to_target(onnxruntime4j_jni onnxruntime_session) @@ -101,6 +110,8 @@ elseif (X86_64) set(JNI_ARCH x64) elseif (POWER) set(JNI_ARCH ppc64) +elseif (LOONGARCH64) + set(JNI_ARCH loongarch64) else() # Now mirror the checks used with MSVC if(MSVC) @@ -148,7 +159,7 @@ if (WIN32) if(NOT onnxruntime_ENABLE_STATIC_ANALYSIS) add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${JAVA_PACKAGE_LIB_DIR}/$) add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${JAVA_PACKAGE_JNI_DIR}/$) - if (onnxruntime_USE_CUDA OR onnxruntime_USE_DNNL OR onnxruntime_USE_OPENVINO OR onnxruntime_USE_TENSORRT OR (onnxruntime_USE_QNN AND NOT onnxruntime_BUILD_QNN_EP_STATIC_LIB)) + if (TARGET onnxruntime_providers_shared) add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${JAVA_PACKAGE_LIB_DIR}/$) endif() if (onnxruntime_USE_CUDA) @@ -166,11 +177,37 @@ if (WIN32) if (onnxruntime_USE_QNN AND NOT onnxruntime_BUILD_QNN_EP_STATIC_LIB) add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${JAVA_PACKAGE_LIB_DIR}/$) endif() + if (onnxruntime_USE_WEBGPU) + if (onnxruntime_ENABLE_DAWN_BACKEND_D3D12) + # TODO: the following code is used to disable building Dawn using vcpkg temporarily + # until we figure out how to resolve the packaging pipeline failures + # + # if (onnxruntime_USE_VCPKG) + if (FALSE) + add_custom_command( + TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different + $ + $ + ${JAVA_PACKAGE_LIB_DIR}/ + ) + else() + add_custom_command( + TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different + $/dxil.dll + $/dxcompiler.dll + ${JAVA_PACKAGE_LIB_DIR}/ + ) + endif() + endif() + if (onnxruntime_BUILD_DAWN_SHARED_LIBRARY) + add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${JAVA_PACKAGE_LIB_DIR}/$) + endif() + endif() endif() else() add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${JAVA_PACKAGE_LIB_DIR}/$) add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${JAVA_PACKAGE_JNI_DIR}/$) - if (onnxruntime_USE_CUDA OR onnxruntime_USE_DNNL OR onnxruntime_USE_OPENVINO OR onnxruntime_USE_TENSORRT OR (onnxruntime_USE_QNN AND NOT onnxruntime_BUILD_QNN_EP_STATIC_LIB)) + if (TARGET onnxruntime_providers_shared) add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${JAVA_PACKAGE_LIB_DIR}/$) endif() if (onnxruntime_USE_CUDA) @@ -188,6 +225,9 @@ else() if (onnxruntime_USE_QNN AND NOT onnxruntime_BUILD_QNN_EP_STATIC_LIB) add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${JAVA_PACKAGE_LIB_DIR}/$) endif() + if (onnxruntime_USE_WEBGPU AND onnxruntime_BUILD_DAWN_SHARED_LIBRARY) + add_custom_command(TARGET onnxruntime4j_jni POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${JAVA_PACKAGE_LIB_DIR}/$) + endif() endif() # run the build process (this copies the results back into CMAKE_CURRENT_BINARY_DIR) diff --git a/cmake/onnxruntime_kernel_explorer.cmake b/cmake/onnxruntime_kernel_explorer.cmake deleted file mode 100644 index 62a6d45088052..0000000000000 --- a/cmake/onnxruntime_kernel_explorer.cmake +++ /dev/null @@ -1,92 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - -include(CheckLanguage) - -if(NOT onnxruntime_ENABLE_PYTHON) - message(FATAL_ERROR "python is required but is not enabled") -endif() - -set(KERNEL_EXPLORER_ROOT ${ONNXRUNTIME_ROOT}/python/tools/kernel_explorer) - -if (onnxruntime_USE_CUDA) - check_language(CUDA) - set(LANGUAGE CUDA) - set(BERT_DIR ${ONNXRUNTIME_ROOT}/contrib_ops/cuda/bert) -elseif(onnxruntime_USE_ROCM) - check_language(HIP) - set(LANGUAGE HIP) - if (onnxruntime_USE_COMPOSABLE_KERNEL) - include(composable_kernel) - endif() - if (onnxruntime_USE_HIPBLASLT) - find_package(hipblaslt REQUIRED) - endif() - set(BERT_DIR ${ONNXRUNTIME_ROOT}/contrib_ops/rocm/bert) -endif() - -file(GLOB kernel_explorer_srcs CONFIGURE_DEPENDS - "${KERNEL_EXPLORER_ROOT}/*.cc" - "${KERNEL_EXPLORER_ROOT}/*.h" -) - -file(GLOB kernel_explorer_kernel_srcs CONFIGURE_DEPENDS - "${KERNEL_EXPLORER_ROOT}/kernels/*.cc" - "${KERNEL_EXPLORER_ROOT}/kernels/*.h" - "${KERNEL_EXPLORER_ROOT}/kernels/*.cu" - "${KERNEL_EXPLORER_ROOT}/kernels/*.cuh" -) - -onnxruntime_add_shared_library_module(kernel_explorer ${kernel_explorer_srcs} ${kernel_explorer_kernel_srcs}) -set_target_properties(kernel_explorer PROPERTIES PREFIX "_") -target_include_directories(kernel_explorer PUBLIC - $ - ${KERNEL_EXPLORER_ROOT}) -target_link_libraries(kernel_explorer PRIVATE $) -target_compile_definitions(kernel_explorer PRIVATE $) -target_compile_options(kernel_explorer PRIVATE -Wno-sign-compare) - -if (onnxruntime_USE_CUDA) - file(GLOB kernel_explorer_cuda_kernel_srcs CONFIGURE_DEPENDS - "${KERNEL_EXPLORER_ROOT}/kernels/cuda/*.cc" - "${KERNEL_EXPLORER_ROOT}/kernels/cuda/*.h" - "${KERNEL_EXPLORER_ROOT}/kernels/cuda/*.cu" - "${KERNEL_EXPLORER_ROOT}/kernels/cuda/*.cuh" - ) - target_sources(kernel_explorer PRIVATE ${kernel_explorer_cuda_kernel_srcs}) - target_include_directories(kernel_explorer PUBLIC ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) -elseif (onnxruntime_USE_ROCM) - file(GLOB kernel_explorer_rocm_kernel_srcs CONFIGURE_DEPENDS - "${KERNEL_EXPLORER_ROOT}/kernels/rocm/*.cc" - "${KERNEL_EXPLORER_ROOT}/kernels/rocm/*.h" - "${KERNEL_EXPLORER_ROOT}/kernels/rocm/*.cu" - "${KERNEL_EXPLORER_ROOT}/kernels/rocm/*.cuh" - ) - auto_set_source_files_hip_language(${kernel_explorer_kernel_srcs} ${kernel_explorer_rocm_kernel_srcs}) - target_sources(kernel_explorer PRIVATE ${kernel_explorer_rocm_kernel_srcs}) - target_compile_definitions(kernel_explorer PRIVATE __HIP_PLATFORM_AMD__=1 __HIP_PLATFORM_HCC__=1 HIPBLAS_V2) - if (onnxruntime_USE_COMPOSABLE_KERNEL) - target_compile_definitions(kernel_explorer PRIVATE USE_COMPOSABLE_KERNEL) - if (onnxruntime_USE_COMPOSABLE_KERNEL_CK_TILE) - target_compile_definitions(kernel_explorer PRIVATE USE_COMPOSABLE_KERNEL_CK_TILE) - endif() - target_link_libraries(kernel_explorer PRIVATE onnxruntime_composable_kernel_includes) - endif() - if (onnxruntime_USE_TRITON_KERNEL) - target_compile_definitions(kernel_explorer PRIVATE USE_TRITON_KERNEL) - endif() - if (onnxruntime_USE_HIPBLASLT) - target_compile_definitions(kernel_explorer PRIVATE USE_HIPBLASLT) - endif() - if (onnxruntime_USE_ROCBLAS_EXTENSION_API) - target_compile_definitions(kernel_explorer PRIVATE USE_ROCBLAS_EXTENSION_API) - target_compile_definitions(kernel_explorer PRIVATE ROCBLAS_NO_DEPRECATED_WARNINGS) - target_compile_definitions(kernel_explorer PRIVATE ROCBLAS_BETA_FEATURES_API) - endif() -endif() - -add_dependencies(kernel_explorer onnxruntime_pybind11_state) - -enable_testing() -find_package(Python COMPONENTS Interpreter REQUIRED) -# add_test(NAME test_kernels COMMAND ${Python_EXECUTABLE} -m pytest ..) diff --git a/cmake/onnxruntime_language_standard_versions.cmake b/cmake/onnxruntime_language_standard_versions.cmake new file mode 100644 index 0000000000000..85546ec9759ea --- /dev/null +++ b/cmake/onnxruntime_language_standard_versions.cmake @@ -0,0 +1,76 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +# +# Minimum required language standard versions. +# + +set(onnxruntime_MINIMUM_C_STANDARD_VERSION 99) +set(onnxruntime_MINIMUM_CXX_STANDARD_VERSION 20) + +# +# Handle CMAKE__STANDARD variables. +# +# We only set them if unset. Otherwise, enforce a minimum value. +# +# We care about the CMAKE__STANDARD variables because we typically want our dependencies to be built with the +# same language standard versions as the rest of our code. +# E.g., this is important for Abseil. +# + +# "Normalize" means make suitable for comparison. +function(onnxruntime_normalize_language_standard_version + language_standard_version_var_name + version + normalized_version_var_name) + set(normalized_version ${version}) + + # Note: For CMAKE_C_STANDARD and CMAKE_CXX_STANDARD, we assume two-digit versions based on years. + if("${language_standard_version_var_name}" STREQUAL "CMAKE_C_STANDARD") + if("${version}" EQUAL "90" OR "${version}" EQUAL "99") + set(base_year 1900) + else() + set(base_year 2000) + endif() + math(EXPR normalized_version "${base_year} + ${version}") + elseif("${language_standard_version_var_name}" STREQUAL "CMAKE_CXX_STANDARD") + if("${version}" EQUAL "98") + set(base_year 1900) + else() + set(base_year 2000) + endif() + math(EXPR normalized_version "${base_year} + ${version}") + endif() + + set(${normalized_version_var_name} ${normalized_version} PARENT_SCOPE) +endfunction() + +function(onnxruntime_ensure_minimum_language_standard_version + language_standard_version_var_name + minimum_version) + if(DEFINED ${language_standard_version_var_name}) + onnxruntime_normalize_language_standard_version( + ${language_standard_version_var_name} "${minimum_version}" normalized_minimum_version) + onnxruntime_normalize_language_standard_version( + ${language_standard_version_var_name} "${${language_standard_version_var_name}}" normalized_version) + + if(normalized_version VERSION_LESS normalized_minimum_version) + message(FATAL_ERROR "${language_standard_version_var_name} must be at least ${minimum_version}. " + "It is ${${language_standard_version_var_name}}.") + endif() + else() + message(STATUS "Setting ${language_standard_version_var_name} to ${minimum_version}") + set(${language_standard_version_var_name} ${minimum_version} PARENT_SCOPE) + endif() +endfunction() + +onnxruntime_ensure_minimum_language_standard_version(CMAKE_C_STANDARD ${onnxruntime_MINIMUM_C_STANDARD_VERSION}) +onnxruntime_ensure_minimum_language_standard_version(CMAKE_CXX_STANDARD ${onnxruntime_MINIMUM_CXX_STANDARD_VERSION}) + +# +# Define onnxruntime__std_compile_feature variables specifying the standard version compile feature name. +# These should be used by all onnxruntime targets via target_compile_features(). +# + +set(onnxruntime_c_std_compile_feature c_std_${onnxruntime_MINIMUM_C_STANDARD_VERSION}) +set(onnxruntime_cxx_std_compile_feature cxx_std_${onnxruntime_MINIMUM_CXX_STANDARD_VERSION}) diff --git a/cmake/onnxruntime_lora.cmake b/cmake/onnxruntime_lora.cmake index 7ba48454d997e..e0579f571e1e0 100644 --- a/cmake/onnxruntime_lora.cmake +++ b/cmake/onnxruntime_lora.cmake @@ -10,8 +10,7 @@ file(GLOB onnxruntime_lora_srcs CONFIGURE_DEPENDS source_group(TREE ${REPO_ROOT} FILES ${onnxruntime_lora_srcs}) onnxruntime_add_static_library(onnxruntime_lora ${onnxruntime_lora_srcs}) -onnxruntime_add_include_to_target(onnxruntime_lora onnx flatbuffers::flatbuffers Boost::mp11 ${GSL_TARGET}) -target_link_libraries(onnxruntime_lora onnxruntime_framework) +onnxruntime_add_include_to_target(onnxruntime_lora onnxruntime_framework onnxruntime_common onnx flatbuffers::flatbuffers Boost::mp11 ${GSL_TARGET}) if(onnxruntime_ENABLE_INSTRUMENT) target_compile_definitions(onnxruntime_lora PUBLIC ONNXRUNTIME_ENABLE_INSTRUMENT) @@ -22,7 +21,7 @@ add_dependencies(onnxruntime_lora ${onnxruntime_EXTERNAL_DEPENDENCIES}) set_target_properties(onnxruntime_lora PROPERTIES FOLDER "ONNXRuntime") if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_lora + install(TARGETS onnxruntime_lora EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/cmake/onnxruntime_mlas.cmake b/cmake/onnxruntime_mlas.cmake index ed3ad89247975..3fc918c6babea 100644 --- a/cmake/onnxruntime_mlas.cmake +++ b/cmake/onnxruntime_mlas.cmake @@ -1,10 +1,23 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. +message(STATUS "++++++++ Paco START onnxruntime_mlas.cmake") +MESSAGE( STATUS "CMAKE_CXX_FLAGS: " ${CMAKE_CXX_FLAGS} ) +MESSAGE( STATUS "CMAKE_C_FLAGS: " ${CMAKE_C_FLAGS} ) +message(STATUS "++++++++ Paco END") + +#message(FATAL_ERROR get_property(target_names DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} PROPERTY BUILDSYSTEM_TARGETS)) set(MLAS_ROOT ${ONNXRUNTIME_ROOT}/core/mlas) set(MLAS_SRC_DIR ${MLAS_ROOT}/lib) set(MLAS_INC_DIR ${MLAS_ROOT}/inc) + +# mlas_private_compile_definitions contains compile definitions that are private to onnxruntime_mlas and targets which +# use internal MLAS headers like mlasi.h. +set(mlas_private_compile_definitions) +if(onnxruntime_BUILD_UNIT_TESTS) + list(APPEND mlas_private_compile_definitions MLAS_ENABLE_TEST_HOOKS) +endif() # # All hardware agnostic source files here # hardware specific files would cause trouble in @@ -19,6 +32,7 @@ onnxruntime_add_static_library(onnxruntime_mlas ${MLAS_SRC_DIR}/qgemm.cpp ${MLAS_SRC_DIR}/qdwconv.cpp ${MLAS_SRC_DIR}/convolve.cpp + ${MLAS_SRC_DIR}/sconv_nchw_depthwise_multiplier_greater_than_1.cpp ${MLAS_SRC_DIR}/convsym.cpp ${MLAS_SRC_DIR}/pooling.cpp ${MLAS_SRC_DIR}/transpose.cpp @@ -27,8 +41,13 @@ onnxruntime_add_static_library(onnxruntime_mlas ${MLAS_SRC_DIR}/activate.cpp ${MLAS_SRC_DIR}/logistic.cpp ${MLAS_SRC_DIR}/tanh.cpp + ${MLAS_SRC_DIR}/eltwise.h + ${MLAS_SRC_DIR}/eltwise.cpp ${MLAS_SRC_DIR}/erf.cpp + ${MLAS_SRC_DIR}/silu.cpp + ${MLAS_SRC_DIR}/gelu.cpp ${MLAS_SRC_DIR}/compute.cpp + ${MLAS_SRC_DIR}/dequantize.cpp ${MLAS_SRC_DIR}/quantize.cpp ${MLAS_SRC_DIR}/qgemm_kernel_default.cpp ${MLAS_SRC_DIR}/qladd.cpp @@ -38,11 +57,15 @@ onnxruntime_add_static_library(onnxruntime_mlas ${MLAS_SRC_DIR}/qdwconv_kernelsize.cpp ${MLAS_SRC_DIR}/qnbitgemm.h ${MLAS_SRC_DIR}/qnbitgemm.cpp + ${MLAS_SRC_DIR}/qlutgemm.h + ${MLAS_SRC_DIR}/qlutgemm.cpp ${MLAS_SRC_DIR}/sqnbitgemm_q8_block.h ${MLAS_SRC_DIR}/flashattn.cpp ${MLAS_SRC_DIR}/cast.cpp ${MLAS_SRC_DIR}/rotary_embedding.h ${MLAS_SRC_DIR}/rotary_embedding.cpp + ${MLAS_SRC_DIR}/softmax.h + ${MLAS_SRC_DIR}/saturation_check.cpp ) target_sources(onnxruntime_mlas PRIVATE @@ -92,11 +115,20 @@ function(setup_mlas_source_for_windows) ${MLAS_SRC_DIR}/sqnbitgemm_kernel_neon_int8.cpp ${MLAS_SRC_DIR}/cast_kernel_neon.cpp ${MLAS_SRC_DIR}/hqnbitgemm_kernel_neon_fp16.cpp + ${MLAS_SRC_DIR}/hqnbitgemm_kernel_neon_fp16_8bit.cpp ${MLAS_SRC_DIR}/rotary_embedding_kernel_neon.h ${MLAS_SRC_DIR}/rotary_embedding_kernel_neon.cpp ${MLAS_SRC_DIR}/rotary_embedding_kernel_neon_fp16.cpp ${MLAS_SRC_DIR}/hgemm_kernel_neon.cpp ${MLAS_SRC_DIR}/halfgemm_kernel_neon_fp16.cpp + ${MLAS_SRC_DIR}/softmax_kernel_neon.h + ${MLAS_SRC_DIR}/softmax_kernel_neon.cpp + ${MLAS_SRC_DIR}/softmax_kernel_neon_fp16.cpp + ${MLAS_SRC_DIR}/eltwise_kernel_neon.h + ${MLAS_SRC_DIR}/eltwise_kernel_neon.cpp + ${MLAS_SRC_DIR}/eltwise_kernel_neon_fp16.cpp + ${MLAS_SRC_DIR}/sqnbitgemm_kernel_neon_int8_i8mm.cpp + ${MLAS_SRC_DIR}/sconv_nchw_depthwise_multiplier_1.cpp ) set(mlas_platform_preprocess_srcs @@ -119,6 +151,14 @@ function(setup_mlas_source_for_windows) ${MLAS_SRC_DIR}/arm64/SymQgemmS8KernelSDot.asm ${MLAS_SRC_DIR}/arm64/SymQgemmS8KernelSDotLd64.asm ) + + if (onnxruntime_USE_ARM_NEON_NCHWC) + setup_arm_neon_nchwc() + endif() + + if (onnxruntime_USE_KLEIDIAI) + setup_kleidiai() + endif() else() target_sources(onnxruntime_mlas PRIVATE ${MLAS_SRC_DIR}/qgemm_kernel_neon.cpp @@ -173,15 +213,29 @@ function(setup_mlas_source_for_windows) ) set_source_files_properties(${mlas_platform_srcs_avx2} PROPERTIES COMPILE_FLAGS "/arch:AVX2") + set(mlas_platform_srcs_avx512 + ${MLAS_SRC_DIR}/intrinsics/avx512/gelu_avx512f.cpp + ${MLAS_SRC_DIR}/intrinsics/avx512/silu_avx512f.cpp + ${MLAS_SRC_DIR}/intrinsics/avx512/quantize_avx512f.cpp + ${MLAS_SRC_DIR}/intrinsics/avx512/sconv_nchw_depthwise_multiplier_greater_than_1_avx512f.cpp + ) + + set_source_files_properties(${mlas_platform_srcs_avx512} PROPERTIES COMPILE_FLAGS "/arch:AVX512") + target_sources(onnxruntime_mlas PRIVATE ${MLAS_SRC_DIR}/dgemm.cpp ${mlas_platform_srcs_avx} ${mlas_platform_srcs_avx2} + ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.h + ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.cpp + ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.cpp ${MLAS_SRC_DIR}/qgemm_kernel_amx.cpp ${MLAS_SRC_DIR}/qgemm_kernel_avx2.cpp ${MLAS_SRC_DIR}/qgemm_kernel_sse.cpp ${MLAS_SRC_DIR}/qgemm_kernel_sse41.cpp - ${MLAS_SRC_DIR}/intrinsics/avx512/quantize_avx512f.cpp + ${mlas_platform_srcs_avx512} + ${MLAS_SRC_DIR}/sqnbitgemm_lut_kernel_avx2.h + ${MLAS_SRC_DIR}/sqnbitgemm_lut_kernel_avx2.cpp ${MLAS_SRC_DIR}/sqnbitgemm_kernel_avx2.cpp ${MLAS_SRC_DIR}/sqnbitgemm_kernel_avx512.cpp ${MLAS_SRC_DIR}/sqnbitgemm_kernel_avx512vnni.cpp @@ -222,6 +276,11 @@ function(setup_mlas_source_for_windows) ${MLAS_SRC_DIR}/amd64/TanhKernelFma3.asm ${MLAS_SRC_DIR}/amd64/ErfKernelFma3.asm ) + + if(onnxruntime_ENABLE_CONVSYMKERNELAVX2_SAT_CHECKER) + set_source_files_properties(${MLAS_SRC_DIR}/amd64/ConvSymKernelAvx2.asm PROPERTIES COMPILE_FLAGS "-DENABLE_CONVSYMKERNELAVX2_SAT_CHECKER") + endif() + if(MSVC_VERSION GREATER_EQUAL 1933) target_sources(onnxruntime_mlas PRIVATE ${MLAS_SRC_DIR}/amd64/cvtfp16Avx.asm @@ -243,6 +302,70 @@ function(setup_mlas_source_for_windows) endif() endfunction() +function(setup_kleidiai) + target_sources(onnxruntime_mlas PRIVATE + ${MLAS_SRC_DIR}/kai_ukernel_interface.cpp + ${MLAS_SRC_DIR}/kleidiai/sgemm_kleidiai.cpp + ${MLAS_SRC_DIR}/kleidiai/sbgemm_kleidiai.cpp + ${MLAS_SRC_DIR}/kleidiai/convolve_kleidiai.cpp + ${MLAS_SRC_DIR}/kleidiai/qgemm_kleidiai.cpp + ) + target_link_libraries(onnxruntime_mlas PRIVATE kleidiai) + list(APPEND onnxruntime_EXTERNAL_LIBRARIES kleidiai) + if(onnxruntime_USE_QMX_KLEIDIAI_COEXIST) + target_link_libraries(onnxruntime_mlas PRIVATE kleidiai-qmx) + target_compile_definitions(onnxruntime_mlas PRIVATE ENABLE_QMX_KERNELS=1) + list(APPEND onnxruntime_EXTERNAL_LIBRARIES kleidiai-qmx) + endif() + set(onnxruntime_EXTERNAL_LIBRARIES ${onnxruntime_EXTERNAL_LIBRARIES} PARENT_SCOPE) + + # If KLEIDIAI_DEBUG_LOGGING is enabled that implies both DEBUG and KERNEL messages. + if(onnxruntime_KLEIDIAI_DEBUG_LOGGING) + target_compile_definitions(onnxruntime_mlas PRIVATE KLEIDIAI_DEBUG_LOGGING=1) + target_compile_definitions(onnxruntime_mlas PRIVATE KLEIDIAI_KERNEL_LOGGING=1) + endif() + if(onnxruntime_KLEIDIAI_KERNEL_LOGGING) + target_compile_definitions(onnxruntime_mlas PRIVATE KLEIDIAI_KERNEL_LOGGING=1) + endif() + + if (NOT onnxruntime_BUILD_SHARED_LIB) + install(TARGETS kleidiai EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() + + if(onnxruntime_USE_QMX_KLEIDIAI_COEXIST) + install(TARGETS kleidiai-qmx EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() +endfunction() + +function (setup_arm_neon_nchwc) + target_sources(onnxruntime_mlas PRIVATE + ${MLAS_SRC_DIR}/sconv_nchwc_kernel_neon.h + ${MLAS_SRC_DIR}/sconv_nchwc_kernel_neon.cpp + ${MLAS_SRC_DIR}/spool_nchwc_kernel_neon.cpp + ) + if(NOT WIN32) + target_sources(onnxruntime_mlas PRIVATE + # Hand written AArch64 micro-kernel for NCHW convolution. Using a + # separate assembly file allows tighter control over register allocation + # and avoids the overhead of C++/intrinsics based code generation. + ${MLAS_SRC_DIR}/aarch64/SconvKernelNeon.S + ${MLAS_SRC_DIR}/aarch64/SconvNchwcKernelNeon.S + ${MLAS_SRC_DIR}/aarch64/SconvDepthwiseKernelNeon.S + ${MLAS_SRC_DIR}/aarch64/SconvPointwiseKernelNeon.S + ) + endif() + list(APPEND mlas_private_compile_definitions MLAS_USE_ARM_NEON_NCHWC) + set(mlas_private_compile_definitions ${mlas_private_compile_definitions} PARENT_SCOPE) +endfunction () + if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") if (onnxruntime_ENABLE_WEBASSEMBLY_SIMD) file(GLOB_RECURSE mlas_platform_srcs @@ -252,6 +375,12 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") ${mlas_platform_srcs} ${MLAS_SRC_DIR}/qgemm_kernel_wasmsimd.cpp ) + if (onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD) + set(mlas_platform_srcs + ${mlas_platform_srcs} + ${MLAS_SRC_DIR}/qgemm_kernel_wasmrelaxedsimd.cpp + ) + endif() else() file(GLOB_RECURSE mlas_platform_srcs "${MLAS_SRC_DIR}/scalar/*.cpp" @@ -261,7 +390,6 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") elseif(MSVC) setup_mlas_source_for_windows() else() - if(APPLE) get_target_property(ONNXRUNTIME_MLAS_OSX_ARCH onnxruntime_mlas OSX_ARCHITECTURES) @@ -316,8 +444,12 @@ else() set(X86 TRUE) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^(x86_64|amd64)$") set(X86_64 TRUE) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^riscv64.*") + set(RISCV64 TRUE) elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^loongarch64.*") set(LOONGARCH64 TRUE) + elseif(CMAKE_SYSTEM_PROCESSOR MATCHES "^s390x$") + set(S390X TRUE) endif() endif() @@ -377,9 +509,37 @@ else() ${MLAS_SRC_DIR}/rotary_embedding_kernel_neon.h ${MLAS_SRC_DIR}/rotary_embedding_kernel_neon.cpp ${MLAS_SRC_DIR}/hgemm_kernel_neon.cpp + ${MLAS_SRC_DIR}/softmax_kernel_neon.h + ${MLAS_SRC_DIR}/softmax_kernel_neon.cpp + ${MLAS_SRC_DIR}/eltwise_kernel_neon.h + ${MLAS_SRC_DIR}/eltwise_kernel_neon.cpp + ${MLAS_SRC_DIR}/sqnbitgemm_kernel_neon_int8_i8mm.cpp + ${MLAS_SRC_DIR}/sconv_nchw_depthwise_multiplier_1.cpp ) + + # Conditionally add the SVE implementation if compiler supports it + if (onnxruntime_USE_SVE) + list(APPEND mlas_platform_srcs ${MLAS_SRC_DIR}/sve/mlasi_sve.h) + list(APPEND mlas_platform_srcs ${MLAS_SRC_DIR}/sve/elementwise_sve.cpp) + list(APPEND mlas_platform_srcs ${MLAS_SRC_DIR}/sve/elementwise_sve_fp16.cpp) + list(APPEND mlas_platform_srcs ${MLAS_SRC_DIR}/sve/mlas_sve_fp16.h) + set_source_files_properties(${MLAS_SRC_DIR}/sve/elementwise_sve.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+sve+fp16 ") + set_source_files_properties(${MLAS_SRC_DIR}/sve/elementwise_sve_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+sve+fp16 ") + list(APPEND mlas_private_compile_definitions MLAS_USE_SVE) + endif() + + if (onnxruntime_USE_ARM_NEON_NCHWC) + setup_arm_neon_nchwc() + endif() + + if (onnxruntime_USE_KLEIDIAI) + setup_kleidiai() + endif() set_source_files_properties(${MLAS_SRC_DIR}/sqnbitgemm_kernel_neon_int8.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+dotprod") + set_source_files_properties(${MLAS_SRC_DIR}/sqnbitgemm_kernel_neon_int8_i8mm.cpp + PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+i8mm ") + if (NOT APPLE) set(mlas_platform_srcs ${mlas_platform_srcs} @@ -394,11 +554,26 @@ else() ${MLAS_SRC_DIR}/qgemm_kernel_smmla.cpp ${MLAS_SRC_DIR}/qgemm_kernel_ummla.cpp ${MLAS_SRC_DIR}/sbgemm_kernel_neon.cpp + ${MLAS_SRC_DIR}/sbconv_kernel_neon.cpp ${MLAS_SRC_DIR}/cast_kernel_neon.cpp ${MLAS_SRC_DIR}/hqnbitgemm_kernel_neon_fp16.cpp + ${MLAS_SRC_DIR}/hqnbitgemm_kernel_neon_fp16_8bit.cpp ${MLAS_SRC_DIR}/rotary_embedding_kernel_neon_fp16.cpp ${MLAS_SRC_DIR}/halfgemm_kernel_neon_fp16.cpp + ${MLAS_SRC_DIR}/softmax_kernel_neon_fp16.cpp + ${MLAS_SRC_DIR}/eltwise_kernel_neon_fp16.cpp + ${MLAS_SRC_DIR}/erf_neon_fp16.h + ${MLAS_SRC_DIR}/erf_neon_fp16.cpp + ${MLAS_SRC_DIR}/gelu_neon_fp16.h + ${MLAS_SRC_DIR}/gelu_neon_fp16.cpp ) + if (onnxruntime_USE_ARM_NEON_NCHWC) + list(APPEND mlas_platform_srcs + ${MLAS_SRC_DIR}/aarch64/SconvDepthwiseKernelNeonBf16.S + ${MLAS_SRC_DIR}/aarch64/SconvKernelNeonBf16.S + ${MLAS_SRC_DIR}/aarch64/SconvPointwiseKernelNeonBf16.S + ) + endif() set_source_files_properties(${MLAS_SRC_DIR}/aarch64/HalfGemmKernelNeon.S PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") set_source_files_properties(${MLAS_SRC_DIR}/aarch64/QgemmS8S8KernelSmmla.S PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+i8mm ") set_source_files_properties(${MLAS_SRC_DIR}/aarch64/QgemmU8X8KernelUmmla.S PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+i8mm ") @@ -407,10 +582,21 @@ else() set_source_files_properties(${MLAS_SRC_DIR}/dwconv.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") set_source_files_properties(${MLAS_SRC_DIR}/pooling_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") set_source_files_properties(${MLAS_SRC_DIR}/sbgemm_kernel_neon.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+bf16 ") + set_source_files_properties(${MLAS_SRC_DIR}/sbconv_kernel_neon.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+bf16 ") set_source_files_properties(${MLAS_SRC_DIR}/cast_kernel_neon.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") set_source_files_properties(${MLAS_SRC_DIR}/hqnbitgemm_kernel_neon_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") + set_source_files_properties(${MLAS_SRC_DIR}/hqnbitgemm_kernel_neon_fp16_8bit.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") set_source_files_properties(${MLAS_SRC_DIR}/rotary_embedding_kernel_neon_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") set_source_files_properties(${MLAS_SRC_DIR}/halfgemm_kernel_neon_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") + set_source_files_properties(${MLAS_SRC_DIR}/softmax_kernel_neon_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") + set_source_files_properties(${MLAS_SRC_DIR}/eltwise_kernel_neon_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") + if (onnxruntime_USE_ARM_NEON_NCHWC) + set_source_files_properties(${MLAS_SRC_DIR}/aarch64/SconvDepthwiseKernelNeonBf16.S PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+bf16 ") + set_source_files_properties(${MLAS_SRC_DIR}/aarch64/SconvKernelNeonBf16.S PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+bf16 ") + set_source_files_properties(${MLAS_SRC_DIR}/aarch64/SconvPointwiseKernelNeonBf16.S PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+bf16 ") + endif() + set_source_files_properties(${MLAS_SRC_DIR}/erf_neon_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") + set_source_files_properties(${MLAS_SRC_DIR}/gelu_neon_fp16.cpp PROPERTIES COMPILE_FLAGS " -march=armv8.2-a+fp16 ") endif() if(ONNXRUNTIME_MLAS_MULTI_ARCH) @@ -453,6 +639,7 @@ else() COMPILES_P10 ) if(COMPILES_P10) + enable_language(ASM) check_cxx_source_compiles(" #ifdef _AIX #define POWER_10 0x40000 @@ -482,6 +669,11 @@ else() ${MLAS_SRC_DIR}/power/DgemmKernelPOWER10.cpp ${MLAS_SRC_DIR}/power/qgemm_kernel_power10.cpp ) + # Only compile assembly on non-AIX systems + if (NOT AIX) + list(APPEND mlas_platform_srcs_power10 ${MLAS_SRC_DIR}/power/SgemmKernelPackA.S) + set_source_files_properties(${MLAS_SRC_DIR}/power/SgemmKernelPackA.S PROPERTIES COMPILE_FLAGS "-O2 -mcpu=power10") + endif() set_source_files_properties(${MLAS_SRC_DIR}/power/SgemmKernelPOWER10.cpp PROPERTIES COMPILE_FLAGS "-O2 -mcpu=power10 -DSINGLE") set_source_files_properties(${MLAS_SRC_DIR}/power/DgemmKernelPOWER10.cpp PROPERTIES COMPILE_FLAGS "-O2 -mcpu=power10") set_source_files_properties(${MLAS_SRC_DIR}/power/qgemm_kernel_power10.cpp PROPERTIES COMPILE_FLAGS "-O3 -mcpu=power10") @@ -585,7 +777,13 @@ else() ${MLAS_SRC_DIR}/x86_64/ErfKernelFma3.S ${MLAS_SRC_DIR}/intrinsics/avx2/qladd_avx2.cpp ${MLAS_SRC_DIR}/intrinsics/avx2/qdwconv_avx2.cpp + ${MLAS_SRC_DIR}/intrinsics/avx2/saturation_check_avx2.cpp ${MLAS_SRC_DIR}/sqnbitgemm_kernel_avx2.cpp + ${MLAS_SRC_DIR}/sqnbitgemm_lut_kernel_avx2.h + ${MLAS_SRC_DIR}/sqnbitgemm_lut_kernel_avx2.cpp + ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.h + ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.cpp + ${MLAS_SRC_DIR}/rotary_embedding_kernel_avx2.cpp ) if(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 13.1 AND NOT(APPLE)) set(mlas_platform_srcs_avx2 @@ -611,7 +809,10 @@ endif() ${MLAS_SRC_DIR}/x86_64/SoftmaxKernelAvx512F.S ${MLAS_SRC_DIR}/x86_64/SpoolKernelAvx512F.S ${MLAS_SRC_DIR}/x86_64/TransKernelAvx512F.S + ${MLAS_SRC_DIR}/intrinsics/avx512/gelu_avx512f.cpp + ${MLAS_SRC_DIR}/intrinsics/avx512/silu_avx512f.cpp ${MLAS_SRC_DIR}/intrinsics/avx512/quantize_avx512f.cpp + ${MLAS_SRC_DIR}/intrinsics/avx512/sconv_nchw_depthwise_multiplier_greater_than_1_avx512f.cpp ) set_source_files_properties(${mlas_platform_srcs_avx512f} PROPERTIES COMPILE_FLAGS "-mavx512f") @@ -661,6 +862,10 @@ endif() set_source_files_properties(${MLAS_SRC_DIR}/x86_64/QgemmU8S8KernelAmx.S PROPERTIES COMPILE_FLAGS "-mavx2 -mavx512bw -mavx512dq -mavx512vl -mavx512f") endif() + if(onnxruntime_ENABLE_CONVSYMKERNELAVX2_SAT_CHECKER) + set_source_files_properties(${MLAS_SRC_DIR}/x86_64/ConvSymKernelAvx2.S PROPERTIES COMPILE_FLAGS "-mavx2 -mfma -mf16c -DENABLE_CONVSYMKERNELAVX2_SAT_CHECKER") + endif() + if(ONNXRUNTIME_MLAS_MULTI_ARCH) onnxruntime_add_static_library(onnxruntime_mlas_x86_64 ${mlas_platform_srcs}) set_target_properties(onnxruntime_mlas_x86_64 PROPERTIES OSX_ARCHITECTURES "x86_64") @@ -673,6 +878,7 @@ endif() if(LOONGARCH64 AND MLAS_SOURCE_IS_NOT_SET) set(mlas_platform_srcs ${MLAS_SRC_DIR}/qgemm_kernel_lsx.cpp + ${MLAS_SRC_DIR}/sqnbitgemm_kernel_lasx.cpp ${MLAS_SRC_DIR}/loongarch64/SgemmKernelLasx.S ${MLAS_SRC_DIR}/loongarch64/DgemmKernelLsx.S ${MLAS_SRC_DIR}/loongarch64/DgemmKernelLasx.S @@ -690,6 +896,77 @@ endif() set(MLAS_SOURCE_IS_NOT_SET 0) endif() endif() + if(S390X AND MLAS_SOURCE_IS_NOT_SET) + set(mlas_platform_srcs + ${MLAS_SRC_DIR}/s390x/SgemmKernel.cpp + ${MLAS_SRC_DIR}/s390x/SgemmKernelZVECTOR.cpp + ${MLAS_SRC_DIR}/dgemm.cpp + ${MLAS_SRC_DIR}/s390x/DgemmKernel.cpp + ${MLAS_SRC_DIR}/s390x/Quantize.cpp + ${MLAS_SRC_DIR}/s390x/QuantizeZVECTOR.cpp + ${MLAS_SRC_DIR}/s390x/qgemm_kernel_zvector.cpp + ) + set_source_files_properties(${MLAS_SRC_DIR}/s390x/SgemmKernel.cpp PROPERTIES COMPILE_FLAGS "-DSINGLE") + set_source_files_properties(${MLAS_SRC_DIR}/s390x/SgemmKernelZVECTOR.cpp PROPERTIES COMPILE_FLAGS "-DSINGLE") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -mvx -mzvector -march=z15") + + if(NOT ONNXRUNTIME_MLAS_MULTI_ARCH) + set(MLAS_SOURCE_IS_NOT_SET 0) + endif() + endif() + if(RISCV64 AND MLAS_SOURCE_IS_NOT_SET) + file(GLOB_RECURSE mlas_platform_srcs CONFIGURE_DEPENDS + "${MLAS_SRC_DIR}/scalar/*.cpp") + # Remove scalar depthwise kernel; replaced by the vectorized version + list(REMOVE_ITEM mlas_platform_srcs + "${MLAS_SRC_DIR}/scalar/SconvDepthwiseKernelScalar.cpp") + list(APPEND mlas_platform_srcs + ${MLAS_SRC_DIR}/sconv_nchw_depthwise_multiplier_1.cpp) + + if(onnxruntime_USE_RVV) + set(OLD_CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS}") + set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS} -march=rv64gcv -mabi=lp64d") + check_cxx_source_compiles(" + #include + #include + int main() { + size_t vl = __riscv_vsetvl_e32m1(4); + return static_cast(vl == 0); + }" + HAS_RISCV64_RVV + ) + set(CMAKE_REQUIRED_FLAGS "${OLD_CMAKE_REQUIRED_FLAGS}") + unset(OLD_CMAKE_REQUIRED_FLAGS) + + if(HAS_RISCV64_RVV) + list(APPEND mlas_platform_srcs + ${MLAS_SRC_DIR}/riscv64/sgemm_pack_b_rvv.cpp + ${MLAS_SRC_DIR}/riscv64/sgemm_kernel_rvv.cpp + ${MLAS_SRC_DIR}/riscv64/softmax_kernel_rvv.cpp + ${MLAS_SRC_DIR}/riscv64/sconv_depthwise_kernel_rvv.cpp + ${MLAS_SRC_DIR}/riscv64/sconv_nchwc_kernel_rvv.cpp + ) + list(REMOVE_ITEM mlas_platform_srcs + "${MLAS_SRC_DIR}/sconv_nchw_depthwise_multiplier_1.cpp") + set_source_files_properties( + ${MLAS_SRC_DIR}/riscv64/sgemm_pack_b_rvv.cpp + ${MLAS_SRC_DIR}/riscv64/sgemm_kernel_rvv.cpp + ${MLAS_SRC_DIR}/riscv64/softmax_kernel_rvv.cpp + ${MLAS_SRC_DIR}/riscv64/sconv_depthwise_kernel_rvv.cpp + ${MLAS_SRC_DIR}/riscv64/sconv_nchwc_kernel_rvv.cpp + PROPERTIES COMPILE_FLAGS "-march=rv64gcv -mabi=lp64d") + list(APPEND mlas_private_compile_definitions MLAS_USE_RVV=1) + else() + message( + WARNING + "onnxruntime_USE_RVV was requested, but the compiler does not support rv64gcv RVV intrinsics. Falling back to scalar MLAS kernels.") + endif() + endif() + + if(NOT ONNXRUNTIME_MLAS_MULTI_ARCH) + set(MLAS_SOURCE_IS_NOT_SET 0) + endif() + endif() if(NOT ONNXRUNTIME_MLAS_MULTI_ARCH AND MLAS_SOURCE_IS_NOT_SET) file(GLOB_RECURSE mlas_platform_srcs "${MLAS_SRC_DIR}/scalar/*.cpp") @@ -706,7 +983,9 @@ endif() foreach(mlas_target ${ONNXRUNTIME_MLAS_LIBS}) target_include_directories(${mlas_target} PRIVATE ${MLAS_INC_DIR} ${MLAS_SRC_DIR}) - onnxruntime_add_include_to_target(${mlas_target} ${GSL_TARGET}) + onnxruntime_add_include_to_target(${mlas_target} ${GSL_TARGET} safeint_interface) + + target_compile_definitions(${mlas_target} PRIVATE ${mlas_private_compile_definitions}) set_target_properties(${mlas_target} PROPERTIES FOLDER "ONNXRuntime") endforeach() @@ -719,13 +998,12 @@ if (WIN32) endif() if (PLATFORM_NAME STREQUAL "macabi") - # Needed for maccatalyst C compilation - # i.e. the flags below add "--target=x86_64-apple-ios14.0-macabi -ffunction-sections -fdata-sections" target_compile_options(onnxruntime_mlas PRIVATE ${CMAKE_C_FLAGS}) endif() + if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_mlas + install(TARGETS onnxruntime_mlas EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/cmake/onnxruntime_nodejs.cmake b/cmake/onnxruntime_nodejs.cmake index 355575be3bcf7..cce0810c5bbe8 100644 --- a/cmake/onnxruntime_nodejs.cmake +++ b/cmake/onnxruntime_nodejs.cmake @@ -5,32 +5,12 @@ set(JS_ROOT ${REPO_ROOT}/js) set(JS_COMMON_ROOT ${JS_ROOT}/common) set(JS_NODE_ROOT ${JS_ROOT}/node) -find_program(NPM_CLI - NAMES "npm.cmd" "npm" - DOC "NPM command line client" - REQUIRED -) - -# verify Node.js and NPM -execute_process(COMMAND node --version - WORKING_DIRECTORY ${JS_NODE_ROOT} - OUTPUT_VARIABLE node_version - RESULT_VARIABLE had_error - OUTPUT_STRIP_TRAILING_WHITESPACE) -if(had_error) - message(FATAL_ERROR "Failed to find Node.js: " ${had_error}) -endif() -execute_process(COMMAND ${NPM_CLI} --version - WORKING_DIRECTORY ${JS_NODE_ROOT} - OUTPUT_VARIABLE npm_version - RESULT_VARIABLE had_error - OUTPUT_STRIP_TRAILING_WHITESPACE) -if(had_error) - message(FATAL_ERROR "Failed to find NPM: " ${had_error}) -endif() +# Include the Node.js helper for finding and validating Node.js and NPM +include(node_helper.cmake) # setup ARCH if (APPLE) + list(LENGTH CMAKE_OSX_ARCHITECTURES CMAKE_OSX_ARCHITECTURES_LEN) if (CMAKE_OSX_ARCHITECTURES_LEN GREATER 1) message(FATAL_ERROR "CMake.js does not support multi-architecture for macOS") endif() @@ -74,10 +54,19 @@ endif() if (onnxruntime_USE_WEBGPU) set(NODEJS_BINDING_USE_WEBGPU "--use_webgpu") if (WIN32 AND onnxruntime_ENABLE_DAWN_BACKEND_D3D12) - list(APPEND NODEJS_DLL_DEPS "$/dxil.dll") - list(APPEND NODEJS_DLL_DEPS "$/dxcompiler.dll") + # TODO: the following code is used to disable building Dawn using vcpkg temporarily + # until we figure out how to resolve the packaging pipeline failures + # + # if (onnxruntime_USE_VCPKG) + if (FALSE) + list(APPEND NODEJS_DLL_DEPS "$") + list(APPEND NODEJS_DLL_DEPS "$") + else() + list(APPEND NODEJS_DLL_DEPS "$/dxil.dll") + list(APPEND NODEJS_DLL_DEPS "$/dxcompiler.dll") + endif() endif() - if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) + if (onnxruntime_BUILD_DAWN_SHARED_LIBRARY) list(APPEND NODEJS_DLL_DEPS "$") endif() endif() diff --git a/cmake/onnxruntime_optimizer.cmake b/cmake/onnxruntime_optimizer.cmake index 9d680cd04af10..c4aa2c522b6d8 100644 --- a/cmake/onnxruntime_optimizer.cmake +++ b/cmake/onnxruntime_optimizer.cmake @@ -9,6 +9,7 @@ if (onnxruntime_MINIMAL_BUILD) list(APPEND onnxruntime_optimizer_src_patterns "${ONNXRUNTIME_INCLUDE_DIR}/core/optimizer/graph_transformer.h" "${ONNXRUNTIME_ROOT}/core/optimizer/graph_transformer.cc" + "${ONNXRUNTIME_ROOT}/core/optimizer/graph_optimizer_registry.cc" ) if (onnxruntime_EXTENDED_MINIMAL_BUILD) @@ -44,6 +45,8 @@ if (onnxruntime_MINIMAL_BUILD) "${ONNXRUNTIME_ROOT}/core/optimizer/selectors_actions/selector_action_transformer_apply_contexts.h" "${ONNXRUNTIME_ROOT}/core/optimizer/selectors_actions/selector_action_transformer.cc" "${ONNXRUNTIME_ROOT}/core/optimizer/selectors_actions/selector_action_transformer.h" + "${ONNXRUNTIME_ROOT}/core/optimizer/slice_concat_to_space_to_depth_fusion.cc" + "${ONNXRUNTIME_ROOT}/core/optimizer/slice_concat_to_space_to_depth_fusion.h" # files required for layout transformation "${ONNXRUNTIME_ROOT}/core/optimizer/layout_transformation/layout_transformation.h" "${ONNXRUNTIME_ROOT}/core/optimizer/layout_transformation/layout_transformation.cc" @@ -130,13 +133,9 @@ set_target_properties(onnxruntime_optimizer PROPERTIES FOLDER "ONNXRuntime") if (NOT onnxruntime_BUILD_SHARED_LIB) install(DIRECTORY ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/optimizer DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/core) - install(TARGETS onnxruntime_optimizer + install(TARGETS onnxruntime_optimizer EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() - -if (onnxruntime_USE_ROCM) - add_dependencies(onnxruntime_optimizer generate_hipified_files) -endif() diff --git a/cmake/onnxruntime_providers.cmake b/cmake/onnxruntime_providers.cmake index 67fa48b28278d..8190ea7883656 100644 --- a/cmake/onnxruntime_providers.cmake +++ b/cmake/onnxruntime_providers.cmake @@ -92,12 +92,6 @@ endif() if(onnxruntime_USE_ACL) set(PROVIDERS_ACL onnxruntime_providers_acl) endif() -if(onnxruntime_USE_ARMNN) - set(PROVIDERS_ARMNN onnxruntime_providers_armnn) -endif() -if(onnxruntime_USE_ROCM) - set(PROVIDERS_ROCM onnxruntime_providers_rocm) -endif() if (onnxruntime_USE_XNNPACK) set(PROVIDERS_XNNPACK onnxruntime_providers_xnnpack) endif() @@ -132,6 +126,10 @@ if (onnxruntime_USE_TENSORRT) include(onnxruntime_providers_tensorrt.cmake) endif() +if (onnxruntime_USE_NV) + include(onnxruntime_providers_nv.cmake) +endif() + if (onnxruntime_USE_VITISAI) include(onnxruntime_providers_vitisai.cmake) endif() @@ -180,14 +178,6 @@ if (onnxruntime_USE_ACL) include(onnxruntime_providers_acl.cmake) endif() -if (onnxruntime_USE_ARMNN) - include(onnxruntime_providers_armnn.cmake) -endif() - -if (onnxruntime_USE_ROCM) - include(onnxruntime_providers_rocm.cmake) -endif() - if (onnxruntime_USE_VSINPU) include(onnxruntime_providers_vsinpu.cmake) endif() diff --git a/cmake/onnxruntime_providers_acl.cmake b/cmake/onnxruntime_providers_acl.cmake index e23d2892713fc..afa41d72c1e9c 100644 --- a/cmake/onnxruntime_providers_acl.cmake +++ b/cmake/onnxruntime_providers_acl.cmake @@ -10,15 +10,17 @@ source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_acl_cc_srcs}) onnxruntime_add_static_library(onnxruntime_providers_acl ${onnxruntime_providers_acl_cc_srcs}) onnxruntime_add_include_to_target(onnxruntime_providers_acl - onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers Boost::mp11 safeint_interface + onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers Boost::mp11 safeint_interface Eigen3::Eigen ) - target_link_libraries(onnxruntime_providers_acl -L$ENV{LD_LIBRARY_PATH}) + if (DEFINED ENV{LD_LIBRARY_PATH}) + target_link_libraries(onnxruntime_providers_acl -L$ENV{LD_LIBRARY_PATH}) + endif() add_dependencies(onnxruntime_providers_acl ${onnxruntime_EXTERNAL_DEPENDENCIES}) set_target_properties(onnxruntime_providers_acl PROPERTIES FOLDER "ONNXRuntime") target_include_directories(onnxruntime_providers_acl PRIVATE - ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS} ${onnxruntime_ACL_HOME} ${onnxruntime_ACL_HOME}/include + ${ONNXRUNTIME_ROOT} ${onnxruntime_ACL_HOME} ${onnxruntime_ACL_HOME}/include ) install(FILES ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/providers/acl/acl_provider_factory.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/ @@ -26,9 +28,9 @@ set_target_properties(onnxruntime_providers_acl PROPERTIES LINKER_LANGUAGE CXX) if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_providers_acl + install(TARGETS onnxruntime_providers_acl EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) - endif() \ No newline at end of file + endif() diff --git a/cmake/onnxruntime_providers_armnn.cmake b/cmake/onnxruntime_providers_armnn.cmake deleted file mode 100644 index 33fadb7c64c2e..0000000000000 --- a/cmake/onnxruntime_providers_armnn.cmake +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - - add_definitions(-DUSE_ARMNN=1) - file(GLOB_RECURSE onnxruntime_providers_armnn_cc_srcs - "${ONNXRUNTIME_ROOT}/core/providers/armnn/*.h" - "${ONNXRUNTIME_ROOT}/core/providers/armnn/*.cc" - ) - - source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_armnn_cc_srcs}) - onnxruntime_add_static_library(onnxruntime_providers_armnn ${onnxruntime_providers_armnn_cc_srcs}) - onnxruntime_add_include_to_target(onnxruntime_providers_armnn - onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers Boost::mp11 safeint_interface - ) - - add_dependencies(onnxruntime_providers_armnn ${onnxruntime_EXTERNAL_DEPENDENCIES}) - set_target_properties(onnxruntime_providers_armnn PROPERTIES FOLDER "ONNXRuntime") - target_include_directories(onnxruntime_providers_armnn PRIVATE - ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS} ${onnxruntime_ARMNN_HOME} ${onnxruntime_ARMNN_HOME}/include - ${onnxruntime_ACL_HOME} ${onnxruntime_ACL_HOME}/include - ) - install(FILES ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/providers/armnn/armnn_provider_factory.h - DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/) - - set_target_properties(onnxruntime_providers_armnn PROPERTIES LINKER_LANGUAGE CXX) - - if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_providers_armnn - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) - endif() \ No newline at end of file diff --git a/cmake/onnxruntime_providers_cann.cmake b/cmake/onnxruntime_providers_cann.cmake index 2b82379ed66a9..30c13c0b4a20a 100644 --- a/cmake/onnxruntime_providers_cann.cmake +++ b/cmake/onnxruntime_providers_cann.cmake @@ -21,9 +21,9 @@ onnxruntime_add_include_to_target(onnxruntime_providers_cann onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers Boost::mp11 safeint_interface) add_dependencies(onnxruntime_providers_cann onnxruntime_providers_shared ${onnxruntime_EXTERNAL_DEPENDENCIES}) - target_link_libraries(onnxruntime_providers_cann PRIVATE ascendcl acl_op_compiler fmk_onnx_parser ${ABSEIL_LIBS} ${ONNXRUNTIME_PROVIDERS_SHARED}) + target_link_libraries(onnxruntime_providers_cann PRIVATE Eigen3::Eigen ascendcl acl_op_compiler fmk_onnx_parser ${ABSEIL_LIBS} ${ONNXRUNTIME_PROVIDERS_SHARED}) target_link_directories(onnxruntime_providers_cann PRIVATE ${onnxruntime_CANN_HOME}/lib64) - target_include_directories(onnxruntime_providers_cann PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${eigen_INCLUDE_DIRS} ${onnxruntime_CANN_HOME} ${onnxruntime_CANN_HOME}/include) + target_include_directories(onnxruntime_providers_cann PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${onnxruntime_CANN_HOME} ${onnxruntime_CANN_HOME}/include) set_target_properties(onnxruntime_providers_cann PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(onnxruntime_providers_cann PROPERTIES FOLDER "ONNXRuntime") diff --git a/cmake/onnxruntime_providers_coreml.cmake b/cmake/onnxruntime_providers_coreml.cmake index 18048c8cdce2f..757198ffb651d 100644 --- a/cmake/onnxruntime_providers_coreml.cmake +++ b/cmake/onnxruntime_providers_coreml.cmake @@ -6,6 +6,8 @@ if (onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD) endif() add_compile_definitions(USE_COREML=1) +add_compile_definitions(COREML_ENABLE_MLPROGRAM=1) + # Check if we can build the coremltools code for creating an mlpackage with an mlprogram. if(LINUX) @@ -17,10 +19,6 @@ if(LINUX) endif() endif() - -add_compile_definitions(COREML_ENABLE_MLPROGRAM=1) - - # Compile CoreML proto definition to ${CMAKE_CURRENT_BINARY_DIR}/coreml_proto set(COREML_PROTO_ROOT ${coremltools_SOURCE_DIR}/mlmodel/format) file(GLOB coreml_proto_srcs "${COREML_PROTO_ROOT}/*.proto") @@ -86,7 +84,6 @@ file(GLOB_RECURSE "${ONNXRUNTIME_ROOT}/core/providers/coreml/builders/*.cc" ) - # Add helpers to create mlpackage weights. limit to just the files we need to minimize the changes to make them # build on Windows and Linux. file(GLOB @@ -114,7 +111,6 @@ set(coremltools_srcs source_group(TREE ${coremltools_SOURCE_DIR} PREFIX coremltools FILES ${coremltools_srcs}) - # Add CoreML objective c++ source code if (APPLE) file(GLOB @@ -156,9 +152,29 @@ onnxruntime_add_static_library(onnxruntime_providers_coreml onnxruntime_add_include_to_target(onnxruntime_providers_coreml onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers Boost::mp11 - safeint_interface + safeint_interface nlohmann_json::nlohmann_json ) +# In ONNX Runtime's code, when we need to use the json library, we have: `#include "nlohmann/json.hpp"`. +# But, coremltool's code includes the json.hpp directly without the folder name: `#include "json.hpp"`. +# Therefore here we need to tweak INCLUDE_DIRECTORIES a little bit to fix that. + +if(nlohmann_json_SOURCE_DIR) + target_include_directories(onnxruntime_providers_coreml PRIVATE ${nlohmann_json_SOURCE_DIR}/single_include/nlohmann) +elseif(TARGET nlohmann_json::nlohmann_json) + get_target_property(nlohmann_json_include_dirs nlohmann_json::nlohmann_json INTERFACE_INCLUDE_DIRECTORIES) + foreach(nlohmann_json_include_dir IN LISTS nlohmann_json_include_dirs) + target_include_directories(onnxruntime_providers_coreml PRIVATE "${nlohmann_json_include_dir}/nlohmann") + endforeach() +endif() + +if(fp16_SOURCE_DIR) + set(FP16_INCLUDE_DIRS ${fp16_SOURCE_DIR}/include) +else() + find_path(FP16_INCLUDE_DIRS "fp16.h") +endif() +target_include_directories(onnxruntime_providers_coreml PRIVATE ${FP16_INCLUDE_DIRS}) + onnxruntime_add_include_to_target(onnxruntime_providers_coreml coreml_proto) target_link_libraries(onnxruntime_providers_coreml PRIVATE coreml_proto) add_dependencies(onnxruntime_providers_coreml coreml_proto) @@ -168,33 +184,20 @@ if (APPLE) endif() -# Setup coremltools fp16 and json dependencies for creating an mlpackage. -# -# fp16 depends on psimd -FetchContent_Declare(psimd URL ${DEP_URL_psimd} URL_HASH SHA1=${DEP_SHA1_psimd}) -onnxruntime_fetchcontent_makeavailable(psimd) -set(PSIMD_SOURCE_DIR ${psimd_SOURCE_DIR}) -FetchContent_Declare(fp16 URL ${DEP_URL_fp16} URL_HASH SHA1=${DEP_SHA1_fp16}) -set(FP16_BUILD_TESTS OFF CACHE INTERNAL "") -set(FP16_BUILD_BENCHMARKS OFF CACHE INTERNAL "") -onnxruntime_fetchcontent_makeavailable(fp16) # need to tweak the include paths to match what the coreml source code expects target_include_directories(onnxruntime_providers_coreml PRIVATE - ${fp16_SOURCE_DIR}/include - ${nlohmann_json_SOURCE_DIR}/single_include/nlohmann - ${coremltools_SOURCE_DIR} - ${coremltools_SOURCE_DIR}/mlmodel/src/ - ${coremltools_SOURCE_DIR}/modelpackage/src/ + ${coremltools_SOURCE_DIR} + ${coremltools_SOURCE_DIR}/mlmodel/src/ + ${coremltools_SOURCE_DIR}/modelpackage/src/ ) -add_dependencies(onnxruntime_providers_coreml nlohmann_json::nlohmann_json fp16) - if (LINUX) target_link_libraries(onnxruntime_providers_coreml PRIVATE uuid) endif() + if (APPLE) target_link_libraries(onnxruntime_providers_coreml PRIVATE "-framework Foundation" "-framework CoreML") endif() @@ -207,7 +210,7 @@ target_include_directories(onnxruntime_providers_coreml PRIVATE ${ONNXRUNTIME_RO set_target_properties(onnxruntime_providers_coreml PROPERTIES LINKER_LANGUAGE CXX) if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_providers_coreml + install(TARGETS onnxruntime_providers_coreml EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/cmake/onnxruntime_providers_cpu.cmake b/cmake/onnxruntime_providers_cpu.cmake index 3e1a9edbd13ba..f6efcb3fad6a9 100644 --- a/cmake/onnxruntime_providers_cpu.cmake +++ b/cmake/onnxruntime_providers_cpu.cmake @@ -25,15 +25,14 @@ file(GLOB_RECURSE onnxruntime_cuda_contrib_ops_cu_srcs CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/contrib_ops/cuda/*.cuh" ) -file(GLOB_RECURSE onnxruntime_rocm_contrib_ops_cc_srcs CONFIGURE_DEPENDS - "${ONNXRUNTIME_ROOT}/contrib_ops/rocm/*.h" - "${ONNXRUNTIME_ROOT}/contrib_ops/rocm/*.cc" -) - -file(GLOB_RECURSE onnxruntime_rocm_contrib_ops_cu_srcs CONFIGURE_DEPENDS - "${ONNXRUNTIME_ROOT}/contrib_ops/rocm/*.cu" - "${ONNXRUNTIME_ROOT}/contrib_ops/rocm/*.cuh" -) +# Quick build mode: Filter flash attention kernels for faster development iteration. +# - We keep only hdim128 fp16 flash attention kernels in quick build mode. +# - All other listed head dimensions are excluded (e.g., 32, 64, 96, 192, 256). +# If new head dimensions are added or removed, update this list to match the supported set. +if(onnxruntime_QUICK_BUILD) + message(STATUS "Quick build mode enabled: Only building hdim128 fp16 flash attention kernels") + list(FILTER onnxruntime_cuda_contrib_ops_cu_srcs EXCLUDE REGEX "flash_fwd.*hdim(32|64|96|192|256)") +endif() file(GLOB_RECURSE onnxruntime_js_contrib_ops_cc_srcs CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/contrib_ops/js/*.h" @@ -181,8 +180,8 @@ if (onnxruntime_ENABLE_CPU_FP16_OPS) set_source_files_properties(${ORTTRAINING_SOURCE_DIR}/training_ops/cuda/collective/adasum_kernels.cc PROPERTIES COMPILE_FLAGS " -fassociative-math -ffast-math -ftree-vectorize -funsafe-math-optimizations -mf16c -mavx -mfma ") endif() -target_include_directories(onnxruntime_providers PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS}) -onnxruntime_add_include_to_target(onnxruntime_providers re2::re2) +target_include_directories(onnxruntime_providers PRIVATE ${ONNXRUNTIME_ROOT}) +onnxruntime_add_include_to_target(onnxruntime_providers re2::re2 Eigen3::Eigen) add_dependencies(onnxruntime_providers onnx ${onnxruntime_EXTERNAL_DEPENDENCIES}) if (onnxruntime_ENABLE_TRAINING_OPS) @@ -196,8 +195,7 @@ endif() if (onnxruntime_ENABLE_DLPACK) target_compile_definitions(onnxruntime_providers PRIVATE ENABLE_DLPACK) # DLPack is a header-only dependency - set(DLPACK_INCLUDE_DIR ${dlpack_SOURCE_DIR}/include) - target_include_directories(onnxruntime_providers PRIVATE ${DLPACK_INCLUDE_DIR}) + onnxruntime_add_include_to_target(onnxruntime_providers dlpack::dlpack) endif() if (onnxruntime_ENABLE_TRAINING) @@ -207,7 +205,7 @@ if (onnxruntime_ENABLE_TRAINING) onnxruntime_add_include_to_target(onnxruntime_providers Python::Module) endif() - if (onnxruntime_USE_NCCL OR onnxruntime_USE_MPI) + if (onnxruntime_USE_NCCL) target_include_directories(onnxruntime_providers PUBLIC ${MPI_CXX_INCLUDE_DIRS}) endif() endif() @@ -218,7 +216,7 @@ set_target_properties(onnxruntime_providers PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(onnxruntime_providers PROPERTIES FOLDER "ONNXRuntime") if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD - AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS" + AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS|tvOS" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") file(GLOB onnxruntime_providers_shared_cc_srcs CONFIGURE_DEPENDS @@ -230,6 +228,12 @@ if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD onnxruntime_add_shared_library(onnxruntime_providers_shared ${onnxruntime_providers_shared_cc_srcs} "${ONNXRUNTIME_ROOT}/core/dll/onnxruntime.rc") set_target_properties(onnxruntime_providers_shared PROPERTIES FOLDER "ONNXRuntime") set_target_properties(onnxruntime_providers_shared PROPERTIES LINKER_LANGUAGE CXX) + #ON AIX, to call dlopen on onnxruntime_providers_shared, we need to generate this library as shared object .so file. + #Latest cmake behavior is changed and cmake will remove shared object .so file after generating the shared archive. + #To prevent that, making AIX_SHARED_LIBRARY_ARCHIVE as OFF for onnxruntime_providers_shared. + if (CMAKE_SYSTEM_NAME MATCHES "AIX") + set_target_properties(onnxruntime_providers_shared PROPERTIES AIX_SHARED_LIBRARY_ARCHIVE OFF) + endif() target_compile_definitions(onnxruntime_providers_shared PRIVATE FILE_NAME=\"onnxruntime_providers_shared.dll\") @@ -242,7 +246,7 @@ if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD if(APPLE) set_property(TARGET onnxruntime_providers_shared APPEND_STRING PROPERTY LINK_FLAGS "-Xlinker -exported_symbols_list ${ONNXRUNTIME_ROOT}/core/providers/shared/exported_symbols.lst") elseif(UNIX) - if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + if(NOT CMAKE_SYSTEM_NAME MATCHES "AIX") target_link_options(onnxruntime_providers_shared PRIVATE "LINKER:--version-script=${ONNXRUNTIME_ROOT}/core/providers/shared/version_script.lds" "LINKER:--gc-sections") @@ -262,7 +266,7 @@ if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD endif() if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_providers + install(TARGETS onnxruntime_providers EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/cmake/onnxruntime_providers_cuda.cmake b/cmake/onnxruntime_providers_cuda.cmake index 4f86717026118..624057dd438e7 100644 --- a/cmake/onnxruntime_providers_cuda.cmake +++ b/cmake/onnxruntime_providers_cuda.cmake @@ -6,6 +6,8 @@ file(GLOB onnxruntime_providers_cuda_cc_srcs CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/core/providers/cuda/*.h" "${ONNXRUNTIME_ROOT}/core/providers/cuda/*.cc" + "${ONNXRUNTIME_ROOT}/core/providers/cuda/ml/*.h" + "${ONNXRUNTIME_ROOT}/core/providers/cuda/ml/*.cc" "${ONNXRUNTIME_ROOT}/core/providers/cuda/tunable/*.h" "${ONNXRUNTIME_ROOT}/core/providers/cuda/tunable/*.cc" ) @@ -20,6 +22,9 @@ "${ONNXRUNTIME_ROOT}/core/providers/cuda/*.cc" ) endif() + # Exclude plugin directory if it was picked up by GLOB_RECURSE + list(FILTER onnxruntime_providers_cuda_cc_srcs EXCLUDE REGEX "core/providers/cuda/plugin/.*") + # Remove pch files list(REMOVE_ITEM onnxruntime_providers_cuda_cc_srcs "${ONNXRUNTIME_ROOT}/core/providers/cuda/cuda_pch.h" @@ -41,8 +46,11 @@ else() set(onnxruntime_providers_cuda_cu_srcs "${ONNXRUNTIME_ROOT}/core/providers/cuda/math/unary_elementwise_ops_impl.cu" + "${ONNXRUNTIME_ROOT}/core/providers/cuda/ml/label_encoder_impl.cu" ) endif() + # Exclude plugin directory if it was picked up by GLOB_RECURSE + list(FILTER onnxruntime_providers_cuda_cu_srcs EXCLUDE REGEX "core/providers/cuda/plugin/.*") source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_cuda_cc_srcs} ${onnxruntime_providers_cuda_shared_srcs} ${onnxruntime_providers_cuda_cu_srcs}) set(onnxruntime_providers_cuda_src ${onnxruntime_providers_cuda_cc_srcs} ${onnxruntime_providers_cuda_shared_srcs} ${onnxruntime_providers_cuda_cu_srcs}) @@ -122,6 +130,7 @@ if (onnxruntime_REDUCED_OPS_BUILD) substitute_op_reduction_srcs(onnxruntime_providers_cuda_src) endif() + if(onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS) # cuda_provider_interface.cc is removed from the object target: onnxruntime_providers_cuda_obj and # added to the lib onnxruntime_providers_cuda separately. @@ -129,10 +138,41 @@ set(cuda_provider_interface_src ${ONNXRUNTIME_ROOT}/core/providers/cuda/cuda_provider_interface.cc) list(REMOVE_ITEM onnxruntime_providers_cuda_src ${cuda_provider_interface_src}) onnxruntime_add_object_library(onnxruntime_providers_cuda_obj ${onnxruntime_providers_cuda_src}) - onnxruntime_add_shared_library_module(onnxruntime_providers_cuda ${cuda_provider_interface_src} $) + + set(onnxruntime_providers_cuda_all_srcs ${cuda_provider_interface_src}) + if(WIN32) + # Sets the DLL version info on Windows: https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource + list(APPEND onnxruntime_providers_cuda_all_srcs "${ONNXRUNTIME_ROOT}/core/providers/cuda/onnxruntime_providers_cuda.rc") + endif() + + onnxruntime_add_shared_library_module(onnxruntime_providers_cuda ${onnxruntime_providers_cuda_all_srcs} + $) else() - onnxruntime_add_shared_library_module(onnxruntime_providers_cuda ${onnxruntime_providers_cuda_src}) + set(onnxruntime_providers_cuda_all_srcs ${onnxruntime_providers_cuda_src}) + if(WIN32) + # Sets the DLL version info on Windows: https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource + list(APPEND onnxruntime_providers_cuda_all_srcs "${ONNXRUNTIME_ROOT}/core/providers/cuda/onnxruntime_providers_cuda.rc") + endif() + + onnxruntime_add_shared_library_module(onnxruntime_providers_cuda ${onnxruntime_providers_cuda_all_srcs}) + endif() + + if (MSVC) + # Use /permissive to work around compilation error from CUTLASS header cute/tensor.hpp: + # cutlass-src\include\cute\stride.hpp(299,46): error C3545: 'Ints': parameter pack expects a non-type + # template argument + # See https://github.com/NVIDIA/cutlass/issues/3065 + target_compile_options(onnxruntime_providers_cuda PRIVATE + "$<$:/permissive>" + "$<$:SHELL:-Xcompiler /permissive>" + ) endif() + + if(WIN32) + # FILE_NAME preprocessor definition is used in onnxruntime_providers_cuda.rc + target_compile_definitions(onnxruntime_providers_cuda PRIVATE FILE_NAME=\"onnxruntime_providers_cuda.dll\") + endif() + # config_cuda_provider_shared_module can be used to config onnxruntime_providers_cuda_obj, onnxruntime_providers_cuda & onnxruntime_providers_cuda_ut. # This function guarantees that all 3 targets have the same configurations. function(config_cuda_provider_shared_module target) @@ -149,14 +189,42 @@ endif() foreach(ORT_FLAG ${ORT_WARNING_FLAGS}) + if (NOT "${ORT_FLAG}" STREQUAL "-Wshorten-64-to-32") target_compile_options(${target} PRIVATE "$<$:SHELL:-Xcompiler \"${ORT_FLAG}\">") + endif() endforeach() + # Note: The minimum required CUDA version is greater than 11.3. # CUDA 11.3+ supports parallel compilation # https://docs.nvidia.com/cuda/cuda-compiler-driver-nvcc/index.html#options-for-guiding-compiler-driver-threads - if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 11.3) - set(onnxruntime_NVCC_THREADS "1" CACHE STRING "Number of threads that NVCC can use for compilation.") - target_compile_options(${target} PRIVATE "$<$:SHELL:--threads \"${onnxruntime_NVCC_THREADS}\">") + set(onnxruntime_NVCC_THREADS "1" CACHE STRING "Number of threads that NVCC can use for compilation.") + target_compile_options(${target} PRIVATE "$<$:SHELL:--threads \"${onnxruntime_NVCC_THREADS}\">") + + # suppress warnings like this: + # cutlass-src\include\cute/arch/mma_sm120.hpp(3128): error #177-D: variable "tidA" was declared but never + # referenced + target_compile_options(${target} PRIVATE "$<$:--diag-suppress=177>") + + # Since CUDA 12.8, compiling diagnostics become stricter + if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.8) + target_compile_options(${target} PRIVATE "$<$:--static-global-template-stub=false>") + + if (MSVC) + target_compile_options(${target} PRIVATE "$<$:SHELL:-Xcompiler /wd4505>") + endif() + # skip diagnosis error caused by cuda header files + target_compile_options(${target} PRIVATE "$<$:--diag-suppress=221>") + endif() + + if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0) + if (UNIX) + # Suppress -Wattributes warning from protobuf headers with nvcc on Linux + target_compile_options(${target} PRIVATE "$<$:SHELL:-Xcompiler -Wno-attributes>") + endif() + + if (MSVC) + target_compile_options(${target} PRIVATE "$<$:--diag-suppress=20199>") + endif() endif() if (UNIX) @@ -164,6 +232,38 @@ "$<$>:-Wno-reorder>") target_compile_options(${target} PRIVATE "$<$:SHELL:-Xcompiler -Wno-error=sign-compare>" "$<$>:-Wno-error=sign-compare>") + if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CXX_COMPILER_ID STREQUAL "IBMClang") + foreach(CLANG_WARNING + braced-scalar-init + defaulted-function-deleted + inconsistent-missing-override + instantiation-after-specialization + logical-op-parentheses + mismatched-tags + shorten-64-to-32 + unneeded-internal-declaration + unknown-warning-option + unused-private-field + unused-variable) + target_compile_options(${target} PRIVATE "$<$>:-Wno-error=${CLANG_WARNING}>") + endforeach() + if (CMAKE_CUDA_HOST_COMPILER_ID STREQUAL "Clang" OR CMAKE_CUDA_HOST_COMPILER_ID STREQUAL "AppleClang" OR CMAKE_CUDA_HOST_COMPILER_ID STREQUAL "IBMClang") + foreach(CLANG_WARNING + braced-scalar-init + defaulted-function-deleted + inconsistent-missing-override + instantiation-after-specialization + logical-op-parentheses + mismatched-tags + shorten-64-to-32 + unneeded-internal-declaration + unknown-warning-option + unused-private-field + unused-variable) + target_compile_options(${target} PRIVATE "$<$:SHELL:-Xcompiler -Wno-error=${CLANG_WARNING}>") + endforeach() + endif() + endif() else() #mutex.cuh(91): warning C4834: discarding return value of function with 'nodiscard' attribute target_compile_options(${target} PRIVATE "$<$:SHELL:-Xcompiler /wd4834>") @@ -174,11 +274,16 @@ # be used due to `&& not_a_const`. This affects too many places for it to be reasonable to disable at a finer # granularity. target_compile_options(${target} PRIVATE "$<$:/wd4127>") + + # Warning C4211: nonstandard extension used: redefined extern to static + # non_max_suppression_impl.cu + target_compile_options(${target} PRIVATE "$<$:SHELL:-Xcompiler /wd4211>") endif() endif() if(MSVC) target_compile_options(${target} PRIVATE "$<$:SHELL:-Xcompiler /Zc:__cplusplus>") + target_compile_options(${target} PRIVATE "$<$:SHELL:-Xcompiler /bigobj>") endif() onnxruntime_add_include_to_target(${target} onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers) @@ -209,26 +314,34 @@ ${ABSEIL_LIBS} ${ONNXRUNTIME_PROVIDERS_SHARED} Boost::mp11 safeint_interface) endif() - if (onnxruntime_USE_TRITON_KERNEL) - # compile triton kernel, generate .a and .h files - include(onnxruntime_compile_triton_kernel.cmake) - compile_triton_kernel(triton_kernel_obj_file triton_kernel_header_dir) - add_dependencies(${target} onnxruntime_triton_kernel) - target_compile_definitions(${target} PRIVATE USE_TRITON_KERNEL) - target_include_directories(${target} PRIVATE ${triton_kernel_header_dir}) - target_link_libraries(${target} PUBLIC -Wl,--whole-archive ${triton_kernel_obj_file} -Wl,--no-whole-archive) - # lib cuda needed by cuLaunchKernel - target_link_libraries(${target} PRIVATE CUDA::cuda_driver) - endif() - include(cutlass) target_include_directories(${target} PRIVATE ${cutlass_SOURCE_DIR}/include ${cutlass_SOURCE_DIR}/examples ${cutlass_SOURCE_DIR}/tools/util/include) + target_link_libraries(${target} PRIVATE Eigen3::Eigen) + target_include_directories(${target} PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} PUBLIC ${CUDAToolkit_INCLUDE_DIRS}) + + # Handle CUDA 13.0 CCCL header directory move + if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 13.0) + foreach(inc_dir ${CUDAToolkit_INCLUDE_DIRS}) + if (EXISTS "${inc_dir}/cccl") + # Add the cccl subdirectory to the include path so can be found + target_include_directories(${target} PRIVATE "${inc_dir}/cccl") + endif() + endforeach() + endif() - target_include_directories(${target} PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${eigen_INCLUDE_DIRS} PUBLIC ${CUDAToolkit_INCLUDE_DIRS}) # ${CMAKE_CURRENT_BINARY_DIR} is so that #include "onnxruntime_config.h" inside tensor_shape.h is found set_target_properties(${target} PROPERTIES LINKER_LANGUAGE CUDA) set_target_properties(${target} PROPERTIES FOLDER "ONNXRuntime") + if("90" IN_LIST CMAKE_CUDA_ARCHITECTURES_ORIG) + target_compile_options(${target} PRIVATE $<$:-Xptxas=-w>) + target_compile_definitions(${target} PRIVATE COMPILE_HOPPER_TMA_GEMMS) + if (MSVC) + target_compile_options(${target} PRIVATE "$<$:SHELL:-Xcompiler /bigobj>") + target_compile_options(${target} PRIVATE "$<$:SHELL:-Xcompiler /wd4172>") + endif() + endif() + if (onnxruntime_ENABLE_CUDA_PROFILING) # configure cupti for cuda profiling target_link_libraries(${target} PRIVATE CUDA::cupti) endif() @@ -241,10 +354,6 @@ target_include_directories(${target} PRIVATE ${ORTTRAINING_ROOT} ${MPI_CXX_INCLUDE_DIRS}) endif() - if(onnxruntime_USE_MPI) - target_link_libraries(${target} PRIVATE ${MPI_LIBRARIES} ${MPI_CXX_LINK_FLAGS}) - endif() - if (onnxruntime_USE_NCCL) target_include_directories(${target} PRIVATE ${NCCL_INCLUDE_DIRS}) target_link_libraries(${target} PRIVATE ${NCCL_LIBRARIES}) diff --git a/cmake/onnxruntime_providers_cuda_plugin.cmake b/cmake/onnxruntime_providers_cuda_plugin.cmake new file mode 100644 index 0000000000000..e345c944dccf8 --- /dev/null +++ b/cmake/onnxruntime_providers_cuda_plugin.cmake @@ -0,0 +1,311 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +# Build the CUDA Execution Provider as a plugin shared library. +# This file is included from the main CMakeLists.txt when onnxruntime_BUILD_CUDA_EP_AS_PLUGIN=ON. + +message(STATUS "Building CUDA EP as plugin shared library") + + + +set(CUDA_PLUGIN_EP_DIR "${ONNXRUNTIME_ROOT}/core/providers/cuda/plugin") + +# --- Collect standard CUDA EP sources --- +file(GLOB_RECURSE CUDA_EP_CC_SRCS CONFIGURE_DEPENDS + "${ONNXRUNTIME_ROOT}/core/providers/cuda/*.cc" +) + +file(GLOB_RECURSE CUDA_EP_CU_SRCS CONFIGURE_DEPENDS + "${ONNXRUNTIME_ROOT}/core/providers/cuda/*.cu" +) + +# --- Collect contrib ops sources --- +file(GLOB_RECURSE CUDA_CONTRIB_OPS_CC_SRCS CONFIGURE_DEPENDS + "${ONNXRUNTIME_ROOT}/contrib_ops/cuda/*.cc" +) + +file(GLOB_RECURSE CUDA_CONTRIB_OPS_CU_SRCS CONFIGURE_DEPENDS + "${ONNXRUNTIME_ROOT}/contrib_ops/cuda/*.cu" +) + +list(APPEND CUDA_PLUGIN_EP_CC_SRCS + ${CUDA_EP_CC_SRCS} + ${CUDA_CONTRIB_OPS_CC_SRCS} +) + +list(APPEND CUDA_PLUGIN_EP_CU_SRCS + ${CUDA_EP_CU_SRCS} + ${CUDA_CONTRIB_OPS_CU_SRCS} +) + +list(FILTER CUDA_PLUGIN_EP_CU_SRCS EXCLUDE REGEX "onnxruntime/contrib_ops/cuda/aten_ops/.*") +list(FILTER CUDA_PLUGIN_EP_CU_SRCS EXCLUDE REGEX "onnxruntime/contrib_ops/cuda/collective/.*") + +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX "onnxruntime/contrib_ops/cuda/aten_ops/.*") +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX "onnxruntime/contrib_ops/cuda/collective/.*") + +# Exclude files that include cuda_execution_provider.h (directly or transitively), +# which conflicts with the adapter shim CUDAExecutionProvider class. +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/cuda_execution_provider\\.cc$") +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/cuda_provider_factory\\.cc$") +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/cuda_provider_interface\\.cc$") + +# Exclude the framework controlflow/ subdirectory — these inherit from CPU base +# classes (If, Loop, Scan). The plugin has its own control flow wrappers in +# plugin/cuda_controlflow_plugin.cc that delegate to OrtEpApi. +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/core/providers/cuda/controlflow/.*") + +# Exclude the entire tunable/ subdirectory — it depends on the real CudaTuningContext +# and CUDAExecutionProvider which are not available in the plugin build. +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/tunable/.*") + +# Exclude real EP infrastructure files (replaced by plugin/ equivalents). +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/cuda_stream_handle\\.cc$") +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/cuda_execution_provider_info\\.cc$") +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/cuda_graph\\.cc$") +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/cuda_mempool_arena\\.cc$") + +# Exclude cuda_common.cc — its HalfGemmOptions definitions conflict with the +# adapter's inline shim. Utility functions are replaced or not needed. +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/cuda_common\\.cc$") + +# Exclude cuda_nhwc_kernels.cc and cuda_contrib_kernels.cc — these files contain +# explicit BuildKernelCreateInfo<> registration tables that reference ALL kernel +# classes (including those in excluded source files like space_depth_ops.cc, +# controlflow/, transformers/, etc.), causing undefined symbols at link time. +# With PluginKernelCollector, individual kernel files self-register via macro +# overrides, so these centralized tables are not needed in the plugin build. +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/cuda_nhwc_kernels\\.cc$") +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/cuda_contrib_kernels\\.cc$") + +# Exclude sequence_op.cc — uses TensorSeq (incomplete type in plugin build). +# identity_op.cc is now included: TensorSeq code path is guarded by +# BUILD_CUDA_EP_AS_PLUGIN and opset 14+ registrations use Tensor-only types. +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/tensor/sequence_op\\.cc$") + +# Permanently excluded — pure CPU ops, handled by GetCpuPreferredNodes. +# size.cc registers onnxruntime::Size (CPU op) whose Compute() body lives +# in the CPU provider and is not linked into the plugin. +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/tensor/size\\.cc$") + +# Permanently excluded — pure CPU ops, handled by GetCpuPreferredNodes. +# shape_op.cc inherits from onnxruntime::OpKernel (framework) +# which cannot convert to ep::adapter::OpKernel in the plugin build. +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/tensor/shape_op\\.cc$") + +# Exclude contrib llm/ for now. The core CUDA llm kernels are adapter-safe, but +# contrib llm kernels still need their own plugin pass. +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/contrib_ops/cuda/llm/.*") +list(FILTER CUDA_PLUGIN_EP_CU_SRCS EXCLUDE REGEX ".*/contrib_ops/cuda/llm/.*") + +# Exclude contrib training ops (shrunken_gather depends on provider_api.h in header). +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/contrib_ops/cuda/tensor/shrunken_gather\\.cc$") + + +# Exclude contrib transformers/ (beam search, greedy search, sampling). Those need subgraph inference. +list(FILTER CUDA_PLUGIN_EP_CC_SRCS EXCLUDE REGEX ".*/contrib_ops/cuda/transformers/.*") +list(FILTER CUDA_PLUGIN_EP_CU_SRCS EXCLUDE REGEX ".*/contrib_ops/cuda/transformers/.*") + +# Create shared library target using the ORT helper function for plugins +onnxruntime_add_shared_library_module(onnxruntime_providers_cuda_plugin + ${CUDA_PLUGIN_EP_CC_SRCS} + ${CUDA_PLUGIN_EP_CU_SRCS} +) + +# Mirror directory structure in the Visual Studio solution tree under "onnxruntime". +source_group(TREE ${ONNXRUNTIME_ROOT} PREFIX "onnxruntime" FILES ${CUDA_EP_CC_SRCS} ${CUDA_EP_CU_SRCS}) +source_group(TREE ${ONNXRUNTIME_ROOT} PREFIX "onnxruntime" FILES ${CUDA_CONTRIB_OPS_CC_SRCS} ${CUDA_CONTRIB_OPS_CU_SRCS}) +# Keep the plugin CUDA target aligned with the repo-wide C++20 baseline. +# Forcing CUDA C++17 here breaks newer protobuf/absl headers used by the plugin +# build, as absl::compare expects standard ordering support in this configuration. +set_target_properties(onnxruntime_providers_cuda_plugin PROPERTIES + CUDA_STANDARD 20 + CUDA_STANDARD_REQUIRED ON +) + +# Suppress -Werror=maybe-uninitialized for local variables written by +# adapter OpKernelInfo::GetAttr<> (GCC falsely warns about variables that are +# initialized inside GetAttr’s output parameter path). +target_compile_options(onnxruntime_providers_cuda_plugin PRIVATE + $<$,$>:-Wno-maybe-uninitialized> +) +target_compile_options(onnxruntime_providers_cuda_plugin PRIVATE + # Flash-attention, XQA, MoE, and other pure CUDA kernel .cu files must NOT + # receive the ORT-framework force-include (it conflicts with cute::Tensor etc.). + # cuda_plugin_kernels.cu already #include "cuda_kernel_adapter.h" directly. + # Op-registration .cc files do not include it directly, so they need it here. + # + # IMPORTANT: The CXX force-include order matters — adapters.h MUST precede + # cuda_kernel_adapter.h because the adapter establishes type aliases that the + # kernel adapter header depends on. + # + # Force NVCC onto C++20 explicitly. With the VS generator the CUDA standard + # property alone still leaves `-std=c++17` in AdditionalOptions. + # Suppress NVCC cudafe warnings: + # 550 - variable set but never used (in adapter headers) + # 2810 - [[nodiscard]] false positive on Status assignments in op_kernel.h / kernel_registry.h + "$<$:SHELL:--std c++20>" + "$<$:--expt-relaxed-constexpr;-Xcudafe;--diag_suppress=550>" + "$<$:SHELL:-Xcudafe --diag_suppress=2810>" + # Force-include adapters.h and cuda_kernel_adapter.h for CXX sources. + # GCC/Clang use -include, MSVC uses /FI. + "$<$,$>>:-include;${REPO_ROOT}/include/onnxruntime/ep/adapters.h>" + "$<$,$>>:SHELL:-include ${CUDA_PLUGIN_EP_DIR}/cuda_kernel_adapter.h>" + "$<$,$>:/FI${REPO_ROOT}/include/onnxruntime/ep/adapters.h>" + "$<$,$>:/FI${CUDA_PLUGIN_EP_DIR}/cuda_kernel_adapter.h>" +) + +if (MSVC) + target_compile_options(onnxruntime_providers_cuda_plugin PRIVATE + "$<$:SHELL:-Xcompiler /permissive>" + "$<$:SHELL:-Xcompiler /wd4834>" + "$<$:SHELL:-Xcompiler /wd4127>" + "$<$:SHELL:-Xcompiler /wd4211>" + "$<$:SHELL:-Xcompiler /Zc:__cplusplus>" + "$<$:SHELL:-Xcompiler /bigobj>" + ) + + target_compile_options(onnxruntime_providers_cuda_plugin PRIVATE + # /permissive is required for CUTLASS cute headers (cute::stride.hpp, cute::Layout etc.) + "$<$:/permissive>" + # /permissive disables C++ alternative tokens (or, and, not, etc.). + # Force-include iso646.h to restore them as macros. + "$<$:/FIiso646.h>" + "$<$:/wd4127>" + ) +endif() + +# Mirror the core CUDA provider's CUDA 12.8+ NVCC workarounds so the plugin +# target handles stricter cudafe diagnostics consistently. +if (DEFINED onnxruntime_NVCC_THREADS) + set(onnxruntime_plugin_nvcc_threads "${onnxruntime_NVCC_THREADS}") +else() + set(onnxruntime_plugin_nvcc_threads "1") +endif() +target_compile_options(onnxruntime_providers_cuda_plugin PRIVATE + "$<$:SHELL:--threads \"${onnxruntime_plugin_nvcc_threads}\">" + "$<$:--diag-suppress=177>" +) + +if (CMAKE_CUDA_COMPILER_VERSION VERSION_GREATER_EQUAL 12.8) + target_compile_options(onnxruntime_providers_cuda_plugin PRIVATE + "$<$:--static-global-template-stub=false>" + "$<$:--diag-suppress=221>" + ) + + if (MSVC) + target_compile_options(onnxruntime_providers_cuda_plugin PRIVATE + "$<$:SHELL:-Xcompiler /wd4505>" + ) + endif() +endif() + +include(cudnn_frontend) +include(cutlass) + +# --- Find cuDNN (may be at a custom path via onnxruntime_CUDNN_HOME) --- +set(_CUDNN_SEARCH_PATHS "") +if(onnxruntime_CUDNN_HOME) + list(APPEND _CUDNN_SEARCH_PATHS "${onnxruntime_CUDNN_HOME}") +endif() +if(DEFINED ENV{CUDNN_HOME}) + list(APPEND _CUDNN_SEARCH_PATHS "$ENV{CUDNN_HOME}") +endif() + +set(CUDA_PLUGIN_CUDNN_INCLUDE_DIR ${CUDNN_INCLUDE_DIR}) +set(CUDA_PLUGIN_CUDNN_LIBRARY ${cudnn_LIBRARY}) + +if(NOT CUDA_PLUGIN_CUDNN_INCLUDE_DIR OR NOT CUDA_PLUGIN_CUDNN_LIBRARY) + message(FATAL_ERROR "cuDNN not found (from main ORT search) for CUDA Plugin EP.") +endif() + +message(STATUS "CUDA Plugin EP: cuDNN include: ${CUDA_PLUGIN_CUDNN_INCLUDE_DIR}") +message(STATUS "CUDA Plugin EP: cuDNN library: ${CUDA_PLUGIN_CUDNN_LIBRARY}") + +# Include directories — only public ORT headers + CUDA toolkit + cuDNN + internal headers for adapter +target_include_directories(onnxruntime_providers_cuda_plugin PRIVATE + ${REPO_ROOT}/include + ${REPO_ROOT}/include/onnxruntime/core/session + ${ONNXRUNTIME_ROOT} + ${CUDAToolkit_INCLUDE_DIRS} + ${CUDA_PLUGIN_CUDNN_INCLUDE_DIR} + ${Eigen3_SOURCE_DIR} + ${cutlass_SOURCE_DIR}/include + ${cutlass_SOURCE_DIR}/examples + ${cutlass_SOURCE_DIR}/tools/util/include +) + +onnxruntime_add_include_to_target( + onnxruntime_providers_cuda_plugin + onnxruntime_common + onnx + onnx_proto + ${PROTOBUF_LIB} + flatbuffers::flatbuffers +) + +# Link libraries +target_link_libraries(onnxruntime_providers_cuda_plugin PRIVATE + CUDA::cudart + CUDA::cublas + CUDA::cublasLt + CUDA::cufft + CUDNN::cudnn_all + cudnn_frontend + Boost::mp11 + safeint_interface + onnxruntime_framework + onnxruntime_graph + onnxruntime_mlas + onnxruntime_flatbuffers + onnxruntime_common + cpuinfo::cpuinfo + onnx + onnx_proto + ${PROTOBUF_LIB} +) + +if (onnxruntime_ENABLE_CUDA_PROFILING) + target_link_libraries(onnxruntime_providers_cuda_plugin PRIVATE CUDA::cupti) + target_compile_definitions(onnxruntime_providers_cuda_plugin PRIVATE ENABLE_CUDA_PROFILING) +endif() + +# Default plugin EP version to ORT_VERSION with "-dev" suffix if not explicitly provided. +if(NOT DEFINED onnxruntime_PLUGIN_EP_VERSION) + set(onnxruntime_PLUGIN_EP_VERSION "${ORT_VERSION}-dev") +endif() + +# Symbol visibility — only export CreateEpFactories and ReleaseEpFactory +target_compile_definitions(onnxruntime_providers_cuda_plugin PRIVATE ORT_API_MANUAL_INIT BUILD_CUDA_EP_AS_PLUGIN ORT_USE_EP_API_ADAPTERS=1 ONNX_ML=1 ONNX_NAMESPACE=onnx ONNX_USE_LITE_PROTO=1 ORT_PLUGIN_EP_VERSION="${onnxruntime_PLUGIN_EP_VERSION}") + +if (onnxruntime_USE_CUDA_NHWC_OPS) + target_compile_definitions(onnxruntime_providers_cuda_plugin PRIVATE ENABLE_CUDA_NHWC_OPS) +endif() + +if(WIN32) + # Windows: use .def file for symbol exports + set(CUDA_PLUGIN_DEF_FILE ${CUDA_PLUGIN_EP_DIR}/cuda_plugin_ep_symbols.def) + if(EXISTS ${CUDA_PLUGIN_DEF_FILE}) + target_sources(onnxruntime_providers_cuda_plugin PRIVATE ${CUDA_PLUGIN_DEF_FILE}) + endif() +else() + # Linux/macOS: hide all symbols by default, explicitly export via __attribute__((visibility("default"))) + set_target_properties(onnxruntime_providers_cuda_plugin PROPERTIES + C_VISIBILITY_PRESET hidden + CXX_VISIBILITY_PRESET hidden + ) +endif() + + + +# Set output name and solution folder +set_target_properties(onnxruntime_providers_cuda_plugin PROPERTIES + OUTPUT_NAME "onnxruntime_providers_cuda_plugin" + FOLDER "ONNXRuntime" +) + +# Install +install(TARGETS onnxruntime_providers_cuda_plugin + LIBRARY DESTINATION lib + RUNTIME DESTINATION bin +) diff --git a/cmake/onnxruntime_providers_dml.cmake b/cmake/onnxruntime_providers_dml.cmake index 3141aa85a1163..ac4f0103ea323 100644 --- a/cmake/onnxruntime_providers_dml.cmake +++ b/cmake/onnxruntime_providers_dml.cmake @@ -11,6 +11,9 @@ onnxruntime_add_include_to_target(onnxruntime_providers_dml onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers Boost::mp11 safeint_interface ${WIL_TARGET} ) + if(TARGET Microsoft::DirectX-Headers) + onnxruntime_add_include_to_target(onnxruntime_providers_dml Microsoft::DirectX-Headers) + endif() add_dependencies(onnxruntime_providers_dml ${onnxruntime_EXTERNAL_DEPENDENCIES}) target_include_directories(onnxruntime_providers_dml PRIVATE ${ONNXRUNTIME_ROOT} @@ -56,7 +59,7 @@ if (GDK_PLATFORM STREQUAL Scarlett) target_link_libraries(onnxruntime_providers_dml PRIVATE ${gdk_dx_libs}) else() - target_link_libraries(onnxruntime_providers_dml PRIVATE dxguid.lib d3d12.lib dxgi.lib dxcore.lib) + target_link_libraries(onnxruntime_providers_dml PRIVATE dxguid.lib d3d12.lib dxgi.lib) endif() target_link_libraries(onnxruntime_providers_dml PRIVATE delayimp.lib) @@ -84,7 +87,7 @@ set_target_properties(onnxruntime_providers_dml PROPERTIES FOLDER "ONNXRuntime") if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_providers_dml + install(TARGETS onnxruntime_providers_dml EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/cmake/onnxruntime_providers_dnnl.cmake b/cmake/onnxruntime_providers_dnnl.cmake index 9e5a7eed44fff..07926a34d5cab 100644 --- a/cmake/onnxruntime_providers_dnnl.cmake +++ b/cmake/onnxruntime_providers_dnnl.cmake @@ -17,9 +17,9 @@ endif() add_dependencies(onnxruntime_providers_dnnl onnxruntime_providers_shared project_dnnl ${onnxruntime_EXTERNAL_DEPENDENCIES}) - target_include_directories(onnxruntime_providers_dnnl PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS} ${DNNL_INCLUDE_DIR} ${DNNL_OCL_INCLUDE_DIR}) + target_include_directories(onnxruntime_providers_dnnl PRIVATE ${ONNXRUNTIME_ROOT} ${DNNL_INCLUDE_DIR} ${DNNL_OCL_INCLUDE_DIR}) # ${CMAKE_CURRENT_BINARY_DIR} is so that #include "onnxruntime_config.h" inside tensor_shape.h is found - target_link_libraries(onnxruntime_providers_dnnl PRIVATE dnnl ${ONNXRUNTIME_PROVIDERS_SHARED} Boost::mp11 ${ABSEIL_LIBS} ${GSL_TARGET} safeint_interface) + target_link_libraries(onnxruntime_providers_dnnl PRIVATE dnnl ${ONNXRUNTIME_PROVIDERS_SHARED} Boost::mp11 ${ABSEIL_LIBS} ${GSL_TARGET} safeint_interface Eigen3::Eigen) install(FILES ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/providers/dnnl/dnnl_provider_options.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/) set_target_properties(onnxruntime_providers_dnnl PROPERTIES FOLDER "ONNXRuntime") diff --git a/cmake/onnxruntime_providers_js.cmake b/cmake/onnxruntime_providers_js.cmake index 306f5c74cb4c6..fefbab5082da4 100644 --- a/cmake/onnxruntime_providers_js.cmake +++ b/cmake/onnxruntime_providers_js.cmake @@ -1,6 +1,10 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. + if (onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD) + message(FATAL_ERROR "JSEP can not be used in a basic minimal build. Please build with '--minimal_build extended'") + endif() + add_compile_definitions(USE_JSEP=1) file(GLOB_RECURSE onnxruntime_providers_js_cc_srcs @@ -15,7 +19,7 @@ source_group(TREE ${ONNXRUNTIME_ROOT} FILES ${onnxruntime_providers_js_cc_srcs}) onnxruntime_add_static_library(onnxruntime_providers_js ${onnxruntime_providers_js_cc_srcs}) onnxruntime_add_include_to_target(onnxruntime_providers_js - onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers Boost::mp11 + onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers Boost::mp11 Eigen3::Eigen ) - target_include_directories(onnxruntime_providers_js PRIVATE ${eigen_INCLUDE_DIRS}) - add_dependencies(onnxruntime_providers_js ${onnxruntime_EXTERNAL_DEPENDENCIES}) \ No newline at end of file + + add_dependencies(onnxruntime_providers_js ${onnxruntime_EXTERNAL_DEPENDENCIES}) diff --git a/cmake/onnxruntime_providers_migraphx.cmake b/cmake/onnxruntime_providers_migraphx.cmake index 685e77bc483bd..8cb5dcf95155a 100644 --- a/cmake/onnxruntime_providers_migraphx.cmake +++ b/cmake/onnxruntime_providers_migraphx.cmake @@ -2,27 +2,19 @@ # Licensed under the MIT License. add_definitions(-DUSE_MIGRAPHX=1) - set(BUILD_LIBRARY_ONLY 1) - add_definitions("-DONNX_ML=1") - add_definitions("-DONNX_NAMESPACE=onnx") - include_directories(${protobuf_SOURCE_DIR} ${eigen_SOURCE_DIR}) - set(MIGRAPHX_ROOT ${onnxruntime_MIGRAPHX_HOME}) - include_directories(${onnx_SOURCE_DIR}) + include_directories(${protobuf_SOURCE_DIR} ${eigen_SOURCE_DIR} ${onnx_SOURCE_DIR}) set(OLD_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) - if ( CMAKE_COMPILER_IS_GNUCC ) + if (CMAKE_COMPILER_IS_GNUCC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wno-missing-field-initializers") endif() - set(CXX_VERSION_DEFINED TRUE) - set(CMAKE_CXX_FLAGS ${OLD_CMAKE_CXX_FLAGS}) - if ( CMAKE_COMPILER_IS_GNUCC ) - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter") - endif() # Add search paths for default rocm installation list(APPEND CMAKE_PREFIX_PATH /opt/rocm/hcc /opt/rocm/hip /opt/rocm $ENV{HIP_PATH}) - # Suppress the warning about the small capitals of the package name - Enable when support to CMake 3.27.0 is used - # cmake_policy(SET CMP0144 NEW) + if(POLICY CMP0144) + # Suppress the warning about the small capitals of the package name + cmake_policy(SET CMP0144 NEW) + endif() if(WIN32 AND NOT HIP_PLATFORM) set(HIP_PLATFORM "amd") @@ -31,8 +23,6 @@ find_package(hip REQUIRED) find_package(migraphx REQUIRED PATHS ${AMD_MIGRAPHX_HOME}) - set(migraphx_libs migraphx::c hip::host) - file(GLOB_RECURSE onnxruntime_providers_migraphx_cc_srcs CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/core/providers/migraphx/*.h" "${ONNXRUNTIME_ROOT}/core/providers/migraphx/*.cc" @@ -40,14 +30,14 @@ "${ONNXRUNTIME_ROOT}/core/providers/shared_library/*.cc" ) source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_migraphx_cc_srcs}) - onnxruntime_add_shared_library_module(onnxruntime_providers_migraphx ${onnxruntime_providers_migraphx_cc_srcs}) + onnxruntime_add_shared_library(onnxruntime_providers_migraphx ${onnxruntime_providers_migraphx_cc_srcs}) onnxruntime_add_include_to_target(onnxruntime_providers_migraphx onnxruntime_common onnx flatbuffers::flatbuffers Boost::mp11 safeint_interface) - add_dependencies(onnxruntime_providers_migraphx onnxruntime_providers_shared ${onnxruntime_EXTERNAL_DEPENDENCIES}) - target_link_libraries(onnxruntime_providers_migraphx PRIVATE ${migraphx_libs} ${ONNXRUNTIME_PROVIDERS_SHARED} onnx flatbuffers::flatbuffers Boost::mp11 safeint_interface) - target_include_directories(onnxruntime_providers_migraphx PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime) + add_dependencies(onnxruntime_providers_migraphx ${onnxruntime_EXTERNAL_DEPENDENCIES}) + target_link_libraries(onnxruntime_providers_migraphx PRIVATE migraphx::c hip::host ${ONNXRUNTIME_PROVIDERS_SHARED} onnx flatbuffers::flatbuffers Boost::mp11 safeint_interface) + target_include_directories(onnxruntime_providers_migraphx PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/migraphx/onnxruntime) set_target_properties(onnxruntime_providers_migraphx PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(onnxruntime_providers_migraphx PROPERTIES FOLDER "ONNXRuntime") - target_compile_definitions(onnxruntime_providers_migraphx PRIVATE ONNXIFI_BUILD_LIBRARY=1) + target_compile_definitions(onnxruntime_providers_migraphx PRIVATE ONNXIFI_BUILD_LIBRARY=1 ONNX_ML=1 ONNX_NAMESPACE=onnx) if(MSVC) set_property(TARGET onnxruntime_providers_migraphx APPEND_STRING PROPERTY LINK_FLAGS /DEF:${ONNXRUNTIME_ROOT}/core/providers/migraphx/symbols.def) target_link_libraries(onnxruntime_providers_migraphx PRIVATE ws2_32) @@ -60,6 +50,15 @@ target_link_libraries(onnxruntime_providers_migraphx PRIVATE stdc++fs) endif() + set(CMAKE_REQUIRED_LIBRARIES migraphx::c) + + check_symbol_exists(migraphx_onnx_options_set_external_data_path + "migraphx/migraphx.h" HAVE_MIGRAPHX_API_ONNX_OPTIONS_SET_EXTERNAL_DATA_PATH) + + if(HAVE_MIGRAPHX_API_ONNX_OPTIONS_SET_EXTERNAL_DATA_PATH) + target_compile_definitions(onnxruntime_providers_migraphx PRIVATE HAVE_MIGRAPHX_API_ONNX_OPTIONS_SET_EXTERNAL_DATA_PATH=1) + endif() + if (onnxruntime_ENABLE_TRAINING_OPS) onnxruntime_add_include_to_target(onnxruntime_providers_migraphx onnxruntime_training) target_link_libraries(onnxruntime_providers_migraphx PRIVATE onnxruntime_training) @@ -69,15 +68,39 @@ endif() if(CMAKE_SYSTEM_NAME STREQUAL "Windows") - install(TARGETS onnxruntime_providers_migraphx - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_BINDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - ) - else() - install(TARGETS onnxruntime_providers_migraphx - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} - ) + foreach(file migraphx-hiprtc-driver.exe migraphx.dll migraphx_c.dll migraphx_cpu.dll migraphx_device.dll migraphx_gpu.dll migraphx_onnx.dll migraphx_tf.dll) + set(_source "${AMD_MIGRAPHX_HOME}/bin/${file}") + if(EXISTS "${_source}") + add_custom_command(TARGET onnxruntime_providers_migraphx + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_source} $) + set(_target "$/${file}") + list(APPEND _migraphx_targets ${_target}) + endif() + endforeach() + set(MIGRAPHX_LIB_FILES ${_migraphx_targets} CACHE INTERNAL "" FORCE) + install(FILES ${_migraphx_targets} + DESTINATION ${CMAKE_INSTALL_BINDIR}) + get_property(_amdhip64_location TARGET hip::amdhip64 PROPERTY IMPORTED_LOCATION_RELEASE) + cmake_path(GET _amdhip64_location PARENT_PATH _hipsdk_path) + foreach(file amd_comgr0602.dll amd_comgr0604.dll amd_comgr0700.dll hiprtc0602.dll hiprtc0604.dll hiprtc0700.dll hiprtc-builtins0602.dll hiprtc-builtins0604.dll hiprtc-builtins0700.dll) + set(_source "${_hipsdk_path}/${file}") + if(EXISTS "${_source}") + add_custom_command(TARGET onnxruntime_providers_migraphx + POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different ${_source} $) + set(_target "$/${file}") + list(APPEND _hipsdk_targets ${_target}) + endif() + endforeach() + set(HIPSDK_LIB_FILES ${_hipsdk_targets} CACHE INTERNAL "" FORCE) + install(FILES ${_hipsdk_targets} + DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() + + install(TARGETS onnxruntime_providers_migraphx + EXPORT onnxruntime_providers_migraphxTargets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/cmake/onnxruntime_providers_nnapi.cmake b/cmake/onnxruntime_providers_nnapi.cmake index b718a976eb26f..06364ebd49593 100644 --- a/cmake/onnxruntime_providers_nnapi.cmake +++ b/cmake/onnxruntime_providers_nnapi.cmake @@ -74,7 +74,7 @@ endif() if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_providers_nnapi + install(TARGETS onnxruntime_providers_nnapi EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/cmake/onnxruntime_providers_nv.cmake b/cmake/onnxruntime_providers_nv.cmake new file mode 100644 index 0000000000000..92fc0ccadd667 --- /dev/null +++ b/cmake/onnxruntime_providers_nv.cmake @@ -0,0 +1,201 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. +# Licensed under the MIT License. + if(onnxruntime_CUDA_HOME) + file(TO_CMAKE_PATH ${onnxruntime_CUDA_HOME} CUDAToolkit_ROOT) + endif() + find_package(CUDAToolkit REQUIRED) + enable_language(CUDA) + if(onnxruntime_DISABLE_CONTRIB_OPS) + message( FATAL_ERROR "To compile TensorRT execution provider contrib ops have to be enabled to dump an engine using com.microsoft:EPContext node." ) + endif() + add_definitions(-DUSE_NV=1) + if (onnxruntime_NV_PLACEHOLDER_BUILDER) + add_definitions(-DORT_NV_PLACEHOLDER_BUILDER) + endif() +if (NOT onnxruntime_USE_TENSORRT_BUILTIN_PARSER) + message(FATAL_ERROR "TensorRT RTX can not be used with the open source parser.") +endif () + set(BUILD_LIBRARY_ONLY 1) + add_definitions("-DONNX_ML=1") + add_definitions("-DONNX_NAMESPACE=onnx") + set(CUDA_INCLUDE_DIRS ${CUDAToolkit_INCLUDE_DIRS}) + set(TENSORRT_RTX_ROOT ${onnxruntime_TENSORRT_RTX_HOME}) + set(OLD_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) + set(PROTOBUF_LIBRARY ${PROTOBUF_LIB}) + if (WIN32) + set(OLD_CMAKE_CUDA_FLAGS ${CMAKE_CUDA_FLAGS}) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4099 /wd4551 /wd4505 /wd4515 /wd4706 /wd4456 /wd4324 /wd4701 /wd4804 /wd4702 /wd4458 /wd4703") + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4805") + endif() + set(CMAKE_CUDA_FLAGS "${CMAKE_CUDA_FLAGS} -include algorithm") + set(DISABLED_WARNINGS_FOR_TRT /wd4456) + endif() + if ( CMAKE_COMPILER_IS_GNUCC ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter -Wno-missing-field-initializers") + endif() + set(CXX_VERSION_DEFINED TRUE) + + find_path(TENSORRT_RTX_INCLUDE_DIR NvInfer.h + HINTS ${TENSORRT_RTX_ROOT} + PATH_SUFFIXES include) + + + file(READ ${TENSORRT_RTX_INCLUDE_DIR}/NvInferVersion.h NVINFER_VER_CONTENT) + string(REGEX MATCH "define TRT_MAJOR_RTX * +([0-9]+)" NV_TRT_MAJOR_RTX "${NVINFER_VER_CONTENT}") + string(REGEX REPLACE "define TRT_MAJOR_RTX * +([0-9]+)" "\\1" NV_TRT_MAJOR_RTX "${NV_TRT_MAJOR_RTX}") + string(REGEX MATCH "define TRT_MINOR_RTX * +([0-9]+)" NV_TRT_MINOR_RTX "${NVINFER_VER_CONTENT}") + string(REGEX REPLACE "define TRT_MINOR_RTX * +([0-9]+)" "\\1" NV_TRT_MINOR_RTX "${NV_TRT_MINOR_RTX}") + math(EXPR NV_TRT_MAJOR_RTX_INT "${NV_TRT_MAJOR_RTX}") + math(EXPR NV_TRT_MINOR_RTX_INT "${NV_TRT_MINOR_RTX}") + + if (NV_TRT_MAJOR_RTX) + MESSAGE(STATUS "NV_TRT_MAJOR_RTX is ${NV_TRT_MAJOR_RTX}") + else() + MESSAGE(STATUS "Can't find NV_TRT_MAJOR_RTX macro") + endif() + + if (WIN32) + set(TRT_RTX_LIB "tensorrt_rtx_${NV_TRT_MAJOR_RTX}_${NV_TRT_MINOR_RTX}") + set(RTX_PARSER_LIB "tensorrt_onnxparser_rtx_${NV_TRT_MAJOR_RTX}_${NV_TRT_MINOR_RTX}") + endif() + + if (NOT TRT_RTX_LIB) + set(TRT_RTX_LIB "tensorrt_rtx") + endif() + + if (NOT RTX_PARSER_LIB) + set(RTX_PARSER_LIB "tensorrt_onnxparser_rtx") + endif() + + MESSAGE(STATUS "Looking for ${TRT_RTX_LIB}") + + find_library(TENSORRT_LIBRARY_INFER ${TRT_RTX_LIB} + HINTS ${TENSORRT_RTX_ROOT} + PATH_SUFFIXES lib lib64 lib/x64) + + if (NOT TENSORRT_LIBRARY_INFER) + MESSAGE(STATUS "Can't find ${TRT_RTX_LIB}") + endif() + + if (onnxruntime_USE_TENSORRT_BUILTIN_PARSER) + MESSAGE(STATUS "Looking for ${RTX_PARSER_LIB}") + + find_library(TENSORRT_LIBRARY_NVONNXPARSER ${RTX_PARSER_LIB} + HINTS ${TENSORRT_RTX_ROOT} + PATH_SUFFIXES lib lib64 lib/x64) + + if (NOT TENSORRT_LIBRARY_NVONNXPARSER) + MESSAGE(STATUS "Can't find ${RTX_PARSER_LIB}") + endif() + + set(TENSORRT_LIBRARY ${TENSORRT_LIBRARY_INFER} ${TENSORRT_LIBRARY_NVONNXPARSER}) + MESSAGE(STATUS "Find TensorRT libs at ${TENSORRT_LIBRARY}") + else() + set(ONNX_USE_LITE_PROTO ON) + + onnxruntime_fetchcontent_declare( + onnx_tensorrt + URL ${DEP_URL_onnx_tensorrt} + URL_HASH SHA1=${DEP_SHA1_onnx_tensorrt} + EXCLUDE_FROM_ALL + ) + if (NOT CUDA_INCLUDE_DIR) + set(CUDA_INCLUDE_DIR ${CUDAToolkit_INCLUDE_DIRS}) # onnx-tensorrt repo needs this variable to build + endif() + # The onnx_tensorrt repo contains a test program, getSupportedAPITest, which doesn't support Windows. It uses + # unistd.h. So we must exclude it from our build. onnxruntime_fetchcontent_makeavailable is for the purpose. + onnxruntime_fetchcontent_makeavailable(onnx_tensorrt) + set(CMAKE_CXX_FLAGS ${OLD_CMAKE_CXX_FLAGS}) + if ( CMAKE_COMPILER_IS_GNUCC ) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter") + endif() + if (WIN32) + set(CMAKE_CUDA_FLAGS ${OLD_CMAKE_CUDA_FLAGS}) + unset(PROTOBUF_LIBRARY) + unset(OLD_CMAKE_CXX_FLAGS) + unset(OLD_CMAKE_CUDA_FLAGS) + set_target_properties(${RTX_PARSER_LIB} PROPERTIES LINK_FLAGS "/ignore:4199") + target_compile_options(nvonnxparser_static PRIVATE /FIio.h /wd4100) + target_compile_options(${RTX_PARSER_LIB} PRIVATE /FIio.h /wd4100) + endif() + # Static libraries are just nvonnxparser_static on all platforms + set(onnxparser_link_libs nvonnxparser_static) + set(TENSORRT_LIBRARY ${TENSORRT_LIBRARY_INFER}) + MESSAGE(STATUS "Find TensorRT libs at ${TENSORRT_LIBRARY}") + endif() + + # ${TENSORRT_LIBRARY} is empty if we link nvonnxparser_static. + # nvonnxparser_static is linked against tensorrt libraries in onnx-tensorrt + # See https://github.com/onnx/onnx-tensorrt/blob/8af13d1b106f58df1e98945a5e7c851ddb5f0791/CMakeLists.txt#L121 + # However, starting from TRT 10 GA, nvonnxparser_static doesn't link against tensorrt libraries. + # Therefore, the above code finds ${TENSORRT_LIBRARY_INFER} + set(trt_link_libs ${CMAKE_DL_LIBS} ${TENSORRT_LIBRARY}) + + file(GLOB_RECURSE onnxruntime_providers_nv_tensorrt_rtx_cc_srcs CONFIGURE_DEPENDS + "${ONNXRUNTIME_ROOT}/core/providers/nv_tensorrt_rtx/*.h" + "${ONNXRUNTIME_ROOT}/core/providers/nv_tensorrt_rtx/*.cc" + "${ONNXRUNTIME_ROOT}/core/providers/shared_library/*.h" + "${ONNXRUNTIME_ROOT}/core/providers/shared_library/*.cc" + "${ONNXRUNTIME_ROOT}/core/providers/cuda/cuda_stream_handle.h" + "${ONNXRUNTIME_ROOT}/core/providers/cuda/cuda_stream_handle.cc" + "${ONNXRUNTIME_ROOT}/core/providers/cuda/cuda_graph.h" + "${ONNXRUNTIME_ROOT}/core/providers/cuda/cuda_graph.cc" + ) + + source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_nv_tensorrt_rtx_cc_srcs}) + onnxruntime_add_shared_library_module(onnxruntime_providers_nv_tensorrt_rtx ${onnxruntime_providers_nv_tensorrt_rtx_cc_srcs}) + onnxruntime_add_include_to_target(onnxruntime_providers_nv_tensorrt_rtx onnxruntime_common) + target_link_libraries(onnxruntime_providers_nv_tensorrt_rtx PRIVATE Eigen3::Eigen onnx flatbuffers::flatbuffers Boost::mp11 safeint_interface Eigen3::Eigen) + add_dependencies(onnxruntime_providers_nv_tensorrt_rtx onnxruntime_providers_shared ${onnxruntime_EXTERNAL_DEPENDENCIES}) + # Make NVML linkage optional: only link CUDA::nvml if the target exists. + set(_nvml_lib "") + if (TARGET CUDA::nvml) + set(_nvml_lib CUDA::nvml) + endif() + if (onnxruntime_USE_TENSORRT_BUILTIN_PARSER) + target_link_libraries(onnxruntime_providers_nv_tensorrt_rtx PRIVATE ${trt_link_libs} ${ONNXRUNTIME_PROVIDERS_SHARED} ${PROTOBUF_LIB} flatbuffers::flatbuffers Boost::mp11 safeint_interface ${ABSEIL_LIBS} ${_nvml_lib} PUBLIC CUDA::cudart CUDA::cuda_driver) + else() + target_link_libraries(onnxruntime_providers_nv_tensorrt_rtx PRIVATE ${onnxparser_link_libs} ${trt_link_libs} ${ONNXRUNTIME_PROVIDERS_SHARED} ${PROTOBUF_LIB} flatbuffers::flatbuffers ${ABSEIL_LIBS} ${_nvml_lib} PUBLIC CUDA::cudart CUDA::cuda_driver) + endif() + target_include_directories(onnxruntime_providers_nv_tensorrt_rtx PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${TENSORRT_RTX_INCLUDE_DIR} ${onnx_tensorrt_SOURCE_DIR} + PUBLIC ${CUDAToolkit_INCLUDE_DIRS}) + + # ${CMAKE_CURRENT_BINARY_DIR} is so that #include "onnxruntime_config.h" inside tensor_shape.h is found + set_target_properties(onnxruntime_providers_nv_tensorrt_rtx PROPERTIES LINKER_LANGUAGE CUDA) + set_target_properties(onnxruntime_providers_nv_tensorrt_rtx PROPERTIES FOLDER "ONNXRuntime") + target_compile_definitions(onnxruntime_providers_nv_tensorrt_rtx PRIVATE ONNXIFI_BUILD_LIBRARY=1) + if (TARGET CUDA::nvml) + target_compile_definitions(onnxruntime_providers_nv_tensorrt_rtx PRIVATE HAVE_NVML=1) + endif() + target_compile_options(onnxruntime_providers_nv_tensorrt_rtx PRIVATE ${DISABLED_WARNINGS_FOR_TRT}) + if (WIN32) + target_compile_options(onnxruntime_providers_nv_tensorrt_rtx INTERFACE /wd4456) + endif() + # set CUDA_MINIMAL as default for NV provider since we do not have fallback to CUDA + target_compile_definitions(onnxruntime_providers_nv_tensorrt_rtx PRIVATE USE_CUDA_MINIMAL=1) + + # Needed for the provider interface, as it includes training headers when training is enabled + if (onnxruntime_ENABLE_TRAINING_OPS) + target_include_directories(onnxruntime_providers_nv_tensorrt_rtx PRIVATE ${ORTTRAINING_ROOT}) + if (onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) + onnxruntime_add_include_to_target(onnxruntime_providers_nv_tensorrt_rtx Python::Module) + endif() + endif() + + if(APPLE) + set_property(TARGET onnxruntime_providers_nv_tensorrt_rtx APPEND_STRING PROPERTY LINK_FLAGS "-Xlinker -exported_symbols_list ${ONNXRUNTIME_ROOT}/core/providers/nv_tensorrt_rtx/exported_symbols.lst") + elseif(UNIX) + set_property(TARGET onnxruntime_providers_nv_tensorrt_rtx APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-deprecated-declarations") + set_property(TARGET onnxruntime_providers_nv_tensorrt_rtx APPEND_STRING PROPERTY LINK_FLAGS "-Xlinker --version-script=${ONNXRUNTIME_ROOT}/core/providers/nv_tensorrt_rtx/version_script.lds -Xlinker --gc-sections") + elseif(WIN32) + set_property(TARGET onnxruntime_providers_nv_tensorrt_rtx APPEND_STRING PROPERTY LINK_FLAGS "-DEF:${ONNXRUNTIME_ROOT}/core/providers/nv_tensorrt_rtx/symbols.def") + else() + message(FATAL_ERROR "onnxruntime_providers_nv_tensorrt_rtx unknown platform, need to specify shared library exports for it") + endif() + + install(TARGETS onnxruntime_providers_nv_tensorrt_rtx + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/cmake/onnxruntime_providers_openvino.cmake b/cmake/onnxruntime_providers_openvino.cmake index f5fae8d169ccc..882fc56d9a40b 100644 --- a/cmake/onnxruntime_providers_openvino.cmake +++ b/cmake/onnxruntime_providers_openvino.cmake @@ -13,8 +13,8 @@ # Header paths find_package(OpenVINO REQUIRED COMPONENTS Runtime ONNX) - if(OpenVINO_VERSION VERSION_LESS 2024.4) - message(FATAL_ERROR "OpenVINO 2024.4 and newer are supported. Please, use latest OpenVINO release") + if(OpenVINO_VERSION VERSION_LESS 2025.0) + message(FATAL_ERROR "OpenVINO 2025.0 and newer are supported. Please, use latest OpenVINO release") endif() if(OpenVINO_VERSION VERSION_GREATER_EQUAL 2024.4) @@ -30,30 +30,41 @@ endif() list(APPEND OPENVINO_LIB_LIST openvino::frontend::onnx openvino::runtime ${PYTHON_LIBRARIES}) - if ((DEFINED ENV{OPENCL_LIBS}) AND (DEFINED ENV{OPENCL_INCS})) - add_definitions(-DIO_BUFFER_ENABLED=1) - list(APPEND OPENVINO_LIB_LIST $ENV{OPENCL_LIBS}) - endif() - source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_openvino_cc_srcs}) onnxruntime_add_shared_library_module(onnxruntime_providers_openvino ${onnxruntime_providers_openvino_cc_srcs} "${ONNXRUNTIME_ROOT}/core/dll/onnxruntime.rc") + + # Propagate leak check define if enabled at top level + if(onnxruntime_ENABLE_MEMLEAK_CHECKER) + target_compile_definitions(onnxruntime_providers_openvino PRIVATE ONNXRUNTIME_ENABLE_MEMLEAK_CHECK) + endif() + onnxruntime_add_include_to_target(onnxruntime_providers_openvino onnxruntime_common onnx nlohmann_json::nlohmann_json) install(FILES ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/providers/openvino/openvino_provider_factory.h DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/) set_target_properties(onnxruntime_providers_openvino PROPERTIES CXX_STANDARD 20) set_target_properties(onnxruntime_providers_openvino PROPERTIES LINKER_LANGUAGE CXX) set_target_properties(onnxruntime_providers_openvino PROPERTIES FOLDER "ONNXRuntime") + + target_compile_options(onnxruntime_providers_openvino PRIVATE + $<$:-DRELEASE> + ) + if(NOT MSVC) target_compile_options(onnxruntime_providers_openvino PRIVATE "-Wno-parentheses") endif() add_dependencies(onnxruntime_providers_openvino onnxruntime_providers_shared ${onnxruntime_EXTERNAL_DEPENDENCIES}) - target_include_directories(onnxruntime_providers_openvino SYSTEM PUBLIC ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${eigen_INCLUDE_DIRS} ${OpenVINO_INCLUDE_DIR} ${OPENVINO_INCLUDE_DIR_LIST} ${PYTHON_INCLUDE_DIRS} $ENV{OPENCL_INCS} $ENV{OPENCL_INCS}/../../cl_headers/) - target_link_libraries(onnxruntime_providers_openvino ${ONNXRUNTIME_PROVIDERS_SHARED} Boost::mp11 ${OPENVINO_LIB_LIST} ${ABSEIL_LIBS}) + target_include_directories(onnxruntime_providers_openvino SYSTEM PUBLIC ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${OpenVINO_INCLUDE_DIR} ${OPENVINO_INCLUDE_DIR_LIST} ${PYTHON_INCLUDE_DIRS} $ENV{OPENCL_INCS} $ENV{OPENCL_INCS}/../../cl_headers/) + target_link_libraries(onnxruntime_providers_openvino ${ONNXRUNTIME_PROVIDERS_SHARED} Boost::mp11 ${OPENVINO_LIB_LIST} ${ABSEIL_LIBS} Eigen3::Eigen onnx_proto) + + # ETW TraceLogging depends on Advapi32 on Windows + if(WIN32) + target_link_libraries(onnxruntime_providers_openvino advapi32) + endif() target_compile_definitions(onnxruntime_providers_openvino PRIVATE FILE_NAME=\"onnxruntime_providers_openvino.dll\") if(MSVC) - target_compile_options(onnxruntime_providers_openvino PUBLIC /wd4099 /wd4275 /wd4100 /wd4005 /wd4244 /wd4267) + target_compile_options(onnxruntime_providers_openvino PRIVATE /wd4099 /wd4275 /wd4100 /wd4005) endif() # Needed for the provider interface, as it includes training headers when training is enabled @@ -86,4 +97,4 @@ set_target_properties(onnxruntime_providers_openvino PROPERTIES MAP_IMPORTED_CONFIG_RELEASE RelWithDebInfo MAP_IMPORTED_CONFIG_DEBUG RelWithDebInfo - ) \ No newline at end of file + ) diff --git a/cmake/onnxruntime_providers_pch.cmake b/cmake/onnxruntime_providers_pch.cmake new file mode 100644 index 0000000000000..dc05853bb1cf4 --- /dev/null +++ b/cmake/onnxruntime_providers_pch.cmake @@ -0,0 +1,8 @@ +# Precompiled header configuration for onnxruntime_providers + +if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + # Visual Studio PCH + target_precompile_headers(onnxruntime_providers PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/providers_pch.h" + ) +endif() diff --git a/cmake/onnxruntime_providers_qnn.cmake b/cmake/onnxruntime_providers_qnn.cmake index 303020145889b..f499c83d5f6c0 100644 --- a/cmake/onnxruntime_providers_qnn.cmake +++ b/cmake/onnxruntime_providers_qnn.cmake @@ -13,6 +13,27 @@ "${ONNXRUNTIME_ROOT}/core/providers/qnn/*.cc" ) + function(extract_qnn_sdk_version_from_yaml QNN_SDK_YAML_FILE QNN_VERSION_OUTPUT) + file(READ "${QNN_SDK_YAML_FILE}" QNN_SDK_YAML_CONTENT) + # Match a line of text like "version: 1.33.2" + string(REGEX MATCH "(^|\n|\r)version: ([0-9]+\\.[0-9]+\\.[0-9]+)" QNN_VERSION_MATCH "${QNN_SDK_YAML_CONTENT}") + if(QNN_VERSION_MATCH) + set(${QNN_VERSION_OUTPUT} "${CMAKE_MATCH_2}" PARENT_SCOPE) + message(STATUS "Extracted QNN SDK version ${CMAKE_MATCH_2} from ${QNN_SDK_YAML_FILE}") + else() + message(WARNING "Failed to extract QNN SDK version from ${QNN_SDK_YAML_FILE}") + endif() + endfunction() + + if(NOT QNN_SDK_VERSION) + if(EXISTS "${onnxruntime_QNN_HOME}/sdk.yaml") + extract_qnn_sdk_version_from_yaml("${onnxruntime_QNN_HOME}/sdk.yaml" QNN_SDK_VERSION) + else() + message(WARNING "Cannot open sdk.yaml to extract QNN SDK version") + endif() + endif() + message(STATUS "QNN SDK version ${QNN_SDK_VERSION}") + if(onnxruntime_BUILD_QNN_EP_STATIC_LIB) # # Build QNN EP as a static library @@ -22,7 +43,8 @@ onnxruntime_add_static_library(onnxruntime_providers_qnn ${onnxruntime_providers_qnn_srcs}) onnxruntime_add_include_to_target(onnxruntime_providers_qnn onnxruntime_common onnxruntime_framework onnx onnx_proto protobuf::libprotobuf-lite - flatbuffers::flatbuffers Boost::mp11) + flatbuffers::flatbuffers Boost::mp11 + nlohmann_json::nlohmann_json) add_dependencies(onnxruntime_providers_qnn onnx ${onnxruntime_EXTERNAL_DEPENDENCIES}) set_target_properties(onnxruntime_providers_qnn PROPERTIES CXX_STANDARD_REQUIRED ON) set_target_properties(onnxruntime_providers_qnn PROPERTIES FOLDER "ONNXRuntime") @@ -35,6 +57,21 @@ if(NOT MSVC) target_compile_options(onnxruntime_providers_qnn PRIVATE "-Wno-unknown-pragmas") endif() + + set(onnxruntime_providers_qnn_target onnxruntime_providers_qnn) + + if (MSVC OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + add_custom_command( + TARGET ${onnxruntime_providers_qnn_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${QNN_LIB_FILES} $ + ) + endif() + if (EXISTS "${onnxruntime_QNN_HOME}/LICENSE.pdf") + add_custom_command( + TARGET ${onnxruntime_providers_qnn_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${onnxruntime_QNN_HOME}/LICENSE.pdf" $/Qualcomm_LICENSE.pdf + ) + endif() else() # # Build QNN EP as a shared library @@ -45,12 +82,20 @@ "${ONNXRUNTIME_ROOT}/core/providers/shared_library/*.cc" ) set(onnxruntime_providers_qnn_srcs ${onnxruntime_providers_qnn_ep_srcs} - ${onnxruntime_providers_qnn_shared_lib_srcs}) + ${onnxruntime_providers_qnn_shared_lib_srcs}) source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_qnn_srcs}) - onnxruntime_add_shared_library_module(onnxruntime_providers_qnn ${onnxruntime_providers_qnn_srcs}) + + set(onnxruntime_providers_qnn_all_srcs ${onnxruntime_providers_qnn_srcs}) + if(WIN32) + # Sets the DLL version info on Windows: https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource + list(APPEND onnxruntime_providers_qnn_all_srcs "${ONNXRUNTIME_ROOT}/core/providers/qnn/onnxruntime_providers_qnn.rc") + endif() + + onnxruntime_add_shared_library_module(onnxruntime_providers_qnn ${onnxruntime_providers_qnn_all_srcs}) onnxruntime_add_include_to_target(onnxruntime_providers_qnn ${ONNXRUNTIME_PROVIDERS_SHARED} ${GSL_TARGET} onnx - onnxruntime_common Boost::mp11 safeint_interface) + onnxruntime_common Boost::mp11 safeint_interface + nlohmann_json::nlohmann_json) target_link_libraries(onnxruntime_providers_qnn PRIVATE ${ONNXRUNTIME_PROVIDERS_SHARED} ${ABSEIL_LIBS} ${CMAKE_DL_LIBS}) add_dependencies(onnxruntime_providers_qnn onnxruntime_providers_shared ${onnxruntime_EXTERNAL_DEPENDENCIES}) target_include_directories(onnxruntime_providers_qnn PRIVATE ${ONNXRUNTIME_ROOT} @@ -58,6 +103,18 @@ ${onnxruntime_QNN_HOME}/include/QNN ${onnxruntime_QNN_HOME}/include) + # Set preprocessor definitions used in onnxruntime_providers_qnn.rc + if(WIN32) + if(NOT QNN_SDK_VERSION) + set(QNN_DLL_FILE_DESCRIPTION "ONNX Runtime QNN Provider") + else() + set(QNN_DLL_FILE_DESCRIPTION "ONNX Runtime QNN Provider (QAIRT ${QNN_SDK_VERSION})") + endif() + + target_compile_definitions(onnxruntime_providers_qnn PRIVATE FILE_DESC=\"${QNN_DLL_FILE_DESCRIPTION}\") + target_compile_definitions(onnxruntime_providers_qnn PRIVATE FILE_NAME=\"onnxruntime_providers_qnn.dll\") + endif() + # Set linker flags for function(s) exported by EP DLL if(UNIX) target_link_options(onnxruntime_providers_qnn PRIVATE @@ -88,4 +145,27 @@ ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + + set(onnxruntime_providers_qnn_target onnxruntime_providers_qnn) + + if (MSVC OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + add_custom_command( + TARGET ${onnxruntime_providers_qnn_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy ${QNN_LIB_FILES} $ + ) + endif() + if (EXISTS "${onnxruntime_QNN_HOME}/LICENSE.pdf") + add_custom_command( + TARGET ${onnxruntime_providers_qnn_target} POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${onnxruntime_QNN_HOME}/LICENSE.pdf" $/Qualcomm_LICENSE.pdf + ) + endif() endif() + +if (NOT onnxruntime_BUILD_SHARED_LIB) + install(TARGETS onnxruntime_providers_qnn EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/cmake/onnxruntime_providers_rknpu.cmake b/cmake/onnxruntime_providers_rknpu.cmake index 408bcfde06c36..831df84aa6e08 100644 --- a/cmake/onnxruntime_providers_rknpu.cmake +++ b/cmake/onnxruntime_providers_rknpu.cmake @@ -36,9 +36,9 @@ set_target_properties(onnxruntime_providers_rknpu PROPERTIES LINKER_LANGUAGE CXX) if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_providers_rknpu + install(TARGETS onnxruntime_providers_rknpu EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) - endif() \ No newline at end of file + endif() diff --git a/cmake/onnxruntime_providers_rocm.cmake b/cmake/onnxruntime_providers_rocm.cmake deleted file mode 100644 index 68f5319c0ae8d..0000000000000 --- a/cmake/onnxruntime_providers_rocm.cmake +++ /dev/null @@ -1,236 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - - add_definitions(-DUSE_ROCM=1) - include(onnxruntime_rocm_hipify.cmake) - - list(APPEND CMAKE_PREFIX_PATH ${onnxruntime_ROCM_HOME}) - - find_package(HIP) - find_package(hiprand REQUIRED) - find_package(hipblas REQUIRED) - find_package(MIOpen REQUIRED) - find_package(hipfft REQUIRED) - - # MIOpen version - if(NOT DEFINED ENV{MIOPEN_PATH}) - set(MIOPEN_PATH ${onnxruntime_ROCM_HOME}) - else() - set(MIOPEN_PATH $ENV{MIOPEN_PATH}) - endif() - find_path(MIOPEN_VERSION_H_PATH - NAMES version.h - HINTS - ${MIOPEN_PATH}/include/miopen - ${MIOPEN_PATH}/miopen/include) - if (MIOPEN_VERSION_H_PATH-NOTFOUND) - MESSAGE(FATAL_ERROR "miopen version.h not found") - endif() - MESSAGE(STATUS "Found miopen version.h at ${MIOPEN_VERSION_H_PATH}") - - file(READ ${MIOPEN_VERSION_H_PATH}/version.h MIOPEN_HEADER_CONTENTS) - string(REGEX MATCH "define MIOPEN_VERSION_MAJOR * +([0-9]+)" - MIOPEN_VERSION_MAJOR "${MIOPEN_HEADER_CONTENTS}") - string(REGEX REPLACE "define MIOPEN_VERSION_MAJOR * +([0-9]+)" "\\1" - MIOPEN_VERSION_MAJOR "${MIOPEN_VERSION_MAJOR}") - string(REGEX MATCH "define MIOPEN_VERSION_MINOR * +([0-9]+)" - MIOPEN_VERSION_MINOR "${MIOPEN_HEADER_CONTENTS}") - string(REGEX REPLACE "define MIOPEN_VERSION_MINOR * +([0-9]+)" "\\1" - MIOPEN_VERSION_MINOR "${MIOPEN_VERSION_MINOR}") - string(REGEX MATCH "define MIOPEN_VERSION_PATCH * +([0-9]+)" - MIOPEN_VERSION_PATCH "${MIOPEN_HEADER_CONTENTS}") - string(REGEX REPLACE "define MIOPEN_VERSION_PATCH * +([0-9]+)" "\\1" - MIOPEN_VERSION_PATCH "${MIOPEN_VERSION_PATCH}") - set(MIOPEN_VERSION_DEV "${MIOPEN_VERSION_MAJOR}.${MIOPEN_VERSION_MINOR}.${MIOPEN_VERSION_PATCH}") - math(EXPR MIOPEN_VERSION_DEV_INT "(${MIOPEN_VERSION_MAJOR}*10000) + (${MIOPEN_VERSION_MINOR}*100) + ${MIOPEN_VERSION_PATCH}") - message("MIOPEN_VERSION_DEV: ${MIOPEN_VERSION_DEV}") - message("MIOPEN_VERSION_DEV_INT: ${MIOPEN_VERSION_DEV_INT}") - add_definitions(-DMIOPEN_VERSION=${MIOPEN_VERSION_DEV_INT}) - - find_library(RCCL_LIB rccl REQUIRED) - find_library(ROCTRACER_LIB roctracer64 REQUIRED) - find_package(rocm_smi REQUIRED) - set(ONNXRUNTIME_ROCM_LIBS roc::hipblas MIOpen hip::hipfft ${ROCM_SMI_LIBRARY} ${RCCL_LIB} ${ROCTRACER_LIB}) - include_directories(${ROCM_SMI_INCLUDE_DIR}) - link_directories(${ROCM_SMI_LIB_DIR}) - - file(GLOB_RECURSE onnxruntime_providers_rocm_cc_srcs CONFIGURE_DEPENDS - "${ONNXRUNTIME_ROOT}/core/providers/rocm/*.h" - "${ONNXRUNTIME_ROOT}/core/providers/rocm/*.cc" - ) - - # The shared_library files are in a separate list since they use precompiled headers, and the above files have them disabled. - file(GLOB_RECURSE onnxruntime_providers_rocm_shared_srcs CONFIGURE_DEPENDS - "${ONNXRUNTIME_ROOT}/core/providers/shared_library/*.h" - "${ONNXRUNTIME_ROOT}/core/providers/shared_library/*.cc" - ) - - file(GLOB_RECURSE onnxruntime_providers_rocm_cu_srcs CONFIGURE_DEPENDS - "${ONNXRUNTIME_ROOT}/core/providers/rocm/*.cu" - "${ONNXRUNTIME_ROOT}/core/providers/rocm/*.cuh" - ) - - hipify("onnxruntime/core/providers" provider_excluded_files onnxruntime_providers_rocm_generated_cc_srcs onnxruntime_providers_rocm_generated_cu_srcs) - - source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_rocm_cc_srcs} ${onnxruntime_providers_rocm_shared_srcs} ${onnxruntime_providers_rocm_cu_srcs}) - set(onnxruntime_providers_rocm_src ${onnxruntime_providers_rocm_cc_srcs} ${onnxruntime_providers_rocm_shared_srcs} ${onnxruntime_providers_rocm_cu_srcs}) - list(APPEND onnxruntime_providers_rocm_src ${onnxruntime_providers_rocm_generated_cc_srcs} ${onnxruntime_providers_rocm_generated_cu_srcs}) - - # disable contrib ops conditionally - if(NOT onnxruntime_DISABLE_CONTRIB_OPS) - hipify("onnxruntime/contrib_ops" contrib_ops_excluded_files onnxruntime_rocm_generated_contrib_ops_cc_srcs onnxruntime_rocm_generated_contrib_ops_cu_srcs) - - # add using ONNXRUNTIME_ROOT so they show up under the 'contrib_ops' folder in Visual Studio - source_group(TREE ${ONNXRUNTIME_ROOT} FILES ${onnxruntime_rocm_contrib_ops_cc_srcs} ${onnxruntime_rocm_contrib_ops_cu_srcs}) - list(APPEND onnxruntime_providers_rocm_src ${onnxruntime_rocm_contrib_ops_cc_srcs} ${onnxruntime_rocm_contrib_ops_cu_srcs}) - list(APPEND onnxruntime_providers_rocm_src ${onnxruntime_rocm_generated_contrib_ops_cc_srcs} ${onnxruntime_rocm_generated_contrib_ops_cu_srcs}) - endif() - - if (onnxruntime_ENABLE_TRAINING_OPS) - file(GLOB_RECURSE onnxruntime_rocm_training_ops_cc_srcs CONFIGURE_DEPENDS - "${ORTTRAINING_SOURCE_DIR}/training_ops/rocm/*.h" - "${ORTTRAINING_SOURCE_DIR}/training_ops/rocm/*.cc" - ) - - file(GLOB_RECURSE onnxruntime_rocm_training_ops_cu_srcs CONFIGURE_DEPENDS - "${ORTTRAINING_SOURCE_DIR}/training_ops/rocm/*.cu" - "${ORTTRAINING_SOURCE_DIR}/training_ops/rocm/*.cuh" - ) - - hipify("orttraining/orttraining/training_ops" training_ops_excluded_files onnxruntime_rocm_generated_training_ops_cc_srcs onnxruntime_rocm_generated_training_ops_cu_srcs) - - # NCCL is not support in Windows build - if (WIN32 OR NOT onnxruntime_USE_NCCL) - list(REMOVE_ITEM onnxruntime_rocm_generated_training_ops_cc_srcs - "${CMAKE_CURRENT_BINARY_DIR}/amdgpu/orttraining/orttraining/training_ops/rocm/collective/nccl_common.cc" - "${CMAKE_CURRENT_BINARY_DIR}/amdgpu/orttraining/orttraining/training_ops/rocm/collective/nccl_kernels.cc" - "${CMAKE_CURRENT_BINARY_DIR}/amdgpu/orttraining/orttraining/training_ops/rocm/collective/megatron.cc" - ) - endif() - - source_group(TREE ${ORTTRAINING_ROOT} FILES ${onnxruntime_rocm_training_ops_cc_srcs} ${onnxruntime_rocm_training_ops_cu_srcs}) - list(APPEND onnxruntime_providers_rocm_src ${onnxruntime_rocm_training_ops_cc_srcs} ${onnxruntime_rocm_training_ops_cu_srcs}) - list(APPEND onnxruntime_providers_rocm_src ${onnxruntime_rocm_generated_training_ops_cc_srcs} ${onnxruntime_rocm_generated_training_ops_cu_srcs}) - endif() - - auto_set_source_files_hip_language(${onnxruntime_providers_rocm_src}) - onnxruntime_add_shared_library_module(onnxruntime_providers_rocm ${onnxruntime_providers_rocm_src}) - target_compile_options(onnxruntime_providers_rocm PRIVATE -D__HIP_PLATFORM_AMD__=1 -D__HIP_PLATFORM_HCC__=1) - target_link_options(onnxruntime_providers_rocm PRIVATE -T ${REPO_ROOT}/cmake/hip_fatbin_insert) - - if(NOT MSVC) - target_compile_options(onnxruntime_providers_rocm PRIVATE -Wno-sign-compare) - target_compile_options(onnxruntime_providers_rocm PRIVATE -Wno-unused-parameter) - target_compile_options(onnxruntime_providers_rocm PRIVATE -Wno-undefined-var-template) - endif() - - onnxruntime_add_include_to_target(onnxruntime_providers_rocm onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers Boost::mp11 safeint_interface) - if (onnxruntime_ENABLE_TRAINING_OPS) - onnxruntime_add_include_to_target(onnxruntime_providers_rocm onnxruntime_training) - target_link_libraries(onnxruntime_providers_rocm PRIVATE onnxruntime_training) - if (onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) - onnxruntime_add_include_to_target(onnxruntime_providers_rocm Python::Module) - endif() - endif() - - add_custom_target(generate_hipified_files DEPENDS - ${onnxruntime_providers_rocm_generated_cc_srcs} - ${onnxruntime_providers_rocm_generated_cu_srcs} - ${onnxruntime_rocm_generated_contrib_ops_cc_srcs} - ${onnxruntime_rocm_generated_contrib_ops_cu_srcs} - ${onnxruntime_rocm_generated_training_ops_cc_srcs} - ${onnxruntime_rocm_generated_training_ops_cu_srcs}) - - add_dependencies(onnxruntime_providers_rocm generate_hipified_files onnxruntime_providers_shared ${onnxruntime_EXTERNAL_DEPENDENCIES}) - target_link_libraries(onnxruntime_providers_rocm PRIVATE ${ONNXRUNTIME_ROCM_LIBS} ${ONNXRUNTIME_PROVIDERS_SHARED} ${ABSEIL_LIBS}) - target_include_directories(onnxruntime_providers_rocm SYSTEM - PRIVATE - ${ONNXRUNTIME_ROOT} - ${CMAKE_CURRENT_BINARY_DIR} - ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime - ${eigen_INCLUDE_DIRS} - PUBLIC - ${onnxruntime_ROCM_HOME}/include - ${onnxruntime_ROCM_HOME}/include/roctracer) - - set_target_properties(onnxruntime_providers_rocm PROPERTIES LINKER_LANGUAGE CXX) - set_target_properties(onnxruntime_providers_rocm PROPERTIES FOLDER "ONNXRuntime") - target_compile_definitions(onnxruntime_providers_rocm PRIVATE HIPBLAS_V2) - - if (onnxruntime_ENABLE_TRAINING) - target_include_directories(onnxruntime_providers_rocm PRIVATE ${ORTTRAINING_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/orttraining ${MPI_CXX_INCLUDE_DIRS}) - if(onnxruntime_USE_MPI) - target_link_libraries(onnxruntime_providers_rocm PRIVATE ${MPI_LIBRARIES} ${MPI_CXX_LINK_FLAGS}) - endif() - - # RCCL is enabled by default for ROCM builds - #if (onnxruntime_USE_NCCL) - # target_include_directories(onnxruntime_providers_rocm PRIVATE ${NCCL_INCLUDE_DIRS}) - # target_link_libraries(onnxruntime_providers_rocm PRIVATE ${NCCL_LIBRARIES}) - #endif() - endif() - - if (onnxruntime_USE_ROCBLAS_EXTENSION_API) - target_compile_definitions(onnxruntime_providers_rocm PRIVATE USE_ROCBLAS_EXTENSION_API) - target_compile_definitions(onnxruntime_providers_rocm PRIVATE ROCBLAS_NO_DEPRECATED_WARNINGS) - target_compile_definitions(onnxruntime_providers_rocm PRIVATE ROCBLAS_BETA_FEATURES_API) - endif() - - if (onnxruntime_USE_HIPBLASLT) - find_package(hipblaslt REQUIRED) - target_link_libraries(onnxruntime_providers_rocm PRIVATE roc::hipblaslt) - target_compile_definitions(onnxruntime_providers_rocm PRIVATE USE_HIPBLASLT) - endif() - - if (onnxruntime_USE_TRITON_KERNEL) - # compile triton kernel, generate .a and .h files - include(onnxruntime_compile_triton_kernel.cmake) - compile_triton_kernel(triton_kernel_obj_file triton_kernel_header_dir) - add_dependencies(onnxruntime_providers_rocm onnxruntime_triton_kernel) - target_compile_definitions(onnxruntime_providers_rocm PRIVATE USE_TRITON_KERNEL) - target_include_directories(onnxruntime_providers_rocm PRIVATE ${triton_kernel_header_dir}) - target_link_libraries(onnxruntime_providers_rocm PUBLIC -Wl,--whole-archive ${triton_kernel_obj_file} -Wl,--no-whole-archive) - endif() - - if (onnxruntime_USE_COMPOSABLE_KERNEL) - include(composable_kernel) - target_link_libraries(onnxruntime_providers_rocm PRIVATE - onnxruntime_composable_kernel_includes - # Currently we shall not use composablekernels::device_operations, the target includes all conv dependencies, which - # are extremely slow to compile. Instead, we only link all gemm related objects. See the following directory on - # updating. - # https://github.com/ROCmSoftwarePlatform/composable_kernel/tree/develop/library/src/tensor_operation_instance/gpu - device_gemm_instance - device_gemm_add_fastgelu_instance - device_gemm_fastgelu_instance - device_gemm_splitk_instance - device_gemm_streamk_instance - device_batched_gemm_instance - device_softmax_instance - ) - target_compile_definitions(onnxruntime_providers_rocm PRIVATE USE_COMPOSABLE_KERNEL) - if (onnxruntime_USE_COMPOSABLE_KERNEL_CK_TILE) - target_link_libraries(onnxruntime_providers_rocm PUBLIC onnxruntime_composable_kernel_fmha) - target_compile_definitions(onnxruntime_providers_rocm PRIVATE USE_COMPOSABLE_KERNEL_CK_TILE) - endif() - endif() - - if(UNIX) - set_property(TARGET onnxruntime_providers_rocm APPEND_STRING PROPERTY LINK_FLAGS "-Xlinker --version-script=${ONNXRUNTIME_ROOT}/core/providers/rocm/version_script.lds -Xlinker --gc-sections") - else() - message(FATAL_ERROR "onnxruntime_providers_rocm unknown platform, need to specify shared library exports for it") - endif() - - if (onnxruntime_ENABLE_ATEN) - target_compile_definitions(onnxruntime_providers_rocm PRIVATE ENABLE_ATEN) - endif() - file(GLOB ONNXRUNTIME_ROCM_PROVIDER_PUBLIC_HEADERS CONFIGURE_DEPENDS - "${REPO_ROOT}/include/onnxruntime/core/providers/rocm/*.h" - ) - set_target_properties(onnxruntime_providers_rocm PROPERTIES - PUBLIC_HEADER "${ONNXRUNTIME_ROCM_PROVIDER_PUBLIC_HEADERS}") - install(TARGETS onnxruntime_providers_rocm - PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/core/providers/rocm - ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} - LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} - RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) diff --git a/cmake/onnxruntime_providers_tensorrt.cmake b/cmake/onnxruntime_providers_tensorrt.cmake index 7b18222f334f9..4184e0b049afc 100644 --- a/cmake/onnxruntime_providers_tensorrt.cmake +++ b/cmake/onnxruntime_providers_tensorrt.cmake @@ -28,25 +28,32 @@ endif() set(CXX_VERSION_DEFINED TRUE) - # There is an issue when running "Debug build" TRT EP with "Release build" TRT builtin parser on Windows. - # We enforce following workaround for now until the real fix. - if (WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Debug") - set(onnxruntime_USE_TENSORRT_BUILTIN_PARSER OFF) - MESSAGE(STATUS "[Note] There is an issue when running \"Debug build\" TRT EP with \"Release build\" TRT built-in parser on Windows. This build will use tensorrt oss parser instead.") - endif() - find_path(TENSORRT_INCLUDE_DIR NvInfer.h HINTS ${TENSORRT_ROOT} PATH_SUFFIXES include) - file(READ ${TENSORRT_INCLUDE_DIR}/NvInferVersion.h NVINFER_VER_CONTENT) - string(REGEX MATCH "define NV_TENSORRT_MAJOR * +([0-9]+)" NV_TENSORRT_MAJOR "${NVINFER_VER_CONTENT}") - string(REGEX REPLACE "define NV_TENSORRT_MAJOR * +([0-9]+)" "\\1" NV_TENSORRT_MAJOR "${NV_TENSORRT_MAJOR}") - string(REGEX MATCH "define NV_TENSORRT_MINOR * +([0-9]+)" NV_TENSORRT_MINOR "${NVINFER_VER_CONTENT}") - string(REGEX REPLACE "define NV_TENSORRT_MINOR * +([0-9]+)" "\\1" NV_TENSORRT_MINOR "${NV_TENSORRT_MINOR}") - string(REGEX MATCH "define NV_TENSORRT_PATCH * +([0-9]+)" NV_TENSORRT_PATCH "${NVINFER_VER_CONTENT}") - string(REGEX REPLACE "define NV_TENSORRT_PATCH * +([0-9]+)" "\\1" NV_TENSORRT_PATCH "${NV_TENSORRT_PATCH}") + + # Starting TRT 10.11, TRT version macros have changed + string(REGEX MATCH "TRT_MAJOR_ENTERPRISE" TRT_VER_CHECK "${NVINFER_VER_CONTENT}") + # Pre TRT 10.11 + if("${TRT_VER_CHECK}" STREQUAL "") + string(REGEX MATCH "define NV_TENSORRT_MAJOR * +([0-9]+)" NV_TENSORRT_MAJOR "${NVINFER_VER_CONTENT}") + string(REGEX REPLACE "define NV_TENSORRT_MAJOR * +([0-9]+)" "\\1" NV_TENSORRT_MAJOR "${NV_TENSORRT_MAJOR}") + string(REGEX MATCH "define NV_TENSORRT_MINOR * +([0-9]+)" NV_TENSORRT_MINOR "${NVINFER_VER_CONTENT}") + string(REGEX REPLACE "define NV_TENSORRT_MINOR * +([0-9]+)" "\\1" NV_TENSORRT_MINOR "${NV_TENSORRT_MINOR}") + string(REGEX MATCH "define NV_TENSORRT_PATCH * +([0-9]+)" NV_TENSORRT_PATCH "${NVINFER_VER_CONTENT}") + string(REGEX REPLACE "define NV_TENSORRT_PATCH * +([0-9]+)" "\\1" NV_TENSORRT_PATCH "${NV_TENSORRT_PATCH}") + # TRT 10.11+ + else() + string(REGEX MATCH "define TRT_MAJOR_ENTERPRISE * +([0-9]+)" NV_TENSORRT_MAJOR "${NVINFER_VER_CONTENT}") + string(REGEX REPLACE "define TRT_MAJOR_ENTERPRISE * +([0-9]+)" "\\1" NV_TENSORRT_MAJOR "${NV_TENSORRT_MAJOR}") + string(REGEX MATCH "define TRT_MINOR_ENTERPRISE * +([0-9]+)" NV_TENSORRT_MINOR "${NVINFER_VER_CONTENT}") + string(REGEX REPLACE "define TRT_MINOR_ENTERPRISE * +([0-9]+)" "\\1" NV_TENSORRT_MINOR "${NV_TENSORRT_MINOR}") + string(REGEX MATCH "define TRT_PATCH_ENTERPRISE * +([0-9]+)" NV_TENSORRT_PATCH "${NVINFER_VER_CONTENT}") + string(REGEX REPLACE "define TRT_PATCH_ENTERPRISE * +([0-9]+)" "\\1" NV_TENSORRT_PATCH "${NV_TENSORRT_PATCH}") + endif() + math(EXPR NV_TENSORRT_MAJOR_INT "${NV_TENSORRT_MAJOR}") math(EXPR NV_TENSORRT_MINOR_INT "${NV_TENSORRT_MINOR}") math(EXPR NV_TENSORRT_PATCH_INT "${NV_TENSORRT_PATCH}") @@ -65,10 +72,9 @@ endif() # TensorRT 10 GA onwards, the TensorRT libraries will have major version appended to the end on Windows, - # for example, nvinfer_10.dll, nvinfer_plugin_10.dll, nvonnxparser_10.dll ... + # for example, nvinfer_10.dll, nvonnxparser_10.dll ... if (WIN32 AND TRT_GREATER_OR_EQUAL_TRT_10_GA) set(NVINFER_LIB "nvinfer_${NV_TENSORRT_MAJOR}") - set(NVINFER_PLUGIN_LIB "nvinfer_plugin_${NV_TENSORRT_MAJOR}") set(PARSER_LIB "nvonnxparser_${NV_TENSORRT_MAJOR}") endif() @@ -76,15 +82,11 @@ set(NVINFER_LIB "nvinfer") endif() - if (NOT NVINFER_PLUGIN_LIB) - set(NVINFER_PLUGIN_LIB "nvinfer_plugin") - endif() - if (NOT PARSER_LIB) set(PARSER_LIB "nvonnxparser") endif() - MESSAGE(STATUS "Looking for ${NVINFER_LIB} and ${NVINFER_PLUGIN_LIB}") + MESSAGE(STATUS "Looking for ${NVINFER_LIB}") find_library(TENSORRT_LIBRARY_INFER ${NVINFER_LIB} HINTS ${TENSORRT_ROOT} @@ -94,14 +96,6 @@ MESSAGE(STATUS "Can't find ${NVINFER_LIB}") endif() - find_library(TENSORRT_LIBRARY_INFER_PLUGIN ${NVINFER_PLUGIN_LIB} - HINTS ${TENSORRT_ROOT} - PATH_SUFFIXES lib lib64 lib/x64) - - if (NOT TENSORRT_LIBRARY_INFER_PLUGIN) - MESSAGE(STATUS "Can't find ${NVINFER_PLUGIN_LIB}") - endif() - if (onnxruntime_USE_TENSORRT_BUILTIN_PARSER) MESSAGE(STATUS "Looking for ${PARSER_LIB}") @@ -113,16 +107,17 @@ MESSAGE(STATUS "Can't find ${PARSER_LIB}") endif() - set(TENSORRT_LIBRARY ${TENSORRT_LIBRARY_INFER} ${TENSORRT_LIBRARY_INFER_PLUGIN} ${TENSORRT_LIBRARY_NVONNXPARSER}) + set(TENSORRT_LIBRARY ${TENSORRT_LIBRARY_INFER} ${TENSORRT_LIBRARY_NVONNXPARSER}) MESSAGE(STATUS "Find TensorRT libs at ${TENSORRT_LIBRARY}") else() if (TRT_GREATER_OR_EQUAL_TRT_10_GA) set(ONNX_USE_LITE_PROTO ON) endif() - FetchContent_Declare( + onnxruntime_fetchcontent_declare( onnx_tensorrt URL ${DEP_URL_onnx_tensorrt} URL_HASH SHA1=${DEP_SHA1_onnx_tensorrt} + EXCLUDE_FROM_ALL ) if (NOT CUDA_INCLUDE_DIR) set(CUDA_INCLUDE_DIR ${CUDAToolkit_INCLUDE_DIRS}) # onnx-tensorrt repo needs this variable to build @@ -130,7 +125,6 @@ # The onnx_tensorrt repo contains a test program, getSupportedAPITest, which doesn't support Windows. It uses # unistd.h. So we must exclude it from our build. onnxruntime_fetchcontent_makeavailable is for the purpose. onnxruntime_fetchcontent_makeavailable(onnx_tensorrt) - include_directories(${onnx_tensorrt_SOURCE_DIR}) set(CMAKE_CXX_FLAGS ${OLD_CMAKE_CXX_FLAGS}) if ( CMAKE_COMPILER_IS_GNUCC ) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wno-unused-parameter") @@ -146,16 +140,15 @@ endif() # Static libraries are just nvonnxparser_static on all platforms set(onnxparser_link_libs nvonnxparser_static) - set(TENSORRT_LIBRARY ${TENSORRT_LIBRARY_INFER} ${TENSORRT_LIBRARY_INFER_PLUGIN}) + set(TENSORRT_LIBRARY ${TENSORRT_LIBRARY_INFER}) MESSAGE(STATUS "Find TensorRT libs at ${TENSORRT_LIBRARY}") endif() - include_directories(${TENSORRT_INCLUDE_DIR}) # ${TENSORRT_LIBRARY} is empty if we link nvonnxparser_static. # nvonnxparser_static is linked against tensorrt libraries in onnx-tensorrt # See https://github.com/onnx/onnx-tensorrt/blob/8af13d1b106f58df1e98945a5e7c851ddb5f0791/CMakeLists.txt#L121 # However, starting from TRT 10 GA, nvonnxparser_static doesn't link against tensorrt libraries. - # Therefore, the above code finds ${TENSORRT_LIBRARY_INFER} and ${TENSORRT_LIBRARY_INFER_PLUGIN}. + # Therefore, the above code finds ${TENSORRT_LIBRARY_INFER}. if(onnxruntime_CUDA_MINIMAL) set(trt_link_libs ${CMAKE_DL_LIBS} ${TENSORRT_LIBRARY}) else() @@ -173,22 +166,38 @@ ) source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_tensorrt_cc_srcs}) - onnxruntime_add_shared_library_module(onnxruntime_providers_tensorrt ${onnxruntime_providers_tensorrt_cc_srcs}) - onnxruntime_add_include_to_target(onnxruntime_providers_tensorrt onnxruntime_common onnx flatbuffers::flatbuffers Boost::mp11 safeint_interface) + + set(onnxruntime_providers_tensorrt_all_srcs ${onnxruntime_providers_tensorrt_cc_srcs}) + if(WIN32) + # Sets the DLL version info on Windows: https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource + list(APPEND onnxruntime_providers_tensorrt_all_srcs "${ONNXRUNTIME_ROOT}/core/providers/tensorrt/onnxruntime_providers_tensorrt.rc") + endif() + + onnxruntime_add_shared_library_module(onnxruntime_providers_tensorrt ${onnxruntime_providers_tensorrt_all_srcs}) + onnxruntime_add_include_to_target(onnxruntime_providers_tensorrt onnxruntime_common) + target_link_libraries(onnxruntime_providers_tensorrt PRIVATE Eigen3::Eigen onnx flatbuffers::flatbuffers Boost::mp11 safeint_interface Eigen3::Eigen) add_dependencies(onnxruntime_providers_tensorrt onnxruntime_providers_shared ${onnxruntime_EXTERNAL_DEPENDENCIES}) if (onnxruntime_USE_TENSORRT_BUILTIN_PARSER) target_link_libraries(onnxruntime_providers_tensorrt PRIVATE ${trt_link_libs} ${ONNXRUNTIME_PROVIDERS_SHARED} ${PROTOBUF_LIB} flatbuffers::flatbuffers Boost::mp11 safeint_interface ${ABSEIL_LIBS} PUBLIC CUDA::cudart) else() target_link_libraries(onnxruntime_providers_tensorrt PRIVATE ${onnxparser_link_libs} ${trt_link_libs} ${ONNXRUNTIME_PROVIDERS_SHARED} ${PROTOBUF_LIB} flatbuffers::flatbuffers ${ABSEIL_LIBS} PUBLIC CUDA::cudart) endif() - target_include_directories(onnxruntime_providers_tensorrt PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${eigen_INCLUDE_DIRS} + target_include_directories(onnxruntime_providers_tensorrt PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${TENSORRT_INCLUDE_DIR} PUBLIC ${CUDAToolkit_INCLUDE_DIRS}) - + if (NOT onnxruntime_USE_TENSORRT_BUILTIN_PARSER) + target_include_directories(onnxruntime_providers_tensorrt PRIVATE ${onnx_tensorrt_SOURCE_DIR}) + endif() # ${CMAKE_CURRENT_BINARY_DIR} is so that #include "onnxruntime_config.h" inside tensor_shape.h is found set_target_properties(onnxruntime_providers_tensorrt PROPERTIES LINKER_LANGUAGE CUDA) set_target_properties(onnxruntime_providers_tensorrt PROPERTIES FOLDER "ONNXRuntime") target_compile_definitions(onnxruntime_providers_tensorrt PRIVATE ONNXIFI_BUILD_LIBRARY=1) target_compile_options(onnxruntime_providers_tensorrt PRIVATE ${DISABLED_WARNINGS_FOR_TRT}) + + if(WIN32) + # FILE_NAME preprocessor definition is used in onnxruntime_providers_tensorrt.rc + target_compile_definitions(onnxruntime_providers_tensorrt PRIVATE FILE_NAME=\"onnxruntime_providers_tensorrt.dll\") + endif() + if (WIN32) target_compile_options(onnxruntime_providers_tensorrt INTERFACE /wd4456) endif() diff --git a/cmake/onnxruntime_providers_vitisai.cmake b/cmake/onnxruntime_providers_vitisai.cmake index 561a323533f48..d59c944c8926f 100644 --- a/cmake/onnxruntime_providers_vitisai.cmake +++ b/cmake/onnxruntime_providers_vitisai.cmake @@ -19,9 +19,18 @@ "${ONNXRUNTIME_ROOT}/core/providers/shared_library/*.cc" ) source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_providers_vitisai_cc_srcs}) - onnxruntime_add_shared_library(onnxruntime_providers_vitisai ${onnxruntime_providers_vitisai_cc_srcs}) - onnxruntime_add_include_to_target(onnxruntime_providers_vitisai ${ONNXRUNTIME_PROVIDERS_SHARED} ${GSL_TARGET} safeint_interface flatbuffers::flatbuffers) - target_link_libraries(onnxruntime_providers_vitisai PRIVATE ${ONNXRUNTIME_PROVIDERS_SHARED}) + set(onnxruntime_providers_vitisai_all_srcs ${onnxruntime_providers_vitisai_cc_srcs}) + if(WIN32) + # Sets the DLL version info on Windows: https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource + list(APPEND onnxruntime_providers_vitisai_all_srcs "${ONNXRUNTIME_ROOT}/core/providers/vitisai/onnxruntime_providers_vitisai.rc") + endif() + onnxruntime_add_shared_library(onnxruntime_providers_vitisai ${onnxruntime_providers_vitisai_all_srcs}) + if(WIN32) + # FILE_NAME preprocessor definition is used in onnxruntime_providers_vitisai.rc + target_compile_definitions(onnxruntime_providers_vitisai PRIVATE FILE_NAME=\"onnxruntime_providers_vitisai.dll\") + endif() + onnxruntime_add_include_to_target(onnxruntime_providers_vitisai ${ONNXRUNTIME_PROVIDERS_SHARED} ${GSL_TARGET} safeint_interface flatbuffers::flatbuffers Boost::mp11) + target_link_libraries(onnxruntime_providers_vitisai PRIVATE ${ONNXRUNTIME_PROVIDERS_SHARED} ${ABSEIL_LIBS}) if(MSVC) onnxruntime_add_include_to_target(onnxruntime_providers_vitisai dbghelp) set_property(TARGET onnxruntime_providers_vitisai APPEND_STRING PROPERTY LINK_FLAGS "-DEF:${ONNXRUNTIME_ROOT}/core/providers/vitisai/symbols.def") diff --git a/cmake/onnxruntime_providers_webgpu.cmake b/cmake/onnxruntime_providers_webgpu.cmake index 4bbca7b1b811a..f64aafa161bea 100644 --- a/cmake/onnxruntime_providers_webgpu.cmake +++ b/cmake/onnxruntime_providers_webgpu.cmake @@ -6,22 +6,137 @@ endif() add_compile_definitions(USE_WEBGPU=1) + if (onnxruntime_ENABLE_WEBASSEMBLY_THREADS) add_definitions(-DENABLE_WEBASSEMBLY_THREADS=1) endif() + if (onnxruntime_WGSL_TEMPLATE STREQUAL "dynamic") + if (onnxruntime_DISABLE_EXCEPTIONS) + message(FATAL_ERROR "Dynamic WGSL template generation requires exception handling to be enabled.") + endif() + if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + message(FATAL_ERROR "Dynamic WGSL template generation is not supported when targeting WebAssembly.") + endif() + add_definitions(-DORT_WGSL_TEMPLATE_DYNAMIC=1) + elseif (NOT onnxruntime_WGSL_TEMPLATE STREQUAL "static") + message(FATAL_ERROR "Unsupported value for onnxruntime_WGSL_TEMPLATE: ${onnxruntime_WGSL_TEMPLATE}. Supported values are 'static' or 'dynamic'.") + endif() + file(GLOB_RECURSE onnxruntime_providers_webgpu_cc_srcs CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/core/providers/webgpu/*.h" "${ONNXRUNTIME_ROOT}/core/providers/webgpu/*.cc" ) if(NOT onnxruntime_DISABLE_CONTRIB_OPS) - source_group(TREE ${ONNXRUNTIME_ROOT} FILES ${onnxruntime_webgpu_contrib_ops_cc_srcs}) list(APPEND onnxruntime_providers_webgpu_cc_srcs ${onnxruntime_webgpu_contrib_ops_cc_srcs}) endif() - source_group(TREE ${REPO_ROOT} FILES ${onnxruntime_providers_webgpu_cc_srcs}) - onnxruntime_add_static_library(onnxruntime_providers_webgpu ${onnxruntime_providers_webgpu_cc_srcs}) - onnxruntime_add_include_to_target(onnxruntime_providers_webgpu - onnxruntime_common onnx onnx_proto flatbuffers::flatbuffers Boost::mp11 safeint_interface) + if(NOT onnxruntime_USE_EP_API_ADAPTERS) + # + # Build WebGPU EP as a static library + # + + # For static library build, exclude the 'ep' folder + file(GLOB_RECURSE ep_files_to_exclude + "${ONNXRUNTIME_ROOT}/core/providers/webgpu/ep/*.h" + "${ONNXRUNTIME_ROOT}/core/providers/webgpu/ep/*.cc" + ) + list(REMOVE_ITEM onnxruntime_providers_webgpu_cc_srcs ${ep_files_to_exclude}) + + source_group(TREE ${ONNXRUNTIME_ROOT} FILES ${onnxruntime_providers_webgpu_cc_srcs}) + onnxruntime_add_static_library(onnxruntime_providers_webgpu ${onnxruntime_providers_webgpu_cc_srcs}) + onnxruntime_add_include_to_target(onnxruntime_providers_webgpu + onnxruntime_common onnx onnx_proto flatbuffers::flatbuffers Boost::mp11 safeint_interface) + else() + # + # Build WebGPU EP as a shared library + # + if(WIN32) + # Sets the DLL version info on Windows: https://learn.microsoft.com/en-us/windows/win32/menurc/versioninfo-resource + list(APPEND onnxruntime_providers_webgpu_cc_srcs "${ONNXRUNTIME_ROOT}/core/providers/webgpu/ep/versioninfo.rc") + endif() + source_group(TREE ${ONNXRUNTIME_ROOT} FILES ${onnxruntime_providers_webgpu_cc_srcs}) + + onnxruntime_add_shared_library_module(onnxruntime_providers_webgpu ${onnxruntime_providers_webgpu_cc_srcs}) + onnxruntime_add_include_to_target(onnxruntime_providers_webgpu + ${REPO_ROOT}/include/onnxruntime/core/session + onnxruntime_common + onnx + onnx_proto + flatbuffers::flatbuffers + Boost::mp11 + safeint_interface) + + target_link_libraries(onnxruntime_providers_webgpu PRIVATE + onnxruntime_optimizer + onnxruntime_providers + onnxruntime_lora + onnxruntime_framework + onnxruntime_graph + onnxruntime_util + ${ONNXRUNTIME_MLAS_LIBS} + onnxruntime_common + onnxruntime_flatbuffers + ${onnxruntime_EXTERNAL_LIBRARIES} + ) + + # Add ONNX compiler definitions + add_definitions("-DONNX_ML=1") + add_definitions("-DONNX_NAMESPACE=onnx") + add_definitions("-DONNX_USE_LITE_PROTO=1") + + # Default plugin EP version to ORT_VERSION with "-dev" suffix if not explicitly provided. + if(NOT DEFINED onnxruntime_PLUGIN_EP_VERSION) + set(onnxruntime_PLUGIN_EP_VERSION "${ORT_VERSION}-dev") + endif() + + # Set preprocessor definition for plugin EP version + target_compile_definitions(onnxruntime_providers_webgpu PRIVATE ORT_PLUGIN_EP_VERSION="${onnxruntime_PLUGIN_EP_VERSION}") + + # Set preprocessor definitions used in onnxruntime_providers_webgpu.rc + if(WIN32) + set(WEBGPU_DLL_FILE_DESCRIPTION "ONNX Runtime WebGPU Provider") + + target_compile_definitions(onnxruntime_providers_webgpu PRIVATE FILE_DESC=\"${WEBGPU_DLL_FILE_DESCRIPTION}\") + target_compile_definitions(onnxruntime_providers_webgpu PRIVATE FILE_NAME=\"onnxruntime_providers_webgpu.dll\") + endif() + + # Set linker flags for function(s) exported by EP DLL + if(UNIX) + if (APPLE) + set_property(TARGET onnxruntime_providers_webgpu APPEND_STRING PROPERTY LINK_FLAGS + "-Xlinker -dead_strip") + elseif (NOT CMAKE_SYSTEM_NAME MATCHES "AIX") + target_link_options(onnxruntime_providers_webgpu PRIVATE + "LINKER:--version-script=${ONNXRUNTIME_ROOT}/core/providers/webgpu/ep/version_script.lds" + "LINKER:--gc-sections" + "LINKER:-rpath=\$ORIGIN") + # TODO: -z noexecstack + endif() + elseif(WIN32) + set_property(TARGET onnxruntime_providers_webgpu APPEND_STRING PROPERTY LINK_FLAGS + "-DEF:${ONNXRUNTIME_ROOT}/core/providers/webgpu/ep/symbols.def") + else() + message(FATAL_ERROR "onnxruntime_providers_webgpu unknown platform, need to specify shared library exports for it") + endif() + + set_target_properties(onnxruntime_providers_webgpu PROPERTIES LINKER_LANGUAGE CXX) + + if (onnxruntime_BUILD_CACHE) + message(FATAL_ERROR "WebGPU EP shared library build does not support build cache. Please disable build cache or use static library build.") + endif() + if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + message(FATAL_ERROR "WebGPU EP shared library build is not supported on Emscripten. Please use static library build.") + endif() + + # Configure precompiled headers for shared library build + # PCH ensures ep/adapters.h is included first and improves compilation speed + target_precompile_headers(onnxruntime_providers_webgpu PRIVATE + "${REPO_ROOT}/include/onnxruntime/ep/adapters.h" + ) + endif() + + set_target_properties(onnxruntime_providers_webgpu PROPERTIES CXX_STANDARD_REQUIRED ON) + set_target_properties(onnxruntime_providers_webgpu PROPERTIES FOLDER "ONNXRuntime") if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") # target "emdawnwebgpu_c" is created by Dawn, including "-fno-exceptions" in its compile options by default. @@ -35,46 +150,99 @@ list(REMOVE_ITEM EM_DAWN_WEBGPU_C_COMPILE_OPTIONS "-fno-exceptions") set_property(TARGET emdawnwebgpu_c PROPERTY COMPILE_OPTIONS ${EM_DAWN_WEBGPU_C_COMPILE_OPTIONS}) endif() + if (CMAKE_CXX_FLAGS MATCHES "-fwasm-exceptions") + get_property(EM_DAWN_WEBGPU_C_COMPILE_OPTIONS TARGET emdawnwebgpu_c PROPERTY COMPILE_OPTIONS) + list(REMOVE_ITEM EM_DAWN_WEBGPU_C_COMPILE_OPTIONS "-fno-exceptions") + set_property(TARGET emdawnwebgpu_c PROPERTY COMPILE_OPTIONS ${EM_DAWN_WEBGPU_C_COMPILE_OPTIONS}) + endif() # target "emdawnwebgpu_cpp" is created by Dawn. When it is linked to onnxruntime_providers_webgpu as "PUBLIC" # dependency, a few build/link flags will be set automatically to make sure emscripten can generate correct # WebAssembly/JavaScript code for WebGPU support. target_link_libraries(onnxruntime_providers_webgpu PUBLIC emdawnwebgpu_cpp) - # ASYNCIFY is required for WGPUFuture support (ie. async functions in WebGPU API) - target_link_options(onnxruntime_providers_webgpu PUBLIC - "SHELL:-s ASYNCIFY=1" - "SHELL:-s ASYNCIFY_STACK_SIZE=65536" + # Dawn's emdawnwebgpu_cpp target has a bug: it lists ${DAWN_INCLUDE_DIR}/webgpu/webgpu_enum_class_bitmasks.h + # in INTERFACE_SOURCES but doesn't add ${DAWN_INCLUDE_DIR} to INTERFACE_INCLUDE_DIRECTORIES. + # In emsdk 4.0.11, this was masked because Emscripten bundled its own copy of the WebGPU headers. + # In emsdk 4.0.21+, Emscripten removed the bundled WebGPU headers, exposing this bug. + # We need to manually add the Dawn include directory to find webgpu_enum_class_bitmasks.h. + # + # IMPORTANT: We must also add the generated emdawnwebgpu include directory BEFORE the Dawn source + # include directory, because ${dawn_SOURCE_DIR}/include/webgpu/webgpu_cpp.h is a stub that redirects + # to dawn/webgpu_cpp.h (native Dawn), but we need the generated Emscripten-specific webgpu_cpp.h. + target_include_directories(onnxruntime_providers_webgpu PRIVATE + "${dawn_BINARY_DIR}/gen/src/emdawnwebgpu/include" + "${dawn_SOURCE_DIR}/include" ) + + if (onnxruntime_ENABLE_WEBASSEMBLY_JSPI) + target_link_options(onnxruntime_providers_webgpu PUBLIC + "SHELL:-s JSPI=1" + ) + else() + # ASYNCIFY is required for WGPUFuture support (ie. async functions in WebGPU API) + target_link_options(onnxruntime_providers_webgpu PUBLIC + "SHELL:-s ASYNCIFY=1" + "SHELL:-s ASYNCIFY_STACK_SIZE=65536" + ) + endif() else() onnxruntime_add_include_to_target(onnxruntime_providers_webgpu dawn::dawncpp_headers dawn::dawn_headers) set(onnxruntime_providers_webgpu_dll_deps) - if (onnxruntime_BUILD_DAWN_MONOLITHIC_LIBRARY) - target_link_libraries(onnxruntime_providers_webgpu dawn::webgpu_dawn) + if (onnxruntime_BUILD_DAWN_SHARED_LIBRARY) + target_link_libraries(onnxruntime_providers_webgpu PUBLIC dawn::webgpu_dawn) if (WIN32) if (onnxruntime_ENABLE_DELAY_LOADING_WIN_DLLS) list(APPEND onnxruntime_DELAYLOAD_FLAGS "/DELAYLOAD:webgpu_dawn.dll") endif() - list(APPEND onnxruntime_providers_webgpu_dll_deps "$") + # TODO: the following code is used to disable building Dawn using vcpkg temporarily + # until we figure out how to resolve the packaging pipeline failures + # + # if (onnxruntime_USE_VCPKG) + if (FALSE) + # Fix Dawn vcpkg build issue (missing IMPORTED_IMPLIB and IMPORTED_LOCATION for target dawn::webgpu_dawn) + get_target_property(webgpu_dawn_target_IMPORTED_IMPLIB dawn::webgpu_dawn IMPORTED_IMPLIB) + if (NOT webgpu_dawn_target_IMPORTED_IMPLIB) + set_target_properties(dawn::webgpu_dawn PROPERTIES IMPORTED_IMPLIB "webgpu_dawn.lib") + endif() + get_target_property(webgpu_dawn_target_IMPORTED_LOCATION dawn::webgpu_dawn IMPORTED_LOCATION) + if (NOT webgpu_dawn_target_IMPORTED_LOCATION) + set_target_properties(dawn::webgpu_dawn PROPERTIES IMPORTED_LOCATION "webgpu_dawn.dll") + endif() + endif() endif() + + list(APPEND onnxruntime_providers_webgpu_dll_deps "$") else() if (NOT onnxruntime_USE_EXTERNAL_DAWN) - target_link_libraries(onnxruntime_providers_webgpu dawn::dawn_native) + target_link_libraries(onnxruntime_providers_webgpu PRIVATE dawn::dawn_native) endif() - target_link_libraries(onnxruntime_providers_webgpu dawn::dawn_proc) + target_link_libraries(onnxruntime_providers_webgpu PRIVATE dawn::dawn_proc) endif() if (WIN32 AND onnxruntime_ENABLE_DAWN_BACKEND_D3D12) # Ensure dxil.dll and dxcompiler.dll exist in the output directory $ - add_dependencies(onnxruntime_providers_webgpu copy_dxil_dll) - add_dependencies(onnxruntime_providers_webgpu dxcompiler) + # TODO: the following code is used to disable building Dawn using vcpkg temporarily + # until we figure out how to resolve the packaging pipeline failures + # + # if (onnxruntime_USE_VCPKG) + if (FALSE) + find_package(directx-dxc CONFIG REQUIRED) + target_link_libraries(onnxruntime_providers_webgpu Microsoft::DirectXShaderCompiler) + target_link_libraries(onnxruntime_providers_webgpu Microsoft::DXIL) + list(APPEND onnxruntime_providers_webgpu_dll_deps "$") + list(APPEND onnxruntime_providers_webgpu_dll_deps "$") + else() + add_dependencies(onnxruntime_providers_webgpu copy_dxil_dll) + add_dependencies(onnxruntime_providers_webgpu dxcompiler) - list(APPEND onnxruntime_providers_webgpu_dll_deps "$/dxil.dll") - list(APPEND onnxruntime_providers_webgpu_dll_deps "$/dxcompiler.dll") + list(APPEND onnxruntime_providers_webgpu_dll_deps "$/dxil.dll") + list(APPEND onnxruntime_providers_webgpu_dll_deps "$/dxcompiler.dll") + endif() endif() if (onnxruntime_providers_webgpu_dll_deps) @@ -88,5 +256,108 @@ endif() endif() - add_dependencies(onnxruntime_providers_webgpu ${onnxruntime_EXTERNAL_DEPENDENCIES}) - set_target_properties(onnxruntime_providers_webgpu PROPERTIES FOLDER "ONNXRuntime") + add_dependencies(onnxruntime_providers_webgpu onnx ${onnxruntime_EXTERNAL_DEPENDENCIES}) + + if (onnxruntime_WGSL_TEMPLATE) + # Define the WGSL templates directory and output directory + set(WGSL_TEMPLATES_DIR "${ONNXRUNTIME_ROOT}/core/providers/webgpu/wgsl_templates") + set(WGSL_GENERATED_ROOT "${CMAKE_CURRENT_BINARY_DIR}/wgsl_generated") + + # Include the Node.js helper for finding and validating Node.js and NPM + include(node_helper.cmake) + + # Install npm dependencies + add_custom_command( + OUTPUT "${WGSL_TEMPLATES_DIR}/node_modules/.install_complete" + COMMAND ${NPM_CLI} ci + COMMAND ${CMAKE_COMMAND} -E touch "${WGSL_TEMPLATES_DIR}/node_modules/.install_complete" + DEPENDS "${WGSL_TEMPLATES_DIR}/package.json" "${WGSL_TEMPLATES_DIR}/package-lock.json" + WORKING_DIRECTORY ${WGSL_TEMPLATES_DIR} + COMMENT "Installing npm dependencies for WGSL template generation" + VERBATIM + ) + + if (onnxruntime_WGSL_TEMPLATE STREQUAL "static") + set(WGSL_GENERATED_DIR "${WGSL_GENERATED_ROOT}/wgsl_template_gen") + # set(WGSL_GEN_OUTPUTS "${WGSL_GENERATED_DIR}/index.h" "${WGSL_GENERATED_DIR}/index_impl.h") + # Define the output files that will be generated + set(WGSL_GENERATED_INDEX_H "${WGSL_GENERATED_DIR}/index.h") + set(WGSL_GENERATED_INDEX_IMPL_H "${WGSL_GENERATED_DIR}/index_impl.h") + elseif(onnxruntime_WGSL_TEMPLATE STREQUAL "dynamic") + set(WGSL_GENERATED_DIR "${WGSL_GENERATED_ROOT}/dynamic") + # set(WGSL_GEN_OUTPUTS "${WGSL_GENERATED_DIR}/templates.js") + set(WGSL_GENERATED_TEMPLATES_JS "${WGSL_GENERATED_DIR}/templates.js") + endif() + + # Ensure the output directory exists + file(MAKE_DIRECTORY ${WGSL_GENERATED_DIR}) + + # Find all WGSL template input files + set(WGSL_SEARCH_PATHS "${ONNXRUNTIME_ROOT}/core/providers/webgpu/*.wgsl.template") + if(NOT onnxruntime_DISABLE_CONTRIB_OPS) + list(APPEND WGSL_SEARCH_PATHS "${ONNXRUNTIME_ROOT}/contrib_ops/webgpu/*.wgsl.template") + endif() + file(GLOB_RECURSE WGSL_TEMPLATE_FILES ${WGSL_SEARCH_PATHS}) + + # Set wgsl-gen command line options as a list + set(WGSL_GEN_OPTIONS + "--output" "${WGSL_GENERATED_DIR}" + "-I" "wgsl_template_gen/" + "--preserve-code-ref" + "--verbose" + "-i" "${ONNXRUNTIME_ROOT}/core/providers/webgpu" + ) + if(NOT onnxruntime_DISABLE_CONTRIB_OPS) + list(APPEND WGSL_GEN_OPTIONS "-i" "${ONNXRUNTIME_ROOT}/contrib_ops/webgpu") + endif() + + if (onnxruntime_WGSL_TEMPLATE STREQUAL "static") + if (CMAKE_BUILD_TYPE STREQUAL "Debug") + list(APPEND WGSL_GEN_OPTIONS "--generator" "static-cpp-literal") + else() + list(APPEND WGSL_GEN_OPTIONS "--generator" "static-cpp") + endif() + elseif(onnxruntime_WGSL_TEMPLATE STREQUAL "dynamic") + list(APPEND WGSL_GEN_OPTIONS "--generator" "dynamic") + endif() + + # Generate WGSL templates + add_custom_command( + OUTPUT ${WGSL_GENERATED_INDEX_H} ${WGSL_GENERATED_INDEX_IMPL_H} ${WGSL_GENERATED_TEMPLATES_JS} + COMMAND ${NPM_CLI} run gen -- ${WGSL_GEN_OPTIONS} + DEPENDS "${WGSL_TEMPLATES_DIR}/node_modules/.install_complete" ${WGSL_TEMPLATE_FILES} + WORKING_DIRECTORY ${WGSL_TEMPLATES_DIR} + COMMENT "Generating WGSL templates from *.wgsl.template files" + COMMAND_EXPAND_LISTS + VERBATIM + ) + + # Create a target to represent the generation step + add_custom_target(onnxruntime_webgpu_wgsl_generation + DEPENDS ${WGSL_GENERATED_INDEX_H} ${WGSL_GENERATED_INDEX_IMPL_H} ${WGSL_GENERATED_TEMPLATES_JS} + SOURCES ${WGSL_TEMPLATE_FILES} + ) + + if (onnxruntime_WGSL_TEMPLATE STREQUAL "static") + # Add the generated directory to include paths + target_include_directories(onnxruntime_providers_webgpu PRIVATE ${WGSL_GENERATED_ROOT}) + elseif(onnxruntime_WGSL_TEMPLATE STREQUAL "dynamic") + target_link_libraries(onnxruntime_providers_webgpu PRIVATE duktape_static) + onnxruntime_add_include_to_target(onnxruntime_providers_webgpu duktape_static) + + # Define the path to the generated templates.js file + target_compile_definitions(onnxruntime_providers_webgpu PRIVATE + "ORT_WGSL_TEMPLATES_JS_PATH=\"${WGSL_GENERATED_TEMPLATES_JS}\"") + endif() + + # Make sure generation happens before building the provider + add_dependencies(onnxruntime_providers_webgpu onnxruntime_webgpu_wgsl_generation) + endif() + + if (NOT onnxruntime_BUILD_SHARED_LIB) + install(TARGETS onnxruntime_providers_webgpu EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) + endif() diff --git a/cmake/onnxruntime_providers_webnn.cmake b/cmake/onnxruntime_providers_webnn.cmake index 05c63c22244db..da5720a9f7cb5 100644 --- a/cmake/onnxruntime_providers_webnn.cmake +++ b/cmake/onnxruntime_providers_webnn.cmake @@ -22,4 +22,12 @@ add_dependencies(onnxruntime_providers_webnn onnx ${onnxruntime_EXTERNAL_DEPENDENCIES}) set_target_properties(onnxruntime_providers_webnn PROPERTIES FOLDER "ONNXRuntime") - set_target_properties(onnxruntime_providers_webnn PROPERTIES LINKER_LANGUAGE CXX) \ No newline at end of file + set_target_properties(onnxruntime_providers_webnn PROPERTIES LINKER_LANGUAGE CXX) + +if (NOT onnxruntime_BUILD_SHARED_LIB) + install(TARGETS onnxruntime_providers_webnn EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/cmake/onnxruntime_providers_xnnpack.cmake b/cmake/onnxruntime_providers_xnnpack.cmake index 796536ac9d12b..1fbe553fa58a0 100644 --- a/cmake/onnxruntime_providers_xnnpack.cmake +++ b/cmake/onnxruntime_providers_xnnpack.cmake @@ -28,7 +28,7 @@ set_target_properties(onnxruntime_providers_xnnpack PROPERTIES LINKER_LANGUAGE CXX) if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_providers_xnnpack + install(TARGETS onnxruntime_providers_xnnpack EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/cmake/onnxruntime_python.cmake b/cmake/onnxruntime_python.cmake index b4a251dc6e282..31487a92aa592 100644 --- a/cmake/onnxruntime_python.cmake +++ b/cmake/onnxruntime_python.cmake @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -include(pybind11) + # ---[ Python + Numpy set(onnxruntime_pybind_srcs_pattern @@ -69,6 +69,20 @@ endif() onnxruntime_add_shared_library_module(onnxruntime_pybind11_state ${onnxruntime_pybind_srcs}) +message(STATUS "Python_EXECUTABLE: ${Python_EXECUTABLE}") + +# Query Py_GIL_DISABLED (PEP 703) +execute_process( + COMMAND "${Python_EXECUTABLE}" -c + "import sysconfig; print(sysconfig.get_config_var('Py_GIL_DISABLED') or '0')" + RESULT_VARIABLE _py_result + OUTPUT_VARIABLE _py_gil_disabled + OUTPUT_STRIP_TRAILING_WHITESPACE +) +if (_py_result EQUAL 0 AND _py_gil_disabled STREQUAL "1") + message(STATUS "Py_GIL_DISABLED=1 detected: Enabling free-threaded support for onnxruntime_pybind11_state") +endif() + if(MSVC) # The following source file is only needed for the EPs that use delayloading. Namely, DML and WebGPU. target_sources(onnxruntime_pybind11_state PRIVATE "${ONNXRUNTIME_ROOT}/core/dll/delay_load_hook.cc") @@ -79,6 +93,12 @@ endif() if(HAS_CAST_FUNCTION_TYPE) target_compile_options(onnxruntime_pybind11_state PRIVATE "-Wno-cast-function-type") endif() +# pybind11 3.0 headers trigger -Wmaybe-uninitialized in GCC's flow analysis +# of property accessor lambdas. Suppress it for this target only. +# See https://github.com/microsoft/onnxruntime/issues/25681 +if(HAS_MAYBE_UNINITIALIZED) + target_compile_options(onnxruntime_pybind11_state PRIVATE "-Wno-maybe-uninitialized") +endif() # We export symbols using linker and the compiler does not know anything about it # There is a problem with classes that have pybind types as members. @@ -96,18 +116,17 @@ if (MSVC AND NOT CMAKE_SIZEOF_VOID_P EQUAL 8) target_compile_options(onnxruntime_pybind11_state PRIVATE "/wd4244") endif() -onnxruntime_add_include_to_target(onnxruntime_pybind11_state Python::Module Python::NumPy) +onnxruntime_add_include_to_target(onnxruntime_pybind11_state Python::Module) target_include_directories(onnxruntime_pybind11_state PRIVATE ${ONNXRUNTIME_ROOT} ${pybind11_INCLUDE_DIRS}) if(onnxruntime_USE_CUDA) - target_include_directories(onnxruntime_pybind11_state PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES} ${CUDNN_INCLUDE_DIR}) + target_include_directories(onnxruntime_pybind11_state PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) + if(NOT onnxruntime_CUDA_MINIMAL) + target_include_directories(onnxruntime_pybind11_state PRIVATE ${CUDNN_INCLUDE_DIR}) + endif() endif() if(onnxruntime_USE_CANN) target_include_directories(onnxruntime_pybind11_state PRIVATE ${onnxruntime_CANN_HOME}/include) endif() -if(onnxruntime_USE_ROCM) - target_compile_options(onnxruntime_pybind11_state PUBLIC -D__HIP_PLATFORM_AMD__=1 -D__HIP_PLATFORM_HCC__=1) - target_include_directories(onnxruntime_pybind11_state PRIVATE ${onnxruntime_ROCM_HOME}/hipfft/include ${onnxruntime_ROCM_HOME}/include ${onnxruntime_ROCM_HOME}/hiprand/include ${onnxruntime_ROCM_HOME}/rocrand/include ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/orttraining) -endif() if (onnxruntime_USE_NCCL) target_include_directories(onnxruntime_pybind11_state PRIVATE ${NCCL_INCLUDE_DIRS}) endif() @@ -131,7 +150,7 @@ if (onnxruntime_ENABLE_ATEN) endif() if (onnxruntime_ENABLE_DLPACK) - target_include_directories(onnxruntime_pybind11_state PRIVATE ${dlpack_SOURCE_DIR}/include) + target_link_libraries(onnxruntime_pybind11_state PRIVATE dlpack::dlpack) endif() if (onnxruntime_ENABLE_TRAINING) @@ -180,16 +199,20 @@ set(onnxruntime_pybind11_state_static_providers ${PROVIDERS_RKNPU} ${PROVIDERS_DML} ${PROVIDERS_ACL} - ${PROVIDERS_ARMNN} ${PROVIDERS_XNNPACK} - ${PROVIDERS_WEBGPU} ${PROVIDERS_AZURE} ) if(onnxruntime_BUILD_QNN_EP_STATIC_LIB) list(APPEND onnxruntime_pybind11_state_static_providers PRIVATE onnxruntime_providers_qnn) endif() - +if(onnxruntime_USE_WEBGPU AND NOT onnxruntime_USE_EP_API_ADAPTERS) + list(APPEND onnxruntime_pybind11_state_static_providers PRIVATE onnxruntime_providers_webgpu) +endif() +if(WIN32) + # onnxruntime_pybind11_state is a DLL + target_sources(onnxruntime_pybind11_state PRIVATE "${ONNXRUNTIME_ROOT}/core/dll/dllmain.cc") +endif() target_link_libraries(onnxruntime_pybind11_state PRIVATE onnxruntime_session ${onnxruntime_libs} @@ -205,8 +228,8 @@ target_link_libraries(onnxruntime_pybind11_state PRIVATE onnxruntime_common onnxruntime_flatbuffers ${pybind11_lib} + Python::NumPy ) - set(onnxruntime_pybind11_state_dependencies ${onnxruntime_EXTERNAL_DEPENDENCIES} ${pybind11_dep} @@ -282,8 +305,22 @@ if (WIN32) if (onnxruntime_USE_CUDA) file(WRITE "${VERSION_INFO_FILE}" "use_cuda = True\n") if(onnxruntime_CUDNN_HOME) - file(GLOB CUDNN_DLL_PATH "${onnxruntime_CUDNN_HOME}/bin/cudnn64_*.dll") - if (NOT CUDNN_DLL_PATH) + # may have x64 in the path + # may have a path with CUDA toolkit version if multiple installed on the machine + set(CUDNN_SEARCH_PATHS + "${onnxruntime_CUDNN_HOME}/bin/cudnn64_*.dll" + "${onnxruntime_CUDNN_HOME}/bin/x64/cudnn64_*.dll" + "${onnxruntime_CUDNN_HOME}/bin/${onnxruntime_CUDA_VERSION}/cudnn64_*.dll" + "${onnxruntime_CUDNN_HOME}/bin/${onnxruntime_CUDA_VERSION}/x64/cudnn64_*.dll" + ) + set(CUDNN_DLL_PATH "") + foreach(search_path ${CUDNN_SEARCH_PATHS}) + file(GLOB CUDNN_DLL_PATH "${search_path}") + if(CUDNN_DLL_PATH) + break() + endif() + endforeach() + if(NOT CUDNN_DLL_PATH) message(FATAL_ERROR "cuDNN not found in ${onnxruntime_CUDNN_HOME}") endif() else() @@ -439,6 +476,9 @@ if (onnxruntime_BUILD_UNIT_TESTS) file(GLOB onnxruntime_python_transformers_test_srcs CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/test/python/transformers/*.py" ) + file(GLOB onnxruntime_python_transformers_test_onnx_attention_srcs CONFIGURE_DEPENDS + "${ONNXRUNTIME_ROOT}/test/python/transformers/test_onnx_attention/*.py" + ) file(GLOB onnxruntime_python_transformers_testdata_srcs CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/test/python/transformers/test_data/models/*.onnx" ) @@ -453,6 +493,9 @@ endif() file(GLOB onnxruntime_python_tools_srcs CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/python/tools/*.py" ) +file(GLOB onnxruntime_python_tools_qnn_src CONFIGURE_DEPENDS + "${ONNXRUNTIME_ROOT}/python/tools/qnn/*.py" +) file(GLOB onnxruntime_python_quantization_src CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/python/tools/quantization/*.py" ) @@ -468,9 +511,18 @@ file(GLOB onnxruntime_python_quantization_fusions_src CONFIGURE_DEPENDS file(GLOB onnxruntime_python_quantization_ep_qnn_src CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/python/tools/quantization/execution_providers/qnn/*.py" ) +file(GLOB onnxruntime_python_quantization_neural_compressor_src CONFIGURE_DEPENDS + "${ONNXRUNTIME_ROOT}/python/tools/quantization/neural_compressor/*.py" +) file(GLOB onnxruntime_python_transformers_src CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/python/tools/transformers/*.py" ) +file(GLOB onnxruntime_python_transformers_models_torch_export_patches_src CONFIGURE_DEPENDS + "${ONNXRUNTIME_ROOT}/python/tools/transformers/models/torch_export_patches/*.py" +) +file(GLOB onnxruntime_python_transformers_models_torch_export_patches_patches_src CONFIGURE_DEPENDS + "${ONNXRUNTIME_ROOT}/python/tools/transformers/models/torch_export_patches/patches/*.py" +) file(GLOB onnxruntime_python_transformers_models_bart_src CONFIGURE_DEPENDS "${ONNXRUNTIME_ROOT}/python/tools/transformers/models/bart/*.py" ) @@ -522,6 +574,7 @@ set(onnxruntime_mobile_util_srcs ${REPO_ROOT}/tools/python/util/pytorch_export_helpers.py ${REPO_ROOT}/tools/python/util/reduced_build_config_parser.py ${REPO_ROOT}/tools/python/util/update_onnx_opset.py + ${REPO_ROOT}/tools/python/remove_initializer_from_input.py ) file(GLOB onnxruntime_ort_format_model_srcs CONFIGURE_DEPENDS ${REPO_ROOT}/tools/python/util/ort_format_model/*.py @@ -555,6 +608,7 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/tools/qdq_helpers COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/tools/ort_format_model COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/tools/ort_format_model/ort_flatbuffers_py + COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/tools/qnn COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/transformers COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/transformers/models COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/transformers/models/bart @@ -566,6 +620,8 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/transformers/models/sam2 COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/transformers/models/stable_diffusion COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/transformers/models/t5 + COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/transformers/models/torch_export_patches + COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/transformers/models/torch_export_patches/patches COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/transformers/models/whisper COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/quantization COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/quantization/operators @@ -573,8 +629,10 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/quantization/fusions COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/quantization/execution_providers COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/quantization/execution_providers/qnn + COMMAND ${CMAKE_COMMAND} -E make_directory $/onnxruntime/quantization/neural_compressor COMMAND ${CMAKE_COMMAND} -E make_directory $/quantization COMMAND ${CMAKE_COMMAND} -E make_directory $/transformers + COMMAND ${CMAKE_COMMAND} -E make_directory $/transformers/test_onnx_attention COMMAND ${CMAKE_COMMAND} -E make_directory $/transformers/test_data/models COMMAND ${CMAKE_COMMAND} -E make_directory $/transformers/test_data/models/whisper COMMAND ${CMAKE_COMMAND} -E make_directory $/eager_test @@ -637,6 +695,9 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E copy_directory ${ONNXRUNTIME_ROOT}/core/flatbuffers/ort_flatbuffers_py $/onnxruntime/tools/ort_format_model/ort_flatbuffers_py + COMMAND ${CMAKE_COMMAND} -E copy + ${onnxruntime_python_tools_qnn_src} + $/onnxruntime/tools/qnn/ COMMAND ${CMAKE_COMMAND} -E copy ${onnxruntime_python_quantization_src} $/onnxruntime/quantization/ @@ -652,6 +713,9 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E copy ${onnxruntime_python_quantization_ep_qnn_src} $/onnxruntime/quantization/execution_providers/qnn/ + COMMAND ${CMAKE_COMMAND} -E copy + ${onnxruntime_python_quantization_neural_compressor_src} + $/onnxruntime/quantization/neural_compressor/ COMMAND ${CMAKE_COMMAND} -E copy ${onnxruntime_python_transformers_src} $/onnxruntime/transformers/ @@ -682,6 +746,12 @@ add_custom_command( COMMAND ${CMAKE_COMMAND} -E copy ${onnxruntime_python_transformers_models_t5_src} $/onnxruntime/transformers/models/t5/ + COMMAND ${CMAKE_COMMAND} -E copy + ${onnxruntime_python_transformers_models_torch_export_patches_src} + $/onnxruntime/transformers/models/torch_export_patches/ + COMMAND ${CMAKE_COMMAND} -E copy + ${onnxruntime_python_transformers_models_torch_export_patches_patches_src} + $/onnxruntime/transformers/models/torch_export_patches/patches/ COMMAND ${CMAKE_COMMAND} -E copy ${onnxruntime_python_transformers_models_whisper_src} $/onnxruntime/transformers/models/whisper/ @@ -708,6 +778,21 @@ if (onnxruntime_USE_OPENVINO) ) endif() +if (onnxruntime_USE_MIGRAPHX) + if (CMAKE_HOST_SYSTEM_NAME STREQUAL "Windows") + add_custom_command( + TARGET onnxruntime_pybind11_state POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${MIGRAPHX_LIB_FILES} + $/onnxruntime/capi/) + add_custom_command( + TARGET onnxruntime_pybind11_state POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${HIPSDK_LIB_FILES} + $/onnxruntime/capi/) + endif() +endif() + if (onnxruntime_ENABLE_EXTERNAL_CUSTOM_OP_SCHEMAS) add_custom_command( TARGET onnxruntime_pybind11_state POST_BUILD @@ -725,9 +810,8 @@ if (onnxruntime_ENABLE_EXTERNAL_CUSTOM_OP_SCHEMAS) endif() if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD - AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS" + AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS|tvOS" AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android" - AND NOT onnxruntime_USE_ROCM AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") add_custom_command( TARGET onnxruntime_pybind11_state POST_BUILD @@ -749,6 +833,9 @@ if (onnxruntime_BUILD_UNIT_TESTS) COMMAND ${CMAKE_COMMAND} -E copy ${onnxruntime_python_transformers_test_srcs} $/transformers/ + COMMAND ${CMAKE_COMMAND} -E copy + ${onnxruntime_python_transformers_test_onnx_attention_srcs} + $/transformers/test_onnx_attention/ COMMAND ${CMAKE_COMMAND} -E copy ${onnxruntime_python_transformers_testdata_srcs} $/transformers/test_data/models/ @@ -914,6 +1001,36 @@ if (onnxruntime_USE_TENSORRT) ) endif() +if (onnxruntime_USE_NV) + if (WIN32 OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") + file(GLOB NV_LIB_FILES LIST_DIRECTORIES false "${TENSORRT_RTX_ROOT}/lib/tensorrt_*.dll" + "${TENSORRT_RTX_ROOT}/bin/tensorrt_*.dll" + "${TENSORRT_RTX_ROOT}/lib/libtensorrt_*.so" + "${TENSORRT_RTX_ROOT}/bin/libtensorrt_*.so") + message(STATUS "NV lib files: " ${NV_LIB_FILES}) + endif() + add_custom_command( + TARGET onnxruntime_pybind11_state POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + ${NV_LIB_FILES} + $ + $ + $/onnxruntime/capi/ + ) + if (EXISTS "${TENSORRT_RTX_ROOT}/doc/LICENSE.txt") + add_custom_command( + TARGET onnxruntime_pybind11_state POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${TENSORRT_RTX_ROOT}/doc/LICENSE.txt" $/onnxruntime/TRT_RTX_LICENSE.txt + ) + endif() + if (EXISTS "${TENSORRT_RTX_ROOT}/doc/Acknowledgements.txt") + add_custom_command( + TARGET onnxruntime_pybind11_state POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${TENSORRT_RTX_ROOT}/doc/Acknowledgements.txt" $/onnxruntime/TRT_RTX_Acknowledgements.txt + ) + endif() +endif() + if (onnxruntime_USE_MIGRAPHX) add_custom_command( TARGET onnxruntime_pybind11_state POST_BUILD @@ -967,16 +1084,6 @@ if (onnxruntime_USE_CANN) ) endif() -if (onnxruntime_USE_ROCM) - add_custom_command( - TARGET onnxruntime_pybind11_state POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - $ - $ - $/onnxruntime/capi/ - ) -endif() - if (onnxruntime_USE_DML) if (NOT onnxruntime_USE_CUSTOM_DIRECTML) set(dml_shared_lib_path ${DML_PACKAGE_DIR}/bin/${onnxruntime_target_platform}-win/${DML_SHARED_LIB}) @@ -1026,18 +1133,44 @@ if (onnxruntime_USE_QNN) ${QNN_LIB_FILES} $/onnxruntime/capi/ ) - add_custom_command( - TARGET onnxruntime_pybind11_state POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy - $ - $/onnxruntime/capi/ - ) - if (EXISTS "${onnxruntime_QNN_HOME}/Qualcomm AI Hub Proprietary License.pdf") + if (EXISTS "${onnxruntime_QNN_HOME}/LICENSE.pdf") + add_custom_command( + TARGET onnxruntime_pybind11_state POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy "${onnxruntime_QNN_HOME}/LICENSE.pdf" $/onnxruntime/Qualcomm_LICENSE.pdf + ) + endif() +endif() + +if (onnxruntime_USE_WEBGPU) + if (WIN32 AND onnxruntime_ENABLE_DAWN_BACKEND_D3D12) + # TODO: the following code is used to disable building Dawn using vcpkg temporarily + # until we figure out how to resolve the packaging pipeline failures + # + # if (onnxruntime_USE_VCPKG) + if (FALSE) + add_custom_command( + TARGET onnxruntime_pybind11_state POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + $ + $ + $/onnxruntime/capi/ + ) + else() + add_custom_command( + TARGET onnxruntime_pybind11_state POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy + $/dxil.dll + $/dxcompiler.dll + $/onnxruntime/capi/ + ) + endif() + endif() + if (onnxruntime_BUILD_DAWN_SHARED_LIBRARY) add_custom_command( TARGET onnxruntime_pybind11_state POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy - "${onnxruntime_QNN_HOME}/Qualcomm AI Hub Proprietary License.pdf" - $/onnxruntime/ + $ + $/onnxruntime/capi/ ) endif() endif() diff --git a/cmake/onnxruntime_rocm_hipify.cmake b/cmake/onnxruntime_rocm_hipify.cmake deleted file mode 100644 index 111033c780712..0000000000000 --- a/cmake/onnxruntime_rocm_hipify.cmake +++ /dev/null @@ -1,257 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. - -find_package(Python3 COMPONENTS Interpreter REQUIRED) - -# GLOB pattern of file to be excluded -set(contrib_ops_excluded_files - "bert/cudnn_fmha/*" - "bert/cutlass_fmha/*" - "bert/fastertransformer_decoder_attention/*" - "bert/flash_attention/*" - "bert/tensorrt_fused_multihead_attention/*" - "bert/attention.cc" - "bert/attention.h" - "bert/attention_impl.cu" - "bert/attention_softmax.h" - "bert/attention_softmax.cu" - "bert/attention_prepare_qkv.cu" - "bert/attention_kernel_options.h" - "bert/attention_kernel_options.cc" - "bert/decoder_attention_impl.h" - "bert/decoder_attention_impl.cu" - "bert/decoder_masked_multihead_attention.h" - "bert/decoder_masked_multihead_attention.cc" - "bert/decoder_masked_self_attention.h" - "bert/decoder_masked_self_attention.cc" - "bert/multihead_attention.cc" - "bert/multihead_attention.h" - "bert/relative_attn_bias.cc" - "bert/relative_attn_bias.h" - "bert/relative_attn_bias_impl.cu" - "bert/relative_attn_bias_impl.h" - "bert/skip_layer_norm.cc" - "bert/skip_layer_norm.h" - "bert/skip_layer_norm_impl.cu" - "bert/skip_layer_norm_impl.h" - "bert/transformer_common.h" - "bert/transformer_common.cc" - "bert/packed_attention.h" - "bert/packed_attention.cc" - "bert/packed_attention_impl.h" - "bert/packed_attention_impl.cu" - "bert/packed_multihead_attention.h" - "bert/packed_multihead_attention.cc" - "bert/packed_multihead_attention_impl.h" - "bert/packed_multihead_attention_impl.cu" - "diffusion/group_norm_impl.cu" - "diffusion/nhwc_conv.cc" - "math/gemm_float8.cc" - "math/gemm_float8.cu" - "math/gemm_float8.h" - "moe/*" - "sparse/*" - "quantization/attention_quantization.cc" - "quantization/attention_quantization.h" - "quantization/attention_quantization_impl.cu" - "quantization/attention_quantization_impl.cuh" - "quantization/dequantize_blockwise_bnb4.cuh" - "quantization/dequantize_blockwise_bnb4.cu" - "quantization/matmul_bnb4.cc" - "quantization/matmul_bnb4.cuh" - "quantization/matmul_bnb4.cu" - "quantization/moe_quantization.h" - "quantization/moe_quantization.cc" - "quantization/quantize_dequantize_linear.cc" - "quantization/qordered_ops/qordered_attention_impl.cu" - "quantization/qordered_ops/qordered_attention_impl.h" - "quantization/qordered_ops/qordered_attention_input_enum.h" - "quantization/qordered_ops/qordered_attention.cc" - "quantization/qordered_ops/qordered_attention.h" - "quantization/qordered_ops/qordered_common.cuh" - "quantization/qordered_ops/qordered_layer_norm.h" - "quantization/qordered_ops/qordered_layer_norm.cc" - "quantization/qordered_ops/qordered_layer_norm_impl.h" - "quantization/qordered_ops/qordered_layer_norm_impl.cu" - "quantization/qordered_ops/qordered_longformer_attention.cc" - "quantization/qordered_ops/qordered_longformer_attention.h" - "quantization/qordered_ops/qordered_matmul.h" - "quantization/qordered_ops/qordered_matmul.cc" - "quantization/qordered_ops/qordered_matmul_utils.h" - "quantization/qordered_ops/qordered_matmul_utils.cc" - "quantization/qordered_ops/qordered_qdq_impl.cu" - "quantization/qordered_ops/qordered_qdq_impl.h" - "quantization/qordered_ops/qordered_qdq.cc" - "quantization/qordered_ops/qordered_qdq.h" - "quantization/qordered_ops/qordered_unary_ops.h" - "quantization/qordered_ops/qordered_unary_ops.cc" - "quantization/qordered_ops/qordered_unary_ops_impl.h" - "quantization/qordered_ops/qordered_unary_ops_impl.cu" - "cuda_contrib_kernels.cc" - "cuda_contrib_kernels.h" - "inverse.cc" - "fused_conv.cc" - "bert/group_query_attention.h" - "bert/group_query_attention.cc" - "bert/group_query_attention_impl.h" - "bert/group_query_attention_impl.cu" - "collective/custom_*" - "collective/distributed_*" - "collective/ipc_*" - "collective/shard*" -) - -if (NOT onnxruntime_USE_NCCL) - # Those are string patterns to exclude. Do NOT use stars such as - # collective/*.cc or *.h. - list(APPEND contrib_ops_excluded_files "collective/nccl_kernels.cc") -endif() - -if (NOT onnxruntime_ENABLE_ATEN) - list(APPEND contrib_ops_excluded_files "aten_ops/aten_op.cc") -endif() - -set(provider_excluded_files - "atomic/common.cuh" - "cu_inc/common.cuh" - "math/einsum_utils/einsum_auxiliary_ops.cc" - "math/einsum_utils/einsum_auxiliary_ops.h" - "math/einsum_utils/einsum_auxiliary_ops_diagonal.cu" - "math/einsum_utils/einsum_auxiliary_ops_diagonal.h" - "math/einsum.cc" - "math/einsum.h" - "math/gemm.cc" - "math/matmul.cc" - "math/softmax_impl.cu" - "math/softmax_warpwise_impl.cuh" - "math/softmax_common.cc" - "math/softmax_common.h" - "math/softmax.cc" - "math/softmax.h" - "nn/conv.cc" - "nn/conv.h" - "nn/conv_transpose.cc" - "nn/conv_transpose.h" - "nn/pool.cc" - "nn/pool.h" - "reduction/reduction_ops.cc" - "rnn/cudnn_rnn_base.cc" - "rnn/cudnn_rnn_base.h" - "rnn/gru.cc" - "rnn/gru.h" - "rnn/lstm.cc" - "rnn/lstm.h" - "rnn/rnn.cc" - "rnn/rnn.h" - "rnn/rnn_impl.cu" - "rnn/rnn_impl.h" - "shared_inc/cuda_call.h" - "shared_inc/cudnn_fe_call.h" - "shared_inc/fpgeneric.h" - "cuda_allocator.cc" - "cuda_allocator.h" - "cuda_call.cc" - "cuda_common.cc" - "cuda_common.h" - "cuda_execution_provider_info.cc" - "cuda_execution_provider_info.h" - "cuda_execution_provider.cc" - "cuda_execution_provider.h" - "cuda_kernel.h" - "cuda_pch.cc" - "cuda_pch.h" - "cuda_profiler.cc" - "cuda_profiler.h" - "cuda_provider_factory.cc" - "cuda_provider_factory.h" - "cuda_stream_handle.cc", - "cuda_stream_handle.h", - "cuda_utils.cu" - "cudnn_common.cc" - "cudnn_common.h" - "cudnn_fe_call.cc" - "cupti_manager.cc" - "cupti_manager.h" - "fpgeneric.cu" - "gpu_data_transfer.cc" - "gpu_data_transfer.h" - "integer_gemm.cc" - "tunable/*" - "cuda_nhwc_kernels.cc" - "cuda_nhwc_kernels.h" -) - -set(training_ops_excluded_files - "activation/gelu_grad_impl_common.cuh" # uses custom tanh - "collective/adasum_kernels.cc" - "collective/adasum_kernels.h" - "math/div_grad.cc" # miopen API differs from cudnn, no double type support - "nn/batch_norm_grad.cc" # no double type support - "nn/batch_norm_grad.h" # miopen API differs from cudnn - "nn/batch_norm_internal.cc" # miopen API differs from cudnn, no double type support - "nn/batch_norm_internal.h" # miopen API differs from cudnn, no double type support - "nn/conv_grad.cc" - "nn/conv_grad.h" - "reduction/reduction_all.cc" # deterministic = true, ignore ctx setting - "reduction/reduction_ops.cc" # no double type support - "cuda_training_kernels.cc" - "cuda_training_kernels.h" - "nn/conv_shared.cc" - "nn/conv_shared.h" - "nn/conv_transpose_grad.cc" - "nn/conv_transpose_grad.h" -) - -function(auto_set_source_files_hip_language) - foreach(f ${ARGN}) - if(f MATCHES ".*\\.cu$") - set_source_files_properties(${f} PROPERTIES LANGUAGE HIP) - endif() - endforeach() -endfunction() - -# cuda_dir must be relative to REPO_ROOT -function(hipify cuda_dir in_excluded_file_patterns out_generated_cc_files out_generated_cu_files) - set(hipify_tool ${REPO_ROOT}/tools/ci_build/amd_hipify.py) - - file(GLOB_RECURSE srcs CONFIGURE_DEPENDS - "${REPO_ROOT}/${cuda_dir}/cuda/*.h" - "${REPO_ROOT}/${cuda_dir}/cuda/*.cc" - "${REPO_ROOT}/${cuda_dir}/cuda/*.cuh" - "${REPO_ROOT}/${cuda_dir}/cuda/*.cu" - ) - - # do exclusion - set(excluded_file_patterns ${${in_excluded_file_patterns}}) - list(TRANSFORM excluded_file_patterns PREPEND "${REPO_ROOT}/${cuda_dir}/cuda/") - file(GLOB_RECURSE excluded_srcs CONFIGURE_DEPENDS ${excluded_file_patterns}) - foreach(f ${excluded_srcs}) - message(STATUS "Excluded from hipify: ${f}") - endforeach() - list(REMOVE_ITEM srcs ${excluded_srcs}) - - foreach(f ${srcs}) - file(RELATIVE_PATH cuda_f_rel "${REPO_ROOT}" ${f}) - string(REPLACE "cuda" "rocm" rocm_f_rel ${cuda_f_rel}) - set(f_out "${CMAKE_CURRENT_BINARY_DIR}/amdgpu/${rocm_f_rel}") - add_custom_command( - OUTPUT ${f_out} - COMMAND Python3::Interpreter ${hipify_tool} - --hipify_perl ${onnxruntime_HIPIFY_PERL} - ${f} -o ${f_out} - DEPENDS ${hipify_tool} ${f} - COMMENT "Hipify: ${cuda_f_rel} -> amdgpu/${rocm_f_rel}" - ) - if(f MATCHES ".*\\.cuh?$") - list(APPEND generated_cu_files ${f_out}) - else() - list(APPEND generated_cc_files ${f_out}) - endif() - endforeach() - - set_source_files_properties(${generated_cc_files} PROPERTIES GENERATED TRUE) - set_source_files_properties(${generated_cu_files} PROPERTIES GENERATED TRUE) - auto_set_source_files_hip_language(${generated_cu_files}) - set(${out_generated_cc_files} ${generated_cc_files} PARENT_SCOPE) - set(${out_generated_cu_files} ${generated_cu_files} PARENT_SCOPE) -endfunction() diff --git a/cmake/onnxruntime_session.cmake b/cmake/onnxruntime_session.cmake index 47cf2dfc5e7aa..1e3357464e991 100644 --- a/cmake/onnxruntime_session.cmake +++ b/cmake/onnxruntime_session.cmake @@ -5,6 +5,10 @@ file(GLOB onnxruntime_session_srcs CONFIGURE_DEPENDS "${ONNXRUNTIME_INCLUDE_DIR}/core/session/*.h" "${ONNXRUNTIME_ROOT}/core/session/*.h" "${ONNXRUNTIME_ROOT}/core/session/*.cc" + "${ONNXRUNTIME_ROOT}/core/session/plugin_ep/*.h" + "${ONNXRUNTIME_ROOT}/core/session/plugin_ep/*.cc" + "${ONNXRUNTIME_ROOT}/core/session/model_package/*.h" + "${ONNXRUNTIME_ROOT}/core/session/model_package/*.cc" ) if (onnxruntime_ENABLE_TRAINING_APIS) @@ -18,10 +22,18 @@ if (onnxruntime_ENABLE_TRAINING_APIS) list(APPEND onnxruntime_session_srcs ${training_api_srcs}) endif() - +# disable for all minimal builds. enabling this pulls in all the provider bridge stuff, +# which is not enabled for any minimal builds. if (onnxruntime_MINIMAL_BUILD) + file(GLOB autoep_srcs + "${ONNXRUNTIME_ROOT}/core/session/plugin_ep/*.*" + "${ONNXRUNTIME_ROOT}/core/session/model_package/*.*" + ) + set(onnxruntime_session_src_exclude "${ONNXRUNTIME_ROOT}/core/session/provider_bridge_ort.cc" + "${ONNXRUNTIME_ROOT}/core/session/model_builder_c_api.cc" + ${autoep_srcs} ) list(REMOVE_ITEM onnxruntime_session_srcs ${onnxruntime_session_src_exclude}) @@ -30,7 +42,7 @@ endif() source_group(TREE ${REPO_ROOT} FILES ${onnxruntime_session_srcs}) onnxruntime_add_static_library(onnxruntime_session ${onnxruntime_session_srcs}) -onnxruntime_add_include_to_target(onnxruntime_session onnxruntime_common onnxruntime_framework onnxruntime_lora onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers Boost::mp11 safeint_interface nlohmann_json::nlohmann_json) +onnxruntime_add_include_to_target(onnxruntime_session onnxruntime_common onnxruntime_framework onnxruntime_lora onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers Boost::mp11 safeint_interface nlohmann_json::nlohmann_json Eigen3::Eigen) target_link_libraries(onnxruntime_session PRIVATE onnxruntime_lora) if(onnxruntime_ENABLE_INSTRUMENT) target_compile_definitions(onnxruntime_session PUBLIC ONNXRUNTIME_ENABLE_INSTRUMENT) @@ -39,19 +51,14 @@ endif() if(NOT MSVC) set_source_files_properties(${ONNXRUNTIME_ROOT}/core/session/environment.cc PROPERTIES COMPILE_FLAGS "-Wno-parentheses") endif() -target_include_directories(onnxruntime_session PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS}) +target_include_directories(onnxruntime_session PRIVATE ${ONNXRUNTIME_ROOT}) if (onnxruntime_USE_EXTENSIONS) target_link_libraries(onnxruntime_session PRIVATE onnxruntime_extensions) endif() add_dependencies(onnxruntime_session ${onnxruntime_EXTERNAL_DEPENDENCIES}) set_target_properties(onnxruntime_session PROPERTIES FOLDER "ONNXRuntime") -if (onnxruntime_USE_ROCM) - target_compile_options(onnxruntime_session PRIVATE -Wno-sign-compare -D__HIP_PLATFORM_AMD__=1 -D__HIP_PLATFORM_HCC__=1) - target_include_directories(onnxruntime_session PRIVATE ${onnxruntime_ROCM_HOME}/hipfft/include ${onnxruntime_ROCM_HOME}/include ${onnxruntime_ROCM_HOME}/hipcub/include ${onnxruntime_ROCM_HOME}/hiprand/include ${onnxruntime_ROCM_HOME}/rocrand/include) -# ROCM provider sources are generated, need to add include directory for generated headers - target_include_directories(onnxruntime_session PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/orttraining) -endif() + if (onnxruntime_ENABLE_TRAINING_OPS) target_include_directories(onnxruntime_session PRIVATE ${ORTTRAINING_ROOT}) endif() @@ -62,13 +69,9 @@ endif() if (NOT onnxruntime_BUILD_SHARED_LIB) install(DIRECTORY ${PROJECT_SOURCE_DIR}/../include/onnxruntime/core/session DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnxruntime/core) - install(TARGETS onnxruntime_session + install(TARGETS onnxruntime_session EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} FRAMEWORK DESTINATION ${CMAKE_INSTALL_BINDIR}) endif() - -if (onnxruntime_USE_NCCL AND onnxruntime_USE_ROCM) - add_dependencies(onnxruntime_session generate_hipified_files) -endif() diff --git a/cmake/onnxruntime_test_pch.cmake b/cmake/onnxruntime_test_pch.cmake new file mode 100644 index 0000000000000..4a8735a9c346c --- /dev/null +++ b/cmake/onnxruntime_test_pch.cmake @@ -0,0 +1,25 @@ +# Precompiled header configuration for onnxruntime_test_all + +if(CMAKE_CXX_COMPILER_ID MATCHES "MSVC") + # Visual Studio PCH + target_precompile_headers(onnxruntime_test_all PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/test_pch.h" + ) + if (TARGET onnxruntime_provider_test) + target_precompile_headers(onnxruntime_provider_test PRIVATE + "${CMAKE_CURRENT_SOURCE_DIR}/test_pch.h" + ) + endif() +endif() + +# Exclude certain files that might conflict with PCH +set(PCH_EXCLUDE_FILES + # Add any problematic source files here + "${TEST_SRC_DIR}/framework/tensor_shape_test.cc" +) + +foreach(file ${PCH_EXCLUDE_FILES}) + set_source_files_properties(${file} PROPERTIES + SKIP_PRECOMPILE_HEADERS ON + ) +endforeach() diff --git a/cmake/onnxruntime_training.cmake b/cmake/onnxruntime_training.cmake index f1a5f908eb245..fab40da1571a9 100644 --- a/cmake/onnxruntime_training.cmake +++ b/cmake/onnxruntime_training.cmake @@ -30,14 +30,14 @@ list(REMOVE_ITEM onnxruntime_training_srcs ${onnxruntime_training_framework_excl onnxruntime_add_static_library(onnxruntime_training ${onnxruntime_training_srcs}) add_dependencies(onnxruntime_training onnx tensorboard ${onnxruntime_EXTERNAL_DEPENDENCIES}) -onnxruntime_add_include_to_target(onnxruntime_training onnxruntime_common onnx onnx_proto tensorboard ${PROTOBUF_LIB} flatbuffers::flatbuffers re2::re2 Boost::mp11 safeint_interface) +onnxruntime_add_include_to_target(onnxruntime_training onnxruntime_common onnx onnx_proto tensorboard ${PROTOBUF_LIB} flatbuffers::flatbuffers re2::re2 Boost::mp11 safeint_interface Eigen3::Eigen) # fix event_writer.cc 4100 warning if(WIN32) target_compile_options(onnxruntime_training PRIVATE /wd4100) endif() -target_include_directories(onnxruntime_training PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${eigen_INCLUDE_DIRS} PUBLIC ${onnxruntime_graph_header} ${MPI_CXX_INCLUDE_DIRS}) +target_include_directories(onnxruntime_training PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} PUBLIC ${onnxruntime_graph_header} ${MPI_CXX_INCLUDE_DIRS}) if (onnxruntime_USE_NCCL) target_include_directories(onnxruntime_training PRIVATE ${NCCL_INCLUDE_DIRS}) @@ -73,19 +73,16 @@ if (onnxruntime_BUILD_UNIT_TESTS) target_link_libraries(onnxruntime_training_runner PRIVATE Python::Python) endif() - onnxruntime_add_include_to_target(onnxruntime_training_runner onnxruntime_training onnxruntime_framework onnxruntime_common onnx onnx_proto ${PROTOBUF_LIB} onnxruntime_training flatbuffers::flatbuffers Boost::mp11 safeint_interface) + onnxruntime_add_include_to_target(onnxruntime_training_runner onnxruntime_training onnxruntime_framework onnxruntime_common onnx onnx_proto ${PROTOBUF_LIB} onnxruntime_training flatbuffers::flatbuffers Boost::mp11 safeint_interface Eigen3::Eigen) - target_include_directories(onnxruntime_training_runner PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${eigen_INCLUDE_DIRS} PUBLIC ${onnxruntime_graph_header}) + target_include_directories(onnxruntime_training_runner PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} PUBLIC ${onnxruntime_graph_header}) target_link_libraries(onnxruntime_training_runner PRIVATE nlohmann_json::nlohmann_json) if (onnxruntime_USE_NCCL) target_include_directories(onnxruntime_training_runner PRIVATE ${NCCL_INCLUDE_DIRS}) endif() - if (onnxruntime_USE_ROCM) - add_definitions(-DUSE_ROCM=1) - target_include_directories(onnxruntime_training_runner PUBLIC ${onnxruntime_ROCM_HOME}/include) - endif() + check_cxx_compiler_flag(-Wno-maybe-uninitialized HAS_NO_MAYBE_UNINITIALIZED) if(UNIX AND NOT APPLE) @@ -94,10 +91,6 @@ if (onnxruntime_BUILD_UNIT_TESTS) endif() endif() - if (onnxruntime_USE_ROCM) - target_compile_options(onnxruntime_training_runner PUBLIC -D__HIP_PLATFORM_AMD__=1 -D__HIP_PLATFORM_HCC__=1) - endif() - set_target_properties(onnxruntime_training_runner PROPERTIES FOLDER "ONNXRuntimeTest") source_group(TREE ${REPO_ROOT} FILES ${onnxruntime_training_runner_srcs} ${onnxruntime_perf_test_src}) @@ -109,7 +102,7 @@ if (onnxruntime_BUILD_UNIT_TESTS) ) onnxruntime_add_executable(onnxruntime_training_mnist ${training_mnist_src}) onnxruntime_add_include_to_target(onnxruntime_training_mnist onnxruntime_common onnx onnx_proto ${PROTOBUF_LIB} onnxruntime_training flatbuffers::flatbuffers Boost::mp11 safeint_interface) - target_include_directories(onnxruntime_training_mnist PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${eigen_INCLUDE_DIRS} ${CXXOPTS} ${extra_includes} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/onnx onnxruntime_training_runner) + target_include_directories(onnxruntime_training_mnist PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${CXXOPTS} ${extra_includes} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/onnx onnxruntime_training_runner) set(ONNXRUNTIME_LIBS onnxruntime_session @@ -131,7 +124,7 @@ if (onnxruntime_BUILD_UNIT_TESTS) ${ONNXRUNTIME_MLAS_LIBS} onnxruntime_common onnxruntime_flatbuffers - Boost::mp11 safeint_interface + Boost::mp11 safeint_interface Eigen3::Eigen ) if(UNIX AND NOT APPLE) @@ -151,7 +144,7 @@ if (onnxruntime_BUILD_UNIT_TESTS) ) onnxruntime_add_executable(onnxruntime_training_squeezenet ${training_squeezene_src}) onnxruntime_add_include_to_target(onnxruntime_training_squeezenet onnxruntime_common onnx onnx_proto ${PROTOBUF_LIB} onnxruntime_training flatbuffers::flatbuffers Boost::mp11 safeint_interface) - target_include_directories(onnxruntime_training_squeezenet PUBLIC ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${eigen_INCLUDE_DIRS} ${extra_includes} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/onnx onnxruntime_training_runner) + target_include_directories(onnxruntime_training_squeezenet PUBLIC ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${extra_includes} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/onnx onnxruntime_training_runner) if(UNIX AND NOT APPLE) target_compile_options(onnxruntime_training_squeezenet PUBLIC "-Wno-maybe-uninitialized") @@ -174,12 +167,7 @@ if (onnxruntime_BUILD_UNIT_TESTS) endif() onnxruntime_add_include_to_target(onnxruntime_training_bert onnxruntime_common onnx onnx_proto ${PROTOBUF_LIB} onnxruntime_training flatbuffers::flatbuffers Boost::mp11 safeint_interface) - target_include_directories(onnxruntime_training_bert PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${MPI_CXX_INCLUDE_DIRS} ${eigen_INCLUDE_DIRS} ${CXXOPTS} ${extra_includes} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/onnx onnxruntime_training_runner) - - # ROCM provider sources are generated, need to add include directory for generated headers - if (onnxruntime_USE_ROCM) - target_include_directories(onnxruntime_training_bert PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime) - endif() + target_include_directories(onnxruntime_training_bert PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${MPI_CXX_INCLUDE_DIRS} ${CXXOPTS} ${extra_includes} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/onnx onnxruntime_training_runner) target_link_libraries(onnxruntime_training_bert PRIVATE onnxruntime_training_runner onnxruntime_training ${ONNXRUNTIME_LIBS} ${onnxruntime_EXTERNAL_LIBRARIES}) set_target_properties(onnxruntime_training_bert PROPERTIES FOLDER "ONNXRuntimeTest") @@ -198,7 +186,7 @@ if (onnxruntime_BUILD_UNIT_TESTS) endif() onnxruntime_add_include_to_target(onnxruntime_training_pipeline_poc onnxruntime_common onnx onnx_proto ${PROTOBUF_LIB} onnxruntime_training flatbuffers::flatbuffers Boost::mp11 safeint_interface) - target_include_directories(onnxruntime_training_pipeline_poc PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${MPI_CXX_INCLUDE_DIRS} ${eigen_INCLUDE_DIRS} ${CXXOPTS} ${extra_includes} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/onnx onnxruntime_training_runner) + target_include_directories(onnxruntime_training_pipeline_poc PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${MPI_CXX_INCLUDE_DIRS} ${CXXOPTS} ${extra_includes} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/onnx onnxruntime_training_runner) if (onnxruntime_USE_NCCL) target_include_directories(onnxruntime_training_pipeline_poc PRIVATE ${NCCL_INCLUDE_DIRS}) endif() @@ -218,7 +206,7 @@ if (onnxruntime_BUILD_UNIT_TESTS) endif() endif() - target_include_directories(onnxruntime_training_gpt2 PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${MPI_CXX_INCLUDE_DIRS} ${eigen_INCLUDE_DIRS} ${CXXOPTS} ${extra_includes} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/onnx onnxruntime_training_runner) + target_include_directories(onnxruntime_training_gpt2 PUBLIC ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} ${MPI_CXX_INCLUDE_DIRS} ${CXXOPTS} ${extra_includes} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} ${CMAKE_CURRENT_BINARY_DIR} ${CMAKE_CURRENT_BINARY_DIR}/onnx onnxruntime_training_runner) target_link_libraries(onnxruntime_training_gpt2 PRIVATE onnxruntime_training_runner onnxruntime_training ${ONNXRUNTIME_LIBS} ${onnxruntime_EXTERNAL_LIBRARIES}) set_target_properties(onnxruntime_training_gpt2 PROPERTIES FOLDER "ONNXRuntimeTest") diff --git a/cmake/onnxruntime_tvos.toolchain.cmake b/cmake/onnxruntime_tvos.toolchain.cmake new file mode 100644 index 0000000000000..5c992a1f465c6 --- /dev/null +++ b/cmake/onnxruntime_tvos.toolchain.cmake @@ -0,0 +1,12 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + +set(CMAKE_SYSTEM_NAME tvOS) +set(CMAKE_SYSTEM_PROCESSOR arm64) + +if (NOT DEFINED CMAKE_XCODE_ATTRIBUTE_DEVELOPMENT_TEAM AND NOT DEFINED CMAKE_XCODE_ATTRIBUTE_CODE_SIGN_IDENTITY) + set(CMAKE_XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED NO) +endif() + +SET(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_MODULES "YES") +SET(CMAKE_XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC "YES") diff --git a/cmake/onnxruntime_unittests.cmake b/cmake/onnxruntime_unittests.cmake index c727f4b7e381b..7f361aa63921f 100644 --- a/cmake/onnxruntime_unittests.cmake +++ b/cmake/onnxruntime_unittests.cmake @@ -10,11 +10,58 @@ if (onnxruntime_ENABLE_TRAINING) list(APPEND TEST_INC_DIR ${ORTTRAINING_ROOT}) endif() +# Exclude files based on CMake options. +function(filter_test_srcs test_srcs_var) + set(excluded_path_prefixes) + + if(onnxruntime_DISABLE_CONTRIB_OPS) + list(APPEND excluded_path_prefixes ${TEST_SRC_DIR}/contrib_ops) + endif() + + if(onnxruntime_DISABLE_ML_OPS) + list(APPEND excluded_path_prefixes ${TEST_SRC_DIR}/providers/cpu/ml) + endif() + + list(LENGTH excluded_path_prefixes num_excluded_path_prefixes) + + if("${num_excluded_path_prefixes}" GREATER "0") + set(filtered_test_srcs) + + foreach(test_src ${${test_srcs_var}}) + set(is_excluded false) + + foreach(excluded_path_prefix ${excluded_path_prefixes}) + cmake_path(ABSOLUTE_PATH test_src OUTPUT_VARIABLE test_src_absolute) + + cmake_path(IS_PREFIX excluded_path_prefix ${test_src_absolute} NORMALIZE is_excluded) + + if (is_excluded) + break() + endif() + endforeach() + + if(NOT is_excluded) + list(APPEND filtered_test_srcs ${test_src}) + endif() + endforeach() + + set(${test_srcs_var} ${filtered_test_srcs} PARENT_SCOPE) + endif() +endfunction() + set(disabled_warnings) function(AddTest) cmake_parse_arguments(_UT "DYN" "TARGET" "LIBS;SOURCES;DEPENDS;TEST_ARGS" ${ARGN}) list(REMOVE_DUPLICATES _UT_SOURCES) + filter_test_srcs(_UT_SOURCES) + + message(VERBOSE "AddTest() TARGET: ${_UT_TARGET}") + message(VERBOSE "AddTest() SOURCES:") + foreach(ut_src ${_UT_SOURCES}) + message(VERBOSE " ${ut_src}") + endforeach() + if (IOS) onnxruntime_add_executable(${_UT_TARGET} ${TEST_SRC_DIR}/xctest/orttestmain.m) else() @@ -61,13 +108,13 @@ function(AddTest) Threads::Threads) target_compile_definitions(${_UT_TARGET} PRIVATE -DUSE_ONNXRUNTIME_DLL) else() - if(onnxruntime_USE_CUDA) + if(onnxruntime_USE_CUDA OR onnxruntime_USE_NV) #XXX: we should not need to do this. onnxruntime_test_all.exe should not have direct dependency on CUDA DLLs, # otherwise it will impact when CUDA DLLs can be unloaded. target_link_libraries(${_UT_TARGET} PRIVATE CUDA::cudart) - if(NOT onnxruntime_CUDA_MINIMAL) - target_link_libraries(${_UT_TARGET} PRIVATE cudnn_frontend) - endif() + endif() + if(onnxruntime_USE_CUDA AND NOT onnxruntime_CUDA_MINIMAL) + target_link_libraries(${_UT_TARGET} PRIVATE cudnn_frontend) endif() target_link_libraries(${_UT_TARGET} PRIVATE ${_UT_LIBS} GTest::gtest GTest::gmock ${onnxruntime_EXTERNAL_LIBRARIES}) endif() @@ -75,7 +122,10 @@ function(AddTest) onnxruntime_add_include_to_target(${_UT_TARGET} date::date flatbuffers::flatbuffers) target_include_directories(${_UT_TARGET} PRIVATE ${TEST_INC_DIR}) if (onnxruntime_USE_CUDA) - target_include_directories(${_UT_TARGET} PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES} ${CUDNN_INCLUDE_DIR}) + target_include_directories(${_UT_TARGET} PRIVATE ${CUDAToolkit_INCLUDE_DIRS}) + if(NOT onnxruntime_CUDA_MINIMAL) + target_include_directories(${_UT_TARGET} PRIVATE ${CUDNN_INCLUDE_DIR}) + endif() if (onnxruntime_USE_NCCL) target_include_directories(${_UT_TARGET} PRIVATE ${NCCL_INCLUDE_DIRS}) endif() @@ -87,6 +137,10 @@ function(AddTest) # used for instantiating placeholder TRT builder to mitigate TRT library load/unload overhead target_include_directories(${_UT_TARGET} PRIVATE ${TENSORRT_INCLUDE_DIR}) endif() + if (onnxruntime_USE_NV) + # used for instantiating placeholder TRT builder to mitigate TRT library load/unload overhead + target_include_directories(${_UT_TARGET} PRIVATE ${NV_INCLUDE_DIR} ${CUDAToolkit_INCLUDE_DIRS}) + endif() if(MSVC) target_compile_options(${_UT_TARGET} PRIVATE "$<$:SHELL:--compiler-options /utf-8>" @@ -116,6 +170,9 @@ function(AddTest) if (${HAS_NOERROR}) target_compile_options(${_UT_TARGET} PRIVATE "$<$:-Wno-error=uninitialized>") endif() + if (${HAS_CHARACTER_CONVERSION}) + target_compile_options(${_UT_TARGET} PRIVATE "$<$:-Wno-error=character-conversion>") + endif() endif() set(TEST_ARGS ${_UT_TEST_ARGS}) @@ -194,13 +251,8 @@ function(AddTest) # xctest_add_test(xctest.${_UT_TARGET} ${_UT_TARGET}_xc) else() if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") - # We might have already executed the following "find_program" code when we build ORT nodejs binding. - # Then the program is found the result is stored in the variable and the search will not be repeated. - find_program(NPM_CLI - NAMES "npm.cmd" "npm" - DOC "NPM command line client" - REQUIRED - ) + # Include the Node.js helper for finding and validating Node.js and NPM + include(node_helper.cmake) if (onnxruntime_WEBASSEMBLY_RUN_TESTS_IN_BROWSER) add_custom_command(TARGET ${_UT_TARGET} POST_BUILD @@ -222,8 +274,11 @@ function(AddTest) else() set(TEST_NODE_FLAGS) + if (onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD) + message(WARNING "Use system `node` to test Wasm relaxed SIMD. Please make sure to install node v21 or newer.") + set(NODE_EXECUTABLE node) # prefer Node from emsdk so the version is more deterministic - if (DEFINED ENV{EMSDK_NODE}) + elseif (DEFINED ENV{EMSDK_NODE}) set(NODE_EXECUTABLE $ENV{EMSDK_NODE}) else() message(WARNING "EMSDK_NODE environment variable was not set. Falling back to system `node`.") @@ -236,18 +291,62 @@ function(AddTest) ) endif() # Set test timeout to 3 hours. - set_tests_properties(${_UT_TARGET} PROPERTIES TIMEOUT 7200) + set_tests_properties(${_UT_TARGET} PROPERTIES TIMEOUT 10800) else() add_test(NAME ${_UT_TARGET} COMMAND ${_UT_TARGET} ${TEST_ARGS} WORKING_DIRECTORY $ ) # Set test timeout to 3 hours. - set_tests_properties(${_UT_TARGET} PROPERTIES TIMEOUT 7200) + set_tests_properties(${_UT_TARGET} PROPERTIES TIMEOUT 10800) endif() endif() endfunction(AddTest) +# Given a list of test source files, in variable `all_srcs_var`, partition it into two lists: +# - a list of the provider-related test source files, stored in `provider_test_srcs_var` +# - a list of the other remaining test source files, stored in `other_srcs_var` +# +# In particular, provider-related test source files are located in these root paths: +# - onnxruntime/test/contrib_ops +# - onnxruntime/test/providers +function(partition_provider_test_srcs + all_srcs_var provider_test_srcs_var other_srcs_var) + set(provider_test_src_roots + ${TEST_SRC_DIR}/contrib_ops + ${TEST_SRC_DIR}/providers + ) + + function(is_provider_test_src src_var result_var) + cmake_path(ABSOLUTE_PATH ${src_var} OUTPUT_VARIABLE src_absolute) + + foreach(provider_test_src_root ${provider_test_src_roots}) + cmake_path(IS_PREFIX provider_test_src_root ${src_absolute} NORMALIZE src_matches_root) + if(src_matches_root) + set(${result_var} true PARENT_SCOPE) + return() + endif() + endforeach() + + set(${result_var} false PARENT_SCOPE) + endfunction() + + set(provider_test_srcs) + set(other_srcs) + + foreach(src ${${all_srcs_var}}) + is_provider_test_src(src is_provider_test_src_result) + if(is_provider_test_src_result) + list(APPEND provider_test_srcs ${src}) + else() + list(APPEND other_srcs ${src}) + endif() + endforeach() + + set(${provider_test_srcs_var} ${provider_test_srcs} PARENT_SCOPE) + set(${other_srcs_var} ${other_srcs} PARENT_SCOPE) +endfunction() + # general program entrypoint for C++ unit tests set(onnxruntime_unittest_main_src "${TEST_SRC_DIR}/unittest_main/test_main.cc") @@ -362,6 +461,11 @@ if(WIN32) "${TEST_SRC_DIR}/platform/windows/logging/*.cc" ) endif() +if(LINUX) + list(APPEND onnxruntime_test_framework_src_patterns + "${TEST_SRC_DIR}/platform/linux/*.cc" ) +endif() + if(NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_REDUCED_OPS_BUILD) if(onnxruntime_USE_CUDA) @@ -372,29 +476,24 @@ if(NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_REDUCED_OPS_BUILD) "${TEST_SRC_DIR}/providers/*.h" "${TEST_SRC_DIR}/providers/*.cc" "${TEST_SRC_DIR}/opaque_api/test_opaque_api.cc" - "${TEST_SRC_DIR}/framework/TestAllocatorManager.cc" - "${TEST_SRC_DIR}/framework/TestAllocatorManager.h" - "${TEST_SRC_DIR}/framework/test_utils.cc" - "${TEST_SRC_DIR}/framework/test_utils.h" + "${TEST_SRC_DIR}/contrib_ops/*.h" + "${TEST_SRC_DIR}/contrib_ops/*.cc" + "${TEST_SRC_DIR}/contrib_ops/math/*.h" + "${TEST_SRC_DIR}/contrib_ops/math/*.cc" ) - if(NOT onnxruntime_DISABLE_CONTRIB_OPS) - list(APPEND onnxruntime_test_providers_src_patterns - "${TEST_SRC_DIR}/contrib_ops/*.h" - "${TEST_SRC_DIR}/contrib_ops/*.cc" - "${TEST_SRC_DIR}/contrib_ops/math/*.h" - "${TEST_SRC_DIR}/contrib_ops/math/*.cc") - endif() - else() set(onnxruntime_test_providers_src_patterns - "${TEST_SRC_DIR}/framework/test_utils.cc" - "${TEST_SRC_DIR}/framework/test_utils.h" # TODO: Add anything that is needed for testing a minimal build ) endif() -file(GLOB onnxruntime_test_providers_src CONFIGURE_DEPENDS ${onnxruntime_test_providers_src_patterns}) +list(LENGTH onnxruntime_test_providers_src_patterns onnxruntime_test_providers_src_patterns_length) +if(onnxruntime_test_providers_src_patterns_length GREATER 0) + file(GLOB onnxruntime_test_providers_src CONFIGURE_DEPENDS ${onnxruntime_test_providers_src_patterns}) +else() + set(onnxruntime_test_providers_src) +endif() if(NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_REDUCED_OPS_BUILD) file(GLOB_RECURSE onnxruntime_test_providers_cpu_src CONFIGURE_DEPENDS @@ -402,10 +501,6 @@ if(NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_REDUCED_OPS_BUILD) ) endif() -if(onnxruntime_DISABLE_ML_OPS) - list(FILTER onnxruntime_test_providers_cpu_src EXCLUDE REGEX ".*/ml/.*") -endif() - list(APPEND onnxruntime_test_providers_src ${onnxruntime_test_providers_cpu_src}) if (onnxruntime_USE_CUDA AND NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_REDUCED_OPS_BUILD) @@ -414,6 +509,13 @@ if (onnxruntime_USE_CUDA AND NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_R ) list(APPEND onnxruntime_test_providers_src ${onnxruntime_test_providers_cuda_src}) + if (onnxruntime_BUILD_CUDA_EP_AS_PLUGIN) + file(GLOB onnxruntime_test_providers_cuda_plugin_src CONFIGURE_DEPENDS + "${TEST_SRC_DIR}/providers/cuda/plugin/*.cc" + ) + list(APPEND onnxruntime_test_providers_src ${onnxruntime_test_providers_cuda_plugin_src}) + endif() + if (onnxruntime_USE_CUDA_NHWC_OPS AND CUDNN_MAJOR_VERSION GREATER 8) file(GLOB onnxruntime_test_providers_cuda_nhwc_src CONFIGURE_DEPENDS "${TEST_SRC_DIR}/providers/cuda/nhwc/*.cc" @@ -446,7 +548,7 @@ if (NOT onnxruntime_MINIMAL_BUILD) list(APPEND onnxruntime_test_providers_src ${orttraining_test_trainingops_cpu_src}) - if (onnxruntime_USE_CUDA OR onnxruntime_USE_ROCM) + if (onnxruntime_USE_CUDA) file(GLOB_RECURSE orttraining_test_trainingops_cuda_src CONFIGURE_DEPENDS "${ORTTRAINING_SOURCE_DIR}/test/training_ops/cuda/*" ) @@ -476,33 +578,42 @@ if (onnxruntime_USE_RKNPU) list(APPEND onnxruntime_test_providers_src ${onnxruntime_test_providers_rknpu_src}) endif() +set(onnxruntime_test_internal_testing_ep_src) if (NOT onnxruntime_MINIMAL_BUILD OR onnxruntime_EXTENDED_MINIMAL_BUILD) file(GLOB_RECURSE onnxruntime_test_providers_internal_testing_src CONFIGURE_DEPENDS - "${TEST_SRC_DIR}/providers/internal_testing/*" + "${TEST_SRC_DIR}/internal_testing_ep/*" ) - list(APPEND onnxruntime_test_providers_src ${onnxruntime_test_providers_internal_testing_src}) + list(APPEND onnxruntime_test_internal_testing_ep_src ${onnxruntime_test_providers_internal_testing_src}) endif() set (ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR "${TEST_SRC_DIR}/shared_lib") set (ONNXRUNTIME_GLOBAL_THREAD_POOLS_TEST_SRC_DIR "${TEST_SRC_DIR}/global_thread_pools") set (ONNXRUNTIME_CUSTOM_OP_REGISTRATION_TEST_SRC_DIR "${TEST_SRC_DIR}/custom_op_registration") set (ONNXRUNTIME_LOGGING_APIS_TEST_SRC_DIR "${TEST_SRC_DIR}/logging_apis") +set (ONNXRUNTIME_AUTOEP_TEST_SRC_DIR "${TEST_SRC_DIR}/autoep") +set (ONNXRUNTIME_EP_GRAPH_TEST_SRC_DIR "${TEST_SRC_DIR}/ep_graph") set (onnxruntime_shared_lib_test_SRC - ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_fixture.h - ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_session_options.cc - ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_run_options.cc + ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/custom_op_utils.h + ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/custom_op_utils.cc ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_allocator.cc - ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_nontensor_types.cc + ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_data_copy.cc + ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_fixture.h ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_model_loading.cc + ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_nontensor_types.cc ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_ort_format_models.cc + ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_run_options.cc + ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_runtime_path.cc + ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_session_options.cc + ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_version.cc ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/utils.h ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/utils.cc - ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/custom_op_utils.h - ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/custom_op_utils.cc) + ) if (NOT onnxruntime_MINIMAL_BUILD) list(APPEND onnxruntime_shared_lib_test_SRC ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_inference.cc) + list(APPEND onnxruntime_shared_lib_test_SRC ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_model_builder_api.cc) + list(APPEND onnxruntime_shared_lib_test_SRC ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/test_env_creation.cc) endif() if(onnxruntime_RUN_ONNX_TESTS) @@ -524,42 +635,10 @@ set (onnxruntime_webgpu_delay_load_test_SRC # the order of libraries should be maintained, with higher libraries being added first in the list set(onnxruntime_test_common_libs - onnxruntime_test_utils + onnxruntime_unittest_utils onnxruntime_common ) -set(onnxruntime_test_ir_libs - onnxruntime_test_utils - onnxruntime_graph - onnxruntime_common -) - -set(onnxruntime_test_optimizer_libs - onnxruntime_test_utils - onnxruntime_framework - onnxruntime_util - onnxruntime_graph - onnxruntime_common -) - -set(onnxruntime_test_framework_libs - onnxruntime_test_utils - onnxruntime_framework - onnxruntime_util - onnxruntime_graph - ${ONNXRUNTIME_MLAS_LIBS} - onnxruntime_common - ) - -set(onnxruntime_test_server_libs - onnxruntime_test_utils - onnxruntime_test_utils_for_server -) - -if(WIN32) - list(APPEND onnxruntime_test_framework_libs Advapi32) -endif() - set (onnxruntime_test_providers_dependencies ${onnxruntime_EXTERNAL_DEPENDENCIES}) if(onnxruntime_USE_CUDA) @@ -582,10 +661,6 @@ if(onnxruntime_USE_JSEP) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_js) endif() -if(onnxruntime_USE_WEBGPU) - list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_webgpu) -endif() - if(onnxruntime_USE_RKNPU) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_rknpu) endif() @@ -599,12 +674,7 @@ if(onnxruntime_USE_DNNL) endif() if(onnxruntime_USE_MIGRAPHX) - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_migraphx) - list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_migraphx onnxruntime_providers_shared) -endif() - -if(onnxruntime_USE_ROCM) - list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_rocm) + list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_migraphx) endif() if(onnxruntime_USE_COREML) @@ -615,22 +685,16 @@ if(onnxruntime_USE_ACL) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_acl) endif() -if(onnxruntime_USE_ARMNN) - list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_armnn) -endif() - set(ONNXRUNTIME_TEST_STATIC_PROVIDER_LIBS - # CUDA, ROCM, TENSORRT, MIGRAPHX, DNNL, and OpenVINO are dynamically loaded at runtime. + # CUDA, TENSORRT, MIGRAPHX, DNNL, and OpenVINO are dynamically loaded at runtime. # QNN EP can be built as either a dynamic and static libs. ${PROVIDERS_NNAPI} ${PROVIDERS_VSINPU} ${PROVIDERS_JS} - ${PROVIDERS_WEBGPU} ${PROVIDERS_SNPE} ${PROVIDERS_RKNPU} ${PROVIDERS_DML} ${PROVIDERS_ACL} - ${PROVIDERS_ARMNN} ${PROVIDERS_COREML} ${PROVIDERS_XNNPACK} ${PROVIDERS_AZURE} @@ -639,6 +703,9 @@ set(ONNXRUNTIME_TEST_STATIC_PROVIDER_LIBS if (onnxruntime_BUILD_QNN_EP_STATIC_LIB) list(APPEND ONNXRUNTIME_TEST_STATIC_PROVIDER_LIBS onnxruntime_providers_qnn) endif() +if (onnxruntime_USE_WEBGPU AND NOT onnxruntime_USE_EP_API_ADAPTERS) + list(APPEND ONNXRUNTIME_TEST_STATIC_PROVIDER_LIBS onnxruntime_providers_webgpu) +endif() set(ONNXRUNTIME_TEST_LIBS onnxruntime_session @@ -669,35 +736,47 @@ set(onnxruntime_test_providers_libs if(onnxruntime_USE_TENSORRT) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/tensorrt/*) list(APPEND onnxruntime_test_framework_src_patterns "${ONNXRUNTIME_ROOT}/core/providers/tensorrt/tensorrt_execution_provider_utils.h") - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_tensorrt) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_tensorrt onnxruntime_providers_shared) list(APPEND onnxruntime_test_providers_libs ${TENSORRT_LIBRARY_INFER}) endif() +if(onnxruntime_USE_NV) + # If an external project (e.g. dawn from Webgpu EP has already added a Vulkan::Headers target we shouldn't try to import another version of the Vulkan headers) + if (NOT TARGET Vulkan::Headers) + onnxruntime_fetchcontent_declare( + vulkan_headers + URL ${DEP_URL_vulkan_headers} + URL_HASH SHA1=${DEP_SHA1_vulkan_headers} + EXCLUDE_FROM_ALL + ) + onnxruntime_fetchcontent_makeavailable(vulkan_headers) + endif() + list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/nv_tensorrt_rtx/*) + list(APPEND onnxruntime_test_framework_src_patterns "${ONNXRUNTIME_ROOT}/core/providers/nv_tensorrt_rtx/nv_execution_provider_utils.h") + list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_nv_tensorrt_rtx onnxruntime_providers_shared) + list(APPEND onnxruntime_test_providers_libs ${TENSORRT_LIBRARY_INFER}) + list(APPEND onnxruntime_test_providers_libs Vulkan::Headers) +endif() + + if(onnxruntime_USE_MIGRAPHX) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/migraphx/*) - list(APPEND onnxruntime_test_framework_src_patterns "${ONNXRUNTIME_ROOT}/core/providers/migraphx/migraphx_execution_provider_utils.h") - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_migraphx) - list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_migraphx onnxruntime_providers_shared) endif() if(onnxruntime_USE_NNAPI_BUILTIN) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/nnapi/*) - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_nnapi) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_nnapi) list(APPEND onnxruntime_test_providers_libs onnxruntime_providers_nnapi) endif() if(onnxruntime_USE_JSEP) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/js/*) - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_js) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_js) list(APPEND onnxruntime_test_providers_libs onnxruntime_providers_js) endif() -if(onnxruntime_USE_WEBGPU) +if(onnxruntime_USE_WEBGPU AND NOT onnxruntime_USE_EP_API_ADAPTERS) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/webgpu/*) - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_webgpu) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_webgpu) list(APPEND onnxruntime_test_providers_libs onnxruntime_providers_webgpu) endif() @@ -706,7 +785,8 @@ endif() # or reduced op builds. if(onnxruntime_USE_QNN AND NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_REDUCED_OPS_BUILD) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/qnn/*) - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_qnn) + list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/qnn/qnn_node_group/*) + list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/qnn/optimizer/*) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_qnn) if(NOT onnxruntime_BUILD_QNN_EP_STATIC_LIB) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_shared) @@ -715,14 +795,12 @@ endif() if(onnxruntime_USE_SNPE) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/snpe/*) - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_snpe) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_snpe) list(APPEND onnxruntime_test_providers_libs onnxruntime_providers_snpe) endif() if(onnxruntime_USE_RKNPU) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/rknpu/*) - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_rknpu) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_rknpu) list(APPEND onnxruntime_test_providers_libs onnxruntime_providers_rknpu) endif() @@ -732,25 +810,28 @@ if(onnxruntime_USE_COREML) if(APPLE) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/coreml/*.mm) endif() - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_coreml coreml_proto) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_coreml coreml_proto) list(APPEND onnxruntime_test_providers_libs onnxruntime_providers_coreml coreml_proto) endif() if(onnxruntime_USE_XNNPACK) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/xnnpack/*) - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_xnnpack) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_xnnpack) list(APPEND onnxruntime_test_providers_libs onnxruntime_providers_xnnpack) endif() if(onnxruntime_USE_AZURE) list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/azure/*) - list(APPEND onnxruntime_test_framework_libs onnxruntime_providers_azure) list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_azure) list(APPEND onnxruntime_test_providers_libs onnxruntime_providers_azure) endif() +if (onnxruntime_USE_OPENVINO) + list(APPEND onnxruntime_test_framework_src_patterns ${TEST_SRC_DIR}/providers/openvino/*) + list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_openvino) + list(APPEND onnxruntime_test_providers_dependencies onnxruntime_providers_shared) +endif() + file(GLOB onnxruntime_test_framework_src CONFIGURE_DEPENDS ${onnxruntime_test_framework_src_patterns} ) @@ -766,26 +847,75 @@ if(MSVC) "$<$>:/wd6326>") else() target_include_directories(onnxruntime_test_utils PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT}) + if (HAS_CHARACTER_CONVERSION) + target_compile_options(onnxruntime_test_utils PRIVATE "$<$:-Wno-error=character-conversion>") + endif() endif() if (onnxruntime_USE_NCCL) target_include_directories(onnxruntime_test_utils PRIVATE ${NCCL_INCLUDE_DIRS}) endif() -if (onnxruntime_USE_ROCM) - target_include_directories(onnxruntime_test_utils PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/orttraining) -endif() -onnxruntime_add_include_to_target(onnxruntime_test_utils onnxruntime_common onnxruntime_framework onnxruntime_session GTest::gtest GTest::gmock onnx onnx_proto flatbuffers::flatbuffers nlohmann_json::nlohmann_json Boost::mp11 safeint_interface) - - - +onnxruntime_add_include_to_target(onnxruntime_test_utils onnxruntime_common onnxruntime_framework onnxruntime_session GTest::gtest GTest::gmock onnx onnx_proto flatbuffers::flatbuffers nlohmann_json::nlohmann_json Boost::mp11 safeint_interface Eigen3::Eigen) if (onnxruntime_USE_DML) target_add_dml(onnxruntime_test_utils) endif() add_dependencies(onnxruntime_test_utils ${onnxruntime_EXTERNAL_DEPENDENCIES}) target_include_directories(onnxruntime_test_utils PUBLIC "${TEST_SRC_DIR}/util/include" PRIVATE - ${eigen_INCLUDE_DIRS} ${ONNXRUNTIME_ROOT}) + ${ONNXRUNTIME_ROOT}) set_target_properties(onnxruntime_test_utils PROPERTIES FOLDER "ONNXRuntimeTest") source_group(TREE ${TEST_SRC_DIR} FILES ${onnxruntime_test_utils_src}) +# onnxruntime_unittest_utils +# This is static library containing utilities that are specifically for unit tests. +# Unlike onnxruntime_test_utils, the source files here may have dependencies on internal onnxruntime code. +# Thus, onnxruntime_unittest_utils is not suitable for use in programs that don't link with internal onnxruntime +# libraries. +block() + +file(GLOB onnxruntime_unittest_utils_src CONFIGURE_DEPENDS + "${TEST_SRC_DIR}/unittest_util/*.h" + "${TEST_SRC_DIR}/unittest_util/*.cc") + +if(onnxruntime_MINIMAL_BUILD OR onnxruntime_REDUCED_OPS_BUILD) + # some exclusions from a minimal or reduced ops build + list(REMOVE_ITEM onnxruntime_unittest_utils_src + "${TEST_SRC_DIR}/unittest_util/base_tester.cc" + "${TEST_SRC_DIR}/unittest_util/base_tester.h" + "${TEST_SRC_DIR}/unittest_util/function_test_util.cc" + "${TEST_SRC_DIR}/unittest_util/function_test_util.h" + "${TEST_SRC_DIR}/unittest_util/graph_transform_test_builder.cc" + "${TEST_SRC_DIR}/unittest_util/graph_transform_test_builder.h" + "${TEST_SRC_DIR}/unittest_util/model_tester.h" + "${TEST_SRC_DIR}/unittest_util/op_tester.cc" + "${TEST_SRC_DIR}/unittest_util/op_tester.h" + "${TEST_SRC_DIR}/unittest_util/qdq_test_utils.cc" + "${TEST_SRC_DIR}/unittest_util/qdq_test_utils.h" + ) + + if (onnxruntime_MINIMAL_BUILD) + list(REMOVE_ITEM onnxruntime_unittest_utils_src + "${TEST_SRC_DIR}/unittest_util/test_dynamic_plugin_ep.cc" + "${TEST_SRC_DIR}/unittest_util/test_dynamic_plugin_ep.h" + ) + endif() +endif() + +onnxruntime_add_static_library(onnxruntime_unittest_utils ${onnxruntime_unittest_utils_src}) + +target_link_libraries(onnxruntime_unittest_utils PUBLIC + onnx + GTest::gtest + GTest::gmock + onnxruntime_test_utils + ${ONNXRUNTIME_TEST_LIBS} + ${onnxruntime_EXTERNAL_LIBRARIES} + ) + +set_target_properties(onnxruntime_unittest_utils PROPERTIES FOLDER "ONNXRuntimeTest") + +source_group(TREE ${TEST_SRC_DIR} FILES ${onnxruntime_unittest_utils_src}) + +endblock() + if(NOT IOS) set(onnx_test_runner_src_dir ${TEST_SRC_DIR}/onnx) file(GLOB onnx_test_runner_common_srcs CONFIGURE_DEPENDS @@ -794,6 +924,14 @@ if(NOT IOS) list(REMOVE_ITEM onnx_test_runner_common_srcs ${onnx_test_runner_src_dir}/main.cc) + # if training is disabled, endian_utils are still used in tests + if (NOT onnxruntime_ENABLE_TRAINING) + list(APPEND onnx_test_runner_common_srcs + ${ONNXRUNTIME_ROOT}/core/framework/endian_utils.cc + ${ONNXRUNTIME_ROOT}/core/framework/endian_utils.h + ) + endif () + onnxruntime_add_static_library(onnx_test_runner_common ${onnx_test_runner_common_srcs}) if(MSVC) target_compile_options(onnx_test_runner_common PRIVATE "$<$:SHELL:--compiler-options /utf-8>" @@ -806,31 +944,44 @@ if(NOT IOS) target_compile_options(onnx_test_runner_common PRIVATE "/wd4244") endif() onnxruntime_add_include_to_target(onnx_test_runner_common onnxruntime_common onnxruntime_framework - onnxruntime_test_utils onnx onnx_proto re2::re2 flatbuffers::flatbuffers Boost::mp11 safeint_interface) + onnxruntime_test_utils onnx onnx_proto re2::re2 flatbuffers::flatbuffers Boost::mp11 safeint_interface Eigen3::Eigen) add_dependencies(onnx_test_runner_common onnx_test_data_proto ${onnxruntime_EXTERNAL_DEPENDENCIES}) - target_include_directories(onnx_test_runner_common PRIVATE ${eigen_INCLUDE_DIRS} - ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT}) + target_include_directories(onnx_test_runner_common PRIVATE ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT}) set_target_properties(onnx_test_runner_common PROPERTIES FOLDER "ONNXRuntimeTest") set(onnx_test_runner_common_lib onnx_test_runner_common) endif() -set(all_tests ${onnxruntime_test_common_src} ${onnxruntime_test_ir_src} ${onnxruntime_test_optimizer_src} - ${onnxruntime_test_framework_src} ${onnxruntime_test_providers_src} ${onnxruntime_test_quantization_src} - ${onnxruntime_test_flatbuffers_src} ${onnxruntime_test_lora_src}) +set(all_tests + ${onnxruntime_test_common_src} + ${onnxruntime_test_ir_src} + ${onnxruntime_test_optimizer_src} + ${onnxruntime_test_framework_src} + ${onnxruntime_test_providers_src} + ${onnxruntime_test_internal_testing_ep_src} + ${onnxruntime_test_quantization_src} + ${onnxruntime_test_flatbuffers_src} + ${onnxruntime_test_lora_src} +) if (onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS) + if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_REDUCED_OPS_BUILD) + set(onnxruntime_test_cuda_kernels_src_patterns "${TEST_SRC_DIR}/contrib_ops/cuda_kernels/*.cc") + endif() + file(GLOB onnxruntime_test_providers_cuda_ut_src CONFIGURE_DEPENDS "${TEST_SRC_DIR}/providers/cuda/test_cases/*" + ${onnxruntime_test_cuda_kernels_src_patterns} ) + # onnxruntime_providers_cuda_ut is only for unittests. onnxruntime_add_shared_library_module(onnxruntime_providers_cuda_ut ${onnxruntime_test_providers_cuda_ut_src} $) config_cuda_provider_shared_module(onnxruntime_providers_cuda_ut) onnxruntime_add_include_to_target(onnxruntime_providers_cuda_ut GTest::gtest GTest::gmock) - add_dependencies(onnxruntime_providers_cuda_ut onnxruntime_test_utils onnxruntime_common) + add_dependencies(onnxruntime_providers_cuda_ut onnxruntime_test_utils) target_include_directories(onnxruntime_providers_cuda_ut PRIVATE ${ONNXRUNTIME_ROOT}/core/mickey) - target_link_libraries(onnxruntime_providers_cuda_ut PRIVATE GTest::gtest GTest::gmock ${ONNXRUNTIME_MLAS_LIBS} onnxruntime_test_utils onnxruntime_common) + target_link_libraries(onnxruntime_providers_cuda_ut PRIVATE GTest::gtest GTest::gmock ${ONNXRUNTIME_MLAS_LIBS} onnxruntime_test_utils) if (MSVC) # Cutlass code has an issue with the following: # warning C4100: 'magic': unreferenced formal parameter @@ -856,9 +1007,6 @@ if (onnxruntime_USE_OPENVINO) list(APPEND all_tests ${onnxruntime_test_openvino_src}) endif() -# this is only added to onnxruntime_test_framework_libs above, but we use onnxruntime_test_providers_libs for the onnxruntime_test_all target. -# for now, add it here. better is probably to have onnxruntime_test_providers_libs use the full onnxruntime_test_framework_libs -# list given it's built on top of that library and needs all the same dependencies. if(WIN32) list(APPEND onnxruntime_test_providers_libs Advapi32) endif() @@ -875,21 +1023,23 @@ if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") "${TEST_SRC_DIR}/providers/memcpy_test.cc" ) endif() - list(REMOVE_ITEM all_tests "${TEST_SRC_DIR}/providers/cpu/reduction/reduction_ops_test.cc" - "${TEST_SRC_DIR}/providers/cpu/tensor/grid_sample_test.cc") + list(REMOVE_ITEM all_tests + "${TEST_SRC_DIR}/providers/cpu/reduction/reduction_ops_test.cc" + "${TEST_SRC_DIR}/providers/cpu/tensor/grid_sample_test.cc" + "${TEST_SRC_DIR}/providers/cpu/tensor/grid_sample_test_custom.cc") endif() if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten" OR IOS) # Because we do not run these model tests in our web or iOS CI build pipelines, and some test code uses C++17 # filesystem functions that are not available in the iOS version we target. - message("Disable model tests in onnxruntime_test_all") + message("Disable model tests") list(REMOVE_ITEM all_tests "${TEST_SRC_DIR}/providers/cpu/model_tests.cc" ) endif() set(test_all_args) -if (onnxruntime_USE_TENSORRT) +if (onnxruntime_USE_TENSORRT OR onnxruntime_USE_NV) # TRT EP CI takes much longer time when updating to TRT 8.2 # So, we only run trt ep and exclude other eps to reduce CI test time. # @@ -901,9 +1051,62 @@ endif () if(NOT onnxruntime_ENABLE_CUDA_EP_INTERNAL_TESTS) list(REMOVE_ITEM all_tests ${TEST_SRC_DIR}/providers/cuda/cuda_provider_test.cc) endif() + +partition_provider_test_srcs(all_tests onnxruntime_provider_test_srcs onnxruntime_test_all_srcs) + +# Workarounds for onnxruntime test targets. +function(onnxruntime_apply_test_target_workarounds target) + if (MSVC) + # TODO: The test code for OpenVINO, QNN, and WebGPU is getting flagged with a warning from ABSL for unreachable code. + # Need to figure out how those particular targets/build variants are failing, but regular windows is not. + target_compile_options(${target} PRIVATE "/wd4702") + endif() + + # TODO fix shorten-64-to-32 warnings + # there are some in builds where sizeof(size_t) != sizeof(int64_t), e.g., in 'ONNX Runtime Web CI Pipeline' + if (HAS_SHORTEN_64_TO_32 AND NOT CMAKE_SIZEOF_VOID_P EQUAL 8) + target_compile_options(${target} PRIVATE -Wno-error=shorten-64-to-32) + endif() +endfunction() + +# Set environment variables for plugin EP tests when run via CTest. +function(onnxruntime_set_plugin_ep_test_environment target) + if(onnxruntime_USE_WEBGPU AND onnxruntime_USE_EP_API_ADAPTERS) + set(ORT_PLUGIN_EP_JSON_CONFIG "{\"ep_library_registration_name\": \"WebGPU_PluginEP\", \"ep_library_path\": \"$\", \"selected_ep_name\": \"WebGpuExecutionProvider\"}") + set_tests_properties(${target} PROPERTIES + ENVIRONMENT "ORT_UNIT_TEST_MAIN_DYNAMIC_PLUGIN_EP_CONFIG_JSON=${ORT_PLUGIN_EP_JSON_CONFIG}" + ) + # TODO: add for other plugin EPs if needed + # elseif() + endif() +endfunction() + +function(onnxruntime_apply_emscripten_test_link_settings target) + if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + set_target_properties(${target} PROPERTIES LINK_DEPENDS ${TEST_SRC_DIR}/wasm/onnxruntime_test_adapter.js) + set_target_properties(${target} PROPERTIES LINK_DEPENDS ${ONNXRUNTIME_ROOT}/wasm/pre.js) + set_target_properties(${target} PROPERTIES LINK_FLAGS "-s STACK_SIZE=5242880 -s INITIAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4294967296 -s INCOMING_MODULE_JS_API=[preRun,locateFile,arguments,onExit,wasmMemory,buffer,instantiateWasm] --pre-js \"${TEST_SRC_DIR}/wasm/onnxruntime_test_adapter.js\" --pre-js \"${ONNXRUNTIME_ROOT}/wasm/pre.js\" -s \"EXPORTED_RUNTIME_METHODS=['FS']\" --preload-file ${CMAKE_CURRENT_BINARY_DIR}/testdata@/testdata -s EXIT_RUNTIME=1") + if (onnxruntime_ENABLE_WEBASSEMBLY_THREADS) + set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " -s DEFAULT_PTHREAD_STACK_SIZE=131072 -s PROXY_TO_PTHREAD=1") + endif() + if (onnxruntime_USE_JSEP) + set_target_properties(${target} PROPERTIES LINK_DEPENDS ${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js) + set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " --pre-js \"${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js\"") + endif() + + ### + ### if you want to investigate or debug a test failure in ${target}, replace the following line. + ### those flags slow down the CI test significantly, so we don't use them by default. + ### + # set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " -s ASSERTIONS=2 -s SAFE_HEAP=1 -s STACK_OVERFLOW_CHECK=2") + set_property(TARGET ${target} APPEND_STRING PROPERTY LINK_FLAGS " -s ASSERTIONS=0 -s SAFE_HEAP=0 -s STACK_OVERFLOW_CHECK=1") + endif() +endfunction() + +list(APPEND onnxruntime_test_all_srcs ${onnxruntime_unittest_main_src}) AddTest( TARGET onnxruntime_test_all - SOURCES ${all_tests} ${onnxruntime_unittest_main_src} + SOURCES ${onnxruntime_test_all_srcs} LIBS ${onnx_test_runner_common_lib} ${onnxruntime_test_providers_libs} ${onnxruntime_test_common_libs} onnx_test_data_proto @@ -912,6 +1115,12 @@ AddTest( ) target_include_directories(onnxruntime_test_all PRIVATE ${ONNXRUNTIME_ROOT}/core/flatbuffers/schema) # ort.fbs.h +onnxruntime_apply_test_target_workarounds(onnxruntime_test_all) + +if (onnxruntime_USE_CUDA AND onnxruntime_BUILD_CUDA_EP_AS_PLUGIN) + target_compile_definitions(onnxruntime_test_all PRIVATE ORT_UNIT_TEST_HAS_CUDA_PLUGIN_EP=1) +endif() + if (MSVC) # The warning means the type of two integral values around a binary operator is narrow than their result. # If we promote the two input values first, it could be more tolerant to integer overflow. @@ -930,18 +1139,6 @@ else() target_compile_options(onnxruntime_test_all PRIVATE "-Wno-parentheses") endif() -# TODO fix shorten-64-to-32 warnings -# there are some in builds where sizeof(size_t) != sizeof(int64_t), e.g., in 'ONNX Runtime Web CI Pipeline' -if (HAS_SHORTEN_64_TO_32 AND NOT CMAKE_SIZEOF_VOID_P EQUAL 8) - target_compile_options(onnxruntime_test_all PRIVATE -Wno-error=shorten-64-to-32) -endif() - -if (UNIX AND onnxruntime_USE_TENSORRT) - # The test_main.cc includes NvInfer.h where it has many deprecated declarations - # simply ignore them for TensorRT EP build - set_property(TARGET onnxruntime_test_all APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-deprecated-declarations") -endif() - if (MSVC AND onnxruntime_ENABLE_STATIC_ANALYSIS) # attention_op_test.cc: Function uses '49152' bytes of stack: exceeds /analyze:stacksize '16384'.. target_compile_options(onnxruntime_test_all PRIVATE "/analyze:stacksize 131072") @@ -968,38 +1165,11 @@ endif() if (onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS) target_compile_definitions(onnxruntime_test_all PRIVATE DEBUG_NODE_INPUTS_OUTPUTS) endif() -if (onnxruntime_USE_ROCM) - if (onnxruntime_USE_COMPOSABLE_KERNEL) - target_compile_definitions(onnxruntime_test_all PRIVATE USE_COMPOSABLE_KERNEL) - if (onnxruntime_USE_COMPOSABLE_KERNEL_CK_TILE) - target_compile_definitions(onnxruntime_test_all PRIVATE USE_COMPOSABLE_KERNEL_CK_TILE) - endif() - endif() - target_compile_options(onnxruntime_test_all PRIVATE -D__HIP_PLATFORM_AMD__=1 -D__HIP_PLATFORM_HCC__=1) - target_include_directories(onnxruntime_test_all PRIVATE ${onnxruntime_ROCM_HOME}/hipfft/include ${onnxruntime_ROCM_HOME}/include ${onnxruntime_ROCM_HOME}/hiprand/include ${onnxruntime_ROCM_HOME}/rocrand/include ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/orttraining) -endif() + if (onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) target_link_libraries(onnxruntime_test_all PRIVATE Python::Python) endif() -if (CMAKE_SYSTEM_NAME STREQUAL "Emscripten") - set_target_properties(onnxruntime_test_all PROPERTIES LINK_DEPENDS ${TEST_SRC_DIR}/wasm/onnxruntime_test_all_adapter.js) - set_target_properties(onnxruntime_test_all PROPERTIES LINK_DEPENDS ${ONNXRUNTIME_ROOT}/wasm/pre.js) - set_target_properties(onnxruntime_test_all PROPERTIES LINK_FLAGS "-s STACK_SIZE=5242880 -s INITIAL_MEMORY=536870912 -s ALLOW_MEMORY_GROWTH=1 -s MAXIMUM_MEMORY=4294967296 -s INCOMING_MODULE_JS_API=[preRun,locateFile,arguments,onExit,wasmMemory,buffer,instantiateWasm] --pre-js \"${TEST_SRC_DIR}/wasm/onnxruntime_test_all_adapter.js\" --pre-js \"${ONNXRUNTIME_ROOT}/wasm/pre.js\" -s \"EXPORTED_RUNTIME_METHODS=['FS']\" --preload-file ${CMAKE_CURRENT_BINARY_DIR}/testdata@/testdata -s EXIT_RUNTIME=1") - if (onnxruntime_ENABLE_WEBASSEMBLY_THREADS) - set_property(TARGET onnxruntime_test_all APPEND_STRING PROPERTY LINK_FLAGS " -s DEFAULT_PTHREAD_STACK_SIZE=131072 -s PROXY_TO_PTHREAD=1") - endif() - if (onnxruntime_USE_JSEP) - set_target_properties(onnxruntime_test_all PROPERTIES LINK_DEPENDS ${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js) - set_property(TARGET onnxruntime_test_all APPEND_STRING PROPERTY LINK_FLAGS " --pre-js \"${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js\"") - endif() - - ### - ### if you want to investigate or debug a test failure in onnxruntime_test_all, replace the following line. - ### those flags slow down the CI test significantly, so we don't use them by default. - ### - # set_property(TARGET onnxruntime_test_all APPEND_STRING PROPERTY LINK_FLAGS " -s ASSERTIONS=2 -s SAFE_HEAP=1 -s STACK_OVERFLOW_CHECK=2") - set_property(TARGET onnxruntime_test_all APPEND_STRING PROPERTY LINK_FLAGS " -s ASSERTIONS=0 -s SAFE_HEAP=0 -s STACK_OVERFLOW_CHECK=1") -endif() +onnxruntime_apply_emscripten_test_link_settings(onnxruntime_test_all) if (onnxruntime_ENABLE_ATEN) target_compile_definitions(onnxruntime_test_all PRIVATE ENABLE_ATEN) @@ -1011,7 +1181,12 @@ onnxruntime_add_static_library(onnx_test_data_proto ${TEST_SRC_DIR}/proto/tml.pr add_dependencies(onnx_test_data_proto onnx_proto ${onnxruntime_EXTERNAL_DEPENDENCIES}) #onnx_proto target should mark this definition as public, instead of private target_compile_definitions(onnx_test_data_proto PRIVATE "-DONNX_API=") -onnxruntime_add_include_to_target(onnx_test_data_proto onnx_proto) +onnxruntime_add_include_to_target(onnx_test_data_proto onnx_proto ${PROTOBUF_LIB}) +if (MSVC) + # Cutlass code has an issue with the following: + # warning C4100: 'magic': unreferenced formal parameter + target_compile_options(onnx_test_data_proto PRIVATE "/wd4100") +endif() target_include_directories(onnx_test_data_proto PRIVATE ${CMAKE_CURRENT_BINARY_DIR}) set_target_properties(onnx_test_data_proto PROPERTIES FOLDER "ONNXRuntimeTest") if(NOT DEFINED onnx_SOURCE_DIR) @@ -1050,21 +1225,6 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) ) endif() - if (onnxruntime_USE_QNN) - if (MSVC OR ${CMAKE_SYSTEM_NAME} STREQUAL "Linux") - add_custom_command( - TARGET ${test_data_target} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy ${QNN_LIB_FILES} $ - ) - endif() - if (EXISTS "${onnxruntime_QNN_HOME}/Qualcomm AI Hub Proprietary License.pdf") - add_custom_command( - TARGET ${test_data_target} POST_BUILD - COMMAND ${CMAKE_COMMAND} -E copy "${onnxruntime_QNN_HOME}/Qualcomm AI Hub Proprietary License.pdf" $ - ) - endif() - endif() - if (onnxruntime_USE_DNNL) if(onnxruntime_DNNL_GPU_RUNTIME STREQUAL "ocl" AND onnxruntime_DNNL_OPENCL_ROOT STREQUAL "") message(FATAL_ERROR "--dnnl_opencl_root required") @@ -1092,6 +1252,75 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) endif() endif() +# onnxruntime_provider_test +# Execution provider-related tests. +# These also have some support for dynamically specified plugin EPs. +if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_REDUCED_OPS_BUILD) +block() + set(supporting_test_srcs + ${TEST_SRC_DIR}/common/cuda_op_test_utils.cc + ${TEST_SRC_DIR}/common/cuda_op_test_utils.h + ${TEST_SRC_DIR}/common/tensor_op_test_utils.cc + ${TEST_SRC_DIR}/common/tensor_op_test_utils.h + ) + + if (onnxruntime_USE_DNNL) + list(APPEND supporting_test_srcs + ${TEST_SRC_DIR}/common/dnnl_op_test_utils.cc + ${TEST_SRC_DIR}/common/dnnl_op_test_utils.h + ) + endif() + + list(APPEND onnxruntime_provider_test_srcs + ${supporting_test_srcs} + ${onnxruntime_unittest_main_src} + ) + + set(onnxruntime_provider_test_libs + ${onnx_test_runner_common_lib} + ${onnxruntime_test_providers_libs} + ${onnxruntime_test_common_libs} + onnx_test_data_proto + ) + + set(onnxruntime_provider_test_deps ${onnxruntime_test_providers_dependencies}) + + AddTest( + TARGET onnxruntime_provider_test + SOURCES ${onnxruntime_provider_test_srcs} + LIBS ${onnxruntime_provider_test_libs} + DEPENDS ${onnxruntime_provider_test_deps} + ) + + onnxruntime_apply_test_target_workarounds(onnxruntime_provider_test) + onnxruntime_set_plugin_ep_test_environment(onnxruntime_provider_test) + + if (onnxruntime_USE_CUDA AND onnxruntime_BUILD_CUDA_EP_AS_PLUGIN) + target_compile_definitions(onnxruntime_provider_test PRIVATE ORT_UNIT_TEST_HAS_CUDA_PLUGIN_EP=1) + endif() + + # Expose QNN SDK headers to unit tests via an interface target + if(onnxruntime_USE_QNN) + add_library(qnn_sdk_headers_include INTERFACE) + target_include_directories(qnn_sdk_headers_include INTERFACE + ${onnxruntime_QNN_HOME}/include + ${onnxruntime_QNN_HOME}/include/QNN) + target_link_libraries(onnxruntime_provider_test PRIVATE qnn_sdk_headers_include) + endif() + + # enable dynamic plugin EP usage + target_compile_definitions(onnxruntime_provider_test PRIVATE ORT_UNIT_TEST_ENABLE_DYNAMIC_PLUGIN_EP_USAGE) + onnxruntime_apply_emscripten_test_link_settings(onnxruntime_provider_test) + + if (IOS) + add_custom_command( + TARGET onnxruntime_provider_test POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_directory + ${TEST_DATA_SRC} + $/testdata) + endif() +endblock() +endif() set(onnx_test_libs onnxruntime_test_utils @@ -1115,9 +1344,7 @@ if (NOT IOS) target_link_libraries(onnx_test_runner PRIVATE onnx_test_runner_common ${GETOPT_LIB_WIDE} ${onnx_test_libs} nlohmann_json::nlohmann_json) target_include_directories(onnx_test_runner PRIVATE ${ONNXRUNTIME_ROOT}) - if (onnxruntime_USE_ROCM) - target_include_directories(onnx_test_runner PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/orttraining) - endif() + if (onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) target_link_libraries(onnx_test_runner PRIVATE Python::Python) endif() @@ -1150,6 +1377,7 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) ${BENCHMARK_DIR}/layer_normalization.cc) target_include_directories(onnxruntime_benchmark PRIVATE ${ONNXRUNTIME_ROOT} ${onnxruntime_graph_header} ${ONNXRUNTIME_ROOT}/core/mlas/inc) target_compile_definitions(onnxruntime_benchmark PRIVATE BENCHMARK_STATIC_DEFINE) + target_compile_definitions(onnxruntime_benchmark PRIVATE ${mlas_private_compile_definitions}) if(WIN32) target_compile_options(onnxruntime_benchmark PRIVATE "$<$:SHELL:--compiler-options /wd4141>" "$<$>:/wd4141>") @@ -1173,10 +1401,12 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) SET(MLAS_BENCH_DIR ${TEST_SRC_DIR}/mlas/bench) file(GLOB_RECURSE MLAS_BENCH_SOURCE_FILES "${MLAS_BENCH_DIR}/*.cpp" "${MLAS_BENCH_DIR}/*.h") - onnxruntime_add_executable(onnxruntime_mlas_benchmark ${MLAS_BENCH_SOURCE_FILES}) + list(FILTER MLAS_BENCH_SOURCE_FILES EXCLUDE REGEX "${MLAS_BENCH_DIR}/riscv64/.*") + onnxruntime_add_executable(onnxruntime_mlas_benchmark ${MLAS_BENCH_SOURCE_FILES} ${ONNXRUNTIME_ROOT}/core/framework/error_code.cc) target_include_directories(onnxruntime_mlas_benchmark PRIVATE ${ONNXRUNTIME_ROOT}/core/mlas/inc) - target_link_libraries(onnxruntime_mlas_benchmark PRIVATE benchmark::benchmark onnxruntime_util onnxruntime_framework ${ONNXRUNTIME_MLAS_LIBS} onnxruntime_common ${CMAKE_DL_LIBS}) + target_link_libraries(onnxruntime_mlas_benchmark PRIVATE benchmark::benchmark onnxruntime_util ${ONNXRUNTIME_MLAS_LIBS} onnxruntime_common ${CMAKE_DL_LIBS}) target_compile_definitions(onnxruntime_mlas_benchmark PRIVATE BENCHMARK_STATIC_DEFINE) + target_compile_definitions(onnxruntime_mlas_benchmark PRIVATE ${mlas_private_compile_definitions}) if(WIN32) target_link_libraries(onnxruntime_mlas_benchmark PRIVATE debug Dbghelp) # Avoid using new and delete. But this is a benchmark program, it's ok if it has a chance to leak. @@ -1190,6 +1420,33 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) target_link_libraries(onnxruntime_mlas_benchmark PRIVATE cpuinfo) endif() set_target_properties(onnxruntime_mlas_benchmark PROPERTIES FOLDER "ONNXRuntimeTest") + + endif() + + if(CMAKE_SYSTEM_PROCESSOR MATCHES "^riscv64.*") + set(MLAS_RISCV64_BENCH_DIR ${TEST_SRC_DIR}/mlas/bench/riscv64) + + onnxruntime_add_executable( + onnxruntime_mlas_sgemm_riscv_bench + ${MLAS_RISCV64_BENCH_DIR}/sgemm_riscv_bench.cpp) + target_include_directories(onnxruntime_mlas_sgemm_riscv_bench PRIVATE ${ONNXRUNTIME_ROOT}/core/mlas/inc) + target_link_libraries( + onnxruntime_mlas_sgemm_riscv_bench + PRIVATE ${ONNXRUNTIME_MLAS_LIBS} onnxruntime_common ${CMAKE_DL_LIBS}) + target_compile_definitions(onnxruntime_mlas_sgemm_riscv_bench PRIVATE ${mlas_private_compile_definitions}) + set_target_properties(onnxruntime_mlas_sgemm_riscv_bench PROPERTIES FOLDER "ONNXRuntimeTest") + + onnxruntime_add_executable( + onnxruntime_mlas_softmax_riscv_compare + ${MLAS_RISCV64_BENCH_DIR}/softmax_rvv_compare.cpp) + target_include_directories( + onnxruntime_mlas_softmax_riscv_compare + PRIVATE ${ONNXRUNTIME_ROOT} ${ONNXRUNTIME_ROOT}/core/mlas/inc) + target_link_libraries( + onnxruntime_mlas_softmax_riscv_compare + PRIVATE ${ONNXRUNTIME_MLAS_LIBS} onnxruntime_common ${CMAKE_DL_LIBS}) + target_compile_definitions(onnxruntime_mlas_softmax_riscv_compare PRIVATE ${mlas_private_compile_definitions}) + set_target_properties(onnxruntime_mlas_softmax_riscv_compare PROPERTIES FOLDER "ONNXRuntimeTest") endif() if(WIN32) @@ -1231,16 +1488,20 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) ${onnxruntime_perf_test_src_patterns} ) onnxruntime_add_executable(onnxruntime_perf_test ${onnxruntime_perf_test_src} ${ONNXRUNTIME_ROOT}/core/platform/path_lib.cc) + + # ABSL_FLAGS_STRIP_NAMES is set to 1 by default to disable flag registration when building for Android, iPhone, and "embedded devices". + # See the issue: https://github.com/abseil/abseil-cpp/issues/1875 + # We set it to 0 for all builds to be able to use ABSL flags for onnxruntime_perf_test. + target_compile_definitions(onnxruntime_perf_test PRIVATE ABSL_FLAGS_STRIP_NAMES=0) + if(MSVC) target_compile_options(onnxruntime_perf_test PRIVATE "$<$:SHELL:--compiler-options /utf-8>" "$<$>:/utf-8>") endif() target_include_directories(onnxruntime_perf_test PRIVATE ${onnx_test_runner_src_dir} ${ONNXRUNTIME_ROOT} - ${eigen_INCLUDE_DIRS} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} + ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} ${CMAKE_CURRENT_BINARY_DIR}) - if (onnxruntime_USE_ROCM) - target_include_directories(onnxruntime_perf_test PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/orttraining) - endif() + if (WIN32) target_compile_options(onnxruntime_perf_test PRIVATE ${disabled_warnings}) if (NOT DEFINED SYS_PATH_LIB) @@ -1255,7 +1516,7 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) onnx_test_runner_common onnxruntime_test_utils onnxruntime_common onnxruntime onnxruntime_flatbuffers onnx_test_data_proto ${onnxruntime_EXTERNAL_LIBRARIES} - ${GETOPT_LIB_WIDE} ${SYS_PATH_LIB} ${CMAKE_DL_LIBS}) + absl::flags absl::flags_parse ${SYS_PATH_LIB} ${CMAKE_DL_LIBS}) if(NOT WIN32) if(onnxruntime_USE_SNPE) list(APPEND onnxruntime_perf_test_libs onnxruntime_providers_snpe) @@ -1264,60 +1525,132 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) if (CMAKE_SYSTEM_NAME STREQUAL "Android") list(APPEND onnxruntime_perf_test_libs ${android_shared_libs}) endif() - if (${CMAKE_SYSTEM_NAME} MATCHES "AIX") + if (CMAKE_SYSTEM_NAME MATCHES "AIX") list(APPEND onnxruntime_perf_test_libs onnxruntime_graph onnxruntime_session onnxruntime_providers onnxruntime_framework onnxruntime_util onnxruntime_mlas onnxruntime_optimizer onnxruntime_flatbuffers iconv re2 gtest absl_failure_signal_handler absl_examine_stack absl_flags_parse absl_flags_usage absl_flags_usage_internal) - endif() + endif() target_link_libraries(onnxruntime_perf_test PRIVATE ${onnxruntime_perf_test_libs} Threads::Threads) + if (onnxruntime_USE_CUDA OR onnxruntime_USE_NV OR onnxruntime_USE_TENSORRT) + target_link_libraries(onnxruntime_perf_test PRIVATE CUDA::cudart) + endif() if(WIN32) target_link_libraries(onnxruntime_perf_test PRIVATE debug dbghelp advapi32) endif() else() - target_link_libraries(onnxruntime_perf_test PRIVATE onnx_test_runner_common ${GETOPT_LIB_WIDE} ${onnx_test_libs}) + target_link_libraries(onnxruntime_perf_test PRIVATE onnx_test_runner_common absl::flags absl::flags_parse ${onnx_test_libs}) + # When onnxruntime_BUILD_SHARED_LIB is OFF (the plugin build path), perf test was missing CUDA include directories and CUDA::cudart linkage. + if (onnxruntime_USE_CUDA OR onnxruntime_USE_NV OR onnxruntime_USE_TENSORRT) + target_include_directories(onnxruntime_perf_test PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) + target_link_libraries(onnxruntime_perf_test PRIVATE CUDA::cudart) + endif() endif() set_target_properties(onnxruntime_perf_test PROPERTIES FOLDER "ONNXRuntimeTest") - endif() +endif() if(onnxruntime_USE_QNN) #qnn ctx generator - set(onnxruntime_qnn_ctx_gen_src_dir ${TEST_SRC_DIR}/qnn_ctx_gen) - set(onnxruntime_qnn_ctx_gen_src_patterns - "${onnxruntime_qnn_ctx_gen_src_dir}/*.cc" - "${onnxruntime_qnn_ctx_gen_src_dir}/*.h") + set(ep_weight_sharing_ctx_gen_src_dir ${TEST_SRC_DIR}/ep_weight_sharing_ctx_gen) + set(ep_weight_sharing_ctx_gen_src_patterns + "${ep_weight_sharing_ctx_gen_src_dir}/*.cc" + "${ep_weight_sharing_ctx_gen_src_dir}/*.h") - file(GLOB onnxruntime_qnn_ctx_gen_src CONFIGURE_DEPENDS - ${onnxruntime_qnn_ctx_gen_src_patterns} + file(GLOB ep_weight_sharing_ctx_gen_src CONFIGURE_DEPENDS + ${ep_weight_sharing_ctx_gen_src_patterns} ) - onnxruntime_add_executable(onnxruntime_qnn_ctx_gen ${onnxruntime_qnn_ctx_gen_src}) - target_include_directories(onnxruntime_qnn_ctx_gen PRIVATE ${onnx_test_runner_src_dir} ${ONNXRUNTIME_ROOT} - ${eigen_INCLUDE_DIRS} ${onnxruntime_graph_header} ${onnxruntime_exec_src_dir} - ${CMAKE_CURRENT_BINARY_DIR}) + onnxruntime_add_executable(ep_weight_sharing_ctx_gen ${ep_weight_sharing_ctx_gen_src}) + target_include_directories(ep_weight_sharing_ctx_gen PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR}) if (WIN32) - target_compile_options(onnxruntime_qnn_ctx_gen PRIVATE ${disabled_warnings}) + target_compile_options(ep_weight_sharing_ctx_gen PRIVATE ${disabled_warnings}) if (NOT DEFINED SYS_PATH_LIB) set(SYS_PATH_LIB shlwapi) endif() endif() - if(WIN32) - target_link_libraries(onnxruntime_qnn_ctx_gen PRIVATE debug dbghelp advapi32) + if (onnxruntime_BUILD_SHARED_LIB) + set(ep_weight_sharing_ctx_gen_libs onnxruntime_common onnxruntime ${onnxruntime_EXTERNAL_LIBRARIES} ${GETOPT_LIB_WIDE}) + target_link_libraries(ep_weight_sharing_ctx_gen PRIVATE ${ep_weight_sharing_ctx_gen_libs}) + if (WIN32) + target_link_libraries(ep_weight_sharing_ctx_gen PRIVATE debug dbghelp advapi32) + endif() + else() + target_link_libraries(ep_weight_sharing_ctx_gen PRIVATE onnxruntime_session ${onnxruntime_test_providers_libs} ${onnxruntime_EXTERNAL_LIBRARIES} ${GETOPT_LIB_WIDE}) endif() - target_link_libraries(onnxruntime_qnn_ctx_gen PRIVATE onnx_test_runner_common onnxruntime_test_utils onnxruntime_common onnxruntime_graph onnxruntime_session onnxruntime_providers onnxruntime_framework onnxruntime_util onnxruntime_mlas onnxruntime_optimizer onnxruntime_flatbuffers onnx_test_data_proto ${onnxruntime_test_providers_libs} ${onnxruntime_EXTERNAL_LIBRARIES} ${GETOPT_LIB_WIDE} ${SYS_PATH_LIB} ${CMAKE_DL_LIBS}) - set_target_properties(onnxruntime_qnn_ctx_gen PROPERTIES FOLDER "ONNXRuntimeTest") + set_target_properties(ep_weight_sharing_ctx_gen PROPERTIES FOLDER "ONNXRuntimeTest") endif() # shared lib if (onnxruntime_BUILD_SHARED_LIB) + if(WIN32) + onnxruntime_add_executable(onnxruntime_shared_lib_dlopen_test ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/dlopen_main.cc) + add_dependencies(onnxruntime_shared_lib_dlopen_test ${all_dependencies} onnxruntime) + add_test(NAME onnxruntime_shared_lib_dlopen_test COMMAND onnxruntime_shared_lib_dlopen_test WORKING_DIRECTORY $) + set_target_properties(onnxruntime_shared_lib_dlopen_test PROPERTIES FOLDER "ONNXRuntimeTest") + + if (MSVC) + # set VS debugger working directory to the test program's directory + set_target_properties(onnxruntime_shared_lib_dlopen_test PROPERTIES VS_DEBUGGER_WORKING_DIRECTORY $) + endif() + endif() onnxruntime_add_static_library(onnxruntime_mocked_allocator ${TEST_SRC_DIR}/util/test_allocator.cc) target_include_directories(onnxruntime_mocked_allocator PUBLIC ${TEST_SRC_DIR}/util/include) target_link_libraries(onnxruntime_mocked_allocator PRIVATE ${GSL_TARGET}) set_target_properties(onnxruntime_mocked_allocator PROPERTIES FOLDER "ONNXRuntimeTest") + # onnxruntime_runtime_path_test_shared_library + block() + set(onnxruntime_runtime_path_test_shared_library_src + "${TEST_SRC_DIR}/shared_lib/runtime_path_test_shared_library/runtime_path_test_shared_library.h" + "${TEST_SRC_DIR}/shared_lib/runtime_path_test_shared_library/runtime_path_test_shared_library.cc") + + onnxruntime_add_shared_library(onnxruntime_runtime_path_test_shared_library + ${onnxruntime_runtime_path_test_shared_library_src}) + + if (CMAKE_SYSTEM_NAME MATCHES "AIX") + target_link_libraries(onnxruntime_runtime_path_test_shared_library PRIVATE + onnxruntime_common ${CMAKE_DL_LIBS}) + set_target_properties(onnxruntime_runtime_path_test_shared_library PROPERTIES AIX_SHARED_LIBRARY_ARCHIVE OFF) + else() + if (CPUINFO_SUPPORTED) + target_link_libraries(onnxruntime_runtime_path_test_shared_library PRIVATE + onnxruntime_common cpuinfo ${CMAKE_DL_LIBS}) + else() + target_link_libraries(onnxruntime_runtime_path_test_shared_library PRIVATE + onnxruntime_common ${CMAKE_DL_LIBS}) + endif() + endif() + target_include_directories(onnxruntime_runtime_path_test_shared_library PRIVATE ${ONNXRUNTIME_ROOT}) + + if(UNIX) + if (APPLE) + set(onnxruntime_runtime_path_test_shared_library_link_flags "-Xlinker -dead_strip") + elseif (NOT CMAKE_SYSTEM_NAME MATCHES "AIX") + string(CONCAT onnxruntime_runtime_path_test_shared_library_link_flags + "-Xlinker --version-script=${TEST_SRC_DIR}/shared_lib/runtime_path_test_shared_library/runtime_path_test_shared_library.lds " + "-Xlinker --no-undefined -Xlinker --gc-sections -z noexecstack") + endif() + else() + set(onnxruntime_runtime_path_test_shared_library_link_flags + "-DEF:${TEST_SRC_DIR}/shared_lib/runtime_path_test_shared_library/runtime_path_test_shared_library.def") + endif() + + set_property(TARGET onnxruntime_runtime_path_test_shared_library APPEND_STRING PROPERTY LINK_FLAGS + ${onnxruntime_runtime_path_test_shared_library_link_flags}) + + set_target_properties(onnxruntime_runtime_path_test_shared_library PROPERTIES FOLDER "ONNXRuntimeTest") + source_group(TREE ${TEST_SRC_DIR} FILES ${onnxruntime_runtime_path_test_shared_library_src}) + endblock() + ################################################################# # test inference using shared lib - set(onnxruntime_shared_lib_test_LIBS onnxruntime_mocked_allocator onnxruntime_test_utils onnxruntime_common onnx_proto) + set(onnxruntime_shared_lib_test_LIBS + onnxruntime_mocked_allocator + onnxruntime_test_utils + onnxruntime_common + onnx_proto + onnxruntime_runtime_path_test_shared_library) + if(NOT WIN32) if(onnxruntime_USE_SNPE) list(APPEND onnxruntime_shared_lib_test_LIBS onnxruntime_providers_snpe) @@ -1329,12 +1662,13 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) if (onnxruntime_USE_CUDA) list(APPEND onnxruntime_shared_lib_test_LIBS CUDA::cudart) endif() - if (onnxruntime_USE_ROCM) - list(APPEND onnxruntime_shared_lib_test_LIBS hip::host) - endif() + if (onnxruntime_USE_TENSORRT) list(APPEND onnxruntime_shared_lib_test_LIBS ${TENSORRT_LIBRARY_INFER}) endif() + if (onnxruntime_USE_NV) + list(APPEND onnxruntime_shared_lib_test_LIBS ${TENSORRT_LIBRARY_INFER} CUDA::cudart) + endif() if (onnxruntime_USE_DML) list(APPEND onnxruntime_shared_lib_test_LIBS d3d12.lib) endif() @@ -1342,7 +1676,7 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) list(APPEND onnxruntime_shared_lib_test_LIBS ${android_shared_libs}) endif() - if (${CMAKE_SYSTEM_NAME} MATCHES "AIX") + if (CMAKE_SYSTEM_NAME MATCHES "AIX") list(APPEND onnxruntime_shared_lib_test_LIBS onnxruntime_graph onnxruntime_session onnxruntime_providers onnxruntime_framework onnxruntime_util onnxruntime_mlas onnxruntime_optimizer onnxruntime_flatbuffers iconv re2 onnx) endif() @@ -1352,14 +1686,18 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) LIBS ${onnxruntime_shared_lib_test_LIBS} DEPENDS ${all_dependencies} ) + + target_include_directories(onnxruntime_shared_lib_test PRIVATE ${ONNXRUNTIME_ROOT}) + if (onnxruntime_USE_CUDA) - target_include_directories(onnxruntime_shared_lib_test PRIVATE ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES}) + target_include_directories(onnxruntime_shared_lib_test PRIVATE ${CUDAToolkit_INCLUDE_DIRS}) target_sources(onnxruntime_shared_lib_test PRIVATE ${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/cuda_ops.cu) endif() - if (onnxruntime_USE_ROCM) - target_include_directories(onnxruntime_shared_lib_test PRIVATE ${onnxruntime_ROCM_HOME}/include) - target_compile_definitions(onnxruntime_shared_lib_test PRIVATE __HIP_PLATFORM_AMD__) + if (onnxruntime_USE_NV) + target_include_directories(onnxruntime_shared_lib_test PRIVATE ${CUDAToolkit_INCLUDE_DIRS}) endif() + + if (CMAKE_SYSTEM_NAME STREQUAL "Android") target_sources(onnxruntime_shared_lib_test PRIVATE "${ONNXRUNTIME_ROOT}/core/platform/android/cxa_demangle.cc" @@ -1368,6 +1706,10 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) target_compile_definitions(onnxruntime_shared_lib_test PRIVATE USE_DUMMY_EXA_DEMANGLE=1) endif() + if (CMAKE_SYSTEM_NAME MATCHES "AIX" AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") + set_target_properties(onnxruntime_shared_lib_test PROPERTIES ENABLE_EXPORTS 1) + endif() + if (IOS) add_custom_command( TARGET onnxruntime_shared_lib_test POST_BUILD @@ -1376,12 +1718,6 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) $/testdata) endif() - if (UNIX AND onnxruntime_USE_TENSORRT) - # The test_main.cc includes NvInfer.h where it has many deprecated declarations - # simply ignore them for TensorRT EP build - set_property(TARGET onnxruntime_shared_lib_test APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-deprecated-declarations") - endif() - # test inference using global threadpools if (NOT CMAKE_SYSTEM_NAME MATCHES "Android|iOS" AND NOT onnxruntime_MINIMAL_BUILD) AddTest(DYN @@ -1400,26 +1736,12 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) TARGET onnxruntime_test_debug_node_inputs_outputs SOURCES "${TEST_SRC_DIR}/debug_node_inputs_outputs/debug_node_inputs_outputs_utils_test.cc" - "${TEST_SRC_DIR}/framework/TestAllocatorManager.cc" - "${TEST_SRC_DIR}/framework/test_utils.cc" - "${TEST_SRC_DIR}/providers/base_tester.h" - "${TEST_SRC_DIR}/providers/base_tester.cc" - "${TEST_SRC_DIR}/providers/checkers.h" - "${TEST_SRC_DIR}/providers/checkers.cc" - "${TEST_SRC_DIR}/providers/op_tester.h" - "${TEST_SRC_DIR}/providers/op_tester.cc" "${TEST_SRC_DIR}/providers/provider_test_utils.h" - "${TEST_SRC_DIR}/providers/tester_types.h" ${onnxruntime_unittest_main_src} LIBS ${onnxruntime_test_providers_libs} ${onnxruntime_test_common_libs} DEPENDS ${all_dependencies} ) - if (onnxruntime_USE_ROCM) - target_include_directories(onnxruntime_test_debug_node_inputs_outputs PRIVATE ${onnxruntime_ROCM_HOME}/hipfft/include ${onnxruntime_ROCM_HOME}/include ${onnxruntime_ROCM_HOME}/hipcub/include ${onnxruntime_ROCM_HOME}/hiprand/include ${onnxruntime_ROCM_HOME}/rocrand/include) - target_include_directories(onnxruntime_test_debug_node_inputs_outputs PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR}/amdgpu/onnxruntime) - endif(onnxruntime_USE_ROCM) - target_compile_definitions(onnxruntime_test_debug_node_inputs_outputs PRIVATE DEBUG_NODE_INPUTS_OUTPUTS) endif(onnxruntime_DEBUG_NODE_INPUTS_OUTPUTS) @@ -1454,12 +1776,15 @@ if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) "$<$>:/wd6326>") target_compile_options(onnxruntime_mlas_test PRIVATE "$<$:SHELL:--compiler-options /wd26426>" "$<$>:/wd26426>") + target_compile_options(onnxruntime_mlas_test PRIVATE "$<$:SHELL:--compiler-options /bigobj>" + "$<$>:/bigobj>") endif() if(IOS) set_target_properties(onnxruntime_mlas_test PROPERTIES XCODE_ATTRIBUTE_CODE_SIGNING_ALLOWED "NO" ) endif() + target_compile_definitions(onnxruntime_mlas_test PRIVATE ${mlas_private_compile_definitions}) target_include_directories(onnxruntime_mlas_test PRIVATE ${ONNXRUNTIME_ROOT}/core/mlas/inc ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR}) target_link_libraries(onnxruntime_mlas_test PRIVATE GTest::gtest GTest::gmock ${ONNXRUNTIME_MLAS_LIBS} onnxruntime_common) @@ -1512,7 +1837,6 @@ endif() ${CMAKE_CURRENT_BINARY_DIR} ${ONNXRUNTIME_ROOT} ${ORTTRAINING_ROOT} - ${eigen_INCLUDE_DIRS} ${CXXOPTS} ${extra_includes} ${onnxruntime_graph_header} @@ -1543,7 +1867,7 @@ endif() endif() endif() -if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") +if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND NOT onnxruntime_CUDA_MINIMAL) set(custom_op_src_patterns "${TEST_SRC_DIR}/testdata/custom_op_library/*.h" @@ -1559,18 +1883,14 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") list(APPEND custom_op_src_patterns "${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/cuda_ops.cu" "${TEST_SRC_DIR}/testdata/custom_op_library/cuda/cuda_ops.*") - list(APPEND custom_op_lib_include ${CMAKE_CUDA_TOOLKIT_INCLUDE_DIRECTORIES} ${CUDNN_INCLUDE_DIR}) + list(APPEND custom_op_lib_include ${CUDAToolkit_INCLUDE_DIRS}) + if(NOT onnxruntime_CUDA_MINIMAL) + list(APPEND custom_op_lib_include ${CUDNN_INCLUDE_DIR}) + endif() if (HAS_QSPECTRE) list(APPEND custom_op_lib_option "$<$:SHELL:--compiler-options /Qspectre>") endif() - endif() - - if (onnxruntime_USE_ROCM) - list(APPEND custom_op_src_patterns - "${ONNXRUNTIME_SHARED_LIB_TEST_SRC_DIR}/rocm_ops.hip" - "${TEST_SRC_DIR}/testdata/custom_op_library/rocm/rocm_ops.*") - list(APPEND custom_op_lib_include ${onnxruntime_ROCM_HOME}/include) - list(APPEND custom_op_lib_option "-D__HIP_PLATFORM_AMD__=1 -D__HIP_PLATFORM_HCC__=1") + set(custom_op_lib_link ${custom_op_lib_link} CUDA::cudart) endif() file(GLOB custom_op_src ${custom_op_src_patterns}) @@ -1582,7 +1902,7 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") if(UNIX) if (APPLE) set(ONNXRUNTIME_CUSTOM_OP_LIB_LINK_FLAG "-Xlinker -dead_strip") - elseif(NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + elseif(NOT CMAKE_SYSTEM_NAME MATCHES "AIX") set(ONNXRUNTIME_CUSTOM_OP_LIB_LINK_FLAG "-Xlinker --version-script=${TEST_SRC_DIR}/testdata/custom_op_library/custom_op_library.lds -Xlinker --no-undefined -Xlinker --gc-sections -z noexecstack") endif() else() @@ -1593,6 +1913,12 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") endif() endif() set_property(TARGET custom_op_library APPEND_STRING PROPERTY LINK_FLAGS ${ONNXRUNTIME_CUSTOM_OP_LIB_LINK_FLAG}) + #ON AIX, to call dlopen on custom_op_library, we need to generate this library as shared object .so file. + #Latest cmake behavior is changed and cmake will remove shared object .so file after generating the shared archive. + #To prevent that, making AIX_SHARED_LIBRARY_ARCHIVE as OFF for custom_op_library. + if (CMAKE_SYSTEM_NAME MATCHES "AIX") + set_target_properties(custom_op_library PROPERTIES AIX_SHARED_LIBRARY_ARCHIVE OFF) + endif() if (NOT onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) if (onnxruntime_BUILD_JAVA AND NOT onnxruntime_ENABLE_STATIC_ANALYSIS) @@ -1617,6 +1943,10 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") add_custom_command(TARGET onnxruntime_providers_qnn POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy ${QNN_LIB_FILES} ${JAVA_NATIVE_TEST_DIR}) endif() + if (WIN32) + set(EXAMPLE_PLUGIN_EP_DST_FILE_NAME $,$,$>) + add_custom_command(TARGET custom_op_library POST_BUILD COMMAND ${CMAKE_COMMAND} -E copy_if_different $ ${JAVA_NATIVE_TEST_DIR}/${EXAMPLE_PLUGIN_EP_DST_FILE_NAME}) + endif() # delegate to gradle's test runner @@ -1660,7 +1990,10 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") if (onnxruntime_USE_TENSORRT) list(APPEND onnxruntime_customopregistration_test_LIBS ${TENSORRT_LIBRARY_INFER}) endif() - if (${CMAKE_SYSTEM_NAME} MATCHES "AIX") + if (onnxruntime_USE_NV) + list(APPEND onnxruntime_customopregistration_test_LIBS ${TENSORRT_LIBRARY_INFER}) + endif() + if (CMAKE_SYSTEM_NAME MATCHES "AIX") list(APPEND onnxruntime_customopregistration_test_LIBS onnxruntime_graph onnxruntime_session onnxruntime_providers onnxruntime_lora onnxruntime_framework onnxruntime_util onnxruntime_mlas onnxruntime_optimizer onnxruntime_flatbuffers iconv re2 ${PROTOBUF_LIB} onnx onnx_proto) endif() AddTest(DYN @@ -1678,12 +2011,6 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten") $/testdata) endif() - if (UNIX AND onnxruntime_USE_TENSORRT) - # The test_main.cc includes NvInfer.h where it has many deprecated declarations - # simply ignore them for TensorRT EP build - set_property(TARGET onnxruntime_customopregistration_test APPEND_STRING PROPERTY COMPILE_FLAGS "-Wno-deprecated-declarations") - endif() - endif() endif() @@ -1697,7 +2024,7 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND (NOT onnxruntime_MINIMAL_BUI if(UNIX) if (APPLE) set(ONNXRUNTIME_CUSTOM_OP_INVALID_LIB_LINK_FLAG "-Xlinker -dead_strip") - elseif (NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + elseif (NOT CMAKE_SYSTEM_NAME MATCHES "AIX") string(CONCAT ONNXRUNTIME_CUSTOM_OP_INVALID_LIB_LINK_FLAG "-Xlinker --version-script=${TEST_SRC_DIR}/testdata/custom_op_invalid_library/custom_op_library.lds " "-Xlinker --no-undefined -Xlinker --gc-sections -z noexecstack") @@ -1728,7 +2055,7 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND (NOT onnxruntime_MINIMAL_BUI if(UNIX) if (APPLE) set(ONNXRUNTIME_CUSTOM_OP_GET_CONST_INPUT_TEST_LIB_LINK_FLAG "-Xlinker -dead_strip") - elseif(NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + elseif(NOT CMAKE_SYSTEM_NAME MATCHES "AIX") string(CONCAT ONNXRUNTIME_CUSTOM_OP_GET_CONST_INPUT_TEST_LIB_LINK_FLAG "-Xlinker --version-script=${TEST_SRC_DIR}/testdata/custom_op_get_const_input_test_library/custom_op_lib.lds " "-Xlinker --no-undefined -Xlinker --gc-sections -z noexecstack") @@ -1760,7 +2087,7 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND (NOT onnxruntime_MINIMAL_BUI if(UNIX) if (APPLE) set(ONNXRUNTIME_CUSTOM_OP_lOCAL_FUNCTION_TEST_LIB_LINK_FLAG "-Xlinker -dead_strip") - elseif(NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") + elseif(NOT CMAKE_SYSTEM_NAME MATCHES "AIX") string(CONCAT ONNXRUNTIME_CUSTOM_OP_lOCAL_FUNCTION_TEST_LIB_LINK_FLAG "-Xlinker --version-script=${TEST_SRC_DIR}/testdata/custom_op_local_function/custom_op_local_function.lds " "-Xlinker --no-undefined -Xlinker --gc-sections -z noexecstack") @@ -1774,12 +2101,172 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND (NOT onnxruntime_MINIMAL_BUI ${ONNXRUNTIME_CUSTOM_OP_lOCAL_FUNCTION_TEST_LIB_LINK_FLAG}) endif() +# Build library that can be used with RegisterExecutionProviderLibrary and automatic EP selection +# We need a shared lib build to use that as a dependency for the test library +if (onnxruntime_BUILD_SHARED_LIB AND + NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND + NOT onnxruntime_MINIMAL_BUILD) + + # + # example_plugin_ep + # + file(GLOB onnxruntime_autoep_test_library_src "${TEST_SRC_DIR}/autoep/library/example_plugin_ep/*.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep/*.cc" + "${TEST_SRC_DIR}/autoep/library/plugin_ep_utils.h") + onnxruntime_add_shared_library_module(example_plugin_ep ${onnxruntime_autoep_test_library_src}) + target_include_directories(example_plugin_ep PRIVATE ${REPO_ROOT}/include/onnxruntime/core/session) + target_link_libraries(example_plugin_ep PRIVATE onnxruntime ${GSL_TARGET}) + + if(UNIX) + if (APPLE) + set(ONNXRUNTIME_AUTOEP_LIB_LINK_FLAG "-Xlinker -dead_strip") + elseif (NOT CMAKE_SYSTEM_NAME MATCHES "AIX") + string(CONCAT ONNXRUNTIME_AUTOEP_LIB_LINK_FLAG + "-Xlinker --version-script=${TEST_SRC_DIR}/autoep/library/example_plugin_ep/example_plugin_ep_library.lds " + "-Xlinker --no-undefined -Xlinker --gc-sections -z noexecstack") + endif() + else() + set(ONNXRUNTIME_AUTOEP_LIB_LINK_FLAG + "-DEF:${TEST_SRC_DIR}/autoep/library/example_plugin_ep/example_plugin_ep_library.def") + endif() + + set_property(TARGET example_plugin_ep APPEND_STRING PROPERTY LINK_FLAGS + ${ONNXRUNTIME_AUTOEP_LIB_LINK_FLAG}) + + set_target_properties(example_plugin_ep PROPERTIES FOLDER "ONNXRuntimeTest") + source_group(TREE ${TEST_SRC_DIR} FILES ${onnxruntime_autoep_test_library_src}) + + # + # example_plugin_ep_virt_gpu + # + set(onnxruntime_autoep_test_example_plugin_ep_virt_gpu_src + "${TEST_SRC_DIR}/autoep/library/plugin_ep_utils.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_virt_gpu/ep_lib_entry.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_virt_gpu/ep_factory.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_virt_gpu/ep_factory.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_virt_gpu/ep.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_virt_gpu/ep.cc") + onnxruntime_add_shared_library_module(example_plugin_ep_virt_gpu ${onnxruntime_autoep_test_example_plugin_ep_virt_gpu_src}) + target_include_directories(example_plugin_ep_virt_gpu PRIVATE ${REPO_ROOT}/include/onnxruntime/core/session) + target_link_libraries(example_plugin_ep_virt_gpu PRIVATE onnxruntime ${GSL_TARGET}) + + if(UNIX) + if (APPLE) + set(ONNXRUNTIME_AUTOEP_EP_LIB_VIRT_GPU_LINK_FLAG "-Xlinker -dead_strip") + elseif (NOT CMAKE_SYSTEM_NAME MATCHES "AIX") + string(CONCAT ONNXRUNTIME_AUTOEP_EP_LIB_VIRT_GPU_LINK_FLAG + "-Xlinker --version-script=${TEST_SRC_DIR}/autoep/library/example_plugin_ep_virt_gpu/ep_lib.lds " + "-Xlinker --no-undefined -Xlinker --gc-sections -z noexecstack") + endif() + else() + set(ONNXRUNTIME_AUTOEP_EP_LIB_VIRT_GPU_LINK_FLAG + "-DEF:${TEST_SRC_DIR}/autoep/library/example_plugin_ep_virt_gpu/ep_lib.def") + endif() + + set_property(TARGET example_plugin_ep_virt_gpu APPEND_STRING PROPERTY LINK_FLAGS + ${ONNXRUNTIME_AUTOEP_EP_LIB_VIRT_GPU_LINK_FLAG}) + + set_target_properties(example_plugin_ep_virt_gpu PROPERTIES FOLDER "ONNXRuntimeTest") + source_group(TREE ${TEST_SRC_DIR} FILES ${onnxruntime_autoep_test_example_plugin_ep_virt_gpu_src}) + + # + # example_plugin_ep_kernel_registry + # + set(onnxruntime_autoep_test_example_plugin_ep_kernel_registry_src + "${TEST_SRC_DIR}/autoep/library/plugin_ep_utils.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_lib_entry.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_factory.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_factory.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_allocator.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_data_transfer.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_data_transfer.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_kernel_registration.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_kernel_registration.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_profiling.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_profiling.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/utils.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/squeeze.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/squeeze.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/relu.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/relu.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/binary_op.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/binary_op.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/scan.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/scan.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/loop.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/loop.cc" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/if.h" + "${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/kernels/if.cc") + onnxruntime_add_shared_library_module(example_plugin_ep_kernel_registry ${onnxruntime_autoep_test_example_plugin_ep_kernel_registry_src}) + target_include_directories(example_plugin_ep_kernel_registry PRIVATE ${REPO_ROOT}/include/onnxruntime/core/session) + target_link_libraries(example_plugin_ep_kernel_registry PRIVATE onnxruntime ${GSL_TARGET}) + + if(UNIX) + if (APPLE) + set(ONNXRUNTIME_EXAMPLE_PLUGIN_EP_KERNEL_REGISTRY_LINK_FLAG "-Xlinker -dead_strip") + elseif (NOT CMAKE_SYSTEM_NAME MATCHES "AIX") + string(CONCAT ONNXRUNTIME_EXAMPLE_PLUGIN_EP_KERNEL_REGISTRY_LINK_FLAG + "-Xlinker --version-script=${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_lib.lds " + "-Xlinker --no-undefined -Xlinker --gc-sections -z noexecstack") + endif() + else() + set(ONNXRUNTIME_EXAMPLE_PLUGIN_EP_KERNEL_REGISTRY_LINK_FLAG + "-DEF:${TEST_SRC_DIR}/autoep/library/example_plugin_ep_kernel_registry/ep_lib.def") + endif() + + set_property(TARGET example_plugin_ep_kernel_registry APPEND_STRING PROPERTY LINK_FLAGS + ${ONNXRUNTIME_EXAMPLE_PLUGIN_EP_KERNEL_REGISTRY_LINK_FLAG}) + + set_target_properties(example_plugin_ep_kernel_registry PROPERTIES FOLDER "ONNXRuntimeTest") + source_group(TREE ${TEST_SRC_DIR} FILES ${onnxruntime_autoep_test_example_plugin_ep_kernel_registry_src}) + + # + # test library + # + file(GLOB onnxruntime_autoep_test_SRC "${ONNXRUNTIME_AUTOEP_TEST_SRC_DIR}/*.h" + "${ONNXRUNTIME_AUTOEP_TEST_SRC_DIR}/*.cc") + + set(onnxruntime_autoep_test_LIBS onnxruntime_mocked_allocator ${ONNXRUNTIME_TEST_LIBS} onnxruntime_test_utils + onnx_proto onnx ${onnxruntime_EXTERNAL_LIBRARIES}) + + if (onnxruntime_USE_TENSORRT) + list(APPEND onnxruntime_autoep_test_LIBS ${TENSORRT_LIBRARY_INFER}) + endif() + + if (onnxruntime_USE_CUDA) + list(APPEND onnxruntime_autoep_test_LIBS CUDA::cudart) + endif() + + if (onnxruntime_USE_DML) + list(APPEND onnxruntime_autoep_test_LIBS d3d12.lib) + endif() + + if (CPUINFO_SUPPORTED) + list(APPEND onnxruntime_autoep_test_LIBS cpuinfo) + endif() + + if (CMAKE_SYSTEM_NAME MATCHES "AIX") + list(APPEND onnxruntime_autoep_test_LIBS onnxruntime_graph onnxruntime_session onnxruntime_providers + onnxruntime_optimizer onnxruntime_mlas onnxruntime_framework onnxruntime_util onnxruntime_flatbuffers + iconv re2 onnx) + endif() + + AddTest(DYN + TARGET onnxruntime_autoep_test + SOURCES ${onnxruntime_autoep_test_SRC} ${onnxruntime_unittest_main_src} + LIBS ${onnxruntime_autoep_test_LIBS} + DEPENDS ${all_dependencies} example_plugin_ep example_plugin_ep_virt_gpu example_plugin_ep_kernel_registry + ) +endif() + if (onnxruntime_BUILD_SHARED_LIB AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND NOT onnxruntime_MINIMAL_BUILD) set (onnxruntime_logging_apis_test_SRC ${ONNXRUNTIME_LOGGING_APIS_TEST_SRC_DIR}/test_logging_apis.cc) set(onnxruntime_logging_apis_test_LIBS onnxruntime_common onnxruntime_test_utils) - if (${CMAKE_SYSTEM_NAME} MATCHES "AIX") + if (CMAKE_SYSTEM_NAME MATCHES "AIX") list(APPEND onnxruntime_logging_apis_test_LIBS onnxruntime_session onnxruntime_util onnxruntime_lora onnxruntime_framework onnxruntime_common onnxruntime_graph onnxruntime_providers onnxruntime_mlas onnxruntime_optimizer onnxruntime_flatbuffers iconv re2 ${PROTOBUF_LIB} onnx onnx_proto) endif() @@ -1820,46 +2307,6 @@ if (NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND onnxruntime_USE_OPENVINO AND ${ONNXRUNTIME_CUSTOM_OP_OPENVINO_WRAPPER_LIB_LINK_FLAG}) endif() -# limit to only test on windows first, due to a runtime path issue on linux -if (NOT onnxruntime_MINIMAL_BUILD AND NOT onnxruntime_EXTENDED_MINIMAL_BUILD - AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin|iOS|visionOS" - AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android" - AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" - AND NOT onnxruntime_USE_ROCM) - file(GLOB_RECURSE test_execution_provider_srcs - "${REPO_ROOT}/onnxruntime/test/testdata/custom_execution_provider_library/*.h" - "${REPO_ROOT}/onnxruntime/test/testdata/custom_execution_provider_library/*.cc" - "${ONNXRUNTIME_ROOT}/core/providers/shared_library/*.h" - "${ONNXRUNTIME_ROOT}/core/providers/shared_library/*.cc" - ) - - onnxruntime_add_shared_library_module(test_execution_provider ${test_execution_provider_srcs}) - add_dependencies(test_execution_provider onnxruntime_providers_shared onnx ${ABSEIL_LIBS}) - if (CMAKE_SYSTEM_NAME MATCHES "AIX") - target_link_options(test_execution_provider PRIVATE -Wl,-brtl -lonnxruntime_providers_shared) - target_link_libraries(test_execution_provider PRIVATE ${ABSEIL_LIBS} Boost::mp11) - else() - target_link_libraries(test_execution_provider PRIVATE onnxruntime_providers_shared ${ABSEIL_LIBS} Boost::mp11) - endif() - target_include_directories(test_execution_provider PRIVATE $) - target_include_directories(test_execution_provider PRIVATE $) - target_include_directories(test_execution_provider PRIVATE ${ONNXRUNTIME_ROOT} ${CMAKE_CURRENT_BINARY_DIR} ${ORTTRAINING_ROOT}) - if (onnxruntime_ENABLE_TRAINING_TORCH_INTEROP) - target_link_libraries(test_execution_provider PRIVATE Python::Python) - endif() - if(APPLE) - set_property(TARGET test_execution_provider APPEND_STRING PROPERTY LINK_FLAGS "-Xlinker -exported_symbols_list ${REPO_ROOT}/onnxruntime/test/testdata/custom_execution_provider_library/exported_symbols.lst") - elseif(UNIX) - if (NOT ${CMAKE_SYSTEM_NAME} MATCHES "AIX") - set_property(TARGET test_execution_provider APPEND_STRING PROPERTY LINK_FLAGS "-Xlinker --version-script=${REPO_ROOT}/onnxruntime/test/testdata/custom_execution_provider_library/version_script.lds -Xlinker --gc-sections -Xlinker -rpath=\\$ORIGIN") - endif() - elseif(WIN32) - set_property(TARGET test_execution_provider APPEND_STRING PROPERTY LINK_FLAGS "-DEF:${REPO_ROOT}/onnxruntime/test/testdata/custom_execution_provider_library/symbols.def") - else() - message(FATAL_ERROR "test_execution_provider unknown platform, need to specify shared library exports for it") - endif() -endif() - if (onnxruntime_USE_WEBGPU AND onnxruntime_USE_EXTERNAL_DAWN) AddTest(TARGET onnxruntime_webgpu_external_dawn_test SOURCES ${onnxruntime_webgpu_external_dawn_test_SRC} @@ -1878,4 +2325,34 @@ if (onnxruntime_USE_WEBGPU AND WIN32 AND onnxruntime_BUILD_SHARED_LIB AND NOT CM ) endif() +# onnxruntime_ep_graph_test tests the implementation of the public OrtGraph APIs for use in plugin EPs (OrtEp). +if (onnxruntime_BUILD_SHARED_LIB AND NOT CMAKE_SYSTEM_NAME STREQUAL "Emscripten" AND NOT onnxruntime_MINIMAL_BUILD) + file(GLOB_RECURSE onnxruntime_ep_graph_test_SRC "${ONNXRUNTIME_EP_GRAPH_TEST_SRC_DIR}/*.h" + "${ONNXRUNTIME_EP_GRAPH_TEST_SRC_DIR}/*.cc") + + set(onnxruntime_ep_graph_test_LIBS ${ONNXRUNTIME_TEST_LIBS} onnxruntime_test_utils ${onnxruntime_EXTERNAL_LIBRARIES}) + if (CMAKE_SYSTEM_NAME MATCHES "AIX") + list(APPEND onnxruntime_ep_graph_test_LIBS onnxruntime_session onnxruntime_util onnxruntime_lora onnxruntime_framework + onnxruntime_common onnxruntime_graph onnxruntime_providers onnxruntime_mlas + onnxruntime_optimizer onnxruntime_flatbuffers iconv re2 + ${PROTOBUF_LIB} onnx onnx_proto) + endif() + + if(NOT WIN32) + list(APPEND onnxruntime_ep_graph_test_LIBS ${CMAKE_DL_LIBS}) + endif() + + if (onnxruntime_USE_TENSORRT OR onnxruntime_USE_NV) + # Need this because unittest_main_src defines a global nvinfer1::IBuilder variable. + list(APPEND onnxruntime_ep_graph_test_LIBS ${TENSORRT_LIBRARY_INFER}) + endif() + + AddTest(DYN + TARGET onnxruntime_ep_graph_test + SOURCES ${onnxruntime_ep_graph_test_SRC} ${onnxruntime_unittest_main_src} + LIBS ${onnxruntime_ep_graph_test_LIBS} + DEPENDS ${all_dependencies} + ) +endif() + include(onnxruntime_fuzz_test.cmake) diff --git a/cmake/onnxruntime_util.cmake b/cmake/onnxruntime_util.cmake index ae7e842f223d6..851b68a4b61a0 100644 --- a/cmake/onnxruntime_util.cmake +++ b/cmake/onnxruntime_util.cmake @@ -9,8 +9,7 @@ file(GLOB_RECURSE onnxruntime_util_srcs CONFIGURE_DEPENDS source_group(TREE ${ONNXRUNTIME_ROOT}/core FILES ${onnxruntime_util_srcs}) onnxruntime_add_static_library(onnxruntime_util ${onnxruntime_util_srcs}) -target_include_directories(onnxruntime_util PRIVATE ${ONNXRUNTIME_ROOT} PUBLIC ${eigen_INCLUDE_DIRS}) -onnxruntime_add_include_to_target(onnxruntime_util onnxruntime_common onnx onnx_proto ${PROTOBUF_LIB} Boost::mp11) +onnxruntime_add_include_to_target(onnxruntime_util onnxruntime_common onnx onnx_proto ${PROTOBUF_LIB} Boost::mp11 Eigen3::Eigen) if(UNIX) target_compile_options(onnxruntime_util PUBLIC "-Wno-error=comment") endif() @@ -22,7 +21,7 @@ if (WIN32) endif() if (NOT onnxruntime_BUILD_SHARED_LIB) - install(TARGETS onnxruntime_util + install(TARGETS onnxruntime_util EXPORT ${PROJECT_NAME}Targets ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} diff --git a/cmake/onnxruntime_webassembly.cmake b/cmake/onnxruntime_webassembly.cmake index 6cd05d1ad024b..fa93113c76160 100644 --- a/cmake/onnxruntime_webassembly.cmake +++ b/cmake/onnxruntime_webassembly.cmake @@ -84,6 +84,10 @@ function(bundle_static_library bundled_target_name) add_dependencies(${bundled_target_name} bundling_target) endfunction() +if (onnxruntime_USE_JSEP AND onnxruntime_USE_WEBGPU) + message(FATAL_ERROR "onnxruntime_USE_JSEP and onnxruntime_USE_WEBGPU cannot be enabled at the same time.") +endif() + if (NOT onnxruntime_ENABLE_WEBASSEMBLY_THREADS) add_compile_definitions( BUILD_MLAS_NO_ONNXRUNTIME @@ -93,7 +97,12 @@ if (NOT onnxruntime_ENABLE_WEBASSEMBLY_THREADS) set_property(TARGET re2 PROPERTY COMPILE_OPTIONS ) endif() -target_compile_options(onnx PRIVATE -Wno-unused-parameter -Wno-unused-variable) +if (NOT onnxruntime_USE_VCPKG) + target_compile_options(onnx PRIVATE -Wno-unused-parameter -Wno-unused-variable) +endif() + +# Include the Node.js helper for finding and validating Node.js and NPM +include(node_helper.cmake) if (onnxruntime_BUILD_WEBASSEMBLY_STATIC_LIB) bundle_static_library(onnxruntime_webassembly @@ -142,11 +151,6 @@ if (onnxruntime_BUILD_WEBASSEMBLY_STATIC_LIB) GTest::gtest ) - find_program(NODE_EXECUTABLE node required) - if (NOT NODE_EXECUTABLE) - message(FATAL_ERROR "Node is required for a test") - endif() - add_test(NAME onnxruntime_webassembly_test COMMAND ${NODE_EXECUTABLE} onnxruntime_webassembly_test.js WORKING_DIRECTORY $ @@ -169,9 +173,9 @@ else() "${ONNXRUNTIME_ROOT}/wasm/api.cc" "${ONNXRUNTIME_ROOT}/core/session/onnxruntime_c_api.cc" ) - set (WASM_API_EXCEPTION_CATCHING "-s DISABLE_EXCEPTION_CATCHING=0") message(STATUS "onnxruntime_ENABLE_WEBASSEMBLY_EXCEPTION_CATCHING_ON_API set") - set_source_files_properties(${onnxruntime_webassembly_src_exc} PROPERTIES COMPILE_FLAGS ${WASM_API_EXCEPTION_CATCHING}) + set_source_files_properties(${onnxruntime_webassembly_src_exc} PROPERTIES COMPILE_FLAGS "-sDISABLE_EXCEPTION_CATCHING=0") + target_link_options(onnxruntime_webassembly PRIVATE "SHELL:-s DISABLE_EXCEPTION_CATCHING=0") endif() target_link_libraries(onnxruntime_webassembly PRIVATE @@ -194,7 +198,7 @@ else() onnxruntime_util re2::re2 ) - set(EXPORTED_RUNTIME_METHODS "'stackAlloc','stackRestore','stackSave','UTF8ToString','stringToUTF8','lengthBytesUTF8','getValue','setValue'") + set(EXPORTED_RUNTIME_METHODS "'stackAlloc','stackRestore','stackSave','UTF8ToString','stringToUTF8','lengthBytesUTF8','getValue','setValue','HEAP8','HEAPU8','HEAP32','HEAPU32'") if (onnxruntime_USE_XNNPACK) target_link_libraries(onnxruntime_webassembly PRIVATE XNNPACK) string(APPEND EXPORTED_RUNTIME_METHODS ",'addFunction'") @@ -209,116 +213,20 @@ else() target_link_libraries(onnxruntime_webassembly PRIVATE tensorboard) endif() + set(onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/pre.js") + + set(EXPORTED_FUNCTIONS "_malloc,_free") if (onnxruntime_USE_JSEP) - set(EXPORTED_FUNCTIONS "_malloc,_free,_JsepOutput,_JsepGetNodeName") - else() - set(EXPORTED_FUNCTIONS "_malloc,_free") + string(APPEND EXPORTED_FUNCTIONS ",_JsepOutput,_JsepGetNodeName") endif() - - if (onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64) - set(MAXIMUM_MEMORY "17179869184") - target_link_options(onnxruntime_webassembly PRIVATE - "SHELL:-s MEMORY64=1" - ) - string(APPEND CMAKE_C_FLAGS " -sMEMORY64 -Wno-experimental") - string(APPEND CMAKE_CXX_FLAGS " -sMEMORY64 -Wno-experimental") - set(SMEMORY_FLAG "-sMEMORY64") - - target_compile_options(onnx PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(onnxruntime_common PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(onnxruntime_session PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(onnxruntime_framework PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(nsync_cpp PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(onnx_proto PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - # target_compile_options(protoc PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(libprotobuf-lite PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(onnxruntime_providers PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(onnxruntime_optimizer PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(onnxruntime_mlas PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(onnxruntime_optimizer PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(onnxruntime_graph PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(onnxruntime_flatbuffers PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(onnxruntime_util PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(re2 PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_flags_private_handle_accessor PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_flags_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_flags_commandlineflag PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_flags_commandlineflag_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_flags_marshalling PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_flags_reflection PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_flags_config PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_flags_program_name PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_cord PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_cordz_info PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_cord_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_cordz_functions PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_cordz_handle PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_crc_cord_state PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_crc32c PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_crc_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_crc_cpu_detect PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_raw_hash_set PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_hashtablez_sampler PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_exponential_biased PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_internal_conditions PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_internal_check_op PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_internal_message PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_internal_format PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_str_format_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_internal_log_sink_set PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_internal_globals PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_sink PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_entry PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_globals PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_hash PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_city PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_low_level_hash PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_bad_variant_access PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_vlog_config_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_synchronization PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_kernel_timeout_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_time PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_time_zone PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_civil_time PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_graphcycles_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_bad_optional_access PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_internal_fnmatch PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_examine_stack PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_symbolize PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_malloc_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_demangle_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_demangle_rust PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_decode_rust_punycode PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_utf8_for_code_point PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_stacktrace PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_debugging_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_internal_proto PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_strerror PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_internal_nullguard PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_strings PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_strings_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_int128 PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_string_view PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_base PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_spinlock_wait PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_throw_delegate PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_raw_logging_internal PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(absl_log_severity PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - if (onnxruntime_USE_EXTENSIONS) - target_compile_options(ortcustomops PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(ocos_operators PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - target_compile_options(noexcep_operators PRIVATE ${SMEMORY_FLAG} -Wno-experimental) - endif() - target_link_options(onnxruntime_webassembly PRIVATE - --post-js "${ONNXRUNTIME_ROOT}/wasm/js_post_js_64.js" - ) - else () - set(MAXIMUM_MEMORY "4294967296") - target_link_options(onnxruntime_webassembly PRIVATE - --post-js "${ONNXRUNTIME_ROOT}/wasm/js_post_js.js" - ) - endif () - + if (onnxruntime_USE_WEBGPU) + string(APPEND EXPORTED_FUNCTIONS ",_wgpuBufferRelease,_wgpuCreateInstance") + endif() + set(MAXIMUM_MEMORY "4294967296") + target_link_options(onnxruntime_webassembly PRIVATE + "SHELL:--post-js \"${ONNXRUNTIME_ROOT}/wasm/js_post_js.js\"" + ) + list(APPEND onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/js_post_js.js") target_link_options(onnxruntime_webassembly PRIVATE "SHELL:-s EXPORTED_RUNTIME_METHODS=[${EXPORTED_RUNTIME_METHODS}]" "SHELL:-s EXPORTED_FUNCTIONS=${EXPORTED_FUNCTIONS}" @@ -331,70 +239,56 @@ else() "SHELL:-s FILESYSTEM=0" "SHELL:-s INCOMING_MODULE_JS_API=[locateFile,instantiateWasm,wasmBinary]" "SHELL:-s WASM_BIGINT=1" - ${WASM_API_EXCEPTION_CATCHING} --no-entry "SHELL:--pre-js \"${ONNXRUNTIME_ROOT}/wasm/pre.js\"" ) - if (onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64) - set(SIGNATURE_CONVERSIONS "OrtRun:_pppppppp,\ -OrtRunWithBinding:_ppppp,\ -OrtGetTensorData:_ppppp,\ -OrtCreateTensor:p_pppp_,\ -OrtCreateSession:pppp,\ -OrtReleaseSession:_p,\ -OrtGetInputOutputCount:_ppp,\ -OrtCreateSessionOptions:pp__p_ppppp,\ -OrtReleaseSessionOptions:_p,\ -OrtAppendExecutionProvider:_pp,\ -OrtAddSessionConfigEntry:_ppp,\ -OrtGetInputName:ppp,\ -OrtGetOutputName:ppp,\ -OrtCreateRunOptions:ppp_p,\ -OrtReleaseRunOptions:_p,\ -OrtReleaseTensor:_p,\ -OrtFree:_p,\ -OrtCreateBinding:_p,\ -OrtBindInput:_ppp,\ -OrtBindOutput:_ppp_,\ -OrtClearBoundOutputs:_p,\ -OrtReleaseBinding:_p,\ -OrtGetLastError:_pp,\ -JsepOutput:pp_p,\ -JsepGetNodeName:pp,\ -JsepOutput:pp_p,\ -jsepCopy:_pp_,\ -jsepCopyAsync:_pp_,\ -jsepDownload:_pp_") - target_link_options(onnxruntime_webassembly PRIVATE - "SHELL:-s ERROR_ON_UNDEFINED_SYMBOLS=0" - "SHELL:-s SIGNATURE_CONVERSIONS='${SIGNATURE_CONVERSIONS}'" - ) - endif () - set_target_properties(onnxruntime_webassembly PROPERTIES LINK_DEPENDS ${ONNXRUNTIME_ROOT}/wasm/pre.js) if (onnxruntime_USE_JSEP) - # NOTE: "-s ASYNCIFY=1" is required for JSEP to work with WebGPU - # This flag allows async functions to be called from sync functions, in the cost of binary size and - # build time. See https://emscripten.org/docs/porting/asyncify.html for more details. - target_compile_definitions(onnxruntime_webassembly PRIVATE USE_JSEP=1) target_link_options(onnxruntime_webassembly PRIVATE "SHELL:--pre-js \"${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js\"" - "SHELL:-s ASYNCIFY=1" - "SHELL:-s ASYNCIFY_STACK_SIZE=65536" ) - set_target_properties(onnxruntime_webassembly PROPERTIES LINK_DEPENDS ${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js) + list(APPEND onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/pre-jsep.js") + + endif() + + if (onnxruntime_USE_WEBGPU) + target_compile_definitions(onnxruntime_webassembly PRIVATE USE_WEBGPU=1) + target_link_options(onnxruntime_webassembly PRIVATE + "SHELL:--post-js \"${ONNXRUNTIME_ROOT}/wasm/post-webgpu.js\"" + ) + list(APPEND onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/post-webgpu.js") + endif() - if (onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64) + if (onnxruntime_USE_WEBNN) + target_compile_definitions(onnxruntime_webassembly PRIVATE USE_WEBNN=1) + if (NOT onnxruntime_USE_JSEP) target_link_options(onnxruntime_webassembly PRIVATE - "SHELL:-s ASYNCIFY_EXPORTS=['OrtRun']" - "SHELL:-s ASYNCIFY_IMPORTS=['Module.jsepCopy','Module.jsepCopyAsync','jsepDownload']" + "SHELL:--post-js \"${ONNXRUNTIME_ROOT}/wasm/post-webnn.js\"" ) + list(APPEND onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/post-webnn.js") endif() endif() - if (onnxruntime_USE_WEBGPU) - target_compile_definitions(onnxruntime_webassembly PRIVATE USE_WEBGPU=1) + if (onnxruntime_USE_JSEP OR onnxruntime_USE_WEBGPU OR onnxruntime_USE_WEBNN) + if (onnxruntime_ENABLE_WEBASSEMBLY_JSPI) + target_link_options(onnxruntime_webassembly PRIVATE + "SHELL:-s JSPI=1" + "SHELL:-s JSPI_EXPORTS=[OrtAppendExecutionProvider,OrtCreateSession,OrtRun,OrtRunWithBinding,OrtBindInput]" + ) + else() + # NOTE: "-s ASYNCIFY=1" is required for JSEP to work with WebGPU + # This flag allows async functions to be called from sync functions, in the cost of binary size and + # build time. See https://emscripten.org/docs/porting/asyncify.html for more details. + # + # if any of the above is enabled, we need to use the asyncify library + target_link_options(onnxruntime_webassembly PRIVATE + "SHELL:--pre-js \"${ONNXRUNTIME_ROOT}/wasm/pre-async.js\"" + "SHELL:-s ASYNCIFY=1" + "SHELL:-s ASYNCIFY_STACK_SIZE=65536" + ) + list(APPEND onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/pre-async.js") + endif() endif() if (onnxruntime_EMSCRIPTEN_SETTINGS) @@ -404,14 +298,21 @@ jsepDownload:_pp_") endif() if (CMAKE_BUILD_TYPE STREQUAL "Debug") - target_link_options(onnxruntime_webassembly PRIVATE - # NOTE: use "SHELL:-s ASSERTIONS=2" to enable more strict assertions, which may help debugging segfaults. - # However, it may be very slow. - # "SHELL:-s ASSERTIONS=2" - "SHELL:-s ASSERTIONS=1" - "SHELL:-s SAFE_HEAP=1" - "SHELL:-s STACK_OVERFLOW_CHECK=2" - ) + if (CMAKE_CXX_FLAGS MATCHES "sanitize=address") + # The integer value below might often need be adjusted. + target_link_options(onnxruntime_webassembly PRIVATE "-sINITIAL_MEMORY=786432000") + target_link_options(onnxruntime_webassembly PRIVATE "-sASSERTIONS=2") + else() + # Enable SAFE_HEAP in debug build + target_link_options(onnxruntime_webassembly PRIVATE + # NOTE: use "SHELL:-s ASSERTIONS=2" to enable more strict assertions, which may help debugging segfaults. + # However, it may be very slow. + # "SHELL:-s ASSERTIONS=2" + "SHELL:-s ASSERTIONS=1" + "SHELL:-s SAFE_HEAP=1" + "SHELL:-s STACK_OVERFLOW_CHECK=2" + ) + endif() else() target_link_options(onnxruntime_webassembly PRIVATE "SHELL:-s ASSERTIONS=0" @@ -428,9 +329,11 @@ jsepDownload:_pp_") endif() endif() - # Set link flag to enable exceptions support, this will override default disabling exception throwing behavior when disable exceptions. - if (NOT onnxruntime_ENABLE_WEBASSEMBLY_MEMORY64) - target_link_options(onnxruntime_webassembly PRIVATE "SHELL:-s DISABLE_EXCEPTION_THROWING=0") + if (NOT onnxruntime_ENABLE_WEBASSEMBLY_JSPI) + # Set link flag to enable exceptions support, this will override default disabling exception throwing behavior when disable exceptions. + target_link_options(onnxruntime_webassembly PRIVATE + "SHELL:-s DISABLE_EXCEPTION_THROWING=0" + ) endif() if (onnxruntime_ENABLE_WEBASSEMBLY_PROFILING) @@ -449,6 +352,21 @@ jsepDownload:_pp_") ) endif() + # + # Apply post-processing script for the generated JavaScript file + # + list(APPEND onnxruntime_webassembly_script_deps "${ONNXRUNTIME_ROOT}/wasm/wasm_post_build.js") + add_custom_command( + TARGET onnxruntime_webassembly + POST_BUILD + # Backup file at $.bak + COMMAND ${CMAKE_COMMAND} -E copy_if_different "$" "$.bak" + COMMAND ${CMAKE_COMMAND} -E echo "Performing post-process for $" + COMMAND ${NODE_EXECUTABLE} "${ONNXRUNTIME_ROOT}/wasm/wasm_post_build.js" "$" + ) + + set_target_properties(onnxruntime_webassembly PROPERTIES LINK_DEPENDS "${onnxruntime_webassembly_script_deps}") + set(target_name_list ort) if (onnxruntime_ENABLE_TRAINING_APIS) @@ -457,7 +375,9 @@ jsepDownload:_pp_") list(APPEND target_name_list "wasm") - if (onnxruntime_ENABLE_WEBASSEMBLY_SIMD) + if (onnxruntime_ENABLE_WEBASSEMBLY_RELAXED_SIMD) + list(APPEND target_name_list "relaxedsimd") + elseif (onnxruntime_ENABLE_WEBASSEMBLY_SIMD) list(APPEND target_name_list "simd") endif() @@ -469,6 +389,12 @@ jsepDownload:_pp_") if (onnxruntime_USE_JSEP) string(APPEND target_name ".jsep") + elseif (onnxruntime_USE_WEBGPU OR onnxruntime_USE_WEBNN) + if (onnxruntime_ENABLE_WEBASSEMBLY_JSPI) + string(APPEND target_name ".jspi") + else() + string(APPEND target_name ".asyncify") + endif() endif() set_target_properties(onnxruntime_webassembly PROPERTIES OUTPUT_NAME ${target_name} SUFFIX ".mjs") diff --git a/cmake/patches/abseil/absl_cuda_warnings.patch b/cmake/patches/abseil/absl_cuda_warnings.patch new file mode 100644 index 0000000000000..144b9f904bf0f --- /dev/null +++ b/cmake/patches/abseil/absl_cuda_warnings.patch @@ -0,0 +1,40 @@ +diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h +index 1234567..abcdefg 100644 +--- a/absl/hash/internal/hash.h ++++ b/absl/hash/internal/hash.h +@@ -477,7 +477,7 @@ H AbslHashValue(H hash_state, T (&)[N]) { + template + H AbslHashValue(H hash_state, T (&)[N]) { + static_assert( +- sizeof(T) == -1, ++ sizeof(T) == size_t(-1), + "Hashing C arrays is not allowed. For string literals, wrap the literal " + "in absl::string_view(). To hash the array contents, use " + "absl::MakeSpan() or make the array an std::array. To hash the array " +diff --git a/absl/hash/hash.h b/absl/hash/hash.h +index 1234567..abcdefg 100644 +--- a/absl/hash/hash.h ++++ b/absl/hash/hash.h +@@ -333,7 +333,8 @@ class HashState : public hash_internal::HashStateBase { + absl::enable_if_t< + std::is_base_of, T>::value, int> = 0> + static HashState Create(T* state) { +- HashState s; ++ HashState s = {}; ++ (void)s; + s.Init(state); + return s; + } +diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h +index 1234567..abcdefg 100644 +--- a/absl/container/internal/raw_hash_set.h ++++ b/absl/container/internal/raw_hash_set.h +@@ -464,7 +464,7 @@ inline uint16_t NextSeed() { + inline uint16_t NextSeed() { + static_assert(PerTableSeed::kBitCount == 16); + thread_local uint16_t seed = +- static_cast(reinterpret_cast(&seed)); ++ static_cast(reinterpret_cast(&seed) & 0xFFFFu); + seed += uint16_t{0xad53}; + return seed; + } diff --git a/cmake/patches/abseil/absl_windows.patch b/cmake/patches/abseil/absl_windows.patch index c50e147aa4a7d..036ead7b88e46 100644 --- a/cmake/patches/abseil/absl_windows.patch +++ b/cmake/patches/abseil/absl_windows.patch @@ -1,163 +1,44 @@ -diff --git a/absl/base/attributes.h b/absl/base/attributes.h -index 5ea5ee3e..f4949898 100644 ---- a/absl/base/attributes.h -+++ b/absl/base/attributes.h -@@ -559,7 +559,7 @@ - #undef ABSL_ATTRIBUTE_UNUSED - #define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__)) - #else --#define ABSL_ATTRIBUTE_UNUSED -+#define ABSL_ATTRIBUTE_UNUSED [[maybe_unused]] - #endif - - // ABSL_ATTRIBUTE_INITIAL_EXEC diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h -index d4fe8f5c..27418d13 100644 +index 3effc441..c339e269 100644 --- a/absl/container/internal/raw_hash_set.h +++ b/absl/container/internal/raw_hash_set.h -@@ -1924,7 +1924,7 @@ HashtablezInfoHandle SampleHashtablezInfo(size_t sizeof_slot, size_t sizeof_key, - // In SOO, we sample on the first insertion so if this is an empty SOO case - // (e.g. when reserve is called), then we still need to sample. - if (kSooEnabled && was_soo && c.size() == 0) { -- return Sample(sizeof_slot, sizeof_key, sizeof_value, SooCapacity()); -+ return Sample(sizeof_slot, sizeof_key, sizeof_value, (int16_t)SooCapacity()); - } - // For non-SOO cases, we sample whenever the capacity is increasing from zero - // to non-zero. -@@ -3525,7 +3525,7 @@ class raw_hash_set { - assert(is_soo()); - if (!ShouldSampleHashtablezInfo()) return HashtablezInfoHandle{}; - return Sample(sizeof(slot_type), sizeof(key_type), sizeof(value_type), -- SooCapacity()); -+ (int16_t)SooCapacity()); +@@ -1121,11 +1121,12 @@ class CommonFields : public CommonFieldsGenerationInfo { + #ifdef NDEBUG + f(); + return; +-#endif ++#else + const size_t cap = capacity(); + set_capacity(InvalidCapacity::kReentrance); + f(); + set_capacity(cap); ++#endif } - inline void destroy_slots() { -diff --git a/absl/copts/GENERATED_AbseilCopts.cmake b/absl/copts/GENERATED_AbseilCopts.cmake -index da2282fe..4c7fc26f 100644 ---- a/absl/copts/GENERATED_AbseilCopts.cmake -+++ b/absl/copts/GENERATED_AbseilCopts.cmake -@@ -181,8 +181,6 @@ list(APPEND ABSL_MSVC_FLAGS - "/wd4005" - "/wd4068" - "/wd4180" -- "/wd4244" -- "/wd4267" - "/wd4503" - "/wd4800" - "/DNOMINMAX" -diff --git a/absl/copts/GENERATED_copts.bzl b/absl/copts/GENERATED_copts.bzl -index b9e0071e..dd8410ec 100644 ---- a/absl/copts/GENERATED_copts.bzl -+++ b/absl/copts/GENERATED_copts.bzl -@@ -182,8 +182,6 @@ ABSL_MSVC_FLAGS = [ - "/wd4005", - "/wd4068", - "/wd4180", -- "/wd4244", -- "/wd4267", - "/wd4503", - "/wd4800", - "/DNOMINMAX", -diff --git a/absl/copts/copts.py b/absl/copts/copts.py -index 2d85ac74..4875d668 100644 ---- a/absl/copts/copts.py -+++ b/absl/copts/copts.py -@@ -118,10 +118,6 @@ MSVC_WARNING_FLAGS = [ - "/wd4068", # unknown pragma - # qualifier applied to function type has no meaning; ignored - "/wd4180", -- # conversion from 'type1' to 'type2', possible loss of data -- "/wd4244", -- # conversion from 'size_t' to 'type', possible loss of data -- "/wd4267", - # The decorated name was longer than the compiler limit - "/wd4503", - # forcing value to bool 'true' or 'false' (performance warning) -diff --git a/absl/debugging/symbolize.cc b/absl/debugging/symbolize.cc -index 638d3954..6b817075 100644 ---- a/absl/debugging/symbolize.cc -+++ b/absl/debugging/symbolize.cc -@@ -14,7 +14,7 @@ - - #include "absl/debugging/symbolize.h" - --#ifdef _WIN32 -+#if defined(_WIN32) && !defined(NDEBUG) - #include - #if !(WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_APP)) || \ - WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) -diff --git a/absl/debugging/symbolize_win32.inc b/absl/debugging/symbolize_win32.inc -index 53a099a1..34d210d6 100644 ---- a/absl/debugging/symbolize_win32.inc -+++ b/absl/debugging/symbolize_win32.inc -@@ -35,15 +35,15 @@ ABSL_NAMESPACE_BEGIN - - static HANDLE process = NULL; - --void InitializeSymbolizer(const char*) { -- if (process != nullptr) { -- return; -- } -+namespace { -+void InitializeSymbolizerImpl() { -+ - process = GetCurrentProcess(); - - // Symbols are not loaded until a reference is made requiring the - // symbols be loaded. This is the fastest, most efficient way to use - // the symbol handler. -+ - SymSetOptions(SYMOPT_DEFERRED_LOADS | SYMOPT_UNDNAME); - if (!SymInitialize(process, nullptr, true)) { - // GetLastError() returns a Win32 DWORD, but we assign to -@@ -54,6 +54,36 @@ void InitializeSymbolizer(const char*) { - } - } - -+bool LookupAndInitialize(const void* pc, SYMBOL_INFO* symbol) { -+ auto hProcess = (process != NULL) ? process : GetCurrentProcess(); -+ if (SymFromAddr(hProcess, reinterpret_cast(pc), nullptr, symbol) != TRUE) { -+ if (GetLastError() == ERROR_INVALID_HANDLE && process == NULL) { -+ InitializeSymbolizerImpl(); -+ if (SymFromAddr(process, reinterpret_cast(pc), nullptr, symbol) != TRUE) { -+ return false; -+ } -+ } else { -+ return false; -+ } -+ return false; + private: +@@ -3344,11 +3345,14 @@ class raw_hash_set { + + // Asserts that hash and equal functors provided by the user are consistent, + // meaning that `eq(k1, k2)` implies `hash(k1)==hash(k2)`. +- template +- void AssertHashEqConsistent(const K& key) { + #ifdef NDEBUG ++ template ++ void AssertHashEqConsistent(const K&) { + return; +-#endif + } -+ return true; -+} -+} -+ -+void InitializeSymbolizer(const char*) { -+ if (process != nullptr) { -+ return; -+ } -+ -+ alignas(SYMBOL_INFO) char buf[sizeof(SYMBOL_INFO) + MAX_SYM_NAME]; -+ SYMBOL_INFO* symbol = reinterpret_cast(buf); -+ symbol->SizeOfStruct = sizeof(SYMBOL_INFO); -+ symbol->MaxNameLen = MAX_SYM_NAME; -+ -+ static_cast(LookupAndInitialize(reinterpret_cast(&InitializeSymbolizer), symbol)); -+} -+ - bool Symbolize(const void* pc, char* out, int out_size) { - if (out_size <= 0) { - return false; -@@ -62,9 +92,11 @@ bool Symbolize(const void* pc, char* out, int out_size) { - SYMBOL_INFO* symbol = reinterpret_cast(buf); - symbol->SizeOfStruct = sizeof(SYMBOL_INFO); - symbol->MaxNameLen = MAX_SYM_NAME; -- if (!SymFromAddr(process, reinterpret_cast(pc), nullptr, symbol)) { -+ -+ if(!LookupAndInitialize(pc, symbol)) { - return false; ++#else ++ template ++ void AssertHashEqConsistent(const K& key) { + // If the hash/eq functors are known to be consistent, then skip validation. + if (std::is_same::value && + std::is_same::value) { +@@ -3386,6 +3390,7 @@ class raw_hash_set { + if (capacity() > 16) return; + IterateOverFullSlots(common(), sizeof(slot_type), assert_consistent); } -+ - const size_t out_size_t = static_cast(out_size); - strncpy(out, symbol->Name, out_size_t); - if (out[out_size_t - 1] != '\0') { ++#endif + + // Attempts to find `key` in the table; if it isn't found, returns an iterator + // where the value can be inserted into, with the control byte already set to diff --git a/cmake/patches/composable_kernel/Add_gfx12x_support.patch b/cmake/patches/composable_kernel/Add_gfx12x_support.patch deleted file mode 100644 index ef529184d2ed8..0000000000000 --- a/cmake/patches/composable_kernel/Add_gfx12x_support.patch +++ /dev/null @@ -1,2280 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index bc326c8b5..db5ad5052 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -117,7 +117,7 @@ else() - add_definitions(-DPROFILER_ONLY) - set(GPU_TARGETS "" CACHE STRING "" FORCE) - if(GPU_TARGETS) -- message(FATAL_ERROR "For PROFILE_ONLY build, please do not set GPU_TARGETS, use GPU_ARCH = gfx90, gfx94, gfx10, or gfx11") -+ message(FATAL_ERROR "For PROFILE_ONLY build, please do not set GPU_TARGETS, use GPU_ARCH = gfx90, gfx94, gfx10, gfx11 or gfx12") - endif() - if(GPU_ARCH MATCHES "gfx90") - rocm_check_target_ids(DEFAULT_GPU_TARGETS TARGETS "gfx908;gfx90a") -@@ -127,8 +127,10 @@ else() - rocm_check_target_ids(DEFAULT_GPU_TARGETS TARGETS "gfx1030") - elseif(GPU_ARCH MATCHES "gfx11") - rocm_check_target_ids(DEFAULT_GPU_TARGETS TARGETS "gfx1100;gfx1101;gfx1102") -+ elseif(GPU_ARCH MATCHES "gfx12") -+ rocm_check_target_ids(DEFAULT_GPU_TARGETS TARGETS "gfx1200;gfx1201") - else() -- message(FATAL_ERROR "For PROFILE_ONLY build, please specify GPU_ARCH as gfx90, gfx94, gfx10, or gfx11") -+ message(FATAL_ERROR "For PROFILE_ONLY build, please specify GPU_ARCH as gfx90, gfx94, gfx10, gfx11 or gfx12") - endif() - set(GPU_TARGETS "${DEFAULT_GPU_TARGETS}" CACHE STRING " " FORCE) - endif() -diff --git a/Jenkinsfile b/Jenkinsfile -index 75800bfc9..b72e2ca4e 100644 ---- a/Jenkinsfile -+++ b/Jenkinsfile -@@ -493,6 +493,7 @@ def Build_CK(Map conf=[:]){ - - def variant = env.STAGE_NAME - def retimage -+ - gitStatusWrapper(credentialsId: "${env.status_wrapper_creds}", gitHubContext: "Jenkins - ${variant}", account: 'ROCm', repo: 'composable_kernel') { - try { - (retimage, image) = getDockerImage(conf) -@@ -660,9 +661,6 @@ CRON_SETTINGS = BRANCH_NAME == "develop" ? '''0 23 * * * % RUN_FULL_QA=true;ROCM - - pipeline { - agent none -- triggers { -- parameterizedCron(CRON_SETTINGS) -- } - options { - parallelsAlwaysFailFast() - } -diff --git a/cmake/EnableCompilerWarnings.cmake b/cmake/EnableCompilerWarnings.cmake -index 8654170b3..42070051b 100644 ---- a/cmake/EnableCompilerWarnings.cmake -+++ b/cmake/EnableCompilerWarnings.cmake -@@ -66,7 +66,7 @@ else() - -Wunreachable-code - -Wunused - -Wno-reserved-identifier -- -Werror -+ -Werror - -Wno-option-ignored - -Wsign-compare - -Wno-extra-semi-stmt -diff --git a/example/01_gemm/gemm_wmma_fp16.cpp b/example/01_gemm/gemm_wmma_fp16.cpp -index 8c52e4f7d..f8afe8d6d 100644 ---- a/example/01_gemm/gemm_wmma_fp16.cpp -+++ b/example/01_gemm/gemm_wmma_fp16.cpp -@@ -23,45 +23,45 @@ static constexpr auto GemmDefault = ck::tensor_operation::device::GemmSpecializa - - // clang-format off - using DeviceGemmInstance = ck::tensor_operation::device::DeviceGemmWmma_CShuffle -- < ALayout, -- BLayout, -- CLayout, -- ADataType, -+ < ALayout, -+ BLayout, -+ CLayout, -+ ADataType, - BDataType, -- CDataType, -- AccDataType, -- CShuffleDataType, -- AElementOp, -- BElementOp, -- CElementOp, -- GemmDefault, -+ CDataType, -+ AccDataType, -+ CShuffleDataType, -+ AElementOp, -+ BElementOp, -+ CElementOp, -+ GemmDefault, - 1, // Prefetch stage - 128, // BlockSize - 64, // MPerBlock - 128, // NPerBlock - 64, // KPerBlock -- 8, // K1 -+ 2, // K1 - 16, // MPerWmma - 16, // NPerWmma - 2, // M-Repeat // M-PerWmma / M-Repeat = M-Wave - 4, // N-Repeat // N-PerWmma / N-Repeat = N-Wave -- S<4, 32, 1>, -- S<1, 0, 2>, -- S<1, 0, 2>, -- 2, -- 8, -- 8, -- true, -- S<4, 32, 1>, -- S<1, 0, 2>, -- S<1, 0, 2>, -- 2, -- 8, -- 8, -- true, -+ S<4, 32, 1>, -+ S<1, 0, 2>, -+ S<1, 0, 2>, -+ 2, -+ 2, -+ 2, -+ true, -+ S<4, 32, 1>, -+ S<1, 0, 2>, -+ S<1, 0, 2>, -+ 2, -+ 2, -+ 2, -+ true, - 1, // C shuffle (M Repeat) Per store - 1, // C shuffle (N Repeat) Per store -- S<1, 32, 1, 4>, -+ S<1, 32, 1, 4>, - 8>; - // clang-format on - -diff --git a/example/01_gemm/run_gemm_example.inc b/example/01_gemm/run_gemm_example.inc -index b04e4e53a..cb15186c3 100644 ---- a/example/01_gemm/run_gemm_example.inc -+++ b/example/01_gemm/run_gemm_example.inc -@@ -159,7 +159,7 @@ bool run_gemm(const ProblemType& problem_size, const ExecutionConfig& config) - ck::utils::FillUniformDistributionIntegerValue{-5.f, 5.f}(b_k_n); - break; - case 4: -- ck::utils::FillUniformDistributionIntegerValue{1.f, 1.f}(a_m_k); -+ ck::utils::FillUniformDistributionIntegerValue{-5.f, 5.f}(a_m_k); - ck::utils::FillUniformDistributionIntegerValue{1.f, 1.f}(b_k_n); - break; - case 5: -diff --git a/example/04_gemm_add_add_fastgelu/CMakeLists.txt b/example/04_gemm_add_add_fastgelu/CMakeLists.txt -index ab19f819e..be47665a2 100644 ---- a/example/04_gemm_add_add_fastgelu/CMakeLists.txt -+++ b/example/04_gemm_add_add_fastgelu/CMakeLists.txt -@@ -24,4 +24,4 @@ foreach(gpu IN LISTS GPU_TARGETS) - add_example_dependencies(example_gemm_add_add_fastgelu_xdl example_gemm_add_add_fastgelu_xdl_lds_direct_load_fp32) - set(target 1) - endif() --endforeach() -\ No newline at end of file -+endforeach() -diff --git a/example/29_batched_gemm_bias_e_permute/batched_gemm_bias_e_permute_wmma_fp16.cpp b/example/29_batched_gemm_bias_e_permute/batched_gemm_bias_e_permute_wmma_fp16.cpp -index 2bbf430c4..f556be887 100644 ---- a/example/29_batched_gemm_bias_e_permute/batched_gemm_bias_e_permute_wmma_fp16.cpp -+++ b/example/29_batched_gemm_bias_e_permute/batched_gemm_bias_e_permute_wmma_fp16.cpp -@@ -83,14 +83,14 @@ using DeviceOpInstanceKKNN = - 2, - 4, - 4, -- true, -+ false, - S<4, 32, 1>, - S<1, 0, 2>, - S<1, 0, 2>, - 2, - 4, - 4, -- true, -+ false, - 1, - 1, - S<1, 64, 1, 2>, -diff --git a/example/32_batched_gemm_scale_softmax_gemm/cross_attention_forward_wmma_fp16.cpp b/example/32_batched_gemm_scale_softmax_gemm/cross_attention_forward_wmma_fp16.cpp -index 4c92c5497..fac19f8b5 100644 ---- a/example/32_batched_gemm_scale_softmax_gemm/cross_attention_forward_wmma_fp16.cpp -+++ b/example/32_batched_gemm_scale_softmax_gemm/cross_attention_forward_wmma_fp16.cpp -@@ -71,7 +71,7 @@ static constexpr auto TensorSpecC = ck::tensor_operation::device::TensorSpecial - #define CK_MHA_USE_WAVE_1 - #define CK_MHA_USE_WAVE_2 - #define CK_MHA_USE_WAVE_4 --#define CK_MHA_USE_WAVE_8 -+//#define CK_MHA_USE_WAVE_8 - using DeviceMHAFactory = - std::tuple< - #ifdef CK_MHA_USE_WAVE_1 -@@ -277,10 +277,10 @@ using DeviceMHAFactory = - S<2, 8, 8>, S<0, 2, 1>, S<0, 2, 1>, 1, 2, 1, false, - // CShuffleBlockTransfer MN - 1, 1, S<1, 64, 1, 2>, 8, -- MaskingSpec>, -+ MaskingSpec> - #endif - #ifdef CK_MHA_USE_WAVE_8 -- ck::tensor_operation::device::DeviceBatchedGemmSoftmaxGemmPermute_Wmma_CShuffle< -+ ,ck::tensor_operation::device::DeviceBatchedGemmSoftmaxGemmPermute_Wmma_CShuffle< - NumDimG, NumDimM, NumDimN, NumDimK, NumDimO, - ADataType, B0DataType, B1DataType, CDataType, Acc0BiasDataType, Acc0DataType, Acc1BiasDataType, Acc1DataType, CShuffleDataType, - AElementOp, B0ElementOp, Acc0ElementOp, B1ElementOp, CElementOp, -diff --git a/example/32_batched_gemm_scale_softmax_gemm/self_attention_forward_wmma_fp16.cpp b/example/32_batched_gemm_scale_softmax_gemm/self_attention_forward_wmma_fp16.cpp -index 8e037272b..d463cc871 100644 ---- a/example/32_batched_gemm_scale_softmax_gemm/self_attention_forward_wmma_fp16.cpp -+++ b/example/32_batched_gemm_scale_softmax_gemm/self_attention_forward_wmma_fp16.cpp -@@ -71,7 +71,7 @@ static constexpr auto TensorSpecC = ck::tensor_operation::device::TensorSpecial - #define CK_MHA_USE_WAVE_1 - #define CK_MHA_USE_WAVE_2 - #define CK_MHA_USE_WAVE_4 --#define CK_MHA_USE_WAVE_8 -+//#define CK_MHA_USE_WAVE_8 - using DeviceMHAFactory = - std::tuple< - #ifdef CK_MHA_USE_WAVE_1 -@@ -277,10 +277,10 @@ using DeviceMHAFactory = - S<2, 8, 8>, S<0, 2, 1>, S<0, 2, 1>, 1, 2, 1, false, - // CShuffleBlockTransfer MN - 1, 1, S<1, 64, 1, 2>, 8, -- MaskingSpec>, -+ MaskingSpec> - #endif - #ifdef CK_MHA_USE_WAVE_8 -- ck::tensor_operation::device::DeviceBatchedGemmSoftmaxGemmPermute_Wmma_CShuffle< -+ ,ck::tensor_operation::device::DeviceBatchedGemmSoftmaxGemmPermute_Wmma_CShuffle< - NumDimG, NumDimM, NumDimN, NumDimK, NumDimO, - ADataType, B0DataType, B1DataType, CDataType, Acc0BiasDataType, Acc0DataType, Acc1BiasDataType, Acc1DataType, CShuffleDataType, - AElementOp, B0ElementOp, Acc0ElementOp, B1ElementOp, CElementOp, -diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt -index 5465adb77..7534bff3b 100644 ---- a/example/CMakeLists.txt -+++ b/example/CMakeLists.txt -@@ -60,7 +60,7 @@ function(add_example_executable EXAMPLE_NAME FILE_NAME) - endforeach() - #Do not build any WMMA examples if gfx11 targets are not on the list - foreach(source IN LISTS FILE_NAME) -- if(NOT GPU_TARGETS MATCHES "gfx11" AND source MATCHES "_wmma") -+ if(NOT GPU_TARGETS MATCHES "gfx11" AND NOT GPU_TARGETS MATCHES "gfx12" AND source MATCHES "_wmma") - message("removing wmma example ${source} ") - list(REMOVE_ITEM FILE_NAME "${source}") - endif() -@@ -134,7 +134,7 @@ function(add_example_executable_no_testing EXAMPLE_NAME FILE_NAME) - endforeach() - #Do not build any WMMA examples if gfx11 targets are not on the list - foreach(source IN LISTS FILE_NAME) -- if(NOT GPU_TARGETS MATCHES "gfx11" AND source MATCHES "_wmma") -+ if(NOT GPU_TARGETS MATCHES "gfx11" AND NOT GPU_TARGETS MATCHES "gfx12" AND source MATCHES "_wmma") - message("removing wmma example ${source} ") - list(REMOVE_ITEM FILE_NAME "${source}") - endif() -diff --git a/include/ck/ck.hpp b/include/ck/ck.hpp -index 55f562061..69a7abf62 100644 ---- a/include/ck/ck.hpp -+++ b/include/ck/ck.hpp -@@ -69,6 +69,9 @@ CK_DECLARE_ENV_VAR_BOOL(CK_LOGGING) - #if defined(__gfx1100__) || defined(__gfx1101__) || defined(__gfx1102__) || defined(__gfx1103__) - #define __gfx11__ - #endif -+#if defined(__gfx1200__) || defined(__gfx1201__) -+#define __gfx12__ -+#endif - - // buffer resource - #ifndef __HIP_DEVICE_COMPILE__ // for host code -@@ -77,7 +80,7 @@ CK_DECLARE_ENV_VAR_BOOL(CK_LOGGING) - #define CK_BUFFER_RESOURCE_3RD_DWORD 0x00020000 - #elif defined(__gfx103__) - #define CK_BUFFER_RESOURCE_3RD_DWORD 0x31014000 --#elif defined(__gfx11__) -+#elif defined(__gfx11__) || defined(__gfx12__) - #define CK_BUFFER_RESOURCE_3RD_DWORD 0x31004000 - #endif - -@@ -89,7 +92,7 @@ CK_DECLARE_ENV_VAR_BOOL(CK_LOGGING) - #define CK_USE_AMD_V_FMAC_F32 - #define CK_USE_AMD_V_DOT2_F32_F16 - #define CK_USE_AMD_V_DOT4_I32_I8 --#elif defined(__gfx11__) -+#elif defined(__gfx11__) || defined(__gfx12__) - #define CK_USE_AMD_V_FMAC_F32 - #define CK_USE_AMD_V_DOT2_F32_F16 - #define CK_USE_AMD_V_DOT4_I32_I8_GFX11 -@@ -110,13 +113,6 @@ CK_DECLARE_ENV_VAR_BOOL(CK_LOGGING) - #define CK_USE_AMD_MFMA_GFX940 - #endif - --// WMMA instruction --#ifndef __HIP_DEVICE_COMPILE__ // for host code --#define CK_USE_AMD_WMMA --#elif defined(__gfx11__) // for GPU code --#define CK_USE_AMD_WMMA --#endif -- - // buffer load - #define CK_USE_AMD_BUFFER_LOAD 1 - -diff --git a/include/ck/host_utility/device_prop.hpp b/include/ck/host_utility/device_prop.hpp -index 116bb3ea0..83af2efe8 100644 ---- a/include/ck/host_utility/device_prop.hpp -+++ b/include/ck/host_utility/device_prop.hpp -@@ -84,4 +84,9 @@ inline bool is_gfx11_supported() - ck::get_device_name() == "gfx1102" || ck::get_device_name() == "gfx1103"; - } - -+inline bool is_gfx12_supported() -+{ -+ return ck::get_device_name() == "gfx1200" || ck::get_device_name() == "gfx1201"; -+} -+ - } // namespace ck -diff --git a/include/ck/tensor_operation/gpu/block/blockwise_gemm_wmma.hpp b/include/ck/tensor_operation/gpu/block/blockwise_gemm_wmma.hpp -index f8ee283c6..7eb7d42eb 100644 ---- a/include/ck/tensor_operation/gpu/block/blockwise_gemm_wmma.hpp -+++ b/include/ck/tensor_operation/gpu/block/blockwise_gemm_wmma.hpp -@@ -13,6 +13,504 @@ - - namespace ck { - -+#ifdef __gfx12__ -+template -+/* Option: Read from LDS, big buffer hold all threads required data -+ * Source -+ * A: K0PerBlock x MPerBlock x K1 -+ * B: K0PerBlock x NPerBlock x K1 -+ * Destination -+ * C, non-transpose -+ * thread level: MRepeat x NRepeat x MAccVgprs -+ * block level: MRepeat x MWave x MSubGroup x NRepeat x NWave x NThreadPerSubGroup x MAccVgprs -+ * KPACK == WMMA_K = 16 -+ * -+ * Option: Read from VMEM, small buffer hold each thread own required data (Skip LDS) -+ * Source: -+ * A(if skip LDS): MRepeat x KPack -+ * B(if skip LDS): NRepeat x KPack -+ * Destination -+ * C, non-transpose -+ * block level: MRepeat x MWave x MSubGroup x NRepeat x NWave x NThreadPerSubGroup x MAccVgprs -+ */ -+struct BlockwiseGemmWMMA -+{ -+ static constexpr auto I0 = Number<0>{}; -+ static constexpr auto I1 = Number<1>{}; -+ static constexpr auto I2 = Number<2>{}; -+ static constexpr auto I3 = Number<3>{}; -+ static constexpr auto I4 = Number<4>{}; -+ static constexpr auto I5 = Number<5>{}; -+ static constexpr auto WmmaK = Number<16>{}; -+ -+ using ThisThreadBlock = ThisThreadBlock; -+ -+ // Hardcode of WaveSize, since current HIP Runtime(5.4.0-10984) could not return correct one. -+ static constexpr index_t WaveSize = 32; -+ -+ // When use LDS, each Row(16 consecutive lanes) read whole data from source buffer -+ // When not use LDS, each Row read half of whole data from source buffer, exchange the data via -+ // permutation -+ static constexpr index_t A_KRow = 2; -+ static constexpr index_t B_KRow = 2; -+ -+ static constexpr index_t A_K1 = ABlockDesc{}.GetLength(I5); -+ static constexpr index_t B_K1 = BBlockDesc{}.GetLength(I5); -+ -+ static constexpr auto wmma_gemm = -+ WmmaGemm{}; -+ -+ static constexpr index_t MWaves = MPerBlock / (MRepeat * MPerWMMA); -+ static constexpr index_t NWaves = NPerBlock / (NRepeat * NPerWMMA); -+ -+ StaticBufferTupleOfVector -+ c_thread_buf_; -+ -+ __host__ __device__ constexpr auto& GetCThreadBuffer() { return c_thread_buf_; } -+ -+ __device__ static auto GetWaveIdx() -+ { -+ const index_t thread_id = ThisThreadBlock::GetThreadId(); -+ -+ constexpr auto threadid_to_wave_idx_adaptor = make_single_stage_tensor_adaptor( -+ make_tuple(make_merge_transform(make_tuple(MWaves, NWaves, WaveSize))), -+ make_tuple(Sequence<0, 1, 2>{}), -+ make_tuple(Sequence<0>{})); -+ -+ return threadid_to_wave_idx_adaptor.CalculateBottomIndex(make_multi_index(thread_id)); -+ } -+ -+ // Default, Block buffer in LDS, thread level offset enabled -+ __device__ static auto CalculateAThreadOriginDataIndex() -+ { -+ if constexpr(AEnableLds) -+ { -+ const auto wave_idx = GetWaveIdx(); -+ const auto waveId_m = wave_idx[I0]; -+ const auto WMMA_a_idx = wmma_gemm.CalculateAThreadOriginDataIndex(); -+ -+ // |KRepeat |MRepeat|MWave |KRow |MLane |KPack -+ return make_tuple(0, 0, waveId_m, wmma_gemm.GetSubGroupId(), WMMA_a_idx, 0); -+ } -+ else -+ { -+ return make_tuple(0, 0, 0, 0, 0, 0); -+ } -+ } -+ -+ __device__ static auto CalculateBThreadOriginDataIndex() -+ { -+ if constexpr(BEnableLds) -+ { -+ const auto wave_idx = GetWaveIdx(); -+ const auto waveId_n = wave_idx[I1]; -+ const auto WMMA_b_idx = wmma_gemm.CalculateBThreadOriginDataIndex(); -+ -+ // |KRepeat |NRepeat|Nwave |KRow |NLane |KPack -+ return make_tuple(0, 0, waveId_n, wmma_gemm.GetSubGroupId(), WMMA_b_idx, 0); -+ } -+ else -+ { -+ return make_tuple(0, 0, 0, 0, 0, 0); -+ } -+ } -+ -+ template -+ __device__ static auto CalculateCThreadOriginDataIndex(Number, Number) -+ { -+ const auto wave_idx = GetWaveIdx(); -+ -+ const auto waveId_m = wave_idx[I0]; -+ const auto waveId_n = wave_idx[I1]; -+ -+ const auto blk_idx = wmma_gemm.GetBeginOfThreadBlk(); -+ -+ constexpr auto mrepeat_mwave_mperWMMA_to_m_adaptor = make_single_stage_tensor_adaptor( -+ make_tuple(make_unmerge_transform(make_tuple(MRepeat, MWaves, MPerWMMA))), -+ make_tuple(Sequence<0>{}), -+ make_tuple(Sequence<0, 1, 2>{})); -+ -+ constexpr auto nrepeat_nwave_nperWMMA_to_n_adaptor = make_single_stage_tensor_adaptor( -+ make_tuple(make_unmerge_transform(make_tuple(NRepeat, NWaves, NPerWMMA))), -+ make_tuple(Sequence<0>{}), -+ make_tuple(Sequence<0, 1, 2>{})); -+ -+ const index_t c_thread_m = mrepeat_mwave_mperWMMA_to_m_adaptor.CalculateBottomIndex( -+ make_tuple(m0, waveId_m, blk_idx[I0]))[I0]; -+ const index_t c_thread_n = nrepeat_nwave_nperWMMA_to_n_adaptor.CalculateBottomIndex( -+ make_tuple(n0, waveId_n, blk_idx[I1]))[I0]; -+ -+ return make_tuple(c_thread_m, c_thread_n); -+ } -+ -+ template -+ __device__ static auto CalculateCThreadOriginDataIndex7D(Number, Number) -+ { -+ const auto wave_idx = GetWaveIdx(); -+ -+ const auto waveId_m = wave_idx[I0]; -+ const auto waveId_n = wave_idx[I1]; -+ -+ const auto blk_idx = wmma_gemm.GetBeginOfThreadBlk3D(); -+ -+ return make_tuple( -+ Number{}, waveId_m, blk_idx[I0], Number{}, waveId_n, blk_idx[I1], blk_idx[I2]); -+ } -+ -+ using Tuple6 = decltype(CalculateAThreadOriginDataIndex()); -+ __host__ __device__ BlockwiseGemmWMMA(Tuple6 a_origin = CalculateAThreadOriginDataIndex(), -+ Tuple6 b_origin = CalculateBThreadOriginDataIndex()) -+ : a_thread_copy_(a_origin), b_thread_copy_(b_origin) -+ { -+ static_assert(ABlockDesc::IsKnownAtCompileTime() && BBlockDesc::IsKnownAtCompileTime(), -+ "wrong! Desc should be known at compile-time"); -+ -+ static_assert(ThisThreadBlock::GetNumOfThread() == MWaves * NWaves * WaveSize, -+ "ThisThreadBlock::GetNumOfThread() != MWaves * NWaves * WaveSize\n"); -+ -+ static_assert(MPerBlock % (MPerWMMA * MRepeat) == 0 && -+ NPerBlock % (NPerWMMA * NRepeat) == 0, -+ "wrong!"); -+ } -+ -+ // transposed WMMA output C' = B' * A' -+ __host__ __device__ static constexpr auto -+ GetCThreadDescriptor_MRepeat_MWave_MThreadPerSubGroup_NRepeat_NWave_NSubGroup_NAccVgprs() -+ { -+ constexpr auto c_msubgroup_nthreadpersubgroup_maccvgprs_tblk_lens = -+ wmma_gemm.GetCMSubGroupNThreadPerSubGroupMAccVgprsThreadBlkLengths(); -+ -+ constexpr auto NAccVgprs = c_msubgroup_nthreadpersubgroup_maccvgprs_tblk_lens[I2]; -+ -+ return make_naive_tensor_descriptor_packed( -+ // |MRepeat |MWave |MSubGroup |NRepeat |NWave -+ // |NThreadPerSubGroup |MAccVgprs -+ make_tuple(Number{}, I1, I1, Number{}, I1, I1, NAccVgprs)); -+ } -+ -+ // Thread level, register decriptor. Vector-write -+ __host__ __device__ static constexpr auto -+ GetCThreadDescriptor_MRepeat_MWave_MSubGroup_NRepeat_NWave_NThreadPerSubGroup_MAccVgprs() -+ { -+ constexpr auto c_msubgroup_nthreadpersubgroup_maccvgprs_tblk_lens = -+ wmma_gemm.GetCMSubGroupNThreadPerSubGroupMAccVgprsThreadBlkLengths(); -+ -+ constexpr auto MAccVgprs = c_msubgroup_nthreadpersubgroup_maccvgprs_tblk_lens[I2]; -+ constexpr auto AccStride = c_msubgroup_nthreadpersubgroup_maccvgprs_tblk_lens[I3]; -+ return make_naive_tensor_descriptor( -+ // |MRepeat |MWave |MSubGroup |NRepeat |NWave -+ // |NThreadPerSubGroup |MAccVgprs -+ make_tuple(Number{}, I1, I1, Number{}, I1, I1, MAccVgprs), -+ make_tuple(Number{} * MAccVgprs * AccStride, -+ Number{} * MAccVgprs * AccStride, -+ Number{} * MAccVgprs * AccStride, -+ MAccVgprs * AccStride, -+ MAccVgprs * AccStride, -+ MAccVgprs * AccStride, -+ AccStride)); -+ } -+ -+ template -+ __host__ __device__ static constexpr auto -+ MakeCGridDescriptor_MBlockxRepeat_MWave_MSubGroup_NBlockxRepeat_NWave_NThreadPerSubGroup_MAccVgprs( -+ const CGridDesc_M_N& c_grid_desc_m_n) -+ { -+ const auto M = c_grid_desc_m_n.GetLength(I0); -+ const auto N = c_grid_desc_m_n.GetLength(I1); -+ -+ const auto c_grid_desc_mblockxrepeat_mwave_mperwmma_nblockxrepeat_nwave_nperwmma = -+ transform_tensor_descriptor( -+ c_grid_desc_m_n, -+ make_tuple( -+ make_unmerge_transform(make_tuple(M / (MWaves * MPerWMMA), MWaves, MPerWMMA)), -+ make_unmerge_transform(make_tuple(N / (NWaves * NPerWMMA), NWaves, NPerWMMA))), -+ make_tuple(Sequence<0>{}, Sequence<1>{}), -+ make_tuple(Sequence<0, 1, 2>{}, Sequence<3, 4, 5>{})); -+ -+ return wmma_gemm -+ .MakeCDesc_MBlockxRepeat_MWave_MSubGroup_NBlockxRepeat_NWave_NThreadPerSubGroup_MAccVgprs( -+ c_grid_desc_mblockxrepeat_mwave_mperwmma_nblockxrepeat_nwave_nperwmma); -+ } -+ -+ // transposed WMMA output C' = B' * A' -+ __host__ __device__ static constexpr auto -+ GetCBlockDescriptor_MRepeat_MWave_MThreadPerSubGroup_NRepeat_NWave_NSubGroup_NAccVgprs() -+ { -+ constexpr auto c_block_desc_mrepeat_mwave_mperwmma_nrepeat_nwave_nperwmma = -+ make_naive_tensor_descriptor_packed(make_tuple(Number{}, -+ Number{}, -+ Number{}, -+ Number{}, -+ Number{}, -+ Number{})); -+ -+ return wmma_gemm -+ .MakeCDesc_MBlockxRepeat_MWave_MThreadPerSubGroup_NBlockxRepeat_NWave_NSubGroup_NAccVgprs( -+ c_block_desc_mrepeat_mwave_mperwmma_nrepeat_nwave_nperwmma); -+ } -+ -+ // Provide dimension size -+ __host__ __device__ static constexpr auto -+ GetCBlockDescriptor_MRepeat_MWave_MSubGroup_NRepeat_NWave_NThreadPerSubGroup_MAccVgprs() -+ { -+ constexpr auto c_block_desc_mrepeat_mwave_mperwmma_nrepeat_nwave_nperwmma = -+ make_naive_tensor_descriptor_packed(make_tuple(Number{}, -+ Number{}, -+ Number{}, -+ Number{}, -+ Number{}, -+ Number{})); -+ -+ return wmma_gemm -+ .MakeCDesc_MBlockxRepeat_MWave_MSubGroup_NBlockxRepeat_NWave_NThreadPerSubGroup_MAccVgprs( -+ c_block_desc_mrepeat_mwave_mperwmma_nrepeat_nwave_nperwmma); -+ } -+ -+ // Describe how data allocated in thread copy src buffer -+ // M0_M1_M2 = MRepeat_MWave_MPerWmma, N0_N1_N2 = NRepeat_NWave_NPerWmma -+ static constexpr ABlockDesc a_block_desc_k0_m0_m1_m2_k1; -+ static constexpr BBlockDesc b_block_desc_k0_n0_n1_n2_k1; -+ -+ template -+ __device__ void Run(const ABlockBuffer& a_block_buf, -+ const BBlockBuffer& b_block_buf, -+ CThreadBuffer& c_thread_buf) const -+ { -+ auto a_thread_buf = make_static_buffer( -+ a_thread_desc_.GetElementSpaceSize()); -+ auto b_thread_buf = make_static_buffer( -+ b_thread_desc_.GetElementSpaceSize()); -+ -+ static_assert(KPack % (A_K1 * A_KRow) == 0, ""); -+ static_assert(KPack % (B_K1 * B_KRow) == 0, ""); -+ -+ // basic intrinsic to determine loopover direction -+ if constexpr(MRepeat < NRepeat) -+ { -+ static_for<0, KPerBlock / KPack, 1>{}( -+ [&](auto k) { // k=0,1,2 instead of k=0,kpack*1, ... -+ static_for<0, MRepeat, 1>{}([&](auto m0) { -+ // read A -+ a_thread_copy_.Run( -+ a_block_desc_k0_m0_m1_m2_k1, -+ make_tuple(Number{}, m0, I0, I0, I0, I0), -+ a_block_buf, -+ a_thread_desc_, -+ make_tuple(I0, m0, I0, I0, I0, I0), -+ a_thread_buf); -+ -+ static_for<0, NRepeat, 1>{}([&](auto n0) { -+ // read B -+ b_thread_copy_.Run( -+ b_block_desc_k0_n0_n1_n2_k1, -+ make_tuple(Number{}, n0, I0, I0, I0, I0), -+ b_block_buf, -+ b_thread_desc_, -+ make_tuple(I0, n0, I0, I0, I0, I0), -+ b_thread_buf); -+ -+ vector_type a_thread_vec; -+ vector_type b_thread_vec; -+ -+ static_for<0, KPack / A_KRow, 1>{}([&](auto i) { -+ a_thread_vec.template AsType()(i) = -+ a_thread_buf[Number{}]; -+ }); -+ -+ static_for<0, KPack / B_KRow, 1>{}([&](auto i) { -+ b_thread_vec.template AsType()(i) = -+ b_thread_buf[Number{}]; -+ }); -+ -+ using wmma_input_type_a = -+ typename vector_type::type; -+ using wmma_input_type_b = -+ typename vector_type::type; -+ -+ constexpr index_t c_offset = -+ c_thread_desc_.CalculateOffset(make_tuple(m0, n0, 0)); -+ -+ wmma_gemm.template Run( -+ a_thread_vec.template AsType(), -+ b_thread_vec.template AsType(), -+ c_thread_buf.GetVectorTypeReference(Number{})); -+ }); -+ }); -+ }); -+ } -+ else -+ { -+ static_for<0, NRepeat, 1>{}([&](auto n0) { -+ static_for<0, MRepeat, 1>{}([&](auto m0) { -+ static_for<0, KPerBlock / KPack, 1>{}([&](auto k) { // k=0,1,2 instead of -+ // k=0,kpack*1, .. -+ // read B -+ b_thread_copy_.Run( -+ b_block_desc_k0_n0_n1_n2_k1, -+ make_tuple(Number{}, n0, I0, I0, I0, I0), -+ b_block_buf, -+ b_thread_desc_, -+ make_tuple(I0, n0, I0, I0, I0, I0), -+ b_thread_buf); -+ // read A -+ a_thread_copy_.Run( -+ a_block_desc_k0_m0_m1_m2_k1, -+ make_tuple(Number{}, m0, I0, I0, I0, I0), -+ a_block_buf, -+ a_thread_desc_, -+ make_tuple(I0, m0, I0, I0, I0, I0), -+ a_thread_buf); -+ -+ vector_type a_thread_vec; -+ vector_type b_thread_vec; -+ -+ static_for<0, KPack / A_KRow, 1>{}([&](auto i) { -+ a_thread_vec.template AsType()(i) = -+ a_thread_buf[Number{}]; -+ }); -+ -+ static_for<0, KPack / B_KRow, 1>{}([&](auto i) { -+ b_thread_vec.template AsType()(i) = -+ b_thread_buf[Number{}]; -+ }); -+ -+ using wmma_input_type_a = -+ typename vector_type::type; -+ using wmma_input_type_b = -+ typename vector_type::type; -+ -+ constexpr index_t c_offset = -+ c_thread_desc_.CalculateOffset(make_tuple(m0, n0, 0)); -+ -+ wmma_gemm.template Run( -+ a_thread_vec.template AsType(), -+ b_thread_vec.template AsType(), -+ c_thread_buf.GetVectorTypeReference(Number{})); -+ }); -+ }); -+ }); -+ } -+ } -+ -+ protected: -+ static constexpr auto a_thread_desc_ = make_naive_tensor_descriptor( -+ make_tuple(Number{}, Number{}, I1, I1, I1, Number{}), -+ make_tuple(Number{}, -+ Number{}, -+ Number{}, -+ Number{}, -+ Number{}, -+ Number<1>{})); -+ -+ static constexpr auto b_thread_desc_ = make_naive_tensor_descriptor( -+ make_tuple(Number{}, Number{}, I1, I1, I1, Number{}), -+ make_tuple(Number{}, -+ Number{}, -+ Number{}, -+ Number{}, -+ Number{}, -+ Number<1>{})); -+ -+ // C[M, N, NumRegWMMA] -+ static constexpr auto c_thread_desc_ = make_naive_tensor_descriptor_packed( -+ make_tuple(Number{}, Number{}, wmma_gemm.GetRegSizePerWmma())); -+ -+ template -+ struct AThreadCopySelector; -+ -+ template <> -+ struct AThreadCopySelector -+ { -+ using type = -+ ThreadwiseTensorSliceTransfer_v4, -+ Sequence<0, 1, 2, 3, 4, 5>, -+ 5, -+ A_K1, -+ A_K1>; -+ }; -+ -+ template <> -+ struct AThreadCopySelector -+ { -+ using type = ThreadwiseTensorSliceTransfer_StaticToStatic_IntraRow< -+ FloatA, -+ FloatA, -+ decltype(a_block_desc_k0_m0_m1_m2_k1), -+ decltype(a_thread_desc_), -+ tensor_operation::element_wise::PassThrough, -+ Sequence, -+ Sequence<0, 1, 2, 3, 4, 5>, -+ 5, -+ A_K1, -+ false>; -+ }; -+ -+ template -+ struct BThreadCopySelector; -+ -+ template <> -+ struct BThreadCopySelector -+ { -+ using type = -+ ThreadwiseTensorSliceTransfer_v4, -+ Sequence<0, 1, 2, 3, 4, 5>, -+ 5, -+ B_K1, -+ B_K1>; -+ }; -+ -+ template <> -+ struct BThreadCopySelector -+ { -+ using type = ThreadwiseTensorSliceTransfer_StaticToStatic_IntraRow< -+ FloatB, -+ FloatB, -+ decltype(b_block_desc_k0_n0_n1_n2_k1), -+ decltype(b_thread_desc_), -+ tensor_operation::element_wise::PassThrough, -+ Sequence, -+ Sequence<0, 1, 2, 3, 4, 5>, -+ 5, -+ B_K1, -+ false>; -+ }; -+ -+ typename AThreadCopySelector::type a_thread_copy_; -+ typename BThreadCopySelector::type b_thread_copy_; -+}; -+#else - template ::type a_thread_copy_; - typename BThreadCopySelector::type b_thread_copy_; - }; -+#endif - - } // namespace ck -diff --git a/include/ck/tensor_operation/gpu/block/blockwise_gemm_xdlops.hpp b/include/ck/tensor_operation/gpu/block/blockwise_gemm_xdlops.hpp -index e5e6245cb..1f7d50429 100644 ---- a/include/ck/tensor_operation/gpu/block/blockwise_gemm_xdlops.hpp -+++ b/include/ck/tensor_operation/gpu/block/blockwise_gemm_xdlops.hpp -@@ -488,7 +488,14 @@ struct BlockwiseGemmXdlopsInterwave_k0mk1_k0nk1_m0n0m1n1m2m3m4n2_v1 - // sync point. - if constexpr(k.value != 0 || KPerInnerLoop == KPerThread) - { -+#ifdef __gfx12__ -+ asm volatile("\ -+ s_barrier_signal -1 \n \ -+ s_barrier_wait -1 \ -+ " ::); -+#else - asm volatile("s_barrier" ::); -+#endif - __builtin_amdgcn_sched_barrier(0); - } - static_for<0, KPerInnerLoop, KPack>{}([&](auto k_) { -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_batched_contraction_multiple_d_wmma_cshuffle.hpp b/include/ck/tensor_operation/gpu/device/impl/device_batched_contraction_multiple_d_wmma_cshuffle.hpp -index a15759559..ab3f3856a 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_batched_contraction_multiple_d_wmma_cshuffle.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_batched_contraction_multiple_d_wmma_cshuffle.hpp -@@ -133,8 +133,13 @@ struct DeviceBatchedContractionMultipleD_Wmma_CShuffle - static constexpr auto NWaves = NPerBlock / (NRepeat * NPerWmma); - static constexpr auto WmmaK = K1 == 16 ? 32 : 16; - -- static constexpr auto AEnableLds_auto = NWaves == 1 ? false : true; -- static constexpr auto BEnableLds_auto = MWaves == 1 ? false : true; -+ static constexpr auto MaxVectorLoadA = K1 * sizeof(ADataType) == 16 ? true : false; -+ static constexpr auto MaxVectorLoadB = K1 * sizeof(BDataType) == 16 ? true : false; -+ -+ static constexpr auto AEnableLds_auto = -+ (NWaves == 1 && (MaxVectorLoadA || MRepeat == 1)) ? false : true; -+ static constexpr auto BEnableLds_auto = -+ (MWaves == 1 && (MaxVectorLoadB || NRepeat == 1)) ? false : true; - - // If true, LDS is used unconditionally - static constexpr auto AEnableLds_manu = false; -@@ -829,7 +834,7 @@ struct DeviceBatchedContractionMultipleD_Wmma_CShuffle - - static bool IsSupportedArgument(const Argument& arg) - { -- if(ck::is_gfx11_supported()) -+ if(ck::is_gfx11_supported() || ck::is_gfx12_supported()) - { - if constexpr(!(is_same_v || is_same_v)) - { -@@ -869,11 +874,15 @@ struct DeviceBatchedContractionMultipleD_Wmma_CShuffle - } - else - { -- if(!(arg.a_kz_stride_ == 1 && -- arg.a_grid_desc_.GetLength(I2) % ABlockTransferSrcScalarPerVector == 0)) -+ if(!(arg.a_kz_stride_ == 1)) - { -- printf("DeviceOp: Vector Access A-k check failure\n"); -- return false; -+ index_t LastK = -+ AEnableLds ? arg.a_grid_desc_.GetLength(I2) : arg.a_grid_desc_.GetLength(I6); -+ if(LastK % ABlockTransferSrcScalarPerVector == 0) -+ { -+ printf("DeviceOp: Vector Access A-k check failure\n"); -+ return false; -+ } - } - } - -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_batched_gemm_multiple_d_dl.hpp b/include/ck/tensor_operation/gpu/device/impl/device_batched_gemm_multiple_d_dl.hpp -index 8fd14afc0..1b487502f 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_batched_gemm_multiple_d_dl.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_batched_gemm_multiple_d_dl.hpp -@@ -70,8 +70,9 @@ __global__ void - const ComputePtrOffsetOfBatch compute_ptr_offset_of_batch, - const Block2CTileMap block_2_ctile_map) - { --#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx906__) || defined(__gfx908__) || \ -- defined(__gfx90a__) || defined(__gfx94__) || defined(__gfx103__) || defined(__gfx11__)) -+#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx906__) || defined(__gfx908__) || \ -+ defined(__gfx90a__) || defined(__gfx94__) || defined(__gfx103__) || defined(__gfx11__) || \ -+ defined(__gfx12__)) - - const index_t num_blocks_per_batch = - __builtin_amdgcn_readfirstlane(get_grid_size() / batch_count); -@@ -648,7 +649,7 @@ struct DeviceBatchedGemmMultipleD_Dl : public DeviceBatchedGemmMultiD || is_same_v)) - { -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_contraction_multiple_d_xdl_cshuffle.hpp b/include/ck/tensor_operation/gpu/device/impl/device_contraction_multiple_d_xdl_cshuffle.hpp -index 9d5b74be6..017d28641 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_contraction_multiple_d_xdl_cshuffle.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_contraction_multiple_d_xdl_cshuffle.hpp -@@ -601,9 +601,7 @@ struct DeviceContractionMultipleD_Xdl_CShuffle - return false; - } - -- if(ck::get_device_name() != "gfx90a" && ck::get_device_name() != "gfx940" && -- ck::get_device_name() != "gfx941" && ck::get_device_name() != "gfx942" && -- std::is_same::value) -+ if(!ck::is_lds_direct_load_supported() && std::is_same::value) - { - return false; - } -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_convnd_bwd_data_nwc_kxc_nwk_dl.hpp b/include/ck/tensor_operation/gpu/device/impl/device_convnd_bwd_data_nwc_kxc_nwk_dl.hpp -index b84e18130..1edae33be 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_convnd_bwd_data_nwc_kxc_nwk_dl.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_convnd_bwd_data_nwc_kxc_nwk_dl.hpp -@@ -1393,7 +1393,7 @@ struct DeviceConvNdBwdDataNwcKxcNwk_Dl - { - // check device - if(!(ck::get_device_name() == "gfx906" || ck::is_gfx103_supported() || -- ck::is_gfx11_supported())) -+ ck::is_gfx11_supported() || ck::is_gfx12_supported())) - { - return false; - } -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_fpAintB_gemm_wmma.hpp b/include/ck/tensor_operation/gpu/device/impl/device_fpAintB_gemm_wmma.hpp -index bf96324d0..553143e28 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_fpAintB_gemm_wmma.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_fpAintB_gemm_wmma.hpp -@@ -509,7 +509,7 @@ struct DeviceFpAintBGemm_Wmma_CShuffle : public DeviceGemm_dequantB || is_same_v || - is_same_v)) -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_gemm_dl.hpp b/include/ck/tensor_operation/gpu/device/impl/device_gemm_dl.hpp -index b1784b385..eb0fb55f5 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_gemm_dl.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_gemm_dl.hpp -@@ -536,7 +536,7 @@ struct DeviceGemmDl : public DeviceGemm || is_same_v)) - { -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_gemm_wmma.hpp b/include/ck/tensor_operation/gpu/device/impl/device_gemm_wmma.hpp -index 93ab8a7e1..a7cc546f5 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_gemm_wmma.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_gemm_wmma.hpp -@@ -84,14 +84,21 @@ struct DeviceGemmWmma_CShuffle : public DeviceGemm{}; - -- static constexpr auto MWaves = MPerBlock / (MRepeat * MPerWmma); -- static constexpr auto NWaves = NPerBlock / (NRepeat * NPerWmma); -- static constexpr auto WmmaK = K1 == 16 ? 32 : 16; -- -- static constexpr auto AEnableLds_auto = -- (NWaves == 1 && is_same::value) ? false : true; -+ static constexpr auto MWaves = MPerBlock / (MRepeat * MPerWmma); -+ static constexpr auto NWaves = NPerBlock / (NRepeat * NPerWmma); -+ static constexpr auto WmmaK = K1 == 16 ? 32 : 16; -+ static constexpr auto MaxVectorLoadA = K1 * sizeof(ADataType) == 16 ? true : false; -+ static constexpr auto MaxVectorLoadB = K1 * sizeof(BDataType) == 16 ? true : false; -+ -+ static constexpr auto AEnableLds_auto = (NWaves == 1 && (MaxVectorLoadA || MRepeat == 1) && -+ is_same::value) -+ ? false -+ : true; - static constexpr auto BEnableLds_auto = -- (MWaves == 1 && is_same::value) ? false : true; -+ (MWaves == 1 && (MaxVectorLoadB || NRepeat == 1) && -+ is_same::value) -+ ? false -+ : true; - - // If true, LDS is used unconditionally - static constexpr auto AEnableLds_manu = false; -@@ -443,7 +450,7 @@ struct DeviceGemmWmma_CShuffle : public DeviceGemm || is_same_v || - is_same_v)) -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_data_multiple_d_wmma_cshuffle.hpp b/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_data_multiple_d_wmma_cshuffle.hpp -index 6f74838fb..6bb5d431c 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_data_multiple_d_wmma_cshuffle.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_data_multiple_d_wmma_cshuffle.hpp -@@ -629,7 +629,7 @@ struct DeviceGroupedConvBwdDataMultipleD_Wmma_CShuffle - static bool IsSupportedArgument(const Argument& arg) - { - // check device -- if(ck::is_gfx11_supported()) -+ if(ck::is_gfx11_supported() || ck::is_gfx12_supported()) - { - if constexpr(!(is_same_v || is_same_v)) - { -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_weight_dl.hpp b/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_weight_dl.hpp -index bd264a3c8..7047e1bda 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_weight_dl.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_weight_dl.hpp -@@ -48,8 +48,9 @@ __global__ void - const Block2CTileMap block_2_ctile_map, - const ComputePtrOffsetOfBatch compute_ptr_offset_of_batch) - { --#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx906__) || defined(__gfx103__) || \ -- defined(__gfx90a__) || defined(__gfx908__) || defined(__gfx94__) || defined(__gfx11__)) -+#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx906__) || defined(__gfx103__) || \ -+ defined(__gfx90a__) || defined(__gfx908__) || defined(__gfx94__) || defined(__gfx11__) || \ -+ defined(__gfx12__)) - const index_t num_blocks_per_batch = - __builtin_amdgcn_readfirstlane(get_grid_size() / batch_count); - const index_t g_idx = __builtin_amdgcn_readfirstlane(get_block_1d_id() / num_blocks_per_batch); -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_weight_wmma_cshuffle.hpp b/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_weight_wmma_cshuffle.hpp -index 211185dfb..5738be0fb 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_weight_wmma_cshuffle.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_bwd_weight_wmma_cshuffle.hpp -@@ -692,7 +692,7 @@ struct DeviceGroupedConvBwdWeight_Wmma_CShuffle - static bool IsSupportedArgument(const Argument& arg) - { - // check device -- if(ck::is_gfx11_supported()) -+ if(ck::is_gfx11_supported() || ck::is_gfx12_supported()) - { - if constexpr(!(is_same_v || is_same_v)) - { -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_fwd_dl_multiple_d_nhwc_kyxc_nhwk.hpp b/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_fwd_dl_multiple_d_nhwc_kyxc_nhwk.hpp -index 7cfbd8a8f..5d5a9de7d 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_fwd_dl_multiple_d_nhwc_kyxc_nhwk.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_fwd_dl_multiple_d_nhwc_kyxc_nhwk.hpp -@@ -90,8 +90,9 @@ __global__ void - const Block2CTileMap block_2_ctile_map, - const ComputePtrOffsetOfBatch compute_ptr_offset_of_batch) - { --#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx906__) || defined(__gfx103__) || \ -- defined(__gfx90a__) || defined(__gfx908__) || defined(__gfx94__) || defined(__gfx11__)) -+#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx906__) || defined(__gfx103__) || \ -+ defined(__gfx90a__) || defined(__gfx908__) || defined(__gfx94__) || defined(__gfx11__) || \ -+ defined(__gfx12__)) - // offset base pointer for each work-group - const index_t num_blocks_per_batch = - __builtin_amdgcn_readfirstlane(get_grid_size() / batch_count); -@@ -666,7 +667,7 @@ struct DeviceGroupedConvFwdDlMultipleD_NHWC_KYXC_NHWK - - // check device - if(!(ck::get_device_name() == "gfx906" || ck::is_xdl_supported() || -- ck::is_gfx103_supported() || ck::is_gfx11_supported())) -+ ck::is_gfx103_supported() || ck::is_gfx11_supported() || ck::is_gfx12_supported())) - { - return false; - } -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_fwd_dl_nhwc_kyxc_nhwk.hpp b/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_fwd_dl_nhwc_kyxc_nhwk.hpp -index 6a4d97d7d..c65370b51 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_fwd_dl_nhwc_kyxc_nhwk.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_grouped_conv_fwd_dl_nhwc_kyxc_nhwk.hpp -@@ -107,7 +107,7 @@ __global__ void - const ComputePtrOffsetOfBatch compute_ptr_offset_of_batch) - { - #if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx906__) || defined(__gfx103__) || \ -- defined(__gfx11__)) -+ defined(__gfx11__) || defined(__gfx12__)) - // offset base pointer for each work-group - const index_t num_blocks_per_batch = - __builtin_amdgcn_readfirstlane(get_grid_size() / batch_count); -@@ -602,7 +602,7 @@ struct DeviceGroupedConvFwdDl_NHWC_KYXC_NHWK : public DeviceGroupedConvFwd || is_same_v)) - { -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_grouped_gemm_multiple_d_dl.hpp b/include/ck/tensor_operation/gpu/device/impl/device_grouped_gemm_multiple_d_dl.hpp -index ac392cddc..060a16d1e 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_grouped_gemm_multiple_d_dl.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_grouped_gemm_multiple_d_dl.hpp -@@ -39,8 +39,9 @@ __global__ void - const BElementwiseOperation b_element_op, - const CDEElementwiseOperation cde_element_op) - { --#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx906__) || defined(__gfx908__) || \ -- defined(__gfx90a__) || defined(__gfx103__) || defined(__gfx11__) || defined(__gfx94__)) -+#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx906__) || defined(__gfx908__) || \ -+ defined(__gfx90a__) || defined(__gfx103__) || defined(__gfx11__) || defined(__gfx94__) || \ -+ defined(__gfx12__)) - __shared__ char p_shared[GridwiseGemm::GetSharedMemoryNumberOfByte()]; - - const index_t block_id = get_block_1d_id(); -@@ -673,7 +674,7 @@ struct DeviceGroupedGemmMultipleD_Dl : public DeviceGroupedGemm || is_same_v)) - { -diff --git a/include/ck/tensor_operation/gpu/device/impl/device_multi_query_attention_forward_wmma.hpp b/include/ck/tensor_operation/gpu/device/impl/device_multi_query_attention_forward_wmma.hpp -index 4e14ed3a5..cc88c1a10 100644 ---- a/include/ck/tensor_operation/gpu/device/impl/device_multi_query_attention_forward_wmma.hpp -+++ b/include/ck/tensor_operation/gpu/device/impl/device_multi_query_attention_forward_wmma.hpp -@@ -60,7 +60,7 @@ __global__ void - bool input_permute, - bool output_permute) - { --#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__)) -+#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__) || defined(__gfx12__)) - - // clang-format off - // *************************************************** -@@ -165,6 +165,7 @@ __global__ void - ignore = O; - ignore = G0; - ignore = G1; -+ ignore = alpha; - ignore = input_permute; - ignore = output_permute; - #endif // end of if (defined(__gfx11__)) -@@ -594,7 +595,7 @@ struct DeviceMultiQueryAttentionForward_Wmma - - static bool IsSupportedArgument(const RawArg& arg) - { -- if(ck::is_gfx11_supported()) -+ if(ck::is_gfx11_supported() || ck::is_gfx12_supported()) - { - if constexpr(!(is_same_v || is_same_v)) - { -diff --git a/include/ck/tensor_operation/gpu/grid/gridwise_batched_gemm_softmax_gemm_wmma_cshuffle.hpp b/include/ck/tensor_operation/gpu/grid/gridwise_batched_gemm_softmax_gemm_wmma_cshuffle.hpp -index 16717ff81..1754e07e6 100644 ---- a/include/ck/tensor_operation/gpu/grid/gridwise_batched_gemm_softmax_gemm_wmma_cshuffle.hpp -+++ b/include/ck/tensor_operation/gpu/grid/gridwise_batched_gemm_softmax_gemm_wmma_cshuffle.hpp -@@ -371,12 +371,16 @@ struct GridwiseBatchedGemmSoftmaxGemm_Wmma - if constexpr(B0EnableLds) - { - // BK0_L_BK1 -> BK0_LRepeat_Lwaves_LPerWmma_BK1 -- constexpr auto B_K0 = B0BlockDesc_{}.GetLength(I0); -- constexpr auto B_K1 = B0BlockDesc_{}.GetLength(I2); -+ constexpr auto B_K0 = B0BlockDesc_{}.GetLength(I0); -+ constexpr auto B_K1 = B0BlockDesc_{}.GetLength(I2); -+#ifdef __gfx12__ -+ constexpr auto B_KRow = I2; -+#else - constexpr auto B_KRow = I1; -+#endif - return transform_tensor_descriptor( - B0BlockDesc_{}, -- make_tuple(make_unmerge_transform(make_tuple(Number{}, B_KRow)), -+ make_tuple(make_unmerge_transform(make_tuple(Number{}, B_KRow)), - make_unmerge_transform(make_tuple( - Number{}, Number{}, Number{})), - make_pass_through_transform(Number{})), -@@ -428,12 +432,16 @@ struct GridwiseBatchedGemmSoftmaxGemm_Wmma - if constexpr(B1EnableLds) - { - // BL0_N_BL1 -> BL0_NRepeat_Nwaves_NPerWmma_BL1 -- constexpr auto B_L0 = B1BlockDesc_{}.GetLength(I0); -- constexpr auto B_L1 = B1BlockDesc_{}.GetLength(I2); -+ constexpr auto B_L0 = B1BlockDesc_{}.GetLength(I0); -+ constexpr auto B_L1 = B1BlockDesc_{}.GetLength(I2); -+#ifdef __gfx12__ -+ constexpr auto B_LRow = I2; -+#else - constexpr auto B_LRow = I1; -+#endif - return transform_tensor_descriptor( - B1BlockDesc_{}, -- make_tuple(make_unmerge_transform(make_tuple(Number{}, B_LRow)), -+ make_tuple(make_unmerge_transform(make_tuple(Number{}, B_LRow)), - make_unmerge_transform(make_tuple( - Number{}, Number{}, Number{})), - make_pass_through_transform(Number{})), -diff --git a/include/ck/tensor_operation/gpu/grid/gridwise_fpAintB_gemm_wmma.hpp b/include/ck/tensor_operation/gpu/grid/gridwise_fpAintB_gemm_wmma.hpp -index 499eb7eb0..21dac6f9e 100644 ---- a/include/ck/tensor_operation/gpu/grid/gridwise_fpAintB_gemm_wmma.hpp -+++ b/include/ck/tensor_operation/gpu/grid/gridwise_fpAintB_gemm_wmma.hpp -@@ -50,7 +50,7 @@ __global__ void - const CElementwiseOperation c_element_op, - const Block2CTileMap block_2_ctile_map) - { --#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__)) -+#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__) || defined(__gfx12__)) - __shared__ char p_shared[GridwiseGemm::SharedMemTrait::lds_size]; - - GridwiseGemm::template Run(p_a_grid, -@@ -302,12 +302,16 @@ struct GridwiseFpAintBGemm_Wmma - if constexpr(AEnableLds) - { - // AK0_M_AK1 -> AK0_MRepeat_Mwaves_AKRow_MPerWmma_AK1 -- constexpr auto A_K0 = ABlockDesc_{}.GetLength(I0); -- constexpr auto A_K1 = ABlockDesc_{}.GetLength(I2); -+ constexpr auto A_K0 = ABlockDesc_{}.GetLength(I0); -+ constexpr auto A_K1 = ABlockDesc_{}.GetLength(I2); -+#ifdef __gfx12__ -+ constexpr auto A_KRow = I2; -+#else - constexpr auto A_KRow = I1; -+#endif - return transform_tensor_descriptor( - ABlockDesc_{}, -- make_tuple(make_unmerge_transform(make_tuple(Number{}, A_KRow)), -+ make_tuple(make_unmerge_transform(make_tuple(Number{}, A_KRow)), - make_unmerge_transform(make_tuple( - Number{}, Number{}, Number{})), - make_pass_through_transform(Number{})), -@@ -360,12 +364,16 @@ struct GridwiseFpAintBGemm_Wmma - if constexpr(BEnableLds) - { - // BK0_N_BK1 -> BK0_NRepeat_Nwaves_NPerWmma_BK1 -- constexpr auto B_K0 = BBlockDesc_{}.GetLength(I0); -- constexpr auto B_K1 = BBlockDesc_{}.GetLength(I2); -+ constexpr auto B_K0 = BBlockDesc_{}.GetLength(I0); -+ constexpr auto B_K1 = BBlockDesc_{}.GetLength(I2); -+#ifdef __gfx12__ -+ constexpr auto B_KRow = I2; -+#else - constexpr auto B_KRow = I1; -+#endif - return transform_tensor_descriptor( - BBlockDesc_{}, -- make_tuple(make_unmerge_transform(make_tuple(Number{}, B_KRow)), -+ make_tuple(make_unmerge_transform(make_tuple(Number{}, B_KRow)), - make_unmerge_transform(make_tuple( - Number{}, Number{}, Number{})), - make_pass_through_transform(Number{})), -diff --git a/include/ck/tensor_operation/gpu/grid/gridwise_gemm_multiple_d_wmma_cshuffle.hpp b/include/ck/tensor_operation/gpu/grid/gridwise_gemm_multiple_d_wmma_cshuffle.hpp -index 82d010a99..fdda649ef 100644 ---- a/include/ck/tensor_operation/gpu/grid/gridwise_gemm_multiple_d_wmma_cshuffle.hpp -+++ b/include/ck/tensor_operation/gpu/grid/gridwise_gemm_multiple_d_wmma_cshuffle.hpp -@@ -54,7 +54,7 @@ __global__ void - const Block2CTileMap block_2_ctile_map, - const ComputePtrOffsetOfBatch compute_ptr_offset_of_batch) - { --#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__)) -+#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__) || defined(__gfx12__)) - // offset base pointer for each work-group - const index_t num_blocks_per_batch = - __builtin_amdgcn_readfirstlane(get_grid_size() / batch_count); -@@ -147,7 +147,7 @@ __global__ void - const ComputePtrOffsetOfBatch compute_ptr_offset_of_batch, - const Block2CTileMap block_2_etile_map) - { --#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__)) -+#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__) || defined(__gfx12__)) - // printf("entry kernel launch"); - __shared__ char p_shared[GridwiseOp::SharedMemTrait::lds_size]; - -@@ -237,7 +237,7 @@ __global__ void - const CDEElementwiseOperation cde_element_op, - const Block2CTileMap block_2_ctile_map) - { --#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__)) -+#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__) || defined(__gfx12__)) - __shared__ char p_shared[GridwiseOp::SharedMemTrait::lds_size]; - - GridwiseOp::template Run(p_a_grid, -@@ -375,8 +375,9 @@ struct GridwiseGemmMultipleD_Wmma - } - else - { -+ constexpr auto A_KRow = I2; - constexpr auto KWmmaPerblock = KPerBlock / WmmaK; -- constexpr auto K0PerWmma = WmmaK / 2 / K1; -+ constexpr auto K0PerWmma = WmmaK / A_KRow / K1; - // KWmma->MRepeat->MWave->K0PerWmma->KRow->MPerWmma->K1 Per Thread - return make_naive_tensor_descriptor( - make_tuple(Number{}, -@@ -422,8 +423,9 @@ struct GridwiseGemmMultipleD_Wmma - } - else - { -+ constexpr auto B_KRow = I2; - constexpr auto KWmmaPerblock = KPerBlock / WmmaK; -- constexpr auto K0PerWmma = WmmaK / 2 / K1; -+ constexpr auto K0PerWmma = WmmaK / B_KRow / K1; - // KWmma->NRepeat->MWave->K0PerWmma->KRow->MPerWmma->K1 Per Thread - return make_naive_tensor_descriptor( - make_tuple(Number{}, -@@ -495,12 +497,16 @@ struct GridwiseGemmMultipleD_Wmma - if constexpr(AEnableLds) - { - // AK0_M_AK1 -> AK0_MRepeat_Mwaves_AKRow_MPerWmma_AK1 -- constexpr auto A_K0 = ABlockDesc_{}.GetLength(I0); -- constexpr auto A_K1 = ABlockDesc_{}.GetLength(I2); -+ constexpr auto A_K0 = ABlockDesc_{}.GetLength(I0); -+ constexpr auto A_K1 = ABlockDesc_{}.GetLength(I2); -+#ifdef __gfx12__ -+ constexpr auto A_KRow = I2; -+#else - constexpr auto A_KRow = I1; -+#endif - return transform_tensor_descriptor( - ABlockDesc_{}, -- make_tuple(make_unmerge_transform(make_tuple(Number{}, A_KRow)), -+ make_tuple(make_unmerge_transform(make_tuple(Number{}, A_KRow)), - make_unmerge_transform(make_tuple( - Number{}, Number{}, Number{})), - make_pass_through_transform(Number{})), -@@ -534,12 +540,16 @@ struct GridwiseGemmMultipleD_Wmma - if constexpr(BEnableLds) - { - // BK0_N_BK1 -> BK0_NRepeat_Nwaves_NPerWmma_BK1 -- constexpr auto B_K0 = BBlockDesc_{}.GetLength(I0); -- constexpr auto B_K1 = BBlockDesc_{}.GetLength(I2); -+ constexpr auto B_K0 = BBlockDesc_{}.GetLength(I0); -+ constexpr auto B_K1 = BBlockDesc_{}.GetLength(I2); -+#ifdef __gfx12__ -+ constexpr auto B_KRow = I2; -+#else - constexpr auto B_KRow = I1; -+#endif - return transform_tensor_descriptor( - BBlockDesc_{}, -- make_tuple(make_unmerge_transform(make_tuple(Number{}, B_KRow)), -+ make_tuple(make_unmerge_transform(make_tuple(Number{}, B_KRow)), - make_unmerge_transform(make_tuple( - Number{}, Number{}, Number{})), - make_pass_through_transform(Number{})), -@@ -571,15 +581,12 @@ struct GridwiseGemmMultipleD_Wmma - // *Caution Here repeat is shuffle repeat - GetCShuffleBlockDescriptor_MShRepeat_MPerShRepeat_NShRepeat_NPerShRepeat() - { -- constexpr index_t MWave = MPerBlock / (MRepeat * MPerWmma); -- constexpr index_t NWave = NPerBlock / (NRepeat * NPerWmma); -- - constexpr auto c_shuffle_block_desc_mshrepeat_mpershrepeat_nshrepeat_npershrepeat = - make_naive_tensor_descriptor_packed( - make_tuple(I1, -- Number{}, -+ Number{}, - I1, -- Number{})); -+ Number{})); - - return c_shuffle_block_desc_mshrepeat_mpershrepeat_nshrepeat_npershrepeat; - } -@@ -799,8 +806,9 @@ struct GridwiseGemmMultipleD_Wmma - const auto M = e_grid_desc_m_n.GetLength(I0); - const auto N = e_grid_desc_m_n.GetLength(I1); - -- const auto MBlock = M / MPerBlock; -- const auto NBlock = N / NPerBlock; -+ const auto MBlock = M / MPerBlock; -+ const auto NBlock = N / NPerBlock; -+ - const auto e_grid_desc_mblock_mperblock_nblock_nperblock = transform_tensor_descriptor( - e_grid_desc_m_n, - make_tuple(make_unmerge_transform(make_tuple(MBlock, Number{})), -diff --git a/include/ck/tensor_operation/gpu/grid/gridwise_gemm_wmma.hpp b/include/ck/tensor_operation/gpu/grid/gridwise_gemm_wmma.hpp -index 8e4117593..4458b9356 100644 ---- a/include/ck/tensor_operation/gpu/grid/gridwise_gemm_wmma.hpp -+++ b/include/ck/tensor_operation/gpu/grid/gridwise_gemm_wmma.hpp -@@ -45,7 +45,7 @@ __global__ void - const CElementwiseOperation c_element_op, - const Block2CTileMap block_2_ctile_map) - { --#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__)) -+#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx11__) || defined(__gfx12__)) - __shared__ char p_shared[GridwiseGemm::SharedMemTrait::lds_size]; - - GridwiseGemm::template Run(p_a_grid, -@@ -170,8 +170,9 @@ struct GridwiseGemm_Wmma - } - else - { -+ constexpr auto A_KRow = I2; - constexpr auto KWmmaPerblock = KPerBlock / WmmaK; -- constexpr auto K0PerWmma = WmmaK / 2 / K1; -+ constexpr auto K0PerWmma = WmmaK / A_KRow / K1; - // KWmma->MRepeat->MWave->K0PerWmma->KRow->MPerWmma->K1 Per Thread - return make_naive_tensor_descriptor( - make_tuple(Number{}, -@@ -217,8 +218,10 @@ struct GridwiseGemm_Wmma - } - else - { -+ -+ constexpr auto B_KRow = I2; - constexpr auto KWmmaPerblock = KPerBlock / WmmaK; -- constexpr auto K0PerWmma = WmmaK / 2 / K1; -+ constexpr auto K0PerWmma = WmmaK / B_KRow / K1; - // KWmma->NRepeat->MWave->K0PerWmma->KRow->MPerWmma->K1 Per Thread - return make_naive_tensor_descriptor( - make_tuple(Number{}, -@@ -290,12 +293,17 @@ struct GridwiseGemm_Wmma - if constexpr(AEnableLds) - { - // AK0_M_AK1 -> AK0_MRepeat_Mwaves_AKRow_MPerWmma_AK1 -- constexpr auto A_K0 = ABlockDesc_{}.GetLength(I0); -- constexpr auto A_K1 = ABlockDesc_{}.GetLength(I2); -+ constexpr auto A_K0 = ABlockDesc_{}.GetLength(I0); -+ constexpr auto A_K1 = ABlockDesc_{}.GetLength(I2); -+#ifdef __gfx12__ -+ constexpr auto A_KRow = I2; -+#else - constexpr auto A_KRow = I1; -+#endif -+ - return transform_tensor_descriptor( - ABlockDesc_{}, -- make_tuple(make_unmerge_transform(make_tuple(Number{}, A_KRow)), -+ make_tuple(make_unmerge_transform(make_tuple(Number{}, A_KRow)), - make_unmerge_transform(make_tuple( - Number{}, Number{}, Number{})), - make_pass_through_transform(Number{})), -@@ -348,12 +356,16 @@ struct GridwiseGemm_Wmma - if constexpr(BEnableLds) - { - // BK0_N_BK1 -> BK0_NRepeat_Nwaves_NPerWmma_BK1 -- constexpr auto B_K0 = BBlockDesc_{}.GetLength(I0); -- constexpr auto B_K1 = BBlockDesc_{}.GetLength(I2); -+ constexpr auto B_K0 = BBlockDesc_{}.GetLength(I0); -+ constexpr auto B_K1 = BBlockDesc_{}.GetLength(I2); -+#ifdef __gfx12__ -+ constexpr auto B_KRow = I2; -+#else - constexpr auto B_KRow = I1; -+#endif - return transform_tensor_descriptor( - BBlockDesc_{}, -- make_tuple(make_unmerge_transform(make_tuple(Number{}, B_KRow)), -+ make_tuple(make_unmerge_transform(make_tuple(Number{}, B_KRow)), - make_unmerge_transform(make_tuple( - Number{}, Number{}, Number{})), - make_pass_through_transform(Number{})), -@@ -522,12 +534,6 @@ struct GridwiseGemm_Wmma - c_grid_desc_m_n); - } - -- using CGridDescriptor_MBlock_MPerBlock_NBlock_NPerBlock = -- remove_cvref_t; -- using DefaultBlock2CTileMap = -- remove_cvref_t; -- - struct SharedMemTrait - { - // LDS allocation for A and B: be careful of alignment -@@ -559,6 +565,12 @@ struct GridwiseGemm_Wmma - b_block_space_size_aligned * sizeof(BDataType)); - }; - -+ using CGridDescriptor_MBlock_MPerBlock_NBlock_NPerBlock = -+ remove_cvref_t; -+ using DefaultBlock2CTileMap = -+ remove_cvref_t; -+ - template - __device__ static void Run(const ADataType* __restrict__ p_a_grid, - const BDataType* __restrict__ p_b_grid, -diff --git a/include/ck/tensor_operation/gpu/grid/gridwise_tensor_rearrange.hpp b/include/ck/tensor_operation/gpu/grid/gridwise_tensor_rearrange.hpp -index 6772524e0..174074990 100644 ---- a/include/ck/tensor_operation/gpu/grid/gridwise_tensor_rearrange.hpp -+++ b/include/ck/tensor_operation/gpu/grid/gridwise_tensor_rearrange.hpp -@@ -35,8 +35,9 @@ __global__ void - const Block2ETileMap block_2_tile_map, - const ComputePtrOffsetOfStridedBatch compute_ptr_offset_of_batch) - { --#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx906__) || defined(__gfx908__) || \ -- defined(__gfx90a__) || defined(__gfx94__) || defined(__gfx103__) || defined(__gfx11__)) -+#if(!defined(__HIP_DEVICE_COMPILE__) || defined(__gfx906__) || defined(__gfx908__) || \ -+ defined(__gfx90a__) || defined(__gfx94__) || defined(__gfx103__) || defined(__gfx11__) || \ -+ defined(__gfx12__)) - GridwiseTensorRearrangeKernel::Run(in_grid_desc, - p_in_global, - out_grid_desc, -diff --git a/include/ck/tensor_operation/gpu/thread/threadwise_tensor_slice_transfer.hpp b/include/ck/tensor_operation/gpu/thread/threadwise_tensor_slice_transfer.hpp -index bcce930fc..d7a6a3624 100644 ---- a/include/ck/tensor_operation/gpu/thread/threadwise_tensor_slice_transfer.hpp -+++ b/include/ck/tensor_operation/gpu/thread/threadwise_tensor_slice_transfer.hpp -@@ -1304,7 +1304,7 @@ struct ThreadwiseTensorSliceTransfer_StaticToStatic - ElementwiseOperation element_op_; - }; - --// Specilized for WMMA -+// Specilized for WMMA-Navi3 - // A single Wave32 is composed by double row - // Data exchange allowed between these two rows - // This RowLane Dst buf will be filled from two Src buf -@@ -1439,4 +1439,111 @@ struct ThreadwiseTensorSliceTransfer_StaticToStatic_InterRow - ElementwiseOperation element_op_{}; - }; - -+// Specilized for WMMA-Navi4 -+template ::type = false> -+struct ThreadwiseTensorSliceTransfer_StaticToStatic_IntraRow -+{ -+ static constexpr index_t nDim = SliceLengths::Size(); -+ -+ using Index = MultiIndex; -+ -+ __device__ constexpr ThreadwiseTensorSliceTransfer_StaticToStatic_IntraRow(const Index& src_idx) -+ { -+ static_assert(SrcDesc::IsKnownAtCompileTime() && DstDesc::IsKnownAtCompileTime(), -+ "wrong! Desc need to known at compile-time"); -+ -+ static_assert(SliceLengths::At(Number{}) % DstScalarPerVector == 0, -+ "wrong! Not divisible"); -+ ignore = src_idx; -+ } -+ -+ template -+ __device__ void Run(const SrcDesc&, -+ const SrcSliceOriginIdx&, -+ const SrcBuffer& src_buf, -+ const DstDesc&, -+ const DstSliceOriginIdx&, -+ DstBuffer& dst_buf) const -+ { -+ static_assert(SrcDesc::IsKnownAtCompileTime() && DstDesc::IsKnownAtCompileTime(), -+ "wrong! Desc need to known at compile-time"); -+ -+ static_assert(is_known_at_compile_time>::value && -+ is_known_at_compile_time>::value, -+ "wrong! SliceOrigin need to known at compile-time"); -+ -+ static_assert(SrcBuffer::IsStaticBuffer() && DstBuffer::IsStaticBuffer(), -+ "wrong! Buffer need to be StaticBuffer"); -+ -+ // SrcDesc and src_slice_origin_idx are known at compile-time -+ constexpr auto src_desc = remove_cvref_t{}; -+ constexpr auto dst_desc = remove_cvref_t{}; -+ constexpr auto src_slice_origin_idx = to_multi_index(SrcSliceOriginIdx{}); -+ constexpr auto dst_slice_origin_idx = to_multi_index(DstSliceOriginIdx{}); -+ -+ // scalar per access on each dim -+ constexpr auto dst_scalar_per_access = generate_sequence( -+ detail::lambda_scalar_per_access{}, Number{}); -+ -+ constexpr auto dst_scalar_step_in_vector = -+ generate_sequence(detail::lambda_scalar_step_in_vector{}, Number{}); -+ -+ using SpaceFillingCurve = SpaceFillingCurve>; -+ -+ static_assert(DstScalarPerVector == SpaceFillingCurve::ScalarPerVector, -+ "wrong!DstScalarPerVector != SpaceFillingCurve::ScalarPerVector"); -+ -+ constexpr auto num_access = SpaceFillingCurve::GetNumOfAccess(); -+ -+ static_for<0, num_access, 1>{}([&](auto idx_1d) { -+ constexpr auto idx_md = SpaceFillingCurve::GetIndex(idx_1d); -+ -+ // copy data from src_buf into dst_vector -+ static_for<0, DstScalarPerVector, 1>{}([&](auto i) { -+ // src_desc error, non constexpr, caused by merge transform -+ constexpr index_t src_offset = src_desc.CalculateOffset( -+ src_slice_origin_idx + idx_md + i * dst_scalar_step_in_vector); -+ -+ constexpr index_t dst_offset = dst_desc.CalculateOffset( -+ dst_slice_origin_idx + idx_md + i * dst_scalar_step_in_vector); -+ -+ SrcData v_this_row; -+ // int type temp value due to intrinsic requirement -+ int temp = 0; -+ -+ // apply element-wise operation -+ element_op_(v_this_row, src_buf[Number{}]); -+ -+ // apply intra-row permute. -+ if constexpr(IntraRowSwizzlePerm) -+ { -+ temp = __builtin_amdgcn_permlane16( -+ temp, type_convert_sp(v_this_row), 0xb3a29180, 0xf7e6d5c4, 1, 0); -+ v_this_row = type_convert_sp(temp); -+ } -+ -+ // apply type convert -+ dst_buf(Number{}) = type_convert_sp(v_this_row); -+ }); -+ }); -+ } -+ ElementwiseOperation element_op_{}; -+}; -+ - } // namespace ck -diff --git a/include/ck/tensor_operation/gpu/warp/wmma_gemm.hpp b/include/ck/tensor_operation/gpu/warp/wmma_gemm.hpp -index 565195f53..9a9ebf559 100644 ---- a/include/ck/tensor_operation/gpu/warp/wmma_gemm.hpp -+++ b/include/ck/tensor_operation/gpu/warp/wmma_gemm.hpp -@@ -11,12 +11,17 @@ namespace ck { - - enum struct WmmaInstr - { -+ // gfx11 - wmma_f32_16x16x16_f16 = 0, - wmma_f32_16x16x16_bf16, - wmma_f16_16x16x16_f16, - wmma_bf16_16x16x16_bf16, - wmma_i32_16x16x16_iu8, -- wmma_i32_16x16x16_iu4 -+ wmma_i32_16x16x16_iu4, -+ // gfx12 -+ wmma_f32_16x16x16_f16_gfx12, -+ wmma_f32_16x16x16_bf16_gfx12, -+ wmma_i32_16x16x16_iu8_gfx12, - }; - - /* -@@ -279,6 +284,122 @@ struct wmma_type -+struct wmma_type> -+{ -+ // Absolute fixing property -+ // * Data Pixel -+ static constexpr index_t m_per_wmma = 16; -+ static constexpr index_t n_per_wmma = 16; -+ static constexpr index_t k_per_wmma = 16; -+ // static constexpr index_t src_a_data_size = 2; -+ // static constexpr index_t src_b_data_size = 2; -+ // static constexpr index_t acc_data_size = 4; -+ // * Thread mapping inside wave, num_thread_per_subgroups always alone N direction -+ static constexpr index_t acc_data_size = 4; -+ static constexpr index_t acc_pack_number = 1; -+ static constexpr index_t num_thread_per_subgroups = n_per_wmma; -+ -+ // Wave mode dependent propety -+ static constexpr index_t wave_size = Number{}; -+ // * Fixed in Navi3x, Will be wave mode dependent on Navi4x -+ // static constexpr index_t num_src_a_vgprs_per_wave = k_per_wmma / 2 * src_a_data_size / 4; -+ // static constexpr index_t num_src_b_vgprs_per_wave = k_per_wmma / 2 * src_b_data_size / 4; -+ // * num_acc_vgprs_per_wave alone M direction -+ // * num_subgroups alone M direction -+ static constexpr index_t num_acc_vgprs_per_wave = m_per_wmma * n_per_wmma / wave_size; -+ static constexpr index_t num_subgroups = wave_size / num_thread_per_subgroups; -+ -+ template -+ __device__ void run(const FloatA& a, const FloatB& b, FloatC& reg_c) const -+ { -+ static_assert(wave_size == 32, "only support wave32 for gfx12 wmma"); -+ if constexpr(wave_size == 32) -+ { -+ intrin_wmma_f32_16x16x16_f16_w32_gfx12::Run(a, b, reg_c); -+ } -+ } -+}; -+ -+template -+struct wmma_type> -+{ -+ // Absolute fixing property -+ static constexpr index_t m_per_wmma = 16; -+ static constexpr index_t n_per_wmma = 16; -+ static constexpr index_t k_per_wmma = 16; -+ // static constexpr index_t src_a_data_size = 2; -+ // static constexpr index_t src_b_data_size = 2; -+ static constexpr index_t acc_data_size = 4; -+ static constexpr index_t acc_pack_number = 1; -+ static constexpr index_t num_thread_per_subgroups = n_per_wmma; -+ -+ // Wave mode dependent propety -+ static constexpr index_t wave_size = Number{}; -+ // static constexpr index_t num_src_a_vgprs_per_wave = m_per_wmma * src_a_data_size / 4; -+ // static constexpr index_t num_src_b_vgprs_per_wave = n_per_wmma * src_b_data_size / 4; -+ static constexpr index_t num_acc_vgprs_per_wave = m_per_wmma * n_per_wmma / wave_size; -+ static constexpr index_t num_subgroups = wave_size / num_thread_per_subgroups; -+ -+ template -+ __device__ void run(const FloatA& a, const FloatB& b, FloatC& reg_c) const -+ { -+ static_assert(wave_size == 32, "only support wave32 for gfx12 wmma"); -+ if constexpr(wave_size == 32) -+ { -+ intrin_wmma_f32_16x16x16_bf16_w32_gfx12::Run(a, b, reg_c); -+ } -+ } -+}; -+ -+template -+struct wmma_type> -+{ -+ // Absolute fixing property -+ static constexpr index_t m_per_wmma = 16; -+ static constexpr index_t n_per_wmma = 16; -+ static constexpr index_t k_per_wmma = 16; -+ // static constexpr index_t src_a_data_size = 2; -+ // static constexpr index_t src_b_data_size = 2; -+ static constexpr index_t acc_data_size = 4; -+ static constexpr index_t acc_pack_number = 1; -+ static constexpr index_t num_thread_per_subgroups = n_per_wmma; -+ -+ // Wave mode dependent propety -+ static constexpr index_t wave_size = Number{}; -+ // static constexpr index_t num_src_a_vgprs_per_wave = m_per_wmma * src_a_data_size / 4; -+ // static constexpr index_t num_src_b_vgprs_per_wave = n_per_wmma * src_b_data_size / 4; -+ static constexpr index_t num_acc_vgprs_per_wave = m_per_wmma * n_per_wmma / wave_size; -+ static constexpr index_t num_subgroups = wave_size / num_thread_per_subgroups; -+ -+ template -+ __device__ void run(const FloatA& a, const FloatB& b, FloatC& reg_c) const -+ { -+ static_assert(wave_size == 32, "only support wave32 for gfx12 wmma"); -+ if constexpr(wave_size == 32) -+ { -+ intrin_wmma_i32_16x16x16_iu8_w32_gfx12::Run( -+ a, b, reg_c); -+ } -+ } -+}; -+ - template - static constexpr auto GetWmma() - { -+#ifdef __gfx12__ -+ return WmmaInstr::wmma_f32_16x16x16_f16_gfx12; -+#else - return WmmaInstr::wmma_f32_16x16x16_f16; -+#endif - } - - template <> - static constexpr auto GetWmma() - { -+#ifdef __gfx12__ -+ return WmmaInstr::wmma_f32_16x16x16_bf16_gfx12; -+#else - return WmmaInstr::wmma_f32_16x16x16_bf16; -+#endif - } - - template <> -@@ -320,8 +449,13 @@ struct WmmaSelector - template <> - static constexpr auto GetWmma() - { -+#ifdef __gfx12__ -+ return WmmaInstr::wmma_i32_16x16x16_iu8_gfx12; -+#else - return WmmaInstr::wmma_i32_16x16x16_iu8; -+#endif - } -+ - #ifdef CK_EXPERIMENTAL_BIT_INT_EXTENSION_INT4 - template <> - static constexpr auto GetWmma() -@@ -502,6 +636,9 @@ struct WmmaGemm - - __device__ static auto GetSubGroupId() - { -+ static_assert(wmma_instr.num_thread_per_subgroups * wmma_instr.num_subgroups == -+ wmma_instr.wave_size, -+ ""); - return (GetLaneId() / wmma_instr.num_thread_per_subgroups) % wmma_instr.num_subgroups; - } - -@@ -516,12 +653,20 @@ struct WmmaGemm - - __host__ __device__ static auto CalculateAThreadOriginDataIndex() - { -+#ifdef __gfx12__ -+ return GetLaneIdUnderSubGroup(); -+#else - return TransposeC ? GetLaneIdUnderSubGroup() : GetSwizzledLaneIdLow(); -+#endif - } - - __host__ __device__ static auto CalculateBThreadOriginDataIndex() - { -+#ifdef __gfx12__ -+ return GetLaneIdUnderSubGroup(); -+#else - return TransposeC ? GetSwizzledLaneIdLow() : GetLaneIdUnderSubGroup(); -+#endif - } - - __device__ static CIndex GetBeginOfThreadBlk() -diff --git a/include/ck/utility/amd_wmma.hpp b/include/ck/utility/amd_wmma.hpp -index 1bb0140f3..322a0f94b 100644 ---- a/include/ck/utility/amd_wmma.hpp -+++ b/include/ck/utility/amd_wmma.hpp -@@ -257,5 +257,87 @@ struct intrin_wmma_i32_16x16x16_iu8_w64<16, 16, neg_a, neg_b, clamp> - } - }; - -+// gfx12 -+/********************************WAVE32 MODE***********************************************/ -+ -+#if defined(__gfx1200__) || defined(__gfx1201__) -+#define __gfx12__ -+#endif -+ -+// src: fp16, dst: fp32 -+template -+struct intrin_wmma_f32_16x16x16_f16_w32_gfx12; -+ -+template <> -+struct intrin_wmma_f32_16x16x16_f16_w32_gfx12<16, 16> -+{ -+ template -+ __device__ static void Run(const half8_t& reg_a, const half8_t& reg_b, FloatC& reg_c) -+ { -+ // * Inline assembly need to elimate the duplicated data load, compiler won't help you -+ // delete them. -+ // amd_assembly_wmma_f32_16x16x16_f16_w32( -+ // reg_a, reg_b, reg_c.template AsType()(Number<0>{})); -+#if defined(__gfx12__) -+ reg_c.template AsType()(Number<0>{}) = -+ __builtin_amdgcn_wmma_f32_16x16x16_f16_w32_gfx12( -+ reg_a, reg_b, reg_c.template AsType()[Number<0>{}]); -+#else -+ ignore = reg_a; -+ ignore = reg_b; -+ ignore = reg_c; -+#endif -+ } -+}; -+ -+// src: bf16, dst: fp32 -+template -+struct intrin_wmma_f32_16x16x16_bf16_w32_gfx12; -+ -+template <> -+struct intrin_wmma_f32_16x16x16_bf16_w32_gfx12<16, 16> -+{ -+ template -+ __device__ static void Run(const bhalf8_t& reg_a, const bhalf8_t& reg_b, FloatC& reg_c) -+ { -+#if defined(__gfx12__) -+ reg_c.template AsType()(Number<0>{}) = -+ __builtin_amdgcn_wmma_f32_16x16x16_bf16_w32_gfx12( -+ reg_a, reg_b, reg_c.template AsType()[Number<0>{}]); -+#else -+ ignore = reg_a; -+ ignore = reg_b; -+ ignore = reg_c; -+#endif -+ } -+}; -+ -+// src: iu8, dst: i32 -+template -+struct intrin_wmma_i32_16x16x16_iu8_w32_gfx12; -+ -+template -+struct intrin_wmma_i32_16x16x16_iu8_w32_gfx12<16, 16, neg_a, neg_b, clamp> -+{ -+ template -+ __device__ static void Run(const int8x8_t& reg_a, const int8x8_t& reg_b, FloatC& reg_c) -+ { -+#if defined(__gfx12__) -+ reg_c.template AsType()(Number<0>{}) = -+ __builtin_amdgcn_wmma_i32_16x16x16_iu8_w32_gfx12( -+ neg_a, -+ bit_cast(reg_a), -+ neg_b, -+ bit_cast(reg_b), -+ reg_c.template AsType()[Number<0>{}], -+ clamp); -+#else -+ ignore = reg_a; -+ ignore = reg_b; -+ ignore = reg_c; -+#endif -+ } -+}; -+ - } // namespace ck - #endif -diff --git a/include/ck/utility/data_type.hpp b/include/ck/utility/data_type.hpp -index 93a1edefb..4df14c621 100644 ---- a/include/ck/utility/data_type.hpp -+++ b/include/ck/utility/data_type.hpp -@@ -203,7 +203,7 @@ struct vector_type - } - }; - --int static err = 0; -+__device__ int static err = 0; - template - struct vector_type - { -diff --git a/include/ck/utility/synchronization.hpp b/include/ck/utility/synchronization.hpp -index 4fe5e3950..d6b6eac26 100644 ---- a/include/ck/utility/synchronization.hpp -+++ b/include/ck/utility/synchronization.hpp -@@ -10,12 +10,20 @@ namespace ck { - __device__ void block_sync_lds() - { - #if CK_EXPERIMENTAL_BLOCK_SYNC_LDS_WITHOUT_SYNC_VMEM -+#ifdef __gfx12__ -+ asm volatile("\ -+ s_wait_dscnt 0x0 \n \ -+ s_barrier_signal -1 \n \ -+ s_barrier_wait -1 \ -+ " ::); -+#else - // asm volatile("\ - // s_waitcnt lgkmcnt(0) \n \ - // s_barrier \ - // " ::); - __builtin_amdgcn_s_waitcnt(0xc07f); - __builtin_amdgcn_s_barrier(); -+#endif - #else - __syncthreads(); - #endif -@@ -23,11 +31,20 @@ __device__ void block_sync_lds() - - __device__ void block_sync_lds_direct_load() - { -+#ifdef __gfx12__ -+ asm volatile("\ -+ s_wait_vmcnt 0x0 \n \ -+ s_wait_dscnt 0x0 \n \ -+ s_barrier_signal -1 \n \ -+ s_barrier_wait -1 \ -+ " ::); -+#else - asm volatile("\ - s_waitcnt vmcnt(0) \n \ - s_waitcnt lgkmcnt(0) \n \ - s_barrier \ - " ::); -+#endif - } - - __device__ void s_nop() -diff --git a/include/ck_tile/core/config.hpp b/include/ck_tile/core/config.hpp -index 601aad19b..9dc2b072a 100644 ---- a/include/ck_tile/core/config.hpp -+++ b/include/ck_tile/core/config.hpp -@@ -17,6 +17,9 @@ - #if defined(__gfx1100__) || defined(__gfx1101__) || defined(__gfx1102__) || defined(__gfx1103__) - #define __gfx11__ - #endif -+#if defined(__gfx1200__) || defined(__gfx1201__) -+#define __gfx12__ -+#endif - - #ifndef CK_TILE_DONT_USE_HIP_RUNTIME_HEADERS - #include "hip/hip_runtime.h" -@@ -155,7 +158,7 @@ - #define CK_TILE_BUFFER_RESOURCE_3RD_DWORD 0x00020000 - #elif defined(__gfx103__) // for GPU code - #define CK_TILE_BUFFER_RESOURCE_3RD_DWORD 0x31014000 --#elif defined(__gfx11__) // for GPU code -+#elif defined(__gfx11__) || defined(__gfx12__) // for GPU code - #define CK_TILE_BUFFER_RESOURCE_3RD_DWORD 0x31004000 - #endif - -diff --git a/library/src/tensor_operation_instance/gpu/CMakeLists.txt b/library/src/tensor_operation_instance/gpu/CMakeLists.txt -index 8c5f36d2e..89c9d6dc6 100644 ---- a/library/src/tensor_operation_instance/gpu/CMakeLists.txt -+++ b/library/src/tensor_operation_instance/gpu/CMakeLists.txt -@@ -52,7 +52,7 @@ function(add_instance_library INSTANCE_NAME) - endforeach() - # Do not build WMMA instances if gfx11 targets are not on the target list - foreach(source IN LISTS ARGN) -- if(NOT GPU_TARGETS MATCHES "gfx11" AND source MATCHES "_wmma") -+ if(NOT GPU_TARGETS MATCHES "gfx11" AND NOT GPU_TARGETS MATCHES "gfx12" AND source MATCHES "_wmma") - message("removing wmma instance ${source} ") - list(REMOVE_ITEM ARGN "${source}") - endif() -@@ -149,7 +149,7 @@ FOREACH(subdir_path ${dir_list}) - message("Found only xdl instances, but gfx9 is not on the targets list. Skipping.") - set(add_inst 0) - endif() -- if(("${cmake_instance}" MATCHES "ONLY WMMA_KERNELS") AND (NOT GPU_TARGETS MATCHES "gfx11")) -+ if(("${cmake_instance}" MATCHES "ONLY WMMA_KERNELS") AND (NOT GPU_TARGETS MATCHES "gfx11") AND (NOT GPU_TARGETS MATCHES "gfx12")) - message("Found only wmma instances, but gfx11 is not on the targets list. Skipping.") - set(add_inst 0) - endif() -@@ -157,11 +157,11 @@ FOREACH(subdir_path ${dir_list}) - message("Found only xdl and dl instances, but gfx9 is not on the targets listand DL_KERNELS is not set. Skipping.") - set(add_inst 0) - endif() -- if(("${cmake_instance}" MATCHES "ONLY XDL_AND_WMMA_KERNELS") AND (NOT GPU_TARGETS MATCHES "gfx11") AND (NOT GPU_TARGETS MATCHES "gfx9")) -+ if(("${cmake_instance}" MATCHES "ONLY XDL_AND_WMMA_KERNELS") AND (NOT GPU_TARGETS MATCHES "gfx11") AND (NOT GPU_TARGETS MATCHES "gfx12") AND (NOT GPU_TARGETS MATCHES "gfx9")) - message("Found only xdl and wmma instances, but gfx11 and gfx9 are not on the targets list. Skipping.") - set(add_inst 0) - endif() -- if(("${cmake_instance}" MATCHES "XDL_DL_WMMA_KERNELS") AND (NOT GPU_TARGETS MATCHES "gfx11") AND (NOT GPU_TARGETS MATCHES "gfx9") AND (NOT DEFINED DL_KERNELS)) -+ if(("${cmake_instance}" MATCHES "XDL_DL_WMMA_KERNELS") AND (NOT GPU_TARGETS MATCHES "gfx11") AND (NOT GPU_TARGETS MATCHES "gfx12") AND (NOT GPU_TARGETS MATCHES "gfx9") AND (NOT DEFINED DL_KERNELS)) - message("Found xdl, dl, and wmma instances, but none of those meet the target list. Skipping.") - set(add_inst 0) - endif() -diff --git a/profiler/src/CMakeLists.txt b/profiler/src/CMakeLists.txt -index 1cfcbfff6..a9557a9b9 100644 ---- a/profiler/src/CMakeLists.txt -+++ b/profiler/src/CMakeLists.txt -@@ -58,7 +58,7 @@ if(GPU_TARGETS MATCHES "gfx9") - - endif() - --if(GPU_TARGETS MATCHES "gfx11" OR GPU_TARGETS MATCHES "gfx9") -+if(GPU_TARGETS MATCHES "gfx11" OR GPU_TARGETS MATCHES "gfx12" OR GPU_TARGETS MATCHES "gfx9") - if(DTYPES MATCHES "fp16" OR NOT DEFINED DTYPES) - list(APPEND PROFILER_SOURCES profile_gemm_bilinear.cpp) - endif() -@@ -133,7 +133,7 @@ if(GPU_TARGETS MATCHES "gfx9") - target_link_libraries(${PROFILER_EXECUTABLE} PRIVATE device_grouped_conv2d_bwd_weight_instance) - endif() - --if(GPU_TARGETS MATCHES "gfx9" OR GPU_TARGETS MATCHES "gfx11") -+if(GPU_TARGETS MATCHES "gfx9" OR GPU_TARGETS MATCHES "gfx11" OR GPU_TARGETS MATCHES "gfx12") - if(DTYPES MATCHES "fp16" OR NOT DEFINED DTYPES) - target_link_libraries(${PROFILER_EXECUTABLE} PRIVATE device_gemm_bilinear_instance) - endif() -diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt -index 25c63ac7f..2a7c52b58 100644 ---- a/test/CMakeLists.txt -+++ b/test/CMakeLists.txt -@@ -53,7 +53,7 @@ function(add_test_executable TEST_NAME) - endif() - endforeach() - foreach(source IN LISTS ARGN) -- if(NOT GPU_TARGETS MATCHES "gfx11" AND source MATCHES "wmma") -+ if(NOT GPU_TARGETS MATCHES "gfx11" AND NOT GPU_TARGETS MATCHES "gfx12" AND source MATCHES "wmma") - message("removing wmma test ${source} ") - list(REMOVE_ITEM ARGN "${source}") - endif() -@@ -118,7 +118,7 @@ function(add_gtest_executable TEST_NAME) - endif() - endforeach() - foreach(source IN LISTS ARGN) -- if(NOT GPU_TARGETS MATCHES "gfx11" AND source MATCHES "wmma") -+ if(NOT GPU_TARGETS MATCHES "gfx11" AND NOT GPU_TARGETS MATCHES "gfx12" AND source MATCHES "wmma") - message("removing wmma test ${source} ") - list(REMOVE_ITEM ARGN "${source}") - endif() -diff --git a/test/grouped_convnd_bwd_weight/test_grouped_convnd_bwd_weight.cpp b/test/grouped_convnd_bwd_weight/test_grouped_convnd_bwd_weight.cpp -index 1c8082645..21f49ec0f 100644 ---- a/test/grouped_convnd_bwd_weight/test_grouped_convnd_bwd_weight.cpp -+++ b/test/grouped_convnd_bwd_weight/test_grouped_convnd_bwd_weight.cpp -@@ -55,7 +55,7 @@ class TestGroupedConvndBwdWeight : public ::testing::Test - } - } - -- if(ck::is_gfx11_supported()) -+ if(ck::is_gfx11_supported() || ck::is_gfx12_supported()) - { - // on gfx11 only support for 3d is implemented - if constexpr(NDimSpatial{} != 3) -diff --git a/test/wmma_op/wmma_op_util.hpp b/test/wmma_op/wmma_op_util.hpp -index 49782bce6..d9ec94771 100644 ---- a/test/wmma_op/wmma_op_util.hpp -+++ b/test/wmma_op/wmma_op_util.hpp -@@ -140,10 +140,18 @@ __global__ void matmul(const src_t* a, const src_t* b, dst_t* c) - p_shared[8 * 16 * lane_hi + 8 * lane_lo + ele + 16 * 16] = b_temp[ele]; - } - -+#ifdef __gfx12__ -+ asm volatile("\ -+ s_wait_dscnt 0x0 \n \ -+ s_barrier_signal -1 \n \ -+ s_barrier_wait -1 \ -+ " ::); -+#else - asm volatile("\ - s_waitcnt lgkmcnt(0) \n \ - s_barrier \ - " ::); -+#endif - - for(int ele = 0; ele < 16; ++ele) - { -@@ -155,10 +163,18 @@ __global__ void matmul(const src_t* a, const src_t* b, dst_t* c) - a_frag[ele] = p_shared[(ele / 8) * 16 * 8 + 8 * lane + ele % 8]; - } - -+#ifdef __gfx12__ -+ asm volatile("\ -+ s_wait_dscnt 0x0 \n \ -+ s_barrier_signal -1 \n \ -+ s_barrier_wait -1 \ -+ " ::); -+#else - asm volatile("\ - s_waitcnt lgkmcnt(0) \n \ - s_barrier \ - " ::); -+#endif - - // sync threads, similar to mma_sync - // __syncthreads(); diff --git a/cmake/patches/composable_kernel/Fix_Clang_Build.patch b/cmake/patches/composable_kernel/Fix_Clang_Build.patch deleted file mode 100644 index d63da63445fde..0000000000000 --- a/cmake/patches/composable_kernel/Fix_Clang_Build.patch +++ /dev/null @@ -1,238 +0,0 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index c23746e7f..bc326c8b5 100644 ---- a/CMakeLists.txt -+++ b/CMakeLists.txt -@@ -23,10 +23,10 @@ endif() - - set(version 1.1.0) - # Check support for CUDA/HIP in Cmake --project(composable_kernel VERSION ${version} LANGUAGES CXX) -+project(composable_kernel VERSION ${version} LANGUAGES CXX HIP) - include(CTest) - --find_package(Python3 3.6 COMPONENTS Interpreter REQUIRED) -+find_package(Python3 COMPONENTS Interpreter REQUIRED) - - list(APPEND CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake") - -@@ -227,27 +227,6 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) - set(CMAKE_CXX_EXTENSIONS OFF) - message("CMAKE_CXX_COMPILER_ID: ${CMAKE_CXX_COMPILER_ID}") - --## OpenMP --if(CMAKE_CXX_COMPILER_ID MATCHES "Clang") -- # workaround issue hipcc in rocm3.5 cannot find openmp -- set(OpenMP_CXX "${CMAKE_CXX_COMPILER}") -- set(OpenMP_CXX_FLAGS "-fopenmp=libomp -Wno-unused-command-line-argument") -- set(OpenMP_CXX_LIB_NAMES "libomp" "libgomp" "libiomp5") -- set(OpenMP_libomp_LIBRARY ${OpenMP_CXX_LIB_NAMES}) -- set(OpenMP_libgomp_LIBRARY ${OpenMP_CXX_LIB_NAMES}) -- set(OpenMP_libiomp5_LIBRARY ${OpenMP_CXX_LIB_NAMES}) --else() -- find_package(OpenMP REQUIRED) --endif() -- --message("OpenMP_CXX_LIB_NAMES: ${OpenMP_CXX_LIB_NAMES}") --message("OpenMP_gomp_LIBRARY: ${OpenMP_gomp_LIBRARY}") --message("OpenMP_pthread_LIBRARY: ${OpenMP_pthread_LIBRARY}") --message("OpenMP_CXX_FLAGS: ${OpenMP_CXX_FLAGS}") -- --link_libraries(${OpenMP_gomp_LIBRARY}) --link_libraries(${OpenMP_pthread_LIBRARY}) -- - ## HIP - find_package(HIP REQUIRED) - # Override HIP version in config.h, if necessary. -@@ -269,12 +248,6 @@ if( DEFINED CK_OVERRIDE_HIP_VERSION_PATCH ) - message(STATUS "CK_HIP_VERSION_PATCH overridden with ${CK_OVERRIDE_HIP_VERSION_PATCH}") - endif() - message(STATUS "Build with HIP ${HIP_VERSION}") --link_libraries(hip::device) --if(CK_hip_VERSION VERSION_GREATER_EQUAL 6.0.23494) -- add_compile_definitions(__HIP_PLATFORM_AMD__=1) --else() -- add_compile_definitions(__HIP_PLATFORM_HCC__=1) --endif() - - ## tidy - include(EnableCompilerWarnings) -@@ -541,11 +514,3 @@ rocm_install(FILES - - set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") - set(CPACK_RPM_PACKAGE_LICENSE "MIT") -- --rocm_create_package( -- NAME composablekernel -- DESCRIPTION "High Performance Composable Kernel for AMD GPUs" -- MAINTAINER "MIOpen Kernels Dev Team " -- LDCONFIG -- HEADER_ONLY --) -diff --git a/example/ck_tile/01_fmha/generate.py b/example/ck_tile/01_fmha/generate.py -index 51fecd07b..5ed371995 100644 ---- a/example/ck_tile/01_fmha/generate.py -+++ b/example/ck_tile/01_fmha/generate.py -@@ -566,7 +566,7 @@ def write_blobs(output_dir : Optional[str], kernel_filter : Optional[str], recei - def list_blobs(output_file : Optional[str], kernel_filter : Optional[str], receipt, mask_impl) -> None: - assert output_file is not None - file_path = Path(output_file) -- with file_path.open('a') as f: -+ with file_path.open('w') as f: - _, kernels = get_blobs(kernel_filter, receipt, mask_impl) - for kernel in kernels: - f.write(str(file_path.parent / GEN_DIR / kernel.filename) + "\n") -diff --git a/include/ck/host_utility/hip_check_error.hpp b/include/ck/host_utility/hip_check_error.hpp -index c0894f1d7..559481fee 100644 ---- a/include/ck/host_utility/hip_check_error.hpp -+++ b/include/ck/host_utility/hip_check_error.hpp -@@ -6,19 +6,7 @@ - #include - #include - --// To be removed, which really does not tell the location of failed HIP functional call --inline void hip_check_error(hipError_t x) --{ -- if(x != hipSuccess) -- { -- std::ostringstream ss; -- ss << "HIP runtime error: " << hipGetErrorString(x) << ". " -- << "hip_check_error.hpp" -- << ": " << __LINE__ << "in function: " << __func__; -- throw std::runtime_error(ss.str()); -- } --} -- -+#ifndef HIP_CHECK_ERROR - #define HIP_CHECK_ERROR(retval_or_funcall) \ - do \ - { \ -@@ -32,3 +20,9 @@ inline void hip_check_error(hipError_t x) - throw std::runtime_error(ostr.str()); \ - } \ - } while(0) -+#endif -+ -+#ifndef hip_check_error -+#define hip_check_error HIP_CHECK_ERROR -+#endif -+ -diff --git a/include/ck_tile/core/utility/transpose_vectors.hpp b/include/ck_tile/core/utility/transpose_vectors.hpp -index a164c3f94..293ead89a 100644 ---- a/include/ck_tile/core/utility/transpose_vectors.hpp -+++ b/include/ck_tile/core/utility/transpose_vectors.hpp -@@ -11,6 +11,9 @@ - - namespace ck_tile { - -+template -+constexpr bool always_false = false; -+ - // S: scalar type (or it can be non-scalar type) - // NX: # of vector before transpose - // NY: # of vector after transpose -@@ -117,9 +120,11 @@ struct transpose_vectors - } - else - { -- static_assert(false, "not implemented"); -+ static_assert(always_false, number>, "not implemented"); - } - } - }; - -+ - } // namespace ck_tile -+ -diff --git a/include/ck_tile/host/hip_check_error.hpp b/include/ck_tile/host/hip_check_error.hpp -index 3acdb4d87..cc26e184f 100644 ---- a/include/ck_tile/host/hip_check_error.hpp -+++ b/include/ck_tile/host/hip_check_error.hpp -@@ -8,20 +8,7 @@ - #include - #include - --namespace ck_tile { --// To be removed, which really does not tell the location of failed HIP functional call --CK_TILE_HOST void hip_check_error(hipError_t x) --{ -- if(x != hipSuccess) -- { -- std::ostringstream ss; -- ss << "HIP runtime error: " << hipGetErrorString(x) << ". " << __FILE__ << ": " << __LINE__ -- << "in function: " << __func__; -- throw std::runtime_error(ss.str()); -- } --} --} // namespace ck_tile -- -+#ifndef HIP_CHECK_ERROR - #define HIP_CHECK_ERROR(retval_or_funcall) \ - do \ - { \ -@@ -34,3 +21,9 @@ CK_TILE_HOST void hip_check_error(hipError_t x) - throw std::runtime_error(ostr.str()); \ - } \ - } while(0) -+#endif -+ -+#ifndef hip_check_error -+#define hip_check_error HIP_CHECK_ERROR -+#endif -+ -diff --git a/library/src/tensor_operation_instance/gpu/CMakeLists.txt b/library/src/tensor_operation_instance/gpu/CMakeLists.txt -index c035e7e56..8c5f36d2e 100644 ---- a/library/src/tensor_operation_instance/gpu/CMakeLists.txt -+++ b/library/src/tensor_operation_instance/gpu/CMakeLists.txt -@@ -59,8 +59,14 @@ function(add_instance_library INSTANCE_NAME) - endforeach() - #only continue if there are some source files left on the list - if(ARGN) -+ set_source_files_properties(${ARGN} PROPERTIES LANGUAGE HIP) - add_library(${INSTANCE_NAME} OBJECT ${ARGN}) -+ # Always disable debug symbol and C debug assert due to -+ # - Linker error: ... relocation truncated to fit ..., caused by object files to be linked are too huge. -+ # - https://github.com/ROCmSoftwarePlatform/composable_kernel/issues/622 -+ target_compile_options(${INSTANCE_NAME} PRIVATE -g0 -DNDEBUG) - target_compile_features(${INSTANCE_NAME} PUBLIC) -+ target_compile_definitions(${INSTANCE_NAME} PRIVATE "__HIP_PLATFORM_AMD__=1" "__HIP_PLATFORM_HCC__=1") - set_target_properties(${INSTANCE_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON) - clang_tidy_check(${INSTANCE_NAME}) - set(result 0) ---- ./include/ck/utility/amd_buffer_addressing.hpp 2024-09-05 10:12:33.343091000 +0800 -+++ ./include/ck/utility/amd_buffer_addressing_new.hpp 2024-09-05 10:12:20.276686000 +0800 -@@ -991,7 +991,8 @@ - asm volatile("s_mov_b32 m0, %0; \n\t" - "buffer_load_dword %1, %2, 0 offen lds;\n\t" ::"s"(lds_ptr_sgpr), - "v"(global_offset_bytes), -- "s"(src_resource)); -+ "s"(src_resource) -+ : "memory"); - #else - // LDS pointer must be attributed with the LDS address space. - __attribute__((address_space(3))) uint32_t* lds_ptr = ---- ./include/ck_tile/core/arch/amd_buffer_addressing.hpp 2024-09-05 10:18:28.884031000 +0800 -+++ ./include/ck_tile/core/arch/amd_buffer_addressing_new.hpp 2024-09-05 10:17:29.434931000 +0800 -@@ -26,7 +26,12 @@ - CK_TILE_DEVICE int32x4_t make_wave_buffer_resource(const void* ptr, uint32_t size = 0xffffffff) - { - buffer_resource res{ptr, size, CK_TILE_BUFFER_RESOURCE_3RD_DWORD}; -- return __builtin_bit_cast(int32x4_t, res); -+ int32x4_t r = __builtin_bit_cast(int32x4_t, res); -+ r.x = __builtin_amdgcn_readfirstlane(r.x); -+ r.y = __builtin_amdgcn_readfirstlane(r.y); -+ r.z = __builtin_amdgcn_readfirstlane(r.z); -+ r.w = __builtin_amdgcn_readfirstlane(r.w); -+ return r; - } - - // TODO: glc/slc/... -@@ -2016,7 +2021,8 @@ - asm volatile("s_mov_b32 m0, %0; \n\t" - "buffer_load_dword %1, %2, 0 offen lds;\n\t" ::"s"(lds_ptr_sgpr), - "v"(global_offset_bytes), -- "s"(src_resource)); -+ "s"(src_resource) -+ : "memory"); - #else - // LDS pointer must be attributed with the LDS address space. - __attribute__((address_space(3))) uint32_t* lds_ptr = diff --git a/cmake/patches/cpuinfo/9bb12d342fd9479679d505d93a478a6f9cd50a47.patch b/cmake/patches/cpuinfo/9bb12d342fd9479679d505d93a478a6f9cd50a47.patch deleted file mode 100644 index 7785621965b00..0000000000000 --- a/cmake/patches/cpuinfo/9bb12d342fd9479679d505d93a478a6f9cd50a47.patch +++ /dev/null @@ -1,35 +0,0 @@ -diff --git a/include/cpuinfo.h b/include/cpuinfo.h -index 6eb4b8c..4346a5a 100644 ---- a/include/cpuinfo.h -+++ b/include/cpuinfo.h -@@ -18,7 +18,7 @@ - #define CPUINFO_ARCH_X86 1 - #endif - --#if defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) -+#if defined(__x86_64__) || defined(__x86_64) || (defined(_M_X64) && !defined(_M_ARM64EC)) || (defined(_M_AMD64) && !defined(_M_ARM64EC)) - #define CPUINFO_ARCH_X86_64 1 - #endif - -@@ -26,7 +26,7 @@ - #define CPUINFO_ARCH_ARM 1 - #endif - --#if defined(__aarch64__) || defined(_M_ARM64) -+#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) - #define CPUINFO_ARCH_ARM64 1 - #endif - -diff --git a/src/arm/windows/init.c b/src/arm/windows/init.c -index de2f6cc..c3a7835 100644 ---- a/src/arm/windows/init.c -+++ b/src/arm/windows/init.c -@@ -175,7 +175,7 @@ static struct woa_chip_info* get_system_info_from_registry(void) { - if (chip_info == NULL) { - /* No match was found, so print a warning and assign the unknown - * case. */ -- cpuinfo_log_error( -+ cpuinfo_log_debug( - "Unknown chip model name '%ls'.\nPlease add new Windows on Arm SoC/chip support to arm/windows/init.c!", - text_buffer); - } else { diff --git a/cmake/patches/cpuinfo/fix_missing_sysfs_fallback.patch b/cmake/patches/cpuinfo/fix_missing_sysfs_fallback.patch new file mode 100644 index 0000000000000..005cd458fdd2b --- /dev/null +++ b/cmake/patches/cpuinfo/fix_missing_sysfs_fallback.patch @@ -0,0 +1,83 @@ +diff --git a/src/linux/processors.c b/src/linux/processors.c +index 47bee76..d0c5569 100644 +--- a/src/linux/processors.c ++++ b/src/linux/processors.c +@@ -2,0 +3 @@ ++#include +@@ -291,0 +293,22 @@ ++static uint32_t cpuinfo_linux_get_max_processor_from_sysconf( ++ uint32_t max_processors_count, ++ const char* processor_list_name) { ++ const long nproc = sysconf(_SC_NPROCESSORS_ONLN); ++ if (nproc <= 0) { ++ cpuinfo_log_warning( ++ "failed to query online processors from sysconf(_SC_NPROCESSORS_ONLN) for %s", ++ processor_list_name); ++ return UINT32_MAX; ++ } ++ ++ uint32_t max_processor = (uint32_t)(nproc - 1); ++ if ((uint64_t)nproc > (uint64_t)max_processors_count) { ++ cpuinfo_log_warning( ++ "online processors count %ld exceeds system limit %" PRIu32 ": truncating to the latter", ++ nproc, ++ max_processors_count); ++ max_processor = max_processors_count - 1; ++ } ++ return max_processor; ++} ++ +@@ -301 +324 @@ +- return UINT32_MAX; ++ return cpuinfo_linux_get_max_processor_from_sysconf(max_processors_count, POSSIBLE_CPULIST_FILENAME); +@@ -323 +346 @@ +- return UINT32_MAX; ++ return cpuinfo_linux_get_max_processor_from_sysconf(max_processors_count, PRESENT_CPULIST_FILENAME); +@@ -357,0 +381,31 @@ ++static bool cpuinfo_linux_detect_processors_from_sysconf( ++ uint32_t max_processors_count, ++ uint32_t* processor0_flags, ++ uint32_t processor_struct_size, ++ uint32_t detected_flag, ++ const char* processor_list_name) { ++ const long nproc = sysconf(_SC_NPROCESSORS_ONLN); ++ if (nproc <= 0) { ++ cpuinfo_log_warning( ++ "failed to query online processors from sysconf(_SC_NPROCESSORS_ONLN) for %s", ++ processor_list_name); ++ return false; ++ } ++ ++ uint32_t processors_count = (uint32_t)nproc; ++ if ((uint64_t)nproc > (uint64_t)max_processors_count) { ++ cpuinfo_log_warning( ++ "online processors count %ld exceeds system limit %" PRIu32 ": truncating to the latter", ++ nproc, ++ max_processors_count); ++ processors_count = max_processors_count; ++ } ++ ++ for (uint32_t processor = 0; processor < processors_count; processor++) { ++ *((uint32_t*)((uintptr_t)processor0_flags + processor_struct_size * processor)) |= detected_flag; ++ } ++ cpuinfo_log_warning( ++ "falling back to sysconf(_SC_NPROCESSORS_ONLN) = %ld for %s", nproc, processor_list_name); ++ return true; ++} ++ +@@ -373 +427,6 @@ +- return false; ++ return cpuinfo_linux_detect_processors_from_sysconf( ++ max_processors_count, ++ processor0_flags, ++ processor_struct_size, ++ possible_flag, ++ POSSIBLE_CPULIST_FILENAME); +@@ -392 +451,6 @@ +- return false; ++ return cpuinfo_linux_detect_processors_from_sysconf( ++ max_processors_count, ++ processor0_flags, ++ processor_struct_size, ++ present_flag, ++ PRESENT_CPULIST_FILENAME); diff --git a/cmake/patches/cpuinfo/patch_cpuinfo_h_for_arm64ec.patch b/cmake/patches/cpuinfo/patch_cpuinfo_h_for_arm64ec.patch new file mode 100644 index 0000000000000..23ceeb8f758cc --- /dev/null +++ b/cmake/patches/cpuinfo/patch_cpuinfo_h_for_arm64ec.patch @@ -0,0 +1,22 @@ +diff --git a/include/cpuinfo.h b/include/cpuinfo.h +index f1d35d4..9e454d2 100644 +--- a/include/cpuinfo.h ++++ b/include/cpuinfo.h +@@ -18,7 +18,7 @@ + #define CPUINFO_ARCH_X86 1 + #endif + +-#if defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) ++#if defined(__x86_64__) || defined(__x86_64) || (defined(_M_X64) && !defined(_M_ARM64EC)) || (defined(_M_AMD64) && !defined(_M_ARM64EC)) + #define CPUINFO_ARCH_X86_64 1 + #endif + +@@ -26,7 +26,7 @@ + #define CPUINFO_ARCH_ARM 1 + #endif + +-#if defined(__aarch64__) || defined(_M_ARM64) ++#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) + #define CPUINFO_ARCH_ARM64 1 + #endif + diff --git a/cmake/patches/cpuinfo/patch_vcpkg_arm64ec_support.patch b/cmake/patches/cpuinfo/patch_vcpkg_arm64ec_support.patch new file mode 100644 index 0000000000000..af0f039b6c2a3 --- /dev/null +++ b/cmake/patches/cpuinfo/patch_vcpkg_arm64ec_support.patch @@ -0,0 +1,91 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index aedc983..dab589e 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -72,6 +72,17 @@ IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD" AND CPUINFO_TARGET_PROCESSOR STREQUAL "am + ENDIF() + IF(IS_APPLE_OS AND CMAKE_OSX_ARCHITECTURES MATCHES "^(x86_64|arm64.*)$") + SET(CPUINFO_TARGET_PROCESSOR "${CMAKE_OSX_ARCHITECTURES}") ++ELSEIF(MSVC AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.10") ++ # Use CMAKE_C_COMPILER_ARCHITECTURE_ID. MSVC values are documented as available since CMake 3.10. ++ IF(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "X86") ++ SET(CPUINFO_TARGET_PROCESSOR "x86") ++ ELSEIF(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "x64") ++ SET(CPUINFO_TARGET_PROCESSOR "x86_64") ++ ELSEIF(CMAKE_C_COMPILER_ARCHITECTURE_ID MATCHES "^(ARM64|ARM64EC)$") ++ SET(CPUINFO_TARGET_PROCESSOR "arm64") ++ ELSE() ++ MESSAGE(FATAL_ERROR "Unsupported MSVC compiler architecture ID \"${CMAKE_C_COMPILER_ARCHITECTURE_ID}\"") ++ ENDIF() + ELSEIF(CMAKE_GENERATOR MATCHES "^Visual Studio " AND CMAKE_VS_PLATFORM_NAME) + IF(CMAKE_VS_PLATFORM_NAME STREQUAL "Win32") + SET(CPUINFO_TARGET_PROCESSOR "x86") +@@ -88,7 +99,7 @@ ENDIF() + + # ---[ Build flags + SET(CPUINFO_SUPPORTED_PLATFORM TRUE) +-IF(NOT CMAKE_SYSTEM_PROCESSOR) ++IF(NOT CPUINFO_TARGET_PROCESSOR) + IF(NOT IOS) + MESSAGE(WARNING + "Target processor architecture is not specified. " +@@ -201,12 +212,12 @@ IF(CPUINFO_SUPPORTED_PLATFORM) + src/arm/linux/chipset.c + src/arm/linux/midr.c + src/arm/linux/hwcap.c) +- IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^armv[5-8]") ++ IF(CPUINFO_TARGET_PROCESSOR MATCHES "^armv[5-8]") + LIST(APPEND CPUINFO_SRCS src/arm/linux/aarch32-isa.c) + IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND ANDROID_ABI STREQUAL "armeabi") + SET_SOURCE_FILES_PROPERTIES(src/arm/linux/aarch32-isa.c PROPERTIES COMPILE_FLAGS -marm) + ENDIF() +- ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)$") ++ ELSEIF(CPUINFO_TARGET_PROCESSOR MATCHES "^(aarch64|arm64)$") + LIST(APPEND CPUINFO_SRCS src/arm/linux/aarch64-isa.c) + ENDIF() + ELSEIF(IS_APPLE_OS AND CPUINFO_TARGET_PROCESSOR MATCHES "arm64.*") +@@ -395,7 +406,7 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_MOCK_TESTS) + TARGET_COMPILE_DEFINITIONS(cpuinfo_mock PRIVATE _GNU_SOURCE=1) + ENDIF() + +- IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv5te|armv7-a)$") ++ IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(armv5te|armv7-a)$") + ADD_EXECUTABLE(atm7029b-tablet-test test/mock/atm7029b-tablet.cc) + TARGET_INCLUDE_DIRECTORIES(atm7029b-tablet-test BEFORE PRIVATE test/mock) + TARGET_LINK_LIBRARIES(atm7029b-tablet-test PRIVATE cpuinfo_mock gtest) +@@ -577,7 +588,7 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_MOCK_TESTS) + ADD_TEST(NAME xperia-sl-test COMMAND xperia-sl-test) + ENDIF() + +- IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv5te|armv7-a|aarch64)$") ++ IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(armv5te|armv7-a|aarch64)$") + ADD_EXECUTABLE(alcatel-revvl-test test/mock/alcatel-revvl.cc) + TARGET_INCLUDE_DIRECTORIES(alcatel-revvl-test BEFORE PRIVATE test/mock) + TARGET_LINK_LIBRARIES(alcatel-revvl-test PRIVATE cpuinfo_mock gtest) +@@ -774,7 +785,7 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_MOCK_TESTS) + ADD_TEST(NAME xperia-c4-dual-test COMMAND xperia-c4-dual-test) + ENDIF() + +- IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|x86_64)$") ++ IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(i686|x86_64)$") + ADD_EXECUTABLE(alldocube-iwork8-test test/mock/alldocube-iwork8.cc) + TARGET_INCLUDE_DIRECTORIES(alldocube-iwork8-test BEFORE PRIVATE test/mock) + TARGET_LINK_LIBRARIES(alldocube-iwork8-test PRIVATE cpuinfo_mock gtest) +@@ -831,7 +842,7 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_UNIT_TESTS) + ADD_TEST(NAME brand-string-test COMMAND brand-string-test) + ENDIF() + +- IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv[5-8].*|aarch64)$") ++ IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(armv[5-8].*|aarch64)$") + ADD_LIBRARY(android_properties_interface STATIC test/name/android-properties-interface.c) + CPUINFO_TARGET_ENABLE_C99(android_properties_interface) + CPUINFO_TARGET_RUNTIME_LIBRARY(android_properties_interface) +@@ -879,7 +890,7 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_TOOLS) + TARGET_LINK_LIBRARIES(cache-info PRIVATE cpuinfo) + INSTALL(TARGETS cache-info RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +- IF(CMAKE_SYSTEM_NAME MATCHES "^(Android|Linux)$" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv[5-8].*|aarch64)$") ++ IF(CMAKE_SYSTEM_NAME MATCHES "^(Android|Linux)$" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(armv[5-8].*|aarch64)$") + ADD_EXECUTABLE(auxv-dump tools/auxv-dump.c) + CPUINFO_TARGET_ENABLE_C99(auxv-dump) + CPUINFO_TARGET_RUNTIME_LIBRARY(auxv-dump) diff --git a/cmake/patches/cpuinfo/win_arm_fp16_detection_fallback.patch b/cmake/patches/cpuinfo/win_arm_fp16_detection_fallback.patch new file mode 100644 index 0000000000000..44ac0f13f5466 --- /dev/null +++ b/cmake/patches/cpuinfo/win_arm_fp16_detection_fallback.patch @@ -0,0 +1,19 @@ +diff --git a/src/arm/windows/init.c b/src/arm/windows/init.c +index 5c0a5f3..a07fbe4 100644 +--- a/src/arm/windows/init.c ++++ b/src/arm/windows/init.c +@@ -249,6 +249,14 @@ static void set_cpuinfo_isa_fields(void) { + // guarantee that, but it holds in practice. + cpuinfo_isa.rdm = dotprod; + ++ // PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE may not be available in older ++ // Windows versions. If fp16arith was not detected with ++ // IsProcessorFeaturePresent(PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE), fall ++ // back to using the value of dotprod. ++ if (!cpuinfo_isa.fp16arith) { ++ cpuinfo_isa.fp16arith = dotprod; ++ } ++ + /* Windows API reports all or nothing for cryptographic instructions. */ + const bool crypto = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0; + cpuinfo_isa.aes = crypto; diff --git a/cmake/patches/cutlass/cutlass_4.4.2.patch b/cmake/patches/cutlass/cutlass_4.4.2.patch new file mode 100644 index 0000000000000..6776eded10640 --- /dev/null +++ b/cmake/patches/cutlass/cutlass_4.4.2.patch @@ -0,0 +1,54 @@ +diff --git a/include/cute/layout.hpp b/include/cute/layout.hpp +index cb161369..2fdff179 100644 +--- a/include/cute/layout.hpp ++++ b/include/cute/layout.hpp +@@ -1487,7 +1487,7 @@ nullspace(Layout const& layout) + [[maybe_unused]] auto flat_stride = flatten(layout.stride()); + + // Select all indices corresponding to stride-0s +- auto iseq = cute::fold(make_seq>{}, cute::tuple<>{}, ++ [[maybe_unused]] auto iseq = cute::fold(make_seq>{}, cute::tuple<>{}, + [&](auto init, auto i){ + if constexpr (is_constant_v<0, decltype(get(flat_stride))>) { return append(init, i); } + else { return init; } +diff --git a/include/cutlass/cuda_host_adapter.hpp b/include/cutlass/cuda_host_adapter.hpp +index a8af62be..22e7332d 100644 +--- a/include/cutlass/cuda_host_adapter.hpp ++++ b/include/cutlass/cuda_host_adapter.hpp +@@ -394,6 +394,10 @@ protected: + * Fills a buffer in Global Memory with a byte sequence copied from host memory. + * This function can be overridden to dispatch to the appropriate cuMemsetD*Async API + */ ++ // Patching to work around this error: ++ // include\cutlass/cuda_host_adapter.hpp(414): error #20011-D: calling a __host__ function("memsetDeviceImpl") ++ // from a __host__ __device__ function("memsetDevice") is not allowed ++ CUTLASS_HOST_DEVICE + virtual Status memsetDeviceImpl( + void* destination, ///< Device memory pointer to be filled + void const* fill_value, ///< Value to be filled in the buffer +diff --git a/include/cutlass/exmy_base.h b/include/cutlass/exmy_base.h +index be207a49..6028e01d 100644 +--- a/include/cutlass/exmy_base.h ++++ b/include/cutlass/exmy_base.h +@@ -1021,18 +1021,18 @@ struct float_exmy_base + + /// Floating point conversion + CUTLASS_HOST_DEVICE +- explicit float_exmy_base(float x) { ++ explicit float_exmy_base(float x) { + storage = static_cast(this)->convert_from_float(x).storage; + } + + // Integer conversion + CUTLASS_HOST_DEVICE +- explicit float_exmy_base(int x) { ++ explicit float_exmy_base(int x) { + storage = static_cast(this)->convert_from_float(float(x)).storage; + } + + CUTLASS_HOST_DEVICE +- explicit float_exmy_base(unsigned x) { ++ explicit float_exmy_base(unsigned x) { + storage = static_cast(this)->convert_from_float(float(x)).storage; + } + diff --git a/cmake/patches/date/date.patch b/cmake/patches/date/date.patch new file mode 100644 index 0000000000000..b3c384b62e834 --- /dev/null +++ b/cmake/patches/date/date.patch @@ -0,0 +1,15 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 012512a..548ee4c 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -24,8 +24,8 @@ include( GNUInstallDirs ) + + get_directory_property( has_parent PARENT_DIRECTORY ) + +-# Override by setting on CMake command line. +-set( CMAKE_CXX_STANDARD 17 CACHE STRING "The C++ standard whose features are requested." ) ++# Don't explicitly set CMAKE_CXX_STANDARD as a cache variable. ++# Cache variables are sticky and global. They may override values from other projects. + + option( USE_SYSTEM_TZ_DB "Use the operating system's timezone database" OFF ) + option( MANUAL_TZ_DB "User will set TZ DB manually by invoking set_install in their code" OFF ) diff --git a/cmake/patches/dawn/dawn_binskim.patch b/cmake/patches/dawn/dawn_binskim.patch new file mode 100644 index 0000000000000..213eb644dc5a2 --- /dev/null +++ b/cmake/patches/dawn/dawn_binskim.patch @@ -0,0 +1,13 @@ +diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt +index 0d5f52a358..90764d21b5 100644 +--- a/src/tint/CMakeLists.txt ++++ b/src/tint/CMakeLists.txt +@@ -143,8 +143,6 @@ function(tint_default_compile_options TARGET) + /W4 + /wd4068 # unknown pragma + /wd4127 # conditional expression is constant +- /wd4244 # 'conversion' conversion from 'type1' to 'type2', possible loss of data +- /wd4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data + /wd4324 # 'struct_name' : structure was padded due to __declspec(align()) + /wd4459 # declaration of 'identifier' hides global declaration + /wd4458 # declaration of 'identifier' hides class member diff --git a/cmake/patches/dawn/dawn_buffer_fix_injection.patch b/cmake/patches/dawn/dawn_buffer_fix_injection.patch new file mode 100644 index 0000000000000..5546311a9901f --- /dev/null +++ b/cmake/patches/dawn/dawn_buffer_fix_injection.patch @@ -0,0 +1,35 @@ +diff --git a/third_party/emdawnwebgpu/pkg/webgpu/src/webgpu.cpp b/third_party/emdawnwebgpu/pkg/webgpu/src/webgpu.cpp +--- a/third_party/emdawnwebgpu/pkg/webgpu/src/webgpu.cpp ++++ b/third_party/emdawnwebgpu/pkg/webgpu/src/webgpu.cpp +@@ -749,7 +749,7 @@ struct WGPUBufferImpl final : public EventSource, + public: + WGPUBufferImpl(const EventSource* source, bool mappedAtCreation); + // Injection constructor used when we already have a backing Buffer. +- WGPUBufferImpl(const EventSource* source, WGPUBufferMapState mapState); ++ WGPUBufferImpl(const EventSource* source); + ~WGPUBufferImpl(); + + void Destroy(); +@@ -1301,7 +1301,7 @@ WGPUAdapter emwgpuCreateAdapter(const EventSource* source) { + } + + WGPUBuffer emwgpuCreateBuffer(const EventSource* source) { +- return ReturnToAPI(AcquireRef(new WGPUBufferImpl(source, false))); ++ return ReturnToAPI(AcquireRef(new WGPUBufferImpl(source))); + } + + WGPUDevice emwgpuCreateDevice(const EventSource* source, WGPUQueue queue) { +@@ -1441,11 +1441,10 @@ WGPUBufferImpl::WGPUBufferImpl(const EventSource* source, bool mappedAtCreation) + } + } + +-WGPUBufferImpl::WGPUBufferImpl(const EventSource* source, +- WGPUBufferMapState mapState) ++WGPUBufferImpl::WGPUBufferImpl(const EventSource* source) + : EventSource(source), + RefCountedWithExternalCount(kImportedFromJS), +- mMapState(mapState) {} ++ mMapState(WGPUBufferMapState_Unmapped) {} + + WGPUBufferImpl::~WGPUBufferImpl() { + if (!IsImported()) { diff --git a/cmake/patches/dawn/dawn_destroy_buffer_on_destructor.patch b/cmake/patches/dawn/dawn_destroy_buffer_on_destructor.patch new file mode 100644 index 0000000000000..6bfbe6427ab83 --- /dev/null +++ b/cmake/patches/dawn/dawn_destroy_buffer_on_destructor.patch @@ -0,0 +1,25 @@ +diff --git a/third_party/emdawnwebgpu/pkg/webgpu/src/webgpu.cpp b/third_party/emdawnwebgpu/pkg/webgpu/src/webgpu.cpp +index be0bb93781..4fe1d34b29 100644 +--- a/third_party/emdawnwebgpu/pkg/webgpu/src/webgpu.cpp ++++ b/third_party/emdawnwebgpu/pkg/webgpu/src/webgpu.cpp +@@ -734,6 +734,7 @@ struct WGPUBufferImpl final : public EventSource, + WGPUBufferImpl(const EventSource* source, bool mappedAtCreation); + // Injection constructor used when we already have a backing Buffer. + WGPUBufferImpl(const EventSource* source, WGPUBufferMapState mapState); ++ ~WGPUBufferImpl(); + + void Destroy(); + const void* GetConstMappedRange(size_t offset, size_t size); +@@ -1416,6 +1417,12 @@ WGPUBufferImpl::WGPUBufferImpl(const EventSource* source, + RefCountedWithExternalCount(kImportedFromJS), + mMapState(mapState) {} + ++WGPUBufferImpl::~WGPUBufferImpl() { ++ if (!IsImported()) { ++ Destroy(); ++ } ++} ++ + void WGPUBufferImpl::Destroy() { + emwgpuBufferDestroy(this); + AbortPendingMap("Buffer was destroyed before mapping was resolved."); diff --git a/cmake/patches/dawn/dawn_device_lost_keepalive.patch b/cmake/patches/dawn/dawn_device_lost_keepalive.patch new file mode 100644 index 0000000000000..1d522c2e7ba71 --- /dev/null +++ b/cmake/patches/dawn/dawn_device_lost_keepalive.patch @@ -0,0 +1,22 @@ +diff --git a/third_party/emdawnwebgpu/pkg/webgpu/src/library_webgpu.js b/third_party/emdawnwebgpu/pkg/webgpu/src/library_webgpu.js +--- a/third_party/emdawnwebgpu/pkg/webgpu/src/library_webgpu.js ++++ b/third_party/emdawnwebgpu/pkg/webgpu/src/library_webgpu.js +@@ -876,7 +876,9 @@ + #if ASSERTIONS + assert(deviceLostFutureId); + #endif +- // Don't keepalive here, because this isn't guaranteed to ever happen. ++ // Keep the runtime alive until device.lost resolves, to prevent ++ // maybeExit() from triggering premature ABORT during callUserCallback. ++ {{{ runtimeKeepalivePush() }}} + WebGPU.Internals.futureInsert(deviceLostFutureId, device.lost.then((info) => { + // If the runtime has exited, avoid calling callUserCallback as it + // will print an error (e.g. if the device got freed during shutdown). +@@ -892,6 +894,7 @@ + {{{ gpu.passAsPointer('messagePtr') }}}); + stackRestore(sp); + }); ++ {{{ runtimeKeepalivePop() }}} + })); + + // Set up uncaptured error handlers. diff --git a/cmake/patches/dawn/dawn_dxc_output_dir.patch b/cmake/patches/dawn/dawn_dxc_output_dir.patch new file mode 100644 index 0000000000000..1036cf6d3f3f0 --- /dev/null +++ b/cmake/patches/dawn/dawn_dxc_output_dir.patch @@ -0,0 +1,17 @@ +diff --git a/third_party/CMakeLists.txt b/third_party/CMakeLists.txt +--- a/third_party/CMakeLists.txt ++++ b/third_party/CMakeLists.txt +@@ -338,10 +338,14 @@ + if (isMultiConfig) + set_target_properties(dxc dxcompiler PROPERTIES + "RUNTIME_OUTPUT_DIRECTORY_DEBUG" "${CMAKE_BINARY_DIR}/$" + "RUNTIME_OUTPUT_DIRECTORY_RELEASE" "${CMAKE_BINARY_DIR}/$" ++ "RUNTIME_OUTPUT_DIRECTORY_RELWITHDEBINFO" "${CMAKE_BINARY_DIR}/$" ++ "RUNTIME_OUTPUT_DIRECTORY_MINSIZEREL" "${CMAKE_BINARY_DIR}/$" + "LIBRARY_OUTPUT_DIRECTORY_DEBUG" "${CMAKE_BINARY_DIR}/$" + "LIBRARY_OUTPUT_DIRECTORY_RELEASE" "${CMAKE_BINARY_DIR}/$" ++ "LIBRARY_OUTPUT_DIRECTORY_RELWITHDEBINFO" "${CMAKE_BINARY_DIR}/$" ++ "LIBRARY_OUTPUT_DIRECTORY_MINSIZEREL" "${CMAKE_BINARY_DIR}/$" + ) + else() + set_target_properties(dxc dxcompiler PROPERTIES diff --git a/cmake/patches/dawn/safari_polyfill.patch b/cmake/patches/dawn/safari_polyfill.patch new file mode 100644 index 0000000000000..33cb657961337 --- /dev/null +++ b/cmake/patches/dawn/safari_polyfill.patch @@ -0,0 +1,17 @@ +diff --git a/third_party/emdawnwebgpu/pkg/webgpu/src/library_webgpu.js b/third_party/emdawnwebgpu/pkg/webgpu/src/library_webgpu.js +index a3ce6dc732..7119eae424 100644 +--- a/third_party/emdawnwebgpu/pkg/webgpu/src/library_webgpu.js ++++ b/third_party/emdawnwebgpu/pkg/webgpu/src/library_webgpu.js +@@ -903,6 +903,12 @@ var LibraryWebGPU = { + stackRestore(sp); + }; + ++ // Polyfill `device.AdapterInfo` if not present (Safari v26.0). ++ // See https://bugs.webkit.org/show_bug.cgi?id=301878 ++ if (!('adapterInfo' in device)) { ++ device.adapterInfo = adapter.info; ++ } ++ + _emwgpuOnRequestDeviceCompleted(futureId, {{{ gpu.RequestDeviceStatus.Success }}}, + {{{ gpu.passAsPointer('devicePtr') }}}, {{{ gpu.NULLPTR }}}); + }, (ex) => { diff --git a/cmake/patches/eigen/eigen-aix.patch b/cmake/patches/eigen/eigen-aix.patch deleted file mode 100644 index 653b54b8d3d63..0000000000000 --- a/cmake/patches/eigen/eigen-aix.patch +++ /dev/null @@ -1,250 +0,0 @@ -diff --git a/Eigen/src/Core/arch/AltiVec/MatrixProduct.h b/Eigen/src/Core/arch/AltiVec/MatrixProduct.h -index 8feb88ea7..01b50b7c4 100644 ---- a/Eigen/src/Core/arch/AltiVec/MatrixProduct.h -+++ b/Eigen/src/Core/arch/AltiVec/MatrixProduct.h -@@ -15,6 +15,21 @@ - #define EIGEN_ALTIVEC_USE_CUSTOM_PACK 1 - #endif - -+#ifdef _AIX -+#define POWER_10 0x40000 -+#define POWER_10_ANDUP (POWER_10) -+#include -+#define __power_10_andup() (_system_configuration.implementation & POWER_10_ANDUP) -+ -+static bool check_mma_support() -+{ -+ if(__power_10_andup() && __power_mma_version() == MMA_V31) -+ return true; -+ else -+ return false; -+} -+#endif -+ - #include "MatrixProductCommon.h" - - // Since LLVM doesn't support dynamic dispatching, force either always MMA or VSX -@@ -2481,12 +2496,21 @@ void gebp_kernel; - #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) -- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -- gemm_function = &Eigen::internal::gemmMMA; -- } -- else{ -- gemm_function = &Eigen::internal::gemm; -- } -+ #if defined(_AIX) -+ if(check_mma_support()){ -+ gemm_function = &Eigen::internal::gemmMMA; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm; -+ } -+ #else -+ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -+ gemm_function = &Eigen::internal::gemmMMA; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm; -+ } -+ #endif - #else - gemm_function = &Eigen::internal::gemm; - #endif -@@ -2520,12 +2544,21 @@ void gebp_kernel, std::complex, Index, DataMapper, mr - //generate with MMA only - gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; - #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) -- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -- gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -- } -- else{ -- gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -- } -+ #if defined(_AIX) -+ if (check_mma_support()){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -+ } -+ #else -+ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -+ } -+ #endif - #else - gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; - #endif -@@ -2558,12 +2591,21 @@ void gebp_kernel, Index, DataMapper, mr, nr, Conjugat - //generate with MMA only - gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; - #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) -- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -- gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -- } -- else{ -- gemm_function = &Eigen::internal::gemm_complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -- } -+ #if defined(_AIX) -+ if (check_mma_support()){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -+ } -+ #else -+ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -+ } -+ #endif - #else - gemm_function = &Eigen::internal::gemm_complex, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; - #endif -@@ -2596,12 +2638,21 @@ void gebp_kernel, float, Index, DataMapper, mr, nr, Conjugat - //generate with MMA only - gemm_function = &Eigen::internal::gemm_complexMMA, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; - #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) -- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -- gemm_function = &Eigen::internal::gemm_complexMMA, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -- } -- else{ -- gemm_function = &Eigen::internal::gemm_complex, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -- } -+ #if defined(_AIX) -+ if (check_mma_support()){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -+ } -+ #else -+ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -+ } -+ #endif - #else - gemm_function = &Eigen::internal::gemm_complex, float, std::complex, float, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; - #endif -@@ -2633,12 +2684,21 @@ void gebp_kernel; - #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) -- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -- gemm_function = &Eigen::internal::gemmMMA; -- } -- else{ -- gemm_function = &Eigen::internal::gemm; -- } -+ #if defined(_AIX) -+ if (check_mma_support()){ -+ gemm_function = &Eigen::internal::gemmMMA; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm; -+ } -+ #else -+ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -+ gemm_function = &Eigen::internal::gemmMMA; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm; -+ } -+ #endif - #else - gemm_function = &Eigen::internal::gemm; - #endif -@@ -2671,12 +2731,21 @@ void gebp_kernel, std::complex, Index, DataMapper, - //generate with MMA only - gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; - #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) -- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -- gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -- } -- else{ -- gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -- } -+ #if defined(_AIX) -+ if (check_mma_support()){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -+ } -+ #else -+ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; -+ } -+ #endif - #else - gemm_function = &Eigen::internal::gemm_complex, std::complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, false>; - #endif -@@ -2709,12 +2778,21 @@ void gebp_kernel, double, Index, DataMapper, mr, nr, Conjug - //generate with MMA only - gemm_function = &Eigen::internal::gemm_complexMMA, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; - #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) -- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -- gemm_function = &Eigen::internal::gemm_complexMMA, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -- } -- else{ -- gemm_function = &Eigen::internal::gemm_complex, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -- } -+ #if defined(_AIX) -+ if (check_mma_support()){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -+ } -+ #else -+ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; -+ } -+ #endif - #else - gemm_function = &Eigen::internal::gemm_complex, double, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, false, true>; - #endif -@@ -2747,12 +2825,21 @@ void gebp_kernel, Index, DataMapper, mr, nr, Conjug - //generate with MMA only - gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; - #elif defined(ALTIVEC_MMA_SUPPORT) && !defined(EIGEN_ALTIVEC_DISABLE_MMA) -- if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -- gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -- } -- else{ -- gemm_function = &Eigen::internal::gemm_complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -- } -+ #if defined(_AIX) -+ if (check_mma_support()){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -+ } -+ #else -+ if (__builtin_cpu_supports ("arch_3_1") && __builtin_cpu_supports ("mma")){ -+ gemm_function = &Eigen::internal::gemm_complexMMA, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -+ } -+ else{ -+ gemm_function = &Eigen::internal::gemm_complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; -+ } -+ #endif - #else - gemm_function = &Eigen::internal::gemm_complex, std::complex, double, Index, Packet, Packetc, RhsPacket, DataMapper, accRows, accCols, ConjugateLhs, ConjugateRhs, true, false>; - #endif diff --git a/cmake/patches/eigen/eigen-edge.patch b/cmake/patches/eigen/eigen-edge.patch deleted file mode 100644 index d8dc850b4bd55..0000000000000 --- a/cmake/patches/eigen/eigen-edge.patch +++ /dev/null @@ -1,13 +0,0 @@ -diff --git a/Eigen/src/Core/util/IndexedViewHelper.h b/Eigen/src/Core/util/IndexedViewHelper.h -index f85de305f..3dc2bb5e7 100644 ---- a/Eigen/src/Core/util/IndexedViewHelper.h -+++ b/Eigen/src/Core/util/IndexedViewHelper.h -@@ -178,7 +178,7 @@ namespace placeholders { - - EIGEN_DEPRECATED static const all_t all = Eigen::all; // PLEASE use Eigen::all instead of Eigen::placeholders::all - EIGEN_DEPRECATED static const last_t last = Eigen::last; // PLEASE use Eigen::last instead of Eigen::placeholders::last -- EIGEN_DEPRECATED static const end_t end = Eigen::lastp1; // PLEASE use Eigen::lastp1 instead of Eigen::placeholders::end -+ // EIGEN_DEPRECATED static const end_t end = Eigen::lastp1; // PLEASE use Eigen::lastp1 instead of Eigen::placeholders::end - } - - } // end namespace Eigen diff --git a/cmake/patches/eigen/s390x-build-werror.patch b/cmake/patches/eigen/s390x-build-werror.patch new file mode 100644 index 0000000000000..d6aab355e2f2f --- /dev/null +++ b/cmake/patches/eigen/s390x-build-werror.patch @@ -0,0 +1,13 @@ +Comment out variable unused in onnxruntime + +--- a/Eigen/src/Core/arch/ZVector/PacketMath.h.orig 2025-10-21 10:24:49.410176124 +0000 ++++ b/Eigen/src/Core/arch/ZVector/PacketMath.h 2025-10-21 10:25:06.010176124 +0000 +@@ -101,7 +101,7 @@ + + static EIGEN_DECLARE_CONST_FAST_Packet4f(ZERO, 0); //{ 0.0, 0.0, 0.0, 0.0} + static EIGEN_DECLARE_CONST_FAST_Packet4i(MINUS1, -1); //{ -1, -1, -1, -1} +-static Packet4f p4f_MZERO = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; ++//static Packet4f p4f_MZERO = {0x80000000, 0x80000000, 0x80000000, 0x80000000}; + #endif + + static Packet4i p4i_COUNTDOWN = {0, 1, 2, 3}; diff --git a/cmake/patches/eigen/s390x-build.patch b/cmake/patches/eigen/s390x-build.patch new file mode 100644 index 0000000000000..e97c30a598c2b --- /dev/null +++ b/cmake/patches/eigen/s390x-build.patch @@ -0,0 +1,528 @@ +From 0e0d3fcf4a829391e4d06cf648fb2137816fa483 Mon Sep 17 00:00:00 2001 +From: Aleksei Nikiforov +Date: Wed, 30 Apr 2025 15:34:33 +0200 +Subject: [PATCH 1/6] Fix compilation of tests for s390x + +cmake command line is: +cmake -DBUILD_TESTING=ON -DEIGEN_TEST_Z13=ON -DEIGEN_TEST_Z14=ON -DEIGEN_TEST_ZVECTOR=ON + +then: +make && make check +--- + Eigen/src/Core/arch/ZVector/Complex.h | 37 +++-- + Eigen/src/Core/arch/ZVector/MathFunctions.h | 14 ++ + Eigen/src/Core/arch/ZVector/PacketMath.h | 162 ++++++++++++++++++-- + 3 files changed, 183 insertions(+), 30 deletions(-) + +diff --git a/Eigen/src/Core/arch/ZVector/Complex.h b/Eigen/src/Core/arch/ZVector/Complex.h +index a750b26b8..40e75d9f1 100644 +--- a/Eigen/src/Core/arch/ZVector/Complex.h ++++ b/Eigen/src/Core/arch/ZVector/Complex.h +@@ -20,7 +20,7 @@ namespace internal { + + #if !defined(__ARCH__) || (defined(__ARCH__) && __ARCH__ >= 12) + inline Packet4ui p4ui_CONJ_XOR() { +- return {0x00000000, 0x80000000, 0x00000000, 0x80000000}; // vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO); ++ return (Packet4ui) {0x00000000, 0x80000000, 0x00000000, 0x80000000}; // vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO); + } + #endif + +@@ -178,7 +178,7 @@ EIGEN_STRONG_INLINE Packet1cd pnegate(const Packet1cd& a) { + } + template <> + EIGEN_STRONG_INLINE Packet1cd pconj(const Packet1cd& a) { +- return Packet1cd((Packet2d)vec_xor((Packet2d)a.v, (Packet2d)p2ul_CONJ_XOR2)); ++ return Packet1cd((Packet2d)vec_xor((Packet2d)a.v, (Packet2d)p2ul_CONJ_XOR2())); + } + template <> + EIGEN_STRONG_INLINE Packet1cd pmul(const Packet1cd& a, const Packet1cd& b) { +@@ -257,8 +257,27 @@ EIGEN_STRONG_INLINE Packet1cd pdiv(const Packet1cd& a, const Packet1c + } + + template <> +-EIGEN_STRONG_INLINE Packet1cd plog(const Packet1cd& a, const Packet1cd& b) { +- return plog_complex(a, b); ++EIGEN_STRONG_INLINE Packet1cd psqrt(const Packet1cd& a) { ++ return psqrt_complex(a); ++} ++ ++template <> ++EIGEN_STRONG_INLINE Packet2cf psqrt(const Packet2cf& a) { ++ return psqrt_complex(a); ++} ++ ++template <> ++EIGEN_STRONG_INLINE Packet1cd plog(const Packet1cd& a) { ++ return plog_complex(a); ++} ++template <> ++EIGEN_STRONG_INLINE Packet2cf plog(const Packet2cf& a) { ++ return plog_complex(a); ++} ++ ++template <> ++EIGEN_STRONG_INLINE Packet2cf pexp(const Packet2cf& a) { ++ return pexp_complex(a); + } + + EIGEN_STRONG_INLINE Packet1cd pcplxflip /**/ (const Packet1cd& x) { +@@ -437,16 +456,6 @@ EIGEN_STRONG_INLINE Packet2cf pdiv(const Packet2cf& a, const Packet2c + return pdiv_complex(a, b); + } + +-template <> +-EIGEN_STRONG_INLINE Packet2cf plog(const Packet2cf& a, const Packet2cf& b) { +- return plog_complex(a, b); +-} +- +-template <> +-EIGEN_STRONG_INLINE Packet2cf pexp(const Packet2cf& a, const Packet2cf& b) { +- return pexp_complex(a, b); +-} +- + EIGEN_STRONG_INLINE Packet2cf pcplxflip /**/ (const Packet2cf& x) { + Packet2cf res; + res.cd[0] = pcplxflip(x.cd[0]); +diff --git a/Eigen/src/Core/arch/ZVector/MathFunctions.h b/Eigen/src/Core/arch/ZVector/MathFunctions.h +index 32e042554..683f6a3f9 100644 +--- a/Eigen/src/Core/arch/ZVector/MathFunctions.h ++++ b/Eigen/src/Core/arch/ZVector/MathFunctions.h +@@ -23,6 +23,20 @@ namespace Eigen { + + namespace internal { + ++EIGEN_DOUBLE_PACKET_FUNCTION(atanh, Packet2d) ++EIGEN_DOUBLE_PACKET_FUNCTION(log, Packet2d) ++EIGEN_DOUBLE_PACKET_FUNCTION(log2, Packet2d) ++EIGEN_DOUBLE_PACKET_FUNCTION(tanh, Packet2d) ++ ++EIGEN_FLOAT_PACKET_FUNCTION(atanh, Packet4f) ++EIGEN_FLOAT_PACKET_FUNCTION(log, Packet4f) ++EIGEN_FLOAT_PACKET_FUNCTION(log2, Packet4f) ++ ++EIGEN_GENERIC_PACKET_FUNCTION(atan, Packet2d) ++EIGEN_GENERIC_PACKET_FUNCTION(atan, Packet4f) ++EIGEN_GENERIC_PACKET_FUNCTION(exp2, Packet2d) ++EIGEN_GENERIC_PACKET_FUNCTION(exp2, Packet4f) ++ + #if !defined(__ARCH__) || (defined(__ARCH__) && __ARCH__ >= 12) + static EIGEN_DECLARE_CONST_Packet4f(1, 1.0f); + static EIGEN_DECLARE_CONST_Packet4f(half, 0.5f); +diff --git a/Eigen/src/Core/arch/ZVector/PacketMath.h b/Eigen/src/Core/arch/ZVector/PacketMath.h +index b45681320..286a53cf7 100644 +--- a/Eigen/src/Core/arch/ZVector/PacketMath.h ++++ b/Eigen/src/Core/arch/ZVector/PacketMath.h +@@ -250,6 +250,7 @@ struct unpacket_traits { + masked_store_available = false + }; + typedef Packet4f half; ++ typedef Packet4i integer_packet; + }; + template <> + struct unpacket_traits { +@@ -262,6 +263,7 @@ struct unpacket_traits { + masked_store_available = false + }; + typedef Packet2d half; ++ typedef Packet2l integer_packet; + }; + + /* Forward declaration */ +@@ -313,38 +315,36 @@ inline std::ostream& operator<<(std::ostream& s, const Packet4f& v) { + + template <> + EIGEN_STRONG_INLINE Packet4i pload(const int* from) { +- // FIXME: No intrinsic yet + EIGEN_DEBUG_ALIGNED_LOAD +- Packet* vfrom; +- vfrom = (Packet*)from; +- return vfrom->v4i; ++ return vec_xl(0, from); + } + + template <> + EIGEN_STRONG_INLINE Packet2d pload(const double* from) { +- // FIXME: No intrinsic yet + EIGEN_DEBUG_ALIGNED_LOAD +- Packet* vfrom; +- vfrom = (Packet*)from; +- return vfrom->v2d; ++ return vec_xl(0, from); + } + + template <> + EIGEN_STRONG_INLINE void pstore(int* to, const Packet4i& from) { +- // FIXME: No intrinsic yet + EIGEN_DEBUG_ALIGNED_STORE +- Packet* vto; +- vto = (Packet*)to; +- vto->v4i = from; ++ vec_xst(from, 0, to); + } + + template <> + EIGEN_STRONG_INLINE void pstore(double* to, const Packet2d& from) { +- // FIXME: No intrinsic yet + EIGEN_DEBUG_ALIGNED_STORE +- Packet* vto; +- vto = (Packet*)to; +- vto->v2d = from; ++ vec_xst(from, 0, to); ++} ++ ++template <> ++EIGEN_STRONG_INLINE Packet4f pfrexp(const Packet4f& a, Packet4f& exponent) { ++ return pfrexp_generic(a, exponent); ++} ++ ++template <> ++EIGEN_STRONG_INLINE Packet2d pfrexp(const Packet2d& a, Packet2d& exponent) { ++ return pfrexp_generic(a, exponent); + } + + template <> +@@ -590,6 +590,45 @@ EIGEN_STRONG_INLINE void prefetch(const double* addr) { + EIGEN_ZVECTOR_PREFETCH(addr); + } + ++template ++EIGEN_STRONG_INLINE Packet2l parithmetic_shift_right(const Packet2l& a) { ++ return Packet2l { parithmetic_shift_right(a[0]), parithmetic_shift_right(a[1]) }; ++} ++template ++EIGEN_STRONG_INLINE Packet4i parithmetic_shift_right(const Packet4i& a) { ++ return Packet4i { ++ parithmetic_shift_right(a[0]), ++ parithmetic_shift_right(a[1]), ++ parithmetic_shift_right(a[2]), ++ parithmetic_shift_right(a[3]) }; ++} ++ ++template ++EIGEN_STRONG_INLINE Packet2l plogical_shift_right(const Packet2l& a) { ++ return Packet2l { plogical_shift_right(a[0]), plogical_shift_right(a[1]) }; ++} ++template ++EIGEN_STRONG_INLINE Packet4i plogical_shift_right(const Packet4i& a) { ++ return Packet4i { ++ plogical_shift_right(a[0]), ++ plogical_shift_right(a[1]), ++ plogical_shift_right(a[2]), ++ plogical_shift_right(a[3]) }; ++} ++ ++template ++EIGEN_STRONG_INLINE Packet2l plogical_shift_left(const Packet2l& a) { ++ return Packet2l { plogical_shift_left(a[0]), plogical_shift_left(a[1]) }; ++} ++template ++EIGEN_STRONG_INLINE Packet4i plogical_shift_left(const Packet4i& a) { ++ return Packet4i { ++ plogical_shift_left(a[0]), ++ plogical_shift_left(a[1]), ++ plogical_shift_left(a[2]), ++ plogical_shift_left(a[3]) }; ++} ++ + template <> + EIGEN_STRONG_INLINE int pfirst(const Packet4i& a) { + EIGEN_ALIGN16 int x[4]; +@@ -1262,6 +1301,28 @@ EIGEN_STRONG_INLINE Packet4f pblend(const Selector<4>& ifPacket, const Packet4f& + + #endif + ++template <> ++EIGEN_STRONG_INLINE Packet4f pldexp(const Packet4f& a, const Packet4f& exponent) { ++ return pldexp_generic(a, exponent); ++} ++ ++template <> ++EIGEN_STRONG_INLINE Packet2d pldexp(const Packet2d& a, const Packet2d& exponent) { ++ // Clamp exponent to [-2099, 2099] ++ const Packet2d max_exponent = pset1(2099.0); ++ const Packet2l e = pcast(pmin(pmax(exponent, pnegate(max_exponent)), max_exponent)); ++ ++ // Split 2^e into four factors and multiply: ++ const Packet2l bias = {1023, 1023}; ++ Packet2l b = plogical_shift_right<2>(e); // floor(e/4) ++ Packet2d c = reinterpret_cast(plogical_shift_left<52>(b + bias)); ++ Packet2d out = pmul(pmul(pmul(a, c), c), c); // a * 2^(3b) ++ b = psub(psub(psub(e, b), b), b); // e - 3b ++ c = reinterpret_cast(plogical_shift_left<52>(b + bias)); // 2^(e - 3b) ++ out = pmul(out, c); // a * 2^e ++ return out; ++} ++ + template <> + EIGEN_STRONG_INLINE void prefetch(const float* addr) { + EIGEN_ZVECTOR_PREFETCH(addr); +@@ -1279,6 +1340,75 @@ EIGEN_STRONG_INLINE Packet4f plset(const float& a) { + return padd(pset1(a), p4f_COUNTDOWN); + } + ++#if !defined(vec_float) || !defined(__ARCH__) || (defined(__ARCH__) && __ARCH__ < 13) ++#warning \ ++ "float->int and int->float conversion is simulated. compile for z15 for improved performance" ++template <> ++struct cast_impl { ++ EIGEN_DEVICE_FUNC static inline Packet4f run(const Packet4i& a) { ++ return Packet4f{float(a[0]), float(a[1]), float(a[2]), float(a[3]) }; ++ } ++}; ++ ++template <> ++struct cast_impl { ++ EIGEN_DEVICE_FUNC static inline Packet4i run(const Packet4f& a) { ++ return Packet4i{int(a[0]), int(a[1]), int(a[2]), int(a[3]) }; ++ } ++}; ++ ++template <> ++struct cast_impl { ++ EIGEN_DEVICE_FUNC static inline Packet2d run(const Packet2l& a) { ++ return Packet2d{double(a[0]), double(a[1]) }; ++ } ++}; ++ ++template <> ++struct cast_impl { ++ EIGEN_DEVICE_FUNC static inline Packet2l run(const Packet2d& a) { ++ return Packet2l{(long long)(a[0]), (long long)(a[1]) }; ++ } ++}; ++#else ++template <> ++struct cast_impl { ++ EIGEN_DEVICE_FUNC static inline Packet4f run(const Packet4i& a) { ++ return vec_float(a); ++ } ++}; ++ ++template <> ++struct cast_impl { ++ EIGEN_DEVICE_FUNC static inline Packet4i run(const Packet4f& a) { ++ return vec_signed(a); ++ } ++}; ++ ++template <> ++struct cast_impl { ++ EIGEN_DEVICE_FUNC static inline Packet2d run(const Packet2l& a) { ++ return vec_double(a); ++ } ++}; ++ ++template <> ++struct cast_impl { ++ EIGEN_DEVICE_FUNC static inline Packet2l run(const Packet2d& a) { ++ return vec_signed(a); ++ } ++}; ++#endif ++ ++template <> ++EIGEN_STRONG_INLINE Packet4f pset1frombits(uint32_t from) { ++ return pset1(Eigen::numext::bit_cast(from)); ++} ++template <> ++EIGEN_STRONG_INLINE Packet2d pset1frombits(uint64_t from) { ++ return pset1(Eigen::numext::bit_cast(from)); ++} ++ + } // end namespace internal + + } // end namespace Eigen +-- +2.43.5 + + +From ab2ca76bfa39a0c70504a8a453f32463d525e560 Mon Sep 17 00:00:00 2001 +From: Aleksei Nikiforov +Date: Mon, 5 May 2025 13:50:21 +0200 +Subject: [PATCH 2/6] Fix random generation for long double on big endian + systems + +This change fixes rand_3 test, and maybe some others as well. +--- + Eigen/src/Core/RandomImpl.h | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/Eigen/src/Core/RandomImpl.h b/Eigen/src/Core/RandomImpl.h +index efba33680..1a82e6253 100644 +--- a/Eigen/src/Core/RandomImpl.h ++++ b/Eigen/src/Core/RandomImpl.h +@@ -131,8 +131,15 @@ struct random_longdouble_impl { + uint64_t randomBits[2]; + long double result = 2.0L; + memcpy(&randomBits, &result, Size); ++#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ + randomBits[0] |= getRandomBits(numLowBits); + randomBits[1] |= getRandomBits(numHighBits); ++#elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ ++ randomBits[0] |= getRandomBits(numHighBits); ++ randomBits[1] |= getRandomBits(numLowBits); ++#else ++#error Unexpected or undefined __BYTE_ORDER__ ++#endif + memcpy(&result, &randomBits, Size); + result -= 3.0L; + return result; +-- +2.43.5 + + +From 255654a39e8f0fcea006652e5ef9b2e58c8e10e0 Mon Sep 17 00:00:00 2001 +From: Aleksei Nikiforov +Date: Tue, 10 Jun 2025 13:34:46 +0200 +Subject: [PATCH 3/6] Fix pround on s390x + +pround now rounds away from 0 instead of towards to even numbers. +--- + Eigen/src/Core/arch/ZVector/PacketMath.h | 10 ++++++---- + 1 file changed, 6 insertions(+), 4 deletions(-) + +diff --git a/Eigen/src/Core/arch/ZVector/PacketMath.h b/Eigen/src/Core/arch/ZVector/PacketMath.h +index 286a53cf7..9c3a37a90 100644 +--- a/Eigen/src/Core/arch/ZVector/PacketMath.h ++++ b/Eigen/src/Core/arch/ZVector/PacketMath.h +@@ -540,7 +540,8 @@ EIGEN_STRONG_INLINE Packet2d pandnot(const Packet2d& a, const Packet2d + + template <> + EIGEN_STRONG_INLINE Packet2d pround(const Packet2d& a) { +- return vec_round(a); ++ /* Uses non-default rounding for vec_round */ ++ return __builtin_s390_vfidb(a, 0, 1); + } + template <> + EIGEN_STRONG_INLINE Packet2d pceil(const Packet2d& a) { +@@ -945,8 +946,8 @@ EIGEN_STRONG_INLINE Packet4f pandnot(const Packet4f& a, const Packet4f + template <> + EIGEN_STRONG_INLINE Packet4f pround(const Packet4f& a) { + Packet4f res; +- res.v4f[0] = vec_round(a.v4f[0]); +- res.v4f[1] = vec_round(a.v4f[1]); ++ res.v4f[0] = generic_round(a.v4f[0]); ++ res.v4f[1] = generic_round(a.v4f[1]); + return res; + } + +@@ -1210,7 +1211,8 @@ EIGEN_STRONG_INLINE Packet4f pandnot(const Packet4f& a, const Packet4f + } + template <> + EIGEN_STRONG_INLINE Packet4f pround(const Packet4f& a) { +- return vec_round(a); ++ /* Uses non-default rounding for vec_round */ ++ return __builtin_s390_vfisb(a, 0, 1); + } + template <> + EIGEN_STRONG_INLINE Packet4f pceil(const Packet4f& a) { +-- +2.43.5 + + +From 30bffb05324439a1878a5c14b12f13bb723dabba Mon Sep 17 00:00:00 2001 +From: Aleksei Nikiforov +Date: Tue, 10 Jun 2025 13:47:49 +0200 +Subject: [PATCH 4/6] Use vec_xl and vec_xst for pload and pstore on s390x + +Fix two missed occurrences. +--- + Eigen/src/Core/arch/ZVector/PacketMath.h | 10 ++-------- + 1 file changed, 2 insertions(+), 8 deletions(-) + +diff --git a/Eigen/src/Core/arch/ZVector/PacketMath.h b/Eigen/src/Core/arch/ZVector/PacketMath.h +index 9c3a37a90..0e88e383e 100644 +--- a/Eigen/src/Core/arch/ZVector/PacketMath.h ++++ b/Eigen/src/Core/arch/ZVector/PacketMath.h +@@ -1107,20 +1107,14 @@ Packet4f EIGEN_STRONG_INLINE pcmp_eq(const Packet4f& a, const Packet4f + #else + template <> + EIGEN_STRONG_INLINE Packet4f pload(const float* from) { +- // FIXME: No intrinsic yet + EIGEN_DEBUG_ALIGNED_LOAD +- Packet* vfrom; +- vfrom = (Packet*)from; +- return vfrom->v4f; ++ return vec_xl(0, from); + } + + template <> + EIGEN_STRONG_INLINE void pstore(float* to, const Packet4f& from) { +- // FIXME: No intrinsic yet + EIGEN_DEBUG_ALIGNED_STORE +- Packet* vto; +- vto = (Packet*)to; +- vto->v4f = from; ++ vec_xst(from, 0, to); + } + + template <> +-- +2.43.5 + + +From 0045fae6306a9a7846f4d5ecb4cfcfa3f8beafa9 Mon Sep 17 00:00:00 2001 +From: Aleksei Nikiforov +Date: Tue, 10 Jun 2025 13:48:32 +0200 +Subject: [PATCH 5/6] Update warning for march option on s390x + +--- + Eigen/src/Core/arch/ZVector/PacketMath.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Eigen/src/Core/arch/ZVector/PacketMath.h b/Eigen/src/Core/arch/ZVector/PacketMath.h +index 0e88e383e..e8eb1ff6d 100644 +--- a/Eigen/src/Core/arch/ZVector/PacketMath.h ++++ b/Eigen/src/Core/arch/ZVector/PacketMath.h +@@ -1337,7 +1337,7 @@ EIGEN_STRONG_INLINE Packet4f plset(const float& a) { + } + + #if !defined(vec_float) || !defined(__ARCH__) || (defined(__ARCH__) && __ARCH__ < 13) +-#warning \ ++#pragma GCC warning \ + "float->int and int->float conversion is simulated. compile for z15 for improved performance" + template <> + struct cast_impl { +-- +2.43.5 + + +From 9ef6acb9f880e805a86e7152211e7c67ffba58ca Mon Sep 17 00:00:00 2001 +From: Aleksei Nikiforov +Date: Tue, 10 Jun 2025 13:48:48 +0200 +Subject: [PATCH 6/6] Fix compound-literal warnings on s390x + +--- + Eigen/src/Core/arch/ZVector/Complex.h | 2 +- + Eigen/src/Core/arch/ZVector/MathFunctions.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/Eigen/src/Core/arch/ZVector/Complex.h b/Eigen/src/Core/arch/ZVector/Complex.h +index 40e75d9f1..692f90f3e 100644 +--- a/Eigen/src/Core/arch/ZVector/Complex.h ++++ b/Eigen/src/Core/arch/ZVector/Complex.h +@@ -20,7 +20,7 @@ namespace internal { + + #if !defined(__ARCH__) || (defined(__ARCH__) && __ARCH__ >= 12) + inline Packet4ui p4ui_CONJ_XOR() { +- return (Packet4ui) {0x00000000, 0x80000000, 0x00000000, 0x80000000}; // vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO); ++ return Packet4ui {0x00000000, 0x80000000, 0x00000000, 0x80000000}; // vec_mergeh((Packet4ui)p4i_ZERO, (Packet4ui)p4f_MZERO); + } + #endif + +diff --git a/Eigen/src/Core/arch/ZVector/MathFunctions.h b/Eigen/src/Core/arch/ZVector/MathFunctions.h +index 683f6a3f9..348d643ac 100644 +--- a/Eigen/src/Core/arch/ZVector/MathFunctions.h ++++ b/Eigen/src/Core/arch/ZVector/MathFunctions.h +@@ -184,7 +184,7 @@ EIGEN_DEFINE_FUNCTION_ALLOWING_MULTIPLE_DEFINITIONS Packet4f pexp(cons + y = padd(y, p4f_1); + + // build 2^n +- emm0 = (Packet4i){(int)fx[0], (int)fx[1], (int)fx[2], (int)fx[3]}; ++ emm0 = Packet4i{(int)fx[0], (int)fx[1], (int)fx[2], (int)fx[3]}; + emm0 = emm0 + p4i_0x7f; + emm0 = emm0 << reinterpret_cast(p4i_23); + +-- +2.43.5 + diff --git a/cmake/patches/emscripten/patch_3.1.74.tgz b/cmake/patches/emscripten/patch_3.1.74.tgz deleted file mode 100644 index cfb52de638653..0000000000000 Binary files a/cmake/patches/emscripten/patch_3.1.74.tgz and /dev/null differ diff --git a/cmake/patches/onnx/onnx.patch b/cmake/patches/onnx/onnx.patch index 162d33581a5ca..0a5680778790b 100644 --- a/cmake/patches/onnx/onnx.patch +++ b/cmake/patches/onnx/onnx.patch @@ -1,88 +1,84 @@ -diff --git a/CMakeLists.txt b/CMakeLists.txt -index 6d7ca846..69aa622f 100644 +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 044996e..ded7e39 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -499,6 +499,7 @@ if (MSVC) - endif() - else() - # On non-Windows, hide all symbols we don't need -+ set(EXTRA_FLAGS "-Wno-unused-parameter") - set(ONNX_API_DEFINE "-DONNX_API=__attribute__\(\(__visibility__\(\"default\"\)\)\)") - set_target_properties(onnx_proto PROPERTIES CXX_VISIBILITY_PRESET hidden) - set_target_properties(onnx_proto PROPERTIES VISIBILITY_INLINES_HIDDEN 1) -@@ -653,20 +654,9 @@ endif() - if(MSVC) - target_compile_options(onnx_proto - PRIVATE /MP -- /wd4244 #'argument': conversion from 'google:: -- #protobuf::uint64' to 'int', possible -- # loss of data -- /wd4267 # Conversion from 'size_t' to 'int', -- # possible loss of data - ${EXTRA_FLAGS}) - target_compile_options(onnx - PRIVATE /MP -- /wd4244 # 'argument': conversion from 'google:: -- # protobuf::uint64' to 'int', possible -- # loss of data -- /wd4267 # Conversion from 'size_t' to 'int', -- # possible loss of data -- /wd4996 # The second parameter is ignored. - ${EXTRA_FLAGS}) - if(ONNX_USE_PROTOBUF_SHARED_LIBS) - target_compile_options(onnx_proto -diff --git a/onnx/common/file_utils.h b/onnx/common/file_utils.h -index b847798e..a6c31904 100644 ---- a/onnx/common/file_utils.h -+++ b/onnx/common/file_utils.h -@@ -6,7 +6,6 @@ - - #pragma once - --#include - #include - #include - -@@ -17,8 +16,7 @@ namespace ONNX_NAMESPACE { - - template - void LoadProtoFromPath(const std::string proto_path, T& proto) { -- std::filesystem::path proto_u8_path = std::filesystem::u8path(proto_path); -- std::fstream proto_stream(proto_u8_path, std::ios::in | std::ios::binary); -+ std::fstream proto_stream(proto_path, std::ios::in | std::ios::binary); - if (!proto_stream.good()) { - fail_check("Unable to open proto file: ", proto_path, ". Please check if it is a valid proto. "); - } -diff --git a/onnx/onnx_pb.h b/onnx/onnx_pb.h -index 0aab3e26..398ac2d6 100644 ---- a/onnx/onnx_pb.h -+++ b/onnx/onnx_pb.h -@@ -47,10 +47,28 @@ - #define ONNX_API ONNX_IMPORT - #endif - -+#if defined(__GNUC__) -+#pragma GCC diagnostic push -+ -+// In file included from onnx/onnx-ml.pb.h:30: -+// In file included from google/protobuf/extension_set.h:53: -+// google/protobuf/parse_context.h:328:47: error: implicit conversion loses integer precision: 'long' to 'int' [-Werror,-Wshorten-64-to-32] -+#if defined(__has_warning) -+#if __has_warning("-Wshorten-64-to-32") -+#pragma GCC diagnostic ignored "-Wshorten-64-to-32" -+#endif -+#endif // defined(__has_warning) -+ -+#endif // defined(__GNUC__) -+ - #ifdef ONNX_ML - #include "onnx/onnx-ml.pb.h" - #else - #include "onnx/onnx.pb.h" - #endif - -+#if defined(__GNUC__) -+#pragma GCC diagnostic pop -+#endif -+ - #endif // ! ONNX_ONNX_PB_H +@@ -53,6 +53,7 @@ option(ONNX_USE_LITE_PROTO "Use lite protobuf instead of full." OFF) + 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_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}) ++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" ++ ) ++ # 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) ++ # Minimal build doesn't need Python or tests ++ 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}) ++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() +diff --git a/onnx/defs/nn/old.cc b/onnx/defs/nn/old.cc +index a6a8a83..153da87 100644 +--- a/onnx/defs/nn/old.cc ++++ b/onnx/defs/nn/old.cc +@@ -4026,7 +4026,6 @@ ONNX_OPERATOR_SET_SCHEMA( + GroupNormalization, + 18, + OpSchema() +- .Deprecate() + .SetDoc(GroupNormalization_ver18_doc) + .Attr("epsilon", "The epsilon value to use to avoid division by zero.", AttributeProto::FLOAT, 1e-5f) + .Attr( diff --git a/cmake/patches/protobuf/protobuf_android_log.patch b/cmake/patches/protobuf/protobuf_android_log.patch new file mode 100644 index 0000000000000..56bca9d325a75 --- /dev/null +++ b/cmake/patches/protobuf/protobuf_android_log.patch @@ -0,0 +1,26 @@ +diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake +index 83e970312..96908991f 100644 +--- a/cmake/libprotobuf-lite.cmake ++++ b/cmake/libprotobuf-lite.cmake +@@ -102,7 +102,7 @@ if(protobuf_LINK_LIBATOMIC) + target_link_libraries(libprotobuf-lite PRIVATE atomic) + endif() + if(${CMAKE_SYSTEM_NAME} STREQUAL "Android") +- target_link_libraries(libprotobuf-lite PRIVATE log) ++ target_link_libraries(libprotobuf-lite PRIVATE -llog) + endif() + target_include_directories(libprotobuf-lite PUBLIC ${protobuf_SOURCE_DIR}/src) + if(protobuf_BUILD_SHARED_LIBS) +diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake +index 07e4bcf57..0cf27caff 100644 +--- a/cmake/libprotobuf.cmake ++++ b/cmake/libprotobuf.cmake +@@ -118,7 +118,7 @@ if(protobuf_LINK_LIBATOMIC) + target_link_libraries(libprotobuf PRIVATE atomic) + endif() + if(${CMAKE_SYSTEM_NAME} STREQUAL "Android") +- target_link_libraries(libprotobuf PRIVATE log) ++ target_link_libraries(libprotobuf PRIVATE -llog) + endif() + target_include_directories(libprotobuf PUBLIC ${protobuf_SOURCE_DIR}/src) + if(protobuf_BUILD_SHARED_LIBS) diff --git a/cmake/patches/protobuf/protobuf_cmake.patch b/cmake/patches/protobuf/protobuf_cmake.patch index e315420e4defe..0026f16a37901 100644 --- a/cmake/patches/protobuf/protobuf_cmake.patch +++ b/cmake/patches/protobuf/protobuf_cmake.patch @@ -35,13 +35,13 @@ index 008c19225..cbab108c2 100644 +++ b/src/google/protobuf/map.h @@ -52,7 +52,8 @@ #endif // defined(__cpp_lib_string_view) - + #if !defined(GOOGLE_PROTOBUF_NO_RDTSC) && defined(__APPLE__) -#include +// apply update from https://github.com/protocolbuffers/protobuf/pull/15662/ +#include #endif - + #include @@ -1154,7 +1155,8 @@ class Map { #if defined(__APPLE__) diff --git a/cmake/patches/protobuf/protobuf_s390x.patch b/cmake/patches/protobuf/protobuf_s390x.patch new file mode 100644 index 0000000000000..039eb8931339a --- /dev/null +++ b/cmake/patches/protobuf/protobuf_s390x.patch @@ -0,0 +1,16 @@ +s390x compatibility changes based on + +https://github.com/protocolbuffers/protobuf/commit/a2859cc2ce25711613002104022186c0c37d9f1f + +diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc +index edd6d5122598e..a0a296a85da3d 100644 +--- a/src/google/protobuf/port_def.inc ++++ b/src/google/protobuf/port_def.inc +@@ -255,6 +255,7 @@ + #error PROTOBUF_TAILCALL was previously defined + #endif + #if __has_cpp_attribute(clang::musttail) && !defined(__arm__) && \ ++ !defined(__s390x__) && \ + !defined(_ARCH_PPC) && !defined(__wasm__) && \ + !(defined(_MSC_VER) && defined(_M_IX86)) && \ + !(defined(__NDK_MAJOR__) && __NDK_MAJOR <= 24) diff --git a/cmake/patches/xnnpack/AddEmscriptenAndIosSupport.patch b/cmake/patches/xnnpack/AddEmscriptenAndIosSupport.patch index c9cb4bcad9e20..ea0bb61274f84 100644 --- a/cmake/patches/xnnpack/AddEmscriptenAndIosSupport.patch +++ b/cmake/patches/xnnpack/AddEmscriptenAndIosSupport.patch @@ -1,8 +1,8 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index f0b3410ae..1e3cb8178 100644 +index 94bcad92e3..be7dfe95fd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -337,7 +337,7 @@ ENDIF() +@@ -360,7 +360,7 @@ ENDIF() # ---[ Build flags IF(NOT CMAKE_SYSTEM_NAME) MESSAGE(FATAL_ERROR "CMAKE_SYSTEM_NAME not defined") @@ -11,21 +11,30 @@ index f0b3410ae..1e3cb8178 100644 MESSAGE(FATAL_ERROR "Unrecognized CMAKE_SYSTEM_NAME value \"${CMAKE_SYSTEM_NAME}\"") ENDIF() IF(CMAKE_SYSTEM_NAME MATCHES "Windows") -@@ -848,7 +848,12 @@ IF(XNNPACK_BUILD_LIBRARY) - TARGET_LINK_LIBRARIES(operator-utils PRIVATE xnnpack-base logging) - TARGET_LINK_LIBRARIES(reference-ukernels PRIVATE xnnpack-base) - TARGET_LINK_LIBRARIES(subgraph PRIVATE xnnpack-base allocator logging memory mutex operators operator-run datatype) -- TARGET_LINK_LIBRARIES(XNNPACK PRIVATE xnnpack-base allocator cache hardware-config indirection memory microkernel-utils microparams-init mutex normalization operators operator-run operator-utils packing microkernels-prod subgraph datatype reference-ukernels) +@@ -903,10 +903,18 @@ IF(XNNPACK_BUILD_LIBRARY) + TARGET_LINK_LIBRARIES(xnnpack-operator-utils PRIVATE xnnpack-base xnnpack-logging) + TARGET_LINK_LIBRARIES(xnnpack-reference-ukernels PRIVATE xnnpack-base xnnpack-datatype) + TARGET_LINK_LIBRARIES(xnnpack-subgraph PRIVATE xnnpack-base xnnpack-allocator xnnpack-logging xnnpack-memory xnnpack-mutex xnnpack-operators xnnpack-operator-run xnnpack-datatype) +- TARGET_LINK_LIBRARIES(XNNPACK PRIVATE xnnpack-base xnnpack-allocator xnnpack-cache +- xnnpack-hardware-config xnnpack-indirection xnnpack-memory xnnpack-microkernel-utils xnnpack-microparams-init +- xnnpack-mutex xnnpack-normalization xnnpack-operators xnnpack-operator-run xnnpack-operator-utils xnnpack-pack-lh xnnpack-packing +- xnnpack-microkernels-prod xnnpack-subgraph xnnpack-datatype xnnpack-reference-ukernels) + IF(CMAKE_SYSTEM_NAME STREQUAL "Emscripten") + # omit microkernels-prod as the list is manually created by ORT in cmake/external/xnnpack.cmake -+ TARGET_LINK_LIBRARIES(XNNPACK PRIVATE xnnpack-base allocator cache hardware-config indirection memory microkernel-utils microparams-init mutex normalization operators operator-run operator-utils packing subgraph datatype reference-ukernels) ++ TARGET_LINK_LIBRARIES(XNNPACK PRIVATE xnnpack-base xnnpack-allocator xnnpack-cache ++ xnnpack-hardware-config xnnpack-indirection xnnpack-memory xnnpack-microkernel-utils xnnpack-microparams-init ++ xnnpack-mutex xnnpack-normalization xnnpack-operators xnnpack-operator-run xnnpack-operator-utils xnnpack-pack-lh xnnpack-packing ++ xnnpack-subgraph xnnpack-datatype xnnpack-reference-ukernels) + ELSE() -+ TARGET_LINK_LIBRARIES(XNNPACK PRIVATE xnnpack-base allocator cache hardware-config indirection memory microkernel-utils microparams-init mutex normalization operators operator-run operator-utils packing microkernels-prod subgraph datatype reference-ukernels) ++ TARGET_LINK_LIBRARIES(XNNPACK PRIVATE xnnpack-base xnnpack-allocator xnnpack-cache ++ xnnpack-hardware-config xnnpack-indirection xnnpack-memory xnnpack-microkernel-utils xnnpack-microparams-init ++ xnnpack-mutex xnnpack-normalization xnnpack-operators xnnpack-operator-run xnnpack-operator-utils xnnpack-pack-lh xnnpack-packing ++ xnnpack-microkernels-prod xnnpack-subgraph xnnpack-datatype xnnpack-reference-ukernels) + ENDIF() - TARGET_LINK_LIBRARIES(XNNPACK PUBLIC pthreadpool logging) + TARGET_LINK_LIBRARIES(XNNPACK PUBLIC pthreadpool xnnpack-logging) SET_TARGET_PROPERTIES(XNNPACK PROPERTIES C_EXTENSIONS YES) ENDIF() -@@ -857,7 +862,8 @@ IF(NOT MSVC) +@@ -915,7 +923,8 @@ IF(NOT MSVC) ENDIF() IF(XNNPACK_TARGET_PROCESSOR STREQUAL "arm") SET_PROPERTY(SOURCE ${ALL_MICROKERNEL_SRCS} APPEND_STRING PROPERTY COMPILE_FLAGS " -marm ") diff --git a/cmake/providers_pch.h b/cmake/providers_pch.h new file mode 100644 index 0000000000000..6b21f9ad838c9 --- /dev/null +++ b/cmake/providers_pch.h @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +// Core framework headers (highest compilation time impact) +#include "core/framework/op_kernel.h" +#include "core/framework/op_kernel_info.h" +#include "core/framework/execution_provider.h" +#include "core/framework/op_node_proto_helper.h" +#include "core/framework/data_types.h" +#include "core/framework/tensor.h" + +// Graph-related headers +#include "core/graph/graph_viewer.h" +#include "core/graph/graph.h" +#include "core/graph/onnx_protobuf.h" + +// ONNX schema definitions +#include "onnx/defs/schema.h" + +// Windows-specific headers (if applicable) +#ifdef _WIN32 +#include +#endif diff --git a/cmake/tensorboard/compat/proto/CMakeLists.txt b/cmake/tensorboard/compat/proto/CMakeLists.txt index ad31e4062a8a4..addc3779e9521 100644 --- a/cmake/tensorboard/compat/proto/CMakeLists.txt +++ b/cmake/tensorboard/compat/proto/CMakeLists.txt @@ -23,3 +23,10 @@ add_dependencies(tensorboard ${onnxruntime_EXTERNAL_DEPENDENCIES}) if(WIN32) target_compile_options(tensorboard PRIVATE "/wd4100" "/wd4125" "/wd4127" "/wd4267" "/wd4456" "/wd4800" "/wd6011" "/wd6387" "/wd28182") endif() + +if (NOT onnxruntime_BUILD_SHARED_LIB) + install(TARGETS tensorboard EXPORT ${PROJECT_NAME}Targets + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) +endif() diff --git a/cmake/test_pch.h b/cmake/test_pch.h new file mode 100644 index 0000000000000..b2a940d2cb781 --- /dev/null +++ b/cmake/test_pch.h @@ -0,0 +1,25 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +// Test framework headers (highest compilation time impact) +#include "gtest/gtest.h" +#include "gtest/gtest-assertion-result.h" +#include "gtest/gtest-message.h" +#include "gtest/internal/gtest-port.h" + +// Core test utilities (most frequently used in tests) +#include "test/providers/provider_test_utils.h" + +// ONNX and Protocol Buffer headers +#include "core/graph/onnx_protobuf.h" +#include "onnx/defs/schema.h" + +// Data types and framework headers +#include "core/framework/data_types.h" + +// Windows-specific headers (if applicable) +#ifdef _WIN32 +#include +#endif diff --git a/cmake/utils/detect_cuda_arch.cu b/cmake/utils/detect_cuda_arch.cu new file mode 100644 index 0000000000000..52a51697326ff --- /dev/null +++ b/cmake/utils/detect_cuda_arch.cu @@ -0,0 +1,33 @@ +#include +#include +#include +#include +#include + +int main(int argc, char* argv[]) { + int n_devices = 0; + int rc = cudaGetDeviceCount(&n_devices); + if (rc != cudaSuccess) { + cudaError_t error = cudaGetLastError(); + std::cout << "CUDA error: " << cudaGetErrorString(error) << std::endl; + return rc; + } + + std::vector> arch(n_devices); + for (int cd = 0; cd < n_devices; ++cd) { + cudaDeviceProp dev; + int rc = cudaGetDeviceProperties(&dev, cd); + if (rc != cudaSuccess) { + cudaError_t error = cudaGetLastError(); + std::cout << "CUDA error: " << cudaGetErrorString(error) << std::endl; + return rc; + } else { + arch[cd] = {dev.major, dev.minor}; + } + } + + std::pair best_cc = *std::max_element(begin(arch), end(arch)); + std::cout << best_cc.first << best_cc.second; + + return 0; +} diff --git a/cmake/vcpkg-configuration.json b/cmake/vcpkg-configuration.json index ffee88f3fc717..ad4be7d57c220 100644 --- a/cmake/vcpkg-configuration.json +++ b/cmake/vcpkg-configuration.json @@ -2,7 +2,10 @@ "default-registry": { "kind": "git", "repository": "https://github.com/Microsoft/vcpkg", - "baseline": "d504de05dcd7b55df34976be1c824324ec6bca2b" + "baseline": "120deac3062162151622ca4860575a33844ba10b" }, + "overlay-ports": [ + "./vcpkg-ports" + ], "registries": [] } diff --git a/cmake/vcpkg-ports/.gitattributes b/cmake/vcpkg-ports/.gitattributes new file mode 100644 index 0000000000000..9812ceb1ffd9b --- /dev/null +++ b/cmake/vcpkg-ports/.gitattributes @@ -0,0 +1 @@ +*.patch text eol=lf diff --git a/cmake/vcpkg-ports/abseil/absl_cuda_warnings.patch b/cmake/vcpkg-ports/abseil/absl_cuda_warnings.patch new file mode 100644 index 0000000000000..144b9f904bf0f --- /dev/null +++ b/cmake/vcpkg-ports/abseil/absl_cuda_warnings.patch @@ -0,0 +1,40 @@ +diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h +index 1234567..abcdefg 100644 +--- a/absl/hash/internal/hash.h ++++ b/absl/hash/internal/hash.h +@@ -477,7 +477,7 @@ H AbslHashValue(H hash_state, T (&)[N]) { + template + H AbslHashValue(H hash_state, T (&)[N]) { + static_assert( +- sizeof(T) == -1, ++ sizeof(T) == size_t(-1), + "Hashing C arrays is not allowed. For string literals, wrap the literal " + "in absl::string_view(). To hash the array contents, use " + "absl::MakeSpan() or make the array an std::array. To hash the array " +diff --git a/absl/hash/hash.h b/absl/hash/hash.h +index 1234567..abcdefg 100644 +--- a/absl/hash/hash.h ++++ b/absl/hash/hash.h +@@ -333,7 +333,8 @@ class HashState : public hash_internal::HashStateBase { + absl::enable_if_t< + std::is_base_of, T>::value, int> = 0> + static HashState Create(T* state) { +- HashState s; ++ HashState s = {}; ++ (void)s; + s.Init(state); + return s; + } +diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h +index 1234567..abcdefg 100644 +--- a/absl/container/internal/raw_hash_set.h ++++ b/absl/container/internal/raw_hash_set.h +@@ -464,7 +464,7 @@ inline uint16_t NextSeed() { + inline uint16_t NextSeed() { + static_assert(PerTableSeed::kBitCount == 16); + thread_local uint16_t seed = +- static_cast(reinterpret_cast(&seed)); ++ static_cast(reinterpret_cast(&seed) & 0xFFFFu); + seed += uint16_t{0xad53}; + return seed; + } diff --git a/cmake/vcpkg-ports/abseil/absl_windows.patch b/cmake/vcpkg-ports/abseil/absl_windows.patch new file mode 100644 index 0000000000000..036ead7b88e46 --- /dev/null +++ b/cmake/vcpkg-ports/abseil/absl_windows.patch @@ -0,0 +1,44 @@ +diff --git a/absl/container/internal/raw_hash_set.h b/absl/container/internal/raw_hash_set.h +index 3effc441..c339e269 100644 +--- a/absl/container/internal/raw_hash_set.h ++++ b/absl/container/internal/raw_hash_set.h +@@ -1121,11 +1121,12 @@ class CommonFields : public CommonFieldsGenerationInfo { + #ifdef NDEBUG + f(); + return; +-#endif ++#else + const size_t cap = capacity(); + set_capacity(InvalidCapacity::kReentrance); + f(); + set_capacity(cap); ++#endif + } + + private: +@@ -3344,11 +3345,14 @@ class raw_hash_set { + + // Asserts that hash and equal functors provided by the user are consistent, + // meaning that `eq(k1, k2)` implies `hash(k1)==hash(k2)`. +- template +- void AssertHashEqConsistent(const K& key) { + #ifdef NDEBUG ++ template ++ void AssertHashEqConsistent(const K&) { + return; +-#endif ++ } ++#else ++ template ++ void AssertHashEqConsistent(const K& key) { + // If the hash/eq functors are known to be consistent, then skip validation. + if (std::is_same::value && + std::is_same::value) { +@@ -3386,6 +3390,7 @@ class raw_hash_set { + if (capacity() > 16) return; + IterateOverFullSlots(common(), sizeof(slot_type), assert_consistent); + } ++#endif + + // Attempts to find `key` in the table; if it isn't found, returns an iterator + // where the value can be inserted into, with the control byte already set to diff --git a/cmake/vcpkg-ports/abseil/portfile.cmake b/cmake/vcpkg-ports/abseil/portfile.cmake new file mode 100644 index 0000000000000..1e9c48ea834b2 --- /dev/null +++ b/cmake/vcpkg-ports/abseil/portfile.cmake @@ -0,0 +1,47 @@ +if(NOT VCPKG_TARGET_IS_WINDOWS) + vcpkg_check_linkage(ONLY_STATIC_LIBRARY) +endif() + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO abseil/abseil-cpp + REF "${VERSION}" + SHA512 4ee1a217203933382e728d354a149253a517150eee7580a0abecc69584b2eb200d91933ef424487e3a3fe0e8ab5e77b0288485cac982171b3585314a4417e7d4 + HEAD_REF master + PATCHES absl_windows.patch + absl_cuda_warnings.patch +) + + +set(ABSL_STATIC_RUNTIME_OPTION "") +if(VCPKG_TARGET_IS_WINDOWS AND VCPKG_CRT_LINKAGE STREQUAL "static") + set(ABSL_STATIC_RUNTIME_OPTION "-DABSL_MSVC_STATIC_RUNTIME=ON") +endif() + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + DISABLE_PARALLEL_CONFIGURE + OPTIONS + -DABSL_PROPAGATE_CXX_STD=ON + ${ABSL_USE_CXX17_OPTION} + ${ABSL_STATIC_RUNTIME_OPTION} +) + +vcpkg_cmake_install() +vcpkg_cmake_config_fixup(PACKAGE_NAME absl CONFIG_PATH lib/cmake/absl) +vcpkg_fixup_pkgconfig() + +vcpkg_copy_pdbs() +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/share" + "${CURRENT_PACKAGES_DIR}/debug/include" + "${CURRENT_PACKAGES_DIR}/include/absl/copts" + "${CURRENT_PACKAGES_DIR}/include/absl/strings/testdata" + "${CURRENT_PACKAGES_DIR}/include/absl/time/internal/cctz/testdata" +) + +if(VCPKG_TARGET_IS_WINDOWS AND VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic") + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/include/absl/base/config.h" "defined(ABSL_CONSUME_DLL)" "1") + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/include/absl/base/internal/thread_identity.h" "defined(ABSL_CONSUME_DLL)" "1") +endif() + +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE") diff --git a/cmake/vcpkg-ports/abseil/vcpkg.json b/cmake/vcpkg-ports/abseil/vcpkg.json new file mode 100644 index 0000000000000..f9a5a2b140723 --- /dev/null +++ b/cmake/vcpkg-ports/abseil/vcpkg.json @@ -0,0 +1,21 @@ +{ + "name": "abseil", + "version": "20250814.0", + "description": [ + "Abseil is an open-source collection of C++ library code designed to augment the C++ standard library. The Abseil library code is collected from Google's own C++ code base, has been extensively tested and used in production, and is the same code we depend on in our daily coding lives.", + "In some cases, Abseil provides pieces missing from the C++ standard; in others, Abseil provides alternatives to the standard for special needs we've found through usage in the Google code base. We denote those cases clearly within the library code we provide you.", + "Abseil is not meant to be a competitor to the standard library; we've just found that many of these utilities serve a purpose within our code base, and we now want to provide those resources to the C++ community as a whole." + ], + "homepage": "https://github.com/abseil/abseil-cpp", + "license": "Apache-2.0", + "dependencies": [ + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] +} \ No newline at end of file diff --git a/cmake/vcpkg-ports/cpuinfo/patch_cpuinfo_h_for_arm64ec.patch b/cmake/vcpkg-ports/cpuinfo/patch_cpuinfo_h_for_arm64ec.patch new file mode 100644 index 0000000000000..23ceeb8f758cc --- /dev/null +++ b/cmake/vcpkg-ports/cpuinfo/patch_cpuinfo_h_for_arm64ec.patch @@ -0,0 +1,22 @@ +diff --git a/include/cpuinfo.h b/include/cpuinfo.h +index f1d35d4..9e454d2 100644 +--- a/include/cpuinfo.h ++++ b/include/cpuinfo.h +@@ -18,7 +18,7 @@ + #define CPUINFO_ARCH_X86 1 + #endif + +-#if defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) ++#if defined(__x86_64__) || defined(__x86_64) || (defined(_M_X64) && !defined(_M_ARM64EC)) || (defined(_M_AMD64) && !defined(_M_ARM64EC)) + #define CPUINFO_ARCH_X86_64 1 + #endif + +@@ -26,7 +26,7 @@ + #define CPUINFO_ARCH_ARM 1 + #endif + +-#if defined(__aarch64__) || defined(_M_ARM64) ++#if defined(__aarch64__) || defined(_M_ARM64) || defined(_M_ARM64EC) + #define CPUINFO_ARCH_ARM64 1 + #endif + diff --git a/cmake/vcpkg-ports/cpuinfo/patch_vcpkg_arm64ec_support.patch b/cmake/vcpkg-ports/cpuinfo/patch_vcpkg_arm64ec_support.patch new file mode 100644 index 0000000000000..af0f039b6c2a3 --- /dev/null +++ b/cmake/vcpkg-ports/cpuinfo/patch_vcpkg_arm64ec_support.patch @@ -0,0 +1,91 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index aedc983..dab589e 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -72,6 +72,17 @@ IF(CMAKE_SYSTEM_NAME MATCHES "FreeBSD" AND CPUINFO_TARGET_PROCESSOR STREQUAL "am + ENDIF() + IF(IS_APPLE_OS AND CMAKE_OSX_ARCHITECTURES MATCHES "^(x86_64|arm64.*)$") + SET(CPUINFO_TARGET_PROCESSOR "${CMAKE_OSX_ARCHITECTURES}") ++ELSEIF(MSVC AND CMAKE_VERSION VERSION_GREATER_EQUAL "3.10") ++ # Use CMAKE_C_COMPILER_ARCHITECTURE_ID. MSVC values are documented as available since CMake 3.10. ++ IF(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "X86") ++ SET(CPUINFO_TARGET_PROCESSOR "x86") ++ ELSEIF(CMAKE_C_COMPILER_ARCHITECTURE_ID STREQUAL "x64") ++ SET(CPUINFO_TARGET_PROCESSOR "x86_64") ++ ELSEIF(CMAKE_C_COMPILER_ARCHITECTURE_ID MATCHES "^(ARM64|ARM64EC)$") ++ SET(CPUINFO_TARGET_PROCESSOR "arm64") ++ ELSE() ++ MESSAGE(FATAL_ERROR "Unsupported MSVC compiler architecture ID \"${CMAKE_C_COMPILER_ARCHITECTURE_ID}\"") ++ ENDIF() + ELSEIF(CMAKE_GENERATOR MATCHES "^Visual Studio " AND CMAKE_VS_PLATFORM_NAME) + IF(CMAKE_VS_PLATFORM_NAME STREQUAL "Win32") + SET(CPUINFO_TARGET_PROCESSOR "x86") +@@ -88,7 +99,7 @@ ENDIF() + + # ---[ Build flags + SET(CPUINFO_SUPPORTED_PLATFORM TRUE) +-IF(NOT CMAKE_SYSTEM_PROCESSOR) ++IF(NOT CPUINFO_TARGET_PROCESSOR) + IF(NOT IOS) + MESSAGE(WARNING + "Target processor architecture is not specified. " +@@ -201,12 +212,12 @@ IF(CPUINFO_SUPPORTED_PLATFORM) + src/arm/linux/chipset.c + src/arm/linux/midr.c + src/arm/linux/hwcap.c) +- IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^armv[5-8]") ++ IF(CPUINFO_TARGET_PROCESSOR MATCHES "^armv[5-8]") + LIST(APPEND CPUINFO_SRCS src/arm/linux/aarch32-isa.c) + IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND ANDROID_ABI STREQUAL "armeabi") + SET_SOURCE_FILES_PROPERTIES(src/arm/linux/aarch32-isa.c PROPERTIES COMPILE_FLAGS -marm) + ENDIF() +- ELSEIF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(aarch64|arm64)$") ++ ELSEIF(CPUINFO_TARGET_PROCESSOR MATCHES "^(aarch64|arm64)$") + LIST(APPEND CPUINFO_SRCS src/arm/linux/aarch64-isa.c) + ENDIF() + ELSEIF(IS_APPLE_OS AND CPUINFO_TARGET_PROCESSOR MATCHES "arm64.*") +@@ -395,7 +406,7 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_MOCK_TESTS) + TARGET_COMPILE_DEFINITIONS(cpuinfo_mock PRIVATE _GNU_SOURCE=1) + ENDIF() + +- IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv5te|armv7-a)$") ++ IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(armv5te|armv7-a)$") + ADD_EXECUTABLE(atm7029b-tablet-test test/mock/atm7029b-tablet.cc) + TARGET_INCLUDE_DIRECTORIES(atm7029b-tablet-test BEFORE PRIVATE test/mock) + TARGET_LINK_LIBRARIES(atm7029b-tablet-test PRIVATE cpuinfo_mock gtest) +@@ -577,7 +588,7 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_MOCK_TESTS) + ADD_TEST(NAME xperia-sl-test COMMAND xperia-sl-test) + ENDIF() + +- IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv5te|armv7-a|aarch64)$") ++ IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(armv5te|armv7-a|aarch64)$") + ADD_EXECUTABLE(alcatel-revvl-test test/mock/alcatel-revvl.cc) + TARGET_INCLUDE_DIRECTORIES(alcatel-revvl-test BEFORE PRIVATE test/mock) + TARGET_LINK_LIBRARIES(alcatel-revvl-test PRIVATE cpuinfo_mock gtest) +@@ -774,7 +785,7 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_MOCK_TESTS) + ADD_TEST(NAME xperia-c4-dual-test COMMAND xperia-c4-dual-test) + ENDIF() + +- IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(i686|x86_64)$") ++ IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(i686|x86_64)$") + ADD_EXECUTABLE(alldocube-iwork8-test test/mock/alldocube-iwork8.cc) + TARGET_INCLUDE_DIRECTORIES(alldocube-iwork8-test BEFORE PRIVATE test/mock) + TARGET_LINK_LIBRARIES(alldocube-iwork8-test PRIVATE cpuinfo_mock gtest) +@@ -831,7 +842,7 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_UNIT_TESTS) + ADD_TEST(NAME brand-string-test COMMAND brand-string-test) + ENDIF() + +- IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv[5-8].*|aarch64)$") ++ IF(CMAKE_SYSTEM_NAME STREQUAL "Android" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(armv[5-8].*|aarch64)$") + ADD_LIBRARY(android_properties_interface STATIC test/name/android-properties-interface.c) + CPUINFO_TARGET_ENABLE_C99(android_properties_interface) + CPUINFO_TARGET_RUNTIME_LIBRARY(android_properties_interface) +@@ -879,7 +890,7 @@ IF(CPUINFO_SUPPORTED_PLATFORM AND CPUINFO_BUILD_TOOLS) + TARGET_LINK_LIBRARIES(cache-info PRIVATE cpuinfo) + INSTALL(TARGETS cache-info RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) + +- IF(CMAKE_SYSTEM_NAME MATCHES "^(Android|Linux)$" AND CMAKE_SYSTEM_PROCESSOR MATCHES "^(armv[5-8].*|aarch64)$") ++ IF(CMAKE_SYSTEM_NAME MATCHES "^(Android|Linux)$" AND CPUINFO_TARGET_PROCESSOR MATCHES "^(armv[5-8].*|aarch64)$") + ADD_EXECUTABLE(auxv-dump tools/auxv-dump.c) + CPUINFO_TARGET_ENABLE_C99(auxv-dump) + CPUINFO_TARGET_RUNTIME_LIBRARY(auxv-dump) diff --git a/cmake/vcpkg-ports/cpuinfo/portfile.cmake b/cmake/vcpkg-ports/cpuinfo/portfile.cmake index e61308bf643b4..67bd18e61cc28 100644 --- a/cmake/vcpkg-ports/cpuinfo/portfile.cmake +++ b/cmake/vcpkg-ports/cpuinfo/portfile.cmake @@ -6,9 +6,13 @@ endif() vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO pytorch/cpuinfo - REF 8a1772a0c5c447df2d18edf33ec4603a8c9c04a6 - SHA512 b94ccbfa886221d6bb16513d074675af0a72928a9dd9485dcacdc1124a8a60aacbbe91913a1579e766dfb024f0be1d52eeead40342004ff0238a8b94a095ed08 + REF 403d652dca4c1046e8145950b1c0997a9f748b57 + SHA512 f7cd6dc44bd1120af610cae1337ed4c0f557ba78d2de9c73fed350fa3dfe9512643a1619ae55f5a540c6316a87d641856cca27297bb8766e48f39b7b7a59da1f HEAD_REF master + PATCHES + patch_cpuinfo_h_for_arm64ec.patch + patch_vcpkg_arm64ec_support.patch # https://github.com/pytorch/cpuinfo/pull/324 + win_arm_fp16_detection_fallback.patch # https://github.com/pytorch/cpuinfo/pull/348 ) vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS diff --git a/cmake/vcpkg-ports/cpuinfo/vcpkg.json b/cmake/vcpkg-ports/cpuinfo/vcpkg.json index ce93591dba5ac..76486eceecf12 100644 --- a/cmake/vcpkg-ports/cpuinfo/vcpkg.json +++ b/cmake/vcpkg-ports/cpuinfo/vcpkg.json @@ -1,7 +1,7 @@ { "name": "cpuinfo", - "version-date": "2024-12-09", - "port-version": 3, + "version-date": "2025-11-18", + "port-version": 5, "description": "CPU INFOrmation library (x86/x86-64/ARM/ARM64, Linux/Windows/Android/macOS/iOS)", "homepage": "https://github.com/pytorch/cpuinfo", "license": "BSD-2-Clause", diff --git a/cmake/vcpkg-ports/cpuinfo/win_arm_fp16_detection_fallback.patch b/cmake/vcpkg-ports/cpuinfo/win_arm_fp16_detection_fallback.patch new file mode 100644 index 0000000000000..44ac0f13f5466 --- /dev/null +++ b/cmake/vcpkg-ports/cpuinfo/win_arm_fp16_detection_fallback.patch @@ -0,0 +1,19 @@ +diff --git a/src/arm/windows/init.c b/src/arm/windows/init.c +index 5c0a5f3..a07fbe4 100644 +--- a/src/arm/windows/init.c ++++ b/src/arm/windows/init.c +@@ -249,6 +249,14 @@ static void set_cpuinfo_isa_fields(void) { + // guarantee that, but it holds in practice. + cpuinfo_isa.rdm = dotprod; + ++ // PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE may not be available in older ++ // Windows versions. If fp16arith was not detected with ++ // IsProcessorFeaturePresent(PF_ARM_V82_FP16_INSTRUCTIONS_AVAILABLE), fall ++ // back to using the value of dotprod. ++ if (!cpuinfo_isa.fp16arith) { ++ cpuinfo_isa.fp16arith = dotprod; ++ } ++ + /* Windows API reports all or nothing for cryptographic instructions. */ + const bool crypto = IsProcessorFeaturePresent(PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE) != 0; + cpuinfo_isa.aes = crypto; diff --git a/cmake/vcpkg-ports/dawn/dawn.patch b/cmake/vcpkg-ports/dawn/dawn.patch new file mode 100644 index 0000000000000..1fe66d2cf917d --- /dev/null +++ b/cmake/vcpkg-ports/dawn/dawn.patch @@ -0,0 +1,59 @@ +diff --git a/src/cmake/DawnCompilerPlatformFlags.cmake b/src/cmake/DawnCompilerPlatformFlags.cmake +index 50638e2456..efa42711e6 100644 +--- a/src/cmake/DawnCompilerPlatformFlags.cmake ++++ b/src/cmake/DawnCompilerPlatformFlags.cmake +@@ -63,7 +63,3 @@ endif () + if (MSVC AND NOT COMPILER_IS_CLANG_CL) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") + endif () +- +-if (TARGET_MACOS) +- set(CMAKE_OSX_DEPLOYMENT_TARGET "11.0" CACHE STRING "Minimum macOS version" FORCE) +-endif () +\ No newline at end of file +diff --git a/third_party/emdawnwebgpu/webgpu.cpp b/third_party/emdawnwebgpu/webgpu.cpp +index 5bfac41dcc..71a153daaa 100644 +--- a/third_party/emdawnwebgpu/webgpu.cpp ++++ b/third_party/emdawnwebgpu/webgpu.cpp +@@ -692,6 +692,7 @@ struct WGPUBufferImpl final : public EventSource, + WGPUBufferImpl(const EventSource* source, bool mappedAtCreation); + // Injection constructor used when we already have a backing Buffer. + WGPUBufferImpl(const EventSource* source, WGPUBufferMapState mapState); ++ ~WGPUBufferImpl(); + + void Destroy(); + const void* GetConstMappedRange(size_t offset, size_t size); +@@ -1361,6 +1362,12 @@ WGPUBufferImpl::WGPUBufferImpl(const EventSource* source, + RefCountedWithExternalCount(kImportedFromJS), + mMapState(mapState) {} + ++WGPUBufferImpl::~WGPUBufferImpl() { ++ if (!IsImported()) { ++ Destroy(); ++ } ++} ++ + void WGPUBufferImpl::Destroy() { + emwgpuBufferDestroy(this); + AbortPendingMap("Buffer was destroyed before mapping was resolved."); +diff --git a/src/tint/utils/memory/aligned_storage.h b/src/tint/utils/memory/aligned_storage.h +index c532c4fc38..19c950af4c 100644 +--- a/src/tint/utils/memory/aligned_storage.h ++++ b/src/tint/utils/memory/aligned_storage.h +@@ -31,6 +31,9 @@ + #include + + #include "src/tint/utils/memory/bitcast.h" ++#include "src/tint/utils/macros/compiler.h" ++ ++TINT_BEGIN_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); + + namespace tint { + +@@ -50,4 +53,6 @@ struct alignas(alignof(T)) AlignedStorage { + + } // namespace tint + ++TINT_END_DISABLE_WARNING(UNSAFE_BUFFER_USAGE); ++ + #endif // SRC_TINT_UTILS_MEMORY_ALIGNED_STORAGE_H_ diff --git a/cmake/vcpkg-ports/dawn/dawn_force_enable_f16_nvidia_vulkan.patch b/cmake/vcpkg-ports/dawn/dawn_force_enable_f16_nvidia_vulkan.patch new file mode 100644 index 0000000000000..2d999a456fdec --- /dev/null +++ b/cmake/vcpkg-ports/dawn/dawn_force_enable_f16_nvidia_vulkan.patch @@ -0,0 +1,19 @@ +diff --git a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp +index 158f10764c..a324c101ed 100644 +--- a/src/dawn/native/vulkan/PhysicalDeviceVk.cpp ++++ b/src/dawn/native/vulkan/PhysicalDeviceVk.cpp +@@ -269,11 +269,9 @@ void PhysicalDevice::InitializeSupportedFeaturesImpl() { + mDeviceInfo.shaderFloat16Int8Features.shaderFloat16 == VK_TRUE && + mDeviceInfo._16BitStorageFeatures.storageBuffer16BitAccess == VK_TRUE && + mDeviceInfo._16BitStorageFeatures.uniformAndStorageBuffer16BitAccess == VK_TRUE) { +- // TODO(crbug.com/tint/2164): Investigate crashes in f16 CTS tests to enable on NVIDIA. +- if (!gpu_info::IsNvidia(GetVendorId())) { +- EnableFeature(Feature::ShaderF16); +- shaderF16Enabled = true; +- } ++ // ONNX Runtime Patch: enable shaderF16 on all devices. ++ EnableFeature(Feature::ShaderF16); ++ shaderF16Enabled = true; + } + + if (mDeviceInfo.HasExt(DeviceExt::DrawIndirectCount) && diff --git a/cmake/vcpkg-ports/dawn/dawn_vcpkg_integration.patch b/cmake/vcpkg-ports/dawn/dawn_vcpkg_integration.patch new file mode 100644 index 0000000000000..6e97475c8ad53 --- /dev/null +++ b/cmake/vcpkg-ports/dawn/dawn_vcpkg_integration.patch @@ -0,0 +1,125 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b46b68204b..3e985ae3cd 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -127,6 +127,8 @@ if (DAWN_SUPPORTS_GLFW_FOR_WINDOWING) + set(BUILD_SAMPLES ON) + endif() + ++option(DAWN_ENABLE_VCPKG "Enable vcpkg integration" OFF) ++ + option(DAWN_ENABLE_ASAN "Enable address sanitizer" OFF) + option(DAWN_ENABLE_INSTALL "Enable install step for Dawn libraries" OFF) + option(DAWN_ENABLE_TSAN "Enable thread sanitizer" OFF) +@@ -439,16 +441,25 @@ set(TINT_SPIRV_TOOLS_DIR ${DAWN_SPIRV_TOOLS_DIR}) + ################################################################################ + # Run on all subdirectories + ################################################################################ +-if (DAWN_BUILD_PROTOBUF AND EXISTS "${DAWN_PROTOBUF_DIR}/cmake") +- if (("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") AND WIN32) +- set(protobuf_HAVE_BUILTIN_ATOMICS 1) ++if (DAWN_ENABLE_VCPKG) ++ find_package(absl REQUIRED) ++ find_package(SPIRV-Headers REQUIRED) ++ find_package(SPIRV-Tools REQUIRED) ++ if (DAWN_USE_BUILT_DXC) ++ find_package(directx-dxc CONFIG REQUIRED) + endif() ++else() ++ if (DAWN_BUILD_PROTOBUF AND EXISTS "${DAWN_PROTOBUF_DIR}/cmake") ++ if (("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") AND WIN32) ++ set(protobuf_HAVE_BUILTIN_ATOMICS 1) ++ endif() + +- # Needs to come before SPIR-V Tools +- include("third_party/protobuf.cmake") +-endif() ++ # Needs to come before SPIR-V Tools ++ include("third_party/protobuf.cmake") ++ endif() + +-add_subdirectory(third_party) ++ add_subdirectory(third_party) ++endif() + + # TODO(crbug.com/tint/455): Tint does not currently build with CMake when + # BUILD_SHARED_LIBS=1, so always build it as static for now. +diff --git a/src/dawn/native/CMakeLists.txt b/src/dawn/native/CMakeLists.txt +index d3128bf764..319a847311 100644 +--- a/src/dawn/native/CMakeLists.txt ++++ b/src/dawn/native/CMakeLists.txt +@@ -865,7 +865,9 @@ if (DAWN_ENABLE_D3D12) + if (DAWN_USE_BUILT_DXC) + target_compile_definitions(dawn_native PRIVATE "DAWN_USE_BUILT_DXC") + target_compile_definitions(dawn_native_objects PRIVATE "DAWN_USE_BUILT_DXC") +- add_dependencies(dawn_native copy_dxil_dll) ++ if (NOT DAWN_ENABLE_VCPKG) ++ add_dependencies(dawn_native copy_dxil_dll) ++ endif() + endif() + endif() + +@@ -942,5 +944,9 @@ endif () + # They happen because dxcompiler is declared a shared library and bundle_libraries + # doesn't work well with shared libs + if (DAWN_USE_BUILT_DXC) +- target_link_libraries(dawn_native PRIVATE dxcompiler) ++ if (DAWN_ENABLE_VCPKG) ++ target_link_libraries(dawn_native PRIVATE Microsoft::DirectXShaderCompiler) ++ else() ++ target_link_libraries(dawn_native PRIVATE dxcompiler) ++ endif() + endif() +diff --git a/src/tint/CMakeLists.txt b/src/tint/CMakeLists.txt +index 8692171222..b3da2fbbbf 100644 +--- a/src/tint/CMakeLists.txt ++++ b/src/tint/CMakeLists.txt +@@ -214,13 +214,21 @@ function(tint_default_compile_options TARGET) + endfunction() + + function(tint_spvheaders_compile_options TARGET) +- target_link_libraries(${TARGET} PRIVATE SPIRV-Headers) +- target_include_directories(${TARGET} PRIVATE "${TINT_SPIRV_HEADERS_DIR}/include") ++ if (DAWN_ENABLE_VCPKG) ++ target_link_libraries(${TARGET} PRIVATE SPIRV-Headers::SPIRV-Headers) ++ else () ++ target_link_libraries(${TARGET} PRIVATE SPIRV-Headers) ++ target_include_directories(${TARGET} PRIVATE "${TINT_SPIRV_HEADERS_DIR}/include") ++ endif() + endfunction() + + function(tint_spvtools_compile_options TARGET) +- target_link_libraries(${TARGET} PRIVATE SPIRV-Tools) +- target_include_directories(${TARGET} PRIVATE "${TINT_SPIRV_TOOLS_DIR}/include") ++ if (DAWN_ENABLE_VCPKG) ++ target_link_libraries(${TARGET} PRIVATE SPIRV-Tools-static) ++ else () ++ target_link_libraries(${TARGET} PRIVATE SPIRV-Tools) ++ target_include_directories(${TARGET} PRIVATE "${TINT_SPIRV_TOOLS_DIR}/include") ++ endif() + endfunction() + + function(tint_lib_compile_options TARGET) +@@ -562,12 +570,16 @@ function(tint_target_add_external_dependencies TARGET KIND) + target_link_libraries(${TARGET} PRIVATE + SPIRV-Tools-opt + ) +- target_include_directories(${TARGET} PRIVATE +- "${TINT_SPIRV_TOOLS_DIR}" +- "${TINT_SPIRV_TOOLS_DIR}/include" +- "${TINT_SPIRV_TOOLS_DIR}/source" +- "${spirv-tools_BINARY_DIR}" +- ) ++ if (DAWN_ENABLE_VCPKG) ++ target_link_libraries(${TARGET} PRIVATE SPIRV-Tools-static) ++ else () ++ target_include_directories(${TARGET} PRIVATE ++ "${TINT_SPIRV_TOOLS_DIR}" ++ "${TINT_SPIRV_TOOLS_DIR}/include" ++ "${TINT_SPIRV_TOOLS_DIR}/source" ++ "${spirv-tools_BINARY_DIR}" ++ ) ++ endif() + elseif(${DEPENDENCY} STREQUAL "thread") + find_package(Threads REQUIRED) + target_link_libraries(${TARGET} PRIVATE Threads::Threads) diff --git a/cmake/vcpkg-ports/dawn/portfile.cmake b/cmake/vcpkg-ports/dawn/portfile.cmake new file mode 100644 index 0000000000000..1c53f8316c372 --- /dev/null +++ b/cmake/vcpkg-ports/dawn/portfile.cmake @@ -0,0 +1,138 @@ +# NOTE: dynamic library vs. static library +# +# We are building Dawn as a shared library `webgpu_dawn`. However, we need to set the `BUILD_SHARED_LIBS` option to +# `OFF` in this portfile. See the explanation below. +# +# In CMake convention, the `BUILD_SHARED_LIBS` option is used to control whether a library is built as a shared library or a static library. +# However, in the Dawn repository, there are multiple targets. Instead of building each target as a shared library, Dawn +# uses a CMake option `DAWN_BUILD_MONOLITHIC_LIBRARY` to control whether to build a monolithic dynamic library. +# +# When `DAWN_BUILD_MONOLITHIC_LIBRARY` is set to `ON`, a single library is built that contains all the targets. The +# library is always built as a shared library, regardless of the value of `BUILD_SHARED_LIBS`. +# +# In the vcpkg migration, we found that when both `DAWN_BUILD_MONOLITHIC_LIBRARY` and `BUILD_SHARED_LIBS` are set to `ON`, the build process will fail with some unexpected errors. +# So we need to set `BUILD_SHARED_LIBS` to `OFF` in this mode. +# +# The following function call ensures BUILD_SHARED_LIBS is set to OFF. +vcpkg_check_linkage(ONLY_STATIC_LIBRARY) + +if(VCPKG_TARGET_IS_EMSCRIPTEN) + message(FATAL_ERROR "This port is currently not supported on Emscripten.") +endif() + +set(onnxruntime_vcpkg_DAWN_OPTIONS) + +list(APPEND onnxruntime_vcpkg_DAWN_OPTIONS + + # enable the vcpkg flag + -DDAWN_ENABLE_VCPKG=ON + + # fetch dependencies is disabled when using vcpkg + -DDAWN_FETCH_DEPENDENCIES=OFF + + -DDAWN_BUILD_SAMPLES=OFF + -DDAWN_ENABLE_NULL=OFF + -DDAWN_BUILD_TESTS=OFF +) + +if (NOT VCPKG_TARGET_IS_EMSCRIPTEN) + list(APPEND onnxruntime_vcpkg_DAWN_OPTIONS + + -DDAWN_BUILD_MONOLITHIC_LIBRARY=ON + -DDAWN_ENABLE_INSTALL=ON + + -DDAWN_ENABLE_DESKTOP_GL=OFF + -DDAWN_ENABLE_OPENGLES=OFF + -DDAWN_SUPPORTS_GLFW_FOR_WINDOWING=OFF + -DDAWN_USE_GLFW=OFF + -DDAWN_USE_WINDOWS_UI=OFF + -DTINT_BUILD_GLSL_WRITER=OFF + -DTINT_BUILD_GLSL_VALIDATOR=OFF + + -DDAWN_DXC_ENABLE_ASSERTS_IN_NDEBUG=OFF + -DDAWN_USE_X11=OFF + + -DTINT_BUILD_TESTS=OFF + -DTINT_BUILD_CMD_TOOLS=OFF + -DTINT_BUILD_IR_BINARY=OFF + -DTINT_BUILD_SPV_READER=OFF + -DTINT_BUILD_WGSL_WRITER=ON + + -DDAWN_ENABLE_SPIRV_VALIDATION=OFF + + # explicitly set the jinja2 and markupsafe directories to empty strings + # when they are empty, the python script will import them from the system + # + # pip install jinja2 markupsafe + # + -DDAWN_JINJA2_DIR= + -DDAWN_MARKUPSAFE_DIR= + ) +endif() + +if(VCPKG_TARGET_IS_WINDOWS) + # feature detection on Windows + vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS + FEATURES + windows-use-d3d12 onnxruntime_vcpkg_ENABLE_DAWN_BACKEND_D3D12 + windows-use-vulkan onnxruntime_vcpkg_ENABLE_DAWN_BACKEND_VULKAN + ) + + list(APPEND onnxruntime_vcpkg_DAWN_OPTIONS + -DDAWN_USE_BUILT_DXC=ON + -DTINT_BUILD_HLSL_WRITER=ON + ) + + if((NOT onnxruntime_vcpkg_ENABLE_DAWN_BACKEND_VULKAN) AND(NOT onnxruntime_vcpkg_ENABLE_DAWN_BACKEND_D3D12)) + message(FATAL_ERROR "At least one of \"windows-use-d3d12\" or \"windows-use-vulkan\" must be enabled when using Dawn on Windows.") + endif() + + if(onnxruntime_vcpkg_ENABLE_DAWN_BACKEND_VULKAN) + list(APPEND onnxruntime_vcpkg_DAWN_OPTIONS + -DDAWN_ENABLE_VULKAN=ON + -DTINT_BUILD_SPV_WRITER=ON + ) + else() + list(APPEND onnxruntime_vcpkg_DAWN_OPTIONS + -DDAWN_ENABLE_VULKAN=OFF + ) + endif() + + if(onnxruntime_vcpkg_ENABLE_DAWN_BACKEND_D3D12) + list(APPEND onnxruntime_vcpkg_DAWN_OPTIONS + -DDAWN_ENABLE_D3D12=ON + ) + else() + list(APPEND onnxruntime_vcpkg_DAWN_OPTIONS + -DDAWN_ENABLE_D3D12=OFF + ) + endif() + + # We are currently always using the D3D12 backend. + list(APPEND onnxruntime_vcpkg_DAWN_OPTIONS + -DDAWN_ENABLE_D3D11=OFF + ) +endif() + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO google/dawn + REF "${VERSION}" + SHA512 9771e0be45ad2b85e4d85e12cbf03b9c9b4cc297e8f819e6277d8f02821adb671bf420fd13e241be4f6d7795a3acf0d0a38649c6e0e38a523a6ec0f042591efe + + PATCHES + dawn.patch + dawn_force_enable_f16_nvidia_vulkan.patch + dawn_vcpkg_integration.patch +) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + WINDOWS_USE_MSBUILD + OPTIONS + ${onnxruntime_vcpkg_DAWN_OPTIONS} + + # MAYBE_UNUSED_VARIABLES +) + +vcpkg_cmake_install() diff --git a/cmake/vcpkg-ports/dawn/vcpkg.json b/cmake/vcpkg-ports/dawn/vcpkg.json new file mode 100644 index 0000000000000..0ea8627f7e17c --- /dev/null +++ b/cmake/vcpkg-ports/dawn/vcpkg.json @@ -0,0 +1,62 @@ +{ + "name": "dawn", + "version-string": "4cb1f9be152a4fa6bb695c08cd707ab078a1e2fb", + "port-version": 1, + "description": "Dawn, a native WebGPU implementation.", + "homepage": "https://dawn.googlesource.com/dawn", + "license": "BSD-3-Clause", + "dependencies": [ + { "name": "vcpkg-cmake", "host": true }, + { "name": "vcpkg-cmake-config", "host": true }, + { "name": "abseil", "version>=": "20250127.1" }, + { "name": "protobuf", "version>=": "3.21.12" }, + { + "name": "spirv-headers", + "version>=": "1.4.304.1", + "platform": "!emscripten" + }, + { + "name": "spirv-tools", + "version>=": "1.4.304.1", + "platform": "!emscripten" + }, + { + "name": "vulkan-headers", + "version>=": "1.4.304.1#1", + "platform": "(windows | linux) & (arm64 | x64)" + }, + { + "name": "vulkan-loader", + "version>=": "1.4.304.1", + "platform": "(windows | linux) & (arm64 | x64)" + }, + { + "name": "vulkan-utility-libraries", + "version>=": "1.4.304.1", + "platform": "(windows | linux) & (arm64 | x64)" + } + ], + "features": { + "windows-use-d3d12": { + "description": "Enable D3D12 backend on Windows.", + "dependencies": [ + { + "name": "directx-dxc", + "version>=": "2025-02-20#1", + "platform": "windows & !arm32" + }, + { + "name": "directx-headers", + "version>=": "1.615.0", + "platform": "windows & !arm32" + } + ] + }, + "windows-use-vulkan": { + "description": "Enable Vulkan backend on Windows." + } + }, + "default-features": [ + { "name": "windows-use-d3d12", "platform": "windows & !arm32" } + ] +} diff --git a/cmake/vcpkg-ports/dlpack/portfile.cmake b/cmake/vcpkg-ports/dlpack/portfile.cmake new file mode 100644 index 0000000000000..fdf328836d4dd --- /dev/null +++ b/cmake/vcpkg-ports/dlpack/portfile.cmake @@ -0,0 +1,25 @@ +set(VCPKG_BUILD_TYPE release) # header-only port + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO dmlc/dlpack + REF 5c210da409e7f1e51ddf445134a4376fdbd70d7d + SHA512 4bc5f5fd36b20ef2943989d5c06fe9cd34f942cdfd4b4866a4405649f7faac47fcdcf3a1fa60eb7b96b643222e5e4b036cbca7d49835dc5f8b659708620a2e8f + HEAD_REF main +) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + -DBUILD_MOCK=FALSE +) + +vcpkg_cmake_install() + +vcpkg_cmake_config_fixup(CONFIG_PATH "lib/cmake/dlpack") + +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/lib") + +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE") + +file(COPY "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") diff --git a/cmake/vcpkg-ports/dlpack/usage b/cmake/vcpkg-ports/dlpack/usage new file mode 100644 index 0000000000000..771ec78517174 --- /dev/null +++ b/cmake/vcpkg-ports/dlpack/usage @@ -0,0 +1,4 @@ +dlpack provides CMake targets: + + find_package(dlpack CONFIG REQUIRED) + target_link_libraries(main PRIVATE dlpack::dlpack) diff --git a/cmake/vcpkg-ports/dlpack/vcpkg.json b/cmake/vcpkg-ports/dlpack/vcpkg.json new file mode 100644 index 0000000000000..48f2f22a0a058 --- /dev/null +++ b/cmake/vcpkg-ports/dlpack/vcpkg.json @@ -0,0 +1,17 @@ +{ + "name": "dlpack", + "version-semver": "1.1.1", + "description": "DLPack is an open in-memory tensor structure for sharing tensors among frameworks", + "homepage": "https://github.com/dmlc/dlpack", + "license": "Apache-2.0", + "dependencies": [ + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] +} diff --git a/cmake/vcpkg-ports/eigen3/fix-vectorized-reductions-half.patch b/cmake/vcpkg-ports/eigen3/fix-vectorized-reductions-half.patch new file mode 100644 index 0000000000000..1c5e592db52fa --- /dev/null +++ b/cmake/vcpkg-ports/eigen3/fix-vectorized-reductions-half.patch @@ -0,0 +1,26 @@ +diff --git a/Eigen/src/Core/PartialReduxEvaluator.h b/Eigen/src/Core/PartialReduxEvaluator.h +index 29abf35..4051fcf 100644 +--- a/Eigen/src/Core/PartialReduxEvaluator.h ++++ b/Eigen/src/Core/PartialReduxEvaluator.h +@@ -54,12 +54,19 @@ struct packetwise_redux_traits + /* Value to be returned when size==0 , by default let's return 0 */ + template + EIGEN_DEVICE_FUNC +-PacketType packetwise_redux_empty_value(const Func& ) { return pset1(0); } ++PacketType packetwise_redux_empty_value(const Func& ) { ++ const typename unpacket_traits::type zero(0); ++ return pset1(zero); ++} ++ + + /* For products the default is 1 */ + template + EIGEN_DEVICE_FUNC +-PacketType packetwise_redux_empty_value(const scalar_product_op& ) { return pset1(1); } ++PacketType packetwise_redux_empty_value(const scalar_product_op& ) { ++ return pset1(Scalar(1)); ++} ++ + + /* Perform the actual reduction */ + template +Date: Mon, 21 Mar 2022 15:56:03 +0000 +Subject: [PATCH] Update warning suppression to latest. + +--- + Eigen/src/Core/util/DisableStupidWarnings.h | 91 ++++++++++++++------- + 1 file changed, 61 insertions(+), 30 deletions(-) + mode change 100755 => 100644 Eigen/src/Core/util/DisableStupidWarnings.h + +diff --git a/Eigen/src/Core/util/DisableStupidWarnings.h b/Eigen/src/Core/util/DisableStupidWarnings.h +old mode 100755 +new mode 100644 +index fe0cfec0b..75056592d +--- a/Eigen/src/Core/util/DisableStupidWarnings.h ++++ b/Eigen/src/Core/util/DisableStupidWarnings.h +@@ -1,7 +1,7 @@ + #ifndef EIGEN_WARNINGS_DISABLED + #define EIGEN_WARNINGS_DISABLED + +-#ifdef _MSC_VER ++#if defined(_MSC_VER) + // 4100 - unreferenced formal parameter (occurred e.g. in aligned_allocator::destroy(pointer p)) + // 4101 - unreferenced local variable + // 4181 - qualifier applied to reference type ignored +@@ -35,25 +35,28 @@ + #pragma warning disable 2196 279 1684 2259 + + #elif defined __clang__ +- // -Wconstant-logical-operand - warning: use of logical && with constant operand; switch to bitwise & or remove constant +- // this is really a stupid warning as it warns on compile-time expressions involving enums + #ifndef EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS + #pragma clang diagnostic push + #endif +- #pragma clang diagnostic ignored "-Wconstant-logical-operand" +- #if __clang_major__ >= 3 && __clang_minor__ >= 5 +- #pragma clang diagnostic ignored "-Wabsolute-value" +- #endif +- #if __clang_major__ >= 10 +- #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" +- #endif +- #if ( defined(__ALTIVEC__) || defined(__VSX__) ) && __cplusplus < 201103L +- // warning: generic selections are a C11-specific feature +- // ignoring warnings thrown at vec_ctf in Altivec/PacketMath.h +- #pragma clang diagnostic ignored "-Wc11-extensions" ++ #if defined(__has_warning) ++ // -Wconstant-logical-operand - warning: use of logical && with constant operand; switch to bitwise & or remove constant ++ // this is really a stupid warning as it warns on compile-time expressions involving enums ++ #if __has_warning("-Wconstant-logical-operand") ++ #pragma clang diagnostic ignored "-Wconstant-logical-operand" ++ #endif ++ #if __has_warning("-Wimplicit-int-float-conversion") ++ #pragma clang diagnostic ignored "-Wimplicit-int-float-conversion" ++ #endif ++ #if ( defined(__ALTIVEC__) || defined(__VSX__) ) && __cplusplus < 201103L ++ // warning: generic selections are a C11-specific feature ++ // ignoring warnings thrown at vec_ctf in Altivec/PacketMath.h ++ #if __has_warning("-Wc11-extensions") ++ #pragma clang diagnostic ignored "-Wc11-extensions" ++ #endif ++ #endif + #endif + +-#elif defined __GNUC__ ++#elif defined __GNUC__ && !defined(__FUJITSU) + + #if (!defined(EIGEN_PERMANENTLY_DISABLE_STUPID_WARNINGS)) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) + #pragma GCC diagnostic push +@@ -74,25 +77,53 @@ + #endif + + #if defined __NVCC__ +- #pragma diag_suppress boolean_controlling_expr_is_constant ++ // MSVC 14.16 (required by CUDA 9.*) does not support the _Pragma keyword, so ++ // we instead use Microsoft's __pragma extension. ++ #if defined _MSC_VER ++ #define EIGEN_MAKE_PRAGMA(X) __pragma(#X) ++ #else ++ #define EIGEN_MAKE_PRAGMA(X) _Pragma(#X) ++ #endif ++ #if defined __NVCC_DIAG_PRAGMA_SUPPORT__ ++ #define EIGEN_NV_DIAG_SUPPRESS(X) EIGEN_MAKE_PRAGMA(nv_diag_suppress X) ++ #else ++ #define EIGEN_NV_DIAG_SUPPRESS(X) EIGEN_MAKE_PRAGMA(diag_suppress X) ++ #endif ++ ++ EIGEN_NV_DIAG_SUPPRESS(boolean_controlling_expr_is_constant) + // Disable the "statement is unreachable" message +- #pragma diag_suppress code_is_unreachable ++ EIGEN_NV_DIAG_SUPPRESS(code_is_unreachable) + // Disable the "dynamic initialization in unreachable code" message +- #pragma diag_suppress initialization_not_reachable ++ EIGEN_NV_DIAG_SUPPRESS(initialization_not_reachable) + // Disable the "invalid error number" message that we get with older versions of nvcc +- #pragma diag_suppress 1222 ++ EIGEN_NV_DIAG_SUPPRESS(1222) + // Disable the "calling a __host__ function from a __host__ __device__ function is not allowed" messages (yes, there are many of them and they seem to change with every version of the compiler) +- #pragma diag_suppress 2527 +- #pragma diag_suppress 2529 +- #pragma diag_suppress 2651 +- #pragma diag_suppress 2653 +- #pragma diag_suppress 2668 +- #pragma diag_suppress 2669 +- #pragma diag_suppress 2670 +- #pragma diag_suppress 2671 +- #pragma diag_suppress 2735 +- #pragma diag_suppress 2737 +- #pragma diag_suppress 2739 ++ EIGEN_NV_DIAG_SUPPRESS(2527) ++ EIGEN_NV_DIAG_SUPPRESS(2529) ++ EIGEN_NV_DIAG_SUPPRESS(2651) ++ EIGEN_NV_DIAG_SUPPRESS(2653) ++ EIGEN_NV_DIAG_SUPPRESS(2668) ++ EIGEN_NV_DIAG_SUPPRESS(2669) ++ EIGEN_NV_DIAG_SUPPRESS(2670) ++ EIGEN_NV_DIAG_SUPPRESS(2671) ++ EIGEN_NV_DIAG_SUPPRESS(2735) ++ EIGEN_NV_DIAG_SUPPRESS(2737) ++ EIGEN_NV_DIAG_SUPPRESS(2739) ++ EIGEN_NV_DIAG_SUPPRESS(2885) ++ EIGEN_NV_DIAG_SUPPRESS(2888) ++ EIGEN_NV_DIAG_SUPPRESS(2976) ++ EIGEN_NV_DIAG_SUPPRESS(2979) ++ EIGEN_NV_DIAG_SUPPRESS(20011) ++ EIGEN_NV_DIAG_SUPPRESS(20014) ++ // Disable the "// __device__ annotation is ignored on a function(...) that is ++ // explicitly defaulted on its first declaration" message. ++ // The __device__ annotation seems to actually be needed in some cases, ++ // otherwise resulting in kernel runtime errors. ++ EIGEN_NV_DIAG_SUPPRESS(2886) ++ EIGEN_NV_DIAG_SUPPRESS(2977) ++ EIGEN_NV_DIAG_SUPPRESS(20012) ++ #undef EIGEN_NV_DIAG_SUPPRESS ++ #undef EIGEN_MAKE_PRAGMA + #endif + + #else +-- +2.37.0.windows.1 + diff --git a/cmake/vcpkg-ports/eigen3/vcpkg.json b/cmake/vcpkg-ports/eigen3/vcpkg.json new file mode 100644 index 0000000000000..86fef988ab3e9 --- /dev/null +++ b/cmake/vcpkg-ports/eigen3/vcpkg.json @@ -0,0 +1,18 @@ +{ + "name": "eigen3", + "version": "3.4.0", + "port-version": 5, + "description": "C++ template library for linear algebra: matrices, vectors, numerical solvers, and related algorithms.", + "homepage": "http://eigen.tuxfamily.org", + "license": "MPL-2.0", + "dependencies": [ + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] +} diff --git a/cmake/vcpkg-ports/onnx/binskim.patch b/cmake/vcpkg-ports/onnx/binskim.patch new file mode 100644 index 0000000000000..0a5680778790b --- /dev/null +++ b/cmake/vcpkg-ports/onnx/binskim.patch @@ -0,0 +1,84 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 044996e..ded7e39 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) + 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_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}) ++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" ++ ) ++ # 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) ++ # Minimal build doesn't need Python or tests ++ 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}) ++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() +diff --git a/onnx/defs/nn/old.cc b/onnx/defs/nn/old.cc +index a6a8a83..153da87 100644 +--- a/onnx/defs/nn/old.cc ++++ b/onnx/defs/nn/old.cc +@@ -4026,7 +4026,6 @@ ONNX_OPERATOR_SET_SCHEMA( + GroupNormalization, + 18, + OpSchema() +- .Deprecate() + .SetDoc(GroupNormalization_ver18_doc) + .Attr("epsilon", "The epsilon value to use to avoid division by zero.", AttributeProto::FLOAT, 1e-5f) + .Attr( diff --git a/cmake/vcpkg-ports/onnx/fix-cmakelists.patch b/cmake/vcpkg-ports/onnx/fix-cmakelists.patch new file mode 100644 index 0000000000000..28a7ef9f81402 --- /dev/null +++ b/cmake/vcpkg-ports/onnx/fix-cmakelists.patch @@ -0,0 +1,21 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 47995579..70feae97 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -91,6 +91,16 @@ endif() + + include(GNUInstallDirs) + ++# install protobuf files ++install(FILES ${CMAKE_CURRENT_BINARY_DIR}/onnx/onnx-data.proto ++ ${CMAKE_CURRENT_BINARY_DIR}/onnx/onnx-data.proto3 ++ ${CMAKE_CURRENT_BINARY_DIR}/onnx/onnx-ml.proto ++ ${CMAKE_CURRENT_BINARY_DIR}/onnx/onnx-ml.proto3 ++ ${CMAKE_CURRENT_BINARY_DIR}/onnx/onnx-operators-ml.proto ++ ${CMAKE_CURRENT_BINARY_DIR}/onnx/onnx-operators-ml.proto3 ++ DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/onnx ++) ++ + set(ONNX_ROOT ${onnx_SOURCE_DIR}) + + # Read ONNX version diff --git a/cmake/vcpkg-ports/onnx/fix-dependency-protobuf.patch b/cmake/vcpkg-ports/onnx/fix-dependency-protobuf.patch new file mode 100644 index 0000000000000..4a438def6cf1b --- /dev/null +++ b/cmake/vcpkg-ports/onnx/fix-dependency-protobuf.patch @@ -0,0 +1,28 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 4a7df7d71..257d77e61 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -159,6 +159,7 @@ if(NOT DEFINED CMAKE_POSITION_INDEPENDENT_CODE) + set(CMAKE_POSITION_INDEPENDENT_CODE ON) + endif() + ++find_package(protobuf CONFIG REQUIRED) + list(APPEND CMAKE_MODULE_PATH ${ONNX_ROOT}/cmake/external) + if(NOT ONNX_BUILD_CUSTOM_PROTOBUF) + if((ONNX_USE_LITE_PROTO AND TARGET protobuf::libprotobuf-lite) OR ((NOT ONNX_USE_LITE_PROTO) AND TARGET protobuf::libprotobuf)) +diff --git a/cmake/ONNXConfig.cmake.in b/cmake/ONNXConfig.cmake.in +index aa1ef47d9..d450b51e5 100644 +--- a/cmake/ONNXConfig.cmake.in ++++ b/cmake/ONNXConfig.cmake.in +@@ -4,9 +4,8 @@ + # library version information + set(ONNX_VERSION "@ONNX_VERSION@") + +-if(NOT @ONNX_USE_PROTOBUF_SHARED_LIBS@) +- find_package(Protobuf REQUIRED CONFIG) +-endif() ++include(CMakeFindDependencyMacro) ++find_dependency(protobuf CONFIG) + + # import targets + include ("${CMAKE_CURRENT_LIST_DIR}/ONNXTargets.cmake") diff --git a/cmake/vcpkg-ports/onnx/portfile.cmake b/cmake/vcpkg-ports/onnx/portfile.cmake new file mode 100644 index 0000000000000..3450dcb2e80ce --- /dev/null +++ b/cmake/vcpkg-ports/onnx/portfile.cmake @@ -0,0 +1,81 @@ +vcpkg_check_linkage(ONLY_STATIC_LIBRARY) + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO onnx/onnx + REF "v${VERSION}" + SHA512 3cee4c0fbc9e260e360a62a59e324e0b127a5749f958e0704989b407a4c1179c637ef86e41a406e7868537a62a11a821e3433005eb0725f979145f8d514926bd + PATCHES + fix-cmakelists.patch + fix-dependency-protobuf.patch + binskim.patch +) + +string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" USE_STATIC_RUNTIME) + +# ONNX_CUSTOM_PROTOC_EXECUTABLE +find_program(PROTOC NAMES protoc PATHS "${CURRENT_HOST_INSTALLED_DIR}/tools/protobuf" REQUIRED NO_DEFAULT_PATH NO_CMAKE_PATH) + +# ONNX_USE_PROTOBUF_SHARED_LIBS: find the library and check its file extension +find_library(PROTOBUF_LIBPATH NAMES protobuf PATHS "${CURRENT_INSTALLED_DIR}/bin" "${CURRENT_INSTALLED_DIR}/lib" REQUIRED) +get_filename_component(PROTOBUF_LIBNAME "${PROTOBUF_LIBPATH}" NAME) +if(PROTOBUF_LIBNAME MATCHES "${CMAKE_SHARED_LIBRARY_SUFFIX}") + set(USE_PROTOBUF_SHARED ON) +else() + set(USE_PROTOBUF_SHARED OFF) +endif() + +vcpkg_find_acquire_program(PYTHON3) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + ${FEATURE_OPTIONS} + "-DPython3_EXECUTABLE:FILEPATH=${PYTHON3}" + "-DONNX_CUSTOM_PROTOC_EXECUTABLE:FILEPATH=${PROTOC}" + "-DProtobuf_PROTOC_EXECUTABLE:FILEPATH=${PROTOC}" + -DONNX_ML=ON + -DONNX_USE_PROTOBUF_SHARED_LIBS=${USE_PROTOBUF_SHARED} + -DONNX_USE_MSVC_STATIC_RUNTIME=${USE_STATIC_RUNTIME} + -DONNX_BUILD_TESTS=OFF + -DONNX_BUILD_BENCHMARKS=OFF + MAYBE_UNUSED_VARIABLES + ONNX_USE_MSVC_STATIC_RUNTIME +) +vcpkg_cmake_install() +vcpkg_cmake_config_fixup(CONFIG_PATH lib/cmake/ONNX PACKAGE_NAME ONNX) + +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE") + +file(REMOVE_RECURSE + "${CURRENT_PACKAGES_DIR}/debug/include" + "${CURRENT_PACKAGES_DIR}/debug/share" + # the others are empty + "${CURRENT_PACKAGES_DIR}/include/onnx/backend" + "${CURRENT_PACKAGES_DIR}/include/onnx/bin" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/controlflow" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/generator" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/image" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/logical" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/math" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/nn" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/object_detection" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/optional" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/quantization" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/reduction" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/rnn" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/sequence" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/text" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/traditionalml" + "${CURRENT_PACKAGES_DIR}/include/onnx/defs/training" + "${CURRENT_PACKAGES_DIR}/include/onnx/examples" + "${CURRENT_PACKAGES_DIR}/include/onnx/frontend" + "${CURRENT_PACKAGES_DIR}/include/onnx/onnx_cpp2py_export" + "${CURRENT_PACKAGES_DIR}/include/onnx/test" + "${CURRENT_PACKAGES_DIR}/include/onnx/tools" + "${CURRENT_PACKAGES_DIR}/include/onnx/onnx_ml" + "${CURRENT_PACKAGES_DIR}/include/onnx/onnx_data" + "${CURRENT_PACKAGES_DIR}/include/onnx/onnx_operators_ml" + "${CURRENT_PACKAGES_DIR}/include/onnx/reference/ops" + "${CURRENT_PACKAGES_DIR}/include/onnx/reference" +) diff --git a/cmake/vcpkg-ports/onnx/vcpkg.json b/cmake/vcpkg-ports/onnx/vcpkg.json new file mode 100644 index 0000000000000..5ad70ff409e05 --- /dev/null +++ b/cmake/vcpkg-ports/onnx/vcpkg.json @@ -0,0 +1,23 @@ +{ + "name": "onnx", + "version-semver": "1.21.0", + "port-version": 0, + "description": "Open standard for machine learning interoperability", + "homepage": "https://onnx.ai", + "license": "Apache-2.0", + "dependencies": [ + "protobuf", + { + "name": "protobuf", + "host": true + }, + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] +} diff --git a/cmake/vcpkg-ports/protobuf/compile_options.patch b/cmake/vcpkg-ports/protobuf/compile_options.patch new file mode 100644 index 0000000000000..8cf5417740f27 --- /dev/null +++ b/cmake/vcpkg-ports/protobuf/compile_options.patch @@ -0,0 +1,48 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 04cb3303a..608c580be 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -242,12 +242,12 @@ endif (protobuf_BUILD_SHARED_LIBS) + if (MSVC) + if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # Build with multiple processes +- add_definitions(/MP) ++ add_compile_options(/MP) + endif() + # Set source file and execution character sets to UTF-8 +- add_definitions(/utf-8) ++ add_compile_options(/utf-8) + # MSVC warning suppressions +- add_definitions( ++ add_compile_options( + /wd4065 # switch statement contains 'default' but no 'case' labels + /wd4244 # 'conversion' conversion from 'type1' to 'type2', possible loss of data + /wd4251 # 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2' +@@ -262,23 +262,17 @@ if (MSVC) + /wd4996 # The compiler encountered a deprecated declaration. + ) + # Allow big object +- add_definitions(/bigobj) ++ add_compile_options(/bigobj) + string(REPLACE "/" "\\" PROTOBUF_SOURCE_WIN32_PATH ${protobuf_SOURCE_DIR}) + string(REPLACE "/" "\\" PROTOBUF_BINARY_WIN32_PATH ${protobuf_BINARY_DIR}) + string(REPLACE "." "," protobuf_RC_FILEVERSION "${protobuf_VERSION}") + configure_file(${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in extract_includes.bat) + + # Suppress linker warnings about files with no symbols defined. +- set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") ++ string(APPEND CMAKE_STATIC_LINKER_FLAGS " /ignore:4221") + +- if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") +- # Configure Resource Compiler +- enable_language(RC) +- # use English language (0x409) in resource compiler +- set(rc_flags "/l0x409") +- # fix rc.exe invocations because of usage of add_definitions() +- set(CMAKE_RC_COMPILE_OBJECT " ${rc_flags} /fo ") +- endif() ++ # use English language (0x409) in resource compiler ++ string(APPEND CMAKE_RC_FLAGS " -l0x409") + + # Generate the version.rc file used elsewhere. + configure_file(${protobuf_SOURCE_DIR}/cmake/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) diff --git a/cmake/vcpkg-ports/protobuf/fix-default-proto-file-path.patch b/cmake/vcpkg-ports/protobuf/fix-default-proto-file-path.patch new file mode 100644 index 0000000000000..1c850b1dec2b9 --- /dev/null +++ b/cmake/vcpkg-ports/protobuf/fix-default-proto-file-path.patch @@ -0,0 +1,21 @@ +diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc +index 5e9a2c4..8eaa6e0 100644 +--- a/src/google/protobuf/compiler/command_line_interface.cc ++++ b/src/google/protobuf/compiler/command_line_interface.cc +@@ -261,12 +261,15 @@ void AddDefaultProtoPaths( + std::pair("", path + "/include")); + return; + } +- // Check if the upper level directory has an "include" subdirectory. ++ // change "'$/bin' is next to 'include'" assumption to "'$/bin/tools' is next to 'include'" ++ for (int i = 0; i < 2; i++) ++ { + pos = path.find_last_of("/\\"); + if (pos == std::string::npos || pos == 0) { + return; + } + path = path.substr(0, pos); ++ } + if (IsInstalledProtoPath(path + "/include")) { + paths->push_back( + std::pair("", path + "/include")); diff --git a/cmake/vcpkg-ports/protobuf/fix-static-build.patch b/cmake/vcpkg-ports/protobuf/fix-static-build.patch new file mode 100644 index 0000000000000..496c6c4d50524 --- /dev/null +++ b/cmake/vcpkg-ports/protobuf/fix-static-build.patch @@ -0,0 +1,13 @@ +diff --git a/cmake/install.cmake b/cmake/install.cmake +index 825cb25..4f453d6 100644 +--- a/cmake/install.cmake ++++ b/cmake/install.cmake +@@ -32,7 +32,7 @@ if (protobuf_BUILD_PROTOC_BINARIES) + install(TARGETS protoc EXPORT protobuf-targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc + BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc) +- if (UNIX AND NOT APPLE) ++ if (UNIX AND NOT APPLE AND NOT protobuf_MSVC_STATIC_RUNTIME) + set_property(TARGET protoc + PROPERTY INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") + elseif (APPLE) diff --git a/cmake/vcpkg-ports/protobuf/portfile.cmake b/cmake/vcpkg-ports/protobuf/portfile.cmake new file mode 100644 index 0000000000000..66ea966abd762 --- /dev/null +++ b/cmake/vcpkg-ports/protobuf/portfile.cmake @@ -0,0 +1,156 @@ +vcpkg_minimum_required(VERSION 2022-10-12) # for ${VERSION} + +vcpkg_from_github( + OUT_SOURCE_PATH SOURCE_PATH + REPO protocolbuffers/protobuf + REF v3.21.12 + SHA512 152f8441c325e808b942153c15e82fdb533d5273b50c25c28916ec568ada880f79242bb61ee332ac5fb0d20f21239ed6f8de02ef6256cc574b1fc354d002c6b0 + HEAD_REF master + PATCHES + protobuf_cmake.patch +) + +string(COMPARE EQUAL "${TARGET_TRIPLET}" "${HOST_TRIPLET}" protobuf_BUILD_PROTOC_BINARIES) +string(COMPARE EQUAL "${VCPKG_LIBRARY_LINKAGE}" "dynamic" protobuf_BUILD_SHARED_LIBS) +string(COMPARE EQUAL "${VCPKG_CRT_LINKAGE}" "static" protobuf_MSVC_STATIC_RUNTIME) + +vcpkg_check_features(OUT_FEATURE_OPTIONS FEATURE_OPTIONS + FEATURES + zlib protobuf_WITH_ZLIB +) + +if(VCPKG_TARGET_IS_UWP) + set(protobuf_BUILD_LIBPROTOC OFF) +else() + set(protobuf_BUILD_LIBPROTOC ON) +endif() + +if (VCPKG_DOWNLOAD_MODE) + # download PKGCONFIG in download mode which is used in `vcpkg_fixup_pkgconfig()` at the end of this script. + # download it here because `vcpkg_cmake_configure()` halts execution in download mode when running configure process. + vcpkg_find_acquire_program(PKGCONFIG) +endif() + +# Delete language backends we aren't targeting to reduce false positives in automated dependency +# detectors like Dependabot. +file(REMOVE_RECURSE + "${SOURCE_PATH}/csharp" + "${SOURCE_PATH}/java" + "${SOURCE_PATH}/objectivec" + "${SOURCE_PATH}/php" + "${SOURCE_PATH}/python" + "${SOURCE_PATH}/ruby" +) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + -Dprotobuf_BUILD_SHARED_LIBS=${protobuf_BUILD_SHARED_LIBS} + -Dprotobuf_MSVC_STATIC_RUNTIME=${protobuf_MSVC_STATIC_RUNTIME} + -Dprotobuf_BUILD_TESTS=OFF + -DCMAKE_INSTALL_CMAKEDIR:STRING=share/protobuf + -Dprotobuf_BUILD_PROTOC_BINARIES=${protobuf_BUILD_PROTOC_BINARIES} + -Dprotobuf_BUILD_LIBPROTOC=${protobuf_BUILD_LIBPROTOC} + ${FEATURE_OPTIONS} +) + +vcpkg_cmake_install() + +# It appears that at this point the build hasn't actually finished. There is probably +# a process spawned by the build, therefore we need to wait a bit. + +function(protobuf_try_remove_recurse_wait PATH_TO_REMOVE) + file(REMOVE_RECURSE ${PATH_TO_REMOVE}) + if (EXISTS "${PATH_TO_REMOVE}") + execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 5) + file(REMOVE_RECURSE ${PATH_TO_REMOVE}) + endif() +endfunction() + +protobuf_try_remove_recurse_wait("${CURRENT_PACKAGES_DIR}/debug/include") + +if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "release") + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/protobuf/protobuf-targets-release.cmake" + "\${_IMPORT_PREFIX}/bin/protoc${VCPKG_HOST_EXECUTABLE_SUFFIX}" + "\${_IMPORT_PREFIX}/tools/protobuf/protoc${VCPKG_HOST_EXECUTABLE_SUFFIX}" + IGNORE_UNCHANGED + ) +endif() + +if(NOT DEFINED VCPKG_BUILD_TYPE OR VCPKG_BUILD_TYPE STREQUAL "debug") + file(READ "${CURRENT_PACKAGES_DIR}/debug/share/protobuf/protobuf-targets-debug.cmake" DEBUG_MODULE) + string(REPLACE "\${_IMPORT_PREFIX}" "\${_IMPORT_PREFIX}/debug" DEBUG_MODULE "${DEBUG_MODULE}") + string(REPLACE "\${_IMPORT_PREFIX}/debug/bin/protoc${EXECUTABLE_SUFFIX}" "\${_IMPORT_PREFIX}/tools/protobuf/protoc${EXECUTABLE_SUFFIX}" DEBUG_MODULE "${DEBUG_MODULE}") + file(WRITE "${CURRENT_PACKAGES_DIR}/share/protobuf/protobuf-targets-debug.cmake" "${DEBUG_MODULE}") +endif() + +protobuf_try_remove_recurse_wait("${CURRENT_PACKAGES_DIR}/debug/share") + +if(protobuf_BUILD_PROTOC_BINARIES) + if(VCPKG_TARGET_IS_WINDOWS) + vcpkg_copy_tools(TOOL_NAMES protoc AUTO_CLEAN) + else() + vcpkg_copy_tools(TOOL_NAMES protoc protoc-${VERSION}.0 AUTO_CLEAN) + endif() +else() + file(COPY "${CURRENT_HOST_INSTALLED_DIR}/tools/${PORT}" DESTINATION "${CURRENT_PACKAGES_DIR}/tools") +endif() + +vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/${PORT}/protobuf-config.cmake" + "if(protobuf_MODULE_COMPATIBLE)" + "if(ON)" +) +if(NOT protobuf_BUILD_LIBPROTOC) + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/share/${PORT}/protobuf-module.cmake" + "_protobuf_find_libraries(Protobuf_PROTOC protoc)" + "" + ) +endif() + +if(VCPKG_LIBRARY_LINKAGE STREQUAL "static") + protobuf_try_remove_recurse_wait("${CURRENT_PACKAGES_DIR}/bin") + protobuf_try_remove_recurse_wait("${CURRENT_PACKAGES_DIR}/debug/bin") +endif() + +if(VCPKG_LIBRARY_LINKAGE STREQUAL "dynamic") + vcpkg_replace_string("${CURRENT_PACKAGES_DIR}/include/google/protobuf/stubs/platform_macros.h" + "\#endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_" + "\#ifndef PROTOBUF_USE_DLLS\n\#define PROTOBUF_USE_DLLS\n\#endif // PROTOBUF_USE_DLLS\n\n\#endif // GOOGLE_PROTOBUF_PLATFORM_MACROS_H_" + ) +endif() + +vcpkg_copy_pdbs() + +function(replace_package_string package) + set(debug_file "${CURRENT_PACKAGES_DIR}/debug/lib/pkgconfig/${package}.pc") + set(release_file "${CURRENT_PACKAGES_DIR}/lib/pkgconfig/${package}.pc") + + if(EXISTS "${release_file}") + if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW) + vcpkg_replace_string(${release_file} "-l${package}" "-llib${package}") + endif() + endif() + + if(EXISTS "${debug_file}") + if(VCPKG_TARGET_IS_WINDOWS AND NOT VCPKG_TARGET_IS_MINGW) + vcpkg_replace_string(${debug_file} "-l${package}" "-llib${package}d") + else() + vcpkg_replace_string(${debug_file} "-l${package}" "-l${package}d") + endif() + endif() +endfunction() + +set(packages protobuf protobuf-lite) +foreach(package IN LISTS packages) + replace_package_string(${package}) +endforeach() + + +vcpkg_fixup_pkgconfig() + +if(NOT protobuf_BUILD_PROTOC_BINARIES) + configure_file("${CMAKE_CURRENT_LIST_DIR}/protobuf-targets-vcpkg-protoc.cmake" "${CURRENT_PACKAGES_DIR}/share/${PORT}/protobuf-targets-vcpkg-protoc.cmake" COPYONLY) +endif() + +configure_file("${CMAKE_CURRENT_LIST_DIR}/vcpkg-cmake-wrapper.cmake" "${CURRENT_PACKAGES_DIR}/share/${PORT}/vcpkg-cmake-wrapper.cmake" @ONLY) +file(INSTALL "${SOURCE_PATH}/LICENSE" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}" RENAME copyright) diff --git a/cmake/vcpkg-ports/protobuf/protobuf-targets-vcpkg-protoc.cmake b/cmake/vcpkg-ports/protobuf/protobuf-targets-vcpkg-protoc.cmake new file mode 100644 index 0000000000000..149e6587eee28 --- /dev/null +++ b/cmake/vcpkg-ports/protobuf/protobuf-targets-vcpkg-protoc.cmake @@ -0,0 +1,8 @@ +# Create imported target protobuf::protoc +add_executable(protobuf::protoc IMPORTED) + +# Import target "protobuf::protoc" for configuration "Release" +set_property(TARGET protobuf::protoc APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE) +set_target_properties(protobuf::protoc PROPERTIES + IMPORTED_LOCATION_RELEASE "${Protobuf_PROTOC_EXECUTABLE}" +) diff --git a/cmake/vcpkg-ports/protobuf/protobuf_cmake.patch b/cmake/vcpkg-ports/protobuf/protobuf_cmake.patch new file mode 100644 index 0000000000000..98c6902a5fd45 --- /dev/null +++ b/cmake/vcpkg-ports/protobuf/protobuf_cmake.patch @@ -0,0 +1,122 @@ +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 04cb3303a..9535ea2af 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -242,16 +242,14 @@ endif (protobuf_BUILD_SHARED_LIBS) + if (MSVC) + if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") + # Build with multiple processes +- add_definitions(/MP) ++ add_compile_options(/MP) + endif() + # Set source file and execution character sets to UTF-8 +- add_definitions(/utf-8) ++ add_compile_options(/utf-8) + # MSVC warning suppressions +- add_definitions( ++ add_compile_options( + /wd4065 # switch statement contains 'default' but no 'case' labels +- /wd4244 # 'conversion' conversion from 'type1' to 'type2', possible loss of data + /wd4251 # 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2' +- /wd4267 # 'var' : conversion from 'size_t' to 'type', possible loss of data + /wd4305 # 'identifier' : truncation from 'type1' to 'type2' + /wd4307 # 'operator' : integral constant overflow + /wd4309 # 'conversion' : truncation of constant value +@@ -259,26 +257,20 @@ if (MSVC) + /wd4355 # 'this' : used in base member initializer list + /wd4506 # no definition for inline function 'function' + /wd4800 # 'type' : forcing value to bool 'true' or 'false' (performance warning) +- /wd4996 # The compiler encountered a deprecated declaration. ++ ${onnxruntime_PROTOBUF_EXTRA_WARNING_DISABLEMENT} + ) + # Allow big object +- add_definitions(/bigobj) ++ add_compile_options(/bigobj) + string(REPLACE "/" "\\" PROTOBUF_SOURCE_WIN32_PATH ${protobuf_SOURCE_DIR}) + string(REPLACE "/" "\\" PROTOBUF_BINARY_WIN32_PATH ${protobuf_BINARY_DIR}) + string(REPLACE "." "," protobuf_RC_FILEVERSION "${protobuf_VERSION}") + configure_file(${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in extract_includes.bat) + + # Suppress linker warnings about files with no symbols defined. +- set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221") ++ string(APPEND CMAKE_STATIC_LINKER_FLAGS " /ignore:4221") + +- if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC") +- # Configure Resource Compiler +- enable_language(RC) +- # use English language (0x409) in resource compiler +- set(rc_flags "/l0x409") +- # fix rc.exe invocations because of usage of add_definitions() +- set(CMAKE_RC_COMPILE_OBJECT " ${rc_flags} /fo ") +- endif() ++ # use English language (0x409) in resource compiler ++ string(APPEND CMAKE_RC_FLAGS " -l0x409") + + # Generate the version.rc file used elsewhere. + configure_file(${protobuf_SOURCE_DIR}/cmake/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY) +@@ -289,7 +281,6 @@ if (MSVC) + else (MSVC) + # No version.rc file. + set(protobuf_version_rc_file) +- + # When building with "make", "lib" prefix will be added automatically by + # the build tool. + set(LIB_PREFIX) +diff --git a/cmake/install.cmake b/cmake/install.cmake +index 825cb25fc..4f453d6cd 100644 +--- a/cmake/install.cmake ++++ b/cmake/install.cmake +@@ -32,7 +32,7 @@ if (protobuf_BUILD_PROTOC_BINARIES) + install(TARGETS protoc EXPORT protobuf-targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc + BUNDLE DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT protoc) +- if (UNIX AND NOT APPLE) ++ if (UNIX AND NOT APPLE AND NOT protobuf_MSVC_STATIC_RUNTIME) + set_property(TARGET protoc + PROPERTY INSTALL_RPATH "$ORIGIN/../${CMAKE_INSTALL_LIBDIR}") + elseif (APPLE) +diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc +index 5e9a2c418..8eaa6e035 100644 +--- a/src/google/protobuf/compiler/command_line_interface.cc ++++ b/src/google/protobuf/compiler/command_line_interface.cc +@@ -261,12 +261,15 @@ void AddDefaultProtoPaths( + std::pair("", path + "/include")); + return; + } +- // Check if the upper level directory has an "include" subdirectory. ++ // change "'$/bin' is next to 'include'" assumption to "'$/bin/tools' is next to 'include'" ++ for (int i = 0; i < 2; i++) ++ { + pos = path.find_last_of("/\\"); + if (pos == std::string::npos || pos == 0) { + return; + } + path = path.substr(0, pos); ++ } + if (IsInstalledProtoPath(path + "/include")) { + paths->push_back( + std::pair("", path + "/include")); +diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h +index 008c19225..cbab108c2 100644 +--- a/src/google/protobuf/map.h ++++ b/src/google/protobuf/map.h +@@ -52,7 +52,8 @@ + #endif // defined(__cpp_lib_string_view) + + #if !defined(GOOGLE_PROTOBUF_NO_RDTSC) && defined(__APPLE__) +-#include ++// apply update from https://github.com/protocolbuffers/protobuf/pull/15662/ ++#include + #endif + + #include +@@ -1154,7 +1155,8 @@ class Map { + #if defined(__APPLE__) + // Use a commpage-based fast time function on Apple environments (MacOS, + // iOS, tvOS, watchOS, etc). +- s += mach_absolute_time(); ++ // apply update from https://github.com/protocolbuffers/protobuf/pull/15662/ ++ s += clock_gettime_nsec_np(CLOCK_UPTIME_RAW); + #elif defined(__x86_64__) && defined(__GNUC__) + uint32_t hi, lo; + asm volatile("rdtsc" : "=a"(lo), "=d"(hi)); diff --git a/cmake/vcpkg-ports/protobuf/vcpkg-cmake-wrapper.cmake b/cmake/vcpkg-ports/protobuf/vcpkg-cmake-wrapper.cmake new file mode 100644 index 0000000000000..3cdf930128406 --- /dev/null +++ b/cmake/vcpkg-ports/protobuf/vcpkg-cmake-wrapper.cmake @@ -0,0 +1,16 @@ +if(CMAKE_VERSION VERSION_GREATER_EQUAL 3.3) + cmake_policy(PUSH) + cmake_policy(SET CMP0057 NEW) + if(NOT "CONFIG" IN_LIST ARGS AND NOT "NO_MODULE" IN_LIST ARGS) + if("@VCPKG_LIBRARY_LINKAGE@" STREQUAL "static") + set(Protobuf_USE_STATIC_LIBS ON) + else() + set(Protobuf_USE_STATIC_LIBS OFF) + endif() + endif() + cmake_policy(POP) +endif() + +find_program(Protobuf_PROTOC_EXECUTABLE NAMES protoc PATHS "${CMAKE_CURRENT_LIST_DIR}/../../../@HOST_TRIPLET@/tools/protobuf" NO_DEFAULT_PATH) + +_find_package(${ARGS}) diff --git a/cmake/vcpkg-ports/protobuf/vcpkg.json b/cmake/vcpkg-ports/protobuf/vcpkg.json new file mode 100644 index 0000000000000..d922e4bb03b42 --- /dev/null +++ b/cmake/vcpkg-ports/protobuf/vcpkg.json @@ -0,0 +1,30 @@ +{ + "name": "protobuf", + "version": "3.21.12", + "port-version": 4, + "description": "Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data.", + "homepage": "https://github.com/protocolbuffers/protobuf", + "license": "BSD-3-Clause", + "dependencies": [ + { + "name": "protobuf", + "host": true + }, + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ], + "features": { + "zlib": { + "description": "ZLib based features like Gzip streams", + "dependencies": [ + "zlib" + ] + } + } +} diff --git a/cmake/vcpkg-ports/pthreadpool/fix-cmakelists.patch b/cmake/vcpkg-ports/pthreadpool/fix-cmakelists.patch index 97fd1ac7a2bb1..cf7df0ea22980 100644 --- a/cmake/vcpkg-ports/pthreadpool/fix-cmakelists.patch +++ b/cmake/vcpkg-ports/pthreadpool/fix-cmakelists.patch @@ -1,8 +1,8 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index f06aada..3c6c6e2 100644 +index efff8cc..1a0f7e9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -31,8 +31,6 @@ IF(CCACHE_BINARY) +@@ -41,8 +41,6 @@ IF(CMAKE_C_COMPILER_ID STREQUAL "MSVC") ENDIF() # ---[ Options. @@ -11,7 +11,7 @@ index f06aada..3c6c6e2 100644 OPTION(PTHREADPOOL_ALLOW_DEPRECATED_API "Enable deprecated API functions" ON) SET(PTHREADPOOL_SYNC_PRIMITIVE "default" CACHE STRING "Synchronization primitive (condvar, futex, gcd, event, or default) for worker threads") SET_PROPERTY(CACHE PTHREADPOOL_SYNC_PRIMITIVE PROPERTY STRINGS default condvar futex gcd event) -@@ -41,7 +39,7 @@ IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?)$") +@@ -51,7 +49,7 @@ IF(CMAKE_SYSTEM_PROCESSOR MATCHES "^(i[3-6]86|AMD64|x86(_64)?)$") ELSE() OPTION(PTHREADPOOL_ENABLE_FASTPATH "Enable fast path using atomic decrement instead of atomic compare-and-swap" OFF) ENDIF() @@ -20,8 +20,8 @@ index f06aada..3c6c6e2 100644 OPTION(PTHREADPOOL_BUILD_TESTS "Build pthreadpool unit tests" ON) OPTION(PTHREADPOOL_BUILD_BENCHMARKS "Build pthreadpool micro-benchmarks" ON) ELSE() -@@ -67,7 +65,8 @@ MACRO(PTHREADPOOL_TARGET_ENABLE_CXX11 target) - ENDMACRO() +@@ -71,7 +69,8 @@ IF(PTHREADPOOL_BUILD_TESTS) + ENDIF() # ---[ Download deps -IF(NOT DEFINED FXDIV_SOURCE_DIR) @@ -30,7 +30,7 @@ index f06aada..3c6c6e2 100644 MESSAGE(STATUS "Downloading FXdiv to ${CMAKE_BINARY_DIR}/FXdiv-source (define FXDIV_SOURCE_DIR to avoid it)") CONFIGURE_FILE(cmake/DownloadFXdiv.cmake "${CMAKE_BINARY_DIR}/FXdiv-download/CMakeLists.txt") EXECUTE_PROCESS(COMMAND "${CMAKE_COMMAND}" -G "${CMAKE_GENERATOR}" . -@@ -118,21 +117,13 @@ ELSE() +@@ -122,21 +121,13 @@ ELSE() ENDIF() ADD_LIBRARY(pthreadpool_interface INTERFACE) @@ -54,7 +54,7 @@ index f06aada..3c6c6e2 100644 IF(PTHREADPOOL_SYNC_PRIMITIVE STREQUAL "condvar") TARGET_COMPILE_DEFINITIONS(pthreadpool PRIVATE PTHREADPOOL_USE_FUTEX=0) -@@ -181,18 +172,22 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") +@@ -182,18 +173,22 @@ IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") ENDIF() # ---[ Configure FXdiv @@ -80,3 +80,4 @@ index f06aada..3c6c6e2 100644 IF(PTHREADPOOL_BUILD_TESTS) # ---[ Build google test + diff --git a/cmake/vcpkg-ports/pthreadpool/portfile.cmake b/cmake/vcpkg-ports/pthreadpool/portfile.cmake index 9400e5e886639..449459feb33cc 100644 --- a/cmake/vcpkg-ports/pthreadpool/portfile.cmake +++ b/cmake/vcpkg-ports/pthreadpool/portfile.cmake @@ -5,8 +5,8 @@ endif() vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO google/pthreadpool - REF 4e80ca24521aa0fb3a746f9ea9c3eaa20e9afbb0 - SHA512 776017cc5d2aa94337292f2f4fbd54d099ef29abf736ab8147f07f98f12b7654cbd2fe38d34646a479a519c261ac253bbaf19c6dcbb0ec4cc0859de70f7e6472 + REF dcc9f28589066af0dbd4555579281230abbf74dd + SHA512 61853fa8f6c3297d8760be3af1df3f2a00583c1e0e58bdd03cd9cb915e8660a4f2817b22e6463cf53f10de902a1c6204ec6054fcbeada72eeee9e44baeb97178 PATCHES fix-cmakelists.patch ) diff --git a/cmake/vcpkg-ports/pybind11/portfile.cmake b/cmake/vcpkg-ports/pybind11/portfile.cmake new file mode 100644 index 0000000000000..e0dd402cf186b --- /dev/null +++ b/cmake/vcpkg-ports/pybind11/portfile.cmake @@ -0,0 +1,30 @@ +# Manually define the download for the .zip archive (to be consistent with deps.txt) +# If we used vcpkg_from_github, it would download the .tar.gz archive, +# which has different SHA512: 19bee2c76320e25202ee078b5680ff8a7acfb33494dec29dad984ab04de8bcb01340d9fec37c8cc5ac9015dfc367e60312dcd8506e66ce8f0af4c49db562ddef +vcpkg_download_distfile(ARCHIVE + URLS "https://github.com/pybind/pybind11/archive/refs/tags/v${VERSION}.zip" + FILENAME "pybind11-${VERSION}.zip" + SHA512 786b1bf534ac67a8d5669f8babf67bb13e48b3a3da1b6344e43ae10a84b80bbc8fea5f12a65fd18739c341fefef5622c5dc096db964dff33cc62ea4259b2e2c1 +) + +vcpkg_extract_source_archive( + SOURCE_PATH + ARCHIVE "${ARCHIVE}" +) + +vcpkg_cmake_configure( + SOURCE_PATH "${SOURCE_PATH}" + OPTIONS + -DPYBIND11_TEST=OFF + # Disable all Python searching, Python required only for tests + -DPYBIND11_NOPYTHON=ON +) + +vcpkg_cmake_install() +vcpkg_cmake_config_fixup(CONFIG_PATH "share/cmake/pybind11") +vcpkg_fixup_pkgconfig() + +file(REMOVE_RECURSE "${CURRENT_PACKAGES_DIR}/debug/") + +file(INSTALL "${CMAKE_CURRENT_LIST_DIR}/usage" DESTINATION "${CURRENT_PACKAGES_DIR}/share/${PORT}") +vcpkg_install_copyright(FILE_LIST "${SOURCE_PATH}/LICENSE") diff --git a/cmake/vcpkg-ports/pybind11/usage b/cmake/vcpkg-ports/pybind11/usage new file mode 100644 index 0000000000000..83162ad9bae25 --- /dev/null +++ b/cmake/vcpkg-ports/pybind11/usage @@ -0,0 +1,23 @@ +pybind11 provides CMake targets. There are two modes provided; classic, which is built on the old Python +discovery packages in CMake, or the new FindPython mode, which uses FindPython +from 3.12+ forward (3.15+ _highly_ recommended). + +New FindPython mode: + + find_package(Python COMPONENTS Interpreter Development) + find_package(pybind11 CONFIG) + + # pybind11 method: + pybind11_add_module(MyModule1 src1.cpp) + + # Python method: + Python_add_library(MyModule2 src2.cpp) + target_link_libraries(MyModule2 pybind11::headers) + set_target_properties(MyModule2 PROPERTIES + INTERPROCEDURAL_OPTIMIZATION ON + CXX_VISIBILITY_PRESET ON + VISIBILITY_INLINES_HIDDEN ON + ) + +For more information see here: + https://pybind11.readthedocs.io/en/latest/compiling.html#building-with-cmake \ No newline at end of file diff --git a/cmake/vcpkg-ports/pybind11/vcpkg.json b/cmake/vcpkg-ports/pybind11/vcpkg.json new file mode 100644 index 0000000000000..058e2235fea08 --- /dev/null +++ b/cmake/vcpkg-ports/pybind11/vcpkg.json @@ -0,0 +1,17 @@ +{ + "name": "pybind11", + "version": "3.0.2", + "description": "pybind11 is a lightweight header-only library that exposes C++ types in Python and vice versa, mainly to create Python bindings of existing C++ code", + "homepage": "https://github.com/pybind/pybind11", + "license": "BSD-3-Clause", + "dependencies": [ + { + "name": "vcpkg-cmake", + "host": true + }, + { + "name": "vcpkg-cmake-config", + "host": true + } + ] +} diff --git a/cmake/vcpkg-ports/xnnpack/fix-build.patch b/cmake/vcpkg-ports/xnnpack/fix-build.patch index b867377d2ff9e..3da8825e2b57d 100644 --- a/cmake/vcpkg-ports/xnnpack/fix-build.patch +++ b/cmake/vcpkg-ports/xnnpack/fix-build.patch @@ -1,21 +1,17 @@ diff --git a/CMakeLists.txt b/CMakeLists.txt -index f0b3410ae..ba54c3bfe 100644 +index 9f6fb5e256..4387298e59 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt -@@ -1047,9 +1047,11 @@ ENDIF() - IF(XNNPACK_BUILD_ALL_MICROKERNELS) - TARGET_INCLUDE_DIRECTORIES(microkernels-all PRIVATE include src) +@@ -1125,7 +1125,7 @@ ELSE() ENDIF() -+ - TARGET_INCLUDE_DIRECTORIES(datatype PRIVATE include src) - TARGET_INCLUDE_DIRECTORIES(microkernels-prod PRIVATE include src) --TARGET_INCLUDE_DIRECTORIES(hardware-config PRIVATE include src ${CPUINFO_SOURCE_DIR}/include) -+TARGET_INCLUDE_DIRECTORIES(hardware-config PRIVATE include src) -+ - TARGET_INCLUDE_DIRECTORIES(indirection PRIVATE include src) - TARGET_INCLUDE_DIRECTORIES(microparams-init PRIVATE include src) - TARGET_INCLUDE_DIRECTORIES(normalization PRIVATE include src) -@@ -1104,14 +1106,9 @@ IF(NOT TARGET cpuinfo) + + INCLUDE_DIRECTORIES(.) +-TARGET_INCLUDE_DIRECTORIES(xnnpack-hardware-config PRIVATE include src ${CPUINFO_SOURCE_DIR}/include) ++TARGET_INCLUDE_DIRECTORIES(xnnpack-hardware-config PRIVATE include src) + IF(XNNPACK_BUILD_LIBRARY) + TARGET_INCLUDE_DIRECTORIES(XNNPACK PUBLIC include) + IF(WIN32) +@@ -1164,14 +1164,9 @@ IF(NOT TARGET cpuinfo) "${CPUINFO_SOURCE_DIR}" "${CMAKE_BINARY_DIR}/cpuinfo") ELSE() @@ -33,7 +29,7 @@ index f0b3410ae..ba54c3bfe 100644 ENDIF() ENDIF() IF(XNNPACK_BUILD_LIBRARY) -@@ -1129,16 +1126,12 @@ IF(NOT TARGET pthreadpool) +@@ -1189,16 +1184,12 @@ IF(NOT TARGET pthreadpool) "${PTHREADPOOL_SOURCE_DIR}" "${CMAKE_BINARY_DIR}/pthreadpool") ELSE() @@ -53,7 +49,7 @@ index f0b3410ae..ba54c3bfe 100644 ENDIF() ENDIF() TARGET_LINK_LIBRARIES(xnnpack-base INTERFACE pthreadpool) -@@ -1152,12 +1145,12 @@ IF(NOT TARGET fxdiv) +@@ -1212,12 +1203,12 @@ IF(NOT TARGET fxdiv) "${FXDIV_SOURCE_DIR}" "${CMAKE_BINARY_DIR}/FXdiv") ELSE() diff --git a/cmake/vcpkg-ports/xnnpack/portfile.cmake b/cmake/vcpkg-ports/xnnpack/portfile.cmake index b07da3186b4b4..60b3566629e10 100644 --- a/cmake/vcpkg-ports/xnnpack/portfile.cmake +++ b/cmake/vcpkg-ports/xnnpack/portfile.cmake @@ -5,18 +5,18 @@ endif() vcpkg_from_github( OUT_SOURCE_PATH SOURCE_PATH REPO google/XNNPACK - REF 854b343f9cad36bd596e4390959ca3648208e048 - SHA512 f37384b43022cb74bf87bd99c2e82e51d48fe4e0e4642611fcbc10cbb86ff2468b67964027f13f82a715dc7201c490d88d5020fb565ad236187b9dd219f3f644 + REF 3cf85e705098622d59056dcb8f5f963ea7bb0a00 + SHA512 af10afde80def08dc3b20a35bd38e84f9f749865ecc4bc9733b5d99d8a2f0f30c19c3f23472d65462a907b3a58226e3b254354a92a6baa31031824f68012a055 HEAD_REF master PATCHES fix-build.patch - disable_gcc_warning.patch + disable_gcc_warning.patch ) vcpkg_find_acquire_program(PYTHON3) vcpkg_cmake_configure( SOURCE_PATH "${SOURCE_PATH}" - WINDOWS_USE_MSBUILD + WINDOWS_USE_MSBUILD OPTIONS "-DPython3_EXECUTABLE=${PYTHON3}" "-DPython_EXECUTABLE=${PYTHON3}" diff --git a/cmake/vcpkg-ports/xnnpack/vcpkg.json b/cmake/vcpkg-ports/xnnpack/vcpkg.json index 5e383c0b37810..643b5c4abe166 100644 --- a/cmake/vcpkg-ports/xnnpack/vcpkg.json +++ b/cmake/vcpkg-ports/xnnpack/vcpkg.json @@ -1,10 +1,9 @@ { "name": "xnnpack", - "version-date": "2025-01-17", + "version-date": "2025-06-22", "description": "High-efficiency floating-point neural network inference operators for mobile, server, and Web", "homepage": "https://github.com/google/XNNPACK", "license": "BSD-3-Clause", - "supports": "!(arm & windows) & !uwp & !arm32", "dependencies": [ "cpuinfo", "fxdiv", diff --git a/cmake/vcpkg-triplets/asan/arm64-linux.cmake b/cmake/vcpkg-triplets/asan/arm64-linux.cmake deleted file mode 100644 index 9f5c9997daedb..0000000000000 --- a/cmake/vcpkg-triplets/asan/arm64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -fsanitize=address") -set(VCPKG_CXX_FLAGS "-g -fsanitize=address") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-fsanitize=address -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/arm64-osx.cmake b/cmake/vcpkg-triplets/asan/arm64-osx.cmake deleted file mode 100644 index ba56684949836..0000000000000 --- a/cmake/vcpkg-triplets/asan/arm64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -fsanitize=address") -set(VCPKG_CXX_FLAGS "-g -fsanitize=address") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-fsanitize=address -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/arm64-windows-static-md.cmake b/cmake/vcpkg-triplets/asan/arm64-windows-static-md.cmake deleted file mode 100644 index 79e10ad9e4436..0000000000000 --- a/cmake/vcpkg-triplets/asan/arm64-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/arm64-windows-static.cmake b/cmake/vcpkg-triplets/asan/arm64-windows-static.cmake deleted file mode 100644 index d0a3305b1f74a..0000000000000 --- a/cmake/vcpkg-triplets/asan/arm64-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/arm64ec-windows-static-md.cmake b/cmake/vcpkg-triplets/asan/arm64ec-windows-static-md.cmake deleted file mode 100644 index 05a9718835ffb..0000000000000 --- a/cmake/vcpkg-triplets/asan/arm64ec-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/arm64ec-windows-static.cmake b/cmake/vcpkg-triplets/asan/arm64ec-windows-static.cmake deleted file mode 100644 index e0f4b2e1e4183..0000000000000 --- a/cmake/vcpkg-triplets/asan/arm64ec-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/universal2-osx.cmake b/cmake/vcpkg-triplets/asan/universal2-osx.cmake deleted file mode 100644 index d74494d578cd9..0000000000000 --- a/cmake/vcpkg-triplets/asan/universal2-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -fsanitize=address") -set(VCPKG_CXX_FLAGS "-g -fsanitize=address") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64;arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-fsanitize=address -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/x64-linux.cmake b/cmake/vcpkg-triplets/asan/x64-linux.cmake deleted file mode 100644 index 64ba6b2216394..0000000000000 --- a/cmake/vcpkg-triplets/asan/x64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -fsanitize=address") -set(VCPKG_CXX_FLAGS "-g -fsanitize=address") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-fsanitize=address -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/x64-osx.cmake b/cmake/vcpkg-triplets/asan/x64-osx.cmake deleted file mode 100644 index bbcaff4c39209..0000000000000 --- a/cmake/vcpkg-triplets/asan/x64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -fsanitize=address") -set(VCPKG_CXX_FLAGS "-g -fsanitize=address") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-fsanitize=address -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/x64-windows-static-md.cmake b/cmake/vcpkg-triplets/asan/x64-windows-static-md.cmake deleted file mode 100644 index c0edb9ca31cb6..0000000000000 --- a/cmake/vcpkg-triplets/asan/x64-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/x64-windows-static.cmake b/cmake/vcpkg-triplets/asan/x64-windows-static.cmake deleted file mode 100644 index 3370987c55a12..0000000000000 --- a/cmake/vcpkg-triplets/asan/x64-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/x86-windows-static-md.cmake b/cmake/vcpkg-triplets/asan/x86-windows-static-md.cmake deleted file mode 100644 index 429a4ac7cea36..0000000000000 --- a/cmake/vcpkg-triplets/asan/x86-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan/x86-windows-static.cmake b/cmake/vcpkg-triplets/asan/x86-windows-static.cmake deleted file mode 100644 index 404cb3fbd07fb..0000000000000 --- a/cmake/vcpkg-triplets/asan/x86-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/arm64-linux.cmake b/cmake/vcpkg-triplets/asan_nortti/arm64-linux.cmake deleted file mode 100644 index 3d78741ebcf1d..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/arm64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -fsanitize=address -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -fsanitize=address -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-fsanitize=address -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/arm64-osx.cmake b/cmake/vcpkg-triplets/asan_nortti/arm64-osx.cmake deleted file mode 100644 index b25f8f8ebb8d1..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/arm64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -fsanitize=address -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -fsanitize=address -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-fsanitize=address -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/arm64-windows-static-md.cmake b/cmake/vcpkg-triplets/asan_nortti/arm64-windows-static-md.cmake deleted file mode 100644 index c4ba82b7cac2a..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/arm64-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/arm64-windows-static.cmake b/cmake/vcpkg-triplets/asan_nortti/arm64-windows-static.cmake deleted file mode 100644 index 3b028c4e40bcc..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/arm64-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/arm64ec-windows-static-md.cmake b/cmake/vcpkg-triplets/asan_nortti/arm64ec-windows-static-md.cmake deleted file mode 100644 index d2d4bda334e38..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/arm64ec-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/arm64ec-windows-static.cmake b/cmake/vcpkg-triplets/asan_nortti/arm64ec-windows-static.cmake deleted file mode 100644 index 8e986eb139862..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/arm64ec-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/universal2-osx.cmake b/cmake/vcpkg-triplets/asan_nortti/universal2-osx.cmake deleted file mode 100644 index 6181e6d1c161b..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/universal2-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -fsanitize=address -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -fsanitize=address -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64;arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-fsanitize=address -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/x64-linux.cmake b/cmake/vcpkg-triplets/asan_nortti/x64-linux.cmake deleted file mode 100644 index d7103ff2508bf..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/x64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -fsanitize=address -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -fsanitize=address -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-fsanitize=address -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/x64-osx.cmake b/cmake/vcpkg-triplets/asan_nortti/x64-osx.cmake deleted file mode 100644 index 191dfb3d35d10..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/x64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -fsanitize=address -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -fsanitize=address -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-fsanitize=address -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/x64-windows-static-md.cmake b/cmake/vcpkg-triplets/asan_nortti/x64-windows-static-md.cmake deleted file mode 100644 index ae3f00b851145..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/x64-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/x64-windows-static.cmake b/cmake/vcpkg-triplets/asan_nortti/x64-windows-static.cmake deleted file mode 100644 index d64f20d3ce7f6..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/x64-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/x86-windows-static-md.cmake b/cmake/vcpkg-triplets/asan_nortti/x86-windows-static-md.cmake deleted file mode 100644 index 24ddfa43c0f59..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/x86-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/asan_nortti/x86-windows-static.cmake b/cmake/vcpkg-triplets/asan_nortti/x86-windows-static.cmake deleted file mode 100644 index 53fcb44313c26..0000000000000 --- a/cmake/vcpkg-triplets/asan_nortti/x86-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /fsanitize=address /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/arm64-linux.cmake b/cmake/vcpkg-triplets/binskim/arm64-linux.cmake deleted file mode 100644 index 8a3cf645d7f5f..0000000000000 --- a/cmake/vcpkg-triplets/binskim/arm64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g") -set(VCPKG_CXX_FLAGS "-g") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/arm64-osx.cmake b/cmake/vcpkg-triplets/binskim/arm64-osx.cmake deleted file mode 100644 index 9892a3eac80e8..0000000000000 --- a/cmake/vcpkg-triplets/binskim/arm64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g") -set(VCPKG_CXX_FLAGS "-g") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/arm64-windows-static-md.cmake b/cmake/vcpkg-triplets/binskim/arm64-windows-static-md.cmake deleted file mode 100644 index 3818356b5c0ce..0000000000000 --- a/cmake/vcpkg-triplets/binskim/arm64-windows-static-md.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/arm64-windows-static.cmake b/cmake/vcpkg-triplets/binskim/arm64-windows-static.cmake deleted file mode 100644 index ab38e9f9a9f18..0000000000000 --- a/cmake/vcpkg-triplets/binskim/arm64-windows-static.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/arm64ec-windows-static-md.cmake b/cmake/vcpkg-triplets/binskim/arm64ec-windows-static-md.cmake deleted file mode 100644 index 6937aea847a8a..0000000000000 --- a/cmake/vcpkg-triplets/binskim/arm64ec-windows-static-md.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/arm64ec-windows-static.cmake b/cmake/vcpkg-triplets/binskim/arm64ec-windows-static.cmake deleted file mode 100644 index 84c0531033699..0000000000000 --- a/cmake/vcpkg-triplets/binskim/arm64ec-windows-static.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/universal2-osx.cmake b/cmake/vcpkg-triplets/binskim/universal2-osx.cmake deleted file mode 100644 index da4c6abb39000..0000000000000 --- a/cmake/vcpkg-triplets/binskim/universal2-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g") -set(VCPKG_CXX_FLAGS "-g") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64;arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/x64-linux.cmake b/cmake/vcpkg-triplets/binskim/x64-linux.cmake deleted file mode 100644 index e3d4d34326409..0000000000000 --- a/cmake/vcpkg-triplets/binskim/x64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g") -set(VCPKG_CXX_FLAGS "-g") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -fstack-clash-protection -fcf-protection") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -fstack-clash-protection -fcf-protection") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/x64-osx.cmake b/cmake/vcpkg-triplets/binskim/x64-osx.cmake deleted file mode 100644 index 426a35e33f747..0000000000000 --- a/cmake/vcpkg-triplets/binskim/x64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g") -set(VCPKG_CXX_FLAGS "-g") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -fstack-clash-protection -fcf-protection") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -fstack-clash-protection -fcf-protection") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/x64-windows-static-md.cmake b/cmake/vcpkg-triplets/binskim/x64-windows-static-md.cmake deleted file mode 100644 index 0f600d7931076..0000000000000 --- a/cmake/vcpkg-triplets/binskim/x64-windows-static-md.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/x64-windows-static.cmake b/cmake/vcpkg-triplets/binskim/x64-windows-static.cmake deleted file mode 100644 index 17d41775c9d06..0000000000000 --- a/cmake/vcpkg-triplets/binskim/x64-windows-static.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/x86-windows-static-md.cmake b/cmake/vcpkg-triplets/binskim/x86-windows-static-md.cmake deleted file mode 100644 index cb981c264a2f1..0000000000000 --- a/cmake/vcpkg-triplets/binskim/x86-windows-static-md.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim/x86-windows-static.cmake b/cmake/vcpkg-triplets/binskim/x86-windows-static.cmake deleted file mode 100644 index 53342263d5ada..0000000000000 --- a/cmake/vcpkg-triplets/binskim/x86-windows-static.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/arm64-linux.cmake b/cmake/vcpkg-triplets/binskim_nortti/arm64-linux.cmake deleted file mode 100644 index 203c85fa3a59e..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/arm64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/arm64-osx.cmake b/cmake/vcpkg-triplets/binskim_nortti/arm64-osx.cmake deleted file mode 100644 index c57a2401e4c0f..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/arm64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/arm64-windows-static-md.cmake b/cmake/vcpkg-triplets/binskim_nortti/arm64-windows-static-md.cmake deleted file mode 100644 index 9963cfb66f4b1..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/arm64-windows-static-md.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/arm64-windows-static.cmake b/cmake/vcpkg-triplets/binskim_nortti/arm64-windows-static.cmake deleted file mode 100644 index 0f4948ff076f1..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/arm64-windows-static.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/arm64ec-windows-static-md.cmake b/cmake/vcpkg-triplets/binskim_nortti/arm64ec-windows-static-md.cmake deleted file mode 100644 index 6a5c8b9f1058a..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/arm64ec-windows-static-md.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/arm64ec-windows-static.cmake b/cmake/vcpkg-triplets/binskim_nortti/arm64ec-windows-static.cmake deleted file mode 100644 index 668d4fb4dc420..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/arm64ec-windows-static.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/universal2-osx.cmake b/cmake/vcpkg-triplets/binskim_nortti/universal2-osx.cmake deleted file mode 100644 index 1956daf30e6d9..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/universal2-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64;arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/x64-linux.cmake b/cmake/vcpkg-triplets/binskim_nortti/x64-linux.cmake deleted file mode 100644 index da17e0073980f..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/x64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -fstack-clash-protection -fcf-protection") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -fstack-clash-protection -fcf-protection") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now -Wl,-z,noexecstack -g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/x64-osx.cmake b/cmake/vcpkg-triplets/binskim_nortti/x64-osx.cmake deleted file mode 100644 index c74e60bc7c206..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/x64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -fstack-clash-protection -fcf-protection") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3 -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fstack-protector-strong -fstack-clash-protection -fcf-protection") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/x64-windows-static-md.cmake b/cmake/vcpkg-triplets/binskim_nortti/x64-windows-static-md.cmake deleted file mode 100644 index 6491d31ae469b..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/x64-windows-static-md.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/x64-windows-static.cmake b/cmake/vcpkg-triplets/binskim_nortti/x64-windows-static.cmake deleted file mode 100644 index 011999df2ac99..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/x64-windows-static.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/x86-windows-static-md.cmake b/cmake/vcpkg-triplets/binskim_nortti/x86-windows-static-md.cmake deleted file mode 100644 index bf843c3e950e2..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/x86-windows-static-md.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/binskim_nortti/x86-windows-static.cmake b/cmake/vcpkg-triplets/binskim_nortti/x86-windows-static.cmake deleted file mode 100644 index 21e0858066ab8..0000000000000 --- a/cmake/vcpkg-triplets/binskim_nortti/x86-windows-static.cmake +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /guard:cf /Qspectre /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -set(VCPKG_LINKER_FLAGS "/profile /DYNAMICBASE") -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/arm64-linux.cmake b/cmake/vcpkg-triplets/default/arm64-linux.cmake deleted file mode 100644 index 120865a5b0b57..0000000000000 --- a/cmake/vcpkg-triplets/default/arm64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g") -set(VCPKG_CXX_FLAGS "-g") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/arm64-osx.cmake b/cmake/vcpkg-triplets/default/arm64-osx.cmake deleted file mode 100644 index 02e8a3430475f..0000000000000 --- a/cmake/vcpkg-triplets/default/arm64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g") -set(VCPKG_CXX_FLAGS "-g") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/arm64-windows-static-md.cmake b/cmake/vcpkg-triplets/default/arm64-windows-static-md.cmake deleted file mode 100644 index 6d5cf67665f4f..0000000000000 --- a/cmake/vcpkg-triplets/default/arm64-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/arm64-windows-static.cmake b/cmake/vcpkg-triplets/default/arm64-windows-static.cmake deleted file mode 100644 index 19ca6f16cd890..0000000000000 --- a/cmake/vcpkg-triplets/default/arm64-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/arm64ec-windows-static-md.cmake b/cmake/vcpkg-triplets/default/arm64ec-windows-static-md.cmake deleted file mode 100644 index d7982158f390c..0000000000000 --- a/cmake/vcpkg-triplets/default/arm64ec-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/arm64ec-windows-static.cmake b/cmake/vcpkg-triplets/default/arm64ec-windows-static.cmake deleted file mode 100644 index fb14ad71c1d91..0000000000000 --- a/cmake/vcpkg-triplets/default/arm64ec-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/universal2-osx.cmake b/cmake/vcpkg-triplets/default/universal2-osx.cmake deleted file mode 100644 index 57386c423cf99..0000000000000 --- a/cmake/vcpkg-triplets/default/universal2-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g") -set(VCPKG_CXX_FLAGS "-g") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64;arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/x64-linux.cmake b/cmake/vcpkg-triplets/default/x64-linux.cmake deleted file mode 100644 index 30c7b1b786302..0000000000000 --- a/cmake/vcpkg-triplets/default/x64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g") -set(VCPKG_CXX_FLAGS "-g") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/x64-osx.cmake b/cmake/vcpkg-triplets/default/x64-osx.cmake deleted file mode 100644 index 7af622e1354b9..0000000000000 --- a/cmake/vcpkg-triplets/default/x64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g") -set(VCPKG_CXX_FLAGS "-g") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/x64-windows-static-md.cmake b/cmake/vcpkg-triplets/default/x64-windows-static-md.cmake deleted file mode 100644 index bec5f2724da13..0000000000000 --- a/cmake/vcpkg-triplets/default/x64-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/x64-windows-static.cmake b/cmake/vcpkg-triplets/default/x64-windows-static.cmake deleted file mode 100644 index 3f62418071583..0000000000000 --- a/cmake/vcpkg-triplets/default/x64-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/x86-windows-static-md.cmake b/cmake/vcpkg-triplets/default/x86-windows-static-md.cmake deleted file mode 100644 index d93d87b3289f3..0000000000000 --- a/cmake/vcpkg-triplets/default/x86-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/default/x86-windows-static.cmake b/cmake/vcpkg-triplets/default/x86-windows-static.cmake deleted file mode 100644 index 727b35cd1f7cc..0000000000000 --- a/cmake/vcpkg-triplets/default/x86-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/gen.py b/cmake/vcpkg-triplets/gen.py deleted file mode 100644 index bec1a87a0a20e..0000000000000 --- a/cmake/vcpkg-triplets/gen.py +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/python3 - -import os - - -# provide build options for vcpkg installed packages -def add_port_configs(f): - f.write( - r"""if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() -""" - ) - - -# provide build options for vcpkg installed packages -def add_copyright_header(f): - f.write( - r"""# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -""" - ) - - -# Gen Windows triplets -target_abis = ["x86", "x64", "arm64", "arm64ec"] -crt_linkages = ["static", "dynamic"] -for enable_rtti in [True, False]: - for enable_binskim in [True, False]: - for enable_asan in [True, False]: - for crt_linkage in crt_linkages: - # Address Sanitizer libs do not have a Qspectre version. So they two cannot be both enabled. - if enable_asan and enable_binskim: - continue - for target_abi in target_abis: - folder_name_parts = [] - if enable_asan: - folder_name_parts.append("asan") - if enable_binskim: - folder_name_parts.append("binskim") - if not enable_rtti: - folder_name_parts.append("nortti") - if len(folder_name_parts) == 0: - folder_name = "default" - else: - folder_name = "_".join(folder_name_parts) - file_name_parts = [target_abi, "windows", "static"] - if crt_linkage == "dynamic": - file_name_parts.append("md") - file_name = "-".join(file_name_parts) + ".cmake" - dest_path = os.path.join(folder_name, file_name) - print(f"Creating file {dest_path}") - os.makedirs(folder_name, exist_ok=True) - with open(dest_path, "w", encoding="utf-8") as f: - add_copyright_header(f) - f.write(f"set(VCPKG_TARGET_ARCHITECTURE {target_abi})\n") - f.write(f"set(VCPKG_CRT_LINKAGE {crt_linkage})\n") - # we only support static. The default triplets use dynamic. - # The default triplets do not work with asan(protoc.exe crashes at startup). Therefore we do not override the default triplets and do not append asan to them. - # The default triplets are used for generating host dependencies(such as protoc.exe) - f.write("set(VCPKG_LIBRARY_LINKAGE static)\n") - cflags = ["/MP", "/DWIN32", "/D_WINDOWS"] - # TODO: if not gdk - cflags += [ - "/DWINAPI_FAMILY=100", - "/DWINVER=0x0A00", - "/D_WIN32_WINNT=0x0A00", - "/DNTDDI_VERSION=0x0A000000", - ] - cxxflags = None - ldflags = None - cflags += [] - if enable_binskim: - cflags += ["/guard:cf", "/Qspectre"] - ldflags = ["/profile", "/DYNAMICBASE"] - elif enable_asan: - cflags.append("/fsanitize=address") - cxxflags = cflags.copy() - cxxflags.append("/Zc:__cplusplus") - if not enable_rtti: - # Disable RTTI and turn usage of dynamic_cast and typeid into errors - cxxflags += ["/GR-", "/we4541"] - # TODO: should it be a cmake list separated by semicolons? - if len(cflags) >= 1: - f.write('set(VCPKG_C_FLAGS "{}")\n'.format(" ".join(cflags))) - if len(cxxflags) >= 1: - f.write('set(VCPKG_CXX_FLAGS "{}")\n'.format(" ".join(cxxflags))) - f.write("list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17)\n") - if ldflags: - f.write('set(VCPKG_LINKER_FLAGS "{}")\n'.format(" ".join(ldflags))) - add_port_configs(f) - - -# Gen Linux triplets -crt_linkages = ["static", "dynamic"] -for os_name in ["linux", "osx"]: - if os_name == "linux": - target_abis = ["x64", "arm64"] - else: - target_abis = ["x64", "arm64", "universal2"] - for enable_rtti in [True, False]: - for enable_binskim in [True, False]: - for enable_asan in [True, False]: - for crt_linkage in crt_linkages: - if enable_asan and enable_binskim: - continue - for target_abi in target_abis: - folder_name_parts = [] - if enable_asan: - folder_name_parts.append("asan") - if enable_binskim: - folder_name_parts.append("binskim") - if not enable_rtti: - folder_name_parts.append("nortti") - if len(folder_name_parts) == 0: - folder_name = "default" - else: - folder_name = "_".join(folder_name_parts) - file_name_parts = [target_abi, os_name] - file_name = "-".join(file_name_parts) + ".cmake" - dest_path = os.path.join(folder_name, file_name) - print(f"Creating file {dest_path}") - os.makedirs(folder_name, exist_ok=True) - with open(dest_path, "w", encoding="utf-8") as f: - add_copyright_header(f) - if target_abi == "universal2": - # Assume the host machine is Intel based - f.write("set(VCPKG_TARGET_ARCHITECTURE x64)\n") - else: - f.write(f"set(VCPKG_TARGET_ARCHITECTURE {target_abi})\n") - f.write(f"set(VCPKG_CRT_LINKAGE {crt_linkage})\n") - f.write("set(VCPKG_LIBRARY_LINKAGE static)\n") - - - if enable_binskim and os_name == "linux": - ldflags = [ - "-Wl,-Bsymbolic-functions", - "-Wl,-z,relro", - "-Wl,-z,now", - "-Wl,-z,noexecstack" - ] - else: - ldflags = [] - # Enable debug info for all build configs - cflags = ["-g"] - cflags_release = ["-DNDEBUG", "-O3"] - if enable_binskim: - # A warning may be generated from include/features.h if the _FORTIFY_SOURCE flag was used in a debug build - cflags_release += [ - "-Wp,-D_FORTIFY_SOURCE=2", - "-Wp,-D_GLIBCXX_ASSERTIONS", - "-fstack-protector-strong", - ] - if target_abi == "x64": - cflags_release += ["-fstack-clash-protection", "-fcf-protection"] - elif enable_asan: - cflags += ["-fsanitize=address"] - ldflags += ["-fsanitize=address"] - # Enable debug info for all build configs - ldflags.append('-g') - # Avoid unboundTypeError for WebNN EP since unbound type names are illegal with RTTI disabled - # in Embind API, relevant issue: https://github.com/emscripten-core/emscripten/issues/7001 - if not enable_rtti: - cflags.append("-DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") - cxxflags = cflags.copy() - if not enable_rtti: - cxxflags.append("-fno-rtti") - if len(cflags) >= 1: - f.write('set(VCPKG_C_FLAGS "{}")\n'.format(" ".join(cflags))) - if len(cxxflags) >= 1: - f.write('set(VCPKG_CXX_FLAGS "{}")\n'.format(" ".join(cxxflags))) - if len(cflags_release) >= 1: - f.write('set(VCPKG_C_FLAGS_RELEASE "{}")\n'.format(" ".join(cflags_release))) - f.write('set(VCPKG_CXX_FLAGS_RELEASE "{}")\n'.format(" ".join(cflags_release))) - if os_name == "linux": - f.write("set(VCPKG_CMAKE_SYSTEM_NAME Linux)\n") - else: - f.write("set(VCPKG_CMAKE_SYSTEM_NAME Darwin)\n") - osx_abi = None - if target_abi == "x64": - osx_abi = "x86_64" - elif target_abi == "universal2": - osx_abi = "x86_64;arm64" - else: - osx_abi = target_abi - f.write(f'set(VCPKG_OSX_ARCHITECTURES "{osx_abi}")\n') - f.write("set(CMAKE_POSITION_INDEPENDENT_CODE ON)\n") - f.write( - "list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF)\n" - ) - - if ldflags: - f.write('set(VCPKG_LINKER_FLAGS "{}")\n'.format(" ".join(ldflags))) - if os_name == 'osx': - f.write('list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20)\n') - else: - f.write('list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17)\n') - add_port_configs(f) diff --git a/cmake/vcpkg-triplets/nortti/arm64-linux.cmake b/cmake/vcpkg-triplets/nortti/arm64-linux.cmake deleted file mode 100644 index f9035fc299ce5..0000000000000 --- a/cmake/vcpkg-triplets/nortti/arm64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/arm64-osx.cmake b/cmake/vcpkg-triplets/nortti/arm64-osx.cmake deleted file mode 100644 index d8971e8122f9d..0000000000000 --- a/cmake/vcpkg-triplets/nortti/arm64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/arm64-windows-static-md.cmake b/cmake/vcpkg-triplets/nortti/arm64-windows-static-md.cmake deleted file mode 100644 index 9d3c86ce644d0..0000000000000 --- a/cmake/vcpkg-triplets/nortti/arm64-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/arm64-windows-static.cmake b/cmake/vcpkg-triplets/nortti/arm64-windows-static.cmake deleted file mode 100644 index 238f7405ec492..0000000000000 --- a/cmake/vcpkg-triplets/nortti/arm64-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/arm64ec-windows-static-md.cmake b/cmake/vcpkg-triplets/nortti/arm64ec-windows-static-md.cmake deleted file mode 100644 index da314824ca7cc..0000000000000 --- a/cmake/vcpkg-triplets/nortti/arm64ec-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/arm64ec-windows-static.cmake b/cmake/vcpkg-triplets/nortti/arm64ec-windows-static.cmake deleted file mode 100644 index 0c7fb60401f1d..0000000000000 --- a/cmake/vcpkg-triplets/nortti/arm64ec-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE arm64ec) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/universal2-osx.cmake b/cmake/vcpkg-triplets/nortti/universal2-osx.cmake deleted file mode 100644 index febc002c0488e..0000000000000 --- a/cmake/vcpkg-triplets/nortti/universal2-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64;arm64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/x64-linux.cmake b/cmake/vcpkg-triplets/nortti/x64-linux.cmake deleted file mode 100644 index c1dac19d33f2c..0000000000000 --- a/cmake/vcpkg-triplets/nortti/x64-linux.cmake +++ /dev/null @@ -1,24 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Linux) -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/x64-osx.cmake b/cmake/vcpkg-triplets/nortti/x64-osx.cmake deleted file mode 100644 index 242d34a358170..0000000000000 --- a/cmake/vcpkg-triplets/nortti/x64-osx.cmake +++ /dev/null @@ -1,25 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0") -set(VCPKG_CXX_FLAGS "-g -DEMSCRIPTEN_HAS_UNBOUND_TYPE_NAMES=0 -fno-rtti") -set(VCPKG_C_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CXX_FLAGS_RELEASE "-DNDEBUG -O3") -set(VCPKG_CMAKE_SYSTEM_NAME Darwin) -set(VCPKG_OSX_ARCHITECTURES "x86_64") -set(CMAKE_POSITION_INDEPENDENT_CODE ON) -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DBENCHMARK_ENABLE_WERROR=OFF) -set(VCPKG_LINKER_FLAGS "-g") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS -DCMAKE_CXX_STANDARD=20) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/x64-windows-static-md.cmake b/cmake/vcpkg-triplets/nortti/x64-windows-static-md.cmake deleted file mode 100644 index a8d2441583d0f..0000000000000 --- a/cmake/vcpkg-triplets/nortti/x64-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/x64-windows-static.cmake b/cmake/vcpkg-triplets/nortti/x64-windows-static.cmake deleted file mode 100644 index 688ed230fd17c..0000000000000 --- a/cmake/vcpkg-triplets/nortti/x64-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x64) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/x86-windows-static-md.cmake b/cmake/vcpkg-triplets/nortti/x86-windows-static-md.cmake deleted file mode 100644 index 1d3de9c1420c4..0000000000000 --- a/cmake/vcpkg-triplets/nortti/x86-windows-static-md.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE dynamic) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg-triplets/nortti/x86-windows-static.cmake b/cmake/vcpkg-triplets/nortti/x86-windows-static.cmake deleted file mode 100644 index 3a856c26797a4..0000000000000 --- a/cmake/vcpkg-triplets/nortti/x86-windows-static.cmake +++ /dev/null @@ -1,18 +0,0 @@ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -set(VCPKG_TARGET_ARCHITECTURE x86) -set(VCPKG_CRT_LINKAGE static) -set(VCPKG_LIBRARY_LINKAGE static) -set(VCPKG_C_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000") -set(VCPKG_CXX_FLAGS "/MP /DWIN32 /D_WINDOWS /DWINAPI_FAMILY=100 /DWINVER=0x0A00 /D_WIN32_WINNT=0x0A00 /DNTDDI_VERSION=0x0A000000 /Zc:__cplusplus /GR- /we4541") -list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS --compile-no-warning-as-error -DCMAKE_CXX_STANDARD=17) -if(PORT MATCHES "onnx") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DONNX_DISABLE_STATIC_REGISTRATION=ON" - ) -endif() -if(PORT MATCHES "benchmark") - list(APPEND VCPKG_CMAKE_CONFIGURE_OPTIONS - "-DBENCHMARK_ENABLE_WERROR=OFF" - ) -endif() diff --git a/cmake/vcpkg.json b/cmake/vcpkg.json index e260699c1ad12..373ecec440921 100644 --- a/cmake/vcpkg.json +++ b/cmake/vcpkg.json @@ -7,6 +7,10 @@ "license": "MIT", "dependencies": [ "abseil", + { + "name": "benchmark", + "platform": "!android" + }, { "name": "boost-config", "version>=": "1.82.0" @@ -15,10 +19,14 @@ "name": "boost-mp11", "version>=": "1.82.0" }, - "cpuinfo", + { + "name": "cpuinfo", + "platform": "!osx" + }, "cxxopts", "date", "dlpack", + "eigen3", { "name": "flatbuffers", "host": true, @@ -28,13 +36,13 @@ "name": "flatbuffers", "version>=": "23.5.26" }, - "ms-gsl", - "nlohmann-json", { - "name": "onnx", - "version>=": "1.17.0" + "name": "mimalloc", + "platform": "windows" }, - "optional-lite", + "ms-gsl", + "nlohmann-json", + "onnx", { "name": "protobuf", "version>=": "3.21.12" @@ -44,6 +52,7 @@ "host": true, "version>=": "3.21.12" }, + "pybind11", "re2", "safeint", "utf8-range", @@ -55,7 +64,10 @@ "name": "vcpkg-cmake-config", "host": true }, - "wil", + { + "name": "wil", + "platform": "windows" + }, { "name": "zlib", "platform": "windows" @@ -64,10 +76,27 @@ "features": { "tests": { "description": "Build ONNXRuntime unit tests", - "dependencies": [ - "benchmark", - "gtest" - ] + "dependencies": ["gtest"] + }, + "xnnpack-ep": { + "description": "Build with XNNPack EP", + "dependencies": ["xnnpack"] + }, + "coreml-ep": { + "description": "Build with CoreML EP", + "dependencies": ["fp16"] + }, + "dml-ep": { + "description": "Build with DirectML EP", + "dependencies": ["directx-headers"] + }, + "webgpu-ep": { + "description": "Build with WebGPU EP", + "dependencies": [] + }, + "webgpu-ep-wgsl-template-dynamic": { + "description": "Build with WebGPU EP with dynamic WGSL template code generator", + "dependencies": ["duktape"] } }, "overrides": [ @@ -77,7 +106,11 @@ }, { "name": "flatbuffers", - "version": "23.5.26#1" + "version": "23.5.26" + }, + { + "name": "duktape", + "version": "2.7.0#2" } ] } diff --git a/cmake/winml.cmake b/cmake/winml.cmake index 63f356fcf831d..8f80299cc491c 100644 --- a/cmake/winml.cmake +++ b/cmake/winml.cmake @@ -316,13 +316,12 @@ if (onnxruntime_WINML_NAMESPACE_OVERRIDE STREQUAL "Windows") target_compile_definitions(winml_adapter PRIVATE "BUILD_INBOX=1") endif() -# wil requires C++17 -set_target_properties(winml_adapter PROPERTIES CXX_STANDARD 17) +set_target_properties(winml_adapter PROPERTIES CXX_STANDARD 20) set_target_properties(winml_adapter PROPERTIES CXX_STANDARD_REQUIRED ON) # Compiler definitions -onnxruntime_add_include_to_target(winml_adapter onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers safeint_interface Boost::mp11) -target_include_directories(winml_adapter PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS}) +onnxruntime_add_include_to_target(winml_adapter onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers safeint_interface Boost::mp11 Eigen3::Eigen) +target_include_directories(winml_adapter PRIVATE ${ONNXRUNTIME_ROOT}) add_dependencies(winml_adapter ${onnxruntime_EXTERNAL_DEPENDENCIES}) # Specify the usage of a precompiled header @@ -516,8 +515,7 @@ target_include_directories(winml_lib_api PRIVATE ${ONNXRUNTIME_INCLUDE_DIR}/core target_include_directories(winml_lib_api PRIVATE ${ONNXRUNTIME_ROOT}) target_include_directories(winml_lib_api PRIVATE ${ONNXRUNTIME_ROOT}/core/graph) target_include_directories(winml_lib_api PRIVATE ${REPO_ROOT}/winml) -target_include_directories(winml_lib_api PRIVATE ${eigen_INCLUDE_DIRS}) -target_link_libraries(winml_lib_api PRIVATE ${GSL_TARGET} safeint_interface flatbuffers::flatbuffers Boost::mp11 onnx onnx_proto) +target_link_libraries(winml_lib_api PRIVATE ${GSL_TARGET} safeint_interface flatbuffers::flatbuffers Boost::mp11 onnx onnx_proto Eigen3::Eigen) # Properties set_target_properties(winml_lib_api @@ -600,11 +598,10 @@ target_include_directories(winml_lib_api_experimental PRIVATE ${CMAKE_CURRENT_BI target_include_directories(winml_lib_api_experimental PRIVATE ${ONNXRUNTIME_INCLUDE_DIR}) target_include_directories(winml_lib_api_experimental PRIVATE ${ONNXRUNTIME_INCLUDE_DIR}/core/graph) +target_include_directories(winml_lib_api_experimental PRIVATE ${REPO_ROOT}/winml) target_include_directories(winml_lib_api_experimental PRIVATE ${ONNXRUNTIME_ROOT}) target_include_directories(winml_lib_api_experimental PRIVATE ${ONNXRUNTIME_ROOT}/core/graph) -target_include_directories(winml_lib_api_experimental PRIVATE ${eigen_INCLUDE_DIRS}) -target_include_directories(winml_lib_api_experimental PRIVATE ${REPO_ROOT}/winml) -onnxruntime_add_include_to_target(winml_lib_api_experimental PRIVATE ${PROTOBUF_LIB} safeint_interface flatbuffers::flatbuffers Boost::mp11 onnx onnx_proto ${GSL_TARGET}) +onnxruntime_add_include_to_target(winml_lib_api_experimental PRIVATE ${PROTOBUF_LIB} safeint_interface flatbuffers::flatbuffers Boost::mp11 onnx onnx_proto ${GSL_TARGET} Eigen3::Eigen) # Properties set_target_properties(winml_lib_api_experimental @@ -647,7 +644,7 @@ onnxruntime_add_static_library(winml_lib_common ${winml_lib_common_dir}/CommonDeviceHelpers.cpp ) -set_target_properties(winml_lib_common PROPERTIES CXX_STANDARD 17) +set_target_properties(winml_lib_common PROPERTIES CXX_STANDARD 20) set_target_properties(winml_lib_common PROPERTIES CXX_STANDARD_REQUIRED ON) target_compile_options(winml_lib_common PRIVATE /GR- /await /bigobj /wd4238) target_link_libraries(winml_lib_common PRIVATE ${WIL_TARGET}) @@ -752,9 +749,8 @@ target_include_directories(winml_dll PRIVATE ${ONNXRUNTIME_INCLUDE_DIR}/core/gra target_include_directories(winml_dll PRIVATE ${ONNXRUNTIME_ROOT}) target_include_directories(winml_dll PRIVATE ${ONNXRUNTIME_ROOT}/core/graph) -target_include_directories(winml_dll PRIVATE ${eigen_INCLUDE_DIRS}) target_include_directories(winml_dll PRIVATE ${REPO_ROOT}/winml) -target_link_libraries(winml_dll PRIVATE onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers safeint_interface Boost::mp11 ${GSL_TARGET}) +target_link_libraries(winml_dll PRIVATE onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers safeint_interface Boost::mp11 ${GSL_TARGET} Eigen3::Eigen) target_link_libraries(winml_dll PRIVATE debug Dbghelp) # Properties set_target_properties(winml_dll @@ -832,9 +828,9 @@ if (winml_is_inbox) target_link_libraries(${new_target} PRIVATE ${link_libraries}) target_link_options(${new_target} PRIVATE ${link_options}) - # Attempt to copy linker flags + # Attempt to copy linker flags get_target_property(link_flags ${target} LINK_FLAGS) - + if (NOT link_flags MATCHES ".*NOTFOUND") set_property(TARGET ${new_target} PROPERTY LINK_FLAGS "${link_flags}") endif() diff --git a/cmake/winml_sdk_helpers.cmake b/cmake/winml_sdk_helpers.cmake index 9241fcd060caf..ca657311b7f14 100644 --- a/cmake/winml_sdk_helpers.cmake +++ b/cmake/winml_sdk_helpers.cmake @@ -1,7 +1,7 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -cmake_minimum_required(VERSION 3.0) +cmake_minimum_required(VERSION 3.5) # utility function(convert_forward_slashes_to_back input output) diff --git a/cmake/winml_unittests.cmake b/cmake/winml_unittests.cmake index 68acac584f2c0..eb2d69e16223e 100644 --- a/cmake/winml_unittests.cmake +++ b/cmake/winml_unittests.cmake @@ -19,7 +19,7 @@ set(WINML_TEST_INC_DIR function(set_winml_target_properties target) set_target_properties(${target} PROPERTIES FOLDER "ONNXRuntimeTest/winml" - CXX_STANDARD 17 + CXX_STANDARD 20 CXX_STANDARD_REQUIRED YES CXX_EXTENSIONS NO ) @@ -254,7 +254,7 @@ get_winml_test_adapter_src(${WINML_TEST_SRC_DIR} winml_test_adapter_src winml_te add_winml_test( TARGET winml_test_adapter SOURCES ${winml_test_adapter_src} - LIBS ${winml_test_adapter_libs} + LIBS ${winml_test_adapter_libs} Eigen3::Eigen ) target_include_directories(winml_test_adapter PRIVATE ${REPO_ROOT}/winml/adapter) target_include_directories(winml_test_adapter PRIVATE ${REPO_ROOT}/winml/lib/Api.Ort) @@ -274,7 +274,6 @@ target_include_directories(winml_test_adapter PRIVATE ${ONNXRUNTIME_INCLUDE_DIR} target_include_directories(winml_test_adapter PRIVATE ${ONNXRUNTIME_ROOT}) onnxruntime_add_include_to_target(winml_test_adapter onnxruntime_common onnxruntime_framework onnx onnx_proto ${PROTOBUF_LIB} flatbuffers::flatbuffers safeint_interface Boost::mp11) -target_include_directories(winml_test_adapter PRIVATE ${ONNXRUNTIME_ROOT} ${eigen_INCLUDE_DIRS}) add_dependencies(winml_test_adapter ${onnxruntime_EXTERNAL_DEPENDENCIES}) target_include_directories(winml_test_adapter PRIVATE ${winml_adapter_dir}) target_include_directories(winml_test_adapter PRIVATE ${winml_lib_common_dir}/inc) diff --git a/csharp/ApiDocs/_exported_templates/default/styles/docfx.css b/csharp/ApiDocs/_exported_templates/default/styles/docfx.css index 64dcde3385eff..0d3cf530038d9 100644 --- a/csharp/ApiDocs/_exported_templates/default/styles/docfx.css +++ b/csharp/ApiDocs/_exported_templates/default/styles/docfx.css @@ -323,6 +323,8 @@ article section { } .docs-search > .search-query:focus { outline: 0; + border: 2px solid #0050C5; + background-color: #f8f9fa; } .search-results-frame { clear: both; @@ -597,6 +599,8 @@ body .toc{ } .toc-filter > input:focus { outline: 0; + border: 2px solid #0050C5; + background-color: #f8f9fa; } .toc-filter > .filter-icon { position: absolute; diff --git a/csharp/ApiDocs/_exported_templates/default/styles/docfx.js b/csharp/ApiDocs/_exported_templates/default/styles/docfx.js index b6167dbd6193d..6412c718be37d 100644 --- a/csharp/ApiDocs/_exported_templates/default/styles/docfx.js +++ b/csharp/ApiDocs/_exported_templates/default/styles/docfx.js @@ -802,6 +802,7 @@ $(function () { } } container.addEventListener('click', function (event) { return handleClick(event, state); }); + container.addEventListener('keydown', function (event) { return handleKeyDown(event, state); }); if (state.groups.length === 0) { return state; } @@ -820,6 +821,7 @@ $(function () { while (li) { var a = li.firstElementChild; a.setAttribute(contentAttrs.name, 'tab'); + a.setAttribute('role', 'tab'); var dataTab = a.getAttribute('data-tab').replace(/\+/g, ' '); a.setAttribute('data-tab', dataTab); var section = element.querySelector("[id=\"" + a.getAttribute('aria-controls') + "\"]"); @@ -915,6 +917,91 @@ $(function () { } } + function handleKeyDown(event, state) { + var info = getTabInfoFromEvent(event); + if (info === null) { + return; + } + + var handled = false; + var tabGroup = info.group; + var currentTabIndex = tabGroup.tabs.findIndex(function(tab) { return tab.a === info.anchor; }); + + switch (event.key) { + case 'ArrowLeft': + case 'ArrowUp': + // Move to previous tab + handled = true; + var prevIndex = currentTabIndex - 1; + if (prevIndex < 0) { + prevIndex = tabGroup.tabs.length - 1; + } + while (prevIndex !== currentTabIndex && !tabGroup.tabs[prevIndex].visible) { + prevIndex--; + if (prevIndex < 0) { + prevIndex = tabGroup.tabs.length - 1; + } + } + if (tabGroup.tabs[prevIndex].visible) { + tabGroup.tabs[prevIndex].focus(); + } + break; + + case 'ArrowRight': + case 'ArrowDown': + // Move to next tab + handled = true; + var nextIndex = currentTabIndex + 1; + if (nextIndex >= tabGroup.tabs.length) { + nextIndex = 0; + } + while (nextIndex !== currentTabIndex && !tabGroup.tabs[nextIndex].visible) { + nextIndex++; + if (nextIndex >= tabGroup.tabs.length) { + nextIndex = 0; + } + } + if (tabGroup.tabs[nextIndex].visible) { + tabGroup.tabs[nextIndex].focus(); + } + break; + + case 'Home': + // Move to first visible tab + handled = true; + for (var i = 0; i < tabGroup.tabs.length; i++) { + if (tabGroup.tabs[i].visible) { + tabGroup.tabs[i].focus(); + break; + } + } + break; + + case 'End': + // Move to last visible tab + handled = true; + for (var i = tabGroup.tabs.length - 1; i >= 0; i--) { + if (tabGroup.tabs[i].visible) { + tabGroup.tabs[i].focus(); + break; + } + } + break; + + case 'Enter': + case ' ': // Space key + // Activate the current tab + handled = true; + handleClick(event, state); + break; + } + + if (handled) { + event.preventDefault(); + event.stopPropagation(); + } + } + function selectTabs(tabIds) { for (var _i = 0, tabIds_1 = tabIds; _i < tabIds_1.length; _i++) { var tabId = tabIds_1[_i]; diff --git a/csharp/ApiDocs/_exported_templates/default/styles/docfx.vendor.css b/csharp/ApiDocs/_exported_templates/default/styles/docfx.vendor.css index 609602eb134dd..0c9f7c0c0aec3 100644 --- a/csharp/ApiDocs/_exported_templates/default/styles/docfx.vendor.css +++ b/csharp/ApiDocs/_exported_templates/default/styles/docfx.vendor.css @@ -1220,7 +1220,7 @@ to{background-position:0 0} .list-group-item.active .list-group-item-text,.list-group-item.active:focus .list-group-item-text,.list-group-item.active:hover .list-group-item-text{color:#c7ddef} a.list-group-item,button.list-group-item{color:#555} a.list-group-item .list-group-item-heading,button.list-group-item .list-group-item-heading{color:#333} -a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#555;text-decoration:none;background-color:#f5f5f5} +a.list-group-item:focus,a.list-group-item:hover,button.list-group-item:focus,button.list-group-item:hover{color:#333;text-decoration:none;background-color:#f5f5f5} button.list-group-item{width:100%;text-align:left} .list-group-item-success{color:#3c763d;background-color:#dff0d8} a.list-group-item-success,button.list-group-item-success{color:#3c763d} @@ -1230,7 +1230,7 @@ a.list-group-item-success.active,a.list-group-item-success.active:focus,a.list-g .list-group-item-info{color:#31708f;background-color:#d9edf7} a.list-group-item-info,button.list-group-item-info{color:#31708f} a.list-group-item-info .list-group-item-heading,button.list-group-item-info .list-group-item-heading{color:inherit} -a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#31708f;background-color:#c4e3f3} +a.list-group-item-info:focus,a.list-group-item-info:hover,button.list-group-item-info:focus,button.list-group-item-info:hover{color:#1e4a5f;background-color:#c4e3f3} a.list-group-item-info.active,a.list-group-item-info.active:focus,a.list-group-item-info.active:hover,button.list-group-item-info.active,button.list-group-item-info.active:focus,button.list-group-item-info.active:hover{color:#fff;background-color:#31708f;border-color:#31708f} .list-group-item-warning{color:#8a6d3b;background-color:#fcf8e3} a.list-group-item-warning,button.list-group-item-warning{color:#8a6d3b} diff --git a/csharp/CONTRIBUTING.md b/csharp/CONTRIBUTING.md new file mode 100644 index 0000000000000..e37b2a4b27232 --- /dev/null +++ b/csharp/CONTRIBUTING.md @@ -0,0 +1,6 @@ +## Guidelines + +### CUDA Plugin Execution Provider + +- The EP name for the CUDA Plugin EP (returned by `OrtEpDevice.EpName`) is `CudaPluginExecutionProvider`. +- The registration name passed to `RegisterExecutionProviderLibrary` is arbitrary and chosen by the application. diff --git a/csharp/OnnxRuntime.CSharp.proj b/csharp/OnnxRuntime.CSharp.proj index 6779fd60bcd0a..9e96c3ca16105 100644 --- a/csharp/OnnxRuntime.CSharp.proj +++ b/csharp/OnnxRuntime.CSharp.proj @@ -50,8 +50,6 @@ CMake creates a target to this project - $(BuildDate) - $(BuildTime) $([System.DateTime]::UtcNow.ToString(yyyyMMdd)) $([System.DateTime]::UtcNow.ToString(hhmm)) diff --git a/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.Maui/Microsoft.ML.OnnxRuntime.InferenceSample.Maui.csproj b/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.Maui/Microsoft.ML.OnnxRuntime.InferenceSample.Maui.csproj index 73a535999672c..310aaf98ae08d 100644 --- a/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.Maui/Microsoft.ML.OnnxRuntime.InferenceSample.Maui.csproj +++ b/csharp/sample/InferenceSample/Microsoft.ML.OnnxRuntime.InferenceSample.Maui/Microsoft.ML.OnnxRuntime.InferenceSample.Maui.csproj @@ -1,7 +1,7 @@  - net8.0-android;net8.0-ios;net8.0-maccatalyst + net9.0-android;net9.0-ios;net9.0-maccatalyst $(TargetFrameworks);net8.0-windows10.0.19041.0 Exe Microsoft.ML.OnnxRuntime.InferenceSample.Maui diff --git a/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj b/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj index f00a08a1a3595..b1452a64934c2 100644 --- a/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj +++ b/csharp/sample/Microsoft.ML.OnnxRuntime.FasterRcnnSample/Microsoft.ML.OnnxRuntime.FasterRcnnSample.csproj @@ -8,7 +8,7 @@ - + diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/CompileModel.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/CompileModel.shared.cs new file mode 100644 index 0000000000000..bde39d9c6e6cc --- /dev/null +++ b/csharp/src/Microsoft.ML.OnnxRuntime/CompileModel.shared.cs @@ -0,0 +1,507 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +namespace Microsoft.ML.OnnxRuntime +{ + using System; + using System.Diagnostics; + using System.Runtime.InteropServices; + + /// + /// Flags representing options to enable when compiling a model. + /// Matches OrtCompileApiFlags in the ORT C API. + /// + [Flags] + public enum OrtCompileApiFlags : uint + { + NONE = 0, + ERROR_IF_NO_NODES_COMPILED = 1 << 0, + ERROR_IF_OUTPUT_FILE_EXISTS = 1 << 1, + } + + /// + /// This class is used to set options for model compilation, and to produce a compiled model using those options. + /// See https://onnxruntime.ai/docs/api/c/ for further details of various options. + /// + public class OrtModelCompilationOptions : IDisposable + { + /// + /// Create a new OrtModelCompilationOptions object from SessionOptions. + /// + /// By default, the GraphOptimizationLevel is set to ORT_DISABLE_ALL. Use SetGraphOptimizationLevel() + /// to enable graph optimizations. + /// SessionOptions instance to read settings from. + public OrtModelCompilationOptions(SessionOptions sessionOptions) + { + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtCreateModelCompilationOptionsFromSessionOptions( + OrtEnv.Instance().Handle, sessionOptions.Handle, out _handle)); + } + + /// + /// Compile the model using the options set in this object. + /// + public void CompileModel() + { + NativeApiStatus.VerifySuccess(NativeMethods.CompileApi.OrtCompileModel(OrtEnv.Instance().Handle, _handle)); + } + + + /// + /// Set the input model to compile. + /// + /// Path to ONNX model to compile. + public void SetInputModelPath(string path) + { + var platformPath = NativeOnnxValueHelper.GetPlatformSerializedString(path); + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtModelCompilationOptions_SetInputModelPath(_handle, platformPath)); + } + + /// + /// Set the input model to compile to be a byte array. + /// The input bytes are NOT copied and must remain valid while in use by ORT. + /// + /// Input model bytes. + public void SetInputModelFromBuffer(byte[] buffer) + { + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtModelCompilationOptions_SetInputModelFromBuffer( + _handle, buffer, (UIntPtr)buffer.Length)); + } + + /// + /// Set the path to write the compiled ONNX model to. + /// + /// Path to write compiled model to. + public void SetOutputModelPath(string path) + { + var platformPath = NativeOnnxValueHelper.GetPlatformSerializedString(path); + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtModelCompilationOptions_SetOutputModelPath(_handle, platformPath)); + + } + + /// + /// Set the path to a file to write initializers as external data to, + /// and the threshold that determines when to write an initializer to the external data file. + /// + /// Path to file to write external data to. + /// Size at which an initializer will be written to external data. + public void SetOutputModelExternalInitializersFile(string filePath, ulong threshold) + { + var platformPath = NativeOnnxValueHelper.GetPlatformSerializedString(filePath); + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtModelCompilationOptions_SetOutputModelExternalInitializersFile( + _handle, platformPath, new UIntPtr(threshold))); + } + + // TODO: In order to use this to create an InferenceSession without copying bytes we need more infrastructure. + // - Need something that wraps the allocator, pointer and size and is SafeHandle based. + // - When it is disposed we need to use the allocator to release the native buffer. + // - Need the 4 InferenceSession ctors that take byte[] for the model to be duplicated to handle this new + // wrapper type. + // Due to that making this API internal so we can test it. We can make it public when the other infrastructure + // is in place as it will change the signature of the API. + internal void SetOutputModelBuffer(OrtAllocator allocator, + ref IntPtr outputModelBufferPtr, ref UIntPtr outputModelBufferSizePtr) + { + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtModelCompilationOptions_SetOutputModelBuffer( + _handle, allocator.Pointer, ref outputModelBufferPtr, ref outputModelBufferSizePtr)); + } + + /// + /// Enables or disables the embedding of EPContext binary data into the `ep_cache_context` attribute + /// of EPContext nodes. + /// + /// Enable if true. Default is false. + public void SetEpContextEmbedMode(bool embed) + { + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtModelCompilationOptions_SetEpContextEmbedMode(_handle, embed)); + } + + /// + /// Sets flags from OrtCompileApiFlags that represent one or more boolean options to enable. + /// + /// bitwise OR of flags in OrtCompileApiFlags to enable. + public void SetFlags(OrtCompileApiFlags flags) + { + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtModelCompilationOptions_SetFlags(_handle, (uint)flags)); + } + + /// + /// Sets information related to EP context binary file. The Ep uses this information to decide the + /// location and context binary file name when compiling with both the input and output models + /// stored in buffers. + /// + /// Path to the model directory. + /// The name of the model. + public void SetEpContextBinaryInformation(string outputDirectory, string modelName) + { + var platformOutputDirectory = NativeOnnxValueHelper.GetPlatformSerializedString(outputDirectory); + var platformModelName = NativeOnnxValueHelper.GetPlatformSerializedString(modelName); + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtModelCompilationOptions_SetEpContextBinaryInformation( + _handle, platformOutputDirectory, platformModelName)); + } + + /// + /// Sets the graph optimization level. Defaults to ORT_DISABLE_ALL if not specified. + /// + /// The graph optimization level to set. + public void SetGraphOptimizationLevel(GraphOptimizationLevel graphOptimizationLevel) + { + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtModelCompilationOptions_SetGraphOptimizationLevel( + _handle, graphOptimizationLevel)); + } + + /// + /// Delegate to write/save a buffer containing ONNX model bytes to a custom destination. The delegate + /// may be called repeatedly until the entire output model has been written out. Each call to the delegate + /// is expected to consume the entire buffer. + /// + /// The buffer to write out. + /// + public delegate void WriteBufferToDestinationDelegate(ReadOnlySpan buffer); + + /// + /// Sets a delegate that is called by ORT to write out the output model's serialized ONNX bytes. + /// The provided delegate may be called repeatedly until the entire output model has been written out. + /// Each call to the delegate is expected to consume/handle the entire input buffer. + /// + /// The delegate called by ORT to write out the model. + public void SetOutputModelWriteDelegate(WriteBufferToDestinationDelegate writeBufferDelegate) + { + _writeBufferToDestinationDelegateState?.Dispose(); + _writeBufferToDestinationDelegateState = + new DelegateResources( + new WriteBufferToDestinationConnector(writeBufferDelegate), + new NativeMethods.DOrtWriteBufferToDestinationDelegate( + WriteBufferToDestinationConnector.WriteBufferToDestinationDelegateWrapper)); + + IntPtr funcPtr = _writeBufferToDestinationDelegateState.GetFunctionPointerForDelegate(); + + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtModelCompilationOptions_SetOutputModelWriteFunc( + _handle, + funcPtr, + _writeBufferToDestinationDelegateState.GetConnectorHandleAsPointer())); + } + + /// + /// Delegate called by ORT for every initializer when generating the compiled model. + /// The delegate allows the user to determine whether the initializer should be stored within the compiled + /// model or externally in a file. If the delegate chooses to store an initializer externally, the delegate + /// implementation is responsible for writing the initializer data to a file. + /// + /// The initializer's name. + /// The readonly OrtValue instance containing the data, type, and + /// shape of the initializer. + /// May be null. If the initializer is originally stored externally, + /// this contains the file path, file offset, and data size. Otherwise, this is null. + /// A new OrtExternalInitializerInfo indicating the new location of the initializer. + /// Returns null if the initializer should be stored within the generated compiled model. + /// The return value may be null. + /// + public delegate OrtExternalInitializerInfo GetInitializerLocationDelegate( + string initializerName, + IReadOnlyOrtValue initializerValue, + IReadOnlyExternalInitializerInfo originalInitializerLocation); + + /// + /// Sets a delegate that is called by ORT for every initializer when generating the compiled model. + /// The delegate allows the user to determine whether the initializer should be stored within the compiled + /// model or externally in a file. If the delegate chooses to store an initializer externally, the delegate + /// implementation is responsible for writing the initializer data to a file. + /// + /// The delegate called by ORT for every initializer. + public void SetOutputModelGetInitializerLocationDelegate( + GetInitializerLocationDelegate getInitializerLocationDelegate) + { + _getInitializerLocationDelegateState?.Dispose(); + _getInitializerLocationDelegateState = + new DelegateResources( + new GetInitializerLocationConnector(getInitializerLocationDelegate), + new NativeMethods.DOrtGetInitializerLocationDelegate( + GetInitializerLocationConnector.GetInitializerLocationDelegateWrapper)); + + IntPtr funcPtr = _getInitializerLocationDelegateState.GetFunctionPointerForDelegate(); + + NativeApiStatus.VerifySuccess( + NativeMethods.CompileApi.OrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc( + _handle, + funcPtr, + _getInitializerLocationDelegateState.GetConnectorHandleAsPointer())); + } + + #region Delegate helpers + /// + /// Class to bridge the C# and native worlds for the "write buffer to destination" delegate + /// + private class WriteBufferToDestinationConnector + { + private readonly WriteBufferToDestinationDelegate _userDelegate; + + internal WriteBufferToDestinationConnector(WriteBufferToDestinationDelegate writeBufferDelegate) + { + _userDelegate = writeBufferDelegate; + } + + public static IntPtr WriteBufferToDestinationDelegateWrapper(IntPtr /* void* */ state, + IntPtr /* const void* */ buffer, + UIntPtr /* size_t */ bufferNumBytes) + { + try + { + + WriteBufferToDestinationConnector connector = (WriteBufferToDestinationConnector) + GCHandle.FromIntPtr(state).Target; + ReadOnlySpan bufferSpan; + + unsafe + { + // NOTE: A Span can only view 2GB of data. This is fine because ORT does not write out + // chunks that large. However, if we ever need to, the solution is to just write a loop here + // that repeatedly calls the delegate with smaller chunks of data. + bufferSpan = new ReadOnlySpan(buffer.ToPointer(), checked((int)bufferNumBytes)); + } + + connector._userDelegate(bufferSpan); + } + catch (Exception ex) + { + var error = $"The C# WriteBufferToDestination delegate threw an exception: {ex.Message}"; + IntPtr status = NativeMethods.OrtCreateStatus((uint)ErrorCode.Fail, + NativeOnnxValueHelper.StringToZeroTerminatedUtf8(error)); + return status; + } + + return IntPtr.Zero; + } + } + + /// + /// Class to bridge the C# and native worlds for the "get initializer location" delegate + /// + private class GetInitializerLocationConnector + { + private readonly GetInitializerLocationDelegate _userDelegate; + + internal GetInitializerLocationConnector(GetInitializerLocationDelegate getInitializerLocationDelegate) + { + _userDelegate = getInitializerLocationDelegate; + } + + public static IntPtr GetInitializerLocationDelegateWrapper( + IntPtr /* void* */ state, + IntPtr /* const char* */ initializerName, + IntPtr /* const OrtValue* */ initializerValue, + IntPtr /* const OrtExternalInitializerInfo* */ originalInitializerLocation, + out IntPtr /* OrtExternalInitializerInfo** */ newInitializerLocationOutput) + { + newInitializerLocationOutput = IntPtr.Zero; + + try + { + + GetInitializerLocationConnector connector = (GetInitializerLocationConnector)GCHandle. + FromIntPtr(state).Target; + string utf8InitializerName = NativeOnnxValueHelper.StringFromNativeUtf8(initializerName); + IReadOnlyOrtValue readOnlyInitializerValue = new OrtValue(initializerValue, owned: false); + IReadOnlyExternalInitializerInfo readOnlyOriginalInitializerLocation = null; + + if (originalInitializerLocation != IntPtr.Zero) + { + readOnlyOriginalInitializerLocation = new OrtExternalInitializerInfo( + originalInitializerLocation, ownsHandle: false); + } + + // Call user's delegate, which may return the new location of the initializer. + OrtExternalInitializerInfo newInitializerLocation = connector._userDelegate( + utf8InitializerName, readOnlyInitializerValue, readOnlyOriginalInitializerLocation); + + if (newInitializerLocation != null) + { + // Delegate returned info about a new location for the initializer. + // Can't guarantee that the new external info returned by user's delegate is not referenced + // by other C# code. ORT expects to own the new external info, so create a copy here and + // give it to ORT. + string newFilePath = newInitializerLocation.GetFilePath(); + byte[] newFilePathBytes = NativeOnnxValueHelper.GetPlatformSerializedString(newFilePath); + + IntPtr status = NativeMethods.OrtCreateExternalInitializerInfo( + newFilePathBytes, + newInitializerLocation.GetFileOffset(), + (UIntPtr)newInitializerLocation.GetByteSize(), + out newInitializerLocationOutput); + + if (status != IntPtr.Zero) + { + return status; + } + } + else + { + // User's delegate did not return a new location for the initializer. ORT will store initializer + // within the generated compiled model. + newInitializerLocationOutput = IntPtr.Zero; + } + } + catch (Exception ex) + { + var error = $"The C# GetInitializerLocation delegate threw an exception: {ex.Message}"; + IntPtr status = NativeMethods.OrtCreateStatus((uint)ErrorCode.Fail, + NativeOnnxValueHelper.StringToZeroTerminatedUtf8(error)); + return status; + } + + return IntPtr.Zero; + } + } + + /// + /// Disposable class that stores resources for a delegate provided by the user. + /// + /// The type of the connector class + /// (e.g., WriteBufferToDestinationConnector) + /// The type of the native delegate. + private class DelegateResources : IDisposable + where Connector : class + where Delegate : class + { + public DelegateResources(Connector connector, Delegate @delegate) + { + _connector = connector; + _delegate = @delegate; + _connectorHandle = GCHandle.Alloc(_connector); + _delegateHandle = GCHandle.Alloc(_delegate); + } + + internal IntPtr GetFunctionPointerForDelegate() + { + return Marshal.GetFunctionPointerForDelegate(_delegate); + } + + internal IntPtr GetConnectorHandleAsPointer() + { + return GCHandle.ToIntPtr(_connectorHandle); + } + + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + // Dispose other children disposables. We have none. + } + + if (_connectorHandle.IsAllocated) + { + _connectorHandle.Free(); + _connector = null; + } + + if (_delegateHandle.IsAllocated) + { + _delegateHandle.Free(); + _delegate = null; + } + + _disposed = true; + } + + ~DelegateResources() + { + Dispose(false); + } + + private Connector _connector = null; + private Delegate _delegate = null; + private GCHandle _connectorHandle = default; + private GCHandle _delegateHandle = default; + private bool _disposed = false; + } + #endregion + + #region IDispose implementation + /// + /// IDispose implementation. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + /// + /// IDispose implementation + /// + /// True if Dispose() has been called by the user-side code. False if + /// called by the runtime from inside the finalizer. + protected virtual void Dispose(bool disposing) + { + if (_disposed) + { + return; + } + + if (disposing) + { + _writeBufferToDestinationDelegateState?.Dispose(); + _getInitializerLocationDelegateState?.Dispose(); + } + + Debug.Assert(_handle != IntPtr.Zero); + NativeMethods.CompileApi.OrtReleaseModelCompilationOptions(_handle); + _handle = IntPtr.Zero; + _disposed = true; + } + + /// + /// Finalizer that releases the native handle if not already released by Dispose(). + /// + ~OrtModelCompilationOptions() + { + Dispose(false); + } + #endregion + + /// + /// Handle to the native OrtModelCompilationOptions object. + /// + private IntPtr _handle; + + /// + /// True if this OrtModelCompilationOptions instance has already been disposed. + /// + private bool _disposed = false; + + /// + /// Stores delegate state for the "write buffer to destination" delegate. + /// + private DelegateResources + _writeBufferToDestinationDelegateState = null; + + /// + /// Stores delegate state for the "get initializer location" delegate. + /// + private DelegateResources + _getInitializerLocationDelegateState = null; + } +} diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/Exceptions.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/Exceptions.shared.cs index 098a18b7444cf..2467475b6b189 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/Exceptions.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/Exceptions.shared.cs @@ -23,8 +23,8 @@ internal enum ErrorCode ModelLoaded = 8, NotImplemented = 9, InvalidGraph = 10, - ShapeInferenceNotRegistered = 11, - RequirementNotRegistered = 12, + ShapeInferenceNotRegistered = 11, // TODO: should be ORT_EP_FAIL + RequirementNotRegistered = 12, // TODO: should be ORT_MODEL_LOAD_CANCELED } /// diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.shared.cs index b62a3c50bfda6..79e6dbbb11c89 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/InferenceSession.shared.cs @@ -214,6 +214,82 @@ public IReadOnlyDictionary OverridableInitializerMetadata } } + /// + /// Fetches memory info for all inputs in the same order as their names. + /// (See InputNames property). + /// + /// A disposable readonly collection of OrtMemoryInfo + public IDisposableReadOnlyCollection GetMemoryInfosForInputs() + { + NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionGetInputCount(_nativeHandle, out UIntPtr numInputs)); + + if(numInputs == UIntPtr.Zero) + { + return new DisposableList(); + } + + var memoryInfoArray = new IntPtr[(ulong)numInputs]; + + NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionGetMemoryInfoForInputs(_nativeHandle, + memoryInfoArray, numInputs)); + + return new DisposableList( + memoryInfoArray.Select(static ptr => new OrtMemoryInfo(ptr, /* owned= */ false))); + } + + /// + /// Fetches memory info for all outputs in the same order as their names. + /// (See OutputNames property). + /// + /// A disposable readonly collection of OrtMemoryInfo + public IDisposableReadOnlyCollection GetMemoryInfosForOutputs() + { + NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionGetOutputCount(_nativeHandle, + out UIntPtr numOutputs)); + + if(numOutputs == UIntPtr.Zero) + { + return new DisposableList(); + } + + var memoryInfoArray = new IntPtr[(ulong)numOutputs]; + + NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionGetMemoryInfoForOutputs(_nativeHandle, + memoryInfoArray, numOutputs)); + return new DisposableList( + memoryInfoArray.Select(static ptr => new OrtMemoryInfo(ptr, /* owned= */ false))); + } + + /// + /// Fetches OrtEpDevice instances for all inputs in the same order as their input names. + /// For inputs that do not have a device, the corresponding entry in the returned list is null. + /// See InputNames property. + /// + /// IReadOnlyList + public IReadOnlyList GetEpDeviceForInputs() + { + NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionGetInputCount(_nativeHandle, + out UIntPtr numInputs)); + + if (numInputs == UIntPtr.Zero) + { + // OrtSessionGetEpDeviceForInputs expects numInputs > 0, otherwise it is an invalid arg. + return []; + } + + var epDevicesForInputs = new IntPtr[(ulong)numInputs]; + + NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionGetEpDeviceForInputs(_nativeHandle, + epDevicesForInputs, numInputs)); + + // Some entries in epDevicesForInputs can be IntPtr.Zero, indicating the input does not + // have a device; return null for those entries. + return epDevicesForInputs + .Select(static ptr => ptr == IntPtr.Zero ? null : new OrtEpDevice(ptr)) + .ToList() + .AsReadOnly(); + } + /// /// Runs the loaded model for the given inputs, and fetches all the outputs. /// @@ -1046,7 +1122,7 @@ public ulong ProfilingStartTimeNs } } - private static void OrtCallback(IntPtr userData, IntPtr[] ouputs, uint numOutputs, IntPtr status) + private static void OrtCallback(IntPtr userData, IntPtr[] outputs, uint numOutputs, IntPtr status) { var hostHdl = GCHandle.FromIntPtr(userData); CallbackHost host = (CallbackHost)hostHdl.Target; @@ -1635,7 +1711,7 @@ internal TensorTypeAndShape(TensorElementType elementType, int[] dimensions, str } /// - /// Represents sequnce metdata + /// Represents sequence metadata /// public class SequenceMetadata { @@ -1648,7 +1724,7 @@ internal SequenceMetadata(NodeMetadata elementData) ElementMeta = elementData; } /// - /// Element Metatada, recursive definition with a Tensor being a base case + /// Element Metadata, recursive definition with a Tensor being a base case /// may contain maps, tensors and other sequences /// public NodeMetadata ElementMeta { get; } @@ -1669,7 +1745,7 @@ internal OptionalMetadata(NodeMetadata elementData) } /// - /// Element Metatada, recursive definition with a Tensor being a base case + /// Element Metadata, recursive definition with a Tensor being a base case /// may contain maps, tensors and sequences /// public NodeMetadata ElementMeta { get; } @@ -1876,7 +1952,7 @@ public TensorElementType ElementDataType } /// - /// Convinience method to check for string + /// Convenience method to check for string /// public bool IsString { diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs index 13117f23e8ef9..8916f11919cfe 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/ManagedProjections.shared.cs @@ -25,7 +25,7 @@ internal class ManagedTypeProjection /// /// /// - /// OrtValye created accoding to the metadata + /// OrtValue created according to the metadata internal static OrtValue CreateProjection(NamedOnnxValue namedOnnxValue, NodeMetadata metadata) { OrtValue result; @@ -191,4 +191,3 @@ private static OrtValue CreateTensorProjection(NamedOnnxValue node, NodeMetadata } } } - diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/Microsoft.ML.OnnxRuntime.csproj b/csharp/src/Microsoft.ML.OnnxRuntime/Microsoft.ML.OnnxRuntime.csproj index be0e8d2ee58a4..193be042ae420 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/Microsoft.ML.OnnxRuntime.csproj +++ b/csharp/src/Microsoft.ML.OnnxRuntime/Microsoft.ML.OnnxRuntime.csproj @@ -19,12 +19,12 @@ - net8.0-android;net8.0-ios;net8.0-maccatalyst + net9.0-android;net9.0-ios;net9.0-maccatalyst - net8.0-android + net9.0-android diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/NativeCompileApiMethods.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/NativeCompileApiMethods.shared.cs new file mode 100644 index 0000000000000..00ca25d0a6367 --- /dev/null +++ b/csharp/src/Microsoft.ML.OnnxRuntime/NativeCompileApiMethods.shared.cs @@ -0,0 +1,234 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Runtime.InteropServices; + +namespace Microsoft.ML.OnnxRuntime.CompileApi +{ + // NOTE: The order of the APIs in this struct should match exactly that in OrtCompileApi + // See onnxruntime/core/session/compile_api.cc. + [StructLayout(LayoutKind.Sequential)] + public struct OrtCompileApi + { + public IntPtr ReleaseModelCompilationOptions; + public IntPtr CreateModelCompilationOptionsFromSessionOptions; + public IntPtr ModelCompilationOptions_SetInputModelPath; + public IntPtr ModelCompilationOptions_SetInputModelFromBuffer; + public IntPtr ModelCompilationOptions_SetOutputModelPath; + public IntPtr ModelCompilationOptions_SetOutputModelExternalInitializersFile; + public IntPtr ModelCompilationOptions_SetOutputModelBuffer; + public IntPtr ModelCompilationOptions_SetEpContextEmbedMode; + public IntPtr CompileModel; + public IntPtr ModelCompilationOptions_SetFlags; + public IntPtr ModelCompilationOptions_SetEpContextBinaryInformation; + public IntPtr ModelCompilationOptions_SetGraphOptimizationLevel; + public IntPtr ModelCompilationOptions_SetOutputModelWriteFunc; + public IntPtr ModelCompilationOptions_SetOutputModelGetInitializerLocationFunc; + public IntPtr ModelCompilationOptions_SetInputModel; + } + + internal class NativeMethods + { + private static OrtCompileApi _compileApi; + + // + // Define the delegate signatures, and a static member for each to hold the marshaled function pointer. + // + // We populate the static members in the constructor of this class. + // + // The C# code will call the C++ API through the delegate instances in the static members. + // + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate void DOrtReleaseModelCompilationOptions(IntPtr /* OrtModelCompilationOptions* */ options); + public DOrtReleaseModelCompilationOptions OrtReleaseModelCompilationOptions; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtCreateModelCompilationOptionsFromSessionOptions( + IntPtr /* const OrtEnv* */ env, + IntPtr /* const OrtSessionOptions* */ sessionOptions, + out IntPtr /* OrtModelCompilationOptions** */ outOptions); + public DOrtCreateModelCompilationOptionsFromSessionOptions + OrtCreateModelCompilationOptionsFromSessionOptions; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetInputModelPath( + IntPtr /* OrtModelCompilationOptions* */ options, + byte[] /* const ORTCHAR_T* */ inputModelPath); + public DOrtModelCompilationOptions_SetInputModelPath OrtModelCompilationOptions_SetInputModelPath; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetInputModelFromBuffer( + IntPtr /* OrtModelCompilationOptions* */ options, + byte[] /* const void* */ inputModelData, + UIntPtr /* size_t */ inputModelDataSize); + public DOrtModelCompilationOptions_SetInputModelFromBuffer + OrtModelCompilationOptions_SetInputModelFromBuffer; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetOutputModelPath( + IntPtr /* OrtModelCompilationOptions* */ options, + byte[] /* const ORTCHAR_T* */ outputModelPath); + public DOrtModelCompilationOptions_SetOutputModelPath OrtModelCompilationOptions_SetOutputModelPath; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetOutputModelExternalInitializersFile( + IntPtr /* OrtModelCompilationOptions* */ options, + byte[] /* const ORTCHAR_T* */ externalInitializersFilePath, + UIntPtr /* size_t */ externalInitializerSizeThreshold); + public DOrtModelCompilationOptions_SetOutputModelExternalInitializersFile + OrtModelCompilationOptions_SetOutputModelExternalInitializersFile; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetOutputModelBuffer( + IntPtr /* OrtModelCompilationOptions* */ options, + IntPtr /* OrtAllocator* */ allocator, + ref IntPtr /* void** */ outputModelBufferPtr, + ref UIntPtr /* size_t* */ outputModelBufferSizePtr); + public DOrtModelCompilationOptions_SetOutputModelBuffer OrtModelCompilationOptions_SetOutputModelBuffer; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetEpContextEmbedMode( + IntPtr /* OrtModelCompilationOptions* */ options, + bool embedEpContextInModel); + public DOrtModelCompilationOptions_SetEpContextEmbedMode OrtModelCompilationOptions_SetEpContextEmbedMode; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtCompileModel( + IntPtr /* const OrtEnv* */ env, + IntPtr /* const OrtModelCompilationOptions* */ modelOptions); + public DOrtCompileModel OrtCompileModel; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetFlags( + IntPtr /* OrtModelCompilationOptions* */ options, + uint flags); + public DOrtModelCompilationOptions_SetFlags OrtModelCompilationOptions_SetFlags; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetEpContextBinaryInformation( + IntPtr /* OrtModelCompilationOptions* */ options, + byte[] /* const ORTCHAR_T* */ outputDirectory, + byte[] /* const ORTCHAR_T* */ modelName); + public DOrtModelCompilationOptions_SetEpContextBinaryInformation + OrtModelCompilationOptions_SetEpContextBinaryInformation; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetGraphOptimizationLevel( + IntPtr /* OrtModelCompilationOptions* */ options, + GraphOptimizationLevel graphOptimizationLevel); + public DOrtModelCompilationOptions_SetGraphOptimizationLevel + OrtModelCompilationOptions_SetGraphOptimizationLevel; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetOutputModelWriteFunc( + IntPtr /* OrtModelCompilationOptions* */ options, + IntPtr /* DOrtWriteBufferDelegate */ writeFunc, + IntPtr /* void* */ state); + public DOrtModelCompilationOptions_SetOutputModelWriteFunc + OrtModelCompilationOptions_SetOutputModelWriteFunc; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc( + IntPtr /* OrtModelCompilationOptions* */ options, + IntPtr /* DOrtHandleInitializerDataDelegate */ handleInitializerFunc, + IntPtr /* void* */ state); + public DOrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc + OrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtModelCompilationOptions_SetInputModel( + IntPtr /* OrtModelCompilationOptions* */ options, + IntPtr /* const OrtModel* */ inputModel); + public DOrtModelCompilationOptions_SetInputModel OrtModelCompilationOptions_SetInputModel; + + internal NativeMethods(OnnxRuntime.NativeMethods.DOrtGetCompileApi getCompileApi) + { + +#if NETSTANDARD2_0 + IntPtr compileApiPtr = getCompileApi(); + _compileApi = (OrtCompileApi)Marshal.PtrToStructure(compileApiPtr, typeof(OrtCompileApi)); +#else + _compileApi = (OrtCompileApi)getCompileApi(); +#endif + + OrtReleaseModelCompilationOptions = + (DOrtReleaseModelCompilationOptions)Marshal.GetDelegateForFunctionPointer( + _compileApi.ReleaseModelCompilationOptions, + typeof(DOrtReleaseModelCompilationOptions)); + + OrtCreateModelCompilationOptionsFromSessionOptions = + (DOrtCreateModelCompilationOptionsFromSessionOptions)Marshal.GetDelegateForFunctionPointer( + _compileApi.CreateModelCompilationOptionsFromSessionOptions, + typeof(DOrtCreateModelCompilationOptionsFromSessionOptions)); + + OrtModelCompilationOptions_SetInputModelPath = + (DOrtModelCompilationOptions_SetInputModelPath)Marshal.GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetInputModelPath, + typeof(DOrtModelCompilationOptions_SetInputModelPath)); + + OrtModelCompilationOptions_SetInputModelFromBuffer = + (DOrtModelCompilationOptions_SetInputModelFromBuffer)Marshal.GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetInputModelFromBuffer, + typeof(DOrtModelCompilationOptions_SetInputModelFromBuffer)); + + OrtModelCompilationOptions_SetOutputModelPath = + (DOrtModelCompilationOptions_SetOutputModelPath)Marshal.GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetOutputModelPath, + typeof(DOrtModelCompilationOptions_SetOutputModelPath)); + + OrtModelCompilationOptions_SetOutputModelExternalInitializersFile = + (DOrtModelCompilationOptions_SetOutputModelExternalInitializersFile)Marshal.GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetOutputModelExternalInitializersFile, + typeof(DOrtModelCompilationOptions_SetOutputModelExternalInitializersFile)); + + OrtModelCompilationOptions_SetOutputModelBuffer = + (DOrtModelCompilationOptions_SetOutputModelBuffer)Marshal.GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetOutputModelBuffer, + typeof(DOrtModelCompilationOptions_SetOutputModelBuffer)); + + OrtModelCompilationOptions_SetEpContextEmbedMode = + (DOrtModelCompilationOptions_SetEpContextEmbedMode)Marshal.GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetEpContextEmbedMode, + typeof(DOrtModelCompilationOptions_SetEpContextEmbedMode)); + + OrtCompileModel = + (DOrtCompileModel)Marshal.GetDelegateForFunctionPointer( + _compileApi.CompileModel, + typeof(DOrtCompileModel)); + + OrtModelCompilationOptions_SetFlags = + (DOrtModelCompilationOptions_SetFlags)Marshal.GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetFlags, + typeof(DOrtModelCompilationOptions_SetFlags)); + + OrtModelCompilationOptions_SetEpContextBinaryInformation = + (DOrtModelCompilationOptions_SetEpContextBinaryInformation)Marshal.GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetEpContextBinaryInformation, + typeof(DOrtModelCompilationOptions_SetEpContextBinaryInformation)); + + OrtModelCompilationOptions_SetGraphOptimizationLevel = + (DOrtModelCompilationOptions_SetGraphOptimizationLevel)Marshal.GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetGraphOptimizationLevel, + typeof(DOrtModelCompilationOptions_SetGraphOptimizationLevel)); + + OrtModelCompilationOptions_SetOutputModelWriteFunc = + (DOrtModelCompilationOptions_SetOutputModelWriteFunc)Marshal.GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetOutputModelWriteFunc, + typeof(DOrtModelCompilationOptions_SetOutputModelWriteFunc)); + + OrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc = + (DOrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc)Marshal. + GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetOutputModelGetInitializerLocationFunc, + typeof(DOrtModelCompilationOptions_SetOutputModelGetInitializerLocationFunc)); + + OrtModelCompilationOptions_SetInputModel = + (DOrtModelCompilationOptions_SetInputModel)Marshal.GetDelegateForFunctionPointer( + _compileApi.ModelCompilationOptions_SetInputModel, + typeof(DOrtModelCompilationOptions_SetInputModel)); + + } + } +} diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs index d628b065ceaa7..dd67fd0589a08 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/NativeMethods.shared.cs @@ -2,7 +2,9 @@ // Licensed under the MIT License. using System; +using System.Reflection; using System.Runtime.InteropServices; +using static Microsoft.ML.OnnxRuntime.NativeMethods; namespace Microsoft.ML.OnnxRuntime { @@ -325,12 +327,169 @@ public struct OrtApi public IntPtr CreateLoraAdapterFromArray; public IntPtr ReleaseLoraAdapter; public IntPtr RunOptionsAddActiveLoraAdapter; + public IntPtr SetEpDynamicOptions; + public IntPtr ReleaseValueInfo; + public IntPtr ReleaseNode; + public IntPtr ReleaseGraph; + public IntPtr ReleaseModel; + public IntPtr GetValueInfoName; + public IntPtr GetValueInfoTypeInfo; + public IntPtr GetModelEditorApi; + public IntPtr CreateTensorWithDataAndDeleterAsOrtValue; + public IntPtr SessionOptionsSetLoadCancellationFlag; + + public IntPtr GetCompileApi; + + public IntPtr CreateKeyValuePairs; + public IntPtr AddKeyValuePair; + public IntPtr GetKeyValue; + public IntPtr GetKeyValuePairs; + public IntPtr RemoveKeyValuePair; + public IntPtr ReleaseKeyValuePairs; + + public IntPtr RegisterExecutionProviderLibrary; + public IntPtr UnregisterExecutionProviderLibrary; + + public IntPtr GetEpDevices; + + public IntPtr SessionOptionsAppendExecutionProvider_V2; + public IntPtr SessionOptionsSetEpSelectionPolicy; + public IntPtr SessionOptionsSetEpSelectionPolicyDelegate; + + public IntPtr HardwareDevice_Type; + public IntPtr HardwareDevice_VendorId; + public IntPtr HardwareDevice_Vendor; + public IntPtr HardwareDevice_DeviceId; + public IntPtr HardwareDevice_Metadata; + + public IntPtr EpDevice_EpName; + public IntPtr EpDevice_EpVendor; + public IntPtr EpDevice_EpMetadata; + public IntPtr EpDevice_EpOptions; + public IntPtr EpDevice_Device; + public IntPtr GetEpApi; + public IntPtr GetTensorSizeInBytes; + + public IntPtr AllocatorGetStats; + + public IntPtr CreateMemoryInfo_V2; + public IntPtr MemoryInfoGetDeviceMemType; + public IntPtr MemoryInfoGetVendorId; + + public IntPtr ValueInfo_GetValueProducer; + public IntPtr ValueInfo_GetValueNumConsumers; + public IntPtr ValueInfo_GetValueConsumers; + public IntPtr ValueInfo_GetInitializerValue; + public IntPtr ValueInfo_GetExternalInitializerInfo; + public IntPtr ValueInfo_IsRequiredGraphInput; + public IntPtr ValueInfo_IsOptionalGraphInput; + public IntPtr ValueInfo_IsGraphOutput; + public IntPtr ValueInfo_IsConstantInitializer; + public IntPtr ValueInfo_IsFromOuterScope; + public IntPtr Graph_GetName; + public IntPtr Graph_GetModelPath; + public IntPtr Graph_GetOnnxIRVersion; + public IntPtr Graph_GetNumOperatorSets; + public IntPtr Graph_GetOperatorSets; + public IntPtr Graph_GetNumInputs; + public IntPtr Graph_GetInputs; + public IntPtr Graph_GetNumOutputs; + public IntPtr Graph_GetOutputs; + public IntPtr Graph_GetNumInitializers; + public IntPtr Graph_GetInitializers; + public IntPtr Graph_GetNumNodes; + public IntPtr Graph_GetNodes; + public IntPtr Graph_GetParentNode; + public IntPtr Graph_GetGraphView; + public IntPtr Node_GetId; + public IntPtr Node_GetName; + public IntPtr Node_GetOperatorType; + public IntPtr Node_GetDomain; + public IntPtr Node_GetSinceVersion; + public IntPtr Node_GetNumInputs; + public IntPtr Node_GetInputs; + public IntPtr Node_GetNumOutputs; + public IntPtr Node_GetOutputs; + public IntPtr Node_GetNumImplicitInputs; + public IntPtr Node_GetImplicitInputs; + public IntPtr Node_GetNumAttributes; + public IntPtr Node_GetAttributes; + public IntPtr Node_GetAttributeByName; + public IntPtr Node_GetTensorAttributeAsOrtValue; + public IntPtr OpAttr_GetType; + public IntPtr OpAttr_GetName; + public IntPtr Node_GetNumSubgraphs; + public IntPtr Node_GetSubgraphs; + public IntPtr Node_GetGraph; + public IntPtr Node_GetEpName; + public IntPtr ReleaseExternalInitializerInfo; + public IntPtr ExternalInitializerInfo_GetFilePath; + public IntPtr ExternalInitializerInfo_GetFileOffset; + public IntPtr ExternalInitializerInfo_GetByteSize; + + public IntPtr GetRunConfigEntry; + + public IntPtr EpDevice_MemoryInfo; + + public IntPtr CreateSharedAllocator; + public IntPtr GetSharedAllocator; + public IntPtr ReleaseSharedAllocator; + + public IntPtr GetTensorData; + + public IntPtr GetSessionOptionsConfigEntries; + + public IntPtr SessionGetMemoryInfoForInputs; + public IntPtr SessionGetMemoryInfoForOutputs; + public IntPtr SessionGetEpDeviceForInputs; + + public IntPtr CreateSyncStreamForEpDevice; + public IntPtr SyncStream_GetHandle; + public IntPtr ReleaseSyncStream; + + public IntPtr CopyTensors; + + public IntPtr Graph_GetModelMetadata; + public IntPtr GetModelCompatibilityForEpDevices; + public IntPtr CreateExternalInitializerInfo; + + // v1.24 APIs + public IntPtr TensorTypeAndShape_HasShape; + public IntPtr KernelInfo_GetConfigEntries; + public IntPtr KernelInfo_GetOperatorDomain; + public IntPtr KernelInfo_GetOperatorType; + public IntPtr KernelInfo_GetOperatorSinceVersion; + public IntPtr GetInteropApi; + public IntPtr SessionGetEpDeviceForOutputs; + public IntPtr GetNumHardwareDevices; + public IntPtr GetHardwareDevices; + public IntPtr GetHardwareDeviceEpIncompatibilityDetails; + public IntPtr DeviceEpIncompatibilityDetails_GetReasonsBitmask; + public IntPtr DeviceEpIncompatibilityDetails_GetNotes; + public IntPtr DeviceEpIncompatibilityDetails_GetErrorCode; + public IntPtr ReleaseDeviceEpIncompatibilityDetails; + public IntPtr GetCompatibilityInfoFromModel; + public IntPtr GetCompatibilityInfoFromModelBytes; + public IntPtr CreateEnvWithOptions; + public IntPtr Session_GetEpGraphAssignmentInfo; + public IntPtr EpAssignedSubgraph_GetEpName; + public IntPtr EpAssignedSubgraph_GetNodes; + public IntPtr EpAssignedNode_GetName; + public IntPtr EpAssignedNode_GetDomain; + public IntPtr EpAssignedNode_GetOperatorType; + public IntPtr RunOptionsSetSyncStream; + public IntPtr GetTensorElementTypeAndShapeDataReference; + // v1.25 APIs + public IntPtr RunOptionsEnableProfiling; + public IntPtr RunOptionsDisableProfiling; } internal static class NativeMethods { static OrtApi api_; + static internal CompileApi.NativeMethods CompileApi; + #if NETSTANDARD2_0 [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr DOrtGetApi(UInt32 version); @@ -346,6 +505,28 @@ internal static class NativeMethods static NativeMethods() { +#if !NETSTANDARD2_0 && !__ANDROID__ && !__IOS__ + if (!OrtEnv.DisableDllImportResolver) + { + try + { + // Register a custom DllImportResolver to handle platform-specific library loading. + // Replaces default resolution specifically on Windows for case-sensitivity. + NativeLibrary.SetDllImportResolver(typeof(NativeMethods).Assembly, DllImportResolver); + } + catch (InvalidOperationException) + { + // A resolver is already registered for this assembly (e.g., by the host application). + // This is not fatal — the host's resolver will handle library loading. + System.Diagnostics.Trace.WriteLine( + "[OnnxRuntime] A DllImportResolver is already registered for this assembly. " + + "OnnxRuntime's built-in resolver will not be used. " + + "To suppress this message, set OrtEnv.DisableDllImportResolver = true " + + "before using any OnnxRuntime APIs."); + } + } +#endif + #if NETSTANDARD2_0 IntPtr ortApiBasePtr = OrtGetApiBase(); OrtApiBase ortApiBase = (OrtApiBase)Marshal.PtrToStructure(ortApiBasePtr, typeof(OrtApiBase)); @@ -364,12 +545,15 @@ static NativeMethods() api_ = (OrtApi)OrtGetApi(ORT_API_VERSION); OrtGetVersionString = (DOrtGetVersionString)Marshal.GetDelegateForFunctionPointer(OrtGetApiBase().GetVersionString, typeof(DOrtGetVersionString)); #endif + OrtCreateStatus = (DOrtCreateStatus)Marshal.GetDelegateForFunctionPointer( + api_.CreateStatus, typeof(DOrtCreateStatus)); OrtCreateEnv = (DOrtCreateEnv)Marshal.GetDelegateForFunctionPointer(api_.CreateEnv, typeof(DOrtCreateEnv)); OrtCreateEnvWithCustomLogger = (DOrtCreateEnvWithCustomLogger)Marshal.GetDelegateForFunctionPointer(api_.CreateEnvWithCustomLogger, typeof(DOrtCreateEnvWithCustomLogger)); OrtCreateEnvWithGlobalThreadPools = (DOrtCreateEnvWithGlobalThreadPools)Marshal.GetDelegateForFunctionPointer(api_.CreateEnvWithGlobalThreadPools, typeof(DOrtCreateEnvWithGlobalThreadPools)); OrtCreateEnvWithCustomLoggerAndGlobalThreadPools = (DOrtCreateEnvWithCustomLoggerAndGlobalThreadPools)Marshal.GetDelegateForFunctionPointer(api_.CreateEnvWithCustomLoggerAndGlobalThreadPools, typeof(DOrtCreateEnvWithCustomLoggerAndGlobalThreadPools)); OrtReleaseEnv = (DOrtReleaseEnv)Marshal.GetDelegateForFunctionPointer(api_.ReleaseEnv, typeof(DOrtReleaseEnv)); + OrtEnableTelemetryEvents = (DOrtEnableTelemetryEvents)Marshal.GetDelegateForFunctionPointer(api_.EnableTelemetryEvents, typeof(DOrtEnableTelemetryEvents)); OrtDisableTelemetryEvents = (DOrtDisableTelemetryEvents)Marshal.GetDelegateForFunctionPointer(api_.DisableTelemetryEvents, typeof(DOrtDisableTelemetryEvents)); @@ -396,6 +580,9 @@ static NativeMethods() OrtSessionGetInputTypeInfo = (DOrtSessionGetInputTypeInfo)Marshal.GetDelegateForFunctionPointer(api_.SessionGetInputTypeInfo, typeof(DOrtSessionGetInputTypeInfo)); OrtSessionGetOutputTypeInfo = (DOrtSessionGetOutputTypeInfo)Marshal.GetDelegateForFunctionPointer(api_.SessionGetOutputTypeInfo, typeof(DOrtSessionGetOutputTypeInfo)); OrtSessionGetOverridableInitializerTypeInfo = (DOrtSessionGetOverridableInitializerTypeInfo)Marshal.GetDelegateForFunctionPointer(api_.SessionGetOverridableInitializerTypeInfo, typeof(DOrtSessionGetOverridableInitializerTypeInfo)); + OrtSessionGetMemoryInfoForInputs = (DOrtSessionGetMemoryInfoForInputs)Marshal.GetDelegateForFunctionPointer(api_.SessionGetMemoryInfoForInputs, typeof(DOrtSessionGetMemoryInfoForInputs)); + OrtSessionGetMemoryInfoForOutputs = (DOrtSessionGetMemoryInfoForOutputs)Marshal.GetDelegateForFunctionPointer(api_.SessionGetMemoryInfoForOutputs, typeof(DOrtSessionGetMemoryInfoForOutputs)); + OrtSessionGetEpDeviceForInputs = (DOrtSessionGetEpDeviceForInputs)Marshal.GetDelegateForFunctionPointer(api_.SessionGetEpDeviceForInputs, typeof(DOrtSessionGetEpDeviceForInputs)); OrtReleaseTypeInfo = (DOrtReleaseTypeInfo)Marshal.GetDelegateForFunctionPointer(api_.ReleaseTypeInfo, typeof(DOrtReleaseTypeInfo)); OrtReleaseSession = (DOrtReleaseSession)Marshal.GetDelegateForFunctionPointer(api_.ReleaseSession, typeof(DOrtReleaseSession)); OrtSessionGetProfilingStartTimeNs = (DOrtSessionGetProfilingStartTimeNs)Marshal.GetDelegateForFunctionPointer(api_.SessionGetProfilingStartTimeNs, typeof(DOrtSessionGetProfilingStartTimeNs)); @@ -404,6 +591,7 @@ static NativeMethods() OrtReleaseSessionOptions = (DOrtReleaseSessionOptions)Marshal.GetDelegateForFunctionPointer(api_.ReleaseSessionOptions, typeof(DOrtReleaseSessionOptions)); OrtCloneSessionOptions = (DOrtCloneSessionOptions)Marshal.GetDelegateForFunctionPointer(api_.CloneSessionOptions, typeof(DOrtCloneSessionOptions)); OrtSetSessionExecutionMode = (DOrtSetSessionExecutionMode)Marshal.GetDelegateForFunctionPointer(api_.SetSessionExecutionMode, typeof(DOrtSetSessionExecutionMode)); + OrtSessionOptionsSetLoadCancellationFlag = (DOrtSessionOptionsSetLoadCancellationFlag)Marshal.GetDelegateForFunctionPointer(api_.SessionOptionsSetLoadCancellationFlag, typeof(DOrtSessionOptionsSetLoadCancellationFlag)); OrtSetOptimizedModelFilePath = (DOrtSetOptimizedModelFilePath)Marshal.GetDelegateForFunctionPointer(api_.SetOptimizedModelFilePath, typeof(DOrtSetOptimizedModelFilePath)); OrtEnableProfiling = (DOrtEnableProfiling)Marshal.GetDelegateForFunctionPointer(api_.EnableProfiling, typeof(DOrtEnableProfiling)); OrtDisableProfiling = (DOrtDisableProfiling)Marshal.GetDelegateForFunctionPointer(api_.DisableProfiling, typeof(DOrtDisableProfiling)); @@ -456,6 +644,9 @@ static NativeMethods() OrtMemoryInfoGetMemType = (DOrtMemoryInfoGetMemType)Marshal.GetDelegateForFunctionPointer(api_.MemoryInfoGetMemType, typeof(DOrtMemoryInfoGetMemType)); OrtMemoryInfoGetType = (DOrtMemoryInfoGetType)Marshal.GetDelegateForFunctionPointer(api_.MemoryInfoGetType, typeof(DOrtMemoryInfoGetType)); OrtGetAllocatorWithDefaultOptions = (DOrtGetAllocatorWithDefaultOptions)Marshal.GetDelegateForFunctionPointer(api_.GetAllocatorWithDefaultOptions, typeof(DOrtGetAllocatorWithDefaultOptions)); + OrtCreateMemoryInfoV2 = (DOrtCreateMemoryInfoV2)Marshal.GetDelegateForFunctionPointer(api_.CreateMemoryInfo_V2, typeof(DOrtCreateMemoryInfoV2)); + OrtMemoryInfoGetDeviceMemType = (DOrtMemoryInfoGetDeviceMemType)Marshal.GetDelegateForFunctionPointer(api_.MemoryInfoGetDeviceMemType, typeof(DOrtMemoryInfoGetDeviceMemType)); + OrtMemoryInfoGetVendorId = (DOrtMemoryInfoGetVendorId)Marshal.GetDelegateForFunctionPointer(api_.MemoryInfoGetVendorId, typeof(DOrtMemoryInfoGetVendorId)); OrtCreateAllocator = (DOrtCreateAllocator)Marshal.GetDelegateForFunctionPointer(api_.CreateAllocator, typeof(DOrtCreateAllocator)); OrtReleaseAllocator = (DOrtReleaseAllocator)Marshal.GetDelegateForFunctionPointer(api_.ReleaseAllocator, typeof(DOrtReleaseAllocator)); OrtAllocatorAlloc = (DOrtAllocatorAlloc)Marshal.GetDelegateForFunctionPointer(api_.AllocatorAlloc, typeof(DOrtAllocatorAlloc)); @@ -478,6 +669,7 @@ static NativeMethods() OrtTensorAt = (DOrtTensorAt)Marshal.GetDelegateForFunctionPointer(api_.TensorAt, typeof(DOrtTensorAt)); OrtCreateAndRegisterAllocator = (DOrtCreateAndRegisterAllocator)Marshal.GetDelegateForFunctionPointer(api_.CreateAndRegisterAllocator, typeof(DOrtCreateAndRegisterAllocator)); + OrtUnregisterAllocator = (DOrtUnregisterAllocator)Marshal.GetDelegateForFunctionPointer(api_.UnregisterAllocator, typeof(DOrtUnregisterAllocator)); OrtSetLanguageProjection = (DOrtSetLanguageProjection)Marshal.GetDelegateForFunctionPointer(api_.SetLanguageProjection, typeof(DOrtSetLanguageProjection)); OrtHasValue = (DOrtHasValue)Marshal.GetDelegateForFunctionPointer(api_.HasValue, typeof(DOrtHasValue)); @@ -492,6 +684,7 @@ static NativeMethods() OrtValueIsTensor = (DOrtValueIsTensor)Marshal.GetDelegateForFunctionPointer(api_.IsTensor, typeof(DOrtValueIsTensor)); OrtValueIsSparseTensor = (DOrtValueIsSparseTensor)Marshal.GetDelegateForFunctionPointer(api_.IsSparseTensor, typeof(DOrtValueIsSparseTensor)); OrtGetTensorMutableData = (DOrtGetTensorMutableData)Marshal.GetDelegateForFunctionPointer(api_.GetTensorMutableData, typeof(DOrtGetTensorMutableData)); + OrtGetTensorSizeInBytes = (DOrtGetTensorSizeInBytes)Marshal.GetDelegateForFunctionPointer(api_.GetTensorSizeInBytes, typeof(DOrtGetTensorSizeInBytes)); OrtFillStringTensor = (DOrtFillStringTensor)Marshal.GetDelegateForFunctionPointer(api_.FillStringTensor, typeof(DOrtFillStringTensor)); OrtGetResizedStringTensorElementBuffer = (DOrtGetResizedStringTensorElementBuffer)Marshal.GetDelegateForFunctionPointer(api_.GetResizedStringTensorElementBuffer, typeof(DOrtGetResizedStringTensorElementBuffer)); OrtGetStringTensorContent = (DOrtGetStringTensorContent)Marshal.GetDelegateForFunctionPointer(api_.GetStringTensorContent, typeof(DOrtGetStringTensorContent)); @@ -563,28 +756,358 @@ static NativeMethods() OrtReleaseROCMProviderOptions = (DOrtReleaseROCMProviderOptions)Marshal.GetDelegateForFunctionPointer(api_.ReleaseROCMProviderOptions, typeof(DOrtReleaseROCMProviderOptions)); OrtCreateAndRegisterAllocatorV2 = (DCreateAndRegisterAllocatorV2)Marshal.GetDelegateForFunctionPointer(api_.CreateAndRegisterAllocatorV2, typeof(DCreateAndRegisterAllocatorV2)); OrtRunAsync = (DOrtRunAsync)Marshal.GetDelegateForFunctionPointer(api_.RunAsync, typeof(DOrtRunAsync)); - CreateLoraAdapter = (DCreateLoraAdapter)Marshal.GetDelegateForFunctionPointer(api_.CreateLoraAdapter, - typeof(DCreateLoraAdapter)); - CreateLoraAdapterFromArray = (DCreateLoraAdapterFromArray)Marshal.GetDelegateForFunctionPointer (api_.CreateLoraAdapterFromArray, typeof(DCreateLoraAdapterFromArray)); - ReleaseLoraAdapter = (DReleaseLoraAdapter)Marshal.GetDelegateForFunctionPointer(api_.ReleaseLoraAdapter, - typeof(DReleaseLoraAdapter)); + OrtCreateLoraAdapter = (DOrtCreateLoraAdapter)Marshal.GetDelegateForFunctionPointer(api_.CreateLoraAdapter, + typeof(DOrtCreateLoraAdapter)); + OrtCreateLoraAdapterFromArray = (DOrtCreateLoraAdapterFromArray)Marshal.GetDelegateForFunctionPointer(api_.CreateLoraAdapterFromArray, typeof(DOrtCreateLoraAdapterFromArray)); + OrtReleaseLoraAdapter = (DOrtReleaseLoraAdapter)Marshal.GetDelegateForFunctionPointer(api_.ReleaseLoraAdapter, + typeof(DOrtReleaseLoraAdapter)); OrtRunOptionsAddActiveLoraAdapter = (DOrtRunOptionsAddActiveLoraAdapter)Marshal.GetDelegateForFunctionPointer( api_.RunOptionsAddActiveLoraAdapter, typeof(DOrtRunOptionsAddActiveLoraAdapter)); + + OrtGetCompileApi = (DOrtGetCompileApi)Marshal.GetDelegateForFunctionPointer( + api_.GetCompileApi, typeof(DOrtGetCompileApi)); + + // populate the CompileApi struct now that we have the delegate to get the compile API pointer. + CompileApi = new CompileApi.NativeMethods(OrtGetCompileApi); + + OrtCreateKeyValuePairs = (DOrtCreateKeyValuePairs)Marshal.GetDelegateForFunctionPointer( + api_.CreateKeyValuePairs, typeof(DOrtCreateKeyValuePairs)); + + OrtAddKeyValuePair = (DOrtAddKeyValuePair)Marshal.GetDelegateForFunctionPointer( + api_.AddKeyValuePair, typeof(DOrtAddKeyValuePair)); + + OrtGetKeyValue = (DOrtGetKeyValue)Marshal.GetDelegateForFunctionPointer( + api_.GetKeyValue, typeof(DOrtGetKeyValue)); + + OrtGetKeyValuePairs = (DOrtGetKeyValuePairs)Marshal.GetDelegateForFunctionPointer( + api_.GetKeyValuePairs, typeof(DOrtGetKeyValuePairs)); + + OrtRemoveKeyValuePair = (DOrtRemoveKeyValuePair)Marshal.GetDelegateForFunctionPointer( + api_.RemoveKeyValuePair, typeof(DOrtRemoveKeyValuePair)); + + OrtReleaseKeyValuePairs = (DOrtReleaseKeyValuePairs)Marshal.GetDelegateForFunctionPointer( + api_.ReleaseKeyValuePairs, typeof(DOrtReleaseKeyValuePairs)); + + OrtHardwareDevice_Type = (DOrtHardwareDevice_Type)Marshal.GetDelegateForFunctionPointer( + api_.HardwareDevice_Type, typeof(DOrtHardwareDevice_Type)); + + OrtHardwareDevice_VendorId = (DOrtHardwareDevice_VendorId)Marshal.GetDelegateForFunctionPointer( + api_.HardwareDevice_VendorId, typeof(DOrtHardwareDevice_VendorId)); + + OrtHardwareDevice_Vendor = (DOrtHardwareDevice_Vendor)Marshal.GetDelegateForFunctionPointer( + api_.HardwareDevice_Vendor, typeof(DOrtHardwareDevice_Vendor)); + + OrtHardwareDevice_DeviceId = (DOrtHardwareDevice_DeviceId)Marshal.GetDelegateForFunctionPointer( + api_.HardwareDevice_DeviceId, typeof(DOrtHardwareDevice_DeviceId)); + + OrtHardwareDevice_Metadata = (DOrtHardwareDevice_Metadata)Marshal.GetDelegateForFunctionPointer( + api_.HardwareDevice_Metadata, typeof(DOrtHardwareDevice_Metadata)); + + + OrtEpDevice_EpName = (DOrtEpDevice_EpName)Marshal.GetDelegateForFunctionPointer( + api_.EpDevice_EpName, typeof(DOrtEpDevice_EpName)); + + OrtEpDevice_EpVendor = (DOrtEpDevice_EpVendor)Marshal.GetDelegateForFunctionPointer( + api_.EpDevice_EpVendor, typeof(DOrtEpDevice_EpVendor)); + + OrtEpDevice_EpMetadata = (DOrtEpDevice_EpMetadata)Marshal.GetDelegateForFunctionPointer( + api_.EpDevice_EpMetadata, typeof(DOrtEpDevice_EpMetadata)); + + OrtEpDevice_EpOptions = (DOrtEpDevice_EpOptions)Marshal.GetDelegateForFunctionPointer( + api_.EpDevice_EpOptions, typeof(DOrtEpDevice_EpOptions)); + + OrtEpDevice_Device = (DOrtEpDevice_Device)Marshal.GetDelegateForFunctionPointer( + api_.EpDevice_Device, typeof(DOrtEpDevice_Device)); + + OrtEpDevice_MemoryInfo = (DOrtEpDevice_MemoryInfo)Marshal.GetDelegateForFunctionPointer( + api_.EpDevice_MemoryInfo, typeof(DOrtEpDevice_MemoryInfo)); + + OrtRegisterExecutionProviderLibrary = + (DOrtRegisterExecutionProviderLibrary)Marshal.GetDelegateForFunctionPointer( + api_.RegisterExecutionProviderLibrary, + typeof(DOrtRegisterExecutionProviderLibrary)); + + OrtUnregisterExecutionProviderLibrary = + (DOrtUnregisterExecutionProviderLibrary)Marshal.GetDelegateForFunctionPointer( + api_.UnregisterExecutionProviderLibrary, + typeof(DOrtUnregisterExecutionProviderLibrary)); + + OrtGetEpDevices = (DOrtGetEpDevices)Marshal.GetDelegateForFunctionPointer( + api_.GetEpDevices, + typeof(DOrtGetEpDevices)); + + OrtSessionOptionsAppendExecutionProvider_V2 = + (DOrtSessionOptionsAppendExecutionProvider_V2)Marshal.GetDelegateForFunctionPointer( + api_.SessionOptionsAppendExecutionProvider_V2, + typeof(DOrtSessionOptionsAppendExecutionProvider_V2)); + + OrtSessionOptionsSetEpSelectionPolicy = + (DSessionOptionsSetEpSelectionPolicy)Marshal.GetDelegateForFunctionPointer( + api_.SessionOptionsSetEpSelectionPolicy, + typeof(DSessionOptionsSetEpSelectionPolicy)); + + OrtSessionOptionsSetEpSelectionPolicyDelegate = + (DSessionOptionsSetEpSelectionPolicyDelegate)Marshal.GetDelegateForFunctionPointer( + api_.SessionOptionsSetEpSelectionPolicyDelegate, + typeof(DSessionOptionsSetEpSelectionPolicyDelegate)); + + OrtReleaseExternalInitializerInfo = + (DOrtReleaseExternalInitializerInfo)Marshal.GetDelegateForFunctionPointer( + api_.ReleaseExternalInitializerInfo, + typeof(DOrtReleaseExternalInitializerInfo)); + + OrtExternalInitializerInfo_GetFilePath = + (DOrtExternalInitializerInfo_GetFilePath)Marshal.GetDelegateForFunctionPointer( + api_.ExternalInitializerInfo_GetFilePath, + typeof(DOrtExternalInitializerInfo_GetFilePath)); + + OrtExternalInitializerInfo_GetFileOffset = + (DOrtExternalInitializerInfo_GetFileOffset)Marshal.GetDelegateForFunctionPointer( + api_.ExternalInitializerInfo_GetFileOffset, + typeof(DOrtExternalInitializerInfo_GetFileOffset)); + + OrtExternalInitializerInfo_GetByteSize = + (DOrtExternalInitializerInfo_GetByteSize)Marshal.GetDelegateForFunctionPointer( + api_.ExternalInitializerInfo_GetByteSize, + typeof(DOrtExternalInitializerInfo_GetByteSize)); + + OrtGetModelCompatibilityForEpDevices = (DOrtGetModelCompatibilityForEpDevices)Marshal.GetDelegateForFunctionPointer( + api_.GetModelCompatibilityForEpDevices, + typeof(DOrtGetModelCompatibilityForEpDevices)); + + OrtCreateExternalInitializerInfo = + (DOrtCreateExternalInitializerInfo)Marshal.GetDelegateForFunctionPointer( + api_.CreateExternalInitializerInfo, + typeof(DOrtCreateExternalInitializerInfo)); + + // Version 24 additions + OrtGetNumHardwareDevices = + (DOrtGetNumHardwareDevices)Marshal.GetDelegateForFunctionPointer( + api_.GetNumHardwareDevices, + typeof(DOrtGetNumHardwareDevices)); + + OrtGetHardwareDevices = + (DOrtGetHardwareDevices)Marshal.GetDelegateForFunctionPointer( + api_.GetHardwareDevices, + typeof(DOrtGetHardwareDevices)); + + OrtGetHardwareDeviceEpIncompatibilityDetails = + (DOrtGetHardwareDeviceEpIncompatibilityDetails)Marshal.GetDelegateForFunctionPointer( + api_.GetHardwareDeviceEpIncompatibilityDetails, + typeof(DOrtGetHardwareDeviceEpIncompatibilityDetails)); + + OrtDeviceEpIncompatibilityDetails_GetReasonsBitmask = + (DOrtDeviceEpIncompatibilityDetails_GetReasonsBitmask)Marshal.GetDelegateForFunctionPointer( + api_.DeviceEpIncompatibilityDetails_GetReasonsBitmask, + typeof(DOrtDeviceEpIncompatibilityDetails_GetReasonsBitmask)); + + OrtDeviceEpIncompatibilityDetails_GetNotes = + (DOrtDeviceEpIncompatibilityDetails_GetNotes)Marshal.GetDelegateForFunctionPointer( + api_.DeviceEpIncompatibilityDetails_GetNotes, + typeof(DOrtDeviceEpIncompatibilityDetails_GetNotes)); + + OrtDeviceEpIncompatibilityDetails_GetErrorCode = + (DOrtDeviceEpIncompatibilityDetails_GetErrorCode)Marshal.GetDelegateForFunctionPointer( + api_.DeviceEpIncompatibilityDetails_GetErrorCode, + typeof(DOrtDeviceEpIncompatibilityDetails_GetErrorCode)); + + OrtReleaseDeviceEpIncompatibilityDetails = + (DOrtReleaseDeviceEpIncompatibilityDetails)Marshal.GetDelegateForFunctionPointer( + api_.ReleaseDeviceEpIncompatibilityDetails, + typeof(DOrtReleaseDeviceEpIncompatibilityDetails)); + + OrtCreateSharedAllocator = + (DOrtCreateSharedAllocator)Marshal.GetDelegateForFunctionPointer( + api_.CreateSharedAllocator, + typeof(DOrtCreateSharedAllocator)); + + OrtGetSharedAllocator = + (DOrtGetSharedAllocator)Marshal.GetDelegateForFunctionPointer( + api_.GetSharedAllocator, + typeof(DOrtGetSharedAllocator)); + + OrtReleaseSharedAllocator = + (DOrtReleaseSharedAllocator)Marshal.GetDelegateForFunctionPointer( + api_.ReleaseSharedAllocator, + typeof(DOrtReleaseSharedAllocator)); + + OrtCreateSyncStreamForEpDevice = + (DOrtCreateSyncStreamForEpDevice)Marshal.GetDelegateForFunctionPointer( + api_.CreateSyncStreamForEpDevice, + typeof(DOrtCreateSyncStreamForEpDevice)); + + OrtSyncStream_GetHandle = + (DOrtSyncStream_GetHandle)Marshal.GetDelegateForFunctionPointer( + api_.SyncStream_GetHandle, + typeof(DOrtSyncStream_GetHandle)); + + OrtReleaseSyncStream = + (DOrtReleaseSyncStream)Marshal.GetDelegateForFunctionPointer( + api_.ReleaseSyncStream, + typeof(DOrtReleaseSyncStream)); + + OrtCopyTensors = + (DOrtCopyTensors)Marshal.GetDelegateForFunctionPointer( + api_.CopyTensors, + typeof(DOrtCopyTensors)); + + OrtGetCompatibilityInfoFromModel = + (DOrtGetCompatibilityInfoFromModel)Marshal.GetDelegateForFunctionPointer( + api_.GetCompatibilityInfoFromModel, + typeof(DOrtGetCompatibilityInfoFromModel)); + + OrtGetCompatibilityInfoFromModelBytes = + (DOrtGetCompatibilityInfoFromModelBytes)Marshal.GetDelegateForFunctionPointer( + api_.GetCompatibilityInfoFromModelBytes, + typeof(DOrtGetCompatibilityInfoFromModelBytes)); } internal class NativeLib { #if __ANDROID__ - // define the library name required for android + // Define the library name required for Android internal const string DllName = "libonnxruntime.so"; #elif __IOS__ - // define the library name required for iOS + // Define the library name required for iOS internal const string DllName = "__Internal"; #else + // For desktop platforms (including .NET Standard 2.0), we use the simple name + // to allow .NET's automatic platform-specific resolution (lib*.so, lib*.dylib, *.dll). + // For .NET Core 3.0+, case-sensitivity on Windows is handled by DllImportResolver. internal const string DllName = "onnxruntime"; #endif } +#if !NETSTANDARD2_0 && !__ANDROID__ && !__IOS__ + /// + /// Custom DllImportResolver to handle platform-specific library loading. + /// On Windows, it explicitly loads the library with a lowercase .dll extension to handle + /// case-sensitive filesystems. + /// +#if NET5_0_OR_GREATER + [System.Diagnostics.CodeAnalysis.UnconditionalSuppressMessage("SingleFile", "IL3000:Avoid accessing Assembly file path when publishing as a single file", Justification = "We also check AppContext.BaseDirectory as a fallback")] +#endif + private static IntPtr DllImportResolver(string libraryName, Assembly assembly, DllImportSearchPath? searchPath) + { + try + { + if (libraryName == NativeLib.DllName || libraryName == OrtExtensionsNativeMethods.ExtensionsDllName) + { + string mappedName = null; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + // Explicitly load with .dll extension to avoid issues where the OS might try .DLL + mappedName = libraryName + ".dll"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + // Explicitly load with .so extension and lib prefix + mappedName = "lib" + libraryName + ".so"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + // Explicitly load with .dylib extension and lib prefix + mappedName = "lib" + libraryName + ".dylib"; + } + + if (mappedName != null) + { + // 1. Try default loading (name only) + if (NativeLibrary.TryLoad(mappedName, assembly, searchPath, out IntPtr handle)) + { + return handle; + } + + // 2. Try relative to assembly location (look into runtimes subfolders) + string assemblyLocation = null; + try { assemblyLocation = assembly.Location; } catch { } + if (!string.IsNullOrEmpty(assemblyLocation)) + { + string assemblyDir = System.IO.Path.GetDirectoryName(assemblyLocation); + string rid = RuntimeInformation.RuntimeIdentifier; + + // Probe the specific RID first, then common fallbacks for the current OS + string[] ridsToTry; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + ridsToTry = new[] { rid, "win-x64", "win-arm64" }; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + ridsToTry = new[] { rid, "linux-x64", "linux-arm64" }; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + // We no longer provide osx-x64 in official package since 1.24. + // However, we keep it in the list for build-from-source users. + ridsToTry = new[] { rid, "osx-arm64", "osx-x64" }; + } + else + { + ridsToTry = new[] { rid }; + } + + foreach (var tryRid in ridsToTry) + { + string probePath = System.IO.Path.Combine(assemblyDir, "runtimes", tryRid, "native", mappedName); + if (System.IO.File.Exists(probePath) && NativeLibrary.TryLoad(probePath, assembly, searchPath, out handle)) + { + LogLibLoad($"[DllImportResolver] Loaded {mappedName} from: {probePath}"); + return handle; + } + } + } + + // 3. Try AppContext.BaseDirectory as a fallback + try + { + string baseDir = AppContext.BaseDirectory; + if (!string.IsNullOrEmpty(baseDir)) + { + string probePath = System.IO.Path.Combine(baseDir, mappedName); + if (NativeLibrary.TryLoad(probePath, assembly, searchPath, out handle)) + { + LogLibLoad($"[DllImportResolver] Loaded {mappedName} from: {probePath}"); + return handle; + } + + string rid = RuntimeInformation.RuntimeIdentifier; + probePath = System.IO.Path.Combine(baseDir, "runtimes", rid, "native", mappedName); + if (NativeLibrary.TryLoad(probePath, assembly, searchPath, out handle)) + { + LogLibLoad($"[DllImportResolver] Loaded {mappedName} from: {probePath}"); + return handle; + } + } + } + catch { } // Ignore AppDomainUnloadedException or similar from AppContext.BaseDirectory + + LogLibLoad($"[DllImportResolver] Failed loading {mappedName} (RID: {RuntimeInformation.RuntimeIdentifier}, Assembly: {assemblyLocation})"); + + } + } + } + catch (Exception ex) + { + // Unhandled exceptions inside DllImportResolver can result in TypeInitializationException. + // Log and swallow the error, returning IntPtr.Zero to fall back to default CLR logic. + try { System.Diagnostics.Trace.WriteLine($"[DllImportResolver] Exception during resolution: {ex}"); } catch { } + } + + // Fall back to default resolution + return IntPtr.Zero; + } + + private static void LogLibLoad(string message) + { + System.Diagnostics.Trace.WriteLine(message); + if (!string.IsNullOrEmpty(Environment.GetEnvironmentVariable("ORT_LOADER_VERBOSITY"))) + { + Console.WriteLine(message); + } + } +#endif + [DllImport(NativeLib.DllName, CharSet = CharSet.Ansi)] #if NETSTANDARD2_0 public static extern IntPtr OrtGetApiBase(); @@ -592,7 +1115,7 @@ internal class NativeLib public static extern ref OrtApiBase OrtGetApiBase(); #endif -#region Runtime / Environment API + #region Runtime / Environment API [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /* OrtStatus* */ DOrtCreateEnv( @@ -649,9 +1172,59 @@ internal class NativeLib public delegate IntPtr /* OrtStatus* */ DOrtUpdateEnvWithCustomLogLevel(IntPtr /*(OrtEnv*)*/ env, OrtLoggingLevel custom_log_level); public static DOrtUpdateEnvWithCustomLogLevel OrtUpdateEnvWithCustomLogLevel; -#endregion Runtime / Environment API + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /*(OrtStatus*)*/ DCreateAndRegisterAllocatorV2( + IntPtr /* OrtEnv* */ environment, + IntPtr /*const char* */ provderType, + IntPtr /* const OrtMemoryInfo* */ memInfo, + IntPtr /* const OrtArenaCfg* */ arenaCfg, + IntPtr[] /* const char* const* */ providerOptionsKeys, + IntPtr[] /* const char* const* */ providerOptionsValues, + UIntPtr /* size_t */ numKeys); + public static DCreateAndRegisterAllocatorV2 OrtCreateAndRegisterAllocatorV2; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtCreateSharedAllocator( + IntPtr /* OrtEnv* */ ortEnv, + IntPtr /* OrtEpDevice* */ epDevice, + OrtDeviceMemoryType deviceMemoryType, + OrtAllocatorType allocatorType, + IntPtr /* const OrtKeyValuePairs* */ allocatorOptions, + out IntPtr /* OrtAllocator** */ allocator); + + public static DOrtCreateSharedAllocator OrtCreateSharedAllocator; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtGetSharedAllocator( + IntPtr /*(OrtEnv*)*/ env, + IntPtr /*(const OrtMemoryInfo*)*/ memInfo, + out IntPtr /* OrtAllocator** */ allocator); + + public static DOrtGetSharedAllocator OrtGetSharedAllocator; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtReleaseSharedAllocator( + IntPtr /*(OrtEnv*)*/ env, + IntPtr /* const OrtEpDevice* */ epDevice, + OrtDeviceMemoryType deviceMemoryType); -#region Provider Options API + public static DOrtReleaseSharedAllocator OrtReleaseSharedAllocator; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtCopyTensors( + IntPtr /* const OrtEnv* */ env, + IntPtr[] /* const OrtValue* const* */ srcTensors, + IntPtr[] /* OrtValue* const* */ dstTensors, + IntPtr /* OrtSynStream* */ stream, + UIntPtr /* size_t */ numTensors + ); + + public static DOrtCopyTensors OrtCopyTensors; + + + #endregion Runtime / Environment API + + #region Provider Options API /// /// Creates native OrtTensorRTProviderOptions instance @@ -785,9 +1358,9 @@ internal class NativeLib public delegate void DOrtReleaseROCMProviderOptions(IntPtr /*(OrtROCMProviderOptions*)*/ rocmProviderOptionsInstance); public static DOrtReleaseROCMProviderOptions OrtReleaseROCMProviderOptions; -#endregion + #endregion -#region Status API + #region Status API [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate ErrorCode DOrtGetErrorCode(IntPtr /*(OrtStatus*)*/ status); public static DOrtGetErrorCode OrtGetErrorCode; @@ -802,16 +1375,21 @@ internal class NativeLib public delegate void DOrtReleaseStatus(IntPtr /*(OrtStatus*)*/ statusPtr); public static DOrtReleaseStatus OrtReleaseStatus; -#endregion Status API + #endregion Status API -#region InferenceSession API + #region InferenceSession API + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtCreateStatus( + uint /* OrtErrorCode */ code, + byte[] /* const char* */ msg); + public static DOrtCreateStatus OrtCreateStatus; [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /* OrtStatus* */ DOrtCreateSession( IntPtr /* (OrtEnv*) */ environment, //[MarshalAs(UnmanagedType.LPStr)]string modelPath byte[] modelPath, - IntPtr /* (OrtSessionOptions*) */ sessopnOptions, + IntPtr /* (OrtSessionOptions*) */ sessionOptions, out IntPtr /**/ session); public static DOrtCreateSession OrtCreateSession; @@ -847,7 +1425,7 @@ internal class NativeLib /// Creates an instance of OrtSession with provided parameters /// /// Native OrtEnv instance - /// Byte array correspoonding to the model + /// Byte array corresponding to the model /// Size of the model in bytes /// Native SessionOptions instance /// Native OrtPrepackedWeightsContainer instance @@ -964,6 +1542,30 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca public static DOrtSessionGetOverridableInitializerTypeInfo OrtSessionGetOverridableInitializerTypeInfo; + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /*(OrtStatus*)*/ DOrtSessionGetMemoryInfoForInputs( + IntPtr /*(const OrtSession*)*/ session, + IntPtr[] /* const OrtMemoryInfo** */ inputsMemoryInfos, + UIntPtr /* size_t */ numInputs); + + public static DOrtSessionGetMemoryInfoForInputs OrtSessionGetMemoryInfoForInputs; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /*(OrtStatus*)*/ DOrtSessionGetMemoryInfoForOutputs( + IntPtr /*(const OrtSession*)*/ session, + IntPtr[] /* OrtMemoryInfo** */ outputsMemoryInfos, + UIntPtr /* size_t */ numOutputs); + + public static DOrtSessionGetMemoryInfoForOutputs OrtSessionGetMemoryInfoForOutputs; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /*(OrtStatus*)*/ DOrtSessionGetEpDeviceForInputs( + IntPtr /*(const OrtSession*)*/ session, + IntPtr[] /* const OrtDevice** */ devices, + UIntPtr /* size_t */ numInputs); + + public static DOrtSessionGetEpDeviceForInputs OrtSessionGetEpDeviceForInputs; + // release the typeinfo using OrtReleaseTypeInfo [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate void DOrtReleaseTypeInfo(IntPtr /*(OrtTypeInfo*)*/ session); @@ -979,17 +1581,6 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca out UIntPtr /*(ulong* out)*/ startTime); public static DOrtSessionGetProfilingStartTimeNs OrtSessionGetProfilingStartTimeNs; - [UnmanagedFunctionPointer(CallingConvention.Winapi)] - public delegate IntPtr /*(ONNStatus*)*/ DCreateAndRegisterAllocatorV2( - IntPtr /* (OrtEnv*) */ environment, - IntPtr /*(char*)*/ provider_type, - IntPtr /*(OrtMemoryInfo*)*/ mem_info, - IntPtr /*(OrtArenaCfg*)*/ arena_cfg, - IntPtr /*(char**)*/ provider_options_keys, - IntPtr /*(char**)*/ provider_options_values, - UIntPtr /*(size_t)*/ num_keys); - public static DCreateAndRegisterAllocatorV2 OrtCreateAndRegisterAllocatorV2; - [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(ONNStatus*)*/ DOrtRunAsync( IntPtr /*(OrtSession*)*/ session, @@ -1004,9 +1595,9 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca IntPtr /*(void*)*/ user_data); public static DOrtRunAsync OrtRunAsync; -#endregion InferenceSession API + #endregion InferenceSession API -#region SessionOptions API + #region SessionOptions API [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(OrtStatus*)*/ DOrtCreateSessionOptions(out IntPtr /*(OrtSessionOptions**)*/ sessionOptions); @@ -1025,6 +1616,12 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca ExecutionMode execution_mode); public static DOrtSetSessionExecutionMode OrtSetSessionExecutionMode; + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /*(OrtStatus*)*/ DOrtSessionOptionsSetLoadCancellationFlag(IntPtr /*(OrtSessionOptions*)*/ options, + bool value); + public static DOrtSessionOptionsSetLoadCancellationFlag OrtSessionOptionsSetLoadCancellationFlag; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(OrtStatus*)*/ DOrtSetOptimizedModelFilePath(IntPtr /* OrtSessionOptions* */ options, byte[] optimizedModelFilepath); public static DOrtSetOptimizedModelFilePath OrtSetOptimizedModelFilePath; @@ -1258,7 +1855,7 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca /// /// Native SessionOptions instance /// Name of the initializer - /// Native OrtValue instnce + /// Native OrtValue instance [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(OrtStatus*)*/ DOrtAddInitializer(IntPtr /*(OrtSessionOptions*)*/ options, byte[] /*(const char*)*/ name, @@ -1288,9 +1885,9 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca public static DSessionOptionsAppendExecutionProvider SessionOptionsAppendExecutionProvider; -#endregion + #endregion -#region LoraAdapter API + #region LoraAdapter API /// /// Memory maps the adapter file, wraps it into the adapter object /// and returns it. @@ -1300,12 +1897,12 @@ IntPtr[] outputValues /* An array of output value pointers. Array must be alloca /// New LoraAdapter object /// [UnmanagedFunctionPointer(CallingConvention.Winapi)] - public delegate IntPtr /*(OrtStatus*)*/ DCreateLoraAdapter( + public delegate IntPtr /*(OrtStatus*)*/ DOrtCreateLoraAdapter( byte[] adapter_path, // This takes const ORTCHAR_T* use GetPlatformSerializedString IntPtr /* OrtAllocator */ allocator, // optional out IntPtr lora_adapter ); - public static DCreateLoraAdapter CreateLoraAdapter; + public static DOrtCreateLoraAdapter OrtCreateLoraAdapter; /// /// Creates LoraAdapter instance from a byte array that must @@ -1314,25 +1911,25 @@ out IntPtr lora_adapter /// bytes /// size in bytes /// optional device allocator - /// resuling LoraAdapter instance + /// resulting LoraAdapter instance /// [UnmanagedFunctionPointer(CallingConvention.Winapi)] - public delegate IntPtr /*(OrtStatus*)*/ DCreateLoraAdapterFromArray( + public delegate IntPtr /*(OrtStatus*)*/ DOrtCreateLoraAdapterFromArray( byte[] bytes, UIntPtr size, IntPtr /* OrtAllocator */ allocator, // optional out IntPtr lora_adapter ); - public static DCreateLoraAdapterFromArray CreateLoraAdapterFromArray; + public static DOrtCreateLoraAdapterFromArray OrtCreateLoraAdapterFromArray; [UnmanagedFunctionPointer(CallingConvention.Winapi)] - public delegate void DReleaseLoraAdapter(IntPtr /* OrtLoraAdapter* */ lora_adapter); - public static DReleaseLoraAdapter ReleaseLoraAdapter; + public delegate void DOrtReleaseLoraAdapter(IntPtr /* OrtLoraAdapter* */ lora_adapter); + public static DOrtReleaseLoraAdapter OrtReleaseLoraAdapter; -#endregion + #endregion - #region RunOptions API + #region RunOptions API [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(OrtStatus*)*/ DOrtCreateRunOptions(out IntPtr /* OrtRunOptions** */ runOptions); @@ -1395,9 +1992,9 @@ out IntPtr lora_adapter byte[] /* const char* */ configValue); public static DOrtAddRunConfigEntry OrtAddRunConfigEntry; -#endregion + #endregion -#region ThreadingOptions API + #region ThreadingOptions API [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(OrtStatus*)*/ DOrtCreateThreadingOptions(out IntPtr /* OrtCreateThreadingOptions** */ threadingOptions); @@ -1422,9 +2019,9 @@ out IntPtr lora_adapter [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(OrtStatus*)*/ DOrtThreadingOptionsSetGlobalSpinControl(IntPtr /* OrtThreadingOptions* */ threadingOptions, int allowSpinning); public static DOrtThreadingOptionsSetGlobalSpinControl OrtThreadingOptionsSetGlobalSpinControl; -#endregion + #endregion -#region Allocator / MemoryInfo API + #region Allocator / MemoryInfo API [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /* (OrtStatus*)*/ DOrtCreateMemoryInfo( @@ -1437,6 +2034,20 @@ out IntPtr lora_adapter public static DOrtCreateMemoryInfo OrtCreateMemoryInfo; + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* (OrtStatus*)*/ DOrtCreateMemoryInfoV2( + byte[] /*(const char*) */ name, + OrtMemoryInfoDeviceType memInfoDeviceType, + UInt32 /* uint32_t */ vendorId, + Int32 /* int32_t */ deviceId, + OrtDeviceMemoryType deviceMemoryType, + UIntPtr /* size_t */ alignment, + OrtAllocatorType allocatorType, + out IntPtr /*(OrtMemoryInfo*)*/ allocatorInfo // memory ownership transferred to caller + ); + + public static DOrtCreateMemoryInfoV2 OrtCreateMemoryInfoV2; + [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /* (OrtStatus*)*/ DOrtCreateCpuMemoryInfo( OrtAllocatorType allocatorType, @@ -1485,6 +2096,18 @@ out IntPtr lora_adapter public static DOrtMemoryInfoGetType OrtMemoryInfoGetType; + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate OrtDeviceMemoryType DOrtMemoryInfoGetDeviceMemType( + IntPtr /*(const OrtMemoryInfo* ptr)*/ memoryInfo); + + public static DOrtMemoryInfoGetDeviceMemType OrtMemoryInfoGetDeviceMemType; + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate UInt32 DOrtMemoryInfoGetVendorId( + IntPtr /*(const OrtMemoryInfo* ptr)*/ memoryInfo); + + public static DOrtMemoryInfoGetVendorId OrtMemoryInfoGetVendorId; + [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(OrtStatus*)*/ DOrtGetAllocatorWithDefaultOptions(out IntPtr /*(OrtAllocator**)*/ allocator); @@ -1561,9 +2184,9 @@ out IntPtr lora_adapter public static DOrtAllocatorFree OrtAllocatorFree; -#endregion Allocator / MemoryInfo API + #endregion Allocator / MemoryInfo API -#region IoBinding API + #region IoBinding API /// /// Create OrtIoBinding instance that is used to bind memory that is allocated @@ -1727,7 +2350,8 @@ out IntPtr lora_adapter /// /// Creates an allocator instance and registers it with the env to enable /// sharing between multiple sessions that use the same env instance. - /// Lifetime of the created allocator will be valid for the duration of the environment. + /// Lifetime of the created allocator will be valid for the duration of the environment + /// or until it is explicitly unregistered by UnregisterAllocator. /// Returns an error if an allocator with the same OrtMemoryInfo is already registered. /// /// Native OrtEnv instance @@ -1741,6 +2365,20 @@ out IntPtr lora_adapter public static DOrtCreateAndRegisterAllocator OrtCreateAndRegisterAllocator; + + /// + /// Unregisters an allocator that was previously registered with the env using + /// or . + /// + /// valid env + /// meminfo used for registering the allocator + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /*(OrtStatus*)*/ DOrtUnregisterAllocator(IntPtr /*(OrtEnv*)*/ env, + IntPtr /*(const OrtMemoryInfo*)*/ memInfo); + + public static DOrtUnregisterAllocator OrtUnregisterAllocator; + /// /// Set the language projection for collecting telemetry data when Env is created /// @@ -1751,9 +2389,9 @@ out IntPtr lora_adapter public static DOrtSetLanguageProjection OrtSetLanguageProjection; -#endregion IoBinding API + #endregion IoBinding API -#region ModelMetadata API + #region ModelMetadata API /// /// Gets the ModelMetadata associated with an InferenceSession @@ -1871,9 +2509,9 @@ out IntPtr lora_adapter public static DOrtReleaseModelMetadata OrtReleaseModelMetadata; -#endregion ModelMetadata API + #endregion ModelMetadata API -#region OrtValue API + #region OrtValue API [UnmanagedFunctionPointer(CallingConvention.Winapi)] public delegate IntPtr /*(OrtStatus*)*/ DOrtHasValue(IntPtr /*(OrtValue*)*/ value, out IntPtr /*(int*)*/ hasValue); @@ -1953,6 +2591,12 @@ out IntPtr lora_adapter public static DOrtGetTensorMutableData OrtGetTensorMutableData; + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /*(OrtStatus*)*/ DOrtGetTensorSizeInBytes(IntPtr /* const struct OrtValue*/ ortValue, + out UIntPtr /* size_t* */ tensorSizeInBytes); + + public static DOrtGetTensorSizeInBytes OrtGetTensorSizeInBytes; + /// \param value A tensor created from OrtCreateTensor... function. /// \param len total data length, not including the trailing '\0' chars. [UnmanagedFunctionPointer(CallingConvention.Winapi)] @@ -2133,9 +2777,427 @@ out IntPtr lora_adapter public static DOrtReleaseValue OrtReleaseValue; -#endregion + #endregion + + #region Compile API -#region Misc API +#if NETSTANDARD2_0 + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr DOrtGetCompileApi(); +#else + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate ref CompileApi.OrtCompileApi DOrtGetCompileApi(); +#endif + public static DOrtGetCompileApi OrtGetCompileApi; + + /// + /// Delegate called by ORT to write a buffer (ONNX model bytes) to a custom destination (e.g., file or stream). + /// + /// State that was provided in when the delegate was registered. + /// The buffer to write. + /// The size of the buffer in bytes. + /// OrtStatus* + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtWriteBufferToDestinationDelegate( + IntPtr /* void* */ state, + IntPtr /* const void* */ buffer, + UIntPtr /* size_t */ bufferNumBytes + ); + + /// + /// Function called by ORT to allow user to specify how an initializer should be saved while compiling + /// a model, that is, either written to an external file or stored within the model. ORT calls this function + /// for every initializer. + /// + /// State that was provided when the delegate was registered. + /// The initializer's name. + /// The OrtValue containing the initializer's data, type, and shape + /// The original initializer's location in an external file, or NULL. + /// Output parameter set to a new OrtExternalInitializerInfo instance + /// indicating the location where the function implementation stored the initializer data. If the function + /// implementation sets `newExternalInfo` to NULL, ORT stores the initializer within the generated model. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtGetInitializerLocationDelegate( + IntPtr /* void* */ state, + IntPtr /* const char* */ initializerName, + IntPtr /* const OrtValue* */ initializerValue, + IntPtr /* const OrtExternalInitializerInfo* */ externalInfo, + out IntPtr /* OrtExternalInitializerInfo** */ newExternalInfo + ); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate void DOrtReleaseExternalInitializerInfo(IntPtr /* OrtExternalInitializerInfo* */ info); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtCreateExternalInitializerInfo( + byte[] /* const ORTCHAR_T* */ filePath, + long /* int64_t */ fileOffset, + UIntPtr /* size_t */ byteSize, + out IntPtr /* OrtExternalInitializerInfo** */ outInfo); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* const ORTCHAR_T* */ DOrtExternalInitializerInfo_GetFilePath( + IntPtr /* const OrtExternalInitializerInfo* */ info); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate long /* int64_t */ DOrtExternalInitializerInfo_GetFileOffset( + IntPtr /* const OrtExternalInitializerInfo* */ info); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate UIntPtr /* size_t */ DOrtExternalInitializerInfo_GetByteSize( + IntPtr /* const OrtExternalInitializerInfo* */ info); + + public static DOrtReleaseExternalInitializerInfo OrtReleaseExternalInitializerInfo; + public static DOrtCreateExternalInitializerInfo OrtCreateExternalInitializerInfo; + public static DOrtExternalInitializerInfo_GetFilePath OrtExternalInitializerInfo_GetFilePath; + public static DOrtExternalInitializerInfo_GetFileOffset OrtExternalInitializerInfo_GetFileOffset; + public static DOrtExternalInitializerInfo_GetByteSize OrtExternalInitializerInfo_GetByteSize; + + #endregion + + #region Hardware Device EP Compatibility API + + /// + /// Get the number of available hardware devices. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtGetNumHardwareDevices( + IntPtr /* const OrtEnv* */ env, + out UIntPtr /* size_t* */ numDevices); + + /// + /// Get the list of available hardware devices. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtGetHardwareDevices( + IntPtr /* const OrtEnv* */ env, + [Out] IntPtr[] /* const OrtHardwareDevice** */ devices, + UIntPtr /* size_t */ numDevices); + + /// + /// Check for known incompatibility issues between hardware device and a specific execution provider. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtGetHardwareDeviceEpIncompatibilityDetails( + IntPtr /* const OrtEnv* */ env, + byte[] /* const char* */ epName, + IntPtr /* const OrtHardwareDevice* */ hw, + out IntPtr /* OrtDeviceEpIncompatibilityDetails** */ details); + + /// + /// Get the incompatibility reasons bitmask from OrtDeviceEpIncompatibilityDetails. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtDeviceEpIncompatibilityDetails_GetReasonsBitmask( + IntPtr /* const OrtDeviceEpIncompatibilityDetails* */ details, + out uint /* uint32_t* */ reasonsBitmask); + + /// + /// Get the notes from OrtDeviceEpIncompatibilityDetails. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtDeviceEpIncompatibilityDetails_GetNotes( + IntPtr /* const OrtDeviceEpIncompatibilityDetails* */ details, + out IntPtr /* const char** */ notes); + + /// + /// Get the EP-specific error code from OrtDeviceEpIncompatibilityDetails. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtDeviceEpIncompatibilityDetails_GetErrorCode( + IntPtr /* const OrtDeviceEpIncompatibilityDetails* */ details, + out int /* int32_t* */ errorCode); + + /// + /// Release an OrtDeviceEpIncompatibilityDetails instance. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate void DOrtReleaseDeviceEpIncompatibilityDetails(IntPtr /* OrtDeviceEpIncompatibilityDetails* */ details); + + public static DOrtGetNumHardwareDevices OrtGetNumHardwareDevices; + public static DOrtGetHardwareDevices OrtGetHardwareDevices; + public static DOrtGetHardwareDeviceEpIncompatibilityDetails OrtGetHardwareDeviceEpIncompatibilityDetails; + public static DOrtDeviceEpIncompatibilityDetails_GetReasonsBitmask OrtDeviceEpIncompatibilityDetails_GetReasonsBitmask; + public static DOrtDeviceEpIncompatibilityDetails_GetNotes OrtDeviceEpIncompatibilityDetails_GetNotes; + public static DOrtDeviceEpIncompatibilityDetails_GetErrorCode OrtDeviceEpIncompatibilityDetails_GetErrorCode; + public static DOrtReleaseDeviceEpIncompatibilityDetails OrtReleaseDeviceEpIncompatibilityDetails; + + #endregion + + #region Auto EP API related + // + // OrtKeyValuePairs + + /// + /// Create an OrtKeyValuePairs instance. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate void DOrtCreateKeyValuePairs(out IntPtr /* OrtKeyValuePairs** */ kvps); + + /// + /// Add/replace a key-value pair in the OrtKeyValuePairs instance. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate void DOrtAddKeyValuePair(IntPtr /* OrtKeyValuePairs* */ kvps, + byte[] /* const char* */ key, + byte[] /* const char* */ value); + + /// + /// Get the value for the provided key. + /// + /// Value. Returns IntPtr.Zero if key was not found. + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* const char* */ DOrtGetKeyValue(IntPtr /* const OrtKeyValuePairs* */ kvps, + byte[] /* const char* */ key); + + /// + /// Get all the key-value pairs in the OrtKeyValuePairs instance. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate void DOrtGetKeyValuePairs(IntPtr /* const OrtKeyValuePairs* */ kvps, + out IntPtr /* const char* const** */ keys, + out IntPtr /* const char* const** */ values, + out UIntPtr /* size_t* */ numEntries); + + /// + /// Remove a key-value pair from the OrtKeyValuePairs instance. + /// Ignores keys that are not present. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate void DOrtRemoveKeyValuePair(IntPtr /* OrtKeyValuePairs* */ kvps, + byte[] /* const char* */ key); + + /// + /// Release the OrtKeyValuePairs instance. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate void DOrtReleaseKeyValuePairs(IntPtr /* OrtKeyValuePairs* */ kvps); + + + public static DOrtCreateKeyValuePairs OrtCreateKeyValuePairs; + public static DOrtAddKeyValuePair OrtAddKeyValuePair; + public static DOrtGetKeyValue OrtGetKeyValue; + public static DOrtGetKeyValuePairs OrtGetKeyValuePairs; + public static DOrtRemoveKeyValuePair OrtRemoveKeyValuePair; + public static DOrtReleaseKeyValuePairs OrtReleaseKeyValuePairs; + + + // + // OrtHardwareDevice + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate int /* OrtHardwareDeviceType */ DOrtHardwareDevice_Type( + IntPtr /* const OrtHardwareDevice* */ device); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate uint /* uint32_t */ DOrtHardwareDevice_VendorId( + IntPtr /* const OrtHardwareDevice* */ device); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* const char* */ DOrtHardwareDevice_Vendor( + IntPtr /* const OrtHardwareDevice* */ device); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate uint /* uint32_t */ DOrtHardwareDevice_DeviceId( + IntPtr /* const OrtHardwareDevice* */ device); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* const OrtKeyValuePairs* */ DOrtHardwareDevice_Metadata( + IntPtr /* const OrtHardwareDevice* */ device); + + + public static DOrtHardwareDevice_Type OrtHardwareDevice_Type; + public static DOrtHardwareDevice_VendorId OrtHardwareDevice_VendorId; + public static DOrtHardwareDevice_Vendor OrtHardwareDevice_Vendor; + public static DOrtHardwareDevice_DeviceId OrtHardwareDevice_DeviceId; + public static DOrtHardwareDevice_Metadata OrtHardwareDevice_Metadata; + + // + // OrtEpDevice + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* const char* */ DOrtEpDevice_EpName(IntPtr /* const OrtEpDevice* */ ep_device); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* const char* */ DOrtEpDevice_EpVendor(IntPtr /* const OrtEpDevice* */ ep_device); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* const OrtKeyValuePairs* */ DOrtEpDevice_EpMetadata( + IntPtr /* const OrtEpDevice* */ ep_device); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* const OrtKeyValuePairs* */ DOrtEpDevice_EpOptions( + IntPtr /* const OrtEpDevice* */ ep_device); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* const OrtHardwareDevice* */ DOrtEpDevice_Device( + IntPtr /* const OrtEpDevice* */ ep_device); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* const OrtMemoryInfo* */ DOrtEpDevice_MemoryInfo( + IntPtr /* const OrtEpDevice* */ ep_device, OrtDeviceMemoryType deviceMemoryType); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtCreateSyncStreamForEpDevice( + IntPtr /* const OrtEpDevice* */ epDevice, + IntPtr /* const OrtKeyValuePairs* */ streamOptions, + out IntPtr /* OrtSyncStream** */ stream + ); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* void* */ DOrtSyncStream_GetHandle( + IntPtr /* OrtSyncStream* */ stream + ); + + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtReleaseSyncStream( + IntPtr /* OrtSyncStream* */ stream + ); + + public static DOrtEpDevice_EpName OrtEpDevice_EpName; + public static DOrtEpDevice_EpVendor OrtEpDevice_EpVendor; + public static DOrtEpDevice_EpMetadata OrtEpDevice_EpMetadata; + public static DOrtEpDevice_EpOptions OrtEpDevice_EpOptions; + public static DOrtEpDevice_Device OrtEpDevice_Device; + public static DOrtEpDevice_MemoryInfo OrtEpDevice_MemoryInfo; + public static DOrtCreateSyncStreamForEpDevice OrtCreateSyncStreamForEpDevice; + public static DOrtSyncStream_GetHandle OrtSyncStream_GetHandle; + public static DOrtReleaseSyncStream OrtReleaseSyncStream; + + // + // Auto Selection EP registration and selection customization + + /// + /// Register an execution provider library. + /// The library must implement CreateEpFactories and ReleaseEpFactory. + /// + /// Environment to add the EP library to. + /// Name to register the library under. + /// Absolute path to the library. + /// OrtStatus* + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtRegisterExecutionProviderLibrary( + IntPtr /* OrtEnv* */ env, + byte[] /* const char* */ registration_name, + byte[] /* const ORTCHAR_T* */ path); + + /// + /// Unregister an execution provider library. + /// + /// The environment to unregister the library from. + /// The name the library was registered under. + /// OrtStatus* + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtUnregisterExecutionProviderLibrary( + IntPtr /* OrtEnv* */ env, + byte[] /* const char* */ registration_name); + + public static DOrtRegisterExecutionProviderLibrary OrtRegisterExecutionProviderLibrary; + public static DOrtUnregisterExecutionProviderLibrary OrtUnregisterExecutionProviderLibrary; + + /// + /// Get the OrtEpDevices that are available. + /// These are all the possible execution provider and device pairs. + /// + /// OrtStatus* + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtGetEpDevices( + IntPtr /* const OrtEnv* */ env, + out IntPtr /* const OrtEpDevice* const** */ ep_devices, + out UIntPtr /* size_t* */ num_ep_devices); + + public static DOrtGetEpDevices OrtGetEpDevices; + + /// + /// Validate compiled model compatibility for the provided EP devices. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtGetModelCompatibilityForEpDevices( + IntPtr[] /* const OrtEpDevice* const* */ ep_devices, + UIntPtr /* size_t */ num_ep_devices, + byte[] /* const char* */ compatibility_info, + out int /* OrtCompiledModelCompatibility */ out_status); + + public static DOrtGetModelCompatibilityForEpDevices OrtGetModelCompatibilityForEpDevices; + + /// + /// Add execution provider devices to the session options. + /// Priority is based on the order of the OrtEpDevice instances. Highest priority first. + /// All OrtEpDevice instances in ep_devices must be for the same execution provider. + /// e.g. selecting OpenVINO for GPU and NPU would have an OrtEpDevice for GPU and NPU. + /// + /// SessionOptions to add to. + /// Environment that the OrtEpDevice instances came from by calling GetEpDevices + /// One or more OrtEpDevice instances. + /// Number of OrtEpDevice instances. + /// User overrides for execution provider options. May be IntPtr.Zero. + /// User overrides for execution provider options. May be IntPtr.Zero. + /// Number of user overrides for execution provider options. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtSessionOptionsAppendExecutionProvider_V2( + IntPtr /* OrtSessionOptions* */ sess_options, + IntPtr /* OrtEnv* */ env, + IntPtr[] /* const OrtEpDevice* const* */ ep_devices, + UIntPtr /* size_t */ num_ep_devices, + IntPtr /* const char* const* */ ep_option_keys, // use OrtKeyValuePairs.GetKeyValuePairHandles + IntPtr /* const char* const* */ ep_option_vals, + UIntPtr /* size_t */ num_ep_options); + + public static DOrtSessionOptionsAppendExecutionProvider_V2 OrtSessionOptionsAppendExecutionProvider_V2; + + /// + /// Delegate to do custom execution provider selection. + /// + /// Available OrtEpDevices to select from. + /// Number of OrtEpDevices. + /// Metadata from the ONNX model. + /// Runtime metadata. May be IntPtr.Zero. + /// OrtEpDevices that were selected. Pre-allocated array for delegate to update. + /// Maximum number of OrtEpDevices that can be selected. + /// Number of OrtEpDevices that were selected. + /// State that was provided in when the delegate was registered. + /// OrtStatus* + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr DOrtEpSelectionDelegate( + IntPtr /* OrtEpDevice** */ epDevices, + uint numDevices, + IntPtr /* OrtKeyValuePairs* */ modelMetadata, + IntPtr /* OrtKeyValuePairs* */ runtimeMetadata, + IntPtr /* OrtEpDevice** */ selected, + uint maxSelected, + out UIntPtr numSelected, + IntPtr /* void* */ state + ); + + /// + /// Set the execution provider selection policy. + /// + /// SessionOptions to set the policy for. + /// Selection policy. + /// OrtStatus* + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DSessionOptionsSetEpSelectionPolicy( + IntPtr /* OrtSessionOptions* */ session_options, + int /* OrtExecutionProviderDevicePolicy */ policy); + public static DSessionOptionsSetEpSelectionPolicy OrtSessionOptionsSetEpSelectionPolicy; + + /// + /// Set the execution provider selection policy delegate. + /// + /// SessionOptions to set the policy for. + /// Selection policy delegate. + /// State that is passed through to the selection delegate. + /// OrtStatus* + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DSessionOptionsSetEpSelectionPolicyDelegate( + IntPtr /* OrtSessionOptions* */ session_options, + IntPtr /* DOrtEpSelectionDelegate* */ selection_delegate, + IntPtr /* void* */ state); + public static DSessionOptionsSetEpSelectionPolicyDelegate OrtSessionOptionsSetEpSelectionPolicyDelegate; + + + #endregion + #region Misc API /// /// Queries all the execution providers supported in the native onnxruntime shared library @@ -2175,7 +3237,32 @@ out IntPtr lora_adapter public static DOrtReleasePrepackedWeightsContainer OrtReleasePrepackedWeightsContainer; -#endregion + /// + /// Extract EP compatibility info from a precompiled model file. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtGetCompatibilityInfoFromModel( + byte[] /* const ORTCHAR_T* */ model_path, + byte[] /* const char* */ ep_type, + IntPtr /* OrtAllocator* */ allocator, + out IntPtr /* char** */ compatibility_info); + + public static DOrtGetCompatibilityInfoFromModel OrtGetCompatibilityInfoFromModel; + + /// + /// Extract EP compatibility info from precompiled model bytes in memory. + /// + [UnmanagedFunctionPointer(CallingConvention.Winapi)] + public delegate IntPtr /* OrtStatus* */ DOrtGetCompatibilityInfoFromModelBytes( + byte[] /* const void* */ model_data, + UIntPtr /* size_t */ model_data_length, + byte[] /* const char* */ ep_type, + IntPtr /* OrtAllocator* */ allocator, + out IntPtr /* char** */ compatibility_info); + + public static DOrtGetCompatibilityInfoFromModelBytes OrtGetCompatibilityInfoFromModelBytes; + + #endregion } // class NativeMethods // onnxruntime-extensions helpers to make usage simpler. @@ -2190,6 +3277,9 @@ internal static class OrtExtensionsNativeMethods #elif __IOS__ internal const string ExtensionsDllName = "__Internal"; #else + // For desktop platforms, use the simple name to allow .NET's + // automatic platform-specific resolution (lib*.so, lib*.dylib, *.dll). + // Case-sensitivity on Windows is handled by DllImportResolver. internal const string ExtensionsDllName = "ortextensions"; #endif diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxValueHelper.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxValueHelper.shared.cs index fc14be00ee47b..f5dc253195ab1 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxValueHelper.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/NativeOnnxValueHelper.shared.cs @@ -150,6 +150,45 @@ internal static byte[] GetPlatformSerializedString(string str) else return StringToZeroTerminatedUtf8(str); } + + /// + /// Converts a null-terminated path string that is pointed to by the given IntPtr handle into + /// a C# UTF-16 string. + /// + /// A path string on Windows is utf-16, but utf-8 on other operating systems. + /// + /// + internal static string StringFromNativePathString(IntPtr strPtr) + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + if (strPtr == IntPtr.Zero) + { + return string.Empty; + } + + // Get length of utf16 string by checking for two 0 bytes in a row. + int length = 0; + while (Marshal.ReadInt16(strPtr, length * 2) != 0) + { + length += 1; + } + + if (length == 0) + { + return string.Empty; + } + + unsafe + { + return System.Text.Encoding.Unicode.GetString((byte*)strPtr, length * 2); + } + } + else + { + return StringFromNativeUtf8(strPtr); + } + } } // Guards an array of disposable objects on stack and disposes them in reverse order @@ -334,23 +373,21 @@ internal static void Update(Dictionary providerOptions, IntPtr handle, Func updateFunc) { - var keyStrings = providerOptions.Keys.ToArray(); - var valStrings = providerOptions.Values.ToArray(); - MarshaledStringArray keys = default; MarshaledStringArray values = default; try { - keys = new MarshaledStringArray(keyStrings); - values = new MarshaledStringArray(valStrings); + keys = new MarshaledStringArray(providerOptions.Keys); + values = new MarshaledStringArray(providerOptions.Values); - var nativeKeys = new IntPtr[keyStrings.Length]; + var nativeKeys = new IntPtr[providerOptions.Count]; keys.Fill(nativeKeys); - var nativeVals = new IntPtr[valStrings.Length]; + var nativeVals = new IntPtr[providerOptions.Count]; values.Fill(nativeVals); - NativeApiStatus.VerifySuccess(updateFunc(handle, nativeKeys, nativeVals, (UIntPtr)providerOptions.Count)); + NativeApiStatus.VerifySuccess(updateFunc(handle, nativeKeys, nativeVals, + (UIntPtr)providerOptions.Count)); } finally { diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtAllocator.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtAllocator.shared.cs index 3f918fc2ad6c8..c189cc1856252 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtAllocator.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtAllocator.shared.cs @@ -3,6 +3,7 @@ using Microsoft.ML.OnnxRuntime.Tensors; using System; +using System.Reflection; using System.Runtime.InteropServices; using System.Text; @@ -28,6 +29,28 @@ public enum OrtMemType Default = 0, // the default allocator for execution provider } + /// + /// See documentation for OrtDeviceMemoryType in C API + /// This matches OrtDevice::MemoryType values + /// + public enum OrtDeviceMemoryType + { + DEFAULT = 0, /// Device memory + HOST_ACCESSIBLE = 5, /// Shared/pinned memory for transferring between CPU and the device + } + + /// + /// See documentation for OrtMemoryInfoDeviceType in C API + /// This mimics OrtDevice type constants so they can be returned in the API + /// + public enum OrtMemoryInfoDeviceType + { + CPU = 0, + GPU = 1, + FPGA = 2, + NPU = 3, + } + /// /// This class encapsulates arena configuration information that will be used to define the behavior /// of an arena based allocator @@ -103,7 +126,8 @@ public class OrtMemoryInfo : SafeHandle private static OrtMemoryInfo CreateCpuMemoryInfo() { // Returns OrtMemoryInfo instance that needs to be disposed - NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateCpuMemoryInfo(OrtAllocatorType.DeviceAllocator, OrtMemType.Cpu, out IntPtr memoryInfo)); + NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateCpuMemoryInfo(OrtAllocatorType.DeviceAllocator, + OrtMemType.Cpu, out IntPtr memoryInfo)); return new OrtMemoryInfo(memoryInfo, true); } @@ -203,6 +227,26 @@ public OrtMemoryInfo(byte[] utf8AllocatorName, OrtAllocatorType allocatorType, i public OrtMemoryInfo(string allocatorName, OrtAllocatorType allocatorType, int deviceId, OrtMemType memoryType) : this(NativeOnnxValueHelper.StringToZeroTerminatedUtf8(allocatorName), allocatorType, deviceId, memoryType) { + + } + + /// + /// Creates an instance of OrtMemoryInfo using OrtCreateMemoryInfoV2 + /// + /// In this overload this is an arbitrary name + /// Device Type + /// Vendor Id + /// Device Id + /// Device Memory Type + /// Alignment is required or 0 + /// Allocator Type + public OrtMemoryInfo(string allocatorName, OrtMemoryInfoDeviceType deviceType, uint vendorId, + int deviceId, OrtDeviceMemoryType deviceMemoryType, ulong alignment, OrtAllocatorType allocatorType) + : base(IntPtr.Zero, true) + { + NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateMemoryInfoV2( + NativeOnnxValueHelper.StringToZeroTerminatedUtf8(allocatorName), + deviceType, vendorId, deviceId, deviceMemoryType, (UIntPtr)alignment, allocatorType, out handle)); } /// @@ -252,6 +296,24 @@ public OrtAllocatorType GetAllocatorType() return allocatorType; } + /// + /// Return the device memory type associated with this memory info + /// + /// OrtDeviceMemoryType for the device + public OrtDeviceMemoryType GetDeviceMemoryType() + { + return NativeMethods.OrtMemoryInfoGetDeviceMemType(handle); + } + + /// + /// Fetches vendor ID + /// + /// uint32_t + public uint GetVendorId() + { + return NativeMethods.OrtMemoryInfoGetVendorId(handle); + } + /// /// Overrides System.Object.Equals(object) /// @@ -493,12 +555,6 @@ internal IntPtr Pointer } } - /// - /// Overrides SafeHandle.IsInvalid - /// - /// returns true if handle is equal to Zero - public override bool IsInvalid { get { return handle == IntPtr.Zero; } } - /// /// Internal constructor wraps existing native allocators /// @@ -560,6 +616,14 @@ internal void FreeMemory(IntPtr allocation) } #region SafeHandle + + /// + /// Overrides SafeHandle.IsInvalid + /// + /// returns true if handle is equal to Zero + public override bool IsInvalid { get { return handle == IntPtr.Zero; } } + + /// /// Overrides SafeHandle.ReleaseHandle() to properly dispose of /// the native instance of OrtAllocator diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtEnv.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtEnv.shared.cs index f4b2649f8d055..5edc4466f9b5b 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtEnv.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtEnv.shared.cs @@ -2,10 +2,47 @@ // Licensed under the MIT License. using System; +using System.Collections.Generic; using System.Runtime.InteropServices; namespace Microsoft.ML.OnnxRuntime { + /// + /// Represents the compatibility status of a pre-compiled model with one or more execution provider devices. + /// + /// + /// This enum is used to determine whether a pre-compiled model can be used with specific execution providers + /// and devices, or if recompilation is needed. + /// + public enum OrtCompiledModelCompatibility + { + EP_NOT_APPLICABLE = 0, + EP_SUPPORTED_OPTIMAL = 1, + EP_SUPPORTED_PREFER_RECOMPILATION = 2, + EP_UNSUPPORTED = 3, + } + + /// + /// Reasons why an execution provider might not be compatible with a device. + /// + /// + /// This is a flags enum. Multiple reasons can be combined using bitwise OR. + /// + [Flags] + public enum OrtDeviceEpIncompatibilityReason : uint + { + /// No incompatibility. + None = 0, + /// Driver is incompatible with the execution provider. + DriverIncompatible = 1 << 0, + /// Device itself is incompatible with the execution provider. + DeviceIncompatible = 1 << 1, + /// Required dependency is missing. + MissingDependency = 1 << 2, + /// Unknown incompatibility reason. + Unknown = 1u << 31 + } + /// /// Delegate for logging function callback. /// Supply your function and register it with the environment to receive logging callbacks via @@ -61,14 +98,14 @@ public struct EnvironmentCreationOptions /// /// The singleton class OrtEnv contains the process-global ONNX Runtime environment. /// It sets up logging, creates system wide thread-pools (if Thread Pool options are provided) - /// and other necessary things for OnnxRuntime to function. - /// + /// and other necessary things for OnnxRuntime to function. + /// /// Create or access OrtEnv by calling the Instance() method. Instance() can be called multiple times. /// It would return the same instance. - /// + /// /// CreateInstanceWithOptions() provides a way to create environment with options. /// It must be called once before Instance() is called, otherwise it would not have effect. - /// + /// /// If the environment is not explicitly created, it will be created as needed, e.g., /// when creating a SessionOptions instance. /// @@ -77,6 +114,28 @@ public sealed class OrtEnv : SafeHandle #region Static members private static readonly int ORT_PROJECTION_CSHARP = 2; + /// + /// Set this to true before accessing any OnnxRuntime type to prevent OnnxRuntime + /// from registering its own DllImportResolver via + /// NativeLibrary.SetDllImportResolver. + /// This is useful when the host application needs to register its own custom resolver + /// for the OnnxRuntime assembly. Must be set before any OnnxRuntime API is used + /// (i.e., before the internal NativeMethods static constructor runs). + /// + /// + /// + /// // Disable OnnxRuntime's built-in resolver before any ORT usage + /// OrtEnv.DisableDllImportResolver = true; + /// + /// // Register your own resolver + /// NativeLibrary.SetDllImportResolver(typeof(OrtEnv).Assembly, MyCustomResolver); + /// + /// // Now use OnnxRuntime normally + /// var env = OrtEnv.Instance(); + /// + /// + public static bool DisableDllImportResolver { get; set; } = false; + private static readonly byte[] _defaultLogId = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(@"CSharpOnnxRuntime"); // This must be static and set before the first creation call, otherwise, has no effect. @@ -258,7 +317,7 @@ private static void SetLanguageProjection(OrtEnv env) /// /// Instantiates (if not already done so) a new OrtEnv instance with the default logging level /// and no other options. Otherwise returns the existing instance. - /// + /// /// It returns the same instance on every call - `OrtEnv` is singleton /// /// Returns a singleton instance of OrtEnv that represents native OrtEnv object @@ -313,14 +372,115 @@ public void DisableTelemetryEvents() } /// - /// Create and register an allocator to the OrtEnv instance - /// so as to enable sharing across all sessions using the OrtEnv instance + /// Create and register an allocator to the OrtEnv instance. + /// This API enhance CreateAndRegisterAllocator that it can create an allocator with specific type, not just CPU allocator + /// Enables sharing the allocator between multiple sessions that use the same env instance. + /// Lifetime of the created allocator will be valid for the duration of the environment. + /// so as to enable sharing across all sessions using the OrtEnv instance. /// OrtMemoryInfo instance to be used for allocator creation /// OrtArenaCfg instance that will be used to define the behavior of the arena based allocator /// public void CreateAndRegisterAllocator(OrtMemoryInfo memInfo, OrtArenaCfg arenaCfg) { - NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateAndRegisterAllocator(Handle, memInfo.Pointer, arenaCfg.Pointer)); + NativeApiStatus.VerifySuccess( + NativeMethods.OrtCreateAndRegisterAllocator(Handle, memInfo.Pointer, arenaCfg.Pointer)); + } + + /// + /// Create and register an allocator to the OrtEnv instance. + /// Use UnregisterAllocator to unregister it. + /// + /// + /// + /// + /// + public void CreateAndRegisterAllocator(string providerType, OrtMemoryInfo memInfo, OrtArenaCfg arenaCfg, + IReadOnlyDictionary provider_options) + { + MarshaledStringArray marshalledKeys = default; + MarshaledStringArray marshalledValues = default; + var keysPtrs = new IntPtr[provider_options.Count]; + var valuesPtrs = new IntPtr[provider_options.Count]; + + try + { + marshalledKeys = new MarshaledStringArray(provider_options.Keys); + marshalledValues = new MarshaledStringArray(provider_options.Values); + marshalledKeys.Fill(keysPtrs); + marshalledValues.Fill(valuesPtrs); + using var marshalledProviderType = new MarshaledString(providerType); + + NativeApiStatus.VerifySuccess( + NativeMethods.OrtCreateAndRegisterAllocatorV2(Handle, marshalledProviderType.Value, + memInfo.Pointer, arenaCfg.Pointer, + keysPtrs, valuesPtrs, + (UIntPtr)provider_options.Count)); + } + finally + { + marshalledValues.Dispose(); + marshalledKeys.Dispose(); + } + } + + /// + /// Unregister a custom allocator previously registered with the OrtEnv instance + /// using CreateAndRegisterAllocator + /// The memory info instance should correspond the one that is used for registration + /// + /// The memory info instance should correspond the one that is used for registration + public void UnregisterAllocator(OrtMemoryInfo memInfo) + { + NativeApiStatus.VerifySuccess( + NativeMethods.OrtUnregisterAllocator(Handle, memInfo.Pointer)); + } + + /// + /// Creates shared allocator owned by the OrtEnv instance. + /// + /// + /// + /// + /// allocator specific options + /// OrtAllocator instance + public OrtAllocator CreateSharedAllocator(OrtEpDevice epDevice, OrtDeviceMemoryType deviceMemoryType, + OrtAllocatorType ortAllocatorType, IReadOnlyDictionary allocatorOptions) + { + using var keyValueOptions = new OrtKeyValuePairs(allocatorOptions); + NativeApiStatus.VerifySuccess( + NativeMethods.OrtCreateSharedAllocator(Handle, epDevice.Handle, deviceMemoryType, + ortAllocatorType, keyValueOptions.Handle, out IntPtr allocatorHandle)); + return new OrtAllocator(allocatorHandle, /* owned= */ false); + } + + /// + /// Returns a shared allocator owned by the OrtEnv instance if such exists + /// (was previously created). If no such allocator exists, the API returns null. + /// + /// + /// OrtAllocator instance or null if the requested allocator does not exist + public OrtAllocator GetSharedAllocator(OrtMemoryInfo memoryInfo) + { + NativeApiStatus.VerifySuccess( + NativeMethods.OrtGetSharedAllocator(Handle, memoryInfo.Pointer, out IntPtr allocatorHandle)); + if (allocatorHandle == IntPtr.Zero) + { + return null; + } + return new OrtAllocator(allocatorHandle, /* owned= */ false); + } + + /// + /// Release a shared allocator from the OrtEnv for the OrtEpDevice and memory type. + /// This will release the shared allocator for the given OrtEpDevice and memory type. + /// If no shared allocator exists, this is a no-op. + /// + /// + /// + public void ReleaseSharedAllocator(OrtEpDevice epDevice, OrtDeviceMemoryType deviceMemoryType) + { + NativeApiStatus.VerifySuccess( + NativeMethods.OrtReleaseSharedAllocator(Handle, epDevice.Handle, deviceMemoryType)); } /// @@ -360,6 +520,170 @@ public string[] GetAvailableProviders() } } + /// + /// Validate a compiled model's compatibility information for one or more EP devices. + /// + /// The list of EP devices to validate against. + /// The compatibility string from the precompiled model to validate. + /// OrtCompiledModelCompatibility enum value denoting the compatibility status + public OrtCompiledModelCompatibility GetModelCompatibilityForEpDevices( + IReadOnlyList epDevices, string compatibilityInfo) + { + if (epDevices == null || epDevices.Count == 0) + throw new ArgumentException("epDevices must be non-empty", nameof(epDevices)); + + var devicePtrs = new IntPtr[epDevices.Count]; + for (int i = 0; i < epDevices.Count; ++i) + { + devicePtrs[i] = epDevices[i].Handle; + } + + var infoUtf8 = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(compatibilityInfo); + NativeApiStatus.VerifySuccess( + NativeMethods.OrtGetModelCompatibilityForEpDevices( + devicePtrs, (UIntPtr)devicePtrs.Length, infoUtf8, out int status)); + return (OrtCompiledModelCompatibility)status; + } + + /// + /// Extract EP compatibility info from a precompiled model file. + /// + /// + /// Parses the model file to extract the compatibility info string for a specific execution provider + /// from the model's metadata properties. This is only applicable to models that have been precompiled + /// for an EP. Standard ONNX models do not contain this information. + /// The compatibility info can then be passed to to + /// check if a precompiled model is compatible with the current system. + /// + /// Path to the ONNX model file. + /// The execution provider type string. Use to get this value. + /// The compatibility info string, or null if no compatibility info exists for the specified EP. + /// If modelPath or epType is null or empty. + /// If the model file cannot be read or parsed. + public string GetCompatibilityInfoFromModel(string modelPath, string epType) + { + if (string.IsNullOrEmpty(modelPath)) + throw new ArgumentException("modelPath must be non-empty", nameof(modelPath)); + if (string.IsNullOrEmpty(epType)) + throw new ArgumentException("epType must be non-empty", nameof(epType)); + + var allocator = OrtAllocator.DefaultInstance; + var pathBytes = NativeOnnxValueHelper.GetPlatformSerializedString(modelPath); + var epTypeUtf8 = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(epType); + + NativeApiStatus.VerifySuccess( + NativeMethods.OrtGetCompatibilityInfoFromModel( + pathBytes, epTypeUtf8, allocator.Pointer, out IntPtr compatInfoPtr)); + + if (compatInfoPtr == IntPtr.Zero) + return null; + + return NativeOnnxValueHelper.StringFromNativeUtf8(compatInfoPtr, allocator); + } + + /// + /// Extract EP compatibility info from precompiled model bytes in memory. + /// + /// + /// Same as but reads from a memory buffer instead of a file. + /// Useful when precompiled models are loaded from encrypted storage, network, or other non-file sources. + /// + /// The model data bytes. + /// The execution provider type string. Use to get this value. + /// The compatibility info string, or null if no compatibility info exists for the specified EP. + /// If modelData is null/empty or epType is null or empty. + /// If the model data cannot be parsed. + public string GetCompatibilityInfoFromModelBytes(byte[] modelData, string epType) + { + if (modelData == null || modelData.Length == 0) + throw new ArgumentException("modelData must be non-empty", nameof(modelData)); + if (string.IsNullOrEmpty(epType)) + throw new ArgumentException("epType must be non-empty", nameof(epType)); + + var allocator = OrtAllocator.DefaultInstance; + var epTypeUtf8 = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(epType); + + NativeApiStatus.VerifySuccess( + NativeMethods.OrtGetCompatibilityInfoFromModelBytes( + modelData, (UIntPtr)modelData.Length, epTypeUtf8, + allocator.Pointer, out IntPtr compatInfoPtr)); + + if (compatInfoPtr == IntPtr.Zero) + return null; + + return NativeOnnxValueHelper.StringFromNativeUtf8(compatInfoPtr, allocator); + } + + /// + /// Get the number of available hardware devices. + /// + /// The number of hardware devices discovered on the system. + public int GetNumHardwareDevices() + { + NativeApiStatus.VerifySuccess( + NativeMethods.OrtGetNumHardwareDevices(Handle, out UIntPtr numDevices)); + return checked((int)numDevices); + } + + /// + /// Get the list of available hardware devices. + /// + /// A list of OrtHardwareDevice objects. The underlying native handles are owned by ORT and should not be released. + public IReadOnlyList GetHardwareDevices() + { + NativeApiStatus.VerifySuccess( + NativeMethods.OrtGetNumHardwareDevices(Handle, out UIntPtr numDevices)); + + int count = checked((int)numDevices); + if (count == 0) + { + return Array.Empty(); + } + + var devicePtrs = new IntPtr[count]; + NativeApiStatus.VerifySuccess( + NativeMethods.OrtGetHardwareDevices(Handle, devicePtrs, numDevices)); + + var devices = new OrtHardwareDevice[count]; + for (int i = 0; i < count; i++) + { + devices[i] = new OrtHardwareDevice(devicePtrs[i]); + } + return devices; + } + + /// + /// Check for known incompatibility issues between a hardware device and a specific execution provider. + /// + /// The name of the execution provider to check. + /// The hardware device to check for incompatibility. + /// Details about incompatibility including reasons and notes. + /// + /// This method can be used with built-in execution providers without calling + /// RegisterExecutionProviderLibrary. + /// For execution providers supplied by external libraries, the provider library must be + /// registered before calling this method. + /// If the returned details have non-zero reasons, the device is not compatible. + /// However, zero reasons don't guarantee 100% compatibility for all models. + /// + public OrtDeviceEpIncompatibilityDetails GetHardwareDeviceEpIncompatibilityDetails( + string epName, OrtHardwareDevice hardwareDevice) + { + if (epName == null) + throw new ArgumentNullException(nameof(epName)); + if (epName.Length == 0) + throw new ArgumentException("epName must be non-empty", nameof(epName)); + if (hardwareDevice == null) + throw new ArgumentNullException(nameof(hardwareDevice)); + + var epNameUtf8 = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(epName); + NativeApiStatus.VerifySuccess( + NativeMethods.OrtGetHardwareDeviceEpIncompatibilityDetails( + Handle, epNameUtf8, hardwareDevice.Handle, out IntPtr details)); + + return new OrtDeviceEpIncompatibilityDetails(details); + } + /// /// Get/Set log level property of OrtEnv instance @@ -376,6 +700,98 @@ public OrtLoggingLevel EnvLogLevel } } + /// + /// Register an execution provider library with the OrtEnv instance. + /// A registered execution provider library can be used by all sessions created with the OrtEnv instance. + /// Devices the execution provider can utilize are added to the values returned by GetEpDevices() and can + /// be used in SessionOptions.AppendExecutionProvider to select an execution provider for a device. + /// + /// Coming: A selection policy can be specified and ORT will automatically select the best execution providers + /// and devices for the model. + /// + /// The name to register the library under. + /// The path to the library to register. + /// + /// + public void RegisterExecutionProviderLibrary(string registrationName, string libraryPath) + { + var registrationNameUtf8 = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(registrationName); + var pathUtf8 = NativeOnnxValueHelper.GetPlatformSerializedString(libraryPath); + + NativeApiStatus.VerifySuccess( + NativeMethods.OrtRegisterExecutionProviderLibrary(handle, registrationNameUtf8, pathUtf8)); + } + + /// + /// Unregister an execution provider library from the OrtEnv instance. + /// + /// The name the library was registered under. + public void UnregisterExecutionProviderLibrary(string registrationName) + { + var registrationNameUtf8 = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(registrationName); + + NativeApiStatus.VerifySuccess( + NativeMethods.OrtUnregisterExecutionProviderLibrary(handle, registrationNameUtf8)); + } + + /// + /// Get the list of all execution provider and device combinations that are available. + /// These can be used to select the execution provider and device for a session. + /// + /// + /// + /// + public IReadOnlyList GetEpDevices() + { + IntPtr epDevicesPtr; + UIntPtr numEpDevices; + + NativeApiStatus.VerifySuccess(NativeMethods.OrtGetEpDevices(handle, out epDevicesPtr, out numEpDevices)); + + int count = (int)numEpDevices; + var epDevices = new List(count); + + IntPtr[] epDevicePtrs = new IntPtr[count]; + Marshal.Copy(epDevicesPtr, epDevicePtrs, 0, count); + + foreach (var ptr in epDevicePtrs) + { + epDevices.Add(new OrtEpDevice(ptr)); + } + + return epDevices.AsReadOnly(); + } + + /// + /// Copies data from source OrtValue tensors to destination OrtValue tensors. + /// The tensors may reside on difference devices if such are supported + /// by the registered execution providers. + /// + /// Source OrtValues + /// pre-allocated OrtValues + /// optional stream or null + /// + public void CopyTensors(IReadOnlyList srcValues, IReadOnlyList dstValues, + OrtSyncStream stream) + { + IntPtr streamHandle = stream != null ? stream.Handle : IntPtr.Zero; + IntPtr[] srcPtrs = new IntPtr[srcValues.Count]; + IntPtr[] dstPtrs = new IntPtr[dstValues.Count]; + + for (int i = 0; i < srcPtrs.Length; i++) + { + if (srcValues[i] == null) + throw new ArgumentNullException($"srcValues[{i}]"); + if (dstValues[i] == null) + throw new ArgumentNullException($"dstValues[{i}]"); + srcPtrs[i] = srcValues[i].Handle; + dstPtrs[i] = dstValues[i].Handle; + } + + NativeApiStatus.VerifySuccess( + NativeMethods.OrtCopyTensors(handle, srcPtrs, dstPtrs, streamHandle, (UIntPtr)srcPtrs.Length)); + } + #endregion #region SafeHandle overrides @@ -413,4 +829,120 @@ protected override bool ReleaseHandle() } #endregion } + + /// + /// Contains details about why an execution provider is incompatible with a hardware device. + /// + /// + /// This class wraps the native OrtDeviceEpIncompatibilityDetails object. + /// Use the properties to query specific incompatibility information. + /// + public sealed class OrtDeviceEpIncompatibilityDetails : IDisposable + { + private IntPtr _handle; + private bool _disposed = false; + + /// + /// Creates a new OrtDeviceEpIncompatibilityDetails wrapper. + /// + /// The native handle to wrap. + internal OrtDeviceEpIncompatibilityDetails(IntPtr handle) + { + _handle = handle; + } + + /// + /// Gets the bitmask of incompatibility reasons. + /// + /// + /// If this value is 0 (None), there are no known incompatibility issues. + /// However, this doesn't guarantee 100% compatibility for all models. + /// + public OrtDeviceEpIncompatibilityReason ReasonsBitmask + { + get + { + if (_disposed) + throw new ObjectDisposedException(nameof(OrtDeviceEpIncompatibilityDetails)); + + NativeApiStatus.VerifySuccess( + NativeMethods.OrtDeviceEpIncompatibilityDetails_GetReasonsBitmask(_handle, out uint bitmask)); + return (OrtDeviceEpIncompatibilityReason)bitmask; + } + } + + /// + /// Gets human-readable notes about the incompatibility. + /// + /// + /// May be null if no notes are available. + /// + public string Notes + { + get + { + if (_disposed) + throw new ObjectDisposedException(nameof(OrtDeviceEpIncompatibilityDetails)); + + NativeApiStatus.VerifySuccess( + NativeMethods.OrtDeviceEpIncompatibilityDetails_GetNotes(_handle, out IntPtr notesPtr)); + + if (notesPtr == IntPtr.Zero) + return null; + + return NativeOnnxValueHelper.StringFromNativeUtf8(notesPtr); + } + } + + /// + /// Gets the EP-specific error code. + /// + /// + /// This allows Independent Hardware Vendors (IHVs) to define their own error codes + /// to provide additional details about device incompatibility. + /// A value of 0 indicates no error code was set. + /// + public int ErrorCode + { + get + { + if (_disposed) + throw new ObjectDisposedException(nameof(OrtDeviceEpIncompatibilityDetails)); + + NativeApiStatus.VerifySuccess( + NativeMethods.OrtDeviceEpIncompatibilityDetails_GetErrorCode(_handle, out int errorCode)); + return errorCode; + } + } + + /// + /// Disposes the native resources. + /// + public void Dispose() + { + Dispose(true); + GC.SuppressFinalize(this); + } + + private void Dispose(bool disposing) + { + if (!_disposed) + { + if (_handle != IntPtr.Zero) + { + NativeMethods.OrtReleaseDeviceEpIncompatibilityDetails(_handle); + _handle = IntPtr.Zero; + } + _disposed = true; + } + } + + /// + /// Finalizer. + /// + ~OrtDeviceEpIncompatibilityDetails() + { + Dispose(false); + } + } } diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtEpDevice.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtEpDevice.shared.cs new file mode 100644 index 0000000000000..9e59754374464 --- /dev/null +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtEpDevice.shared.cs @@ -0,0 +1,167 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; + +namespace Microsoft.ML.OnnxRuntime +{ + /// + /// Represents a synchronization primitive for stream operations. + /// + public class OrtSyncStream : SafeHandle + { + internal OrtSyncStream(IntPtr streamHandle) + : base(IntPtr.Zero, true) // Provide required arguments to SafeHandle constructor + { + handle = streamHandle; + } + + /// + /// Fetch sync stream handle for possible use + /// in session options. + /// + /// Opaque stream handle + public IntPtr GetHandle() + { + return NativeMethods.OrtSyncStream_GetHandle(handle); + } + + internal IntPtr Handle => handle; + + /// + /// Implements SafeHandle interface + /// + public override bool IsInvalid => handle == IntPtr.Zero; + + /// + /// Implements SafeHandle interface to release native handle + /// + /// always true + protected override bool ReleaseHandle() + { + NativeMethods.OrtReleaseSyncStream(handle); + handle = IntPtr.Zero; + return true; + } + } + + /// + /// Represents the combination of an execution provider and a hardware device + /// that the execution provider can utilize. + /// + public class OrtEpDevice + { + /// + /// Construct an OrtEpDevice from an existing native OrtEpDevice instance. + /// + /// Native OrtEpDevice handle. + internal OrtEpDevice(IntPtr epDeviceHandle) + { + _handle = epDeviceHandle; + } + + internal IntPtr Handle => _handle; + + /// + /// The name of the execution provider. + /// + public string EpName + { + get + { + IntPtr namePtr = NativeMethods.OrtEpDevice_EpName(_handle); + return NativeOnnxValueHelper.StringFromNativeUtf8(namePtr); + } + } + + /// + /// The vendor who owns the execution provider. + /// + public string EpVendor + { + get + { + IntPtr vendorPtr = NativeMethods.OrtEpDevice_EpVendor(_handle); + return NativeOnnxValueHelper.StringFromNativeUtf8(vendorPtr); + } + } + + /// + /// Execution provider metadata. + /// + public OrtKeyValuePairs EpMetadata + { + get + { + return new OrtKeyValuePairs(NativeMethods.OrtEpDevice_EpMetadata(_handle)); + } + } + + /// + /// Execution provider options. + /// + public OrtKeyValuePairs EpOptions + { + get + { + return new OrtKeyValuePairs(NativeMethods.OrtEpDevice_EpOptions(_handle)); + } + } + + /// + /// The hardware device that the execution provider can utilize. + /// + public OrtHardwareDevice HardwareDevice + { + get + { + IntPtr devicePtr = NativeMethods.OrtEpDevice_Device(_handle); + return new OrtHardwareDevice(devicePtr); + } + } + + /// + /// The OrtMemoryInfo instance describing the memory characteristics of the device. + /// + /// memory type requested + /// + public OrtMemoryInfo GetMemoryInfo(OrtDeviceMemoryType deviceMemoryType) + { + IntPtr memoryInfoPtr = NativeMethods.OrtEpDevice_MemoryInfo(_handle, deviceMemoryType); + return new OrtMemoryInfo(memoryInfoPtr, /* owned= */ false); + } + + /// + /// Creates a synchronization stream for operations on this device. + /// Can be used to implement async operations on the device such as + /// CopyTensors. + /// + /// stream options can be null + /// + public OrtSyncStream CreateSyncStream(IReadOnlyDictionary streamOptions) + { + OrtKeyValuePairs options = null; + IntPtr optionsHandle = IntPtr.Zero; + try + { + if (streamOptions != null) + { + options = new OrtKeyValuePairs(streamOptions); + optionsHandle = options.Handle; + } + + NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateSyncStreamForEpDevice(_handle, + optionsHandle, out IntPtr syncStream)); + return new OrtSyncStream(syncStream); + } + finally + { + options?.Dispose(); + } + } + + private readonly IntPtr _handle; + } +} \ No newline at end of file diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtExternalInitializerInfo.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtExternalInitializerInfo.shared.cs new file mode 100644 index 0000000000000..aca16e939ce21 --- /dev/null +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtExternalInitializerInfo.shared.cs @@ -0,0 +1,136 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +namespace Microsoft.ML.OnnxRuntime +{ + using System; + using System.Diagnostics; + using System.Runtime.InteropServices; + + /// + /// Class to that stores information about the file location where an "external" initializer is stored. + /// + /// + public class OrtExternalInitializerInfo : SafeHandle, IReadOnlyExternalInitializerInfo + { + // Set to false when constructed with an externally managed constant handle owned by ORT. + private readonly bool _ownsHandle = true; + + /// + /// Create a new OrtExternalInitializerInfo instance. + /// + /// The path to the file that stores the initializer data. + /// The byte offset in the file where the data is stored. + /// The size of the data (in bytes) within the file. + public OrtExternalInitializerInfo(string filePath, long fileOffset, long byteSize) + : base(IntPtr.Zero, ownsHandle: true) + { + var platformFilePath = NativeOnnxValueHelper.GetPlatformSerializedString(filePath); + NativeApiStatus.VerifySuccess( + NativeMethods.OrtCreateExternalInitializerInfo(platformFilePath, fileOffset, (UIntPtr)byteSize, out handle)); + _ownsHandle = true; + } + + /// + /// Create a new OrtExternalInitializerInfo instance from an existing native OrtExternalInitializerInfo handle. + /// + /// Native OrtExternalInitializerInfo handle. + /// True if the OrtExternalInitializerInfo instance owns the native handle. + /// Defaults to false. + internal OrtExternalInitializerInfo(IntPtr constHandle, bool ownsHandle = false) + : base(IntPtr.Zero, ownsHandle) + { + Debug.Assert(constHandle != IntPtr.Zero); + SetHandle(constHandle); + _ownsHandle = ownsHandle; + } + + /// + /// Get the file path to the file that store's the initializer's data. + /// + /// + /// The path is relative to the filesystem directory where the ONNX model was stored. + /// + /// The file path. + public string GetFilePath() + { + IntPtr filePathPtr = NativeMethods.OrtExternalInitializerInfo_GetFilePath(handle); + if (filePathPtr == IntPtr.Zero) + { + return string.Empty; + } + + return NativeOnnxValueHelper.StringFromNativePathString(filePathPtr); + } + + /// + /// Get the byte offset within the file where the initializer's data is stored. + /// + /// The file offset location. + public long GetFileOffset() + { + return NativeMethods.OrtExternalInitializerInfo_GetFileOffset(handle); + } + + /// + /// Get the size in bytes of the initializer's data within the file. + /// + /// The size in bytes of the initializer data. + public long GetByteSize() + { + UIntPtr byteSize = NativeMethods.OrtExternalInitializerInfo_GetByteSize(handle); + return checked((long)byteSize); + } + + /// + /// Indicates whether the native handle is invalid. + /// + public override bool IsInvalid { get { return handle == IntPtr.Zero; } } + + /// + /// Release the native instance of OrtExternalInitializerInfo if we own it. + /// + /// true on success and false on error. + protected override bool ReleaseHandle() + { + if (!_ownsHandle) + { + // Return false to indicate an error. + // ReleaseHandle() should not be called on a const handle that this class does not own. + return false; + } + + NativeMethods.OrtReleaseExternalInitializerInfo(handle); + handle = IntPtr.Zero; + return true; + } + } + + /// + /// Interface for all readonly methods implemented by OrtExternalInitializerInfo. + /// + public interface IReadOnlyExternalInitializerInfo + { + /// + /// Get the file path to the file that store's the initializer's data. + /// + /// + /// The path is relative to the filesystem directory where the ONNX model was stored. + /// + /// The file path. + string GetFilePath(); + + /// + /// Get the byte offset within the file where the initializer's data is stored. + /// + /// The file offset location. + long GetFileOffset(); + + /// + /// Get the size in bytes of the initializer's data within the file. + /// + /// The size in bytes of the initializer data. + long GetByteSize(); + } +} \ No newline at end of file diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtHardwareDevice.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtHardwareDevice.shared.cs new file mode 100644 index 0000000000000..a1cfd9eedb154 --- /dev/null +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtHardwareDevice.shared.cs @@ -0,0 +1,109 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +namespace Microsoft.ML.OnnxRuntime +{ + using System; + using System.Runtime.InteropServices; + + /// + /// Represents the type of hardware device. + /// Matches OrtHardwareDeviceType in the ORT C API. + /// + public enum OrtHardwareDeviceType + { + CPU = 0, + GPU = 1, + NPU = 2, + } + + /// + /// Represents a hardware device that is available on the current system. + /// + public class OrtHardwareDevice + { + + /// + /// Construct an OrtHardwareDevice for a native OrtHardwareDevice instance. + /// + /// Native OrtHardwareDevice handle. + internal OrtHardwareDevice(IntPtr deviceHandle) + { + _handle = deviceHandle; + } + + /// + /// Get the type of hardware device. + /// + public OrtHardwareDeviceType Type + { + get + { + return (OrtHardwareDeviceType)NativeMethods.OrtHardwareDevice_Type(_handle); + } + } + + /// + /// Get the vendor ID of the hardware device if known. + /// + /// + /// For PCIe devices the vendor ID is the PCIe vendor ID. See https://pcisig.com/membership/member-companies. + /// + public uint VendorId + { + get + { + return NativeMethods.OrtHardwareDevice_VendorId(_handle); + } + } + + /// + /// The vendor (manufacturer) of the hardware device. + /// + public string Vendor + { + get + { + IntPtr vendorPtr = NativeMethods.OrtHardwareDevice_Vendor(_handle); + return NativeOnnxValueHelper.StringFromNativeUtf8(vendorPtr); + } + } + + /// + /// Get the device ID of the hardware device if known. + /// + /// + /// This is the identifier of the device model. + /// PCIe device IDs can be looked up at https://www.pcilookup.com/ when combined with the VendorId. + /// It is NOT a unique identifier for the device in the current system. + /// + public uint DeviceId + { + get + { + return NativeMethods.OrtHardwareDevice_DeviceId(_handle); + } + } + + /// + /// Get device metadata. + /// This may include information such as whether a GPU is discrete or integrated. + /// The available metadata will differ by platform and device type. + /// + public OrtKeyValuePairs Metadata + { + get + { + return new OrtKeyValuePairs(NativeMethods.OrtHardwareDevice_Metadata(_handle)); + } + } + + private readonly IntPtr _handle; + + /// + /// Gets the native handle for internal use. + /// + internal IntPtr Handle => _handle; + } +} \ No newline at end of file diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtKeyValuePairs.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtKeyValuePairs.shared.cs new file mode 100644 index 0000000000000..50fd1965231e1 --- /dev/null +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtKeyValuePairs.shared.cs @@ -0,0 +1,197 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + + +namespace Microsoft.ML.OnnxRuntime +{ + using System; + using System.Collections.Generic; + using System.Runtime.InteropServices; + + /// + /// Class to manage key-value pairs. + /// These are most often used for options and metadata. + /// + /// + /// + /// + public class OrtKeyValuePairs : SafeHandle + { + private readonly bool _createdHandle; + + // cache the values here for convenience. + // we could force a call to the C API every time in case something was changed in the background. + private Dictionary _keyValuePairs; + + /// + /// Create a new OrtKeyValuePairs instance. + /// + /// + /// A backing native instance is created and kept in sync with the C# content. + /// + public OrtKeyValuePairs() + : base(IntPtr.Zero, ownsHandle: true) + { + NativeMethods.OrtCreateKeyValuePairs(out handle); + _createdHandle = true; + _keyValuePairs = new Dictionary(); + } + + /// + /// Create a new OrtKeyValuePairs instance from an existing native OrtKeyValuePairs handle. + /// + /// Native OrtKeyValuePairs handle. + /// + /// The instance is read-only, so calling Add or Remove will throw an InvalidOperationError. + /// + internal OrtKeyValuePairs(IntPtr constHandle) + : base(constHandle, ownsHandle: false) + { + _createdHandle = false; + _keyValuePairs = GetLatest(); + } + + /// + /// Create a new OrtKeyValuePairs instance from a dictionary. + /// + /// Key-value pairs to add. + /// + /// A backing native instance is created and kept in sync with the C# content. + /// + public OrtKeyValuePairs(IReadOnlyDictionary keyValuePairs) + : base(IntPtr.Zero, ownsHandle: true) + { + NativeMethods.OrtCreateKeyValuePairs(out handle); + _createdHandle = true; + _keyValuePairs = new Dictionary(keyValuePairs != null ? keyValuePairs.Count : 0); + + if (keyValuePairs != null && keyValuePairs.Count > 0) + { + foreach (var kvp in keyValuePairs) + { + Add(kvp.Key, kvp.Value); + } + } + } + + /// + /// Current key-value pair entries. + /// + /// + /// Call Refresh() to update the cached values with the latest from the backing native instance. + /// In general that should not be required as it's not expected an OrtKeyValuePairs instance would be + /// updated by both native and C# code. + /// + public IReadOnlyDictionary Entries => _keyValuePairs; + + /// + /// Adds a key-value pair. Overrides any existing value for the key. + /// + /// Key to add. Must not be null or empty. + /// Value to add. May be empty. Must not be null. + public void Add(string key, string value) + { + if (!_createdHandle) + { + throw new InvalidOperationException($"{nameof(Add)} can only be called on instances you created."); + } + + var keyPtr = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(key); + var valuePtr = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(value); + NativeMethods.OrtAddKeyValuePair(handle, keyPtr, valuePtr); + _keyValuePairs[key] = value; // update the cached value + } + + /// + /// Update the cached values with the latest from the backing native instance as that is the source of truth. + /// + public void Refresh() + { + // refresh the cached values. + _keyValuePairs = GetLatest(); + } + + /// + /// Removes a key-value pair by key. Ignores keys that do not exist. + /// + /// Key to remove. + public void Remove(string key) + { + if (!_createdHandle) + { + throw new InvalidOperationException($"{nameof(Remove)} can only be called on instances you created."); + } + + var keyPtr = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(key); + NativeMethods.OrtRemoveKeyValuePair(handle, keyPtr); + + _keyValuePairs.Remove(key); // update the cached value + } + + // for internal usage to pass into the call to OrtSessionOptionsAppendExecutionProvider_V2 + // from SessionOptions::AppendExecutionProvider + internal void GetKeyValuePairHandles(out IntPtr keysHandle, out IntPtr valuesHandle, out UIntPtr numEntries) + { + if (IsInvalid) + { + throw new InvalidOperationException($"{nameof(GetKeyValuePairHandles)}: Invalid instance."); + } + + NativeMethods.OrtGetKeyValuePairs(handle, out keysHandle, out valuesHandle, out numEntries); + } + + /// + /// Fetch all the key/value pairs to make sure we are in sync with the C API. + /// + private Dictionary GetLatest() + { + var dict = new Dictionary(); + if (IsInvalid) + { + return dict; + } + + IntPtr keys, values; + UIntPtr numEntries; + NativeMethods.OrtGetKeyValuePairs(handle, out keys, out values, out numEntries); + + ulong count = numEntries.ToUInt64(); + int offset = 0; + for (ulong i = 0; i < count; i++, offset += IntPtr.Size) + { + IntPtr keyPtr = Marshal.ReadIntPtr(keys, offset); + IntPtr valuePtr = Marshal.ReadIntPtr(values, offset); + var key = NativeOnnxValueHelper.StringFromNativeUtf8(keyPtr); + var value = NativeOnnxValueHelper.StringFromNativeUtf8(valuePtr); + dict.Add(key, value); + } + + return dict; + } + + /// + /// Native handle to the OrtKeyValuePairs instance. + /// + internal IntPtr Handle => handle; + + /// + /// Indicates whether the native handle is invalid. + /// + public override bool IsInvalid { get { return handle == IntPtr.Zero; } } + + /// + /// Release the native instance of OrtKeyValuePairs if we own it. + /// + /// true + protected override bool ReleaseHandle() + { + if (_createdHandle) + { + NativeMethods.OrtReleaseKeyValuePairs(handle); + handle = IntPtr.Zero; + } + + return true; + } + } +} \ No newline at end of file diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtLoraAdapter.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtLoraAdapter.shared.cs index e2249b4c47fec..f1c03faccf16f 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtLoraAdapter.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtLoraAdapter.shared.cs @@ -23,7 +23,7 @@ public static OrtLoraAdapter Create(string adapterPath, OrtAllocator ortAllocato { var platformPath = NativeOnnxValueHelper.GetPlatformSerializedString(adapterPath); var allocatorHandle = (ortAllocator != null) ? ortAllocator.Pointer : IntPtr.Zero; - NativeApiStatus.VerifySuccess(NativeMethods.CreateLoraAdapter(platformPath, allocatorHandle, + NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateLoraAdapter(platformPath, allocatorHandle, out IntPtr adapterHandle)); return new OrtLoraAdapter(adapterHandle); } @@ -38,7 +38,7 @@ public static OrtLoraAdapter Create(string adapterPath, OrtAllocator ortAllocato public static OrtLoraAdapter Create(byte[] bytes, OrtAllocator ortAllocator) { var allocatorHandle = (ortAllocator != null) ? ortAllocator.Pointer : IntPtr.Zero; - NativeApiStatus.VerifySuccess(NativeMethods.CreateLoraAdapterFromArray(bytes, + NativeApiStatus.VerifySuccess(NativeMethods.OrtCreateLoraAdapterFromArray(bytes, new UIntPtr((uint)bytes.Length), allocatorHandle, out IntPtr adapterHandle)); return new OrtLoraAdapter(adapterHandle); } @@ -71,7 +71,7 @@ internal IntPtr Handle /// always returns true protected override bool ReleaseHandle() { - NativeMethods.ReleaseLoraAdapter(handle); + NativeMethods.OrtReleaseLoraAdapter(handle); handle = IntPtr.Zero; return true; } diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.shared.cs index 7a5c3aaa19eac..d848c63450ec1 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/OrtValue.shared.cs @@ -33,6 +33,147 @@ public enum OnnxValueType ONNX_TYPE_OPTIONAL = 6, // It's an optional type that designates anything above (except UNKNOWN) } + /// + /// Interface for all readonly methods implemented by OrtValue. + /// + public interface IReadOnlyOrtValue + { + /// + /// Get the ONNX value type for the OrtValue (e.g., OnnxValueType.ONNX_TYPE_TENSOR). + /// + /// OnnxValueType + OnnxValueType OnnxType { get; } + + /// + /// Returns true if OrtValue contains a tensor + /// + /// true if tensor + bool IsTensor { get; } + + /// + /// Returns true if OrtValue contains a sparse tensor + /// + /// true if sparse tensor + bool IsSparseTensor { get; } + + /// + /// Returns type information about the contained OnnxValue. + /// + /// a disposable instance of OrtTypeInfo + OrtTypeInfo GetTypeInfo(); + + /// + /// Obtains Tensor And Type Information from the OrtValue iff it contains a tensor. + /// Valid only for OrtValues that contain a tensor. + /// + /// A disposable instance of OrtTensorTypeAndShapeInfo + OrtTensorTypeAndShapeInfo GetTensorTypeAndShape(); + + /// + /// Returns the size of the tensor data in bytes. + /// + /// size of the tensor data in bytes + long GetTensorSizeInBytes(); + + /// + /// Returns OrtMemoryInfo iff this OrtValue contains a tensor or a sparse tensor. + /// + /// OrtMemoryInfo that describes the underlying memory allocation + /// + OrtMemoryInfo GetTensorMemoryInfo(); + + /// + /// Returns a ReadOnlySpan over tensor native buffer that + /// provides a read-only view. + /// + /// Note, that the memory may be device allocated and, therefore, not accessible from the CPU. + /// To get memory descriptor use GetTensorMemoryInfo(). + /// + /// OrtValue must contain a non-string tensor. + /// The span is valid as long as the OrtValue instance is alive (not disposed). + /// + /// + /// ReadOnlySpan + /// + ReadOnlySpan GetTensorDataAsSpan() where T : unmanaged; + +#if NET8_0_OR_GREATER + /// + /// Returns a ReadOnlyTensorSpan over tensor native buffer that + /// provides a read-only view. + /// + /// Note, that the memory may be device allocated and, therefore, not accessible from the CPU. + /// To get memory descriptor use GetTensorMemoryInfo(). + /// + /// OrtValue must contain a non-string tensor. + /// The span is valid as long as the OrtValue instance is alive (not disposed). + /// + /// + /// ReadOnlySpan + /// + [Experimental("SYSLIB5001")] + SystemNumericsTensors.ReadOnlyTensorSpan GetTensorDataAsTensorSpan() where T : unmanaged; +#endif + + /// + /// Valid for composite ML types like map, sequence. + /// Returns 2 for map (keys, values) and N for sequence, where N is the number of elements + /// in the sequence. + /// + /// Element count + int GetValueCount(); + + /// + /// For non tensors return OrtValue element at the specified index. + /// For maps only indices 0 and 1 are valid. For sequences, [0..N) are valid. + /// See GetValueCount() to determine the valid range. + /// + /// + /// allocator to use + /// OrtValue disposable instance that points to the corresponding element of the composite type + OrtValue GetValue(int index, OrtAllocator allocator); + + /// + /// Fetch string tensor element buffer pointer at the specified index, + /// convert/copy to UTF-16 char[] and return a ReadOnlyMemory{char} instance. + /// + /// Obtain TensorTypeAndShape to get shape and element count. + /// + /// flat string tensor element index + /// ReadOnlyMemory{char} backed by a managed char[]. Its lifespan is not + /// tied to the native buffer of OrtValue. + ReadOnlyMemory GetStringElementAsMemory(int index); + + /// + /// Fetch string tensor element buffer pointer at the specified index, + /// copy/convert UTF-8 into a UTF-16 string and return it. + /// + /// Obtain TensorTypeAndShape to get shape and element count. + /// + /// flat string tensor element index + /// UTF-16 string instance + string GetStringElement(int index); + + /// + /// Get a span over the native memory of the string tensor element. + /// The span is valid as long as the OrtValue is valid. + /// + /// This is useful if you want to perform your own UTF-8 decoding or + /// you do not care about decoding. + /// Obtain TensorTypeAndShape to get shape and element count. + /// + /// flat element index + /// ReadOnlySpan over UTF-8 bytes of the string tensor element + ReadOnlySpan GetStringElementAsSpan(int index); + + /// + /// Convenience method to obtain all string tensor elements as a string array. + /// + /// string[] + /// + string[] GetStringTensorAsArray(); + } + /// /// Represents a disposable OrtValue. /// This class exposes a native instance of OrtValue. @@ -44,7 +185,7 @@ public enum OnnxValueType /// disposed properly, the pinned memory will continue to be pinned and interfere /// with GC operation. /// - public class OrtValue : IOrtValueOwner, IDisposable + public class OrtValue : IOrtValueOwner, IDisposable, IReadOnlyOrtValue { // OrtValues that are members of Sequences or Maps that map. They potentially map managed memory and we need to keep them around. // this exists only when we deal with compose ML types. @@ -52,11 +193,20 @@ public class OrtValue : IOrtValueOwner, IDisposable private IntPtr _handle; private MemoryHandle? _memHandle; // Present when the OrtValue is created on top of managed memory private bool _disposed; + private bool _owned = true; - internal OrtValue(IntPtr handle) + /// + /// Constructs OrtValue from a native handle. If `owned` is true, the OrtValue instance takes + /// ownership of the native handle and disposes it when the OrtValue instance is disposed. + /// + /// The native OrtValue handle. + /// True if this class instance owns the handle. If false, the handle + /// will not be released. Defaults to true. + internal OrtValue(IntPtr handle, bool owned = true) { _handle = handle; InitOnnxType(); + _owned = owned; } /// @@ -312,6 +462,17 @@ public SystemNumericsTensors.TensorSpan GetTensorSpanMutableRawData() w } #endif + /// + /// This API computes and returns the size of the tensor data in bytes. + /// + /// size of the tensor data in bytes + public long GetTensorSizeInBytes() + { + // The native API verifies that this is a non-string tensor + NativeApiStatus.VerifySuccess(NativeMethods.OrtGetTensorSizeInBytes(Handle, out UIntPtr size)); + return (long)size; + } + /// /// Fetch string tensor element buffer pointer at the specified index, /// convert/copy to UTF-16 char[] and return a ReadOnlyMemory{char} instance. @@ -689,8 +850,8 @@ public static OrtValue CreateTensorValueFromMemory(T[] data, long[] shape) wh /// The method will attempt to pin managed memory so no copying occurs when data is passed down /// to native code. /// - /// Tensor object - /// discovered tensor element type + /// + /// Tensor object /// And instance of OrtValue constructed on top of the object [Experimental("SYSLIB5001")] public static OrtValue CreateTensorValueFromSystemNumericsTensorObject(SystemNumericsTensors.Tensor tensor) where T : unmanaged @@ -1357,7 +1518,7 @@ public static OrtValue CreateMapWithStringValues(K[] keys, IReadOnlyCollectio /// This API helps the user to process a map OrtValue without /// having to deal with the lifespan of intermediate OrtValues. /// - /// each API value is fed to the vistor functor. + /// each API value is fed to the visitor functor. /// /// visitor function /// Allocator to use for intermediate values @@ -1453,7 +1614,10 @@ protected virtual void Dispose(bool disposing) } Debug.Assert(_handle != IntPtr.Zero); - NativeMethods.OrtReleaseValue(_handle); + if (_owned) + { + NativeMethods.OrtReleaseValue(_handle); + } _handle = IntPtr.Zero; _disposed = true; } diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs index bd450451a1265..6e325f7fe9646 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/SessionOptions.shared.cs @@ -17,6 +17,7 @@ public enum GraphOptimizationLevel ORT_DISABLE_ALL = 0, ORT_ENABLE_BASIC = 1, ORT_ENABLE_EXTENDED = 2, + ORT_ENABLE_LAYOUT = 3, ORT_ENABLE_ALL = 99 } @@ -32,6 +33,21 @@ public enum ExecutionMode ORT_PARALLEL = 1, } + /// + /// Controls the execution provider selection when using automatic EP selection. + /// Execution providers must be registered with the OrtEnv to be available for selection. + /// + public enum ExecutionProviderDevicePolicy + { + DEFAULT = 0, + PREFER_CPU = 1, + PREFER_NPU, + PREFER_GPU, + MAX_PERFORMANCE, + MAX_EFFICIENCY, + MIN_OVERALL_POWER, + } + /// /// Holds the options for creating an InferenceSession /// It forces the instantiation of the OrtEnv singleton. @@ -408,6 +424,82 @@ public void AppendExecutionProvider(string providerName, Dictionary + /// Select execution providers from the list of available execution providers and devices returned by + /// GetEpDevices. + /// + /// One or more OrtEpDevice instances may be provided in epDevices, but must all be for the same + /// execution provider. + /// + /// Make multiple calls to AppendExecutionProvider if you wish to use multiple execution providers. + /// + /// e.g. + /// - if execution provider 'A' has an OrtEpDevice for NPU and one for GPU and you wish to use it for + /// both devices, pass the two OrtEpDevice instances in the epDevices list in one call. + /// - if you wish to use execution provider 'B' for GPU and execution provider 'C' for CPU, + /// make two calls to AppendExecutionProvider, with one OrtEpDevice in the epDevices list in each call. + /// + /// The priority of the execution providers is set by the order in which they are appended. + /// Highest priority is first. + /// + /// OrtEnv that provided the OrtEpDevice instances via a call to GetEpDevices. + /// One or more OrtEpDevice instances to append. + /// These must all have the save EpName value. + /// Optional options to configure the execution provider. May be null. + /// epDevices was empty. + /// + public void AppendExecutionProvider(OrtEnv env, IReadOnlyList epDevices, + IReadOnlyDictionary epOptions) + { + if (epDevices == null || epDevices.Count == 0) + { + throw new ArgumentException("No execution provider devices were specified."); + } + + // Convert EpDevices to native pointers + IntPtr[] epDevicePtrs = new IntPtr[epDevices.Count]; + for (int i = 0; i < epDevices.Count; i++) + { + epDevicePtrs[i] = epDevices[i].Handle; + } + + if (epOptions != null && epOptions.Count > 0) + { + // this creates an OrtKeyValuePairs instance with a backing native instance + using var kvps = new OrtKeyValuePairs(epOptions); + + // get the native key/value handles so we can pass those straight through to the C API + // and not have to do any special marshaling here. + IntPtr epOptionsKeys, epOptionsValues; + UIntPtr epOptionsCount; + kvps.GetKeyValuePairHandles(out epOptionsKeys, out epOptionsValues, out epOptionsCount); + + NativeApiStatus.VerifySuccess( + NativeMethods.OrtSessionOptionsAppendExecutionProvider_V2( + handle, + env.Handle, + epDevicePtrs, + (UIntPtr)epDevices.Count, + epOptionsKeys, + epOptionsValues, + epOptionsCount)); + } + else + { + NativeApiStatus.VerifySuccess( + NativeMethods.OrtSessionOptionsAppendExecutionProvider_V2( + handle, + env.Handle, + epDevicePtrs, + (UIntPtr)epDevices.Count, + IntPtr.Zero, // EP options keys + IntPtr.Zero, // EP options values + UIntPtr.Zero)); // EP options count + } + + } + #endregion //ExecutionProviderAppends #region Public Methods @@ -452,8 +544,8 @@ public void RegisterCustomOpLibraryV2(string libraryPath, out IntPtr libraryHand // End result of that is // SessionOptions.RegisterCustomOpLibrary calls NativeMethods.OrtRegisterCustomOpsLibrary_V2 // SessionOptions.RegisterCustomOpLibraryV2 calls NativeMethods.OrtRegisterCustomOpsLibrary - var utf8Path = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(libraryPath); - NativeApiStatus.VerifySuccess(NativeMethods.OrtRegisterCustomOpsLibrary(handle, utf8Path, + var platformPath = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(libraryPath); + NativeApiStatus.VerifySuccess(NativeMethods.OrtRegisterCustomOpsLibrary(handle, platformPath, out libraryHandle)); } @@ -536,6 +628,41 @@ public void AddFreeDimensionOverrideByName(string dimName, long dimValue) var utf8 = NativeOnnxValueHelper.StringToZeroTerminatedUtf8(dimName); NativeApiStatus.VerifySuccess(NativeMethods.OrtAddFreeDimensionOverrideByName(handle, utf8, dimValue)); } + + /// + /// Set the execution provider selection policy if using automatic execution provider selection. + /// Execution providers must be registered with the OrtEnv to be available for selection. + /// + /// Policy to use. + public void SetEpSelectionPolicy(ExecutionProviderDevicePolicy policy) + { + NativeApiStatus.VerifySuccess( + NativeMethods.OrtSessionOptionsSetEpSelectionPolicy(handle, (int)policy)); + } + + /// + /// Set the execution provider selection policy if using automatic execution provider selection. + /// Execution providers must be registered with the OrtEnv to be available for selection. + /// + /// Delegate that implements the custom selection policy. + public void SetEpSelectionPolicyDelegate(EpSelectionDelegate selectionDelegate = null) + { + _epSelectionPolicyConnector = new EpSelectionPolicyConnector(selectionDelegate); + _epSelectionPolicyDelegate = new NativeMethods.DOrtEpSelectionDelegate( + EpSelectionPolicyConnector.EpSelectionPolicyWrapper); + + // make sure these stay alive. not sure if this is necessary when they're class members though + _epSelectionPolicyConnectorHandle = GCHandle.Alloc(_epSelectionPolicyConnector); + _epSelectionPolicyDelegateHandle = GCHandle.Alloc(_epSelectionPolicyDelegate); + + IntPtr funcPtr = Marshal.GetFunctionPointerForDelegate(_epSelectionPolicyDelegate); + + NativeApiStatus.VerifySuccess( + NativeMethods.OrtSessionOptionsSetEpSelectionPolicyDelegate( + handle, + funcPtr, + GCHandle.ToIntPtr(_epSelectionPolicyConnectorHandle))); + } #endregion internal IntPtr Handle @@ -802,6 +929,129 @@ public ExecutionMode ExecutionMode } private ExecutionMode _executionMode = ExecutionMode.ORT_SEQUENTIAL; + /// + /// Sets the load cancellation flag for the session. Default is set to false. + /// Provides an opportunity for the user to cancel model loading. + /// + /// true to request cancellation, false to proceed + public void SetLoadCancellationFlag(bool value) + { + NativeApiStatus.VerifySuccess(NativeMethods.OrtSessionOptionsSetLoadCancellationFlag(handle, value)); + } + #endregion + + #region Selection Policy Delegate helpers + /// + /// Delegate to select execution provider devices from a list of available devices. + /// + /// OrtEpDevices to select from. + /// Model metadata. + /// Runtime metadata. + /// Maximum number of devices that can be selected. + /// Selected devices. Ordered by priority. Highest priority first. + public delegate List EpSelectionDelegate(IReadOnlyList epDevices, + OrtKeyValuePairs modelMetadata, + OrtKeyValuePairs runtimeMetadata, + uint maxSelections); + + /// + /// Class to bridge the C# and native worlds for the EP selection policy delegate + /// + internal class EpSelectionPolicyConnector + { + private readonly EpSelectionDelegate _csharpDelegate; + + internal EpSelectionPolicyConnector(EpSelectionDelegate selectionDelegate) + { + _csharpDelegate = selectionDelegate; + } + + /// + /// Delegate to convert between the C and C# worlds + /// + /// OrtEpDevices to select from. + /// Number of OrtEpDevices. + /// Model metadata. + /// Runtime metadata. + /// Pre-allocated OrtEpDevice buffer to update with selected devices. + /// Number of entries in selectedOut. + /// Number of OrtEpDevies that were selected. + /// Opaque state. + /// nullptr for OrtStatus* to indicate success. + /// Currently we don't have a way to create an OrtStatus instance from the C# bindings. + /// Can add if we need to return an explicit error message. + /// + public static IntPtr EpSelectionPolicyWrapper(IntPtr /* OrtEpDevice** */ epDevicesIn, + uint numDevices, + IntPtr /* OrtKeyValuePairs* */ modelMetadataIn, + IntPtr /* OrtKeyValuePairs* */ runtimeMetadataIn, + IntPtr /* OrtEpDevice** */ selectedOut, + uint maxSelected, + out UIntPtr numSelected, + IntPtr state) + { + numSelected = UIntPtr.Zero; + + try + { + + Span epDevicesIntPtrs; + Span selectedDevicesIntPtrs; + EpSelectionPolicyConnector connector = (EpSelectionPolicyConnector)GCHandle.FromIntPtr(state).Target; + + unsafe + { + void* ptr = epDevicesIn.ToPointer(); + epDevicesIntPtrs = new Span(ptr, checked((int)numDevices)); + } + + List epDevices = new List(); + for (int i = 0; i < numDevices; i++) + { + + epDevices.Add(new OrtEpDevice(epDevicesIntPtrs[i])); + } + + OrtKeyValuePairs modelMetadata = new OrtKeyValuePairs(modelMetadataIn); + OrtKeyValuePairs runtimeMetadata = new OrtKeyValuePairs(runtimeMetadataIn); + + var selected = connector._csharpDelegate(epDevices, modelMetadata, runtimeMetadata, maxSelected); + + if (selected.Count > maxSelected) + { + var error = $"The number of selected devices ({selected.Count}) returned by " + + $"the C# selection delegate exceeds the maximum ({maxSelected})."; + IntPtr status = NativeMethods.OrtCreateStatus((uint)ErrorCode.Fail, + NativeOnnxValueHelper.StringToZeroTerminatedUtf8(error)); + return status; + } + + numSelected = (UIntPtr)selected.Count; + + unsafe + { + void* ptr = selectedOut.ToPointer(); + selectedDevicesIntPtrs = new Span(ptr, (int)maxSelected); + } + + int idx = 0; + foreach (var epDevice in selected) + { + selectedDevicesIntPtrs[idx] = epDevice.Handle; + idx++; + } + } + catch (Exception ex) + { + var error = $"The C# selection delegate threw an exception: {ex.Message}"; + IntPtr status = NativeMethods.OrtCreateStatus((uint)ErrorCode.Fail, + NativeOnnxValueHelper.StringToZeroTerminatedUtf8(error)); + return status; + } + + return IntPtr.Zero; + } + } #endregion #region Private Methods @@ -887,8 +1137,43 @@ protected override bool ReleaseHandle() { NativeMethods.OrtReleaseSessionOptions(handle); handle = IntPtr.Zero; + + if (_epSelectionPolicyConnectorHandle.IsAllocated) + { + _epSelectionPolicyConnectorHandle.Free(); + _epSelectionPolicyConnector = null; + } + + if (_epSelectionPolicyDelegateHandle.IsAllocated) + { + _epSelectionPolicyDelegateHandle.Free(); + _epSelectionPolicyDelegate = null; + } + + return true; } #endregion + + /// + /// Helper class to connect C and C# usage of the EP selection policy delegate. + /// + EpSelectionPolicyConnector _epSelectionPolicyConnector = null; + + /// + /// Handle to the EP selection policy connector that is passed to the C API as state for the + /// EP selection policy delegate. + /// + GCHandle _epSelectionPolicyConnectorHandle = default; + + /// + /// Delegate instance that is provided to the C API. + /// + NativeMethods.DOrtEpSelectionDelegate _epSelectionPolicyDelegate = null; + + /// + /// Handle to the EP selection policy delegate that is passed to the C API. + /// + GCHandle _epSelectionPolicyDelegateHandle = default; } } diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/ArrayUtilities.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/ArrayUtilities.shared.cs index 025c1331ce54d..a0c1a0a150365 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/ArrayUtilities.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/ArrayUtilities.shared.cs @@ -179,7 +179,7 @@ public static void GetIndices(ReadOnlySpan strides, bool reverseStride, int } /// - /// Calculates the n-d indices from the 1-d index in a layout specificed by strides + /// Calculates the n-d indices from the 1-d index in a layout specified by strides /// /// /// diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/Tensor.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/Tensor.shared.cs index e927b8105c6c9..9de80a15942e4 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/Tensor.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/Tensors/Tensor.shared.cs @@ -68,7 +68,7 @@ public class TensorTypeInfo /// Ctor /// /// TensorElementType value - /// size fo the type in bytes + /// size of the type in bytes public TensorTypeInfo(TensorElementType elementType, int typeSize) { ElementType = elementType; @@ -674,7 +674,7 @@ public Tensor GetDiagonal(int offset) // the diagonal will be the length of the smaller axis // if offset it positive, the length will shift along the second axis - // if the offsett is negative, the length will shift along the first axis + // if the offset is negative, the length will shift along the first axis // In that way the length of the diagonal will be // Min(offset < 0 ? axisLength0 + offset : axisLength0, offset > 0 ? axisLength1 - offset : axisLength1) // To illustrate, consider the following @@ -907,21 +907,21 @@ public virtual T this[ReadOnlySpan indices] } /// - /// Gets the value at the specied index, where index is a linearized version of n-dimension indices using strides. + /// Gets the value at the specified index, where index is a linearized version of n-dimension indices using strides. /// /// An integer index computed as a dot-product of indices. /// The value at the specified position in this Tensor. public abstract T GetValue(int index); /// - /// Sets the value at the specied index, where index is a linearized version of n-dimension indices using strides. + /// Sets the value at the specified index, where index is a linearized version of n-dimension indices using strides. /// /// An integer index computed as a dot-product of indices. /// The new value to set at the specified position in this Tensor. public abstract void SetValue(int index, T value); - #region statics + #region statistics /// /// Performs a value comparison of the content and shape of two tensors. Two tensors are equal if they have the same shape and same value at every set of indices. If not equal a tensor is greater or less than another tensor based on the first non-equal element when enumerating in linear order. /// diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs b/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs index b4067806c5f93..7756250608ff9 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs +++ b/csharp/src/Microsoft.ML.OnnxRuntime/Training/NativeTrainingMethods.shared.cs @@ -76,7 +76,7 @@ static NativeTrainingMethods() DOrtGetApi OrtGetApi = (DOrtGetApi)Marshal.GetDelegateForFunctionPointer(NativeMethods.OrtGetApiBase().GetApi, typeof(DOrtGetApi)); #endif - const uint ORT_API_VERSION = 21; + const uint ORT_API_VERSION = 26; #if NETSTANDARD2_0 IntPtr ortApiPtr = OrtGetApi(ORT_API_VERSION); api_ = (OrtApi)Marshal.PtrToStructure(ortApiPtr, typeof(OrtApi)); diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-android/targets.xml b/csharp/src/Microsoft.ML.OnnxRuntime/targets/net9.0-android/targets.xml similarity index 100% rename from csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-android/targets.xml rename to csharp/src/Microsoft.ML.OnnxRuntime/targets/net9.0-android/targets.xml diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-ios/targets.xml b/csharp/src/Microsoft.ML.OnnxRuntime/targets/net9.0-ios/targets.xml similarity index 100% rename from csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-ios/targets.xml rename to csharp/src/Microsoft.ML.OnnxRuntime/targets/net9.0-ios/targets.xml diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-maccatalyst/README.md b/csharp/src/Microsoft.ML.OnnxRuntime/targets/net9.0-maccatalyst/README.md similarity index 100% rename from csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-maccatalyst/README.md rename to csharp/src/Microsoft.ML.OnnxRuntime/targets/net9.0-maccatalyst/README.md diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-maccatalyst/_._ b/csharp/src/Microsoft.ML.OnnxRuntime/targets/net9.0-maccatalyst/_._ similarity index 100% rename from csharp/src/Microsoft.ML.OnnxRuntime/targets/net8.0-maccatalyst/_._ rename to csharp/src/Microsoft.ML.OnnxRuntime/targets/net9.0-maccatalyst/_._ diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/targets/netstandard/props.xml b/csharp/src/Microsoft.ML.OnnxRuntime/targets/netstandard/props.xml index efe5c659f250a..c3cd38c9cd56b 100644 --- a/csharp/src/Microsoft.ML.OnnxRuntime/targets/netstandard/props.xml +++ b/csharp/src/Microsoft.ML.OnnxRuntime/targets/netstandard/props.xml @@ -28,14 +28,7 @@ - - - $(MSBuildThisFileDirectory)../../runtimes/win-x86/native/onnxruntime.lib;%(AdditionalDependencies) - - - - x86 arm64 arm $(Platform) @@ -120,7 +113,8 @@ + Condition="'$(PlatformTarget)' == 'ARM64' AND + Exists('$(MSBuildThisFileDirectory)..\..\runtimes\win-arm64\native\onnxruntime.dll')"> onnxruntime.dll PreserveNewest false @@ -135,7 +129,8 @@ + Condition="'$(PlatformTarget)' == 'ARM' AND + Exists('$(MSBuildThisFileDirectory)..\..\runtimes\win-arm\native\onnxruntime.dll')"> onnxruntime.dll PreserveNewest false @@ -147,34 +142,5 @@ PreserveNewest false - - - - onnxruntime.dll - PreserveNewest - false - - - dnnl.dll - PreserveNewest - false - - - mklml.dll - PreserveNewest - false - - - libiomp5md.dll - PreserveNewest - false - diff --git a/csharp/src/Microsoft.ML.OnnxRuntime/targets/netstandard/props_qnn.xml b/csharp/src/Microsoft.ML.OnnxRuntime/targets/netstandard/props_qnn.xml new file mode 100644 index 0000000000000..c1ad99a778a67 --- /dev/null +++ b/csharp/src/Microsoft.ML.OnnxRuntime/targets/netstandard/props_qnn.xml @@ -0,0 +1,88 @@ + + + + + + $(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories) + + + $(MSBuildThisFileDirectory)../../build/native/include/;%(AdditionalIncludeDirectories) + + + + + + $(MSBuildThisFileDirectory)../../runtimes/win-arm64/native/onnxruntime.lib;%(AdditionalDependencies) + + + + + + $(MSBuildThisFileDirectory)../../runtimes/win-arm/native/onnxruntime.lib;%(AdditionalDependencies) + + + + + + $(MSBuildThisFileDirectory)../../runtimes/win-arm64/native/onnxruntime.lib;%(AdditionalDependencies) + + + + + arm64 + arm + $(Platform) + + + + $(MSBuildThisFileDirectory)..\..\runtimes\win-$(EnginePlatform)\native\onnxruntime.dll + + + + + + onnxruntime.dll + PreserveNewest + false + + + onnxruntime_providers_shared.dll + PreserveNewest + false + + + + + onnxruntime.dll + PreserveNewest + false + + + onnxruntime_providers_shared.dll + PreserveNewest + false + + + + + onnxruntime.dll + PreserveNewest + false + + + onnxruntime_providers_shared.dll + PreserveNewest + false + + + diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/Tests.cs b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/Tests.cs index c28830ec72157..6e6190b8227b8 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/Tests.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests.Mobile/EndToEndTests.Mobile.Automation/Tests.cs @@ -40,10 +40,12 @@ public void RunPlatformUnitTest() var serializedResultSummary = _app.Invoke(_getResultsBackdoorMethodName)?.ToString(); Assert.IsNotEmpty(serializedResultSummary, "Test results were not returned"); + // Fix security issue (overflow with too much nesting): GHSA-5crp-9r3c-p9vr + JsonConvert.DefaultSettings = () => new JsonSerializerSettings { MaxDepth = 128 }; var testSummary = JsonConvert.DeserializeObject(serializedResultSummary); Assert.AreEqual(testSummary.Failed, 0, $"{testSummary.Failed} tests failed"); _app.Screenshot("Post-testing"); } } -} \ No newline at end of file +} diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj index 67addd2731744..4da9b5ffae3e4 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj @@ -50,6 +50,7 @@ + diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/runtest.sh b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/runtest.sh index a500e4bce8fbf..91e05e6ba58a2 100755 --- a/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/runtest.sh +++ b/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/runtest.sh @@ -11,7 +11,6 @@ RunTestNative=${RunTestNative:-true} set -x -e -pushd . cd $BUILD_SOURCESDIRECTORY echo "Current NuGet package version is $CurrentOnnxRuntimeVersion" @@ -40,9 +39,6 @@ if [ $RunTestCsharp = "true" ]; then exit 1 fi dotnet test -p:DefineConstants=USE_TENSORRT $BUILD_SOURCESDIRECTORY/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj --no-restore --verbosity detailed - elif [ $PACKAGENAME = "Microsoft.ML.OnnxRuntime.ROCm" ]; then - export TESTONGPU=ON - dotnet test -p:DefineConstants=USE_ROCM $BUILD_SOURCESDIRECTORY/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj --no-restore --verbosity detailed else dotnet test $BUILD_SOURCESDIRECTORY/csharp/test/Microsoft.ML.OnnxRuntime.EndToEndTests/Microsoft.ML.OnnxRuntime.EndToEndTests.csproj --no-restore --verbosity detailed fi @@ -52,5 +48,3 @@ if [ $RunTestCsharp = "true" ]; then fi fi -cd $OldDir -popd diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/.config/dotnet-tools.json b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/.config/dotnet-tools.json new file mode 100644 index 0000000000000..67d39c423d4d7 --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/.config/dotnet-tools.json @@ -0,0 +1,13 @@ +{ + "version": 1, + "isRoot": true, + "tools": { + "browserstack-sdk": { + "version": "1.16.13", + "commands": [ + "browserstack-sdk" + ], + "rollForward": false + } + } +} \ No newline at end of file diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/BrowserStackTest.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/BrowserStackTest.cs new file mode 100644 index 0000000000000..6ab341d75683f --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/BrowserStackTest.cs @@ -0,0 +1,68 @@ +using Newtonsoft.Json; +using NUnit.Framework.Interfaces; +using NUnit.Framework; +using OpenQA.Selenium; +using OpenQA.Selenium.Appium; +using OpenQA.Selenium.Appium.Android; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android +{ + public class BrowserStackTest + { + public AndroidDriver driver; + public BrowserStackTest() + {} + + [SetUp] + public void Init() + { + var androidOptions = new AppiumOptions { + AutomationName = "UIAutomator2", + PlatformName = "Android", + }; + + driver = new AndroidDriver(new Uri("http://127.0.0.1:4723/wd/hub"), androidOptions); + } + + /// + /// Passes the correct test status to BrowserStack and ensures the driver quits. + /// + [TearDown] + public void Dispose() + { + try + { + // According to + // https://www.browserstack.com/docs/app-automate/appium/set-up-tests/mark-tests-as-pass-fail + // BrowserStack doesn't know whether test assertions have passed or failed. Below handles + // passing the test status to BrowserStack along with any relevant information. + if (TestContext.CurrentContext.Result.Outcome.Status == TestStatus.Failed) + { + String failureMessage = TestContext.CurrentContext.Result.Message; + String jsonToSendFailure = + String.Format("browserstack_executor: {{\"action\": \"setSessionStatus\", \"arguments\": " + + "{{\"status\":\"failed\", \"reason\": {0}}}}}", + JsonConvert.ToString(failureMessage)); + + ((IJavaScriptExecutor)driver).ExecuteScript(jsonToSendFailure); + } + else + { + ((IJavaScriptExecutor)driver) + .ExecuteScript("browserstack_executor: {\"action\": \"setSessionStatus\", \"arguments\": " + + "{\"status\":\"passed\", \"reason\": \"\"}}"); + } + } + finally + { + // will run even if exception is thrown by previous block + ((AndroidDriver)driver).Quit(); + } + } + } +} diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android.csproj new file mode 100644 index 0000000000000..9b9028d30cc5b --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android.csproj @@ -0,0 +1,22 @@ + + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/README.md b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/README.md new file mode 100644 index 0000000000000..d92bb394210f6 --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/README.md @@ -0,0 +1,48 @@ +# BrowserStack Android test +This project will run the Android MAUI tests on BrowserStack, which allows you to run automated tests on a variety of mobile devices. + +## Context +Microsoft.ML.OnnxRuntime.Tests.MAUI uses DeviceRunners.VisualRunners to allow running the unit tests (found in Microsoft.ML.OnnxRuntime.Tests.Common) across multiple devices. DeviceRunners.VisualRunners provides a simple UI with a button that will run the unit tests and a panel with the unit test results. + +In order to automate the process of running the unit tests across mobile devices, Appium is used for UI testing orchestration (it provides a way to interact with the UI), and BrowserStack automatically runs these Appium tests across different mobile devices. + +This project does not include the capability to start an Appium server locally or attach to a local emulator or device. + +## Build & run instructions +### Requirements +* A BrowserStack account with access to App Automate + * You can set BrowserStack credentials as environment variables as shown [here](https://www.browserstack.com/docs/app-automate/appium/getting-started/c-sharp/nunit/integrate-your-tests#CLI) +* ONNXRuntime NuGet package + 1. You can either download the [stable NuGet package](https://www.nuget.org/packages/Microsoft.ML.OnnxRuntime) then follow the instructions from [NativeLibraryInclude.props file](../Microsoft.ML.OnnxRuntime.Tests.Common/NativeLibraryInclude.props) to use the downloaded .nupkg file + 2. Or follow the [build instructions](https://onnxruntime.ai/docs/build/android.html) to build the Android package locally +* The dotnet workloads for maui and maui-android, which will not always automatically install correctly + 1. `dotnet workload install maui` + 2. `dotnet workload install maui-android` +* [Appium](https://appium.io/docs/en/latest/quickstart/) and the [UiAutomator2 driver](https://appium.io/docs/en/latest/quickstart/uiauto2-driver/) + +### Run instructions +1. Build the Microsoft.ML.OnnxRuntime.Tests.MAUI project into a signed APK. + 1. Run the following: `dotnet publish -c Release -f net9.0-android` in the Microsoft.ML.OnnxRuntime.Tests.MAUI directory. + 2. Search for the APK files generated. They should be located in `bin\Release\net9.0-android\publish`. + 3. If they're in a different location, edit the `browserstack.yml` file to target the path to the signed APK. +2. Ensure you've set the BrowserStack credentials as environment variables. +3. Run the following in the Microsoft.ML.OnnxRuntime.Tests.Android.BrowserStack directory: `dotnet test` +4. Navigate to the [BrowserStack App Automate dashboard](https://app-automate.browserstack.com/dashboard/v2/builds) to see your test running! + +## Troubleshooting & Resources +### BrowserStack Resources +- [Configuration docs](https://www.browserstack.com/docs/app-automate/appium/sdk-params#test-context) for browserstack.yml +- [Configuration generator](https://www.browserstack.com/docs/app-automate/capabilities) for browserstack.yml +- [Integration guide](https://www.browserstack.com/docs/app-automate/appium/getting-started/c-sharp/nunit/integrate-your-tests#CLI) + +### Troubleshooting +- Issues building the MAUI app: + - Make sure that the maui and maui-android workloads are installed correctly by running `dotnet workload list` + - If you believe the issues are workload related, you can also try running `dotnet workload repair` (this has personally never worked for me) + - Try running `dotnet clean`. However, this does not fully remove all the previous intermediaries. If you're still running into the errors, manually deleting the bin and obj folders can sometimes resolve them. +- After building the MAUI app, try installing on an emulator and clicking the "Run All" button to ensure that everything is working. (If you are missing the ONNXRuntime package, it will not show up as an error until you click "Run All".) + - Running the MAUI app from Visual Studio will not replicate running it through BrowserStack. Instead, use `adb install [path to signed apk]` to install the app then use the emulator to launch the app. +- Issues with the Android.BrowserStack test app: there is an Appium Doctor package on npm -- run `npm install @appium/doctor --location=global` then `appium-doctor --android` and follow the directed instructions. Some errors with Appium on Android will not appear until runtime. +- Connection refused by Appium server: this can happen if you already have an Appium server running locally. If you do, stop the Appium server then try `dotnet test` again. +- App is crashing on BrowserStack or it emits an error that it cannot run this APK file: make sure that you are passing in the correct signed APK from the publish folder. +- It appears that a test runs on CLI but a build is not launched on BrowserStack: this happens when the BrowserStack Test Adapter cannot find the browserstack.yml file (which has to be named "browserstack.yml" -- do not be tricked by BrowserStack's article on custom-named configuration files) diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/RunAllTest.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/RunAllTest.cs new file mode 100644 index 0000000000000..b62c2f052455e --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/RunAllTest.cs @@ -0,0 +1,123 @@ +using OpenQA.Selenium.Appium; +using OpenQA.Selenium; +using NUnit.Framework; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android +{ + /// + /// This class contains a single test: RunAll, which interacts with the UI from + /// https://github.com/mattleibow/DeviceRunners/tree/main by clicking the "Run All" button and checking the number + /// of passed and failed tests. + /// + /// It searches for elements on the page using Appium's WebDriver. These searches use the XPath attributes. + /// + /// Launching the MAUI test app in Appium Inspector will allow you to see the exact XPath attributes for each + /// element. + /// + [TestFixture] + public class RunAllTest : BrowserStackTest + { + public AppiumElement FindAppiumElement(String xpathQuery, String text) + { + IReadOnlyCollection appiumElements = driver.FindElements(By.XPath(xpathQuery)); + + foreach (var element in appiumElements) + { + if (element.Text.Contains(text)) + { + return element; + } + } + // was unable to find given element + throw new Exception(String.Format("Could not find {0}: {1} on the page.", xpathQuery, text)); + } + + public AppiumElement FindAppiumElementThenClick(String xpathQuery, String text) + { + AppiumElement appiumElement = FindAppiumElement(xpathQuery, text); + appiumElement.Click(); + return appiumElement; + } + + public (int, int) GetPassFailCount() + { + int numPassed = -1; + int numFailed = -1; + + IReadOnlyCollection labelElements = + driver.FindElements(By.XPath("//android.widget.TextView")); + + for (int i = 0; i < labelElements.Count; i++) + { + AppiumElement element = labelElements.ElementAt(i); + + if (element.Text.Equals("✔")) + { + i++; + numPassed = int.Parse(labelElements.ElementAt(i).Text); + } + + if (element.Text.Equals("⛔")) + { + i++; + numFailed = int.Parse(labelElements.ElementAt(i).Text); + break; + } + } + + Assert.That(numPassed, Is.GreaterThanOrEqualTo(0), "Could not find number passed label."); + Assert.That(numFailed, Is.GreaterThanOrEqualTo(0), "Could not find number failed label."); + + return (numPassed, numFailed); + } + + [Test] + public async Task ClickRunAllTest() + { + // XAML for the main page: + // https://github.com/mattleibow/DeviceRunners/blob/cba7644e07b305ba64dc930b01c3eee55ef2b93d/src/DeviceRunners.VisualRunners.Maui/App/Pages/HomePage.xaml + AppiumElement runAllButton = FindAppiumElementThenClick("//android.widget.Button", "Run All"); + + while (!runAllButton.Enabled) + { + // waiting for unit tests to execute + await Task.Delay(500); + } + + (int numPassed, int numFailed) = GetPassFailCount(); + + if (numFailed == 0) + { + return; + } + + // click into test results if tests have failed + FindAppiumElementThenClick("//android.widget.TextView", "⛔"); + await Task.Delay(500); + + // Brings you to the test assembly page + // XAML for test assembly page: + // https://github.com/mattleibow/DeviceRunners/blob/cba7644e07b305ba64dc930b01c3eee55ef2b93d/src/DeviceRunners.VisualRunners.Maui/App/Pages/TestAssemblyPage.xaml + FindAppiumElementThenClick("//android.widget.EditText", "All"); + await Task.Delay(100); + FindAppiumElementThenClick("//android.widget.TextView", "Failed"); + await Task.Delay(500); + + StringBuilder sb = new StringBuilder(); + sb.AppendLine("PASSED TESTS: " + numPassed + " | FAILED TESTS: " + numFailed); + + IReadOnlyCollection textResults = driver.FindElements(By.XPath("//android.widget.TextView")); + foreach (var element in textResults) + { + sb.AppendLine(element.Text); + } + + Assert.That(numFailed, Is.EqualTo(0), sb.ToString()); + } + } +} diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/browserstack.yml b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/browserstack.yml new file mode 100644 index 0000000000000..d9866901fd95c --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.BrowserStack.Android/browserstack.yml @@ -0,0 +1,13 @@ +app: ..\Microsoft.ML.OnnxRuntime.Tests.MAUI\bin\Release\net9.0-android\publish\ORT.CSharp.Tests.MAUI-Signed.apk +platforms: + - platformName: android + deviceName: Samsung Galaxy S22 Ultra + platformVersion: 12.0 +browserstackLocal: false +buildName: ORT android test +buildIdentifier: ${BUILD_NUMBER} +projectName: ORT-UITests +debug: true +networkLogs: false +testContextOptions: + skipSessionStatus: true diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssertUtils.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssertUtils.cs new file mode 100644 index 0000000000000..7d689628ceab7 --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/AssertUtils.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.Text; +using Xunit; + +namespace Microsoft.ML.OnnxRuntime.Tests +{ + internal static class AssertUtils + { + + /// + /// Check if the action throws the expected exception. If it doesn't, the method passes. If it does, check for + /// the exception type and the expected exception message. More detailed Assert method to be used for unit tests + /// written with XUnit. + /// + /// Type of exception expected to be thrown. + /// Action to be executed or tested. + /// Feedback message if an unexpected exception happens. + /// Expected exception message. If null, the exception message is not + // checked. + public static void IfThrowsCheckException(Action action, string feedbackMessage, string expectedExceptionMessage = null) where T : Exception + { + try + { + action(); + } + catch (T ex) + { + if (expectedExceptionMessage == null) + { + return; + } + else + { + Assert.True(ex.Message.Contains(expectedExceptionMessage), + $"{feedbackMessage}\nExpected exception message to contain '{expectedExceptionMessage}', but got '{ex.Message}'"); + } + } + catch (Exception ex) + { + Assert.Fail($"{feedbackMessage}\nExpected {typeof(T).Name} but got {ex.GetType().Name}. "); + } + } + + + /// + /// Check if the action throws the expected exception. If it doesn't, the method fails with the feedbackMessage. + /// If it does, check for the exception type and the expected exception message. More detailed Assert method to be + /// used for unit tests written with XUnit. + /// + /// Type of exception expected to be thrown. + /// Action to be executed or tested. It is expected that the action will throw. + /// Feedback message if an unexpected exception happens. + /// Expected exception message. If null, the exception message is not + // checked. + public static void AssertThrowsCheckException(Action action, string feedbackMessage, string expectedExceptionMessage = null) where T : Exception + { + try + { + action(); + Assert.Fail($"{feedbackMessage}\nExpected {typeof(T).Name} but no exception was thrown."); + } + catch (T ex) + { + if (expectedExceptionMessage == null) + { + return; + } + else + { + Assert.True(ex.Message.Contains(expectedExceptionMessage), + $"{feedbackMessage}\nExpected exception message to contain '{expectedExceptionMessage}', but got '{ex.Message}'"); + } + } + catch (Exception ex) + { + Assert.Fail($"{feedbackMessage}\nExpected {typeof(T).Name} but got {ex.GetType().Name}. "); + } + } + } +} diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/CompileApiTests.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/CompileApiTests.cs new file mode 100644 index 0000000000000..fe2cab57658c8 --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/CompileApiTests.cs @@ -0,0 +1,272 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// not supported on mobile platforms +#if !(ANDROID || IOS) + +namespace Microsoft.ML.OnnxRuntime.Tests; + +using System; +using System.Globalization; +using System.IO; +using System.Runtime.InteropServices; +using Xunit; + + +public class CompileApiTests +{ + private OrtEnv ortEnvInstance = OrtEnv.Instance(); + + + [Fact] + public void BasicUsage() + { + using (var sessionOptions = new SessionOptions()) + { + using (var compileOptions = new OrtModelCompilationOptions(sessionOptions)) + { + // mainly checking these don't throw which ensures all the plumbing for the binding works. + compileOptions.SetInputModelPath("model.onnx"); + compileOptions.SetOutputModelPath("compiled_model.onnx"); + + compileOptions.SetOutputModelExternalInitializersFile("external_data.bin", 512); + compileOptions.SetEpContextEmbedMode(true); + compileOptions.SetGraphOptimizationLevel(GraphOptimizationLevel.ORT_ENABLE_BASIC); + + } + + // setup a new instance as SetOutputModelExternalInitializersFile is incompatible with SetOutputModelBuffer + using (var compileOptions = new OrtModelCompilationOptions(sessionOptions)) + { + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + compileOptions.SetInputModelFromBuffer(model); + + // SetOutputModelBuffer updates the user provided IntPtr and size when it allocates data post-compile. + // Due to that we need to allocate an IntPtr and UIntPtr here. + IntPtr bytePtr = new IntPtr(); + UIntPtr bytesSize = new UIntPtr(); + var allocator = OrtAllocator.DefaultInstance; + compileOptions.SetOutputModelBuffer(allocator, ref bytePtr, ref bytesSize); + compileOptions.SetEpContextBinaryInformation("./", "squeezenet.onnx"); + + compileOptions.CompileModel(); + + Assert.NotEqual(IntPtr.Zero, bytePtr); + Assert.NotEqual(UIntPtr.Zero, bytesSize); + + byte[] compiledBytes = new byte[bytesSize.ToUInt64()]; + Marshal.Copy(bytePtr, compiledBytes, 0, (int)bytesSize.ToUInt32()); + + // Check the compiled model is valid + using (var session = new InferenceSession(compiledBytes, sessionOptions)) + { + Assert.NotNull(session); + } + + allocator.FreeMemory(bytePtr); + } + + // Test using OrtCompileApiFlags.ERROR_NO_NODES_COMPILED. A model compiled with CPU EP will not generate + // any compiled EPContext nodes, so expect an ORT_FAIL error. + using (var compileOptions = new OrtModelCompilationOptions(sessionOptions)) + { + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + var output_model_file = "should_not_generate.onnx"; + compileOptions.SetInputModelFromBuffer(model); + compileOptions.SetOutputModelPath(output_model_file); + compileOptions.SetFlags(OrtCompileApiFlags.ERROR_IF_NO_NODES_COMPILED); + + // compile should fail + try + { + compileOptions.CompileModel(); + Assert.Fail("CompileModel() should have thrown an exception"); + } + catch (OnnxRuntimeException ex) + { + Assert.Contains("Unable to compile any nodes", ex.Message); + } + + Assert.False(File.Exists(output_model_file)); // Output file should not be generated. + } + + // Test using OrtCompileApiFlags.ERROR_IF_OUTPUT_FILE_EXISTS. + var outputModelFile = "squeezenet_ctx.onnx"; + try + { + using (var compileOptions = new OrtModelCompilationOptions(sessionOptions)) + { + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + + // Compile and generate an output model. + compileOptions.SetInputModelFromBuffer(model); + compileOptions.SetOutputModelPath(outputModelFile); + compileOptions.CompileModel(); + Assert.True(File.Exists(outputModelFile)); + + // Try to compile again with flag that prevents replacing an existing file. + // Expect failure. + compileOptions.SetFlags(OrtCompileApiFlags.ERROR_IF_OUTPUT_FILE_EXISTS); + + // compile should fail + try + { + compileOptions.CompileModel(); + Assert.Fail("CompileModel() should have thrown an exception"); + } + catch (OnnxRuntimeException ex) + { + Assert.Contains("exists already", ex.Message); + } + } + } + finally + { + if (File.Exists(outputModelFile)) + { + // This file is created by ORT, so we delete it manually in finally block. + File.Delete(outputModelFile); + } + } + } + } + + [Fact] + public void WriteOutModelWithDelegate() + { + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + var outputModelFilePath = "squeezenet_write_delegate_ctx.onnx"; + + using (FileStream fs = new FileStream(outputModelFilePath, FileMode.Create, FileAccess.Write, FileShare.None, + 4096, FileOptions.DeleteOnClose)) + using (var sessionOptions = new SessionOptions()) + using (var compileOptions = new OrtModelCompilationOptions(sessionOptions)) + { + void BasicWriteBufferDelegate(ReadOnlySpan buffer) + { + Assert.True(buffer.Length > 0); + fs.Write(buffer.ToArray(), 0, buffer.Length); // Write it out to a file + } + + // Compile and generate an output model. + compileOptions.SetInputModelFromBuffer(model); + compileOptions.SetOutputModelWriteDelegate(BasicWriteBufferDelegate); + compileOptions.CompileModel(); + Assert.True(File.Exists(outputModelFilePath)); + } + } + + [Fact] + public void BasicGetInitializerLocationDelegate() + { + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + var outputModelFilePath = "squeezenet_handle_initializer_delegate_ctx.onnx"; + var initializersFilePath = "squeezenet_handle_initializer_delegate_ctx.bin"; + + try + { + using (FileStream fs = new FileStream(initializersFilePath, FileMode.Create, FileAccess.Write, + FileShare.None, 4096, FileOptions.DeleteOnClose)) + using (var sessionOptions = new SessionOptions()) + using (var compileOptions = new OrtModelCompilationOptions(sessionOptions)) + { + // Custom delegate that stores large initializers in a new file. + OrtExternalInitializerInfo BasicHandleInitializer( + string initializerName, IReadOnlyOrtValue initializerValue, + IReadOnlyExternalInitializerInfo originalInitializerLocation) + { + Assert.True(initializerName.Length > 0); + + var byteSize = initializerValue.GetTensorSizeInBytes(); + if (byteSize <= 64) + { + // Keep small initializers stored within model. + return null; + } + + long byteOffset = fs.Position; + ReadOnlySpan dataSpan = initializerValue.GetTensorDataAsSpan(); + fs.Write(dataSpan.ToArray(), 0, dataSpan.Length); // Write it out to a file + + // Return the data's new location. + return new OrtExternalInitializerInfo(initializersFilePath, byteOffset, byteSize); + } + + // Compile and generate an output model. + compileOptions.SetInputModelFromBuffer(model); + compileOptions.SetOutputModelPath(outputModelFilePath); + compileOptions.SetOutputModelGetInitializerLocationDelegate(BasicHandleInitializer); + compileOptions.CompileModel(); + Assert.True(File.Exists(outputModelFilePath)); + } + } + finally + { + if (File.Exists(outputModelFilePath)) + { + // This file is created by ORT, so we delete it manually in finally block. + File.Delete(outputModelFilePath); + } + } + } + + [Fact] + public void GetInitializerLocationDelegateThatReusesExternalInitializers() + { + var model = TestDataLoader.LoadModelFromEmbeddedResource("conv_qdq_external_ini.onnx"); + var outputModelFilePath = "conv_qdq_external_ini.reuse.ctx.onnx"; + bool reusedExternalInitializers = false; + + try + { + using (var sessionOptions = new SessionOptions()) + using (var compileOptions = new OrtModelCompilationOptions(sessionOptions)) + { + // Custom delegate that reuses the original external initializer file. + OrtExternalInitializerInfo ReuseExternalInitializers( + string initializerName, IReadOnlyOrtValue initializerValue, + IReadOnlyExternalInitializerInfo originalInitializerLocation) + { + Assert.True(initializerName.Length > 0); + + if (originalInitializerLocation != null) + { + reusedExternalInitializers = true; // For test assertion only + string originalFilePath = originalInitializerLocation.GetFilePath(); + long originalFileOffset = originalInitializerLocation.GetFileOffset(); + long originalByteSize = originalInitializerLocation.GetByteSize(); + + Assert.True(originalFilePath.Length > 0); + Assert.True(originalFileOffset >= 0); + Assert.True(originalByteSize > 0); + + // This initializer comes from an external file. Reuse it for compiled model. + return new OrtExternalInitializerInfo(originalFilePath, originalFileOffset, originalByteSize); + } + + // Otherwise, embed initializers that were not originally external. + return null; + } + + // Compile and generate an output model. + compileOptions.SetInputModelFromBuffer(model); + compileOptions.SetOutputModelPath(outputModelFilePath); + compileOptions.SetOutputModelGetInitializerLocationDelegate(ReuseExternalInitializers); + compileOptions.CompileModel(); + + Assert.True(File.Exists(outputModelFilePath)); + Assert.True(reusedExternalInitializers); + } + } + finally + { + if (File.Exists(outputModelFilePath)) + { + // This file is created by ORT, so we delete it manually in finally block. + File.Delete(outputModelFilePath); + } + } + } +} + +#endif \ No newline at end of file diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/CudaPluginEpTests.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/CudaPluginEpTests.cs new file mode 100644 index 0000000000000..d1cf2f5da1dd3 --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/CudaPluginEpTests.cs @@ -0,0 +1,329 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// not supported on mobile platforms +#if !(ANDROID || IOS) + +namespace Microsoft.ML.OnnxRuntime.Tests; + +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Runtime.InteropServices; +using Microsoft.ML.OnnxRuntime.Tensors; +using Xunit; + +/// +/// Tests for the CUDA Plugin Execution Provider registration and functionality. +/// These tests are skipped if the CUDA Plugin EP library is not available. +/// +[Collection("Ort Inference Tests")] +public class CudaPluginEpTests +{ + private readonly OrtEnv ortEnvInstance = OrtEnv.Instance(); + + // EP name as returned by OrtEpDevice.EpName. Also used as the registration name for convenience. + private const string CudaPluginEpName = "CudaPluginExecutionProvider"; + + private static string GetCudaPluginLibraryPath() + { + string libName; + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + libName = "onnxruntime_providers_cuda_plugin.dll"; + } + else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux)) + { + libName = "libonnxruntime_providers_cuda_plugin.so"; + } + else + { + return null; + } + + string fullPath = Path.Combine(Directory.GetCurrentDirectory(), libName); + return fullPath; + } + + private static bool IsCudaPluginEpAvailable() + { + string libPath = GetCudaPluginLibraryPath(); + return libPath != null && File.Exists(libPath); + } + + [SkippableFact] + public void RegisterCudaPluginEp() + { + Skip.IfNot(IsCudaPluginEpAvailable(), "CUDA Plugin EP library not available."); + + string libPath = GetCudaPluginLibraryPath(); + + // Register the CUDA Plugin EP library + ortEnvInstance.RegisterExecutionProviderLibrary(CudaPluginEpName, libPath); + try + { + // Verify the CUDA Plugin EP device is now available + var epDevices = ortEnvInstance.GetEpDevices(); + var cudaPluginDevice = epDevices.FirstOrDefault( + d => d.EpName == CudaPluginEpName); + Skip.If(cudaPluginDevice == null, "CUDA Plugin EP registered but no devices available (no GPU?)."); + } + finally + { + ortEnvInstance.UnregisterExecutionProviderLibrary(CudaPluginEpName); + } + } + + [SkippableFact] + public void CudaPluginEp_CreateSessionAndRunInference() + { + Skip.IfNot(IsCudaPluginEpAvailable(), "CUDA Plugin EP library not available."); + + string libPath = GetCudaPluginLibraryPath(); + + ortEnvInstance.RegisterExecutionProviderLibrary(CudaPluginEpName, libPath); + try + { + var epDevices = ortEnvInstance.GetEpDevices(); + var cudaPluginDevices = epDevices + .Where(d => d.EpName == CudaPluginEpName) + .ToList(); + + Skip.If(cudaPluginDevices.Count == 0, "No CUDA Plugin EP devices available (no GPU?)."); + + using var sessionOptions = new SessionOptions(); + sessionOptions.AppendExecutionProvider(ortEnvInstance, cudaPluginDevices, null); + // Ensure all nodes are placed on the CUDA Plugin EP; fail if any would fall back to CPU + sessionOptions.AddSessionConfigEntry("session.disable_cpu_ep_fallback", "1"); + + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + + using var session = new InferenceSession(model, sessionOptions); + Assert.NotNull(session); + + // Run inference with the CUDA Plugin EP using OrtValue API + float[] inputData = TestDataLoader.LoadTensorFromEmbeddedResource("bench.in"); + float[] expectedOutput = TestDataLoader.LoadTensorFromEmbeddedResource("bench.expected_out"); + long[] expectedShape = { 1, 1000, 1, 1 }; + + var inputMeta = session.InputMetadata; + var inputName = inputMeta.Keys.First(); + var inputShape = Array.ConvertAll(inputMeta[inputName].Dimensions, d => (long)d); + + using var runOptions = new RunOptions(); + + // Run multiple times to verify no memory corruption across runs + for (int i = 0; i < 3; i++) + { + using var inputOrtValue = OrtValue.CreateTensorValueFromMemory(inputData, inputShape); + using var results = session.Run( + runOptions, + new[] { inputName }, + new[] { inputOrtValue }, + session.OutputNames); + + Assert.Single(results); + + var output = results[0]; + Assert.True(output.IsTensor); + + var typeShape = output.GetTensorTypeAndShape(); + Assert.Equal(TensorElementType.Float, typeShape.ElementDataType); + Assert.Equal(expectedShape, typeShape.Shape); + + var resultArray = output.GetTensorDataAsSpan().ToArray(); + Assert.Equal(expectedOutput.Length, resultArray.Length); + Assert.Equal(expectedOutput, resultArray, new FloatComparer()); + } + } + finally + { + ortEnvInstance.UnregisterExecutionProviderLibrary(CudaPluginEpName); + } + } + + [SkippableFact] + public void CudaPluginEp_DeviceProperties() + { + Skip.IfNot(IsCudaPluginEpAvailable(), "CUDA Plugin EP library not available."); + + string libPath = GetCudaPluginLibraryPath(); + + ortEnvInstance.RegisterExecutionProviderLibrary(CudaPluginEpName, libPath); + try + { + var epDevices = ortEnvInstance.GetEpDevices(); + var cudaPluginDevice = epDevices.FirstOrDefault( + d => d.EpName == CudaPluginEpName); + Skip.If(cudaPluginDevice == null, "No CUDA Plugin EP devices available (no GPU?)."); + + // Validate device properties + Assert.NotEmpty(cudaPluginDevice.EpName); + Assert.NotEmpty(cudaPluginDevice.EpVendor); + + var hwDevice = cudaPluginDevice.HardwareDevice; + Assert.Equal(OrtHardwareDeviceType.GPU, hwDevice.Type); + + var metadata = cudaPluginDevice.EpMetadata; + Assert.NotNull(metadata); + + var options = cudaPluginDevice.EpOptions; + Assert.NotNull(options); + } + finally + { + ortEnvInstance.UnregisterExecutionProviderLibrary(CudaPluginEpName); + } + } + + [SkippableFact] + public void CudaPluginEp_WithProviderOptions() + { + Skip.IfNot(IsCudaPluginEpAvailable(), "CUDA Plugin EP library not available."); + + string libPath = GetCudaPluginLibraryPath(); + + ortEnvInstance.RegisterExecutionProviderLibrary(CudaPluginEpName, libPath); + try + { + var epDevices = ortEnvInstance.GetEpDevices(); + var cudaPluginDevices = epDevices + .Where(d => d.EpName == CudaPluginEpName) + .ToList(); + + Skip.If(cudaPluginDevices.Count == 0, "No CUDA Plugin EP devices available (no GPU?)."); + + // Extract actual device_id from the first discovered device's memory info + var firstDevice = cudaPluginDevices[0]; + var deviceMemInfo = firstDevice.GetMemoryInfo(OrtDeviceMemoryType.DEFAULT); + int deviceId = deviceMemInfo.Id; + + using var sessionOptions = new SessionOptions(); + + // Pass provider options with device_id matching the discovered device + var epOptions = new Dictionary + { + { "device_id", deviceId.ToString() } + }; + + sessionOptions.AppendExecutionProvider(ortEnvInstance, new[] { firstDevice }.ToList(), epOptions); + + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + + using var session = new InferenceSession(model, sessionOptions); + Assert.NotNull(session); + } + finally + { + ortEnvInstance.UnregisterExecutionProviderLibrary(CudaPluginEpName); + } + } + + [SkippableFact] + public void CudaPluginEp_AutoEpSelection() + { + Skip.IfNot(IsCudaPluginEpAvailable(), "CUDA Plugin EP library not available."); + + string libPath = GetCudaPluginLibraryPath(); + + ortEnvInstance.RegisterExecutionProviderLibrary(CudaPluginEpName, libPath); + try + { + // Skip if no CUDA devices available (e.g., CI without GPU) + var epDevices = ortEnvInstance.GetEpDevices(); + Skip.If(!epDevices.Any(d => d.EpName == CudaPluginEpName), + "No CUDA Plugin EP devices available (no GPU?)."); + + using var sessionOptions = new SessionOptions(); + + // Use automatic EP selection which should pick up the registered CUDA Plugin EP + sessionOptions.SetEpSelectionPolicy(ExecutionProviderDevicePolicy.PREFER_GPU); + // Ensure the CUDA Plugin EP is actually selected, not silently falling back to CPU + sessionOptions.AddSessionConfigEntry("session.disable_cpu_ep_fallback", "1"); + + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + + using var session = new InferenceSession(model, sessionOptions); + Assert.NotNull(session); + } + finally + { + ortEnvInstance.UnregisterExecutionProviderLibrary(CudaPluginEpName); + } + } + + [SkippableFact] + public void CudaPluginEp_RunWithIoBinding() + { + Skip.IfNot(IsCudaPluginEpAvailable(), "CUDA Plugin EP library not available."); + + string libPath = GetCudaPluginLibraryPath(); + + ortEnvInstance.RegisterExecutionProviderLibrary(CudaPluginEpName, libPath); + try + { + var epDevices = ortEnvInstance.GetEpDevices(); + var cudaPluginDevices = epDevices + .Where(d => d.EpName == CudaPluginEpName) + .ToList(); + + Skip.If(cudaPluginDevices.Count == 0, "No CUDA Plugin EP devices available (no GPU?)."); + + // Get CUDA device memory info for output binding + var cudaDevice = cudaPluginDevices[0]; + var cudaDeviceMemInfo = cudaDevice.GetMemoryInfo(OrtDeviceMemoryType.DEFAULT); + var expectedVendorId = cudaDeviceMemInfo.GetVendorId(); + + using var sessionOptions = new SessionOptions(); + sessionOptions.AppendExecutionProvider(ortEnvInstance, cudaPluginDevices, null); + // Ensure all nodes are placed on the CUDA Plugin EP; fail if any would fall back to CPU + sessionOptions.AddSessionConfigEntry("session.disable_cpu_ep_fallback", "1"); + + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + + using var session = new InferenceSession(model, sessionOptions); + + float[] inputData = TestDataLoader.LoadTensorFromEmbeddedResource("bench.in"); + long[] expectedShape = { 1, 1000, 1, 1 }; + + var inputMeta = session.InputMetadata; + var inputName = inputMeta.Keys.First(); + var inputShape = Array.ConvertAll(inputMeta[inputName].Dimensions, d => (long)d); + var outputName = session.OutputNames[0]; + + using var runOptions = new RunOptions(); + using var ioBinding = session.CreateIoBinding(); + + using var inputOrtValue = OrtValue.CreateTensorValueFromMemory(inputData, inputShape); + ioBinding.BindInput(inputName, inputOrtValue); + // Bind output to CUDA device memory + ioBinding.BindOutputToDevice(outputName, cudaDeviceMemInfo); + + ioBinding.SynchronizeBoundInputs(); + + using var results = session.RunWithBoundResults(runOptions, ioBinding); + ioBinding.SynchronizeBoundOutputs(); + + Assert.Single(results); + + var output = results.First(); + Assert.True(output.IsTensor); + + var typeShape = output.GetTensorTypeAndShape(); + Assert.Equal(TensorElementType.Float, typeShape.ElementDataType); + Assert.Equal(expectedShape, typeShape.Shape); + + // Verify output resides on GPU device memory + var outputMemInfo = output.GetTensorMemoryInfo(); + Assert.Equal(OrtDeviceMemoryType.DEFAULT, outputMemInfo.GetDeviceMemoryType()); + Assert.Equal(expectedVendorId, outputMemInfo.GetVendorId()); + } + finally + { + ortEnvInstance.UnregisterExecutionProviderLibrary(CudaPluginEpName); + } + } +} + +#endif diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/EpCompatibilityTests.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/EpCompatibilityTests.cs new file mode 100644 index 0000000000000..201c3cae77a24 --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/EpCompatibilityTests.cs @@ -0,0 +1,247 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// not supported on mobile platforms +#if !(ANDROID || IOS) + +namespace Microsoft.ML.OnnxRuntime.Tests; + +using System; +using System.Linq; +using Xunit; +using System.Collections.Generic; +using Google.Protobuf; +using Onnx; + +public class EpCompatibilityTests +{ + private readonly OrtEnv ortEnvInstance = OrtEnv.Instance(); + + private IReadOnlyList GetDevices() + { + var epDevices = ortEnvInstance.GetEpDevices(); + Assert.NotNull(epDevices); + Assert.NotEmpty(epDevices); + return epDevices; + } + + /// + /// Creates a minimal valid ONNX ModelProto with optional compatibility metadata. + /// + private static byte[] CreateModelWithCompatibilityMetadata( + Dictionary epCompatibilityInfo = null) + { + var modelProto = new ModelProto(); + modelProto.IrVersion = (long)Onnx.Version.IrVersion; + modelProto.Graph = new GraphProto { Name = "test_graph" }; + + var opset = new OperatorSetIdProto(); + opset.Domain = ""; + opset.Version = 13; + modelProto.OpsetImport.Add(opset); + + if (epCompatibilityInfo != null) + { + foreach (var kvp in epCompatibilityInfo) + { + var prop = new StringStringEntryProto(); + prop.Key = "ep_compatibility_info." + kvp.Key; + prop.Value = kvp.Value; + modelProto.MetadataProps.Add(prop); + } + } + + return modelProto.ToByteArray(); + } + + [Fact] + public void GetEpCompatibility_InvalidArgs() + { + Assert.Throws(() => ortEnvInstance.GetModelCompatibilityForEpDevices(null, "info")); + Assert.Throws(() => ortEnvInstance.GetModelCompatibilityForEpDevices(new List(), "info")); + } + + [Fact] + public void GetEpCompatibility_SingleDeviceCpuProvider() + { + var devices = GetDevices(); + var someInfo = "arbitrary-compat-string"; + + // Use CPU device + var cpu = devices.First(d => d.EpName == "CPUExecutionProvider"); + Assert.NotNull(cpu); + var selected = new List { cpu }; + var status = ortEnvInstance.GetModelCompatibilityForEpDevices(selected, someInfo); + + // CPU defaults to not applicable in this scenario + Assert.Equal(OrtCompiledModelCompatibility.EP_NOT_APPLICABLE, status); + } + + [Fact] + public void GetCompatibilityInfoFromModel_InvalidArgs() + { + Assert.Throws(() => ortEnvInstance.GetCompatibilityInfoFromModel(null, "TestEP")); + Assert.Throws(() => ortEnvInstance.GetCompatibilityInfoFromModel("", "TestEP")); + Assert.Throws(() => ortEnvInstance.GetCompatibilityInfoFromModel("model.onnx", null)); + Assert.Throws(() => ortEnvInstance.GetCompatibilityInfoFromModel("model.onnx", "")); + } + + [Fact] + public void GetCompatibilityInfoFromModel_FileNotFound() + { + Assert.Throws( + () => ortEnvInstance.GetCompatibilityInfoFromModel("nonexistent_model_path.onnx", "TestEP")); + } + + [Fact] + public void GetCompatibilityInfoFromModelBytes_InvalidArgs() + { + Assert.Throws(() => ortEnvInstance.GetCompatibilityInfoFromModelBytes(null, "TestEP")); + Assert.Throws(() => ortEnvInstance.GetCompatibilityInfoFromModelBytes(new byte[0], "TestEP")); + Assert.Throws(() => ortEnvInstance.GetCompatibilityInfoFromModelBytes(new byte[] { 1, 2, 3 }, null)); + Assert.Throws(() => ortEnvInstance.GetCompatibilityInfoFromModelBytes(new byte[] { 1, 2, 3 }, "")); + } + + [Fact] + public void GetCompatibilityInfoFromModel_WithMetadata() + { + const string epType = "TestCompatEP"; + const string expectedCompatInfo = "test_compat_v1.0_driver_123"; + + byte[] modelData = CreateModelWithCompatibilityMetadata( + new Dictionary { { epType, expectedCompatInfo } }); + + string tempModelPath = System.IO.Path.Combine( + System.IO.Path.GetTempPath(), + System.IO.Path.GetRandomFileName() + ".onnx"); + + System.IO.File.WriteAllBytes(tempModelPath, modelData); + + try + { + string result = ortEnvInstance.GetCompatibilityInfoFromModel(tempModelPath, epType); + Assert.NotNull(result); + Assert.Equal(expectedCompatInfo, result); + } + finally + { + if (System.IO.File.Exists(tempModelPath)) + { + System.IO.File.Delete(tempModelPath); + } + } + } + + [Fact] + public void GetNumHardwareDevices_ReturnsPositive() + { + var numDevices = ortEnvInstance.GetNumHardwareDevices(); + // Should return at least one device (CPU) + Assert.True(numDevices > 0, "Expected at least one hardware device"); + } + + [Fact] + public void GetHardwareDevices_ReturnsDevices() + { + var devices = ortEnvInstance.GetHardwareDevices(); + Assert.NotNull(devices); + Assert.NotEmpty(devices); + + // Each device should have valid properties + foreach (var device in devices) + { + Assert.NotNull(device); + // Device type should be valid (CPU, GPU, or NPU) + var deviceType = device.Type; + Assert.True( + deviceType == OrtHardwareDeviceType.CPU || + deviceType == OrtHardwareDeviceType.GPU || + deviceType == OrtHardwareDeviceType.NPU, + $"Unexpected device type: {deviceType}"); + + // Vendor should not be null + Assert.NotNull(device.Vendor); + } + } + + [Fact] + public void GetCompatibilityInfoFromModelBytes_InvalidModelData() + { + byte[] invalidData = System.Text.Encoding.UTF8.GetBytes("this is not a valid ONNX model"); + Assert.Throws( + () => ortEnvInstance.GetCompatibilityInfoFromModelBytes(invalidData, "TestEP")); + } + + [Fact] + public void GetCompatibilityInfoFromModelBytes_WithMetadata() + { + const string epType = "TestCompatEP"; + const string expectedCompatInfo = "test_compat_v1.0_driver_123"; + + byte[] modelData = CreateModelWithCompatibilityMetadata( + new Dictionary { { epType, expectedCompatInfo } }); + + string result = ortEnvInstance.GetCompatibilityInfoFromModelBytes(modelData, epType); + Assert.NotNull(result); + Assert.Equal(expectedCompatInfo, result); + } + + [Fact] + public void GetCompatibilityInfoFromModelBytes_NotFound() + { + // Create model with metadata for a different EP + byte[] modelData = CreateModelWithCompatibilityMetadata( + new Dictionary { { "DifferentEP", "some_value" } }); + + string result = ortEnvInstance.GetCompatibilityInfoFromModelBytes(modelData, "NonExistentEP"); + Assert.Null(result); + } + + [Fact] + public void GetCompatibilityInfoFromModelBytes_NoMetadata() + { + // Create model without any compatibility metadata + byte[] modelData = CreateModelWithCompatibilityMetadata(); + + string result = ortEnvInstance.GetCompatibilityInfoFromModelBytes(modelData, "AnyEP"); + Assert.Null(result); + } + + [Fact] + public void GetHardwareDeviceEpIncompatibilityDetails_CpuEp() + { + var devices = ortEnvInstance.GetHardwareDevices(); + Assert.NotNull(devices); + Assert.NotEmpty(devices); + + // Find CPU device + var cpuDevice = devices.FirstOrDefault(d => d.Type == OrtHardwareDeviceType.CPU); + Assert.NotNull(cpuDevice); + + // Get incompatibility details for CPU EP with CPU device + using (var details = ortEnvInstance.GetHardwareDeviceEpIncompatibilityDetails("CPUExecutionProvider", cpuDevice)) + { + // CPU EP should be compatible with CPU device (no incompatibility reasons) + Assert.Equal(OrtDeviceEpIncompatibilityReason.None, details.ReasonsBitmask); + Assert.Equal(0, details.ErrorCode); + } + } + + [Fact] + public void GetHardwareDeviceEpIncompatibilityDetails_InvalidEpName() + { + var devices = ortEnvInstance.GetHardwareDevices(); + Assert.NotNull(devices); + Assert.NotEmpty(devices); + + var firstDevice = devices[0]; + Assert.NotNull(firstDevice); + + // Invalid EP name should throw + Assert.Throws(() => + ortEnvInstance.GetHardwareDeviceEpIncompatibilityDetails("", firstDevice)); + Assert.Throws(() => + ortEnvInstance.GetHardwareDeviceEpIncompatibilityDetails(null, firstDevice)); + } +} +#endif diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs index 17738da515134..3779a72d4de69 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/InferenceTest.cs @@ -4,13 +4,10 @@ using Microsoft.ML.OnnxRuntime.Tensors; using System; using System.Collections.Generic; +using System.IO; using System.Linq; -using System.Linq.Expressions; -using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Text.RegularExpressions; -using System.Threading; using System.Threading.Tasks; using Xunit; using Xunit.Abstractions; @@ -93,18 +90,35 @@ public void TestSessionOptions() opt.GraphOptimizationLevel = GraphOptimizationLevel.ORT_ENABLE_EXTENDED; Assert.Equal(GraphOptimizationLevel.ORT_ENABLE_EXTENDED, opt.GraphOptimizationLevel); - Assert.Throws(() => { opt.GraphOptimizationLevel = (GraphOptimizationLevel)10; }); + AssertUtils.AssertThrowsCheckException( + () => { opt.GraphOptimizationLevel = (GraphOptimizationLevel)10; }, + "Set an invalid Graph Optimization Level."); opt.AddSessionConfigEntry("key", "value"); - var ex = Assert.Throws(() => { opt.AddSessionConfigEntry("", "invalid key"); }); - Assert.Contains("[ErrorCode:InvalidArgument] Config key is empty", ex.Message); + AssertUtils.AssertThrowsCheckException( + () => { opt.AddSessionConfigEntry("", "invalid key"); }, + "Added an invalid config entry.", + "[ErrorCode:InvalidArgument] Config key is empty"); // SessionOptions.RegisterOrtExtensions can be manually tested by referencing the // Microsoft.ML.OnnxRuntime.Extensions nuget package. After that is done, this should not throw. - ex = Assert.Throws(() => { opt.RegisterOrtExtensions(); }); - Assert.Contains("Microsoft.ML.OnnxRuntime.Extensions NuGet package must be referenced", ex.Message); - + AssertUtils.AssertThrowsCheckException( + () => { opt.RegisterOrtExtensions(); }, + "RegisterOrtExtensions should throw if the Extensions package is not referenced", + "Microsoft.ML.OnnxRuntime.Extensions NuGet package must be referenced"); + + // The below tests what happens when various execution providers are added + // to the session options. + + // We can only check what EPs the package was built with for the + // Microsoft.ML.OnnxRuntime.Managed package because the managed package defines + // the C# preprocessor symbols (such as USE_CUDA) for the EPs that it was built with. + + // The Microsoft.ML.OnnxRuntime package will use the appropriate platform bindings + // (ie the native Android bindings) where the C# preprocessor symbols + // identifying the EPs included in the build may not be available, so we use + // IfThrowsCheckException instead of using ifdefs. #if USE_CUDA opt.AppendExecutionProvider_CUDA(0); #endif @@ -150,37 +164,28 @@ public void TestSessionOptions() opt.AppendExecutionProvider_OpenVINO(); #endif -#if USE_ROCM - opt.AppendExecutionProvider_ROCm(0); -#endif - #if USE_TENSORRT opt.AppendExecutionProvider_Tensorrt(0); #endif -#if USE_XNNPACK - opt.AppendExecutionProvider("XNNPACK"); -#else - ex = Assert.Throws(() => { opt.AppendExecutionProvider("XNNPACK"); }); - Assert.Contains("XNNPACK execution provider is not supported in this build", ex.Message); -#endif -#if USE_SNPE - opt.AppendExecutionProvider("SNPE"); -#else - ex = Assert.Throws(() => { opt.AppendExecutionProvider("SNPE"); }); - Assert.Contains("SNPE execution provider is not supported in this build", ex.Message); -#endif -#if USE_QNN - opt.AppendExecutionProvider("QNN"); -#else - ex = Assert.Throws(() => { opt.AppendExecutionProvider("QNN"); }); - Assert.Contains("QNN execution provider is not supported in this build", ex.Message); -#endif -#if USE_COREML - opt.AppendExecutionProvider("CoreML"); -#else - ex = Assert.Throws(() => { opt.AppendExecutionProvider("CoreML"); }); - Assert.Contains("CoreML execution provider is not supported in this build", ex.Message); -#endif + AssertUtils.IfThrowsCheckException( + () => { opt.AppendExecutionProvider("CoreML"); }, + "Appending CoreML EP should have succeeded or thrown an OnnRuntimeException with the expected message. ", + "CoreML execution provider is not supported in this build"); + + AssertUtils.IfThrowsCheckException( + () => { opt.AppendExecutionProvider("XNNPACK"); }, + "Appending XNNPACK EP should have succeeded or thrown an OnnRuntimeException with the expected message. ", + "XNNPACK execution provider is not supported in this build"); + + AssertUtils.IfThrowsCheckException( + () => { opt.AppendExecutionProvider("SNPE"); }, + "Appending SNPE EP should have succeeded or thrown an OnnRuntimeException with the expected message. ", + "SNPE execution provider is not supported in this build"); + + AssertUtils.IfThrowsCheckException( + () => { opt.AppendExecutionProvider("QNN"); }, + "Appending QNN EP should have succeeded or thrown an OnnRuntimeException with the expected message. ", + "QNN execution provider is not supported in this build"); opt.AppendExecutionProvider_CPU(1); } @@ -825,7 +830,7 @@ private async Task TestMultiThreads() Assert.Equal(res, expectedOut, (IEqualityComparer)new FloatComparer()); } })); - }; + } await Task.WhenAll(tasks); session.Dispose(); } @@ -1682,37 +1687,52 @@ private void TestInferenceSessionWithByteArray() void TestCPUAllocatorInternal(InferenceSession session) + { int device_id = 0; - using (var info_cpu = new OrtMemoryInfo(OrtMemoryInfo.allocatorCPU, OrtAllocatorType.ArenaAllocator, device_id, OrtMemType.Default)) - { - Assert.Equal("Cpu", info_cpu.Name); - Assert.Equal(device_id, info_cpu.Id); - Assert.Equal(OrtAllocatorType.ArenaAllocator, info_cpu.GetAllocatorType()); - Assert.Equal(OrtMemType.Default, info_cpu.GetMemoryType()); - - using (var allocator = new OrtAllocator(session, info_cpu)) - { - var alloc_info = allocator.Info; - // Allocator type returned may be different on x86 so we don't compare. - Assert.Equal(info_cpu.Name, alloc_info.Name); - Assert.Equal(info_cpu.GetMemoryType(), alloc_info.GetMemoryType()); - Assert.Equal(info_cpu.Id, alloc_info.Id); - - uint size = 1024; - OrtMemoryAllocation chunk = allocator.Allocate(size); - Assert.Equal(chunk.Size, size); - var chunk_info = chunk.Info; - // Allocator type returned may be different on x86 so we don't compare. - Assert.Equal(chunk_info.Name, alloc_info.Name); - Assert.Equal(chunk_info.GetMemoryType(), alloc_info.GetMemoryType()); - Assert.Equal(chunk_info.Id, alloc_info.Id); - chunk.Dispose(); - alloc_info.Dispose(); - } - } + using var info_cpu = new OrtMemoryInfo(OrtMemoryInfo.allocatorCPU, + OrtAllocatorType.ArenaAllocator, device_id, OrtMemType.Default); + Assert.Equal("Cpu", info_cpu.Name); + Assert.Equal(device_id, info_cpu.Id); + Assert.Equal(OrtAllocatorType.ArenaAllocator, info_cpu.GetAllocatorType()); + Assert.Equal(OrtMemType.Default, info_cpu.GetMemoryType()); + var deviceMemoryType = info_cpu.GetDeviceMemoryType(); + Assert.Equal(OrtDeviceMemoryType.DEFAULT, deviceMemoryType); + Assert.Equal(0U, info_cpu.GetVendorId()); + + using var allocator = new OrtAllocator(session, info_cpu); + using var alloc_info = allocator.Info; + // Allocator type returned may be different on x86 so we don't compare. + Assert.Equal(info_cpu.Name, alloc_info.Name); + Assert.Equal(info_cpu.GetMemoryType(), alloc_info.GetMemoryType()); + Assert.Equal(info_cpu.Id, alloc_info.Id); + + uint size = 1024; + using OrtMemoryAllocation chunk = allocator.Allocate(size); + Assert.Equal(chunk.Size, size); + var chunk_info = chunk.Info; + // Allocator type returned may be different on x86 so we don't compare. + Assert.Equal(chunk_info.Name, alloc_info.Name); + Assert.Equal(chunk_info.GetMemoryType(), alloc_info.GetMemoryType()); + Assert.Equal(chunk_info.Id, alloc_info.Id); + } + + [Fact(DisplayName = "TestMemoryInfoCreateV2")] + void TestMemoryInfoCreateV2() + { + const int device_id = 0; + const uint vendor_id = 1234U; + using var info_cpu = new OrtMemoryInfo("Test_CPU", OrtMemoryInfoDeviceType.CPU, vendor_id, device_id, + OrtDeviceMemoryType.DEFAULT, 0, OrtAllocatorType.DeviceAllocator); + Assert.Equal("Test_CPU", info_cpu.Name); + Assert.Equal(device_id, info_cpu.Id); + Assert.Equal(OrtAllocatorType.DeviceAllocator, info_cpu.GetAllocatorType()); + Assert.Equal(OrtMemType.Default, info_cpu.GetMemoryType()); + Assert.Equal(OrtDeviceMemoryType.DEFAULT, info_cpu.GetDeviceMemoryType()); + Assert.Equal(vendor_id, info_cpu.GetVendorId()); } + #if USE_CUDA void TestCUDAAllocatorInternal(InferenceSession session) { @@ -1740,33 +1760,6 @@ void TestCUDAAllocatorInternal(InferenceSession session) } #endif -#if USE_ROCM - void TestROCMAllocatorInternal(InferenceSession session) - { - int device_id = 0; - using (var info_rocm = new OrtMemoryInfo(OrtMemoryInfo.allocatorHIP, OrtAllocatorType.ArenaAllocator, device_id, OrtMemType.Default)) - { - Assert.Equal("Hip", info_rocm.Name); - Assert.Equal(device_id, info_rocm.Id); - Assert.Equal(OrtAllocatorType.ArenaAllocator, info_rocm.GetAllocatorType()); - Assert.Equal(OrtMemType.Default, info_rocm.GetMemoryType()); - - using (var allocator = new OrtAllocator(session, info_rocm)) - { - var alloc_info = allocator.Info; - Assert.True(info_rocm.Equals(alloc_info)); - - uint size = 1024; - OrtMemoryAllocation chunk = allocator.Allocate(size); - Assert.Equal(chunk.Size, size); - Assert.True(chunk.Info.Equals(alloc_info)); - chunk.Dispose(); - alloc_info.Dispose(); - } - } - } -#endif - [Fact(DisplayName = "TestAllocator")] private void TestAllocator() { @@ -1777,21 +1770,12 @@ private void TestAllocator() #if USE_CUDA options.AppendExecutionProvider_CUDA(0); #endif - -#if USE_ROCM - options.AppendExecutionProvider_ROCm(0); -#endif - using (var session = new InferenceSession(model, options)) { TestCPUAllocatorInternal(session); #if USE_CUDA TestCUDAAllocatorInternal(session); #endif -#if USE_ROCM - TestROCMAllocatorInternal(session); -#endif - } } } @@ -1884,81 +1868,6 @@ private void TestSharingOfInitializerAndItsPrepackedVersion() } } - [Fact(DisplayName = "TestSharedAllocatorUsingCreateAndRegisterAllocator")] - private void TestSharedAllocatorUsingCreateAndRegisterAllocator() - { - var model = TestDataLoader.LoadModelFromEmbeddedResource("mul_1.onnx"); - - using (var memInfo = new OrtMemoryInfo(OrtMemoryInfo.allocatorCPU, - OrtAllocatorType.ArenaAllocator, 0, OrtMemType.Default)) - using (var arenaCfg = new OrtArenaCfg(0, -1, -1, -1)) - { - var env = OrtEnv.Instance(); - // Create and register the arena based allocator - env.CreateAndRegisterAllocator(memInfo, arenaCfg); - - using (var sessionOptions = new SessionOptions()) - { - // Key must match kOrtSessionOptionsConfigUseEnvAllocators in onnxruntime_session_options_config_keys.h - sessionOptions.AddSessionConfigEntry("session.use_env_allocators", "1"); - - // Create two sessions to share the allocator - // Create a third session that DOES NOT use the allocator in the environment - using (var session1 = new InferenceSession(model, sessionOptions)) - using (var session2 = new InferenceSession(model, sessionOptions)) - using (var session3 = new InferenceSession(model)) // Use the default SessionOptions instance - { - // Input data - var inputDims = new long[] { 3, 2 }; - var input = new float[] { 1.0F, 2.0F, 3.0F, 4.0F, 5.0F, 6.0F }; - - // Output data - int[] outputDims = { 3, 2 }; - float[] output = { 1.0F, 4.0F, 9.0F, 16.0F, 25.0F, 36.0F }; - - // Run inference on all three models - var inputMeta = session1.InputMetadata; - var container = new List(); - - foreach (var name in inputMeta.Keys) - { - Assert.Equal(typeof(float), inputMeta[name].ElementType); - Assert.True(inputMeta[name].IsTensor); - var tensor = new DenseTensor(input, inputMeta[name].Dimensions); - container.Add(NamedOnnxValue.CreateFromTensor(name, tensor)); - } - - // Run inference with named inputs and outputs created with in Run() - using (var results = session1.Run(container)) // results is an IReadOnlyList container - { - foreach (var r in results) - { - ValidateRunResultData(r.AsTensor(), output, outputDims); - } - } - - // Run inference with named inputs and outputs created with in Run() - using (var results = session2.Run(container)) // results is an IReadOnlyList container - { - foreach (var r in results) - { - ValidateRunResultData(r.AsTensor(), output, outputDims); - } - } - - // Run inference with named inputs and outputs created with in Run() - using (var results = session3.Run(container)) // results is an IReadOnlyList container - { - foreach (var r in results) - { - ValidateRunResultData(r.AsTensor(), output, outputDims); - } - } - } - } - } - } - internal static Tuple, float[]> OpenSessionSqueezeNet(int? deviceId = null) { var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); @@ -1993,15 +1902,6 @@ internal static Tuple, float[]> Op { option.AppendExecutionProvider_CPU(1); } -#elif USE_ROCM - using (var option = (deviceId.HasValue) ? - SessionOptions.MakeSessionOptionWithRocmProvider(deviceId.Value) : - new SessionOptions()) - { - if(!deviceId.HasValue) - { - option.AppendExecutionProvider_CPU(1); - } #else using (var option = new SessionOptions()) { diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj index 07ca7fe7c64bf..42d6cb6e42baa 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/Microsoft.ML.OnnxRuntime.Tests.Common.csproj @@ -102,6 +102,7 @@ + diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OnnxMl.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OnnxMl.cs index 510097e2f4c29..f9e9f42f8b78e 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OnnxMl.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OnnxMl.cs @@ -209,7 +209,7 @@ public enum Version { [pbr::OriginalName("IR_VERSION_2019_9_19")] IrVersion2019919 = 6, /// /// IR VERSION 7 published on May 8, 2020 - /// - Add support to allow function body graph to rely on multiple external opreator sets. + /// - Add support to allow function body graph to rely on multiple external operator sets. /// - Add a list to promote inference graph's initializers to global and /// mutable variables. Global variables are visible in all graphs of the /// stored models. @@ -2481,7 +2481,7 @@ public string DocString { /// /// Name of the function "FunctionProto.name" should be unique within the domain "FunctionProto.domain". /// In case of any conflicts the behavior (whether the model local functions are given higher priority, - /// or standard opserator sets are given higher priotity or this is treated as error) is defined by + /// or standard opserator sets are given higher priority or this is treated as error) is defined by /// the runtimes. /// /// The operator sets imported by FunctionProto should be compatible with the ones diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtAutoEpTests.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtAutoEpTests.cs new file mode 100644 index 0000000000000..1be0b6e9530ed --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtAutoEpTests.cs @@ -0,0 +1,291 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// not supported on mobile platforms +#if !(ANDROID || IOS) + +namespace Microsoft.ML.OnnxRuntime.Tests; + +using System; +using System.Linq; +using System.IO; +using System.Runtime.InteropServices; +using Xunit; +using System.Collections.Generic; + +/// +/// Tests for auto ep selection/registration. +/// Includes testing of OrtHardwareDevice and OrtEpDevice as those only come from auto ep related code and we only +/// get read-only access to them (i.e. we can't directly create instances of them to test). +/// +public class OrtAutoEpTests +{ + private OrtEnv ortEnvInstance = OrtEnv.Instance(); + + private void ReadHardwareDeviceValues(OrtHardwareDevice device) + { + Assert.True(device.Type == OrtHardwareDeviceType.CPU || + device.Type == OrtHardwareDeviceType.GPU || + device.Type == OrtHardwareDeviceType.NPU); + if (device.Type == OrtHardwareDeviceType.CPU) + { + Assert.NotEmpty(device.Vendor); + } + else + { + Assert.True(device.VendorId != 0); + Assert.True(device.DeviceId != 0); + } + + var metadata = device.Metadata; + Assert.NotNull(metadata); + foreach (var kvp in metadata.Entries) + { + Assert.NotEmpty(kvp.Key); + // Assert.NotEmpty(kvp.Value); this is allowed + } + } + + [Fact] + public void GetEpDevices() + { + var epDevices = ortEnvInstance.GetEpDevices(); + Assert.NotNull(epDevices); + Assert.NotEmpty(epDevices); + foreach (var ep_device in epDevices) + { + Assert.NotEmpty(ep_device.EpName); + Assert.NotEmpty(ep_device.EpVendor); + var metadata = ep_device.EpMetadata; + Assert.NotNull(metadata); + var options = ep_device.EpOptions; + Assert.NotNull(options); + var memInfo = ep_device.GetMemoryInfo(OrtDeviceMemoryType.DEFAULT); + Assert.NotNull(memInfo); + ReadHardwareDeviceValues(ep_device.HardwareDevice); + } + } + + [Fact] + public void RegisterUnregisterLibrary() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + string libFullPath = Path.Combine(Directory.GetCurrentDirectory(), "example_plugin_ep.dll"); + Assert.True(File.Exists(libFullPath), $"Expected lib {libFullPath} does not exist."); + + // example plugin ep uses the registration name as the ep name + const string epName = "csharp_ep"; + + // register. shouldn't throw + ortEnvInstance.RegisterExecutionProviderLibrary(epName, libFullPath); + try + { + // check OrtEpDevice was found + var epDevices = ortEnvInstance.GetEpDevices(); + var found = epDevices.Any(d => string.Equals(epName, d.EpName, StringComparison.OrdinalIgnoreCase)); + Assert.True(found); + } + finally + { // unregister + ortEnvInstance.UnregisterExecutionProviderLibrary(epName); + } + } + } + + [Fact] + public void AppendToSessionOptionsV2() + { + var runTest = (Func> getEpOptions) => + { + using SessionOptions sessionOptions = new SessionOptions(); + sessionOptions.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_VERBOSE; + + var epDevices = ortEnvInstance.GetEpDevices(); + + // cpu ep ignores the provider options so we can use any value in epOptions and it won't break. + List selectedEpDevices = epDevices.Where(d => d.EpName == "CPUExecutionProvider").ToList(); + + Dictionary epOptions = getEpOptions(); + sessionOptions.AppendExecutionProvider(ortEnvInstance, selectedEpDevices, epOptions); + + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + + // session should load successfully + using (var session = new InferenceSession(model)) + { + Assert.NotNull(session); + } + }; + + runTest(() => + { + // null options + return null; + }); + + runTest(() => + { + // empty options + return new Dictionary(); + }); + + runTest(() => + { + // dummy options + return new Dictionary + { + { "random_key", "value" }, + }; + }); + } + + [Fact] + public void SetEpSelectionPolicy() + { + using SessionOptions sessionOptions = new SessionOptions(); + sessionOptions.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_VERBOSE; + + var epDevices = ortEnvInstance.GetEpDevices(); + Assert.NotEmpty(epDevices); + + // doesn't matter what the value is. should fallback to ORT CPU EP + sessionOptions.SetEpSelectionPolicy(ExecutionProviderDevicePolicy.PREFER_GPU); + + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + + // session should load successfully + using (var session = new InferenceSession(model, sessionOptions)) + { + Assert.NotNull(session); + } + } + + private static List SelectionPolicyDelegate(IReadOnlyList epDevices, + OrtKeyValuePairs modelMetadata, + OrtKeyValuePairs runtimeMetadata, + uint maxSelections) + { + Assert.NotEmpty(modelMetadata.Entries); + Assert.True(epDevices.Count > 0); + + // select first device and last (if there are more than one). + var selected = new List(); + + selected.Add(epDevices[0]); + + // add ORT CPU EP which is always last. + if (maxSelections > 2 && epDevices.Count > 1) + { + selected.Add(epDevices.Last()); + } + + return selected; + } + + [Fact] + public void SetEpSelectionPolicyDelegate() + { + using SessionOptions sessionOptions = new SessionOptions(); + sessionOptions.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_VERBOSE; + + var epDevices = ortEnvInstance.GetEpDevices(); + Assert.NotEmpty(epDevices); + + // doesn't matter what the value is. should fallback to ORT CPU EP + sessionOptions.SetEpSelectionPolicyDelegate(SelectionPolicyDelegate); + + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + + // session should load successfully + using (var session = new InferenceSession(model, sessionOptions)) + { + Assert.NotNull(session); + } + } + + // select max + 1, starting with all devices + private static List SelectionPolicyDelegateTooMany(IReadOnlyList epDevices, + OrtKeyValuePairs modelMetadata, + OrtKeyValuePairs runtimeMetadata, + uint maxSelections) + { + Assert.NotEmpty(modelMetadata.Entries); + Assert.True(epDevices.Count > 0); + var selected = new List(epDevices); + + while (selected.Count < (maxSelections + 1)) + { + selected.Add(epDevices.Last()); + } + + return selected; + } + + [Fact] + public void SetEpSelectionPolicyDelegateTooMany() + { + using SessionOptions sessionOptions = new SessionOptions(); + sessionOptions.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_VERBOSE; + + var epDevices = ortEnvInstance.GetEpDevices(); + Assert.NotEmpty(epDevices); + + // select too many devices + sessionOptions.SetEpSelectionPolicyDelegate(SelectionPolicyDelegateTooMany); + + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + + // session should fail + try + { + using var session = new InferenceSession(model, sessionOptions); + Assert.Fail("Should have thrown an exception"); + } + catch (OnnxRuntimeException ex) + { + // Current C++ max is 8. We copy all devices and keep adding until we exceed that. + const int max = 8; + var numSelected = epDevices.Count > max ? epDevices.Count : (max + 1); + var expected = "[ErrorCode:Fail] EP selection delegate failed: The number of selected devices " + + $"({numSelected}) returned by the C# selection delegate exceeds the maximum ({max})"; + Assert.Contains(expected, ex.Message); + } + } + + // throw exception in user provided delegate + private static List SelectionPolicyDelegateThrows(IReadOnlyList epDevices, + OrtKeyValuePairs modelMetadata, + OrtKeyValuePairs runtimeMetadata, + uint maxSelections) + { + throw new ArgumentException("Test exception"); + } + + [Fact] + public void SetEpSelectionPolicyDelegateThrows() + { + using SessionOptions sessionOptions = new SessionOptions(); + sessionOptions.LogSeverityLevel = OrtLoggingLevel.ORT_LOGGING_LEVEL_VERBOSE; + + var epDevices = ortEnvInstance.GetEpDevices(); + Assert.NotEmpty(epDevices); + + sessionOptions.SetEpSelectionPolicyDelegate(SelectionPolicyDelegateThrows); + + var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); + + try + { + using var session = new InferenceSession(model, sessionOptions); + Assert.Fail("Should have thrown an exception"); + } + catch (OnnxRuntimeException ex) + { + var expected = "[ErrorCode:Fail] EP selection delegate failed: " + + "The C# selection delegate threw an exception: Test exception"; + Assert.Contains(expected, ex.Message); + } + } +} +#endif \ No newline at end of file diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtEnvTests.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtEnvTests.cs index 229d683c162fd..88c7810439c5b 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtEnvTests.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtEnvTests.cs @@ -1,7 +1,13 @@ -using System; +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using Microsoft.ML.OnnxRuntime.Tensors; +using System; +using System.Collections.Generic; +using System.IO; +using System.Runtime.InteropServices; using Xunit; - namespace Microsoft.ML.OnnxRuntime.Tests { /// @@ -50,9 +56,6 @@ public void GetAvailableProviders() #if USE_CUDA Assert.True(Array.Exists(providers, provider => provider == "CUDAExecutionProvider")); -#endif -#if USE_ROCM - Assert.True(Array.Exists(providers, provider => provider == "ROCMExecutionProvider")); #endif } } @@ -212,5 +215,413 @@ public void TestEnvWithCustomLoggerAndThredingOptions() } } } -} + [Collection("Ort Inference Tests")] + public class OrtEnvSharedAllocatorsTests + { + private void ValidateRunResultData(Tensor resultTensor, float[] expectedOutput, int[] expectedDimensions) + { + Assert.Equal(expectedDimensions.Length, resultTensor.Rank); + + var resultDimensions = resultTensor.Dimensions; + for (int i = 0; i < expectedDimensions.Length; i++) + { + Assert.Equal(expectedDimensions[i], resultDimensions[i]); + } + + var resultArray = new float[resultTensor.Length]; + for (int i = 0; i < resultTensor.Length; i++) + { + resultArray[i] = resultTensor.GetValue(i); + } + Assert.Equal(expectedOutput.Length, resultArray.Length); + Assert.Equal(expectedOutput, resultArray, new FloatComparer()); + } + + [Fact(DisplayName = "TestSharedAllocatorUsingCreateAndRegisterAllocator")] + private void TestSharedAllocatorUsingCreateAndRegisterAllocator() + { + var model = TestDataLoader.LoadModelFromEmbeddedResource("mul_1.onnx"); + + using var memInfo = new OrtMemoryInfo(OrtMemoryInfo.allocatorCPU, + OrtAllocatorType.ArenaAllocator, 0, OrtMemType.Default); + using var arenaCfg = new OrtArenaCfg(0, -1, -1, -1); + var env = OrtEnv.Instance(); + // Create and register the arena based allocator + env.CreateAndRegisterAllocator(memInfo, arenaCfg); + try + { + using var sessionOptions = new SessionOptions(); + // Key must match kOrtSessionOptionsConfigUseEnvAllocators in onnxruntime_session_options_config_keys.h + sessionOptions.AddSessionConfigEntry("session.use_env_allocators", "1"); + + // Create two sessions to share the allocator + // Create a third session that DOES NOT use the allocator in the environment + using var session1 = new InferenceSession(model, sessionOptions); + using var session2 = new InferenceSession(model, sessionOptions); + using var session3 = new InferenceSession(model); // Use the default SessionOptions instance + // Input data + var inputDims = new long[] { 3, 2 }; + var input = new float[] { 1.0F, 2.0F, 3.0F, 4.0F, 5.0F, 6.0F }; + + // Output data + int[] outputDims = { 3, 2 }; + float[] output = { 1.0F, 4.0F, 9.0F, 16.0F, 25.0F, 36.0F }; + + // Run inference on all three models + var inputMeta = session1.InputMetadata; + var container = new List(); + + foreach (var name in inputMeta.Keys) + { + Assert.Equal(typeof(float), inputMeta[name].ElementType); + Assert.True(inputMeta[name].IsTensor); + var tensor = new DenseTensor(input, inputMeta[name].Dimensions); + container.Add(NamedOnnxValue.CreateFromTensor(name, tensor)); + } + + // Run inference with named inputs and outputs created with in Run() + using var results = session1.Run(container); // results is an IReadOnlyList container + foreach (var r in results) + { + ValidateRunResultData(r.AsTensor(), output, outputDims); + } + + // Run inference with named inputs and outputs created with in Run() + using var results2 = session2.Run(container); // results is an IReadOnlyList container + foreach (var r in results2) + { + ValidateRunResultData(r.AsTensor(), output, outputDims); + } + + // Run inference with named inputs and outputs created with in Run() + using var results3 = session3.Run(container); // results is an IReadOnlyList container + foreach (var r in results3) + { + ValidateRunResultData(r.AsTensor(), output, outputDims); + } + } + finally + { + // Unregister the allocator + env.UnregisterAllocator(memInfo); + } + } + + [Fact(DisplayName = "TestSharedAllocatorUsingCreateAndRegisterAllocatorV2")] + private void TestSharedAllocatorUsingCreateAndRegisterAllocatorV2() + { + var model = TestDataLoader.LoadModelFromEmbeddedResource("mul_1.onnx"); + + using var memInfo = new OrtMemoryInfo(OrtMemoryInfo.allocatorCPU, + OrtAllocatorType.ArenaAllocator, 0, OrtMemType.Default); + using var arenaCfg = new OrtArenaCfg(0, -1, -1, -1); + var env = OrtEnv.Instance(); + + // Fill in with two arbitrary key-value pairs + var options = new Dictionary() { + { "key1", "value1" }, + { "key2", "value2" } + }; + + // Simply execute CreateAndRegisterAllocatorV2 to verify that C# API works as expected + env.CreateAndRegisterAllocator("CPUExecutionProvider", memInfo, arenaCfg, options); + try + { + using var sessionOptions = new SessionOptions(); + // Key must match kOrtSessionOptionsConfigUseEnvAllocators in onnxruntime_session_options_config_keys.h + sessionOptions.AddSessionConfigEntry("session.use_env_allocators", "1"); + using var session = new InferenceSession(model, sessionOptions); + } + finally + { + // Unregister the allocator + env.UnregisterAllocator(memInfo); + } + } + [Fact(DisplayName = "TestCreateGetReleaseSharedAllocator")] + private void TestCreateGetReleaseSharedAllocator() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var env = OrtEnv.Instance(); + string libFullPath = Path.Combine(Directory.GetCurrentDirectory(), "example_plugin_ep.dll"); + Assert.True(File.Exists(libFullPath), $"Expected lib {libFullPath} does not exist."); + + // example plugin ep uses the registration name as the ep name + const string epName = "csharp_ep"; + + env.RegisterExecutionProviderLibrary(epName, libFullPath); + try + { + // Find OrtEpDevice for the example EP + OrtEpDevice epDevice = null; + var epDevices = env.GetEpDevices(); + foreach (var d in epDevices) + { + if (string.Equals(epName, d.EpName, StringComparison.OrdinalIgnoreCase)) + { + epDevice = d; + } + } + Assert.NotNull(epDevice); + + using var epMemoryInfo = epDevice.GetMemoryInfo(OrtDeviceMemoryType.DEFAULT); + + var options = new Dictionary() { + { "arena.initial_chunk_size_bytes", "25600" }, + }; + + // Strictly speaking the allocator is owned by the env + // but we want to dispose the C# object anyway + using var sharedAllocator = env.CreateSharedAllocator(epDevice, + OrtDeviceMemoryType.DEFAULT, + OrtAllocatorType.DeviceAllocator, + options); + + try + { + using var getAllocator = env.GetSharedAllocator(epMemoryInfo); + Assert.NotNull(getAllocator); + } + finally + { + // ReleaseSharedAllocator is a no-op if the allocator was created with CreateAndRegisterAllocator + env.ReleaseSharedAllocator(epDevice, OrtDeviceMemoryType.DEFAULT); + } + } + finally + { + env.UnregisterExecutionProviderLibrary(epName); + } + } + } + + [Fact(DisplayName = "TestCopyTensors")] + void TestCopyTensors() + { + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + var env = OrtEnv.Instance(); + string libFullPath = Path.Combine(Directory.GetCurrentDirectory(), "example_plugin_ep.dll"); + Assert.True(File.Exists(libFullPath), $"Expected lib {libFullPath} does not exist."); + + // example plugin ep uses the registration name as the ep name + const string epName = "csharp_ep"; + + env.RegisterExecutionProviderLibrary(epName, libFullPath); + try + { + // Find the example device + OrtEpDevice epDevice = null; + var epDevices = env.GetEpDevices(); + foreach (var d in epDevices) + { + if (string.Equals(epName, d.EpName, StringComparison.OrdinalIgnoreCase)) + { + epDevice = d; + } + } + Assert.NotNull(epDevice); + + using var syncStream = epDevice.CreateSyncStream(null); + Assert.NotNull(syncStream); + // This returned Zero for example EP + // therefore do not assert for zero. + var streamHandle = syncStream.GetHandle(); + // Assert.NotEqual(IntPtr.Zero, streamHandle); + + var inputDims = new long[] { 3, 2 }; + float[] inputData1 = [1.0F, 2.0F, 3.0F, 4.0F, 5.0F, 6.0F]; + long[] inputData2 = [1, 2, 3, 4, 5, 6]; + + // Create source OrtValues on CPU on top of inputData + using var inputList = new DisposableListTest(2) + { + OrtValue.CreateTensorValueFromMemory(inputData1, inputDims), + OrtValue.CreateTensorValueFromMemory(inputData2, inputDims) + }; + + using var epMemoryInfo = epDevice.GetMemoryInfo(OrtDeviceMemoryType.DEFAULT); + var options = new Dictionary() { + { "arena.initial_chunk_size_bytes", "25600" }, + }; + + // Strictly speaking the allocator is owned by the env + // but we want to dispose the C# object anyway + using var sharedAllocator = env.CreateSharedAllocator(epDevice, + OrtDeviceMemoryType.DEFAULT, + OrtAllocatorType.DeviceAllocator, + options); + try + { + // Create destination empty OrtValues on the example EP device + using var outputList = new DisposableListTest(2) + { + OrtValue.CreateAllocatedTensorValue(sharedAllocator, + TensorElementType.Float, inputDims), + OrtValue.CreateAllocatedTensorValue(sharedAllocator, + TensorElementType.Int64, inputDims) + }; + + env.CopyTensors(inputList, outputList, syncStream); + + // Assert.Equal data on inputList and outputList + Assert.Equal(inputList[0].GetTensorDataAsSpan(), + outputList[0].GetTensorDataAsSpan()); + Assert.Equal(inputList[1].GetTensorDataAsSpan(), + outputList[1].GetTensorDataAsSpan()); + } + finally + { + // Unregister from the env + env.ReleaseSharedAllocator(epDevice, OrtDeviceMemoryType.DEFAULT); + } + } + finally + { + env.UnregisterExecutionProviderLibrary(epName); + } + } + } + } + + [Collection("Ort Inference Tests")] + public class OrtEnvDllImportResolverTest + { + [Fact(DisplayName = "TestDllImportResolverDoesNotThrow")] + public void TestDllImportResolverDoesNotThrow() + { + // The DllImportResolver is a private static method in NativeMethods. + var nativeMethodsType = typeof(OrtEnv).Assembly.GetType("Microsoft.ML.OnnxRuntime.NativeMethods"); + Assert.NotNull(nativeMethodsType); + + // It might not be defined on all platforms (defined when !NETSTANDARD2_0 && !__ANDROID__ && !__IOS__). + var resolverMethod = nativeMethodsType.GetMethod("DllImportResolver", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static); + + if (resolverMethod != null) + { + try + { + // Invoke with null assembly to force it into edge cases where assembly.Location would throw NullReferenceException. + // It should catch the exception and return IntPtr.Zero gracefully rather than throwing. + var result = resolverMethod.Invoke(null, new object[] { "onnxruntime", null, null }); + + // If it reaches here without throwing TargetInvocationException, the try-catch in DllImportResolver works. + Assert.True(result is IntPtr); + } + catch (System.Reflection.TargetInvocationException ex) + { + // If NativeMethods..cctor() threw because the native library is missing, + // we will get a TypeInitializationException wrapping a DllNotFoundException (or DllImportException). + // This is acceptable locally. What we want to avoid is NullReferenceException from DllImportResolver. + if (ex.InnerException is TypeInitializationException typeInitEx) + { + Assert.IsNotType(typeInitEx.InnerException); + } + else + { + Assert.IsNotType(ex.InnerException); + throw; + } + } + } + } + } + +#if !NETSTANDARD2_0 + [Collection("Ort Inference Tests")] + public class OrtEnvExternalDllImportResolverTest + { + private System.Reflection.Assembly LoadIsolatedOnnxRuntimeAssembly(out System.Runtime.Loader.AssemblyLoadContext alc) + { + // Load a fresh copy of the ONNX Runtime assembly into a new AssemblyLoadContext. + // This guarantees we get a clean slate for static fields/constructors, avoiding + // interference from other xUnit tests that may have already initialized OrtEnv + // in the default context. + // + // Native library resolution (e.g., onnxruntime.dll) falls through to the default + // ALC when the isolated context cannot resolve it, so P/Invoke calls still work. + alc = new System.Runtime.Loader.AssemblyLoadContext("IsolatedORT_" + Guid.NewGuid(), isCollectible: true); + string asmPath = typeof(OrtEnv).Assembly.Location; + return alc.LoadFromAssemblyPath(asmPath); + } + + /// + /// Verifies the scenario where an external caller registers a DllImportResolver FIRST, + /// and then OrtEnv is initialized. ORT's try/catch should handle the conflict gracefully. + /// + [Fact(DisplayName = "TestExternalResolverRegisteredFirst")] + public void TestExternalResolverRegisteredFirst() + { + var asm = LoadIsolatedOnnxRuntimeAssembly(out var alc); + try + { + // 1. External application registers its own resolver FIRST. + // Returning IntPtr.Zero means "not handled" — the runtime falls back to + // its default resolution logic, so native libraries still load normally. + NativeLibrary.SetDllImportResolver(asm, (libraryName, a, searchPath) => IntPtr.Zero); + + // 2. ORT initializes (triggers NativeMethods static constructor). + // It will attempt to register its own resolver, which will throw + // InvalidOperationException internally, but the try/catch safety net + // prevents an unhandled TypeInitializationException. + var ortEnvType = asm.GetType("Microsoft.ML.OnnxRuntime.OrtEnv"); + var instanceMethod = ortEnvType.GetMethod("Instance", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + var ortEnvInstance = instanceMethod.Invoke(null, null); + Assert.NotNull(ortEnvInstance); + + // Verify ORT is fully functional despite the resolver conflict. + var getVersionMethod = ortEnvType.GetMethod("GetVersionString", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance); + var version = (string)getVersionMethod.Invoke(ortEnvInstance, null); + Assert.False(string.IsNullOrEmpty(version)); + } + finally + { + alc.Unload(); + } + } + + /// + /// Verifies that setting DisableDllImportResolver = true BEFORE ORT initializes + /// successfully prevents ORT from registering its own resolver, leaving the assembly + /// free for the external application to register theirs LATER without throwing. + /// + [Fact(DisplayName = "TestDisableDllImportResolverWorks")] + public void TestDisableDllImportResolverWorks() + { + var asm = LoadIsolatedOnnxRuntimeAssembly(out var alc); + try + { + var ortEnvType = asm.GetType("Microsoft.ML.OnnxRuntime.OrtEnv"); + + // 1. Set OrtEnv.DisableDllImportResolver = true FIRST. + var disableProp = ortEnvType.GetProperty("DisableDllImportResolver", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + Assert.NotNull(disableProp); + disableProp.SetValue(null, true); + + // 2. ORT initializes (triggers NativeMethods static constructor). + // It should respect the flag and SKIP calling NativeLibrary.SetDllImportResolver. + var instanceMethod = ortEnvType.GetMethod("Instance", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); + var ortEnvInstance = instanceMethod.Invoke(null, null); + Assert.NotNull(ortEnvInstance); + + // 3. External application registers its own resolver AFTER ORT initialized. + // If the flag works correctly, ORT skipped its own SetDllImportResolver call, + // so this registration should succeed without throwing InvalidOperationException. + // Returning IntPtr.Zero means "not handled" — falls back to default resolution. + var ex = Record.Exception(() => + { + NativeLibrary.SetDllImportResolver(asm, (libraryName, a, searchPath) => IntPtr.Zero); + }); + + Assert.Null(ex); // No InvalidOperationException = ORT correctly skipped registration + } + finally + { + alc.Unload(); + } + } + } +#endif +} diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtKeyValuePairsTests.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtKeyValuePairsTests.cs new file mode 100644 index 0000000000000..b89b970688d5f --- /dev/null +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtKeyValuePairsTests.cs @@ -0,0 +1,39 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +using System; +using Xunit; + +namespace Microsoft.ML.OnnxRuntime.Tests; + +public class OrtKeyValuePairsTests +{ + private OrtEnv ortEnvInstance = OrtEnv.Instance(); + + + [Fact] + public void CRUD() + { + using var kvp = new OrtKeyValuePairs(); + kvp.Add("key1", "value1"); + kvp.Add("key2", "value2"); + kvp.Add("key3", ""); // allowed + + Assert.Equal("value1", kvp.Entries["key1"]); + Assert.Equal("value2", kvp.Entries["key2"]); + Assert.Equal("", kvp.Entries["key3"]); + + kvp.Remove("key1"); + Assert.False(kvp.Entries.ContainsKey("key1")); + + kvp.Remove("invalid_key"); // shouldn't break + + Assert.Equal(2, kvp.Entries.Count); + + // refresh from the C API to make sure everything is in sync + kvp.Refresh(); + Assert.Equal(2, kvp.Entries.Count); + Assert.Equal("value2", kvp.Entries["key2"]); + Assert.Equal("", kvp.Entries["key3"]); + } +} diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtValueTests.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtValueTests.cs index 69baa3f58b23a..eb2e4ad7fb5bb 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtValueTests.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/OrtValueTests.cs @@ -153,6 +153,8 @@ static void VerifyTensorCreateWithData(OrtValue tensor, TensorElementType dat // Verify contained data Assert.Equal(originalData.ToArray(), tensor.GetTensorDataAsSpan().ToArray()); + var byteData = tensor.GetTensorMutableRawData(); + Assert.Equal(byteData.Length, tensor.GetTensorSizeInBytes()); } [Fact(DisplayName = "CreateTensorOverManagedBuffer")] @@ -278,7 +280,8 @@ public void CreateMapFromValues() // Must return always 2 for map since we have two ort values Assert.Equal(2, map.GetValueCount()); - map.ProcessMap((keys, values) => { + map.ProcessMap((keys, values) => + { Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, keys.OnnxType); Assert.Equal(OnnxValueType.ONNX_TYPE_TENSOR, values.OnnxType); Assert.Equal(ml_data_1, keys.GetTensorDataAsSpan().ToArray()); diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TestDataLoader.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TestDataLoader.cs index 9e5e2b6203790..2efbd55f9f350 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TestDataLoader.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TestDataLoader.cs @@ -550,7 +550,7 @@ internal static OrtValue CreateOrtValueFromRawData(OrtAllocator allocator, ReadO var ortValue = OrtValue.CreateAllocatedTensorValue(allocator, elementType, shape); try { - // The endianess data in protobuf is little endian. + // The endianness data in protobuf is little endian. // We simply copy raw memory into the tensor raw data. var span = ortValue.GetTensorMutableRawData(); Assert.Equal(rawData.Length, span.Length); diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TrainingTest.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TrainingTest.cs index 9b72326201322..455b48ec81a5c 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TrainingTest.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Common/TrainingTest.cs @@ -26,16 +26,6 @@ public TrainingTest(ITestOutputHelper o) this.output = o; } -#if !__TRAINING_ENABLED_NATIVE_BUILD__ - [Fact(DisplayName = "TestLoadCheckpointThrows")] - public void TestLoadCheckpointThrows() - { - string path = Path.Combine(Directory.GetCurrentDirectory(), "checkpoint.ckpt"); - var ex = Assert.Throws(() => { var opt = CheckpointState.LoadCheckpoint(path); }); - Assert.Contains("Please install the Microsoft.ML.OnnxRuntime.Training NuGet package.", ex.Message); - } -#endif - #if __TRAINING_ENABLED_NATIVE_BUILD__ [Fact(DisplayName = "TestLoadCheckpoint")] public void TestLoadCheckpoint() diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Devices/TestResultProcessor.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Devices/TestResultProcessor.cs index 8419d261e4a41..625cc2c54055c 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Devices/TestResultProcessor.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.Devices/TestResultProcessor.cs @@ -45,8 +45,9 @@ public TestResultSummary GetResults() public string GetSerializedResults() { var resultSummary = GetResults(); + JsonConvert.DefaultSettings = () => new JsonSerializerSettings { MaxDepth = 128 }; var serializedResultSummary = JsonConvert.SerializeObject(resultSummary, Formatting.Indented); return serializedResultSummary; } } -} \ No newline at end of file +} diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Microsoft.ML.OnnxRuntime.Tests.MAUI.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Microsoft.ML.OnnxRuntime.Tests.MAUI.csproj index e07448daeea7f..b181767aaf247 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Microsoft.ML.OnnxRuntime.Tests.MAUI.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.MAUI/Microsoft.ML.OnnxRuntime.Tests.MAUI.csproj @@ -1,125 +1,139 @@  - - $(ProjectDir)..\..\.. - - - - - - - net8.0-android;net8.0-ios;net8.0-maccatalyst - $(TargetFrameworks);net8.0-windows10.0.19041.0 - - - - - Exe - Microsoft.ML.OnnxRuntime.Tests.MAUI - true - true - enable - enable - true - - 8002 - - - $(DefineConstants);INCLUDE_FAILING_TESTS - $(DefineConstants);MODE_NON_INTERACTIVE_VISUAL - $(DefineConstants);MODE_XHARNESS - - - Microsoft.ML.OnnxRuntime.Tests.MAUI - - - ORT.CSharp.Tests.MAUI - - - 1.0 - 1 - - 15.0 - 13.1 - 30.0 - 10.0.17763.0 - 10.0.17763.0 - - true - ..\..\OnnxRuntime.snk - - + + $(ProjectDir)..\..\.. + + + + + + + + + + net9.0-android + $(TargetFrameworks);net8.0-windows10.0.19041.0 + + + + + Exe + Microsoft.ML.OnnxRuntime.Tests.MAUI + true + true + enable + enable + true + + 8002 + + + $(DefineConstants);INCLUDE_FAILING_TESTS + $(DefineConstants);MODE_NON_INTERACTIVE_VISUAL + $(DefineConstants);MODE_XHARNESS + + + Microsoft.ML.OnnxRuntime.Tests.MAUI + + + ORT.CSharp.Tests.MAUI + + + 1.0 + 1 + + 15.0 + 13.1 + 30.0 + 10.0.17763.0 + 10.0.17763.0 + + true + ..\..\OnnxRuntime.snk + + + + + + + + + + + + + + + + + + + + + + + + InferenceTest.cs + + + OrtIoBindingAllocationTest.cs + + + TensorTests.cs + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - + <_VisualStudioTestRunnerFiles Include="@(PackagingOutputs)" Condition="$([System.String]::Copy('%(PackagingOutputs.FullPath)').Contains('xunit.runner.visualstudio'))" /> + + - - - - InferenceTest.cs - - - OrtIoBindingAllocationTest.cs - - - TensorTests.cs - - + + + - - - - - - - - - - - - - - - - - - + + false + en + - - - - + + apk + - - - <_VisualStudioTestRunnerFiles - Include="@(PackagingOutputs)" - Condition="$([System.String]::Copy('%(PackagingOutputs.FullPath)').Contains('xunit.runner.visualstudio'))" /> - - - diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs index 816511150a137..c0475bb6102c1 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs @@ -42,43 +42,46 @@ public partial class InferenceTest public void CanCreateAndDisposeSessionWithModelPath() { string modelPath = Path.Combine(Directory.GetCurrentDirectory(), "squeezenet.onnx"); - using (var session = new InferenceSession(modelPath)) + using var session = new InferenceSession(modelPath); + Assert.NotNull(session); + Assert.NotNull(session.InputMetadata); + Assert.Single(session.InputMetadata); // 1 input nodeMeta + Assert.True(session.InputMetadata.ContainsKey("data_0")); // input nodeMeta name + Assert.Equal(typeof(float), session.InputMetadata["data_0"].ElementType); + Assert.True(session.InputMetadata["data_0"].IsTensor); + var expectedInputDimensions = new int[] { 1, 3, 224, 224 }; + Assert.Equal(expectedInputDimensions.Length, session.InputMetadata["data_0"].Dimensions.Length); + for (int i = 0; i < expectedInputDimensions.Length; i++) { - Assert.NotNull(session); - Assert.NotNull(session.InputMetadata); - Assert.Single(session.InputMetadata); // 1 input nodeMeta - Assert.True(session.InputMetadata.ContainsKey("data_0")); // input nodeMeta name - Assert.Equal(typeof(float), session.InputMetadata["data_0"].ElementType); - Assert.True(session.InputMetadata["data_0"].IsTensor); - var expectedInputDimensions = new int[] { 1, 3, 224, 224 }; - Assert.Equal(expectedInputDimensions.Length, session.InputMetadata["data_0"].Dimensions.Length); - for (int i = 0; i < expectedInputDimensions.Length; i++) - { - Assert.Equal(expectedInputDimensions[i], session.InputMetadata["data_0"].Dimensions[i]); - } + Assert.Equal(expectedInputDimensions[i], session.InputMetadata["data_0"].Dimensions[i]); + } - Assert.NotNull(session.OutputMetadata); - Assert.Single(session.OutputMetadata); // 1 output nodeMeta - Assert.True(session.OutputMetadata.ContainsKey("softmaxout_1")); // output nodeMeta name - Assert.Equal(typeof(float), session.OutputMetadata["softmaxout_1"].ElementType); - Assert.True(session.OutputMetadata["softmaxout_1"].IsTensor); - var expectedOutputDimensions = new int[] { 1, 1000, 1, 1 }; - Assert.Equal(expectedOutputDimensions.Length, session.OutputMetadata["softmaxout_1"].Dimensions.Length); - for (int i = 0; i < expectedOutputDimensions.Length; i++) - { - Assert.Equal(expectedOutputDimensions[i], session.OutputMetadata["softmaxout_1"].Dimensions[i]); - } + Assert.NotNull(session.OutputMetadata); + Assert.Single(session.OutputMetadata); // 1 output nodeMeta + Assert.True(session.OutputMetadata.ContainsKey("softmaxout_1")); // output nodeMeta name + Assert.Equal(typeof(float), session.OutputMetadata["softmaxout_1"].ElementType); + Assert.True(session.OutputMetadata["softmaxout_1"].IsTensor); + var expectedOutputDimensions = new int[] { 1, 1000, 1, 1 }; + Assert.Equal(expectedOutputDimensions.Length, session.OutputMetadata["softmaxout_1"].Dimensions.Length); + for (int i = 0; i < expectedOutputDimensions.Length; i++) + { + Assert.Equal(expectedOutputDimensions[i], session.OutputMetadata["softmaxout_1"].Dimensions[i]); } + + using var inputsMemoryInfos = session.GetMemoryInfosForInputs(); + Assert.Equal(session.InputNames.Count, inputsMemoryInfos.Count); + using var outputsMemoryInfos = session.GetMemoryInfosForOutputs(); + Assert.Equal(session.OutputNames.Count, outputsMemoryInfos.Count); + var inputsEpDevices = session.GetEpDeviceForInputs(); + Assert.Equal(session.InputNames.Count, inputsEpDevices.Count); } #if NET8_0_OR_GREATER #pragma warning disable SYSLIB5001 // System.Numerics.Tensors is only in preview so we can continue receiving API feedback [Theory] - [InlineData(GraphOptimizationLevel.ORT_DISABLE_ALL, true)] - [InlineData(GraphOptimizationLevel.ORT_DISABLE_ALL, false)] - [InlineData(GraphOptimizationLevel.ORT_ENABLE_EXTENDED, true)] - [InlineData(GraphOptimizationLevel.ORT_ENABLE_EXTENDED, false)] - private void CanRunInferenceOnAModelDotnetTensors(GraphOptimizationLevel graphOptimizationLevel, bool enableParallelExecution) + [InlineData(GraphOptimizationLevel.ORT_DISABLE_ALL)] + [InlineData(GraphOptimizationLevel.ORT_ENABLE_EXTENDED)] + private void CanRunInferenceOnAModelDotnetTensors(GraphOptimizationLevel graphOptimizationLevel) { var model = TestDataLoader.LoadModelFromEmbeddedResource("squeezenet.onnx"); @@ -151,15 +154,15 @@ public void InferenceSessionDisposedDotnetTensors() using (var inputOrtValues = new DisposableListTest>(session.InputMetadata.Count)) using (var outputOrtValues = new DisposableListTest>(session.OutputMetadata.Count)) { - + foreach (var name in inputMeta.Keys) { Assert.Equal(typeof(float), inputMeta[name].ElementType); Assert.True(inputMeta[name].IsTensor); - var tensor = SystemNumericsTensors.Tensor.Create(inputData, inputMeta[name].Dimensions.Select(x => (nint) x).ToArray()); + var tensor = SystemNumericsTensors.Tensor.Create(inputData, inputMeta[name].Dimensions.Select(x => (nint)x).ToArray()); inputOrtValues.Add(new DisposableTestPair(name, OrtValue.CreateTensorValueFromSystemNumericsTensorObject(tensor))); } - + // Run inference with named inputs and outputs created with in Run() using (var results = session.Run(runOptions, inputOrtValues.Select(x => x.Key).ToList(), inputOrtValues.Select(x => x.Value).ToList(), new List(["softmaxout_1"]))) // results is an IDisposableReadOnlyCollection container { @@ -224,7 +227,7 @@ private void ThrowWrongOutputDimensionDotnetTensors() inputOrtValues.Add(new DisposableTestPair("data_0", OrtValue.CreateTensorValueFromSystemNumericsTensorObject(tensor))); outputOrtValues.Add(new DisposableTestPair("softmaxout_1", OrtValue.CreateTensorValueFromSystemNumericsTensorObject(outputTensor))); - + var ex = Assert.Throws(() => session.Run(runOptions, ["data_0"], [inputOrtValues[0].Value], ["softmaxout_1"], [outputOrtValues[0].Value])); } @@ -598,6 +601,29 @@ private static Dictionary GetSkippedModels(DirectoryInfo modelsD skipModels["VGG 16-fp32"] = "bad allocation"; } + // The following models are from onnx repo and fail on MacOS nuget test pipeline. + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + var macOSSkips = new[] + { + "test_castlike_FLOAT_to_STRING_expanded", + "test_castlike_FLOAT_to_BFLOAT16_expanded", + "test_castlike_BFLOAT16_to_FLOAT", + "test_cast_FLOAT_to_STRING", + "test_castlike_FLOAT_to_BFLOAT16", + "test_castlike_STRING_to_FLOAT_expanded", + "test_castlike_STRING_to_FLOAT", + "test_cast_STRING_to_FLOAT", + "test_castlike_BFLOAT16_to_FLOAT_expanded", + "test_cast_BFLOAT16_to_FLOAT", + "test_castlike_FLOAT_to_STRING" + }; + foreach (var model in macOSSkips) + { + skipModels[model] = "Skipped on macOS due to flakes or lack of support"; + } + } + return skipModels; } @@ -931,6 +957,7 @@ public void TestPretrainedModelsWithOrtValue(string opsetDir, string modelName) [MemberData(nameof(GetSkippedModelForTest), Skip = "Skipped due to Error, please fix the error and enable the test")] private void TestPreTrainedModels(string opsetDir, string modelName, bool useOrtValueAPIs = false) { + var opsetDirInfo = new DirectoryInfo(opsetDir); var opset = opsetDirInfo.Name; string onnxModelFileName = null; @@ -1528,7 +1555,6 @@ private void TestInferenceWithLoraAdapterFromArray() // TestGpu() will test // - the CUDA EP on CUDA enabled builds // - the DML EP on DML enabled builds - // - the ROCm EP on ROCm enabled builds [GpuFact(DisplayName = "TestGpu")] private void TestGpu() { @@ -1572,9 +1598,6 @@ private void VerifyNativeMethodsExist() #if USE_CUDA ,"OrtSessionOptionsAppendExecutionProvider_CUDA" #endif -#if USE_ROCM - ,"OrtSessionOptionsAppendExecutionProvider_ROCM" -#endif #if USE_DML ,"OrtSessionOptionsAppendExecutionProvider_DML" #endif diff --git a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp.csproj b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp.csproj index a8abcd2b4aa1c..54b9925710296 100644 --- a/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp.csproj +++ b/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp.csproj @@ -70,7 +70,8 @@ + $(NativeBuildOutputDir)\custom_op_library*.dll; + $(NativeBuildOutputDir)\example_plugin_ep*.dll"> PreserveNewest false diff --git a/csharp/testdata/conv_qdq_external_ini.bin b/csharp/testdata/conv_qdq_external_ini.bin new file mode 100644 index 0000000000000..89eea0dba1fa4 Binary files /dev/null and b/csharp/testdata/conv_qdq_external_ini.bin differ diff --git a/csharp/testdata/conv_qdq_external_ini.onnx b/csharp/testdata/conv_qdq_external_ini.onnx new file mode 100644 index 0000000000000..c53e1f3ad4d9b Binary files /dev/null and b/csharp/testdata/conv_qdq_external_ini.onnx differ diff --git a/csharp/tools/MauiModelTester/MauiModelTester.csproj b/csharp/tools/MauiModelTester/MauiModelTester.csproj index 39e688ce6c1b8..2660d07c17d02 100644 --- a/csharp/tools/MauiModelTester/MauiModelTester.csproj +++ b/csharp/tools/MauiModelTester/MauiModelTester.csproj @@ -1,7 +1,7 @@  - net8.0-ios;net8.0-android34.0 + net9.0-ios;net9.0-android35.0 $(TargetFrameworks);net8.0-windows10.0.19041.0 Exe MauiModelTester diff --git a/csharp/tools/MauiModelTester/create_test_data.py b/csharp/tools/MauiModelTester/create_test_data.py index d73fd950a7bc0..d6435b6cb85b4 100644 --- a/csharp/tools/MauiModelTester/create_test_data.py +++ b/csharp/tools/MauiModelTester/create_test_data.py @@ -84,7 +84,7 @@ def parse_args(): def create_existing_data_map(pb_files: list[Path]): - import onnx_test_data_utils as data_utils + import onnx_test_data_utils as data_utils # noqa: PLC0415 data_map = {} for file in pb_files: @@ -101,7 +101,7 @@ def add_model_and_test_data_to_app( input_map: dict[str, np.ndarray] | None = None, output_map: dict[str, np.ndarray] | None = None, ): - import ort_test_dir_utils as utils + import ort_test_dir_utils as utils # noqa: PLC0415 output_path = SOLUTION_DIR / "Resources" / "Raw" test_name = "test_data" diff --git a/csharp/tools/Microsoft.ML.OnnxRuntime.PerfTool/OnnxMl.cs b/csharp/tools/Microsoft.ML.OnnxRuntime.PerfTool/OnnxMl.cs index 9ee5e44a356da..6dd94750afd0a 100644 --- a/csharp/tools/Microsoft.ML.OnnxRuntime.PerfTool/OnnxMl.cs +++ b/csharp/tools/Microsoft.ML.OnnxRuntime.PerfTool/OnnxMl.cs @@ -209,7 +209,7 @@ public enum Version { [pbr::OriginalName("IR_VERSION_2019_9_19")] IrVersion2019919 = 6, /// /// IR VERSION 7 published on May 8, 2020 - /// - Add support to allow function body graph to rely on multiple external opreator sets. + /// - Add support to allow function body graph to rely on multiple external operator sets. /// - Add a list to promote inference graph's initializers to global and /// mutable variables. Global variables are visible in all graphs of the /// stored models. @@ -2481,7 +2481,7 @@ public string DocString { /// /// Name of the function "FunctionProto.name" should be unique within the domain "FunctionProto.domain". /// In case of any conflicts the behavior (whether the model local functions are given higher priority, - /// or standard opserator sets are given higher priotity or this is treated as error) is defined by + /// or standard opserator sets are given higher priority or this is treated as error) is defined by /// the runtimes. /// /// The operator sets imported by FunctionProto should be compatible with the ones diff --git a/dockerfiles/Dockerfile.migraphx b/dockerfiles/Dockerfile.migraphx index 876a07e4ffaf6..3c52b7574ccf6 100644 --- a/dockerfiles/Dockerfile.migraphx +++ b/dockerfiles/Dockerfile.migraphx @@ -5,22 +5,17 @@ # Dockerfile to run ONNXRuntime with MIGraphX integration #-------------------------------------------------------------------------- -FROM rocm/pytorch:rocm6.2.3_ubuntu22.04_py3.10_pytorch_release_2.3.0 +FROM rocm/pytorch:rocm7.1_ubuntu24.04_py3.12_pytorch_release_2.9.1 -ARG ONNXRUNTIME_REPO=https://github.com/Microsoft/onnxruntime +ARG ONNXRUNTIME_REPO=https://github.com/microsoft/onnxruntime ARG ONNXRUNTIME_BRANCH=main -ENV PATH=/code/cmake-3.27.3-linux-x86_64/bin:${PATH} - -RUN apt-get update &&\ - apt-get install -y migraphx - WORKDIR /code # Prepare onnxruntime repository & build onnxruntime RUN git clone --single-branch --branch ${ONNXRUNTIME_BRANCH} --recursive ${ONNXRUNTIME_REPO} onnxruntime &&\ /bin/sh onnxruntime/dockerfiles/scripts/install_common_deps.sh &&\ cd onnxruntime && pip install --upgrade pip &&\ - /bin/sh ./build.sh --allow_running_as_root --cmake_extra_defines ONNXRUNTIME_VERSION=`cat ./VERSION_NUMBER` --config Release --parallel \ - --skip_tests --build_wheel --use_rocm --rocm_version=${ROCM_VERSION} --rocm_home /opt/rocm --use_migraphx &&\ + /bin/sh ./build.sh --allow_running_as_root --cmake_extra_defines ONNXRUNTIME_VERSION=`cat ./VERSION_NUMBER` \ + --config Release --parallel --skip_tests --build_wheel --use_migraphx &&\ pip install /code/onnxruntime/build/Linux/Release/dist/*.whl diff --git a/dockerfiles/Dockerfile.rocm b/dockerfiles/Dockerfile.rocm deleted file mode 100644 index aca8c3feaff71..0000000000000 --- a/dockerfiles/Dockerfile.rocm +++ /dev/null @@ -1,24 +0,0 @@ -# -------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. -# -------------------------------------------------------------- -# Dockerfile to run ONNXRuntime with ROCm integration -#-------------------------------------------------------------------------- - -FROM rocm/pytorch:rocm6.2.3_ubuntu22.04_py3.10_pytorch_release_2.3.0 - -ARG ONNXRUNTIME_REPO=https://github.com/Microsoft/onnxruntime -ARG ONNXRUNTIME_BRANCH=main - -WORKDIR /code - -ENV PATH=/code/cmake-3.27.3-linux-x86_64/bin:${PATH} - -# Prepare onnxruntime repository & build onnxruntime -RUN git clone --single-branch --branch ${ONNXRUNTIME_BRANCH} --recursive ${ONNXRUNTIME_REPO} onnxruntime &&\ - /bin/sh onnxruntime/dockerfiles/scripts/install_common_deps.sh &&\ - cd onnxruntime &&\ - /bin/sh ./build.sh --allow_running_as_root --config Release --build_wheel --update --build --parallel --cmake_extra_defines\ - ONNXRUNTIME_VERSION=$(cat ./VERSION_NUMBER) --use_rocm --rocm_home=/opt/rocm &&\ - pip install /code/onnxruntime/build/Linux/Release/dist/*.whl &&\ - cd .. diff --git a/dockerfiles/Dockerfile.source b/dockerfiles/Dockerfile.source index 5822a805c674e..51291e59aa0d5 100644 --- a/dockerfiles/Dockerfile.source +++ b/dockerfiles/Dockerfile.source @@ -4,18 +4,16 @@ # -------------------------------------------------------------- # Dockerfile to run ONNXRuntime with source build for CPU -FROM mcr.microsoft.com/cbl-mariner/base/python:3 +FROM mcr.microsoft.com/azurelinux/base/python:3 MAINTAINER Changming Sun "chasun@microsoft.com" ADD . /code RUN tdnf install -y tar ca-certificates build-essential cmake curl python3-devel python3-setuptools python3-wheel python3-pip python3-numpy python3-flatbuffers python3-packaging python3-protobuf -# The latest cmake version in Mariner2 is 3.21, but we need 3.26+ -RUN /code/dockerfiles/scripts/install_cmake.sh # Prepare onnxruntime repository & build onnxruntime RUN cd /code && /bin/bash ./build.sh --allow_running_as_root --skip_submodule_sync --config Release --build_wheel --update --build --parallel --cmake_extra_defines ONNXRUNTIME_VERSION=$(cat ./VERSION_NUMBER) -FROM mcr.microsoft.com/cbl-mariner/base/python:3 +FROM mcr.microsoft.com/azurelinux/base/python:3 COPY --from=0 /code/build/Linux/Release/dist /root COPY --from=0 /code/dockerfiles/LICENSE-IMAGE.txt /code/LICENSE-IMAGE.txt -RUN tdnf install -y ca-certificates python3-setuptools python3-wheel python3-pip python3-numpy python3-flatbuffers python3-packaging python3-protobuf python3-mpmath python3-sympy && python3 -m pip install coloredlogs humanfriendly && python3 -m pip install --no-index --find-links /root onnxruntime && rm -rf /root/*.whl +RUN tdnf install -y ca-certificates python3-setuptools python3-wheel python3-pip python3-numpy python3-flatbuffers python3-packaging python3-protobuf python3-mpmath python3-sympy && python3 -m pip install humanfriendly && python3 -m pip install --no-index --find-links /root onnxruntime && rm -rf /root/*.whl diff --git a/dockerfiles/README.md b/dockerfiles/README.md index 9f83fc390eee7..88c542b63ccd2 100644 --- a/dockerfiles/README.md +++ b/dockerfiles/README.md @@ -1,9 +1,8 @@ # Dockerfiles **Execution Providers** - CPU: [Dockerfile](Dockerfile.source), [Instructions](#cpu) -- CUDA/cuDNN: [Dockerfile](Dockerfile.cuda), [Instructions](#cuda) +- CUDA: [Dockerfile](Dockerfile.cuda), [Instructions](#cuda) - MIGraphX: [Dockerfile](Dockerfile.migraphx), [Instructions](#migraphx) -- ROCm: [Dockerfile](Dockerfile.rocm), [Instructions](#rocm) - OpenVINO: [Dockerfile](Dockerfile.openvino), [Instructions](#openvino) - TensorRT: [Dockerfile](Dockerfile.tensorrt), [Instructions](#tensorrt) - VitisAI: [Dockerfile](Dockerfile.vitisai) @@ -35,7 +34,7 @@ The docker file supports both x86_64 and ARM64(aarch64). You may use docker's "--platform" parameter to explicitly specify which CPU architecture you want to build. For example: ```bash - docker build --platform linux/arm64/v8 -f Dockerfile.source + docker build --platform linux/arm64/v8 -f Dockerfile.source .. ``` However, we cannot build the code for 32-bit ARM in such a way since a 32-bit compiler/linker might not have enough memory to generate the binaries. @@ -304,17 +303,3 @@ Note: When running the container you built in Docker, please either use 'nvidia- ``` docker run -it --device=/dev/kfd --device=/dev/dri --group-add video onnxruntime-migraphx ``` - - ## ROCm -**Ubuntu 22.04, ROCm6.2.3** - -1. Build the docker image from the Dockerfile in this repository. - ``` - docker build -t onnxruntime-rocm -f Dockerfile.rocm . - ``` - -2. Run the Docker image - - ``` - docker run -it --device=/dev/kfd --device=/dev/dri --group-add video onnxruntime-rocm - ``` diff --git a/dockerfiles/scripts/install_cmake.sh b/dockerfiles/scripts/install_cmake.sh index e89c323460ac4..6229339251ec4 100755 --- a/dockerfiles/scripts/install_cmake.sh +++ b/dockerfiles/scripts/install_cmake.sh @@ -5,7 +5,7 @@ cd /tmp/src echo "Installing cmake" CPU_ARCH=`uname -m` -CMAKE_VERSION='3.27.3' +CMAKE_VERSION='3.28.0' curl https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-linux-$CPU_ARCH.tar.gz -sSL --retry 5 -o /tmp/src/cmake.tar.gz tar -zxf /tmp/src/cmake.tar.gz --strip=1 -C /usr rm -f /tmp/src/cmake.tar.gz diff --git a/dockerfiles/scripts/install_common_deps.sh b/dockerfiles/scripts/install_common_deps.sh index 41bdc068d8cde..bbb672a99e8ed 100644 --- a/dockerfiles/scripts/install_common_deps.sh +++ b/dockerfiles/scripts/install_common_deps.sh @@ -21,6 +21,6 @@ pip install "wheel>=0.35.1" rm -rf /opt/miniconda/pkgs # Dependencies: cmake -wget --quiet https://github.com/Kitware/CMake/releases/download/v3.30.1/cmake-3.30.1-linux-x86_64.tar.gz -tar zxf cmake-3.30.1-linux-x86_64.tar.gz -rm -rf cmake-3.30.1-linux-x86_64.tar.gz +wget --quiet https://github.com/Kitware/CMake/releases/download/v3.31.5/cmake-3.31.5-linux-x86_64.tar.gz +tar zxf cmake-3.31.5-linux-x86_64.tar.gz +rm -rf cmake-3.31.5-linux-x86_64.tar.gz diff --git a/dockerfiles/scripts/install_rocm_deps.sh b/dockerfiles/scripts/install_rocm_deps.sh deleted file mode 100644 index fd445be87479b..0000000000000 --- a/dockerfiles/scripts/install_rocm_deps.sh +++ /dev/null @@ -1,84 +0,0 @@ -#!/bin/bash -prefix=/opt/rocm -DEBIAN_FRONTEND=noninteractive -apt-get update && apt-get install -y --no-install-recommends \ - wget \ - zip \ - ca-certificates \ - build-essential \ - curl \ - libcurl4-openssl-dev \ - libssl-dev \ - python3-dev - -# rocm-cmake -rocm_cmake_version=4.5.2 -wget --quiet https://github.com/RadeonOpenCompute/rocm-cmake/archive/refs/tags/rocm-${rocm_cmake_version}.tar.gz -tar -xzvf rocm-${rocm_cmake_version}.tar.gz -rm rocm-${rocm_cmake_version}.tar.gz -cd rocm-cmake-rocm-${rocm_cmake_version} -mkdir build -cd build -cmake -DCMAKE_INSTALL_PREFIX=$prefix .. -make -j8 -make install -cd ../.. -rm -rf rocm-cmake-rocm-${rocm_cmake_version} - -# rccl -rccl_version=4.5.2 -wget --quiet https://github.com/ROCmSoftwarePlatform/rccl/archive/refs/tags/rocm-${rccl_version}.tar.gz -tar -xzvf rocm-${rccl_version}.tar.gz -rm rocm-${rccl_version}.tar.gz -cd rccl-rocm-${rccl_version} -mkdir build -cd build -CXX=/opt/rocm/bin/hipcc cmake -DCMAKE_INSTALL_PREFIX=$prefix .. -make -j8 -make install -cd ../.. -rm -rf rccl-rocm-${rccl_version} - -#rocrand -rocrand_version=4.5.2 -wget --quiet https://github.com/ROCmSoftwarePlatform/rocRAND/archive/refs/tags/rocm-${rocrand_version}.tar.gz -tar -xzvf rocm-${rocrand_version}.tar.gz -rm rocm-${rocrand_version}.tar.gz -cd rocRAND-rocm-${rocrand_version} -mkdir build -cd build -CXX=/opt/rocm/bin/hipcc cmake -DCMAKE_INSTALL_PREFIX=$prefix .. -make -j8 -make install -cd ../.. -rm -rf rocRAND-rocm-${rocrand_version} - -#hipcub -hipcub_version=4.5.2 -wget --quiet https://github.com/ROCmSoftwarePlatform/hipCUB/archive/refs/tags/rocm-${hipcub_version}.tar.gz -tar -xzvf rocm-${hipcub_version}.tar.gz -rm rocm-${hipcub_version}.tar.gz -cd hipCUB-rocm-${hipcub_version} -mkdir build -cd build -CXX=/opt/rocm/bin/hipcc cmake -DCMAKE_INSTALL_PREFIX=$prefix .. -make -j8 -make package -make install -cd ../.. -rm -rf hipCUB-rocm-${hipcub_version} - -#rocprim -rocprim_version=4.5.2 -wget --quiet https://github.com/ROCmSoftwarePlatform/rocPRIM/archive/refs/tags/rocm-${rocprim_version}.tar.gz -tar -xzvf rocm-${rocprim_version}.tar.gz -rm rocm-${rocprim_version}.tar.gz -cd rocPRIM-rocm-${rocprim_version} -mkdir build -cd build -CXX=/opt/rocm/bin/hipcc cmake -DCMAKE_INSTALL_PREFIX=$prefix .. -make -j8 -make install -cd ../.. -rm -rf rocPRIM-rocm-${rocprim_version} - diff --git a/docs/ContribOperators.md b/docs/ContribOperators.md index 571d26bc1903b..fb6a4eb22a872 100644 --- a/docs/ContribOperators.md +++ b/docs/ContribOperators.md @@ -15,6 +15,7 @@ Do not modify directly.* * com.microsoft.BitmaskBiasDropout * com.microsoft.BitmaskDropout * com.microsoft.CDist + * com.microsoft.CausalConvWithState * com.microsoft.ComplexMul * com.microsoft.ComplexMulConj * com.microsoft.ConvTransposeWithDynamicPads @@ -49,6 +50,7 @@ Do not modify directly.* * com.microsoft.GroupQueryAttention * com.microsoft.Inverse * com.microsoft.Irfft + * com.microsoft.LinearAttention * com.microsoft.LongformerAttention * com.microsoft.MatMulBnb4 * com.microsoft.MatMulFpQ4 @@ -67,6 +69,7 @@ Do not modify directly.* * com.microsoft.PackedAttention * com.microsoft.PackedMultiHeadAttention * com.microsoft.Pad + * com.microsoft.PagedAttention * com.microsoft.QAttention * com.microsoft.QGemm * com.microsoft.QLinearAdd @@ -198,7 +201,7 @@ This version of the operator has been available since version 1 of the 'com.micr #### Type Constraints
-
T : tensor(float), tensor(float16)
+
T : tensor(float), tensor(float16), tensor(bfloat16)
Constrain input and output types to float tensors.
M : tensor(int32)
Constrain mask index to integer types
@@ -815,7 +818,7 @@ This version of the operator has been available since version 1 of the 'com.micr scale = 1. / (1. - ratio). ``` - This op functions in much the same was as Dropout-11 and Dropout-13 do, execpt that the mask is output as a bit-packed uint32 tensor, instead of a boolean tensor. + This op functions in much the same was as Dropout-11 and Dropout-13 do, except that the mask is output as a bit-packed uint32 tensor, instead of a boolean tensor. #### Version @@ -899,6 +902,68 @@ This version of the operator has been available since version 1 of the 'com.micr
+### **com.microsoft.CausalConvWithState** + + Stateful causal depthwise convolution, generalized to N spatial dimensions. + + Used by Gated DeltaNet (Qwen3.5) and Mamba (Jamba, FalconMamba) as a preprocessing step. + Replaces the 3-op pattern (Concat + Conv + Slice) with a single fused operation. + + The convolution is causal (looks only at current and past positions along the last + spatial dimension) and depthwise (each channel is convolved independently with its own kernel). + + Input layout is channels-first: (batch_size, channels, ...). + Weight layout: (channels, 1, k_1, ...) for depthwise convolution. + The carry state stores the last (k-1) positions along the causal axis for incremental decode. + + The ndim attribute generalizes the op to 1D, 2D, or 3D spatial dimensions. Causality is + enforced on the last spatial dimension only. + + The optional activation attribute supports fused SiLU/Swish activation. + +#### Version + +This version of the operator has been available since version 1 of the 'com.microsoft' operator set. + +#### Attributes + +
+
activation : string
+
Fused activation function. One of: 'silu', 'swish', 'none'. Default is 'none'.
+
ndim : int
+
Spatial dimensionality: 1, 2, or 3. Default is 1.
+
+ +#### Inputs (2 - 4) + +
+
input : T
+
Input tensor with shape (batch_size, channels, ...). Channels-first layout. Spatial dims: 1D: (L,); 2D: (H, W); 3D: (D, H, W).
+
weight : T
+
Depthwise convolution kernel with shape (channels, 1, k_1, ...). Spatial kernel sizes: (k_1, ..., k_ndim).
+
bias (optional) : T
+
Optional per-channel bias with shape (channels).
+
past_state (optional) : T
+
Carry state from previous step. For ndim=1: (batch_size, channels, k_1 - 1). If not provided, padding is zero.
+
+ +#### Outputs + +
+
output : T
+
Convolution output with same shape as input.
+
present_state : T
+
Updated carry state. For ndim=1: (batch_size, channels, k_1 - 1). Contains the last (k-1) values from the virtual input along the causal axis.
+
+ +#### Type Constraints + +
+
T : tensor(float), tensor(float16), tensor(bfloat16)
+
Constrain input and output types to float tensors.
+
+ + ### **com.microsoft.ComplexMul** #### Version @@ -1191,17 +1256,17 @@ This version of the operator has been available since version 1 of the 'com.micr
present state for key with shape (batch_size, num_heads, total_sequence_length, head_size). If past_present_share_buffer is set, its shape is (batch_size, num_heads, max_sequence_length, head_size), while effective_seq_length = (past_sequence_length + kv_sequence_length).
present_value (optional) : T
present state for value with shape (batch_size, num_heads, total_sequence_length, head_size). If past_present_share_buffer is set, its shape is (batch_size, num_heads, max_sequence_length, head_size), while effective_seq_length = (past_sequence_length + kv_sequence_length).
-
qk (optional) : V
+
qk (optional) : QK
normalized Q * K, of shape (batch_size, num_heads, 1, total_sequence_length).
#### Type Constraints
-
V : tensor(float)
-
Constrain qk output types to float32 tensors.
T : tensor(float), tensor(float16)
Constrain input and output types to float tensors.
+
QK : tensor(float), tensor(float16)
+
Constrain QK output to float32 or float16 tensors, independent of input type or output type.
M : tensor(int32)
Constrain mask index to integer types
@@ -1625,7 +1690,7 @@ This version of the operator has been available since version 1 of the 'com.micr #### Type Constraints
-
T : tensor(int8), tensor(int16), tensor(int32), tensor(int64), tensor(uint8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(float16), tensor(float), tensor(double), tensor(bfloat16)
+
T : tensor(bool), tensor(int8), tensor(int16), tensor(int32), tensor(int64), tensor(uint8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(float16), tensor(float), tensor(double), tensor(bfloat16)
Constrain input and output types.
@@ -2037,12 +2102,13 @@ This version of the operator has been available since version 1 of the 'com.micr GatherBlockQuantized is a Gather with data quantized. It is similar to Gather (https://github.com/onnx/onnx/blob/main/docs/Operators.md#gather) with differences: 1. Input `data` is a constant. It is quantized block-wise along attribute `quantize_axis` with block size specified by attribute `block_size`. - `block_size must` be a power of 2 and not smaller than 16, like 16, 32, 64, 128, .. + `block_size` must be a power of 2 and not smaller than 16, like 16, 32, 64, 128, ... 2. Input `data`'s scale and zero point are specified by input `scales` and `zero_points`. `scales` and `zero_points` are also constants. - If `zero_points` is not provided, 0 is the zero point. + If `zero_points` is not provided, the default value is 0 for int4/uint4, or 2^(bits-1) for uint8. 3. During the op execution, `data` and `indices` are first used to generate the quantized output. Then, `scales` and `zero_points` are used to dequantize the output. 4. The `output` and `scales` have the same type. The `data` and `zero_points` have the same type. + 5. For uint8 data, the `gather_axis` must be 0. #### Version @@ -2051,6 +2117,8 @@ This version of the operator has been available since version 1 of the 'com.micr #### Attributes
+
bits : int
+
Number of bits used for weight quantization. Must be either 4 or 8.
block_size : int
(Optional) block size used for weight quantization. It needs to be a power of 2 and not smaller than 16.
gather_axis : int
@@ -2082,7 +2150,7 @@ This version of the operator has been available since version 1 of the 'com.micr #### Type Constraints
-
T1 : tensor(int4), tensor(uint4)
+
T1 : tensor(int4), tensor(uint4), tensor(uint8)
Constrain quantized types.
T2 : tensor(float), tensor(float16), tensor(bfloat16)
Constrain dequantized types.
@@ -2230,9 +2298,9 @@ This version of the operator has been available since version 1 of the 'com.micr
dtype : int
Output Type. Same definition as attribute 'to' for operator Cast.
transA : int
-
Whether A should be transposed. Float 8 only supprted transA=0.
+
Whether A should be transposed. Float 8 only supported transA=0.
transB : int
-
Whether B should be transposed. Float 8 only supprted transB=1.
+
Whether B should be transposed. Float 8 only supported transB=1.
#### Inputs (2 - 6) @@ -2308,7 +2376,7 @@ This version of the operator has been available since version 1 of the 'com.micr
emb : U
-
embeddding - 3D tensor with shape (batch_size, seq_len, dim)
+
embedding - 3D tensor with shape (batch_size, seq_len, dim)
q : T
q state - 4D tensor with shape (batch_size, num_heads, seq_len, dim)
q_rot : T
@@ -2516,15 +2584,26 @@ This version of the operator has been available since version 1 of the 'com.micr ### **com.microsoft.GroupQueryAttention** - Group Query Self/Cross Attention. + Group Query Self/Cross Attention with KV Cache Quantization Support. + + This operator implements causal grouped-query attention with past state (KV cache) support. + It also supports optional float8, int8 or int4 quantization for the KV cache to reduce memory footprint. + + **Cache Format:** + The past and present KV cache tensors are expected in a BNSH format: `(batch_size, num_heads, cache_sequence_length, head_size)`, where `cache_sequence_length` is the length of the cached key/value sequences, or the maximum sequence length when past and present buffer sharing is used. + + **Quantization:** + When quantization is enabled, `past_key` and `past_value` inputs can be of type `float8e4m3fn`, `uint8` or `int8`. The corresponding `k_scale` and `v_scale` tensors must be provided. + The operator will output `present_key` and `present_value` in same format as the `past_key` and `past_value`. + + For 4-bit quantization, the data type is uint8 where each byte contains two 4-bit values. The bit width of quantized KV cache can be set using `kv_cache_bit_width` attribute. - *Highly recommend using k-v cache share buffer for both CPU and CUDA. Enabled through IOBinding past and present kv. - Supports different number of heads for q and kv for CPU and CUDA. - Only supports causal and local attention. - Supports rotary position embedding for CPU and CUDA. - Supports packed input for CPU and CUDA. - Supports continuous decoding for batch_size == 1 for CPU and CUDA. + The shapes of the k_scale, v_scale tensors shall be broadcastable to present_key shape. + **Quantization Modes (`k_quant_type`, `v_quant_type` attributes):** + - **"NONE"**: No quantization. + - **"PER_TENSOR"**: A single scale for the entire tensor. Scale example shape: `[1]`. + - **"PER_CHANNEL"**: A scale for each channel. Scale example shape: `[1, num_heads_k, 1, head_size]`. #### Version @@ -2535,12 +2614,18 @@ This version of the operator has been available since version 1 of the 'com.micr
do_rotary : int
Whether to use rotary position embedding. Default value is 0.
+
k_quant_type : string
+
Quantization type for K cache. One of 'NONE', 'PER_TENSOR', 'PER_CHANNEL'.
+
kv_cache_bit_width : int
+
Bit width of quantized KV cache. Supported values are 8 and 4.
kv_num_heads : int (required)
Number of attention heads for k and v
local_window_size : int
left_window_size for local attention (like Mistral). Default value is -1 meaning unused.
num_heads : int (required)
Number of attention heads for q
+
qk_output : int
+
Output values of QK matrix multiplication before (1) or after (2) softmax normalization. Default value is 0 (don't output).
rotary_interleaved : int
Rotate using interleaved pattern. Default value is 0 (False).
scale : float
@@ -2549,9 +2634,11 @@ This version of the operator has been available since version 1 of the 'com.micr
Use a smooth factor in softmax.
softcap : float
Softcap value for attention weights. Default value is 0.
+
v_quant_type : string
+
Quantization type for V cache. One of 'NONE', 'PER_TENSOR', 'PER_CHANNEL'.
-#### Inputs (7 - 9) +#### Inputs (7 - 14)
query : T
@@ -2560,9 +2647,9 @@ This version of the operator has been available since version 1 of the 'com.micr
Key with shape (batch_size, kv_sequence_length, kv_hidden_size)
value (optional) : T
Value with shape (batch_size, kv_sequence_length, kv_hidden_size)
-
past_key (optional) : T
+
past_key (optional) : T_CACHE
past state key with support for format BNSH. When past_key uses same tensor as present_key(k-v cache), it is of length max_sequence_length... otherwise of length past_sequence_length.
-
past_value (optional) : T
+
past_value (optional) : T_CACHE
past state value with support for format BNSH. When past_value uses same tensor as present_value(k-v cache), it is of length max_sequence_length... otherwise of length past_sequence_length.
seqlens_k : M
1D Tensor of shape (batch_size). Equivalent to (total_sequence_lengths - 1).
@@ -2572,17 +2659,29 @@ This version of the operator has been available since version 1 of the 'com.micr
2D tensor with shape (max_sequence_length, head_size / 2).
sin_cache (optional) : T
2D tensor with shape (max_sequence_length, head_size / 2).
+
position_ids (optional) : tensor(int64)
+
2D tensor with shape (batch_size, sequence_length). When processing the first prompt the kernel uses only the first element
+
attention_bias (optional) : T
+
additional add to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length)
+
head_sink (optional) : T
+
1D tensor with shape (num_heads). Each head has a smooth factor adding to the denominator of softmax.
+
k_scale (optional) : T_KV_SCALE
+
Scale tensor for past_key.
+
v_scale (optional) : T_KV_SCALE
+
Scale tensor for past_value.
-#### Outputs +#### Outputs (3 - 4)
output : T
3D output tensor with shape (batch_size, sequence_length, hidden_size)
-
present_key : T
+
present_key : T_CACHE
present state key with support for format BNSH. When past_key uses same tensor as present_key(k-v buffer), it is of length max_sequence_length... otherwise of length past_sequence_length +kv_sequence_length.
-
present_value : T
+
present_value : T_CACHE
present state value with support for format BNSH. When past_value uses same tensor as present_value(k-v buffer), it is of length max_sequence_length... otherwise of length past_sequence_length +kv_sequence_length.
+
output_qk (optional) : T
+
Values of QK matrix multiplication, either before or after softmax normalization
#### Type Constraints @@ -2590,6 +2689,10 @@ This version of the operator has been available since version 1 of the 'com.micr
T : tensor(float16), tensor(bfloat16), tensor(float)
Constrain input and output to float tensors.
+
T_CACHE : tensor(float), tensor(float16), tensor(bfloat16), tensor(uint8), tensor(int8), tensor(float8e4m3fn)
+
Constrain KV cache types.
+
T_KV_SCALE : tensor(float)
+
Constrain KV cache scale types.
M : tensor(int32)
Constrain mask to int tensor.
@@ -2664,6 +2767,79 @@ This version of the operator has been available since version 1 of the 'com.micr
+### **com.microsoft.LinearAttention** + + Unified linear attention operator for autoregressive decoding (T=1) and prefill (T>1). + + All inputs use 3D packed format [B, T, H*D]; q_num_heads and kv_num_heads are always + required. The op internally unpacks to 4D for computation. + + The update_rule attribute selects the recurrence type: + - "linear": S_t = S_{t-1} + k_t ⊗ v_t; o_t = scale * q_t^T S_t + - "gated": S_t = exp(g_t) * S_{t-1} + k_t ⊗ v_t; o_t = scale * q_t^T S_t + - "delta": S_t = S_{t-1} + β_t * k_t ⊗ (v_t - S_{t-1}^T k_t); o_t = scale * q_t^T S_t + - "gated_delta": S_t = exp(g_t) * S_{t-1} + β_t * k_t ⊗ (v_t - exp(g_t) * S_{t-1}^T k_t); o_t = scale * q_t^T S_t + + where g_t is the decay (in log-space), β_t is the update rate, and ⊗ denotes outer product. + + Semantics: Equivalent to running the recurrent update sequentially for each token, + but may be implemented using chunk-parallel algorithms for GPU efficiency. + +#### Version + +This version of the operator has been available since version 1 of the 'com.microsoft' operator set. + +#### Attributes + +
+
chunk_size : int
+
Chunk size for the chunk-parallel WY decomposition during prefill (T>1). Tuning hint; does not affect output correctness.
+
kv_num_heads : int (required)
+
Number of key/value heads. Always required.
+
q_num_heads : int (required)
+
Number of query heads. Always required.
+
scale : float
+
Output scaling factor. When 0.0 (default), derives d_k = query.shape[-1] / q_num_heads and uses 1/sqrt(d_k). Set explicitly to override.
+
update_rule : string
+
The update rule for the linear attention recurrence. One of: 'linear', 'gated', 'delta', 'gated_delta'. Default is 'gated_delta'.
+
+ +#### Inputs (3 - 6) + +
+
query : T
+
Query vectors with 3D packed shape (B, T, H_q * d_k). Heads are packed into the last dimension.
+
key : T
+
Key vectors with 3D packed shape (B, T, H_kv * d_k). Should be L2-normalized for delta/gated_delta modes.
+
value : T
+
Value vectors with 3D packed shape (B, T, H_kv * d_v).
+
past_state (optional) : S
+
Recurrent state from previous step with shape (B, H_kv, d_k, d_v). Always 4D. If not provided, defaults to zeros.
+
decay (optional) : T
+
Exponential decay gate in log-space. 3D packed shape: (B, T, H_kv * d_k) for per-key-dimension decay (GLA/RWKV-6), or (B, T, H_kv) for per-head scalar decay (DeltaNet/RetNet). Required for 'gated' and 'gated_delta' modes.
+
beta (optional) : T
+
Update rate (sigmoid output). 3D packed shape: (B, T, H_kv) or (B, T, 1). Required for 'delta' and 'gated_delta' modes.
+
+ +#### Outputs + +
+
output : T
+
Attention output with 3D packed shape (B, T, H_q * d_v).
+
present_state : S
+
Updated recurrent state with shape (B, H_kv, d_k, d_v). Always 4D.
+
+ +#### Type Constraints + +
+
T : tensor(float), tensor(float16), tensor(bfloat16)
+
Constrain input and output types to float tensors.
+
S : tensor(float), tensor(float16), tensor(bfloat16)
+
Constrain state types to float tensors.
+
+ + ### **com.microsoft.LongformerAttention** Longformer Self Attention with a local context and a global context. Tokens attend locally: Each token @@ -2811,7 +2987,7 @@ This version of the operator has been available since version 1 of the 'com.micr Matrix product with right hand matrix being pre-packed and quantized int4 data blob. During quantization, the matrix is divided into blocks, where each block is a - continguous subset inside each column. Each block is quantized into a + contiguous subset inside each column. Each block is quantized into a sequence of 4b integers with a scaling factor and an optional offset. Currently 3 quantization types are supported: (0): block size 32, no offset, (1): block size 32, with offset, (2): block size 64, @@ -2941,29 +3117,20 @@ This version of the operator has been available since version 1 of the 'com.micr ### **com.microsoft.MatMulNBits** - MatMulNBits is a MatMul with weight quantized with N bits(e.g., 2, 3, 4, 5, 6, 7).It does Matrix Multiplication like MatMul (https://github.com/onnx/onnx/blob/main/docs/Operators.md#matmul) with differences: - 1. Input B is a 2D constant Matrix. Its input feature count and output feature count are specified by attribute 'K' and 'N'. - 2. Input B is quantized with x bits which is specified by attribute 'bits'. It is quantized blockwisely along dimension 0 (e.g. column) with block size specified by attribute block_size. - And block_size is not an arbitrary number and must be a power of 2 and not smaller than 16, like 16, 32, 64, 128,.. - 3. Input B's scale and zero point are specified by input scales and zero_points. - - Input B is stored as uint8_t with shape: [N][n_blocks_per_col][blob_size] in which: - - n_blocks_per_col = (K + block_size - 1) / block_size - - blob_size = CeilDiv(block_size * bits, bitsof(uint8_t)<8>) - For all bits from 2-8, a row of data is stored squeezely and represented by uint8_t. - - for 2,4,8 bits, 4x2bit,2x4bit,1x8bit are stored in one uint8_t. - 4bit example: - |.|.|.|.| .|.|.|.| =uint8_t (2x4bit) - - for 3,5,6,7 bits, 32x3bit,32x5bit,16x6bit,32x7bit are stored in 12xuint8_t,20xuint8_t,12xuint8_t,28xuint8_t separately. no bits are wasted. - 3bit example: - |.|.|. |.|.|. |.|.|. = 9bit, which across 2 uint8_t, the highest bit for the second uint8_t is used. - The last uint_8 may have some bits unused. - - - Input scales is stored in same type as original type of B(float32, float16) with shape like: [N * n_blocks_per_col] - Input zero_points is stored as uint8_t or same as type(A). It has the same packing method as input B. - - [N * CeilDiv(n_blocks_per_col * bits, 8)] - If zero_points has same type as A, it's not packed and has the same shape as Scales. + MatMulNBits performs a matrix multiplication where the right-hand-side matrix (weights) is quantized to N bits. + + It is a fusion of two operations: + 1. Linear dequantization of the quantized weights using scale and (optionally) zero-point with formula: + dequantized_weight = (quantized_weight - zero_point) * scale + 2. Matrix multiplication between the input matrix A and the dequantized weight matrix. + + The weight matrix is a 2D constant matrix with the input feature count and output feature count specified by attributes 'K' and 'N'. + It is quantized block-wise along the K dimension with a block size specified by the 'block_size' attribute. + The block size must be a power of 2 and not smaller than 16 (e.g., 16, 32, 64, 128). Each block has its own scale and zero-point. + The quantization is performed using a bit-width specified by the 'bits' attribute, which can take values from 2 to 8. + + The quantized weights are stored in a bit-packed format along the K dimension, with each block being represented by a blob of uint8. + For example, for 4 bits, the first 4 bits are stored in the lower 4 bits of a byte, and the second 4 bits are stored in the higher 4 bits of a byte. #### Version @@ -2973,30 +3140,30 @@ This version of the operator has been available since version 1 of the 'com.micr
K : int (required)
-
size of each input feature
+
Input feature dimension of the weight matrix.
N : int (required)
-
size of each output feature
+
Output feature dimension of the weight matrix.
accuracy_level : int
The minimum accuracy level of input A, can be: 0(unset), 1(fp32), 2(fp16), 3(bf16), or 4(int8) (default unset). It is used to control how input A is quantized or downcast internally while doing computation, for example: 0 means input A will not be quantized or downcast while doing computation. 4 means input A can be quantized with the same block_size to int8 internally from type T1.
-
bits : int (required)
-
number of bits used for weight quantization (default 4)
+
bits : int
+
Bit-width used to quantize the weights (valid range: 2~8)
block_size : int (required)
-
number of groupsize used for weight quantization,(default 128). It needs to be a power of 2 and not smaller than 16.
+
Size of each quantization block along the K (input feature) dimension. Must be a power of two and ≥ 16 (e.g., 16, 32, 64, 128).
#### Inputs (3 - 6)
A : T1
-
The input tensor, not quantized
+
The input tensor, not quantized.
B : T2
-
1 or 2 dimensional data blob
+
Packed uint8 tensor of shape (N, k_blocks, blob_size), where k_blocks = ceil(K / block_size) and blob_size = (block_size * bits / 8). The quantized weights are stored in a bit-packed format along the K dimension, packed within each block_size.
scales : T1
-
quantization scale
+
Per-block scaling factors for dequantization with shape (N, k_blocks) and same data type as input A.
zero_points (optional) : T3
-
quantization zero points
+
Per-block zero point for dequantization. It can be either packed or unpacked: Packed (uint8) format has shape (N, ceil(k_blocks * bits / 8)), and it uses same bit-packing method as Input B. Unpacked (same type as A) format has shape (N, k_blocks). If not provided, a default zero point is used: 2^(bits - 1) (e.g., 8 for 4-bit quantization, 128 for 8-bit).
g_idx (optional) : T4
-
group_idx
+
group_idx. This input is deprecated
bias (optional) : T1
Bias to add to result. It should have shape [N].
@@ -3011,12 +3178,12 @@ This version of the operator has been available since version 1 of the 'com.micr #### Type Constraints
-
T1 : tensor(float), tensor(float16)
-
Constrain input and output types to float/half_float tensors.
-
T2 : tensor(uint8), tensor(int32)
-
Constrain quantized weight types to uint8/int32.
-
T3 : tensor(uint8), tensor(int32), tensor(float16), tensor(float)
-
Constrain quantized zero point types to uint8/int32/float16/float.
+
T1 : tensor(float), tensor(float16), tensor(bfloat16)
+
Constrain input and output types to float tensors.
+
T2 : tensor(uint8)
+
Constrain quantized weight types to uint8.
+
T3 : tensor(uint8), tensor(float16), tensor(float), tensor(bfloat16)
+
Constrain quantized zero point types to uint8 or float tensors.
T4 : tensor(int32)
the index tensor.
@@ -3074,6 +3241,17 @@ This version of the operator has been available since version 1 of the 'com.micr Mixture of experts. Examples: Switch transformer(https://arxiv.org/pdf/2101.03961.pdf) use top 1, GLaM(https://arxiv.org/abs/2112.06905) activates top 2 FFN, Vision MOE(https://arxiv.org/pdf/2106.05974.pdf) usually uses top 32 experts and Mixtral(https://huggingface.co/blog/mixtral). + + The SwiGLU (Swish-Gated Linear Unit) activation function is like: + g = xW + b + l = xV + c + G = clamp(g, max=limit) + L = clamp(l, min=-limit, max=limit) + swiglu = G * sigmoid(alpha * G) * (L + beta) + where x is the input, W and V are weight matrices, b and c are bias vectors, and alpha, beta and limit are constant float parameters. + When swiglu_fusion=0, two GEMMs are not fused, and they are FC1 and FC3 in the inputs. + When swiglu_fusion=1, two GEMMs are fused so that g and l are computed in a single GEMM (FC1), and g and l are interleaved on each row of size 2 * inter_size. + When swiglu_fusion=2, two GEMMs are fused, and g and l are concatenated on each row. #### Version @@ -3083,12 +3261,20 @@ This version of the operator has been available since version 1 of the 'com.micr #### Attributes
+
activation_alpha : float
+
Alpha parameter used in activation function.
+
activation_beta : float
+
Beta parameter used in activation function.
activation_type : string
-
Activation function to use. Choose from relu, gelu, silu and identity. Default is relu
+
Activation function to use. Choose from relu, gelu, silu, swiglu and identity. Default is relu
k : int
Number of top experts to select from expert pool
normalize_routing_weights : int
Whether to normalize routing weights
+
swiglu_fusion : int
+
0: not fused, 1: fused and interleaved. 2: fused and not interleaved.
+
swiglu_limit : float
+
The limit used to clamp in SwiGLU. No clamp when limit is not provided.
use_sparse_mixer : int
Whether to use sparse mixer
@@ -3097,19 +3283,19 @@ This version of the operator has been available since version 1 of the 'com.micr
input : T
-
2D input tensor with shape (num_rows, hidden_size) or 3D input tensor with shape (batch_size, sequence_length, hidden_size)
+
2D input tensor with shape (num_tokens, hidden_size) or 3D input tensor with shape (batch_size, sequence_length, hidden_size)
router_probs : T
-
2D input tensor with shape (num_rows, num_experts)
+
2D input tensor with shape (num_tokens, num_experts)
fc1_experts_weights : T
-
3D input tensor with shape (num_experts, hidden_size, inter_size)
+
3D input tensor with shape (num_experts, fusion_size * inter_size, hidden_size), where fusion_size is 2 for fused swiglu, and 1 otherwise
fc1_experts_bias (optional) : T
-
2D optional input tensor with shape (num_experts, inter_size)
+
2D optional input tensor with shape (num_experts, fusion_size * inter_size)
fc2_experts_weights : T
-
3D input tensor with shape (num_experts, inter_size, hidden_size)
+
3D input tensor with shape (num_experts, hidden_size, inter_size)
fc2_experts_bias (optional) : T
2D optional input tensor with shape (num_experts, hidden_size)
fc3_experts_weights (optional) : T
-
3D optional input tensor with shape (num_experts, hidden_size, inter_size)
+
3D optional input tensor with shape (num_experts, inter_size, hidden_size)
fc3_experts_bias (optional) : T
2D optional input tensor with shape (num_experts, inter_size)
@@ -3118,14 +3304,14 @@ This version of the operator has been available since version 1 of the 'com.micr
output : T
-
2D input tensor with shape (num_rows, hidden_size) or 3D input tensor with shape (batch_size, sequence_length, hidden_size)
+
2D input tensor with shape (num_tokens, hidden_size) or 3D input tensor with shape (batch_size, sequence_length, hidden_size)
#### Type Constraints
-
T : tensor(float), tensor(float16)
-
Constrain input and output types to float or float16 tensors.
+
T : tensor(float), tensor(float16), tensor(bfloat16)
+
Constrain input and output types to float tensors.
@@ -3199,7 +3385,7 @@ This version of the operator has been available since version 1 of the 'com.micr
Whether every token can only attend to previous tokens. Default value is 0.
-#### Inputs (1 - 8) +#### Inputs (1 - 10)
query : T
@@ -3215,27 +3401,35 @@ This version of the operator has been available since version 1 of the 'com.micr
attention_bias (optional) : T
bias added to QxK' with shape (batch_size or 1, num_heads or 1, sequence_length, total_sequence_length)
past_key (optional) : T
-
past state for self attention key with shape (batch_size, num_heads, past_sequence_length, head_size)
+
past state for key with shape (batch_size, num_heads, past_sequence_length, head_size) or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used
past_value (optional) : T
-
past state for self attention value with shape (batch_size, num_heads, past_sequence_length, head_size)
+
past state for value with shape (batch_size, num_heads, past_sequence_length, head_size) or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used
+
past_sequence_length (optional) : M
+
The past_sequence_length buffer sharing is used with
+
cache_indirection (optional) : M
+
A buffer of shape [batch_size, beam_width, max_sequence_length] where an [i, j, k] entry specifieswhich beam the 'k' th token came from for the 'j' th beam for batch 'i' in the current iteration
-#### Outputs (1 - 3) +#### Outputs (1 - 4)
output : T
3D output tensor with shape (batch_size, sequence_length, v_hidden_size)
present_key (optional) : T
-
present state for cross attention key with shape (batch_size, num_heads, kv_sequence_length, head_size)or present state for self attention key with shape (batch_size, num_heads, total_sequence_length, head_size)
+
present state for key with shape (batch_size, num_heads, total_sequence_length, head_size) or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used
present_value (optional) : T
-
present state for cross attention value with shape (batch_size, num_heads, kv_sequence_length, head_size)or present state for self attention value with shape (batch_size, num_heads, total_sequence_length, head_size)
+
present state for value with shape (batch_size, num_heads, total_sequence_length, head_size) or (batch_size, num_heads, max_sequence_length, head_size) when buffer sharing is used
+
qk (optional) : QK
+
normalized Q * K, of shape (batch_size, num_heads, sequence_length, total_sequence_length).
#### Type Constraints
-
T : tensor(float), tensor(float16)
+
T : tensor(float), tensor(float16), tensor(bfloat16)
Constrain input and output to float tensors.
+
QK : tensor(float), tensor(float16), tensor(bfloat16)
+
Constrain QK output to float32 or float16 tensors, independent of input type or output type.
M : tensor(int32)
Constrain mask to integer types
@@ -3679,6 +3873,100 @@ This version of the operator has been available since version 1 of the 'com.micr +### **com.microsoft.PagedAttention** + + Paged Attention. + + This op leverages a block-based KV cache to enable continuous batching for LLMs. Currently, it is designed to work with + the CUDA Execution Provider only. + + In other attention ops, batch entries typically aren't of the same length, so they are padded. + Below is a batch with 3 sequences where * denotes a padding token. + Sequence_0: 0, 1*, 2*, 3* + Sequence_1: 4, 5, 6*, 7* + Sequence_2: 8, 9, 10, 11 + + PagedAttention is designed to take in packed input, i.e., only the real tokens without padding. + For example, the input shown above will be packed into 3 tensors like below: + - query ([q0, q4, q5, q8, q9, q10, q11]) + - key ([k0, k4, k5, k8, k9, k10, k11]) + - value ([v0, v4, v5, v8, v9, v10, v11]) + - cumulative_sequence_length: 0, 1, 1+2, 1+2+4 + This packing omits padding tokens. + + The query, key and value tensors contain result of hidden embedding of real tokens after input projections. + cumulative_sequence_length records cumulated length of each sequence length. + + +#### Version + +This version of the operator has been available since version 1 of the 'com.microsoft' operator set. + +#### Attributes + +
+
do_rotary : int
+
Whether to use rotary position embedding. Default value is 0.
+
kv_num_heads : int (required)
+
Number of attention heads for k and v
+
local_window_size : int
+
left_window_size for local attention (like Mistral). Default value is -1 meaning unused.
+
num_heads : int (required)
+
Number of attention heads for q
+
rotary_interleaved : int
+
Rotate using interleaved pattern. Default value is 0 (False).
+
scale : float
+
Custom scale will be used if specified. Default value is 1/sqrt(head_size)
+
softcap : float
+
Softcap value for attention weights. Default value is 0.
+
+ +#### Inputs (8 - 10) + +
+
query : T
+
Query with shape (num_tokens, hidden_size), or packed QKV with shape (num_tokens, d) where d is (num_heads * head_size + 2 * kv_num_heads * head_size).
+
key (optional) : T
+
Key with shape (num_tokens, kv_hidden_size)
+
value (optional) : T
+
Value with shape (num_tokens, kv_hidden_size)
+
key_cache : T
+
Block-based key cache with shape (num_blocks, block_size, kv_num_heads, head_size). This is updated in place within the op.
+
value_cache : T
+
Block-based value cache with shape (num_blocks, block_size, kv_num_heads, head_size). This is updated in place within the op. This should be the same shape as key_cache.
+
cumulative_sequence_length : S
+
A tensor with shape (batch_size + 1). It specifies the cumulative sequence lengths between the packed entries in Q/K/V.
+
past_seqlens : S
+
A tensor with shape (batch_size). It specifies the past lengths of cached sequence in the KV cache.
+
block_table : S
+
2D tensor with shape (batch_size, max_blocks_per_sequence) that maps each sequence in the batch to itscorresponding blocks in the KV cache.
+
cos_cache (optional) : T
+
2D tensor with shape (max total seqlen, head_size / 2).
+
sin_cache (optional) : T
+
2D tensor with shape (max total seqlen, head_size / 2).
+
+ +#### Outputs (1 - 3) + +
+
output : T
+
3D output tensor with shape (num_tokens, hidden_size)
+
key_cache_out (optional) : T
+
Block-based key cache with shape (num_blocks, block_size, kv_num_heads, head_size). This is always the same tensor as key_cache.
+
value_cache_out (optional) : T
+
Block-based value cache with shape (num_blocks, block_size, kv_num_heads, head_size). This is always the same tensor as value_cache.
+
+ +#### Type Constraints + +
+
T : tensor(float16), tensor(bfloat16)
+
Constrain input and output to float tensors.
+
S : tensor(int32)
+
Constrain Positional inputs to int tensor.
+
+ + ### **com.microsoft.QAttention** Quantization of Multi-Head Self Attention. @@ -4406,7 +4694,32 @@ This version of the operator has been available since version 1 of the 'com.micr ### **com.microsoft.QMoE** - Quantized MoE + Quantized mixture of experts (MoE). + + The quantized weights are stored in column major order per expert. + The quantization block size can be specified. If not provided, column wise quantization is used. + + The formula of linear dequantization of the quantized weights using scale and (optionally) zero-point is: + dequantized_weight = (quantized_weight - zero_point) * scale + When zero_point is not provided, the default value is 2^(bits-1): 2 for 2 bits, 8 for 4 bits, 128 for 8 bits. + + If block_size is provided, both hidden_size and inter_size must be divisible by the block size, and + the dequantization is performed per block of size block_size along the K (input feature) dimension. + + If block_size and zero_point are provided, both hidden_size and inter_size must be divisible by block_size * pack_size, + where pack_size = 8 / expert_weight_bits. + + The SwiGLU (Swish-Gated Linear Unit) activation function is like: + g = xW + b + l = xV + c + G = clamp(g, max=limit) + L = clamp(l, min=-limit, max=limit) + swiglu = G * sigmoid(alpha * G) * (L + beta) + where x is the input, W and V are weight matrices, b and c are bias vectors, and alpha, beta and limit are constant float parameters. + When swiglu_fusion=0, two GEMMs are not fused, and they are FC1 and FC3 in the inputs. + When swiglu_fusion=1, two GEMMs are fused so that g and l are computed in a single GEMM (FC1), and g and l are interleaved on each row of size 2 * inter_size. + When swiglu_fusion=2, two GEMMs are fused, and g and l are concatenated on each row. + #### Version @@ -4415,59 +4728,79 @@ This version of the operator has been available since version 1 of the 'com.micr #### Attributes
+
activation_alpha : float
+
Alpha parameter used in activation function.
+
activation_beta : float
+
Beta parameter used in activation function.
activation_type : string
-
Activation function to use. Choose from relu, gelu, silu and identity. Default is relu
+
Activation function to use. Choose from relu, gelu, silu, swiglu and identity. Default is relu
+
block_size : int
+
Size of each quantization block along the K (input feature) dimension. Must be power of two and ≥ 16 (e.g., 16, 32, 64, 128). If provided, both hidden_size and inter_size must be divisible by the block size. Otherwise, there is no blocking and a whole column shares one scaling factor.
expert_weight_bits : int
-
Number of bits used in quantized weights. Default is 4 bits
+
Number of bits used in quantized weights. Supported values are 2, 4, and 8. Default is 4 bits
k : int
Number of top experts to select from expert pool
normalize_routing_weights : int
Whether to normalize routing weights
+
swiglu_fusion : int
+
0: not fused, 1: fused and interleaved. 2: fused and not interleaved.
+
swiglu_limit : float
+
The limit used to clamp inputs in SwiGLU. It is infinite when limit is not provided.
use_sparse_mixer : int
Whether to use sparse mixer
-#### Inputs (7 - 11) +#### Inputs (7 - 15)
input : T
-
2D input tensor with shape (num_rows, hidden_size) or 3D input tensor with shape (batch_size, sequence_length, hidden_size)
+
2D tensor with shape (num_tokens, hidden_size), or 3D tensor with shape (batch_size, sequence_length, hidden_size)
router_probs : T
-
2D input tensor with shape (num_rows, num_experts)
+
2D tensor with shape (num_tokens, num_experts)
fc1_experts_weights : T1
-
3D input tensor with shape (num_experts, hidden_size, inter_size) or (num_experts, hidden_size, inter_size / 2)
-
fc1_scales : T
-
2D input tensor with shape (num_experts, inter_size)
+
3D tensor with shape (num_experts, fusion_size * inter_size, hidden_size / pack_size), The fusion_size is 2 for fused swiglu, or 1 otherwise. The pack_size is 8 / expert_weight_bits.
+
fc1_scales : T2
+
2D tensor with shape (num_experts, fusion_size * inter_size), or 3D tensor with shape (num_experts, fusion_size * inter_size, hidden_size / block_size) when block_size is provided.
fc1_experts_bias (optional) : T
-
2D optional input tensor with shape (num_experts, inter_size)
+
2D optional tensor with shape (num_experts, fusion_size * inter_size)
fc2_experts_weights : T1
-
3D input tensor with shape (num_experts, inter_size, hidden_size) or (num_experts, inter_size, hidden_size / 2)
-
fc2_scales : T
-
2D input tensor with shape (num_experts, hidden_size)
+
3D tensor with shape (num_experts, hidden_size, inter_size / pack_size)
+
fc2_scales : T2
+
2D tensor with shape (num_experts, hidden_size), or 3D tensor with shape (num_experts, hidden_size, inter_size / block_size) when block_size is provided.
fc2_experts_bias (optional) : T
-
2D optional input tensor with shape (num_experts, hidden_size)
+
2D optional tensor with shape (num_experts, hidden_size)
fc3_experts_weights (optional) : T1
-
3D optional input tensor with shape (num_experts, hidden_size, inter_size) or (num_experts, hidden_size, inter_size / 2)
-
fc3_scales (optional) : T
-
2D optional input tensor with shape (num_experts, inter_size)
+
3D optional tensor with shape (num_experts, inter_size, hidden_size / pack_size)
+
fc3_scales (optional) : T2
+
2D optional tensor with shape (num_experts, inter_size), or 3D optional tensor with shape (num_experts, inter_size, hidden_size / block_size) when block_size is provided.
fc3_experts_bias (optional) : T
-
2D optional input tensor with shape (num_experts, inter_size)
+
2D optional tensor with shape (num_experts, inter_size)
+
fc1_zero_points (optional) : T1
+
2D tensor with shape (num_experts, fusion_size * inter_size / pack_size), or 3D tensor with shape (num_experts, fusion_size * inter_size, hidden_size / block_size / pack_size) when block_size is provided.
+
fc2_zero_points (optional) : T1
+
2D tensor with shape (num_experts, hidden_size / pack_size), or 3D tensor with shape (num_experts, hidden_size, inter_size / block_size / pack_size) when block_size is provided.
+
fc3_zero_points (optional) : T1
+
2D optional tensor with shape (num_experts, inter_size / pack_size), or 3D optional tensor with shape (num_experts, inter_size, hidden_size / block_size / pack_size) when block_size is provided.
+
router_weights (optional) : T
+
2D optional tensor with shape (num_tokens, num_experts). When provided, router_probs is used only for Top-K expert selection, and router_weights is used for aggregating expert outputs (the values at the selected expert indices are gathered and used as mixing weights). This enables DeepSeek-style noaux_tc routing where different tensors are used for selection and aggregation. When not provided, router_probs is used for both selection and aggregation (backward compatible).
#### Outputs
output : T
-
2D input tensor with shape (num_rows, hidden_size) or 3D input tensor with shape (batch_size, sequence_length, hidden_size)
+
output tensor with same shape of input
#### Type Constraints
-
T : tensor(float16)
-
Constrain input and output types to float or float16 tensors.
+
T : tensor(float), tensor(float16), tensor(bfloat16)
+
Constrain input and output types to float tensors.
T1 : tensor(uint8)
Constrain weights type to uint8 tensors.
+
T2 : tensor(float), tensor(float16), tensor(bfloat16)
+
Constrain scales type to float tensors.
@@ -5253,7 +5586,7 @@ This version of the operator has been available since version 1 of the 'com.micr
interleaved : int
-
Rotate using interleaved pattern. Default value is 0 (False).
+
Indicates whether the input has real and imaginary parts interleaved. Default value is 0 (False), meaning the first half of the input consists of real values and the second half consists of imaginary values.
is_packed_batching : int
ragged batch inputs or not. Default value is 0
num_heads : int
@@ -5521,7 +5854,7 @@ This version of the operator has been available since version 1 of the 'com.micr #### Type Constraints
-
T : tensor(float), tensor(float16)
+
T : tensor(float), tensor(float16), tensor(bfloat16)
Constrain input and output types to float or half tensors.
U : tensor(float)
Constrain mean and inv_std_var to float tensors.
@@ -5572,8 +5905,8 @@ This version of the operator has been available since version 1 of the 'com.micr #### Type Constraints
-
T : tensor(float), tensor(float16)
-
Constrain input and output types to float or half tensors.
+
T : tensor(float), tensor(float16), tensor(bfloat16)
+
Constrain input and output to float tensors.
U : tensor(float)
Constrain mean and inv_std_var to float tensors.
@@ -5776,7 +6109,7 @@ This version of the operator has been available since version 1 of the 'com.micr Similarly, if input shape is [C] then the output should be [C, D]. Tokenizer has two different operation modes. The first mode is selected when "tokenexp" is not set and "separators" is set. If "tokenexp" is set and "separators" is not set, the second mode will be used. The first mode breaks each input string into tokens by matching and removing separators. - "separators" is a list of strings which are regular expressions. "tokenexp" is a single regular expression. + "separators" is a list of strings which are RE2 regular expressions. "tokenexp" is a single RE2 regular expression. Let's assume "separators" is [" "] and consider an example. If input is ["Hello World", "I love computer science !"] whose shape is [2], @@ -5785,8 +6118,9 @@ This version of the operator has been available since version 1 of the 'com.micr ["I", "love", "computer", "science", "!"]] whose shape is [2, 5] because you can find at most 5 tokens per input string. Note that the input at most can have two axes, so 3-D and higher dimension are not supported. - If "separators" contains a single empty string, the Tokenizer will enter into character tokenezation mode. This means all strings - will be broken part into individual characters. + If "separators" contains a single empty string, the Tokenizer will enter into character tokenization mode. This means all strings + will be broken apart into individual characters. + Similarly, if "tokenexp" is set to "." (match any single character), character tokenization mode is used. For each input string, the second mode searches matches of "tokenexp" and each match will be a token in Y. The matching of "tokenexp" is conducted greedily (i.e., a match should be as long as possible). This operator searches for the first match starting from the beginning of the considered string, @@ -5816,9 +6150,9 @@ This version of the operator has been available since version 1 of the 'com.micr
pad_value : string (required)
The string used to pad output tensors when the tokens extracted doesn't match the maximum number of tokens found. If start/end markers are needed, padding will appear outside the markers.
separators : list of strings
-
an optional list of strings attribute that contains a list of separators - regular expressions to match separators Two consecutive segments in X connected by a separator would be divided into two tokens. For example, if the input is "Hello World!" and this attribute contains only one space character, the corresponding output would be ["Hello", "World!"]. To achieve character-level tokenization, one should set the 'separators' to [""], which contains an empty string.
+
an optional list of strings attribute that contains a list of separators - RE2 regular expressions to match separators. Two consecutive segments in X connected by a separator would be divided into two tokens. For example, if the input is "Hello World!" and this attribute contains only one space character, the corresponding output would be ["Hello", "World!"]. To achieve character-level tokenization, one should set the 'separators' to [""], which contains an empty string.
tokenexp : string
-
An optional string. Token's regular expression in basic POSIX format (pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap09.html#tag_09_03). If set, tokenizer may produce tokens matching the specified pattern. Note that one and only of 'tokenexp' and 'separators' should be set.
+
An optional string. Token's regular expression in RE2 format (https://github.com/google/re2/wiki/Syntax). If set, tokenizer may produce tokens matching the specified pattern. Note that one and only one of 'tokenexp' and 'separators' should be set. If tokenexp is ".", the tokenizer enters character tokenization mode.
#### Inputs @@ -6063,7 +6397,7 @@ This version of the operator has been available since version 1 of the 'com.micr ### **com.microsoft.WhisperBeamSearch** - Beam Search for whisper model, especiall with cross_qk features etc. + Beam Search for whisper model, especially with cross_qk features etc. #### Version diff --git a/docs/How_To_Update_ONNX_Dev_Notes.md b/docs/How_To_Update_ONNX_Dev_Notes.md index 997812d7e7acf..67e7c2ab22a30 100644 --- a/docs/How_To_Update_ONNX_Dev_Notes.md +++ b/docs/How_To_Update_ONNX_Dev_Notes.md @@ -4,7 +4,12 @@ This note is only for ONNX Runtime developers. If you need to update the ONNX submodule to a different version, follow the steps below. -1. Update the ONNX submodule +## Update ONNX installation + +Currently, ONNXRUNTIME supports two ways to install ONNX cpp dependencies, one is through cmake/deps.txt, and the other one is by vcpkg. And both of them are guarded by CI. It is recommended to test vcpkg within Windows machines. + +### Update the ONNX submodule (commit would be more precise than branch) + ```sh cd cmake/external/onnx git remote update @@ -12,34 +17,95 @@ git reset --hard cd .. git add onnx ``` -(Change the to yours. If you are not sure, use 'origin/master'. Like 'git reset --hard origin/master') -1. Update [cgmanifests/generated/cgmanifest.json](/cgmanifests/generated/cgmanifest.json). -This file should be generated. See [cgmanifests/README](/cgmanifests/README.md) for instructions. +(Change the to yours. If you are not sure, use 'origin/main'. Like 'git reset --hard origin/main') + +### Update cmake/deps.txt + +1. Update [cmake/deps.txt](/cmake/deps.txt) with the correct zip download link and SHA (alternatively, build it with the wrong SHA and ORT should tell you the expected one.). +2. Check [cmake/patches/onnx/onnx.patch](/cmake/patches/onnx/onnx.patch) to see whether the diffs are resolved in the latest ONNX version. +3. Try to build ONNXRUNTIME from source. If the build fails, please make the changes accordingly, or use onnx.patch if it's ONNX bugs. An example build: + +```bash +./build.sh --config RelWithDebInfo --use_cuda --cuda_home /usr/local/cuda-12.6/ --cudnn_home /usr/local/cuda-12.6/ --build_wheel --parallel --skip_tests +``` + +### Update cmake/vcpkg-ports + +1. Modify [cmake/vcpkg-ports/onnx/binskim.patch](/cmake/vcpkg-ports/onnx/binskim.patch) to be the same as [cmake/patches/onnx/onnx.patch](/cmake/patches/onnx/onnx.patch). +2. The other patches are required/created by vcpkg repository to build ONNX. We just need to re-run diff to makes sure the patches can be applied in the updated ONNX version. + a. VCPKG relies these patches to build ONNX. +3. Update [cmake/vcpkg-ports/onnx/portfile.cmake](/cmake/vcpkg-ports/onnx/portfile.cmake) with the correct commit id and SHA512. (alternatively, build it with the wrong SHA and ORT should tell you the expected one.) +4. Upload your package: [Follow the instructions](https://microsoft.sharepoint.com/:o:/r/teams/ONNX2/_layouts/15/Doc.aspx?sourcedoc=%7B170774BE-E1C6-4F8B-A3AE-984F211FE410%7D&wd=target(Development.one%7C63D3AB47-51D1-4A62-9965-66882234BD44%2FUpdate%20a%20VCPKG%20package%7CB6AE6A97-94FC-4436-8FC6-08C21AE895DA%2F)&wdpartid=%7BB5CF19CC-40FE-0EC7-32B6-8119B427B32A%7D%7B1%7D&wdsectionfileid=%7B9DD25660-A195-48EA-B9E0-DF8B902AFDD7%7D&ovuser=72f988bf-86f1-41af-91ab-2d7cd011db47%2Ctitaiwang%40microsoft.com&clickparams=eyJBcHBOYW1lIjoiVGVhbXMtRGVza3RvcCIsIkFwcFZlcnNpb24iOiI0OS8yNTA5MTExNjAxNiIsIkhhc0ZlZGVyYXRlZFVzZXIiOmZhbHNlfQ%3D%3D&CID=fb9dcaa1-c0b5-1000-5597-c19e3adf468c&cidOR=SPO)one%7C63d3ab47-51d1-4a62-9965-66882234bd44%2FAdd%20or%20Update%20a%20C%2B%2B%20dependency%7Cb6ae6a97-94fc-4436-8fc6-08c21ae895da%2F%29&wdorigin=NavigationUrl + +Alternatively, directly run Terrapin to upload ONNX package (need SHA512): + +``` +C:\local\Terrapin\TerrapinRetrievalTool.exe -b https://vcpkg.storage.devpackages.microsoft.io/artifacts/ -a true -u Environment -p https://github.com/onnx/onnx/archive/866d145a8168e36f34741534df4c94d8e7588379.tar.gz -s 80e3a5db347bf3046a6fb8721f308c054c923aa5649ab704f0265e83bba6edac9f7e402dde2be3d9c01d3b291f5eb284eaba2df6986744161ece887e0c2fc845 -d "C:\Users\titaiwang\onnxruntime\build\Windows\vcpkg\downloads\onnx-onnx-866d145a8168e36f34741534df4c94d8e7588379.tar.gz.25136.part" +``` + +5. Try to build ONNXRUNTIME from source. If the build fails, please make the changes accordingly, or use binskim.patch if it's ONNX bugs. An example build: + +```bash +./build.sh --config RelWithDebInfo --use_cuda --cuda_home /usr/local/cuda-12.6/ --cudnn_home /usr/local/cuda-12.6/ --build_wheel --parallel --skip_tests --use_vcpkg +``` + +## Update ONNX related documentations + +We need to update the auto-generated ONNX kernels markdowns and requirements.txt. + +### AUTO-generated ONNX kernels + +We can either use the following command lines to generate them, or go to CI (AzureDevOps published Artifacts) to download and upload the generated markdowns from CI to update them (suggested). + +If you want to do the command lines: + +1. Update [docs/OperatorKernels.md](/docs/OperatorKernels.md) + +```bash +# under onnxruntime root +python tools/python/gen_opkernel_doc.py --output_path docs/OperatorKernels.md +``` + +1. Update [js/web/docs/webgl-operators.md](/js/web/docs/webgl-operators.md) with the script: [generate-webgl-operator-md.ts](/js/web/script/generate-webgl-operator-md.ts) + +```bash +# Install dependencies at the parent JS level +cd /path/to/onnxruntime/js +npm install +# Install dependencies at the web level +cd /path/to/onnxruntime/js/web +npm install +# Build the doc +npm run build:doc +``` + +### Update requirements.txt + +Update Python requirements files with the updated ONNX version (e.g., `onnx==1.16.0`) or commit hash if building from source (e.g., `git+http://github.com/onnx/onnx.git@targetonnxcommithash#egg=onnx`). -1. Update Python requirements files with the updated ONNX version (e.g., `onnx==1.16.0`) or commit hash if building from source (e.g., `git+http://github.com/onnx/onnx.git@targetonnxcommithash#egg=onnx`). - [onnxruntime/test/python/requirements.txt](/onnxruntime/test/python/requirements.txt) - [tools/ci_build/github/linux/docker/scripts/requirements.txt](/tools/ci_build/github/linux/docker/scripts/requirements.txt) - [tools/ci_build/github/linux/docker/scripts/manylinux/requirements.txt](/tools/ci_build/github/linux/docker/scripts/manylinux/requirements.txt) - [tools/ci_build/github/linux/python/requirements.txt](/tools/ci_build/github/linux/python/requirements.txt) - Run `git grep -rn "onnx==1" .` to find other locations and update this document if necessary. +## Additional Notes + 1. If there is any change to `cmake/external/onnx/onnx/*.in.proto`, you need to regenerate OnnxMl.cs. [Building onnxruntime with Nuget](https://onnxruntime.ai/docs/build/inferencing.html#build-nuget-packages) will do this. - -1. If you are updating ONNX from a released tag to a new commit, please ask Changming (@snnn) to deploy the new test +2. If you are updating ONNX from a released tag to a new commit, please ask Changming (@snnn) to deploy the new test data along with other test models to our CI build machines. This is to ensure that our tests cover every ONNX opset. - -1. Send your PR, and **manually** queue a build for every packaging pipeline for your branch. - -1. If there is a build failure in stage "Check out of dated documents" in WebAssembly CI pipeline, update ONNX Runtime +3. Send your PR, and **manually** queue a build for every packaging pipeline for your branch. +4. If there is a build failure in stage "Check out of dated documents" in WebAssembly CI pipeline, update ONNX Runtime Web WebGL operator support document: + - Make sure Node.js is installed (see [Prerequisites](../js/README.md#Prerequisites) for instructions). - Follow [js/Build](../js/README.md#Build-2) to install dependencies. - Follow instructions in [Generate document](../js/README.md#Generating-Document) to update document. Commit changes applied to file `docs/operators.md`. +5. Usually some newly introduced tests will fail. Then you may need to update -2. Usually some newly introduced tests will fail. Then you may need to update - [onnxruntime/test/onnx/main.cc](/onnxruntime/test/onnx/main.cc) - [onnxruntime/test/providers/cpu/model_tests.cc](/onnxruntime/test/providers/cpu/model_tests.cc) - [csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs](/csharp/test/Microsoft.ML.OnnxRuntime.Tests.NetCoreApp/InferenceTest.netcore.cs) @@ -47,5 +113,6 @@ This file should be generated. See [cgmanifests/README](/cgmanifests/README.md) - [onnxruntime/test/testdata/onnx_backend_test_series_overrides.jsonc](/onnxruntime/test/testdata/onnx_backend_test_series_overrides.jsonc) 1. If an operator has changed we may need to update optimizers involving that operator. + - Run [find_optimizer_opset_version_updates_required.py](/tools/python/find_optimizer_opset_version_updates_required.py), compare with the output from the current main branch, and check for any new warnings. - If there are new warnings contact the optimizer owner (which can usually be determined by looking at who edited the file most recently) or failing that ask the 'ONNX Runtime Shared Core' mailing list. diff --git a/docs/OperatorKernels.md b/docs/OperatorKernels.md index f565c607c4b37..5cf92c6c53e4b 100644 --- a/docs/OperatorKernels.md +++ b/docs/OperatorKernels.md @@ -2,6 +2,14 @@ *This file is automatically generated from the registered kernels by [this script](https://github.com/microsoft/onnxruntime/blob/main/tools/python/gen_opkernel_doc.py). Do not modify directly.* +### Version Notation + +The **OpSet Version** column uses the following notation: + +- `N` — registered only for opset N (e.g., `13`). +- `[N, M]` — registered for opsets N through M inclusive (e.g., `[6, 12]`). +- `N+` — registered for opset N and all later opsets until superseded by a newer kernel registration (e.g., `16+`). + ## Execution Providers - [CPUExecutionProvider](#cpuexecutionprovider) @@ -43,6 +51,8 @@ Do not modify directly.* |||[7, 21]|**T** = tensor(float)| |Atanh|*in* input:**T**
*out* output:**T**|22+|**T** = tensor(float)| |||[9, 21]|**T** = tensor(float)| +|Attention|*in* Q:**T1**
*in* K:**T1**
*in* V:**T2**
*in* attn_mask:**U**
*in* past_key:**T1**
*in* past_value:**T2**
*in* nonpad_kv_seqlen:**tensor(int64)**
*out* Y:**T1**
*out* present_key:**T1**
*out* present_value:**T2**
*out* qk_matmul_output:**T1**

or

*in* Q:**T1**
*in* K:**T1**
*in* V:**T2**
*in* attn_mask:**U**
*in* past_key:**T1**
*in* past_value:**T2**
*out* Y:**T1**
*out* present_key:**T1**
*out* present_value:**T2**
*out* qk_matmul_output:**T1**|24+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float), tensor(float16)
**U** = tensor(bool), tensor(float), tensor(float16)| +|||23|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float), tensor(float16)
**U** = tensor(bool), tensor(float), tensor(float16)| |AveragePool|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(float)| |||[19, 21]|**T** = tensor(float)| |||[11, 18]|**T** = tensor(float)| @@ -52,16 +62,20 @@ Do not modify directly.* |||14|**T** = tensor(double), tensor(float)
**U** = tensor(double), tensor(float)| |||[9, 13]|**T** = tensor(double), tensor(float)| |||[7, 8]|**T** = tensor(double), tensor(float)| +|BitCast|*in* input:**T1**
*out* output:**T2**|26+|**T1** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |BitShift|*in* X:**T**
*in* Y:**T**
*out* Z:**T**|11+|**T** = tensor(uint32), tensor(uint64), tensor(uint8)| |BitwiseAnd|*in* A:**T**
*in* B:**T**
*out* C:**T**|18+|**T** = tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |BitwiseNot|*in* X:**T**
*out* Y:**T**|18+|**T** = tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |BitwiseOr|*in* A:**T**
*in* B:**T**
*out* C:**T**|18+|**T** = tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |BitwiseXor|*in* A:**T**
*in* B:**T**
*out* C:**T**|18+|**T** = tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |BlackmanWindow|*in* size:**T1**
*out* output:**T2**|17+|**T1** = tensor(int32), tensor(int64)
**T2** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|Cast|*in* input:**T1**
*out* output:**T2**|21+|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|||[19, 20]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|||[13, 18]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|||[6, 12]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Cast|*in* input:**T1**
*out* output:**T2**|25+|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(float8e8m0), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(float8e8m0), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| +|||24|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(float8e8m0), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(float8e8m0), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| +|||23|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| +|||[21, 22]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| +|||[19, 20]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| +|||[13, 18]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| +|||[6, 12]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| |Ceil|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(double), tensor(float)| |||[6, 12]|**T** = tensor(double), tensor(float)| |Celu|*in* X:**T**
*out* Y:**T**|12+|**T** = tensor(float)| @@ -76,13 +90,16 @@ Do not modify directly.* |||[11, 12]|**T** = 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)| |||[4, 10]|**T** = 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)| |ConcatFromSequence|*in* input_sequence:**S**
*out* concat_result:**T**|11+|**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))| -|ConstantOfShape|*in* input:**T1**
*out* output:**T2**|21+|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|ConstantOfShape|*in* input:**T1**
*out* output:**T2**|25+|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||24|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||23|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||20|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[9, 19]|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Conv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|22+|**T** = tensor(float)| |||[11, 21]|**T** = tensor(float)| |||[1, 10]|**T** = tensor(float)| -|ConvInteger|*in* x:**T1**
*in* w:**T2**
*in* x_zero_point:**T1**
*in* w_zero_point:**T2**
*out* y:**T3**|10+|**T1** = tensor(uint8)
**T2** = tensor(uint8)
**T3** = tensor(int32)| +|ConvInteger|*in* x:**T1**
*in* w:**T2**
*in* x_zero_point:**T1**
*in* w_zero_point:**T2**
*out* y:**T3**|10+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(int32)| |ConvTranspose|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|22+|**T** = tensor(float)| |||[11, 21]|**T** = tensor(float)| |||[1, 10]|**T** = tensor(float)| @@ -91,14 +108,20 @@ Do not modify directly.* |Cosh|*in* input:**T**
*out* output:**T**|22+|**T** = tensor(float)| |||[9, 21]|**T** = tensor(float)| |Crop|*in* input:**T**
*out* output:**T**|1+|**T** = tensor(float)| +|CumProd|*in* x:**T**
*in* axis:**T2**
*out* y:**T**|26+|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)
**T2** = tensor(int32), tensor(int64)| |CumSum|*in* x:**T**
*in* axis:**T2**
*out* y:**T**|14+|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)
**T2** = tensor(int32), tensor(int64)| |||[11, 13]|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)
**T2** = tensor(int32), tensor(int64)| |DFT|*in* input:**T1**
*in* dft_length:**T2**
*in* axis:**tensor(int64)**
*out* output:**T1**

or

*in* input:**T1**
*in* dft_length:**T2**
*out* output:**T1**|20+|**T1** = tensor(double), tensor(float)
**T2** = tensor(int32), tensor(int64)| |||[17, 19]|**T1** = tensor(double), tensor(float)
**T2** = tensor(int32), tensor(int64)| +|DeformConv|*in* X:**T**
*in* W:**T**
*in* offset:**T**
*in* B:**T**
*in* mask:**T**
*out* Y:**T**|22+|**T** = tensor(double), tensor(float)| +|||[19, 21]|**T** = tensor(double), tensor(float)| |DepthToSpace|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float), tensor(uint8)| |||[11, 12]|**T** = tensor(double), tensor(float), tensor(uint8)| |||[1, 10]|**T** = tensor(double), tensor(float)| -|DequantizeLinear|*in* x:**T**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T**
*out* y:**tensor(float)**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|21+|**T1** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int4), tensor(int8), tensor(uint16), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)| +|DequantizeLinear|*in* x:**T**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T**
*out* y:**tensor(float)**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T3**|25+|**T1** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int8), tensor(uint16), tensor(uint2), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)| +|||24|**T1** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int4), tensor(int8), tensor(uint16), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)| +|||23|**T1** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int4), tensor(int8), tensor(uint16), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)| +|||[21, 22]|**T1** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int4), tensor(int8), tensor(uint16), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)| |||[19, 20]|**T1** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int32), tensor(int8), tensor(uint8)
**T2** = tensor(float), tensor(float16)| |||[13, 18]|**T** = tensor(int32), tensor(int8), tensor(uint8)| |||[10, 12]|**T** = tensor(int32), tensor(int8), tensor(uint8)| @@ -117,9 +140,9 @@ Do not modify directly.* |Einsum|*in* Inputs:**T**
*out* Output:**T**|12+|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)| |Elu|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(float)| |||[6, 21]|**T** = tensor(float)| -|Equal|*in* A:**T**
*in* B:**T**
*out* C:**T1**|19+|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(string)
**T1** = tensor(bool)| -|||[13, 18]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64)
**T1** = tensor(bool)| -|||[11, 12]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64)
**T1** = tensor(bool)| +|Equal|*in* A:**T**
*in* B:**T**
*out* C:**T1**|19+|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(bool)| +|||[13, 18]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(bool)| +|||[11, 12]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(bool)| |||[7, 10]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64)
**T1** = tensor(bool)| |Erf|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(float)| |||[9, 12]|**T** = tensor(float)| @@ -129,7 +152,10 @@ Do not modify directly.* |||[8, 12]|**T** = 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)| |EyeLike|*in* input:**T1**
*out* output:**T2**|22+|**T1** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(uint64)
**T2** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(uint64)| |||[9, 21]|**T1** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(uint64)
**T2** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(uint64)| -|Flatten|*in* input:**T**
*out* output:**T**|21+|**T** = 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)| +|Flatten|*in* input:**T**
*out* output:**T**|25+|**T** = 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)| +|||24|**T** = 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)| +|||23|**T** = 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)| +|||[21, 22]|**T** = 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)| |||[13, 20]|**T** = 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)| |||[11, 12]|**T** = 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)| |||[9, 10]|**T** = 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)| @@ -157,11 +183,11 @@ Do not modify directly.* |GlobalLpPool|*in* X:**T**
*out* Y:**T**|2+|**T** = tensor(float)| |GlobalMaxPool|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(float)| |||[1, 21]|**T** = tensor(float)| -|Greater|*in* A:**T**
*in* B:**T**
*out* C:**T1**|13+|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)
**T1** = tensor(bool)| -|||[9, 12]|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)
**T1** = tensor(bool)| +|Greater|*in* A:**T**
*in* B:**T**
*out* C:**T1**|13+|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(bool)| +|||[9, 12]|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(bool)| |||[7, 8]|**T** = tensor(double), tensor(float)
**T1** = tensor(bool)| -|GreaterOrEqual|*in* A:**T**
*in* B:**T**
*out* C:**T1**|16+|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)
**T1** = tensor(bool)| -|||[12, 15]|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)
**T1** = tensor(bool)| +|GreaterOrEqual|*in* A:**T**
*in* B:**T**
*out* C:**T1**|16+|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(bool)| +|||[12, 15]|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(bool)| |GridSample|*in* X:**T1**
*in* grid:**T2**
*out* Y:**T1**|22+|**T1** = tensor(double), tensor(float)
**T2** = tensor(double), tensor(float)| |||[20, 21]|**T1** = tensor(double), tensor(float)
**T2** = tensor(double), tensor(float)| |||[16, 19]|**T1** = tensor(float)
**T2** = tensor(float)| @@ -172,13 +198,19 @@ Do not modify directly.* |Hardmax|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(float)| |||[11, 12]|**T** = tensor(float)| |||[1, 10]|**T** = tensor(float)| -|Identity|*in* input:**T**
*out* output:**T**

or

*in* input:**V**
*out* output:**V**|21+|**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Identity|*in* input:**T**
*out* output:**T**

or

*in* input:**V**
*out* output:**V**|25+|**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||24|**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||23|**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[19, 20]|**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[16, 18]|**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), 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)| |||[14, 15]|**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), 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)| |||13|**T** = 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)| |||[1, 12]|**T** = 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)| -|If|*in* cond:**B**
*out* outputs:**V**|21+|**B** = tensor(bool)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|If|*in* cond:**B**
*out* outputs:**V**|25+|**B** = tensor(bool)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||24|**B** = tensor(bool)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||23|**B** = tensor(bool)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**B** = tensor(bool)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[19, 20]|**B** = tensor(bool)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[16, 18]|**B** = tensor(bool)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), 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)| |||[13, 15]|**B** = tensor(bool)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), 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)| @@ -201,23 +233,27 @@ Do not modify directly.* |||[1, 16]|**T** = tensor(double), tensor(float), tensor(float16)
**U** = tensor(double), tensor(float), tensor(float16)
**V** = tensor(double), tensor(float), tensor(float16)| |LeakyRelu|*in* X:**T**
*out* Y:**T**|16+|**T** = tensor(float)| |||[6, 15]|**T** = tensor(float)| -|Less|*in* A:**T**
*in* B:**T**
*out* C:**T1**|13+|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)
**T1** = tensor(bool)| -|||[9, 12]|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)
**T1** = tensor(bool)| +|Less|*in* A:**T**
*in* B:**T**
*out* C:**T1**|13+|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(bool)| +|||[9, 12]|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(bool)| |||[7, 8]|**T** = tensor(double), tensor(float)
**T1** = tensor(bool)| -|LessOrEqual|*in* A:**T**
*in* B:**T**
*out* C:**T1**|16+|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)
**T1** = tensor(bool)| -|||[12, 15]|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)
**T1** = tensor(bool)| +|LessOrEqual|*in* A:**T**
*in* B:**T**
*out* C:**T1**|16+|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(bool)| +|||[12, 15]|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(bool)| |Log|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float)| |||[6, 12]|**T** = tensor(double), tensor(float)| |LogSoftmax|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float)| |||[11, 12]|**T** = tensor(double), tensor(float)| |||[1, 10]|**T** = tensor(double), tensor(float)| -|Loop|*in* M:**I**
*in* cond:**B**
*in* v_initial:**V**
*out* v_final_and_scan_outputs:**V**|21+|**B** = tensor(bool)
**I** = tensor(int64)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Loop|*in* M:**I**
*in* cond:**B**
*in* v_initial:**V**
*out* v_final_and_scan_outputs:**V**|25+|**B** = tensor(bool)
**I** = tensor(int64)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||24|**B** = tensor(bool)
**I** = tensor(int64)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||23|**B** = tensor(bool)
**I** = tensor(int64)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[19, 20]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[16, 18]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = optional(seq(tensor(bfloat16))), optional(seq(tensor(bool))), optional(seq(tensor(double))), optional(seq(tensor(float))), optional(seq(tensor(float16))), optional(seq(tensor(int16))), optional(seq(tensor(int32))), optional(seq(tensor(int64))), optional(seq(tensor(int8))), optional(seq(tensor(string))), optional(seq(tensor(uint16))), optional(seq(tensor(uint32))), optional(seq(tensor(uint64))), optional(seq(tensor(uint8))), optional(tensor(bfloat16)), optional(tensor(bool)), optional(tensor(double)), optional(tensor(float)), optional(tensor(float16)), optional(tensor(int16)), optional(tensor(int32)), optional(tensor(int64)), optional(tensor(int8)), optional(tensor(string)), optional(tensor(uint16)), optional(tensor(uint32)), optional(tensor(uint64)), optional(tensor(uint8)), seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), 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)| |||[13, 15]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), 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)| |||[11, 12]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = 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)| |||[1, 10]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = 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)| -|LpNormalization|*in* input:**T**
*out* output:**T**|1+|**T** = tensor(double), tensor(float)| +|LpNormalization|*in* input:**T**
*out* output:**T**|22+|**T** = tensor(double), tensor(float)| +|||[1, 21]|**T** = tensor(double), tensor(float)| |LpPool|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(float)| |||[18, 21]|**T** = tensor(float)| |||[11, 17]|**T** = tensor(float)| @@ -226,8 +262,8 @@ Do not modify directly.* |||[9, 12]|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| |||[1, 8]|**T** = tensor(double), tensor(float)| |MatMulInteger|*in* A:**T1**
*in* B:**T2**
*in* a_zero_point:**T1**
*in* b_zero_point:**T2**
*out* Y:**T3**|10+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(int32)| -|Max|*in* data_0:**T**
*out* max:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| -|||12|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| +|Max|*in* data_0:**T**
*out* max:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| +|||12|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| |||[8, 11]|**T** = tensor(double), tensor(float)| |||[6, 7]|**T** = tensor(float)| |MaxPool|*in* X:**T**
*out* Y:**T**

or

*in* X:**T**
*out* Y:**T**
*out* Indices:**I**|22+|**I** = tensor(int64)
**T** = tensor(double), tensor(float), tensor(int8), tensor(uint8)| @@ -245,8 +281,10 @@ Do not modify directly.* |||[9, 12]|**T** = tensor(float)| |||[1, 8]|**T** = tensor(float)| |MelWeightMatrix|*in* num_mel_bins:**T1**
*in* dft_length:**T1**
*in* sample_rate:**T1**
*in* lower_edge_hertz:**T2**
*in* upper_edge_hertz:**T2**
*out* output:**T3**|17+|**T1** = tensor(int32), tensor(int64)
**T2** = tensor(float)
**T3** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|Min|*in* data_0:**T**
*out* min:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| -|||12|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| +|MemcpyFromHost|*in* X:**T**
*out* Y:**T**|1+|**T** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|MemcpyToHost|*in* X:**T**
*out* Y:**T**|1+|**T** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Min|*in* data_0:**T**
*out* min:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| +|||12|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| |||[8, 11]|**T** = tensor(double), tensor(float)| |||[6, 7]|**T** = tensor(float)| |Mod|*in* A:**T**
*in* B:**T**
*out* C:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| @@ -271,7 +309,10 @@ Do not modify directly.* |PRelu|*in* X:**T**
*in* slope:**T**
*out* Y:**T**|16+|**T** = tensor(float)| |||[9, 15]|**T** = tensor(float)| |||[7, 8]|**T** = tensor(float)| -|Pad|*in* data:**T**
*in* pads:**tensor(int64)**
*in* constant_value:**T**
*in* axes:**Tind**
*out* output:**T**

or

*in* data:**T**
*in* pads:**tensor(int64)**
*in* constant_value:**T**
*out* output:**T**

or

*in* data:**T**
*out* output:**T**|21+|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| +|Pad|*in* data:**T**
*in* pads:**tensor(int64)**
*in* constant_value:**T**
*in* axes:**Tind**
*out* output:**T**

or

*in* data:**T**
*in* pads:**tensor(int64)**
*in* constant_value:**T**
*out* output:**T**

or

*in* data:**T**
*out* output:**T**|25+|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| +|||24|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| +|||23|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| |||[19, 20]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| |||18|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| |||[13, 17]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(int8), tensor(uint32), tensor(uint64), tensor(uint8)| @@ -285,10 +326,14 @@ Do not modify directly.* |QLinearConv|*in* x:**T1**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T1**
*in* w:**T2**
*in* w_scale:**tensor(float)**
*in* w_zero_point:**T2**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T3**
*in* B:**T4**
*out* y:**T3**|10+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(int8), tensor(uint8)
**T4** = tensor(int32)| |QLinearMatMul|*in* a:**T1**
*in* a_scale:**TS**
*in* a_zero_point:**T1**
*in* b:**T2**
*in* b_scale:**TS**
*in* b_zero_point:**T2**
*in* y_scale:**TS**
*in* y_zero_point:**T3**
*out* y:**T3**

or

*in* a:**T1**
*in* a_scale:**tensor(float)**
*in* a_zero_point:**T1**
*in* b:**T2**
*in* b_scale:**tensor(float)**
*in* b_zero_point:**T2**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T3**
*out* y:**T3**|21+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(int8), tensor(uint8)
**TS** = tensor(float)| |||[10, 20]|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(int8), tensor(uint8)| -|QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**

or

*in* x:**T1**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T2**
*out* y:**T2**|21+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int4), tensor(int8), tensor(uint16), tensor(uint4), tensor(uint8)| +|QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**

or

*in* x:**T1**
*in* y_scale:**T2**
*in* y_zero_point:**T3**
*out* y:**T3**

or

*in* x:**T1**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T2**
*out* y:**T2**|25+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float), tensor(float16)
**T3** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int4), tensor(int8), tensor(uint16), tensor(uint2), tensor(uint4), tensor(uint8)| +|||24|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float), tensor(float16)
**T3** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int4), tensor(int8), tensor(uint16), tensor(uint4), tensor(uint8)| +|||23|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float), tensor(float16)
**T3** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int4), tensor(int8), tensor(uint16), tensor(uint4), tensor(uint8)| +|||[21, 22]|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int4), tensor(int8), tensor(uint16), tensor(uint4), tensor(uint8)| |||[19, 20]|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int8), tensor(uint8)| |||[13, 18]|**T1** = tensor(float)
**T2** = tensor(int8), tensor(uint8)| |||[10, 12]|**T1** = tensor(float)
**T2** = tensor(int8), tensor(uint8)| +|RMSNormalization|*in* X:**T**
*in* scale:**V**
*out* Y:**V**|23+|**T** = tensor(double), tensor(float), tensor(float16)
**V** = tensor(double), tensor(float), tensor(float16)| |RNN|*in* X:**T**
*in* W:**T**
*in* R:**T**
*in* B:**T**
*in* sequence_lens:**T1**
*in* initial_h:**T**
*out* Y:**T**
*out* Y_h:**T**|22+|**T** = tensor(float)
**T1** = tensor(int32)| |||[14, 21]|**T** = tensor(float)
**T1** = tensor(int32)| |||[7, 13]|**T** = tensor(float)
**T1** = tensor(int32)| @@ -346,7 +391,10 @@ Do not modify directly.* |Relu|*in* X:**T**
*out* Y:**T**|14+|**T** = tensor(double), tensor(float), tensor(int32), tensor(int8)| |||13|**T** = tensor(double), tensor(float)| |||[6, 12]|**T** = tensor(double), tensor(float)| -|Reshape|*in* data:**T**
*in* shape:**tensor(int64)**
*out* reshaped:**T**

or

*in* data:**T**
*out* reshaped:**T**|21+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| +|Reshape|*in* data:**T**
*in* shape:**tensor(int64)**
*out* reshaped:**T**

or

*in* data:**T**
*out* reshaped:**T**|25+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| +|||24|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| +|||23|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| +|||[21, 22]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| |||[19, 20]|**T** = 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)
**shape** = tensor(int64)| |||[14, 18]|**T** = 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)
**shape** = tensor(int64)| |||13|**T** = 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)
**shape** = tensor(int64)| @@ -360,12 +408,16 @@ Do not modify directly.* |ReverseSequence|*in* input:**T**
*in* sequence_lens:**tensor(int64)**
*out* Y:**T**|10+|**T** = 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)| |RoiAlign|*in* X:**T1**
*in* rois:**T1**
*in* batch_indices:**T2**
*out* Y:**T1**|16+|**T1** = tensor(double), tensor(float)
**T2** = tensor(int64)| |||[10, 15]|**T1** = tensor(double), tensor(float)
**T2** = tensor(int64)| +|RotaryEmbedding|*in* X:**T**
*in* cos_cache:**T**
*in* sin_cache:**T**
*in* position_ids:**M**
*out* Y:**T**|23+|**M** = tensor(int64)
**T** = tensor(float), tensor(float16)| |Round|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(double), tensor(float), tensor(float16)| |||[11, 21]|**T** = tensor(double), tensor(float), tensor(float16)| |STFT|*in* signal:**T1**
*in* frame_step:**T2**
*in* window:**T1**
*in* frame_length:**T2**
*out* output:**T1**|17+|**T1** = tensor(double), tensor(float)
**T2** = tensor(int32), tensor(int64)| |Scale|*in* input:**T**
*out* output:**T**|1+|**T** = tensor(float)| |ScaledTanh|*in* input:**T**
*out* output:**T**|1+|**T** = tensor(float)| -|Scan|*in* initial_state_and_scan_inputs:**V**
*out* final_state_and_scan_outputs:**V**

or

*in* sequence_lens:**I**
*in* initial_state_and_scan_inputs:**V**
*out* final_state_and_scan_outputs:**V**|21+|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Scan|*in* initial_state_and_scan_inputs:**V**
*out* final_state_and_scan_outputs:**V**

or

*in* sequence_lens:**I**
*in* initial_state_and_scan_inputs:**V**
*out* final_state_and_scan_outputs:**V**|25+|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||24|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||23|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[19, 20]|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[16, 18]|**V** = 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)| |||[11, 15]|**V** = 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)| @@ -388,7 +440,10 @@ Do not modify directly.* |SequenceErase|*in* input_sequence:**S**
*in* position:**I**
*out* output_sequence:**S**|11+|**I** = tensor(int32), tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))| |SequenceInsert|*in* input_sequence:**S**
*in* tensor:**T**
*in* position:**I**
*out* output_sequence:**S**|11+|**I** = tensor(int32), tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))| |SequenceLength|*in* input_sequence:**S**
*out* length:**I**|11+|**I** = tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))| -|Shape|*in* data:**T**
*out* shape:**T1**|21+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|Shape|*in* data:**T**
*out* shape:**T1**|25+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||24|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||23|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||[21, 22]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| |||[19, 20]|**T** = 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)
**T1** = tensor(int64)| |||[15, 18]|**T** = 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)
**T1** = tensor(int64)| |||[13, 14]|**T** = 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)
**T1** = tensor(int64)| @@ -403,7 +458,10 @@ Do not modify directly.* |||[7, 21]|**T** = tensor(double), tensor(float)| |Sinh|*in* input:**T**
*out* output:**T**|22+|**T** = tensor(float)| |||[9, 21]|**T** = tensor(float)| -|Size|*in* data:**T**
*out* size:**T1**|21+|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|Size|*in* data:**T**
*out* size:**T1**|25+|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||24|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||23|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||[21, 22]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| |||[19, 20]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| |||[13, 18]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| |||[1, 12]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| @@ -424,10 +482,14 @@ Do not modify directly.* |||[13, 17]|**T** = 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)| |||[11, 12]|**T** = 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)| |||[2, 10]|**T** = 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)| -|SplitToSequence|*in* input:**T**
*in* split:**I**
*out* output_sequence:**S**|11+|**I** = tensor(int32), tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))
**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(string)| +|SplitToSequence|*in* input:**T**
*in* split:**I**
*out* output_sequence:**S**|24+|**I** = tensor(int32), tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))
**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(string)| +|||[11, 23]|**I** = tensor(int32), tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))
**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(string)| |Sqrt|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(double), tensor(float)| |||[6, 12]|**T** = tensor(double), tensor(float)| -|Squeeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* squeezed:**T**

or

*in* data:**T**
*out* squeezed:**T**|21+|**T** = 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)| +|Squeeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* squeezed:**T**

or

*in* data:**T**
*out* squeezed:**T**|25+|**T** = 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)| +|||24|**T** = 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)| +|||23|**T** = 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)| +|||[21, 22]|**T** = 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)| |||[13, 20]|**T** = 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)| |||[11, 12]|**T** = 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)| |||[1, 10]|**T** = 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)| @@ -444,21 +506,29 @@ Do not modify directly.* |||[7, 21]|**T** = tensor(float)| |Tanh|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float)| |||[6, 12]|**T** = tensor(double), tensor(float)| +|TensorScatter|*in* past_cache:**T**
*in* update:**T**
*in* write_indices:**tensor(int64)**
*out* present_cache:**T**|24+|**T** = 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)| |TfIdfVectorizer|*in* X:**T**
*out* Y:**T1**|9+|**T** = tensor(int32), tensor(int64), tensor(string)
**T1** = tensor(float)| |ThresholdedRelu|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(float)| |||[10, 21]|**T** = tensor(float)| |||[1, 9]|**T** = tensor(float)| |Tile|*in* input:**T**
*in* repeats:**T1**
*out* output:**T**

or

*in* input:**T**
*in* tiles:**T**
*in* axis:**T**
*out* output:**T**|13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| |||[6, 12]|**T** = tensor(bool), tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| -|TopK|*in* X:**T**
*in* K:**tensor(int64)**
*out* Values:**T**
*out* Indices:**I**

or

*in* X:**T**
*out* Values:**T**
*out* Indices:**I**|11+|**I** = tensor(int64)
**T** = tensor(double), tensor(float), tensor(int32), tensor(int64)| +|TopK|*in* X:**T**
*in* K:**tensor(int64)**
*out* Values:**T**
*out* Indices:**I**

or

*in* X:**T**
*out* Values:**T**
*out* Indices:**I**|24+|**I** = tensor(int64)
**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint8)| +|||[11, 23]|**I** = tensor(int64)
**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint8)| |||10|**I** = tensor(int64)
**T** = tensor(double), tensor(float)| |||[1, 9]|**I** = tensor(int64)
**T** = tensor(double), tensor(float)| -|Transpose|*in* data:**T**
*out* transposed:**T**|21+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| +|Transpose|*in* data:**T**
*out* transposed:**T**|25+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int2), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint2), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| +|||24|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| +|||23|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| +|||[21, 22]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int4), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint4), tensor(uint64), tensor(uint8)| |||[13, 20]|**T** = 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)| |||[1, 12]|**T** = 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)| |Trilu|*in* input:**T**
*in* k:**tensor(int64)**
*out* output:**T**|14+|**T** = tensor(bool), tensor(double), tensor(float), tensor(int64)| |Unique|*in* X:**T**
*out* Y:**T**
*out* indices:**tensor(int64)**
*out* inverse_indices:**tensor(int64)**
*out* counts:**tensor(int64)**|11+|**T** = tensor(double), tensor(float), tensor(int64), tensor(int8), tensor(string)| -|Unsqueeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* expanded:**T**

or

*in* data:**T**
*out* expanded:**T**|21+|**T** = 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)| +|Unsqueeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* expanded:**T**

or

*in* data:**T**
*out* expanded:**T**|25+|**T** = 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)| +|||24|**T** = 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)| +|||23|**T** = 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)| +|||[21, 22]|**T** = 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)| |||[13, 20]|**T** = 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)| |||[11, 12]|**T** = 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)| |||[1, 10]|**T** = 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)| @@ -502,9 +572,10 @@ Do not modify directly.* |BiasGelu|*in* A:**T**
*in* B:**T**
*out* C:**T**|1+|**T** = tensor(float)| |BifurcationDetector|*in* src_tokens:**T**
*in* cur_tokens:**T**
*in* prev_suffix_match_idx:**T**
*in* pred_tokens:**T**
*out* tokens:**T**
*out* suffix_match_idx:**T**|1+|**T** = tensor(int64)| |CDist|*in* A:**T**
*in* B:**T**
*out* C:**T**|1+|**T** = tensor(double), tensor(float)| +|CausalConvWithState|*in* input:**T**
*in* weight:**T**
*in* bias:**T**
*in* past_state:**T**
*out* output:**T**
*out* present_state:**T**|1+|**T** = tensor(float)| |ConvTransposeWithDynamicPads|*in* X:**T**
*in* W:**T**
*in* Pads:**tensor(int64)**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |CropAndResize|*in* X:**T1**
*in* rois:**T1**
*in* batch_indices:**T2**
*in* crop_size:**T2**
*out* Y:**T1**|1+|**T1** = tensor(float)
**T2** = tensor(int32)| -|DecoderMaskedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* mask_index:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*in* bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**V**|1+|**T** = tensor(float)| +|DecoderMaskedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* mask_index:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*in* bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**QK**|1+|**T** = tensor(float)| |DequantizeLinear|*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|1+|**T1** = tensor(int16), tensor(int32), tensor(int4), tensor(int8), tensor(uint16), tensor(uint4), tensor(uint8)
**T2** = tensor(float)| |DynamicQuantizeLSTM|*in* X:**T**
*in* W:**T2**
*in* R:**T2**
*in* B:**T**
*in* sequence_lens:**T1**
*in* initial_h:**T**
*in* initial_c:**T**
*in* P:**T**
*in* W_scale:**T**
*in* W_zero_point:**T2**
*in* R_scale:**T**
*in* R_zero_point:**T2**
*out* Y:**T**
*out* Y_h:**T**
*out* Y_c:**T**|1+|**T** = tensor(float)
**T1** = tensor(int32)
**T2** = tensor(int8), tensor(uint8)| |DynamicQuantizeMatMul|*in* A:**T1**
*in* B:**T2**
*in* b_scale:**T1**
*in* b_zero_point:**T2**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float)
**T2** = tensor(int8), tensor(uint8)| @@ -514,21 +585,23 @@ Do not modify directly.* |FastGelu|*in* X:**T**
*in* bias:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |FusedConv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*in* Z:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |FusedGemm|*in* A:**T**
*in* B:**T**
*in* C:**T**
*out* Y:**T**|1+|**T** = tensor(float)| -|FusedMatMul|*in* A:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float)| -|GatherBlockQuantized|*in* data:**T1**
*in* indices:**Tind**
*in* scales:**T2**
*in* zero_points:**T1**
*out* output:**T2**|1+|**T1** = tensor(int4), tensor(uint4)
**T2** = tensor(float), tensor(float16)
**Tind** = tensor(int32), tensor(int64)| +|FusedMatMul|*in* A:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float)| +|GatherBlockQuantized|*in* data:**T1**
*in* indices:**Tind**
*in* scales:**T2**
*in* zero_points:**T1**
*out* output:**T2**|1+|**T1** = tensor(int4), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)
**Tind** = tensor(int32), tensor(int64)| |GatherND|*in* data:**T**
*in* indices:**Tind**
*out* output:**T**|1+|**T** = 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)
**Tind** = tensor(int32), tensor(int64)| |Gelu|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |GreedySearch|*in* input_ids:**I**
*in* max_length:**I**
*in* min_length:**I**
*in* repetition_penalty:**T**
*in* vocab_mask:**I**
*in* prefix_vocab_mask:**I**
*in* attention_mask:**I**
*out* sequences:**I**|1+|**T** = tensor(float)| |GridSample|*in* X:**T1**
*in* Grid:**T1**
*out* Y:**T2**|1+|**T1** = tensor(float)
**T2** = tensor(float)| -|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| +|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T_CACHE**
*in* past_value:**T_CACHE**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*in* position_ids:**tensor(int64)**
*in* attention_bias:**T**
*in* head_sink:**T**
*in* k_scale:**T_KV_SCALE**
*in* v_scale:**T_KV_SCALE**
*out* output:**T**
*out* present_key:**T_CACHE**
*out* present_value:**T_CACHE**
*out* output_qk:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |Inverse|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| +|LinearAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_state:**S**
*in* decay:**T**
*in* beta:**T**
*out* output:**T**
*out* present_state:**S**|1+|**T** = tensor(float)| |MatMulBnb4|*in* A:**T1**
*in* B:**T2**
*in* absmax:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float)
**T2** = tensor(uint8)| |MatMulFpQ4|*in* A:**T1**
*in* B:**T2**
*in* B_shape:**T3**
*out* Y:**T1**|1+|**T1** = tensor(float)
**T2** = tensor(uint8)
**T3** = tensor(int64)| |MatMulInteger16|*in* A:**T1**
*in* B:**T2**
*out* Y:**T3**|1+|**T1** = tensor(int16)
**T2** = tensor(int16)
**T3** = tensor(int32)| |MatMulIntegerToFloat|*in* A:**T1**
*in* B:**T2**
*in* a_scale:**T3**
*in* b_scale:**T3**
*in* a_zero_point:**T1**
*in* b_zero_point:**T2**
*in* bias:**T3**
*out* Y:**T3**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float)| |MatMulNBits|*in* A:**T1**
*in* B:**T2**
*in* scales:**T1**
*in* zero_points:**T3**
*in* g_idx:**T4**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(uint8)
**T3** = tensor(float), tensor(float16), tensor(uint8)
**T4** = tensor(int32)| |MaxpoolWithMask|*in* X:**T**
*in* M:**tensor(int32)**
*out* Y:**T**|1+|**T** = tensor(float)| -|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**T** = tensor(float)| +|MoE|*in* input:**T**
*in* router_probs:**T**
*in* fc1_experts_weights:**T**
*in* fc1_experts_bias:**T**
*in* fc2_experts_weights:**T**
*in* fc2_experts_bias:**T**
*in* fc3_experts_weights:**T**
*in* fc3_experts_bias:**T**
*out* output:**T**|1+|**T** = tensor(float)| +|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* cache_indirection:**M**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**QK**|1+|**T** = tensor(float)| |MurmurHash3|*in* X:**T1**
*out* Y:**T2**|1+|**T1** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(string), tensor(uint32), tensor(uint64)
**T2** = tensor(int32), tensor(uint32)| |NGramRepeatBlock|*in* input_ids:**Tid**
*in* scores:**T**
*out* scores_out:**T**|1+|**T** = tensor(float)
**Tid** = tensor(int64)| |NhwcMaxPool|*in* x:**T**
*out* y:**T**|1+|**T** = tensor(int8), tensor(uint8)| @@ -543,6 +616,7 @@ Do not modify directly.* |QLinearSigmoid|*in* X:**T**
*in* X_scale:**tensor(float)**
*in* X_zero_point:**T**
*in* Y_scale:**tensor(float)**
*in* Y_zero_point:**T**
*out* Y:**T**|1+|**T** = tensor(int8), tensor(uint8)| |QLinearSoftmax|*in* X:**T**
*in* X_scale:**tensor(float)**
*in* x_zero_point:**T**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T**
*out* Y:**T**|1+|**T** = tensor(int8), tensor(uint8)| |QLinearWhere|*in* condition:**B**
*in* X:**T**
*in* x_scale:**TF**
*in* x_zero_point:**T**
*in* Y:**T**
*in* y_scale:**TF**
*in* y_zero_point:**T**
*in* z_scale:**TF**
*in* z_zero_point:**T**
*out* Z:**T**|1+|**T** = tensor(int8), tensor(uint8)| +|QMoE|*in* input:**T**
*in* router_probs:**T**
*in* fc1_experts_weights:**T1**
*in* fc1_scales:**T2**
*in* fc1_experts_bias:**T**
*in* fc2_experts_weights:**T1**
*in* fc2_scales:**T2**
*in* fc2_experts_bias:**T**
*in* fc3_experts_weights:**T1**
*in* fc3_scales:**T2**
*in* fc3_experts_bias:**T**
*in* fc1_zero_points:**T1**
*in* fc2_zero_points:**T1**
*in* fc3_zero_points:**T1**
*in* router_weights:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)
**T1** = tensor(uint8)
**T2** = tensor(float), tensor(float16)| |QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**|1+|**T1** = tensor(float)
**T2** = tensor(int16), tensor(int4), tensor(int8), tensor(uint16), tensor(uint4), tensor(uint8)| |QuickGelu|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |Range|*in* start:**T**
*in* limit:**T**
*in* delta:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(int16), tensor(int32), tensor(int64)| @@ -551,7 +625,7 @@ Do not modify directly.* |Sampling|*in* input_ids:**I**
*in* max_length:**I**
*in* min_length:**I**
*in* repetition_penalty:**T**
*in* vocab_mask:**I**
*in* prefix_vocab_mask:**I**
*in* attention_mask:**I**
*in* presence_mask:**I**
*in* seed:**I**
*out* sequences:**I**
*out* filtered_logits:**T**|1+|**T** = tensor(float)| |SkipLayerNormalization|*in* input:**T**
*in* skip:**T**
*in* gamma:**T**
*in* beta:**T**
*in* bias:**T**
*out* output:**T**
*out* mean:**U**
*out* inv_std_var:**U**
*out* input_skip_bias_sum:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| |SkipSimplifiedLayerNormalization|*in* input:**T**
*in* skip:**T**
*in* gamma:**T**
*in* bias:**T**
*out* output:**T**
*out* mean:**U**
*out* inv_std_var:**U**
*out* input_skip_bias_sum:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| -|SparseAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* block_row_indices:**M**
*in* block_col_indices:**M**
*in* total_sequence_length:**M**
*in* key_total_sequence_lengths:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float)| +|SparseAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* block_row_indices:**M**
*in* block_col_indices:**M**
*in* total_sequence_length:**M**
*in* key_total_sequence_lengths:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |SparseToDenseMatMul|*in* A:**T**
*in* B:**T1**
*out* Y:**T1**|1+|**T** = sparse_tensor(double), sparse_tensor(float), sparse_tensor(int32), sparse_tensor(int64), sparse_tensor(uint32), sparse_tensor(uint64)
**T1** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| |Tokenizer|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(string)| |TransposeMatMul|*in* A:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float)| @@ -582,7 +656,7 @@ Do not modify directly.* | Op Name | Parameters | OpSet Version | Types Supported | |---------|------------|---------------|-----------------| |**Operator Domain:** *ai.onnx*|||| -|Abs|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Abs|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Add|*in* A:**T**
*in* B:**T**
*out* C:**T**|14+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||13|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| @@ -595,17 +669,24 @@ Do not modify directly.* |ArgMin|*in* data:**T**
*out* reduced:**tensor(int64)**|13+|**T** = tensor(double), tensor(float), tensor(float16)| |||12|**T** = tensor(double), tensor(float), tensor(float16)| |||[1, 11]|**T** = tensor(double), tensor(float), tensor(float16)| -|AveragePool|*in* X:**T**
*out* Y:**T**|11+|**T** = tensor(double), tensor(float), tensor(float16)| +|Attention|*in* Q:**T1**
*in* K:**T1**
*in* V:**T2**
*in* attn_mask:**U**
*in* past_key:**T1**
*in* past_value:**T2**
*in* nonpad_kv_seqlen:**tensor(int64)**
*out* Y:**T1**
*out* present_key:**T1**
*out* present_value:**T2**
*out* qk_matmul_output:**T1**

or

*in* Q:**T1**
*in* K:**T1**
*in* V:**T2**
*in* attn_mask:**U**
*in* past_key:**T1**
*in* past_value:**T2**
*out* Y:**T1**
*out* present_key:**T1**
*out* present_value:**T2**
*out* qk_matmul_output:**T1**|24+|**T1** = tensor(bfloat16), tensor(float), tensor(float16)
**T2** = tensor(bfloat16), tensor(float), tensor(float16)
**U** = tensor(bfloat16), tensor(bool), tensor(float), tensor(float16)| +|||23|**T1** = tensor(bfloat16), tensor(float), tensor(float16)
**T2** = tensor(bfloat16), tensor(float), tensor(float16)
**U** = tensor(bfloat16), tensor(bool), tensor(float), tensor(float16)| +|AveragePool|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| +|||[19, 21]|**T** = tensor(double), tensor(float), tensor(float16)| +|||[11, 18]|**T** = tensor(double), tensor(float), tensor(float16)| |||10|**T** = tensor(double), tensor(float), tensor(float16)| |||[7, 9]|**T** = tensor(double), tensor(float), tensor(float16)| |BatchNormalization|*in* X:**T**
*in* scale:**T**
*in* B:**T**
*in* input_mean:**U**
*in* input_var:**U**
*out* Y:**T**
*out* running_mean:**U**
*out* running_var:**U**

or

*in* X:**T**
*in* scale:**T**
*in* B:**T**
*in* mean:**T**
*in* var:**T**
*out* Y:**T**
*out* mean:**T**
*out* var:**T**
*out* saved_mean:**T**
*out* saved_var:**T**

or

*in* X:**T**
*in* scale:**T1**
*in* B:**T1**
*in* input_mean:**T2**
*in* input_var:**T2**
*out* Y:**T**
*out* running_mean:**T2**
*out* running_var:**T2**|15+|**T** = tensor(double), tensor(float), tensor(float16)
**T1** = tensor(double), tensor(float), tensor(float16)
**T2** = tensor(double), tensor(float), tensor(float16)| |||14|**T** = tensor(double), tensor(float), tensor(float16)
**U** = tensor(double), tensor(float), tensor(float16)| |||[9, 13]|**T** = tensor(double), tensor(float), tensor(float16)| |||[7, 8]|**T** = tensor(double), tensor(float), tensor(float16)| -|Cast|*in* input:**T1**
*out* output:**T2**|19+|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|||[13, 18]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|||[9, 12]|**T1** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|||[6, 8]|**T1** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Cast|*in* input:**T1**
*out* output:**T2**|25+|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[23, 24]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[19, 20]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[13, 18]|**T1** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[9, 12]|**T1** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[6, 8]|**T1** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float4e2m1), tensor(float8e4m3fn), tensor(float8e5m2), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Ceil|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16)| |Clip|*in* input:**T**
*in* min:**T**
*in* max:**T**
*out* output:**T**

or

*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int64), tensor(int8), tensor(uint64), tensor(uint8)| @@ -618,19 +699,29 @@ Do not modify directly.* |||[11, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[4, 10]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |ConcatFromSequence|*in* input_sequence:**S**
*out* concat_result:**T**|11+|**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))| -|ConstantOfShape|*in* input:**T1**
*out* output:**T2**|9+|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|Conv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|11+|**T** = tensor(double), tensor(float), tensor(float16)| +|ConstantOfShape|*in* input:**T1**
*out* output:**T2**|25+|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[23, 24]|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[9, 20]|**T1** = tensor(int64)
**T2** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Conv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|22+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| +|||[11, 21]|**T** = tensor(double), tensor(float), tensor(float16)| |||[1, 10]|**T** = tensor(double), tensor(float), tensor(float16)| -|ConvTranspose|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|11+|**T** = tensor(double), tensor(float), tensor(float16)| +|ConvTranspose|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|22+|**T** = tensor(double), tensor(float), tensor(float16)| +|||[11, 21]|**T** = tensor(double), tensor(float), tensor(float16)| |||[1, 10]|**T** = tensor(double), tensor(float), tensor(float16)| -|Cos|*in* input:**T**
*out* output:**T**|7+|**T** = tensor(double), tensor(float), tensor(float16)| +|Cos|*in* input:**T**
*out* output:**T**|22+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| +|||[7, 21]|**T** = tensor(double), tensor(float), tensor(float16)| |Crop|*in* input:**T**
*out* output:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| |CumSum|*in* x:**T**
*in* axis:**T2**
*out* y:**T**|14+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)
**T2** = tensor(int32), tensor(int64)| |||[11, 13]|**T** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)
**T2** = tensor(int32), tensor(int64)| +|DeformConv|*in* X:**T**
*in* W:**T**
*in* offset:**T**
*in* B:**T**
*in* mask:**T**
*out* Y:**T**|22+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| +|||[19, 21]|**T** = tensor(double), tensor(float), tensor(float16)| |DepthToSpace|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16)| |||[11, 12]|**T** = tensor(double), tensor(float), tensor(float16)| |||[1, 10]|**T** = tensor(double), tensor(float), tensor(float16)| -|DequantizeLinear|*in* x:**T**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T**
*out* y:**tensor(float)**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|21+|**T1** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)| +|DequantizeLinear|*in* x:**T**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T**
*out* y:**tensor(float)**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T3**|25+|**T1** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)
**T3** = tensor(float), tensor(float16)| +|||[23, 24]|**T1** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)
**T3** = tensor(float), tensor(float16)| +|||[21, 22]|**T1** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)| |||[19, 20]|**T1** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int8), tensor(uint8)
**T2** = tensor(float), tensor(float16)| |||[13, 18]|**T** = tensor(int8), tensor(uint8)| |||[10, 12]|**T** = tensor(int8), tensor(uint8)| @@ -644,7 +735,8 @@ Do not modify directly.* |DynamicSlice|*in* data:**T**
*in* starts:**Tind**
*in* ends:**Tind**
*in* axes:**Tind**
*out* output:**T**|1+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**Tind** = tensor(int32), tensor(int64)| |Einsum|*in* Inputs:**T**
*out* Output:**T**|12+|**T** = tensor(double), tensor(float), tensor(float16)| |Elu|*in* X:**T**
*out* Y:**T**|6+|**T** = tensor(double), tensor(float), tensor(float16)| -|Equal|*in* A:**T**
*in* B:**T**
*out* C:**T1**|13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)
**T1** = tensor(bool)| +|Equal|*in* A:**T**
*in* B:**T**
*out* C:**T1**|19+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)
**T1** = tensor(bool)| +|||[13, 18]|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)
**T1** = tensor(bool)| |||[11, 12]|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| |||[7, 10]|**T** = tensor(bool), tensor(int32), tensor(int64)| |Erf|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| @@ -654,13 +746,17 @@ Do not modify directly.* |Expand|*in* input:**T**
*in* shape:**tensor(int64)**
*out* output:**T**|13+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[8, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |EyeLike|*in* input:**T1**
*out* output:**T2**|9+|**T1** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(uint64)
**T2** = tensor(double), tensor(float), tensor(int32), tensor(int64), tensor(uint64)| -|Flatten|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Flatten|*in* input:**T**
*out* output:**T**|25+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[23, 24]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[13, 20]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[11, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[9, 10]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[1, 8]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Floor|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16)| -|GRU|*in* X:**T**
*in* W:**T**
*in* R:**T**
*in* B:**T**
*in* sequence_lens:**T1**
*in* initial_h:**T**
*out* Y:**T**
*out* Y_h:**T**|14+|**T** = tensor(double), tensor(float), tensor(float16)
**T1** = tensor(int32)| +|GRU|*in* X:**T**
*in* W:**T**
*in* R:**T**
*in* B:**T**
*in* sequence_lens:**T1**
*in* initial_h:**T**
*out* Y:**T**
*out* Y_h:**T**|22+|**T** = tensor(double), tensor(float), tensor(float16)
**T1** = tensor(int32)| +|||[14, 21]|**T** = tensor(double), tensor(float), tensor(float16)
**T1** = tensor(int32)| |||[7, 13]|**T** = tensor(double), tensor(float), tensor(float16)
**T1** = tensor(int32)| |Gather|*in* data:**T**
*in* indices:**Tind**
*out* output:**T**|13+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**Tind** = tensor(int32), tensor(int64)| |||[11, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**Tind** = tensor(int32), tensor(int64)| @@ -670,25 +766,38 @@ Do not modify directly.* |GatherND|*in* data:**T**
*in* indices:**tensor(int64)**
*out* output:**T**|13+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int64)
**indices** = tensor(int64)| |||12|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int64)
**indices** = tensor(int64)| |||11|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int64)
**indices** = tensor(int64)| -|Gelu|*in* X:**T**
*out* Y:**T**|20+|**T** = tensor(double), tensor(float), tensor(float16)| +|Gelu|*in* X:**T**
*out* Y:**T**|20+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |Gemm|*in* A:**T**
*in* B:**T**
*in* C:**T**
*out* Y:**T**|13+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |||[11, 12]|**T** = tensor(double), tensor(float), tensor(float16)| |||[9, 10]|**T** = tensor(double), tensor(float), tensor(float16)| |||[7, 8]|**T** = tensor(double), tensor(float), tensor(float16)| -|GlobalAveragePool|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| -|GlobalMaxPool|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| +|GlobalAveragePool|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(double), tensor(float), tensor(float16)| +|||[1, 21]|**T** = tensor(double), tensor(float), tensor(float16)| +|GlobalMaxPool|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(double), tensor(float), tensor(float16)| +|||[1, 21]|**T** = tensor(double), tensor(float), tensor(float16)| |Greater|*in* A:**T**
*in* B:**T**
*out* C:**T1**|13+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)
**T1** = tensor(bool)| |||[9, 12]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)| |||[7, 8]|**T** = tensor(double), tensor(float), tensor(float16)| |GreaterOrEqual|*in* A:**T**
*in* B:**T**
*out* C:**T1**|16+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)
**T1** = tensor(bool)| |||[12, 15]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(uint32), tensor(uint64)
**T1** = tensor(bool)| -|GridSample|*in* X:**T1**
*in* grid:**T2**
*out* Y:**T1**|16+|**T1** = tensor(float)
**T2** = tensor(float)| -|HardSigmoid|*in* X:**T**
*out* Y:**T**|6+|**T** = tensor(double), tensor(float), tensor(float16)| -|Identity|*in* input:**T**
*out* output:**T**

or

*in* input:**V**
*out* output:**V**|19+|**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|GridSample|*in* X:**T1**
*in* grid:**T2**
*out* Y:**T1**|22+|**T1** = tensor(float)
**T2** = tensor(float)| +|||[20, 21]|**T1** = tensor(float)
**T2** = tensor(float)| +|||[16, 19]|**T1** = tensor(float)
**T2** = tensor(float)| +|HardSigmoid|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| +|||[6, 21]|**T** = tensor(double), tensor(float), tensor(float16)| +|HardSwish|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| +|||[14, 21]|**T** = tensor(double), tensor(float), tensor(float16)| +|Identity|*in* input:**T**
*out* output:**T**

or

*in* input:**V**
*out* output:**V**|25+|**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[23, 24]|**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[19, 20]|**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[14, 18]|**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||13|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[1, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|If|*in* cond:**B**
*out* outputs:**V**|19+|**B** = tensor(bool)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|If|*in* cond:**B**
*out* outputs:**V**|25+|**B** = tensor(bool)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[23, 24]|**B** = tensor(bool)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**B** = tensor(bool)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[19, 20]|**B** = tensor(bool)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[13, 18]|**B** = tensor(bool)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), 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)| |||[11, 12]|**B** = tensor(bool)
**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[1, 10]|**B** = tensor(bool)
**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| @@ -717,7 +826,10 @@ Do not modify directly.* |LogSoftmax|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16)| |||[11, 12]|**T** = tensor(double), tensor(float), tensor(float16)| |||[1, 10]|**T** = tensor(double), tensor(float), tensor(float16)| -|Loop|*in* M:**I**
*in* cond:**B**
*in* v_initial:**V**
*out* v_final_and_scan_outputs:**V**|19+|**B** = tensor(bool)
**I** = tensor(int64)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Loop|*in* M:**I**
*in* cond:**B**
*in* v_initial:**V**
*out* v_final_and_scan_outputs:**V**|25+|**B** = tensor(bool)
**I** = tensor(int64)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[23, 24]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[19, 20]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(float8e4m3fn)), seq(tensor(float8e4m3fnuz)), seq(tensor(float8e5m2)), seq(tensor(float8e5m2fnuz)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(string), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[13, 18]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(string)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8)), 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)| |||[11, 12]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[1, 10]|**B** = tensor(bool)
**I** = tensor(int64)
**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| @@ -753,25 +865,38 @@ Do not modify directly.* |PRelu|*in* X:**T**
*in* slope:**T**
*out* Y:**T**|16+|**T** = tensor(double), tensor(float), tensor(float16)| |||[9, 15]|**T** = tensor(double), tensor(float), tensor(float16)| |||[7, 8]|**T** = tensor(double), tensor(float), tensor(float16)| -|Pad|*in* data:**T**
*in* pads:**tensor(int64)**
*in* constant_value:**T**
*in* axes:**Tind**
*out* output:**T**

or

*in* data:**T**
*in* pads:**tensor(int64)**
*in* constant_value:**T**
*out* output:**T**

or

*in* data:**T**
*out* output:**T**|18+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16)| +|Pad|*in* data:**T**
*in* pads:**tensor(int64)**
*in* constant_value:**T**
*in* axes:**Tind**
*out* output:**T**

or

*in* data:**T**
*in* pads:**tensor(int64)**
*in* constant_value:**T**
*out* output:**T**

or

*in* data:**T**
*out* output:**T**|25+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16)| +|||24|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16)| +|||23|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16)| +|||[21, 22]|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16)| +|||[19, 20]|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16)| +|||18|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16)| |||[13, 17]|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16)| |||[11, 12]|**T** = tensor(double), tensor(float), tensor(float16)| |||[2, 10]|**T** = tensor(double), tensor(float), tensor(float16)| |ParametricSoftplus|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| -|Pow|*in* X:**T**
*in* Y:**T**
*out* Z:**T**

or

*in* X:**T**
*in* Y:**T1**
*out* Z:**T**|15+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)
**T1** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)| -|||[13, 14]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)
**T1** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)| +|Pow|*in* X:**T**
*in* Y:**T**
*out* Z:**T**

or

*in* X:**T**
*in* Y:**T1**
*out* Z:**T**|15+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)
**T1** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)| +|||[13, 14]|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)
**T1** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)| |||12|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)
**T1** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)| |||[7, 11]|**T** = tensor(double), tensor(float), tensor(float16)| -|QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**

or

*in* x:**T1**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T2**
*out* y:**T2**|21+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)| +|QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**

or

*in* x:**T1**
*in* y_scale:**T2**
*in* y_zero_point:**T3**
*out* y:**T3**

or

*in* x:**T1**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T2**
*out* y:**T2**|25+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float), tensor(float16)
**T3** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)| +|||[23, 24]|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float), tensor(float16)
**T3** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)| +|||[21, 22]|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)| |||[19, 20]|**T1** = tensor(float), tensor(float16)
**T2** = tensor(float8e4m3fn), tensor(float8e5m2), tensor(int8), tensor(uint8)| |||[13, 18]|**T1** = tensor(float)
**T2** = tensor(int8), tensor(uint8)| |||[10, 12]|**T1** = tensor(float)
**T2** = tensor(int8), tensor(uint8)| -|RNN|*in* X:**T**
*in* W:**T**
*in* R:**T**
*in* B:**T**
*in* sequence_lens:**T1**
*in* initial_h:**T**
*out* Y:**T**
*out* Y_h:**T**|14+|**T** = tensor(double), tensor(float), tensor(float16)
**T1** = tensor(int32)| +|RMSNormalization|*in* X:**T**
*in* scale:**V**
*out* Y:**V**|23+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**V** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| +|RNN|*in* X:**T**
*in* W:**T**
*in* R:**T**
*in* B:**T**
*in* sequence_lens:**T1**
*in* initial_h:**T**
*out* Y:**T**
*out* Y_h:**T**|22+|**T** = tensor(double), tensor(float), tensor(float16)
**T1** = tensor(int32)| +|||[14, 21]|**T** = tensor(double), tensor(float), tensor(float16)
**T1** = tensor(int32)| |||[7, 13]|**T** = tensor(double), tensor(float), tensor(float16)
**T1** = tensor(int32)| -|RandomNormal|*out* output:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| -|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), tensor(float16)| -|RandomUniform|*out* output:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| -|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), tensor(float16)| +|RandomNormal|*out* output:**T**|22+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| +|||[1, 21]|**T** = tensor(double), tensor(float), tensor(float16)| +|RandomNormalLike|*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)| +|RandomUniform|*out* output:**T**|22+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| +|||[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)| |Reciprocal|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16)| @@ -783,11 +908,13 @@ Do not modify directly.* |||[1, 17]|**T** = tensor(double), tensor(float), tensor(float16)| |ReduceLogSumExp|*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)| |||[1, 17]|**T** = tensor(double), tensor(float), tensor(float16)| -|ReduceMax|*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), tensor(int64)| -|||[1, 17]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)| +|ReduceMax|*in* data:**T**
*in* axes:**tensor(int64)**
*out* reduced:**T**

or

*in* data:**T**
*out* reduced:**T**|20+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(int8), tensor(uint8)| +|||[18, 19]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(int8), tensor(uint8)| +|||[1, 17]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(int8), tensor(uint8)| |ReduceMean|*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)| |||[1, 17]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32)| -|ReduceMin|*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), tensor(int64), tensor(int8), tensor(uint8)| +|ReduceMin|*in* data:**T**
*in* axes:**tensor(int64)**
*out* reduced:**T**

or

*in* data:**T**
*out* reduced:**T**|20+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(int8), tensor(uint8)| +|||[18, 19]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(int8), tensor(uint8)| |||[1, 17]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64), tensor(int8), tensor(uint8)| |ReduceProd|*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)| |||[1, 17]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32)| @@ -798,20 +925,31 @@ Do not modify directly.* |Relu|*in* X:**T**
*out* Y:**T**|14+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |||13|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16)| -|Reshape|*in* data:**T**
*in* shape:**tensor(int64)**
*out* reshaped:**T**

or

*in* data:**T**
*out* reshaped:**T**|19+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| +|Reshape|*in* data:**T**
*in* shape:**tensor(int64)**
*out* reshaped:**T**

or

*in* data:**T**
*out* reshaped:**T**|25+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| +|||[23, 24]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| +|||[21, 22]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| +|||[19, 20]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| |||[14, 18]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| |||13|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| |||[5, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**shape** = tensor(int64)| |||[1, 4]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|Resize|*in* X:**T**
*in* scales:**tensor(float)**
*out* Y:**T**

or

*in* X:**T1**
*in* roi:**T2**
*in* scales:**tensor(float)**
*in* sizes:**tensor(int64)**
*out* Y:**T1**|18+|**T1** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(uint8)| +|Resize|*in* X:**T**
*in* scales:**tensor(float)**
*out* Y:**T**

or

*in* X:**T1**
*in* roi:**T2**
*in* scales:**tensor(float)**
*in* sizes:**tensor(int64)**
*out* Y:**T1**|19+|**T1** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(uint8)| +|||18|**T1** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(uint8)| |||[13, 17]|**T1** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(uint8)| |||[11, 12]|**T1** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(uint8)| |||10|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(uint8)| |ReverseSequence|*in* input:**T**
*in* sequence_lens:**tensor(int64)**
*out* Y:**T**|10+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|RoiAlign|*in* X:**T1**
*in* rois:**T1**
*in* batch_indices:**T2**
*out* Y:**T1**|10+|**T1** = tensor(double), tensor(float)
**T2** = tensor(int64)| -|Round|*in* X:**T**
*out* Y:**T**|11+|**T** = tensor(double), tensor(float), tensor(float16)| +|RoiAlign|*in* X:**T1**
*in* rois:**T1**
*in* batch_indices:**T2**
*out* Y:**T1**|22+|**T1** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**T2** = tensor(int64)| +|||[16, 21]|**T1** = tensor(double), tensor(float), tensor(float16)
**T2** = tensor(int64)| +|||[10, 15]|**T1** = tensor(double), tensor(float)
**T2** = tensor(int64)| +|RotaryEmbedding|*in* X:**T**
*in* cos_cache:**T**
*in* sin_cache:**T**
*in* position_ids:**M**
*out* Y:**T**|23+|**M** = tensor(int64)
**T** = tensor(bfloat16), tensor(float), tensor(float16)| +|Round|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(double), tensor(float), tensor(float16)| +|||[11, 21]|**T** = tensor(double), tensor(float), tensor(float16)| |ScaledTanh|*in* input:**T**
*out* output:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| -|Scan|*in* initial_state_and_scan_inputs:**V**
*out* final_state_and_scan_outputs:**V**

or

*in* sequence_lens:**I**
*in* initial_state_and_scan_inputs:**V**
*out* final_state_and_scan_outputs:**V**|19+|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Scan|*in* initial_state_and_scan_inputs:**V**
*out* final_state_and_scan_outputs:**V**

or

*in* sequence_lens:**I**
*in* initial_state_and_scan_inputs:**V**
*out* final_state_and_scan_outputs:**V**|25+|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[23, 24]|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[19, 20]|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[16, 18]|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[11, 15]|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[9, 10]|**V** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| @@ -832,17 +970,24 @@ Do not modify directly.* |SequenceErase|*in* input_sequence:**S**
*in* position:**I**
*out* output_sequence:**S**|11+|**I** = tensor(int32), tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))| |SequenceInsert|*in* input_sequence:**S**
*in* tensor:**T**
*in* position:**I**
*out* output_sequence:**S**|11+|**I** = tensor(int32), tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))| |SequenceLength|*in* input_sequence:**S**
*out* length:**I**|11+|**I** = tensor(int64)
**S** = seq(tensor(bfloat16)), seq(tensor(bool)), seq(tensor(double)), seq(tensor(float)), seq(tensor(float16)), seq(tensor(int16)), seq(tensor(int32)), seq(tensor(int64)), seq(tensor(int8)), seq(tensor(uint16)), seq(tensor(uint32)), seq(tensor(uint64)), seq(tensor(uint8))| -|Shape|*in* data:**T**
*out* shape:**T1**|19+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|Shape|*in* data:**T**
*out* shape:**T1**|25+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||[23, 24]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||[21, 22]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| +|||[19, 20]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e4m3fnuz), tensor(float8e5m2), tensor(float8e5m2fnuz), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| |||[15, 18]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| |||[13, 14]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| |||[1, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**T1** = tensor(int64)| |Shrink|*in* input:**T**
*out* output:**T**|9+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Sigmoid|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16)| -|Sign|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Sign|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |SimplifiedLayerNormalization|*in* X:**T**
*in* scale:**V**
*out* Y:**V**
*out* inv_std_var:**U**|1+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**U** = tensor(double), tensor(float)
**V** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| -|Sin|*in* input:**T**
*out* output:**T**|7+|**T** = tensor(double), tensor(float), tensor(float16)| -|Size|*in* data:**T**
*out* size:**T1**|13+|**T** = 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)
**T1** = tensor(int64)| +|Sin|*in* input:**T**
*out* output:**T**|22+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| +|||[7, 21]|**T** = tensor(double), tensor(float), tensor(float16)| +|Size|*in* data:**T**
*out* size:**T1**|25+|**T** = 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)
**T1** = tensor(int64)| +|||[23, 24]|**T** = 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)
**T1** = tensor(int64)| +|||[21, 22]|**T** = 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)
**T1** = tensor(int64)| +|||[13, 20]|**T** = 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)
**T1** = tensor(int64)| |||[1, 12]|**T** = 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)
**T1** = tensor(int64)| |Slice|*in* data:**T**
*in* starts:**Tind**
*in* ends:**Tind**
*in* axes:**Tind**
*in* steps:**Tind**
*out* output:**T**

or

*in* data:**T**
*out* output:**T**|13+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**Tind** = tensor(int32), tensor(int64)| |||[11, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)
**Tind** = tensor(int32), tensor(int64)| @@ -861,7 +1006,11 @@ Do not modify directly.* |||[2, 10]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Sqrt|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16)| -|Squeeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* squeezed:**T**

or

*in* data:**T**
*out* squeezed:**T**|13+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Squeeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* squeezed:**T**

or

*in* data:**T**
*out* squeezed:**T**|25+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||24|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||23|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[13, 20]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[11, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[1, 10]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Sub|*in* A:**T**
*in* B:**T**
*out* C:**T**|14+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| @@ -872,17 +1021,26 @@ Do not modify directly.* |||[6, 7]|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |Tanh|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16)| +|TensorScatter|*in* past_cache:**T**
*in* update:**T**
*in* write_indices:**tensor(int64)**
*out* present_cache:**T**|24+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |ThresholdedRelu|*in* X:**T**
*out* Y:**T**|10+|**T** = tensor(double), tensor(float), tensor(float16)| |||1+|**T** = tensor(double), tensor(float), tensor(float16)| |Tile|*in* input:**T**
*in* repeats:**T1**
*out* output:**T**

or

*in* input:**T**
*in* tiles:**T**
*in* axis:**T**
*out* output:**T**|13+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)
**T1** = tensor(int64)| |||[6, 12]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)
**T1** = tensor(int64)| -|TopK|*in* X:**T**
*in* K:**tensor(int64)**
*out* Values:**T**
*out* Indices:**I**

or

*in* X:**T**
*out* Values:**T**
*out* Indices:**I**|11+|**I** = tensor(int64)
**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)| +|TopK|*in* X:**T**
*in* K:**tensor(int64)**
*out* Values:**T**
*out* Indices:**I**

or

*in* X:**T**
*out* Values:**T**
*out* Indices:**I**|24+|**I** = tensor(int64)
**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint8)| +|||[11, 23]|**I** = tensor(int64)
**T** = tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint8)| |||10|**I** = tensor(int64)
**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)| |||[1, 9]|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(int64)| -|Transpose|*in* data:**T**
*out* transposed:**T**|13+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Transpose|*in* data:**T**
*out* transposed:**T**|25+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[23, 24]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[13, 20]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[1, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Trilu|*in* input:**T**
*in* k:**tensor(int64)**
*out* output:**T**|14+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|Unsqueeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* expanded:**T**

or

*in* data:**T**
*out* expanded:**T**|13+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|Unsqueeze|*in* data:**T**
*in* axes:**tensor(int64)**
*out* expanded:**T**

or

*in* data:**T**
*out* expanded:**T**|25+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||24|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||23|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[21, 22]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| +|||[13, 20]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[11, 12]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||[1, 10]|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |Upsample|*in* X:**T**
*in* scales:**tensor(float)**
*out* Y:**T**

or

*in* X:**T**
*out* Y:**T**|9|**T** = tensor(double), tensor(float), tensor(float16), tensor(int32), tensor(uint8)| @@ -892,8 +1050,13 @@ Do not modify directly.* |Xor|*in* A:**T**
*in* B:**T**
*out* C:**T1**|7+|**T** = tensor(bool)
**T1** = tensor(bool)| | | | | +|**Operator Domain:** *ai.onnx.ml*|||| +|LabelEncoder|*in* X:**T1**
*out* Y:**T2**|4+|**T1** = tensor(double), tensor(float), tensor(int64)
**T2** = tensor(double), tensor(float), tensor(int64)| +|||[2, 3]|**T1** = tensor(float), tensor(int64)
**T2** = tensor(float), tensor(int64)| +| | +| | |**Operator Domain:** *com.microsoft*|||| -|Attention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* attention_bias:**T**
*in* past_sequence_length:**M**
*out* output:**T**
*out* present:**T**|1+|**T** = tensor(float), tensor(float16)| +|Attention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* attention_bias:**T**
*in* past_sequence_length:**M**
*out* output:**T**
*out* present:**T**|1+|**T** = tensor(bfloat16), tensor(float), tensor(float16)| |BeamSearch|*in* input_ids:**F**
*in* max_length:**I**
*in* min_length:**I**
*in* num_beams:**I**
*in* num_return_sequences:**I**
*in* length_penalty:**T**
*in* repetition_penalty:**T**
*in* vocab_mask:**M**
*in* prefix_vocab_mask:**M**
*in* attention_mask:**I**
*in* decoder_input_ids:**I**
*in* logits_processor:**I**
*out* sequences:**I**
*out* sequences_scores:**T**
*out* scores:**T**|1+|**T** = tensor(float), tensor(float16)| |BiasAdd|*in* X:**T**
*in* bias:**T**
*in* skip:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |BiasDropout|*in* data:**T**
*in* bias:**T**
*in* residual:**T**
*in* ratio:**T1**
*in* training_mode:**T2**
*out* output:**T**
*out* mask:**T2**|1+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**T1** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**T2** = tensor(bool)| @@ -902,11 +1065,12 @@ Do not modify directly.* |BiasSplitGelu|*in* X:**T**
*in* bias:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |BitmaskBiasDropout|*in* data:**T**
*in* bias:**T**
*in* residual:**T**
*in* ratio:**T1**
*in* training_mode:**T2**
*out* output:**T**
*out* mask:**T3**|1+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**T1** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**T2** = tensor(bool)
**T3** = tensor(uint32)| |BitmaskDropout|*in* data:**T**
*in* ratio:**T1**
*in* training_mode:**T2**
*out* output:**T**
*out* mask:**T3**|1+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**T1** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)
**T2** = tensor(bool)
**T3** = tensor(uint32)| +|CausalConvWithState|*in* input:**T**
*in* weight:**T**
*in* bias:**T**
*in* past_state:**T**
*out* output:**T**
*out* present_state:**T**|1+|**T** = tensor(float), tensor(float16)| |ComplexMul|*in* A:**T**
*in* B:**T**
*out* C:**T**|1+|**T** = tensor(float), tensor(float16)| |ComplexMulConj|*in* A:**T**
*in* B:**T**
*out* C:**T**|1+|**T** = tensor(float), tensor(float16)| |ConvTransposeWithDynamicPads|*in* X:**T**
*in* W:**T**
*in* Pads:**tensor(int64)**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |DecoderAttention|*in* query:**T**
*in* key:**T**
*in* q_weight:**T**
*in* kv_weight:**T**
*in* bias:**T**
*in* key_padding_mask:**B**
*in* key_cache:**T**
*in* value_cache:**T**
*in* static_kv:**B**
*in* use_past:**B**
*in* has_layer_state:**B**
*in* has_key_padding_mask:**B**
*out* output:**T**
*out* new_key_cache:**T**
*out* new_value_cache:**T**|1+|**T** = tensor(float), tensor(float16)| -|DecoderMaskedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* mask_index:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*in* bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**V**|1+|**T** = tensor(float), tensor(float16)| +|DecoderMaskedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* mask_index:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*in* bias:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**QK**|1+|**QK** = tensor(float), tensor(float16)
**T** = tensor(float), tensor(float16)| |DecoderMaskedSelfAttention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* mask_index:**M**
*in* past:**T**
*in* attention_bias:**T**
*in* past_sequence_length:**M**
*in* beam_width:**M**
*in* cache_indirection:**M**
*out* output:**T**
*out* present:**T**|1+|**T** = tensor(float), tensor(float16)| |DequantizeLinear|*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(float16)| |DequantizeWithOrder|*in* input:**Q**
*in* scale_input:**S**
*out* output:**F**|1+|**F** = tensor(float), tensor(float16)
**Q** = tensor(int8)
**S** = tensor(float)| @@ -916,26 +1080,29 @@ Do not modify directly.* |FusedConv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*in* Z:**T**
*out* Y:**T**|1+|**T** = tensor(float)| |FusedMatMul|*in* A:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |GatedRelativePositionBias|*in* query_layer:**T**
*in* query_bias:**T**
*in* rel_pos:**T**
*in* weight:**T**
*in* bias:**T**
*in* eco_a:**T**
*in* token_offset:**M**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| +|GatherBlockQuantized|*in* data:**T1**
*in* indices:**Tind**
*in* scales:**T2**
*in* zero_points:**T1**
*out* output:**T2**|1+|**T1** = tensor(int4), tensor(uint4), tensor(uint8)
**T2** = tensor(bfloat16), tensor(float), tensor(float16)
**Tind** = tensor(int32), tensor(int64)| |Gelu|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |GemmFloat8|*in* A:**TA**
*in* B:**TB**
*in* C:**TC**
*in* scaleA:**TS**
*in* scaleB:**TS**
*in* scaleY:**TS**
*out* Y:**TR**|1+|**TA** = tensor(bfloat16), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e5m2)
**TB** = tensor(bfloat16), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e5m2)
**TR** = tensor(bfloat16), tensor(float), tensor(float16), tensor(float8e4m3fn), tensor(float8e5m2)
**TS** = tensor(float)| |GemmaRotaryEmbedding|*in* emb:**U**
*in* q:**T**
*in* q_rot:**T**
*in* k:**T**
*in* k_rot:**T**
*out* output1:**T**
*out* output2:**T**|1+|**T** = tensor(float16)
**U** = tensor(float)| |GreedySearch|*in* input_ids:**I**
*in* max_length:**I**
*in* min_length:**I**
*in* repetition_penalty:**T**
*in* vocab_mask:**I**
*in* prefix_vocab_mask:**I**
*in* attention_mask:**I**
*out* sequences:**I**|1+|**T** = tensor(float), tensor(float16)| |GridSample|*in* X:**T1**
*in* Grid:**T1**
*out* Y:**T2**|1+|**T1** = tensor(float)
**T2** = tensor(float)| |GroupNorm|*in* X:**T**
*in* gamma:**M**
*in* beta:**M**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| -|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(bfloat16), tensor(float16)| +|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T_CACHE**
*in* past_value:**T_CACHE**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*in* position_ids:**tensor(int64)**
*in* attention_bias:**T**
*in* head_sink:**T**
*in* k_scale:**T_KV_SCALE**
*in* v_scale:**T_KV_SCALE**
*out* output:**T**
*out* present_key:**T_CACHE**
*out* present_value:**T_CACHE**
*out* output_qk:**T**|1+|**M** = tensor(int32)
**T** = tensor(bfloat16), tensor(float16)
**T_CACHE** = tensor(bfloat16), tensor(float16), tensor(float8e4m3fn), tensor(int8)
**T_KV_SCALE** = tensor(float)| |Inverse|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| |Irfft|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| +|LinearAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_state:**S**
*in* decay:**T**
*in* beta:**T**
*out* output:**T**
*out* present_state:**S**|1+|**T** = tensor(float), tensor(float16)| |LongformerAttention|*in* input:**T**
*in* weight:**T**
*in* bias:**T**
*in* mask:**T**
*in* global_weight:**T**
*in* global_bias:**T**
*in* global:**G**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| |MatMulBnb4|*in* A:**T1**
*in* B:**T2**
*in* absmax:**T1**
*out* Y:**T1**|1+|**T1** = tensor(bfloat16), tensor(float), tensor(float16)
**T2** = tensor(uint8)| -|MatMulNBits|*in* A:**T1**
*in* B:**T2**
*in* scales:**T1**
*in* zero_points:**T3**
*in* g_idx:**T4**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(uint8)| -|MoE|*in* input:**T**
*in* router_probs:**T**
*in* fc1_experts_weights:**T**
*in* fc1_experts_bias:**T**
*in* fc2_experts_weights:**T**
*in* fc2_experts_bias:**T**
*in* fc3_experts_weights:**T**
*in* fc3_experts_bias:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| -|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**T** = tensor(float), tensor(float16)| +|MatMulNBits|*in* A:**T1**
*in* B:**T2**
*in* scales:**T1**
*in* zero_points:**T3**
*in* g_idx:**T4**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(bfloat16), tensor(float), tensor(float16)
**T2** = tensor(uint8)
**T3** = tensor(bfloat16), tensor(float), tensor(float16), tensor(uint8)| +|MoE|*in* input:**T**
*in* router_probs:**T**
*in* fc1_experts_weights:**T**
*in* fc1_experts_bias:**T**
*in* fc2_experts_weights:**T**
*in* fc2_experts_bias:**T**
*in* fc3_experts_weights:**T**
*in* fc3_experts_bias:**T**
*out* output:**T**|1+|**T** = tensor(bfloat16), tensor(float), tensor(float16)| +|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* cache_indirection:**M**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**QK**|1+|**QK** = tensor(bfloat16), tensor(float), tensor(float16)
**T** = tensor(bfloat16), tensor(float), tensor(float16)| |NGramRepeatBlock|*in* input_ids:**Tid**
*in* scores:**T**
*out* scores_out:**T**|1+|**T** = tensor(float)
**Tid** = tensor(int64)| |NhwcConv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |PackedAttention|*in* input:**T**
*in* weights:**T**
*in* bias:**T**
*in* token_offset:**M**
*in* cumulative_sequence_length:**M**
*in* attention_bias:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| |PackedMultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* token_offset:**M**
*in* cumulative_sequence_length:**M**
*in* attention_bias:**T**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| +|PagedAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* key_cache:**T**
*in* value_cache:**T**
*in* cumulative_sequence_length:**S**
*in* past_seqlens:**S**
*in* block_table:**S**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* key_cache_out:**T**
*out* value_cache_out:**T**|1+|**S** = tensor(int32)
**T** = tensor(bfloat16), tensor(float16)| |QAttention|*in* input:**T1**
*in* weight:**T2**
*in* bias:**T3**
*in* input_scale:**T3**
*in* weight_scale:**T3**
*in* mask_index:**T4**
*in* input_zero_point:**T1**
*in* weight_zero_point:**T2**
*in* past:**T3**
*out* output:**T3**
*out* present:**T3**|1+|**T1** = tensor(int8)
**T2** = tensor(int8)
**T3** = tensor(float), tensor(float16)
**T4** = tensor(int32)| -|QMoE|*in* input:**T**
*in* router_probs:**T**
*in* fc1_experts_weights:**T1**
*in* fc1_scales:**T**
*in* fc1_experts_bias:**T**
*in* fc2_experts_weights:**T1**
*in* fc2_scales:**T**
*in* fc2_experts_bias:**T**
*in* fc3_experts_weights:**T1**
*in* fc3_scales:**T**
*in* fc3_experts_bias:**T**
*out* output:**T**|1+|**T** = tensor(float16)
**T1** = tensor(uint8)| +|QMoE|*in* input:**T**
*in* router_probs:**T**
*in* fc1_experts_weights:**T1**
*in* fc1_scales:**T2**
*in* fc1_experts_bias:**T**
*in* fc2_experts_weights:**T1**
*in* fc2_scales:**T2**
*in* fc2_experts_bias:**T**
*in* fc3_experts_weights:**T1**
*in* fc3_scales:**T2**
*in* fc3_experts_bias:**T**
*in* fc1_zero_points:**T1**
*in* fc2_zero_points:**T1**
*in* fc3_zero_points:**T1**
*in* router_weights:**T**
*out* output:**T**|1+|**T** = tensor(bfloat16), tensor(float16)
**T1** = tensor(uint8)
**T2** = tensor(bfloat16), tensor(float16)| |QOrderedAttention|*in* input:**Q**
*in* scale_input:**S**
*in* scale_Q_gemm:**S**
*in* scale_K_gemm:**S**
*in* scale_V_gemm:**S**
*in* Q_weight:**Q**
*in* K_weight:**Q**
*in* V_weight:**Q**
*in* scale_Q_weight:**S**
*in* scale_K_weight:**S**
*in* scale_V_weight:**S**
*in* Q_bias:**S**
*in* K_bias:**S**
*in* V_bias:**S**
*in* scale_QKT_gemm:**S**
*in* scale_QKT_softmax:**S**
*in* scale_values_gemm:**S**
*in* mask_index:**G**
*in* past:**Q**
*in* attention_bias:**S**
*out* output:**Q**|1+|**G** = tensor(int32)
**Q** = tensor(int8)
**S** = tensor(float)| |QOrderedGelu|*in* X:**Q**
*in* scale_X:**S**
*in* scale_Y:**S**
*out* Y:**Q**|1+|**Q** = tensor(int8)
**S** = tensor(float)| |QOrderedLayerNormalization|*in* X:**Q**
*in* scale_X:**S**
*in* scale:**F**
*in* B:**F**
*in* scale_Y:**S**
*out* Y:**Q**|1+|**F** = tensor(float), tensor(float16)
**Q** = tensor(int8)
**S** = tensor(float)| @@ -943,7 +1110,7 @@ Do not modify directly.* |QOrderedMatMul|*in* A:**Q**
*in* scale_A:**S**
*in* B:**Q**
*in* scale_B:**S**
*in* scale_Y:**S**
*in* bias:**S**
*in* C:**Q**
*in* scale_C:**S**
*out* Y:**Q**|1+|**Q** = tensor(int8)
**S** = tensor(float)| |QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**|1+|**T1** = tensor(float16)
**T2** = tensor(int8), tensor(uint8)| |QuantizeWithOrder|*in* input:**F**
*in* scale_input:**S**
*out* output:**Q**|1+|**F** = tensor(float), tensor(float16)
**Q** = tensor(int8)
**S** = tensor(float)| -|QuickGelu|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(double), tensor(float), tensor(float16)| +|QuickGelu|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |RelativePositionBias|*in* bias_table:**T**
*in* query_length:**U**
*in* key_length:**U**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| |RemovePadding|*in* input:**T**
*in* sequence_token_count:**M**
*out* output:**T**
*out* token_offset:**M**
*out* cumulated_seq_len:**M**
*out* max_seq_len:**M**|1+|**T** = tensor(float), tensor(float16)| |RestorePadding|*in* input:**T**
*in* token_offset:**M**
*out* output:**T**|1+|**T** = tensor(float), tensor(float16)| @@ -951,8 +1118,8 @@ Do not modify directly.* |RotaryEmbedding|*in* input:**T**
*in* position_ids:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**|1+|**M** = tensor(int64)
**T** = tensor(bfloat16), tensor(float), tensor(float16)| |Sampling|*in* input_ids:**I**
*in* max_length:**I**
*in* min_length:**I**
*in* repetition_penalty:**T**
*in* vocab_mask:**I**
*in* prefix_vocab_mask:**I**
*in* attention_mask:**I**
*in* presence_mask:**I**
*in* seed:**I**
*out* sequences:**I**
*out* filtered_logits:**T**|1+|**T** = tensor(float), tensor(float16)| |SkipGroupNorm|*in* X:**T**
*in* gamma:**M**
*in* beta:**M**
*in* skip:**T**
*in* bias:**T**
*out* Y:**T**
*out* S:**T**|1+|**T** = tensor(float), tensor(float16)| -|SkipLayerNormalization|*in* input:**T**
*in* skip:**T**
*in* gamma:**T**
*in* beta:**T**
*in* bias:**T**
*out* output:**T**
*out* mean:**U**
*out* inv_std_var:**U**
*out* input_skip_bias_sum:**T**|1+|**T** = tensor(float), tensor(float16)| -|SkipSimplifiedLayerNormalization|*in* input:**T**
*in* skip:**T**
*in* gamma:**T**
*in* bias:**T**
*out* output:**T**
*out* mean:**U**
*out* inv_std_var:**U**
*out* input_skip_bias_sum:**T**|1+|**T** = tensor(float), tensor(float16)| +|SkipLayerNormalization|*in* input:**T**
*in* skip:**T**
*in* gamma:**T**
*in* beta:**T**
*in* bias:**T**
*out* output:**T**
*out* mean:**U**
*out* inv_std_var:**U**
*out* input_skip_bias_sum:**T**|1+|**T** = tensor(bfloat16), tensor(float), tensor(float16)| +|SkipSimplifiedLayerNormalization|*in* input:**T**
*in* skip:**T**
*in* gamma:**T**
*in* bias:**T**
*out* output:**T**
*out* mean:**U**
*out* inv_std_var:**U**
*out* input_skip_bias_sum:**T**|1+|**T** = tensor(bfloat16), tensor(float), tensor(float16)| |SparseAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* block_row_indices:**M**
*in* block_col_indices:**M**
*in* total_sequence_length:**M**
*in* key_total_sequence_lengths:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(bfloat16), tensor(float16)| |TransposeMatMul|*in* A:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(bfloat16), tensor(double), tensor(float), tensor(float16)| |Trilu|*in* X:**T**
*in* k:**tensor(int64)**
*out* Y:**T**|1+|**T** = tensor(bfloat16), tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| @@ -961,23 +1128,31 @@ Do not modify directly.* | | | | |**Operator Domain:** *com.ms.internal.nhwc*|||| -|AveragePool|*in* X:**T**
*out* Y:**T**|11+|**T** = tensor(float), tensor(float16)| +|AveragePool|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(float), tensor(float16)| +|||[19, 21]|**T** = tensor(float), tensor(float16)| +|||[11, 18]|**T** = tensor(float), tensor(float16)| |||10|**T** = tensor(float), tensor(float16)| |||[7, 9]|**T** = tensor(float), tensor(float16)| |BatchNormalization|*in* X:**T**
*in* scale:**T**
*in* B:**T**
*in* input_mean:**U**
*in* input_var:**U**
*out* Y:**T**
*out* running_mean:**U**
*out* running_var:**U**

or

*in* X:**T**
*in* scale:**T**
*in* B:**T**
*in* mean:**T**
*in* var:**T**
*out* Y:**T**
*out* mean:**T**
*out* var:**T**
*out* saved_mean:**T**
*out* saved_var:**T**

or

*in* X:**T**
*in* scale:**T1**
*in* B:**T1**
*in* input_mean:**T2**
*in* input_var:**T2**
*out* Y:**T**
*out* running_mean:**T2**
*out* running_var:**T2**|15+|**T** = tensor(double), tensor(float), tensor(float16)
**T1** = tensor(double), tensor(float), tensor(float16)
**T2** = tensor(double), tensor(float), tensor(float16)| |||14|**T** = tensor(double), tensor(float), tensor(float16)
**U** = tensor(double), tensor(float), tensor(float16)| |||[9, 13]|**T** = tensor(double), tensor(float), tensor(float16)| |||[7, 8]|**T** = tensor(double), tensor(float), tensor(float16)| -|Conv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|11+|**T** = tensor(float), tensor(float16)| +|Conv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|22+|**T** = tensor(float), tensor(float16)| +|||[11, 21]|**T** = tensor(float), tensor(float16)| |||[1, 10]|**T** = tensor(float), tensor(float16)| -|ConvTranspose|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|11+|**T** = tensor(float), tensor(float16)| +|ConvTranspose|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|22+|**T** = tensor(float), tensor(float16)| +|||[11, 21]|**T** = tensor(float), tensor(float16)| |||[1, 10]|**T** = tensor(float), tensor(float16)| |DepthToSpace|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16)| |||[11, 12]|**T** = tensor(double), tensor(float), tensor(float16)| |||[1, 10]|**T** = tensor(double), tensor(float), tensor(float16)| -|GlobalAveragePool|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| -|GlobalMaxPool|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| -|GridSample|*in* X:**T1**
*in* grid:**T2**
*out* Y:**T1**|16+|**T1** = tensor(float)
**T2** = tensor(float)| +|GlobalAveragePool|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(float), tensor(float16)| +|||[1, 21]|**T** = tensor(float), tensor(float16)| +|GlobalMaxPool|*in* X:**T**
*out* Y:**T**|22+|**T** = tensor(float), tensor(float16)| +|||[1, 21]|**T** = tensor(float), tensor(float16)| +|GridSample|*in* X:**T1**
*in* grid:**T2**
*out* Y:**T1**|22+|**T1** = tensor(float)
**T2** = tensor(float)| +|||[20, 21]|**T1** = tensor(float)
**T2** = tensor(float)| +|||[16, 19]|**T1** = tensor(float)
**T2** = tensor(float)| |LRN|*in* X:**T**
*out* Y:**T**|13+|**T** = tensor(double), tensor(float), tensor(float16)| |||[1, 12]|**T** = tensor(double), tensor(float), tensor(float16)| |MaxPool|*in* X:**T**
*out* Y:**T**

or

*in* X:**T**
*out* Y:**T**
*out* Indices:**I**|12+|**I** = tensor(int64)
**T** = tensor(float), tensor(float16), tensor(int8), tensor(uint8)| @@ -1069,7 +1244,7 @@ Do not modify directly.* |DepthToSpace|*in* input:**T**
*out* output:**T**|13+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||11+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| |||1+|**T** = tensor(bool), tensor(double), tensor(float), tensor(float16), tensor(int16), tensor(int32), tensor(int64), tensor(int8), tensor(uint16), tensor(uint32), tensor(uint64), tensor(uint8)| -|DequantizeLinear|*in* x:**T**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T**
*out* y:**tensor(float)**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**|21+|**T1** = tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)| +|DequantizeLinear|*in* x:**T**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T**
*out* y:**tensor(float)**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T2**

or

*in* x:**T1**
*in* x_scale:**T2**
*in* x_zero_point:**T1**
*out* y:**T3**|21+|**T1** = tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)
**T2** = tensor(float), tensor(float16)| |||19+|**T1** = tensor(int32), tensor(int8), tensor(uint8)
**T2** = tensor(float), tensor(float16)| |||13+|**T** = tensor(int32), tensor(int8), tensor(uint8)| |||10+|**T** = tensor(int32), tensor(int8), tensor(uint8)| @@ -1228,7 +1403,7 @@ Do not modify directly.* |QLinearConv|*in* x:**T1**
*in* x_scale:**tensor(float)**
*in* x_zero_point:**T1**
*in* w:**T2**
*in* w_scale:**tensor(float)**
*in* w_zero_point:**T2**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T3**
*in* B:**T4**
*out* y:**T3**|10+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(int8), tensor(uint8)
**T4** = tensor(int32)| |QLinearMatMul|*in* a:**T1**
*in* a_scale:**TS**
*in* a_zero_point:**T1**
*in* b:**T2**
*in* b_scale:**TS**
*in* b_zero_point:**T2**
*in* y_scale:**TS**
*in* y_zero_point:**T3**
*out* y:**T3**

or

*in* a:**T1**
*in* a_scale:**tensor(float)**
*in* a_zero_point:**T1**
*in* b:**T2**
*in* b_scale:**tensor(float)**
*in* b_zero_point:**T2**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T3**
*out* y:**T3**|21+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(int8), tensor(uint8)| |||10+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(int8), tensor(uint8)| -|QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**

or

*in* x:**T1**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T2**
*out* y:**T2**|21+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)| +|QuantizeLinear|*in* x:**T1**
*in* y_scale:**T1**
*in* y_zero_point:**T2**
*out* y:**T2**

or

*in* x:**T1**
*in* y_scale:**T2**
*in* y_zero_point:**T3**
*out* y:**T3**

or

*in* x:**T1**
*in* y_scale:**tensor(float)**
*in* y_zero_point:**T2**
*out* y:**T2**|21+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(int4), tensor(int8), tensor(uint4), tensor(uint8)| |||19+|**T1** = tensor(float), tensor(float16), tensor(int32)
**T2** = tensor(int8), tensor(uint8)| |||13+|**T1** = tensor(float), tensor(int32)
**T2** = tensor(int8), tensor(uint8)| |||10+|**T1** = tensor(float), tensor(int32)
**T2** = tensor(int8), tensor(uint8)| @@ -1399,10 +1574,10 @@ Do not modify directly.* |FusedMatMulActivation|*in* A:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |Gelu|*in* X:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |GroupNorm|*in* X:**T**
*in* gamma:**M**
*in* beta:**M**
*out* Y:**T**|1+|**M** = tensor(float), tensor(float16)
**T** = tensor(float), tensor(float16)| -|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| +|GroupQueryAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* past_key:**T_CACHE**
*in* past_value:**T_CACHE**
*in* seqlens_k:**M**
*in* total_sequence_length:**M**
*in* cos_cache:**T**
*in* sin_cache:**T**
*in* position_ids:**tensor(int64)**
*in* attention_bias:**T**
*in* head_sink:**T**
*in* k_scale:**T_KV_SCALE**
*in* v_scale:**T_KV_SCALE**
*out* output:**T**
*out* present_key:**T_CACHE**
*out* present_value:**T_CACHE**
*out* output_qk:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |MatMulIntegerToFloat|*in* A:**T1**
*in* B:**T2**
*in* a_scale:**T3**
*in* b_scale:**T3**
*in* a_zero_point:**T1**
*in* b_zero_point:**T2**
*in* bias:**T3**
*out* Y:**T3**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float), tensor(float16)| |MatMulNBits|*in* A:**T1**
*in* B:**T2**
*in* scales:**T1**
*in* zero_points:**T3**
*in* g_idx:**T4**
*in* bias:**T1**
*out* Y:**T1**|1+|**T1** = tensor(float), tensor(float16)
**T2** = tensor(uint8)| -|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| +|MultiHeadAttention|*in* query:**T**
*in* key:**T**
*in* value:**T**
*in* bias:**T**
*in* key_padding_mask:**M**
*in* attention_bias:**T**
*in* past_key:**T**
*in* past_value:**T**
*in* past_sequence_length:**M**
*in* cache_indirection:**M**
*out* output:**T**
*out* present_key:**T**
*out* present_value:**T**
*out* qk:**QK**|1+|**M** = tensor(int32)
**T** = tensor(float), tensor(float16)| |NhwcConv|*in* X:**T**
*in* W:**T**
*in* B:**T**
*out* Y:**T**|1+|**T** = tensor(float), tensor(float16)| |QAttention|*in* input:**T1**
*in* weight:**T2**
*in* bias:**T3**
*in* input_scale:**T3**
*in* weight_scale:**T3**
*in* mask_index:**T4**
*in* input_zero_point:**T1**
*in* weight_zero_point:**T2**
*in* past:**T3**
*out* output:**T3**
*out* present:**T3**|1+|**T1** = tensor(int8), tensor(uint8)
**T2** = tensor(int8), tensor(uint8)
**T3** = tensor(float), tensor(float16)
**T4** = tensor(int32)| |QLinearAdd|*in* A:**T**
*in* A_scale:**tensor(float)**
*in* A_zero_point:**T**
*in* B:**T**
*in* B_scale:**tensor(float)**
*in* B_zero_point:**T**
*in* C_scale:**tensor(float)**
*in* C_zero_point:**T**
*out* C:**T**|1+|**T** = tensor(int8), tensor(uint8)| diff --git a/docs/Optimizer_Layering_Annotations.md b/docs/Optimizer_Layering_Annotations.md new file mode 100644 index 0000000000000..a268bd8fbe84f --- /dev/null +++ b/docs/Optimizer_Layering_Annotations.md @@ -0,0 +1,130 @@ +# Optimizer Layering Annotations + +## Overview + +Layering annotations are per-node metadata strings that guide graph partitioning by indicating which execution provider (EP) layer a node belongs to. They are loaded from the ONNX model's `NodeProto` metadata (key `"layer_ann"`) and consumed during the partitioning phase to influence EP assignment. + +## Execution Pipeline + +Graph optimizers run in ordered levels: + +``` +Level 0 (Basic) ─► Level 1 (Extended) ─► Partitioning ─► Level 2+ (Layout, etc.) +``` + +1. **Level 0 and Level 1** optimizers run **before** partitioning. At this point, layering annotations are present on nodes and must be preserved through any graph transformations. +2. **Partitioning** reads the annotations to assign nodes to execution providers. +3. After partitioning, `Graph::RemoveAllLayeringAnnotations()` clears all annotations. +4. **Level 2, 3, and 4** optimizers run **after** annotations have been cleared. They do not need to handle annotations. + +**Key rule: Only Level 1 (and Level 0) optimizers need to propagate layering annotations.** + +## Why Propagation Matters + +When an optimizer replaces, fuses, or decomposes nodes, the original annotated node is removed and new nodes are created. If the new nodes do not carry the original annotation, partitioning loses the assignment hint for that subgraph, potentially causing incorrect EP placement. + +## How to Propagate Annotations + +### Preferred: Use the `AddNode` Overload with `annotation_source` + +`Graph::AddNode` provides overloads that accept a `const Node& annotation_source` parameter. The new node automatically inherits the layering annotation from the source node. + +```cpp +// Instead of: +Node& new_node = graph.AddNode(name, op_type, description, inputs, outputs); +// Missing annotation propagation! + +// Use: +Node& new_node = graph.AddNode(name, op_type, description, inputs, outputs, + original_node); // annotation_source +``` + +All standard `AddNode` signatures have a corresponding `annotation_source` variant: + +```cpp +// With const NodeAttributes* +Node& AddNode(name, op_type, description, + gsl::span inputs, + gsl::span outputs, + const Node& annotation_source, + const NodeAttributes* attributes = nullptr, + const std::string& domain = kOnnxDomain); + +// With NodeAttributes&& +Node& AddNode(name, op_type, description, + gsl::span inputs, + gsl::span outputs, + const Node& annotation_source, + NodeAttributes&& attributes, + const std::string& domain = kOnnxDomain); + +// initializer_list variants also available +``` + +### Legacy: `DuplicateNodeAnnotation` + +The utility function `optimizer_utils::DuplicateNodeAnnotation(src, dst)` copies annotations between existing nodes. This is still used when the annotation source is conditional (e.g., when the source node pointer may be null). Prefer the `AddNode` overload for unconditional propagation. + +### Automatic Propagation + +`Graph::AddNode(const Node& other)` — the copy overload used for duplicating nodes — automatically copies annotations. No additional action is needed when duplicating a node via this overload. + +## Post-Partitioning: Propagating EP Assignments + +Although Level 2+ optimizers do not deal with layering annotations directly (they have been cleared), they must still propagate **execution provider (EP) assignments**. EP assignments are the downstream result of the annotation-driven partitioning step. After partitioning, each node carries an EP assignment (e.g., `CUDAExecutionProvider`, `CPUExecutionProvider`) that determines where the node's kernel runs. + +When a Level 2+ optimizer creates new nodes that replace or derive from existing ones, it must copy the EP assignment from the source node: + +```cpp +Node& new_node = graph.AddNode(name, op_type, description, inputs, outputs); +new_node.SetExecutionProviderType(original_node.GetExecutionProviderType()); +``` + +Failing to propagate the EP assignment causes the new node to fall back to the default provider (typically CPU), silently breaking the intended placement and potentially degrading performance or correctness. This requirement predates the layering annotation feature and applies to all optimizers that run after partitioning. + +> **Note:** The `AddNode` overload with `annotation_source` propagates both the layering annotation *and* nothing else — EP assignment is still set separately. Layering annotations and EP assignments serve different stages of the pipeline and are managed independently. + +## When You Do NOT Need to Propagate Annotations + +- **Level 2+ optimizers** — annotations have already been consumed and cleared (but EP assignments must still be propagated, see above). +- **Training optimizers** — training runs after partitioning. +- **Optimizers that only remove nodes** (e.g., identity elimination) — no new nodes are created. +- **Optimizers that modify nodes in-place** — the annotation remains on the existing node. + +## Examples + +### Fusion (replacing multiple nodes with one) + +```cpp +// GeluFusion: fusing Div + Erf + Add + Mul + Mul into a single Gelu +Node& gelu_node = graph.AddNode( + graph.GenerateNodeName("Gelu"), + "Gelu", "fused Gelu subgraphs", + {gelu_input}, {gelu_output}, + div_node); // propagate annotation from the root matched node +``` + +### Decomposition (replacing one node with many) + +```cpp +// STFT decomposition: each new node inherits from the original STFT node +auto [reshape_node, reshape_out] = AddNode(graph, "Reshape", ep, inputs, &stft); +auto [conv_node, conv_out] = AddNode(graph, "Conv", ep, conv_inputs, &stft); +auto [concat_node, concat_out] = AddNode(graph, "Concat", ep, concat_inputs, &stft); +``` + +### Conditional source (use DuplicateNodeAnnotation) + +```cpp +Node& q_node = graph.AddNode(...); +if (src_node) { + optimizer_utils::DuplicateNodeAnnotation(*src_node, q_node); +} +``` + +## Checklist for New Level 1 Optimizers + +1. Identify the "source" node whose annotation should propagate (typically the root of the matched pattern). +2. For every `graph.AddNode(...)` call that creates a replacement node, use the `annotation_source` overload. +3. If the source is conditional (may be null), use `optimizer_utils::DuplicateNodeAnnotation` after the `AddNode` call. +4. Test with an annotated model to verify annotations survive the transformation. diff --git a/docs/Versioning.md b/docs/Versioning.md index 683030e928623..9e3984db5ba89 100644 --- a/docs/Versioning.md +++ b/docs/Versioning.md @@ -11,6 +11,73 @@ The version number of the current stable release can be found ## Release cadence See [Release Management](ReleaseManagement.md) +## Updating the Version for a Release + +When preparing a release, follow these steps to update the version number across the codebase. This applies both when creating an initial release branch (updating `main`) and when preparing patch releases on release branches: + +### Prerequisites +- Node.js (check [js/.nvmrc](../js/.nvmrc) for the required version) +- npm (comes with Node.js) +- Python 3 + +Verify your setup: +```bash +node --version # Should match the version in js/.nvmrc +npm --version # Should be v8.0 or newer +``` + +### Steps + +1. **Update the VERSION_NUMBER file** + + Edit [VERSION_NUMBER](../VERSION_NUMBER) in the repository root to reflect the new version (e.g., `1.23.3`). + +2. **Run the version update script** + + From the repository root, run: + ```bash + python tools/python/update_version.py + ``` + + This script automatically updates version numbers in: + - `docs/Versioning.md` - Adds a new row to the version table + - `docs/python/README.rst` - Adds release notes entry + - `onnxruntime/__init__.py` - Python package version + - `js/` packages - All NPM package versions and lock files + +3. **Update the C API static_assert (Manual Step)** + + The script does **not** update the version check in the C API. You must manually update the `static_assert` in [onnxruntime/core/session/onnxruntime_c_api.cc](../onnxruntime/core/session/onnxruntime_c_api.cc). + + Search for `static_assert(std::string_view(ORT_VERSION)` and update the version string: + ```cpp + static_assert(std::string_view(ORT_VERSION) == "X.Y.Z", + "ORT_Version change detected, please follow below steps to ensure OrtApi is updated properly"); + ``` + + Replace `X.Y.Z` with your new version number. The comments following this assert explain additional steps if new APIs were added to this release. + +4. **Update the C API header `ORT_API_VERSION` value (Manual Step)** + + The script does **not** update the value of `ORT_API_VERSION` in [include/onnxruntime/core/session/onnxruntime_c_api.h](../include/onnxruntime/core/session/onnxruntime_c_api.h). + + The value should be set to the second component of the version string. E.g., `26` for version `1.26.0`. + +5. **Review all changes** + + Review all modified files. Verify: + - Version numbers are correct in all updated files + - The release notes URL format is correct (e.g., `https://github.com/Microsoft/onnxruntime/releases/tag/vX.Y.Z`) + +6. **Commit and create PR** + + Commit all changes and create a PR targeting `main` or a release branch as appropriate. + +### Notes + +- The version table in this file and the ONNX opset compatibility information on [onnxruntime.ai](https://onnxruntime.ai/docs/reference/compatibility.html#onnx-opset-support) are the canonical sources for version compatibility information. +- For ONNX version/opset/IR reference numbers, see the [ONNX Versioning documentation](https://github.com/onnx/onnx/blob/main/docs/Versioning.md#released-versions). + # Compatibility ## Backwards compatibility diff --git a/docs/annotated_partitioning/PartitioningWithAnnotationsAndMemoryConstraints.md b/docs/annotated_partitioning/PartitioningWithAnnotationsAndMemoryConstraints.md new file mode 100644 index 0000000000000..1131c5cf7dacd --- /dev/null +++ b/docs/annotated_partitioning/PartitioningWithAnnotationsAndMemoryConstraints.md @@ -0,0 +1,308 @@ +# Graph Partitioning with Annotations and Memory Constraints + +ONNX Runtime automatically partitions a model graph across the execution providers (EPs) registered with a session. This page describes the advanced partitioning features introduced for controlling how nodes are assigned to devices and how GPU memory consumption is managed during partitioning. + +## Overview + +Large models may exceed the memory capacity of a single accelerator (e.g., a CUDA GPU). These features allow you to: +1. Annotate model layers so that specific parts of the model are directed to specific devices (CPU, GPU, NPU). +2. Collect per-node memory statistics during a profiling run. +3. Set a memory budget for an EP so that ONNX Runtime only places nodes on the accelerator until the budget is exhausted; remaining nodes are then eligible for assignment by the subsequent EPs in the session's provider list (often CPU, but not necessarily). + +Together, these form a two-phase workflow: profile the model once to collect memory data, then partition it in production using that data and a memory limit. + +## Layer Assignment Annotations + +### Concept + +Each node in an ONNX model can carry a metadata property called `layer_ann` (layering annotation). This is a free-form string that identifies which logical layer or group the node belongs to. At session creation time, you provide a configuration that maps annotation patterns to target devices. ONNX Runtime then uses these mappings to pre-assign nodes to the corresponding EPs before the normal capability-based partitioning runs. + +### Annotating the Model + +Annotations are stored in each ONNX `NodeProto`'s `metadata_props` field with the key `layer_ann`. You can add them manually using the ONNX Python API: + +```python +import onnx +model = onnx.load("model.onnx") +for node in model.graph.node: + # Assign a layer annotation based on your own logic + entry = next((prop for prop in node.metadata_props if prop.key == "layer_ann"), None) + if entry is None: + entry = node.metadata_props.add() + entry.key = "layer_ann" + entry.value = "encoder_layer_0" # your annotation string + +onnx.save(model, "model_annotated.onnx") +``` + +### Annotating with Olive + +Olive provides built-in support for adding layer annotations during ONNX conversion via the `CaptureLayerAnnotations` pass (added in [PR #2361](https://github.com/microsoft/Olive/pull/2361)). You supply a `layer_annotations` dictionary where each **key** is the annotation string to write into `layer_ann`, and each **value** is a list of node-name substrings. During ONNX export, every node whose name contains one of the substrings receives the corresponding `layer_ann` metadata property. If multiple substrings match, the first one in iteration order wins. + +Many exported transformer models use consistent node naming patterns. For example, node names often include recurring substrings such as `embed_tokens`, `self_attn`, `mlp`, or `norm`. Because `CaptureLayerAnnotations` matches node-name substrings, these patterns can be used to group related nodes into logical layers and write the corresponding `layer_ann` values during export. Adjust the substrings to match the naming conventions in your own model. + +#### Step 1 — Create the workflow config file + +Save the following as `annotate_model.json`: + +```json +{ + "input_model": { + "type": "HfModel", + "model_path": "microsoft/Phi-3.5-mini-instruct" + }, + "passes": { + "capture_annotations": { + "type": "CaptureLayerAnnotations", + "layer_annotations": { + "embedding_layer": ["embed_tokens"], + "attention_layer": ["self_attn", "q_proj", "k_proj", "v_proj", "o_proj"], + "mlp_layer": ["mlp", "gate_proj", "up_proj", "down_proj"], + "norm_layer": ["norm", "layernorm"] + } + }, + "conversion": { + "type": "OnnxConversion", + "target_opset": 16, + "save_as_external_data": true, + "all_tensors_to_one_file": true + } + }, + "log_severity_level": 1, + "output_dir": "models/annotated_phi3" +} +``` + +The `layer_annotations` dictionary maps annotation names to node-name substring patterns: +- Any node whose name contains `"embed_tokens"` → annotated as `"embedding_layer"` +- Any node whose name contains `"self_attn"`, `"q_proj"`, etc. → annotated as `"attention_layer"` +- And so on for `"mlp_layer"` and `"norm_layer"`. + +You can also use `ModelBuilder` instead of `OnnxConversion` — both paths apply the annotations automatically: + +```json + "conversion": { + "type": "ModelBuilder", + "precision": "int4" + } +``` + +#### Step 2 — Run the workflow + +```bash +pip install 'olive-ai[auto-opt]' +olive run --config annotate_model.json +``` + +This will: +1. Download the model from Hugging Face. +2. Store the `layer_annotations` mapping inside `model_attributes` (via `CaptureLayerAnnotations`). +3. Convert to ONNX and stamp every matching node with `metadata_props["layer_ann"]` set to the corresponding annotation name. +4. Write the annotated ONNX model to `models/annotated_phi3/`. + +#### Verifying the annotations + +You can verify that the annotations were applied: + +```python +import onnx + +model = onnx.load("models/annotated_phi3/model.onnx", load_external_data=False) +for node in model.graph.node: + for prop in node.metadata_props: + if prop.key == "layer_ann": + print(f"{node.name}: {prop.value}") +``` + +The annotated model is now ready for use with the ORT session options described below. + +### Configuring Layer Assignment at Runtime + +Use the session option `session.layer_assignment_settings` to tell ONNX Runtime how to map annotations to devices. + +``` +device1(annotation1, annotation2, ...); device2(=annotation3, annotation4, ...) +``` + +- `device`: a recognized device designator, matched against the execution providers registered in the session. The supported designators are: + +| Device Designator | Meaning | Examples of EPs That May Bind | +|:------------------|:--------|:-----------------------------| +| `cpu` | Any CPU device | CPUExecutionProvider | +| `gpu` | Anything discovered and designated as `OrtHardwareDeviceType_GPU` | CUDA EP, ROCm EP, DirectML EP running on discrete or integrated GPUs | +| `cuda` | NVIDIA CUDA GPU. A device that is `OrtHardwareDeviceType_GPU` and NVIDIA is a vendor. Same as `gpu:nvidia`. | CUDAExecutionProvider | +| `dml` | DirectX-compatible GPU | DMLExecutionProvider | +| `npu` | Neural processing unit | Qualcomm QNN EP, Intel NPU EP | +| `fpga` | FPGA-backed accelerators | Custom plugin EPs | +| `accelerator` | Catch-all for any non-CPU device | Any vendor EP | +| `gpu:` | Vendor specialization | `gpu:nvidia`, `gpu:amd`, `gpu:intel` | +| `gpu:` | Specific device index | GPU 0, GPU 1 | + +- `annotation`: string to match against the `layer_ann` value on each node. +- `=` prefix: denotes an exact match. Without `=`, the annotation is treated as a prefix match (any node whose `layer_ann` starts with the string will match). +- Prefix rules have higher priority than exact-match rules. Within the same match type, priority is left-to-right. +- Multiple device rules are separated by `;`. + +```python +import onnxruntime as ort + +opts = ort.SessionOptions() + +# Nodes annotated with layer_ann starting with "encoder" go to GPU, +# nodes with exact annotation "final_output" go to CPU. +opts.add_session_config_entry( + "session.layer_assignment_settings", + "gpu(encoder); cpu(=final_output)" +) + +session = ort.InferenceSession("model_annotated.onnx", opts, + providers=["CUDAExecutionProvider", "CPUExecutionProvider"]) +``` + +#### Targeting a Specific GPU + +On a machine with multiple GPUs, use `gpu:` to direct annotations to a particular device: + +```python +opts.add_session_config_entry( + "session.layer_assignment_settings", + "gpu:1(encoder, decoder); cpu(=postprocess)" +) +``` + +> **Note:** ONNX Runtime currently allows only one instance of a given EP type per session, so you cannot split annotations across multiple GPUs in a single session. The `gpu:` designator selects *which* GPU the single registered EP targets. + +Nodes that do not match any rule fall through to the normal EP capability-based assignment. + +> **Unmatched device designators:** If a device designator in the settings does not match any EP registered in the session, ONNX Runtime logs a warning and skips that rule. Nodes covered by the skipped rule are not pre-assigned and fall through to the normal capability-based partitioning. + +> **Note — Annotations vs. actual placement:** An annotation expresses a *preference*, not a guarantee. If the target EP does not have a registered kernel for a node (for example, a particular data-type / opset-version combination is not implemented in the CUDA EP), that node will not be placed on the requested device. Instead it falls through to the next EP in the provider list that can handle it. + +## Capacity-Aware Partitioning (implemented for CUDA) + +When running models on a CUDA GPU with limited memory, you can set a memory budget so ONNX Runtime stops assigning nodes to the CUDA EP once the estimated memory consumption reaches the limit. Nodes are considered in topological order and assignment halts at the first node that would exceed the budget — ONNX Runtime does not search ahead for smaller nodes that might still fit. Remaining nodes are then eligible for assignment by the subsequent EPs in the session's provider list (often CPU, but not necessarily). + +### Step 1: Collect Memory Statistics (Profiling Run) + +Run the model once with memory statistics collection enabled. This records per-node allocation data to a CSV file. + +```python +import onnxruntime as ort +import numpy as np + +opts = ort.SessionOptions() +# Disable memory patterns for accurate per-node measurement +opts.enable_mem_pattern = False +opts.add_session_config_entry( + "session.collect_node_memory_stats_to_file", + "node_memory_stats.csv" +) + +session = ort.InferenceSession("model.onnx", opts, + providers=["CUDAExecutionProvider", "CPUExecutionProvider"]) + +def make_concrete_shape(shape, default_dim=1): + """ORT input shapes may contain symbolic dims or None (e.g. batch size). + Replace those with a small concrete value for profiling. + + For the most accurate memory statistics, use the largest input shapes + your production workload will encounter. For example, if your service + runs with a maximum batch size of 8, pass default_dim=8 so the profiled + allocations reflect that peak usage.""" + return tuple( + dim if isinstance(dim, int) and dim > 0 else default_dim + for dim in shape + ) + +# Run inference at least once to collect statistics. +# For models with dynamic inputs, prefer real sample inputs or model-appropriate +# concrete shapes instead of relying on the declared ORT input shape directly. +input_data = { + inp.name: np.zeros(make_concrete_shape(inp.shape), dtype=np.float32) + for inp in session.get_inputs() +} +session.run(None, input_data) +``` + +This produces a CSV file with columns: +`#name,input_sizes,initializers_sizes,total_dynamic_sizes,total_temp_allocations` + +In this example, `node_memory_stats.csv` is a relative path. Relative paths are resolved against the model's directory when the model was loaded from a filesystem path. If you provide an absolute path, that path is used as-is. If the model was not loaded from a filesystem path (for example, it was loaded from bytes), the output file is written relative to the current working directory. + +Multiple `session.run()` calls update the stats with the maximum values observed per node. + +> **What if the GPU cannot hold the entire model?** The profiling run itself requires the model to fit in GPU memory because the CUDA EP must execute each node to record its actual allocations. If the model exceeds GPU capacity during profiling, reduce the input dimensions (e.g., use a smaller batch size) so that the run completes. The resulting per-node statistics will still be representative of relative node costs and can be used to set the memory budget for subsequent production sessions. + +### Step 2: Partition with a Memory Budget + +In a subsequent session, provide the memory limit and the stats file to enable capacity-aware partitioning. + +```python +import onnxruntime as ort + +opts = ort.SessionOptions() + +# Format: "memory_limit_in_kb,stats_filename" +# Set a 4 GB limit and use the stats from the profiling run +opts.add_session_config_entry( + "session.resource_cuda_partitioning_settings", + "4194304,node_memory_stats.csv" +) + +session = ort.InferenceSession("model.onnx", opts, + providers=["CUDAExecutionProvider", "CPUExecutionProvider"]) +``` + +ONNX Runtime processes nodes in topological order, accumulating estimated memory. When the cumulative cost exceeds the budget, assignment to the CUDA EP halts immediately — remaining nodes are not considered even if they would individually fit within the budget. Those nodes are eligible for assignment by the subsequent EPs in the session's provider list. + +Because assignment follows topological order, groups of nodes that you would prefer to offload (for example, MoE expert blocks) may appear at arbitrary positions in the graph. If you want specific node groups to have the lowest priority for device placement, combine the memory budget with layer annotations: annotate the nodes you want to offload to CPU explicitly, and let the capacity-aware partitioner handle the rest. + +### Ad-Hoc Mode (No Stats File) + +If you do not have pre-recorded statistics, you can specify only a memory limit. ONNX Runtime will estimate per-node cost from initializer sizes and static output shapes, applying a 1.5x safety multiplier. + +This mode is less accurate than using pre-recorded stats but provides a quick way to constrain GPU memory without a profiling run. + +```python +# Memory limit only, no stats file (note the trailing comma) +opts.add_session_config_entry( + "session.resource_cuda_partitioning_settings", + "4194304," +) +``` + +### Setting Format Summary +The value of `session.resource_cuda_partitioning_settings` is a comma-separated pair: + +| Format | Meaning | +|:------|:-------| +| `,` | Use both memory limit and pre-recorded stats | +| `,` | Memory limit only (ad-hoc estimation) | +| `,` | Stats only (no explicit limit) | +| `,` | Neither (EP attempts auto-detection) | + +The stats file path follows the same resolution rules described above: relative paths are resolved against the model's directory, absolute paths are used as-is. + +## Combining Both Features +Layer annotations and capacity-aware partitioning can be used together. When both are configured: +- Layer annotations provide the initial node-to-device mapping. +- The capacity-aware partitioner enforces the memory budget, potentially overriding assignments that would exceed the GPU memory limit. + +This combination gives you fine-grained control: use annotations to express logical model structure, and let the memory budget act as a safety net. + +```python +opts = ort.SessionOptions() + +opts.add_session_config_entry( + "session.layer_assignment_settings", + "gpu(encoder, decoder); cpu(=postprocess)" +) + +opts.add_session_config_entry( + "session.resource_cuda_partitioning_settings", + "4194304,node_memory_stats.csv" +) + +session = ort.InferenceSession("model_annotated.onnx", opts, + providers=["CUDAExecutionProvider", "CPUExecutionProvider"]) +``` diff --git a/docs/c_cxx/Doxyfile b/docs/c_cxx/Doxyfile index aedb1fdcfee75..fce7ed134ab9b 100644 --- a/docs/c_cxx/Doxyfile +++ b/docs/c_cxx/Doxyfile @@ -945,6 +945,7 @@ WARN_LOGFILE = INPUT = ../../include/onnxruntime/core/session/onnxruntime_c_api.h \ ../../include/onnxruntime/core/session/onnxruntime_cxx_api.h \ + ../../include/onnxruntime/core/session/onnxruntime_ep_c_api.h \ ../../orttraining/orttraining/training_api/include/onnxruntime_training_c_api.h \ ../../orttraining/orttraining/training_api/include/onnxruntime_training_cxx_api.h diff --git a/docs/c_cxx/README.md b/docs/c_cxx/README.md index eabfd289a6ed0..7a631608eeebc 100644 --- a/docs/c_cxx/README.md +++ b/docs/c_cxx/README.md @@ -4,8 +4,6 @@ This directory contains doxygen configuration to generate the C/C++ API docs for The actual generation is performed by a GitHub actions workflow: [publish-c-apidocs.yml](../../.github/workflows/publish-c-apidocs.yml). -The workflow is currently manually triggered, and generates a PR to the gh-pages branch, for publication on https://onnxruntime.ai. - # C/C++ API Documentation Conventions ## Handling API changes across versions diff --git a/docs/cmake_guideline.md b/docs/cmake_guideline.md index e03706476d73f..2ea0d5e0841b3 100644 --- a/docs/cmake_guideline.md +++ b/docs/cmake_guideline.md @@ -144,7 +144,7 @@ Here system means the combination of - CPU Arch: x86_32, x86_64, armv6, armv7, arvm7l, aarch64, … - OS: bare-metal, linux, Windows - Libc: gnu libc/ulibc/musl/… -- ABI: ARM has mutilple ABIs like eabi, eabihf… +- ABI: ARM has multiple ABIs like eabi, eabihf… When "host system" != "target system" (any different in the four dimensions), we call it cross-compiling. For example, when you build a Windows EXE on Linux, or build an ARM program on an x86_64 CPU, you are doing cross-compiling. Then special handling is needed. diff --git a/docs/compile_onnxruntime_xcframework.md b/docs/compile_onnxruntime_xcframework.md new file mode 100644 index 0000000000000..433eb17368af3 --- /dev/null +++ b/docs/compile_onnxruntime_xcframework.md @@ -0,0 +1,69 @@ +# Prepare ONNXRuntime XCFramework for iOS or MacCatalyst +The instructions should be executed on a Mac machine. + +## Step 1: Extract required operators for your network +You have to find out what operators to be included in the ONNXLibrary. +Operators could be extracted via `tools/python/create_reduced_build_config.py` +Let say we have a network (ONNX file) which is stored in `/home/username/models/generator_network.onnx` +You could use the following command and find the configuration file in `/home/username/ops_config/generator_network.ops.config` + +``` +python3 tools/python/create_reduced_build_config.py /home/username/models/generator_network.onnx /home/username/ops_config/generator_network.ops.config +``` + +The generator_network.ops.config looks like this: +``` +# Generated from ONNX model/s: +# - /Users/goodnotesci/goodnotes/GoodNotes-5/Packages/GNHandwritingSynthesis/Tests/GNHandwritingSynthesisTests/Resources/models/generator_network.onnx +ai.onnx;9;Add,Cast,Concat,Constant,ConstantOfShape,Div,Exp,Gather,Gemm,LogSoftmax,MatMul,Mul,Neg,NonZero,ReduceSum,Reshape,Shape,Sigmoid,Slice,Softmax,Softplus,Split,Squeeze,Sub,Tanh,Transpose,Unsqueeze +``` + +`ai.onnx` is the opset domain, and `9` is the opset version. The remainings of the line show the names of the operators. + +You could also put a path to model directory in `create_reduced_build_config.py` and the script will search for all models in the directory. + +You could find our latest [`hws_mobile_package.required_operators.config` here.](https://github.com/GoodNotes/onnxruntime/blob/develop/tools/ci_build/github/apple/hws_mobile_package.required_operators.config) +As you may notice some additional operators come from `com.microsoft` domain, +``` +# internal ops added by optimizers +# Note: LayerNormalization is an internal op even though it is (incorrectly) registered in the ONNX domain. +ai.onnx;1;LayerNormalization +com.microsoft;1;DynamicQuantizeMatMul,FusedConv,FusedGemm,FusedMatMul,Gelu,MatMulIntegerToFloat,NhwcMaxPool,QLinearAdd,QLinearAveragePool,QLinearConv,QLinearGlobalAveragePool,QLinearMul,QLinearSigmoid,QuickGelu + +# NHWC transformer also uses this, so assuming it's valuable enough to include +com.microsoft;1;QLinearLeakyRelu +``` +These operators are discovered when the library is deployed in iOS. It was found that ONNXRuntime will optimize the graph so you should add these custom operators back to `hws_mobile_package.required_operators.config`. + +## Step 2: Compile ONNXRuntime XCFramework +For iOS simulator and iOS devices, we could follow the official tutorial to build the XCFramework. +In particular, you could use `build_ios_framework.py` compiles the library with the following command: +``` +python tools/ci_build/github/apple/build_ios_framework.py --config Release --build_dir /home/username/onnxlibrary/ios_release_v20230327_2320 --include_ops_by_config tools/ci_build/github/apple/hws_mobile_package.required_operators.config --path_to_protoc_exe /usr/local/bin/protoc-3.21.12.0 tools/ci_build/github/apple/default_full_ios_framework_build_settings.json +``` + +MacCatalyst is not supported officially. `build_macabi_framework.py` has been created for our use. +To compile, use the follow command +``` +python tools/ci_build/github/apple/build_macabi_framework.py --config Release --build_dir /home/username/onnxlibrary/macabi_release_v20230327_2320 --include_ops_by_config tools/ci_build/github/apple/hws_mobile_package.required_operators.config --path_to_protoc_exe /usr/local/bin/protoc-3.21.12.0 tools/ci_build/github/apple/default_full_macabi_framework_build_settings.json +``` + +Both of these scripts will invoke `tools/ci_build/build.py`. [This section](https://github.com/GoodNotes/onnxruntime/blob/eeca6fea2b4d02ddc729c7a7cdc39b123d23fbf8/tools/ci_build/build.py#L1221) contains the target platform-specific parameters when executing CMake. + +## Step 3: Use it in a Swift package in GoodNotes +Since we compile the framework for different target separately, we need to merge the iOS xcframework and MacCatlyst xcframework manually at the moment. +Please refer to this [PR#12971](https://github.com/GoodNotes/GoodNotes-5/pull/12971) for the directory structure. +You would also need to combine the `Info.plist` manually. + +At last, you can import `onnxruntime` as a binary target. +``` +targets: [ + .binaryTarget( + name: "onnxruntime", + path: "onnxruntime/onnxruntime.xcframework"), + ] + ``` + + + + diff --git a/docs/contrib_ops/cpu/qmoe.md b/docs/contrib_ops/cpu/qmoe.md new file mode 100644 index 0000000000000..213602746dc32 --- /dev/null +++ b/docs/contrib_ops/cpu/qmoe.md @@ -0,0 +1,286 @@ +# QMoE CPU Implementation Notes + +This document describes the current CPU implementation of the `com.microsoft.QMoE` operator in ONNX Runtime. + +## Scope + +The CPU QMoE kernel is implemented in: + +- `onnxruntime/contrib_ops/cpu/moe/moe_quantization_cpu.h` +- `onnxruntime/contrib_ops/cpu/moe/moe_quantization_cpu.cc` +- `onnxruntime/contrib_ops/cpu/moe/moe_helper.h` + +The operator schema itself is defined in: + +- `onnxruntime/core/graph/contrib_ops/contrib_defs.cc` + +This document focuses on runtime behavior on the CPU Execution Provider, not on the general QMoE schema. + +## High-Level Execution Flow + +At a high level, the CPU kernel executes QMoE in five stages: + +1. Validate input shapes and attributes. +2. Compute top-k expert routing from `router_probs` or `router_weights`. +3. Group routed tokens by expert. +4. Run expert-local FC1 -> activation -> FC2. +5. Scatter and accumulate weighted expert outputs back to the final output tensor. + +The implementation keeps routing and accumulation shared across bit-widths. The main bit-width-specific differences are in how expert weights are prepared and how the FC1/FC2 GEMMs are executed. + +## Supported Data Types and Weight Bit-Widths + +### Activations and scales + +- Activations/output (`T`): `float` or `MLFloat16` +- Scales (`T2`): `float` or `MLFloat16` +- Quantized weights (`T1`): `uint8` + +For CPU, the kernel currently accepts: + +- `expert_weight_bits = 2` +- `expert_weight_bits = 4` +- `expert_weight_bits = 8` + +Internally, most CPU compute is performed in `float`. `MLFloat16` inputs such as activations, router values, scales, and biases are converted to `float` scratch buffers when needed. + +## Supported Quantization Layouts + +The CPU implementation supports both row-wise and block-wise quantization. + +### Row-wise quantization + +- `block_size = 0` +- One scale per output row +- Optional zero points are packed along the row dimension + +Weight tensor shapes: + +- FC1: `(num_experts, fc1_out_features, hidden_size / pack_size)` +- FC2: `(num_experts, hidden_size, inter_size / pack_size)` + +### Block-wise quantization + +- `block_size > 0` +- Quantization is along the K dimension of each GEMM +- One scale per output row and per block + +Weight tensor shapes (same as row-wise — block-wise only changes scales): + +- FC1: `(num_experts, fc1_out_features, hidden_size / pack_size)` +- FC2: `(num_experts, hidden_size, inter_size / pack_size)` + +Scale tensor shapes (ceiling division for partial last blocks): + +- FC1: `(num_experts, fc1_out_features, ceil(hidden_size / block_size))` +- FC2: `(num_experts, hidden_size, ceil(inter_size / block_size))` + +For packed weights: + +- `pack_size = 8 / expert_weight_bits` +- 2-bit stores 4 values per byte +- 4-bit stores 2 values per byte +- 8-bit stores 1 value per byte + +The CPU implementation validates that packed dimensions are compatible with `pack_size`, and also validates that `hidden_size` and inferred `inter_size` divide cleanly where required. + +## Routing + +Routing is shared for all bit-widths. + +For each input token: + +1. The kernel reads one row of `router_probs`. +2. It selects the top-`k` experts. +3. It computes aggregation weights: + - from softmax of `router_probs`, or + - directly from `router_weights` if that optional input is provided +4. It stores `(token, expert, weight)` assignments into per-expert route lists. + +To reduce contention, the routing stage first builds thread-local expert-token maps and merges them afterward. + +## Expert Execution + +After routing, the kernel processes experts independently: + +1. Gather the routed token activations for one expert into `A1` +2. Run FC1 +3. Apply activation +4. Run FC2 +5. Scatter-add weighted results into a thread-local output buffer + +The final output tensor is produced by reducing all thread-local output buffers. + +## FC1/FC2 Execution Paths + +The CPU implementation uses multiple execution paths depending on bit-width, quantization style, and MLAS support. + +### 2-bit path + +The 2-bit path has a dedicated fast path for block-wise quantization using MLAS LUT GEMM. + +#### 2-bit LUT GEMM fast path + +This is used when: + +- `expert_weight_bits == 2` +- quantization is block-wise +- the weight shape satisfies MLAS LUT GEMM constraints + +As of the current MLAS implementation, this effectively requires: + +- non-zero `block_size` +- `block_size` compatible with LUT GEMM +- K divisible by 32 +- N divisible by 128 for the 2-bit kernel + +The CPU kernel: + +1. Detects whether FC1/FC2 can use LUT GEMM. +2. Uses prepacked LUT weights when available. +3. Otherwise packs the current expert's quantized weights, scales, and optional zero points into a thread-local LUT buffer. +4. Calls `MlasLutGemm` for FC1 and/or FC2. + +The LUT-specific helper logic is intentionally isolated from the shared routing and accumulation flow. + +#### 2-bit fallback path + +If LUT GEMM is not available for a particular shape or layout, the kernel falls back to: + +1. dequantize packed weights into `float` +2. run standard `MlasGemm` + +This fallback supports both row-wise and block-wise quantization. + +### 4-bit path + +The 4-bit path supports several modes: + +#### Direct MLAS Q4 GEMM fast path + +When the configuration is compatible, the kernel can use MLAS Q4 GEMM directly. + +This path is used only for symmetric 4-bit weights where the MLAS Q4 layout is supported. + +#### Prepacked transposed fallback + +If direct Q4 GEMM is not used, the kernel can reuse prepacked transposed/unpacked buffers and then run: + +1. dequantize from the prepacked layout +2. `MlasGemm` + +#### General fallback + +Otherwise, the kernel dequantizes directly from the packed ONNX input tensors and runs `MlasGemm`. + +### 8-bit path + +The 8-bit path currently uses the general dequantize-plus-GEMM flow. It shares the same routing, activation, and output accumulation logic as the other paths. + +## PrePack Behavior + +The CPU kernel implements `PrePack()` and `UseSharedPrePackedBuffers()` to reduce repeated setup cost. + +### 2-bit prepack + +When FC1/FC2 weights and scales, plus any zero points, are constant initializers and the block-wise shape is +supported by MLAS LUT GEMM, the kernel pre-packs the weights into MLAS LUT GEMM packed buffers. These packed +buffers are cached and can be reused across sessions through shared prepacked buffers. If scales or zero points are +runtime inputs, execution falls back to packing per expert during `Compute()`. + +### 4-bit prepack + +The kernel pre-packs 4-bit weights into a transposed/unpacked format used by the fallback path. When possible, it also creates a direct MLAS Q4 packed cache for faster execution. + +### 8-bit prepack + +There is no special MLAS packed path today analogous to the 2-bit LUT or 4-bit Q4 paths. + +## Activation Handling + +The CPU QMoE kernel currently supports: + +- `identity` +- `gelu` +- `relu` +- `silu` +- `swiglu` + +For CPU, `SwiGLU` requires `swiglu_fusion = 1`, meaning FC1 output is interpreted as interleaved gate/value data and activation writes directly into the FC2 input buffer. + +## Bias Handling + +Biases are optional for FC1 and FC2. + +- If the fast GEMM path does not apply bias internally, the kernel converts bias to `float` and applies it afterward. +- FC2 bias is added during the final scatter-add stage when it was not already fused into the GEMM path. + +## Zero Points + +Optional zero-point tensors are supported for FC1 and FC2. + +- 2-bit and 4-bit zero points are packed +- block-wise zero points are packed per row and per K-block +- row-wise zero points are packed per row + +The direct 4-bit MLAS Q4 path only supports symmetric weights, so it is not used when zero points are present. + +The 2-bit LUT path supports both symmetric and asymmetric packed inputs as long as the MLAS LUT requirements are satisfied. + +## Threading Model + +The CPU implementation uses the ORT thread pool in several phases: + +- routing +- per-expert token gather +- block dequantization +- activation +- final accumulation + +It avoids global write contention by accumulating expert outputs into thread-local output buffers and reducing them at the end. + +## Current CPU Limitations + +The current CPU QMoE implementation has a few important limitations: + +- FC3 gating path is not implemented on CPU for QMoE +- the 2-bit fast path is limited to MLAS LUT-supported block-wise shapes +- the direct 4-bit MLAS path only applies to supported symmetric layouts +- some paths still dequantize into `float` scratch buffers before GEMM, which is simpler but slower than a fully native low-bit kernel + +## Code Structure Summary + +- `moe_helper::CheckInputs(...)` + - central input validation and shape inference +- `QMoECPU::PrePack(...)` + - builds reusable weight caches +- `QMoECPU::UseSharedPrePackedBuffers(...)` + - restores shared prepacked buffers +- `QMoECPU::Compute(...)` + - shared validation and dispatch into the common execution flow +- `TryRunLutGemm(...)` + - isolates the 2-bit LUT pack-and-run fast path + +## Tests + +Relevant CPU-side tests live in: + +- `onnxruntime/test/contrib_ops/moe_test.cc` +- `onnxruntime/test/python/transformers/test_qmoe_cpu.py` + +These cover: + +- 2-bit and 4-bit CPU execution +- row-wise and block-wise quantization +- validation failures +- non-trivial numeric correctness cases +- the 2-bit LUT-eligible block-wise identity case + +## Notes for Future Work + +Likely future improvements include: + +- more aggressive native low-bit CPU GEMM support beyond the current LUT/Q4 fast paths +- broader prepacking support for additional 2-bit and 8-bit cases +- reducing temporary dequantization buffers on fallback paths +- extending CPU support for FC3 gating if needed diff --git a/docs/cuda_plugin_ep/QUICK_START.md b/docs/cuda_plugin_ep/QUICK_START.md new file mode 100644 index 0000000000000..b55080b028f9d --- /dev/null +++ b/docs/cuda_plugin_ep/QUICK_START.md @@ -0,0 +1,159 @@ +# CUDA Plugin EP Quick Start + +## Build Instructions + +To build ONNX Runtime with the CUDA Plugin Execution Provider instead of the statically linked CUDA EP, use the `--cmake_extra_defines "onnxruntime_BUILD_CUDA_EP_AS_PLUGIN=ON"` flag with the build script. + +Example command to build the CUDA Plugin EP in Windows: +``` +build.bat --cmake_generator "Visual Studio 17 2022" --config Release --build_wheel ^ + --parallel --nvcc_threads 1 --build_shared_lib ^ + --use_cuda --cuda_version "12.8" --cuda_home "C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v12.8" ^ + --cudnn_home "D:\path\to\cudnn-installation-root" ^ + --use_vcpkg --use_binskim_compliant_compile_flags ^ + --cmake_extra_defines "CMAKE_CUDA_ARCHITECTURES=native" ^ + --cmake_extra_defines "onnxruntime_BUILD_CUDA_EP_AS_PLUGIN=ON" +``` + +## Running + +When the plugin is built, it will produce `libonnxruntime_providers_cuda_plugin.so` (or `.dll` on Windows) in the build output directory alongside `libonnxruntime.so`. + +The plugin EP is registered under the name **`CudaPluginExecutionProvider`** and uses the EP Plugin API (`RegisterExecutionProviderLibrary` / `GetEpDevices` / `SessionOptionsAppendExecutionProvider_V2`). It is **not** a drop-in replacement for the in-tree `CUDAExecutionProvider` — you must register the plugin library, enumerate its devices, and add them to the session. + +### C++ API + +Use `Env::RegisterExecutionProviderLibrary` to load the plugin, `Env::GetEpDevices` to discover the CUDA devices it exposes, and `SessionOptions::AppendExecutionProvider_V2` to add the selected device to the session. + +```cpp +#include "onnxruntime_cxx_api.h" + +Ort::Env env(ORT_LOGGING_LEVEL_WARNING, "PluginTest"); + +// 1. Register the plugin library. +env.RegisterExecutionProviderLibrary("CudaPluginExecutionProvider", + ORT_TSTR("libonnxruntime_providers_cuda_plugin.so")); + +// 2. Enumerate available EP devices and pick the CUDA plugin device. +auto ep_devices = env.GetEpDevices(); +std::vector plugin_devices; +for (const auto& dev : ep_devices) { + if (std::string(dev.EpName()) == "CudaPluginExecutionProvider") { + plugin_devices.push_back(dev); + break; // use the first CUDA plugin device + } +} + +// 3. Add the plugin device to session options. +Ort::SessionOptions session_options; +session_options.AppendExecutionProvider_V2(env, plugin_devices, {}); + +Ort::Session session(env, "model.onnx", session_options); +``` + +### Python API + +Use `onnxruntime.register_execution_provider_library` to load the plugin, `onnxruntime.get_ep_devices` to discover devices, and `SessionOptions.add_provider_for_devices` to add the selected device. + +**Device-based approach (recommended):** + +```python +import onnxruntime as ort + +# 1. Register the plugin library. +ort.register_execution_provider_library( + "CudaPluginExecutionProvider", + "libonnxruntime_providers_cuda_plugin.so", +) + +# 2. Enumerate devices and pick the CUDA plugin device. +devices = ort.get_ep_devices() +plugin_device = next(d for d in devices if d.ep_name == "CudaPluginExecutionProvider") + +# 3. Create session with the plugin device. +sess_options = ort.SessionOptions() +sess_options.add_provider_for_devices([plugin_device], {}) + +sess = ort.InferenceSession("model.onnx", sess_options=sess_options) +``` + +**Provider-name approach:** + +You can also pass `CudaPluginExecutionProvider` by name in the `providers` list +(the plugin library must already be registered): + +```python +import onnxruntime as ort + +ort.register_execution_provider_library( + "CudaPluginExecutionProvider", + "libonnxruntime_providers_cuda_plugin.so", +) + +sess = ort.InferenceSession( + "model.onnx", + providers=[ + ("CudaPluginExecutionProvider", {"device_id": "0"}), + "CPUExecutionProvider", + ], +) +``` + +## Running Tests + +The focused validation script for the CUDA Plugin EP is `onnxruntime/test/python/transformers/test_cuda_plugin_ep.py`. + +### Test prerequisites + +- Build ONNX Runtime with `onnxruntime_BUILD_CUDA_EP_AS_PLUGIN=ON`. +- Install the built ONNX Runtime wheel. +- Install Python test dependencies. `test_cuda_plugin_ep.py` uses PyTorch for CPU-side reference computations, so CPU-only PyTorch is sufficient. + +Example dependency install: + +```bash +python -m pip install numpy onnx +python -m pip install torch --index-url https://download.pytorch.org/whl/cpu +``` + +### Point the test to the plugin library + +The test helper tries to auto-detect the plugin library from the installed wheel or a local build tree. If you have multiple builds or want to be explicit, set `ORT_CUDA_PLUGIN_PATH` to the plugin library produced by your build. + +Linux example: + +```bash +export ORT_CUDA_PLUGIN_PATH=/path/to/build/Release/libonnxruntime_providers_cuda_plugin.so +``` + +Windows example: + +```cmd +set ORT_CUDA_PLUGIN_PATH=E:\path\to\build\Release\Release\onnxruntime_providers_cuda_plugin.dll +``` + +### Run the test script + +Run the script from a directory outside the repository checkout to avoid Python module shadowing. + +```bash +cd onnxruntime/test/python/transformers +python test_cuda_plugin_ep.py +``` + +On Windows: + +```cmd +cd /d onnxruntime\test\python\transformers +python test_cuda_plugin_ep.py +``` + +The script validates plugin registration, device enumeration, provider options, operator coverage, and that key nodes are actually assigned to `CudaPluginExecutionProvider`. + + +## Verification +You can generate a parity report comparing the kernels available in the plugin EP versus the statically linked CUDA EP. +```bash +# Check runtime registry parity: +python tools/ci_build/cuda_plugin_parity_report.py --runtime --plugin-ep-lib build/Linux/RelWithDebInfo/libonnxruntime_providers_cuda_plugin.so +``` diff --git a/docs/cuda_plugin_ep/arena_allocator_migration_design.md b/docs/cuda_plugin_ep/arena_allocator_migration_design.md new file mode 100644 index 0000000000000..285aa3e60ed5c --- /dev/null +++ b/docs/cuda_plugin_ep/arena_allocator_migration_design.md @@ -0,0 +1,757 @@ +# CUDA Plugin EP — Arena Allocator Integration Design + +## 1. Problem Statement + +The CUDA plugin EP currently uses raw `cudaMalloc`/`cudaFree` through `CudaDeviceAllocator` (an `OrtAllocator*` wrapper). The in-tree (bridge-based) CUDA EP wraps its allocators in arenas by default: + +| Allocator | In-Tree CUDA EP | Plugin CUDA EP (today) | +|-----------|----------------|----------------------| +| GPU device | `CUDAAllocator` → arena (stream-aware) | `CudaDeviceAllocator` → raw `cudaMalloc`/`cudaFree` | +| GPU device (mempool) | `CudaMempoolArena` (native CUDA mempool) | Not available | +| Pinned (host) | `CUDAPinnedAllocator` → arena (non-stream-aware) | `CudaPinnedAllocator` → raw `cudaHostAlloc`/`cudaFreeHost` | + +This gap means the plugin EP has significantly worse allocation performance for typical workloads. + +--- + +## 2. Reference Implementation: Example Plugin EP Arena + +The ORT test suite contains a complete reference implementation of a plugin-hosted arena in `onnxruntime/test/autoep/library/example_plugin_ep/`: + +| File | Purpose | +|------|---------| +| `ep_arena.h` | `ArenaConfig`, `ArenaImpl` (arena allocator — ~632 lines), `ArenaAllocator` (OrtAllocator wrapper) | +| `ep_arena.cc` | `ArenaImpl` implementation: bins, chunks, region management, stream-aware allocation | +| `ep_allocator.h` | `BaseAllocator` (virtual dtor for `OrtAllocator`), `CustomAllocator` (raw malloc/free device allocator), `AllocatorStats` | +| `ep_factory.cc` | `CreateAllocatorImpl` — creates shared `ArenaAllocator` wrapping `CustomAllocator`; ref-counted lifecycle | +| `ep_stream_support.cc` | `StreamImpl::OnSessionRunEndImpl` — calls `arena->ResetChunksUsingStream()` | + +### 2.1 Key Design Patterns + +**Arena lives inside the plugin.** The arena implementation is self-contained in the plugin library. ORT core sees only an `OrtAllocator*` with `OrtDeviceAllocator` type — it is unaware that the allocator internally manages an arena. This is the intended plugin EP architecture: the EP library owns its allocation strategy. + +**Factory creates a shared arena.** `ExampleEpFactory::CreateAllocatorImpl` creates one `ArenaAllocator` instance on first call and returns the same pointer on subsequent calls, with reference counting: + +```cpp +// ep_factory.cc — CreateAllocatorImpl (simplified) +if (!factory.arena_allocator_) { + AllocatorUniquePtr ep_allocator = std::make_unique(memory_info, factory); + factory.arena_allocator_using_default_settings_ = allocator_options == nullptr; + ArenaAllocator::CreateOrtArenaAllocator(std::move(ep_allocator), allocator_options, + factory.ort_api, factory.default_logger_, + factory.arena_allocator_); +} else { + if (factory.arena_allocator_using_default_settings_ && allocator_options) { + // arena settings may have changed — EP decides how to handle + } +} +++factory.num_arena_users_; +*allocator = factory.arena_allocator_.get(); +``` + +**Arena config via `OrtKeyValuePairs`.** `ArenaConfig::FromKeyValuePairs()` parses standard `arena.*` keys: + +| Key | Type | Default | +|-----|------|---------| +| `arena.extend_strategy` | `"0"` (power of two) or `"1"` (same as requested) | `kNextPowerOfTwo` | +| `arena.initial_chunk_size_bytes` | int | 1 MB | +| `arena.max_dead_bytes_per_chunk` | int | 128 MB | +| `arena.initial_growth_chunk_size_bytes` | int | 2 MB | +| `arena.max_power_of_two_extend_bytes` | int64 | 1 GB | +| `arena.max_mem` | size_t | `SIZE_MAX` | + +**Stream-aware allocation.** `ArenaImpl::AllocOnStream(size, stream)` tracks which chunks are assigned to which stream. `ResetChunksUsingStream(stream_impl)` is called from `OrtSyncStreamImpl::OnSessionRunEnd` to release chunk-to-stream assignments when a session run completes. + +**Read-only allocator bypasses arena.** The factory creates a plain `CustomAllocator` (no arena) for `OrtReadOnlyAllocator` (initializers), since initializer memory doesn't benefit from arena allocation. + +### 2.2 How ORT Core Calls the Factory + +**Path 1: Shared allocators (environment level)** +``` +RegisterExecutionProviderLibrary() + → CreateSharedAllocatorImpl(ep_device, memory_info, OrtDeviceAllocator, nullptr, ...) + → ep_factory->CreateAllocator(factory, &mem_info, /*options=*/ nullptr, &alloc) + → [factory creates ArenaAllocator wrapping raw allocator] + → if alloc->version >= 25 && alloc->Shrink != nullptr: + IArenaImplWrappingOrtAllocator(alloc) // wraps as IArena (see Section 5.4) + else: + IAllocatorImplWrappingOrtAllocator(alloc) + → shared_allocators_.push_back(wrapped) +``` + +**Path 2: Per-session allocators** +``` +SessionState constructor + → ep->CreatePreferredAllocators() + → PluginExecutionProvider::CreatePreferredAllocators() + → OrtEp::CreateAllocator(ep, &mem_info, &alloc) [if set] + OR ep_factory.CreateAllocator(&factory, &mem_info, /*options=*/ nullptr, &alloc) + → [factory returns same shared ArenaAllocator] + → if alloc->Shrink != nullptr: + IArenaImplWrappingOrtAllocator(alloc) + else: + IAllocatorImplWrappingOrtAllocator(alloc) + → session allocator maps +``` + +**Path 3: User-created allocators (public API)** +``` +OrtApi::CreateSharedAllocator(env, ep_device, mem_type, alloc_type, allocator_options, &alloc) + → Environment::CreateSharedAllocator() + → CreateSharedAllocatorImpl(ep_device, mem_info, alloc_type, allocator_options, &alloc, replace=true) + → ep_factory->CreateAllocator(factory, &mem_info, allocator_options, &alloc) + → [factory creates ArenaAllocator with user-provided config] +``` + +**Key point:** `CreateSharedAllocatorImpl` explicitly rejects `OrtArenaAllocator` type from plugin factories and verifies the returned allocator doesn't use it either. The arena is opaque — ORT core sees `OrtDeviceAllocator`. + +--- + +## 3. Applying the Pattern to CUDA Plugin EP + +The CUDA plugin EP should follow the example plugin's architecture: **the arena lives inside the plugin library**. The previous design explored ORT-core-wrapping approaches (wrapping plugin allocators in ORT's internal arena). The example plugin EP demonstrates the intended approach: the EP library includes its own arena and wraps its raw allocators (both device and pinned) internally. + +### 3.1 What Needs to Change in the CUDA Plugin Factory + +`CudaEpFactory::CreateAllocatorImpl` currently creates raw `CudaDeviceAllocator` or `CudaPinnedAllocator` and returns them directly. The change: + +```cpp +// Current (cuda_ep_factory.cc — CreateAllocatorImpl): +if (strcmp(name, "Cuda") == 0) { + auto cuda_allocator = std::make_unique(memory_info, req_device_id); + *allocator = cuda_allocator.release(); // raw cudaMalloc/cudaFree +} + +// Target: wrap in CudaArenaAllocator, following the example plugin pattern. +// NOTE: The factory must maintain a separate arena per device_id, since each GPU +// has its own memory space. The factory already has a device_cache_ mapping +// HardwareDeviceKey → DeviceCacheEntry; the arena is stored there. Because +// CreateAllocatorImpl only knows the CUDA ordinal (from OrtMemoryInfoGetId), +// the factory must also maintain an efficient ordinal → DeviceCacheEntry mapping +// (e.g., a std::unordered_map built during +// GetSupportedDevicesImpl when device_cache_ is populated). +if (strcmp(name, "Cuda") == 0) { + auto& entry = factory.GetDeviceCacheEntryForOrdinal(req_device_id); + std::lock_guard lock{entry.arena_mutex}; + + if (/* use_cuda_mempool option */) { + // CudaMempoolArena path — see Section 4 + } else if (!entry.device_arena) { + // Arena path — first call for this device: + AllocatorUniquePtr raw_allocator( + new CudaDeviceAllocator(memory_info, req_device_id), + [](OrtAllocator* p) { delete static_cast(p); }); + entry.device_arena_using_defaults = (allocator_options == nullptr); + CudaArenaAllocator::Create(CudaAllocatorKind::kDevice, memory_info, + std::move(raw_allocator), allocator_options, + factory.ort_api_, factory.default_logger_, + entry.device_arena); + } + ++entry.num_device_arena_users; + *allocator = entry.device_arena.get(); +} + +if (strcmp(name, "CudaPinned") == 0) { + // Pinned memory is CPU-side and technically shared, but each device's pinned + // allocator has a distinct OrtMemoryInfo (device_id). Keep per-device. + auto& entry = factory.GetDeviceCacheEntryForOrdinal(req_device_id); + std::lock_guard lock{entry.arena_mutex}; + + if (!entry.pinned_arena) { + AllocatorUniquePtr raw_allocator( + new CudaPinnedAllocator(memory_info), + [](OrtAllocator* p) { delete static_cast(p); }); + CudaArenaAllocator::Create(CudaAllocatorKind::kPinned, memory_info, + std::move(raw_allocator), allocator_options, + factory.ort_api_, factory.default_logger_, + entry.pinned_arena); + } + ++entry.num_pinned_arena_users; + *allocator = entry.pinned_arena.get(); +} +``` + +### 3.2 Adapting the Arena Code for CUDA + +The `ep_arena.h`/`ep_arena.cc` from the example plugin are designed to be copied and adapted. For the CUDA plugin EP, the raw allocator (`CustomAllocator` in the example) is replaced with `CudaDeviceAllocator` (for GPU) or `CudaPinnedAllocator` (for pinned). + +#### Arena wrapper: `CudaArenaAllocator : CudaAllocatorBase` + +The example plugin defines `ArenaAllocator : BaseAllocator`, where `BaseAllocator` adds a virtual destructor to `OrtAllocator` so that `std::unique_ptr` can delete derived types. We do **not** introduce `BaseAllocator` into the CUDA plugin. Instead, `CudaArenaAllocator` inherits from the existing `CudaAllocatorBase`: + +```cpp +// In cuda_arena.h: +class CudaArenaAllocator final : public CudaAllocatorBase { + public: + static OrtStatus* Create(CudaAllocatorKind kind, + const OrtMemoryInfo* memory_info, + AllocatorUniquePtr raw_allocator, + const OrtKeyValuePairs* options, + const OrtApi& api, + const OrtLogger& logger, + std::unique_ptr& out); + + CudaArenaAllocator(CudaAllocatorKind kind, const OrtMemoryInfo* memory_info, + std::unique_ptr impl) + : CudaAllocatorBase(kind, memory_info), impl_(std::move(impl)) { + version = ORT_API_VERSION; + Alloc = AllocImpl; + Reserve = ReserveImpl; + Free = FreeImpl; + Info = InfoImpl; + GetStats = GetStatsImpl; + // Stream-aware only for device arena, not pinned + AllocOnStream = (kind == CudaAllocatorKind::kDevice) ? AllocOnStreamImpl : nullptr; + } + + OrtStatus* ResetChunksUsingStream(const OrtSyncStreamImpl* stream_impl) { + impl_->ResetChunksUsingStream(stream_impl); + return nullptr; + } + + private: + static void* ORT_API_CALL AllocImpl(OrtAllocator* this_, size_t size); + static void* ORT_API_CALL AllocOnStreamImpl(OrtAllocator* this_, size_t size, OrtSyncStream* stream); + static void* ORT_API_CALL ReserveImpl(OrtAllocator* this_, size_t size); + static void ORT_API_CALL FreeImpl(OrtAllocator* this_, void* p); + static const OrtMemoryInfo* ORT_API_CALL InfoImpl(const OrtAllocator* this_); + static OrtStatus* ORT_API_CALL GetStatsImpl(const OrtAllocator* this_, OrtKeyValuePairs** out) noexcept; + + std::unique_ptr impl_; +}; +``` + +**Why this works.** `CudaAllocatorBase` is intentionally defined as a standard-layout type with the `OrtAllocator` base subobject at offset 0; it only adds plain data members (`kind_`, `memory_info_`) after the `OrtAllocator` C struct layout. Under this constraint, `OrtAllocator*` and `CudaAllocatorBase*` (and further-derived pointers) all share the same address. In production code this should be enforced with `static_assert(std::is_standard_layout_v)`, and pointer comparisons should use `static_cast(entry.device_arena.get())` rather than relying on implicit same-address assumptions. This means: + +- **`ReleaseAllocatorImpl`** can safely `static_cast(allocator)` on arena pointers — `GetKind()` returns `kDevice` or `kPinned` correctly. +- **`AllocOnStream`** is set to `nullptr` for pinned arenas at construction time; ORT's `AllocateBufferWithOptions` falls through to plain `Alloc()` when `AllocOnStream` is null. +- **No ABI impact (by construction)** — given the standard-layout/offset-0 requirement, the object layout is compatible across `CudaAllocatorBase` subclasses (`CudaDeviceAllocator`, `CudaPinnedAllocator`, `CudaArenaAllocator`) for the `OrtAllocator` portion. + +#### Raw allocator ownership inside `ArenaImpl` + +`ArenaImpl` stores and owns the raw allocator (e.g. `CudaDeviceAllocator`). It interacts with it exclusively through the C-level `OrtAllocator` function pointers (`Alloc`, `Free`, `Info`). Since `CudaAllocatorBase` has no virtual destructor, `ArenaImpl` uses a type-erasing deleter: + +```cpp +// In cuda_arena.h: +using AllocatorUniquePtr = std::unique_ptr>; +``` + +The factory creates the raw allocator with a deleter that knows the concrete type: + +```cpp +AllocatorUniquePtr raw( + new CudaDeviceAllocator(memory_info, device_id), + [](OrtAllocator* p) { delete static_cast(p); }); +``` + +This is safe because the arena code (`ArenaImpl`) only calls through the C function pointers and never casts the stored allocator to a C++ type. + +#### Class hierarchy + +All CUDA plugin allocators inherit from `CudaAllocatorBase`, keeping a uniform object layout and enabling `ReleaseAllocatorImpl` to use `GetKind()` on any plugin-created allocator: + +``` +OrtAllocator (C struct) + └─ CudaAllocatorBase (adds kind_, memory_info_ — no virtual functions) + ├─ CudaDeviceAllocator (raw cudaMalloc/cudaFree) + ├─ CudaPinnedAllocator (raw cudaHostAlloc/cudaFreeHost) + ├─ CudaArenaAllocator (BFC arena wrapping a raw allocator via ArenaImpl) + └─ CudaMempoolOrtAllocator (CUDA native mempool — see Section 4.4) +``` + +### 3.3 Shared Arena Lifecycle and Reference Counting + +**Multi-GPU consideration.** A system may have multiple CUDA devices. Each GPU has its own device memory, so each needs its own arena. The CUDA plugin factory already maintains a per-device cache (`device_cache_`) mapping `HardwareDeviceKey → DeviceCacheEntry` that stores `OrtMemoryInfo` instances per GPU. The arena pointers and ref counts are added to this existing cache structure. + +**Per-device key correctness.** `HardwareDeviceKey` is `{type, vendor_id, device_id, cuda_ordinal}`. The `device_id` field is the PCI Device ID — it identifies the hardware *model* (e.g. 0x2684 for all RTX 4090s), **not** an individual physical device. On a host with two identical GPUs, `{type, vendor_id, device_id}` alone would produce the same key for both, causing them to share a single `DeviceCacheEntry` and a single arena — allocating memory on only one GPU. Including `cuda_ordinal` (assigned sequentially by the factory during `GetSupportedDevicesImpl`) ensures each physical GPU gets its own cache entry, arena, and `OrtMemoryInfo`. + +```cpp +// Existing structure in cuda_ep_factory.h — extended with arena members: +struct DeviceCacheEntry { + int cuda_device_id{-1}; + Ort::MemoryInfo device_memory_info{nullptr}; // GPU device memory + Ort::MemoryInfo pinned_memory_info{nullptr}; // CPU pinned memory for this GPU + + // Arena members (new): + std::mutex arena_mutex; + std::unique_ptr device_arena; + std::unique_ptr pinned_arena; + std::unique_ptr mempool_allocator; // alternative to device_arena (Section 4) + int num_device_arena_users = 0; + int num_pinned_arena_users = 0; + int num_mempool_users = 0; + bool device_arena_using_defaults = true; +}; +``` + +The factory's `device_cache_` is populated during `GetSupportedDevicesImpl` (one entry per GPU discovered). `CreateAllocatorImpl` extracts the `device_id` from the incoming `OrtMemoryInfo`, locates the corresponding `DeviceCacheEntry`, and creates/returns the arena for that device. Each GPU gets independent arena instances with independent lifecycle. + +`CreateAllocatorImpl` creates the arena on first call for a given device and increments its ref count. `ReleaseAllocatorImpl` decrements; when zero, the arena is destroyed: + +```cpp +// cuda_ep_factory.cc — ReleaseAllocatorImpl: +/*static*/ +void ORT_API_CALL CudaEpFactory::ReleaseAllocatorImpl( + OrtEpFactory* this_ptr, OrtAllocator* allocator) noexcept { + if (!allocator) return; + auto* factory = static_cast(this_ptr); + + // Check if allocator is a shared arena or mempool (pointer identity match). + for (auto& [key, entry] : factory->device_cache_) { + std::lock_guard lock{entry.arena_mutex}; + if (allocator == entry.device_arena.get()) { + if (--entry.num_device_arena_users == 0) entry.device_arena.reset(); + return; + } + if (allocator == entry.pinned_arena.get()) { + if (--entry.num_pinned_arena_users == 0) entry.pinned_arena.reset(); + return; + } + if (allocator == entry.mempool_allocator.get()) { + if (--entry.num_mempool_users == 0) entry.mempool_allocator.reset(); + return; + } + } + + // Fallback: raw allocator not managed by arena/mempool (e.g. read-only allocator). + // CudaAllocatorBase cast is safe — all CUDA plugin allocators inherit from it. + auto* typed = static_cast(allocator); + switch (typed->GetKind()) { + case CudaAllocatorKind::kDevice: + delete static_cast(allocator); + return; + case CudaAllocatorKind::kPinned: + delete static_cast(allocator); + return; + default: + assert(false && "Unknown CudaAllocatorKind"); + return; + } +} +``` + +This handles: +- **Shared allocators** — `RegisterExecutionProviderLibrary` iterates over each `OrtEpDevice` and calls `CreateAllocator` for each device's memory infos. Each device gets its own shared arena. +- **Per-session allocators** — each session calls `CreateAllocator` (returning the same shared arena for the device) and `ReleaseAllocator` on session teardown. + +The `OrtApi::CreateSharedAllocator` public API also flows through `CreateAllocatorImpl` with `replace_existing=true`. When replacing, `ReleaseAllocator` is called on the old allocator first (dropping that device's arena if ref count hits zero), then `CreateAllocator` is called again with the new options — potentially creating a new arena with different config for that specific device. + +**Note:** The example plugin EP uses single `arena_allocator_` / `num_arena_users_` members because it only registers for one device (`device_id=0`). The CUDA plugin must generalize this to per-device storage. + +### 3.4 Stream Integration + +The CUDA plugin's `CudaSyncStream` (from `OrtSyncStreamImpl`) must call `ResetChunksUsingStream` on the device arena at session run end, following the example. Since there may be multiple GPUs, the stream must know which device's arena to reset. Each stream is created for a specific `OrtMemoryDevice`, which has a device_id — this maps to the corresponding `DeviceCacheEntry`: + +```cpp +// cuda_stream_plugin.cc — OnSessionRunEndImpl: +OrtStatus* ORT_API_CALL CudaSyncStream::OnSessionRunEndImpl(OrtSyncStreamImpl* this_ptr) noexcept { + auto& impl = *static_cast(this_ptr); + // impl.device_id_ was set at stream creation from the OrtMemoryDevice + auto* arena = impl.factory_->GetDeviceArenaAllocator(impl.device_id_); + if (arena) { + arena->ResetChunksUsingStream(this_ptr); + } + return nullptr; +} +``` + +`GetDeviceArenaAllocator(device_id)` looks up the `DeviceCacheEntry` for the given device and returns its `device_arena.get()`. + +The pinned allocator is also wrapped in `CudaArenaAllocator` but must **not** be stream-aware, matching the in-tree EP where pinned uses plain `BFCArena` (not `StreamAwareBFCArena`). `CudaArenaAllocator`'s constructor handles this: it sets `AllocOnStream = nullptr` when `kind == CudaAllocatorKind::kPinned` (see Section 3.2). ORT's `AllocateBufferWithOptions` checks for a non-null `AllocOnStream` before calling it, so the pinned arena transparently falls through to plain `Alloc()`. Accordingly, `ResetChunksUsingStream` is not called for the pinned arena at session run end. + +### 3.5 Arena Config Flow + +**Shared allocators (environment level):** + +`RegisterExecutionProviderLibrary` calls `CreateSharedAllocatorImpl` with `allocator_options = nullptr`. This means the factory's first arena creation uses default `ArenaConfig` values. This is acceptable: +- The defaults (1 MB initial chunk, 128 MB max dead, kNextPowerOfTwo growth) are reasonable. +- If the user configures arena options via `OrtApi::CreateSharedAllocator` later, the old allocator is released and a new one is created with the provided options (because `replace_existing=true`). + +**Per-session allocators:** + +`PluginExecutionProvider::CreatePreferredAllocators()` calls `ep_factory_.CreateAllocator()` for each memory info registered by the EP's devices. Today this passes `allocator_options = nullptr`, which means the factory always creates arenas with default config. + +**Session-level plumbing (new).** To support session-level arena config (e.g. `ep.cudapluginexecutionprovider.arena.max_mem`), `PluginExecutionProvider` needs to: + +1. **Extract arena options at construction time (gated).** The constructor already receives `const OrtSessionOptions& session_options`. The extraction is gated on `ep_factory_.CreateAllocator != nullptr` — only factory-based allocator creation accepts `allocator_options`, so the scan is skipped entirely for plugin EPs that don't implement factory-level allocator creation (the `OrtEp::CreateAllocator` path has no options parameter). When gated in, the constructor constructs the EP-specific prefix via `OrtSessionOptions::GetProviderOptionPrefix(ep->GetName(ep.get()))` (which lowercases the EP name), appends `"arena."`, and scans `session_options.value.config_options` for matching keys. Matching keys are stored with the EP prefix stripped (bare `"arena.*"` keys) in a `std::optional` member (`session_arena_options_`). The EP-name prefix ensures that only keys intended for this specific EP are extracted — e.g. `ep.cudapluginexecutionprovider.arena.*` keys will never match a session for a different plugin EP. + +2. **Pass options in `CreatePreferredAllocators`.** If `session_arena_options_` has a value, pass it as `allocator_options` to `ep_factory_.CreateAllocator()`. Otherwise pass `nullptr` (preserving existing behavior for EPs that don't use arena keys). + +This means: +- The factory's first `CreateAllocator` call (from `RegisterExecutionProviderLibrary` → shared allocators) uses env-level arena config (or defaults if none). +- Subsequent calls from `CreatePreferredAllocators` pass session-level arena config. If the factory already holds a shared arena for that device (from the env-level path) and the incoming session options differ, the factory decides how to handle it — typically logging a warning and keeping the existing arena (since it's shared). If no shared arena exists yet (e.g. `use_env_allocators=0`), the factory creates a new arena with the session-provided config. +- The `OrtApi::CreateSharedAllocator` public API also flows through `CreateAllocatorImpl` with `replace_existing=true`, allowing users to replace an existing arena with a new config at any time. + +``` +Session-level flow: +SessionOptionsAppendExecutionProvider_V2(session, ep_devices, keys[], values[]) + → keys stored in session_options.config_options as "ep.cudapluginexecutionprovider.arena.*" + → PluginExecutionProvider constructor extracts "arena.*" keys + → CreatePreferredAllocators() builds OrtKeyValuePairs and passes to CreateAllocator() + → factory creates/reuses arena with provided config +``` + +**ORT core change required:** `PluginExecutionProvider` constructor and `CreatePreferredAllocators()` in `ep_plugin_provider_interfaces.cc/.h` (see Section 5.3). + +**User-provided config via `CreateEnvWithOptions`:** + +Environment-level config can be passed via `OrtEnvCreationOptions::config_entries`: + +```cpp +api->AddKeyValuePair(kvps, "ep_factory.CudaPluginExecutionProvider.arena.extend_strategy", "1"); +api->AddKeyValuePair(kvps, "ep_factory.CudaPluginExecutionProvider.arena.max_mem", "4294967296"); + +OrtEnvCreationOptions options{}; +options.config_entries = kvps; +api->CreateEnvWithOptions(&options, &env); +``` + +**Current gap:** `RegisterExecutionProviderLibrary` does not extract env config entries and pass them as `allocator_options` to `CreateSharedAllocatorImpl`. To support env-level arena config, this needs to be plumbed: + +1. `RegisterExecutionProviderLibrary` constructs a prefix via `"ep_factory." + std::string(factory->GetName ? factory->GetName(factory) : "") + "."` (case-sensitive, using `GetName` as-is — see Section 3.6). Note: `GetName` is a C function pointer on `OrtEpFactory`, invoked as `factory->GetName(factory)`. Implementations must handle `GetName == nullptr` or a `nullptr` return defensively. The prefix is then used to obtain a snapshot of the environment config entries via `Environment::GetConfigEntries()` (which acquires `config_entries_mutex_` under a shared lock) +2. Scans the snapshot for keys matching the prefix, strips the prefix, and builds `OrtKeyValuePairs` with bare `arena.*` keys +3. Passes to `CreateSharedAllocatorImpl` as `allocator_options` +4. `CreateSharedAllocatorImpl` forwards to `ep_factory->CreateAllocator` + +**Concurrency note:** `config_entries_` is guarded by `config_entries_mutex_` (a `std::shared_mutex`). `RegisterExecutionProviderLibrary` does not hold any lock itself. Implementations must use `GetConfigEntries()` (which takes a shared lock and returns a copy) rather than iterating `config_entries_` directly. + +This is a small ORT core change that enables the existing config mechanism to reach the plugin's arena. + +### 3.6 Environment vs. Session Config + +ORT has two separate configuration namespaces for EP-specific options. + +#### Current state + +| | Environment-level | Session-level | +|---|---|---| +| **Prefix pattern** | `ep_factory..` | `ep..` | +| **Who constructs the prefix?** | No one — convention from C API doc comments only | ORT core (`GetProviderOptionPrefix`) | +| **Lowercasing applied?** | **Not defined** — ORT never constructs or parses this prefix today | **Yes** — `GetLowercaseString(GetName())` | +| **Backing store** | `std::map` (case-sensitive) | `std::unordered_map` (case-sensitive) | +| **Set via** | `CreateEnvWithOptions` (`OrtEnvCreationOptions.config_entries`) | `SessionOptionsAppendExecutionProvider_V2` | +| **CUDA plugin `GetName()`** | `"CudaPluginExecutionProvider"` | `"CudaPluginExecutionProvider"` | + +The C API documentation (`onnxruntime_c_api.h`) describes the environment-level prefix as `ep_factory..` where `` is the factory's own name (from `OrtEpFactory::GetName()`), **not** the user-provided registration name passed to `RegisterExecutionProviderLibrary`. However, ORT core does not currently construct, parse, or normalize this prefix — it is purely a documentation convention. The design (Section 3.5 / 5.3) proposes new code in `RegisterExecutionProviderLibrary` that would extract these keys for the first time, which requires deciding on a casing convention. + +The session-level prefix is always lowercased by ORT via `GetLowercaseString`: + +```cpp +// abi_session_options.cc — GetProviderOptionPrefix +std::string key_prefix = "ep."; +key_prefix += onnxruntime::utils::GetLowercaseString(provider_name); +key_prefix += "."; +``` + +Both backing stores (`std::map` and `std::unordered_map`) use exact string comparison — key lookup is case-sensitive. + +#### Casing convention for `ep_factory.` prefix + +Since new code must be written to extract `ep_factory.` keys, we must decide how the `` portion is matched: + +| Option | Env-level example key | Pros | Cons | +|--------|----------------------|------|------| +| **(A) Use `GetName()` as-is** | `ep_factory.CudaPluginExecutionProvider.arena.*` | Exact match to factory identity; unambiguous | Inconsistent with session-level (lowercase); users must get casing exactly right; error-prone | +| **(B) Lowercase like session-level** | `ep_factory.cudapluginexecutionprovider.arena.*` | Consistent with `ep.cudapluginexecutionprovider.*`; users see one pattern | Diverges from C API doc comment which doesn't specify lowercasing; slight surprise if user reads `GetName()` | +| **(C) Case-insensitive matching** | Either casing works | Most forgiving for users | Requires scanning all map entries (can't use `std::map::find`); unusual; extra code | + +**Recommendation: Option A** — use `GetName()` as-is, respecting the C API specification which is case-sensitive. The `ep_factory..` prefix uses the factory's own name verbatim: + +``` +Environment: ep_factory.CudaPluginExecutionProvider.arena.extend_strategy +Session: ep.cudapluginexecutionprovider.arena.extend_strategy +``` + +The new code in `RegisterExecutionProviderLibrary` constructs the prefix as: + +```cpp +// Note: GetName is a function pointer on the C struct OrtEpFactory. +// Must be called as factory->GetName(factory) and null-checked. +const char* ep_name = (factory->GetName) ? factory->GetName(factory) : nullptr; +std::string prefix = "ep_factory." + std::string(ep_name ? ep_name : "") + "."; +``` + +The session-level prefix continues to use `GetLowercaseString` independently. While the two prefixes use different casing conventions, the `ep_factory.` prefix is specified by the C API documentation as `` (the factory's identity), and the backing store (`std::map`) is case-sensitive. Introducing lowercasing here would diverge from the documented contract. + +#### Conflict between namespaces + +The EP factory may receive arena config from two sources: environment-level keys (via `RegisterExecutionProviderLibrary`) and session-level keys (via `PluginExecutionProvider::CreatePreferredAllocators`). The factory is unaware of conflicts between these two namespaces. This is acceptable because: +- Shared allocators are created first (environment level) — only env config applies at that point. +- Per-session `CreatePreferredAllocators` calls arrive later with session-level config. Since the factory typically holds a shared arena already, session options are only effective if: (a) no shared arena exists yet, or (b) the user explicitly calls `OrtApi::CreateSharedAllocator` with `replace_existing=true`. +- When per-session config differs from the shared arena's config, the factory logs a warning but keeps the existing arena (it's shared across sessions and cannot be reconfigured mid-flight). +- The two config paths serve different lifecycle scopes and are independent. + +**Runtime validation (recommended):** When `CreateAllocatorImpl` receives `allocator_options` and the factory already holds a shared arena for that device, log a warning if the incoming keys differ from the keys used at first creation. This makes misconfiguration visible without silently ignoring the second set of options. + +--- + +## 4. Migrating `CudaMempoolArena` to the Plugin + +### 4.1 Overview + +`CudaMempoolArena` is CUDA's native memory pool (`cudaMallocFromPoolAsync`/`cudaFreeAsync`). It is an alternative to the plugin's arena for GPU device memory — mutually exclusive, selected by config. It is self-contained (CUDA SDK only) and already stream-aware. + +### 4.2 Current Dependencies + +| Dependency | Plugin-Safe? | Notes | +|-----------|-------------|-------| +| `` | ✅ | CUDA SDK — always available | +| `core/common/common.h` | ✅ | `ORT_THROW`, `ORT_ENFORCE` — no framework deps | +| `core/providers/cuda/cuda_stream_handle.h` | ❌ | Pulls in in-tree framework types (`OrtDevice`, `Stream` base class); plugin CMake excludes its `.cc`. Use `OrtApi::SyncStream_GetHandle` on `OrtSyncStream*` to obtain `cudaStream_t` instead | +| `core/providers/cuda/shared_inc/cuda_call.h` | ✅ | CUDA error-handling macros | +| `core/providers/shared_library/provider_api.h` | ❌ | Provider-bridge header defining `logging::Logger` forward decl used by `CudaMempoolArena`; must be removed/guarded in plugin build | +| `logging::Logger*` | ❌ | **Primary blocker** — provider-bridge logger type (from `provider_api.h`), not available in plugin build | + +### 4.3 Logger Adaptation + +Replace `const logging::Logger* logger_` with a build-conditional type using `#ifdef BUILD_CUDA_EP_AS_PLUGIN`. This follows the established pattern already used across 20+ CUDA provider files (`cuda_common.h`, `cuda_kernel.h`, `cudnn_common.h`, `space_depth_ops.h`, `identity_op.cc`, `pad.cc`, `scatter_nd.cc`, etc.) where shared headers use `#ifdef BUILD_CUDA_EP_AS_PLUGIN` to adapt between in-tree and plugin builds: + +```cpp +#ifdef BUILD_CUDA_EP_AS_PLUGIN + const OrtApi& ort_api_; // stored reference to OrtApi (set at construction) + const OrtLogger* logger_; // plugin: OrtLogger from EP C API + // Logger_LogMessage returns OrtStatus* which must be released if non-null. + #define MEMPOOL_LOG(ort_api_ref, logger, level, msg) do { \ + OrtStatus* _s = (ort_api_ref).Logger_LogMessage( \ + (logger), ORT_LOGGING_LEVEL_##level, \ + (msg).c_str(), ORT_FILE, __LINE__, __FUNCTION__); \ + if (_s) (ort_api_ref).ReleaseStatus(_s); \ + } while (0) +#else + const logging::Logger* logger_; // in-tree: ORT internal logger + #define MEMPOOL_LOG(ort_api_ref, logger, level, msg) LOGS(*logger, level) << msg +#endif +``` + +The plugin build stores a `const OrtApi&` reference (passed at construction from the factory) so the macro can call `Logger_LogMessage`. The returned `OrtStatus*` is released if non-null — logging failures are not propagated. + +**Decision:** Use the `#ifdef` macro approach (not a virtual `ICudaMempoolLogger` interface) for consistency with the existing codebase convention. + +### 4.4 OrtAllocator Wrapper + +The factory returns `CudaMempoolArena` wrapped behind `OrtAllocator*`, inheriting from `CudaAllocatorBase` — consistent with all other CUDA plugin allocators (see Section 3.2 class hierarchy). This keeps `ReleaseAllocatorImpl`'s `GetKind()` dispatch and pointer-identity match working for mempool allocators: + +```cpp +class CudaMempoolOrtAllocator final : public CudaAllocatorBase { + public: + static OrtStatus* Create(const OrtMemoryInfo* memory_info, + const OrtKeyValuePairs* options, + const OrtApi& api, + const OrtLogger& logger, + std::unique_ptr& out); + + CudaMempoolOrtAllocator(const OrtMemoryInfo* memory_info, /* ... */) + : CudaAllocatorBase(CudaAllocatorKind::kDevice, memory_info) { + version = ORT_API_VERSION; + Alloc = AllocImpl; + AllocOnStream = AllocOnStreamImpl; // mempool is stream-aware + Free = FreeImpl; + Reserve = ReserveImpl; + Info = InfoImpl; + GetStats = GetStatsImpl; + } + + private: + // OrtAllocator callbacks — delegate to CudaMempoolArena + static void* ORT_API_CALL AllocImpl(OrtAllocator* this_, size_t size); + static void* ORT_API_CALL AllocOnStreamImpl(OrtAllocator* this_, size_t size, OrtSyncStream* stream); + static void ORT_API_CALL FreeImpl(OrtAllocator* this_, void* p); + static void* ORT_API_CALL ReserveImpl(OrtAllocator* this_, size_t size); + static const OrtMemoryInfo* ORT_API_CALL InfoImpl(const OrtAllocator* this_); + static OrtStatus* ORT_API_CALL GetStatsImpl(const OrtAllocator* this_, OrtKeyValuePairs** out) noexcept; + + const OrtApi& ort_api_; // needed for SyncStream_GetHandle, KVP creation + std::unique_ptr arena_; +}; +``` + +`AllocOnStreamImpl` resolves `OrtSyncStream*` → `cudaStream_t` via `OrtApi::SyncStream_GetHandle()`. This requires the wrapper to store a reference to `const OrtApi&` (already present via the `Create` factory method's `api` parameter). The stored `OrtApi` reference is also needed for `GetStatsImpl` (to create `OrtKeyValuePairs`) and for `Create` itself (to parse config options). The `OrtApi` pointer is available in all allocator callback contexts because it is captured in the `CudaMempoolOrtAllocator` instance that `this_` points to. + +**OrtMemoryInfo type:** Must be `OrtDeviceAllocator` (ORT core rejects `OrtArenaAllocator` from plugins). + +### 4.5 Arena Mode Selection in CreateAllocatorImpl + +The factory selects between the plugin's arena and CUDA mempool based on allocator options: + +```cpp +OrtStatus* CudaEpFactory::CreateAllocatorImpl(OrtEpFactory* this_ptr, + const OrtMemoryInfo* memory_info, + const OrtKeyValuePairs* allocator_options, + OrtAllocator** allocator) noexcept { + auto& factory = *static_cast(this_ptr); + // ... + if (strcmp(name, "Cuda") == 0) { + bool use_mempool = false; + if (allocator_options) { + const char* v = factory.ort_api_.GetKeyValue(allocator_options, "arena.use_cuda_mempool"); + use_mempool = v && std::string(v) == "1"; + } + + if (use_mempool) { + auto& entry = factory.GetOrCreateDeviceCacheEntry(req_device_id); + std::lock_guard lock{entry.arena_mutex}; + if (!entry.mempool_allocator) { + CudaMempoolOrtAllocator::Create(memory_info, allocator_options, + factory.ort_api_, factory.default_logger_, + entry.mempool_allocator); + } + ++entry.num_mempool_users; + *allocator = entry.mempool_allocator.get(); + } else { + // Arena path (Section 3.1) + } + } +} +``` + +### 4.6 Config Keys for Mempool + +| Key | Type | Default | Description | +|-----|------|---------|-------------| +| `arena.use_cuda_mempool` | `"0"` or `"1"` | `"0"` | Enable CUDA native mempool instead of the plugin arena | +| `arena.cuda_mempool_release_threshold` | uint64 bytes | `0` | `cudaMemPoolAttrReleaseThreshold` value | +| `arena.cuda_mempool_bytes_to_keep_on_shrink` | size_t bytes | `0` | Target for `cudaMemPoolTrimTo()` on `Shrink()` | + +--- + +## 5. Summary of Changes + +### 5.1 Files Copied from Example Plugin EP + +The arena implementation in `onnxruntime/test/autoep/library/example_plugin_ep/` is the reference. Two files are copied into the CUDA plugin directory and adapted: + +| Source | Target | What to copy | Adaptations needed | +|---|---|---|---| +| `ep_arena.h` (~632 lines) | `plugin/cuda_arena.h` | `ArenaExtendStrategy` enum, `ArenaConfig` struct (with `FromKeyValuePairs` parser and `ConfigKeyNames`), `ArenaImpl` class (full arena implementation) | **License header:** Preserve the original Apache-2.0 TensorFlow-derived license header and attribution notices. **Namespace:** Wrap in `onnxruntime::cuda_plugin`. **Includes:** Replace `#include "ep_allocator.h"` and `#include "../plugin_ep_utils.h"` with `#include "cuda_allocator_plugin.h"` and `#include "cuda_plugin_utils.h"`. **`ArenaAllocator` → `CudaArenaAllocator`:** The example’s `ArenaAllocator : BaseAllocator` is replaced by `CudaArenaAllocator : CudaAllocatorBase` (see Section 3.2), defined in `cuda_arena.h` alongside the copied `ArenaImpl`. **`AllocatorUniquePtr`:** Redefine as `std::unique_ptr>` (type-erasing deleter — see Section 3.2). **Macros:** The `EP_ENFORCE`, `LOG`, `RETURN_ERROR` macros come from `plugin_ep_utils.h`; replace with equivalents from `cuda_plugin_utils.h` or define locally (see 5.2). **No CUDA-specific changes** — the arena operates on the `OrtAllocator` C interface and is CUDA-agnostic. | +| `ep_arena.cc` (~750 lines) | `plugin/cuda_arena.cc` | Full `ArenaImpl` implementation: constructor, destructor, `Alloc`, `AllocOnStream`, `Free`, `Reserve`, `Extend`, `FindChunkPtr`, `SplitChunk`, `Merge`, `FreeAndMaybeCoalesce`, `Coalesce`, `ResetChunksUsingStream`, `DumpMemoryLog`, `GetStats` | **License header:** Preserve the original Apache-2.0 TensorFlow-derived license header and attribution notices. **Namespace:** Wrap in `onnxruntime::cuda_plugin`. **Include:** `#include "cuda_arena.h"`. **Macros:** Same as header. No other changes needed — the implementation is allocator-agnostic (delegates to `device_allocator_->Alloc/Free`). | + +**Not copied** — `ep_allocator.h`. The CUDA plugin already has `cuda_allocator_plugin.h` with `CudaAllocatorBase`, `CudaDeviceAllocator`, `CudaPinnedAllocator`. We add `AllocatorStats` to this existing file (see 5.2). `AllocatorUniquePtr` (type-erasing deleter) is defined in `cuda_arena.h` alongside `ArenaImpl` which uses it. `BaseAllocator` is **not** needed — see Section 3.2. + +**CMake:** No changes needed. The plugin CMake uses `file(GLOB_RECURSE ... "core/providers/cuda/*.cc")` which automatically picks up new `.cc` files in the `plugin/` directory. + +### 5.2 CUDA Plugin Changes + +| File | Change | +|------|--------| +| `plugin/cuda_arena.h` | **New file.** Copied from `ep_arena.h` with namespace/include adaptations per 5.1. Contains `ArenaExtendStrategy`, `ArenaConfig`, `ArenaImpl`, `AllocatorUniquePtr` typedef, and `CudaArenaAllocator` (replaces example’s `ArenaAllocator`). | +| `plugin/cuda_arena.cc` | **New file.** Copied from `ep_arena.cc` with namespace/include adaptations per 5.1. | +| `plugin/cuda_allocator_plugin.h` | **(a)** Add `AllocatorStats` struct (POD with `ToKeyValuePairs` helper, copied from `ep_allocator.h`). **(b)** Add arena-support macros: `EP_ENFORCE` (ostringstream + throw), `LOG` (delegates to `OrtApi::Logger_LogMessage`), `RETURN_ERROR` (creates OrtStatus). These can go in `cuda_plugin_utils.h` instead if preferred. | +| `plugin/cuda_ep_factory.h` | Extend `DeviceCacheEntry` with per-device arena and mempool members: `std::mutex arena_mutex; std::unique_ptr device_arena; std::unique_ptr pinned_arena; std::unique_ptr mempool_allocator;` plus ref counts and `device_arena_using_defaults` flag (Section 3.3). Add `#include "cuda_arena.h"`. Add helper `CudaArenaAllocator* GetDeviceArenaForDevice(int device_id)` for stream integration. | +| `plugin/cuda_ep_factory.cc` | Rewrite `CreateAllocatorImpl`: extract `device_id` from `OrtMemoryInfo`, find `DeviceCacheEntry`, create/return shared `CudaArenaAllocator` wrapping `CudaDeviceAllocator` or `CudaPinnedAllocator` per device (Section 3.1 pseudocode). Rewrite `ReleaseAllocatorImpl`: pointer identity match against `DeviceCacheEntry` arenas and mempool allocator, decrement ref count, destroy if zero; fall back to `CudaAllocatorBase`-based `delete` for raw allocators (Section 3.3 pseudocode). | +| `plugin/cuda_stream_plugin.cc` | Update `CudaSyncStream::OnSessionRunEndImpl`: after stream synchronization and deferred buffer cleanup, call `factory.GetDeviceArenaForDevice(stream->device_id_)->ResetChunksUsingStream(this_ptr)` to release chunk-to-stream assignments (Section 3.4). | + +### 5.3 ORT Core Changes (Minimal) + +| File | Change | +|------|--------| +| `allocator.h` | Added `virtual IArena* AsArena()` (const and non-const, returning `nullptr`) to `IAllocator`. Overridden in `IArena` to return `this`. This eliminates the RTTI dependency in `SafeArenaCast()`, which now delegates to `allocator->AsArena()`. | +| `allocator.cc` | Simplified `SafeArenaCast()` to `return allocator ? allocator->AsArena() : nullptr;` — no `dynamic_cast`, no `#ifdef ORT_NO_RTTI`. | +| `allocator_adapters.h` | Added `IArenaImplWrappingOrtAllocator` — wraps an `OrtAllocator*` that implements `Shrink()` as an `IArena`. See Section 5.4. | +| `allocator_adapters.cc` | Implemented `IArenaImplWrappingOrtAllocator` methods (Alloc, Free, Reserve, IsStreamAware, AllocOnStream, GetStats, Shrink). Added `GetStatsFromOrtAllocator()` helper using safe `TryParseStringWithClassicLocale` parsing. Added `kOrtAllocatorShrinkMinVersion = 25`. | +| `environment.cc` | **`CreateSharedAllocator`**: When the plugin allocator's `version >= 25` and `Shrink != nullptr`, wraps it as `IArenaImplWrappingOrtAllocator` (IArena) instead of `IAllocatorImplWrappingOrtAllocator` (IAllocator). This makes plugin arenas discoverable by session-level arena management such as `ShrinkMemoryArenas`. | +| `inference_session.cc` | **`ValidateAndParseShrinkArenaString`** and **`ShrinkMemoryArenas`**: simplified to use `allocator->AsArena()` directly, which now also discovers plugin arenas wrapped via `IArenaImplWrappingOrtAllocator`. | +| `device_stream_collection.cc` | `ReleaseSingleStreamBuffers`: simplified to use `allocator->AsArena()` directly (removed `alloc_type == OrtArenaAllocator` check). | +| Future: `environment.cc` | `RegisterExecutionProviderLibrary`: construct prefix `"ep_factory." + factory->GetName(factory) + "."` (case-sensitive, with null-guard), obtain config snapshot via `GetConfigEntries()`, extract matching `arena.*` keys, strip prefix, build `OrtKeyValuePairs` with bare `arena.*` keys, pass as `allocator_options` to `CreateSharedAllocatorImpl` instead of `nullptr` (see Section 3.6 for casing convention). | +| Future: `ep_plugin_provider_interfaces.h` | Add `std::optional session_arena_options_` member to `PluginExecutionProvider` to store session-level arena config extracted at construction time. | +| Future: `ep_plugin_provider_interfaces.cc` | **(a)** In `PluginExecutionProvider` constructor: gated on `ep_factory_.CreateAllocator != nullptr` — construct EP prefix via `GetProviderOptionPrefix(ep->GetName(ep.get()))`, scan `session_options.value.config_options` for keys matching `arena.*`, strip the EP prefix, and store as bare `"arena.*"` keys in `session_arena_options_`. The EP-name prefix naturally scopes extraction to the current EP. **(b)** In `CreatePreferredAllocators()`: if `session_arena_options_` has a value, pass it as `allocator_options` to `ep_factory_.CreateAllocator()` instead of `nullptr`. | + +### 5.4 Shrink and ORT Core Arena Integration + +The in-tree CUDA EP's `BFCArena` / `StreamAwareBFCArena` directly implements the `IArena` interface inside ORT core. ORT session-level code — `InferenceSession::ShrinkMemoryArenas()`, `DeviceStreamCollection::ReleaseSingleStreamBuffers()`, `ValidateAndParseShrinkArenaString()` — discovers arenas via `IArena::SafeArenaCast()` and calls `Shrink()` or `ReleaseStreamBuffers()` on them. Plugin EP allocators are returned as `OrtAllocator*` (a C struct), which ORT core wraps in a C++ `IAllocator` adapter. Without additional work, plugin arenas are invisible to these session-level arena management paths. + +This PR introduces two complementary mechanisms to bridge the gap: + +#### 5.4.1 `IArenaImplWrappingOrtAllocator` — Plugin Arena as IArena + +`IArenaImplWrappingOrtAllocator` (in `allocator_adapters.h/.cc`) wraps an `OrtAllocator*` whose `Shrink` function pointer is non-null, exposing it through the standard `IArena` C++ interface: + +| IArena method | How it maps to OrtAllocator | +|---|---| +| `Alloc(size)` | `ort_allocator_->Alloc(ort_allocator_, size)` | +| `Free(p)` | `ort_allocator_->Free(ort_allocator_, p)` | +| `Reserve(size)` | `ort_allocator_->Reserve(ort_allocator_, size)` (version ≥ 18) | +| `IsStreamAware()` | `ort_allocator_->AllocOnStream != nullptr` (version ≥ 23) | +| `AllocOnStream(size, stream)` | `ort_allocator_->AllocOnStream(ort_allocator_, size, stream->GetRawHandle())` | +| `GetStats(stats)` | Calls `ort_allocator_->GetStats` (version ≥ 23), parses the returned `OrtKeyValuePairs` into `AllocatorStats` using safe `TryParseStringWithClassicLocale` | +| **`Shrink()`** | `ort_allocator_->Shrink(ort_allocator_)` → converts returned `OrtStatus*` to `Status` (version ≥ 25) | +| `ReleaseStreamBuffers(stream)` | **No-op** — plugin EPs handle stream buffer cleanup internally via `OrtSyncStreamImpl::OnSessionRunEnd` → `ResetChunksUsingStream()` | + +The version gate `kOrtAllocatorShrinkMinVersion = 25` ensures the `Shrink` field is only accessed on allocators that declare support for it. + +#### 5.4.2 `AsArena()` Virtual Method — RTTI-Free Arena Discovery + +`IAllocator` now declares `virtual IArena* AsArena()` (both const and non-const), returning `nullptr` by default. `IArena` overrides this to return `this`. `SafeArenaCast()` delegates to `AsArena()`, removing the previous dependency on `dynamic_cast` (or unsafe `static_cast` in `ORT_NO_RTTI` builds). + +Because `IArenaImplWrappingOrtAllocator` inherits from `IArena`, its `AsArena()` automatically returns a non-null pointer, making plugin arenas discoverable by all existing arena-aware code paths without any RTTI. + +#### 5.4.3 How Plugin Arenas Participate in `ShrinkMemoryArenas` + +The end-to-end flow for shrinking plugin arenas: + +``` +User calls OrtApi::ShrinkMemoryArenas(session, "arena_name:0") + → InferenceSession::ShrinkMemoryArenas() + → iterates session allocators + → allocator->AsArena() // non-null for IArenaImplWrappingOrtAllocator + → arena->Shrink() + → IArenaImplWrappingOrtAllocator::Shrink() + → ort_allocator_->Shrink(ort_allocator_) // crosses into plugin DLL + → CudaArenaAllocator::ShrinkImpl() + → ArenaImpl::Shrink() // releases free regions back to CUDA +``` + +For `CudaMempoolOrtAllocator`, the same path calls `cudaMemPoolTrimTo()` with the configured `bytes_to_keep_on_shrink`. + +#### 5.4.4 Selection Logic in `Environment::CreateSharedAllocator` + +`Environment::CreateSharedAllocator` inspects the `OrtAllocator*` returned by the plugin factory: + +```cpp +if (allocator->version >= 25 && allocator->Shrink != nullptr) { + shared_allocator = std::make_shared(std::move(ort_allocator)); +} else { + shared_allocator = std::make_shared(std::move(ort_allocator)); +} +``` + +Plugin allocators that do not implement `Shrink` (e.g., read-only allocators) continue to be wrapped as plain `IAllocator`. The selection is automatic — no user-facing configuration is needed. + +--- + +## 6. Implementation Plan + +### Phase 1: Arena in CUDA Plugin + +1. **Add support types to `cuda_allocator_plugin.h`:** Add `AllocatorStats` (POD). No changes to `CudaAllocatorBase` inheritance. +2. **Add arena macros to `cuda_plugin_utils.h`:** Add `EP_ENFORCE` (ostringstream throw), `LOG` (delegates to `OrtApi::Logger_LogMessage`), `RETURN_ERROR` (creates OrtStatus). These are needed by the arena code copied from the example plugin. +3. **Copy `ep_arena.h` → `plugin/cuda_arena.h`:** Wrap in `onnxruntime::cuda_plugin` namespace. Replace includes with `cuda_allocator_plugin.h` and `cuda_plugin_utils.h`. Replace `ArenaAllocator : BaseAllocator` with `CudaArenaAllocator : CudaAllocatorBase` (see Section 3.2). Add `AllocatorUniquePtr` typedef (type-erasing deleter). Set `AllocOnStream` conditionally by `CudaAllocatorKind` in the constructor. +4. **Copy `ep_arena.cc` → `plugin/cuda_arena.cc`:** Wrap in `onnxruntime::cuda_plugin` namespace. Replace includes. No other changes needed. +5. **Extend `DeviceCacheEntry` in `cuda_ep_factory.h`:** Add per-device arena members (`device_arena`, `pinned_arena`, ref counts, mutex) as described in Section 3.3. Add `#include "cuda_arena.h"`. Add `CudaArenaAllocator* GetDeviceArenaForDevice(int device_id)` accessor. +6. **Rewrite `CreateAllocatorImpl` in `cuda_ep_factory.cc`:** Look up `DeviceCacheEntry` by `device_id`, create shared `CudaArenaAllocator` wrapping `CudaDeviceAllocator`/`CudaPinnedAllocator` on first call per device, return same pointer on subsequent calls (Section 3.1 pseudocode). +7. **Rewrite `ReleaseAllocatorImpl` in `cuda_ep_factory.cc`:** Pointer identity match against device cache entries, decrement ref count, destroy if zero. Fall back to `CudaAllocatorBase`-based `delete` for non-arena types (Section 3.3 pseudocode). +8. **Update `OnSessionRunEndImpl` in `cuda_stream_plugin.cc`:** After existing stream sync and deferred buffer cleanup, call `arena->ResetChunksUsingStream(this_ptr)` for the device's arena (Section 3.4). +9. **No CMake changes needed:** The glob picks up new `.cc` files in `plugin/` automatically. +10. **Update `RegisterExecutionProviderLibrary` in `environment.cc`:** Construct prefix via `factory->GetName(factory)` (case-sensitive, with null-guard), obtain config snapshot via `GetConfigEntries()`, extract `ep_factory..arena.*` keys, pass as `allocator_options` to `CreateSharedAllocatorImpl` (see Section 3.6). +11. **Plumb session-level arena options in `PluginExecutionProvider`:** In the constructor (`ep_plugin_provider_interfaces.cc`), extract `ep..arena.*` keys from `session_options.value.config_options`, strip the EP prefix, and store as bare `arena.*` keys. In `CreatePreferredAllocators()`, build `OrtKeyValuePairs` from the stored map and pass to `ep_factory_.CreateAllocator()` (see Section 3.5). + +### Phase 2: CudaMempoolArena Migration + +1. Add conditional logger abstraction to `cuda_mempool_arena.h/.cc` +2. Create `CudaMempoolOrtAllocator : CudaAllocatorBase` wrapper (Section 4.4) +3. Add mempool arena mode selection in `CreateAllocatorImpl` based on `arena.use_cuda_mempool` option +4. Remove `cuda_mempool_arena.cc` from plugin CMake exclusion list + +### Phase 3: Validation + +1. Verify default arena gives same allocation behavior as in-tree EP +2. Test mempool mode with `arena.use_cuda_mempool=1` +3. Test env-level arena config via `CreateEnvWithOptions` +4. Test shared allocator replacement via `OrtApi::CreateSharedAllocator` +5. Benchmark allocation performance vs. in-tree EP +6. Verify `use_env_allocators=1` works correctly (shared arena replaces per-session) + +--- + +## 7. Open Questions + +1. **Arena code sharing vs. copying.** Should the CUDA plugin copy `ep_arena.h/cc` verbatim, or should there be a shared location for the arena code that multiple plugin EPs can use? Copying is simpler and avoids coupling, but risks divergence if bugs are found. A shared `plugin_arena/` directory under `onnxruntime/test/autoep/library/` (or a new location) could be consumed by multiple plugin EPs. diff --git a/docs/cuda_plugin_ep/cuda_graph_for_cuda_plugin.md b/docs/cuda_plugin_ep/cuda_graph_for_cuda_plugin.md new file mode 100644 index 0000000000000..8092a15e26973 --- /dev/null +++ b/docs/cuda_plugin_ep/cuda_graph_for_cuda_plugin.md @@ -0,0 +1,134 @@ +# CUDA Graph Support for CUDA Plugin EP + +## Design Overview + +### Background + +The CUDA Plugin EP is a standalone shared library (`libonnxruntime_providers_cuda_plugin.so`) that implements the OrtEp C API, allowing CUDA EP updates independent of ORT releases. CUDA graph capture/replay is a critical performance optimization that records a sequence of GPU operations into a graph, then replays it with minimal CPU overhead on subsequent runs. + +The OrtEp C API (v1.26+) provides four graph-capture callbacks: + +| Callback | Signature | Purpose | +|----------|-----------|---------| +| `IsGraphCaptureEnabled` | `bool(const OrtEp*)` | Report whether graph capture is enabled | +| `IsGraphCaptured` | `bool(const OrtEp*, int graph_annotation_id)` | Check if a graph has been captured for a given annotation ID | +| `ReplayGraph` | `OrtStatus*(OrtEp*, int graph_annotation_id)` | Launch a previously captured graph | +| `GetGraphCaptureNodeAssignmentPolicy` | `OrtGraphCaptureNodeAssignmentPolicy(const OrtEp*)` | Specify validation strictness for node assignment | + +These are supplemented by the existing `OnRunStart` / `OnRunEnd` lifecycle callbacks that drive the capture workflow. + +### Architecture + +``` +Session::Run() + │ + ├─ Run 1..N (warmup): OnRunStart → kernel dispatch → OnRunEnd (increment counter) + │ + ├─ Run N+1 (capture): OnRunStart → cudaStreamBeginCapture → kernel dispatch + │ → OnRunEnd → cudaStreamEndCapture → cudaGraphInstantiate → Replay + │ + └─ Run N+2+ (replay): IsGraphCaptured() → true → ReplayGraph() → cudaGraphLaunch + (OnRunStart/OnRunEnd are NOT called during replay) +``` + +**Key design choices:** + +- Each thread gets its own dedicated graph `cudaStream_t`, `CudaGraphManager`, and capture bookkeeping for the EP instance. `CudaSyncStream::InitHandlesWithExternalStream()` wraps the thread's graph stream so graph capture sees the same stream as kernels. The manager stores captured `cudaGraphExec_t` executables keyed by annotation ID, allowing multiple graphs (e.g., different input shapes) for that thread. +- Warm-up runs (default: 2) allow memory allocations to stabilize before capture begins. +- Graph annotation IDs are parsed from `OrtRunOptions` key `"gpu_graph_id"`. ID `-1` skips capture; `0` is the default. + +### New Components + +- **`CudaGraphSet`** — Hash map storage for `cudaGraphExec_t`, keyed by annotation ID. Owns the CUDA graph exec resources. +- **`CudaGraphManager`** — Orchestrates capture lifecycle: `CaptureBegin()`, `CaptureEnd()`, `Replay()`, warm-up tracking via `IncrementRegularRunCount()` / `IsGraphCaptureAllowed()`. +- **`CudaEp::PerThreadContext`** — Per-thread owner for the graph stream, `CudaGraphManager`, and the pre-capture free-memory watermark. The context is owned by a thread-local cache keyed by `CudaEp*`, so it is destroyed automatically when that thread exits. `CudaEp` keeps weak references to live thread-local cache maps only so it can erase its entry during EP teardown, and it prunes expired cache-map references while creating new contexts. +- **`CudaSyncStream::InitHandlesWithExternalStream()`** — Wraps an external (non-owned) `cudaStream_t` for registration/lifecycle tracking. Migrated kernels bind cuBLAS/cuDNN/cuBLASLt through thread-local fallback handles at dispatch time when the wrapper does not own library handles. + +### Config Options + +| Option Key | Type | Default | Description | +|-----------|------|---------|-------------| +| `ep.cudapluginexecutionprovider.enable_cuda_graph` | bool | false | Enable CUDA graph capture/replay | +| `ep.cudapluginexecutionprovider.min_num_runs_before_cuda_graph_capture` | int | 2 | Warmup runs before capture | + +Legacy aliases `ep.cuda.enable_cuda_graph` and `enable_cuda_graph` are also supported. For the warm-up count, `ep.cuda.min_num_runs_before_cuda_graph_capture` is also accepted. + +--- + +## Implementation Summary + +### Files Changed + +| File | Change | +|------|--------| +| `onnxruntime/core/providers/cuda/plugin/cuda_ep.cc` | Implemented graph capture callbacks (`OnRunStartImpl`, `OnRunEndImpl`, `IsGraphCaptureEnabledImpl`, `IsGraphCapturedImpl`, `ReplayGraphImpl`, `IsConcurrentRunSupportedImpl`), updated `CreateSyncStreamForDeviceImpl` to use the current thread's graph stream when graph capture is enabled, added per-thread graph state, preserved `sync_stream` synchronization, and added a `cudaMemGetInfo` defensive allocation check | +| `onnxruntime/core/providers/cuda/plugin/cuda_ep.h` | Added `enable_cuda_graph` and `min_num_runs_before_cuda_graph_capture` config fields, graph callback declarations, and a per-thread graph context cache | +| `onnxruntime/core/providers/cuda/plugin/cuda_graph_plugin.cc` | **NEW** — Complete `CudaGraphSet` and `CudaGraphManager` implementation | +| `onnxruntime/core/providers/cuda/plugin/cuda_graph_plugin.h` | **NEW** — Header for graph manager types and constants | +| `onnxruntime/core/providers/cuda/plugin/cuda_stream_plugin.cc` | Added `InitHandlesWithExternalStream()`, updated destructor for `owns_stream_` | +| `onnxruntime/core/providers/cuda/plugin/cuda_stream_plugin.h` | Added `InitHandlesWithExternalStream()` declaration, `owns_stream_` member | +| `onnxruntime/core/providers/cuda/plugin/cuda_ep_factory.cc` | Added config parsing for `enable_cuda_graph` and `min_num_runs_before_cuda_graph_capture` | +| `include/onnxruntime/core/session/onnxruntime_ep_c_api.h` | Added `IsGraphCaptureEnabled`, `IsGraphCaptured`, `ReplayGraph`, `GetGraphCaptureNodeAssignmentPolicy` callbacks and `OrtGraphCaptureNodeAssignmentPolicy` enum to `OrtEp` | +| `include/onnxruntime/core/framework/execution_provider.h` | Added `GetGraphCaptureNodeAssignmentPolicy()` virtual to `IExecutionProvider` | +| `onnxruntime/core/session/inference_session.cc` | Replaced hard-coded EP name list with policy-driven graph capture validation loop; added bounded recursion via `RunImpl()` with `kMaxGraphCaptureWarmupRuns`; graph-enabled runs now reacquire stream collections through ORT core's thread-affine pool across internal warm-up/capture recursion | +| `onnxruntime/core/framework/session_state.cc` | Sharded the `DeviceStreamCollection` cache by caller thread using per-thread lifetime tokens, so stream wrappers are only reused on the creating thread | +| `onnxruntime/core/framework/session_state.h` | Added thread-affine stream pool bucket state for `DeviceStreamCollection` reuse | +| `onnxruntime/core/session/inference_session.h` | Added `RunImpl()` private method and `kMaxGraphCaptureWarmupRuns` constant | +| `onnxruntime/core/session/plugin_ep/ep_plugin_provider_interfaces.cc` | Added version-gated `IsGraphCaptureEnabled`, `IsGraphCaptured`, `ReplayGraph`, `GetGraphCaptureNodeAssignmentPolicy` bridge implementations | +| `onnxruntime/core/providers/webgpu/ep/ep.cc` | Added graph capture callback delegation to underlying `IExecutionProvider` | + +### Key Design Decisions + +- **`GetGraphCaptureNodeAssignmentPolicy`**: Returns `ALLOW_CPU_FOR_SHAPES` — consistent with the non-plugin CUDA EP behavior and allows shape-inference nodes on CPU. +- **Thread safety**: Mutable graph state and graph streams are stored per thread. ORT core's `DeviceStreamCollection` cache is also thread-affine, so graph-enabled runs can recycle stream wrappers without exposing them to a different thread. +- **Scope**: Capture/replay pipeline plus allocator compatibility. Arena integration is complete — see the [Arena Allocator Integration](#arena-allocator-integration) section. +- **Callback assignment**: `IsGraphCaptureEnabled` and `GetGraphCaptureNodeAssignmentPolicy` are always set. `OnRunStart`, `OnRunEnd` are conditional on `enable_cuda_graph`. `IsGraphCaptured` and `ReplayGraph` are always set (return false/error when disabled). +- **Stream management**: `CreateSyncStreamForDevice` remains unconditional — it branches internally to use the current thread's graph stream (via `InitHandlesWithExternalStream`) when graph capture is enabled, or creates an owned stream when disabled. +- **Run-end synchronization**: `OnRunEndImpl` honors the `sync_stream` flag without double-synchronizing replayed graphs, preserving the normal EP completion contract. +- **Stream collection reuse**: ORT core now recycles `DeviceStreamCollection` objects into a thread-affine session pool keyed by a per-thread lifetime token. Warm-up, capture, replay, and later user-visible `Run()` calls on the same thread can reuse the same stream wrappers, while dead-thread buckets are pruned before they can be reused by another thread. +- **Per-thread context lifecycle**: Thread-local caches hold the strong `PerThreadContext` references, so CUDA streams and captured graph executables are released when the owning thread exits. The EP tracks weak references to those cache maps to remove stale entries during EP destruction without keeping the contexts alive. + +### Arena Allocator Integration + +CUDA graph capture requires that all memory allocations happen during warmup, not during capture. The plugin arena allocator (PR #27931) is now landed and integrated with the graph capture path. + +**Allocation-during-capture detection:** + +- `OnRunStartImpl` records free GPU memory in the per-thread context via `cudaMemGetInfo` before `CaptureBegin`. +- `OnRunEndImpl` compares post-capture free memory in the same per-thread context. If it decreased, a warning is logged advising the user to increase `min_num_runs_before_cuda_graph_capture`. +- This `cudaMemGetInfo` check is retained as a last-line diagnostic after arena integration, because custom arena options, insufficient warm-up, or regressions can still surface allocation-during-capture issues. + +**Arena integration details (now implemented):** + +- Default CUDA device allocations come from the plugin-hosted arena (`CudaArenaAllocator`). During warmup runs, the arena grows to accommodate all needed chunks; during capture and replay, the same chunks are reused without `cudaMalloc` calls. +- When `arena.use_cuda_mempool=1` is configured, CUDA device allocations come from `CudaMempoolOrtAllocator`, which wraps `cudaMallocFromPoolAsync`/`cudaFreeAsync`. These async allocation/free operations are CUDA-graph-safe since CUDA 11.4+ and become part of the captured graph topology. +- Pinned allocations are also arena-backed, but remain non-stream-aware. +- The graph stream created by `CudaEp::PerThreadContext` flows through `CudaSyncStream::InitHandlesWithExternalStream()` so stream-aware arena allocation uses the same `cudaStream_t` during warm-up, capture, and replay. +- `CudaSyncStream::OnSessionRunEndImpl()` resets arena chunk-to-stream assignments via `factory_.ResetDeviceArenaChunksUsingStream()` at the end of each run, even for graph-enabled runs. `OnSessionRunEnd` executes before the stream collection is recycled into the current thread's pool bucket. +- The plugin allocator's `OrtMemoryInfo::alloc_type` stays as `OrtDeviceAllocator`; the arena remains opaque to ORT core. + +### Concurrent Run Support + +Concurrent `Session::Run()` is supported with CUDA graph enabled: + +- `CudaEp::PerThreadContext` owns the graph stream, graph manager, warm-up run counts, and memory watermark for the current thread. +- The current thread's cache owns the `PerThreadContext`; new threads get independent contexts, and exited threads release their contexts automatically. +- `CreateSyncStreamForDeviceImpl()` wraps the current thread's graph stream, so warm-up, capture, and replay all use the same stream for that thread. +- `CudaGraphManager::CaptureBegin()` uses `cudaStreamCaptureModeThreadLocal`, allowing overlapping capture scopes on different threads. +- ORT core recycles graph-enabled `DeviceStreamCollection` objects into a thread-affine session pool, so internal warm-up/capture recursion and later top-level `Run()` calls on the same thread reuse the same stream wrappers without cross-thread leakage. +- `IsGraphCaptured()` and `ReplayGraph()` resolve the current thread's graph context. If a new thread runs a graph-enabled session for the first time, that thread performs its own warm-up and capture before replaying. + +## Verification + +1. Build and deploy the plugin using the instructions in [QUICK_START.md](QUICK_START.md#build-instructions) and [QUICK_START.md](QUICK_START.md#running-tests). +2. Run `onnxruntime/test/python/transformers/test_cuda_plugin_ep.py` as described in [QUICK_START.md](QUICK_START.md#running-tests). +3. The CUDA graph tests in that script validate: + - `test_cuda_graph_capture_and_replay` — warmup + capture + replay with default arena + - `test_cuda_graph_replay_with_updated_input` — in-place input update after graph capture + - `test_cuda_graph_with_mempool` — graph capture with `arena.use_cuda_mempool=1` + - `test_cuda_graph_annotation_id` — multiple graphs via `gpu_graph_id` run config + - `test_cuda_graph_add_model` — graph capture with Add op (arena-backed) + +## Future Work + +1. **Profiling integration**: CUDA graph replay currently bypasses the CUDA plugin EP profiler path because the CUDA plugin EP does not yet implement `OrtEp::CreateProfiler`. Wiring graph replay into that path is future work. diff --git a/docs/cuda_plugin_ep/cuda_plugin_ep_design.md b/docs/cuda_plugin_ep/cuda_plugin_ep_design.md new file mode 100644 index 0000000000000..15f8188505b37 --- /dev/null +++ b/docs/cuda_plugin_ep/cuda_plugin_ep_design.md @@ -0,0 +1,981 @@ +# CUDA Plugin EP — Design Document + +## 1. Overview + +The CUDA Plugin EP is an alternative build of the ONNX Runtime CUDA Execution Provider that compiles as a standalone shared library (`libonnxruntime_providers_cuda_plugin.so`). It loads at runtime through the ORT EP Plugin API instead of being statically linked into the main runtime binary. + +**Goals:** +- Allow CUDA EP updates independent of ORT core releases +- Support all operators currently supported by the in-tree CUDA EP (tunable ops are low priority) +- Minimize changes to existing CUDA kernel source files + +**Current status:** The plugin build is functional. Most core CUDA kernels now compile in the plugin build; the remaining source-level exclusions are documented in [Section 7](#7-excluded-operators). + +--- + +## 2. Architecture + +### 2.1 Build Targets + +The ORT CUDA build produces four separate libraries: + +| Target | Output | Type | Description | +|--------|--------|------|-------------| +| `onnxruntime_providers` | `libonnxruntime_providers.a` | Static lib | CPU provider + framework ops | +| `onnxruntime_providers_shared` | `libonnxruntime_providers_shared.so` | Shared lib | DLL-boundary bridge for in-tree EPs | +| `onnxruntime_providers_cuda` | `libonnxruntime_providers_cuda.so` | Shared module | In-tree CUDA EP (uses `SHARED_PROVIDER` bridge) | +| `onnxruntime_providers_cuda_plugin` | `libonnxruntime_providers_cuda_plugin.so` | Shared module | Plugin CUDA EP (uses EP API adapters) | + +### 2.2 Preprocessor Defines + +Each build target uses different preprocessor defines that control how framework types are resolved: + +| Define | Set In | Purpose | +|--------|--------|---------| +| `SHARED_PROVIDER` | `onnxruntime_providers_shared`, `onnxruntime_providers_cuda` | Activates the DLL-boundary proxy types in `provider_api.h` | +| `BUILD_CUDA_EP_AS_PLUGIN` | `onnxruntime_providers_cuda_plugin` | Makes `provider_api.h` a no-op; activates plugin-specific code paths | +| `ORT_USE_EP_API_ADAPTERS` | `onnxruntime_providers_cuda_plugin` | Enables the EP adapter type aliases (`ep/adapters.h`) | +| `ORT_API_MANUAL_INIT` | `onnxruntime_providers_cuda_plugin` | Manual ORT API initialization in plugin DLL | + +### 2.3 Class Hierarchy + +``` +OrtEpFactory OrtEp + ↑ ↑ +CudaEpFactory adapter::Ep + │ ↑ + ├─ creates OrtEpDevice CudaEp + ├─ provides fallback ├─ stores session-derived Config + │ CreateSyncStreamForDevice ├─ implements OrtEp::CreateSyncStreamForDevice + ├─ caches kernel registry │ for per-session CudaSyncStream creation + ├─ caches stable OrtMemoryInfo ├─ synchronizes device (Sync) + └─ maps OrtHardwareDevice* └─ owns a real shim CUDAExecutionProvider via EpImpl() + → CUDA ordinal + +Migrated CUDA kernels + └─ use CudaKernel / cuda_kernel_adapter.h + ├─ cache a shared runtime-config handle during construction + ├─ use CudaKernel accessors for provider settings during Compute() + └─ resolve stream-local handles via CudaSyncStream::FromCudaStream() +``` + +Key ownership relationships: +- `CudaEpFactory` implements raw `OrtEpFactory` callbacks and owns shared factory-level state such as the kernel registry, cached `OrtMemoryInfo` instances, and the hardware-device to CUDA-ordinal map. +- `CudaEpFactory` also implements the factory-level `OrtEpFactory::CreateSyncStreamForDevice` callback as a fallback path when the `OrtEp` callback is not used. +- `CudaEp` inherits from `ep::adapter::Ep`, which itself derives from `OrtEp` and owns a framework-facing `IExecutionProvider` object. +- `CudaEp` implements the `OrtEp::CreateSyncStreamForDevice` callback, which is the per-session stream-creation entry point used in preference to the factory callback. +- The plugin-local `CUDAExecutionProvider` in `cuda_kernel_adapter.h` is a real shim object owned by `ep::adapter::Ep`. It is not the full in-tree CUDA EP, but it has its own object identity and stores plugin-specific members — including the wrapped `OrtEp*` and a provider-owned shared runtime-config object. +- Runtime configuration needed by migrated kernels is stored on that shim provider and exposed to kernels as a cached `shared_ptr`, rather than through a separate global map keyed by the provider address. +- `CudaSyncStream` owns `cudaStream_t`, `cublasHandle_t`, `cudnnHandle_t`, and `cublasLtHandle_t` for each sync stream created through the EP API. + +### 2.4 Plugin DLL Entry Points + +The plugin exports exactly two C symbols: +- `CreateEpFactories()` — called by ORT to create the EP factory +- `ReleaseEpFactory()` — called by ORT to destroy the factory + +All other symbols have hidden visibility. + +--- + +## 3. Type Resolution — How Kernel Code Compiles Unchanged + +The core design principle is that existing CUDA kernel `.cc` files compile in the plugin build with **zero or minimal source changes**. This is achieved through a two-layer force-include mechanism. + +### 3.1 Force-Include Chain + +For every `.cc` file in the plugin build, CMake injects two force-includes before any source code: + +``` +1. ep/adapters.h — adapter type aliasing +2. cuda_kernel_adapter.h — CudaKernel base class, macros, CPU shims +``` + +Note: `.cu` files do NOT receive force-includes (conflicts with CUTLASS/cute). They must include `cuda_kernel_adapter.h` explicitly if needed. + +### 3.2 Adapter Type Aliasing (`ep/adapters.h`) + +`ep/adapters.h` defines `using` aliases in both `onnxruntime::cuda` and `onnxruntime::contrib::cuda` namespaces: + +```cpp +namespace onnxruntime::cuda { + using OpKernel = ep::adapter::OpKernel; + using OpKernelContext = ep::adapter::OpKernelContext; + using OpKernelInfo = ep::adapter::OpKernelInfo; + using KernelRegistry = ep::adapter::KernelRegistry; + using KernelDefBuilder = ep::adapter::KernelDefBuilder; + using DataTransferManager = ep::adapter::DataTransferManager; + // ... etc +} +``` + +When kernel code in `namespace onnxruntime::cuda` references `OpKernelContext`, it resolves to the adapter type instead of the framework type. **No kernel source changes needed.** + +### 3.3 Provider API Bypass + +In the plugin build, `provider_api.h` (normally included from `cuda_common.h`) is a **complete no-op** — it does NOT define `SHARED_PROVIDER`. This means: + +- `#ifndef SHARED_PROVIDER` guards in framework headers remain **active**, exposing real types +- Header-inlined utility methods (see [Section 4](#4-cpu-base-class-helpers)) get their inline bodies +- The `ProviderHostCPU` virtual table bridge is bypassed entirely + +### 3.4 Kernel Adapter (`cuda_kernel_adapter.h`) + +This 1100+ line header provides everything CUDA kernels need that would normally come from framework infrastructure: + +| Section | What It Provides | +|---------|-----------------| +| Error macros | `CUDA_RETURN_IF_ERROR`, `CUBLAS_RETURN_IF_ERROR`, `CUDNN_RETURN_IF_ERROR`, `CUFFT_RETURN_IF_ERROR` | +| Type mappings | `ToCudaType::MappedType = half`, etc. | +| CudaKernel base | Scratch buffers, handle access, `Stream()`, `GetComputeStream()` | +| Kernel registration | Self-registering `ONNX_OPERATOR_*_KERNEL_EX` macro overrides via `PluginKernelCollector`, including `ONNX_OPERATOR_TWO_TYPED_KERNEL_EX`, `ONNX_OPERATOR_VERSIONED_TWO_TYPED_KERNEL_EX`, and `ONNX_OPERATOR_THREE_TYPED_KERNEL_EX` variants | +| CPU shims | Lightweight reimplementations of CPU helpers not linked into plugin | +| Math helpers | `HalfGemmOptions`, `CublasMathModeSetter` | +| Stream shim | `OrtStreamAdapter`/`PluginStreamShim` to present a framework-compatible `Stream*` view over a raw `cudaStream_t` where needed | + +### 3.5 Kernel Registration + +In the in-tree build, kernels register through centralized tables (`cuda_nhwc_kernels.cc`, `cuda_contrib_kernels.cc`). In the plugin build, the `ONNX_OPERATOR_*_KERNEL_EX` macros are overridden to auto-register each kernel into the `PluginKernelCollector` singleton at static initialization time: + +```cpp +// Macro override generates: +// 1. BuildKernelCreateInfo() function +// 2. Static PluginKernelCollector::Register() call + +// At plugin startup, CreateCudaKernelRegistry() iterates the collector +// and registers each kernel into an adapter::KernelRegistry. +``` + +#### 3.5.1 Type Constraint Names and OpSchema Access + +Every kernel registration includes type constraint names — string literals such as `"T"`, `"T1"`, `"U"` — that must exactly match the formal parameter type-constraint strings defined in the ONNX operator schema. In the current plugin build, these names are **hard-coded** at compile time with no runtime validation against the actual schema. If a constraint name is wrong, kernel matching silently fails during `GetCapability`. + +PR #27713 adds `OrtEpApi` functions that let plugin EPs query ONNX operator schemas from ORT's global schema registry at runtime (available from ORT 1.25): + +| `OrtEpApi` Function | C++ Wrapper | Purpose | +|---------------------|-------------|----------| +| `GetOpSchema(name, max_ver, domain)` | `Ort::GetOpSchema()` | Look up a schema by op name, max opset version, and domain | +| `OpSchema_GetSinceVersion` | `ConstOpSchema::GetSinceVersion()` | Opset version that introduced this schema entry | +| `OpSchema_GetNumInputs` / `_GetNumOutputs` | `GetNumInputs()` / `GetNumOutputs()` | Formal input/output count | +| `OpSchema_GetInputName` / `_GetOutputName` | `GetInputName(i)` / `GetOutputName(i)` | Formal parameter name | +| `OpSchema_GetInputTypeStr` / `_GetOutputTypeStr` | `GetInputTypeStr(i)` / `GetOutputTypeStr(i)` | Type constraint string (e.g., `"T"`) | +| `OpSchema_HasTypeConstraint` | `HasTypeConstraint(str)` | Whether a string is a valid type constraint name in the schema | + +The returned `OrtOpSchema*` is non-owning — it points into the global `ONNX_NAMESPACE::OpSchemaRegistry` singleton and is valid for the lifetime of the ORT process. + +**Why the plugin cannot link its own ONNX library:** The `OpSchemaRegistry` is a Meyers singleton (`static` local in `Instance()`). Each shared library gets its own copy of that static variable — on Windows each DLL is isolated by default, on macOS two-level namespaces have the same effect, and on Linux behavior depends on `dlopen` flags. Even when isolation doesn't occur, the EP's registry would lack ORT's contrib and internal schemas, and version mismatches between the EP's ONNX library and ORT's vendored copy could cause silent divergence. The `OrtEpApi` route is the only reliable, portable way to query the schemas ORT actually uses. + +**Impact on the CUDA plugin EP:** + +1. **Registration-time validation.** `CreateCudaKernelRegistry()` can optionally validate each registered kernel's type constraint names against the schema after collecting all entries from `PluginKernelCollector`. A mismatch can be logged as a warning (debug builds) or an error, catching drift when ONNX spec updates rename constraint strings. + +2. **NHWC / internal-domain diagnostics.** For rewritten `com.ms.internal.nhwc` nodes, the schema API can confirm that the kernel's registered domain, version range, and constraint names actually match the internal-domain schema entry, improving the diagnostics called for in [Section 5.3.1.3](#5313-nhwc-design-requirements). + +3. **Parity tooling.** `cuda_plugin_parity_report.py` can use the C++ wrapper to compare the plugin's registered constraint names against the schema, flagging incorrect or missing constraints in the parity report. + +4. **Future: schema-driven registration helpers.** A `KernelDefBuilder` helper could derive constraint names automatically from the schema rather than relying on hard-coded strings, reducing the manual maintenance burden when new opset versions change constraint names. See [Section 11.6](#116-if-opschema-access-is-available-schema-validated-type-constraints). + +--- + +## 4. CPU Base Class Helpers — The SHARED_PROVIDER Pattern + +Many CUDA kernels inherit from CPU base classes and call utility methods (e.g., `PadBase::HandleDimValueZero`, `SliceBase::PrepareForCompute`). In the in-tree build, these call across the DLL boundary through `ProviderHostCPU`. The plugin doesn't use this bridge. + +### 4.1 Pattern: Inline in Header + +The primary approach moves pure-computation helpers from CPU `.cc` files to headers: + +```cpp +// In padbase.h: +#ifdef SHARED_PROVIDER + // In-tree build: declaration only, body in ProviderHostCPU bridge + static void HandleDimValueZero(Mode mode, const TensorShape& input_shape, TensorShape& output_shape); +#else + // Plugin build + CPU provider: inline body + static inline void HandleDimValueZero(Mode mode, const TensorShape& input_shape, + TensorShape& output_shape) { + // ... implementation ... + } +#endif +``` + +**Files refactored with this pattern:** +- `padbase.h` — `HandleDimValueZero`, `ComputePads` (delegates to `ComputePadsImpl` template) +- `scatter_nd.h` — `ValidateShapes` +- `split.h` — `PrepareForCompute` +- `tile.h` — `IsTileMemcpy` +- `slice.h` — `PrepareForCompute`, `FlattenOutputDims` +- `cumsum.h` — `cumsum_op::GetAxis` +- `bias_gelu_helper.h` — `bias_gelu_helper::CheckInputs` +- `concatbase.h` — `PrepareForCompute` +- `gatherbase.h` — `PrepareForCompute`/`PrepareForComputeImpl` (template) +- `unsqueeze.h` — `PrepareCompute` +- `embed_layer_norm_helper.h` — `embed_layer_norm::CheckInputs` (templatized on context type) +- `non_max_suppression_helper.h` — `NonMaxSuppressionBaseImpl` template class (new file) +- `attention_base.h` — `AttentionBase::CheckInputs`, `CheckMask`, `GetPresent` (templatized on context type) +- `longformer_attention_base.h` — `LongformerAttentionBase::CheckInputs` +- `roialign.h` — `CheckROIAlignValidInput`, `RoiAlignBase` constructor (templatized on info type) +- `upsamplebase.h` — `UpsampleBase::AdjustOutputSizeAsPolicy` +- `crop.h` — `CropBase` constructor (templatized on info type) +- `space_depth_ops.h` — `SpaceDepthBase` constructor plus shared `ReadBlocksize`, `ReadIsDCR`, and dimension-validation helpers (templatized on info/context type where needed) +- `clip.h` — Clip min/max attribute handling (removed `Clip_6Base` CPU dependency) +- `cuda_common_type_helpers.h` — CUDA type conversion and handle error string helpers (moved from `cuda_common.cc`) + +### 4.2 Pattern: Template Methods + +For methods that take `OpKernelContext&` (which differs between plugin and in-tree builds), template versions accept any context type: + +```cpp +// In padbase.h: +template +static void ComputePadsImpl(KernelContextType& ctx, size_t data_rank, + gsl::span pads_data, PadsVector& pads) { ... } +``` + +The CUDA kernel calls `PadBase::ComputePadsImpl(*ctx, ...)` directly, avoiding the `OpKernelContext&` type mismatch. + +The same pattern is applied to constructors that receive `OpKernelInfo`: + +```cpp +// In roialign.h: +template +RoiAlignBase(const TKernelInfo& info) { + info.template GetAttr("mode", &mode_string); + info.template GetAttr("output_height", &output_height_); + // ... +} +``` + +This allows the base class constructor to work with both the framework `OpKernelInfo` and the plugin adapter's `OpKernelInfo`. Applied to: `RoiAlignBase`, `CropBase`, `SpaceDepthBase` (#27628). + +### 4.3 Files That Cannot Be Inlined + +Some CPU base classes have heavy dependencies (protobuf, `UnpackTensor`) that make inlining impractical: + +- **`ConstantOfShapeBase`** — depends on `TensorProto` and `UnpackTensor`. The plugin path in `constant_of_shape.h` stays self-contained: it reuses `ConstantOfShapeCore` but fetches the `value` attribute through the ORT C++ API instead of depending on the full CPU base implementation. + +`UpsampleBase` no longer belongs in this category: the adapter now exposes `OpKernelInfo::GetAllocator(OrtMemType)`, and the remaining shape-rank query already has an adapter-safe fallback when `Node::InputDefs()` is unavailable. That lets the CUDA `Upsample` antialias path reuse the same persistent device lookup-table initialization in both bundled and plugin builds instead of keeping a plugin-only scratch-buffer fallback. + +--- + +## 5. Handle and Stream Management + +### 5.1 Stream Ownership + +`CudaSyncStream` is the plugin's CUDA sync-stream implementation: +- Owns `cudaStream_t`, `cublasHandle_t`, `cudnnHandle_t`, `cublasLtHandle_t` +- Can be created at two levels: + - **OrtEp-level** via `CudaEp::CreateSyncStreamForDeviceImpl` for per-session stream creation + - **OrtEpFactory-level** via `CudaEpFactory::CreateSyncStreamForDeviceImpl` as the fallback path +- Registers itself in a global `cudaStream_t -> CudaSyncStream*` map so migrated kernels can recover per-stream handles from a raw CUDA stream +- Defers host-buffer cleanup until `OnSessionRunEnd()` after the stream is synchronized + +#### 5.1.1 Device Synchronization (Sync API) + +`CudaEp` implements `OrtEp::Sync` to block until the configured CUDA device has completed all preceding work. ORT uses this path for scenarios such as `IOBinding`, where asynchronous input copies must finish before kernel execution begins. + +Implementation details: +- `CudaEp::SyncImpl` temporarily switches to the EP's configured device via `cudaSetDevice(device_id)` and restores the caller's previous CUDA device before returning +- It then issues `cudaDeviceSynchronize()` as a conservative device-wide barrier + +This is intentionally conservative and correct for the plugin EP's first sync integration. A narrower stream-scoped synchronization strategy can be considered later if profiling shows a need. + +### 5.2 Handle Access Path + +``` +CudaKernel::GetCublasHandle(OpKernelContext* ctx) + → Stream(ctx) // raw cudaStream_t from adapter ctx + → CudaSyncStream::FromCudaStream() // global stream map + TLS cache + → sync_stream->GetCublasHandle() +``` + +The stream lookup path uses a thread-local last-hit cache plus a generation counter so destroyed streams invalidate stale TLS entries without requiring per-thread cleanup. + +For code paths that need handles without an active stream, `cuda_kernel_adapter.h` also provides thread-local default cuBLAS/cuDNN handles via `GetDefaultCudaHandlesForDevice(device_id)`. + +### 5.3 Provider Access + +Kernels still discover the shim provider through the pointer returned by `info.GetExecutionProvider()` at construction time. In the plugin build, `ep::adapter::OpKernelInfo` snapshots three related pointers from the framework `OpKernelInfo` when the kernel is created: + +- the session-owned outer `PluginExecutionProvider` +- the wrapped plugin `OrtEp` / `CudaEp` +- the inner shim provider returned by `static_cast(ort_ep)->EpImpl()` + +`OpKernelInfo::GetExecutionProvider()` then returns that cached shim pointer, so migrated kernels receive the real shim `CUDAExecutionProvider` object owned by `ep::adapter::Ep`, not the outer `PluginExecutionProvider` and not the `OrtEp`/`CudaEp` object reinterpreted at the same address. + +Caching the shim pointer at kernel-creation time is important for the NHWC path. Re-querying `OrtKernelInfo -> OrtEp -> EpImpl()` during execution was fragile after layout transformation. The current implementation resolves the shim once in the `CudaKernel` constructor, caches a `shared_ptr`, and routes later provider-setting reads through `CudaKernel` accessors instead of repeated provider-pointer casts during `Compute()`. + +This changes the safety model from the earlier "phantom shim" design: +- The shim no longer needs to remain layout-compatible with `IExecutionProvider`. +- Adding plugin-local members to the shim is safe as long as normal C++ object lifetime/ownership rules are respected. +- The shim still is not the full bundled `CUDAExecutionProvider`; it only exposes the subset of methods that migrated kernels currently need. + +Provider options flow through the plugin in two stages: +- `CudaEpFactory` parses session/provider options into `CudaEp::Config`. +- `CudaEp` copies the subset needed by migrated kernels into the shim provider's runtime config via `SetCudaKernelAdapterRuntimeConfigForProvider(EpImpl(), ...)` during EP construction. + +Because the runtime config is provider-owned and cached by kernels as a shared pointer, there is no global map and no mutex. Today that stored subset includes TF32, device ID/device properties, cuDNN convolution settings, skip-layer-norm strict mode, fused-conv-bias, and SDPA kernel selection. Other plugin behaviors, such as preferred layout, are handled directly by `CudaEp` callbacks instead of through the shim. + +For stream bridging, the preferred helpers are: +- `Stream(ctx)` when the kernel only needs a raw `cudaStream_t` +- `GetComputeStream(ctx)` when the kernel API already accepts the adapter's opaque stream pointer +- `GetOrtStream(ctx)` when framework-style `Stream*` plumbing is still needed by shared helper code + +#### 5.3.1 NHWC Layout-Transformation Support + +The bundled CUDA EP's NHWC path is not just a kernel-registration feature. It is a coordinated contract between provider configuration, ORT's layout transformer, kernel registration, adapter/provider access, and graph partitioning. The current implementation supports this path when NHWC is compiled in and the session requests `prefer_nhwc`. + +#### 5.3.1.1 End-to-End Flow + +When NHWC is enabled for an EP, the expected ORT flow is: + +1. The EP reports `NHWC` from `GetPreferredLayout()` (or `OrtEp::GetPreferredDataLayout()` for plugins) when `prefer_nhwc` is enabled. +2. During layout transformation, ORT asks the EP whether each layout-sensitive op should be converted via `ShouldConvertDataLayoutForOp()`. +3. For each accepted op, `TransformLayoutForEP()` inserts `Transpose` nodes around the operator and rewrites the operator into the internal NHWC domain (`com.ms.internal.nhwc`). +4. Graph partitioning runs again. The EP must now claim the rewritten internal-domain nodes, not the original ONNX-domain nodes. +5. Kernel lookup must succeed against the EP's kernel registry for the rewritten internal-domain node, with matching domain, opset range, and type constraints. + +This means the plugin must satisfy two distinct contracts at the same time: + +| Contract | Owner | Requirement | +|----------|-------|-------------| +| Layout preference contract | `CudaEp` + ORT plugin bridge | Only request NHWC when the plugin can handle the rewritten graph | +| Kernel/capability contract | Kernel registry + `CudaEp::GetCapabilityImpl()` | Claim the resulting `com.ms.internal.nhwc` nodes during partitioning | + +#### 5.3.1.2 Current Plugin Status + +The current implementation already has the core runtime pieces in place: + +| Component | Current state | +|-----------|---------------| +| ORT plugin bridge | `PluginExecutionProvider` already maps `OrtEp::GetPreferredDataLayout()` and `OrtEp::ShouldConvertDataLayoutForOp()` into the normal `IExecutionProvider` layout APIs | +| Plugin callback implementations | `CudaEp` installs `GetPreferredDataLayoutImpl()` and `ShouldConvertDataLayoutForOpImpl()` and advertises NHWC when `prefer_nhwc` is enabled | +| Provider option parsing | `CudaEpFactory` already parses `prefer_nhwc` / `prefer_nhwc_layout` into `CudaEp::Config` | +| Build-time gating | `cmake/onnxruntime_providers_cuda_plugin.cmake` propagates `ENABLE_CUDA_NHWC_OPS` to the plugin target when `onnxruntime_USE_CUDA_NHWC_OPS=ON` | +| NHWC kernel registration | NHWC kernels are compiled from the normal CUDA kernel sources and self-register through `PluginKernelCollector`; the centralized `cuda_nhwc_kernels.cc` table stays excluded in plugin builds | +| Second capability pass | `CudaEp::GetCapabilityImpl()` preserves nodes already assigned to `CudaPluginExecutionProvider`, so ORT's post-layout-transformation partitioning pass does not drop rewritten NHWC nodes that were previously selected by the plugin | +| Adapter provider access | `ep::adapter::OpKernelInfo` caches the inner shim `EpImpl()` pointer at kernel-creation time, avoiding a fragile runtime `OrtKernelInfo -> OrtEp -> EpImpl()` round-trip in NHWC kernels | +| Focused validation | `test_cuda_plugin_ep.py` Stage 3 now runs NHWC-requested sessions for Conv, BatchNormalization, MaxPool, and AveragePool and requires plugin-backed execution to succeed numerically | + +The fixes that made this work were not limited to turning the callbacks back on: + +- The plugin now keeps both newly discovered candidate nodes and nodes already assigned to `CudaPluginExecutionProvider` during the second `GetCapability()` pass that runs after layout transformation. +- NHWC kernels now obtain provider configuration through the cached shim pointer in `ep::adapter::OpKernelInfo`, which removed a runtime crash path in migrated kernels such as NHWC `Conv`. + +With those pieces in place, NHWC-requested sessions take the real plugin execution path rather than silently falling back to the stable NCHW path. + +#### 5.3.1.3 NHWC Design Requirements + +The implementation should preserve the following invariants: + +| Requirement | Why it matters | +|-------------|----------------| +| The plugin must never advertise NHWC unless it can claim every internal-domain op it requests ORT to generate | Otherwise ORT can create an invalid graph containing `com.ms.internal.nhwc` nodes that no EP selects | +| The NHWC conversion allowlist must come from a single shared source of truth | The bundled CUDA EP and the plugin EP must not drift on which ops are safe to rewrite | +| Kernel coverage checks must validate internal-domain registrations, not just original ONNX-domain registrations | The rewritten graph uses `com.ms.internal.nhwc`, so ONNX-domain coverage alone is insufficient | +| Capability diagnostics must identify internal-domain kernel misses clearly | NHWC failures are difficult to debug after rewrite unless the missing domain/op/version/type information is surfaced | +| Tests must verify plugin-backed NHWC execution explicitly | Output correctness alone is not enough because a fallback path can still pass numerically | + +#### 5.3.1.4 Implemented Design and Remaining Follow-Ups + +The current implementation has the minimum runtime fixes required for plugin-side NHWC execution. The remaining work is mostly cleanup, consolidation, and stronger diagnostics. + +**A. Keep partitioning registry-driven and preserve pre-assigned NHWC nodes** + +`CudaEp::GetCapabilityImpl()` should continue to rely on `EpGraphSupportInfo_LookUpKernel()` as the source of truth for whether a rewritten node is supported. The important implementation detail is that it must preserve nodes already assigned to the plugin when ORT reruns partitioning after layout transformation. + +That behavior is now implemented by tracking: +- `tentative_nodes`: newly discovered nodes with matching kernel registrations +- `candidate_nodes`: both tentative nodes and nodes already assigned to `CudaPluginExecutionProvider` + +The final support set is chosen from `candidate_nodes`, with the existing CPU-preferred-node filtering applied only where appropriate. + +**B. Cache the shim provider pointer at kernel creation** + +Migrated CUDA kernels expect `info.GetExecutionProvider()` to return the shim `CUDAExecutionProvider`, not the outer `PluginExecutionProvider`. The adapter now resolves that relationship once during kernel creation, captures the shim provider's runtime-config object, and uses `CudaKernel` accessors for later provider-setting reads. + +This is especially important for NHWC kernels because layout transformation introduces additional runtime paths before the actual CUDA kernel executes. Repeatedly reconstructing provider access from `OrtKernelInfo` during execution proved fragile in that path. The cached-config approach keeps provider access deterministic and matches the actual object model: + +- outer session EP: `PluginExecutionProvider` +- wrapped plugin object: `CudaEp` / `ep::adapter::Ep` +- inner shim: `CUDAExecutionProvider` returned by `EpImpl()` + +**C. Remaining follow-ups** + +The main follow-ups are now design quality items rather than blockers: + +- Unify the NHWC conversion allowlist between the bundled CUDA EP and the plugin CUDA EP instead of keeping separate hard-coded tables. +- Improve diagnostics when kernel lookup fails for a rewritten `com.ms.internal.nhwc` node. +- Extend tests to assert internal-domain rewrite structure directly, not just plugin-backed execution and numerical correctness. + +#### 5.3.1.5 Rollout Status + +The NHWC rollout is effectively in a "runtime enabled, cleanup remaining" state: + +| Phase | Change | Expected outcome | +|-------|--------|------------------| +| 1 | Enable plugin NHWC callbacks and preserve pre-assigned nodes in the second capability pass | Implemented | +| 2 | Cache the shim provider pointer in the adapter `OpKernelInfo` | Implemented; fixes the observed NHWC runtime crash | +| 3 | Consolidate allowlists, improve internal-domain diagnostics, and strengthen structural NHWC assertions | Recommended follow-up work | + +### 5.4 CUDA Graph Support + +CUDA Graph capture/replay is fully implemented for the plugin EP, including arena integration (both default BFC arena and CUDA native mempool), multi-graph via annotation IDs with different input shapes, and concurrent `Session::Run()` support. The full design — plugin-side implementation, per-thread isolation, arena integration, capture flow, and concurrent run details — is in [cuda_graph_for_cuda_plugin.md](cuda_graph_for_cuda_plugin.md). This section documents only the framework-level and C API changes that affect the broader ORT architecture. + +#### 5.4.1 OrtEp C API Extensions (v1.26) + +Four new optional callbacks in `OrtEp` (`onnxruntime_ep_c_api.h`): + +| Callback | Signature | Default (NULL) | Purpose | +|----------|-----------|----------------|---------| +| `IsGraphCaptureEnabled` | `bool(const OrtEp*)` | `false` | Report whether graph capture is enabled | +| `IsGraphCaptured` | `bool(const OrtEp*, int graph_annotation_id)` | `false` | Check if a graph has been captured for a given annotation ID | +| `ReplayGraph` | `OrtStatus*(OrtEp*, int graph_annotation_id)` | OK | Launch a previously captured graph | +| `GetGraphCaptureNodeAssignmentPolicy` | `OrtGraphCaptureNodeAssignmentPolicy(const OrtEp*)` | `ALL_NODES_ON_EP` | Specify validation strictness for node assignment | + +These are supplemented by the existing `OnRunStart` / `OnRunEnd` lifecycle callbacks that drive the capture workflow. + +The `PluginExecutionProvider` bridge (`ep_plugin_provider_interfaces.cc`) delegates to these callbacks with version gating (`ort_version_supported >= 26`), falling back to safe defaults for older plugins. + +#### 5.4.2 Framework Changes + +The `IExecutionProvider` base class gained a `GetGraphCaptureNodeAssignmentPolicy()` virtual (default: `ALL_NODES_ON_EP`). All in-tree EPs with graph capture (CUDA, DML, JS, WebGPU) override to `ALLOW_CPU_FOR_SHAPES`. + +Session-level changes in `inference_session.cc`: + +- **Policy-driven validation**: Graph capture validation at session initialization now iterates all EPs and queries `GetGraphCaptureNodeAssignmentPolicy()` instead of hard-coding EP name lists. +- **Bounded recursion**: After each normal run when graph capture is enabled, the session recursively calls `RunImpl()` (bounded by `kMaxGraphCaptureWarmupRuns = 8`) until the graph is captured. From the user's perspective, a single `Run()` call handles the entire warm-up + capture sequence. +- **Stream collection lifetime**: ORT core now caches `DeviceStreamCollection` objects in thread-affine session buckets keyed by a per-thread lifetime token. Graph-enabled runs recycle and reacquire stream wrappers only on the creating thread, which preserves warm-up/capture reuse without cross-thread leakage. + +--- + +## 6. EP Adapter Layer (`include/onnxruntime/ep/adapter/`) + +The adapter layer provides thin wrappers around the ORT C API that present a C++ interface matching the framework types: + +| Adapter Class | Wraps | Key Methods | +|---------------|-------|-------------| +| `OpKernel` | `OrtKernelImpl` | `Compute()`, `PrePack()` | +| `OpKernelContext` | `OrtKernelContext` | `Input()`, `Output()`, `InputCount()`, `GetGPUComputeStream()`, `GetComputeStream()` | +| `OpKernelInfo` | `Ort::ConstKernelInfo` | `GetAttr()`, `GetExecutionProvider()`, `TryGetConstantInput()`, `GetDataTransferManager()` | +| `KernelRegistry` | `Ort::KernelRegistry` | `Register(KernelCreateInfo&&)` | +| `KernelDefBuilder` | `Ort::KernelDefBuilder` | `TypeConstraint()`, `InputMemoryType()`, `SetName()` | +| `Ep` | `OrtEp` | `EpImpl()`, allocators, data transfer | +| `Logger` | Plugin logger | Logging interface | +| `DataTransferManager` | `IDataTransfer` | `CopyTensor()` | +| `ConstOpSchema` | `const OrtOpSchema*` | `GetSinceVersion()`, `GetNumInputs()`, `GetInputName()`, `GetInputTypeStr()`, `HasTypeConstraint()` (ORT ≥ 1.25, PR #27713) | + +--- + +## 7. Excluded Operators + +Section 7 reflects the current source exclusions in `cmake/onnxruntime_providers_cuda_plugin.cmake`, plus the small set of intentionally out-of-scope directories. This is the source of truth for what the plugin build omits today. + +### 7.1 Infrastructure (Permanently Excluded — Replaced by Plugin Equivalents) + +| File | Reason | +|------|--------| +| `cuda_execution_provider.cc` | Replaced by `cuda_ep.h/.cc` and the plugin adapter/runtime shim | +| `cuda_provider_factory.cc` | Replaced by `cuda_ep_factory.cc` | +| `cuda_provider_interface.cc` | Not needed in plugin architecture | +| `cuda_stream_handle.cc` | Replaced by `cuda_stream_plugin.cc` | +| `cuda_execution_provider_info.cc` | Config parsed directly in `CudaEp::Config` | +| `cuda_graph.cc` | Replaced by plugin-local `cuda_graph_plugin.h/.cc`, which implements graph capture/replay through the OrtEp graph callbacks | +| `cuda_mempool_arena.cc` | Replaced by plugin-native `cuda_mempool_allocator_plugin.h/.cc` (uses CUDA mempool directly behind `OrtAllocator`) | +| `cuda_common.cc` | Utility functions shimmed in `cuda_kernel_adapter.h` | +| `cuda_nhwc_kernels.cc` | Replaced by `PluginKernelCollector` auto-registration | +| `cuda_contrib_kernels.cc` | Replaced by `PluginKernelCollector` auto-registration | + +### 7.2 Pure CPU Ops (Permanently Excluded) + +| File | Reason | +|------|--------| +| `tensor/size.cc` | Pure CPU op, handled by `GetCpuPreferredNodes` | +| `tensor/shape_op.cc` | Pure CPU op, inherits from `onnxruntime::OpKernel` (framework) | + +### 7.3 Additional Current Source Exclusions + +| File / Pattern | Why It Is Excluded Today | What Would Unblock It | +|----------------|--------------------------|------------------------| +| `core/providers/cuda/controlflow/*` | The framework controlflow kernels inherit from CPU-side controlflow bases (`If`, `Loop`, `Scan`) and are intentionally omitted from the plugin source list | No change is currently planned. The plugin uses its own `cuda_controlflow_plugin.cc` wrappers instead of these framework sources | +| `tunable/*` | Depends on the real `CudaTuningContext` and other framework CUDA EP infrastructure that is not available in the plugin build | Add a plugin-capable tuning context and remove the remaining framework-only tunable dependencies | +| `tensor/sequence_op.cc` | Uses `TensorSeq`, which is still not adapter-safe here | Add `TensorSeq` adapter coverage | +| `contrib_ops/cuda/llm/*` | Contrib LLM sources have not gone through the same adapter-migration pass as the core CUDA LLM kernels | Finish contrib-LLM-specific adapter work | +| `contrib_ops/cuda/tensor/shrunken_gather.cc` | The training-side header path still depends on framework/provider API wiring | Low-priority training-specific adapter work | + +| `contrib_ops/cuda/transformers/*` | Beam search, greedy search, and sampling depend on broader framework/subgraph integration that has not been adapted for the plugin build | Significant adapter and subgraph support work | +| `contrib_ops/cuda/aten_ops/*` | ATen interop is intentionally out of scope for the standalone CUDA plugin build | A separate ATen/plugin strategy | +| `contrib_ops/cuda/collective/*` | Collective/NCCL support is intentionally out of scope for the standalone CUDA plugin build | A separate collective/NCCL plugin strategy | + +### 7.4 Common Exclusion Themes + +The current exclusions fall into a few categories: + +1. **Tunable/framework-dependent infrastructure** — `tunable/*`, contrib transformers, and some contrib LLM paths still rely on framework-only execution-provider services. + +2. **Remaining adapter gaps** — `TensorSeq` (needed for `sequence_op.cc`) and contrib-LLM-specific plumbing still need dedicated adapter work. + +3. **Deliberate scope cuts** — ATen and collective/NCCL sources remain intentionally out of scope for the standalone CUDA plugin. + +--- + +## 8. Remaining `#ifdef` Guards in Kernel Code + +The branch still contains a small set of plugin guards in both infrastructure and operator code. The important pattern has not changed: + +- Infrastructure files such as `cuda_kernel.h`, `cuda_common.h`, and `cudnn_common.h` still need build-mode gates. +- `generator/constant_of_shape.h` still needs a plugin-specific path because `ConstantOfShapeBase` depends on framework-only tensor-attribute helpers. +- Tunable kernels such as `math/matmul.cc` still gate framework-only registration paths. +- `tensor/identity_op.h` guards the `TensorSeq` code path and `context->InputType()` call with `#ifndef BUILD_CUDA_EP_AS_PLUGIN` — the plugin build handles only the `Tensor` path. `identity_op.cc` uses conditional macros (`IDENTITY_V_TYPES` / `IDENTITY_V_TYPES_IRv9`) so opset 14+ registrations use `AllFixedSizeTensorTypes()` in the plugin build. Additionally, old Dropout opset 7–9 and 10–11 kernel registrations were moved from `identity_op.cc` to `nn/dropout.cc` so that each op's registrations live in that op's own source file. +- A few tensor kernels (`pad.cc`, `tile.cc`, `unsqueeze.cc`) still contain localized plugin guards where adapter and framework paths have not fully converged. Recent cleanup removed the plugin-only branches from `upsample.*`, `space_depth_ops.h`, and `scatter_nd.*` by moving reusable logic into shared adapter-safe helpers and by adding allocator access to `ep::adapter::OpKernelInfo`. + +The broad trend remains positive: most operator-level plugin conditionals were removed by moving reusable CPU/helper logic into shared headers and by centralizing stream bridging in `CudaKernel` helpers. + +--- + +## 9. Building + +### 9.1 CMake Flag + +The plugin is enabled by setting `onnxruntime_BUILD_CUDA_EP_AS_PLUGIN=ON`: + +```bash +sh build.sh --config Release --build_dir build/cuda --parallel --use_cuda \ + --cuda_version 12.8 --cuda_home /path/to/cuda \ + --cudnn_home /path/to/cudnn \ + --build_wheel --skip_tests \ + --cmake_generator Ninja \ + --enable_cuda_nhwc_ops \ + --cmake_extra_defines onnxruntime_BUILD_CUDA_EP_AS_PLUGIN=ON \ + --cmake_extra_defines CMAKE_CUDA_ARCHITECTURES="90" +``` + +### 9.2 Impact on Other Build Targets + +The `onnxruntime_BUILD_CUDA_EP_AS_PLUGIN=ON` flag has **no impact** on `libonnxruntime_providers_cuda.so` or `libonnxruntime_providers_shared.so`. It only: + +1. Adds the `onnxruntime_providers_cuda_plugin` target (producing `libonnxruntime_providers_cuda_plugin.so`) +2. Appends `"cuda-plugin-ep=1"` to the build info string (cosmetic) + +The in-tree CUDA EP and shared provider bridge are compiled identically regardless of this flag. A single build with the flag ON produces all four libraries — there is no need for separate build scripts or build directories. + +### 9.3 Plugin Independence + +`libonnxruntime_providers_cuda_plugin.so` is **fully self-contained**. It does not depend on `libonnxruntime_providers_cuda.so` or `libonnxruntime_providers_shared.so` at load time. It statically links against `onnxruntime_framework`, `onnxruntime_graph`, `onnxruntime_common`, `onnxruntime_mlas`, `onnxruntime_flatbuffers`, and links dynamically against CUDA (`cudart`, `cublas`, `cublasLt`, `cufft`), cuDNN, and protobuf. Communication with the ORT runtime happens exclusively through the C API (`OrtApi`/`OrtEpApi`) passed at load time. + +### 9.4 Build Outputs + +After a successful build with the plugin flag ON, `build/cuda/Release/` contains: + +| File | Description | +|------|-------------| +| `libonnxruntime_providers.a` | CPU provider (static, linked into main binary) | +| `libonnxruntime_providers_shared.so` | Shared provider bridge (for in-tree CUDA EP) | +| `libonnxruntime_providers_cuda.so` | In-tree CUDA EP (uses shared provider bridge) | +| `libonnxruntime_providers_cuda_plugin.so` | Plugin CUDA EP (standalone, uses C API) | + +### 9.5 Deployment + +To use the plugin EP, copy the `.so` to the ORT Python package's `capi/` directory: + +```bash +cp build/cuda/Release/libonnxruntime_providers_cuda_plugin.so \ + $(python -c "import onnxruntime; print(onnxruntime.__path__[0])")/capi/ +``` + +The plugin is then available as `CudaPluginExecutionProvider` in session provider lists. + +--- + +## 10. Testing + +### 10.1 Test Script + +`onnxruntime/test/python/transformers/test_cuda_plugin_ep.py` provides the current focused plugin validation flow: + +| Category | What It Tests | +|----------|---------------| +| Registration | Dynamic loading via `register_execution_provider_library()` and EP device discovery (Add, MatMul, Gemm, Conv) | +| Provider options | Valid option parsing, invalid device rejection, multi-device selection | +| NHWC | NHWC-requested sessions: Conv, BatchNorm, MaxPool, AveragePool. These validate correctness under `prefer_nhwc` and require plugin-backed NHWC execution to succeed; they are the focused regression suite for the plugin NHWC path | +| Tensor ops | Reshape, Split, Concat, Gather, Unsqueeze, Tile, Pad, Slice, Transpose, Cast, Where, Flatten, ArgMax, TopK, Trilu, NonZero | +| Math ops | Softmax, Relu, Sigmoid, Tanh, Einsum (single and batched) | +| Reduce | ReduceMean, ReduceSum | +| Space/depth | SpaceToDepth, DepthToSpace, Upsample | +| Shape ops | CumSum, ConstantOfShape, Resize, Sum (variadic) | +| Normalization | LayerNormalization, InstanceNormalization | +| Conv | ConvTranspose | +| Scatter/gather | GatherND, ScatterElements, OneHot | +| Spatial | GridSample | +| Contrib ops | FastGelu, Gelu, BiasGelu, SkipLayerNorm, BiasDropout, FusedMatMul | +| Dropout | Dropout opset 7 and opset 10 — verifies registrations moved to `dropout.cc` | +| Quantization | DequantizeLinear / QuantizeLinear opset 21 — exercises `TWO_TYPED_KERNEL_EX` adapter macro; MatMulInteger | +| GatherBlockQuantized | Contrib `GatherBlockQuantized` — exercises `THREE_TYPED_KERNEL_EX` adapter macro | +| Identity | Identity opset 13 and opset 25 — re-enabled op with `TensorSeq` path guarded | +| Crop | Crop (opset 1) — previously excluded contrib op, now re-enabled | +| Memcpy | Explicit `MemcpyFromHost` and `MemcpyToHost` standalone tests to ensure copy ops are dispatched | +| CUDA Graph | Capture/replay with default arena (`test_cuda_graph_capture_and_replay`, `test_cuda_graph_add_model`), in-place input update after capture (`test_cuda_graph_replay_with_updated_input`), CUDA native mempool allocator (`test_cuda_graph_with_mempool`), and multiple annotation IDs (`test_cuda_graph_annotation_id`) | +| IOBinding / Sync | IOBinding-based tests (Add, MatMul) that bind CPU inputs and CUDA outputs to exercise `OrtEp::Sync` and `OrtEp::CreateSyncStreamForDevice` | +| Key-ops probe | Session-based probing that all key ops are assigned to `CudaPluginExecutionProvider` | + +### 10.2 Running Tests + +After building and deploying the plugin (see [Section 9.5](#95-deployment)), use the shared test instructions in [QUICK_START.md](QUICK_START.md#running-tests). That section is the source of truth for prerequisites, `ORT_CUDA_PLUGIN_PATH`, and platform-specific test commands. + +### 10.3 Parity Report + +`tools/ci_build/cuda_plugin_parity_report.py` generates both static and runtime parity reports: + +- **Static mode** (default): Parses CMake exclusion patterns and kernel registration macros from source to compare what the plugin build includes vs. the bundled CUDA EP. + ```bash + python tools/ci_build/cuda_plugin_parity_report.py + ``` +- **Runtime mode** (`--runtime`): Uses the pybind `get_registered_ep_kernel_defs()` API (added in `onnxruntime_pybind_schema.cc`) to query actual kernel registries from both the bundled and plugin EPs, providing an accurate comparison of registered op/domain/version/type-constraint coverage. + ```bash + python tools/ci_build/cuda_plugin_parity_report.py --runtime [--plugin-ep-lib /path/to/plugin.so] + ``` + +The runtime API (`get_registered_ep_kernel_defs(ep_name)`) creates a temporary EP factory and EP instance for the named EP, iterates its kernel registry, and returns `KernelDef` objects with `op_name`, `domain`, `version_range`, `provider`, and `type_constraints` fields. + +--- + +## 11. How to Add a New Kernel to the Plugin + +### 11.1 If the kernel compiles as-is + +Most kernels that don't use `GetComputeStream()` (returning `Stream*`) or inherit from excluded CPU base classes will compile without changes. The force-include mechanism handles type resolution automatically. + +Just verify it's not in the exclusion list in `cmake/onnxruntime_providers_cuda_plugin.cmake`. + +### 11.2 If the kernel calls a CPU base class helper + +Apply the inline-header pattern: + +1. Move the helper implementation from the CPU `.cc` file to the `.h` file +2. Wrap with `#ifdef SHARED_PROVIDER` (declaration only) / `#else` (inline body) +3. In the CUDA kernel, call the base class method directly (remove any local wrappers) +4. Verify all 4 build targets compile + +Example from `cumsum.h`: +```cpp +namespace cumsum_op { +#ifdef SHARED_PROVIDER +Status GetAxis(const Tensor* axis_tensor, int64_t input_rank, int64_t& axis_out); +#else +inline Status GetAxis(const Tensor* axis_tensor, int64_t input_rank, int64_t& axis_out) { + // ... implementation ... +} +#endif +} +``` + +### 11.3 If the helper takes OpKernelContext& + +Use a template version that accepts any context type: + +```cpp +template +static void ComputePadsImpl(KernelContextType& ctx, ...) { ... } +``` + +The CUDA kernel calls `ComputePadsImpl(*ctx, ...)` directly. + +### 11.4 If the kernel uses stream helpers + +Prefer the shared helpers in `CudaKernel` instead of introducing new plugin-only stream shims: + +- If the code only needs a raw CUDA stream, use `Stream(ctx)`. +- If the shared helper API accepts the adapter's opaque stream handle, use `GetComputeStream(ctx)`. +- If framework-style helper code still expects `onnxruntime::Stream*`, use `GetOrtStream(ctx)`. +- Prefer `GetCublasHandle(ctx)`, `GetCudnnHandle(ctx)`, and `GetCublasLtHandle(ctx)` over re-discovering handles from the stream manually. + +### 11.5 If the kernel uses handle accessors + +Use the plugin-compatible overloads already in `CudaKernel`: + +```cpp +// Instead of: GetCublasHandle(ctx->GetComputeStream()) +// Use: GetCublasHandle(ctx) // or GetCublasHandle(Stream(ctx)) +``` + +### 11.6 If OpSchema access is available — schema-validated type constraints + +With the `OrtEpApi` OpSchema APIs (ORT ≥ 1.25, PR #27713), the plugin can validate or derive type constraint names at kernel registration time rather than relying solely on hard-coded strings. + +#### 11.6.1 Validation mode (recommended first step) + +Add a debug-mode validation pass in `CreateCudaKernelRegistry()` that runs after all kernels are collected from `PluginKernelCollector`. For each registered kernel, look up its `OrtOpSchema` and verify that every type constraint name used in the `KernelDef` actually appears in the schema's type constraint map: + +```cpp +// In CreateCudaKernelRegistry(), after building the registry: +#ifndef NDEBUG +for (auto build_fn : entries) { + auto info = build_fn(); + if (info.kernel_def == nullptr) continue; + + // Retrieve the op name, domain, and since_version from the KernelDef. + const char* op_name = info.kernel_def->GetOpName(); + const char* domain = info.kernel_def->GetDomain(); + int since_version = info.kernel_def->GetSinceVersion(); + + // Look up the ONNX schema from ORT's global registry. + Ort::ConstOpSchema schema = Ort::GetOpSchema(op_name, since_version, domain); + if (!schema) continue; // contrib/internal ops may not have an ONNX schema + + // Validate each type constraint name against the schema. + for (const auto& [constraint_name, types] : info.kernel_def->GetTypeConstraints()) { + if (!schema.HasTypeConstraint(constraint_name.c_str())) { + LOGS_DEFAULT(WARNING) << "Plugin kernel " << op_name + << ": type constraint '" << constraint_name + << "' not found in OpSchema (domain=" << domain + << ", version=" << since_version << ")"; + } + } +} +#endif +``` + +This catches hard-to-debug kernel-matching failures caused by constraint name typos or opset version drift. + +#### 11.6.2 Schema-driven constraint helper (future) + +A `KernelDefBuilder` extension could derive constraint names from the schema automatically: + +```cpp +/// Look up the type constraint string for a given input index from the OpSchema. +/// Falls back to the provided default if the schema is not found (e.g., contrib ops). +inline const char* GetInputTypeConstraintName( + const char* op_name, int opset_version, const char* domain, size_t input_index, + const char* fallback = "T") { + Ort::ConstOpSchema schema = Ort::GetOpSchema(op_name, opset_version, domain); + if (!schema || input_index >= schema.GetNumInputs()) return fallback; + // Cache the result to avoid repeated lookups for typed kernel variants. + static thread_local std::string cached_name; + cached_name = schema.GetInputTypeStr(input_index); + return cached_name.c_str(); +} +``` + +This is a quality-of-life improvement rather than a required change — the existing hard-coded constraint names are correct for all currently registered kernels. + +--- + +## 12. Memory Arena Integration + +The CUDA plugin EP now includes a full BFC-style arena (`CudaArenaAllocator` / `ArenaImpl`) and a CUDA native mempool allocator (`CudaMempoolOrtAllocator`), both residing inside the plugin library. The detailed design — factory lifecycle, per-device cache, stream integration, arena config flow, and the `CudaMempoolArena` migration — is documented in [arena_allocator_migration_design.md](arena_allocator_migration_design.md). + +**ORT core integration:** Plugin arenas implement `OrtAllocator::Shrink` (added in ORT API version 25). When ORT core detects a non-null `Shrink` function pointer on the returned `OrtAllocator*`, it wraps the allocator as `IArenaImplWrappingOrtAllocator` (an `IArena`). This makes the plugin arena visible to session-level arena management — `InferenceSession::ShrinkMemoryArenas()`, `ValidateAndParseShrinkArenaString()`, `DeviceStreamCollection::ReleaseSingleStreamBuffers()` — through the standard `IArena::SafeArenaCast()` / `AsArena()` virtual method, without requiring RTTI. + +**Key files introduced:** + +| File | Purpose | +|------|---------| +| `plugin/cuda_arena.h` | `ArenaConfig`, `ArenaImpl` (BFC arena), `CudaArenaAllocator` (`OrtAllocator` wrapper) | +| `plugin/cuda_arena.cc` | Arena implementation: bins, chunks, regions, stream-aware alloc, `Shrink()`, `GetStats()` | +| `plugin/cuda_mempool_allocator_plugin.h` | `CudaMempoolOrtAllocator` — wraps CUDA native mempool behind `OrtAllocator` | +| `plugin/cuda_mempool_allocator_plugin.cc` | Mempool implementation: `cudaMallocFromPoolAsync`/`cudaFreeAsync`, pool lifecycle, `Shrink()` via `cudaMemPoolTrimTo` | +| `core/session/allocator_adapters.h` | `IArenaImplWrappingOrtAllocator` — wraps plugin `OrtAllocator*` with `Shrink` as `IArena` | +| `core/session/allocator_adapters.cc` | Adapter implementation; `GetStatsFromOrtAllocator()` helper; `kOrtAllocatorShrinkMinVersion` | + +--- + +## 13. File Layout + +``` +onnxruntime/core/providers/cuda/plugin/ +├── cuda_kernel_adapter.h # CudaKernel base, macros, CPU shims (force-included) +├── cuda_ep.h / .cc # CudaEp : OrtEp implementation (GetCapability, Sync, CreateSyncStreamForDevice) +├── cuda_ep_factory.h / .cc # CudaEpFactory : OrtEpFactory (arena lifecycle, per-device cache) +├── cuda_plugin_ep.cc # DLL entry points (CreateEpFactories/ReleaseEpFactory) +├── cuda_plugin_ep_symbols.def # Windows DLL export definitions +├── cuda_plugin_kernels.h / .cu # Kernel registry creation +├── cuda_stream_plugin.h / .cc # CudaSyncStream (handles, notifications, arena chunk reset) +├── cuda_allocator_plugin.h / .cc # Device/pinned raw allocators (CudaAllocatorBase hierarchy) +├── cuda_arena.h / .cc # BFC arena (ArenaConfig, ArenaImpl, CudaArenaAllocator) +├── cuda_mempool_allocator_plugin.h / .cc # CUDA native mempool allocator (CudaMempoolOrtAllocator) +├── cuda_data_transfer_plugin.h / .cc # GPU↔CPU data transfer +├── cuda_memcpy_plugin.cc # MemcpyFromHost/MemcpyToHost standalone kernels +├── cuda_controlflow_plugin.h / .cc / .cu # If/Loop/Scan wrappers +├── cuda_plugin_utils.h # Common macros, error handling +└── provider_api_shims.cc # Reimplemented utility functions + +onnxruntime/core/session/ +├── allocator_adapters.h / .cc # OrtAllocator↔IAllocator/IArena bidirectional adapters +│ # (IAllocatorImplWrappingOrtAllocator, IArenaImplWrappingOrtAllocator, +│ # OrtAllocatorImplWrappingIAllocator) +└── ... + +include/onnxruntime/core/framework/ +├── allocator.h # IAllocator (AsArena virtual), IArena (Shrink, SafeArenaCast) +└── ... + +include/onnxruntime/ep/ +├── README.md # EP adapter layer overview +├── adapters.h # Master include + type aliasing (force-included) +├── api.h # ORT C API includes +├── common.h # EP common utilities +├── get_capability_utils.h # GetCapability helper utilities +└── adapter/ + ├── allocator.h # IAllocator adapter + ├── data_transfer_manager.h # DataTransferManager adapter + ├── ep.h # Ep base class (wraps IExecutionProvider) + ├── kernel_def.h # KernelDef adapter + ├── kernel_def_builder.h # KernelDefBuilder adapter + ├── kernel_registry.h # KernelRegistry adapter + ├── logging.h # Logger adapter + ├── node.h # Node adapter + ├── op_kernel.h # OpKernel + OpKernelContext adapters + ├── op_kernel_info.h # OpKernelInfo adapter + └── tensor_helper.h # Tensor creation from C API values +``` + +--- + +## 14. Profiling and Observability + +The CUDA plugin EP implements the `OrtEpProfilerImpl` interface (introduced in ORT 1.25 via [PR #27649](https://github.com/microsoft/onnxruntime/pull/27649)) to participate in ORT's profiling system. When profiling is enabled, GPU kernel executions (CUDA kernels, memory copies) captured by NVIDIA CUPTI appear alongside ORT's CPU-side events in the profiling output. + +### 14.1 Architecture + +The profiling stack has three layers: + +1. **ORT Core** (`Profiler` in `profiler.cc`) — drives the profiling lifecycle. It calls `PluginExecutionProvider::GetProfiler()`, which invokes `OrtEp::CreateProfiler` on the plugin and wraps the returned `OrtEpProfilerImpl` in a `PluginEpProfiler` bridge. +2. **Bridge** (`PluginEpProfiler` in `ep_event_profiling.cc`) — adapts the C++ `EpProfiler` interface to the C `OrtEpProfilerImpl` callbacks. It handles clock synchronization (provides an epoch-independent offset in `StartProfiling`) and converts relative ORT event IDs to absolute epoch-based correlation IDs for `StartEvent`/`StopEvent`. +3. **Plugin-side profiler** (`CudaPluginEpProfiler` in `cuda_profiler_plugin.h/.cc`) — implements `OrtEpProfilerImpl` inside the plugin DLL. Delegates to `CUPTIManager` for GPU activity tracing. + +``` +ORT Profiler + └─ PluginEpProfiler (bridge, in ORT core) + └─ OrtEpProfilerImpl callbacks (C API boundary) + └─ CudaPluginEpProfiler (in plugin DLL) + └─ CUPTIManager singleton (in plugin DLL) + └─ CUPTI activity APIs (GPU tracing) +``` + +### 14.2 CUPTI Integration + +The plugin DLL links `CUDA::cupti` and compiles `cupti_manager.cc` when `onnxruntime_ENABLE_CUDA_PROFILING` is ON. The `CUPTIManager` singleton lives inside the plugin DLL, isolated from any in-tree CUDA EP in the same process. This is the expected isolation model for plugin EPs. + +CUPTI activities enabled: +- `CUPTI_ACTIVITY_KIND_RUNTIME` — CUDA runtime API calls +- `CUPTI_ACTIVITY_KIND_DRIVER` — CUDA driver API calls +- `CUPTI_ACTIVITY_KIND_CONCURRENT_KERNEL` — GPU kernel execution +- `CUPTI_ACTIVITY_KIND_MEMCPY` — device memory transfers +- `CUPTI_ACTIVITY_KIND_EXTERNAL_CORRELATION` — maps GPU activities to ORT event correlation IDs + +### 14.3 Correlation ID Flow + +The plugin API's `StartEvent`/`StopEvent` receive **absolute epoch-based** correlation IDs (converted by the `PluginEpProfiler` bridge from ORT's relative event IDs). These are pushed directly to CUPTI's external correlation stack via `cuptiActivityPushExternalCorrelationId`, allowing CUPTI to tag GPU activities with the corresponding ORT event. When `StopEvent` is called, the correlation ID is popped. This matches the pattern used by the in-tree CUDA EP's `GPUTracerManager::PushCorrelation`/`PopCorrelation`. + +### 14.4 Event Collection (EndProfiling) + +When ORT calls `EndProfiling`: +1. CUPTI activity buffers are flushed (`cuptiActivityFlushAll`). +2. GPU activity records are processed — kernel names, timestamps, durations, and stream/grid metadata are extracted. +3. Events are converted to `Ort::ProfilingEvent` instances with `OrtProfilingEventCategory_KERNEL`. +4. Events are appended to the `OrtProfilingEventsContainer` via `AddEvents`. + +The plugin does **not** perform the post-hoc merge/sort that the in-tree `GPUProfilerBase::EndProfiling` does. The plugin API is append-only, and the `PluginEpProfiler` bridge on the ORT side likewise appends EP events to ORT's profiling event collection without merge/sort by timestamp or correlation ID. Any ordering or interleaving into a global timeline is handled by downstream trace consumers. + +### 14.5 Design Differences from In-Tree CUDA EP Profiler + +| Aspect | In-tree CUDA EP | CUDA Plugin EP | +|--------|----------------|----------------| +| Event merge | `GPUProfilerBase::MergeEvents` interleaves GPU events into ORT's array (has known sort-order bug) | Append-only; ORT-side bridge appends only, and trace consumers handle ordering | +| Correlation IDs | Relative → absolute conversion in `GPUTracerManager::PushCorrelation` | Bridge provides absolute IDs directly; plugin pushes to CUPTI as-is | +| `StopEvent` metadata | Ignored (just pops correlation) | ORT event metadata available; currently unused, can annotate GPU events in future | +| GPU→ORT event linkage | Implicit via CUPTI external correlation IDs merged into timeline | GPU events carry only CUPTI metadata (`stream`, `grid_*`, `block_*`); no ORT correlation or parent identifier is attached. Downstream consumers must relate GPU kernels to ORT nodes via timestamp proximity. This is a known limitation; future work may attach `correlation_id` or parent event name via `StopEvent`'s `OrtProfilingEvent` parameter | +| Singleton scope | Process-wide `CUPTIManager` in main ORT DLL | DLL-local `CUPTIManager` in plugin (process isolation) | + +### 14.6 Build Configuration + +CUPTI profiling is conditional: +- **CMake flag**: `onnxruntime_ENABLE_CUDA_PROFILING=ON` +- **Compile definition**: `ENABLE_CUDA_PROFILING` added to the plugin target +- **Link**: `CUDA::cupti` linked to `onnxruntime_providers_cuda_plugin` +- **Source**: `cupti_manager.cc` compiled into the plugin + +When profiling is disabled (default), `CudaEp::CreateProfiler` is set to `nullptr` and no CUPTI code is compiled. + +### 14.7 Files + +| File | Role | +|------|------| +| `plugin/cuda_profiler_plugin.h` | `CudaPluginEpProfiler` struct definition | +| `plugin/cuda_profiler_plugin.cc` | Profiler callback implementations | +| `plugin/cuda_ep.h` | `CreateProfilerImpl` declaration | +| `plugin/cuda_ep.cc` | `CreateProfiler` callback wiring | +| `cmake/onnxruntime_providers_cuda_plugin.cmake` | Conditional CUPTI linkage | + +--- + +## 15. Future Work + +1. **Remaining stream/adapter parity for framework-style `Stream*` consumers** — Much of the broad `Stream*` gap has already been addressed: the plugin adapter now provides an `OrtStreamAdapter` / `PluginStreamShim` path for framework-style `Stream*` call sites, FFT is included, and quantization/diffusion kernels are no longer excluded as a class. Remaining work is narrower: + + - Continue using `Stream(context)` / `GetOrtStream(context)` patterns for migrated kernels rather than adding raw-stream-only forks. + - Audit still-excluded directories that require more than a stream handle: `contrib_ops/cuda/llm/*`, `contrib_ops/cuda/transformers/*`, and `contrib_ops/cuda/collective/*`. + - For each re-inclusion pass, add or extend focused plugin tests before removing the CMake exclusion. + +2. **Contrib LLM migration pass** — Still open. The core CUDA LLM attention path is now adapter-safe, but `contrib_ops/cuda/llm/*` remains excluded in `cmake/onnxruntime_providers_cuda_plugin.cmake`. The remaining work is a dedicated contrib-LLM adapter pass: resolve any plugin build failures under `ORT_USE_EP_API_ADAPTERS`, keep the normal stream/scratch-buffer helpers, remove the `contrib_ops/cuda/llm/*` CMake filters, and add focused tests or parity-report coverage for the first re-included kernels. + +3. **Tunable ops** — Implement a plugin-side `ITuningContext` and remove the `ORT_USE_EP_API_ADAPTERS` guards in `matmul.cc`/`gemm.cc` so the plugin can recover runtime kernel selection and profiling-based tuning behavior. + +4. **TensorSeq and additional C API coverage** — Add enough sequence/tensor-sequence support to unblock `sequence_op.cc` (the last remaining TensorSeq-dependent file), and extend the ORT C API where needed for remaining framework-style attribute accessors such as string-array attributes used by RNN kernels. Note: `identity_op.cc` is now included in the plugin build — its TensorSeq code path is guarded by `#ifndef BUILD_CUDA_EP_AS_PLUGIN` and opset 14+ registrations use `AllFixedSizeTensorTypes()` (Tensor-only) instead of `AllFixedSizeTensorAndSequenceTensorTypes()`. + +5. **Remaining contrib exclusions** — Remaining contrib exclusions are: `shrunken_gather.cc` (training), `transformers/*` (subgraph), `aten_ops/*` (ATen), `collective/*` (NCCL), and `llm/*` (contrib LLM pass). + +6. **CI integration and targeted benchmarking** — Partially complete. Basic CUDA plugin build + `test_cuda_plugin_ep.py` coverage now exists in Linux and Windows plugin CI workflows. Remaining work is perf-oriented and feature-specific validation: add targeted benchmarks or perf gates for graph replay and allocator behavior, and extend CI once profiling and tunable-op support land. + +7. **NHWC cleanup and hardening** — Partially complete. Runtime NHWC callbacks, second-pass capability handling for pre-assigned NHWC nodes, cached provider-config access, and focused Conv/BatchNormalization/Pool tests are in place. Remaining work is the cleanup described in [Section 5.3.1](#531-nhwc-layout-transformation-support): unify the conversion allowlist with the bundled CUDA EP, improve internal-domain kernel-miss diagnostics, and add stronger structural assertions that plugin-backed NHWC execution was actually selected. + +8. **OpSchema-validated kernel registration after PR #27713** — PR #27713 has already landed, so the `OrtEpApi` and C++ wrappers for querying ONNX operator schemas are available (see [Section 3.5.1](#351-type-constraint-names-and-opschema-access)). The remaining work is plugin-side adoption: + + **A. Registration-time validation pass** + + Still open. Add a debug/diagnostic pass in `CreateCudaKernelRegistry()` that validates every registered kernel's type constraint names against the schema. This is the highest-value, lowest-risk change — it catches silent kernel-matching failures caused by constraint name drift without altering the registration flow. See [Section 11.6.1](#1161-validation-mode-recommended-first-step) for the implementation pattern. + + **B. NHWC internal-domain schema diagnostics** + + Still open. Extend the validation pass to cover `com.ms.internal.nhwc`-domain registrations. When kernel lookup fails for a rewritten NHWC node, the diagnostic can now report exactly which constraint name was expected vs. what the kernel registered, directly addressing the diagnostic requirement in [Section 5.3.1.3](#5313-nhwc-design-requirements). + + **C. Parity report enhancement** + + Still open. Update `cuda_plugin_parity_report.py` to use the schema API (via a small C++ test harness or Python ONNX bindings) to flag type-constraint mismatches between the plugin's registered kernels and the ONNX schema, in addition to the existing op-coverage comparison. + + **D. Schema-driven `KernelDefBuilder` helpers (longer term)** + + Still open and lower priority. Create a `KernelDefBuilder` helper that auto-derives constraint names from the schema instead of requiring hard-coded strings. This reduces maintenance burden when new opset versions introduce constraint name changes, but is lower priority than the validation pass since all current constraint names are correct. + + **E. Potential code locations for changes** + + | File | Change | + |------|--------| + | `cuda_plugin_kernels.cu` / `CreateCudaKernelRegistry()` | Add schema validation loop after kernel collection | + | `cuda_kernel_adapter.h` | (Optional) Add schema-aware macro variant or post-registration hook | + | `include/onnxruntime/ep/adapter/kernel_def_builder.h` | (Optional) Add schema-lookup helper for constraint names | + | `cuda_ep.cc` / `GetCapabilityImpl()` | (Optional) Add schema-based diagnostic when `EpGraphSupportInfo_LookUpKernel` returns nullptr | + | `test_cuda_plugin_ep.py` | Add a validation stage that exercises schema-validated registration | + +9. **Resource accounting and annotation-based partitioning after PR #27595** — PR #27595 has already landed, so ORT now has framework-side resource accounting and layering annotations. The remaining CUDA plugin work is to bridge those capabilities through the plugin EP API and plugin capability implementation. + + **A. Resource accounting** + + `IResourceAccountant` lets an EP declare a resource budget (e.g., available VRAM) and have the partitioner stop assigning nodes once that budget is exhausted. The framework passes an `IResourceAccountant*` to `IExecutionProvider::GetCapability()`; the in-tree CUDA EP uses it to compute per-node estimated VRAM cost from initializer sizes. + + For plugin EPs, the `OrtEp::GetCapability` callback still has no mechanism to receive or report resource usage. `PluginExecutionProvider::GetCapability()` receives an `IResourceAccountant*`, but it currently leaves that parameter unused before calling the `OrtEp::GetCapability` callback. Two design options remain: + + - **Option A (preferred — ORT core change):** Add an `OrtEp` analogue of the current `IResourceAccountant` flow, such as resource-accounting helpers on `OrtEpGraphSupportInfo`. This would let the plugin request per-node resource budget during `CudaEp::GetCapabilityImpl()` without duplicating partitioner budget logic. + + - **Option B (plugin-side workaround):** Expose the VRAM threshold through a plugin-specific session option key. During `GetCapabilityImpl`, the plugin reads the threshold from the parsed config and performs its own initializer-size accounting using `OrtEp_GetNodeAttributes` / node-graph-view APIs already present in the `OrtEp` API surface. This avoids an ORT core change but duplicates budget-tracking logic. + + **B. Annotation-based layering** + + PR #27595 also introduced `layering_annotations` — node-level `"layer_ann"` metadata that routes nodes to specific EPs or CPU during partitioning. The expected model is that plugin EPs participate through the same `GetCapability` flow and therefore observe whatever node set ORT presents after applying layering rules. In practice that should mean no plugin-specific changes are needed to respect annotations that exclude nodes from the plugin. However, the plugin design should avoid depending on undocumented filtering details in the `OrtGraph*` contract. If the plugin EP itself needs to *read* layering annotations for internal decisions, or if the API needs to make filtered-vs-unfiltered graph semantics explicit, that would require new `OrtEp` API surface. + + Current known limitations to keep in future work: + + - The `cuda(...)` device selector currently matches only the built-in `CUDAExecutionProvider`. It does not match the plugin EP name `CudaPluginExecutionProvider`, so layer assignment settings written against `cuda(...)` do not work with the CUDA plugin EP today. + - The `gpu:(...)` selector is currently matched using `OrtHardwareDevice::device_id`. That field is not a stable CUDA ordinal and is not guaranteed to uniquely identify one physical GPU, so index-based layer assignment is unreliable for the CUDA plugin EP, especially on hosts with multiple similar NVIDIA GPUs. + + **Recommended action:** First add the plugin API bridge for resource accounting, then update `CudaEp::GetCapabilityImpl()` to request resource budget for candidate nodes when layer assignments exist. Until that bridge exists, the plugin can observe the filtered node set from ORT partitioning but cannot report resource consumption through the same `IResourceAccountant` flow as the in-tree CUDA EP. diff --git a/docs/python/README.rst b/docs/python/README.rst index cce966f7d7d0c..e8190c584fb62 100644 --- a/docs/python/README.rst +++ b/docs/python/README.rst @@ -8,6 +8,36 @@ For more information on ONNX Runtime, please see `aka.ms/onnxruntime `_. -**OpenVINO™ Execution Provider for ONNX Runtime** Linux Wheels comes with pre-built libraries of OpenVINO™ version 2024.1.0 eliminating the need to install OpenVINO™ separately. +**OpenVINO™ Execution Provider for ONNX Runtime** Linux Wheels comes with pre-built libraries of OpenVINO™ version 2025.1.0 eliminating the need to install OpenVINO™ separately. For more details on build and installation please refer to `Build `_. Usage ^^^^^ -By default, Intel® CPU is used to run inference. However, you can change the default option to either Intel® integrated GPU, discrete GPU, integrated NPU (Windows only). +By default, Intel® CPU is used to run inference. However, you can change the default option to either Intel® integrated GPU, discrete GPU, integrated NPU. Invoke `the provider config device type argument `_ to change the hardware on which inferencing is done. For more API calls and environment variables, see `Usage `_. diff --git a/docs/python/_common/onnx_sphinx.py b/docs/python/_common/onnx_sphinx.py index 1b99dcf805530..f5581f817536f 100644 --- a/docs/python/_common/onnx_sphinx.py +++ b/docs/python/_common/onnx_sphinx.py @@ -23,7 +23,7 @@ def get_template(): try: - from jinja2 import Template + from jinja2 import Template # noqa: PLC0415 except ImportError: # pragma no cover class Template: @@ -251,7 +251,7 @@ def _clean_unicode(text): def _populate__get_all_schemas_with_history(): - import onnxruntime.capi.onnxruntime_pybind11_state as rtpy + import onnxruntime.capi.onnxruntime_pybind11_state as rtpy # noqa: PLC0415 get_schemas = rtpy.get_all_operator_schema or rtpy.get_all_opkernel_def @@ -885,7 +885,7 @@ def setup(app): Sphinx extension `onnx_sphinx` displays documentation of all ONNX Operators. """ - import sphinx + import sphinx # noqa: PLC0415 app.add_config_value("onnx_doc_folder", "operators", "env") app.add_config_value("max_opsets", {}, "env") diff --git a/docs/python/conf.py b/docs/python/conf.py index 438c21570eaac..990afd6c3f789 100644 --- a/docs/python/conf.py +++ b/docs/python/conf.py @@ -119,7 +119,7 @@ def setup(app): this = os.path.abspath(os.path.dirname(__file__)) dest = os.path.join(this, "model.onnx") if not os.path.exists(dest): - import urllib.request + import urllib.request # noqa: PLC0415 url = "https://raw.githubusercontent.com/onnx/onnx/master/onnx/backend/test/data/node/test_sigmoid/model.onnx" urllib.request.urlretrieve(url, dest) diff --git a/docs/python/examples/plot_convert_pipeline_vectorizer.py b/docs/python/examples/plot_convert_pipeline_vectorizer.py index 2215cb73ee643..62617e581b2e8 100644 --- a/docs/python/examples/plot_convert_pipeline_vectorizer.py +++ b/docs/python/examples/plot_convert_pipeline_vectorizer.py @@ -95,4 +95,4 @@ ######################### # Very similar. *ONNX Runtime* uses floats instead of doubles, -# that explains the small discrepencies. +# that explains the small discrepancies. diff --git a/docs/python/examples/plot_train_convert_predict.py b/docs/python/examples/plot_train_convert_predict.py index f0fd8694fb541..24e49d421f285 100644 --- a/docs/python/examples/plot_train_convert_predict.py +++ b/docs/python/examples/plot_train_convert_predict.py @@ -16,7 +16,7 @@ Train a logistic regression +++++++++++++++++++++++++++ -The first step consists in retrieving the iris datset. +The first step consists in retrieving the iris dataset. """ from sklearn.datasets import load_iris @@ -95,7 +95,7 @@ ############################# # And then with ONNX Runtime. -# The probabilies appear to be +# The probabilities appear to be prob_name = sess.get_outputs()[1].name prob_rt = sess.run([prob_name], {input_name: X_test.astype(numpy.float32)})[0] diff --git a/docs/python/requirements.txt b/docs/python/requirements.txt index b528063e1aa94..0b0e5d464b26e 100644 --- a/docs/python/requirements.txt +++ b/docs/python/requirements.txt @@ -11,7 +11,6 @@ furo pyquickhelper pandas pydot -coloredlogs flatbuffers numpy<2.0.0 packaging @@ -21,4 +20,4 @@ onnx sphinx_exec_code sphinx_tabs furo -torch +torch >= 2.6.0 diff --git a/include/onnxruntime/core/common/common.h b/include/onnxruntime/core/common/common.h index 0822eba950f50..820d140ccaabc 100644 --- a/include/onnxruntime/core/common/common.h +++ b/include/onnxruntime/core/common/common.h @@ -148,6 +148,26 @@ void LogRuntimeError(uint32_t session_id, const common::Status& status, const ch abort(); \ } while (false) +#define ORT_THROW_FROM_STATUS(status) \ + do { \ + ::onnxruntime::PrintFinalMessage( \ + ::onnxruntime::OnnxRuntimeException( \ + ORT_WHERE_WITH_STACK, status.ToString()) \ + .what()); \ + abort(); \ + } while (false) + +#define ORT_THROW_WITH_CATEGORY_AND_CODE(category, code, ...) \ + do { \ + ::onnxruntime::PrintFinalMessage( \ + ::onnxruntime::OnnxRuntimeException(ORT_WHERE_WITH_STACK, \ + ::onnxruntime::MakeString(__VA_ARGS__), \ + ::onnxruntime::common::category, \ + ::onnxruntime::common::code) \ + .what()); \ + abort(); \ + } while (false) + #else #define ORT_TRY try @@ -180,6 +200,16 @@ void LogRuntimeError(uint32_t session_id, const common::Status& status, const ch #define ORT_THROW_EX(ex, ...) \ throw ex(__VA_ARGS__) +#define ORT_THROW_FROM_STATUS(status) \ + throw ::onnxruntime::OnnxRuntimeException(ORT_WHERE_WITH_STACK, status.ToString(), status.Category(), \ + static_cast<::onnxruntime::common::StatusCode>(status.Code())) + +#define ORT_THROW_WITH_CATEGORY_AND_CODE(category, code, ...) \ + throw ::onnxruntime::OnnxRuntimeException(ORT_WHERE_WITH_STACK, \ + ::onnxruntime::MakeString(__VA_ARGS__), \ + ::onnxruntime::common::category, \ + ::onnxruntime::common::code) + #endif #define ORT_MAKE_STATUS(category, code, ...) \ @@ -237,7 +267,7 @@ void LogRuntimeError(uint32_t session_id, const common::Status& status, const ch auto _status = (expr); \ if ((!_status.IsOK())) { \ ::onnxruntime::LogRuntimeError(0, _status, __FILE__, static_cast(__FUNCTION__), __LINE__); \ - ORT_THROW(_status); \ + ORT_THROW_FROM_STATUS(_status); \ } \ } while (0) @@ -264,15 +294,29 @@ inline std::string ToUTF8String(const std::string& s) { return s; } /** * Convert a wide character string to a UTF-8 string */ -std::string ToUTF8String(const std::wstring& s); - -std::wstring ToWideString(const std::string& s); +std::string ToUTF8String(std::wstring_view s); +inline std::string ToUTF8String(const wchar_t* s) { + return ToUTF8String(std::wstring_view{s}); +} +inline std::string ToUTF8String(const std::wstring& s) { + return ToUTF8String(std::wstring_view{s}); +} +std::wstring ToWideString(std::string_view s); +inline std::wstring ToWideString(const char* s) { + return ToWideString(std::string_view{s}); +} +inline std::wstring ToWideString(const std::string& s) { + return ToWideString(std::string_view{s}); +} inline std::wstring ToWideString(const std::wstring& s) { return s; } +inline std::wstring ToWideString(std::wstring_view s) { return std::wstring{s}; } #else inline std::string ToWideString(const std::string& s) { return s; } +inline std::string ToWideString(const char* s) { return s; } +inline std::string ToWideString(std::string_view s) { return std::string{s}; } #endif -constexpr size_t kMaxStrLen = 2048; +constexpr size_t kMaxStrLen = 4096; // Returns whether `key` is in `container`. // Like C++20's map/set contains() member function. diff --git a/include/onnxruntime/core/common/const_pointer_container.h b/include/onnxruntime/core/common/const_pointer_container.h index 1d821ba609205..80343b4fea4d6 100644 --- a/include/onnxruntime/core/common/const_pointer_container.h +++ b/include/onnxruntime/core/common/const_pointer_container.h @@ -79,6 +79,10 @@ class ConstPointerContainer { return data_[index]; } + const T* const* data() const { + return data_.data(); + } + private: const Container& data_; }; diff --git a/include/onnxruntime/core/framework/endian.h b/include/onnxruntime/core/common/endian.h similarity index 100% rename from include/onnxruntime/core/framework/endian.h rename to include/onnxruntime/core/common/endian.h diff --git a/include/onnxruntime/core/common/exceptions.h b/include/onnxruntime/core/common/exceptions.h index 494a770b8db98..6d0f6edd6e7c4 100644 --- a/include/onnxruntime/core/common/exceptions.h +++ b/include/onnxruntime/core/common/exceptions.h @@ -11,6 +11,7 @@ #include #include "core/common/common.h" +#include "core/common/status.h" #include "core/common/code_location.h" namespace onnxruntime { @@ -35,12 +36,44 @@ class OnnxRuntimeException : public std::exception { /** Create a new exception that captures the location it was thrown from. @param location Location in the source code the exception is being thrown from + @param msg Message containing additional information about the exception cause. + @param category Error category + @param code Error code + */ + + OnnxRuntimeException(const CodeLocation& location, + const std::string& message, + common::StatusCategory category, + common::StatusCode code) noexcept + : OnnxRuntimeException(location, nullptr, message, category, code) { + } + + /** + Create a new exception that captures the location it was thrown from. + The instance will be created with ONNXRUNTIME category and FAIL code. + @param location Location in the source code the exception is being thrown from @param failed_condition Optional string containing the condition that failed. e.g. "tensor.Size() == input.Size()". May be nullptr. @param msg Message containing additional information about the exception cause. */ - OnnxRuntimeException(const CodeLocation& location, const char* failed_condition, const std::string& msg) - : location_{location} { + OnnxRuntimeException(const CodeLocation& location, const char* failed_condition, const std::string& msg) noexcept + : OnnxRuntimeException(location, failed_condition, msg, + common::StatusCategory::ONNXRUNTIME, common::StatusCode::FAIL) { + } + + /** + Create a new exception that captures the location it was thrown from. + @param location Location in the source code the exception is being thrown from + @param failed_condition Optional string containing the condition that failed. + e.g. "tensor.Size() == input.Size()". May be nullptr. + @param msg Message containing additional information about the exception cause. + @param category Error category + @param code Error code + */ + OnnxRuntimeException(const CodeLocation& location, const char* failed_condition, const std::string& msg, + common::StatusCategory category, + common::StatusCode code) + : location_{location}, category_(category), code_(code) { std::ostringstream ss; ss << location.ToString(CodeLocation::kFilenameAndPath); // output full path in case just the filename is ambiguous @@ -58,6 +91,14 @@ class OnnxRuntimeException : public std::exception { what_ = ss.str(); } + common::StatusCategory Category() const noexcept { + return category_; + } + + common::StatusCode Code() const noexcept { + return code_; + } + const char* what() const noexcept override { return what_.c_str(); } @@ -66,6 +107,8 @@ class OnnxRuntimeException : public std::exception { const CodeLocation location_; const std::vector stacktrace_; std::string what_; + common::StatusCategory category_; + common::StatusCode code_; }; } // namespace onnxruntime diff --git a/include/onnxruntime/core/framework/float16.h b/include/onnxruntime/core/common/float16.h similarity index 99% rename from include/onnxruntime/core/framework/float16.h rename to include/onnxruntime/core/common/float16.h index 97420ffe438d1..e9700be59fd3f 100644 --- a/include/onnxruntime/core/framework/float16.h +++ b/include/onnxruntime/core/common/float16.h @@ -4,9 +4,9 @@ #include -#include "endian.h" +#include "core/common/endian.h" #if defined(CUDA_VERSION) && CUDA_VERSION >= 11000 -#include "cuda_bf16.h" +#include "cuda_bf16.h" // from CUDA SDK #endif #if !defined(__CUDACC__) && !defined(__HIPCC__) @@ -46,6 +46,7 @@ struct MLFloat16 : onnxruntime_float16::Float16Impl { static const MLFloat16 Infinity; static const MLFloat16 NegativeInfinity; static const MLFloat16 MaxValue; + static const MLFloat16 MinValue; static const MLFloat16 Zero; static const MLFloat16 One; static const MLFloat16 MinusOne; @@ -180,6 +181,7 @@ struct BFloat16 : onnxruntime_float16::BFloat16Impl { static const BFloat16 Infinity; static const BFloat16 NegativeInfinity; static const BFloat16 MaxValue; + static const BFloat16 MinValue; static const BFloat16 Zero; static const BFloat16 One; static const BFloat16 MinusOne; diff --git a/include/onnxruntime/core/common/float8.h b/include/onnxruntime/core/common/float8.h new file mode 100644 index 0000000000000..9c342a346ee0b --- /dev/null +++ b/include/onnxruntime/core/common/float8.h @@ -0,0 +1,1230 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// IMPORTANT NOTE: Users of this file MUST include "cuda.h" before including this header +// if they would like to leverage the CUDA implementation for the conversion routines +// in their HOST code (code compiled by MSVC/GCC). +// This is because there is a check on CUDA_VERSION which is a macro defined in cuda.h. +// We can't include cuda.h in this header unconditionally because this header is also +// included in core framework files which are CUDA-agnostic. +// Not including "cuda.h" in GCC/MSVC will fall-back to the CPU conversion routines +// implemented in this file. +// For code compiled by NVCC which includes this header, this file will automatically +// include cuda.h (based on the CUDA_CC macro). + +#pragma once + +#if !defined(DISABLE_FLOAT8_TYPES) + +#include "core/common/endian.h" + +#if defined(__CUDACC__) +// Needed for CUDA_VERSION check below +#include +#endif + +#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 +#include "cuda_fp8.h" +#endif + +#if !defined(__CUDACC__) && !defined(__HIPCC__) +#include "core/common/narrow.h" +#endif + +#include "core/common/common.h" + +namespace onnxruntime { + +#if defined(__CUDACC__) || defined(__HIPCC__) +#define ORT_HOST_DEVICE __host__ __device__ +#else +#define ORT_HOST_DEVICE +#endif + +// Float8E4M3FN +struct Float8E4M3FN { + uint8_t val{0}; +#if defined(__HIP__) + ORT_HOST_DEVICE Float8E4M3FN() = default; +#else + Float8E4M3FN() = default; +#endif + struct FromBitsT {}; + static constexpr ORT_HOST_DEVICE FromBitsT FromBits() { return FromBitsT(); } + constexpr ORT_HOST_DEVICE Float8E4M3FN(unsigned char bits, FromBitsT) : val(bits) {} + + inline explicit ORT_HOST_DEVICE Float8E4M3FN(float v, bool saturate = true) { +#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 + val = __nv_cvt_float_to_fp8(v, saturate ? __NV_SATFINITE : __NV_NOSAT, __NV_E4M3); +#else + uint32_t b; + std::memcpy(&b, &v, sizeof(b)); + + val = static_cast((b & 0x80000000) >> 24); // sign + if ((b & 0x7fffffff) == 0x7f800000) { // infinity + if (saturate) { + val |= 126; + } else { + val |= 0x7f; + } + } else if ((b & 0x7F800000) == 0x7F800000) { // NaN + val |= 0x7f; + } else { + uint8_t e = static_cast((b & 0x7F800000) >> 23); // exponent + uint32_t m = static_cast(b & 0x007FFFFF); // mantissa + if (e != 0) { + if (e < 117) { + } else if (e < 121) { + // denormalized number + auto d = 120 - e; + if (d < 3) { + val |= 1 << (2 - d); + val |= m >> (21 + d); + } else if (m > 0) { + val |= 1; + } + auto mask = 1 << (20 + d); + if ((m & mask) && ((val & 1) || ((m & (mask - 1)) > 0) || ((m & mask) && (m & (mask << 1)) && ((m & (mask - 1)) == 0)))) { + // rounding + val += 1; + } + } else if (e < 136) { + // normalized number + auto ex = e - 120; + if (ex == 0) { + val |= 0x4; + val |= m >> 21; + } else { + val |= ex << 3; + val |= m >> 20; + if ((val & 0x7F) == 0x7F) { + val &= 0xFE; + } + } + if ((m & 0x80000) && ((m & 0x100000) || (m & 0x7FFFF))) { + if ((val & 0x7F) < 0x7E) { + // rounding + val += 1; + } else if (!saturate) { + val |= 0x7F; + } + } + } else if (saturate) { + val |= 126; // 0b01111110 + } else { + val |= 0x7F; + } + } + } +#endif + } + + inline ORT_HOST_DEVICE bool IsNaN() const { + return (val & 0b01111111) == 0b01111111; + } + + inline ORT_HOST_DEVICE float ToFloat() const { +#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 + return __half2float(__nv_cvt_fp8_to_halfraw(val, __NV_E4M3)); +#else + uint32_t res; + if (val == 255) { + res = 0xffc00000; + } else if (val == 127) { + res = 0x7fc00000; + } else { + uint32_t expo = (val & 0x78) >> 3; + uint32_t mant = val & 0x07; + uint32_t sign = val & 0x80; + res = sign << 24; + if (expo == 0) { + if (mant > 0) { + expo = 0x7F - 7; + if ((mant & 0x4) == 0) { + mant &= 0x3; + mant <<= 1; + expo -= 1; + } + if ((mant & 0x4) == 0) { + mant &= 0x3; + mant <<= 1; + expo -= 1; + } + res |= (mant & 0x3) << 21; + res |= expo << 23; + } + } else { + res |= mant << 20; + expo -= 0x7; + expo += 0x7F; + res |= expo << 23; + } + } + float float_res; + std::memcpy(&float_res, &res, sizeof(float)); + return float_res; +#endif + } + + inline ORT_HOST_DEVICE operator float() const { return ToFloat(); } + +#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 + explicit ORT_HOST_DEVICE Float8E4M3FN(const __nv_fp8_e4m3& value) { val = *reinterpret_cast(&value); } + explicit ORT_HOST_DEVICE operator __nv_fp8_e4m3() const { return *reinterpret_cast(&val); } +#endif +}; + +inline ORT_HOST_DEVICE bool operator==(const Float8E4M3FN& left, const Float8E4M3FN& right) { return left.val == right.val; } +inline ORT_HOST_DEVICE bool operator!=(const Float8E4M3FN& left, const Float8E4M3FN& right) { return left.val != right.val; } +inline ORT_HOST_DEVICE bool operator<(const Float8E4M3FN& left, const Float8E4M3FN& right) { return left.val < right.val; } + +// User defined suffixes to make it easier to declare +// initializers with MLFloat8E4M3FN and Float8E4M3FN from unsigned char +#if !defined(__CUDACC__) && !defined(__HIPCC__) + +inline Float8E4M3FN operator""_f8e4m3fn(unsigned long long int v) { + return Float8E4M3FN(narrow(v), Float8E4M3FN::FromBits()); +} + +inline Float8E4M3FN operator""_f8e4m3fnp8(long double v) { + return Float8E4M3FN(static_cast(v), true); +} + +#endif + +inline void Float8E4M3FNToFloat(const Float8E4M3FN* blf, float* flt, size_t size) { + auto src = blf; + auto d = flt; + for (; size != 0; ++src, ++d, --size) { + *d = src->ToFloat(); + } +} + +inline void FloatToFloat8E4M3FN(const float* flt, Float8E4M3FN* blf, size_t size, bool saturate) { + auto src = flt; + auto d = blf; + for (; size != 0; ++src, ++d, --size) { + new (d) Float8E4M3FN(*src, saturate); + } +} + +// Float8E4M3FNUZ +struct Float8E4M3FNUZ { + uint8_t val{0}; +#if defined(__HIP__) + ORT_HOST_DEVICE Float8E4M3FNUZ() = default; +#else + Float8E4M3FNUZ() = default; +#endif + + struct FromBitsT {}; + static constexpr ORT_HOST_DEVICE FromBitsT FromBits() { return FromBitsT(); } + constexpr ORT_HOST_DEVICE Float8E4M3FNUZ(unsigned char bits, FromBitsT) : val(bits) {} + + inline explicit ORT_HOST_DEVICE Float8E4M3FNUZ(float v, bool saturate = true) { + // This type does not exist on CUDA. + uint32_t b; + std::memcpy(&b, &v, sizeof(b)); + + val = static_cast((b & 0x80000000) >> 24); // sign + if ((b & 0x7fffffff) == 0x7f800000) { // infinity + if (saturate) { + // the highest available value + val |= 0x7F; + } else { + // NaN + val = 0x80; + } + } else if ((b & 0x7F800000) == 0x7F800000) { // NaN + val = 0x80; + } else { + uint8_t e = static_cast((b & 0x7F800000) >> 23); // exponent + uint32_t m = static_cast(b & 0x007FFFFF); // mantissa + + if (e < 116) { + // all near-zero numbers round to positive zero: + val = 0; + } else if (e < 120) { + // denormalized number + auto d = 119 - e; + if (d < 3) { + val |= 1 << (2 - d); + val |= m >> (21 + d); + } else if (m > 0) { + val |= 1; + } else { + // round to positive zero: + val = 0; + } + auto mask = 1 << (20 + d); + if ((m & mask) && ((val & 1) || ((m & (mask - 1)) > 0) || ((m & mask) && (m & (mask << 1)) && ((m & (mask - 1)) == 0)))) { + // rounding + val += 1; + } + } else if (e < 135) { + // normalized number + auto ex = e - 119; + if (ex == 0) { + val |= 0x4; + val |= m >> 21; + } else { + val |= ex << 3; + val |= m >> 20; + } + if ((m & 0x80000) && ((m & 0x100000) || (m & 0x7FFFF))) { + if ((val & 0x7F) < 0x7F) { + // rounding + val += 1; + } else if (!saturate) { + val = 0x80; + } + } + } else if (saturate) { + val |= 0x7F; + } else { + val = 0x80; + } + } + } + + inline ORT_HOST_DEVICE bool IsNaN() const { + return val == 0b10000000; + } + + inline ORT_HOST_DEVICE float ToFloat() const { + // This type does not exist on CUDA. + uint32_t res; + if (val == 0x80) { + res = 0xffc00000; + } else { + uint32_t expo = (val & 0x78) >> 3; + uint32_t mant = val & 0x07; + uint32_t sign = val & 0x80; + res = sign << 24; + if (expo == 0) { + if (mant > 0) { + expo = 0x7F - 8; + if ((mant & 0x4) == 0) { + mant &= 0x3; + mant <<= 1; + expo -= 1; + } + if ((mant & 0x4) == 0) { + mant &= 0x3; + mant <<= 1; + expo -= 1; + } + res |= (mant & 0x3) << 21; + res |= expo << 23; + } + } else { + res |= mant << 20; + expo -= 8; + expo += 0x7F; + res |= expo << 23; + } + } + float float_res; + std::memcpy(&float_res, &res, sizeof(float)); + return float_res; + } + + inline ORT_HOST_DEVICE operator float() const { return ToFloat(); } +}; + +inline ORT_HOST_DEVICE bool operator==(const Float8E4M3FNUZ& left, const Float8E4M3FNUZ& right) { return left.val == right.val; } +inline ORT_HOST_DEVICE bool operator!=(const Float8E4M3FNUZ& left, const Float8E4M3FNUZ& right) { return left.val != right.val; } +inline ORT_HOST_DEVICE bool operator<(const Float8E4M3FNUZ& left, const Float8E4M3FNUZ& right) { return left.val < right.val; } + +// User defined suffixes to make it easier to declare +// initializers with MLFloat8E4M3FN and Float8E4M3FN from unsigned char +#if !defined(__CUDACC__) && !defined(__HIPCC__) + +inline Float8E4M3FNUZ operator""_f8e4m3p8fnuz(unsigned long long int v) { + return Float8E4M3FNUZ(narrow(v), Float8E4M3FNUZ::FromBits()); +} + +inline Float8E4M3FNUZ operator""_f8e4m3fnuzp8(long double v) { + return Float8E4M3FNUZ(static_cast(v), true); +} + +#endif + +inline void Float8E4M3FNUZToFloat(const Float8E4M3FNUZ* blf, float* flt, size_t size) { + auto src = blf; + auto d = flt; + for (; size != 0; ++src, ++d, --size) { + *d = src->ToFloat(); + } +} + +inline void FloatToFloat8E4M3FNUZ(const float* flt, Float8E4M3FNUZ* blf, size_t size, bool saturate) { + auto src = flt; + auto d = blf; + for (; size != 0; ++src, ++d, --size) { + new (d) Float8E4M3FNUZ(*src, saturate); + } +} + +// Float8E5M2 +struct Float8E5M2 { + uint8_t val{0}; +#if defined(__HIP__) + ORT_HOST_DEVICE Float8E5M2() = default; +#else + Float8E5M2() = default; +#endif + + struct FromBitsT {}; + static constexpr ORT_HOST_DEVICE FromBitsT FromBits() { return FromBitsT(); } + constexpr ORT_HOST_DEVICE Float8E5M2(unsigned char bits, FromBitsT) : val(bits) {} + + inline explicit ORT_HOST_DEVICE Float8E5M2(float v, bool saturate = true) { +#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 + val = __nv_cvt_float_to_fp8(v, saturate ? __NV_SATFINITE : __NV_NOSAT, __NV_E5M2); +#else + uint32_t b; + std::memcpy(&b, &v, sizeof(b)); + + val = (b & 0x80000000) >> 24; // sign + if ((b & 0x7FFFFFFF) == 0x7F800000) { // inf + if (saturate) { + // the highest available value + val |= 0x7B; + } else { + // the infinity + val |= 0x7C; + } + } else if ((b & 0x7F800000) == 0x7F800000) { // NaN + val |= 0x7f; + } else { + uint32_t e = (b & 0x7F800000) >> 23; // exponent + uint32_t m = b & 0x007FFFFF; // mantissa + + if (e != 0) { + if (e < 110) { + } else if (e < 113) { + // denormalized number + auto d = 112 - e; + if (d < 2) { + val |= 1 << (1 - d); + val |= m >> (22 + d); + } else if (m > 0) { + val |= 1; + } + auto mask = 1 << (21 + d); + if ((m & mask) && ((val & 1) || ((m & (mask - 1)) > 0) || ((m & mask) && (m & (mask << 1)) && ((m & (mask - 1)) == 0)))) { + // rounding + val += 1; + } + } else if (e < 143) { // 127 + 15 + 1 + auto ex = e - 112; // 127 - 15 + val |= ex << 2; + val |= m >> 21; + if ((m & 0x100000) && ((m & 0xFFFFF) || (m & 0x200000))) { + if ((val & 0x7F) < 0x7B) { + // rounding + val += 1; + } else if (saturate) { + val |= 0x7B; + } else { + val |= 0x7C; + } + } + } else if (saturate) { + val |= 0x7B; + } else { + val |= 0x7C; + } + } + } +#endif + } + + inline ORT_HOST_DEVICE bool IsNaN() const { + // 7D, 7E, 7F are positive NaNs; FD, FE, FF are negative NaNs + return (val & 0b01111111) > 0b01111100; + } + + inline ORT_HOST_DEVICE bool IsInfinity() const { + // 7C and FC are infinity + return (val & 0b01111111) == 0b01111100; + } + + inline ORT_HOST_DEVICE float ToFloat() const { +#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 + return __half2float(__nv_cvt_fp8_to_halfraw(val, __NV_E5M2)); +#else + uint32_t res; + if (val >= 253) { + res = 0xffc00000; + } else if (val >= 125 && val <= 127) { + res = 0x7fc00000; + } else if (val == 252) { + res = 0xff800000; + } else if (val == 124) { + res = 0x7f800000; + } else { + uint32_t expo = (val & 0x7C) >> 2; + uint32_t mant = val & 0x03; + uint32_t sign = val & 0x80; + res = sign << 24; + if (expo == 0) { + if (mant > 0) { + expo = 0x7F - 15; + if ((mant & 0x2) == 0) { + mant &= 0x1; + mant <<= 1; + expo -= 1; + } + res |= (mant & 0x1) << 22; + res |= expo << 23; + } + } else { + res |= mant << 21; + expo -= 15; + expo += 0x7F; + res |= expo << 23; + } + } + + float float_res; + std::memcpy(&float_res, &res, sizeof(float)); + return float_res; +#endif + } + + inline ORT_HOST_DEVICE operator float() const { return ToFloat(); } + +#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 + ORT_HOST_DEVICE Float8E5M2(const __nv_fp8_e5m2& value) { val = *reinterpret_cast(&value); } + explicit ORT_HOST_DEVICE operator __nv_fp8_e5m2() const { return *reinterpret_cast(&val); } +#endif +}; + +inline ORT_HOST_DEVICE bool operator==(const Float8E5M2& left, const Float8E5M2& right) { return left.val == right.val; } +inline ORT_HOST_DEVICE bool operator!=(const Float8E5M2& left, const Float8E5M2& right) { return left.val != right.val; } +inline ORT_HOST_DEVICE bool operator<(const Float8E5M2& left, const Float8E5M2& right) { return left.val < right.val; } + +// User defined suffixes to make it easier to declare +// initializers with MLFloat8E5M2 and Float8E5M2 from unsigned char +#if !defined(__CUDACC__) && !defined(__HIPCC__) + +inline Float8E5M2 operator""_f8e5m2fn(unsigned long long int v) { + return Float8E5M2(narrow(v), Float8E5M2::FromBits()); +} + +inline Float8E5M2 operator""_f8e5m2fnp8(long double v) { + return Float8E5M2(static_cast(v), true); +} + +#endif + +inline void Float8E5M2ToFloat(const Float8E5M2* blf, float* flt, size_t size) { + auto src = blf; + auto d = flt; + for (; size != 0; ++src, ++d, --size) { + *d = src->ToFloat(); + } +} + +inline void FloatToFloat8E5M2(const float* flt, Float8E5M2* blf, size_t size, bool saturate) { + auto src = flt; + auto d = blf; + for (; size != 0; ++src, ++d, --size) { + new (d) Float8E5M2(*src, saturate); + } +} + +// Float8E5M2FNUZ +struct Float8E5M2FNUZ { + uint8_t val{0}; +#if defined(__HIP__) + ORT_HOST_DEVICE Float8E5M2FNUZ() = default; +#else + Float8E5M2FNUZ() = default; +#endif + + struct FromBitsT {}; + static constexpr ORT_HOST_DEVICE FromBitsT FromBits() { return FromBitsT(); } + constexpr ORT_HOST_DEVICE Float8E5M2FNUZ(unsigned char bits, FromBitsT) : val(bits) {} + + inline explicit ORT_HOST_DEVICE Float8E5M2FNUZ(float v, bool saturate = true) { + // This type does not exist on CUDA. + uint32_t b; + std::memcpy(&b, &v, sizeof(b)); + + val = (b & 0x80000000) >> 24; // sign + if ((b & 0x7FFFFFFF) == 0x7F800000) { // inf + if (saturate) { + val |= 0x7F; + } else { + val = 0x80; + } + } else if ((b & 0x7F800000) == 0x7F800000) { // NaN + val = 0x80; + } else { + uint32_t e = (b & 0x7F800000) >> 23; // exponent + uint32_t m = b & 0x007FFFFF; // mantissa + + if (e < 109) { + // all near-zero numbers round to positive zero: + val = 0; + } else if (e < 112) { + // denormalized number + auto d = 111 - e; + if (d < 2) { + val |= 1 << (1 - d); + val |= m >> (22 + d); + } else if (m > 0) { + val |= 1; + } else { + // round to positive zero: + val = 0; + } + auto mask = 1 << (21 + d); + if ((m & mask) && ((val & 1) || ((m & (mask - 1)) > 0) || ((m & mask) && (m & (mask << 1)) && ((m & (mask - 1)) == 0)))) { + // rounding + val += 1; + } + } else if (e < 143) { + // normalized number + auto ex = e - 111; + val |= ex << 2; + val |= m >> 21; + if ((m & 0x100000) && ((m & 0xFFFFF) || (m & 0x200000))) { + if ((val & 0x7F) < 0x7F) { + // rounding + val += 1; + } else if (!saturate) { + val = 0x80; + } + } + } else if ((e == 255) && (m == 0)) { + val = 0x80; + } else if (saturate) { + val |= 0x7F; + } else { + val = 0x80; + } + } + } + + inline ORT_HOST_DEVICE bool IsNaN() const { + return val == 0b10000000; + } + + inline ORT_HOST_DEVICE float ToFloat() const { + // This type does not exist on CUDA. + uint32_t res; + if (val == 0x80) { + res = 0xffc00000; + } else { + uint32_t expo = (val & 0x7C) >> 2; + uint32_t mant = val & 0x03; + uint32_t sign = val & 0x80; + res = sign << 24; + if (expo == 0) { + if (mant > 0) { + expo = 0x7F - 16; + if ((mant & 0x2) == 0) { + mant &= 0x1; + mant <<= 1; + expo -= 1; + } + res |= (mant & 0x1) << 22; + res |= expo << 23; + } + } else { + res |= mant << 21; + expo -= 16; + expo += 0x7F; + res |= expo << 23; + } + } + + float float_res; + std::memcpy(&float_res, &res, sizeof(float)); + return float_res; + } + + inline ORT_HOST_DEVICE operator float() const { return ToFloat(); } +}; + +inline ORT_HOST_DEVICE bool operator==(const Float8E5M2FNUZ& left, const Float8E5M2FNUZ& right) { return left.val == right.val; } +inline ORT_HOST_DEVICE bool operator!=(const Float8E5M2FNUZ& left, const Float8E5M2FNUZ& right) { return left.val != right.val; } +inline ORT_HOST_DEVICE bool operator<(const Float8E5M2FNUZ& left, const Float8E5M2FNUZ& right) { return left.val < right.val; } + +// User defined suffixes to make it easier to declare +// initializers with MLFloat8E5M2 and Float8E5M2 from unsigned char +#if !defined(__CUDACC__) && !defined(__HIPCC__) + +inline Float8E5M2FNUZ operator""_f8e5m2fnuz(unsigned long long int v) { + return Float8E5M2FNUZ(narrow(v), Float8E5M2FNUZ::FromBits()); +} + +inline Float8E5M2FNUZ operator""_f8e5m2fnuzp8(long double v) { + return Float8E5M2FNUZ(static_cast(v), true); +} + +#endif + +inline void Float8E5M2FNUZToFloat(const Float8E5M2FNUZ* blf, float* flt, size_t size) { + auto src = blf; + auto d = flt; + for (; size != 0; ++src, ++d, --size) { + *d = src->ToFloat(); + } +} + +inline void FloatToFloat8E5M2FNUZ(const float* flt, Float8E5M2FNUZ* blf, size_t size, bool saturate) { + auto src = flt; + auto d = blf; + for (; size != 0; ++src, ++d, --size) { + new (d) Float8E5M2FNUZ(*src, saturate); + } +} + +// Float8E8M0 +// 8-bit floating point with 8 exponent bits and 0 mantissa bits (no sign bit). +// All representable values are powers of two: 2^(val - 127). +// Special value: 0xFF = NaN. +struct Float8E8M0 { + uint8_t val{0}; // Raw 8-bit exponent value. Represents 2^(val - 127). 0xFF = NaN. +#if defined(__HIP__) + ORT_HOST_DEVICE Float8E8M0() = default; +#else + Float8E8M0() = default; +#endif + + struct FromBitsT {}; + static constexpr ORT_HOST_DEVICE FromBitsT FromBits() { return FromBitsT(); } + constexpr ORT_HOST_DEVICE Float8E8M0(unsigned char bits, FromBitsT) : val(bits) {} + + /// Rounding modes for Float8E8M0 conversion from float. + /// These correspond to the ONNX Cast op's round_mode attribute for float8e8m0. + /// See: https://github.com/onnx/onnx/blob/main/onnx/numpy_helper.py (to_float8e8m0) + enum class RoundMode : uint8_t { + Up, // Ceiling: always round up to next power of 2 when not exact (default). + Down, // Floor: always truncate to lower power of 2. + Nearest, // Round to nearest power of 2; ties round to higher power (round-half-up). + }; + + inline explicit ORT_HOST_DEVICE Float8E8M0(float v, bool saturate = true, + RoundMode round_mode = RoundMode::Up) { + uint32_t b; + std::memcpy(&b, &v, sizeof(b)); + + uint32_t sign = b & 0x80000000; + uint32_t exponent = (b & 0x7F800000) >> 23; + uint32_t mantissa = b & 0x007FFFFF; + + // NaN (check before sign since NaN has no sign semantics) + if (exponent == 0xFF && mantissa != 0) { + val = 0xFF; + return; + } + + // Infinity (check before sign to handle -Inf consistently) + if (exponent == 0xFF && mantissa == 0) { + if (sign) { + // Negative infinity + if (saturate) { + val = 0x00; + } else { + val = 0xFF; // NaN + } + } else { + // Positive infinity + if (saturate) { + val = 0xFE; // Largest finite value: 2^127 + } else { + val = 0xFF; // NaN (no infinity in this format) + } + } + return; + } + + // Negative values (except -0) cannot be represented + if (sign && (exponent != 0 || mantissa != 0)) { + if (saturate) { + // Saturate negative to smallest positive (2^-127) + val = 0x00; + } else { + val = 0xFF; // NaN + } + return; + } + + // Zero: E8M0 cannot represent zero. + if (exponent == 0 && mantissa == 0) { + if (saturate) { + val = 0x00; // Saturate to smallest representable: 2^(-127) + } else { + val = 0xFF; // NaN (zero is out of range) + } + return; + } + + // Denormalized float32: value = 2^(-126) * (mantissa / 2^23), range (0, 2^(-126)). + // E8M0 can represent 2^(-127) (val=0) and 2^(-126) (val=1). For nearest rounding, + // the midpoint is 1.5 * 2^(-127), which is mantissa 0x600000. Ties round up. + if (exponent == 0) { + // Subnormals with mantissa < 0x400000 have value < E8M0_MIN (2^-127) and + // cannot be represented. Without saturation they map to NaN. + // Subnormals with mantissa >= 0x400000 have value >= E8M0_MIN, so they + // round to val=0 or val=1, both valid E8M0 values. + if (!saturate && mantissa < 0x00400000) { + val = 0xFF; // NaN: x < E8M0_MIN is not representable without saturation + return; + } + bool round_up; + switch (round_mode) { + case RoundMode::Up: + // Ceiling: round up only when value > 2^(-127). Denorm mantissa == 0x400000 + // is exactly 2^(-127) (val=0), so it must NOT round up. + round_up = (mantissa > 0x00400000); + break; + case RoundMode::Down: + // Floor: always keep val=0 (2^(-127)), never increment. + round_up = false; + break; + case RoundMode::Nearest: + default: + round_up = (mantissa >= 0x00600000); + break; + } + if (round_up) { + val = 0x01; // 2^(-126) + } else { + val = 0x00; // 2^(-127) + } + return; + } + + // Normal float32: value is 2^(exponent - 127) * (1 + mantissa/2^23). + // Values with exponent=254 and mantissa>0 are in (2^127, 2^128). Since 2^128 + // is not representable in E8M0 (val 255 = NaN), without saturation these + // values cannot be rounded to any valid E8M0 value and must become NaN. + if (!saturate && exponent == 0xFE && mantissa != 0) { + val = 0xFF; // NaN: x > E8M0_MAX is not representable without saturation + return; + } + // Round to the nearest power of 2 using the ONNX semantics: + // Up (ceiling): round up when the float is not exactly a power of 2 (mantissa > 0). + // Down (floor): never round up; always keep the lower exponent. + // Nearest: G bit (bit 22) determines direction -- round up when mantissa >= 0x400000. + // For normal floats lsb of exponent is always considered 1, so ties + // round to the higher power of 2 (round-half-up). + bool round_up; + switch (round_mode) { + case RoundMode::Up: + round_up = (mantissa > 0); + break; + case RoundMode::Down: + round_up = false; + break; + case RoundMode::Nearest: + default: + round_up = (mantissa >= 0x00400000); + break; + } + if (round_up) { + exponent += 1; + } + + // After rounding, exponent may overflow. + if (exponent > 0xFE) { + if (saturate) { + val = 0xFE; // Largest finite: 2^127 + } else { + val = 0xFF; // NaN + } + return; + } + + val = static_cast(exponent); + } + + inline ORT_HOST_DEVICE bool IsNaN() const { + return val == 0xFF; + } + + inline ORT_HOST_DEVICE float ToFloat() const { + if (val == 0xFF) { + // NaN + uint32_t res = 0x7FC00000; // quiet NaN + float float_res; + std::memcpy(&float_res, &res, sizeof(float)); + return float_res; + } + + if (val == 0) { + // 2^(-127) is a denormalized float32: sign=0, exponent=0, mantissa=2^22 + // Denorm value = 2^(-126) * (mantissa/2^23) = 2^(-126) * 0.5 = 2^(-127) + uint32_t res = 0x00400000; + float float_res; + std::memcpy(&float_res, &res, sizeof(float)); + return float_res; + } + + // For val 1-254: Value is 2^(val - 127) + // In float32: exponent field = val, mantissa = 0, sign = 0 + uint32_t res = static_cast(val) << 23; + float float_res; + std::memcpy(&float_res, &res, sizeof(float)); + return float_res; + } + + inline ORT_HOST_DEVICE operator float() const { return ToFloat(); } +}; + +inline ORT_HOST_DEVICE bool operator==(const Float8E8M0& left, const Float8E8M0& right) { return left.val == right.val; } +inline ORT_HOST_DEVICE bool operator!=(const Float8E8M0& left, const Float8E8M0& right) { return left.val != right.val; } +inline ORT_HOST_DEVICE bool operator<(const Float8E8M0& left, const Float8E8M0& right) { return left.val < right.val; } + +// User defined suffixes to make it easier to declare +// initializers with Float8E8M0 from unsigned char +#if !defined(__CUDACC__) && !defined(__HIPCC__) + +inline Float8E8M0 operator""_f8e8m0(unsigned long long int v) { + return Float8E8M0(narrow(v), Float8E8M0::FromBits()); +} + +inline Float8E8M0 operator""_f8e8m0f(long double v) { + return Float8E8M0(static_cast(v), true); +} + +#endif + +inline void Float8E8M0ToFloat(const Float8E8M0* blf, float* flt, size_t size) { + auto src = blf; + auto d = flt; + for (; size != 0; ++src, ++d, --size) { + *d = src->ToFloat(); + } +} + +inline void FloatToFloat8E8M0(const float* flt, Float8E8M0* blf, size_t size, bool saturate) { + auto src = flt; + auto d = blf; + for (; size != 0; ++src, ++d, --size) { + new (d) Float8E8M0(*src, saturate); + } +} + +} // namespace onnxruntime + +namespace std { + +template <> +class numeric_limits { + public: + static constexpr onnxruntime::Float8E4M3FN lowest() { + return onnxruntime::Float8E4M3FN(0xFE, onnxruntime::Float8E4M3FN::FromBits()); // -448 + } + + static constexpr onnxruntime::Float8E4M3FN max() { + return onnxruntime::Float8E4M3FN(0x7E, onnxruntime::Float8E4M3FN::FromBits()); // 448 + } + + static constexpr onnxruntime::Float8E4M3FN min() { + return onnxruntime::Float8E4M3FN(0x08, onnxruntime::Float8E4M3FN::FromBits()); // 2^-6 = 0.015625 + } + + static constexpr onnxruntime::Float8E4M3FN denorm_min() { + return onnxruntime::Float8E4M3FN(0x01, onnxruntime::Float8E4M3FN::FromBits()); // 2^-9 = 0.001953125 + } + + static constexpr onnxruntime::Float8E4M3FN epsilon() { + return onnxruntime::Float8E4M3FN(0x20, onnxruntime::Float8E4M3FN::FromBits()); + } + + static constexpr onnxruntime::Float8E4M3FN round_error() { + return onnxruntime::Float8E4M3FN(0x30, onnxruntime::Float8E4M3FN::FromBits()); + } + + static constexpr onnxruntime::Float8E4M3FN infinity() { + // no infinity, returns quiet NaN instead + return quiet_NaN(); + } + + static constexpr onnxruntime::Float8E4M3FN quiet_NaN() { + return onnxruntime::Float8E4M3FN(0x7F, onnxruntime::Float8E4M3FN::FromBits()); + } + + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr auto has_denorm = true; + static constexpr auto has_denorm_loss = true; + static constexpr auto round_style = round_to_nearest; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 4; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 3; + static constexpr int radix = 2; + static constexpr int min_exponent = -5; + static constexpr int min_exponent10 = -1; + static constexpr int max_exponent = 8; + static constexpr int max_exponent10 = 2; + static constexpr auto traps = false; + static constexpr auto tinyness_before = false; +}; + +template <> +class numeric_limits { + public: + static constexpr onnxruntime::Float8E5M2 lowest() { + return onnxruntime::Float8E5M2(0xFB, onnxruntime::Float8E5M2::FromBits()); // -57344.0 + } + + static constexpr onnxruntime::Float8E5M2 max() { + return onnxruntime::Float8E5M2(0x7B, onnxruntime::Float8E5M2::FromBits()); // 57344.0 + } + + static constexpr onnxruntime::Float8E5M2 min() { + return onnxruntime::Float8E5M2(0x4, onnxruntime::Float8E5M2::FromBits()); // 2^-14 = 0.00006103515 + } + + static constexpr onnxruntime::Float8E5M2 denorm_min() { + return onnxruntime::Float8E5M2(0x01, onnxruntime::Float8E5M2::FromBits()); // 2^-16 = 0.00001525878 + } + + static constexpr onnxruntime::Float8E5M2 epsilon() { + return onnxruntime::Float8E5M2(0x34, onnxruntime::Float8E5M2::FromBits()); + } + + static constexpr onnxruntime::Float8E5M2 round_error() { + return onnxruntime::Float8E5M2(0x38, onnxruntime::Float8E5M2::FromBits()); + } + + static constexpr onnxruntime::Float8E5M2 infinity() { + return onnxruntime::Float8E5M2(0x7C, onnxruntime::Float8E5M2::FromBits()); + } + + static constexpr onnxruntime::Float8E5M2 quiet_NaN() { + return onnxruntime::Float8E5M2(0x7F, onnxruntime::Float8E5M2::FromBits()); + } + + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = true; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr auto has_denorm = true; + static constexpr auto has_denorm_loss = true; + static constexpr auto round_style = round_to_nearest; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 3; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 2; + static constexpr int radix = 2; + static constexpr int min_exponent = -13; + static constexpr int min_exponent10 = -4; + static constexpr int max_exponent = 16; + static constexpr int max_exponent10 = 4; + static constexpr auto traps = false; + static constexpr auto tinyness_before = false; +}; + +template <> +class numeric_limits { + public: + static constexpr onnxruntime::Float8E4M3FNUZ lowest() { + return onnxruntime::Float8E4M3FNUZ(0xFF, onnxruntime::Float8E4M3FNUZ::FromBits()); // -240.0 + } + + static constexpr onnxruntime::Float8E4M3FNUZ max() { + return onnxruntime::Float8E4M3FNUZ(0x7F, onnxruntime::Float8E4M3FNUZ::FromBits()); // 240.0 + } + + static constexpr onnxruntime::Float8E4M3FNUZ min() { + return onnxruntime::Float8E4M3FNUZ(0x08, onnxruntime::Float8E4M3FNUZ::FromBits()); // 2^-7 = 0.0078125 + } + + static constexpr onnxruntime::Float8E4M3FNUZ denorm_min() { + return onnxruntime::Float8E4M3FNUZ(0x01, onnxruntime::Float8E4M3FNUZ::FromBits()); // 2^-10 = 0.0009765625 + } + + static constexpr onnxruntime::Float8E4M3FNUZ epsilon() { + return onnxruntime::Float8E4M3FNUZ(0x28, onnxruntime::Float8E4M3FNUZ::FromBits()); + } + + static constexpr onnxruntime::Float8E4M3FNUZ round_error() { + return onnxruntime::Float8E4M3FNUZ(0x38, onnxruntime::Float8E4M3FNUZ::FromBits()); + } + + static constexpr onnxruntime::Float8E4M3FNUZ infinity() { + // no infinity, returns quiet NaN instead + return quiet_NaN(); + } + + static constexpr onnxruntime::Float8E4M3FNUZ quiet_NaN() { + return onnxruntime::Float8E4M3FNUZ(0x80, onnxruntime::Float8E4M3FNUZ::FromBits()); + } + + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr auto has_denorm = true; + static constexpr auto has_denorm_loss = true; + static constexpr auto round_style = round_to_nearest; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 4; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 3; + static constexpr int radix = 2; + static constexpr int min_exponent = -6; + static constexpr int min_exponent10 = -1; + static constexpr int max_exponent = 8; + static constexpr int max_exponent10 = 2; + static constexpr auto traps = false; + static constexpr auto tinyness_before = false; +}; + +template <> +class numeric_limits { + public: + static constexpr onnxruntime::Float8E5M2FNUZ lowest() { + return onnxruntime::Float8E5M2FNUZ(0xFF, onnxruntime::Float8E5M2FNUZ::FromBits()); // -57344.0 + } + + static constexpr onnxruntime::Float8E5M2FNUZ max() { + return onnxruntime::Float8E5M2FNUZ(0x7F, onnxruntime::Float8E5M2FNUZ::FromBits()); // 57344.0 + } + + static constexpr onnxruntime::Float8E5M2FNUZ min() { + return onnxruntime::Float8E5M2FNUZ(0x04, onnxruntime::Float8E5M2FNUZ::FromBits()); // 2^-15 = 0.00003051757 + } + + static constexpr onnxruntime::Float8E5M2FNUZ denorm_min() { + return onnxruntime::Float8E5M2FNUZ(0x01, onnxruntime::Float8E5M2FNUZ::FromBits()); // 2^-17 = 0.00000762939 + } + + static constexpr onnxruntime::Float8E5M2FNUZ epsilon() { + return onnxruntime::Float8E5M2FNUZ(0x34, onnxruntime::Float8E5M2FNUZ::FromBits()); + } + + static constexpr onnxruntime::Float8E5M2FNUZ round_error() { + return onnxruntime::Float8E5M2FNUZ(0x38, onnxruntime::Float8E5M2FNUZ::FromBits()); + } + + static constexpr onnxruntime::Float8E5M2FNUZ infinity() { + // no infinity, returns quiet NaN instead + return quiet_NaN(); + } + + static constexpr onnxruntime::Float8E5M2FNUZ quiet_NaN() { + return onnxruntime::Float8E5M2FNUZ(0x80, onnxruntime::Float8E5M2FNUZ::FromBits()); + } + + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr auto has_denorm = true; + static constexpr auto has_denorm_loss = true; + static constexpr auto round_style = round_to_nearest; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 3; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 2; + static constexpr int radix = 2; + static constexpr int min_exponent = -14; + static constexpr int min_exponent10 = -4; + static constexpr int max_exponent = 16; + static constexpr int max_exponent10 = 4; + static constexpr auto traps = false; + static constexpr auto tinyness_before = false; +}; + +template <> +class numeric_limits { + public: + // Float8E8M0 has no sign bit, so lowest == min (smallest positive normal) + static constexpr onnxruntime::Float8E8M0 lowest() { + return onnxruntime::Float8E8M0(0x00, onnxruntime::Float8E8M0::FromBits()); // 2^-127 + } + + static constexpr onnxruntime::Float8E8M0 max() { + return onnxruntime::Float8E8M0(0xFE, onnxruntime::Float8E8M0::FromBits()); // 2^127 + } + + static constexpr onnxruntime::Float8E8M0 min() { + return onnxruntime::Float8E8M0(0x00, onnxruntime::Float8E8M0::FromBits()); // 2^-127 + } + + static constexpr onnxruntime::Float8E8M0 denorm_min() { + // E8M0 has no denormalized values; return min() as required by the standard when has_denorm == false + return onnxruntime::Float8E8M0(0x00, onnxruntime::Float8E8M0::FromBits()); + } + + static constexpr onnxruntime::Float8E8M0 epsilon() { + // epsilon = (next representable value above 1.0) - 1.0 = 2.0 - 1.0 = 1.0 + // because E8M0 values are powers of 2, so 1.0 (val=127) is followed by 2.0 (val=128) + return onnxruntime::Float8E8M0(0x7F, onnxruntime::Float8E8M0::FromBits()); + } + + static constexpr onnxruntime::Float8E8M0 round_error() { + return onnxruntime::Float8E8M0(0x7F, onnxruntime::Float8E8M0::FromBits()); // 1.0 + } + + static constexpr onnxruntime::Float8E8M0 infinity() { + // no infinity, returns quiet NaN instead + return quiet_NaN(); + } + + static constexpr onnxruntime::Float8E8M0 quiet_NaN() { + return onnxruntime::Float8E8M0(0xFF, onnxruntime::Float8E8M0::FromBits()); + } + + static constexpr bool is_specialized = true; + static constexpr bool is_signed = false; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = true; + static constexpr bool has_signaling_NaN = false; + static constexpr auto has_denorm = false; + static constexpr auto has_denorm_loss = false; + static constexpr auto round_style = round_to_nearest; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 1; + static constexpr int digits10 = 0; + static constexpr int max_digits10 = 1; + static constexpr int radix = 2; + static constexpr int min_exponent = -126; + static constexpr int min_exponent10 = -38; + static constexpr int max_exponent = 128; + static constexpr int max_exponent10 = 38; + static constexpr auto traps = false; + static constexpr auto tinyness_before = false; +}; + +} // namespace std + +#endif // DISABLE_FLOAT8_TYPES diff --git a/include/onnxruntime/core/common/gpu_profiler_common.h b/include/onnxruntime/core/common/gpu_profiler_common.h index 00d5033ef2df4..8a86039b19680 100644 --- a/include/onnxruntime/core/common/gpu_profiler_common.h +++ b/include/onnxruntime/core/common/gpu_profiler_common.h @@ -122,6 +122,10 @@ class GPUTracerManager { tracing_enabled_ = this_as_derived->OnStartLogging(); } + bool IsTracingEnabled() const noexcept { + return tracing_enabled_; + } + void Consume(uint64_t client_handle, const TimePoint& start_time, std::map& events) { auto this_as_derived = static_cast(this); events.clear(); @@ -377,10 +381,14 @@ class GPUProfilerBase : public EpProfiler { virtual ~GPUProfilerBase() {} void MergeEvents(std::map& events_to_merge, Events& events) { + // TODO: Fix incorrect assumption that ORT events are sorted by non-decreasing start time. + // They are actually sorted by non-decreasing end time, which prevents this algorithm + // from properly merging and annotating all EP events. + // See Profiler::EndTimeAndRecordEvent() in onnxruntime/core/common/profiler.cc Events merged_events; - auto event_iter = std::make_move_iterator(events.begin()); - auto event_end = std::make_move_iterator(events.end()); + auto event_iter = events.begin(); + auto event_end = events.end(); for (auto& map_iter : events_to_merge) { if (map_iter.second.empty()) { continue; @@ -395,7 +403,7 @@ class GPUProfilerBase : public EpProfiler { (event_iter->ts == ts && (event_iter + 1) != event_end && (event_iter + 1)->ts == ts))) { - merged_events.emplace_back(*event_iter); + merged_events.emplace_back(*std::make_move_iterator(event_iter)); ++event_iter; } @@ -409,7 +417,7 @@ class GPUProfilerBase : public EpProfiler { copy_op_names = true; op_name = event_iter->args["op_name"]; parent_name = event_iter->name; - merged_events.emplace_back(*event_iter); + merged_events.emplace_back(*std::make_move_iterator(event_iter)); ++event_iter; } @@ -428,7 +436,9 @@ class GPUProfilerBase : public EpProfiler { } // move any remaining events - merged_events.insert(merged_events.end(), event_iter, event_end); + merged_events.insert(merged_events.end(), + std::make_move_iterator(event_iter), + std::make_move_iterator(event_end)); std::swap(events, merged_events); } @@ -436,11 +446,16 @@ class GPUProfilerBase : public EpProfiler { TimePoint profiling_start_time_; public: - virtual bool StartProfiling(TimePoint profiling_start_time) override { + virtual Status StartProfiling(TimePoint profiling_start_time) override { auto& manager = TManager::GetInstance(); manager.StartLogging(); profiling_start_time_ = profiling_start_time; - return true; + if (!manager.IsTracingEnabled()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, EP_FAIL, + "GPU activity tracing failed to start. " + "The tracing library may be unavailable or blocked by system policy."); + } + return Status::OK(); } virtual void EndProfiling(TimePoint start_time, Events& events) override { @@ -455,7 +470,7 @@ class GPUProfilerBase : public EpProfiler { manager.PushCorrelation(client_handle_, id, profiling_start_time_); } - virtual void Stop(uint64_t) override { + virtual void Stop(uint64_t, const EventRecord&) override { auto& manager = TManager::GetInstance(); manager.PopCorrelation(); } diff --git a/include/onnxruntime/core/common/inlined_containers.h b/include/onnxruntime/core/common/inlined_containers.h index bd61e691a5d5d..00bf2d19c11b5 100644 --- a/include/onnxruntime/core/common/inlined_containers.h +++ b/include/onnxruntime/core/common/inlined_containers.h @@ -16,6 +16,8 @@ // C4324: structure was padded due to alignment specifier // Usage of alignas causes some internal padding in places. #pragma warning(disable : 4324) +// C4702: unreachable code +#pragma warning(disable : 4702) #endif // _MSC_VER #include diff --git a/include/onnxruntime/core/common/inlined_containers_fwd.h b/include/onnxruntime/core/common/inlined_containers_fwd.h index 21a55f9b315bc..4b150955ece17 100644 --- a/include/onnxruntime/core/common/inlined_containers_fwd.h +++ b/include/onnxruntime/core/common/inlined_containers_fwd.h @@ -14,6 +14,8 @@ // C4324: structure was padded due to alignment specifier // Usage of alignas causes some internal padding in places. #pragma warning(disable : 4324) +// C4702: unreachable code +#pragma warning(disable : 4702) #else // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=102329#c2 #if !defined(__clang__) && defined(__GNUC__) diff --git a/include/onnxruntime/core/common/logging/logging.h b/include/onnxruntime/core/common/logging/logging.h index ab2c476f2975a..c822d430c2a23 100644 --- a/include/onnxruntime/core/common/logging/logging.h +++ b/include/onnxruntime/core/common/logging/logging.h @@ -17,7 +17,6 @@ #include "core/common/logging/macros.h" #include "core/common/logging/severity.h" #include "core/common/logging/sink_types.h" -#include "date/date.h" /* @@ -51,47 +50,43 @@ */ -namespace onnxruntime { +struct OrtLogger; // opaque API type. is always an instance of Logger +namespace onnxruntime { namespace logging { -using Timestamp = std::chrono::time_point; +// This class wraps `std::chrono::system_clock::time_point` and provides `operator<<`. +// It is a workaround for the inconsistent availability of `std::chrono::operator<<` for +// `std::chrono::system_clock::time_point`. +// TODO When all builds support `std::chrono::operator<<`, we can simply use `std::chrono::system_clock::time_point`: +// `using Timestamp = std::chrono::system_clock::time_point;` +class Timestamp { + public: + using TimePoint = std::chrono::system_clock::time_point; -// C++20 has operator<< in std::chrono for Timestamp type but mac builds need additional checks -// to ensure usage is valid. -// TODO: As we enable C++20 on other platforms we may need similar checks. -// define a temporary value to determine whether to use the std::chrono or date implementation. -#define ORT_USE_CXX20_STD_CHRONO __cplusplus >= 202002L + // This constructor is intentionally not `explicit` to allow implicit conversion from + // `std::chrono::system_clock::time_point`, a.k.a., `TimePoint`. + // The hope is that eventually we can replace the `Timestamp` class with an alias to `TimePoint`. + Timestamp(const TimePoint& time_point) noexcept : time_point_{time_point} {} -// Apply constraints for mac builds -#if __APPLE__ -#include + // Partial implementation of `std::chrono::system_clock::time_point` interface. -// Catalyst check must be first as it has both TARGET_OS_MACCATALYST and TARGET_OS_MAC set -#if TARGET_OS_MACCATALYST -// maccatalyst requires version 16.3 -#if (defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 160300) -#undef ORT_USE_CXX20_STD_CHRONO -#endif + using duration = TimePoint::duration; -#elif TARGET_OS_MAC -// Xcode added support for C++20's std::chrono::operator<< in SDK version 14.4, -// but the target macOS version must also be >= 13.3 for it to be used. -#if (defined(__MAC_OS_X_VERSION_MAX_ALLOWED) && __MAC_OS_X_VERSION_MAX_ALLOWED < 140400) || \ - (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 130300) -#undef ORT_USE_CXX20_STD_CHRONO -#endif + friend std::ostream& operator<<(std::ostream& os, const Timestamp& time_stamp) { + return time_stamp.WriteToStream(os); + } -#endif -#endif // __APPLE__ + friend std::wostream& operator<<(std::wostream& os, const Timestamp& time_stamp) { + return time_stamp.WriteToWStream(os); + } -#if ORT_USE_CXX20_STD_CHRONO -namespace timestamp_ns = std::chrono; -#else -namespace timestamp_ns = ::date; -#endif + private: + std::ostream& WriteToStream(std::ostream& os) const; + std::wostream& WriteToWStream(std::wostream& os) const; -#undef ORT_USE_CXX20_STD_CHRONO + TimePoint time_point_{}; +}; #ifndef NDEBUG ORT_ATTRIBUTE_UNUSED static bool vlog_enabled = true; // Set directly based on your needs. @@ -352,6 +347,10 @@ class Logger { logging_manager_->SendProfileEvent(eventRecord); } + // convert to API type for custom ops and plugin EPs + OrtLogger* ToExternal() { return reinterpret_cast(this); } + const OrtLogger* ToExternal() const { return reinterpret_cast(this); } + private: const LoggingManager* logging_manager_; const std::string id_; @@ -391,7 +390,7 @@ inline Timestamp LoggingManager::GetTimestamp() const noexcept { static const Epochs& epochs = GetEpochs(); const auto high_res_now = std::chrono::high_resolution_clock::now(); - return std::chrono::time_point_cast( + return std::chrono::time_point_cast( epochs.system + (high_res_now - epochs.high_res) + epochs.localtime_offset_from_utc); } diff --git a/include/onnxruntime/core/common/parse_string.h b/include/onnxruntime/core/common/parse_string.h index 6345b2a55490d..5f88d490b3415 100644 --- a/include/onnxruntime/core/common/parse_string.h +++ b/include/onnxruntime/core/common/parse_string.h @@ -35,13 +35,30 @@ template std::enable_if_t, bool> TryParseStringWithClassicLocale(std::string_view str, T& value) { T parsed_value{}; - const auto [ptr, ec] = std::from_chars(str.data(), str.data() + str.size(), parsed_value); - if (ec != std::errc{}) { + std::from_chars_result conversion_result{}; + if constexpr (std::is_integral_v && std::is_unsigned_v) { + // For unsigned integral types, also handle hex values, i.e., those beginning with "0x". + // std::from_chars() does not accept the "0x" prefix. + const bool has_hex_prefix = str.size() >= 2 && + str[0] == '0' && + (str[1] == 'x' || str[1] == 'X'); + + if (has_hex_prefix) { + str = str.substr(2); + } + + const int base = has_hex_prefix ? 16 : 10; + conversion_result = std::from_chars(str.data(), str.data() + str.size(), parsed_value, base); + } else { + conversion_result = std::from_chars(str.data(), str.data() + str.size(), parsed_value); + } + + if (conversion_result.ec != std::errc{}) { return false; } - if (ptr != str.data() + str.size()) { + if (conversion_result.ptr != str.data() + str.size()) { return false; } diff --git a/include/onnxruntime/core/common/profiler_common.h b/include/onnxruntime/core/common/profiler_common.h index ab973256fe5f1..48a75731eb5e1 100644 --- a/include/onnxruntime/core/common/profiler_common.h +++ b/include/onnxruntime/core/common/profiler_common.h @@ -4,13 +4,15 @@ #pragma once #include "core/common/common.h" +#include "core/common/inlined_containers.h" #include -#include namespace onnxruntime { namespace profiling { +// Profiling event categories. +// Note: Keep in sync with OrtProfilingEventCategory in onnxruntime_ep_c_api.h. enum EventCategory { SESSION_EVENT = 0, NODE_EVENT, @@ -35,7 +37,7 @@ struct EventRecord { std::string&& event_name, long long time_stamp, long long duration, - std::unordered_map&& event_args) + InlinedHashMap&& event_args) : cat(category), pid(process_id), tid(thread_id), @@ -50,7 +52,7 @@ struct EventRecord { const std::string& event_name, long long time_stamp, long long duration, - const std::unordered_map& event_args) + const InlinedHashMap& event_args) : cat(category), pid(process_id), tid(thread_id), @@ -70,7 +72,7 @@ struct EventRecord { std::string name{}; long long ts = 0; long long dur = 0; - std::unordered_map args{}; + InlinedHashMap args{}; }; using Events = std::vector; @@ -79,10 +81,74 @@ using Events = std::vector; class EpProfiler { public: virtual ~EpProfiler() = default; - virtual bool StartProfiling(TimePoint profiling_start_time) = 0; // called when profiling starts - virtual void EndProfiling(TimePoint start_time, Events& events) = 0; // called when profiling ends, save all captures numbers to "events" - virtual void Start(uint64_t) {} // called before op start, accept an id as argument to identify the op - virtual void Stop(uint64_t) {} // called after op stop, accept an id as argument to identify the op + + /// + /// Called when profiling starts. + /// Allows EP profiler to initialize profiling utilities and record the profiling start time. + /// + /// Timepoint denoting the start of profiling. + /// Status::OK() if profiling was started successfully, or an error Status + /// describing why profiling could not start (e.g., CUPTI unavailable, tracing blocked by policy). + /// Callers should not treat a failed start as fatal — the session can still execute without + /// profiling, but the status should be surfaced for diagnostic purposes. + virtual Status StartProfiling(TimePoint profiling_start_time) = 0; + + /// + /// Called when profiling ends to collect the EP's new profiling events since the last call to StartProfiling. + /// + /// Timepoint denoting the start of profiling. Same value passed to StartProfiling. + /// Modifiable events container to which the EP profiler appends its events. + virtual void EndProfiling(TimePoint start_time, Events& events) = 0; + + /// + /// Optional to override (default implementation does nothing). + /// + /// Called when an ORT event (e.g., session initialization, node kernel execution, etc.) starts. + /// ORT pairs every Start call with a corresponding call to Stop with the same relative ORT event ID. + /// EP profiler implementations may use the calls to Start and Stop to maintain a stack of ORT event IDs + /// that can be correlated with EP events (e.g., GPU kernel events). + /// + /// A relative ORT event ID is computed as a timestamp offset relative to the profiling start time: + /// relative_ort_event_id = + /// std::chrono::duration_cast(event_start_time - profiling_start_time).count(); + /// + /// Because relative ORT event IDs are relative to profiling start, different profiling sessions may reuse the same + /// values. If the EP's profiling utilities (e.g., CUPTI or ROCTracer) require correlation IDs that are practically + /// unique across concurrent profiling sessions (collisions require sub-microsecond event concurrency), then the + /// EP profiler should compute an absolute correlation ID: + /// absolute_ort_correlation_id = + /// relative_ort_event_id + + /// std::chrono::duration_cast(profiling_start_time.time_since_epoch()).count(); + /// + /// Note: For plugin EPs using the binary-stable C API (OrtEpProfilerImpl), ORT performs this conversion + /// automatically. The C API's StartEvent/StopEvent receive the absolute correlation ID directly. + /// + /// + /// Relative ID of the ORT event that is starting (microseconds since profiling start). + /// The same value is passed to a corresponding call to Stop. + /// + virtual void Start(uint64_t /*relative_ort_event_id*/) {} + + /// + /// Optional to override (default implementation does nothing). + /// + /// Called when an ORT event (e.g., session initialization, node kernel execution, etc.) ends. + /// ORT pairs every Start call with a corresponding call to Stop with the same relative ORT event ID. + /// EP profiler implementations may use the calls to Start and Stop to maintain a stack of ORT event IDs + /// that can be correlated with EP events (e.g., GPU kernel events). + /// + /// The ort_event parameter provides the full ORT event record including metadata such as op_name + /// (in event args), event name, category, timestamps, etc. EP profilers can use this to annotate + /// their own events with ORT event context. + /// + /// + /// Relative ID of the ORT event that is ending (microseconds since profiling start). + /// The same value was passed to a corresponding call to Start. + /// + /// + /// The ORT event record containing metadata for this event. + /// + virtual void Stop(uint64_t /*relative_ort_event_id*/, const EventRecord& /*ort_event*/) {} }; // Demangle C++ symbols diff --git a/include/onnxruntime/core/common/spin_pause.h b/include/onnxruntime/core/common/spin_pause.h index 49b71e5567d3e..d3576195bfe12 100644 --- a/include/onnxruntime/core/common/spin_pause.h +++ b/include/onnxruntime/core/common/spin_pause.h @@ -3,26 +3,17 @@ #pragma once -#if defined(_M_AMD64) -#include -#endif - -#if defined(__x86_64__) -#include -#endif - namespace onnxruntime { - namespace concurrency { // Intrinsic to use in spin-loops +void SpinPause(); -inline void SpinPause() { -#if defined(_M_AMD64) || defined(__x86_64__) - _mm_pause(); -#endif -} +// Measure the average duration of a single SpinPause() call in nanoseconds. +// Runs exactly once per process (thread-safe via function-local static init). +// Used to convert a user-specified spin duration in microseconds into an +// iteration count, avoiding clock reads in the hot spin loop. +int CalibrateSpinPauseNs(); } // namespace concurrency - } // namespace onnxruntime diff --git a/include/onnxruntime/core/common/status.h b/include/onnxruntime/core/common/status.h index 8f171daabbb1e..8cf6420f2d0f7 100644 --- a/include/onnxruntime/core/common/status.h +++ b/include/onnxruntime/core/common/status.h @@ -43,7 +43,10 @@ enum StatusCode { MODEL_LOADED = 8, NOT_IMPLEMENTED = 9, INVALID_GRAPH = 10, - EP_FAIL = 11 + EP_FAIL = 11, + MODEL_LOAD_CANCELED = 12, + MODEL_REQUIRES_COMPILATION = 13, + NOT_FOUND = 14, }; constexpr const char* StatusCodeToString(StatusCode status) noexcept { @@ -72,6 +75,12 @@ constexpr const char* StatusCodeToString(StatusCode status) noexcept { return "INVALID_GRAPH"; case StatusCode::EP_FAIL: return "EP_FAIL"; + case StatusCode::MODEL_LOAD_CANCELED: + return "MODEL_LOAD_CANCELED"; + case StatusCode::MODEL_REQUIRES_COMPILATION: + return "MODEL_REQUIRES_COMPILATION"; + case StatusCode::NOT_FOUND: + return "NOT_FOUND"; default: return "GENERAL ERROR"; } @@ -104,6 +113,12 @@ constexpr HRESULT StatusCodeToHRESULT(StatusCode status) noexcept { return HRESULT_FROM_WIN32(ERROR_FILE_CORRUPT); case StatusCode::EP_FAIL: return HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR); + case StatusCode::MODEL_LOAD_CANCELED: + return HRESULT_FROM_WIN32(ERROR_CANCELLED); + case StatusCode::MODEL_REQUIRES_COMPILATION: + return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED); + case StatusCode::NOT_FOUND: + return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); default: return E_FAIL; } diff --git a/include/onnxruntime/core/common/string_helper.h b/include/onnxruntime/core/common/string_helper.h index 1304303132d5a..c0b331cb8e9a8 100644 --- a/include/onnxruntime/core/common/string_helper.h +++ b/include/onnxruntime/core/common/string_helper.h @@ -7,5 +7,9 @@ // forward declaration struct OrtAllocator; namespace onnxruntime { -char* StrDup(const std::string& str, OrtAllocator* allocator); +char* StrDup(std::string_view str, OrtAllocator* allocator); +inline char* StrDup(const std::string& str, OrtAllocator* allocator) { + return StrDup(std::string_view{str}, allocator); +} +wchar_t* StrDup(std::wstring_view str, OrtAllocator* allocator); } // namespace onnxruntime diff --git a/include/onnxruntime/core/framework/allocator.h b/include/onnxruntime/core/framework/allocator.h index 523d2a9d1a8be..3098c35c1c1c5 100644 --- a/include/onnxruntime/core/framework/allocator.h +++ b/include/onnxruntime/core/framework/allocator.h @@ -7,6 +7,7 @@ #include "core/common/common.h" #include "core/framework/allocator_stats.h" +#include "core/session/abi_key_value_pairs.h" // some enums are defined in session/onnxruntime_c_api.h but used in ortdevice.h/ortmemory.h #include "core/session/onnxruntime_c_api.h" #include "core/framework/ortdevice.h" @@ -37,10 +38,41 @@ struct OrtArenaCfg { int max_dead_bytes_per_chunk; // use -1 to allow ORT to choose the default int initial_growth_chunk_size_bytes; // use -1 to allow ORT to choose the default int64_t max_power_of_two_extend_bytes; // use -1 to allow ORT to choose the default + // Use CudaMemPool based arena if available (starting with cuda 11.2) + int use_cuda_mempool = -1; + // Amount of reserved memory in bytes to hold onto before trying + // to release memory back to the OS. + uint64_t cuda_mempool_release_threshold = 0; + // Bytes to keep on shrink for CudaMemPool, 0 is to attempt to release all, allocated space not affected. + size_t cuda_mempool_bytes_to_keep_on_shrink = 0; + + bool IsValid() { + return arena_extend_strategy >= -1 && arena_extend_strategy <= 1 && + initial_chunk_size_bytes >= -1 && + max_dead_bytes_per_chunk >= -1 && + initial_growth_chunk_size_bytes >= -1 && + max_power_of_two_extend_bytes >= -1; + } + + // config key names that we parse in FromKeyValuePairs + struct ConfigKeyNames { + static constexpr const char* ArenaExtendStrategy = "arena.extend_strategy"; + static constexpr const char* InitialChunkSizeBytes = "arena.initial_chunk_size_bytes"; + static constexpr const char* MaxDeadBytesPerChunk = "arena.max_dead_bytes_per_chunk"; + static constexpr const char* InitialGrowthChunkSizeBytes = "arena.initial_growth_chunk_size_bytes"; + static constexpr const char* MaxPowerOfTwoExtendBytes = "arena.max_power_of_two_extend_bytes"; + static constexpr const char* MaxMem = "arena.max_mem"; + static constexpr const char* UseCudaMemPool = "arena.use_cuda_mempool"; + static constexpr const char* CudaMempoolReleaseThreshold = "arena.cuda_mempool_release_threshold"; + static constexpr const char* CudaMempoolBytesToKeepOnShrink = "arena.cuda_mempool_bytes_to_keep_on_shrink"; + }; + + static onnxruntime::common::Status FromKeyValuePairs(const OrtKeyValuePairs& kvps, OrtArenaCfg& cfg); }; namespace onnxruntime { constexpr const char* CPU = "Cpu"; +constexpr const char* CPU_ALIGNED_4K = "CpuAligned4K"; constexpr const char* CUDA = "Cuda"; constexpr const char* CUDA_PINNED = "CudaPinned"; constexpr const char* CANN = "Cann"; @@ -53,18 +85,22 @@ constexpr const char* OpenVINO_GPU = "OpenVINO_GPU"; constexpr const char* OpenVINO_RT = "OpenVINO_RT"; constexpr const char* OpenVINO_RT_NPU = "OpenVINO_RT_NPU"; constexpr const char* QNN_HTP_SHARED = "QnnHtpShared"; -constexpr const char* WEBGPU_BUFFER = "WebGPU_Buffer"; -constexpr const char* WEBNN_TENSOR = "WebNN_Tensor"; +constexpr const char* WEBGPU_BUFFER = "WebGPU_Buf"; // limited to 10 chars to ensure std::string SSO for web +constexpr const char* WEBNN_TENSOR = "WebNN_Ten"; // limited to 10 chars to ensure std::string SSO for web constexpr size_t kAllocAlignment = 256; +constexpr const size_t kAlloc4KAlignment = 4096; class IAllocator; class Stream; namespace synchronize { class Notification; } -using WaitNotificationFn = std::function; -void* AllocateBufferWithOptions(IAllocator& allocator, size_t size, bool use_reserve, Stream* stream, WaitNotificationFn wait_fn); + +using WaitNotificationFn = std::function; +void* AllocateBufferWithOptions(IAllocator& allocator, size_t size, bool use_reserve, Stream* stream, + // wait fn is for backwards compat with provider bridge + WaitNotificationFn ignored = nullptr); template using IAllocatorUniquePtr = std::unique_ptr>; @@ -82,6 +118,43 @@ class IAllocator { */ virtual void* Alloc(size_t size) = 0; + /** Return true if the allocator implements Stream handling in AllocOnStream. + */ + virtual bool IsStreamAware() const { return false; } + + /** Allocate memory, handling usage across different Streams + * + * A device Stream may be available when executing a model on non-CPU devices. In this case operations are queued + * asynchronously and the allocation/free call is made when the operation is queued rather than executed. + * Due to this it is not safe to use the memory on another stream or with no stream unless synchronization has + * occurred. + * + * ORT currently handles the synchronization when executing the model using streams. + * + * When two streams are synchronized the event used is identified by the producer stream's latest sync id. + * This pair is copied into the sync information of the consumer stream. + * Each new event creates a new sync id. + * + * It is safe to re-use an allocated piece of memory if: + * - the stream that currently owns the memory and the stream that wants to use the memory have been synchronized, + * - and the sync id from when the memory was assigned to the stream that currently owns it is less than the + * sync id from the last synchronization between the two streams. + * - e.g. stream0 is assigned the memory when its sync id is 1. + * stream0 (producer) and stream1 (consumer) are synchronized. + * stream0 sync id will be incremented to 2 when creating the event used in the synchronization. + * stream1 will copy this information into its sync info and now contains an entry for stream0 + * with a sync id of 2. + * stream0 frees the memory + * the memory is marked as not in use, but still assigned to stream0 + * stream1 is now able to use the memory as it is not in use, and the sync id from the allocation (1) + * is less than the sync id (2) that is has for stream0. + * or + * - the inference session that owned the Stream has completed inferencing + * - Stream::CleanUpOnRunEnd is called when this occurs + * - any memory assigned to the Stream is now able to be used by other streams when it is not longer in use. + */ + virtual void* AllocOnStream(size_t size, Stream* /*stream*/) { return Alloc(size); } + /** * Free memory at p. * If p is nullptr, do nothing. @@ -99,7 +172,14 @@ class IAllocator { const OrtMemoryInfo& Info() const { return memory_info_; }; // Each implementation of IAllocator can override and provide their own implementation - virtual void GetStats(AllocatorStats* /*stats*/) { return; } + virtual void GetStats(AllocatorStats* stats) { + *stats = {}; + } + + // Returns a pointer to this allocator as an IArena if it is one, nullptr otherwise. + // Used by SafeArenaCast to avoid dependency on RTTI. + virtual class IArena* AsArena() { return nullptr; } + virtual const class IArena* AsArena() const { return nullptr; } static bool CalcMemSizeForArray(size_t nmemb, size_t size, size_t* out) noexcept { return CalcMemSizeForArrayWithAlignment(nmemb, size, 0, out); @@ -167,7 +247,7 @@ class IAllocator { template static IAllocatorUniquePtr MakeUniquePtr(std::shared_ptr allocator, size_t count_or_bytes, bool use_reserve = false, - Stream* stream = nullptr, WaitNotificationFn wait_fn = nullptr) { + Stream* stream = nullptr) { ValidateAllocator(allocator); // for now limit to fundamental types. we could support others, but to do so either we or the caller @@ -185,7 +265,7 @@ class IAllocator { } // allocate - T* p = static_cast(AllocateBufferWithOptions(*allocator, alloc_size, use_reserve, stream, std::move(wait_fn))); + T* p = static_cast(AllocateBufferWithOptions(*allocator, alloc_size, use_reserve, stream, nullptr)); ValidateAllocation(p, alloc_size); return IAllocatorUniquePtr{p, @@ -201,7 +281,8 @@ class IAllocator { @returns std::unique_ptr with allocated memory and deleter. Throws if it cannot allocate memory. */ template - static IAllocatorUniquePtr MakeUniquePtrFromOrtAllocator(OrtAllocator* ort_allocator, size_t count_or_bytes) { + static IAllocatorUniquePtr MakeUniquePtrFromOrtAllocator(OrtAllocator* ort_allocator, size_t count_or_bytes, + bool use_reserve = false) { ValidateAllocator(ort_allocator); size_t alloc_size = count_or_bytes; @@ -213,7 +294,12 @@ class IAllocator { alloc_size = ValidatedCalcMemSizeForArray(count_or_bytes, size); } - T* p = static_cast(ort_allocator->Alloc(ort_allocator, alloc_size)); + T* p = nullptr; + if (use_reserve) { + p = static_cast(ort_allocator->Reserve(ort_allocator, alloc_size)); + } else { + p = static_cast(ort_allocator->Alloc(ort_allocator, alloc_size)); + } ValidateAllocation(p, alloc_size); return IAllocatorUniquePtr{p, @@ -255,19 +341,37 @@ bool IAllocator::CalcMemSizeForArrayWithAlignment(size_t nmemb, size_t size, siz return CalcMemSizeForArrayWithAlignment(nmemb, size, alignment, out); } +using AllocatorPtr = std::shared_ptr; +using AllocatorMap = std::map; + class CPUAllocator : public IAllocator { public: explicit CPUAllocator(const OrtMemoryInfo& memory_info) : IAllocator(memory_info) {} + // Creates a function local static and returns a shared pointer to it. + // Re-use in all places where we need a standalone CPUAllocator instance + static AllocatorPtr DefaultInstance(); + CPUAllocator() : IAllocator(OrtMemoryInfo(CPU, OrtAllocatorType::OrtDeviceAllocator)) {} void* Alloc(size_t size) override; void Free(void* p) override; }; -using AllocatorPtr = std::shared_ptr; -using AllocatorMap = std::map; - void* AllocatorDefaultAlloc(size_t size); void AllocatorDefaultFree(void* p); +void* AllocatorDefaultAllocAligned(size_t size, size_t alignment); +void AllocatorDefaultFreeAligned(void* p, size_t alignment); + +class IArena : public IAllocator { + public: + using IAllocator::IAllocator; + virtual Status Shrink() = 0; + // Only implemented when IsStreamAware() returns true + virtual void ReleaseStreamBuffers(Stream* /*stream*/) {} + IArena* AsArena() override { return this; } + const IArena* AsArena() const override { return this; } + static IArena* SafeArenaCast(IAllocator* allocator); +}; + } // namespace onnxruntime diff --git a/include/onnxruntime/core/framework/data_types.h b/include/onnxruntime/core/framework/data_types.h index d8822b3e452d5..43ee8d36ed95c 100644 --- a/include/onnxruntime/core/framework/data_types.h +++ b/include/onnxruntime/core/framework/data_types.h @@ -12,10 +12,12 @@ #include #include "core/common/common.h" #include "core/common/exceptions.h" -#include "core/framework/endian.h" -#include "core/framework/float8.h" -#include "core/framework/float16.h" +#include "core/common/endian.h" +#include "core/common/float8.h" +#include "core/common/float16.h" #include "core/framework/int4.h" +#include "core/framework/int2.h" +#include "core/framework/float4.h" #include "core/graph/onnx_protobuf.h" #include "core/framework/to_tensor_proto_element_type.h" @@ -209,6 +211,8 @@ class DataTypeImpl { static const std::vector& AllTensorTypesIRv4(); static const std::vector& AllTensorTypesIRv9(); static const std::vector& AllTensorTypesIRv10(); + static const std::vector& AllTensorTypesIRv11(); + static const std::vector& AllTensorTypesIRv13(); static const std::vector& AllFixedSizeTensorTypes(); // up to IR4 (no float 8), deprecated static const std::vector& AllFixedSizeTensorTypesIRv4(); @@ -283,10 +287,14 @@ template struct IsTensorContainedType : public IsAnyOf { }; @@ -298,10 +306,15 @@ struct IsTensorContainedType : public IsAnyOf struct IsSparseTensorContainedType : public IsAnyOf { }; @@ -921,7 +934,7 @@ class OpaqueType : public NonTensorType { * * \details This class contains an integer constant that can be * used for input data type dispatching. This class also stores the number of subelements per size units. - * Example: For int4, the size unit is 1 byte and the number of subelements is 2. + * Example: For float4/int4, the size unit is 1 byte and the number of subelements is 2. * */ class PrimitiveDataTypeBase : public DataTypeImpl { @@ -1101,6 +1114,7 @@ inline const PrimitiveDataTypeBase* DataTypeImpl::AsPrimitiveDataType() const { // Registers a subbyte primitive. // Examples: // - Int4x2 stores 2 packed 4-bit elements in 1 byte: ORT_*_SUBBYTE_TYPE(Int4x2, 2) +// - Float4E2M1x2 stores 2 packed 4-bit elements in 1 byte: ORT_*_SUBBYTE_TYPE(Float4E2M1x2, 2) // - [not supported] Int3x8 could store 8 packed 3-bit elements in 3 bytes: ORT_*_SUBBYTE_TYPE(Int3x8, 8) #define ORT_REGISTER_PRIM_SUBBYTE_TYPE(TYPE, NUM_SUB_ELEMS) \ template <> \ diff --git a/include/onnxruntime/core/framework/data_types_internal.h b/include/onnxruntime/core/framework/data_types_internal.h index 05f4c10995ef2..8ccfb1d20994c 100644 --- a/include/onnxruntime/core/framework/data_types_internal.h +++ b/include/onnxruntime/core/framework/data_types_internal.h @@ -35,7 +35,7 @@ namespace utils { // Invoking DataTypeImpl::GetType() for switching on input types is discouraged and should be avoided. // Every primitive type carries with it an integer constant that can be used for quick switching on types. -#if !defined(DISABLE_FLOAT8_TYPES) +#if !defined(DISABLE_FLOAT8_TYPES) && !defined(DISABLE_FLOAT4_TYPES) #define DispatchOnTensorType(tensor_type, function, ...) \ switch (tensor_type->AsPrimitiveDataType()->GetDataType()) { \ @@ -93,12 +93,307 @@ namespace utils { case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E5M2FNUZ: \ function(__VA_ARGS__); \ break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E8M0: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT4E2M1: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT4: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT4: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT2: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT2: \ + function(__VA_ARGS__); \ + break; \ + default: \ + ORT_ENFORCE(false, "Unknown tensor type of ", tensor_type); \ + } + +#define DispatchOnTensorTypeWithReturn(tensor_type, retval, function, ...) \ + switch (tensor_type->AsPrimitiveDataType()->GetDataType()) { \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_BOOL: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_DOUBLE: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_STRING: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT8: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT8: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT16: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT16: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT32: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT32: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT64: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT64: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT16: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_BFLOAT16: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E4M3FN: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E4M3FNUZ: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E5M2: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E5M2FNUZ: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E8M0: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT4E2M1: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT4: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT4: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT2: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT2: \ + retval = function(__VA_ARGS__); \ + break; \ + default: \ + ORT_ENFORCE(false, "Unknown tensor type of ", tensor_type); \ + } + +#elif !defined(DISABLE_FLOAT4_TYPES) + +#define DispatchOnTensorType(tensor_type, function, ...) \ + switch (tensor_type->AsPrimitiveDataType()->GetDataType()) { \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_BOOL: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_DOUBLE: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_STRING: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT8: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT8: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT16: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT16: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT32: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT32: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT64: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT64: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT16: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_BFLOAT16: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT4E2M1: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT4: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT4: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT2: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT2: \ + function(__VA_ARGS__); \ + break; \ + default: \ + ORT_ENFORCE(false, "Unknown tensor type of ", tensor_type); \ + } + +#define DispatchOnTensorTypeWithReturn(tensor_type, retval, function, ...) \ + switch (tensor_type->AsPrimitiveDataType()->GetDataType()) { \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_BOOL: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_DOUBLE: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_STRING: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT8: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT8: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT16: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT16: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT32: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT32: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT64: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT64: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT16: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_BFLOAT16: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT4E2M1: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT4: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT4: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT2: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT2: \ + retval = function(__VA_ARGS__); \ + break; \ + default: \ + ORT_ENFORCE(false, "Unknown tensor type of ", tensor_type); \ + } + +#elif !defined(DISABLE_FLOAT8_TYPES) + +#define DispatchOnTensorType(tensor_type, function, ...) \ + switch (tensor_type->AsPrimitiveDataType()->GetDataType()) { \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_BOOL: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_DOUBLE: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_STRING: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT8: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT8: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT16: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT16: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT32: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT32: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT64: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT64: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT16: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_BFLOAT16: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E4M3FN: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E4M3FNUZ: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E5M2: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E5M2FNUZ: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E8M0: \ + function(__VA_ARGS__); \ + break; \ case ONNX_NAMESPACE::TensorProto_DataType_INT4: \ function(__VA_ARGS__); \ break; \ case ONNX_NAMESPACE::TensorProto_DataType_UINT4: \ function(__VA_ARGS__); \ break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT2: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT2: \ + function(__VA_ARGS__); \ + break; \ default: \ ORT_ENFORCE(false, "Unknown tensor type of ", tensor_type); \ } @@ -159,12 +454,21 @@ namespace utils { case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E5M2FNUZ: \ retval = function(__VA_ARGS__); \ break; \ + case ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E8M0: \ + retval = function(__VA_ARGS__); \ + break; \ case ONNX_NAMESPACE::TensorProto_DataType_INT4: \ retval = function(__VA_ARGS__); \ break; \ case ONNX_NAMESPACE::TensorProto_DataType_UINT4: \ retval = function(__VA_ARGS__); \ break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT2: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT2: \ + retval = function(__VA_ARGS__); \ + break; \ default: \ ORT_ENFORCE(false, "Unknown tensor type of ", tensor_type); \ } @@ -221,6 +525,12 @@ namespace utils { case ONNX_NAMESPACE::TensorProto_DataType_UINT4: \ function(__VA_ARGS__); \ break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT2: \ + function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT2: \ + function(__VA_ARGS__); \ + break; \ default: \ ORT_ENFORCE(false, "Unknown tensor type of ", tensor_type); \ } @@ -275,6 +585,12 @@ namespace utils { case ONNX_NAMESPACE::TensorProto_DataType_UINT4: \ retval = function(__VA_ARGS__); \ break; \ + case ONNX_NAMESPACE::TensorProto_DataType_INT2: \ + retval = function(__VA_ARGS__); \ + break; \ + case ONNX_NAMESPACE::TensorProto_DataType_UINT2: \ + retval = function(__VA_ARGS__); \ + break; \ default: \ ORT_ENFORCE(false, "Unknown tensor type of ", tensor_type); \ } @@ -319,6 +635,10 @@ class CallableDispatchableHelper { public: explicit CallableDispatchableHelper(int32_t dt_type) noexcept : dt_type_(dt_type), called_(0) {} +#if defined(_MSC_VER) +#pragma warning(push) +#pragma warning(disable : 4702) +#endif // Must return integer to be in a expandable context template int Invoke(Fn&& fn, Args&&... args) { @@ -328,6 +648,9 @@ class CallableDispatchableHelper { } return 0; } +#if defined(_MSC_VER) +#pragma warning(pop) +#endif void CheckCalledOnce() const { ORT_ENFORCE(called_ == 1, "Unsupported data type: ", dt_type_); @@ -338,7 +661,7 @@ class CallableDispatchableHelper { // Other policies may set the second result argument accordingly. template struct UnsupportedTypeDefaultPolicy { - void operator()(int32_t dt_type, Ret& /*result*/) const { + [[noreturn]] void operator()(int32_t dt_type, Ret& /*result*/) const { ORT_THROW("Unsupported data type: ", dt_type); } }; diff --git a/include/onnxruntime/core/framework/execution_provider.h b/include/onnxruntime/core/framework/execution_provider.h index 0d9e6db1a7748..7395d823fd2be 100644 --- a/include/onnxruntime/core/framework/execution_provider.h +++ b/include/onnxruntime/core/framework/execution_provider.h @@ -5,6 +5,8 @@ #ifndef SHARED_PROVIDER #include +#include +#include #include #include @@ -20,6 +22,7 @@ struct ComputeCapability; class KernelRegistry; struct KernelCreateInfo; class Node; +class GraphOptimizerRegistry; } // namespace onnxruntime #else #include @@ -33,11 +36,15 @@ class Node; #include "core/framework/framework_provider_common.h" #include "core/framework/stream_handles.h" #include "core/framework/tuning_context.h" +#include "core/session/onnxruntime_c_api.h" +struct OrtEpDevice; struct OrtRunOptions; namespace onnxruntime { +class IResourceAccountant; + /** Logical device representation. */ @@ -59,7 +66,9 @@ using RunOptions = ::OrtRunOptions; enum class DataLayout { NCHW, NHWC, - NCHWC, + + // NCHW is the default ONNX standard data layout. So default to it. + Default = NCHW, }; class IExecutionProvider { @@ -71,11 +80,28 @@ class IExecutionProvider { : default_device_(device), type_{type} { } + IExecutionProvider(const std::string& type, OrtDevice device, const logging::Logger& logger) + : default_device_(device), type_{type}, logger_{&logger} { + } + + IExecutionProvider(const std::string& type, OrtDevice device, + std::vector ep_devices, const logging::Logger& logger) + : default_device_(device), ep_devices_{ep_devices}, type_{type}, logger_{&logger} { + } + /* default device for this ExecutionProvider */ const OrtDevice default_device_; + /* + The OrtEpDevice list this execution provider supports. + + It's mainly for plugin EP which implements this interface or provider-bridge EP that + implements OrtEpFactory as OrtEpDevice(s) are available for such scenarios. + */ + const std::vector ep_devices_; + public: virtual ~IExecutionProvider() = default; @@ -127,10 +153,26 @@ class IExecutionProvider { and decide whether a node will be assigned to <*this> execution provider. For kernels registered in a kernel registry, `kernel_lookup` must be used to find a matching kernel for this EP. + + The graph_optimizer_registry is designed for enabling L2+ graph optimizations tailored for EPs. + These optimizations are applied after the graph partitioner assigns ComputeCapability to the EP + and before EP's "Compile" or fusion. + + Steps to use graph_optimizer_registry and create the optimization ComputeCapability: + 1. Lookup Optimizer: The EP calls provider bridge API to lookup pre-defined optimizer by name and get selection function. + - Example: g_host->GetOptimizerByName(optimizer_name, graph_optimizer_registry, selection_func) + 2. Run Selection Function: The EP executes the selection function to obtain the selection ComputeCapability. + - ComputeCapability.optimize_func would be set by the optimizer to the function that does the optimization. + 3. Create Optimization ComputeCapability: The EP uses the selection ComputeCapability to create the optimization ComputeCapability. + 4. Return ComputeCapability: The EP returns the final ComputeCapability, with nodes_to_optimize set to the optimization ComputeCapability. + + Note: For more detailed implementations of using graph_optimizer_registry, please refer to TensorRT EP. */ virtual std::vector> GetCapability(const onnxruntime::GraphViewer& graph_viewer, - const IKernelLookup& kernel_lookup) const; + const IKernelLookup& kernel_lookup, + const GraphOptimizerRegistry& graph_optimizer_registry, + IResourceAccountant* resource_accountant = nullptr) const; /** Get kernel registry per execution provider type. @@ -151,7 +193,17 @@ class IExecutionProvider { /** Get the device id of current execution provider */ - virtual int GetDeviceId() const { return 0; }; + virtual int GetDeviceId() const { return default_device_.Id(); } + + /** + * Get the OrtDevice the execution provider was registered with. + */ + const OrtDevice& GetDevice() const { return default_device_; } + + /** + * Get the OrtEpDevice list the execution provider was registered with. + */ + const std::vector& GetEpDevices() const { return ep_devices_; } /** Get execution provider's configuration options. @@ -223,8 +275,8 @@ class IExecutionProvider { } /** - Indicate whether the graph capturing mode (e.g., cuda graph) is enabled for - the provider. + Indicate whether graph capture/replay (for example, CUDA graph capture) is + enabled for the provider. */ virtual bool IsGraphCaptureEnabled() const { return false; } @@ -240,6 +292,15 @@ class IExecutionProvider { return Status::OK(); } + /** + Get the node assignment validation policy for graph capture. + When graph capture is enabled, ORT validates that nodes are assigned to EPs + in a way compatible with graph capture. This tells ORT which policy to apply. + */ + virtual OrtGraphCaptureNodeAssignmentPolicy GetGraphCaptureNodeAssignmentPolicy() const { + return OrtGraphCaptureNodeAssignmentPolicy_ALL_NODES_ON_EP; + } + /** Called when session creation is complete This provides an opportunity for execution providers to optionally synchronize and @@ -289,6 +350,29 @@ class IExecutionProvider { virtual common::Status Compile(const std::vector& fused_nodes_and_graphs, std::vector& node_compute_funcs); + /** + * Get the compatibility info for a compiled model. + * + * The execution provider determines this value, which denotes the compatibility of the compiled model with the EP. + * This is stored in the model metadata under a key associated with the EP type. + */ + virtual std::string GetCompiledModelCompatibilityInfo(const onnxruntime::GraphViewer& graph_viewer) const { + // graph_viewer and model_metadata are not used in the default implementation. + ORT_UNUSED_PARAMETER(graph_viewer); + // Default implementation returns empty string + return std::string(); + } + + /** + * Validate the compatibility of a compiled model with this execution provider. + */ + virtual common::Status ValidateCompiledModelCompatibilityInfo(const std::string& /*compatibility_info*/, + OrtCompiledModelCompatibility& model_compatibility) const { + // Default implementation indicates this EP does not support model compatibility validation + model_compatibility = OrtCompiledModelCompatibility_EP_NOT_APPLICABLE; + return Status::OK(); + } + #endif void SetLogger(const logging::Logger* logger) { @@ -304,9 +388,21 @@ class IExecutionProvider { } virtual DataLayout GetPreferredLayout() const { - // NCHW is the default ONNX standard data layout. So default to it. // EPs which prefer a different layout should override to return their preferred layout. - return DataLayout::NCHW; + return DataLayout::Default; + } + + /** + Given an op with domain `domain` and type `op_type`, determine whether an associated node's data layout should be + converted to `target_data_layout`. + If the EP prefers a non-default data layout (see `GetPreferredLayout()`), this function will be called during + layout transformation with `target_data_layout` set to the EP's preferred data layout. + A return value of `std::nullopt` indicates that this decision is left to ORT. + */ + virtual std::optional ShouldConvertDataLayoutForOp(std::string_view /*domain*/, + std::string_view /*op_type*/, + DataLayout /*target_data_layout*/) const { + return std::nullopt; } virtual void RegisterStreamHandlers(IStreamCommandHandleRegistry& /*stream_handle_registry*/, AllocatorMap&) const {} @@ -347,6 +443,15 @@ class IExecutionProvider { return InlinedVector(); } + /** + * Returns the underlying OrtEp instance if this IExecutionProvider wraps a plugin EP. + * Otherwise, returns a nullptr (default implementation). + * This is used to retrieve the OrtEp instance from a OrtKernelInfo instance in a plugin EP's kernel implementation. + */ + virtual const OrtEp* GetOrtEp() const { + return nullptr; + } + private: const std::string type_; diff --git a/include/onnxruntime/core/framework/float4.h b/include/onnxruntime/core/framework/float4.h new file mode 100644 index 0000000000000..3662556f53398 --- /dev/null +++ b/include/onnxruntime/core/framework/float4.h @@ -0,0 +1,297 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// IMPORTANT NOTE: Users of this file MUST include "cuda.h" before including this header +// if they would like to leverage the CUDA implementation for the conversion routines +// in their HOST code (code compiled by MSVC/GCC). +// This is because there is a check on CUDA_VERSION which is a macro defined in cuda.h. +// We can't include cuda.h in this header unconditionally because this header is also +// included in core framework files which are CUDA-agnostic. +// Not including "cuda.h" in GCC/MSVC will fall-back to the CPU conversion routines +// implemented in this file. +// For code compiled by NVCC which includes this header, this file will automatically +// include cuda.h (based on the CUDA_CC macro). + +#pragma once + +#if !defined(DISABLE_FLOAT4_TYPES) + +#if defined(__CUDACC__) +// Needed for CUDA_VERSION check below +#include +#endif + +#if defined(CUDA_VERSION) && CUDA_VERSION >= 12080 + +#if defined(_MSC_VER) +#pragma warning(push) +// 'fp4_interpretation' : unreferenced parameter +#pragma warning(disable : 4100) +#endif + +#include + +#if defined(_MSC_VER) +#pragma warning(pop) +#endif + +#endif + +#include +#include +#include +#include + +#include "core/common/common.h" + +namespace onnxruntime { + +#if defined(__CUDACC__) +#define ORT_HOST_DEVICE __host__ __device__ +#else +#define ORT_HOST_DEVICE +#endif + +struct Float4E2M1x2 { + uint8_t val_{0}; + using UnpackedType = float; + +#if defined(CUDA_VERSION) && CUDA_VERSION >= 12080 + using PackedCudaType = __nv_fp4x2_e2m1; + using PackedCudaStorageType = __nv_fp4x2_storage_t; +#endif + + private: + ORT_HOST_DEVICE UnpackedType Fp4ToFloatConversionCpuHelper(uint8_t fp4x2, size_t shift) const { + assert(shift == 0 || shift == 4); + + constexpr uint8_t sign_bitmask = 0x08; + constexpr uint8_t exponent_bitmask = 0x06; + constexpr uint8_t mantissa_bitmask = 0x01; + + uint8_t bits_shifted = (fp4x2 >> shift); + + float sign = 1.f; + if (bits_shifted & sign_bitmask) { + sign = -1.f; + } + + int exponent = static_cast((bits_shifted & exponent_bitmask) >> 1); + float mantissa = static_cast(bits_shifted & mantissa_bitmask); + + return (exponent == 0) ? (sign * (mantissa / 2.f)) : (sign * (1.f + mantissa / 2.f) * static_cast(1 << (exponent - 1))); + } + + ORT_HOST_DEVICE uint8_t FloatToFp4ConversionCpuHelper(float f, size_t shift) const { + assert(shift == 0 || shift == 4); + + constexpr uint32_t sign_bitmask = 0x80000000; + constexpr uint32_t exponent_bitmask = 0x7F800000; + constexpr uint32_t mantissa_bitmask = 0x007FFFFF; + constexpr uint32_t zero = 0x00000000; + + uint8_t res = 0; + + uint32_t float_bits = 0; + std::memcpy(&float_bits, &f, sizeof(f)); + + // NaN always maps to +6 (irrespective of sign) + // https://github.com/onnx/onnx/blob/main/docs/docsgen/source/technical/float4.md + if (((float_bits & exponent_bitmask) == exponent_bitmask) && (float_bits & mantissa_bitmask)) { + return (0x07 << shift); + } + + if (float_bits & sign_bitmask) { + res = 0x08; + } + + // Infinity is sign preserving - magnitude is 6 + if (((float_bits & exponent_bitmask) == exponent_bitmask) && ((float_bits & mantissa_bitmask) == zero)) { + return ((res | 0x07) << shift); + } + + float f_abs = std::abs(f); + if (f_abs > 0.25 && f_abs < 0.75) { + res |= 0x01; + } else if (f_abs >= 0.75 && f_abs <= 1.25) { + res |= 0x02; + } else if (f_abs > 1.25 && f_abs < 1.75) { + res |= 0x03; + } else if (f_abs >= 1.75 && f_abs <= 2.5) { + res |= 0x04; + } else if (f_abs > 2.5 && f_abs < 3.5) { + res |= 0x05; + } else if (f_abs >= 3.5 && f_abs <= 5.0) { + res |= 0x06; + } else if (f_abs > 5.0) { + res |= 0x07; + } + + return res << shift; + } + + public: + Float4E2M1x2() = default; + + struct FromBitsT {}; + static constexpr ORT_HOST_DEVICE FromBitsT FromBits() { return FromBitsT(); } + constexpr ORT_HOST_DEVICE Float4E2M1x2(unsigned char bits, FromBitsT) : val_(bits) {} + + inline explicit ORT_HOST_DEVICE Float4E2M1x2(UnpackedType f1, UnpackedType f2) { +#if defined(CUDA_VERSION) && CUDA_VERSION >= 12080 + float2 temp; + temp.x = f1; + temp.y = f2; + + // Converts input vector of two single precision numbers packed in float2 x + // into a vector of two values of fp4 type of the requested kind using specified + // rounding mode and saturating the out-of-range values. + val_ = __nv_cvt_float2_to_fp4x2(temp, __NV_E2M1, cudaRoundNearest); +#else + val_ = (FloatToFp4ConversionCpuHelper(f1, 0) | FloatToFp4ConversionCpuHelper(f2, 4)); +#endif + } + +#if defined(CUDA_VERSION) && CUDA_VERSION >= 12080 + inline explicit ORT_HOST_DEVICE Float4E2M1x2(float2 f2) { + val_ = __nv_cvt_float2_to_fp4x2(f2, __NV_E2M1, cudaRoundNearest); + } + + inline explicit ORT_HOST_DEVICE Float4E2M1x2(const __nv_fp4x2_e2m1& value) { + val_ = *reinterpret_cast(&value); + } + + inline explicit ORT_HOST_DEVICE operator __nv_fp4x2_e2m1() const { + return *reinterpret_cast(&val_); + } + + inline ORT_HOST_DEVICE float2 ToCudaFloat2() const { + return __half22float2(__nv_cvt_fp4x2_to_halfraw2(static_cast(val_), __NV_E2M1)); + } +#endif + + inline ORT_HOST_DEVICE std::pair ToFloat2() const { +#if defined(CUDA_VERSION) && CUDA_VERSION >= 12080 + float2 temp = ToCudaFloat2(); + return std::make_pair(temp.x, temp.y); +#else + return std::make_pair(Fp4ToFloatConversionCpuHelper(val_, 0), Fp4ToFloatConversionCpuHelper(val_, 4)); +#endif + } + + inline ORT_HOST_DEVICE uint8_t ToBits() const { + return val_; + } + + static size_t CalcNumFloat4Pairs(size_t num_float4_elems) { + return (num_float4_elems + 1) / 2; + } + + static void UnpackFloat4E2M1ToFloat(const Float4E2M1x2* fp4x2_arr, + UnpackedType* flt_arr, size_t size) { + auto src = fp4x2_arr; + auto dst = flt_arr; + + size_t dst_i = 0; + + for (; dst_i < size - 1; dst_i += 2) { + auto src_i = dst_i >> 1; + auto flt_pair = src[src_i].ToFloat2(); + dst[dst_i] = flt_pair.first; + dst[dst_i + 1] = flt_pair.second; + } + + if (dst_i < size) { + auto src_i = dst_i >> 1; + dst[dst_i] = fp4x2_arr[src_i].ToFloat2().first; + } + } + + static void PackFloatToFloat4E2M1(const UnpackedType* flt_arr, + Float4E2M1x2* fp4x2_arr, size_t size) { + auto src = flt_arr; + auto dst = fp4x2_arr; + + size_t src_i = 0; + + for (; src_i < size - 1; src_i += 2) { + new (dst) Float4E2M1x2(src[src_i], src[src_i + 1]); + ++dst; + } + + if (src_i < size) { + new (dst) Float4E2M1x2(src[src_i], 0); + } + } + + static inline std::pair GetTensorElemIndices(size_t index) { + return {index >> 1, index & 0x1}; + } + + inline UnpackedType GetElem(size_t index) const { + assert(index <= 1); + auto pair = ToFloat2(); + if (index == 0) { + return static_cast(pair.first); + } + + return static_cast(pair.second); + } +}; + +inline ORT_HOST_DEVICE bool operator==(const Float4E2M1x2& left, const Float4E2M1x2& right) { return left.val_ == right.val_; } +inline ORT_HOST_DEVICE bool operator!=(const Float4E2M1x2& left, const Float4E2M1x2& right) { return left.val_ != right.val_; } + +static_assert(sizeof(Float4E2M1x2) == sizeof(uint8_t)); +} // namespace onnxruntime + +namespace std { +// TODO (hasesh): Does numeric_limits make sense for packed types ? +// For now, produce limits of each element in a packed format, refine +// this based on usage later +template <> +class numeric_limits { + public: + static constexpr onnxruntime::Float4E2M1x2 lowest() { + return onnxruntime::Float4E2M1x2(0xFF, onnxruntime::Float4E2M1x2::FromBits()); // -6.0 + } + + static constexpr onnxruntime::Float4E2M1x2 max() { + return onnxruntime::Float4E2M1x2(0x77, onnxruntime::Float4E2M1x2::FromBits()); // +6.0 + } + + static constexpr onnxruntime::Float4E2M1x2 min() { + return onnxruntime::Float4E2M1x2(0x22, onnxruntime::Float4E2M1x2::FromBits()); // +1.0 + } + + static constexpr onnxruntime::Float4E2M1x2 denorm_min() { + return onnxruntime::Float4E2M1x2(0x11, onnxruntime::Float4E2M1x2::FromBits()); // +0.5 + } + + static constexpr bool is_specialized = true; + static constexpr bool is_signed = true; + static constexpr bool is_integer = false; + static constexpr bool is_exact = false; + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr auto has_denorm = true; + static constexpr auto has_denorm_loss = true; + static constexpr auto round_style = round_to_nearest; + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = false; + static constexpr int digits = 2; // (1 mantissa bit + 1 implicit bit) + static constexpr int digits10 = 0; // (digits -1) * std::log10(2) rounded down + static constexpr int max_digits10 = 1; // Mantissa bits + static constexpr int radix = 2; + static constexpr int min_exponent = 1; // 2 ^ (1-1) = 1 is the valid normalized value min ceiling we can reach + static constexpr int min_exponent10 = 0; // 10 ^ 0 is the valid normalized value min ceiling we can reach + static constexpr int max_exponent = 3; // 2 ^ (3-1) = 4 is valid normalized value max ceiling we can reach + static constexpr int max_exponent10 = 0; // 10 ^ 0 is the valid normalized value max ceiling we can reach + static constexpr auto traps = false; + static constexpr auto tinyness_before = false; +}; +} // namespace std + +#endif // DISABLE_FLOAT4_TYPES diff --git a/include/onnxruntime/core/framework/float8.h b/include/onnxruntime/core/framework/float8.h deleted file mode 100644 index 9e94cc297f782..0000000000000 --- a/include/onnxruntime/core/framework/float8.h +++ /dev/null @@ -1,920 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#pragma once - -#if !defined(DISABLE_FLOAT8_TYPES) - -#include "endian.h" -#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 -#include "cuda_fp8.h" -#endif - -#if !defined(__CUDACC__) && !defined(__HIPCC__) -#include "core/common/narrow.h" -#endif - -#include "core/common/common.h" - -namespace onnxruntime { - -#if defined(__CUDACC__) || defined(__HIPCC__) -#define ORT_HOST_DEVICE __host__ __device__ -#else -#define ORT_HOST_DEVICE -#endif - -// Float8E4M3FN -struct Float8E4M3FN { - uint8_t val{0}; -#if defined(__HIP__) - ORT_HOST_DEVICE Float8E4M3FN() = default; -#else - Float8E4M3FN() = default; -#endif - struct FromBitsT {}; - static constexpr ORT_HOST_DEVICE FromBitsT FromBits() { return FromBitsT(); } - constexpr ORT_HOST_DEVICE Float8E4M3FN(unsigned char bits, FromBitsT) : val(bits) {} - - inline explicit ORT_HOST_DEVICE Float8E4M3FN(float v, bool saturate = true) { -#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 - val = __nv_cvt_float_to_fp8(v, saturate ? __NV_SATFINITE : __NV_NOSAT, __NV_E4M3); -#else - uint32_t b; - std::memcpy(&b, &v, sizeof(b)); - - val = static_cast((b & 0x80000000) >> 24); // sign - if ((b & 0x7fffffff) == 0x7f800000) { // infinity - if (saturate) { - val |= 126; - } else { - val |= 0x7f; - } - } else if ((b & 0x7F800000) == 0x7F800000) { // NaN - val |= 0x7f; - } else { - uint8_t e = static_cast((b & 0x7F800000) >> 23); // exponent - uint32_t m = static_cast(b & 0x007FFFFF); // mantissa - if (e != 0) { - if (e < 117) { - } else if (e < 121) { - // denormalized number - auto d = 120 - e; - if (d < 3) { - val |= 1 << (2 - d); - val |= m >> (21 + d); - } else if (m > 0) { - val |= 1; - } - auto mask = 1 << (20 + d); - if ((m & mask) && ((val & 1) || ((m & (mask - 1)) > 0) || ((m & mask) && (m & (mask << 1)) && ((m & (mask - 1)) == 0)))) { - // rounding - val += 1; - } - } else if (e < 136) { - // normalized number - auto ex = e - 120; - if (ex == 0) { - val |= 0x4; - val |= m >> 21; - } else { - val |= ex << 3; - val |= m >> 20; - if ((val & 0x7F) == 0x7F) { - val &= 0xFE; - } - } - if ((m & 0x80000) && ((m & 0x100000) || (m & 0x7FFFF))) { - if ((val & 0x7F) < 0x7E) { - // rounding - val += 1; - } else if (!saturate) { - val |= 0x7F; - } - } - } else if (saturate) { - val |= 126; // 0b01111110 - } else { - val |= 0x7F; - } - } - } -#endif - } - - inline ORT_HOST_DEVICE bool IsNaN() const { - return (val & 0b01111111) == 0b01111111; - } - - inline ORT_HOST_DEVICE float ToFloat() const { -#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 - return __half2float(__nv_cvt_fp8_to_halfraw(val, __NV_E4M3)); -#else - uint32_t res; - if (val == 255) { - res = 0xffc00000; - } else if (val == 127) { - res = 0x7fc00000; - } else { - uint32_t expo = (val & 0x78) >> 3; - uint32_t mant = val & 0x07; - uint32_t sign = val & 0x80; - res = sign << 24; - if (expo == 0) { - if (mant > 0) { - expo = 0x7F - 7; - if ((mant & 0x4) == 0) { - mant &= 0x3; - mant <<= 1; - expo -= 1; - } - if ((mant & 0x4) == 0) { - mant &= 0x3; - mant <<= 1; - expo -= 1; - } - res |= (mant & 0x3) << 21; - res |= expo << 23; - } - } else { - res |= mant << 20; - expo -= 0x7; - expo += 0x7F; - res |= expo << 23; - } - } - float float_res; - std::memcpy(&float_res, &res, sizeof(float)); - return float_res; -#endif - } - - inline ORT_HOST_DEVICE operator float() const { return ToFloat(); } - -#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 - explicit ORT_HOST_DEVICE Float8E4M3FN(const __nv_fp8_e4m3& value) { val = *reinterpret_cast(&value); } - explicit ORT_HOST_DEVICE operator __nv_fp8_e4m3() const { return *reinterpret_cast(&val); } -#endif -}; - -inline ORT_HOST_DEVICE bool operator==(const Float8E4M3FN& left, const Float8E4M3FN& right) { return left.val == right.val; } -inline ORT_HOST_DEVICE bool operator!=(const Float8E4M3FN& left, const Float8E4M3FN& right) { return left.val != right.val; } -inline ORT_HOST_DEVICE bool operator<(const Float8E4M3FN& left, const Float8E4M3FN& right) { return left.val < right.val; } - -// User defined suffixes to make it easier to declare -// initializers with MLFloat8E4M3FN and Float8E4M3FN from unsigned char -#if !defined(__CUDACC__) && !defined(__HIPCC__) - -inline Float8E4M3FN operator""_f8e4m3fn(unsigned long long int v) { - return Float8E4M3FN(narrow(v), Float8E4M3FN::FromBits()); -} - -inline Float8E4M3FN operator""_f8e4m3fnp8(long double v) { - return Float8E4M3FN(static_cast(v), true); -} - -#endif - -inline void Float8E4M3FNToFloat(const Float8E4M3FN* blf, float* flt, size_t size) { - auto src = blf; - auto d = flt; - for (; size != 0; ++src, ++d, --size) { - *d = src->ToFloat(); - } -} - -inline void FloatToFloat8E4M3FN(const float* flt, Float8E4M3FN* blf, size_t size, bool saturate) { - auto src = flt; - auto d = blf; - for (; size != 0; ++src, ++d, --size) { - new (d) Float8E4M3FN(*src, saturate); - } -} - -// Float8E4M3FNUZ -struct Float8E4M3FNUZ { - uint8_t val{0}; -#if defined(__HIP__) - ORT_HOST_DEVICE Float8E4M3FNUZ() = default; -#else - Float8E4M3FNUZ() = default; -#endif - - struct FromBitsT {}; - static constexpr ORT_HOST_DEVICE FromBitsT FromBits() { return FromBitsT(); } - constexpr ORT_HOST_DEVICE Float8E4M3FNUZ(unsigned char bits, FromBitsT) : val(bits) {} - - inline explicit ORT_HOST_DEVICE Float8E4M3FNUZ(float v, bool saturate = true) { - // This type does not exist on CUDA. - uint32_t b; - std::memcpy(&b, &v, sizeof(b)); - - val = static_cast((b & 0x80000000) >> 24); // sign - if ((b & 0x7fffffff) == 0x7f800000) { // infinity - if (saturate) { - // the highest available value - val |= 0x7F; - } else { - // NaN - val = 0x80; - } - } else if ((b & 0x7F800000) == 0x7F800000) { // NaN - val = 0x80; - } else { - uint8_t e = static_cast((b & 0x7F800000) >> 23); // exponent - uint32_t m = static_cast(b & 0x007FFFFF); // mantissa - - if (e < 116) { - // all near-zero numbers round to positive zero: - val = 0; - } else if (e < 120) { - // denormalized number - auto d = 119 - e; - if (d < 3) { - val |= 1 << (2 - d); - val |= m >> (21 + d); - } else if (m > 0) { - val |= 1; - } else { - // round to positive zero: - val = 0; - } - auto mask = 1 << (20 + d); - if ((m & mask) && ((val & 1) || ((m & (mask - 1)) > 0) || ((m & mask) && (m & (mask << 1)) && ((m & (mask - 1)) == 0)))) { - // rounding - val += 1; - } - } else if (e < 135) { - // normalized number - auto ex = e - 119; - if (ex == 0) { - val |= 0x4; - val |= m >> 21; - } else { - val |= ex << 3; - val |= m >> 20; - } - if ((m & 0x80000) && ((m & 0x100000) || (m & 0x7FFFF))) { - if ((val & 0x7F) < 0x7F) { - // rounding - val += 1; - } else if (!saturate) { - val = 0x80; - } - } - } else if (saturate) { - val |= 0x7F; - } else { - val = 0x80; - } - } - } - - inline ORT_HOST_DEVICE bool IsNaN() const { - return val == 0b10000000; - } - - inline ORT_HOST_DEVICE float ToFloat() const { - // This type does not exist on CUDA. - uint32_t res; - if (val == 0x80) { - res = 0xffc00000; - } else { - uint32_t expo = (val & 0x78) >> 3; - uint32_t mant = val & 0x07; - uint32_t sign = val & 0x80; - res = sign << 24; - if (expo == 0) { - if (mant > 0) { - expo = 0x7F - 8; - if ((mant & 0x4) == 0) { - mant &= 0x3; - mant <<= 1; - expo -= 1; - } - if ((mant & 0x4) == 0) { - mant &= 0x3; - mant <<= 1; - expo -= 1; - } - res |= (mant & 0x3) << 21; - res |= expo << 23; - } - } else { - res |= mant << 20; - expo -= 8; - expo += 0x7F; - res |= expo << 23; - } - } - float float_res; - std::memcpy(&float_res, &res, sizeof(float)); - return float_res; - } - - inline ORT_HOST_DEVICE operator float() const { return ToFloat(); } -}; - -inline ORT_HOST_DEVICE bool operator==(const Float8E4M3FNUZ& left, const Float8E4M3FNUZ& right) { return left.val == right.val; } -inline ORT_HOST_DEVICE bool operator!=(const Float8E4M3FNUZ& left, const Float8E4M3FNUZ& right) { return left.val != right.val; } -inline ORT_HOST_DEVICE bool operator<(const Float8E4M3FNUZ& left, const Float8E4M3FNUZ& right) { return left.val < right.val; } - -// User defined suffixes to make it easier to declare -// initializers with MLFloat8E4M3FN and Float8E4M3FN from unsigned char -#if !defined(__CUDACC__) && !defined(__HIPCC__) - -inline Float8E4M3FNUZ operator""_f8e4m3p8fnuz(unsigned long long int v) { - return Float8E4M3FNUZ(narrow(v), Float8E4M3FNUZ::FromBits()); -} - -inline Float8E4M3FNUZ operator""_f8e4m3fnuzp8(long double v) { - return Float8E4M3FNUZ(static_cast(v), true); -} - -#endif - -inline void Float8E4M3FNUZToFloat(const Float8E4M3FNUZ* blf, float* flt, size_t size) { - auto src = blf; - auto d = flt; - for (; size != 0; ++src, ++d, --size) { - *d = src->ToFloat(); - } -} - -inline void FloatToFloat8E4M3FNUZ(const float* flt, Float8E4M3FNUZ* blf, size_t size, bool saturate) { - auto src = flt; - auto d = blf; - for (; size != 0; ++src, ++d, --size) { - new (d) Float8E4M3FNUZ(*src, saturate); - } -} - -// Float8E5M2 -struct Float8E5M2 { - uint8_t val{0}; -#if defined(__HIP__) - ORT_HOST_DEVICE Float8E5M2() = default; -#else - Float8E5M2() = default; -#endif - - struct FromBitsT {}; - static constexpr ORT_HOST_DEVICE FromBitsT FromBits() { return FromBitsT(); } - constexpr ORT_HOST_DEVICE Float8E5M2(unsigned char bits, FromBitsT) : val(bits) {} - - inline explicit ORT_HOST_DEVICE Float8E5M2(float v, bool saturate = true) { -#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 - val = __nv_cvt_float_to_fp8(v, saturate ? __NV_SATFINITE : __NV_NOSAT, __NV_E5M2); -#else - uint32_t b; - std::memcpy(&b, &v, sizeof(b)); - - val = (b & 0x80000000) >> 24; // sign - if ((b & 0x7FFFFFFF) == 0x7F800000) { // inf - if (saturate) { - // the highest available value - val |= 0x7B; - } else { - // the infinity - val |= 0x7C; - } - } else if ((b & 0x7F800000) == 0x7F800000) { // NaN - val |= 0x7f; - } else { - uint32_t e = (b & 0x7F800000) >> 23; // exponent - uint32_t m = b & 0x007FFFFF; // mantissa - - if (e != 0) { - if (e < 110) { - } else if (e < 113) { - // denormalized number - auto d = 112 - e; - if (d < 2) { - val |= 1 << (1 - d); - val |= m >> (22 + d); - } else if (m > 0) { - val |= 1; - } - auto mask = 1 << (21 + d); - if ((m & mask) && ((val & 1) || ((m & (mask - 1)) > 0) || ((m & mask) && (m & (mask << 1)) && ((m & (mask - 1)) == 0)))) { - // rounding - val += 1; - } - } else if (e < 143) { // 127 + 15 + 1 - auto ex = e - 112; // 127 - 15 - val |= ex << 2; - val |= m >> 21; - if ((m & 0x100000) && ((m & 0xFFFFF) || (m & 0x200000))) { - if ((val & 0x7F) < 0x7B) { - // rounding - val += 1; - } else if (saturate) { - val |= 0x7B; - } else { - val |= 0x7C; - } - } - } else if (saturate) { - val |= 0x7B; - } else { - val |= 0x7C; - } - } - } -#endif - } - - inline ORT_HOST_DEVICE bool IsNaN() const { - // 7D, 7E, 7F are positive NaNs; FD, FE, FF are negative NaNs - return (val & 0b01111111) > 0b01111100; - } - - inline ORT_HOST_DEVICE bool IsInfinity() const { - // 7C and FC are infinity - return (val & 0b01111111) == 0b01111100; - } - - inline ORT_HOST_DEVICE float ToFloat() const { -#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 - return __half2float(__nv_cvt_fp8_to_halfraw(val, __NV_E5M2)); -#else - uint32_t res; - if (val >= 253) { - res = 0xffc00000; - } else if (val >= 125 && val <= 127) { - res = 0x7fc00000; - } else if (val == 252) { - res = 0xff800000; - } else if (val == 124) { - res = 0x7f800000; - } else { - uint32_t expo = (val & 0x7C) >> 2; - uint32_t mant = val & 0x03; - uint32_t sign = val & 0x80; - res = sign << 24; - if (expo == 0) { - if (mant > 0) { - expo = 0x7F - 15; - if ((mant & 0x2) == 0) { - mant &= 0x1; - mant <<= 1; - expo -= 1; - } - res |= (mant & 0x1) << 22; - res |= expo << 23; - } - } else { - res |= mant << 21; - expo -= 15; - expo += 0x7F; - res |= expo << 23; - } - } - - float float_res; - std::memcpy(&float_res, &res, sizeof(float)); - return float_res; -#endif - } - - inline ORT_HOST_DEVICE operator float() const { return ToFloat(); } - -#if defined(CUDA_VERSION) && CUDA_VERSION >= 11080 - ORT_HOST_DEVICE Float8E5M2(const __nv_fp8_e5m2& value) { val = *reinterpret_cast(&value); } - explicit ORT_HOST_DEVICE operator __nv_fp8_e5m2() const { return *reinterpret_cast(&val); } -#endif -}; - -inline ORT_HOST_DEVICE bool operator==(const Float8E5M2& left, const Float8E5M2& right) { return left.val == right.val; } -inline ORT_HOST_DEVICE bool operator!=(const Float8E5M2& left, const Float8E5M2& right) { return left.val != right.val; } -inline ORT_HOST_DEVICE bool operator<(const Float8E5M2& left, const Float8E5M2& right) { return left.val < right.val; } - -// User defined suffixes to make it easier to declare -// initializers with MLFloat8E5M2 and Float8E5M2 from unsigned char -#if !defined(__CUDACC__) && !defined(__HIPCC__) - -inline Float8E5M2 operator""_f8e5m2fn(unsigned long long int v) { - return Float8E5M2(narrow(v), Float8E5M2::FromBits()); -} - -inline Float8E5M2 operator""_f8e5m2fnp8(long double v) { - return Float8E5M2(static_cast(v), true); -} - -#endif - -inline void Float8E5M2ToFloat(const Float8E5M2* blf, float* flt, size_t size) { - auto src = blf; - auto d = flt; - for (; size != 0; ++src, ++d, --size) { - *d = src->ToFloat(); - } -} - -inline void FloatToFloat8E5M2(const float* flt, Float8E5M2* blf, size_t size, bool saturate) { - auto src = flt; - auto d = blf; - for (; size != 0; ++src, ++d, --size) { - new (d) Float8E5M2(*src, saturate); - } -} - -// Float8E5M2FNUZ -struct Float8E5M2FNUZ { - uint8_t val{0}; -#if defined(__HIP__) - ORT_HOST_DEVICE Float8E5M2FNUZ() = default; -#else - Float8E5M2FNUZ() = default; -#endif - - struct FromBitsT {}; - static constexpr ORT_HOST_DEVICE FromBitsT FromBits() { return FromBitsT(); } - constexpr ORT_HOST_DEVICE Float8E5M2FNUZ(unsigned char bits, FromBitsT) : val(bits) {} - - inline explicit ORT_HOST_DEVICE Float8E5M2FNUZ(float v, bool saturate = true) { - // This type does not exist on CUDA. - uint32_t b; - std::memcpy(&b, &v, sizeof(b)); - - val = (b & 0x80000000) >> 24; // sign - if ((b & 0x7FFFFFFF) == 0x7F800000) { // inf - if (saturate) { - val |= 0x7F; - } else { - val = 0x80; - } - } else if ((b & 0x7F800000) == 0x7F800000) { // NaN - val = 0x80; - } else { - uint32_t e = (b & 0x7F800000) >> 23; // exponent - uint32_t m = b & 0x007FFFFF; // mantissa - - if (e < 109) { - // all near-zero numbers round to positive zero: - val = 0; - } else if (e < 112) { - // denormalized number - auto d = 111 - e; - if (d < 2) { - val |= 1 << (1 - d); - val |= m >> (22 + d); - } else if (m > 0) { - val |= 1; - } else { - // round to positive zero: - val = 0; - } - auto mask = 1 << (21 + d); - if ((m & mask) && ((val & 1) || ((m & (mask - 1)) > 0) || ((m & mask) && (m & (mask << 1)) && ((m & (mask - 1)) == 0)))) { - // rounding - val += 1; - } - } else if (e < 143) { - // normalized number - auto ex = e - 111; - val |= ex << 2; - val |= m >> 21; - if ((m & 0x100000) && ((m & 0xFFFFF) || (m & 0x200000))) { - if ((val & 0x7F) < 0x7F) { - // rounding - val += 1; - } else if (!saturate) { - val = 0x80; - } - } - } else if ((e == 255) && (m == 0)) { - val = 0x80; - } else if (saturate) { - val |= 0x7F; - } else { - val = 0x80; - } - } - } - - inline ORT_HOST_DEVICE bool IsNaN() const { - return val == 0b10000000; - } - - inline ORT_HOST_DEVICE float ToFloat() const { - // This type does not exist on CUDA. - uint32_t res; - if (val == 0x80) { - res = 0xffc00000; - } else { - uint32_t expo = (val & 0x7C) >> 2; - uint32_t mant = val & 0x03; - uint32_t sign = val & 0x80; - res = sign << 24; - if (expo == 0) { - if (mant > 0) { - expo = 0x7F - 16; - if ((mant & 0x2) == 0) { - mant &= 0x1; - mant <<= 1; - expo -= 1; - } - res |= (mant & 0x1) << 22; - res |= expo << 23; - } - } else { - res |= mant << 21; - expo -= 16; - expo += 0x7F; - res |= expo << 23; - } - } - - float float_res; - std::memcpy(&float_res, &res, sizeof(float)); - return float_res; - } - - inline ORT_HOST_DEVICE operator float() const { return ToFloat(); } -}; - -inline ORT_HOST_DEVICE bool operator==(const Float8E5M2FNUZ& left, const Float8E5M2FNUZ& right) { return left.val == right.val; } -inline ORT_HOST_DEVICE bool operator!=(const Float8E5M2FNUZ& left, const Float8E5M2FNUZ& right) { return left.val != right.val; } -inline ORT_HOST_DEVICE bool operator<(const Float8E5M2FNUZ& left, const Float8E5M2FNUZ& right) { return left.val < right.val; } - -// User defined suffixes to make it easier to declare -// initializers with MLFloat8E5M2 and Float8E5M2 from unsigned char -#if !defined(__CUDACC__) && !defined(__HIPCC__) - -inline Float8E5M2FNUZ operator""_f8e5m2fnuz(unsigned long long int v) { - return Float8E5M2FNUZ(narrow(v), Float8E5M2FNUZ::FromBits()); -} - -inline Float8E5M2FNUZ operator""_f8e5m2fnuzp8(long double v) { - return Float8E5M2FNUZ(static_cast(v), true); -} - -#endif - -inline void Float8E5M2FNUZToFloat(const Float8E5M2FNUZ* blf, float* flt, size_t size) { - auto src = blf; - auto d = flt; - for (; size != 0; ++src, ++d, --size) { - *d = src->ToFloat(); - } -} - -inline void FloatToFloat8E5M2FNUZ(const float* flt, Float8E5M2FNUZ* blf, size_t size, bool saturate) { - auto src = flt; - auto d = blf; - for (; size != 0; ++src, ++d, --size) { - new (d) Float8E5M2FNUZ(*src, saturate); - } -} - -} // namespace onnxruntime - -namespace std { - -template <> -class numeric_limits { - public: - static constexpr onnxruntime::Float8E4M3FN lowest() { - return onnxruntime::Float8E4M3FN(0xFE, onnxruntime::Float8E4M3FN::FromBits()); // -448 - } - - static constexpr onnxruntime::Float8E4M3FN max() { - return onnxruntime::Float8E4M3FN(0x7E, onnxruntime::Float8E4M3FN::FromBits()); // 448 - } - - static constexpr onnxruntime::Float8E4M3FN min() { - return onnxruntime::Float8E4M3FN(0x08, onnxruntime::Float8E4M3FN::FromBits()); // 2^-6 = 0.015625 - } - - static constexpr onnxruntime::Float8E4M3FN denorm_min() { - return onnxruntime::Float8E4M3FN(0x01, onnxruntime::Float8E4M3FN::FromBits()); // 2^-9 = 0.001953125 - } - - static constexpr onnxruntime::Float8E4M3FN epsilon() { - return onnxruntime::Float8E4M3FN(0x20, onnxruntime::Float8E4M3FN::FromBits()); - } - - static constexpr onnxruntime::Float8E4M3FN round_error() { - return onnxruntime::Float8E4M3FN(0x30, onnxruntime::Float8E4M3FN::FromBits()); - } - - static constexpr onnxruntime::Float8E4M3FN infinity() { - // no infinity, returns quiet NaN instead - return quiet_NaN(); - } - - static constexpr onnxruntime::Float8E4M3FN quiet_NaN() { - return onnxruntime::Float8E4M3FN(0x7F, onnxruntime::Float8E4M3FN::FromBits()); - } - - static constexpr bool is_specialized = true; - static constexpr bool is_signed = true; - static constexpr bool is_integer = false; - static constexpr bool is_exact = false; - static constexpr bool has_infinity = false; - static constexpr bool has_quiet_NaN = true; - static constexpr bool has_signaling_NaN = false; - static constexpr auto has_denorm = true; - static constexpr auto has_denorm_loss = true; - static constexpr auto round_style = round_to_nearest; - static constexpr bool is_iec559 = false; - static constexpr bool is_bounded = true; - static constexpr bool is_modulo = false; - static constexpr int digits = 4; - static constexpr int digits10 = 0; - static constexpr int max_digits10 = 3; - static constexpr int radix = 2; - static constexpr int min_exponent = -5; - static constexpr int min_exponent10 = -1; - static constexpr int max_exponent = 8; - static constexpr int max_exponent10 = 2; - static constexpr auto traps = false; - static constexpr auto tinyness_before = false; -}; - -template <> -class numeric_limits { - public: - static constexpr onnxruntime::Float8E5M2 lowest() { - return onnxruntime::Float8E5M2(0xFB, onnxruntime::Float8E5M2::FromBits()); // -57344.0 - } - - static constexpr onnxruntime::Float8E5M2 max() { - return onnxruntime::Float8E5M2(0x7B, onnxruntime::Float8E5M2::FromBits()); // 57344.0 - } - - static constexpr onnxruntime::Float8E5M2 min() { - return onnxruntime::Float8E5M2(0x4, onnxruntime::Float8E5M2::FromBits()); // 2^-14 = 0.00006103515 - } - - static constexpr onnxruntime::Float8E5M2 denorm_min() { - return onnxruntime::Float8E5M2(0x01, onnxruntime::Float8E5M2::FromBits()); // 2^-16 = 0.00001525878 - } - - static constexpr onnxruntime::Float8E5M2 epsilon() { - return onnxruntime::Float8E5M2(0x34, onnxruntime::Float8E5M2::FromBits()); - } - - static constexpr onnxruntime::Float8E5M2 round_error() { - return onnxruntime::Float8E5M2(0x38, onnxruntime::Float8E5M2::FromBits()); - } - - static constexpr onnxruntime::Float8E5M2 infinity() { - return onnxruntime::Float8E5M2(0x7C, onnxruntime::Float8E5M2::FromBits()); - } - - static constexpr onnxruntime::Float8E5M2 quiet_NaN() { - return onnxruntime::Float8E5M2(0x7F, onnxruntime::Float8E5M2::FromBits()); - } - - static constexpr bool is_specialized = true; - static constexpr bool is_signed = true; - static constexpr bool is_integer = false; - static constexpr bool is_exact = false; - static constexpr bool has_infinity = true; - static constexpr bool has_quiet_NaN = true; - static constexpr bool has_signaling_NaN = false; - static constexpr auto has_denorm = true; - static constexpr auto has_denorm_loss = true; - static constexpr auto round_style = round_to_nearest; - static constexpr bool is_iec559 = false; - static constexpr bool is_bounded = true; - static constexpr bool is_modulo = false; - static constexpr int digits = 3; - static constexpr int digits10 = 0; - static constexpr int max_digits10 = 2; - static constexpr int radix = 2; - static constexpr int min_exponent = -13; - static constexpr int min_exponent10 = -4; - static constexpr int max_exponent = 16; - static constexpr int max_exponent10 = 4; - static constexpr auto traps = false; - static constexpr auto tinyness_before = false; -}; - -template <> -class numeric_limits { - public: - static constexpr onnxruntime::Float8E4M3FNUZ lowest() { - return onnxruntime::Float8E4M3FNUZ(0xFF, onnxruntime::Float8E4M3FNUZ::FromBits()); // -240.0 - } - - static constexpr onnxruntime::Float8E4M3FNUZ max() { - return onnxruntime::Float8E4M3FNUZ(0x7F, onnxruntime::Float8E4M3FNUZ::FromBits()); // 240.0 - } - - static constexpr onnxruntime::Float8E4M3FNUZ min() { - return onnxruntime::Float8E4M3FNUZ(0x08, onnxruntime::Float8E4M3FNUZ::FromBits()); // 2^-7 = 0.0078125 - } - - static constexpr onnxruntime::Float8E4M3FNUZ denorm_min() { - return onnxruntime::Float8E4M3FNUZ(0x01, onnxruntime::Float8E4M3FNUZ::FromBits()); // 2^-10 = 0.0009765625 - } - - static constexpr onnxruntime::Float8E4M3FNUZ epsilon() { - return onnxruntime::Float8E4M3FNUZ(0x28, onnxruntime::Float8E4M3FNUZ::FromBits()); - } - - static constexpr onnxruntime::Float8E4M3FNUZ round_error() { - return onnxruntime::Float8E4M3FNUZ(0x38, onnxruntime::Float8E4M3FNUZ::FromBits()); - } - - static constexpr onnxruntime::Float8E4M3FNUZ infinity() { - // no infinity, returns quiet NaN instead - return quiet_NaN(); - } - - static constexpr onnxruntime::Float8E4M3FNUZ quiet_NaN() { - return onnxruntime::Float8E4M3FNUZ(0x80, onnxruntime::Float8E4M3FNUZ::FromBits()); - } - - static constexpr bool is_specialized = true; - static constexpr bool is_signed = true; - static constexpr bool is_integer = false; - static constexpr bool is_exact = false; - static constexpr bool has_infinity = false; - static constexpr bool has_quiet_NaN = true; - static constexpr bool has_signaling_NaN = false; - static constexpr auto has_denorm = true; - static constexpr auto has_denorm_loss = true; - static constexpr auto round_style = round_to_nearest; - static constexpr bool is_iec559 = false; - static constexpr bool is_bounded = true; - static constexpr bool is_modulo = false; - static constexpr int digits = 4; - static constexpr int digits10 = 0; - static constexpr int max_digits10 = 3; - static constexpr int radix = 2; - static constexpr int min_exponent = -6; - static constexpr int min_exponent10 = -1; - static constexpr int max_exponent = 8; - static constexpr int max_exponent10 = 2; - static constexpr auto traps = false; - static constexpr auto tinyness_before = false; -}; - -template <> -class numeric_limits { - public: - static constexpr onnxruntime::Float8E5M2FNUZ lowest() { - return onnxruntime::Float8E5M2FNUZ(0xFF, onnxruntime::Float8E5M2FNUZ::FromBits()); // -57344.0 - } - - static constexpr onnxruntime::Float8E5M2FNUZ max() { - return onnxruntime::Float8E5M2FNUZ(0x7F, onnxruntime::Float8E5M2FNUZ::FromBits()); // 57344.0 - } - - static constexpr onnxruntime::Float8E5M2FNUZ min() { - return onnxruntime::Float8E5M2FNUZ(0x04, onnxruntime::Float8E5M2FNUZ::FromBits()); // 2^-15 = 0.00003051757 - } - - static constexpr onnxruntime::Float8E5M2FNUZ denorm_min() { - return onnxruntime::Float8E5M2FNUZ(0x01, onnxruntime::Float8E5M2FNUZ::FromBits()); // 2^-17 = 0.00000762939 - } - - static constexpr onnxruntime::Float8E5M2FNUZ epsilon() { - return onnxruntime::Float8E5M2FNUZ(0x34, onnxruntime::Float8E5M2FNUZ::FromBits()); - } - - static constexpr onnxruntime::Float8E5M2FNUZ round_error() { - return onnxruntime::Float8E5M2FNUZ(0x38, onnxruntime::Float8E5M2FNUZ::FromBits()); - } - - static constexpr onnxruntime::Float8E5M2FNUZ infinity() { - // no infinity, returns quiet NaN instead - return quiet_NaN(); - } - - static constexpr onnxruntime::Float8E5M2FNUZ quiet_NaN() { - return onnxruntime::Float8E5M2FNUZ(0x80, onnxruntime::Float8E5M2FNUZ::FromBits()); - } - - static constexpr bool is_specialized = true; - static constexpr bool is_signed = true; - static constexpr bool is_integer = false; - static constexpr bool is_exact = false; - static constexpr bool has_infinity = false; - static constexpr bool has_quiet_NaN = true; - static constexpr bool has_signaling_NaN = false; - static constexpr auto has_denorm = true; - static constexpr auto has_denorm_loss = true; - static constexpr auto round_style = round_to_nearest; - static constexpr bool is_iec559 = false; - static constexpr bool is_bounded = true; - static constexpr bool is_modulo = false; - static constexpr int digits = 3; - static constexpr int digits10 = 0; - static constexpr int max_digits10 = 2; - static constexpr int radix = 2; - static constexpr int min_exponent = -14; - static constexpr int min_exponent10 = -4; - static constexpr int max_exponent = 16; - static constexpr int max_exponent10 = 4; - static constexpr auto traps = false; - static constexpr auto tinyness_before = false; -}; - -} // namespace std - -#endif // DISABLE_FLOAT8_TYPES diff --git a/include/onnxruntime/core/framework/int2.h b/include/onnxruntime/core/framework/int2.h new file mode 100644 index 0000000000000..40af5746c9273 --- /dev/null +++ b/include/onnxruntime/core/framework/int2.h @@ -0,0 +1,187 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include +#include "core/common/common.h" +#include +#include "onnxruntime_config.h" + +namespace onnxruntime { + +template +struct Int2Traits; + +template <> +struct Int2Traits { + using UnpackedType = int8_t; + static constexpr int8_t min_val = -2; + static constexpr int8_t max_val = 1; +}; + +template <> +struct Int2Traits { + using UnpackedType = uint8_t; + static constexpr uint8_t min_val = 0; + static constexpr uint8_t max_val = 3; +}; + +/// +/// Stores 4 packed 2-bit elements in 1 byte. +/// Packing follows ONNX spec: x0 | (x1 << 2) | (x2 << 4) | (x3 << 6) +/// +/// Set to true if signed int2, or false if unsigned uint2. +template +struct Int2x4Base { + using UnpackedType = typename Int2Traits::UnpackedType; + static constexpr UnpackedType min_val = Int2Traits::min_val; + static constexpr UnpackedType max_val = Int2Traits::max_val; + + std::byte bits_{}; + + Int2x4Base() = default; + + explicit Int2x4Base(std::byte bits) { + bits_ = bits; + } + + Int2x4Base(UnpackedType val0, UnpackedType val1, UnpackedType val2, UnpackedType val3) { + bits_ = static_cast( + (val0 & 0x3) | + ((val1 & 0x3) << 2) | + ((val2 & 0x3) << 4) | + ((val3 & 0x3) << 6)); + } + + static inline int8_t SignExtendLower2Bits(std::byte bits) { + // Sign-extend lower 2-bits by left shifting and then doing an arithmetic right shift. + constexpr uint8_t shift = (sizeof(int32_t) * 8) - 2; + return static_cast((static_cast(bits) << shift) >> shift); + } + + inline UnpackedType GetElem(size_t index) const { + assert(index <= 3); + const uint8_t shift = 2 * static_cast(index); + const std::byte val = (bits_ >> shift) & std::byte{0x3}; + + if constexpr (Signed) { + return SignExtendLower2Bits(val); + } else { + return static_cast(val); + } + } + + inline void SetElem(size_t index, UnpackedType val) { + assert(index <= 3); + const uint8_t shift = 2 * static_cast(index); + const std::byte clear_mask = ~(std::byte{0x3} << shift); + + bits_ &= clear_mask; // Clear 2-bit element to 0 + bits_ |= static_cast((val & 0x3) << shift); // Set 2-bit element to val + } + + inline std::byte ToBits() const { + return bits_; + } + + /// + /// Calculates the number of packed byte units needed to store the given number of 2-bit elements. + /// Each byte stores 4 x 2-bit elements. + /// + static size_t CalcNumInt2Quads(size_t num_int2_elems) { + return (num_int2_elems + 3) / 4; + } + + /// + /// Copy a source buffer of 2-bit elements (packed) into a destination buffer of 8-bit elements (unpacked). + /// + /// Destination buffer to store unpacked 8-bit elements + /// Source buffer with 2-bit elements + /// True on success + static bool Unpack(gsl::span dst, gsl::span> src) { + if (CalcNumInt2Quads(dst.size()) != src.size()) { + return false; + } + + if (src.empty()) { + return true; + } + + for (size_t i = 0; i < dst.size(); i++) { + size_t byte_idx = i >> 2; // i / 4 + size_t elem_idx = i & 0x3; // i % 4 + dst[i] = src[byte_idx].GetElem(elem_idx); + } + + return true; + } + + /// + /// Copy a source buffer of 8-bit elements (unpacked) into a destination buffer of 2-bit elements (packed). + /// + /// Destination buffer to store packed 2-bit elements + /// Source buffer with 8-bit elements + /// True on success + static bool Pack(gsl::span> dst, gsl::span src) { + if (CalcNumInt2Quads(src.size()) != dst.size()) { + return false; + } + + if (src.empty()) { + return true; + } + + size_t src_i = 0; + size_t dst_i = 0; + const size_t full_quads = src.size() / 4; + + // Process complete groups of 4 elements + + for (; dst_i < full_quads; dst_i++) { +#if defined(__GNUC__) && defined(HAS_ARRAY_BOUNDS) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Warray-bounds" +#endif + dst[dst_i] = Int2x4Base(src[src_i], src[src_i + 1], src[src_i + 2], src[src_i + 3]); +#if defined(__GNUC__) && defined(HAS_ARRAY_BOUNDS) +#pragma GCC diagnostic pop +#endif + src_i += 4; + } + + // Handle remaining elements (1-3) + if (src_i < src.size()) { + UnpackedType vals[4] = {0, 0, 0, 0}; + size_t remaining = src.size() - src_i; + for (size_t j = 0; j < remaining; j++) { + vals[j] = src[src_i + j]; + } + dst[dst_i] = Int2x4Base(vals[0], vals[1], vals[2], vals[3]); + } + + return true; + } + + /// + /// Returns hierarchical indices for a packed int2 element from the given element index. + /// + /// Usage: + /// Int2x4* data = ...; + /// auto indices = GetTensorElemIndices(5); // 6th int2 element + /// int8_t elem = data[indices.first].GetElem(indices.second); + /// + /// Index of 2-bit element + /// Pair of (byte_index, element_index_within_byte) + static inline std::pair GetTensorElemIndices(size_t index) { + return {index >> 2, index & 0x3}; + } +}; + +using Int2x4 = Int2x4Base; +using UInt2x4 = Int2x4Base; +static_assert(sizeof(Int2x4) == sizeof(std::byte)); +static_assert(sizeof(UInt2x4) == sizeof(std::byte)); + +} // namespace onnxruntime diff --git a/include/onnxruntime/core/framework/op_kernel.h b/include/onnxruntime/core/framework/op_kernel.h index 375f0a4dc8dd2..42e8e9c5e3cbe 100644 --- a/include/onnxruntime/core/framework/op_kernel.h +++ b/include/onnxruntime/core/framework/op_kernel.h @@ -4,6 +4,7 @@ #pragma once #include "boost/mp11.hpp" +#include // It is safe to include the below header even if SHARED_PROVIDER macro is enabled // as it doesn't include any pb headers. @@ -26,7 +27,6 @@ #include "core/graph/constants.h" #include "core/graph/graph_viewer.h" #include "core/graph/onnx_protobuf.h" -#include namespace onnxruntime { class OpKernelContext; } @@ -107,6 +107,7 @@ class OpKernel { // Override this function to use provided pre-packed weight. // Status UseSharedPrePackedBuffers(std::vector& prepacked_buffers, + // gsl::span prepacked_buffer_sizes, // int input_idx, // /*out*/ bool& used_shared_buffers) { // used_shared_buffers = true; @@ -120,10 +121,12 @@ class OpKernel { // and must use the same order for retrieval in UseSharedPrePackedBuffers(). Though each element // of this vector is a BufferUniquePtr, the deleter of the BufferUniquePtr is NULL. So actually they // are raw pointers. + // @param prepacked_buffer_sizes: The sizes (in bytes) of each buffer in prepacked_buffers. // @param input_idx: The input index of the tensor in this kernel // @param used_shared_buffers: Boolean flag set by the kernel implementation indicating // that the provided weight has been used by the kernel. virtual Status UseSharedPrePackedBuffers(std::vector& /*prepacked_buffers*/, + gsl::span /*prepacked_buffer_sizes*/, int /*input_idx*/, /*out*/ bool& used_shared_buffers) { used_shared_buffers = false; @@ -190,13 +193,6 @@ KernelCreateInfo BuildKernelCreateInfo(); } // namespace js } // namespace contrib -namespace contrib { -namespace rocm { -template -KernelCreateInfo BuildKernelCreateInfo(); -} // namespace rocm -} // namespace contrib - namespace contrib { namespace snpe { template @@ -305,6 +301,24 @@ using BuildKernelCreateInfoFn = KernelCreateInfo (*)(); static_cast([](FuncManager&, const OpKernelInfo& info, std::unique_ptr& out) -> Status { out = std::make_unique<__VA_ARGS__>(info); return Status::OK(); })); \ } +#define ONNX_OPERATOR_THREE_TYPED_KERNEL_CLASS_NAME(provider, domain, ver, type1, type2, type3, name) \ + provider##_##name##_##domain##_ver##ver##_##type1##_##type2##_##type3 + +#define ONNX_OPERATOR_THREE_TYPED_KERNEL_EX(name, domain, ver, type1, type2, type3, provider, builder, ...) \ + class ONNX_OPERATOR_THREE_TYPED_KERNEL_CLASS_NAME(provider, domain, ver, type1, type2, type3, name); \ + template <> \ + KernelCreateInfo \ + BuildKernelCreateInfo() { \ + return KernelCreateInfo( \ + builder.SetName(#name) \ + .SetDomain(domain) \ + .SinceVersion(ver) \ + .Provider(provider) \ + .Build(), \ + static_cast([](FuncManager&, const OpKernelInfo& info, std::unique_ptr& out) -> Status { \ + out = std::make_unique<__VA_ARGS__>(info); return Status::OK(); })); \ + } + #define ONNX_OPERATOR_VERSIONED_TYPED_KERNEL_CLASS_NAME(provider, domain, startver, endver, type, name) \ provider##_##name##_##domain##_ver##startver##_##endver##_##type diff --git a/include/onnxruntime/core/framework/op_kernel_context.h b/include/onnxruntime/core/framework/op_kernel_context.h index ac22d9130983a..3fd9ee0d8b292 100644 --- a/include/onnxruntime/core/framework/op_kernel_context.h +++ b/include/onnxruntime/core/framework/op_kernel_context.h @@ -192,7 +192,7 @@ class OpKernelContext { onnxruntime::NodeIndex GetNodeIndex() const; virtual const OrtValue* GetInputMLValue(int index) const; - const OrtValue* GetImplicitInputMLValue(int index) const; + virtual const OrtValue* GetImplicitInputMLValue(int index) const; OrtValue* GetOutputMLValue(int index); #ifdef ENABLE_ATEN @@ -204,6 +204,8 @@ class OpKernelContext { virtual OrtValue* GetOrCreateOutputMLValue(int index); + virtual int GetOrtValueIndexForOutput(int output_index) const; + private: ORT_DISALLOW_COPY_AND_ASSIGNMENT(OpKernelContext); int GetInputArgIndex(int index) const; diff --git a/include/onnxruntime/core/framework/ort_value.h b/include/onnxruntime/core/framework/ort_value.h index a071f3182faad..0ed427dfb7695 100644 --- a/include/onnxruntime/core/framework/ort_value.h +++ b/include/onnxruntime/core/framework/ort_value.h @@ -18,7 +18,7 @@ class SparseTensor; class TensorSeq; } // namespace onnxruntime -#endif +#endif // SHARED_PROVIDER /** Represents both tensors and non-tensors. @@ -37,8 +37,8 @@ struct OrtValue { type_ = type; } - void Init(void* pData, onnxruntime::MLDataType type, const std::function& deleter) { - data_.reset(pData, deleter); + void Init(void* pData, onnxruntime::MLDataType type, std::function deleter) { + data_.reset(pData, std::move(deleter)); type_ = type; } diff --git a/include/onnxruntime/core/framework/ortdevice.h b/include/onnxruntime/core/framework/ortdevice.h index adade482f6a17..c85b01210fc3b 100644 --- a/include/onnxruntime/core/framework/ortdevice.h +++ b/include/onnxruntime/core/framework/ortdevice.h @@ -4,55 +4,124 @@ #pragma once #include +#include "core/common/common.h" #include "core/common/hash_combine.h" -// Struct to represent a physical device. +// fix clash with INTEL that is defined in +// MacOSX14.2.sdk/System/Library/Frameworks/Security.framework/Headers/oidsbase.h +#if defined(__APPLE__) +#undef INTEL +#endif + +// Struct to represent a combination of physical device and memory type. +// A memory allocation and allocator have a specific OrtDevice associated with them, and this information is used +// to determine when data transfer is required. struct OrtDevice { using DeviceType = int8_t; using MemoryType = int8_t; using DeviceId = int16_t; + using VendorId = uint32_t; + using Alignment = size_t; // Pre-defined device types. - static const DeviceType CPU = 0; - static const DeviceType GPU = 1; // Nvidia or AMD - static const DeviceType FPGA = 2; - static const DeviceType NPU = 3; // Ascend - static const DeviceType DML = 4; + static constexpr DeviceType CPU = 0; + static constexpr DeviceType GPU = 1; + static constexpr DeviceType FPGA = 2; + static constexpr DeviceType NPU = 3; + // this is used in the python API so we need to keep it for backward compatibility + // it is only used in the OrtDevice ctor, and is mapped to GPU + VendorIds::MICROSOFT + static constexpr DeviceType DML = 4; struct MemType { - // Pre-defined memory types. - static const MemoryType DEFAULT = 0; - static const MemoryType CUDA_PINNED = 1; - static const MemoryType HIP_PINNED = 2; - static const MemoryType CANN_PINNED = 3; - static const MemoryType QNN_HTP_SHARED = 4; + static constexpr MemoryType DEFAULT = 0; + + // deprecated values. MemType + VendorId is used to identify the memory type. + enum Deprecated : MemoryType { + CUDA_PINNED = 1, + HIP_PINNED = 2, + CANN_PINNED = 3, + QNN_HTP_SHARED = 4, + }; + + // HOST_ACCESSIBLE memory is treated as CPU memory. + // When creating an OrtDevice with MemType::HOST_ACCESSIBLE: + // - For memory that is only accessible by a specific device and CPU, use the specific device type and id. + // - When creating an OrtDevice for an EP allocator, you would typically use the same device type and id + // that the EP is registered with (i.e. the OrtDevice passed to the base IExecutionProvider constructor). + // - Otherwise use OrtDevice::CPU. + static constexpr MemoryType HOST_ACCESSIBLE = 5; + }; + + // PCI vendor ids + enum VendorIds : VendorId { + // No vendor ID. Valid for DeviceType::CPU + MemType::DEFAULT or for generic allocators like WebGPU. + NONE = 0x0000, + AMD = 0x1002, // MIGraphX EP + NVIDIA = 0x10DE, // CUDA/TensorRT + ARM = 0x13B5, // ARM GPU EP + MICROSOFT = 0x1414, // DML EP + HUAWEI = 0x19E5, // CANN EP + QUALCOMM = 0x5143, // QNN DP + INTEL = 0x8086, // OpenVINO }; - constexpr OrtDevice(DeviceType device_type_, MemoryType memory_type_, DeviceId device_id_) + constexpr OrtDevice(DeviceType device_type_, MemoryType memory_type_, VendorId vendor_id_, DeviceId device_id_, + Alignment alignment) /*noexcept*/ : device_type(device_type_), memory_type(memory_type_), - device_id(device_id_) {} + device_id(device_id_), + vendor_id(vendor_id_), + alignment(alignment) { + // temporary to make sure we haven't missed any places where the deprecated values were used + // ctor can go back to noexcept once everything is validated and this is removed`1 + ORT_ENFORCE(memory_type == MemType::DEFAULT || memory_type == MemType::HOST_ACCESSIBLE, + "Invalid memory type: ", static_cast(memory_type)); + + if (device_type == DML) { + device_type = GPU; + vendor_id = VendorIds::MICROSOFT; + } + } - constexpr OrtDevice() : OrtDevice(CPU, MemType::DEFAULT, 0) {} + constexpr OrtDevice(DeviceType device_type_, MemoryType memory_type_, VendorId vendor_id_, + DeviceId device_id_) noexcept + : OrtDevice(device_type_, memory_type_, vendor_id_, device_id_, /*alignment*/ 0) {} - DeviceType Type() const { + constexpr OrtDevice() noexcept : OrtDevice(CPU, MemType::DEFAULT, VendorIds::NONE, 0) {} + + DeviceType Type() const noexcept { return device_type; } - MemoryType MemType() const { + MemoryType MemType() const noexcept { return memory_type; } - DeviceId Id() const { + VendorId Vendor() const noexcept { + return vendor_id; + } + + DeviceId Id() const noexcept { return device_id; } + Alignment GetAlignment() const noexcept { + return alignment; + } + + // CPU or HOST_ACCESSIBLE memory. + bool UsesCpuMemory() const noexcept { + return device_type == CPU || memory_type == MemType::HOST_ACCESSIBLE; + } + std::string ToString() const { std::ostringstream ostr; ostr << "Device:[" << "DeviceType:" << static_cast(device_type) << " MemoryType:" << static_cast(memory_type) + << " VendorId:" << vendor_id << " DeviceId:" << device_id + << " Alignment:" << alignment << "]"; return ostr.str(); } @@ -61,7 +130,9 @@ struct OrtDevice { size_t Hash() const { auto h = std::hash()(device_type); onnxruntime::HashCombine(memory_type, h); + onnxruntime::HashCombine(vendor_id, h); onnxruntime::HashCombine(device_id, h); + onnxruntime::HashCombine(alignment, h); return h; } @@ -71,8 +142,19 @@ struct OrtDevice { return device_type < other.device_type; if (memory_type != other.memory_type) return memory_type < other.memory_type; + if (vendor_id != other.vendor_id) + return vendor_id < other.vendor_id; + if (device_id != other.device_id) + return device_id < other.device_id; - return device_id < other.device_id; + return alignment < other.alignment; + } + + bool EqualIgnoringAlignment(const OrtDevice& other) const { + return device_type == other.device_type && + memory_type == other.memory_type && + vendor_id == other.vendor_id && + device_id == other.device_id; } private: @@ -84,10 +166,19 @@ struct OrtDevice { // Device index. int32_t device_id : 16; + + uint32_t vendor_id; + + // Required alignment + Alignment alignment; }; inline bool operator==(const OrtDevice& left, const OrtDevice& other) { - return left.Id() == other.Id() && left.MemType() == other.MemType() && left.Type() == other.Type(); + return left.Type() == other.Type() && + left.MemType() == other.MemType() && + left.Vendor() == other.Vendor() && + left.Id() == other.Id() && + left.GetAlignment() == other.GetAlignment(); } inline bool operator!=(const OrtDevice& left, const OrtDevice& other) { diff --git a/include/onnxruntime/core/framework/ortmemoryinfo.h b/include/onnxruntime/core/framework/ortmemoryinfo.h index 82f581e994904..1be81e77064d2 100644 --- a/include/onnxruntime/core/framework/ortmemoryinfo.h +++ b/include/onnxruntime/core/framework/ortmemoryinfo.h @@ -13,20 +13,14 @@ struct OrtMemoryInfo { OrtMemoryInfo() = default; // to allow default construction of Tensor // use string for name, so we could have customized allocator in execution provider. - const char* name = nullptr; - int id = -1; + std::string name; OrtMemType mem_type = OrtMemTypeDefault; OrtAllocatorType alloc_type = OrtInvalidAllocator; OrtDevice device; - constexpr OrtMemoryInfo(const char* name_, OrtAllocatorType type_, OrtDevice device_ = OrtDevice(), int id_ = 0, - OrtMemType mem_type_ = OrtMemTypeDefault) -#if ((defined(__GNUC__) && __GNUC__ > 4) || defined(__clang__)) - // this causes a spurious error in CentOS gcc 4.8 build so disable if GCC version < 5 - __attribute__((nonnull)) -#endif - : name(name_), - id(id_), + OrtMemoryInfo(std::string name_, OrtAllocatorType type_, OrtDevice device_ = OrtDevice(), + OrtMemType mem_type_ = OrtMemTypeDefault) + : name(std::move(name_)), mem_type(mem_type_), alloc_type(type_), device(device_) { @@ -38,18 +32,17 @@ struct OrtMemoryInfo { return alloc_type < other.alloc_type; if (mem_type != other.mem_type) return mem_type < other.mem_type; - if (id != other.id) - return id < other.id; + if (device != other.device) + return device < other.device; - return strcmp(name, other.name) < 0; + return name < other.name; } // This is to make OrtMemoryInfo a valid key in hash tables - // we ignore device id size_t Hash() const { auto h = std::hash()(alloc_type); onnxruntime::HashCombine(mem_type, h); - onnxruntime::HashCombine(id, h); + onnxruntime::HashCombine(device.Hash(), h); onnxruntime::HashCombine(name, h); return h; } @@ -58,7 +51,6 @@ struct OrtMemoryInfo { std::ostringstream ostr; ostr << "OrtMemoryInfo:[" << "name:" << name - << " id:" << id << " OrtMemType:" << mem_type << " OrtAllocatorType:" << alloc_type << " " << device.ToString() @@ -71,8 +63,8 @@ struct OrtMemoryInfo { inline bool operator==(const OrtMemoryInfo& left, const OrtMemoryInfo& other) { return left.mem_type == other.mem_type && left.alloc_type == other.alloc_type && - left.id == other.id && - strcmp(left.name, other.name) == 0; + left.device == other.device && + left.name == other.name; } inline bool operator!=(const OrtMemoryInfo& lhs, const OrtMemoryInfo& rhs) { return !(lhs == rhs); } diff --git a/include/onnxruntime/core/framework/provider_options_utils.h b/include/onnxruntime/core/framework/provider_options_utils.h index 5967fb91523d0..badb7320ea49e 100644 --- a/include/onnxruntime/core/framework/provider_options_utils.h +++ b/include/onnxruntime/core/framework/provider_options_utils.h @@ -83,12 +83,24 @@ class ProviderOptionsParser { template ProviderOptionsParser& AddValueParser( const std::string& name, ValueParserType value_parser) { + return AddValueParser(std::string_view{name}, value_parser); + } + + template + ProviderOptionsParser& AddValueParser( + std::string_view name, ValueParserType value_parser) { ORT_ENFORCE( value_parsers_.emplace(name, ValueParser{value_parser}).second, "Provider option \"", name, "\" already has a value parser."); return *this; } + template + ProviderOptionsParser& AddValueParser( + const char* name, ValueParserType value_parser) { + return AddValueParser(std::string_view{name}, value_parser); + } + /** * Adds a parser for a particular provider option value which converts a * value to the right type and assigns it to the given reference. @@ -104,13 +116,25 @@ class ProviderOptionsParser { template ProviderOptionsParser& AddAssignmentToReference( const std::string& name, ValueType& dest) { + return AddAssignmentToReference(std::string_view{name}, dest); + } + + template + ProviderOptionsParser& AddAssignmentToReference( + std::string_view name, ValueType& dest) { return AddValueParser( name, - [&dest](const std::string& value_str) -> Status { + [&dest](std::string_view value_str) -> Status { return ParseStringWithClassicLocale(value_str, dest); }); } + template + ProviderOptionsParser& AddAssignmentToReference( + const char* name, ValueType& dest) { + return AddAssignmentToReference(std::string_view{name}, dest); + } + /** * Adds a parser for a particular provider option value which maps an * enumeration name to a value and assigns it to the given reference. @@ -128,6 +152,12 @@ class ProviderOptionsParser { template ProviderOptionsParser& AddAssignmentToEnumReference( const std::string& name, const EnumNameMapping& mapping, EnumType& dest) { + return AddAssignmentToEnumReference(std::string_view{name}, mapping, dest); + } + + template + ProviderOptionsParser& AddAssignmentToEnumReference( + std::string_view name, const EnumNameMapping& mapping, EnumType& dest) { return AddValueParser( name, [&mapping, &dest](const std::string& value_str) -> Status { @@ -135,6 +165,12 @@ class ProviderOptionsParser { }); } + template + ProviderOptionsParser& AddAssignmentToEnumReference( + const char* name, const EnumNameMapping& mapping, EnumType& dest) { + return AddAssignmentToEnumReference(std::string_view{name}, mapping, dest); + } + /** * Parses the given provider options. */ diff --git a/include/onnxruntime/core/framework/resource_accountant.h b/include/onnxruntime/core/framework/resource_accountant.h new file mode 100644 index 0000000000000..d28c5e45c99a2 --- /dev/null +++ b/include/onnxruntime/core/framework/resource_accountant.h @@ -0,0 +1,164 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include +#include +#include +#include +#include + +#include "core/common/common.h" +#include "core/common/inlined_containers_fwd.h" + +namespace onnxruntime { + +struct ConfigOptions; +#ifndef SHARED_PROVIDER +class Node; +#else +struct Node; +#endif + +// Common holder for potentially different resource accounting +// for different EPs +using ResourceCount = std::variant; + +// Type-erased arithmetic for ResourceCount values. +// Implementations use std::visit so the compiler enforces exhaustive handling +// of all variant members — adding a new type to ResourceCount will produce +// build errors at each call site that must be addressed. +// +// NOTE: These functions are NOT available through the provider bridge (shared library EPs). +// Budget enforcement for bridge-based EPs (e.g., in-tree CUDA EP) will be moved to the +// graph partitioner in a follow-up PR. +ResourceCount AddResourceCounts(const ResourceCount& a, const ResourceCount& b); +bool ResourceCountExceeds(const ResourceCount& a, const ResourceCount& b); +std::string FormatResourceCount(const ResourceCount& rc); + +/// +/// This class is used for graph partitioning by EPs +/// It stores the cumulative amount of the resource such as +/// memory that would be consumed by the graph nodes if it is assigned to the EP. +/// +/// It provides interfaces to add, remove and query the resource consumption. +/// +/// Each provider may assign its own meaning to the resource according to its constraints. +/// +class IResourceAccountant { + protected: + IResourceAccountant() = default; + IResourceAccountant(const ResourceCount& threshold) : threshold_(threshold) {} + + public: + virtual ~IResourceAccountant() = default; + virtual ResourceCount GetConsumedAmount() const = 0; + virtual void AddConsumedAmount(const ResourceCount& amount) = 0; + virtual void RemoveConsumedAmount(const ResourceCount& amount) = 0; + virtual ResourceCount ComputeResourceCount(const Node& node) = 0; + + std::optional GetThreshold() const { + return threshold_; + } + + void SetThreshold(const ResourceCount& threshold) { + threshold_ = threshold; + } + + void SetStopAssignment() noexcept { + stop_assignment_ = true; + } + + bool IsStopIssued() const noexcept { return stop_assignment_; } + + // Called before each GetCapability pass to reset per-pass state: + // clears the stop flag (which only applies to the pass that set it) + // and discards pending weight tracking from a previous (discarded) pass. + // Subclasses override ResetPendingWeightsImpl for EP-specific cleanup. + void ResetForNewPass() { + stop_assignment_ = false; + ResetPendingWeightsImpl(); + } + + // Called when a node's cost is committed (AccountForNode/AccountForAllNodes). + // Moves the node's pending weights into the committed set so they persist + // across GetCapability passes. Default no-op for stats-based accountants. + virtual void CommitWeightsForNode(size_t /*node_index*/) {} + + static std::string MakeUniqueNodeName(const Node& node); + + protected: + // Override to discard EP-specific pending weight tracking. + // Default no-op for stats-based accountants. + virtual void ResetPendingWeightsImpl() {} + + private: + bool stop_assignment_ = false; + std::optional threshold_; +}; + +// A map of Ep Type to a resource accountant for this EP +using ResourceAccountantMap = InlinedHashMap>; + +// This struct keeps accounting of the memory allocation stats +// for a kernel during runtime if enabled. +// Each metric describes max value seen as a result of inference run(s) +struct NodeAllocationStats { + // Total input sizes for the node + size_t input_sizes = 0; + // consumed initializer sizes + size_t initializers_sizes = 0; + // dynamically allocated outputs that actually occurred + // at inference time. (usually not fixed size and not pre-allocated) + size_t total_dynamic_sizes = 0; + // Temporary allocations that took place at this execution. + size_t total_temp_allocations = 0; + + NodeAllocationStats& operator+=(const NodeAllocationStats& other) { + input_sizes += other.input_sizes; + initializers_sizes += other.initializers_sizes; + total_dynamic_sizes += other.total_dynamic_sizes; + total_temp_allocations += other.total_temp_allocations; + return *this; + } + + void UpdateIfGreater(const NodeAllocationStats& other) { + input_sizes = std::max(input_sizes, other.input_sizes); + initializers_sizes = std::max(initializers_sizes, other.initializers_sizes); + total_dynamic_sizes = std::max(total_dynamic_sizes, other.total_dynamic_sizes); + total_temp_allocations = std::max(total_temp_allocations, other.total_temp_allocations); + } +}; + +class NodeStatsRecorder { + public: + explicit NodeStatsRecorder(const std::filesystem::path& stats_file_name); + ~NodeStatsRecorder(); + + ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(NodeStatsRecorder); + + const std::filesystem::path& GetNodeStatsFileName() const noexcept; + + bool ShouldAccountFor(const std::string& input_output_name) const; + + void ResetPerRunNameDeduper(); + + void ReportNodeStats(const std::string& node_name, const NodeAllocationStats& stats); + + void DumpStats(const std::filesystem::path& model_path) const; + + private: + void DumpStats(std::ostream& os) const; + + struct Impl; + std::unique_ptr impl_; +}; + +Status CreateAccountants( + const ConfigOptions& config_options, + const std::filesystem::path& model_path, + std::optional& acc_map); + +} // namespace onnxruntime diff --git a/include/onnxruntime/core/framework/run_options.h b/include/onnxruntime/core/framework/run_options.h index fab65e8fee692..54a0355537f8e 100644 --- a/include/onnxruntime/core/framework/run_options.h +++ b/include/onnxruntime/core/framework/run_options.h @@ -35,6 +35,14 @@ struct OrtRunOptions { // So it is possible that only some of the nodes are executed. bool only_execute_path_to_fetches = false; + // Set to 'true' to enable profiling for this run. + bool enable_profiling = false; + + // File prefix for profiling result for this run. + // The actual filename will be: _.json + // Only used when enable_profiling is true. + std::basic_string profile_file_prefix = ORT_TSTR("onnxruntime_run_profile"); + #ifdef ENABLE_TRAINING // Used by onnxruntime::training::TrainingSession. This class is now deprecated. // Delete training_mode when TrainingSession is deleted. @@ -43,13 +51,19 @@ struct OrtRunOptions { #endif // Stores the configurations for this run - // To add an configuration to this specific run, call OrtApis::AddRunConfigEntry + // To add a configuration value to this specific run, call OrtApis::AddRunConfigEntry + // To get a configuration value, call OrtApis::GetRunConfigEntry // The configuration keys and value formats are defined in // /include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h onnxruntime::ConfigOptions config_options; onnxruntime::InlinedVector active_adapters; + // Optional sync stream for external resource import. + // When set, the EP uses this stream for execution, enabling proper + // synchronization with imported external semaphores. + OrtSyncStream* sync_stream = nullptr; + OrtRunOptions() = default; ~OrtRunOptions() = default; }; diff --git a/include/onnxruntime/core/framework/sparse_tensor.h b/include/onnxruntime/core/framework/sparse_tensor.h index da10e3bc10307..4e9d5c41fbc76 100644 --- a/include/onnxruntime/core/framework/sparse_tensor.h +++ b/include/onnxruntime/core/framework/sparse_tensor.h @@ -93,7 +93,7 @@ class SparseTensor final { /// /// The factory function creates an instance of SparseTensor on the heap - /// using appropriate constructor and initializes OrtValue instance wit it. + /// using appropriate constructor and initializes OrtValue instance with it. /// /// element data type /// dense shape of the sparse tensor @@ -110,7 +110,7 @@ class SparseTensor final { /// /// The factory function creates an instance of SparseTensor on the heap - /// using appropriate constructor and initializes OrtValue instance wit it. + /// using appropriate constructor and initializes OrtValue instance with it. /// /// element data type /// dense shape of the sparse tensor diff --git a/include/onnxruntime/core/framework/stream_handles.h b/include/onnxruntime/core/framework/stream_handles.h index 01631e1fb2aa6..7d27c7471d71f 100644 --- a/include/onnxruntime/core/framework/stream_handles.h +++ b/include/onnxruntime/core/framework/stream_handles.h @@ -2,8 +2,11 @@ // Licensed under the MIT License. #pragma once +#include #include +#include #include + #include "core/framework/allocator.h" #include "core/framework/ortdevice.h" #include "core/common/status.h" @@ -20,131 +23,123 @@ namespace synchronize { class Notification; } -// a stream abstraction which hold an opaque handle, and a reference to which OrtDevice instance this stream belong to. -// it need to be OrtDevice instance as we might have different stream on different OrtDevice with same type. -// i.e. different cuda stream on different GPU. +/// +/// Class to represent a stream on the OrtDevice. +/// class Stream { public: - Stream(StreamHandle h, const OrtDevice& d) : handle_(h), device_(d) {} + Stream(StreamHandle h, const OrtDevice& d) + : handle_(h), device_(d) { + } virtual ~Stream() = default; + virtual std::unique_ptr CreateNotification(size_t /*num_consumers*/) { return {}; }; + // block the host thread until all the tasks in the stream finished. virtual void Flush() {}; + // The framework may reuse the stream instance for multiple iterations. // This is the API that provide a chance to let the device stream cleanup // resource at the end of a iteration. virtual Status CleanUpOnRunEnd() { return Status::OK(); }; + // Get the native stream handle. nullptr if the OrtDevice doesn't support streams. StreamHandle GetHandle() const { return handle_; } const OrtDevice& GetDevice() const { return device_; } - // We use the timestamp based vector clocks to optimize the resource sharing - // between different streams. - // Each stream maintain following data structure: - // 1. Current timestamp - // 2. A lookup table that for a given stream, what is its timestamp when the - // last synchronization happened with current stream. - // 3. When a notification is activated, it take a snapshot of current stream's - // lookup table. - // 4. When synchronization happened (current stream wait on a notification), - // update its lookup table with the table snapshot in notification. - // The memory reusing strategy is: - // A kernel in current stream is safe to reuse another stream's memory chunk - // as long as the reused chunk's timestamp is less than the last synchronized - // timestamp recorded in the lookup table. - - // Get the current timestamp - uint64_t GetCurrentTimestamp() const { return timestamp_; } - - // return the timestamp when the last synchronization happened between target stream and current stream. - // return 0 if no synchronization happened. - // if target_stream is nullptr, it means it is a sequence running on device doesn't support Stream (i.e. CPU) - // we can safely return 0 in that case to save a lookup. - uint64_t GetLastSyncTimestampWithTargetStream(Stream* target_stream) const { - if (!target_stream) - return 0; - auto it = other_stream_clock_.find(target_stream); - return it == other_stream_clock_.end() ? 0 : it->second; + // Get the current synchronization ID. + // The value is 0 until this stream records an event. + // The sync id is incremented before each new event that is recorded in our stream via Notification::Activate. + uint64_t GetSyncId() const { return sync_id_; } + + // Return the sync id from when the last synchronization happened between producer_stream and this stream. + // i.e. the id for the event that the producer stream recorded and we waited on + // + // Returns 0 if the streams have not previously been synchronized. + uint64_t GetSyncIdForLastWaitOnStream(const Stream& producer_stream) const { + auto it = producer_stream_sync_info_.find(&producer_stream); + return it == producer_stream_sync_info_.end() ? 0 : it->second; } - // make a copy of the current stream lookup table. - // this is used to create a snapshot of the stream lookup table in notification. - void CloneCurrentStreamSyncTable(std::unordered_map& output) const { - output.reserve(other_stream_clock_.size()); - output.insert(other_stream_clock_.begin(), other_stream_clock_.end()); - } + // Get the sync information that is added to a notification when it is activated. + // This contains sync ids for all streams we have waited on, and the new sync id for our stream. + std::unordered_map OnNotificationActivation() { + // copy our sync info so the notification can pass it on to any waiting streams + auto sync_info = producer_stream_sync_info_; + // and add our info to the copy, incrementing the sync_id + sync_info[this] = ++sync_id_; - // bump the current timestamp - // When a notification get activated, bump the snapshot in its owner. - // Stream is not shared across threads, BumpTimeStampAndReturn will only be invoked on the current thread - // where the stream is executed on, so there is no race condition. - uint64_t BumpTimeStampAndReturn() { - return ++timestamp_; + return sync_info; } - // update the stream lookup table with the snapshot saved in notification. - void UpdateStreamClock(const std::unordered_map& clock) { - for (const auto& kv : clock) { - auto ret = other_stream_clock_.insert(kv); - if (!ret.second) { - ret.first->second = std::max(ret.first->second, kv.second); - } - } - } + // Record information from a Notification we waited on. + // - copies the producer stream info from the notification. + void UpdateWithAwaitedNotification(const synchronize::Notification& notification); + // used in custom ops. doesn't really belong here. virtual void* GetResource(int /*version*/, int /*id*/) const { return nullptr; } - virtual WaitNotificationFn GetWaitNotificationFn() const { return nullptr; } - private: StreamHandle handle_; const OrtDevice& device_; - uint64_t timestamp_{0}; + + // current sync id. equivalent to a counter for the number of events we have recorded in the underlying stream. + // 0 == no events recorded. sync_id_ is updated prior to recording a new event. + std::atomic sync_id_{0}; + + // This is a map to track synchronization points between streams. When we wait on another stream (the producer) + // we add an entry to the map for that stream. + // The entry has the sync id from the producer stream for the event we waited on. + // // TODO: use inline container. // currently this class is header only, but abseil doesn't compile with nvcc // we need to add new symbol to provider_bridge and hide abseil from the header. - std::unordered_map other_stream_clock_{}; + std::unordered_map producer_stream_sync_info_{}; ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(Stream); }; namespace synchronize { -// An abstraction used for synchronization between streams. See its concrete subclass (CudaNotification, etc.) how the activate -// and wait works for a specific stream +// An abstraction used for synchronization between streams. +// See derived classes (CudaNotification, etc.) for implementation examples. class Notification { public: explicit Notification(Stream& s) : stream_(s) {} virtual ~Notification() = default; - // this api will perform three operations: - // 1. activate the notification on device, for example, record an event on GPU. - // 2. take a snapshot of the timestamp lookup table in current stream. - // 3. bump the timestamp for current stream. + // Activate the notification. This records an event in the Stream that created the Notification that other streams can wait on. void ActivateAndUpdate() { Activate(); - stream_.CloneCurrentStreamSyncTable(stream_clock_); - stream_clock_[&stream_] = stream_.BumpTimeStampAndReturn(); + + // copy the sync info. this includes an entry for stream_ with the next sync id. + stream_sync_info_ = stream_.OnNotificationActivation(); } - // return the timestamp lookup table saved in the notification. - const std::unordered_map& GetStreamSyncTable() { - return stream_clock_; + // Get the sync history for the producer stream that created this Notification. + // The notification must have be activated previously. + const std::unordered_map& GetStreamSyncInfo() const { + return stream_sync_info_; } protected: virtual void Activate() = 0; - // which stream create this notification. + + Stream& GetStream() { + return stream_; + } + + private: + // Stream that created the notification (producer stream). Stream& stream_; - // TODO: use inline container. - // currently this class is header only, but abseil doesn't compile with nvcc - // we need to add new symbol to provider_bridge and hide abseil from the header. - std::unordered_map stream_clock_{}; + + // This is a snapshot of the sync history for the stream that created the Notification. + std::unordered_map stream_sync_info_{}; }; } // namespace synchronize @@ -154,6 +149,12 @@ class Notification { // TODO: use a better way to dispatch handles. using CreateStreamFn = std::function(const OrtDevice&)>; +// This SetDevice function is used by TRT EP or CUDA EP to handle the case where ExecutionMode::ORT_PARALLEL is enabled. +// In that case, ORT retrieves a thread from the thread pool to run kernels for a given session. +// Since new threads default to using device 0, but the session may be tightly bound to a device > 0, +// This SetDevice function will be called in RunSince to ensure running kernels on a correct GPU device. +using SetDeviceFn = std::function; + // an interface of a simple registry which hold the handles EP registered. // make it interface so we can pass it through shared library based execution providers class IStreamCommandHandleRegistry { @@ -161,16 +162,34 @@ class IStreamCommandHandleRegistry { virtual ~IStreamCommandHandleRegistry() = default; // Wait is a little special as we need to consider the source stream the notification generated, and the stream we are waiting. // i.e., for an cuda event what notify the memory copy, it could be wait on a CPU stream, or on another cuda stream. - [[nodiscard]] virtual WaitNotificationFn GetWaitHandle(OrtDevice::DeviceType notification_ower_device_type, - OrtDevice::DeviceType executor_device_type) const = 0; - // Get the stream creation function registered on the given device type. + [[nodiscard]] virtual WaitNotificationFn GetWaitHandle(const OrtDevice& notification_owner_device, + const OrtDevice& executor_device) const = 0; + + // Get the stream creation function registered for the given device type. [[nodiscard]] virtual CreateStreamFn GetCreateStreamFn(OrtDevice::DeviceType execution_device_type) const = 0; - // register a wait methond which will be invoked when we wait a notification (created by 'notification_device_type' device) on a stream at 'device_type' device. + + // register a wait method which will be invoked to await a notification that is + // created by 'notification_device_type' device on a stream at 'device_type' device. virtual void RegisterWaitFn(OrtDevice::DeviceType notification_device_type, OrtDevice::DeviceType device_type, WaitNotificationFn fn) = 0; + // register a handle about how to create stream on given device type. virtual void RegisterCreateStreamFn(OrtDevice::DeviceType device_type, CreateStreamFn f) = 0; + + // Register a SetDevice function. + // This interface is currently used by TRT EP or CUDA EP only. + virtual void RegisterSetDeviceFn(OrtDevice::DeviceType device_type, SetDeviceFn f) { + ORT_UNUSED_PARAMETER(device_type); + ORT_UNUSED_PARAMETER(f); + }; + + // Get a SetDevice function. + // This interface is currently used by TRT EP or CUDA EP only and is called in RunSince from stream execution. + virtual std::optional GetSetDeviceFn(OrtDevice::DeviceType device_type) const { + ORT_UNUSED_PARAMETER(device_type); + return std::nullopt; + }; }; } // namespace onnxruntime diff --git a/include/onnxruntime/core/framework/tensor.h b/include/onnxruntime/core/framework/tensor.h index dd2603d214f63..bd87c49d39ea5 100644 --- a/include/onnxruntime/core/framework/tensor.h +++ b/include/onnxruntime/core/framework/tensor.h @@ -43,6 +43,16 @@ class Tensor final { // Strive not to allocate Tensor with new/delete as it is a shallow class and using it by value is just fine. // Use InitOrtValue() methods to allocate for OrtValue. +#ifdef BUILD_CUDA_EP_AS_PLUGIN + /// Static factory kept for plugin EP kernels that still call Tensor::Create(). + /// The main tree deprecated these in favor of constructors, but dynamically-linked + /// plugin code relies on the static method. + static std::unique_ptr Create(MLDataType elt_type, const TensorShape& shape, + std::shared_ptr allocator) { + return std::make_unique(elt_type, shape, std::move(allocator)); + } +#endif + Tensor() = default; // to allow creating vector to support seq(tensor) /** @@ -284,9 +294,9 @@ class Tensor final { /// /// The number of Tensor "storage" elements. A single storage element may contain multiple sub-elements for - /// sub-byte data types (e.g., int4). + /// sub-byte data types (e.g., int4/float4). /// - /// For element types smaller than 1 byte (e.g., int4), a single storage element stores multiple sub-byte elements. + /// For element types smaller than 1 byte (e.g., int4/float4), a single storage element stores multiple sub-byte elements. /// Example: Tensor of shape (4,) has 2 storage elements. /// /// For element types >= 1 byte, this function returns the product of the shape. diff --git a/include/onnxruntime/core/framework/to_tensor_proto_element_type.h b/include/onnxruntime/core/framework/to_tensor_proto_element_type.h index e9e28e4864a67..3aa183eb7a6a2 100644 --- a/include/onnxruntime/core/framework/to_tensor_proto_element_type.h +++ b/include/onnxruntime/core/framework/to_tensor_proto_element_type.h @@ -10,8 +10,10 @@ #include "core/graph/onnx_protobuf.h" #endif -#include "core/framework/float8.h" -#include "core/framework/float16.h" +#include "core/framework/float4.h" +#include "core/common/float8.h" +#include "core/common/float16.h" +#include "core/framework/int2.h" #include "core/framework/int4.h" namespace onnxruntime { @@ -96,8 +98,20 @@ template <> constexpr ONNX_NAMESPACE::TensorProto_DataType ToTensorProtoElementType() { return ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E5M2FNUZ; } +template <> +constexpr ONNX_NAMESPACE::TensorProto_DataType ToTensorProtoElementType() { + return ONNX_NAMESPACE::TensorProto_DataType_FLOAT8E8M0; +} + +#endif +#if !defined(DISABLE_FLOAT4_TYPES) +template <> +constexpr ONNX_NAMESPACE::TensorProto_DataType ToTensorProtoElementType() { + return ONNX_NAMESPACE::TensorProto_DataType_FLOAT4E2M1; +} #endif + template <> constexpr ONNX_NAMESPACE::TensorProto_DataType ToTensorProtoElementType() { return ONNX_NAMESPACE::TensorProto_DataType_INT4; @@ -107,5 +121,14 @@ constexpr ONNX_NAMESPACE::TensorProto_DataType ToTensorProtoElementType return ONNX_NAMESPACE::TensorProto_DataType_UINT4; } +template <> +constexpr ONNX_NAMESPACE::TensorProto_DataType ToTensorProtoElementType() { + return ONNX_NAMESPACE::TensorProto_DataType_INT2; +} +template <> +constexpr ONNX_NAMESPACE::TensorProto_DataType ToTensorProtoElementType() { + return ONNX_NAMESPACE::TensorProto_DataType_UINT2; +} + } // namespace utils } // namespace onnxruntime diff --git a/include/onnxruntime/core/graph/constants.h b/include/onnxruntime/core/graph/constants.h index f072badd199ba..e92569264082c 100644 --- a/include/onnxruntime/core/graph/constants.h +++ b/include/onnxruntime/core/graph/constants.h @@ -31,19 +31,19 @@ constexpr size_t kMaxExecutionProviderNameLen = 30; constexpr const char* kCpuExecutionProvider = "CPUExecutionProvider"; constexpr const char* kCudaExecutionProvider = "CUDAExecutionProvider"; +constexpr const char* kCudaPluginExecutionProvider = "CudaPluginExecutionProvider"; constexpr const char* kCudaNHWCExecutionProvider = "CUDANHWCExecutionProvider"; constexpr const char* kDnnlExecutionProvider = "DnnlExecutionProvider"; constexpr const char* kOpenVINOExecutionProvider = "OpenVINOExecutionProvider"; constexpr const char* kVitisAIExecutionProvider = "VitisAIExecutionProvider"; constexpr const char* kTensorrtExecutionProvider = "TensorrtExecutionProvider"; +constexpr const char* kNvTensorRTRTXExecutionProvider = "NvTensorRTRTXExecutionProvider"; constexpr const char* kNnapiExecutionProvider = "NnapiExecutionProvider"; constexpr const char* kQnnExecutionProvider = "QNNExecutionProvider"; constexpr const char* kRknpuExecutionProvider = "RknpuExecutionProvider"; constexpr const char* kDmlExecutionProvider = "DmlExecutionProvider"; constexpr const char* kMIGraphXExecutionProvider = "MIGraphXExecutionProvider"; constexpr const char* kAclExecutionProvider = "ACLExecutionProvider"; -constexpr const char* kArmNNExecutionProvider = "ArmNNExecutionProvider"; -constexpr const char* kRocmExecutionProvider = "ROCMExecutionProvider"; constexpr const char* kCoreMLExecutionProvider = "CoreMLExecutionProvider"; constexpr const char* kJsExecutionProvider = "JsExecutionProvider"; constexpr const char* kSnpeExecutionProvider = "SNPEExecutionProvider"; @@ -55,7 +55,4 @@ constexpr const char* kCannExecutionProvider = "CANNExecutionProvider"; constexpr const char* kAzureExecutionProvider = "AzureExecutionProvider"; constexpr const char* kVSINPUExecutionProvider = "VSINPUExecutionProvider"; -constexpr const char* kExecutionProviderSharedLibraryPath = "shared_lib_path"; -constexpr const char* kExecutionProviderSharedLibraryEntry = "provider_factory_entry_point"; - } // namespace onnxruntime diff --git a/include/onnxruntime/core/graph/graph.h b/include/onnxruntime/core/graph/graph.h index 7798394b045dc..92d9105530597 100644 --- a/include/onnxruntime/core/graph/graph.h +++ b/include/onnxruntime/core/graph/graph.h @@ -27,6 +27,7 @@ #include "core/common/span_utils.h" #include "core/common/status.h" #include "core/common/logging/logging.h" +#include "core/framework/ort_value.h" #include "core/framework/prepacked_weights_container.h" #include "core/graph/onnx_protobuf.h" #include "core/graph/basic_types.h" @@ -39,7 +40,11 @@ #include "core/graph/node_arg.h" #include "core/graph/ort_format_load_options.h" +// Type from Model Editor API in ORT C API so can't be in a namespace +struct OrtGraph; + namespace onnxruntime { +class ExternalDataInfo; class Graph; struct IndexedSubGraph; class Model; @@ -68,7 +73,10 @@ class Node { Fused = 1, ///< The node refers to a function. }; - explicit Node() = default; + // Constructor and destructor defined out-of-line in graph.cc so that Graph + // is a complete type when std::unique_ptr in subgraphs_ is destroyed + // (required by libc++). + explicit Node(); #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) || defined(ORT_MINIMAL_BUILD_CUSTOM_OPS) Node(std::string_view name, @@ -77,15 +85,10 @@ class Node { gsl::span input_args, gsl::span output_args, const NodeAttributes* attributes, - std::string_view domain) { - Init(name, op_type, description, - input_args, - output_args, - attributes, domain); - } + std::string_view domain); #endif - ~Node() = default; + ~Node(); /** @class EdgeEnd @@ -140,6 +143,14 @@ class Node { */ const std::string& Domain() const noexcept { return domain_; } + /** Gets the overload identifier for model-local function dispatch (IR version 10+). + * @remarks Empty string for non-overloaded operators. + */ + const std::string& Overload() const noexcept { return overload_; } + + /** Sets the overload identifier for model-local function dispatch. */ + void SetOverload(std::string_view overload) { overload_ = overload; } + /** Gets the path of the owning model if any. */ const std::filesystem::path& ModelPath() const noexcept; @@ -169,7 +180,14 @@ class Node { */ void SetSinceVersion(int since_version) noexcept { since_version_ = since_version; } + void SetLayeringAnnotation(std::string annotation) { layering_annotation_ = std::move(annotation); } + + const std::string& GetLayeringAnnotation() const noexcept { return layering_annotation_; } + + const Graph* GetContainingGraph() const noexcept { return graph_; } + #if !defined(ORT_MINIMAL_BUILD) + /** Gets the Node's OpSchema. @remarks The graph containing this node must be resolved, otherwise nullptr will be returned. */ const ONNX_NAMESPACE::OpSchema* Op() const noexcept { return op_; } @@ -251,6 +269,13 @@ class Node { #endif // !defined(ORT_MINIMAL_BUILD) #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) + + // Make sure that the annotation does not occupy memory after partitioning is done. + void ClearLayeringAnnotation() { + std::string t; + layering_annotation_.swap(t); + } + /** Gets a modifiable count of arguments for each of the Node's explicit inputs. @todo This should be removed in favor of a method that updates the input args and the count. Currently these operations are separate which is not a good setup. */ @@ -561,7 +586,14 @@ class Node { // NOTE: This friendship relationship should ONLY be used for calling methods of the Node class and not accessing // the data members directly, so that the Node can maintain its internal invariants. friend class Graph; - Node(NodeIndex index, Graph& graph) : index_(index), graph_(&graph), can_be_saved_(true) {} + Node(NodeIndex index, Graph& graph); + + protected: +#if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) + // internal only method to allow selected classes to directly alter the input/output definitions and arg counts + // made protected to facilitate testing + Definitions& MutableDefinitions() noexcept; +#endif private: ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(Node); @@ -584,9 +616,6 @@ class Node { #endif #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) - // internal only method to allow selected classes to directly alter the input/output definitions and arg counts - Definitions& MutableDefinitions() noexcept; - // internal only method to allow selected classes to directly alter the links between nodes. Relationships& MutableRelationships() noexcept; @@ -616,6 +645,9 @@ class Node { // OperatorSet domain of op_type_. std::string domain_; + // Overload identifier for model-local function dispatch (IR version 10+). + std::string overload_; + #if !defined(ORT_MINIMAL_BUILD) // OperatorSchema that <*this> node refers to. const ONNX_NAMESPACE::OpSchema* op_ = nullptr; @@ -676,6 +708,8 @@ class Node { // Graph instances for subgraphs that are owned by this Node std::vector> subgraphs_; + std::string layering_annotation_; + // Can be saved? The node cannot be saved anymore if removable attributes have been cleared. bool can_be_saved_; }; @@ -717,11 +751,12 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi /** Replaces the initializer tensor with the same name as the given initializer tensor. The replacement initializer tensor must have the same type and shape as the existing initializer tensor. + The new_initializer is expected to be either small or have external data reference stored in OrtValue. Note: This currently has linear time complexity. There is room for improvement but it would likely require changes to how initializer tensors are stored and tracked. */ - common::Status ReplaceInitializedTensor(ONNX_NAMESPACE::TensorProto new_initializer); + common::Status ReplaceInitializedTensor(const ONNX_NAMESPACE::TensorProto& new_initializer, const OrtValue& ort_value); #if !defined(DISABLE_EXTERNAL_INITIALIZERS) /** This function takes externally provided data for initializers with external data @@ -730,7 +765,7 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi common::Status InjectExternalInitializedTensors(const InlinedHashMap& external_initializers); /** This function takes externally provided files in memory for initializers with external - * data and replaces graph initializers with its content. + * data and replaces main graph initializers with its content. */ common::Status InjectExternalInitializersFromFilesInMemory( const InlinedHashMap>& external_initializer_files); @@ -741,6 +776,18 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) /** Add an initializer tensor to the Graph. */ void AddInitializedTensor(const ONNX_NAMESPACE::TensorProto& tensor_proto); + + /// + /// Add initializer to the Graph. This method takes a tensor proto that contains + /// a data pointer to ort_value. For small tensors (LT utils::kSmallTensorExternalDataThreshold), + /// the data would still be contained within tensor_proto, and + /// OrtValue would be unallocated in this case, and not added to ortvalue_initializers_. + /// + /// tensor proto with external data pointing to OrtValue. + /// value that contains the initializer tensor. This may + /// be unallocated for small tensors. + Status AddInitializedOrtValue(const ONNX_NAMESPACE::TensorProto& tensor_proto, + const OrtValue& ort_value_initializer); #endif /** Remove the initializer tensor with the provided name from the Graph. */ @@ -757,12 +804,44 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi bool IsSparseInitializer(const std::string& name) const; #endif +#if !defined(ORT_MINIMAL_BUILD) + /** Gets the frequency count of weight data types in this graph. */ + gsl::span GetWeightDataTypeFrequency() const noexcept { + return weight_data_type_freq_; + } +#endif + /** Gets an initializer tensor with the provided name. @param[out] value Set to the TensorProto* if the initializer is found, or nullptr if not. @returns True if found. */ bool GetInitializedTensor(const std::string& tensor_name, const ONNX_NAMESPACE::TensorProto*& value) const; + /** Populate `value` if an externally allocated OrtValue exists for an initializer with the given name. + */ + bool GetOrtValueInitializer(const std::string& name, OrtValue& value, bool check_outer_scope = false) const; + + /// + /// Loads an initializer with data in an external file into an OrtValue. Does NOT cache the OrtValue + /// in this Graph. + /// + /// The name of the initializer. + /// Output parameter set to the loaded OrtValue. Set to an existing OrtValue if + /// it is already loaded. + /// A status indicating an error or success. An error occurs if `name` is not an initializer + /// with external data. + Status LoadExternalInitializerAsOrtValue(const std::string& name, OrtValue& value) const; + + /// + /// Gets information (external filepath, file offset, num bytes) for an initializer with data in an external file. + /// + /// The initializer's name. + /// Output parameter set to the location information of the external data. + /// Set to true if parent graphs should be checked. + /// True if `name` refers to an initializer with data in an external file. Otherwise, returns false + bool GetExternalInitializerInfo(const std::string& name, std::unique_ptr& ext_info, + bool check_outer_scope = false) const; + /** Gets all the initializer tensors in this Graph. */ const InitializedTensorSet& GetAllInitializedTensors() const noexcept { return name_to_initial_tensor_; } @@ -772,6 +851,9 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi /** Returns true if an initializer value can be overridden by a graph input with the same name. */ bool CanOverrideInitializer() const noexcept { return ir_version_ >= 4; } + /** Returns the ONNX IR version for the model. */ + Version GetOnnxIRVersion() const noexcept { return ir_version_; } + /** returns the initializer's TensorProto if 'name' is an initializer, is constant and cannot be overridden at runtime. If the initializer is not found or is not constant, a nullptr is returned. @param check_outer_scope If true and the graph is a subgraph, @@ -787,6 +869,21 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi */ const ONNX_NAMESPACE::TensorProto* GetInitializer(const std::string& name, bool check_outer_scope) const; + /// + /// Returns the initializer's TensorProto if 'name' is an initializer (either constant or overridable). + /// If the initializer is not found, a nullptr is returned. Also returns, via output parameters, the + /// OrtValue that holds the actual data (if any) and a boolean that indicates if the initializer is constant. + /// + /// The initializer's name. + /// Output OrtValue that is populated if the initializer tensor proto has been configured + /// to use external data that points to an OrtValue. Is set to an unallocated OrtValue for + /// a tensor proto that holds the weight data (e.g., small initializers). + /// Output parameter set to true if the initializer is a constant. + /// Checks outer scope if set to true and the graph is a subgraph. + /// The initializer's TensorProto or nullptr. + const ONNX_NAMESPACE::TensorProto* GetInitializer(const std::string& name, OrtValue& value, + bool& is_constant, bool check_outer_scope = false) const; + /** Gets the Graph inputs excluding initializers. These are the required inputs to the Graph as the initializers can be optionally overridden via graph inputs. @remarks Contains no nullptr values. */ @@ -909,9 +1006,12 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi return const_cast(this)->GetNodeArg(name); } - // search this and up through any parent_graph_ instance for a NodeArg + // Searches for a NodeArg in the current graph and its parent graphs, and returns the corresponding mutable NodeArg NodeArg* GetNodeArgIncludingParentGraphs(const std::string& node_arg_name); + // Searches for a NodeArg in the current graph and its parent graphs, and returns the corresponding const NodeArg + const NodeArg* GetNodeArgIncludingParentGraphs(const std::string& node_arg_name) const; + /** Gets a mutable NodeArg by name. Creates a new NodeArg that is owned by this Graph if not found. @param name The NodeArg name. @param[in] p_arg_type Optional TypeProto to use if the NodeArg needs to be created. @@ -969,6 +1069,41 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi gsl::span output_args, NodeAttributes&& attributes, const std::string& domain = kOnnxDomain); + + /** Add a Node to this Graph, propagating the layering annotation from an existing node. + This is the preferred way to create new nodes in Level 1 (pre-partitioning) graph optimizers. + The new node automatically inherits the layering annotation from @p annotation_source, which + ensures correct layer-based partitioning when annotations are present. + @param name The Node name. Must be unique in this Graph. + @param op_type The operator type. e.g. ONNX operator name. + @param description Arbitrary description of the Node. + @param input_args The explicit inputs to this Node. + @param output_args The outputs from this Node. + @param annotation_source The node from which to inherit the layering annotation. + @param attributes Optional NodeAttributes to add. + @param domain The domain for the op_type. + @returns Reference to the new Node. + @remarks Use this overload in Level 1 optimizers that create nodes replacing or derived from + existing annotated nodes. See docs/Optimizer_Layering_Annotations.md for details. + */ + Node& AddNode(const std::string& name, + const std::string& op_type, + const std::string& description, + gsl::span input_args, + gsl::span output_args, + const Node& annotation_source, + const NodeAttributes* attributes = nullptr, + const std::string& domain = kOnnxDomain); + + Node& AddNode(const std::string& name, + const std::string& op_type, + const std::string& description, + gsl::span input_args, + gsl::span output_args, + const Node& annotation_source, + NodeAttributes&& attributes, + const std::string& domain = kOnnxDomain); + Node& AddNode(const std::string& name, const std::string& op_type, const std::string& description, @@ -982,16 +1117,59 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi attributes, domain); } + Node& AddNode(const std::string& name, + const std::string& op_type, + const std::string& description, + std::initializer_list input_args, + std::initializer_list output_args, + const Node& annotation_source, + const NodeAttributes* attributes = nullptr, + const std::string& domain = kOnnxDomain) { + return AddNode(name, op_type, description, + AsSpan(input_args), + AsSpan(output_args), + annotation_source, + attributes, domain); + } + + Node& AddNode(const std::string& name, + const std::string& op_type, + const std::string& description, + gsl::span input_args, + std::initializer_list output_args, + const NodeAttributes* attributes = nullptr, + const std::string& domain = kOnnxDomain) { + return AddNode(name, op_type, description, + input_args, + AsSpan(output_args), + attributes, domain); + } + Node& AddNode(const std::string& name, const std::string& op_type, const std::string& description, gsl::span input_args, std::initializer_list output_args, + const Node& annotation_source, const NodeAttributes* attributes = nullptr, const std::string& domain = kOnnxDomain) { return AddNode(name, op_type, description, input_args, AsSpan(output_args), + annotation_source, + attributes, domain); + } + + Node& AddNode(const std::string& name, + const std::string& op_type, + const std::string& description, + std::initializer_list input_args, + gsl::span output_args, + const NodeAttributes* attributes = nullptr, + const std::string& domain = kOnnxDomain) { + return AddNode(name, op_type, description, + AsSpan(input_args), + output_args, attributes, domain); } @@ -1000,11 +1178,13 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi const std::string& description, std::initializer_list input_args, gsl::span output_args, + const Node& annotation_source, const NodeAttributes* attributes = nullptr, const std::string& domain = kOnnxDomain) { return AddNode(name, op_type, description, AsSpan(input_args), output_args, + annotation_source, attributes, domain); } @@ -1152,8 +1332,19 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi #endif #if !defined(ORT_MINIMAL_BUILD) - /** Gets the GraphProto representation of this Graph. */ + /** Gets the GraphProto representation of this Graph only. + * This does not remove in-memory tags for graph initializers. + * Use ToGraphProto() const to get a GraphProto that can be serialized externally. + */ const ONNX_NAMESPACE::GraphProto& ToGraphProto(); + + /// + // This function recurses subgraphs and examines each initializer + // If initializer data points to in-memory location, it is inlined + // otherwise, the initializer is copied as is including any + // external data references. + /// + /// GraphProto ONNX_NAMESPACE::GraphProto ToGraphProto() const; /** Gets the GraphProto representation of this Graph @@ -1168,6 +1359,18 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi const std::filesystem::path& model_file_path, const ModelSavingOptions& model_saving_options) const; + /// + /// Serialize the Graph to a onnx::GraphProto. Caller provides a function that determines where each initializer + /// is stored (i.e., either in an external file or within the model). + /// + /// Function called for every initializer. + /// Opaque user state passed to the handle_initializer_func. + /// Output parameter set to the serialized onnx::GraphProto. + /// A status indicating success or an error. + common::Status ToGraphProtoWithCustomInitializerHandling(OrtGetInitializerLocationFunc handle_initializer_func, + void* state, + /*out*/ ONNX_NAMESPACE::GraphProto& graph_proto) const; + /** Gets the ISchemaRegistry instances being used with this Graph. */ IOnnxRuntimeOpSchemaCollectionPtr GetSchemaRegistry() const; @@ -1224,10 +1427,12 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi The Graph needs to be Resolve()d after this call. @param func_to_inline + @param parent_annotation. Annotation inherited from the parent node that is being inlined. @returns Status indicating success or providing an error message. */ - Status InlineFunctionProto(const ONNX_NAMESPACE::FunctionProto& func_to_inline); + Status InlineFunctionProto(const ONNX_NAMESPACE::FunctionProto& func_to_inline, + const std::string& parent_annotation); /** Mark a NodeArg name as coming from the outer scope when programmatically constructing a Graph that will be used as a GraphProto attribute in another Node. @@ -1363,6 +1568,24 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi return Resolve(default_options); } + /// + /// This function converts all the graph TensorProto initializers into OrtValues + /// and creates a in-memory external data reference for each OrtValue. + /// + /// + Status ConvertInitializersIntoOrtValues(); + + /** + * @brief This function examines the specified initializers in the graph and converts them inline + * if any has external data in memory. + * + * @param iterators Span of iterators pointing to the initializers and the order that should be processed + * @param output_graph_proto The GraphProto to be updated with the modified initializers + * @return Status Returns a Status object indicating success or any errors that occurred during conversion + */ + Status RegenerateInitializersAndReplaceInMemory(gsl::span iterators, + ONNX_NAMESPACE::GraphProto& output_graph_proto) const; + const std::unordered_set& GetOuterScopeNodeArgNames() const noexcept { return outer_scope_node_arg_names_; } @@ -1430,6 +1653,16 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi const OrtFormatLoadOptions& load_options, const logging::Logger& logger, std::unique_ptr& graph); + static Status LoadFromModelEditorApiModel(const OrtGraph& api_graph, + const Model& owning_model, + const std::unordered_map& domain_to_version, + IOnnxRuntimeOpSchemaCollectionPtr schema_registry, + bool strict_shape_type_inference, + const logging::Logger& logger, + std::unique_ptr& graph); + + Status UpdateUsingModelEditorApiModel(const OrtModel& api_model); + #if !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) const RuntimeOptimizationRecordContainer& RuntimeOptimizations() const { return runtime_optimizations_; @@ -1443,6 +1676,11 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi // compiled model during partitioning, leaving them unused in the ORT Graph. To allow the memory to be freed // we need to manually run the cleanup that would usually happen as part of Graph::Resolve. Status RemovedUnusedInitializersOrtFormat(); + + // This examines all the nodes and removes any annotations that are only used for layering. + // This potentially saves memory. + Status RemoveAllLayeringAnnotations(); + #endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) // This friendship relationship should only be used to call Graph::Graph and @@ -1490,6 +1728,8 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(Graph); private: + int32_t weight_data_type_freq_[ONNX_NAMESPACE::TensorProto_DataType_DataType_ARRAYSIZE] = {0}; + void InitializeStateFromModelFileGraphProto(); // Add node with specified . @@ -1503,6 +1743,19 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi Status AddConstantProtoAsInitializer(const ONNX_NAMESPACE::NodeProto& constant_node_proto, std::optional new_name); + /// + /// This function is used by ToGraphProto() to ensure in-memory external data references + /// don't leak externally since they are non-standard. + /// + /// It is used when GraphSynchronizationNeeded() is false: GraphProto is simply copied + /// from graph_proto_ by ToGraphProto(). This copy includes both main graph + /// and subgraph initializers. This function examines all initializers + /// and inlines any in-memory data references. + /// + /// The GraphProto to process + /// Status indicating success or failure + Status ProcessSubgraphsInMemoryData(ONNX_NAMESPACE::GraphProto& output_graph_proto) const; + /// /// This function traverses the graph bottom up and externalizes /// constant initializers along with their pre-packed blobs from different @@ -1528,6 +1781,9 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi std::ostream& external_stream, int64_t& external_offset) const; + Status ToGraphProtoWithCustomInitializerHandlingImpl(OrtGetInitializerLocationFunc handle_initializer_func, + void* state, + /*out*/ ONNX_NAMESPACE::GraphProto& output_graph_proto) const; #endif Version IrVersion() const noexcept { @@ -1589,7 +1845,8 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi #if !defined(ORT_MINIMAL_BUILD) // Build and verify node connection (edges). // Verify NodeArg name/type/shape matching correctly. - common::Status BuildConnections(std::unordered_set& outer_scope_node_args_consumed); + common::Status BuildConnections(std::unordered_set& outer_scope_node_args_consumed, + bool& removed_node_with_subgraph); common::Status VerifyNoDuplicateName(); @@ -1609,6 +1866,15 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi std::vector& output_types, const Graph::ResolveOptions& options); + // If ONNX operator's PartialDataPropagationFunction() infers concrete shape values in the output + // save them to the output NodeArg as a TensorShapeProto or a scalar value so that downstream (consumer) nodes + // can use them later for their TypeAndShapeInferenceFunction() and PartialDataPropagationFunction(). + common::Status SaveShapeValuesFromDataPropagation(const Node& node, NodeArg& output_def, + const ONNX_NAMESPACE::TypeProto& propagated_value_as_type_proto) const; + + // Remove intermediate inferred shape values stored in all NodeArgs to reduce memory usage. + common::Status CleanUpShapeValuesFromDataPropagation(); + // Apply type-inference and type-checking to all inputs and initializers: common::Status TypeCheckInputsAndInitializers(); @@ -1627,10 +1893,19 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi // so they can be used to resolve outer scope dependencies when running BuildConnections for the subgraphs. common::Status SetOuterScopeNodeArgs(const std::unordered_set& outer_scope_node_args); - // Implementation for initializer replacement - Status ReplaceInitializedTensorImpl(ONNX_NAMESPACE::TensorProto new_initializer, bool is_external); - - std::vector CreateNodeArgs(const google::protobuf::RepeatedPtrField& names, + /// + /// Replace initializer with new_initializer. + /// + /// + /// ort_value with data, may be empty + /// This is true when we replace the initializer with external data + /// with OrtValue from the customer, in which case we enforce that the original initializer must have external data + /// + Status ReplaceInitializedTensorImpl(ONNX_NAMESPACE::TensorProto new_initializer, + OrtValue ort_value, bool must_replace_external); + + template // range-initializer returning std::string + std::vector CreateNodeArgs(const StringRange& names, const ArgNameToTypeMap& name_to_type_map); void ToGraphProtoInternal(ONNX_NAMESPACE::GraphProto& graph_proto) const; @@ -1694,6 +1969,8 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi return nodes_[node_index].get(); } + Status LoadFromModelEditorApiModel(const OrtGraph& api_graph, bool updating_existing_graph = false); + const Model& owning_model_; // GraphProto to store name, version, initializer. @@ -1708,6 +1985,12 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi InitializedTensorSet name_to_initial_tensor_; + // Initializers that are external to the Graph. + // e.g. created from existing memory using CreateTensorWithDataAndDeleterAsOrtValue in the ORT API. + // As we need to convert to TensorProto for the optimizers to work and keep the deleter information we store them + // in the Graph instance and retrieve during session state finalization. + std::unordered_map ortvalue_initializers_; + std::unordered_set, std::hash, std::equal_to> sparse_tensor_names_; @@ -1744,6 +2027,7 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi // in some case, a fused sub-graph will happens multiple times in one model, we use a map // to store reusable-schema in lookup. InlinedHashMap> reusable_fused_schema_map_; + #endif // !defined(ORT_MINIMAL_BUILD) // Graph nodes. @@ -1806,7 +2090,7 @@ class Graph { // NOLINT(clang-analyzer-optin.performance.Padding): preserve exi std::unordered_map> node_arg_to_consumer_nodes_; #endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) - const std::unordered_map domain_to_version_; + std::unordered_map domain_to_version_; // Model IR version. Version ir_version_{ONNX_NAMESPACE::Version::IR_VERSION}; diff --git a/include/onnxruntime/core/graph/graph_viewer.h b/include/onnxruntime/core/graph/graph_viewer.h index 9385e2f092e58..73ec34fd45f02 100644 --- a/include/onnxruntime/core/graph/graph_viewer.h +++ b/include/onnxruntime/core/graph/graph_viewer.h @@ -57,6 +57,11 @@ class GraphViewer { /** Returns true if an initializer value can be overridden by a graph input with the same name. */ bool CanOverrideInitializer() const noexcept; + /** Returns the ONNX IR version for the model. */ + Version GetOnnxIRVersion() const noexcept { + return graph_->GetOnnxIRVersion(); + } + /** Gets the Graph inputs, excluding initializers. @returns Collection of NodeArg pointers for the graph inputs, excluding inputs that have matching initializers. @@ -193,6 +198,12 @@ class GraphViewer { IOnnxRuntimeOpSchemaCollectionPtr GetSchemaRegistry() const { return graph_->GetSchemaRegistry(); } #endif + /** Populate `value` if an externally allocated OrtValue exists for an initializer with the given name. + */ + bool GetOrtValueInitializer(const std::string& name, OrtValue& value) const { + return graph_->GetOrtValueInitializer(name, value); + } + private: ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(GraphViewer); GraphViewer(const Graph& graph, const IndexedSubGraph* filter_info); diff --git a/include/onnxruntime/core/graph/indexed_sub_graph.h b/include/onnxruntime/core/graph/indexed_sub_graph.h index c57db41254159..54e878761ba87 100644 --- a/include/onnxruntime/core/graph/indexed_sub_graph.h +++ b/include/onnxruntime/core/graph/indexed_sub_graph.h @@ -7,6 +7,8 @@ #include #include +#include "core/common/inlined_containers_fwd.h" +#include "core/framework/resource_accountant.h" #include "core/graph/basic_types.h" #include "core/graph/onnx_protobuf.h" @@ -29,7 +31,7 @@ struct IndexedSubGraph { std::string domain; ///< Domain of customized SubGraph/FunctionProto int since_version; ///< Since version of customized SubGraph/FunctionProto. - ONNX_NAMESPACE::OperatorStatus status; ///< Status of customized SubGraph/FunctionProto. + ONNX_NAMESPACE::OperatorStatus status{ONNX_NAMESPACE::OperatorStatus::STABLE}; ///< Status of customized SubGraph/FunctionProto. std::vector inputs; ///< Inputs of customized SubGraph/FunctionProto. std::vector outputs; ///< Outputs of customized SubGraph/FunctionProto. @@ -70,9 +72,65 @@ struct IndexedSubGraph { return meta_def_.get(); } + /** Gets the mutable meta definition needed to represent this subgraph as a FunctionProto. + @returns MetaDef instance if it has been set. nullptr if not. */ + MetaDef* GetMutableMetaDef() { + return meta_def_.get(); + } + + // Check if the accounting is enabled for the current EP + bool IsAccountingEnabled() const { + return resource_accountant != nullptr && + nodes_costs.size() == nodes.size(); + } + + // Should call IsAccountingEnabled() first + // Takes the previously computed ResourceCount for the node + // (usually during GetCapability()) + // if present and adds it to the consumed amount + void AccountForNode(size_t cost_index) const { + assert(cost_index < nodes_costs.size()); + resource_accountant->AddConsumedAmount(nodes_costs[cost_index]); + resource_accountant->CommitWeightsForNode(nodes[cost_index]); + } + + // Accounts for all constituent nodes by summing their pre-stored costs. + // Use this when fusing nodes into a single node so the total cost + // reflects what was computed during GetCapability() (with correct + // cross-node weight deduplication already applied). + void AccountForAllNodes() const { + assert(resource_accountant != nullptr); + for (size_t i = 0; i < nodes_costs.size(); ++i) { + resource_accountant->AddConsumedAmount(nodes_costs[i]); + resource_accountant->CommitWeightsForNode(nodes[i]); + } + } + + // Accounts for a node given its index and a pre-computed resource cost. + // Use this when the cost was computed externally (e.g. for a fused node). + void AccountForNode(NodeIndex node_index, const ResourceCount& resource_count) const { + assert(resource_accountant != nullptr); + resource_accountant->AddConsumedAmount(resource_count); + resource_accountant->CommitWeightsForNode(node_index); + } + + void SetAccountant(IResourceAccountant* res_accountant) { + resource_accountant = res_accountant; + } + + // Append resource count to the list of costs for the nodes. + void AppendNodeCost(const ResourceCount& cost) { + assert(resource_accountant != nullptr); + nodes_costs.emplace_back(cost); + } + private: // subgraph meta definition. std::unique_ptr meta_def_; + // Optional resource accountant for this subgraph. + IResourceAccountant* resource_accountant = nullptr; + // Vector with resource costs for nodes above. Should have the same size + InlinedVector nodes_costs; }; } // namespace onnxruntime diff --git a/include/onnxruntime/core/graph/model_saving_options.h b/include/onnxruntime/core/graph/model_saving_options.h index 924799f15b247..06c1b1ac6475f 100644 --- a/include/onnxruntime/core/graph/model_saving_options.h +++ b/include/onnxruntime/core/graph/model_saving_options.h @@ -9,36 +9,33 @@ class PrepackedWeightsForGraph; // These options affect how the model initializers are written to the external file. // This includes options to align external initializer offset. -// For models running on CPU, ORT will try to use mmap to load external -// initializers. To use mmap, external initializer need to be offset aligned. +// ORT will try to use mmap to load external initializers. +// // ORT saves external initializers into single data file, each initializer is // accessed with offset(start position of initializer) and length(byte length of -// initializer) of the data file. To use mmap, each offset need to be aligned -// which means offset need to divisible by allocation granularity(64KB for -// windows and 4K for other OSes). With align_offset to true, ORT will align -// offset for large initializer when save ONNX model with external data file. +// initializer) of the data file. With align_offset to true, ORT will align +// offset for large initializer (larger than align_threshold) +// when save ONNX model with external data file. It will align then to +// on_disk_alignment value. struct ModelSavingOptions { explicit ModelSavingOptions(size_t size_threshold) : initializer_size_threshold(size_threshold) {} - // Mimimal initializer size in bytes to be externalized on disk + // Minimal initializer size in bytes to be externalized on disk size_t initializer_size_threshold; - // Offset will always be page aligned and allocation granularity aligned for - // mmap support. This is done by padding previous tensor data with zeros - // keeping same length. + // Offset will always be aligned for mmap support. + // This is done by padding previous tensor data with zeros keeping same length. bool align_offset = false; // Alignment threshold for size of data. // Having a low threshold will waste file space for small initializers. // Only when tensor's data size is > the page_align_threshold it will be force // aligned. Default to 1MB. int64_t align_threshold = 1048576; - // The allocation Granularity for mmap() support. - // Typically 64KB for Windows & 4KB for other OSes. Default to 64KB. -#ifdef _WIN32 - int64_t allocation_granularity = 65536; -#else - int64_t allocation_granularity = 4096; -#endif + // Alignment factor for big tensors (bigger than align_threshold). Defaults to 4K. + int64_t on_disk_alignment = 4096; + // Force embed all external initializer into the Onnx file + // Used for EPContext model generation while some nodes fallback on CPU which has external data dependency + bool force_embed_external_ini = false; }; } // namespace onnxruntime diff --git a/include/onnxruntime/core/graph/node_arg.h b/include/onnxruntime/core/graph/node_arg.h index 0ddf1a2b9d3de..4a18d7617ac13 100644 --- a/include/onnxruntime/core/graph/node_arg.h +++ b/include/onnxruntime/core/graph/node_arg.h @@ -9,6 +9,8 @@ #include "core/common/status.h" #include "core/common/logging/logging.h" +#include + namespace onnxruntime { // Node argument definition, for both input and output, @@ -107,6 +109,18 @@ class NodeArg { /** Gets this NodeArg as a NodeArgInfo, AKA ValueInfoProto. */ const NodeArgInfo& ToProto() const noexcept { return node_arg_info_; } + /** Gets the inferred shape values as a TensorShapeProto. */ + const std::optional& GetInferredShapeValues() const noexcept { return inferred_shape_values_; } + + /** Gets mutable inferred shape values as a TensorShapeProto. */ + std::optional& GetMutableInferredShapeValues() noexcept { return inferred_shape_values_; } + + /** Gets the inferred shape scalar value */ + const std::optional GetInferredShapeScalarValue() const noexcept { return inferred_scalar_value_; } + + /** Sets the inferred shape scalar value */ + void SetInferredShapeScalarValue(int64_t value) noexcept { inferred_scalar_value_ = value; } + /** Gets a flag indicating whether this NodeArg exists or not. Optional inputs are allowed in ONNX and an empty #Name represents a non-existent input argument. */ bool Exists() const noexcept; @@ -128,6 +142,24 @@ class NodeArg { // Node arg name, type and shape. NodeArgInfo node_arg_info_; + // This variable stores the actual tensor data of the shape as a TensorShapeProto after executing + // the ONNX operator's PartialDataPropagationFunction(). It's used for shape inference purpose. + // + // Calling an operator's TypeAndShapeInferenceFunction() alone is sometimes insufficient + // for complete shape inference. For example, the Shape operator's TypeAndShapeInferenceFunction() + // only provides the output's rank which is 1 but not its actual shape values. + // + // The PartialDataPropagationFunction(), defined in the ONNX operator schema, must also + // be executed to obtain the concrete shape values output, allowing accurate propagation + // of shape information throughout the graph. If the concrete shape values output is not + // computed, nothing is stored here that's why this is optional. + std::optional inferred_shape_values_; + + // This variable stores the actual scalar value. + // It is also used for shape inference and data propagation to ensure consistent shape and + // value information throughout the graph. + std::optional inferred_scalar_value_; + // Flag indicates whether <*this> node arg exists or not. bool exists_; }; diff --git a/include/onnxruntime/core/optimizer/graph_transformer_level.h b/include/onnxruntime/core/optimizer/graph_transformer_level.h index 111f38f9ccb6e..3f2126ce494a6 100644 --- a/include/onnxruntime/core/optimizer/graph_transformer_level.h +++ b/include/onnxruntime/core/optimizer/graph_transformer_level.h @@ -12,8 +12,9 @@ enum class TransformerLevel : int { Level1, // basic optimizations Level2, // extended optimizations Level3, // layout optimizations + Level4, // unsupported datatypes optimizations // The max level should always be same as the last level. - MaxLevel = Level3 + MaxLevel = Level4 }; } // namespace onnxruntime diff --git a/include/onnxruntime/core/optimizer/graph_transformer_utils.h b/include/onnxruntime/core/optimizer/graph_transformer_utils.h index 31b0f22340510..7535b704cd4f0 100644 --- a/include/onnxruntime/core/optimizer/graph_transformer_utils.h +++ b/include/onnxruntime/core/optimizer/graph_transformer_utils.h @@ -36,7 +36,8 @@ namespace optimizer_utils { TODO: This is visible for testing at the moment, but we should rather make it private. */ InlinedVector> GenerateRewriteRules( TransformerLevel level, - const InlinedHashSet& rules_to_disable = {}); + const InlinedHashSet& rules_to_disable = {}, + const bool enable_cast_chain_elimination = false); /** Given a TransformerLevel, this method generates a name for the rule-based graph transformer of that level. */ std::string GenerateRuleBasedTransformerName(TransformerLevel level); @@ -45,7 +46,8 @@ std::string GenerateRuleBasedTransformerName(TransformerLevel level); std::unique_ptr GenerateRuleBasedGraphTransformer( TransformerLevel level, const InlinedHashSet& rules_to_disable, - const InlinedHashSet& compatible_execution_providers); + const InlinedHashSet& compatible_execution_providers, + const bool enable_cast_chain_elimination = false); /** Generates all predefined (both rule-based and non-rule-based) transformers for this level. Any transformers or rewrite rules named in rules_and_transformers_to_disable will be excluded. */ @@ -55,8 +57,7 @@ InlinedVector> GenerateTransformers( const IExecutionProvider& execution_provider /*required by constant folding*/, const logging::Logger& logger, const InlinedHashSet& rules_and_transformers_to_disable = {}, - concurrency::ThreadPool* intra_op_thread_pool = nullptr, - std::unordered_map>* p_buffered_tensors = nullptr); + concurrency::ThreadPool* intra_op_thread_pool = nullptr); #endif // !defined(ORT_MINIMAL_BUILD) @@ -87,8 +88,7 @@ InlinedVector> GenerateTransformersForMinimalB const IExecutionProvider& cpu_execution_provider, const logging::Logger& logger, const InlinedHashSet& rules_and_transformers_to_disable = {}, - concurrency::ThreadPool* intra_op_thread_pool = nullptr, - std::unordered_map>* p_buffered_tensors = nullptr); + concurrency::ThreadPool* intra_op_thread_pool = nullptr); #endif // !defined(ORT_MINIMAL_BUILD) || defined(ORT_EXTENDED_MINIMAL_BUILD) diff --git a/include/onnxruntime/core/platform/EigenNonBlockingThreadPool.h b/include/onnxruntime/core/platform/EigenNonBlockingThreadPool.h index 26fc440f7bfc5..6416c83ae45e2 100644 --- a/include/onnxruntime/core/platform/EigenNonBlockingThreadPool.h +++ b/include/onnxruntime/core/platform/EigenNonBlockingThreadPool.h @@ -9,8 +9,6 @@ /* Modifications Copyright (c) Microsoft. */ -#include - #pragma once #include "onnxruntime_config.h" // build/external/eigen/unsupported/Eigen/CXX11/src/Tensor/TensorEvaluator.h:162:71: @@ -39,6 +37,7 @@ #pragma warning(disable : 4127) #pragma warning(disable : 4805) #endif +#include #include #include "unsupported/Eigen/CXX11/ThreadPool" @@ -52,6 +51,13 @@ #include "core/common/spin_pause.h" #include "core/platform/ort_spin_lock.h" #include "core/platform/Barrier.h" +#include "core/platform/threadpool_config.h" +#include "core/session/onnxruntime_c_api.h" + +// Forward declaration for callback policy types +namespace onnxruntime { +struct ThreadOptions; +} // namespace onnxruntime // ORT thread pool overview // ------------------------ @@ -256,7 +262,7 @@ class ThreadPoolProfiler { void LogCoreAndBlock(std::ptrdiff_t block_size); // called in main thread to log core and block size for task breakdown void LogThreadId(int thread_idx); // called in child thread to log its id void LogRun(int thread_idx); // called in child thread to log num of run - std::string DumpChildThreadStat(); // return all child statitics collected so far + std::string DumpChildThreadStat(); // return all child statistics collected so far private: static const char* GetEventName(ThreadPoolEvent); @@ -338,6 +344,8 @@ class ExtendedThreadPoolInterface : public Eigen::ThreadPoolInterface { unsigned n, std::ptrdiff_t block_size) = 0; virtual void StartProfiling() = 0; virtual std::string StopProfiling() = 0; + virtual void EnableSpinning() = 0; + virtual void DisableSpinning() = 0; }; class ThreadPoolParallelSection { @@ -404,9 +412,92 @@ class ThreadPoolLoop { ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(ThreadPoolLoop); }; -template +// Callback policy that does not invoke callbacks. Work = std::function. +// All methods are trivial no-ops; the compiler eliminates them entirely. +struct WorkNoCallbackPolicy { + using Task = std::function; + using Work = Task; + + explicit WorkNoCallbackPolicy(const onnxruntime::ThreadOptions&) {} + + Work MakeWork(Task fn) const { return fn; } + + void Execute(const Work& w) const { w(); } + + void OnAbandon(const Work&) const noexcept {} +}; + +#ifdef ORT_ENABLE_SESSION_THREADPOOL_CALLBACKS +// Callback-aware policy that invokes user-supplied callbacks around work items. +// Work = WorkItem, a struct bundling a task with opaque callback data. +struct WorkWithCallbackPolicy { + using Task = std::function; + + struct WorkItem { + Task task_; + void* enqueue_data_ = nullptr; + + explicit WorkItem(Task t = {}, void* data = nullptr) : task_(std::move(t)), enqueue_data_(data) {} + + explicit operator bool() const { return static_cast(task_); } + }; + + using Work = WorkItem; + + explicit WorkWithCallbackPolicy(const onnxruntime::ThreadOptions& opts) { + if (opts.work_callbacks) { + callbacks_ = *opts.work_callbacks; + } + } + + Work MakeWork(Task fn) const { + return Work(std::move(fn), OnEnqueue()); + } + + void Execute(const Work& w) const { + void* data = w.enqueue_data_; + if (callbacks_.on_start_work) { + callbacks_.on_start_work(callbacks_.user_context, data); + } + ORT_TRY { + w.task_(); + } + ORT_CATCH(...) { + if (callbacks_.on_stop_work) { + callbacks_.on_stop_work(callbacks_.user_context, data); + } + ORT_RETHROW; + } + if (callbacks_.on_stop_work) { + callbacks_.on_stop_work(callbacks_.user_context, data); + } + } + + void OnAbandon(const Work& w) const noexcept { + if (callbacks_.on_abandon) { + callbacks_.on_abandon(callbacks_.user_context, w.enqueue_data_); + } + } + + private: + void* OnEnqueue() const noexcept { + if (callbacks_.on_enqueue) { + return callbacks_.on_enqueue(callbacks_.user_context); + } + return nullptr; + } + + OrtThreadPoolCallbacksConfig callbacks_{}; +}; +#endif // ORT_ENABLE_SESSION_THREADPOOL_CALLBACKS + +template class RunQueue { public: + using Work = typename CallbackPolicy::Work; + + void SetPolicy(CallbackPolicy* p) { policy_ = p; } + RunQueue() : front_(0), back_(0) { // require power-of-two for fast masking assert((kSize & (kSize - 1)) == 0); @@ -479,7 +570,7 @@ class RunQueue { // subsequent call to RevokeWithTag to remove the item from the queue in combination // with w_idx. Typically the tag will be a per-thread ID to distinguish work // submitted from different threads. - PushResult PushBackWithTag(Work w, Tag tag, unsigned& w_idx) { + PushResult PushBackWithTag(Work& w, Tag tag, unsigned& w_idx) { #ifdef USE_LOCK_FREE_QUEUE std::lock_guard mtx(spin_lock_); #else @@ -548,6 +639,9 @@ class RunQueue { // Return true iff the item is successfully revoked. If the item is not revoked then // the caller must assume that it may still execute, for instance because it // has been pop'd from the queue concurrent with the revocation request. + // + // On successful revocation the queue calls the policy's OnAbandon callback + // to free any resources associated with the work item. bool RevokeWithTag(Tag tag, unsigned w_idx) { bool revoked = false; @@ -568,6 +662,7 @@ class RunQueue { if (e.tag == tag) { unsigned back = back_.load(std::memory_order_relaxed); unsigned back_idx = back & kMask; + policy_->OnAbandon(e.w); if (back_idx != w_idx) { // Item is not at the back of the queue, mark it in-place as revoked e.tag = Tag(); @@ -627,6 +722,8 @@ class RunQueue { Work w; }; + CallbackPolicy* policy_ = nullptr; + #ifdef USE_LOCK_FREE_QUEUE OrtSpinLock spin_lock_; #else @@ -694,7 +791,7 @@ class RunQueue { static std::atomic next_tag{1}; -template +template class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInterface { private: struct PerThread; @@ -739,7 +836,7 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter // Allocate a new tag to use to identify work items from a given // thread in a parallel section. Ideally, threads will have // unique tags, but re-use is not incorrect if the counter wraps - // (for intsance, if a long-running workload is calling into ORT + // (for instance, if a long-running workload is calling into ORT // from a fresh thread for each request). We must not re-use the // default tag 0 which is used to identify work items added via // Schedule as opposed to requests for help in parallel sections. @@ -764,15 +861,22 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter }; typedef std::function Task; - typedef RunQueue Queue; - ThreadPoolTempl(const CHAR_TYPE* name, int num_threads, bool allow_spinning, Environment& env, - const ThreadOptions& thread_options) + using Work = typename CallbackPolicy::Work; + + typedef RunQueue Queue; + + ThreadPoolTempl(const CHAR_TYPE* name, int num_threads, int spin_duration_us, + unsigned int spin_backoff_max, + Environment& env, const ThreadOptions& thread_options) : profiler_(num_threads, name), env_(env), num_threads_(num_threads), - allow_spinning_(allow_spinning), + spin_backoff_max_(NormalizeBackoff(spin_backoff_max)), + spin_count_(ScaleSpinCountForBackoff(ComputeSpinCount(spin_duration_us), spin_backoff_max_)), + steal_interval_(std::max(spin_count_ / 100, 1)), set_denormal_as_zero_(thread_options.set_denormal_as_zero), + callback_policy_(thread_options), worker_data_(num_threads), all_coprimes_(num_threads), blocked_(0), @@ -795,6 +899,7 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter ORT_TRY { worker_data_.resize(num_threads_); for (auto i = 0u; i < num_threads_; i++) { + worker_data_[i].queue.SetPolicy(&callback_policy_); worker_data_[i].thread.reset(env_.CreateThread(name, i, WorkerLoop, this, thread_options)); } } @@ -816,17 +921,19 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter // reject work if the queue of pending work is full. void Schedule(std::function fn) override { + Work work_item = callback_policy_.MakeWork(std::move(fn)); + PerThread* pt = GetPerThread(); int q_idx = Rand(&pt->rand) % num_threads_; WorkerData& td = worker_data_[q_idx]; Queue& q = td.queue; - fn = q.PushBack(std::move(fn)); - if (!fn) { + work_item = q.PushBack(std::move(work_item)); + if (!work_item) { // The queue accepted the work; ensure that the thread will pick it up td.EnsureAwake(); } else { // Run the work directly if the queue rejected the work - fn(); + callback_policy_.Execute(work_item); } } @@ -912,7 +1019,7 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter } } - // Now we know that dispatch is finshed, we synchronize with the + // Now we know that dispatch is finished, we synchronize with the // tasks that were created (if any) for the parallel section. We // revoke tasks still in queues, and then wait for any that are // still running. @@ -1004,7 +1111,7 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter // * First, suppose that a single job is running a series of loops. // Its main thread enters a parallel loop. Initially, let's assume // its preferred worker array is [_,0,1,2], writing "_" for the - // unusued element for the par_idx=0 work that the main thread will + // unused element for the par_idx=0 work that the main thread will // run. // // The main thread schedules the dispatcher task onto worker 0. @@ -1098,15 +1205,14 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter Queue& q = td.queue; unsigned w_idx; - // Attempt to enqueue the task - auto push_status = q.PushBackWithTag([worker_fn, par_idx, &preferred_workers, &ps, this]() { - // Record the worker thread that actually runs this task. - // This will form the preferred worker for the next loop. + Work work_item = callback_policy_.MakeWork([worker_fn, par_idx, &preferred_workers, &ps, this]() { UpdatePreferredWorker(preferred_workers, par_idx); worker_fn(par_idx); ps.tasks_finished++; - }, - pt.tag, w_idx); + }); + + // Attempt to enqueue the task + auto push_status = q.PushBackWithTag(work_item, pt.tag, w_idx); // Queue accepted the task; wake the thread that owns the queue. // In addition, if the queue was non-empty, attempt to wake @@ -1117,6 +1223,8 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter if (push_status == PushResult::ACCEPTED_BUSY) { worker_data_[Rand(&pt.rand) % num_threads_].EnsureAwake(); } + } else { + callback_policy_.OnAbandon(work_item); } } } @@ -1205,13 +1313,15 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter ps.work_done.store(true, std::memory_order_release); }; + Work dispatch_work_item = callback_policy_.MakeWork(std::move(dispatch_task)); + profiler_.LogStart(); ps.dispatch_q_idx = preferred_workers[current_dop] % num_threads_; WorkerData& dispatch_td = worker_data_[ps.dispatch_q_idx]; Queue& dispatch_que = dispatch_td.queue; // assign dispatch task to selected dispatcher - auto push_status = dispatch_que.PushBackWithTag(dispatch_task, pt.tag, ps.dispatch_w_idx); + auto push_status = dispatch_que.PushBackWithTag(dispatch_work_item, pt.tag, ps.dispatch_w_idx); // Queue accepted the task; wake the thread that owns the queue. // In addition, if the queue was non-empty, attempt to wake // another thread (which may then steal the task). @@ -1222,6 +1332,7 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter } } else { ps.dispatch_q_idx = -1; // failed to enqueue dispatch_task + callback_policy_.OnAbandon(dispatch_work_item); } profiler_.LogEnd(ThreadPoolProfiler::DISTRIBUTION_ENQUEUE); } else { @@ -1323,11 +1434,11 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter return -1; } - void EnableSpinning() { + void EnableSpinning() override { spin_loop_status_ = SpinLoopStatus::kBusy; } - void DisableSpinning() { + void DisableSpinning() override { spin_loop_status_ = SpinLoopStatus::kIdle; } @@ -1492,10 +1603,91 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter std::condition_variable cv; }; + // Measure the average duration of a single SpinPause() call in nanoseconds. + // Runs exactly once per process (thread-safe via function-local static init). + // The result is used to convert a user-specified spin duration in microseconds + // into an iteration count, avoiding clock reads in the hot spin loop. + static int CalibrateSpinPauseNs() { + return onnxruntime::concurrency::CalibrateSpinPauseNs(); + } + + // Convert spin_duration_us into an iteration count for the spin loop. + // -1 (default): use the original fixed iteration count (1 << 20). + // 0: no spinning. + // >0: calibrate SpinPause() latency and compute the corresponding count. + static int ComputeSpinCount(int spin_duration_us) { + if (spin_duration_us == 0) return 0; + if (spin_duration_us < 0) return 1 << 20; // ~1M iterations (original default) + int ns_per_iter = CalibrateSpinPauseNs(); + auto count = static_cast(spin_duration_us) * 1000 / ns_per_iter; + return static_cast(std::min(count, 1 << 30)); + } + + // Clamp user-supplied backoff cap into a valid range. Any value < 1 is + // treated as 1 (no backoff, one SpinPause() per iteration), and very large + // values are capped so a single wait() cannot emit an excessive pause burst. + static unsigned int NormalizeBackoff(unsigned int spin_backoff_max) { + return std::min(std::max(spin_backoff_max, 1U), onnxruntime::concurrency::kSpinBackoffMaxLimit); + } + + // With exponential backoff capped at M, ThreadPoolWaiter::wait() ramps up to + // M SpinPause() calls per iteration and then stays at M. To preserve the + // targeted spin budget, divide the iteration budget by M so that + // (iterations) x (steady-state pauses per iter) ~= original pause budget. + // For explicit spin_duration_us > 0 this keeps the wall-clock spin window + // close to the requested duration. For the legacy default path + // (spin_duration_us < 0), the original semantic was "spin for ~1M + // iterations", so this scaling intentionally preserves only an approximate + // pause budget rather than the historical outer-loop iteration count. The + // ramp-up phase is O(log M) iterations and is negligible for typical M + // (<=64). + static int ScaleSpinCountForBackoff(int spin_count, unsigned int spin_backoff_max) { + if (spin_count <= 0 || spin_backoff_max <= 1U) { + return spin_count; + } + const int divisor = static_cast(spin_backoff_max); + return std::max(spin_count / divisor, 1); + } + + // Exponential-backoff waiter adapted from the approach in + // https://github.com/microsoft/onnxruntime/pull/23278 and combined with the + // configurable spin-window in this PR. Each call to wait() emits a growing + // number of SpinPause() instructions (1, 2, 4, ... capped at max_backoff_), + // reducing CPU/power density during the spin window. The object must be reset + // between unrelated spin windows (cheap: just reconstruct). + class ThreadPoolWaiter { + unsigned pause_time_{0}; + const unsigned max_backoff_; + + public: + explicit ThreadPoolWaiter(unsigned max_backoff) : max_backoff_(max_backoff) {} + + template + bool wait(ShouldInterrupt should_interrupt) { + unsigned pause_count = 1U; + if (max_backoff_ > 1U) { + // Double pause_time_ each call (starting from 1) and cap at max_backoff_. + // Produces the sequence 1, 2, 4, ..., max_backoff_, max_backoff_, ... + pause_count = (pause_time_ == 0U) ? 1U : std::min(pause_time_ * 2U, max_backoff_); + } + pause_time_ = pause_count; + for (unsigned i = 0; i < pause_count; ++i) { + if (should_interrupt()) { + return true; + } + onnxruntime::concurrency::SpinPause(); + } + return should_interrupt(); + } + }; + Environment& env_; const unsigned num_threads_; - const bool allow_spinning_; + const unsigned int spin_backoff_max_; // 1 = no backoff, >=2 exp-backoff cap + const int spin_count_; // Number of spin iterations before blocking (0 = no spin) + const int steal_interval_; // Attempt work steal every steal_interval_ iterations const bool set_denormal_as_zero_; + CallbackPolicy callback_policy_; Eigen::MaxSizeVector worker_data_; Eigen::MaxSizeVector> all_coprimes_; std::atomic blocked_; // Count of blocked workers, used as a termination condition @@ -1535,33 +1727,52 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter assert(td.GetStatus() == WorkerData::ThreadStatus::Spinning); - constexpr int log2_spin = 20; - const int spin_count = allow_spinning_ ? (1ull << log2_spin) : 0; - const int steal_count = spin_count / 100; - SetDenormalAsZero(set_denormal_as_zero_); profiler_.LogThreadId(thread_id); while (!should_exit) { - Task t = q.PopFront(); - if (!t) { - // Spin waiting for work. - for (int i = 0; i < spin_count && !done_; i++) { - if (((i + 1) % steal_count == 0)) { - t = Steal(StealAttemptKind::TRY_ONE); + Work w = q.PopFront(); + if (!w) { + // Spin waiting for work. spin_count_ is determined at construction: + // default (-1): 1<<20 iterations (original behavior) + // 0: no spinning (skip loop entirely) + // >0 us: iteration count derived from one-time SpinPause() calibration + // When spin_backoff_max_ > 1, ThreadPoolWaiter emits an exponentially + // growing number of SpinPause() calls per iteration to reduce pause + // density; spin_count_ has already been scaled to preserve the + // targeted wall-clock window. + // steal_interval_ = max(spin_count_/100, 1), yielding ~100 steal attempts per spin window. + // When backoff stretches each outer iteration, the wall-clock spacing + // between steal attempts also grows. We keep the same approximate + // number of steal attempts per spin window to preserve the legacy + // steal-vs-block trade-off. + ThreadPoolWaiter waiter{spin_backoff_max_}; + int steal_countdown = steal_interval_; + for (int i = 0; i < spin_count_ && !done_; i++) { + if (--steal_countdown == 0) { + w = Steal(StealAttemptKind::TRY_ONE); + steal_countdown = steal_interval_; } else { - t = q.PopFront(); + w = q.PopFront(); } - if (t) break; - + if (w) break; if (spin_loop_status_.load(std::memory_order_relaxed) == SpinLoopStatus::kIdle) { break; } - onnxruntime::concurrency::SpinPause(); + if (waiter.wait([&]() { + if (done_.load(std::memory_order_relaxed) || + spin_loop_status_.load(std::memory_order_relaxed) == SpinLoopStatus::kIdle) { + return true; + } + w = q.PopFront(); + return static_cast(w); + })) { + break; + } } // Attempt to block - if (!t) { + if (!w) { if (!td.SetBlocked( // Pre-block test [&]() -> bool { bool should_block = true; @@ -1580,9 +1791,9 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter // If #A is before #2 then main sees worker blocked and wakes // // If #A if after #2 then #B will see #1, and we abandon blocking - assert(!t); - t = q.PopFront(); - if (t) { + assert(!w); + w = q.PopFront(); + if (w) { should_block = false; } @@ -1625,14 +1836,14 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter // Thread just unblocked. Unless we picked up work while // blocking, or are exiting, then either work was pushed to // us, or it was pushed to an overloaded queue - if (!t) t = q.PopFront(); - if (!t) t = Steal(StealAttemptKind::TRY_ALL); + if (!w) w = q.PopFront(); + if (!w) w = Steal(StealAttemptKind::TRY_ALL); } } - if (t) { + if (w) { td.SetActive(); - t(); + callback_policy_.Execute(w); profiler_.LogRun(thread_id); td.SetSpinning(); } @@ -1652,7 +1863,7 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter // "snatching" work from a thread which is just about to notice the // work itself. - Task Steal(StealAttemptKind steal_kind) { + Work Steal(StealAttemptKind steal_kind) { PerThread* pt = GetPerThread(); unsigned size = num_threads_; unsigned num_attempts = (steal_kind == StealAttemptKind::TRY_ALL) ? size : 1; @@ -1663,9 +1874,9 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter for (unsigned i = 0; i < num_attempts; i++) { assert(victim < size); if (worker_data_[victim].GetStatus() == WorkerData::ThreadStatus::Active) { - Task t = worker_data_[victim].queue.PopBack(); - if (t) { - return t; + Work w = worker_data_[victim].queue.PopBack(); + if (w) { + return w; } } victim += inc; @@ -1674,7 +1885,7 @@ class ThreadPoolTempl : public onnxruntime::concurrency::ExtendedThreadPoolInter } } - return Task(); + return Work(); } int NonEmptyQueueIndex() { diff --git a/include/onnxruntime/core/platform/threadpool.h b/include/onnxruntime/core/platform/threadpool.h index 04df6dc982c6a..70f1cf11526d8 100644 --- a/include/onnxruntime/core/platform/threadpool.h +++ b/include/onnxruntime/core/platform/threadpool.h @@ -22,6 +22,7 @@ limitations under the License. #include #include "core/common/common.h" #include "core/platform/env.h" +#include "core/platform/threadpool_config.h" #include #include @@ -129,7 +130,11 @@ struct TensorOpCost { namespace concurrency { -template +// Sentinel value for spin_duration_us indicating the default iteration-count-based +// spinning behavior. This preserves the original spin loop performance characteristics +// where the spin duration varies by architecture depending on pause instruction latency. +static constexpr int kSpinDurationDefault = -1; +template class ThreadPoolTempl; class ExtendedThreadPoolInterface; @@ -145,19 +150,50 @@ class ThreadPool { #endif // Constructs a pool for running with with "degree_of_parallelism" threads with // specified "name". env->StartThread() is used to create individual threads - // with the given ThreadOptions. If "low_latency_hint" is true the thread pool - // implementation may use it as a hint that lower latency is preferred at the - // cost of higher CPU usage, e.g. by letting one or more idle threads spin - // wait. Conversely, if the threadpool is used to schedule high-latency - // operations like I/O the hint should be set to false. + // with the given ThreadOptions. "spin_duration_us" controls idle thread spin behavior: + // -1 (kSpinDurationDefault) = use default iteration-count-based spinning (best throughput, + // but spin duration varies by CPU architecture and pause instruction latency) + // 0 = disable spinning entirely (threads block immediately when idle) + // >0 = calibrated iteration-based spinning for the specified duration in microseconds + // (best-effort duration via one-time SpinPause() calibration; actual spin time + // may vary with CPU frequency changes) + // + // Note: The OrtThreadPoolParams.allow_spinning flag (controlled by the + // session.intra_op.allow_spinning / session.inter_op.allow_spinning config keys or + // the C API) takes priority. When allow_spinning is false, spin_duration_us is forced + // to 0 by CreateThreadPoolHelper regardless of the value passed here. + // + // "spin_backoff_max" controls an optional exponential-backoff inside the spin + // window. 1 (default) keeps the legacy behavior (single SpinPause() per iteration). + // Values >= 2 emit 1, 2, 4, ... pause calls per iteration capped at this value, + // reducing CPU/power density during the same targeted spin budget. For + // explicit spin_duration_us > 0 this keeps the wall-clock spin duration close + // to the requested value. On the legacy default path + // (spin_duration_us == kSpinDurationDefault), it preserves only an + // approximate pause budget rather than the exact historical outer-loop + // iteration count. Values above kSpinBackoffMaxLimit are clamped to that + // limit. // // REQUIRES: degree_of_parallelism > 0 ThreadPool(Env* env, const ThreadOptions& thread_options, const NAME_CHAR_TYPE* name, int degree_of_parallelism, - bool low_latency_hint, - bool force_hybrid = false); + int spin_duration_us = kSpinDurationDefault, + bool force_hybrid = false, + unsigned int spin_backoff_max = 1); + + // Backward-compatible overload: maps the legacy bool parameter to the new + // spin_duration_us semantics so that external callers passing true/false + // don't silently get implicit bool-to-int conversion (true -> 1us). + ThreadPool(Env* env, + const ThreadOptions& thread_options, + const NAME_CHAR_TYPE* name, + int degree_of_parallelism, + bool allow_spinning, + bool force_hybrid = false) + : ThreadPool(env, thread_options, name, degree_of_parallelism, + allow_spinning ? kSpinDurationDefault : 0, force_hybrid) {} // Waits until all scheduled work has finished and then destroy the // set of threads. @@ -424,7 +460,7 @@ class ThreadPool { ExtendedThreadPoolInterface* underlying_threadpool_ = nullptr; // If used, underlying_threadpool_ is instantiated and owned by the ThreadPool. - std::unique_ptr > extended_eigen_threadpool_; + std::unique_ptr extended_eigen_threadpool_; // Force the thread pool to run in hybrid mode on a normal cpu. bool force_hybrid_ = false; diff --git a/include/onnxruntime/core/platform/threadpool_config.h b/include/onnxruntime/core/platform/threadpool_config.h new file mode 100644 index 0000000000000..e4e0f76090a1f --- /dev/null +++ b/include/onnxruntime/core/platform/threadpool_config.h @@ -0,0 +1,12 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +namespace onnxruntime { +namespace concurrency { + +static constexpr unsigned int kSpinBackoffMaxLimit = 64U; + +} // namespace concurrency +} // namespace onnxruntime diff --git a/include/onnxruntime/core/providers/armnn/armnn_provider_factory.h b/include/onnxruntime/core/providers/armnn/armnn_provider_factory.h deleted file mode 100644 index 35276db323ff4..0000000000000 --- a/include/onnxruntime/core/providers/armnn/armnn_provider_factory.h +++ /dev/null @@ -1,18 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "onnxruntime_c_api.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \param use_arena zero: false. non-zero: true. - */ -ORT_API_STATUS(OrtSessionOptionsAppendExecutionProvider_ArmNN, _In_ OrtSessionOptions* options, int use_arena) -ORT_ALL_ARGS_NONNULL; - -#ifdef __cplusplus -} -#endif diff --git a/include/onnxruntime/core/providers/cann/cann_provider_options.h b/include/onnxruntime/core/providers/cann/cann_provider_options.h index 51b423e68110a..4b33ee77a892e 100644 --- a/include/onnxruntime/core/providers/cann/cann_provider_options.h +++ b/include/onnxruntime/core/providers/cann/cann_provider_options.h @@ -15,6 +15,8 @@ struct OrtCANNProviderOptions { onnxruntime::ArenaExtendStrategy arena_extend_strategy; // Strategy used to grow the memory arena int enable_cann_graph; // Flag indicating if prioritizing the use of // CANN's graph-running capabilities + int enable_cann_subgraph; // Flag indicating whether to generate subgraph + // automaticly int dump_graphs; // Flag indicating if dumping graphs int dump_om_model; // Flag indicating if dumping om model std::string precision_mode; // Operator Precision Mode diff --git a/include/onnxruntime/core/providers/dml/dml_provider_factory.h b/include/onnxruntime/core/providers/dml/dml_provider_factory.h index 33b98edf3bf4b..813153c8a299c 100644 --- a/include/onnxruntime/core/providers/dml/dml_provider_factory.h +++ b/include/onnxruntime/core/providers/dml/dml_provider_factory.h @@ -151,6 +151,18 @@ struct OrtDmlApi { * (high power, low power, or default) and a device filter (None, GPU, or NPU). */ ORT_API2_STATUS(SessionOptionsAppendExecutionProvider_DML2, _In_ OrtSessionOptions* options, OrtDmlDeviceOptions* device_opts); + + /** + * GetDMLDevice + * returns the DML device attched to the DML execution provider + */ + ORT_API2_STATUS(GetDMLDevice, _In_ OrtSessionOptions* options, _Out_ IDMLDevice** dmlDevice); + + /** + * GetDMLCommandQueue + * returns the command queue used by DML + */ + ORT_API2_STATUS(GetDMLCommandQueue, _In_ OrtSessionOptions* options, _Out_ ID3D12CommandQueue** dmlCommandQueue); }; #ifdef __cplusplus diff --git a/include/onnxruntime/core/providers/nv_tensorrt_rtx/nv_provider_options.h b/include/onnxruntime/core/providers/nv_tensorrt_rtx/nv_provider_options.h new file mode 100644 index 0000000000000..283c6be0f082b --- /dev/null +++ b/include/onnxruntime/core/providers/nv_tensorrt_rtx/nv_provider_options.h @@ -0,0 +1,49 @@ +#pragma once + +/** + + * @namespace onnxruntime::nv::provider_option_names + * @details The `provider_option_names` namespace contains the following constants: + * - `kDeviceId`: Specifies the GPU device ID to use. + * - `kHasUserComputeStream`: Indicates whether a user-provided compute stream is used. + * - `kUserComputeStream`: Specifies the user-provided compute stream. + * - `kUserAuxStreamArray`: Specifies the user-provided aux stream. + * - `kMaxWorkspaceSize`: Sets the maximum workspace size for GPU memory allocation. + * - 'kMaxSharedMemSize': Sets the maximum amount of shared memory that TensorRT kernels are allowed to use + * - `kLengthAuxStreamArray`: Specifies the length/size of the auxiliary streams array (kUserAuxStreamArray). Also sets the maximum number of auxiliary streams for TensorRT execution. + * - `kDumpSubgraphs`: Enables or disables dumping of subgraphs for debugging. + * - `kDetailedBuildLog`: Enables or disables detailed build logs for debugging. + * - `kProfilesMinShapes`: Specifies the minimum shapes for profiling. + * - `kProfilesMaxShapes`: Specifies the maximum shapes for profiling. + * - `kProfilesOptShapes`: Specifies the optimal shapes for profiling. + * - `kCudaGraphEnable`: Enables or disables CUDA graph optimizations. + * - `kONNXBytestream`: Specifies the ONNX model as a bytestream. + * - `kONNXBytestreamSize`: Specifies the size of the ONNX bytestream. + */ +namespace onnxruntime { +namespace nv { +namespace provider_option_names { +constexpr const char* kDeviceId = "device_id"; +constexpr const char* kHasUserComputeStream = "has_user_compute_stream"; +constexpr const char* kUserComputeStream = "user_compute_stream"; +constexpr const char* kUserAuxStreamArray = "user_aux_stream_array"; +constexpr const char* kMaxWorkspaceSize = "nv_max_workspace_size"; +constexpr const char* kMaxSharedMemSize = "nv_max_shared_mem_size"; +constexpr const char* kLengthAuxStreamArray = "nv_length_aux_stream_array"; +constexpr const char* kDumpSubgraphs = "nv_dump_subgraphs"; +constexpr const char* kDetailedBuildLog = "nv_detailed_build_log"; +constexpr const char* kProfilesMinShapes = "nv_profile_min_shapes"; +constexpr const char* kProfilesMaxShapes = "nv_profile_max_shapes"; +constexpr const char* kProfilesOptShapes = "nv_profile_opt_shapes"; +constexpr const char* kCudaGraphEnable = "enable_cuda_graph"; +constexpr const char* kMultiProfileEnable = "nv_multi_profile_enable"; +constexpr const char* kUseExternalDataInitializer = "nv_use_external_data_initializer"; +constexpr const char* kRuntimeCacheFile = "nv_runtime_cache_path"; +constexpr const char* kExternalComputeQueueDataParamNV_data = "VkExternalComputeQueueDataParamsNV_data"; + +} // namespace provider_option_names +namespace run_option_names { +constexpr const char* kProfileIndex = "nv_profile_index"; +} +} // namespace nv +} // namespace onnxruntime diff --git a/include/onnxruntime/core/providers/providers.h b/include/onnxruntime/core/providers/providers.h index 2cfd5acf66293..8097be287df82 100644 --- a/include/onnxruntime/core/providers/providers.h +++ b/include/onnxruntime/core/providers/providers.h @@ -2,6 +2,10 @@ // Licensed under the MIT License. #pragma once +#include + +struct OrtSessionOptions; +struct OrtLogger; namespace onnxruntime { class IExecutionProvider; @@ -9,5 +13,20 @@ class IExecutionProvider; struct IExecutionProviderFactory { virtual ~IExecutionProviderFactory() = default; virtual std::unique_ptr CreateProvider() = 0; + + /// + /// Creates an IExecutionProvider instance. Enables initialization of an EP instance using session-level options + /// such as session configs (string key/value pairs), graph optimization level, etc. + /// + /// The default implementation ignores the arguments and calls the above CreateProvider() function, + /// which does not take in any arguments. + /// + /// This version of CreateProvider() is used by InferenceSession when registering EPs. + /// + /// Options for the session in which the IExecutionProvider is used + /// Session logger that should be used by the IExecutionProvider. + /// An IExecutionProvider + virtual std::unique_ptr CreateProvider(const OrtSessionOptions& session_options, + const OrtLogger& session_logger); }; } // namespace onnxruntime diff --git a/include/onnxruntime/core/providers/resource.h b/include/onnxruntime/core/providers/resource.h index bd123e1cd41c2..8f9451ad11a4e 100644 --- a/include/onnxruntime/core/providers/resource.h +++ b/include/onnxruntime/core/providers/resource.h @@ -7,8 +7,8 @@ enum ResourceOffset { cpu_resource_offset = 0, cuda_resource_offset = 10000, dml_resource_offset = 20000, - rocm_resource_offset = 30000, + migraphx_resource_offset = 30000, // offsets for other ort eps custom_ep_resource_offset = 10000000, // offsets for customized eps -}; \ No newline at end of file +}; diff --git a/include/onnxruntime/core/providers/rocm/rocm_context.h b/include/onnxruntime/core/providers/rocm/rocm_context.h deleted file mode 100644 index aad1736217129..0000000000000 --- a/include/onnxruntime/core/providers/rocm/rocm_context.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#define ORT_ROCM_CTX - -#include "rocm_resource.h" -#include "core/providers/custom_op_context.h" -#include -#include -#include - -namespace Ort { - -namespace Custom { - -struct RocmContext : public CustomOpContext { - hipStream_t hip_stream = {}; - miopenHandle_t miopen_handle = {}; - hipblasHandle_t blas_handle = {}; - - void Init(const OrtKernelContext& kernel_ctx) { - const auto& ort_api = Ort::GetApi(); - void* resource = {}; - OrtStatus* status = nullptr; - - status = ort_api.KernelContext_GetResource( - &kernel_ctx, ORT_ROCM_RESOURCE_VERSION, RocmResource::hip_stream_t, &resource); - if (status) { - ORT_CXX_API_THROW("failed to fetch hip stream", OrtErrorCode::ORT_RUNTIME_EXCEPTION); - } - hip_stream = reinterpret_cast(resource); - - resource = {}; - status = ort_api.KernelContext_GetResource( - &kernel_ctx, ORT_ROCM_RESOURCE_VERSION, RocmResource::miopen_handle_t, &resource); - if (status) { - ORT_CXX_API_THROW("failed to fetch miopen handle", OrtErrorCode::ORT_RUNTIME_EXCEPTION); - } - miopen_handle = reinterpret_cast(resource); - - resource = {}; - status = ort_api.KernelContext_GetResource( - &kernel_ctx, ORT_ROCM_RESOURCE_VERSION, RocmResource::hipblas_handle_t, &resource); - if (status) { - ORT_CXX_API_THROW("failed to fetch hipblas handle", OrtErrorCode::ORT_RUNTIME_EXCEPTION); - } - blas_handle = reinterpret_cast(resource); - } -}; - -} // namespace Custom -} // namespace Ort diff --git a/include/onnxruntime/core/providers/rocm/rocm_resource.h b/include/onnxruntime/core/providers/rocm/rocm_resource.h deleted file mode 100644 index db032b48714c3..0000000000000 --- a/include/onnxruntime/core/providers/rocm/rocm_resource.h +++ /dev/null @@ -1,16 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -#include "core/providers/resource.h" - -#define ORT_ROCM_RESOURCE_VERSION 1 - -enum RocmResource : int { - hip_stream_t = rocm_resource_offset, - miopen_handle_t, - hipblas_handle_t, - deferred_cpu_allocator_t, - // below are rocm ep options - device_id_t, // 10004 - arena_extend_strategy_t -}; diff --git a/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h b/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h index ec9be80a63574..0aad80c4ddab9 100644 --- a/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h +++ b/include/onnxruntime/core/providers/tensorrt/tensorrt_provider_options.h @@ -21,6 +21,7 @@ struct OrtTensorRTProviderOptionsV2 { int trt_min_subgraph_size{1}; // minimum size of TensorRT subgraphs size_t trt_max_workspace_size{0}; // maximum workspace size for TensorRT. Default is 0 means max device memory size int trt_fp16_enable{0}; // enable TensorRT FP16 precision. Default 0 = false, nonzero = true + int trt_bf16_enable{0}; // enable TensorRT BF16 precision. Default 0 = false, nonzero = true int trt_int8_enable{0}; // enable TensorRT INT8 precision. Default 0 = false, nonzero = true const char* trt_int8_calibration_table_name{nullptr}; // TensorRT INT8 calibration table name. int trt_int8_use_native_calibration_table{0}; // use native TensorRT generated calibration table. Default 0 = false, nonzero = true @@ -42,13 +43,15 @@ struct OrtTensorRTProviderOptionsV2 { int trt_sparsity_enable{0}; // Control if sparsity can be used by TRT. Default 0 = false, 1 = true int trt_builder_optimization_level{3}; // Set the builder optimization level. WARNING: levels below 3 do not guarantee good engine performance, but greatly improve build time. Default 3, valid range [0-5] int trt_auxiliary_streams{-1}; // Set maximum number of auxiliary streams per inference stream. Setting this value to 0 will lead to optimal memory usage. Default -1 = heuristics - const char* trt_tactic_sources{nullptr}; // pecify the tactics to be used by adding (+) or removing (-) tactics from the default + const char* trt_tactic_sources{nullptr}; // Specify the tactics to be used by adding (+) or removing (-) tactics from the default // tactic sources (default = all available tactics) e.g. "-CUDNN,+CUBLAS" available keys: "CUBLAS"|"CUBLAS_LT"|"CUDNN"|"EDGE_MASK_CONVOLUTIONS" - const char* trt_extra_plugin_lib_paths{nullptr}; // specify extra TensorRT plugin library paths + const char* trt_extra_plugin_lib_paths{nullptr}; // Specify extra TensorRT plugin library paths const char* trt_profile_min_shapes{nullptr}; // Specify the range of the input shapes to build the engine with const char* trt_profile_max_shapes{nullptr}; // Specify the range of the input shapes to build the engine with const char* trt_profile_opt_shapes{nullptr}; // Specify the range of the input shapes to build the engine with int trt_cuda_graph_enable{0}; // Enable CUDA graph in ORT TRT + const char* trt_preview_features{nullptr}; // Specify the preview features to be enabled, features should be separated by comma + // available keys: "ALIASED_PLUGIN_IO_10_03" /* * Please note that there are rules for using following context model related provider options: @@ -86,6 +89,12 @@ struct OrtTensorRTProviderOptionsV2 { size_t trt_onnx_bytestream_size{0}; // size of the byte stream provided as "trt_onnx_bytestream" // can be updated using: UpdateTensorRTProviderOptionsWithValue - const char* trt_engine_cache_prefix{nullptr}; // specify engine cache prefix - int trt_engine_hw_compatible{0}; // Enable hardware compatibility. Default 0 = false, nonzero = true + const void* trt_external_data_bytestream{nullptr}; // The byte stream containing the weights to override the ones provided in the ONNX model. + // can be updated using: UpdateTensorRTProviderOptionsWithValue + size_t trt_external_data_bytestream_size{0}; // size of the byte stream provided as "trt_external_data_bytestream" + // can be updated using: UpdateTensorRTProviderOptionsWithValue + const char* trt_engine_cache_prefix{nullptr}; // specify engine cache prefix + int trt_engine_hw_compatible{0}; // Enable hardware compatibility. Default 0 = false, nonzero = true + const char* trt_op_types_to_exclude{}; // Exclude specific ops from running on TRT. + int trt_load_user_initializer{0}; // Save initializers locally instead of to disk. Default 0 = false, nonzero = true }; diff --git a/include/onnxruntime/core/providers/utils/ort_graph_to_proto.h b/include/onnxruntime/core/providers/utils/ort_graph_to_proto.h new file mode 100644 index 0000000000000..2b61890225888 --- /dev/null +++ b/include/onnxruntime/core/providers/utils/ort_graph_to_proto.h @@ -0,0 +1,849 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// DO NOT include ORT header files as this is meant to be a header-only utility that can be copied +// to other projects. + +/* + SUMMARY: + Utilities to serialize an OrtGraph into an ONNX GraphProto or ModelProto. Can be used by execution provider + implementations that need to convert an OrtGraph instance into an ONNX protobuf model. + + Users may copy this file and modify as needed. + + USAGE: + This is a header-only implementation that includes both the function declarations and definitions. Copy this file + into a project that links with both ONNX Runtime and ONNX. + + Define the ORT_EP_UTILS_ORT_GRAPH_TO_PROTO_IMPL preprocessor macro before the #include statement in exactly one C++ + file to define the implementation. Example: + + #define ORT_EP_UTILS_ORT_GRAPH_TO_PROTO_IMPL + #include "ort_graph_to_proto.h" + + Other compilation units that depend on these utilities should include this file without defining the + preprocessor macro. + + Example program snippets are shown below. Refer to the function declarations for detailed usage information. + + EXAMPLE SNIPPET (initializers stored within TensorProto): + + ```C++ + #define ORT_EP_UTILS_ORT_GRAPH_TO_PROTO_IMPL + #include "ort_graph_to_proto.h" + + OrtStatus* ORT_API_CALL GetCapabilityImpl(OrtEp* this_ptr, const OrtGraph* ort_graph, + OrtEpGraphSupportInfo* graph_support_info) { + onnx::GraphProto graph_proto; + OrtEpUtils::OrtGraphToProto(*ort_graph, graph_proto); + + // graph_proto stores initializers internally + } + ``` + + EXAMPLE SNIPPET (large initializers stored in external file): + + ```C++ + #define ORT_EP_UTILS_ORT_GRAPH_TO_PROTO_IMPL + #include "ort_graph_to_proto.h" + + OrtStatus* ORT_API_CALL GetCapabilityImpl(OrtEp* this_ptr, const OrtGraph* ort_graph, + OrtEpGraphSupportInfo* graph_support_info) { + std::string external_file_path = "weights.bin"; + std::ofstream out_file(external_file_path, std::ios::binary); + + auto handle_initializer_data = [&external_file_path, &out_file](const OrtValueInfo* value_info, + const void* data, size_t bytes, + bool& is_external, std::string& location, + int64_t& offset) -> Ort::Status { + // OrtValueInfo* could be used to query initializer's name, type, shape, consumers, etc. + (void)value_info; + + if (bytes <= 127) { + is_external = false; // Keep small initializers stored inside the TensorProto. + return Ort::Status{nullptr}; + } + + offset = out_file.tellp(); + location = external_file_path; + out_file.write(static_cast(data), bytes); + out_file.flush(); + is_external = true; // True if is external initializer + return Ort::Status{nullptr}; + } + + ONNX_NAMESPACE::GraphProto graph_proto; + OrtEpUtils::OrtGraphToProto(*ort_graph, graph_proto, handle_initializer_data); + + // graph_proto stores large initializers in an external file + } + ``` + + EXAMPLE SNIPPET (external initializers that point to data in memory, not officially supported by ONNX spec): + + This example stores initializers externally. However, instead of storing the initializers in a separate + file, the onnx::TensorProto objects point directly to memory addresses. This requires setting the initializer's + location to a special tag like "_MEM_ADDR_" (instead of a file path). The offset is set to the pointer to the + initializer's data in memory (instead of an offset into a file). + + Because this is not standard ONNX, such a onnx::GraphProto should not be saved as an ONNX file. + However, it allows custom tools that operate directly on a onnx::GraphProto to get the initializer data + if it has already been loaded into memory. + + ```C++ + #define ORT_EP_UTILS_ORT_GRAPH_TO_PROTO_IMPL + #include "ort_graph_to_proto.h" + + OrtStatus* ORT_API_CALL GetCapabilityImpl(OrtEp* this_ptr, const OrtGraph* ort_graph, + OrtEpGraphSupportInfo* graph_support_info) { + auto handle_initializer_data = [](const OrtValueInfo* value_info, + const void* data, size_t bytes, + bool& is_external, std::string& location, + int64_t& offset) -> Ort::Status { + (void)value_info; + (void)bytes; + + offset = reinterpret_cast(data); + location = "_MEM_ADDR_"; // Some special location tag that indicates the offset is a pointer. + is_external = true; // True if is external initializer + return Ort::Status{nullptr}; + } + + ONNX_NAMESPACE::GraphProto graph_proto; + OrtEpUtils::OrtGraphToProto(*ort_graph, graph_proto, handle_initializer_data); + + // graph_proto has initializers that look like they are stored in an external file, + // but they are actually pointing to the data in memory. + } + ``` +*/ + +#ifndef INCLUDE_ONNXRUNTIME_CORE_PROVIDERS_UTILS_ORT_GRAPH_TO_PROTO_H_ +#define INCLUDE_ONNXRUNTIME_CORE_PROVIDERS_UTILS_ORT_GRAPH_TO_PROTO_H_ + +#include +#include +#include "core/session/onnxruntime_cxx_api.h" +#include "onnx/onnx_pb.h" + +namespace OrtEpUtils { + +/// +/// Signature of user-provided function to handle initializer data. Called by OrtGraphToProto() for every initializer. +/// +/// If the function sets the `is_external` output parameter to false, OrtGraphToProto() stores initializer data +/// within the TensorProto as raw_data. +/// +/// Otherwise, if the function sets `is_external` to true, OrtGraphToProto() assumes that this function stores the +/// initializer data in a file. In this case, OrtGraphToProto() configures the corresponding TensorProto to point the +/// location and offset returned via the `location` and `offset` output parameters. +/// +/// It is recommended to keep small initializers with byte size <= 127 stored inline the TensorProto to ensure +/// ONNX shape inference works correctly with the serialized ONNX model. +/// +/// OrtValueInfo for the initializer. Can be used to query name, type, shape, +/// and consumer nodes. +/// Opaque pointer to the initializer data. +/// Size in bytes of the initializer data. +/// Output parameter set to true if the initializer data is stored externally. The +/// implementer is responsible for writing the initializer data to file. If set to false, +/// the initializer will be stored within the TensorProto. +/// Output parameter set to the location (e.g., file) into which the initializer is stored +/// by the implementer of this function. Ignored if `is_external` is set to false. +/// Output parameter set to the offset (e.g., file offset) into which the initializer is stored +/// by the implementer of this function. Ignored if `is_external` is set to false. +/// An Ort::Status indicating success or an error. Serialization exits if this returns an error. +using HandleInitializerDataFunc = std::function; + +/// +/// Serializes the provided OrtGraph to a onnx::GraphProto. +/// Allows the caller to provide a function that specifies whether an initializer should be stored +/// within a TensorProto, written to a file, or remain as an in-memory external initializer (not valid ONNX). +/// +/// OrtGraph instance to serialize. +/// Destination GraphProto into which to serialize the input OrtGraph. +/// Optional function called to allow the user to determine +/// where the initializer data is stored. +/// An Ort::Status indicating success or an error. +Ort::Status OrtGraphToProto(const OrtGraph& ort_graph, + onnx::GraphProto& graph_proto, + HandleInitializerDataFunc handle_initializer_data_func = nullptr); + +/// +/// Serializes the provided top-level OrtGraph to a onnx::ModelProto. +/// Allows the caller to provide a function that specifies whether an initializer should be stored +/// within a TensorProto, written to a file, or remain as an in-memory external initializer (not valid ONNX). +/// +/// OrtGraph instance to serialize. +/// Destination ModelProto into which to serialize the input OrtGraph. +/// Optional function called to allow the user to determine +/// where the initializer data is stored. +/// An Ort::Status indicating success or an error. +Ort::Status OrtGraphToProto(const OrtGraph& ort_graph, + onnx::ModelProto& model_proto, + HandleInitializerDataFunc handle_initializer_data_func = nullptr); +/// +/// Convert the endianess of data based of tensor element type. Mainly used in BE systems. +/// +/// OrtValueInfo for the initializer. Can be used to query name, type, shape, +/// and consumer nodes. +/// Pointer to data buffer. +/// Length of data buffer. +/// An Ort::Status indicating success or an error. +Ort::Status ConvertExternalData(const OrtValueInfo* value_info, void* data, size_t bytes); + +} // namespace OrtEpUtils + +// End of header +#endif // INCLUDE_ONNXRUNTIME_CORE_PROVIDERS_UTILS_ORT_GRAPH_TO_PROTO_H_ + +// +// IMPLEMENTATION BELOW +// +#ifdef ORT_EP_UTILS_ORT_GRAPH_TO_PROTO_IMPL + +#include +#include +#include +#include +#include +#include + +#define ORT_EP_UTILS_C_RETURN_IF_ERROR(fn) \ + do { \ + Ort::Status _status{(fn)}; \ + if (!_status.IsOK()) { \ + return _status; \ + } \ + } while (0) + +#define ORT_EP_UTILS_CXX_RETURN_IF_ERROR(fn) \ + ORT_EP_UTILS_C_RETURN_IF_ERROR(fn) + +#define ORT_EP_UTILS_C_RETURN_IF(cond, msg) \ + do { \ + if ((cond)) { \ + return Ort::Status{msg, ORT_FAIL}; \ + } \ + } while (0) + +namespace OrtEpUtils { + +static Ort::Status GetOrtValueInfoTensorTypeShape(Ort::ConstValueInfo vi, + bool get_symbolic_dims, + /*out*/ ONNXTensorElementDataType& elem_type, + /*out*/ std::vector& dims, + /*out*/ std::vector& symbolic_dims, + /*out*/ bool& has_shape); +static Ort::Status OrtValueInfoToProto(Ort::ConstValueInfo ort_value_info, onnx::ValueInfoProto& value_info_proto); +static Ort::Status OrtOpAttrToProto(Ort::ConstOpAttr ort_attr, onnx::AttributeProto& attr_proto); +static Ort::Status GetTensorElementSize(const ONNXTensorElementDataType& element_type, size_t& element_size); +static void SwapByteOrderInplace(void* data, const size_t& data_len, const size_t& element_size); + +// Below endian enum class is referenced from include/onnxruntime/core/framework/endian.h +enum class endian { +#if defined(_WIN32) + little = 0, + big = 1, + native = little, +#elif defined(__GNUC__) || defined(__clang__) + little = __ORDER_LITTLE_ENDIAN__, + big = __ORDER_BIG_ENDIAN__, + native = __BYTE_ORDER__, +#else +#error onnxruntime::endian is not implemented in this environment. +#endif +}; + +Ort::Status OrtGraphToProto(const OrtGraph& graph, + onnx::GraphProto& graph_proto, + HandleInitializerDataFunc handle_initializer_data_func) { + try { + Ort::ConstGraph ort_graph{&graph}; + // + // Set GraphProto metadata + // + auto graph_name = ort_graph.GetName(); + graph_proto.set_name(graph_name); + graph_proto.set_doc_string("Serialized from OrtGraph"); + + // + // Set GraphProto inputs and outputs + // + std::vector graph_inputs = ort_graph.GetInputs(); + std::vector graph_outputs = ort_graph.GetOutputs(); + + for (const auto& ort_value_info : graph_inputs) { + onnx::ValueInfoProto* value_info_proto = graph_proto.mutable_input()->Add(); + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(OrtValueInfoToProto(ort_value_info, *value_info_proto)); + } + + for (const auto& ort_value_info : graph_outputs) { + onnx::ValueInfoProto* value_info_proto = graph_proto.mutable_output()->Add(); + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(OrtValueInfoToProto(ort_value_info, *value_info_proto)); + } + + // + // Set GraphProto nodes, value_infos, and initializers. + // + + // Use std::maps to store OrtValueInfos for GraphProto.value_info and GraphProto.initializer. + // A std::map maintains its elements in a stable ordering. + std::map value_infos; // For GraphProto.value_info + std::map initializer_value_infos; // For GraphProto.initializer + + // Helper function to collect an OrtValueInfo into `value_infos` or `initializer_value_infos`. + // Optionally returns the OrtValueInfo name to the caller. + auto collect_value_info = [&value_infos, + &initializer_value_infos](Ort::ConstValueInfo ort_value_info, + /*out*/ std::optional& value_name_out) { + auto value_name = ort_value_info.GetName(); + + if (value_name_out) { + *value_name_out = value_name; + } + + if (value_infos.count(value_name) != 0 || initializer_value_infos.count(value_name) != 0) { + return; // Already processed this OrtValueInfo. + } + + bool is_required_graph_input = ort_value_info.IsRequiredGraphInput(); + bool is_optional_graph_input = ort_value_info.IsOptionalGraphInput(); + bool is_graph_output = ort_value_info.IsGraphOutput(); + bool is_constant_initializer = ort_value_info.IsConstantInitializer(); + bool is_from_outer_scope = ort_value_info.IsFromOuterScope(); + + // Don't add graph inputs or graph outputs to GraphProto's list of value_infos. + // Do add initializers (constant and non-constant) to GraphProto's list of initializer tensors. + if (is_from_outer_scope) { + value_infos.emplace(value_name, ort_value_info); + if (is_constant_initializer) { + initializer_value_infos.emplace(value_name, ort_value_info); + } + } else if (is_optional_graph_input) { + initializer_value_infos.emplace(value_name, ort_value_info); + } else if (is_constant_initializer) { + value_infos.emplace(value_name, ort_value_info); + initializer_value_infos.emplace(value_name, ort_value_info); + } else if (!is_required_graph_input && !is_graph_output) { + value_infos.emplace(value_name, ort_value_info); // This is an internal OrtValueInfo. + } + }; + + std::vector nodes = ort_graph.GetNodes(); + // Loop through all nodes (topological order): add NodeProto instances to GraphProto and track OrtValueInfos + // that will be stored in GraphProto.value_info and GraphProto.initializer. + for (const auto& ort_node : nodes) { + onnx::NodeProto* node_proto = graph_proto.add_node(); + + std::string node_name = ort_node.GetName(); + std::string node_domain = ort_node.GetDomain(); + std::string node_op_type = ort_node.GetOperatorType(); + + node_proto->set_name(node_name); + node_proto->set_domain(node_domain); + node_proto->set_op_type(node_op_type); + + // Handle node attributes + std::vector ort_attrs = ort_node.GetAttributes(); + for (const auto& attr : ort_attrs) { + OrtOpAttrType attr_type = attr.GetType(); + if (attr_type == OrtOpAttrType::ORT_OP_ATTR_GRAPH) { + // ORT does not support reading subgraphs via ReadOpAttr(), so skip it. + // Can use Node_GetSubgraphs to get subgraphs. + continue; + } + + onnx::AttributeProto* attr_proto = node_proto->add_attribute(); + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(OrtOpAttrToProto(attr, *attr_proto)); + } + + // Handle node subgraphs + std::vector ort_subgraphs = ort_node.GetSubgraphs(); + for (const auto& [subgraph_attr_name, ort_subgraph] : ort_subgraphs) { + onnx::AttributeProto* attr_proto = node_proto->add_attribute(); + onnx::GraphProto* subgraph_proto = attr_proto->mutable_g(); + attr_proto->set_name(subgraph_attr_name); + attr_proto->set_type(onnx::AttributeProto_AttributeType_GRAPH); + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(OrtGraphToProto(*ort_subgraph, *subgraph_proto)); + } + + // Handle node inputs + std::vector ort_inputs = ort_node.GetInputs(); + for (const auto& vi : ort_inputs) { + if (vi == nullptr) { + // missing optional input. + node_proto->add_input(""); + continue; + } + + std::optional value_name; + value_name.emplace(); + collect_value_info(vi, value_name); + node_proto->add_input(*value_name); + } + + // Handle implicit inputs to this node. + std::vector ort_implicit_inputs = ort_node.GetImplicitInputs(); + for (const auto& vi : ort_implicit_inputs) { + assert(vi != nullptr); + std::optional value_name; + collect_value_info(vi, value_name); + } + + // Handle node outputs + std::vector ort_outputs = ort_node.GetOutputs(); + for (const auto& vi : ort_outputs) { + if (vi == nullptr) { + // missing optional output. + node_proto->add_output(""); + continue; + } + + std::optional value_name; + value_name.emplace(); + collect_value_info(vi, value_name); + node_proto->add_output(*value_name); + } + } + + // Add value_infos to GraphProto as ValueInfoProto objects. + for (const auto& [value_name, value_info] : value_infos) { + onnx::ValueInfoProto* value_info_proto = graph_proto.mutable_value_info()->Add(); + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(OrtValueInfoToProto(value_info, *value_info_proto)); + } + + // There may be initializers in the original OrtGraph that have not been added yet. + // For example, an initializer may not be used by any node but is still a graph output. + // Iterating through all nodes to collect initializer value info is therefore not sufficient, + // initializers must also be obtained from ort_graph.GetInitializers(). + // Add those missing initializers and skip the ones that already in `initializer_value_infos` + std::vector ort_graph_initializers = ort_graph.GetInitializers(); + for (const auto& initializer : ort_graph_initializers) { + initializer_value_infos.emplace(initializer.GetName(), initializer); + } + + // Add initializers to GraphProto as TensorProto objects. + for (const auto& [initializer_name, initializer_value_info] : initializer_value_infos) { + std::vector initializer_dims; + std::vector initializer_sym_dims; + ONNXTensorElementDataType initializer_elem_type = ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED; + bool has_shape = false; + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(GetOrtValueInfoTensorTypeShape(initializer_value_info, /*get_sym_dims*/ false, + initializer_elem_type, initializer_dims, + initializer_sym_dims, has_shape)); + + onnx::TensorProto* tensor_proto = graph_proto.add_initializer(); + tensor_proto->set_name(initializer_name); + tensor_proto->set_data_type(initializer_elem_type); + + auto* tensor_proto_dims = tensor_proto->mutable_dims(); + for (int64_t dim : initializer_dims) { + tensor_proto_dims->Add(dim); + } + + Ort::ConstValue ort_value{nullptr}; + ORT_EP_UTILS_C_RETURN_IF_ERROR(initializer_value_info.GetInitializer(ort_value)); + + assert(ort_value.IsTensor()); + const void* data = ort_value.GetTensorRawData(); + const size_t data_bytes = ort_value.GetTensorSizeInBytes(); + + std::string ext_location; + int64_t ext_offset = 0; + bool is_external = false; + + if (handle_initializer_data_func != nullptr) { + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(handle_initializer_data_func(initializer_value_info, data, data_bytes, + is_external, ext_location, ext_offset)); + } + + if (is_external) { + tensor_proto->set_data_location(onnx::TensorProto_DataLocation_EXTERNAL); + auto* ext_data_entries = tensor_proto->mutable_external_data(); + onnx::StringStringEntryProto* location_entry = ext_data_entries->Add(); + onnx::StringStringEntryProto* offset_entry = ext_data_entries->Add(); + onnx::StringStringEntryProto* length_entry = ext_data_entries->Add(); + + location_entry->set_key("location"); + location_entry->set_value(ext_location); + offset_entry->set_key("offset"); + offset_entry->set_value(std::to_string(ext_offset)); + length_entry->set_key("length"); + length_entry->set_value(std::to_string(data_bytes)); + } else { + // User wants to store data inline the TensorProto's raw_data + tensor_proto->set_data_location(onnx::TensorProto_DataLocation_DEFAULT); + if constexpr (endian::native == endian::big) { + size_t element_size = 0; + GetTensorElementSize(initializer_elem_type, element_size); + // create local copy of data and do endianess conversion + auto raw_data_buf = std::make_unique(data_bytes); + std::memcpy(raw_data_buf.get(), data, data_bytes); + SwapByteOrderInplace(raw_data_buf.get(), data_bytes, element_size); + tensor_proto->set_raw_data(raw_data_buf.get(), data_bytes); + } else { + tensor_proto->set_raw_data(data, data_bytes); + } + } + } + } catch (const Ort::Exception& ex) { + return Ort::Status{ex}; + } catch (const std::exception& ex) { + return Ort::Status{ex.what(), ORT_FAIL}; + } + + return Ort::Status{nullptr}; +} + +Ort::Status OrtGraphToProto(const OrtGraph& graph, + onnx::ModelProto& model_proto, + HandleInitializerDataFunc handle_initializer_data_func) { + try { + Ort::ConstGraph ort_graph{&graph}; + + // Set model description. + model_proto.set_doc_string("Serialized from OrtGraph"); + model_proto.set_producer_name("ort_ep_utils::OrtGraphToProto"); + + // Set ir version. + int64_t ir_version = ort_graph.GetOnnxIRVersion(); + model_proto.set_ir_version(ir_version); + + // Set operator sets. + std::vector op_sets = ort_graph.GetOperatorSets(); + ORT_EP_UTILS_C_RETURN_IF(op_sets.empty(), "OrtGraph should have at least one operator set."); + + auto* operator_sets = model_proto.mutable_opset_import(); + + for (const auto& op_set : op_sets) { + onnx::OperatorSetIdProto* operator_set = operator_sets->Add(); + operator_set->set_domain(op_set.domain); + operator_set->set_version(op_set.version); + } + + model_proto.clear_graph(); + onnx::GraphProto* graph_proto = model_proto.mutable_graph(); + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(OrtGraphToProto(*ort_graph, *graph_proto, handle_initializer_data_func)); + + } catch (const Ort::Exception& ex) { + return Ort::Status(ex); + } catch (const std::exception& ex) { + return Ort::Status(ex.what(), ORT_EP_FAIL); + } + + return Ort::Status{nullptr}; +} + +static Ort::Status GetOrtValueInfoTensorTypeShape(Ort::ConstValueInfo vi, + bool get_symbolic_dims, + /*out*/ ONNXTensorElementDataType& elem_type, + /*out*/ std::vector& dims, + /*out*/ std::vector& symbolic_dims, + /*out*/ bool& has_shape) { + try { + Ort::ConstTypeInfo ort_type_info = vi.TypeInfo(); + ONNXType ort_onnx_type = ort_type_info.GetONNXType(); + ORT_EP_UTILS_C_RETURN_IF(ort_onnx_type != ONNX_TYPE_TENSOR, "Expected OrtValueInfo to represent a Tensor"); + + Ort::ConstTensorTypeAndShapeInfo ort_type_shape = ort_type_info.GetTensorTypeAndShapeInfo(); + elem_type = ort_type_shape.GetElementType(); + has_shape = ort_type_shape.HasShape(); + + if (has_shape) { + const size_t num_dims = ort_type_shape.GetDimensionsCount(); + dims = ort_type_shape.GetShape(); + + if (get_symbolic_dims) { + std::vector ort_dim_syms(num_dims, nullptr); + ort_type_shape.GetSymbolicDimensions(ort_dim_syms.data(), ort_dim_syms.size()); + + symbolic_dims.reserve(num_dims); + for (const char* sym_dim : ort_dim_syms) { + symbolic_dims.push_back(sym_dim); + } + } + } + } catch (const Ort::Exception& ex) { + return Ort::Status{ex}; + } catch (const std::exception& ex) { + return Ort::Status{ex.what(), ORT_EP_FAIL}; + } + return Ort::Status{nullptr}; +} + +// Create an onnx::ValueInfoProto from an OrtValueInfo (name, type, shape). +static Ort::Status OrtValueInfoToProto(Ort::ConstValueInfo ort_value_info, + onnx::ValueInfoProto& value_info_proto) { + std::vector ort_dims; + std::vector ort_dim_syms; + ONNXTensorElementDataType ort_elem_type = ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED; + + // We currently only support ONNX tensors. Support for other types (e.g., ONNX_TYPE_SEQUENCE) can be added later. + bool has_shape = false; + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(GetOrtValueInfoTensorTypeShape(ort_value_info, /*get_sym_dims*/ true, + ort_elem_type, ort_dims, ort_dim_syms, + has_shape)); + + value_info_proto.set_name(ort_value_info.GetName()); + + onnx::TypeProto_Tensor* type_proto_tensor = value_info_proto.mutable_type()->mutable_tensor_type(); + type_proto_tensor->set_elem_type(ort_elem_type); + + // If there is no shape, do not set a TensorShapeProto. + if (has_shape) { + onnx::TensorShapeProto* shape_proto = type_proto_tensor->mutable_shape(); + + for (size_t dim_idx = 0; dim_idx < ort_dims.size(); dim_idx++) { + onnx::TensorShapeProto_Dimension* dim_proto = shape_proto->add_dim(); + + if (ort_dims[dim_idx] >= 0) { + dim_proto->set_dim_value(ort_dims[dim_idx]); + } else { + const std::string& dim_param = ort_dim_syms[dim_idx]; + + // If dim_param is empty, leave dim_proto with neither the dim_value or dim_param set, + // which represents an unknown dimension. + if (!dim_param.empty()) { + dim_proto->set_dim_param(dim_param); + } + } + } + } + + return Ort::Status{nullptr}; +} + +static Ort::Status OrtOpAttrToProto(Ort::ConstOpAttr attr, onnx::AttributeProto& attr_proto) { + try { + std::string attr_name = attr.GetName(); + attr_proto.set_name(attr_name); + + OrtOpAttrType attr_type = attr.GetType(); + + switch (attr_type) { + case OrtOpAttrType::ORT_OP_ATTR_INT: { + int64_t i_val = 0; + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(attr.GetValue(i_val)); + attr_proto.set_type(onnx::AttributeProto_AttributeType_INT); + attr_proto.set_i(i_val); + break; + } + case OrtOpAttrType::ORT_OP_ATTR_INTS: { + std::vector i_vals; + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(attr.GetValueArray(i_vals)); + auto* ints = attr_proto.mutable_ints(); + ints->Assign(i_vals.begin(), i_vals.end()); + attr_proto.set_type(onnx::AttributeProto_AttributeType_INTS); + break; + } + case OrtOpAttrType::ORT_OP_ATTR_FLOAT: { + float f_val = 0.0f; + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(attr.GetValue(f_val)); + attr_proto.set_type(onnx::AttributeProto_AttributeType_FLOAT); + attr_proto.set_f(f_val); + break; + } + case OrtOpAttrType::ORT_OP_ATTR_FLOATS: { + std::vector f_vals; + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(attr.GetValueArray(f_vals)); + auto* floats = attr_proto.mutable_floats(); + floats->Assign(f_vals.begin(), f_vals.end()); + attr_proto.set_type(onnx::AttributeProto_AttributeType_FLOATS); + break; + } + case OrtOpAttrType::ORT_OP_ATTR_STRING: { + std::string* str = attr_proto.mutable_s(); + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(attr.GetValue(*str)); + attr_proto.set_type(onnx::AttributeProto_AttributeType_STRING); + break; + } + case OrtOpAttrType::ORT_OP_ATTR_STRINGS: { + std::vector result; + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(attr.GetValueArray(result)); + auto* strs = attr_proto.mutable_strings(); + strs->Assign(result.begin(), result.end()); + attr_proto.set_type(onnx::AttributeProto_AttributeType_STRINGS); + break; + } + case OrtOpAttrType::ORT_OP_ATTR_TENSOR: { + attr_proto.set_type(onnx::AttributeProto_AttributeType_TENSOR); + + onnx::TensorProto tensor_proto; + + // TensorProto as an attribute value doesn't require a name. + + Ort::Value tensor; + ORT_EP_UTILS_C_RETURN_IF_ERROR(attr.GetTensorAttributeAsOrtValue(tensor)); + + // Get tensor type and shape info + Ort::TensorTypeAndShapeInfo type_shape_info = tensor.GetTensorTypeAndShapeInfo(); + + // Get tensor type + ONNXTensorElementDataType element_type = type_shape_info.GetElementType(); + + switch (element_type) { + case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: { + tensor_proto.set_data_type(onnx::TensorProto_DataType_FLOAT); + break; + } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: { + tensor_proto.set_data_type(onnx::TensorProto_DataType_UINT8); + break; + } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: { + tensor_proto.set_data_type(onnx::TensorProto_DataType_INT8); + break; + } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16: { + tensor_proto.set_data_type(onnx::TensorProto_DataType_UINT16); + break; + } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16: { + tensor_proto.set_data_type(onnx::TensorProto_DataType_INT16); + break; + } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: { + tensor_proto.set_data_type(onnx::TensorProto_DataType_INT32); + break; + } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: { + tensor_proto.set_data_type(onnx::TensorProto_DataType_INT64); + break; + } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL: { + tensor_proto.set_data_type(onnx::TensorProto_DataType_BOOL); + break; + } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE: { + tensor_proto.set_data_type(onnx::TensorProto_DataType_DOUBLE); + break; + } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32: { + tensor_proto.set_data_type(onnx::TensorProto_DataType_UINT32); + break; + } + case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64: { + tensor_proto.set_data_type(onnx::TensorProto_DataType_UINT64); + break; + } + default: { + std::string err_msg = "Unexpected ONNXTensorElementDataType with value " + std::to_string(static_cast(element_type)); + return Ort::Status(err_msg.c_str(), ORT_FAIL); + } + } + + auto shape = type_shape_info.GetShape(); + + for (auto& dim : shape) { + tensor_proto.add_dims(dim); + } + + const void* data = tensor.GetTensorRawData(); + const size_t data_bytes = tensor.GetTensorSizeInBytes(); + + // Copy the Ortvalue to TensorProto as raw data + if constexpr (endian::native == endian::big) { + size_t element_size = 0; + GetTensorElementSize(element_type, element_size); + // create local copy of data and do endianess conversion + auto raw_data_buf = std::make_unique(data_bytes); + std::memcpy(raw_data_buf.get(), data, data_bytes); + SwapByteOrderInplace(raw_data_buf.get(), data_bytes, element_size); + tensor_proto.set_raw_data(raw_data_buf.get(), data_bytes); + } else { + tensor_proto.set_raw_data(data, data_bytes); + } + + *(attr_proto.mutable_t()) = std::move(tensor_proto); + break; + } + default: { + std::string err_msg = "Unexpected OrtOpAttrType with value " + std::to_string(static_cast(attr_type)); + return Ort::Status(err_msg.c_str(), ORT_FAIL); + } + } + } catch (const Ort::Exception& ex) { + return Ort::Status{ex}; + } catch (const std::exception& ex) { + return Ort::Status{ex.what(), ORT_FAIL}; + } + + return Ort::Status{nullptr}; +} + +Ort::Status ConvertExternalData(const OrtValueInfo* value_info, void* data, size_t bytes) { +#if !defined(_WIN32) + if constexpr (endian::native == endian::little) { + return Ort::Status{nullptr}; + } + std::vector initializer_dims; + std::vector initializer_sym_dims; + ONNXTensorElementDataType initializer_elem_type = ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED; + size_t element_size = 0; + Ort::ConstValueInfo ort_value_info{value_info}; + bool has_shape{false}; + ORT_EP_UTILS_CXX_RETURN_IF_ERROR(GetOrtValueInfoTensorTypeShape(ort_value_info, false, + initializer_elem_type, initializer_dims, + initializer_sym_dims, has_shape)); + GetTensorElementSize(initializer_elem_type, element_size); + if (element_size != 1) { + SwapByteOrderInplace(data, bytes, element_size); + } +#else + (value_info); + (data); + (bytes); +#endif + return Ort::Status{nullptr}; +} + +static Ort::Status GetTensorElementSize(const ONNXTensorElementDataType& element_type, size_t& element_size) { + using TensorElemDataMap = std::unordered_map; + static TensorElemDataMap tensor_elem_data_size{ + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, sizeof(float)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8, sizeof(uint8_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8, sizeof(int8_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16, sizeof(uint16_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16, sizeof(int16_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16, sizeof(uint16_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16, sizeof(uint16_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32, sizeof(int32_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32, sizeof(uint32_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64, sizeof(int64_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64, sizeof(uint64_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE, sizeof(double)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL, sizeof(uint8_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT8E4M3FN, sizeof(uint8_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT8E4M3FNUZ, sizeof(uint8_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT8E5M2, sizeof(uint8_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT8E5M2FNUZ, sizeof(uint8_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT4, sizeof(uint8_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT4, sizeof(uint8_t)}, + }; + auto pos = tensor_elem_data_size.find(element_type); + if (pos == tensor_elem_data_size.end()) { + std::string err_msg = "Unexpected ONNXTensorElementDataType with value " + std::to_string(static_cast(element_type)); + return Ort::Status(err_msg.c_str(), ORT_FAIL); + } + element_size = pos->second; + return Ort::Status{nullptr}; +} + +static void SwapByteOrderInplace(void* data, const size_t& data_len, const size_t& element_size) { + char* bytes = reinterpret_cast(data); + size_t num_elements = data_len / element_size; + for (size_t i = 0; i < num_elements; ++i) { + char* start_byte = bytes + i * element_size; + char* end_byte = start_byte + element_size - 1; + for (size_t count = 0; count < element_size / 2; ++count) { + std::swap(*start_byte++, *end_byte--); + } + } +} + +} // namespace OrtEpUtils +#endif // ORT_EP_UTILS_ORT_GRAPH_TO_PROTO_IMPL diff --git a/include/onnxruntime/core/session/environment.h b/include/onnxruntime/core/session/environment.h index 20c7cace152d5..338dbf85ef664 100644 --- a/include/onnxruntime/core/session/environment.h +++ b/include/onnxruntime/core/session/environment.h @@ -4,16 +4,41 @@ #pragma once #include +#include #include +#include +#include +#include +#include + #include "core/common/common.h" -#include "core/common/status.h" -#include "core/platform/threadpool.h" +#include "core/common/basic_types.h" #include "core/common/logging/logging.h" +#include "core/common/status.h" #include "core/framework/allocator.h" +#include "core/framework/execution_provider.h" +#include "core/framework/data_transfer_manager.h" +#include "core/platform/device_discovery.h" +#include "core/platform/threadpool.h" + +#include "core/session/abi_devices.h" +#include "core/session/abi_key_value_pairs.h" +#include "core/session/plugin_ep/ep_library.h" +#include "core/session/onnxruntime_c_api.h" struct OrtThreadingOptions; namespace onnxruntime { -/** TODO: remove this class +class EpFactoryInternal; +class InferenceSession; +struct IExecutionProviderFactory; +struct OrtAllocatorImplWrappingIAllocator; +struct SessionOptions; + +namespace plugin_ep { +class DataTransfer; +} // namespace plugin_ep + +/** Provides the runtime environment for onnxruntime. Create one instance for the duration of execution. */ @@ -29,11 +54,23 @@ class Environment { @param tp_options optional set of parameters controlling the number of intra and inter op threads for the global threadpools. @param create_global_thread_pools determine if this function will create the global threadpools or not. + @param config_entries Application-specified configuration entries. */ static Status Create(std::unique_ptr logging_manager, std::unique_ptr& environment, const OrtThreadingOptions* tp_options = nullptr, - bool create_global_thread_pools = false); + bool create_global_thread_pools = false, + const OrtKeyValuePairs* config_entries = nullptr); + + /** + * Set the global threading options for the environment, if no global thread pools have been created yet. + * + * This function is not safe to call simultaneously from multiple threads, and will return a FAIL status on all calls + * after the first. + * @param tp_options set of parameters controlling the number of intra and inter op threads for the global + threadpools. + */ + Status SetGlobalThreadingOptions(const OrtThreadingOptions& tp_options); logging::LoggingManager* GetLoggingManager() const { return logging_manager_.get(); @@ -59,7 +96,7 @@ class Environment { * Registers an allocator for sharing between multiple sessions. * Return an error if an allocator with the same OrtMemoryInfo is already registered. */ - Status RegisterAllocator(AllocatorPtr allocator); + Status RegisterAllocator(OrtAllocator* allocator); /** * Creates and registers an allocator for sharing between multiple sessions. @@ -74,6 +111,15 @@ class Environment { return shared_allocators_; } + /** + * Returns an AllocatorPtr for a shared IAllocator based allocator if it matches the memory info. + * The OrtMemoryInfo name and whether it's an arena or device allocator is ignored in the lookup, as is the + * alignment. + * The user calling this function is not expected to know the alignment, and we expect the allocator instance to be + * created with a valid alignment for the device. + */ + AllocatorPtr GetRegisteredSharedAllocator(const OrtMemoryInfo& mem_info) const; + /** * Removes registered allocator that was previously registered for sharing between multiple sessions. */ @@ -86,18 +132,192 @@ class Environment { * Return an error if an allocator with the same OrtMemoryInfo is already registered. * For provider_type please refer core/graph/constants.h */ - Status CreateAndRegisterAllocatorV2(const std::string& provider_type, const OrtMemoryInfo& mem_info, const std::unordered_map& options, const OrtArenaCfg* arena_cfg = nullptr); + Status CreateAndRegisterAllocatorV2(const std::string& provider_type, const OrtMemoryInfo& mem_info, + const std::unordered_map& options, + const OrtArenaCfg* arena_cfg = nullptr); + +#if !defined(ORT_MINIMAL_BUILD) + Status RegisterExecutionProviderLibrary(const std::string& registration_name, const ORTCHAR_T* lib_path); + Status UnregisterExecutionProviderLibrary(const std::string& registration_name); + + // convert an OrtEpFactory* to EpFactoryInternal* if possible. + EpFactoryInternal* GetEpFactoryInternal(OrtEpFactory* factory) const { + // we're comparing pointers so the reinterpret_cast should be safe + auto it = internal_ep_factories_.find(reinterpret_cast(factory)); + return it != internal_ep_factories_.end() ? *it : nullptr; + } + + const std::vector& GetOrtEpDevices() const { + return execution_devices_; + } + + /// Get hardware device incompatibility details for a specific EP. + /// @param ep_name The name of the execution provider to check. + /// @param hw The hardware device to check for incompatibility. + /// @param details Output: Incompatibility details including reasons for incompatibility if any. + /// @returns Status indicating success or failure. + Status GetHardwareDeviceEpIncompatibilityDetails(const std::string& ep_name, + const OrtHardwareDevice* hw, + std::unique_ptr& details) const; + + const std::vector& GetSortedOrtHardwareDevices() const; + + Status CreateSharedAllocator(const OrtEpDevice& ep_device, + OrtDeviceMemoryType mem_type, OrtAllocatorType allocator_type, + const OrtKeyValuePairs* allocator_options, OrtAllocator** allocator); + Status ReleaseSharedAllocator(const OrtEpDevice& ep_device, OrtDeviceMemoryType mem_type); + + const DataTransferManager& GetDataTransferManager() const { + return data_transfer_mgr_; + } +#endif // !defined(ORT_MINIMAL_BUILD) + + // return a shared allocator from a plugin EP or custom allocator added with RegisterAllocator + Status GetSharedAllocator(const OrtMemoryInfo& mem_info, OrtAllocator*& allocator); + + /// + /// Returns a copy of the configuration entries set by the application on environment creation. + /// + /// Primarily used by EP libraries to retrieve environment-level configurations, but could be used + /// more generally to specify global settings. + /// + /// Refer to OrtApi::CreateEnvWithOptions(). + /// + /// + OrtKeyValuePairs GetConfigEntries() const; + +#ifdef ORT_ENABLE_SESSION_THREADPOOL_CALLBACKS + /** + * Returns the per-session thread pool work callbacks, or nullptr if not set. + * + * Not safe to call concurrently with SetPerSessionWorkCallbacks. + */ + const OrtThreadPoolCallbacksConfig* GetPerSessionWorkCallbacks() const { + return per_session_work_callbacks_.has_value() + ? &per_session_work_callbacks_.value() + : nullptr; + } + + /** + * Sets thread pool work callbacks for per-session thread pools. + * Only affects sessions created after this call. Does not affect global thread pools. + * + * Not safe to call concurrently with GetPerSessionWorkCallbacks or session creation. + * Must be called before creating any sessions that should use the callbacks. + */ + Status SetPerSessionWorkCallbacks(const OrtThreadPoolCallbacksConfig& config); +#endif + + ~Environment(); private: ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(Environment); + Status Initialize(std::unique_ptr logging_manager, const OrtThreadingOptions* tp_options = nullptr, - bool create_global_thread_pools = false); + bool create_global_thread_pools = false, + const OrtKeyValuePairs* config_entries = nullptr); + + Status RegisterAllocatorImpl(AllocatorPtr allocator); + Status UnregisterAllocatorImpl(const OrtMemoryInfo& mem_info, bool error_if_not_found = true); + Status CreateSharedAllocatorImpl(const OrtEpDevice& ep_device, + const OrtMemoryInfo& memory_info, OrtAllocatorType allocator_type, + const OrtKeyValuePairs* allocator_options, OrtAllocator** allocator, + bool replace_existing); + + // Inserts (or assigns) a config entry into `config_entries_`. Locks `config_entries_mutex_`. + void InsertOrAssignConfigEntry(std::string key, std::string value); + + // Removes a config entry from `config_entries_`. Does nothing if the key does not exist. + // Locks `config_entries_mutex_`. + void RemoveConfigEntry(const std::string& key); std::unique_ptr logging_manager_; std::unique_ptr intra_op_thread_pool_; std::unique_ptr inter_op_thread_pool_; bool create_global_thread_pools_{false}; + + mutable std::mutex mutex_; + + // shared allocators from various sources. + // CreateAndRegisterAllocator[V2]: IAllocator allocators created by ORT + // RegisterAllocator: IAllocatorImplWrappingOrtAllocator custom allocators registered by the user. + // TODO: How can we detect registration of an allocator from an InferenceSession? + // OrtEpDevice: We create a default shared IAllocatorImplWrappingOrtAllocator for each OrtEpDevice memory info. std::vector shared_allocators_; + + // RegisterAllocator and CreateSharedAllocator pointers. Used for GetSharedAllocator. + // Every instance here is also in shared_allocators_. + std::unordered_set shared_ort_allocators_; + + // OrtAllocator wrapped CPUAllocator::DefaultInstance that is returned by GetSharedAllocator when no plugin EP is + // providing a CPU allocator. + std::unique_ptr default_cpu_ort_allocator_; + + using OrtAllocatorUniquePtr = std::unique_ptr>; + +#if !defined(ORT_MINIMAL_BUILD) + // register EPs that are built into the ORT binary so they can take part in AutoEP selection + // added to ep_libraries + Status CreateAndRegisterInternalEps(); + + Status RegisterExecutionProviderLibrary(const std::string& registration_name, + std::unique_ptr ep_library, + const std::vector& internal_factories = {}); + + struct EpInfo { + // calls EpLibrary::Load + // for each factory gets the OrtEpDevice instances and adds to execution_devices + // internal_factory is set if this is an internal EP + static Status Create(std::unique_ptr library_in, std::unique_ptr& out, + const std::vector& internal_factories = {}); + + // removes entries for this library from execution_devices + // calls EpLibrary::Unload + ~EpInfo(); + + std::unique_ptr library; + std::vector> execution_devices; + std::vector factories; + std::vector internal_factories; // factories that can create IExecutionProvider instances + std::vector data_transfers; // data transfer instances for this EP. + + private: + EpInfo() = default; + }; + + // registration name to EpInfo for library + std::unordered_map> ep_libraries_; + + // combined set of OrtEpDevices for all registered OrtEpFactory instances + // std::vector so we can use directly in GetEpDevices. + // inefficient when EPs are unregistered but that is not expected to be a common operation. + std::vector execution_devices_; + + // lookup set for internal EPs so we can create an IExecutionProvider directly + std::unordered_set internal_ep_factories_; + + DataTransferManager data_transfer_mgr_; // plugin EP IDataTransfer instances + +#endif // !defined(ORT_MINIMAL_BUILD) + + // Application-specified environment configuration entries + // The environment may add or remove an entry on EP library registration and unregistration, respectively. + OrtKeyValuePairs config_entries_; + mutable std::shared_mutex config_entries_mutex_; // Should be locked when accessing config_entries_ + + // Tracks the number of registered EP libraries that can create virtual devices. + // It is incremented when an EP library is registered with a name that ends in ".virtual". + // It is decremented when that EP library is unregistered. + // If it reaches 0, the config entry "allow_virtual_devices" is removed. + // + // This starts at 1 if user created an OrtEnv with the config "allow_virtual_devices" set to "1" + // to prevent removal of the config entry in that case. + size_t num_allow_virtual_device_uses_{}; + +#ifdef ORT_ENABLE_SESSION_THREADPOOL_CALLBACKS + std::optional per_session_work_callbacks_; +#endif }; + } // namespace onnxruntime diff --git a/include/onnxruntime/core/session/onnxruntime_c_api.h b/include/onnxruntime/core/session/onnxruntime_c_api.h index 6fef2448be0fe..f8cb2d6ad46de 100644 --- a/include/onnxruntime/core/session/onnxruntime_c_api.h +++ b/include/onnxruntime/core/session/onnxruntime_c_api.h @@ -38,7 +38,7 @@ * * This value is used by some API functions to behave as this version of the header expects. */ -#define ORT_API_VERSION 21 +#define ORT_API_VERSION 27 #ifdef __cplusplus extern "C" { @@ -52,8 +52,9 @@ extern "C" { #define _In_opt_ #define _In_opt_z_ #define _Out_ -#define _Outptr_ #define _Out_opt_ +#define _Outptr_ +#define _Outptr_opt_ #define _Inout_ #define _Inout_opt_ #define _Frees_ptr_opt_ @@ -61,9 +62,12 @@ extern "C" { #define _Ret_notnull_ #define _Check_return_ #define _Outptr_result_maybenull_ +#define _Outptr_result_maybenull_z_ #define _In_reads_(X) +#define _In_reads_opt_ #define _Inout_updates_(X) #define _Out_writes_(X) +#define _Out_writes_opt_(X) #define _Inout_updates_all_(X) #define _Out_writes_bytes_all_(X) #define _Out_writes_all_(X) @@ -83,12 +87,19 @@ extern "C" { #else #define ORT_EXPORT #endif -#define ORT_API_CALL _stdcall +#define ORT_API_CALL __stdcall #define ORT_MUST_USE_RESULT #define ORTCHAR_T wchar_t #else -// To make symbols visible on macOS/iOS -#ifdef __APPLE__ +// Make symbols visible on non-Windows platforms. The visibility attribute is +// needed when ORT is built as a shared library without a version script +// (e.g. when compiled within another project's build system). On non-Apple +// platforms, the default ORT build uses a generated version script +// (tools/ci_build/gen_def.py) that exports the needed symbols, so this was +// previously only enabled for __APPLE__. Expanding to __GNUC__ (GCC/Clang) +// covers additional embedding scenarios while remaining harmless when a +// version script is also in use. +#if defined(__GNUC__) #define ORT_EXPORT __attribute__((visibility("default"))) #else #define ORT_EXPORT @@ -142,6 +153,9 @@ extern "C" { // __VA_ARGS__ on Windows and Linux are different #define ORT_API(RETURN_TYPE, NAME, ...) RETURN_TYPE ORT_API_CALL NAME(__VA_ARGS__) NO_EXCEPTION +#define ORT_API_T(RETURN_TYPE, NAME, ...) \ + RETURN_TYPE(ORT_API_CALL* NAME)(__VA_ARGS__) NO_EXCEPTION + #define ORT_API_STATUS(NAME, ...) \ _Success_(return == 0) _Check_return_ _Ret_maybenull_ OrtStatusPtr ORT_API_CALL NAME(__VA_ARGS__) \ NO_EXCEPTION ORT_MUST_USE_RESULT @@ -199,7 +213,14 @@ typedef enum ONNXTensorElementDataType { ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT8E5M2FNUZ, // Non-IEEE floating-point format based on IEEE754 single-precision // Int4 types were introduced in ONNX 1.16. See https://onnx.ai/onnx/technical/int4.html ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT4, // maps to a pair of packed uint4 values (size == 1 byte) - ONNX_TENSOR_ELEMENT_DATA_TYPE_INT4 // maps to a pair of packed int4 values (size == 1 byte) + ONNX_TENSOR_ELEMENT_DATA_TYPE_INT4, // maps to a pair of packed int4 values (size == 1 byte) + // Float4 types were introduced in ONNX 1.18. See https://onnx.ai/onnx/technical/float4.html + ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT4E2M1, // maps to a pair of packed float4 values (size == 1 byte) + // Int2 types were introduced in ONNX 1.20. See https://onnx.ai/onnx/technical/int2.html + ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT2, // maps to 4 packed uint2 values (size == 1 byte) + ONNX_TENSOR_ELEMENT_DATA_TYPE_INT2, // maps to 4 packed int2 values (size == 1 byte) + // Float8E8M0 type introduced in ONNX 1.21. 8-bit float with 8 exponent bits, 0 mantissa bits, no sign bit. + ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT8E8M0, // Non-IEEE floating-point format, all values are powers of two } ONNXTensorElementDataType; // Synced with onnx TypeProto oneof @@ -255,6 +276,9 @@ typedef enum OrtErrorCode { ORT_NOT_IMPLEMENTED, ORT_INVALID_GRAPH, ORT_EP_FAIL, + ORT_MODEL_LOAD_CANCELED, + ORT_MODEL_REQUIRES_COMPILATION, + ORT_NOT_FOUND, } OrtErrorCode; typedef enum OrtOpAttrType { @@ -265,6 +289,8 @@ typedef enum OrtOpAttrType { ORT_OP_ATTR_FLOATS, ORT_OP_ATTR_STRING, ORT_OP_ATTR_STRINGS, + ORT_OP_ATTR_GRAPH, + ORT_OP_ATTR_TENSOR, } OrtOpAttrType; //! @} @@ -297,6 +323,7 @@ ORT_RUNTIME_CLASS(ThreadingOptions); ORT_RUNTIME_CLASS(ArenaCfg); ORT_RUNTIME_CLASS(PrepackedWeightsContainer); ORT_RUNTIME_CLASS(TensorRTProviderOptionsV2); +ORT_RUNTIME_CLASS(NvTensorRtRtxProviderOptions); ORT_RUNTIME_CLASS(CUDAProviderOptionsV2); ORT_RUNTIME_CLASS(CANNProviderOptions); ORT_RUNTIME_CLASS(DnnlProviderOptions); @@ -305,8 +332,24 @@ ORT_RUNTIME_CLASS(OpAttr); ORT_RUNTIME_CLASS(Logger); ORT_RUNTIME_CLASS(ShapeInferContext); ORT_RUNTIME_CLASS(LoraAdapter); - -#ifdef _WIN32 +ORT_RUNTIME_CLASS(ValueInfo); +ORT_RUNTIME_CLASS(Node); +ORT_RUNTIME_CLASS(Graph); +ORT_RUNTIME_CLASS(Model); +ORT_RUNTIME_CLASS(ModelCompilationOptions); +ORT_RUNTIME_CLASS(HardwareDevice); +ORT_RUNTIME_CLASS(EpDevice); +ORT_RUNTIME_CLASS(KeyValuePairs); +ORT_RUNTIME_CLASS(SyncStream); // Opaque class to create an onnxruntime::Stream. +ORT_RUNTIME_CLASS(ExternalInitializerInfo); +ORT_RUNTIME_CLASS(ExternalResourceImporter); // Capability object for external resource import +ORT_RUNTIME_CLASS(ExternalMemoryHandle); // EP-imported view of shared external allocation +ORT_RUNTIME_CLASS(ExternalSemaphoreHandle); // EP-imported view of shared external semaphore +ORT_RUNTIME_CLASS(DeviceEpIncompatibilityDetails); +ORT_RUNTIME_CLASS(EpAssignedSubgraph); +ORT_RUNTIME_CLASS(EpAssignedNode); + +#ifdef _MSC_VER typedef _Return_type_success_(return == 0) OrtStatus* OrtStatusPtr; #else typedef OrtStatus* OrtStatusPtr; @@ -319,16 +362,87 @@ typedef OrtStatus* OrtStatusPtr; * When an allocator is passed to any function, be sure that the allocator object is not destroyed until the last allocated object using it is freed. */ typedef struct OrtAllocator { - uint32_t version; ///< Must be initialized to ORT_API_VERSION - void*(ORT_API_CALL* Alloc)(struct OrtAllocator* this_, size_t size); ///< Returns a pointer to an allocated block of `size` bytes - void(ORT_API_CALL* Free)(struct OrtAllocator* this_, void* p); ///< Free a block of memory previously allocated with OrtAllocator::Alloc - const struct OrtMemoryInfo*(ORT_API_CALL* Info)(const struct OrtAllocator* this_); ///< Return a pointer to an ::OrtMemoryInfo that describes this allocator + uint32_t version; ///< Must be initialized to ORT_API_VERSION + + /// Returns a pointer to an allocated block of `size` bytes + void*(ORT_API_CALL* Alloc)(struct OrtAllocator* this_, size_t size); + + /// Free a block of memory previously allocated with OrtAllocator::Alloc + void(ORT_API_CALL* Free)(struct OrtAllocator* this_, void* p); + + /// Return a pointer to an ::OrtMemoryInfo that describes this allocator + const struct OrtMemoryInfo*(ORT_API_CALL* Info)(const struct OrtAllocator* this_); /** * @brief Optional allocation function to use for memory allocations made during session initialization. * Use this function if you want to separate allocations made by ORT during Run() calls from - * those made during session initialization. This allows for separate memory management strategies for these allocations. + * those made during session initialization. This allows for separate memory management strategies for these + * allocations. + * + * \return pointer to an allocated block of `size` bytes. nullptr if size was 0 or allocation failed. + * + * \since 1.18 + */ + void*(ORT_API_CALL* Reserve)(struct OrtAllocator* this_, size_t size); + + /** + * @brief Function used to get the statistics of the allocator. + * + * Return a pointer to the OrtKeyValuePairs structure that contains the statistics of the allocator. + * The user should call OrtApi::ReleaseKeyValuePairs when done. + * + * Current known keys are: + * - Limit: Bytes limit of the allocator. -1 if no limit is set. + * - InUse: Number of bytes in use. + * - TotalAllocated: The total number of allocated bytes by the allocator. + * - MaxInUse: The maximum bytes in use. + * - NumAllocs: Number of allocations. + * - NumReserves: Number of reserves. (Number of calls to Reserve() in arena-based allocators) + * - NumArenaExtensions: Number of arena extensions (Relevant only for arena based allocators) + * - NumArenaShrinkages: Number of arena shrinkages (Relevant only for arena based allocators) + * - MaxAllocSize: The max single allocation seen. + * + * The allocator is free to add other entries as appropriate. + * + * \note Implementation of this function is optional and GetStats may be set to a nullptr. + * If the OrtAllocator is wrapping an internal ORT allocator that does not implement GetStats + * the returned OrtKeyValuePairs instance will be empty. + * + * \since 1.23 + */ + ORT_API2_STATUS(GetStats, _In_ const struct OrtAllocator* this_, _Outptr_ OrtKeyValuePairs** out); + + /** \brief Allocate using a stream. + * + * If the allocator is stream aware this performs allocation using a stream. + * + * Alloc will be used if this is nullptr. + * + * \param[in] this_ OrtAllocator instance + * \param[in] size Size of the allocation in bytes. nullptr if size was 0 or allocation failed. + * \param[in] stream The stream to allocate on. + * + * \return pointer to an allocated block of `size` bytes + * + * \note Implementation of this function is optional and AllocOnStream may be set to a nullptr. + * \since 1.23 + */ + void*(ORT_API_CALL* AllocOnStream)(struct OrtAllocator* this_, size_t size, OrtSyncStream* stream); + + /** \brief Release unused memory held by the allocator back to the system. + * + * For arena-based allocators, this frees allocation regions that are completely unused. + * For mempool-based allocators, this trims the pool to a configured minimum. + * For non-arena allocators this is a no-op. + * + * \param[in] this_ OrtAllocator instance + * + * \return nullptr on success, or an OrtStatus* on failure. + * + * \note Implementation of this function is optional and Shrink may be set to a nullptr. + * Callers must check for nullptr before invoking. + * \since 1.25 */ - void*(ORT_API_CALL* Reserve)(struct OrtAllocator* this_, size_t size); ///< Returns a pointer to an allocated block of `size` bytes + ORT_API2_STATUS(Shrink, _In_ struct OrtAllocator* this_); } OrtAllocator; typedef void(ORT_API_CALL* OrtLoggingFunction)( @@ -344,6 +458,7 @@ typedef enum GraphOptimizationLevel { ORT_DISABLE_ALL = 0, ORT_ENABLE_BASIC = 1, ORT_ENABLE_EXTENDED = 2, + ORT_ENABLE_LAYOUT = 3, ORT_ENABLE_ALL = 99 } GraphOptimizationLevel; @@ -375,27 +490,146 @@ typedef struct OrtCustomOp OrtCustomOp; typedef enum OrtAllocatorType { OrtInvalidAllocator = -1, OrtDeviceAllocator = 0, - OrtArenaAllocator = 1 + OrtArenaAllocator = 1, + OrtReadOnlyAllocator = 2, } OrtAllocatorType; /** \brief Memory types for allocated memory, execution provider specific types should be extended in each provider. */ // Whenever this struct is updated, please also update the MakeKey function in onnxruntime / core / framework / execution_provider.cc typedef enum OrtMemType { - OrtMemTypeCPUInput = -2, ///< Any CPU memory used by non-CPU execution provider - OrtMemTypeCPUOutput = -1, ///< CPU accessible memory outputted by non-CPU execution provider, i.e. CUDA_PINNED - OrtMemTypeCPU = OrtMemTypeCPUOutput, ///< Temporary CPU accessible memory allocated by non-CPU execution provider, i.e. CUDA_PINNED - OrtMemTypeDefault = 0, ///< The default allocator for execution provider + /// Any CPU memory used by non-CPU execution provider + OrtMemTypeCPUInput = -2, + /// CPU accessible memory outputted by non-CPU execution provider, i.e. HOST_ACCESSIBLE + OrtMemTypeCPUOutput = -1, + /// CPU accessible memory allocated by non-CPU execution provider, i.e. HOST_ACCESSIBLE + OrtMemTypeCPU = OrtMemTypeCPUOutput, + /// The default allocator for execution provider + OrtMemTypeDefault = 0, } OrtMemType; +/** \brief This matches OrtDevice::MemoryType values */ +typedef enum OrtDeviceMemoryType { + OrtDeviceMemoryType_DEFAULT = 0, ///< Device memory + OrtDeviceMemoryType_HOST_ACCESSIBLE = 5, ///< Shared/pinned memory for transferring between CPU and the device +} OrtDeviceMemoryType; + /** \brief This mimics OrtDevice type constants so they can be returned in the API */ typedef enum OrtMemoryInfoDeviceType { OrtMemoryInfoDeviceType_CPU = 0, OrtMemoryInfoDeviceType_GPU = 1, - OrtMemoryInfoDeviceType_FPGA = 2 + OrtMemoryInfoDeviceType_FPGA = 2, + OrtMemoryInfoDeviceType_NPU = 3, } OrtMemoryInfoDeviceType; +typedef enum OrtHardwareDeviceType { + OrtHardwareDeviceType_CPU, + OrtHardwareDeviceType_GPU, + OrtHardwareDeviceType_NPU +} OrtHardwareDeviceType; + +/** \brief These are the default EP selection policies used by ORT when doing automatic EP selection. + */ +typedef enum OrtExecutionProviderDevicePolicy { + OrtExecutionProviderDevicePolicy_DEFAULT, + OrtExecutionProviderDevicePolicy_PREFER_CPU, + OrtExecutionProviderDevicePolicy_PREFER_NPU, + OrtExecutionProviderDevicePolicy_PREFER_GPU, + OrtExecutionProviderDevicePolicy_MAX_PERFORMANCE, + OrtExecutionProviderDevicePolicy_MAX_EFFICIENCY, + OrtExecutionProviderDevicePolicy_MIN_OVERALL_POWER, +} OrtExecutionProviderDevicePolicy; + +/** \brief Reasons why an execution provider might not be compatible with a device + */ +typedef enum OrtDeviceEpIncompatibilityReason { + OrtDeviceEpIncompatibility_NONE = 0, + OrtDeviceEpIncompatibility_DRIVER_INCOMPATIBLE = 1 << 0, + OrtDeviceEpIncompatibility_DEVICE_INCOMPATIBLE = 1 << 1, + OrtDeviceEpIncompatibility_MISSING_DEPENDENCY = 1 << 2, + OrtDeviceEpIncompatibility_UNKNOWN = 1 << 31 +} OrtDeviceEpIncompatibilityReason; + +/** \brief Delegate to allow providing custom OrtEpDevice selection logic + * + * This delegate is called by the EP selection code to allow the user to provide custom device selection logic. + * The user can use this to select OrtEpDevice instances from the list of available devices. + * + * \param ep_devices The list of available devices. + * \param num_devices The number of available devices. + * \param model_metadata The model metadata. + * \param runtime_metadata The runtime metadata. May be nullptr. + * \param selected Pre-allocated array to populate with selected OrtEpDevice pointers from ep_devices. + * \param max_selected The maximum number of devices that can be selected in the pre-allocated array. + Currently the maximum is 8. + * \param num_selected The number of selected devices. + * \param state Opaque pointer. Required to use the delegate from other languages like C# and python. + * + * \return OrtStatus* Selection status. Return nullptr on success. + * Use CreateStatus to provide error info. Use ORT_FAIL as the error code. + * ORT will release the OrtStatus* if not null. + */ +typedef OrtStatus*(ORT_API_CALL* EpSelectionDelegate)(_In_ const OrtEpDevice** ep_devices, + _In_ size_t num_devices, + _In_ const OrtKeyValuePairs* model_metadata, + _In_opt_ const OrtKeyValuePairs* runtime_metadata, + _Inout_ const OrtEpDevice** selected, + _In_ size_t max_selected, + _Out_ size_t* num_selected, + _In_ void* state); + +/** \brief Function called by ORT to write a buffer to a custom destination (e.g., file, stream, etc.). + * + * \param state Opaque pointer holding the user's state. + * \param buffer The buffer to write. + * \param buffer_num_bytes The size of the buffer in bytes. + * + * \return OrtStatus* Write status. Return nullptr on success. + * Use CreateStatus to provide error info. Use ORT_FAIL as the error code. + * ORT will release the OrtStatus* if not null. + */ +typedef OrtStatus*(ORT_API_CALL* OrtWriteBufferFunc)(_In_ void* state, + _In_ const void* buffer, + _In_ size_t buffer_num_bytes); + +/** \brief Function called by ORT to allow user to specify how an initializer should be saved, that is, either + * written to an external file or stored within the model. ORT calls this function for every initializer when + * generating a model. + * + * If the function implementation sets the `new_external_info` output parameter to NULL, ORT stores the initializer data + * within the generated model. + * + * Otherwise, if the function implementation sets `new_external_info` to a valid OrtExternalInitializerInfo instance, + * ORT assumes that this function stores the initializer data in a file. In this case, ORT configures the model's + * initializer to point to the location specified by the `new_external_info` output parameter. + * + * \param[in] state Opaque pointer holding the user's state. + * \param[in] initializer_name The initializer's name as a null-terminated string. + * \param[in] initializer_value OrtValue containing the initializer's data, type, and shape. + * \param[in] external_info If the initializer is originally stored in an external file, `external_info` contains + * the file path, file offset, and the data's byte size within the file. Otherwise, + * `external_info` is NULL if the initializer is not originally stored in a file. + * \param[out] new_external_info Output parameter set to a new OrtExternalInitializerInfo instance indicating the + * location where the function implementation stored the initializer data. + * The function implementation must use `OrtApi::CreateExternalInitializerInfo()` to + * create the instance. + * If the function implementation sets `new_external_info` to NULL, + * ORT stores the initializers within the model. + * + * \note ORT takes ownership of the `new_external_info` output parameter. + * + * \return OrtStatus* Write status. Return nullptr on success. + * Use CreateStatus to provide error info. Use ORT_FAIL as the error code. + * ORT will release the OrtStatus* if not null. + */ +typedef OrtStatus*(ORT_API_CALL* OrtGetInitializerLocationFunc)( + _In_ void* state, + _In_ const char* initializer_name, + _In_ const OrtValue* initializer_value, + _In_opt_ const OrtExternalInitializerInfo* external_info, + _Outptr_result_maybenull_ OrtExternalInitializerInfo** new_external_info); + /** \brief Algorithm to use for cuDNN Convolution Op */ typedef enum OrtCudnnConvAlgoSearch { @@ -517,7 +751,7 @@ typedef struct OrtROCMProviderOptions { */ int device_id; - /** \brief ROCM MIOpen Convolution algorithm exaustive search option. + /** \brief ROCM MIOpen Convolution algorithm exhaustive search option. * Defaults to 0 (false). */ int miopen_conv_exhaustive_search; @@ -615,14 +849,31 @@ typedef struct OrtTensorRTProviderOptions { typedef struct OrtMIGraphXProviderOptions { int device_id; // hip device id. int migraphx_fp16_enable; // MIGraphX FP16 precision. Default 0 = false, nonzero = true + int migraphx_fp8_enable; // MIGraphX FP8 precision. Default 0 = false, nonzero = true int migraphx_int8_enable; // MIGraphX INT8 precision. Default 0 = false, nonzero = true - int migraphx_use_native_calibration_table; // MIGraphx INT8 cal table. Default 0 = false, noznero = true + int migraphx_use_native_calibration_table; // MIGraphx INT8 cal table. Default 0 = false, nonzero = true const char* migraphx_int8_calibration_table_name; // MIGraphx INT8 calibration table name - int migraphx_save_compiled_model; // migraphx save compiled model. Default 0 = false, noznero = true + int migraphx_save_compiled_model; // migraphx save compiled model. Default 0 = false, nonzero = true const char* migraphx_save_model_path; // migraphx model path name - int migraphx_load_compiled_model; // migraphx int8 cal table. Default 0 = false, noznero = true + int migraphx_load_compiled_model; // migraphx int8 cal table. Default 0 = false, nonzero = true const char* migraphx_load_model_path; // migraphx model path name - bool migraphx_exhaustive_tune; // migraphx tuned compile Default = false + bool migraphx_exhaustive_tune; // MIGraphX tuned compile. Default = false, nonzero = true + + /** \brief MIGraphX memory limit (To use all possible memory pass in maximum size_t) + * Defaults to SIZE_MAX. + * \note If a ::OrtArenaCfg has been applied, it will override this field + */ + size_t migraphx_mem_limit; + + /** \brief Strategy used to grow the memory arena + * 0 = kNextPowerOfTwo
+ * 1 = kSameAsRequested
+ * Defaults to 0. + * \note If a ::OrtArenaCfg has been applied, it will override this field + */ + int migraphx_arena_extend_strategy; + + // This is the legacy struct and don't add new fields here. } OrtMIGraphXProviderOptions; /** \brief OpenVINO Provider Options @@ -665,6 +916,18 @@ typedef struct OrtApi OrtApi; struct OrtTrainingApi; typedef struct OrtTrainingApi OrtTrainingApi; +struct OrtModelEditorApi; +typedef struct OrtModelEditorApi OrtModelEditorApi; + +struct OrtCompileApi; +typedef struct OrtCompileApi OrtCompileApi; + +struct OrtInteropApi; +typedef struct OrtInteropApi OrtInteropApi; + +struct OrtEpApi; +typedef struct OrtEpApi OrtEpApi; + /** \brief The helper interface to get the right version of OrtApi * * Get a pointer to this structure through ::OrtGetApiBase @@ -721,6 +984,69 @@ typedef OrtCustomThreadHandle (*OrtCustomCreateThreadFn)(void* ort_custom_thread */ typedef void (*OrtCustomJoinThreadFn)(OrtCustomThreadHandle ort_custom_thread_handle); +/** \brief Thread pool work enqueue callback + * + * Called when work is about to be enqueued to a thread pool worker thread. + * This runs on the thread that is submitting the work. + * \param[in] user_context The user-provided context passed when configuring callbacks + * \return Callback-specific data that will be passed to the configured + * OrtThreadPoolCallbacksConfig::on_start_work and OrtThreadPoolCallbacksConfig::on_stop_work. + * May return NULL. + */ +typedef _Ret_maybenull_ void* (*OrtThreadPoolWorkEnqueueFn)(_In_opt_ void* user_context)NO_EXCEPTION; + +/** \brief Thread pool work start callback + * + * Called when a thread is about to start executing work. + * This typically runs on a worker thread, but may also run on the submitting thread + * when the work queue is full and work is executed synchronously. + * \param[in] user_context The user-provided context passed when configuring callbacks + * \param[in] enqueue_data Data returned by the corresponding OrtThreadPoolCallbacksConfig::on_enqueue call + */ +typedef void (*OrtThreadPoolWorkStartFn)(_In_opt_ void* user_context, _In_opt_ void* enqueue_data) NO_EXCEPTION; + +/** \brief Thread pool work stop callback + * + * Called when a thread has finished executing work. + * This typically runs on a worker thread, but may also run on the submitting thread + * when the work queue is full and work is executed synchronously. + * Guaranteed to be called regardless of whether the work finishes successfully or not. + * \param[in] user_context The user-provided context passed when configuring callbacks + * \param[in] enqueue_data Data returned by the corresponding OrtThreadPoolCallbacksConfig::on_enqueue call + */ +typedef void (*OrtThreadPoolWorkStopFn)(_In_opt_ void* user_context, _In_opt_ void* enqueue_data) NO_EXCEPTION; + +/** \brief Thread pool work abandon callback + * + * Called when enqueued work is abandoned (revoked or rejected) without execution. + * This allows the caller to free any resources associated with enqueue_data. + * \param[in] user_context The user-provided context passed when configuring callbacks + * \param[in] enqueue_data Data returned by the corresponding OrtThreadPoolCallbacksConfig::on_enqueue call + */ +typedef void (*OrtThreadPoolWorkAbandonFn)(_In_opt_ void* user_context, _In_opt_ void* enqueue_data) NO_EXCEPTION; + +/** \brief Configuration for thread pool work callbacks. + * + * A versioned struct that bundles all thread pool callback function pointers and a user context. + * Pass to OrtApi::SetPerSessionThreadPoolCallbacks. + * + * \note The version field must be set to ORT_API_VERSION. + * \note New fields MUST only be appended at the end of this struct. + * + * \since Version 1.25. + */ +typedef struct OrtThreadPoolCallbacksConfig { + uint32_t version; /**< Must be ORT_API_VERSION */ + OrtThreadPoolWorkEnqueueFn on_enqueue; /**< Called when work is enqueued. May be NULL. */ + OrtThreadPoolWorkStartFn on_start_work; /**< Called when work starts. May be NULL. */ + OrtThreadPoolWorkStopFn on_stop_work; /**< Called when work completes. May be NULL. */ + OrtThreadPoolWorkAbandonFn on_abandon; /**< Called when work is abandoned. May be NULL. */ + void* user_context; /**< User-provided context passed to all callbacks. May be NULL. + Must remain valid for the lifetime of the session. + Subject to concurrent invocations from multiple threads + and must be thread-safe. May affect inference performance. */ +} OrtThreadPoolCallbacksConfig; + typedef OrtStatus*(ORT_API_CALL* RegisterCustomOpsFn)(OrtSessionOptions* options, const OrtApiBase* api); /** \brief Callback function for RunAsync @@ -732,6 +1058,238 @@ typedef OrtStatus*(ORT_API_CALL* RegisterCustomOpsFn)(OrtSessionOptions* options */ typedef void (*RunAsyncCallbackFn)(void* user_data, OrtValue** outputs, size_t num_outputs, OrtStatusPtr status); +/** \brief External memory handle type for importing GPU resources. + * + * \todo Add Linux DMA-BUF file descriptor for embedded GPU memory sharing + * + * \since Version 1.24. + */ +typedef enum OrtExternalMemoryHandleType { + ORT_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE = 0, /**< Shared HANDLE from ID3D12Device::CreateSharedHandle(resource) */ + ORT_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_HEAP = 1, /**< Shared HANDLE from ID3D12Device::CreateSharedHandle(heap) */ + ORT_EXTERNAL_MEMORY_HANDLE_TYPE_VK_MEMORY_WIN32 = 2, /**< Shared HANDLE from vkGetMemoryWin32HandleKHR, non-dedicated allocation */ + ORT_EXTERNAL_MEMORY_HANDLE_TYPE_VK_MEMORY_OPAQUE_FD = 3, /**< File descriptor from vkGetMemoryOpaqueFdKHR, non-dedicated allocation */ +} OrtExternalMemoryHandleType; + +/** \brief Descriptor for importing external memory. + * + * \note The version field must be set to ORT_API_VERSION. + * This ensures forward compatibility as fields may be added in future versions. + * + * \since Version 1.24. + */ +typedef struct OrtExternalMemoryDescriptor { + uint32_t version; /**< Must be ORT_API_VERSION */ + OrtExternalMemoryHandleType handle_type; /**< Type of the external memory handle */ + void* native_handle; /**< Platform-specific handle (e.g., Windows HANDLE) */ + size_t size_bytes; /**< Total size in bytes of the external allocation */ + size_t offset_bytes; /**< Offset in bytes into the allocation (default 0). + Base offset for the imported memory region. */ +} OrtExternalMemoryDescriptor; + +/** \brief External semaphore type for GPU synchronization. + * + * \since Version 1.24. + */ +typedef enum OrtExternalSemaphoreType { + ORT_EXTERNAL_SEMAPHORE_D3D12_FENCE = 0, /**< Shared HANDLE from ID3D12Device::CreateSharedHandle(fence) */ + ORT_EXTERNAL_SEMAPHORE_VK_TIMELINE_SEMAPHORE_WIN32 = 1, /**< Shared HANDLE from vkGetSemaphoreWin32HandleKHR of a VkSemaphore created as VK_SEMAPHORE_TYPE_TIMELINE */ + ORT_EXTERNAL_SEMAPHORE_VK_TIMELINE_SEMAPHORE_OPAQUE_FD = 2, /**< File descriptor from vkGetSemaphoreFdKHR of a VkSemaphore created as VK_SEMAPHORE_TYPE_TIMELINE */ +} OrtExternalSemaphoreType; + +/** \brief Descriptor for importing external semaphores. + * + * \note The version field must be set to ORT_API_VERSION. + * This ensures forward compatibility as fields may be added in future versions. + * + * \since Version 1.24. + */ +typedef struct OrtExternalSemaphoreDescriptor { + uint32_t version; /**< Must be ORT_API_VERSION */ + OrtExternalSemaphoreType type; /**< Type of the external semaphore */ + void* native_handle; /**< Platform-specific handle (e.g., Windows HANDLE) */ +} OrtExternalSemaphoreDescriptor; + +/** \brief Graphics API type for interop configuration. + * + * Specifies the graphics API used for GPU interop with the execution provider. + * This enables synchronization between graphics workloads (e.g., rendering, compute shaders) + * and ONNX Runtime inference. + * + * \since Version 1.25. + */ +typedef enum OrtGraphicsApi { + ORT_GRAPHICS_API_NONE = 0, /**< No graphics interop (default) */ + ORT_GRAPHICS_API_D3D12 = 1, /**< Direct3D 12 interop */ + ORT_GRAPHICS_API_VULKAN = 2, /**< Vulkan interop */ +} OrtGraphicsApi; + +/** \brief Configuration for initializing graphics interop on an EP factory. + * + * This structure contains all parameters needed to set up graphics interop between + * ONNX Runtime and an external graphics API (D3D12, Vulkan). The factory stores this + * configuration and uses it when creating synchronization streams. + * + * Design rationale: + * - Single init function with all required params to avoid multiple init signatures + * - Factory stores the context and uses it in stream creation + * - Supports extensibility via additional_options for future requirements + * + * Example usage for D3D12: + * \code + * const OrtInteropApi* interop_api = ort_api->GetInteropApi(); + * OrtGraphicsInteropConfig config = {0}; + * config.version = ORT_API_VERSION; + * config.graphics_api = ORT_GRAPHICS_API_D3D12; + * config.command_queue = my_d3d12_command_queue; // ID3D12CommandQueue* + * status = interop_api->InitGraphicsInteropForEpDevice(ep_device, &config); + * \endcode + * + * \note The version field must be set to ORT_API_VERSION. + * This ensures forward compatibility as fields may be added in future versions. + * + * \since Version 1.25. + */ +typedef struct OrtGraphicsInteropConfig { + uint32_t version; /**< Must be ORT_API_VERSION */ + OrtGraphicsApi graphics_api; /**< The graphics API to use for interop */ + + /** \brief Command queue/submission queue for graphics workloads (optional). + * + * Optional. When provided, the factory may use it for efficient GPU-side synchronization + * with inference streams (performance optimization). When null, the Interop API still + * works; streams use the default context. + * + * For D3D12: ID3D12CommandQueue* + * For Vulkan: pass NULL + */ + void* command_queue; + + /** \brief Additional API-specific options (optional). + * + * Can be used for future extensibility without changing the struct layout. + * For example, D3D12 fence sharing flags or provider-specific options like + * onnxruntime::nv::provider_option_names::kExternalComputeQueueDataParamNV_data + * for Vulkan interop for the NvTensorRTRTX provider. + */ + const OrtKeyValuePairs* additional_options; +} OrtGraphicsInteropConfig; + +/** \brief Descriptor for creating a tensor from imported external memory. + * + * \note The version field must be set to ORT_API_VERSION. + * This ensures forward compatibility as fields may be added in future versions. + * + * \since Version 1.24. + */ +typedef struct OrtExternalTensorDescriptor { + uint32_t version; /**< Must be ORT_API_VERSION */ + ONNXTensorElementDataType element_type; /**< Data type of tensor elements */ + const int64_t* shape; /**< Array of dimension sizes */ + size_t rank; /**< Number of dimensions */ + size_t offset_bytes; /**< Additional offset within imported memory (default 0). + Applied relative to OrtExternalMemoryDescriptor::offset_bytes. + Enables multiple tensors from the same imported memory handle. */ +} OrtExternalTensorDescriptor; + +/* + * Public enum for compiled model compatibility across EPs. + */ +typedef enum OrtCompiledModelCompatibility { + OrtCompiledModelCompatibility_EP_NOT_APPLICABLE = 0, + OrtCompiledModelCompatibility_EP_SUPPORTED_OPTIMAL, + OrtCompiledModelCompatibility_EP_SUPPORTED_PREFER_RECOMPILATION, + OrtCompiledModelCompatibility_EP_UNSUPPORTED, +} OrtCompiledModelCompatibility; + +/** \brief Configuration options for creating an OrtEnv. + * + * \note The version field must be set to ORT_API_VERSION. + * This ensures forward compatibility as fields may be added in future versions. + * + * \since Version 1.24. + */ +typedef struct OrtEnvCreationOptions { + uint32_t version; ///< Must be set to ORT_API_VERSION + + /** \brief The logging severity level for the environment. Must be set to a value from OrtLoggingLevel. + * + * \note Logging messages which are less severe than the `logging_severity_level` are not emitted. + * + * \note Serves as the default logging severity level for session creation and runs. + * Use OrtApi::SetSessionLogSeverityLevel to set a logging severity level for the creation of specific session. + * Use OrtApi::RunOptionsSetRunLogSeverityLevel to set a logging severity level for a specific session run. + * + * \since Version 1.24. + */ + int32_t logging_severity_level; + + /** \brief The log identifier. Must be set to a valid UTF-8 null-terminated string. + * + * \note This string identifier is copied by ORT. + * + * \since Version 1.24. + */ + const char* log_id; + + /** \brief Optional custom logging function. May be set to NULL. + * + * \note The OrtEnvCreationOptions::custom_logging_param is provided as the first argument to this logging function. + * This allows passing custom state into the logging function. + * + * \note This function is only called when a message's severity meets or exceeds the set logging severity level. + * + * \since Version 1.24. + */ + OrtLoggingFunction custom_logging_function; + + /** \brief Optional state to pass as the first argument to OrtEnvCreationOptions::custom_logger_function. + * May be set to NULL. + * + * \since Version 1.24. + */ + void* custom_logging_param; + + /** \brief Optional threading options for creating an environment with global thread pools shared across sessions. + * May be set to NULL. + * + * \note The OrtThreadingOptions instance is copied by ORT. + * + * \note Use OrtApi::CreateThreadingOptions() to create an instance of OrtThreadingOptions. + * + * \note Use this in conjunction with OrtApi::DisablePerSessionThreads or else the session will use its own + * thread pools. + * + * \since Version 1.24. + */ + const OrtThreadingOptions* threading_options; + + /** \brief Optional environment configuration entries represented as string key-value pairs. May be set to NULL. + * + * \note The OrtKeyValuePairs instance is copied by ORT. + * + * \note Refer to onnxruntime_env_config_keys.h for common config entry keys and their supported values. + * + * \note An application provides environment-level configuration options for execution provider libraries by + * using keys with the prefix 'ep_factory.\\.'. Ex: the key 'ep_factory.my_ep.some_ep_key' represents + * a key named 'some_ep_key' that is meant to be consumed by an execution provider named 'my_ep'. Refer to + * the specific execution provider's documentation for valid keys and values. + * + * \note An application may separately set session-level configuration options for execution providers via other APIs + * such as SessionOptionsAppendExecutionProvider_V2, which store configuration entries within OrtSessionOptions. + * If an environment-level configuration conflicts with a session-level configuration, then + * precedence is determined by the execution provider library itself. + * + * \since Version 1.24. + */ + const OrtKeyValuePairs* config_entries; + + // + // End of fields available in ORT 1.24 + // + +} OrtEnvCreationOptions; + /** \brief The C API * * All C API functions are defined inside this structure as pointers to functions. @@ -847,7 +1405,8 @@ struct OrtApi { * * \snippet{doc} snippets.dox OrtStatus Return Value */ - ORT_API2_STATUS(CreateSessionFromArray, _In_ const OrtEnv* env, _In_ const void* model_data, size_t model_data_length, + ORT_API2_STATUS(CreateSessionFromArray, _In_ const OrtEnv* env, + _In_ const void* model_data, size_t model_data_length, _In_ const OrtSessionOptions* options, _Outptr_ OrtSession** out); /** \brief Run the model in an ::OrtSession @@ -1340,6 +1899,8 @@ struct OrtApi { * Create a tensor with user's buffer. You can fill the buffer either before calling this function or after. * p_data is owned by caller. ReleaseValue won't release p_data. * + * If you wish to transfer ownership of p_data to ORT use CreateTensorWithDataAndDeleterAsOrtValue. + * * \param[in] info Memory description of where the p_data buffer resides (CPU vs GPU etc). * \param[in] p_data Pointer to the data buffer. * \param[in] p_data_len The number of bytes in the data buffer. @@ -1618,7 +2179,7 @@ struct OrtApi { */ ORT_API2_STATUS(MemoryInfoGetName, _In_ const OrtMemoryInfo* ptr, _Out_ const char** out); - /** \brief Get the id from ::OrtMemoryInfo + /** \brief Get the device id from ::OrtMemoryInfo */ ORT_API2_STATUS(MemoryInfoGetId, _In_ const OrtMemoryInfo* ptr, _Out_ int* out); @@ -1997,7 +2558,8 @@ struct OrtApi { /** \brief Get the value type from an ::OrtMapTypeInfo * * \param[in] map_type_info - * \param[out] type_info + * \param[out] type_info A copy of the OrtTypeInfo for the map value type. + * The user must free this value with ReleaseTypeInfo. * * \snippet{doc} snippets.dox OrtStatus Return Value */ @@ -2012,7 +2574,8 @@ struct OrtApi { * This is used by WinML to support model reflection APIs. * * \param[in] sequence_type_info - * \param[out] type_info + * \param[out] type_info A copy of the OrtTypeInfo for the sequence element type. + * The user must free this value with ReleaseTypeInfo. * * \snippet{doc} snippets.dox OrtStatus Return Value */ @@ -2293,6 +2856,8 @@ struct OrtApi { /// @{ /** \brief Create an allocator for an ::OrtSession following an ::OrtMemoryInfo + * + * The allocator wraps the internal allocator from the OrtSession and becomes invalid when the session does. * * \param[in] session * \param[in] mem_info valid ::OrtMemoryInfo instance @@ -2804,7 +3369,7 @@ struct OrtApi { * crossing which the current chunk is chunked into 2. * "initial_growth_chunk_size_bytes": (Possible) Size of the second allocation in the arena. * Only relevant if arena strategy is `kNextPowerOfTwo`. Use -1 to allow ORT to choose the default. - * "max_power_of_two_extend_bytes": The maximum enxtend size if arena strategy is `kNextPowerOfTwo`. + * "max_power_of_two_extend_bytes": The maximum extend size if arena strategy is `kNextPowerOfTwo`. * It is not an allocation limit, it is only a limit for extension when requested byte is less than the limit. * When requested bytes is more than the limit, allocator will still return as requested. * Use -1 to allow ORT to choose the default 1GB for max_power_of_two_extend_bytes. @@ -2887,7 +3452,8 @@ struct OrtApi { * \snippet{doc} snippets.dox OrtStatus Return Value */ ORT_API2_STATUS(CreateSessionWithPrepackedWeightsContainer, _In_ const OrtEnv* env, _In_ const ORTCHAR_T* model_path, - _In_ const OrtSessionOptions* options, _Inout_ OrtPrepackedWeightsContainer* prepacked_weights_container, + _In_ const OrtSessionOptions* options, + _Inout_ OrtPrepackedWeightsContainer* prepacked_weights_container, _Outptr_ OrtSession** out); /** \brief Create session from memory with prepacked weights container @@ -2910,7 +3476,8 @@ struct OrtApi { */ ORT_API2_STATUS(CreateSessionFromArrayWithPrepackedWeightsContainer, _In_ const OrtEnv* env, _In_ const void* model_data, size_t model_data_length, - _In_ const OrtSessionOptions* options, _Inout_ OrtPrepackedWeightsContainer* prepacked_weights_container, + _In_ const OrtSessionOptions* options, + _Inout_ OrtPrepackedWeightsContainer* prepacked_weights_container, _Outptr_ OrtSession** out); /// @} @@ -3536,7 +4103,8 @@ struct OrtApi { * * \param[in] name Name of the attribute * \param[in] data Data content of the attribute - * \param[in] len Number of bytes stored in data + * \param[in] len Number of bytes stored in data for ORT_OP_ATTR_STRING. + Number of elements if data represents an array (e.g., ORT_OP_ATTR_INTS). Otherwise, set to 1. * \param[in] type Data type * \param[out] op_attr Attribute that has been created, which must be released by OrtApi::ReleaseOpAttr * @@ -3563,9 +4131,9 @@ struct OrtApi { * \param[in] op_name Operator name * \param[in] domain Operator domain * \param[in] version Operator opset version - * \param[in] type_constraint_names Name of the type contraints, such as "T" or "T1" - * \param[in] type_constraint_values Type of each contraints - * \param[in] type_constraint_count Number of contraints + * \param[in] type_constraint_names Name of the type constraints, such as "T" or "T1" + * \param[in] type_constraint_values Type of each constraints + * \param[in] type_constraint_count Number of constraints * \param[in] attr_values Attributes used to initialize the operator * \param[in] attr_count Number of the attributes * \param[in] input_count Number of inputs @@ -3623,72 +4191,114 @@ struct OrtApi { * \param[in] provider_options_values - values to configure the provider options * \param[in] num_keys - number of keys passed in * - * Currently supported providers: - * QNN - * SNPE - * XNNPACK + * Currently supported provider names: + * QNNExecutionProvider (or QNN) + * OpenVINOExecutionProvider (or OpenVINO) + * XnnpackExecutionProvider (or XNNPACK) + * WebNNExecutionProvider (or WEBNN) + * WebGpuExecutionProvider (or WebGPU) + * AzureExecutionProvider (or AZURE) + * JsExecutionProvider (or JS) + * VitisAIExecutionProvider (or VitisAI) + * CoreMLExecutionProvider (or CoreML) * * Note: If an execution provider has a dedicated SessionOptionsAppendExecutionProvider_ function * that should be used to add it. * * QNN supported keys: - * "backend_path": file path to QNN backend library. - * "profiling_level": QNN profiling level, options: "off", "basic", "detailed". Default to off. + * "backend_type": Type of QNN backend. Specifies a backend path that is the associated QNN backend library file + * name. E.g., given backend type "htp", on Windows, the backend path would be "QnnHtp.dll", and on other + * platforms, it would be "libQnnHtp.so". Mutually exclusive with "backend_path". + * Available options: + * -# "cpu" + * -# "gpu" + * -# "htp": Default. + * -# "saver" + * -# "ir" + * "backend_path": File path to QNN backend library. Mutually exclusive with "backend_type". + * "profiling_level": QNN profiling level. + * Available options: + * -# "off": Default. + * -# "basic" + * -# "detailed" * "profiling_file_path": QNN profiling file path if ETW not enabled. * "rpc_control_latency": QNN RPC control latency. * "vtcm_mb": QNN VTCM size in MB. default to 0(not set). - * "htp_performance_mode": QNN performance mode, options: "burst", "balanced", "default", "high_performance", - * "high_power_saver", "low_balanced", "extreme_power_saver", "low_power_saver", "power_saver", "sustained_high_performance". Default to "default". + * "htp_performance_mode": QNN performance mode. + * Available options: + * -# "burst" + * -# "balanced" + * -# "default": Default. + * -# "high_performance" + * -# "high_power_saver" + * -# "low_balanced" + * -# "extreme_power_saver" + * -# "low_power_saver" + * -# "power_saver" + * -# "sustained_high_performance" + * "dump_qnn_ir_dlc": Use the QnnIr backend library to write .dlc files for each subgraph dispatched to QNN. When + * enabled, inference results will be incorrect. Use only for debugging. + * -# "0": Default: disabled + * -# "1": enabled + * "dump_qnn_ir_dlc_dir": Set the directory into which QnnIr will be configured to write QNN graphs as .dlc files. + * Default is current working directory. + * "qnn_ir_backend_path": File path to the QnnIr backend library. If "dump_qnn_ir_dlc" is enabled, use this path + * instead of looking for the Ir backend in the standard location. * "qnn_saver_path": File path to the QNN Saver backend library. If specified, QNN Saver will be enabled and will - * dump QNN API calls to disk for replay/debugging. QNN Saver produces incorrect model inference results and - * may alter model/EP partitioning. Use only for debugging. - * "qnn_context_priority": QNN context priority, options: "low", "normal", "normal_high", "high". Default to "normal". - * "htp_graph_finalization_optimization_mode": Set the optimization mode for graph finalization on the HTP backend. Available options: - * - "0": Default. - * - "1": Faster preparation time, less optimal graph. - * - "2": Longer preparation time, more optimal graph. - * - "3": Longest preparation time, most likely even more optimal graph. See QNN SDK documentation for specific details. - * "soc_model": The SoC model number. Refer to the QNN SDK documentation for valid values. Defaults to "0" (unknown). - * "htp_arch": The minimum HTP architecture the driver will use to select compatible QNN operators. Available options: - * - "0": Default (none). - * - "68" - * - "69" - * - "73" - * - "75" + * dump QNN API calls to disk for replay/debugging. QNN Saver produces incorrect model inference results and + * may alter model/EP partitioning. Use only for debugging. + * "qnn_context_priority": QNN context priority. + * Available options: + * -# "low" + * -# "normal": Default. + * -# "normal_high" + * -# "high" + * "htp_graph_finalization_optimization_mode": Set the optimization mode for graph finalization on the HTP backend. + * Available options: + * -# "0": Default. + * -# "1": Faster preparation time, less optimal graph. + * -# "2": Longer preparation time, more optimal graph. + * -# "3": Longest preparation time, most likely even more optimal graph. See QNN SDK documentation for specific + * details. + * "soc_model": The SoC model number. Refer to the QNN SDK documentation for valid values. + * Defaults to "0" (unknown). + * "htp_arch": The minimum HTP architecture the driver will use to select compatible QNN operators. + * Available options: + * -# "0": Default (none). + * -# "68" + * -# "69" + * -# "73" + * -# "75" + * -# "81" * "device_id": The ID of the device to use when setting 'htp_arch'. Defaults to "0" (for single device). * "enable_htp_fp16_precision": Used for float32 model for HTP backend. - * Enable the float32 model to be inferenced with fp16 precision. Otherwise, it will be fp32 precision. - * - "0": With fp32 precision. - * - "1": Default. With fp16 precision. - * "enable_htp_weight_sharing": Enable QNN weight sharing feature while compiling multiple graphs into one QNN context. - * - "0": Default. Disabled. - * - "1": Enabled. + * Enable the float32 model to be inferenced with fp16 precision. Otherwise, it will be fp32 precision. + * -# "0": With fp32 precision. + * -# "1": Default. With fp16 precision. * "offload_graph_io_quantization": Offload graph input quantization and graph output dequantization to another - * execution provider (typically CPU EP). - * - "0": Default. Disabled. QNN EP will handle quantization and dequantization of graph I/O. - * - "1": Enabled. - * "enable_htp_spill_fill_buffer": Enable HTP spill fill buffer setting. The flag is used while generating context binary. - * - "0": Default. Disabled. - * - "1": Enabled. + * execution provider (typically CPU EP). + * -# "0": Disabled. QNN EP will handle quantization and dequantization of graph I/O. + * -# "1": Enabled. This is the default value. + * "enable_htp_spill_fill_buffer": Enable HTP spill fill buffer setting. The flag is used while generating context + * binary. + * -# "0": Default. Disabled. + * -# "1": Enabled. * "enable_htp_shared_memory_allocator": Enable the QNN HTP shared memory allocator. Requires libcdsprpc.so/dll to - * be available. - * - "0": Default. Disabled. - * - "1": Enabled. - * - * SNPE supported keys: - * "runtime": SNPE runtime engine, options: "CPU", "CPU_FLOAT32", "GPU", "GPU_FLOAT32_16_HYBRID", "GPU_FLOAT16", - * "DSP", "DSP_FIXED8_TF", "AIP_FIXED_TF", "AIP_FIXED8_TF". - * Mapping to SNPE Runtime_t definition: CPU, CPU_FLOAT32 => zdl::DlSystem::Runtime_t::CPU; - * GPU, GPU_FLOAT32_16_HYBRID => zdl::DlSystem::Runtime_t::GPU; - * GPU_FLOAT16 => zdl::DlSystem::Runtime_t::GPU_FLOAT16; - * DSP, DSP_FIXED8_TF => zdl::DlSystem::Runtime_t::DSP. - * AIP_FIXED_TF, AIP_FIXED8_TF => zdl::DlSystem::Runtime_t::AIP_FIXED_TF. - * "priority": execution priority, options: "low", "normal". - * "buffer_type": ITensor or user buffers, options: "ITENSOR", user buffer with different types - "TF8", "TF16", "UINT8", "FLOAT". - * "ITENSOR" -- default, ITensor which is float only. - * "TF8" -- quantized model required, "FLOAT" -- for both quantized or non-quantized model - * "enable_init_cache": enable SNPE init caching feature, set to 1 to enabled it. Disabled by default. - * If SNPE is not available (due to a non Snpe enabled build or its dependencies not being installed), this function will fail. + * be available. + * -# "0": Default. Disabled. + * -# "1": Enabled. + * "dump_json_qnn_graph": Set to "1" to dump QNN graphs generated by QNN EP as JSON files. Each graph partition + * assigned to QNN EP is dumped to a separate file. + * "json_qnn_graph_dir": Directory in which to dump QNN JSON graphs. If not specified, QNN graphs are dumped in the + * program's current working directory. Ignored if "dump_json_qnn_graph" is not set. + * "op_packages": QNN UDO op_package for QNN EP, allowed format: + *   "::[:],::[:]", + *   where op_type is the name of the operation, op_package_path is the path to the op package shared library, + * interface is the symbol name to register the op life cycle functions, and target is the backend type. For more + * details, refer to: https://docs.qualcomm.com/bundle/publicresource/topics/80-63442-50/op_packages.html + * [Advanced] "skip_qnn_version_check": Set to "1" to allow a different version of QNN to be used than what was compiled + * into ONNX Runtime. Differences in operator support, accuracy, performance, and QNN's ABI may lead to crashes, inaccurate + * results, and poor performance. Use with caution and test thoroughly. * * XNNPACK supported keys: * "intra_op_num_threads": number of thread-pool size to use for XNNPACK execution provider. @@ -3926,7 +4536,7 @@ struct OrtApi { * If `out` is nullptr, the value of `size` is set to the size of the name * string (including null-terminator), and a success status is returned. * - * If the `size` parameter is greater than or equal to the name string's size, + * If the `size` parameter is greater than or equal to the name string's size and `out` is not nullptr, * the value of `size` is set to the true size of the string (including null-terminator), * the provided memory is filled with the string's contents, and a success status is returned. * @@ -3942,7 +4552,7 @@ struct OrtApi { * \snippet{doc} snippets.dox OrtStatus Return Value * \since Version 1.14 */ - ORT_API2_STATUS(KernelInfo_GetInputName, _In_ const OrtKernelInfo* info, size_t index, _Out_ char* out, + ORT_API2_STATUS(KernelInfo_GetInputName, _In_ const OrtKernelInfo* info, size_t index, _Out_opt_ char* out, _Inout_ size_t* size); /** \brief Get the name of a ::OrtKernelInfo's output. @@ -3953,7 +4563,7 @@ struct OrtApi { * If `out` is nullptr, the value of `size` is set to the size of the name * string (including null-terminator), and a success status is returned. * - * If the `size` parameter is greater than or equal to the name string's size, + * If the `size` parameter is greater than or equal to the name string's size and `out` is not nullptr, * the value of `size` is set to the true size of the string (including null-terminator), * the provided memory is filled with the string's contents, and a success status is returned. * @@ -3970,7 +4580,7 @@ struct OrtApi { * \snippet{doc} snippets.dox OrtStatus Return Value * \since Version 1.14 */ - ORT_API2_STATUS(KernelInfo_GetOutputName, _In_ const OrtKernelInfo* info, size_t index, _Out_ char* out, + ORT_API2_STATUS(KernelInfo_GetOutputName, _In_ const OrtKernelInfo* info, size_t index, _Out_opt_ char* out, _Inout_ size_t* size); /** \brief Get the type information for a ::OrtKernelInfo's input. @@ -4150,7 +4760,7 @@ struct OrtApi { * If `out` is nullptr, the value of `size` is set to the size of the name * string (including null-terminator), and a success status is returned. * - * If the `size` parameter is greater than or equal to the name string's size, + * If the `size` parameter is greater than or equal to the name string's size and `out` is not nullptr, * the value of `size` is set to the true size of the string (including null-terminator), * the provided memory is filled with the string's contents, and a success status is returned. * @@ -4167,7 +4777,7 @@ struct OrtApi { * \snippet{doc} snippets.dox OrtStatus Return Value * \since Version 1.15 */ - ORT_API2_STATUS(KernelInfo_GetNodeName, _In_ const OrtKernelInfo* info, _Out_ char* out, _Inout_ size_t* size); + ORT_API2_STATUS(KernelInfo_GetNodeName, _In_ const OrtKernelInfo* info, _Out_opt_ char* out, _Inout_ size_t* size); /** \brief Get the session logger from ::OrtKernelInfo. * @@ -4229,7 +4839,7 @@ struct OrtApi { /** \brief Get the logging severity level of the ::OrtLogger. * - * Can be used in a custom operator to get the logging serverity level of the ::OrtLogger associated with + * Can be used in a custom operator to get the logging severity level of the ::OrtLogger associated with * the ::OrtKernelInfo. * * \param[in] logger The ::OrtLogger instance. @@ -4289,8 +4899,8 @@ struct OrtApi { * specific type that is described by the returned ::OrtTypeInfo. * * \param[in] optional_type_info - * \param[out] out A pointer to the ::OrtTypeInfo for what the optional value could be. - * it is owned by OrtOptionalTypeInfo instance. + * \param[out] out A copy of ::OrtTypeInfo for what the optional value could be. + * The user must free this value with ReleaseTypeInfo. * * \snippet{doc} snippets.dox OrtStatus Return Value * @@ -4315,7 +4925,7 @@ struct OrtApi { * * \param[in] context OrtKernelContext instance * \param[in] mem_info OrtMemoryInfo instance - * \param[out] out A pointer to OrtAllocator. + * \param[out] out A pointer to OrtAllocator. Must be released with OrtApi::ReleaseAllocator. * * \snippet{doc} snippets.dox OrtStatus Return Value * @@ -4403,7 +5013,8 @@ struct OrtApi { * \param[in] provider_options_values value of the provider options map * \param[in] num_keys Length of the provider options map */ - ORT_API2_STATUS(CreateAndRegisterAllocatorV2, _Inout_ OrtEnv* env, _In_ const char* provider_type, _In_ const OrtMemoryInfo* mem_info, _In_ const OrtArenaCfg* arena_cfg, + ORT_API2_STATUS(CreateAndRegisterAllocatorV2, _Inout_ OrtEnv* env, _In_ const char* provider_type, + _In_ const OrtMemoryInfo* mem_info, _In_ const OrtArenaCfg* arena_cfg, _In_reads_(num_keys) const char* const* provider_options_keys, _In_reads_(num_keys) const char* const* provider_options_values, _In_ size_t num_keys); /** \brief Run the model asynchronously in a thread owned by intra op thread pool @@ -4580,6 +5191,8 @@ struct OrtApi { * \param[in] len Number of bytes allowed to store in data * \param[out] out Number of bytes required to save the data when the call failed, or the real number of bytes saved to data on success * + * \note Does not support reading graph attributes. Refer to Node_GetSubgraphs. + * * \since Version 1.17. */ ORT_API2_STATUS(ReadOpAttr, _In_ const OrtOpAttr* op_attr, _In_ OrtOpAttrType type, _Inout_ void* data, _In_ size_t len, _Out_ size_t* out); @@ -4647,12 +5260,12 @@ struct OrtApi { _In_reads_(num_keys) const char* const* provider_options_values, _In_ size_t num_keys); - /** \brief Get scratch buffer from the corresponding allocator under the sepcific OrtMemoryInfo object. + /** \brief Get scratch buffer from the corresponding allocator under the specific OrtMemoryInfo object. * NOTE: callers are responsible to release this scratch buffer from the corresponding allocator * \param[in] context OrtKernelContext instance * \param[in] mem_info OrtMemoryInfo instance * \param[in] count_or_bytes How many bytes is this scratch buffer - * \param[out] out A pointer to the scrach buffer + * \param[out] out A pointer to the scratch buffer * * \snippet{doc} snippets.dox OrtStatus Return Value * @@ -4782,118 +5395,3167 @@ struct OrtApi { */ ORT_API2_STATUS(SetEpDynamicOptions, _Inout_ OrtSession* sess, _In_reads_(kv_len) const char* const* keys, _In_reads_(kv_len) const char* const* values, _In_ size_t kv_len); -}; -/* - * Steps to use a custom op: - * 1 Create an OrtCustomOpDomain with the domain name used by the custom ops - * 2 Create an OrtCustomOp structure for each op and add them to the domain - * 3 Call OrtAddCustomOpDomain to add the custom domain of ops to the session options - */ + /// @} -// Specifies some characteristics of inputs/outputs of custom ops: -// Specify if the inputs/outputs are one of: -// 1) Non-optional (input/output must be present in the node) -// 2) Optional (input/output may be absent in the node) -// 3) Variadic: A variadic input or output specifies N (i.e., the minimum arity) or more operands. -// Only the last input or output of a custom op may be marked as variadic. -// The homogeneity of the variadic input or output determines whether all operands must be of the same -// tensor element type. -typedef enum OrtCustomOpInputOutputCharacteristic { - INPUT_OUTPUT_REQUIRED = 0, - INPUT_OUTPUT_OPTIONAL, - INPUT_OUTPUT_VARIADIC, -} OrtCustomOpInputOutputCharacteristic; + /** \brief Release an OrtValueInfo instance if it was not added to an OrtGraph. + * \since Version 1.22. + */ + ORT_CLASS_RELEASE(ValueInfo); -/* - * The OrtCustomOp structure defines a custom op's schema and its kernel callbacks. The callbacks are filled in by - * the implementor of the custom op. - */ -struct OrtCustomOp { - uint32_t version; // Must be initialized to ORT_API_VERSION + /** \brief Release an OrtNode if it was not added to an OrtGraph. + * \since Version 1.22. + */ + ORT_CLASS_RELEASE(Node); - // This callback creates the kernel, which is a user defined - // parameter that is passed to the Kernel* callbacks below. It is - // recommended to use CreateKernelV2 which allows for a safe error - // propagation by returning an OrtStatusPtr. - void*(ORT_API_CALL* CreateKernel)(_In_ const struct OrtCustomOp* op, _In_ const OrtApi* api, - _In_ const OrtKernelInfo* info); + /** \brief Release an OrtGraph. + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.22. + */ + ORT_CLASS_RELEASE(Graph); - // Returns the name of the op - const char*(ORT_API_CALL* GetName)(_In_ const struct OrtCustomOp* op); + /** \brief Release an OrtModel. + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.22. + */ + ORT_CLASS_RELEASE(Model); - // Returns the type of the execution provider, return nullptr to use CPU execution provider - const char*(ORT_API_CALL* GetExecutionProviderType)(_In_ const struct OrtCustomOp* op); + /** \brief Get the value name from an OrtValueInfo instance. + * \param[in] value_info The OrtValueInfo instance. + * \param[out] name The name of the OrtValueInfo + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.22. + */ + ORT_API2_STATUS(GetValueInfoName, _In_ const OrtValueInfo* value_info, _Out_ const char** name); - // Returns the count and types of the input & output tensors - ONNXTensorElementDataType(ORT_API_CALL* GetInputType)(_In_ const struct OrtCustomOp* op, _In_ size_t index); - size_t(ORT_API_CALL* GetInputTypeCount)(_In_ const struct OrtCustomOp* op); - ONNXTensorElementDataType(ORT_API_CALL* GetOutputType)(_In_ const struct OrtCustomOp* op, _In_ size_t index); - size_t(ORT_API_CALL* GetOutputTypeCount)(_In_ const struct OrtCustomOp* op); + /** \brief Get the type information from an OrtValueInfo instance. + * \param[in] value_info The OrtValueInfo instance. + * \param[out] type_info The type info of the OrtValueInfo + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.22. + */ + ORT_API2_STATUS(GetValueInfoTypeInfo, _In_ const OrtValueInfo* value_info, _Outptr_ const OrtTypeInfo** type_info); - // Perform a computation step. It is recommended to use - // KernelComputeV2 which allows for a safe error propagation by - // returning an OrtStatusPtr. - void(ORT_API_CALL* KernelCompute)(_In_ void* op_kernel, _In_ OrtKernelContext* context); - void(ORT_API_CALL* KernelDestroy)(_In_ void* op_kernel); + /** \brief Get the Model Editor API instance + * + * Get the Model Editor API instance to create a new model or augment an existing model. + * + * \return Model Editor API struct + * + * \since Version 1.22. + */ + const OrtModelEditorApi*(ORT_API_CALL* GetModelEditorApi)(void); - // Returns the characteristics of the input & output tensors - OrtCustomOpInputOutputCharacteristic(ORT_API_CALL* GetInputCharacteristic)(_In_ const struct OrtCustomOp* op, _In_ size_t index); - OrtCustomOpInputOutputCharacteristic(ORT_API_CALL* GetOutputCharacteristic)(_In_ const struct OrtCustomOp* op, _In_ size_t index); + /** \brief Create an OrtValue for a Tensor that uses pre-existing memory. + * + * ORT will take ownership of the memory and free it using the provided deleter when no longer in use. + * + * \param[in] deleter OrtAllocator instance that will be used to free the memory. + * Only the OrtAllocator:Info and OrtAllocator::Release functions are required. + * The OrtMemoryInfo returned by OrtAllocator::Info must match the location of p_data. + * \param[in] p_data Pointer to the memory that will be used by the Tensor. ORT will take ownership of the memory. + * \param[in] p_data_len Length of the memory in bytes. + * \param[in] shape Dimensions of the Tensor. All values should be > 0. + * \param[in] shape_len Number of dimensions in the shape array. + * \param[in] type Data type of the Tensor. + * \param[out] out Newly created ::OrtValue. Must be freed with OrtApi::ReleaseValue + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateTensorWithDataAndDeleterAsOrtValue, _In_ OrtAllocator* deleter, + _In_ void* p_data, size_t p_data_len, + _In_ const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type, + _Outptr_ OrtValue** out); - // Returns the memory type of the input tensors. This API allows the custom op - // to place the inputs on specific devices. By default, it returns - // OrtMemTypeDefault, which means the input is placed on the default device for - // the execution provider. If the inputs need to be with different memory tyeps, - // this function can be overridden to return the specific memory types. - OrtMemType(ORT_API_CALL* GetInputMemoryType)(_In_ const struct OrtCustomOp* op, _In_ size_t index); + /** \brief sets load cancellation flag to abort session loading process. + * + * \param[in] options instance that was passed to the session at creation time. + * \param[in] cancel setting this to true after model loading process was initiated will + * attempt to cancel the loading process. If cancellation is successful, CreateSession() + * CreateSessionFromArray() or any other session creation API that take session options as an + * argument will return an OrtStatus indicating that session loading was canceled at user request, + * error code ORT_MODEL_LOAD_CANCELED. + * The APIs above would not return any valid Session instance. This is the best case effort and the result + * is not guaranteed. The session may have already been created and initialized + * before the cancellation request was issued. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(SessionOptionsSetLoadCancellationFlag, _Inout_ OrtSessionOptions* options, + _In_ bool cancel); - // Returns the minimum number of input arguments expected for the variadic input. - // Applicable only for custom ops that have a variadic input. - int(ORT_API_CALL* GetVariadicInputMinArity)(_In_ const struct OrtCustomOp* op); + /** \brief Get the Compile API instance. + * + * Get the Compile API instance to compile ONNX models. Execution providers that support compilation fuse a subgraph + * into an EPContext node that wraps a provider-specific binary representation of the subgraph. + * For more details about the EPContext design, refer to: + * \htmlonly + * EPContext design document. + * \endhtmlonly + * + * \return Compile API struct instance. + * + * \since Version 1.22. + */ + const OrtCompileApi*(ORT_API_CALL* GetCompileApi)(void); - // Returns true (non-zero) if all arguments of a variadic input have to be of the same type (homogeneous), - // and false (zero) otherwise. - // Applicable only for custom ops that have a variadic input. - int(ORT_API_CALL* GetVariadicInputHomogeneity)(_In_ const struct OrtCustomOp* op); + // + // OrtKeyValuePairs + // + + /** \brief Create an OrtKeyValuePairs instance. + * + * \param[out] out A pointer to a newly created OrtKeyValuePairs instance. + * + * \note Must be released by calling ReleaseKeyValuePairs. + * + * \since Version 1.22. + */ + void(ORT_API_CALL* CreateKeyValuePairs)(_Outptr_ OrtKeyValuePairs** out); + + /** \brief Add a key-value pair to the OrtKeyValuePairs instance. + * + * If a pair with the same key already exists, it is overwritten. + * + * \param[in] kvps OrtKeyValuePairs instance. + * \param[in] key Key to be added. + * \param[in] value Value to be added. + * + * \note The `key` and `value` are copied internally. + * + * \since Version 1.22. + */ + + void(ORT_API_CALL* AddKeyValuePair)(_In_ OrtKeyValuePairs* kvps, _In_ const char* key, _In_ const char* value); + + /** \brief Get the value associated with a key in the OrtKeyValuePairs instance. + * + * \param[in] kvps OrtKeyValuePairs instance. + * \param[in] key Key to be searched. + * + * \return The value associated with the key, or nullptr if the key does not exist. + * + * \since Version 1.22. + */ + const char*(ORT_API_CALL* GetKeyValue)(_In_ const OrtKeyValuePairs* kvps, _In_ const char* key); + + /** \brief Get all the key-value pairs from the OrtKeyValuePairs instance. + * + * \param[in] kvps OrtKeyValuePairs instance. + * \param[out] keys Array of keys from `kvps`. + * \param[out] values Array of values from `kvps`. + * \param[out] num_entries Number of entries in `keys` and `values`. + * + * \since Version 1.22. + */ + void(ORT_API_CALL* GetKeyValuePairs)(_In_ const OrtKeyValuePairs* kvps, + _Outptr_ const char* const** keys, _Outptr_ const char* const** values, + _Out_ size_t* num_entries); + + /** \brief Remove a key-value pair from the OrtKeyValuePairs instance. + * + * \param[in] kvps OrtKeyValuePairs instance. + * \param[in] key Key to be removed. No error if not found. + * + * \since Version 1.22. + */ + void(ORT_API_CALL* RemoveKeyValuePair)(_In_ OrtKeyValuePairs* kvps, _In_ const char* key); + + /** \brief Release an OrtKeyValuePairs instance. + * + * \param[in] input OrtKeyValuePairs instance to be released. + * + * \since Version 1.22. + */ + ORT_CLASS_RELEASE(KeyValuePairs); + + /** \brief Register an execution provider library with ORT. + * + * The library must export 'CreateEpFactories' and 'ReleaseEpFactory' functions. + * See OrtEpApi for more details. + * + * \param[in] env The OrtEnv instance to register the library in. + * \param[in] registration_name The name to register the execution provider library under. + * \param[in] path The path to the execution provider library. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(RegisterExecutionProviderLibrary, _In_ OrtEnv* env, _In_ const char* registration_name, + _In_ const ORTCHAR_T* path); + + /** \brief Unregister an execution provider library with ORT. + * + * ORT will call ReleaseEpFactory for all factories created by the library, and unload the library. + * + * You MUST ensure there are no Session instances using execution providers created by the library + * before calling this function. + * + * \param[in] env The OrtEnv instance to unregister the library from. + * \param[in] registration_name The name the execution provider library was registered under. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(UnregisterExecutionProviderLibrary, _In_ OrtEnv* env, _In_ const char* registration_name); + + /** \brief Get the list of available OrtEpDevice instances. + * + * Each OrtEpDevice instance contains details of the execution provider and the device it will use. + * + * \param[in] env The OrtEnv instance to query. + * \param[out] ep_devices The OrtEpDevice instances that the execution provider will use. + * \param[out] num_ep_devices The number of OrtEpDevice instances returned. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(GetEpDevices, _In_ const OrtEnv* env, + _Outptr_ const OrtEpDevice* const** ep_devices, _Out_ size_t* num_ep_devices); + + /** \brief Append the execution provider that is responsible for the selected OrtEpDevice instances + * to the session options. + * + * \param[in] session_options Session options to add execution provider to. + * \param[in] env Environment that execution providers were registered with. + * \param[in] ep_devices One or more OrtEpDevice instances to create an execution provider for. + * Obtain from GetEpDevices. All OrtEpDevice instances must be from the same execution + * provider. It is only necessary to provide multiple OrtEpDevices if you want to use the + * same execution provider for multiple devices. + * e.g. the EP is capable of running on GPU and NPU. + * \param[in] num_ep_devices Number of OrtEpDevice instances. + * \param[in] ep_option_keys Optional keys to configure the execution provider. + * \param[in] ep_option_vals Optional values to configure the execution provider. + * \param[in] num_ep_options Number of execution provide options to add. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(SessionOptionsAppendExecutionProvider_V2, _In_ OrtSessionOptions* session_options, + _In_ OrtEnv* env, + _In_reads_(num_ep_devices) const OrtEpDevice* const* ep_devices, _In_ size_t num_ep_devices, + _In_reads_(num_op_options) const char* const* ep_option_keys, + _In_reads_(num_op_options) const char* const* ep_option_vals, + size_t num_ep_options); + + /** \brief Set the execution provider selection policy for the session. + * + * Allows users to specify a device selection policy for automatic execution provider (EP) selection. + * If custom selection is required please use SessionOptionsSetEpSelectionPolicyDelegate instead. + * + * \param[in] session_options The OrtSessionOptions instance. + * \param[in] policy The device selection policy to use (see OrtExecutionProviderDevicePolicy). + * + * \since Version 1.22 + */ + ORT_API2_STATUS(SessionOptionsSetEpSelectionPolicy, _In_ OrtSessionOptions* session_options, + _In_ OrtExecutionProviderDevicePolicy policy); + + /** \brief Set the execution provider selection policy delegate for the session. + * + * Allows users to provide a custom device selection policy for automatic execution provider (EP) selection. + * + * \param[in] session_options The OrtSessionOptions instance. + * \param[in] delegate Delegate callback for custom selection. + * \param[in] delegate_state Optional state that will be passed to the delegate callback. nullptr if not required. + * + * \since Version 1.22 + */ + ORT_API2_STATUS(SessionOptionsSetEpSelectionPolicyDelegate, _In_ OrtSessionOptions* session_options, + _In_ EpSelectionDelegate delegate, + _In_opt_ void* delegate_state); + + /** \brief Get the hardware device type. + * + * \param[in] device The OrtHardwareDevice instance to query. + * \return The hardware device type. + * + * \since Version 1.22. + */ + OrtHardwareDeviceType(ORT_API_CALL* HardwareDevice_Type)(_In_ const OrtHardwareDevice* device); + + /** \brief Get the hardware device's vendor identifier. + * + * \param[in] device The OrtHardwareDevice instance to query. + * \return The hardware device vendor identifier. + * + * \since Version 1.22. + */ + uint32_t(ORT_API_CALL* HardwareDevice_VendorId)(_In_ const OrtHardwareDevice* device); + + /** \brief Get the hardware device's vendor name. + * + * \param[in] device The OrtHardwareDevice instance to query. + * \return The hardware device's vendor name. + * + * \since Version 1.22. + */ + const char*(ORT_API_CALL* HardwareDevice_Vendor)(_In_ const OrtHardwareDevice* device); + + /** \brief Get the hardware device's unique identifier. + * + * \param[in] device The OrtHardwareDevice instance to query. + * \return The device id. + * + * \note This is not a unique identifier. It identifies the hardware type when combined with vendor id. + * \since Version 1.22. + */ + uint32_t(ORT_API_CALL* HardwareDevice_DeviceId)(_In_ const OrtHardwareDevice* device); + + /** \brief Get hardware device metadata. + * + * \param[in] device The OrtHardwareDevice instance to query. + * \return An OrtKeyValuePairs instance containing the metadata for the device. + * Note: ORT owns the instance so the user must not call ReleaseKeyValuePairs with it. + * + * \since Version 1.22. + */ + const OrtKeyValuePairs*(ORT_API_CALL* HardwareDevice_Metadata)(_In_ const OrtHardwareDevice* device); + + /** \brief Get the execution provider name. + * + * \param[in] ep_device The OrtEpDevice instance to query. + * \return The execution provider name. + * + * \since Version 1.22. + */ + const char*(ORT_API_CALL* EpDevice_EpName)(_In_ const OrtEpDevice* ep_device); + + /** \brief Get the execution provider's vendor name. + * + * \param[in] ep_device The OrtEpDevice instance to query. + * \return The execution provider's vendor name. + * + * \since Version 1.22. + */ + const char*(ORT_API_CALL* EpDevice_EpVendor)(_In_ const OrtEpDevice* ep_device); + + /** \brief Get the metadata for the OrtEpDevice. + * + * \param[in] ep_device The OrtEpDevice instance to query. + * \return An OrtKeyValuePairs instance containing the metadata for the device. + * + * \since Version 1.22. + */ + const OrtKeyValuePairs*(ORT_API_CALL* EpDevice_EpMetadata)(_In_ const OrtEpDevice* ep_device); + + /** \brief Get the execution provider options for the OrtEpDevice. + * + * \param[in] ep_device The OrtEpDevice instance to query. + * \return An OrtKeyValuePairs instance containing the execution provider options for the device. + * + * \since Version 1.22. + */ + const OrtKeyValuePairs*(ORT_API_CALL* EpDevice_EpOptions)(_In_ const OrtEpDevice* ep_device); + + /** \brief Get the OrtHardwareDevice instance for the OrtEpDevice. + * + * \param[in] ep_device The OrtEpDevice instance to query. + * \return The OrtHardwareDevice instance for the device. + * + * \since Version 1.22. + */ + const OrtHardwareDevice*(ORT_API_CALL* EpDevice_Device)(_In_ const OrtEpDevice* ep_device); + + /** \brief Get the OrtEpApi instance for implementing an execution provider. + * + * \since Version 1.22. + */ + const OrtEpApi*(ORT_API_CALL* GetEpApi)(void); + + /** \brief Compute total size in bytes of the tensor data contained in an OrtValue. + * + * Returns the total number of bytes used to store the tensor data. For numeric tensors, + * this is sizeof(element_type) * total_element_count. OrtValues that are not tensors or + * that are tensors that contain strings will cause an error to be returned. + * + * \param[in] ort_value OrtValue instance containing a tensor + * \param[out] size The total size of the tensor data in bytes + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API2_STATUS(GetTensorSizeInBytes, _In_ const OrtValue* ort_value, _Out_ size_t* size); + + /** \brief Calls OrtAllocator::GetStats function + * + * Return a pointer to the OrtKeyValuePairs structure that contains the statistics of the allocator + * and the user should call OrtApi::ReleaseKeyValuePairs. + * + * NOTE: If the allocator does not implement this function, the OrtKeyValuePairs instance will be empty. + * + * \param[in] ort_allocator The allocator to get stats from + * \param[out] out A pointer to the OrtKeyValuePairs instance that contains the stats + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(AllocatorGetStats, _In_ const OrtAllocator* ort_allocator, _Outptr_ OrtKeyValuePairs** out); + + /** \brief Create an ::OrtMemoryInfo + * + * \param[in] name Arbitrary name. + * \param[in] device_type Device type. + * \param[in] vendor_id PCI Vendor ID. Use 0 for a generic allocator (e.g. WebGPU). + * \param[in] device_id Device ID if there are multiple devices of the same type. e.g. 2 GPU devices. + * \param[in] mem_type Memory type. Use OrtDeviceMemoryType_DEFAULT for device memory, and + * OrtDeviceMemoryType_HOST_ACCESSIBLE (if applicable) for memory used to transfer between the + * device and the CPU. Use the device_type and device_id of the GPU/NPU that the memory is also + * accessible to. + * \param[in] alignment Alignment of the memory if required. Pass 0 for default alignment. + * \param[in] allocator_type Allocator type. If OrtAllocatorType::OrtArenaAllocator, the ORT arena will be used. + * Caveat: Support for OrtArenaAllocator is currently limited to usage of internal ORT + * allocators via CreateAllocator/CreateAndRegisterAllocator/CreateAndRegisterAllocatorV2. + * \param[out] out Newly created ::OrtMemoryInfo. Must be freed with OrtApi::ReleaseMemoryInfo + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API2_STATUS(CreateMemoryInfo_V2, _In_ const char* name, _In_ enum OrtMemoryInfoDeviceType device_type, + _In_ uint32_t vendor_id, _In_ int32_t device_id, _In_ enum OrtDeviceMemoryType mem_type, + _In_ size_t alignment, enum OrtAllocatorType allocator_type, + _Outptr_ OrtMemoryInfo** out); + + /** \brief Get the device memory type from ::OrtMemoryInfo + * + * \param[in] ptr The OrtMemoryInfo instance to query. + * \return The device memory type. + * + * \since Version 1.23 + */ + ORT_API_T(OrtDeviceMemoryType, MemoryInfoGetDeviceMemType, _In_ const OrtMemoryInfo* ptr); + + /** \brief Get the vendor id from ::OrtMemoryInfo + * + * \param[in] ptr The OrtMemoryInfo instance to query. + * \return The vendor id. + * + * \since Version 1.23 + */ + ORT_API_T(uint32_t, MemoryInfoGetVendorId, _In_ const OrtMemoryInfo* ptr); + + /// \name OrtValueInfo + /// @{ + + /** \brief Get the OrtNode that produces the value represented by the given OrtValueInfo. + * Optionally returns the associated output index. + * + * \param[in] value_info The OrtValueInfo instance. + * \param[out] producer_node Output parameter set to the OrtNode that produces the OrtValueInfo. + * \param[out] producer_output_index Optional output parameter set to the OrtNode instance's output index + * that produces the value. Ignored if set to NULL. + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.23. + */ + ORT_API2_STATUS(ValueInfo_GetValueProducer, _In_ const OrtValueInfo* value_info, + _Outptr_ const OrtNode** producer_node, _Out_opt_ size_t* producer_output_index); + + /** \brief Get the number of consumers of a value as a node input. + * + * Only nodes are considered "consumers" by this function. To check if an OrtValueInfo is a graph output, + * call ValueInfo_IsGraphOutput(). + * + * A single OrtNode may use a single value for more than one input (e.g., Mul(x, x)), so the returned + * `num_consumers` may be larger than the number of unique OrtNode instances that consume the value. + * + * \param[in] value_info The OrtValueInfo instance. + * \param[out] num_consumers Output parameter set to the number of consumers of the value. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ValueInfo_GetValueNumConsumers, _In_ const OrtValueInfo* value_info, _Out_ size_t* num_consumers); + + /** \brief Returns information (OrtNode and input index) for all consumer nodes that use the value as an input. + * + * Only nodes are considered "consumers" by this function. + * + * Caller provides 2 pre-allocated arrays that will be filled with the OrtNode and input index values. + * Use ValueInfo_GetValueNumConsumers() to get the number of consumers of the value. + * + * An OrtNode instance may appear multiple times if it uses the given value more than once. + * Example: For a node MulNode(x, x) that consumes the value 'x' twice, the following is returned: + * - nodes: [MulNode, MulNode] + * - input_indices: [0, 1] + * + * \param[in] value_info The OrtValueInfo instance. + * \param[out] nodes Pre-allocated array of size `num_consumers` that is filled with OrtNode instances. + * \param[out] input_indices Pre-allocated array of `num_consumers` elements that is filled + * with input indices. Index is set to -1 for an "implicit" input to a consumer node + * that contains a subgraph (e.g., If, Loop) with nodes that use the value internally. + * \param[in] num_consumers The size of the `consumer_nodes` and `consumer_input_indices` arrays. + * Typical usage sets this to the value of ValueInfo_GetValueNumConsumers(). + * An error status is returned if `num_consumers` is less than the number of actual + * consumers. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ValueInfo_GetValueConsumers, _In_ const OrtValueInfo* value_info, + _Out_writes_all_(num_consumers) const OrtNode** nodes, + _Out_writes_all_(num_consumers) int64_t* input_indices, + _In_ size_t num_consumers); + + /** \brief Get the underlying initializer value, as an OrtValue, from the given OrtValueInfo. + * + * Sets the output parameter to NULL if the given OrtValueInfo does not represent an initializer. + * Does not return an error status in this case. + * + * Supports initializers defined in an outer scope (i.e., a parent graph). + * + * Supports initializers stored in an external file. For external initializers, ORT memory maps + * the initializer data on the first call to this function. If caller needs custom memory mapping, + * use ValueInfo_GetExternalInitializerInfo to get the location of the initializer data. + * + * \param[in] value_info The OrtValueInfo instance. + * \param[out] initializer_value Output parameter set to the initializer value or NULL. Do not cache the OrtValue + * as it is released when the owning OrtGraph is released. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ValueInfo_GetInitializerValue, _In_ const OrtValueInfo* value_info, + _Outptr_ const OrtValue** initializer_value); + + /** \brief Get information about an external initializer (e.g., filepath, file offset, byte size). + * + * Sets the output parameter `info` to NULL if the given OrtValueInfo does not represent an initializer + * with external data. In this case, a NULL status (non-error) is returned. + * + * \param[in] value_info The OrtValueInfo instance. + * \param[out] info Output parameter set to an OrtExternalInitializerInfo instance that can be used to query + * file path, file offset, etc. ORT sets this to NULL if the OrtValueInfo does not represent + * an external initializer. + * Must release with ReleaseExternalInitializerInfo. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ValueInfo_GetExternalInitializerInfo, _In_ const OrtValueInfo* value_info, + _Outptr_result_maybenull_ OrtExternalInitializerInfo** info); + + /** \brief Returns a boolean indicating if the given value is a required graph input. + * + * For ONNX IR version < 4, all graph inputs without a matching initializer are required. + * + * For ONNX IR version >=4, a graph input with a matching initializer is an optional graph input + * with the initializer serving as the default value. + * + * \param[in] value_info The OrtValueInfo instance representing the graph value. + * \param[out] is_required_graph_input Output parameter set to true if the graph value is a required graph input. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ValueInfo_IsRequiredGraphInput, _In_ const OrtValueInfo* value_info, + _Out_ bool* is_required_graph_input); + + /** \brief Returns a boolean indicating if the given value is an optional graph input. + * + * Optional graph inputs were introduced in ONNX IR version 4. For ONNX IR version >=4, a graph input with a + * matching initializer is an optional graph input with the initializer serving as the default value. + * The matching initializer is also known as a non-constant initializer. + * + * \param[in] value_info The OrtValueInfo instance representing the graph value. + * \param[out] is_optional_graph_input Output parameter set to true if the graph value is an optional graph input. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ValueInfo_IsOptionalGraphInput, _In_ const OrtValueInfo* value_info, + _Out_ bool* is_optional_graph_input); + + /** \brief Returns a boolean indicating if the given value is a graph output. + * + * \param[in] value_info The OrtValueInfo instance representing the graph value. + * \param[out] is_graph_output Output parameter set to true if the graph value is a graph output. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ValueInfo_IsGraphOutput, _In_ const OrtValueInfo* value_info, _Out_ bool* is_graph_output); + + /** \brief Returns a boolean indicating if the given value is a constant initializer. + * + * For ONNX IR version < 4, all initializers are constant. + * + * For ONNX IR version >=4, an initializer that serves as the default value for a matching graph input is not a + * constant initializer. + * + * \param[in] value_info The OrtValueInfo instance representing the graph value. + * \param[out] is_constant_initializer Output parameter set to true if the graph value is a constant initializer. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ValueInfo_IsConstantInitializer, _In_ const OrtValueInfo* value_info, + _Out_ bool* is_constant_initializer); + + /** \brief Returns a boolean indicating if the given value is defined in an outer scope. + * + * Certain operator types (e.g., If and Loop) contain nested subgraphs. This function enables + * determining whether a value is defined in a parent node's graph. + * + * \param[in] value_info The OrtValueInfo instance representing the graph value. + * \param[out] is_from_outer_scope Output parameter set to true if the value is defined in an outer + * scope (i.e., a parent graph). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ValueInfo_IsFromOuterScope, _In_ const OrtValueInfo* value_info, + _Out_ bool* is_from_outer_scope); + + /// @} + + /// \name OrtGraph + /// @{ + + /** \brief Returns a graph's name. + * + * \param[in] graph The OrtGraph instance. + * \param[out] graph_name Output parameter set to the graph's name. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetName, _In_ const OrtGraph* graph, _Outptr_ const char** graph_name); + + /** \brief Get the filepath to the model from which an OrtGraph is constructed. + * + * \note The model's filepath is empty if the filepath is unknown, such as when the model is loaded from bytes + * via CreateSessionFromArray. + * + * \param[in] graph The OrtGraph instance. + * \param[out] model_path Output parameter set to the model's null-terminated filepath. + * Set to an empty path string if unknown. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetModelPath, _In_ const OrtGraph* graph, _Outptr_ const ORTCHAR_T** model_path); + + /** \brief Returns the ONNX IR version. + * + * \param[in] graph The OrtGraph instance. + * \param[out] onnx_ir_version Output parameter set to the ONNX IR version. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetOnnxIRVersion, _In_ const OrtGraph* graph, _Out_ int64_t* onnx_ir_version); + + /** \brief Returns the number of operator sets that the graph's model uses. + * + * \note An operator set is uniquely identified by the (domain, opset_version) pair. All models must have at + * least one entry that specifies which entry of the ONNX operator set is used. The ONNX domain is represented by + * an empty string. + * + * \param[in] graph The OrtGraph instance. + * \param[out] num_operator_sets Output parameter set to the number of operator sets that the graph's model uses. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetNumOperatorSets, _In_ const OrtGraph* graph, _Out_ size_t* num_operator_sets); + + /** \brief Returns the operator sets that the graph's model uses. + * + * \note An operator set is uniquely identified by the (domain, opset_version) pair. All models must have at + * least one entry that specifies which entry of the ONNX operator set is used. The ONNX domain is represented by + * an empty string. + * + * \param[in] graph The OrtGraph instance. + * \param[out] domains Pre-allocated array of `num_operator_sets` elements that is filled with + * null-terminated domain names. + * \param[out] opset_versions Pre-allocated array of `num_operator_sets` elements that is filled with + * the opset version of the corresponding domain in the `domains` array. + * \param[in] num_operator_sets The size of the `domains` and `opset_versions` arrays. + * Typical usage sets this to the result of Graph_GetNumOperatorSets(). + * An error status is returned if `num_operator_sets` is less than the actual number + * of operator sets. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetOperatorSets, _In_ const OrtGraph* graph, + _Out_writes_(num_operator_sets) const char** domains, + _Out_writes_(num_operator_sets) int64_t* opset_versions, _In_ size_t num_operator_sets); + + /** \brief Returns the number of graph inputs. + * + * \note The count includes initializers that are included in the list of graph inputs. + * + * \param[in] graph The OrtGraph instance. + * \param[out] num_inputs Output parameter set to the number of graph inputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetNumInputs, _In_ const OrtGraph* graph, _Out_ size_t* num_inputs); + + /** \brief Returns the graph's inputs as OrtValueInfo instances. + * + * \note The result includes initializers that are included in the list of graph inputs. + * + * \param[in] graph The OrtGraph instance. + * \param[out] inputs Pre-allocated array of `num_inputs` elements that is filled with the graph's inputs. + * \param[in] num_inputs The size of the `inputs` array. + * Typical usage sets this to the result of Graph_GetNumInputs(). An error status is + * returned if `num_inputs` is less than the number of graph inputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetInputs, _In_ const OrtGraph* graph, + _Out_writes_(num_inputs) const OrtValueInfo** inputs, _In_ size_t num_inputs); + + /** \brief Returns the number of graph outputs. + * + * \param[in] graph The OrtGraph instance. + * \param[out] num_outputs Output parameter set to the number of graph outputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetNumOutputs, _In_ const OrtGraph* graph, _Out_ size_t* num_outputs); + + /** \brief Returns the graph's outputs as OrtValueInfo instances. + * + * \param[in] graph The OrtGraph instance. + * \param[out] outputs Pre-allocated array of `num_outputs` elements that is filled with the graph's outputs. + * \param[in] num_outputs The size of the `outputs` array. + * Typical usage sets this to the result of Graph_GetNumOutputs(). An error status is + * returned if `num_outputs` is less than the number of graph outputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetOutputs, _In_ const OrtGraph* graph, + _Out_writes_(num_outputs) const OrtValueInfo** outputs, _In_ size_t num_outputs); + + /** \brief Returns the number of graph initializers. + * + * Counts constant and non-constant initializers. + * + * \param[in] graph The OrtGraph instance. + * \param[out] num_initializers Output parameter set to the number of graph initializers. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetNumInitializers, _In_ const OrtGraph* graph, _Out_ size_t* num_initializers); + + /** \brief Returns the graph's initializers as OrtValueInfo instances. + * + * Includes constant and non-constant initializers. + * + * For ONNX IR version < 4, all initializers are constant. + * + * For ONNX IR version >= 4, an initializer with a name that matches a graph input is considered a + * non-constant initializer. + * + * Call ValueInfo_GetInitializerValue to get the initializer's data. + * + * \param[in] graph The OrtGraph instance. + * \param[out] initializers Pre-allocated array of `num_outputs` elements that is filled with the initializers. + * \param[in] num_initializers The size of the `initializers` array. Typical usage sets this to the + * result of Graph_GetNumInitializers(). An error status is returned if + * `num_initializers` is less than the number of graph initializers. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetInitializers, _In_ const OrtGraph* graph, + _Out_writes_(num_initializers) const OrtValueInfo** initializers, + _In_ size_t num_initializers); + + /** \brief Returns the number of graph nodes. + * + * \param[in] graph The OrtGraph instance. + * \param[out] num_nodes Output parameter set to the number of graph nodes. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetNumNodes, _In_ const OrtGraph* graph, _Out_ size_t* num_nodes); + + /** \brief Returns the graph's nodes as OrtNode instances. + * + * The nodes are sorted using a stable topological ordering. Callers are responsible for maintaining their + * own node ordering if a different order is required. + * + * \param[in] graph The OrtGraph instance. + * \param[out] nodes Pre-allocated array of `num_nodes` elements that is filled with the graph's nodes. + * \param[in] num_nodes The size of the `nodes` array. Typical usage sets this to the + * result of Graph_GetNumNodes(). An error status is returned if + * `num_nodes` is less than the number of graph nodes. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetNodes, _In_ const OrtGraph* graph, + _Out_writes_(num_nodes) const OrtNode** nodes, _In_ size_t num_nodes); + + /** \brief Get the parent node for the given graph, if any exists. + * + * Certain operator types (e.g., If and Loop) contain nested subgraphs. This function enables + * access to the parent node (e.g., the If and Loop node) from a nested subgraph. + * + * \param[in] graph The OrtGraph instance. + * \param[out] node Output parameter that is set to the graph's parent node. + * Set to NULL if a parent node does not exist (e.g., for a top-level graph). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetParentNode, _In_ const OrtGraph* graph, _Outptr_result_maybenull_ const OrtNode** node); + + /** \brief Returns an OrtGraph that contains a subset of nodes in the source OrtGraph. + * + * \note The lifetime of "dst_graph" is tied to that of "src_graph", as they both internally reference + * the same underlying graph. "dst_graph" preserves the input order of "src_graph", and + * its output order corresponds to the outputs produced by the nodes in "nodes" with the given order. + * + * \param[in] src_graph The source OrtGraph instance. + * \param[in] nodes A subset of the nodes/OrtNodes in 'graph'. + * \param[in] num_nodes Number of nodes. + * \param[out] dst_graph An OrtGraph created from a given set of nodes. Must be released by calling ReleaseGraph. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetGraphView, _In_ const OrtGraph* src_graph, _In_ const OrtNode** nodes, + _In_ size_t num_nodes, _Outptr_ OrtGraph** dst_graph); + + /// @} + + /// \name OrtNode + /// @{ + + /** \brief Returns a node's identifier. + * + * The node's identifier is only unique in the node's parent graph. Different nested subgraphs + * (e.g., subgraphs contained by If and Loop nodes) may reuse identifiers. + * + * \param[in] node The OrtNode instance. + * \param[out] node_id Output parameter set to the node's identifier. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetId, _In_ const OrtNode* node, _Out_ size_t* node_id); + + /** \brief Returns a node's name. Can be an empty string. + * + * \param[in] node The OrtNode instance. + * \param[out] node_name Output parameter set to the node's name. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetName, _In_ const OrtNode* node, _Outptr_ const char** node_name); + + /** \brief Returns a node's operator type (e.g., "Conv"). + * + * \param[in] node The OrtNode instance. + * \param[out] operator_type Output parameter set to the name of the node's operator type. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetOperatorType, _In_ const OrtNode* node, _Outptr_ const char** operator_type); + + /** \brief Returns a node's domain name. + * + * \param[in] node The OrtNode instance. + * \param[out] domain_name Output parameter set to the node's domain name. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetDomain, _In_ const OrtNode* node, _Outptr_ const char** domain_name); + + /** \brief Get the opset version in which the given node's operator type was first defined. + * + * \param[in] node The OrtNode instance. + * \param[out] since_version The opset version in which the node's operator type was first defined. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetSinceVersion, _In_ const OrtNode* node, _Out_ int* since_version); + + /** \brief Returns the number of node inputs. + * + * \param[in] node The OrtNode instance. + * \param[out] num_inputs Output parameter set to the number of node inputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetNumInputs, _In_ const OrtNode* node, _Out_ size_t* num_inputs); + + /** \brief Returns the node's inputs as OrtValueInfo instances. + * + * \param[in] node The OrtNode instance. + * \param[out] inputs Pre-allocated array of `num_inputs` elements that is filled with the node's inputs. + * \param[in] num_inputs The size of the `inputs` array. + * Typical usage sets this to the result of Node_GetNumInputs(). An error status is + * returned if `num_inputs` is less than the number of node inputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetInputs, _In_ const OrtNode* node, + _Out_writes_(num_inputs) const OrtValueInfo** inputs, _In_ size_t num_inputs); + + /** \brief Returns the number of node outputs. + * + * \param[in] node The OrtNode instance. + * \param[out] num_outputs Output parameter set to the number of node outputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetNumOutputs, _In_ const OrtNode* node, _Out_ size_t* num_outputs); + + /** \brief Returns the node's outputs as OrtValueInfo instances. + * + * \param[in] node The OrtNode instance. + * \param[out] outputs Pre-allocated array of `num_outputs` elements that is filled with the node's outputs. + * \param[in] num_outputs The size of the `outputs` array. + * Typical usage sets this to the result of Node_GetNumOutputs(). An error status is + * returned if `num_outputs` is less than the number of node outputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetOutputs, _In_ const OrtNode* node, + _Out_writes_(num_outputs) const OrtValueInfo** outputs, _In_ size_t num_outputs); + + /** \brief Returns the number of node implicit inputs. + * + * Certain operator types (e.g., If and Loop) contain nested subgraphs. The internal nodes within the nested subgraphs + * may use values from the outer scope. Those "outer scope" values are considered implicit inputs to the node that + * contains the subgraphs (e.g., the If or Loop node). + * + * \param[in] node The OrtNode instance. + * \param[out] num_implicit_inputs Output parameter set to the number of node implicit inputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetNumImplicitInputs, _In_ const OrtNode* node, _Out_ size_t* num_implicit_inputs); + + /** \brief Get the implicit inputs, as OrtValueInfo instances, that are used within the given node's subgraphs. + * + * \note Only certain operator types (e.g., If and Loop) contain nested subgraphs. + * The internal nodes within the nested subgraphs may use values from the outer scope. Those "outer scope" values + * are considered implicit inputs to the node that contains the subgraphs (e.g., the If or Loop node). + * + * \param[in] node The OrtNode instance. + * \param[out] implicit_inputs Pre-allocated array of `num_implicit_inputs` elements that is filled the node's + * implicit inputs. + * \param[in] num_implicit_inputs The size of the `implicit_inputs` array. Typical usage sets this to the result + * of Node_GetNumImplicitInputs(). An error status is returned if + * `num_implicit_inputs` is less than the number of node implicit inputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetImplicitInputs, _In_ const OrtNode* node, + _Out_writes_(num_implicit_inputs) const OrtValueInfo** implicit_inputs, + _In_ size_t num_implicit_inputs); + + /** \brief Returns the number of node attributes. + * + * \param[in] node The OrtNode instance. + * \param[out] num_attributes Output parameter set to the number of node attributes. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetNumAttributes, _In_ const OrtNode* node, _Out_ size_t* num_attributes); + + /** \brief Returns a node's attributes as OrtOpAttr instances. + * + * \param[in] node The OrtNode instance. + * \param[out] attributes Pre-allocated array of `num_attributes` elements that is filled with the node's attributes. + * \param[in] num_attributes The size of the `num_attributes` array. + * Typical usage sets this to the result of Node_GetNumAttributes(). An error status is + * returned if `num_attributes` is less than the number of node attributes. + * + * \note ONNX Runtime automatically sets optional (unset) attributes to their default values if the default value + * is a constant expression that does not depend on other tensor/model characteristics. Conv's 'kernel_shape' + * attribute is an example of an optional attribute that does not have a constant default value. This function + * does not provide any unset optional attributes without a constant default value. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetAttributes, _In_ const OrtNode* node, + _Out_writes_(num_attributes) const OrtOpAttr** attributes, _In_ size_t num_attributes); + + /** \brief Gets the OrtNode's attribute as OrtOpAttr by name. + * + * \param[in] node The OrtNode instance. + * \param[in] attribute_name The name of the attribute + * \param[out] attribute Output parameter set to the OrtOpAttr instance if an attribute by the given name exists. + * For an unset optional attribute, `attribute` is set to NULL and a non-error status is + * returned. For an invalid attribute name, `attribute` is set to NULL and an error status with + * code ORT_NOT_FOUND is returned. + * + * \note ONNX Runtime automatically sets optional (unset) attributes to their default values if the default value + * is a constant expression that does not depend on other tensor/model characteristics. Conv's 'kernel_shape' + * attribute is an example of an optional attribute that does not have a constant default value. This function + * does not provide any unset optional attributes without a constant default value. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetAttributeByName, _In_ const OrtNode* node, _In_ const char* attribute_name, + _Outptr_result_maybenull_ const OrtOpAttr** attribute); + + /** \brief Get the OrtNode's 'TENSOR' attribute as an OrtValue. + * + * \param[in] attribute The OrtOpAttr instance. + * \param[out] attr_tensor If successful, contains the 'TENSOR' attribute as a newly created OrtValue. + Must be freed with OrtApi::ReleaseValue. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(OpAttr_GetTensorAttributeAsOrtValue, _In_ const OrtOpAttr* attribute, + _Outptr_result_maybenull_ OrtValue** attr_tensor); + + /** \brief Get the attribute type as OrtOpAttrType from an OrtOpAttr. + * + * \param[in] attribute The OrtOpAttr instance. + * \param[out] type Output the attribute type as OrtOpAttrType. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(OpAttr_GetType, _In_ const OrtOpAttr* attribute, _Out_ OrtOpAttrType* type); + + /** \brief Get the attribute name from an OrtOpAttr. + * + * \param[in] attribute The OrtOpAttr instance. + * \param[out] name Output parameter set to the attribute's name. The name is a null-terminated string. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(OpAttr_GetName, _In_ const OrtOpAttr* attribute, _Outptr_ const char** name); + + /** \brief Returns the number of subgraphs contained by the given node. + * + * \note Only certain operator types (e.g., If and Loop) contain nested subgraphs. + * + * \param[in] node The OrtNode instance. + * \param[out] num_subgraphs Output parameter set to the number of node subgraphs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetNumSubgraphs, _In_ const OrtNode* node, _Out_ size_t* num_subgraphs); + + /** \brief Get the subgraphs, as OrtGraph instances, contained by the given node. + * + * \note Only certain operator types (e.g., If and Loop) contain nested subgraphs. ONNX nodes store subgraphs in + * their attributes, however, this function must be used to obtain subgraphs from an OrtNode. + * + * \param[in] node The OrtNode instance. + * \param[out] subgraphs Pre-allocated array of `num_subgraphs` elements that is filled with the node's subgraphs. + * \param[in] num_subgraphs The size of the `num_subgraphs` array. + * Typical usage sets this to the result of Node_GetNumSubgraphs(). An error status is + * returned if `num_subgraphs` is less than the number of node subgraphs. + * \param[out] attribute_names Optional pre-allocated array of `num_subgraphs` elements that is filled with the + * attribute names that correspond to the subgraphs. Ignored if set to NULL. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetSubgraphs, _In_ const OrtNode* node, + _Out_writes_(num_subgraphs) const OrtGraph** subgraphs, _In_ size_t num_subgraphs, + _Out_writes_opt_(num_subgraphs) const char** attribute_names); + + /** \brief Get the node's parent OrtGraph instance. + * + * Can return NULL if the OrtNode was created without an owning graph. + * In another case, this API may also return NULL if `node` is obtained by calling Graph_GetParentNode() + * on an OrtGraph that is a subgraph of a control-flow op, and the parent graph has not been created yet, + * for example during ORT's GetCapability() when processing the innermost subgraph. + * + * \param[in] node The OrtNode instance. + * \param[out] graph Output parameter set to the node's OrtGraph. Can be set to NULL + * if the node is not currently contained by a graph. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetGraph, _In_ const OrtNode* node, _Outptr_result_maybenull_ const OrtGraph** graph); + + /** \brief Returns the execution provider name that this node is assigned to run on. + * Returns NULL if the node has not been assigned to any execution provider yet. + * For plugin execution providers, the name is the one returned by OrtEp::GetName. + * + * \param[in] node The OrtNode instance. + * \param[out] out Output execution provider type and can be NULL if node has not been assigned. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Node_GetEpName, _In_ const OrtNode* node, _Outptr_result_maybenull_ const char** out); + + /// @} + + /// \name OrtExternalInitializerInfo + /// @{ + + /** \brief Release an OrtExternalInitializerInfo instance. + * + * \param[in] input OrtExternalInitializerInfo instance to be released. + * + * \since Version 1.23. + */ + ORT_CLASS_RELEASE(ExternalInitializerInfo); + + /** \brief Get the relative path to the file that stores the initializer's data. + * + * \note The path is relative to the filesystem directory where the ONNX model was stored. + * Caller can use Graph_GetModelPath to get the model's full path and construct the absolute path to the + * external initializer file if necessary. + * + * \param[in] info The OrtExternalInitializerInfo instance. + * \return The relative path to the file that stores the initializer's data. Do NOT free this pointer. + * + * \since Version 1.23. + */ + ORT_API_T(const ORTCHAR_T*, ExternalInitializerInfo_GetFilePath, _In_ const OrtExternalInitializerInfo* info); + + /** \brief Get the byte offset within the file where the initializer's data is stored. + * + * \param[in] info The OrtExternalInitializerInfo instance. + * \return The byte offset where the initializer's data is stored within the file. + * + * \since Version 1.23. + */ + ORT_API_T(int64_t, ExternalInitializerInfo_GetFileOffset, _In_ const OrtExternalInitializerInfo* info); + + /** \brief Get the size in bytes of the initializer's data within the file. + * + * \param[in] info The OrtExternalInitializerInfo instance. + * \return The size in bytes of the initializer's data within the file. + * + * \since Version 1.23. + */ + ORT_API_T(size_t, ExternalInitializerInfo_GetByteSize, _In_ const OrtExternalInitializerInfo* info); + + /// @} + + /// \name OrtRunOptions + /// @{ + + /** \brief Get a run configuration entry. + * + * If a run configuration entry with key `config_key` doesn't exist, `config_value` will be set to NULL. + * + * `config_key`s are defined in onnxruntime_run_options_config_keys.h. + * + * \param[in] options The OrtRunOptions instance. + * \param[in] config_key The configuration entry key. A null-terminated string. + * \return The configuration entry value. Either a null-terminated string if the entry was found. nullptr otherwise. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API_T(const char*, GetRunConfigEntry, _In_ const OrtRunOptions* options, + _In_z_ const char* config_key); + + /// @} + + /** \brief Get the OrtMemoryInfo for the device. + * + * \param[in] ep_device The OrtEpDevice instance to query. + * \param[in] memory_type The memory type to return. + * \return A pointer to the OrtMemoryInfo for the device. This may be nullptr if not set. + * If memory_type is OrtDeviceMemoryType_DEFAULT and nullptr is returned the EP uses CPU memory. + * + * \since Version 1.23 + */ + ORT_API_T(const OrtMemoryInfo*, EpDevice_MemoryInfo, _In_ const OrtEpDevice* ep_device, + _In_ OrtDeviceMemoryType memory_type); + + /** \brief Create/replace a shared allocator for the OrtEpDevice in the OrtEnv. + * + * OrtEpDevice maps to the EP factory, and the factory provides the allocator implementation. + * + * Both OrtDeviceMemoryType_DEFAULT and OrtDeviceMemoryType_HOST_ACCESSIBLE are optional for an EP to provide. + * It is EP implementation dependent as to what is available. + * + * If a shared allocator already exists for the OrtEpDevice and OrtDeviceMemoryType, it is replaced. This allows + * changing the shared allocator configuration from the default. e.g. adding an arena. + * + * \param[in] env The OrtEnv instance to create the shared allocator in. + * \param[in] ep_device The OrtEpDevice instance to create the shared allocator for. + * \param[in] mem_type The memory type to use for the shared allocator. + * \param[in] allocator_type The type of allocator to create. Only OrtDeviceAllocator is valid currently. + * \param[in] allocator_options Optional key-value pairs to configure the allocator. If arena based, see + * include/onnxruntime/core/framework/allocator.h for the keys and values that can be + * used. + * \param[out] allocator A pointer to the created shared allocator. Owned by the OrtEnv instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API2_STATUS(CreateSharedAllocator, _In_ OrtEnv* env, _In_ const OrtEpDevice* ep_device, + _In_ OrtDeviceMemoryType mem_type, _In_ OrtAllocatorType allocator_type, + _In_opt_ const OrtKeyValuePairs* allocator_options, + _Outptr_opt_ OrtAllocator** allocator); + + /** \brief Get a shared allocator from the OrtEnv. + * + * By default there is a shared allocator created for all OrtEpDevice instances, so if you get the OrtMemoryInfo + * from the OrtEpDevice using EpDevice_MemoryInfo a shared allocator is guaranteed to exist. + * + * This will also match and return custom allocators added with RegisterAllocator. + * + * It is not an error to not find a matching allocator. + * + * \param[in] env The OrtEnv instance to get the shared allocator from. + * \param[in] mem_info The OrtMemoryInfo instance to get the shared allocator for. + * \param[out] allocator A pointer to the shared allocator, or nullptr if no shared allocator exists for + * the given memory info. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API2_STATUS(GetSharedAllocator, _In_ OrtEnv* env, _In_ const OrtMemoryInfo* mem_info, + _Outptr_result_maybenull_ OrtAllocator** allocator); + + /** \brief Release a shared allocator from the OrtEnv for the OrtEpDevice and memory type. + * + * This will release the shared allocator for the given OrtEpDevice and memory type. + * If no shared allocator exists, this is a no-op. + * + * \param[in] env The OrtEnv instance to release the shared allocator from. + * \param[in] ep_device The OrtEpDevice instance to release the shared allocator for. + * \param[in] mem_type The memory type of the shared allocator to release. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API2_STATUS(ReleaseSharedAllocator, _In_ OrtEnv* env, _In_ const OrtEpDevice* ep_device, + _In_ OrtDeviceMemoryType mem_type); + + /** \brief Get a const pointer to the raw data inside a tensor + * + * Used to read the internal tensor data directly. + * \note The returned pointer is valid until the OrtValue is destroyed. + * + * \param[in] value A tensor type (string tensors are not supported) + * \param[out] out Filled in with a pointer to the internal storage + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API2_STATUS(GetTensorData, _In_ const OrtValue* value, _Outptr_ const void** out); + + /** \brief Get Session configuration entries. + * + * \param[in] options The session options. + * \param[out] out A pointer to a newly created OrtKeyValuePairs instance. + * + * An OrtKeyValuePairs instance containing all session configuration entries. + * Note: the user should call OrtApi::ReleaseKeyValuePairs. + * + * \since Version 1.23. + */ + ORT_API2_STATUS(GetSessionOptionsConfigEntries, _In_ const OrtSessionOptions* options, _Outptr_ OrtKeyValuePairs** out); + + /** \brief Get the OrtMemoryInfo for each input of the session. + * + * The memory info can be used to determine where the input tensors are required. + * + * The session must be fully initialized before calling this function as the input locations are not known until + * this has occurred. + * + * \param[in] session The OrtSession instance. + * \param[out] inputs_memory_info Pre-allocated array of size `num_inputs` that will be filled with the + * OrtMemoryInfo* value for each input. + * The order is the same as returned by SessionGetInputName. + * \param[in] num_inputs The number of inputs in the session. Must match SessionGetInputCount. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API2_STATUS(SessionGetMemoryInfoForInputs, _In_ const OrtSession* session, + _Out_writes_(num_inputs) const OrtMemoryInfo** inputs_memory_info, + _In_ size_t num_inputs); + + /** \brief Get the OrtMemoryInfo for each output of the session. + * + * The memory info can be used to determine the device the output tensors are produced on. + * The user can pre-allocate an OrtValue using this information or use IOBinding to keep the data on the device. + * ORT will copy the output to CPU otherwise. + * + * The session must be fully initialized before calling this function as the output locations are not known until + * this has occurred. + * + * \param[in] session The OrtSession instance. + * \param[out] outputs_memory_info Pre-allocated array of size `num_outputs` that will be filled with + * OrtMemoryInfo* values for each output. + * The order is the same as returned by SessionGetOutputName. + * \param[in] num_outputs The number of outputs in the session. Must match SessionGetOutputCount. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API2_STATUS(SessionGetMemoryInfoForOutputs, _In_ const OrtSession* session, + _Out_writes_(num_outputs) const OrtMemoryInfo** outputs_memory_info, + _In_ size_t num_outputs); + + /** \brief Get the OrtEpDevice (if available) for each input of the session. + * + * An OrtEpDevice will be available if auto EP selection is enabled by calling + * SessionOptionsSetEpSelectionPolicy or SessionOptionsSetEpSelectionPolicyDelegate, + * or if the OrtEpDevice was manually added to the session using SessionOptionsAppendExecutionProvider_V2. + * + * If an OrtEpDevice is not available for the input a nullptr is returned. + * + * The returned OrtEpDevice can be used to create an OrtSyncStream via CreateSyncStreamForEpDevice to asynchronously + * provide input to the inference session Run. + * + * The session must be fully initialized before calling this function as the assigned EPs are not known until + * this has occurred. + * + * \param[in] session The OrtSession instance. + * \param[out] inputs_ep_devices Pre-allocated array of size `num_inputs` that will be filled with + * OrtEpDevice* values for each input. + * The order is the same as returned by SessionGetInputName. + * \param[in] num_inputs The number of inputs in the session. Must match SessionGetInputCount. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API2_STATUS(SessionGetEpDeviceForInputs, _In_ const OrtSession* session, + _Out_writes_(num_inputs) const OrtEpDevice** inputs_ep_devices, + _In_ size_t num_inputs); + + /** \brief Create an OrtSyncStream for the given OrtEpDevice. + * + * The OrtSyncStream can be used to enable asynchronous operations. + * e.g. async usage of CopyTensors to provide input to an OrtSession Run call. + * + * An error code of ORT_NOT_IMPLEMENTED will be returned if the EP does not support OrtSyncStream. + * + * \param[in] ep_device The OrtEpDevice instance to create the sync stream for. + * \param[in] stream_options Options for OrtSyncStream creation. May be nullptr. + * \param[out] stream Output parameter set to the created OrtSyncStream instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API2_STATUS(CreateSyncStreamForEpDevice, _In_ const OrtEpDevice* ep_device, + _In_opt_ const OrtKeyValuePairs* stream_options, + _Outptr_ OrtSyncStream** stream); + + /** \brief Get the native handle of the sync stream. + * + * This returns the native handle for the stream. e.g. cudaStream_t for CUDA streams. + * + * \param[in] stream The OrtSyncStream instance to get the handle from. + * + * \returns The native handle of the stream. + * + * \since Version 1.23 + */ + ORT_API_T(void*, SyncStream_GetHandle, _In_ OrtSyncStream* stream); + + ORT_CLASS_RELEASE(SyncStream); + + /** \brief Copy OrtValue instances containing Tensors between devices. + * + * The overall copy must be between a single source device and a single destination device. i.e. + * - all src_tensors must have matching OrtMemoryInfo, + * - all dst_tensors must have matching OrtMemoryInfo. + * + * OrtValue instances can be created by: + * - Use GetSharedAllocator to get the shared allocator for the OrtMemoryInfo if you need to allocate memory + * on the device. + * - Use CreateTensorAsOrtValue, CreateTensorWithDataAsOrtValue or CreateTensorWithDataAndDeleterAsOrtValue + * to create an OrtValue containing a tensor depending on whether you have existing data or not, and whether + * you want ORT to free the existing data once it is done with the OrtValue. + * + * \param[in] env The OrtEnv instance to use. The data transfer implementation is provided by an execution provider + * that is registered in this OrtEnv. + * \param[in] src_tensors Array of OrtValue instances containing the source tensors to copy. + * \param[in] dst_tensors Array of OrtValue instances to copy the source tensors to. + * \param[in] stream Optional OrtSyncStream that can be used to perform the copy asynchronously. May be nullptr. + * \param[in] num_tensors The number of tensors to copy. The size of `src_tensors` and `dst_tensors` must match. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23 + */ + ORT_API2_STATUS(CopyTensors, _In_ const OrtEnv* env, + _In_reads_(num_tensors) const OrtValue* const* src_tensors, + _In_reads_(num_tensors) OrtValue* const* dst_tensors, + _In_opt_ OrtSyncStream* stream, + _In_ size_t num_tensors); + + /** \brief Get ::OrtModelMetadata from an ::OrtGraph + * + * \param[in] graph The OrtGraph instance. + * \param[out] out Newly created ::OrtModelMetadata. Must be freed using OrtApi::ReleaseModelMetadata. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Graph_GetModelMetadata, _In_ const OrtGraph* graph, _Outptr_ OrtModelMetadata** out); + + /** \brief Validate a compiled model's compatibility information for one or more EP devices. + * + * \param[in] ep_devices The EP devices to validate against (e.g., from GetEpDevices). + * All devices must belong to the same execution provider. + * \param[in] num_ep_devices The number of EP devices provided. + * \param[in] compatibility_info The compatibility info string produced when the model was compiled. + * \param[out] out_status The resulting compatibility status for the EP devices. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(GetModelCompatibilityForEpDevices, + _In_reads_(num_ep_devices) const OrtEpDevice* const* ep_devices, + _In_ size_t num_ep_devices, + _In_ const char* compatibility_info, + _Out_ OrtCompiledModelCompatibility* out_status); + + /// \name OrtExternalInitializerInfo + /// @{ + + /** \brief Creates an OrtExternalInitializerInfo instance. + * + * \param[in] filepath The relative path to the file that stores the initializer's data. ORT copies this path string. + * \param[in] file_offset The byte offset where the initializer's data is stored within the file. + * \param[in] byte_size The size in bytes of the initializer's data within the file. + * \param[out] out Output parameter set to the new OrtExternalInitializerInfo instance. + * Must be released by calling ReleaseExternalInitializerInfo(). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(CreateExternalInitializerInfo, _In_ const ORTCHAR_T* filepath, _In_ int64_t file_offset, + _In_ size_t byte_size, _Outptr_ OrtExternalInitializerInfo** out); + + /// @} + /** \brief Fetch whether the tensor has shape information. + * \param[in] info The OrtTensorTypeAndShapeInfo instance. + * \return true if the tensor has shape information, false otherwise. + * + * \since Version 1.24 + */ + ORT_API_T(bool, TensorTypeAndShape_HasShape, _In_ const OrtTensorTypeAndShapeInfo* info); + + /** \brief Get all config entries from ::OrtKernelInfo. + * + * Gets all configuration entries from the ::OrtKernelInfo object as key-value pairs. + * Config entries are set on the ::OrtSessionOptions and are accessible in custom operator kernels. + * + * Used in the CreateKernel callback of an OrtCustomOp to access all session configuration entries + * during kernel construction. + * + * \param[in] info An instance of ::OrtKernelInfo. + * \param[out] out A pointer to a newly created OrtKeyValuePairs instance containing all config entries. + * Note: the user should call OrtApi::ReleaseKeyValuePairs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.24 + */ + ORT_API2_STATUS(KernelInfo_GetConfigEntries, _In_ const OrtKernelInfo* info, _Outptr_ OrtKeyValuePairs** out); + + /** \brief Get the graph node's operator domain from ::OrtKernelInfo. + * + * If `out` is nullptr, the value of `size` is set to the size of the operator domain + * string (including null-terminator), and a success status is returned. + * + * If the `size` parameter is greater than or equal to the string's size and `out` is not nullptr, + * the value of `size` is set to the true size of the string (including null-terminator), + * the provided memory is filled with the string's contents, and a success status is returned. + * + * If the `size` parameter is less than the actual string's size and `out` + * is not nullptr, the value of `size` is set to the true size of the string + * and a failure status with error code ORT_INVALID_ARGUMENT is returned. + * + * \param[in] info An instance of ::OrtKernelInfo. + * \param[out] out Memory location into which to write the UTF-8 null-terminated string representing the + * operator domain. + * \param[in,out] size Pointer to the size of the `out` buffer. See above comments for details. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.24 + */ + ORT_API2_STATUS(KernelInfo_GetOperatorDomain, _In_ const OrtKernelInfo* info, _Out_opt_ char* out, + _Inout_ size_t* size); + + /** \brief Get the graph node's operator type from ::OrtKernelInfo. + * + * If `out` is nullptr, the value of `size` is set to the size of the operator type + * string (including null-terminator), and a success status is returned. + * + * If the `size` parameter is greater than or equal to the string's size and `out` is not nullptr, + * the value of `size` is set to the true size of the string (including null-terminator), + * the provided memory is filled with the string's contents, and a success status is returned. + * + * If the `size` parameter is less than the actual string's size and `out` + * is not nullptr, the value of `size` is set to the true size of the string + * and a failure status with error code ORT_INVALID_ARGUMENT is returned. + * + * \param[in] info An instance of ::OrtKernelInfo. + * \param[out] out Memory location into which to write the UTF-8 null-terminated string representing the + * operator type. + * \param[in,out] size Pointer to the size of the `out` buffer. See above comments for details. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.24 + */ + ORT_API2_STATUS(KernelInfo_GetOperatorType, _In_ const OrtKernelInfo* info, _Out_opt_ char* out, + _Inout_ size_t* size); + + /** \brief Get the opset version in which the given node's operator type was first defined from ::OrtKernelInfo. + * + * \param[in] info An instance of ::OrtKernelInfo. + * \param[out] since_version The opset version in which the node's operator type was first defined. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.24 + */ + ORT_API2_STATUS(KernelInfo_GetOperatorSinceVersion, _In_ const OrtKernelInfo* info, + _Out_ int* since_version); + + /** \brief Get the EP Interop API instance. + * + * Get the Interop API instance to work with external resources. This API provides functions + * for importing external GPU memory and semaphores for zero-copy sharing between ORT inference + * and other GPU workloads. + * + * \return Interop API struct instance. + * + * \since Version 1.24. + */ + const OrtInteropApi*(ORT_API_CALL* GetInteropApi)(void); + + /** \brief Get the EP device assigned to each session output. + * + * Returns the OrtEpDevice assigned to each output of the session after graph partitioning. + * This allows validation that outputs are placed on the expected device for external resource sharing. + * + * The EP device for each output is determined by which execution provider will produce that output + * during inferencing. This information is useful for: + * - Validating that outputs will be placed on the expected device for external resource sharing + * - Deciding whether to use external memory handles for outputs + * + * \param[in] session The OrtSession instance to query. + * \param[out] outputs_ep_devices An array to be filled with the EP device for each output. + * The array must be allocated by the caller with space for + * OrtEpDevice* values for each output. + * The order is the same as returned by SessionGetOutputName. + * \param[in] num_outputs The number of outputs in the session. Must match SessionGetOutputCount. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24 + */ + ORT_API2_STATUS(SessionGetEpDeviceForOutputs, _In_ const OrtSession* session, + _Out_writes_(num_outputs) const OrtEpDevice** outputs_ep_devices, + _In_ size_t num_outputs); + /** \brief Get the number of available hardware devices. + * + * Returns the count of hardware devices discovered on the system. + * Use this to allocate an array before calling GetHardwareDevices(). + * + * \param[in] env The OrtEnv instance where device discovery results are stored. + * \param[out] num_devices The number of OrtHardwareDevice instances available. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(GetNumHardwareDevices, _In_ const OrtEnv* env, _Out_ size_t* num_devices); + + /** \brief Get the list of available hardware devices. + * + * Enumerates hardware devices available on the system. + * Populates a user-provided array with pointers to OrtHardwareDevice instances. The caller is responsible + * for allocating the array with sufficient space (use GetNumHardwareDevices() to get the count). + * + * The returned pointers reference internal ORT data structures that are discovered once at process + * startup and remain valid for the lifetime of the OrtEnv. The caller does not need to release these + * pointers, but should not use them after calling ReleaseEnv(). + * + * \param[in] env The OrtEnv instance where device discovery results are stored. + * \param[out] devices User-allocated array to receive pointers to OrtHardwareDevice instances. + * The array must have space for at least num_devices elements. + * \param[in] num_devices The size of the user-allocated devices array. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(GetHardwareDevices, _In_ const OrtEnv* env, + _Out_writes_(num_devices) const OrtHardwareDevice** devices, + _In_ size_t num_devices); + + /** \brief Check for known incompatibility issues between hardware device and a specific execution provider. + * + * This function checks for known incompatibility issues between the specified hardware device + * and a specific execution provider. + * If returned incompatibility details have non-zero reasons, it indicates the device is not compatible. + * However, if returned detail have reason == 0, it doesn't guarantee 100% compatibility for all models, + * as models may have specific requirements. + * + * Note: This method should only be called when the OrtEnv has been initialized with execution + * providers (after RegisterExecutionProviderLibrary is called). + * + * \param[in] env The OrtEnv instance with registered execution providers. + * \param[in] ep_name The name of the execution provider to check. Required and cannot be null or empty. + * \param[in] hw The hardware device to check for incompatibility. + * \param[out] details Compatibility details including reasons for incompatibility if any. + * Must be freed with OrtApi::ReleaseDeviceEpIncompatibilityDetails. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(GetHardwareDeviceEpIncompatibilityDetails, _In_ const OrtEnv* env, + _In_ const char* ep_name, + _In_ const OrtHardwareDevice* hw, + _Outptr_ OrtDeviceEpIncompatibilityDetails** details); + + /// \name OrtDeviceEpIncompatibilityDetails + /// Accessor functions for device incompatibility details + /// @{ + + /** \brief Get the incompatibility reasons bitmask from OrtDeviceEpIncompatibilityDetails. + * + * \param[in] details The OrtDeviceEpIncompatibilityDetails instance to query. + * \param[out] reasons_bitmask Pointer to store the bitmask of incompatibility reasons. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(DeviceEpIncompatibilityDetails_GetReasonsBitmask, + _In_ const OrtDeviceEpIncompatibilityDetails* details, + _Out_ uint32_t* reasons_bitmask); + + /** \brief Get the notes from OrtDeviceEpIncompatibilityDetails. + * + * \param[in] details The OrtDeviceEpIncompatibilityDetails instance to query. + * \param[out] notes Pointer to the notes string. May be nullptr if no notes are available. + * The returned string is owned by the details object and should not be freed. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(DeviceEpIncompatibilityDetails_GetNotes, + _In_ const OrtDeviceEpIncompatibilityDetails* details, + _Outptr_result_maybenull_ const char** notes); + + /** \brief Get the execution provider error code from OrtDeviceEpIncompatibilityDetails. + * + * This allows Independent Hardware Vendors (IHVs) to define their own error codes + * to provide additional details about device incompatibility. + * + * \param[in] details The OrtDeviceEpIncompatibilityDetails instance to query. + * \param[out] error_code Pointer to store the EP-specific error code. A value of 0 indicates no error code was set. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(DeviceEpIncompatibilityDetails_GetErrorCode, + _In_ const OrtDeviceEpIncompatibilityDetails* details, + _Out_ int32_t* error_code); + + /** \brief Release an OrtDeviceEpIncompatibilityDetails instance. + * + * \since Version 1.24. + */ + ORT_CLASS_RELEASE(DeviceEpIncompatibilityDetails); + + /// @} + + /// \name Model Compatibility APIs + /// @{ + + /** \brief Extract EP compatibility info from a precompiled model file. + * + * Parses the model file to extract the compatibility info string for a specific execution provider + * from the model's metadata properties. This is only applicable to models that have been precompiled + * for an EP (e.g., via OrtCompileApi). Standard ONNX models do not contain this information. + * + * The compatibility info string must be valid UTF-8 without embedded NUL characters. + * + * \note This API performs standalone model parsing, separate from session creation. This means + * the protobuf parsing cost is incurred here and again during session creation. It is intended + * for scenarios where applications need to check compatibility before deciding whether to proceed + * with session creation, such as providing early user feedback. + * + * \note This operation parses the full ONNX ModelProto from disk. For very large models, consider + * using GetCompatibilityInfoFromModelBytes with a pre-loaded buffer if the model is already in memory. + * + * The compatibility info can then be passed to GetModelCompatibilityForEpDevices to check if a + * precompiled model is compatible with the current system. + * + * \param[in] model_path Path to the ONNX model file. + * \param[in] ep_type The execution provider type string. Must be non-empty. + * Use OrtApi::EpDevice_EpName to get this value from an OrtEpDevice. + * \param[in] allocator Allocator to use for the output string. Use OrtApi::GetAllocatorWithDefaultOptions. + * \param[out] compatibility_info Output pointer to the compatibility info string. + * Returns nullptr if no compatibility info exists for the specified EP. + * Caller must free with OrtApi::AllocatorFree when non-null. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(GetCompatibilityInfoFromModel, + _In_ const ORTCHAR_T* model_path, + _In_ const char* ep_type, + _Inout_ OrtAllocator* allocator, + _Outptr_result_maybenull_ char** compatibility_info); + + /** \brief Extract EP compatibility info from precompiled model bytes in memory. + * + * Same as GetCompatibilityInfoFromModel but reads from a memory buffer instead of a file. + * Useful when precompiled models are loaded from encrypted storage, network, or other non-file sources. + * + * \note This API performs standalone model parsing, separate from session creation. This means + * the protobuf parsing cost is incurred here and again during session creation. It is intended + * for scenarios where applications need to check compatibility before deciding whether to proceed + * with session creation, such as providing early user feedback. + * + * \param[in] model_data Pointer to the model data in memory. + * \param[in] model_data_length Size of the model data in bytes. + * \param[in] ep_type The execution provider type string. Must be non-empty. + * \param[in] allocator Allocator to use for the output string. Use OrtApi::GetAllocatorWithDefaultOptions. + * \param[out] compatibility_info Output pointer to the compatibility info string. + * Returns nullptr if no compatibility info exists for the specified EP. + * Caller must free with OrtApi::AllocatorFree when non-null. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(GetCompatibilityInfoFromModelBytes, + _In_reads_(model_data_length) const void* model_data, + _In_ size_t model_data_length, + _In_ const char* ep_type, + _Inout_ OrtAllocator* allocator, + _Outptr_result_maybenull_ char** compatibility_info); + + /// @} + + /** \brief Create an OrtEnv instance with the given options. + * + * \note Invoking this function will return the same instance of the environment as that returned by a previous call + * to another env creation function; all arguments to this function will be ignored. + * + * \param[in] options The OrtEnvCreationOptions instance that contains creation options. + * \param[out] out Output parameter set to the new OrtEnv instance. Must be freed with OrtApi::ReleaseEnv. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24 + */ + ORT_API2_STATUS(CreateEnvWithOptions, _In_ const OrtEnvCreationOptions* options, _Outptr_ OrtEnv** out); + + /** \brief Get information about the subgraphs assigned to each execution provider (EP) and the nodes within. + * + * Each returned OrtEpAssignedSubgraph instance contains details of the subgraph/nodes assigned to an execution + * provider, including the execution provider's name, and the name, domain, and operator type for every node. + * + * For compiling execution providers, a single OrtEpAssignedSubgraph instance contains information about the + * nodes that are fused and compiled within a single subgraph assigned to the execution provider. + * + * For execution providers that use kernel registration (e.g., CPU EP), each node with a registered kernel is + * contained in its own OrtEpAssignedSubgraph instance. + * + * \note The caller must enable the collection of this information by enabling the session + * configuration entry "session.record_ep_graph_assignment_info" during session creation. + * Refer to onnxruntime_session_options_config_keys.h. Otherwise, if not enabled, this function returns a + * status with error code ORT_FAIL. + * + * \note The information reported by this function is obtained immediately after running basic optimizations on the + * original graph if the session optimization level is set to ORT_ENABLE_BASIC or higher. If the session + * optimization level is set to ORT_DISABLE_ALL, only minimal/required optimizations are run before + * the information is collected. + * + * \param[in] session The OrtSession instance. + * \param[out] ep_subgraphs Output parameter set to the array of OrtEpAssignedSubgraph instances. + * \param[out] num_ep_subgraphs Output parameter set to the number of elements in the `ep_subgraphs` array. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(Session_GetEpGraphAssignmentInfo, _In_ const OrtSession* session, + _Outptr_ const OrtEpAssignedSubgraph* const** ep_subgraphs, + _Out_ size_t* num_ep_subgraphs); + + /** \brief Get the name of the execution provider to which the subgraph was assigned. + * + * \param[in] ep_subgraph The OrtEpAssignedSubgraph instance. + * \param[out] out Output parameter set to the execution provider's name as a UTF-8 null-terminated string. + * Owned by the OrtEpAssignedSubgraph instance (do not free). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(EpAssignedSubgraph_GetEpName, _In_ const OrtEpAssignedSubgraph* ep_subgraph, + _Outptr_ const char** out); + + /** \brief Get the nodes in a subgraph assigned to a specific execution provider. + * + * \param[in] ep_subgraph The OrtEpAssignedSubgraph instance. + * \param[out] ep_nodes Output parameter set to the array of OrtEpAssignedNode instances. + * \param[out] num_ep_nodes Output parameter set to the number of OrtEpAssignedNode instance returned. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(EpAssignedSubgraph_GetNodes, _In_ const OrtEpAssignedSubgraph* ep_subgraph, + _Outptr_ const OrtEpAssignedNode* const** ep_nodes, _Out_ size_t* num_ep_nodes); + + /** \brief Get the name of the node assigned to an execution provider. + * + * \param[in] ep_node The OrtEpAssignedNode instance. + * \param[out] out Output parameter set to the node's name as a UTF-8 null-terminated string. + * Owned by the OrtEpAssignedNode instance (do not free). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(EpAssignedNode_GetName, _In_ const OrtEpAssignedNode* ep_node, _Outptr_ const char** out); + + /** \brief Get the domain of the node assigned to an execution provider. + * + * \param[in] ep_node The OrtEpAssignedNode instance. + * \param[out] out Output parameter set to the node's domain as a UTF-8 null-terminated string. + * Owned by the OrtEpAssignedNode instance (do not free). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(EpAssignedNode_GetDomain, _In_ const OrtEpAssignedNode* ep_node, _Outptr_ const char** out); + + /** \brief Get the operator type of the node assigned to an execution provider. + * + * \param[in] ep_node The OrtEpAssignedNode instance. + * \param[out] out Output parameter set to the node's operator type as a UTF-8 null-terminated string. + * Owned by the OrtEpAssignedNode instance (do not free). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(EpAssignedNode_GetOperatorType, _In_ const OrtEpAssignedNode* ep_node, _Outptr_ const char** out); + + /** \brief Sets OrtSyncStream for the run options + * + * OrtSyncStream is used to synchronize the execution of the model run for the device + * of the stream. It overrides the existing stream for the duration of the Run(). + * The stream instance must be alive for the duration of the Run() call. + * + * \param[in] options + * \param[in] sync_stream The synchronization stream. Pass nullptr to clear previous setting. + * + * \since 1.24 + */ + ORT_API_T(void, RunOptionsSetSyncStream, _Inout_ OrtRunOptions* options, _In_ OrtSyncStream* sync_stream); + + /** \brief Get the element data type and shape for an OrtValue that represents a Tensor (scalar, dense, or sparse). + * + * \note This function is an alternative to OrtApi::GetTensorTypeAndShape that does not allocate a new array for + * the shape data. The OrtValue instance's internal shape data is returned directly. + * + * \note Returns an error if the underlying OrtValue is not a Tensor. + * + * \param[in] value The OrtValue instance. + * \param[out] elem_type Output parameter set to the tensor element data type. + * \param[out] shape_data Output parameter set to the OrtValue instance's internal shape data array. + * For a scalar, `shape_data` is NULL and `shape_data_count` is 0. + * Must not be released as it is owned by the OrtValue instance. This pointer becomes invalid + * when the OrtValue is released or if the underlying shape data is updated or reallocated. + * \param[out] shape_data_count Output parameter set to the number of elements in `shape_data`. + * `shape_data_count` is 0 for a scalar. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(GetTensorElementTypeAndShapeDataReference, _In_ const OrtValue* value, + _Out_ ONNXTensorElementDataType* elem_type, + _Outptr_result_maybenull_ const int64_t** shape_data, + _Out_ size_t* shape_data_count); + + /** \brief Enable profiling for this run + * + * \param[in] options + * \param[in] profile_file_prefix The prefix for the profile file. The actual filename will be: + * [profile_file_prefix]_[timestamp].json + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(RunOptionsEnableProfiling, _Inout_ OrtRunOptions* options, _In_ const ORTCHAR_T* profile_file_prefix); + + /** \brief Disable profiling for this run + * + * \param[in] options + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(RunOptionsDisableProfiling, _Inout_ OrtRunOptions* options); + + /** \brief Fetch an array of strings stored as an attribute in the graph node + * + * If `out` is nullptr, the value of `size` is set to the true size of the attribute + * array and a success status is returned. + * + * Otherwise, the strings and pointer array are allocated using `allocator`. + * The caller must free each string and the pointer array with `allocator`. + * If the attribute array is empty, `*out` is set to nullptr and `*size` is set to 0. + * + * \param[in] info instance + * \param[in] name name of the attribute to be parsed + * \param[in] allocator allocator used to allocate the returned string array and strings + * \param[out] out pointer to the returned array of null-terminated UTF-8 strings + * \param[out] size actual size of attribute array + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(KernelInfoGetAttributeArray_string, _In_ const OrtKernelInfo* info, _In_ const char* name, + _Inout_ OrtAllocator* allocator, _Outptr_result_buffer_maybenull_(*size) char*** out, _Out_ size_t* size); + + /// \name OrtEnv + /// @{ + + /** \brief Set thread pool work callbacks for per-session thread pools. + * + * Stores callbacks on the Env that will be applied to per-session thread pools + * created by subsequent sessions. Does not affect sessions already created or + * global thread pools created via OrtApi::CreateEnvWithGlobalThreadPools. + * + * Requires ORT built with --enable_session_threadpool_callbacks. + * + * \param[in] env OrtEnv instance. + * \param[in] config Versioned callbacks configuration. ORT copies the struct contents; + * the caller does not need to keep the struct alive after this call returns. + * However, all pointers within the struct must remain valid for the + * lifetime of any session that uses these callbacks. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(SetPerSessionThreadPoolCallbacks, _Inout_ OrtEnv* env, + _In_ const OrtThreadPoolCallbacksConfig* config); + + /// @} + + /** \brief Check if the memory pattern optimization is enabled in the session options. + * + * \param[in] options + * \param[out] out Set to 1 if the memory pattern optimization is enabled, 0 otherwise. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.27. + * + * \see OrtApi::EnableMemPattern, OrtApi::DisableMemPattern + */ + ORT_API2_STATUS(GetMemPatternEnabled, _In_ const OrtSessionOptions* options, _Out_ int* out); + + /** \brief Get the current execution mode setting. + * + * \param[in] options + * \param[out] out Set to the current execution mode (ORT_SEQUENTIAL or ORT_PARALLEL). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.27. + * + * \see OrtApi::SetSessionExecutionMode + */ + ORT_API2_STATUS(GetSessionExecutionMode, _In_ const OrtSessionOptions* options, _Out_ ExecutionMode* out); +}; + +/* + * Steps to use a custom op: + * 1 Create an OrtCustomOpDomain with the domain name used by the custom ops + * 2 Create an OrtCustomOp structure for each op and add them to the domain + * 3 Call OrtAddCustomOpDomain to add the custom domain of ops to the session options + */ + +// Specifies some characteristics of inputs/outputs of custom ops: +// Specify if the inputs/outputs are one of: +// 1) Non-optional (input/output must be present in the node) +// 2) Optional (input/output may be absent in the node) +// 3) Variadic: A variadic input or output specifies N (i.e., the minimum arity) or more operands. +// Only the last input or output of a custom op may be marked as variadic. +// The homogeneity of the variadic input or output determines whether all operands must be of the same +// tensor element type. +typedef enum OrtCustomOpInputOutputCharacteristic { + INPUT_OUTPUT_REQUIRED = 0, + INPUT_OUTPUT_OPTIONAL, + INPUT_OUTPUT_VARIADIC, +} OrtCustomOpInputOutputCharacteristic; + +/* + * The OrtCustomOp structure defines a custom op's schema and its kernel callbacks. The callbacks are filled in by + * the implementor of the custom op. + */ +struct OrtCustomOp { + uint32_t version; // Must be initialized to ORT_API_VERSION + + // This callback creates the kernel, which is a user defined + // parameter that is passed to the Kernel* callbacks below. It is + // recommended to use CreateKernelV2 which allows for a safe error + // propagation by returning an OrtStatusPtr. + void*(ORT_API_CALL* CreateKernel)(_In_ const struct OrtCustomOp* op, _In_ const OrtApi* api, + _In_ const OrtKernelInfo* info); + + // Returns the name of the op + const char*(ORT_API_CALL* GetName)(_In_ const struct OrtCustomOp* op); + + // Returns the type of the execution provider, return nullptr to use CPU execution provider + const char*(ORT_API_CALL* GetExecutionProviderType)(_In_ const struct OrtCustomOp* op); + + // Returns the count and types of the input & output tensors + ONNXTensorElementDataType(ORT_API_CALL* GetInputType)(_In_ const struct OrtCustomOp* op, _In_ size_t index); + size_t(ORT_API_CALL* GetInputTypeCount)(_In_ const struct OrtCustomOp* op); + ONNXTensorElementDataType(ORT_API_CALL* GetOutputType)(_In_ const struct OrtCustomOp* op, _In_ size_t index); + size_t(ORT_API_CALL* GetOutputTypeCount)(_In_ const struct OrtCustomOp* op); + + // Perform a computation step. It is recommended to use + // KernelComputeV2 which allows for a safe error propagation by + // returning an OrtStatusPtr. + void(ORT_API_CALL* KernelCompute)(_In_ void* op_kernel, _In_ OrtKernelContext* context); + void(ORT_API_CALL* KernelDestroy)(_In_ void* op_kernel); + + // Returns the characteristics of the input & output tensors + OrtCustomOpInputOutputCharacteristic(ORT_API_CALL* GetInputCharacteristic)(_In_ const struct OrtCustomOp* op, _In_ size_t index); + OrtCustomOpInputOutputCharacteristic(ORT_API_CALL* GetOutputCharacteristic)(_In_ const struct OrtCustomOp* op, _In_ size_t index); + + // Returns the memory type of the input tensors. This API allows the custom op + // to place the inputs on specific devices. By default, it returns + // OrtMemTypeDefault, which means the input is placed on the default device for + // the execution provider. If the inputs need to be with different memory types, + // this function can be overridden to return the specific memory types. + OrtMemType(ORT_API_CALL* GetInputMemoryType)(_In_ const struct OrtCustomOp* op, _In_ size_t index); + + // Returns the minimum number of input arguments expected for the variadic input. + // Applicable only for custom ops that have a variadic input. + int(ORT_API_CALL* GetVariadicInputMinArity)(_In_ const struct OrtCustomOp* op); + + // Returns true (non-zero) if all arguments of a variadic input have to be of the same type (homogeneous), + // and false (zero) otherwise. + // Applicable only for custom ops that have a variadic input. + int(ORT_API_CALL* GetVariadicInputHomogeneity)(_In_ const struct OrtCustomOp* op); // Returns the minimum number of output values expected for the variadic output. // Applicable only for custom ops that have a variadic output. int(ORT_API_CALL* GetVariadicOutputMinArity)(_In_ const struct OrtCustomOp* op); - // Returns true (non-zero) if all outputs values of a variadic output have to be of the same type (homogeneous), - // and false (zero) otherwise. - // Applicable only for custom ops that have a variadic output. - int(ORT_API_CALL* GetVariadicOutputHomogeneity)(_In_ const struct OrtCustomOp* op); + // Returns true (non-zero) if all outputs values of a variadic output have to be of the same type (homogeneous), + // and false (zero) otherwise. + // Applicable only for custom ops that have a variadic output. + int(ORT_API_CALL* GetVariadicOutputHomogeneity)(_In_ const struct OrtCustomOp* op); + + // Create the kernel state which is passed to each compute call. + OrtStatusPtr(ORT_API_CALL* CreateKernelV2)(_In_ const struct OrtCustomOp* op, _In_ const OrtApi* api, + _In_ const OrtKernelInfo* info, + _Out_ void** kernel); + + // Perform the computation step. + OrtStatusPtr(ORT_API_CALL* KernelComputeV2)(_In_ void* op_kernel, _In_ OrtKernelContext* context); + + OrtStatusPtr(ORT_API_CALL* InferOutputShapeFn)(_In_ const struct OrtCustomOp* op, _In_ OrtShapeInferContext*); + + // Get start range + int(ORT_API_CALL* GetStartVersion)(_In_ const struct OrtCustomOp* op); + int(ORT_API_CALL* GetEndVersion)(_In_ const struct OrtCustomOp* op); + + // Get the inplace_map that defines which output can reuse which input + // Callers will provide 2 raw int* and pass in their address, this function will fill these 2 arrays + // when return, output (*output_index)[i] may reuse the input (*input_index[i]). + // The return value is the size of these 2 arrays. + // Callers are responsible to delete these 2 arrays after use by calling OrtCustomOp::ReleaseMayInplace(). + size_t(ORT_API_CALL* GetMayInplace)(_Out_ int** input_index, _Out_ int** output_index); + + // Release the pointer input_index and output_index allocated from GetMayInplace() function. + // If GetMayInplace() is defined, this function MUST be defined as well. + void(ORT_API_CALL* ReleaseMayInplace)(_Frees_ptr_opt_ int* input_index, _Frees_ptr_opt_ int* output_index); + + // Same as GetMayInplace() and ReleaseMayInplace() + size_t(ORT_API_CALL* GetAliasMap)(_Out_ int** input_index, _Out_ int** output_index); + void(ORT_API_CALL* ReleaseAliasMap)(_Frees_ptr_opt_ int* input_index, _Frees_ptr_opt_ int* output_index); +}; + +/** + * ORT Model Editor API + */ + +/** + * \brief The OrtModelEditorApi struct provides functions to create or edit an ONNX model. + * + * See onnxruntime/test/shared_lib/test_model_editor_api.cc for example usage. + * + * \since Version 1.22. + */ +struct OrtModelEditorApi { + // Model building/editing requires a full build. We return nullptr from GetModelEditorApi if this is a minimal + // build, so it doesn't matter if there are no function pointers in this struct as a user will never get an + // OrtModelEditorApi instance. We do however need a dummy field to avoid empty struct warning. +#if defined(ORT_MINIMAL_BUILD) + const bool not_defined_in_this_build; +#else + /** \brief Create an OrtTypeInfo instance for a Tensor. + * + * Create an OrtTypeInfo instance for a Tensor to use as graph inputs/outputs with the Model Editor API. + * + * User can release `tensor_info` after creating the OrtTypeInfo. + * + * \param[in] tensor_info Tensor type and shape information. + * \param[out] type_info TypeInfo instance for the tensor. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateTensorTypeInfo, _In_ const OrtTensorTypeAndShapeInfo* tensor_info, + _Outptr_ OrtTypeInfo** type_info); + + /** \brief Create an OrtTypeInfo instance for a SparseTensor. + * + * Create an OrtTypeInfo instance for a SparseTensor to use as graph inputs/outputs with the Model Editor API. + * + * User can release `tensor_info` after creating the OrtTypeInfo. + * + * \param[in] tensor_info SparseTensor type and shape information. + * \param[out] type_info TypeInfo instance for the tensor. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateSparseTensorTypeInfo, _In_ const OrtTensorTypeAndShapeInfo* tensor_info, + _Outptr_ OrtTypeInfo** type_info); + + /** \brief Create an OrtTypeInfo instance for a Map. + * + * Create an OrtTypeInfo instance for a Map to use as graph inputs/outputs with the Model Editor API. + * + * User can release `map_value_type` after creating the OrtTypeInfo. + * + * \param[in] map_key_type Key type for the map. + * \param[in] map_value_type Value type for the map. + * \param[out] type_info TypeInfo instance for the map. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateMapTypeInfo, ONNXTensorElementDataType map_key_type, _In_ const OrtTypeInfo* map_value_type, + _Outptr_ OrtTypeInfo** type_info); + + /** \brief Create an OrtTypeInfo instance for a Sequence. + * + * Create an OrtTypeInfo instance for a Sequence to use as graph inputs/outputs with the Model Editor API. + * + * User can release `sequence_type` after creating the OrtTypeInfo. + * + * \param[in] sequence_type Sequence type and shape information. + * \param[out] type_info TypeInfo instance for the sequence. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateSequenceTypeInfo, _In_ const OrtTypeInfo* sequence_type, _Outptr_ OrtTypeInfo** type_info); + + /** \brief Create an OrtTypeInfo instance for an Optional. + * + * Create an OrtTypeInfo instance for an Optional to use as graph inputs/outputs with the Model Editor API. + * + * User can release `contained_type` after creating the OrtTypeInfo. + * + * \param[in] contained_type Tensor type and shape information. + * \param[out] type_info TypeInfo instance for the tensor. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateOptionalTypeInfo, _In_ const OrtTypeInfo* contained_type, _Outptr_ OrtTypeInfo** type_info); + + /** \brief Create an OrtValueInfo for use as an OrtGraph input or output. + * + * \param[in] name The name of the input or output. + * \param[in] type_info The type information for the input or output. The provided value is copied. + * \param[out] value_info The OrtValueInfo instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateValueInfo, _In_ const char* name, _In_ const OrtTypeInfo* type_info, + _Outptr_ OrtValueInfo** value_info); + + /** \brief Create an OrtNode to add to an OrtGraph. + * + * Create an OrtNode. + * + * Create attributes with CreateOpAttr. OrtOpAttr instances are copied. + * + * \param[in] operator_name The name of the operator. + * \param[in] domain_name The domain of the operator. Use an empty string for ONNX operators. + * \param[in] node_name The name of the node. + * \param[in] input_names The names of the inputs. + * \param[in] input_names_len The number of input names. + * \param[in] output_names The names of the outputs. + * \param[in] output_names_len The number of output names. + * \param[in] attributes The optional attributes of the node. + * \param[in] attribs_len The number of attributes. May be zero. + * \param[out] node The OrtNode instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateNode, _In_ const char* operator_name, _In_ const char* domain_name, _In_ const char* node_name, + _In_reads_(input_names_len) const char* const* input_names, size_t input_names_len, + _In_reads_(output_names_len) const char* const* output_names, size_t output_names_len, + _In_reads_(attribs_len) _In_opt_ OrtOpAttr** attributes, _In_ size_t attribs_len, + _Outptr_ OrtNode** node); + + /** \brief Create an OrtGraph + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateGraph, _Outptr_ OrtGraph** graph); + + /** \brief Set the inputs for the OrtGraph. + * + * Set the graph inputs. This will replace any existing inputs with the new values. + * The OrtGraph takes ownership of the OrtValueInfo instances and you should NOT call OrtApi::ReleaseValueInfo. + * + * \param[in] graph The OrtGraph instance to update. + * \param[in] inputs The input OrtValueInfo instances. + * \param[in] inputs_len The number of input OrtValueInfo instances. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(SetGraphInputs, _Inout_ OrtGraph* graph, + _In_reads_(inputs_len) _In_ OrtValueInfo** inputs, _In_ size_t inputs_len); + + /** \brief Set the outputs for the OrtGraph. + * + * Set the graph outputs. This will replace any existing outputs with the new values. + * The OrtGraph takes ownership of the OrtValueInfo instances provided and you should NOT call OrtApi::ReleaseValueInfo. + * + * \param[in] graph The OrtGraph instance to update. + * \param[in] outputs The output OrtValueInfo instances. + * \param[in] outputs_len The number of output OrtValueInfo instances. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(SetGraphOutputs, _Inout_ OrtGraph* graph, + _In_reads_(outputs_len) _In_ OrtValueInfo** outputs, _In_ size_t outputs_len); + + /** \brief Add an initializer to the OrtGraph + * + * ORT will copy the OrtValue wrapper internally. The caller retains ownership of the OrtValue and should + * release it with OrtApi::ReleaseValue when done. Note that the underlying data buffer is not copied. + * If the OrtValue was created with a user-provided buffer (e.g., OrtApi::CreateTensorWithDataAsOrtValue), + * that buffer must remain valid for the duration of the inference session. + * + * Two options: + * + * Allocated memory: + * Use OrtApi::CreateTensorAsOrtValue (allocates memory) and populate the tensor with the data. + * Set `data_is_external` to false. + * + * Pre-existing memory: + * Use OrtApi::CreateTensorWithDataAsOrtValue or OrtApi::CreateTensorWithDataAndDeleterAsOrtValue to create an OrtValue + * with a tensor that contains a pointer to the existing data. + * Set `data_is_external` to true. + * + * The pointer must remain valid for the duration of the inference session. + * If using OrtApi::CreateTensorWithDataAsOrtValue you are responsible for freeing the memory after the inference session + * is released. + * If using OrtApi::CreateTensorWithDataAndDeleterAsOrtValue, ORT will free the memory using the provided deleter as + * soon as the OrtValue is no longer in use. + * + * NOTE: A tensor containing pre-existing memory MUST have 128 bytes of data or more. + * For smaller tensors use OrtApi::CreateTensorAsOrtValue. + * + * ONNX shape inferencing does not support external data. An initializer involved in shape inferencing is + * typically small (a single value or limited by the rank of a tensor) and uses less than 128 bytes of + * memory, so this limit acts as a simple catch-all rule to avoid issues. + * e.g. Reshape's `shape`, Clip's `min` and `max`, various ops `axes`. + * + * \param[in] graph The OrtGraph instance to update. + * \param[in] name The value name for the initializer. + * \param[in] ort_value The OrtValue instance containing the tensor data. + * \param[in] data_is_external Set to true if the data is external and should not be serialized into the model. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(AddInitializerToGraph, _Inout_ OrtGraph* graph, _In_ const char* name, + _In_ const OrtValue* ort_value, bool data_is_external); + + /** \brief Add an OrtNode to an OrtGraph + * + * Add the node to the graph. The OrtGraph will take ownership of OrtNode and you should NOT call OrtApi::ReleaseNode. + * + * \param[in] graph The OrtGraph instance to update. + * \param[in] node The OrtNode instance to add to the graph. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(AddNodeToGraph, _Inout_ OrtGraph* graph, _In_ OrtNode* node); + + /** \brief Create an OrtModel. + * + * Create an OrtModel. + * + * This can be used to build a new model, or to augment an existing model. + * + * \param[in] domain_names The domain names for the model. + * If augmenting an existing model add additional domains if needed. + * \param[in] opset_versions The opset versions for the model. + * If augmenting an existing model add additional opset versions if needed. + * \param[in] opset_entries_len The number of domain_names and opset_versions entries. + * Domain and opset entries should be 1:1 + * \param[out] model The OrtModel instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateModel, + _In_reads_(opset_entries_len) const char* const* domain_names, + _In_reads_(opset_entries_len) const int* opset_versions, + size_t opset_entries_len, + _Outptr_ OrtModel** model); + + /** \brief Add an OrtGraph to an OrtModel. + * + * Add the graph to a model. This should be called once when creating a new model. + * + * The OrtModel takes ownership of the OrtGraph and you should NOT call OrtApi::ReleaseGraph. + * + * \param[in] model The OrtModel instance to update. + * \param[in] graph The OrtGraph instance to add to the model. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(AddGraphToModel, _Inout_ OrtModel* model, _In_ OrtGraph* graph); + + /** \brief Create an OrtSession using the OrtModel. + * + * Create an inference session using the OrtModel instance. + * The OrtModel should have been populated with an OrtGraph containing nodes and initializers, and SetGraphInputs + * and SetGraphOutputs must have been called. + * This will validate the model, run optimizers, and prepare the session for inferencing. + * + * OrtApi::ReleaseModel must be called to free the OrtModel after session creation. + * + * \param[in] env The OrtEnv instance. + * \param[in] model The OrtModel instance. + * \param[in] options The OrtSessionOptions instance. + * \param[out] out The OrtSession instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateSessionFromModel, _In_ const OrtEnv* env, _In_ const OrtModel* model, + _In_ const OrtSessionOptions* options, _Outptr_ OrtSession** out); + + /** \brief Create an OrtSession to augment an existing model. + * + * Create an OrtSession with an existing model that will be augmented with additional nodes and initializers. + * Nodes can be added before or after the existing nodes in the model. ONNX Runtime will connect the nodes when the + * model is finalized. + * + * To add nodes and initializers to the existing model, first create an OrtModel using CreateModel(). + * Add nodes and initializers to the OrtModel using AddNodeToGraph() and AddInitializerToGraph(). + * Graph inputs/outputs should be updated with SetGraphInputs() and SetGraphOutputs() as needed to reflect changes made + * by the new nodes. The list of graph inputs/outputs should be for the overall model and not just the new nodes. + * + * Add the new information from the OrtModel to the original model using ApplyModelToSession(), and prepare the + * session for inferencing by calling FinalizeModelEditorSession(). + * + * \param{in} env The OrtEnv instance. + * \param{in} model_path The path to the existing ONNX model to augment. + * \param{in} options The OrtSessionOptions instance. + * \param{out} out The created OrtSession instance. + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateModelEditorSession, _In_ const OrtEnv* env, _In_ const ORTCHAR_T* model_path, + _In_ const OrtSessionOptions* options, + _Outptr_ OrtSession** out); + + /** \brief Create an OrtSession to augment an existing model. + * + * Create an OrtSession with an existing model that will be augmented with additional nodes and initializers. + * Nodes can be added before or after the existing nodes in the model. ONNX Runtime will connect the nodes when the + * model is finalized. + * + * To add nodes and initializers to the existing model, first create an OrtModel using CreateModel(). + * Add nodes and initializers to the OrtModel using AddNodeToGraph() and AddInitializerToGraph(). + * Graph inputs/outputs should be updated with SetGraphInputs() and SetGraphOutputs() as needed to reflect changes made + * by the new nodes. The list of graph inputs/outputs should be for the overall model and not just the new nodes. + * + * Add the new information from the OrtModel to the original model using ApplyModelToSession(), and prepare the + * session for inferencing by calling FinalizeModelEditorSession(). + * + * \param{in} env The OrtEnv instance. + * \param{in} model_data The model data for the existing model to augment. + * \param{in} model_data_length The length of the model data. + * \param{in} options The OrtSessionOptions instance. + * \param{out} out The created OrtSession instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateModelEditorSessionFromArray, _In_ const OrtEnv* env, + _In_ const void* model_data, size_t model_data_length, + _In_ const OrtSessionOptions* options, + _Outptr_ OrtSession** out); + + /** \brief Query the session for the opset version of a domain. + * + * When using the Model Editor API to augment a model, any new nodes must conform to the opset version of the + * original model. To do that the user must be able to discover that opset version. + * Returns an error if the domain is not used in the model. + * + * \param[in] session OrtSession to query + * \param[in] domain Domain to query. The ONNX domain is an empty string. + * \param[out] opset The opset version of the domain. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(SessionGetOpsetForDomain, _In_ const OrtSession* session, _In_ const char* domain, _Out_ int* opset); + + /** \brief Apply changes to augment the ONNX model in a session created using CreateModelEditorSession[FromArray] + * + * Adds new nodes and updates graph inputs/outputs using `model` to augment the original ONNX model in the session. + * All changes will be validated. + * Call FinalizeModelEditorSession to prepare the session for inferencing. + * + * Existing input/outputs will only be updated if the OrtGraph inputs/outputs are set in the OrtModel. + * i.e. you don't need to call SetGraphInputs/SetGraphOutputs if they are unchanged. + * + * ReleaseOrtModel must be called to free the OrtModel after it is applied to the session. + * + * \param[in] session OrtSession to update. Session must have been created using CreateModelEditorSession[FromArray]. + * \param[in] model OrtModel containing new nodes, new initializers, and updated graph input and/or output info. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(ApplyModelToModelEditorSession, _Inout_ OrtSession* session, _In_ OrtModel* model); - // Create the kernel state which is passed to each compute call. - OrtStatusPtr(ORT_API_CALL* CreateKernelV2)(_In_ const struct OrtCustomOp* op, _In_ const OrtApi* api, - _In_ const OrtKernelInfo* info, - _Out_ void** kernel); + /** \brief Finalize the Model Editor session that was created using CreateModelEditorSession[FromArray]. + * + * Finalize the Model Editor session that augmented an ONNX model by adding new nodes. + * This will run optimizers and prepare the session for inferencing. + * + * \param[in] session OrtSession to finalize. Session must have been created using CreateModelEditorSession[FromArray]. + * \param[in] options OrtSessionOptions to use for the session. + * \param[in] prepacked_weights_container Optional OrtPrepackedWeightsContainer to use for the session. + Set to nullptr if not used. + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(FinalizeModelEditorSession, _Inout_ OrtSession* session, _In_ const OrtSessionOptions* options, + _In_opt_ OrtPrepackedWeightsContainer* prepacked_weights_container); +#endif // !defined(ORT_MINIMAL_BUILD) +}; - // Perform the computation step. - OrtStatusPtr(ORT_API_CALL* KernelComputeV2)(_In_ void* op_kernel, _In_ OrtKernelContext* context); +/** + * ORT Compile API + */ - OrtStatusPtr(ORT_API_CALL* InferOutputShapeFn)(_In_ const struct OrtCustomOp* op, _In_ OrtShapeInferContext*); +/** \brief Flags representing options to enable when compiling a model. + */ +typedef enum OrtCompileApiFlags { + // Default. Do not enable any additional compilation options. + OrtCompileApiFlags_NONE = 0, - // Get start range - int(ORT_API_CALL* GetStartVersion)(_In_ const struct OrtCustomOp* op); - int(ORT_API_CALL* GetEndVersion)(_In_ const struct OrtCustomOp* op); + // Force compilation to return an error (ORT_FAIL) if no nodes were compiled. + // Otherwise, a model with basic optimizations (ORT_ENABLE_BASIC) is still generated by default. + OrtCompileApiFlags_ERROR_IF_NO_NODES_COMPILED = 1 << 0, - // Get the inplace_map that defines which output can reuse which input - // Callers will provide 2 raw int* and pass in their address, this function will fill these 2 arrays - // when return, output (*output_index)[i] may reuse the input (*input_index[i]). - // The return value is the size of these 2 arrays. - // Callers are responsible to delete these 2 arrays after use by calling OrtCustomOp::ReleaseMayInplace(). - size_t(ORT_API_CALL* GetMayInplace)(_Out_ int** input_index, _Out_ int** output_index); + // Force compilation to return an error (ORT_FAIL) if a file with the same filename as the output model exists. + // Otherwise, compilation will automatically overwrite the output file if it exists. + OrtCompileApiFlags_ERROR_IF_OUTPUT_FILE_EXISTS = 1 << 1, +} OrtCompileApiFlags; - // Release the pointer input_index and output_index allocated from GetMayInplace() function. - // If GetMayInplace() is defined, this function MUST be defined as well. - void(ORT_API_CALL* ReleaseMayInplace)(_Frees_ptr_opt_ int* input_index, _Frees_ptr_opt_ int* output_index); +/** + * \brief The OrtCompileApi struct provides functions to compile ONNX models. + * + * Execution providers that support compilation fuse a subgraph into an EPContext node that wraps a provider-specific + * binary representation of the subgraph. + * For more details about the EPContext design, refer to: + * \htmlonly + * EPContext design document. + * \endhtmlonly + * + * Example (error handling not shown): + * OrtStatus* status = NULL; + * OrtCompileApi* compile_api = ort_api->GetCompileApi(); + * OrtModelCompilationOptions* compile_options = NULL; + * + * status = compile_api->CreateModelCompilationOptionsFromSessionOptions(env, session_options, &compile_options); + * status = compile_api->ModelCompilationOptions_SetInputModelPath(compile_options, ORT_TSTR("model.onnx")); + * status = compile_api->ModelCompilationOptions_SetOutputModelPath(compile_options, ORT_TSTR("model.compiled.onnx")); + * status = compile_api->CompileModel(env, compile_options); + * compile_api->ReleaseModelCompilationOptions(compile_options); + * + * \since Version 1.22. + */ +struct OrtCompileApi { + /// \name OrtModelCompilationOptions + /// @{ + ORT_CLASS_RELEASE(ModelCompilationOptions); - // Same as GetMayInplace() and ReleaseMayInplace() - size_t(ORT_API_CALL* GetAliasMap)(_Out_ int** input_index, _Out_ int** output_index); - void(ORT_API_CALL* ReleaseAliasMap)(_Frees_ptr_opt_ int* input_index, _Frees_ptr_opt_ int* output_index); + /** \brief Creates an OrtModelCompilationOptions object from an existing OrtSessionOptions object. + * + * An OrtModelCompilationOptions object contains the settings used to generate a compiled ONNX model. + * The OrtSessionOptions object has the execution providers with which the model will be compiled. + * + * ReleaseOrtModelCompilationsOptions must be called to free the OrtModelCompilationOptions after calling + * CompileModel. + * + * \note By default, the GraphOptimizationLevel is set to ORT_DISABLE_ALL. Use + * ModelCompilationOptions_SetGraphOptimizationLevel to enable graph optimizations. + * + * \param[in] env OrtEnv object. + * \param[in] session_options The OrtSessionOptions instance from which to create the OrtModelCompilationOptions. + * \param[out] out The created OrtModelCompilationOptions instance. + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateModelCompilationOptionsFromSessionOptions, _In_ const OrtEnv* env, + _In_ const OrtSessionOptions* session_options, _Outptr_ OrtModelCompilationOptions** out); + + /** \brief Sets the file path to the input ONNX model to compile. + * + * The input model's location (e.g., file path or memory buffer) must be set with either + * ModelCompilationOptions_SetInputModelPath or ModelCompilationOptions_SetInputModelFromBuffer. + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] input_model_path Null terminated string of the path (wchar on Windows, char otherwise). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetInputModelPath, _In_ OrtModelCompilationOptions* model_compile_options, + _In_ const ORTCHAR_T* input_model_path); + + /** \brief Sets the buffer that stores the bytes of the loaded ONNX model to compile. + * + * The input model's location (e.g., file path or memory buffer) must be set with either + * ModelCompilationOptions_SetInputModelPath or ModelCompilationOptions_SetInputModelFromBuffer. + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] input_model_data Buffer containing the loaded ONNX model bytes. + * \param[in] input_model_data_size The number of bytes in the `input_model_data` buffer. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetInputModelFromBuffer, + _In_ OrtModelCompilationOptions* model_compile_options, + _In_ const void* input_model_data, + size_t input_model_data_size); + + /** \brief Sets the file path for the output ONNX model generated by CompileModel. + * + * The output model's location (e.g., file path or memory buffer) can be set with either + * ModelCompilationOptions_SetOutputModelPath or ModelCompilationOptions_SetOutputModelBuffer. + * + * If the output model's location is not set, ONNX Runtime will generate an output file with a path based on + * the input model's file path. Examples: + * /Path/my_model.onnx -> /Path/my_model_ctx.onnx + * /Path/my_model -> /Path/my_model_ctx.onnx + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] output_model_path Null terminated string of the path (wchar on Windows, char otherwise). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetOutputModelPath, _In_ OrtModelCompilationOptions* model_compile_options, + _In_ const ORTCHAR_T* output_model_path); + + /** \brief Optionally sets the file that should store external initializers for the compiled ONNX model. + * If not set, initializers are stored within the model. + * + * Only initializers for nodes that were not compiled are stored in the external initializers file. + * Compiled nodes contain their initializer data within the `ep_cache_context` attribute of EPContext nodes. + * Refer to ModelCompilationOptions_SetEpContextEmbedMode. + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] external_initializers_file_path Null terminated string of the path to the file. + * \param[in] external_initializers_size_threshold Initializers larger than this threshold are stored in the file. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetOutputModelExternalInitializersFile, + _In_ OrtModelCompilationOptions* model_compile_options, + _In_ const ORTCHAR_T* external_initializers_file_path, + size_t external_initializers_size_threshold); + + /** \brief Configures model compilation to store the output compiled ONNX model in a buffer. + * + * The caller passes an OrtAllocator that ONNX Runtime uses to allocate memory for the buffer. + * + * The output model's location (e.g., file path or memory buffer) can be set with either + * ModelCompilationOptions_SetOutputModelPath or ModelCompilationOptions_SetOutputModelBuffer. + * + * If the output model's location is not set, ONNX Runtime will generate an output file with a path based on + * the input model's file path. Examples: + * /Path/my_model.onnx -> /Path/my_model_ctx.onnx + * /Path/my_model -> /Path/my_model_ctx.onnx + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] allocator The allocator used to allocate the buffer for the compiled model. + * \param[out] output_model_buffer_ptr Pointer to the buffer that stores the compiled model. + * \param[out] output_model_buffer_size_ptr Pointer set to the size of output model in bytes. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetOutputModelBuffer, + _In_ OrtModelCompilationOptions* model_compile_options, + _Inout_ OrtAllocator* allocator, + _Outptr_ void** output_model_buffer_ptr, + _Out_ size_t* output_model_buffer_size_ptr); + + /** \brief Enables or disables the embedding of EPContext binary data into the `ep_cache_context` attribute + * of EPContext nodes. Defaults to false. + * + * If enabled, the `ep_cache_context` attribute of EPContext nodes will store the context binary data, which may + * include weights for compiled subgraphs. + * + * If disabled, the `ep_cache_context` attribute of EPContext nodes will contain the path to the file containing the + * context binary data. The path is set by the execution provider creating the EPContext node. + * + * More details relate to EPContext design refers to: + * \htmlonly + * EPContext design document. + * \endhtmlonly + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] embed_ep_context_in_model True to embed EPContext binary data into the EPContext node + * `ep_cache_context` attributes. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetEpContextEmbedMode, _In_ OrtModelCompilationOptions* model_compile_options, + bool embed_ep_context_in_model); + + /** \brief Compiles an input ONNX model with the given compilation options. + * + * \param[in] env OrtEnv object. + * \param[in] model_options The compilation options that defines compilation options for a model. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CompileModel, _In_ const OrtEnv* env, _In_ const OrtModelCompilationOptions* model_options); + + /** \brief Sets flags from OrtCompileApiFlags that represent one or more boolean options to enable. + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] flags bitwise OR of flags in OrtCompileApiFlags to enable. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetFlags, _In_ OrtModelCompilationOptions* model_compile_options, + uint32_t flags); + + /** Sets information related to EP context binary file. + * + * EP uses this information to decide the location and context binary file name. + * Used while compiling model with input and output in memory buffer + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] output_directory Null terminated string of the path (wchar on Windows, char otherwise). + * \param[in] model_name Null terminated string of the model name (wchar on Windows, char otherwise). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetEpContextBinaryInformation, + _In_ OrtModelCompilationOptions* model_compile_options, + _In_ const ORTCHAR_T* output_directory, + _In_ const ORTCHAR_T* model_name); + + /** Set the graph optimization level. + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] graph_optimization_level The graph optimization level. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetGraphOptimizationLevel, + _In_ OrtModelCompilationOptions* model_compile_options, + _In_ GraphOptimizationLevel graph_optimization_level); + + /** \brief Sets a OrtWriteBufferFunc function that is called by ORT to write out the output model's serialized + * ONNX bytes. + * + * The provided write function may be called repeatedly until then entire output model has been written out. Each call + * to the write function is expected to consume the entire input buffer. + * + * The output model's destination (e.g., file path, memory buffer, or stream) can be set with any of the functions + * that begin with ModelCompilationOptions_SetOutputModel____. + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] write_func The OrtWriteBufferFunc function called by ORT when writing out the model. + * \param[in] state Opaque state passed as the first argument to OrtWriteBufferFunc. Can be NULL. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetOutputModelWriteFunc, + _In_ OrtModelCompilationOptions* model_compile_options, + _In_ OrtWriteBufferFunc write_func, _In_ void* state); + + /** \brief Sets a OrtGetInitializerLocationFunc function that is called by ORT for every initializer in the generated + * model. Allows implementer to specify whether initializers should be stored within the model or externally. + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] get_initializer_location_func The OrtGetInitializerLocationFunc function called by ORT when + * to determine the location of the initializer. + * \param[in] state Opaque state passed as the first argument to OrtGetInitializerLocationFunc. Can be NULL. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetOutputModelGetInitializerLocationFunc, + _In_ OrtModelCompilationOptions* model_compile_options, + _In_ OrtGetInitializerLocationFunc get_initializer_location_func, _In_ void* state); + + /** \brief Sets the OrtModel to compile. + * + * Sets an OrtModel created via the Model Editor API as the input for compilation. + * + * The input model's source (file path, memory buffer, or OrtModel) must be set with + * one of: ModelCompilationOptions_SetInputModelPath, ModelCompilationOptions_SetInputModelFromBuffer, + * or ModelCompilationOptions_SetInputModel. + * + * The OrtModel must have a complete graph with inputs, outputs, and nodes defined. + * The caller retains ownership of the OrtModel and must not release it until after + * CompileModel returns. + * + * \param[in] model_compile_options The OrtModelCompilationOptions instance. + * \param[in] model The OrtModel to compile. The model is borrowed (not copied or owned). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(ModelCompilationOptions_SetInputModel, + _In_ OrtModelCompilationOptions* model_compile_options, + _In_ const OrtModel* model); +}; + +/** + * \brief The OrtInteropApi struct provides functions for external resource interop with execution providers. + * + * This API enables importing external GPU resources (memory and semaphores) for zero-copy sharing + * between ORT inference and other GPU workloads (e.g., D3D12 applications, media pipelines). + * + * The API is designed to be EP-agnostic and can be extended to support various GPU interop mechanisms + * (D3D12 shared handles, CUDA external memory, Vulkan, etc.). + * + * Example usage (error handling not shown): + * const OrtInteropApi* interop_api = ort_api->GetInteropApi(); + * OrtExternalResourceImporter* importer = NULL; + * + * status = interop_api->CreateExternalResourceImporterForDevice(ep_device, &importer); + * if (importer == nullptr) { + * // External resource import is optional for EPs to implement + * return; + * } + * bool can_import = false; + * status = interop_api->CanImportMemory(importer, ORT_EXTERNAL_MEMORY_HANDLE_TYPE_D3D12_RESOURCE, &can_import); + * if (can_import) { + * OrtExternalMemoryHandle* mem_handle = NULL; + * status = interop_api->ImportMemory(importer, &mem_desc, &mem_handle); + * // ... use mem_handle to create tensors ... + * interop_api->ReleaseExternalMemoryHandle(mem_handle); + * } + * interop_api->ReleaseExternalResourceImporter(importer); + * + * \since Version 1.24. + */ +struct OrtInteropApi { + /// \name OrtExternalResourceImporter + /// @{ + + /** \brief Create an external resource importer for a specific EP device. + * + * The external resource importer is a capability object that provides methods for importing + * external GPU memory and semaphores for zero-copy import with an execution provider. + * + * This is an optional EP capability. If the EP does not support external resource import, + * out_importer is set to nullptr and the function returns success (nullptr status). + * This allows callers to use the simple "if (status != nullptr) handle_error()" pattern + * and check out_importer separately for capability detection. + * + * \param[in] ep_device The OrtEpDevice instance to create the importer for. + * \param[out] out_importer Output parameter set to the created OrtExternalResourceImporter instance, + * or nullptr if the EP does not support external resource import. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(CreateExternalResourceImporterForDevice, + _In_ const OrtEpDevice* ep_device, + _Outptr_result_maybenull_ OrtExternalResourceImporter** out_importer); + + /** \brief Release an OrtExternalResourceImporter instance. + * + * \param[in] input The OrtExternalResourceImporter instance to release. May be nullptr. + * + * \since Version 1.24. + */ + ORT_CLASS_RELEASE(ExternalResourceImporter); + + /// @} + /// \name Memory Import + /// @{ + + /** \brief Check if the external resource importer can import a specific memory handle type. + * + * \param[in] importer The OrtExternalResourceImporter instance. + * \param[in] handle_type The type of external memory handle to check. + * \param[out] out_supported Set to true if the handle type is supported. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(CanImportMemory, + _In_ const OrtExternalResourceImporter* importer, + _In_ OrtExternalMemoryHandleType handle_type, + _Out_ bool* out_supported); + + /** \brief Import external memory into the execution provider. + * + * \param[in] importer The OrtExternalResourceImporter instance. + * \param[in] desc Descriptor containing the external memory handle and properties. + * \param[out] out_handle Output parameter set to the created OrtExternalMemoryHandle. + * The caller owns the returned handle and must call ReleaseExternalMemoryHandle to free it. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(ImportMemory, + _In_ OrtExternalResourceImporter* importer, + _In_ const OrtExternalMemoryDescriptor* desc, + _Outptr_ OrtExternalMemoryHandle** out_handle); + + /** \brief Release an OrtExternalMemoryHandle instance. + * + * \param[in] input The OrtExternalMemoryHandle instance to release. May be nullptr. + * + * \since Version 1.24. + */ + ORT_CLASS_RELEASE(ExternalMemoryHandle); + + /** \brief Create a tensor backed by imported external memory. + * + * The created tensor is a view over the imported memory and does not copy data. + * The OrtExternalMemoryHandle must remain valid for the lifetime of the tensor. + * + * \param[in] importer The OrtExternalResourceImporter instance. + * \param[in] mem_handle The imported external memory handle. + * \param[in] tensor_desc Descriptor specifying tensor element type, shape, and optional offset. + * \param[out] out_tensor Output parameter set to the created OrtValue containing the tensor. + * The caller owns the returned tensor and must call ReleaseValue to free it. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(CreateTensorFromMemory, + _In_ OrtExternalResourceImporter* importer, + _In_ const OrtExternalMemoryHandle* mem_handle, + _In_ const OrtExternalTensorDescriptor* tensor_desc, + _Outptr_ OrtValue** out_tensor); + + /// @} + /// \name Semaphore Import + /// @{ + + /** \brief Check if the external resource importer can import a specific semaphore type. + * + * \param[in] importer The OrtExternalResourceImporter instance. + * \param[in] type The type of external semaphore to check. + * \param[out] out_supported Set to true if the semaphore type is supported. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(CanImportSemaphore, + _In_ const OrtExternalResourceImporter* importer, + _In_ OrtExternalSemaphoreType type, + _Out_ bool* out_supported); + + /** \brief Import an external semaphore into the execution provider. + * + * The returned OrtExternalSemaphoreHandle can be used with WaitSemaphore and an OrtSyncStream + * to synchronize execution with external operations. + * + * \param[in] importer The OrtExternalResourceImporter instance. + * \param[in] desc Descriptor containing the external semaphore handle and type. + * \param[out] out_handle Output parameter set to the created OrtExternalSemaphoreHandle. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(ImportSemaphore, + _In_ OrtExternalResourceImporter* importer, + _In_ const OrtExternalSemaphoreDescriptor* desc, + _Outptr_ OrtExternalSemaphoreHandle** out_handle); + + /** \brief Release an OrtExternalSemaphoreHandle instance. + * + * \param[in] input The OrtExternalSemaphoreHandle instance to release. May be nullptr. + * + * \since Version 1.24. + */ + ORT_CLASS_RELEASE(ExternalSemaphoreHandle); + + /** \brief Wait on an external semaphore on the EP's stream. + * + * Inserts a wait operation into the EP's stream that blocks until the semaphore + * reaches the specified value. This is used to synchronize with external GPU work + * (e.g., D3D12 timeline fence). + * + * \param[in] importer The OrtExternalResourceImporter instance. + * \param[in] semaphore_handle The imported external semaphore. + * \param[in] stream The OrtSyncStream to wait on. + * \param[in] value The fence/semaphore value to wait for. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(WaitSemaphore, + _In_ OrtExternalResourceImporter* importer, + _In_ OrtExternalSemaphoreHandle* semaphore_handle, + _In_ OrtSyncStream* stream, + _In_ uint64_t value); + + /** \brief Signal an external semaphore from the EP's stream. + * + * Inserts a signal operation into the EP's stream that sets the semaphore + * to the specified value when reached. This is used to notify external GPU work + * (e.g., D3D12 timeline fence) that ORT inference is complete. + * + * \param[in] importer The OrtExternalResourceImporter instance. + * \param[in] semaphore_handle The imported external semaphore. + * \param[in] stream The OrtSyncStream to signal from. + * \param[in] value The fence/semaphore value to signal. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(SignalSemaphore, + _In_ OrtExternalResourceImporter* importer, + _In_ OrtExternalSemaphoreHandle* semaphore_handle, + _In_ OrtSyncStream* stream, + _In_ uint64_t value); + + /// @} + /// \name Graphics interop + /// @{ + + /** \brief Initialize graphics interop for an execution provider device. + * + * Requests the EP factory to set up graphics interop for the given ep_device using the + * provided config. How the factory uses the config (e.g. creating a context, affecting + * later stream creation) is implementation-defined. The config (OrtGraphicsInteropConfig) + * supplies the graphics API and optional handles; the command_queue member is optional. + * Passing command_queue and calling this before CreateSyncStreamForEpDevice for the same + * ep_device may allow the factory to enable more efficient GPU-side sync; see the EP + * documentation for details. + * + * Initialization is tied to the OrtEpDevice instance and applies across all sessions + * that use that ep_device (i.e. it is global per ep_device, not per-session). + * + * \param[in] ep_device The OrtEpDevice to initialize graphics interop for. + * \param[in] config Configuration (OrtGraphicsInteropConfig): required fields are version (ORT_API_VERSION) + * and graphics_api; optional handles include command_queue and additional_options. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(InitGraphicsInteropForEpDevice, _In_ const OrtEpDevice* ep_device, + _In_ const OrtGraphicsInteropConfig* config); + + /** \brief Deinitialize graphics interop for an execution provider device. + * + * This function cleans up the graphics interop context that was created by InitGraphicsInteropForEpDevice. + * Should be called when graphics interop is no longer needed for the ep_device. + * + * The caller must release all resources that use the interop context before calling this function: + * - OrtSyncStream instances created for this ep_device via CreateSyncStreamForEpDevice + * - OrtExternalSemaphoreHandle and OrtExternalResourceImporter instances created for this ep_device + * Failure to do so may lead to undefined behavior if the implementation destroys the underlying context. + * + * \param[in] ep_device The OrtEpDevice to deinitialize graphics interop for. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(DeinitGraphicsInteropForEpDevice, _In_ const OrtEpDevice* ep_device); + + /// @} }; /* @@ -4946,3 +8608,5 @@ ORT_API_STATUS(OrtSessionOptionsAppendExecutionProvider_Tensorrt, _In_ OrtSessio } #endif /// @} + +#include "onnxruntime_ep_c_api.h" diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_api.h b/include/onnxruntime/core/session/onnxruntime_cxx_api.h index 123ef98901003..9bc9be34514ee 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_api.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_api.h @@ -26,16 +26,17 @@ #include "onnxruntime_c_api.h" #include "onnxruntime_float16.h" +#include #include #include -#include #include #include #include -#include +#include #include #include -#include +#include +#include #ifdef ORT_NO_EXCEPTIONS #include @@ -51,6 +52,7 @@ namespace Ort { * If ORT_NO_EXCEPTIONS is defined, then any error will result in a call to abort() */ struct Exception : std::exception { + Exception(const std::string& string, OrtErrorCode code) : message_{string}, code_{code} {} Exception(std::string&& string, OrtErrorCode code) : message_{std::move(string)}, code_{code} {} OrtErrorCode GetOrtErrorCode() const { return code_; } @@ -78,22 +80,19 @@ struct Exception : std::exception { throw Ort::Exception(string, code) #endif -// This is used internally by the C++ API. This class holds the global variable that points to the OrtApi, -// it's in a template so that we can define a global variable in a header and make -// it transparent to the users of the API. -template -struct Global { - static const OrtApi* api_; -}; - -// If macro ORT_API_MANUAL_INIT is defined, no static initialization will be performed. Instead, user must call InitApi() before using it. -template #ifdef ORT_API_MANUAL_INIT -const OrtApi* Global::api_{}; -inline void InitApi() noexcept { Global::api_ = OrtGetApiBase()->GetApi(ORT_API_VERSION); } - -// Used by custom operator libraries that are not linked to onnxruntime. Sets the global API object, which is -// required by C++ APIs. +// If the macro ORT_API_MANUAL_INIT is defined, no static initialization +// will be performed. Instead, users must call InitApi() before using the +// ORT C++ APIs.. +// +// InitApi() sets the global API object using the default initialization +// logic. Users call this to initialize the ORT C++ APIs at a time that +// makes sense in their program. +inline void InitApi() noexcept; + +// InitApi(const OrtApi*) is used by custom operator libraries that are not +// linked to onnxruntime. It sets the global API object, which is required +// by the ORT C++ APIs. // // Example mycustomop.cc: // @@ -106,22 +105,88 @@ inline void InitApi() noexcept { Global::api_ = OrtGetApiBase()->GetApi(OR // // ... // } // -inline void InitApi(const OrtApi* api) noexcept { Global::api_ = api; } -#else -#if defined(_MSC_VER) && !defined(__clang__) -#pragma warning(push) -// "Global initializer calls a non-constexpr function." Therefore you can't use ORT APIs in the other global initializers. -// Please define ORT_API_MANUAL_INIT if it conerns you. -#pragma warning(disable : 26426) +inline void InitApi(const OrtApi* api) noexcept; #endif -const OrtApi* Global::api_ = OrtGetApiBase()->GetApi(ORT_API_VERSION); -#if defined(_MSC_VER) && !defined(__clang__) -#pragma warning(pop) + +namespace detail { +// This is used internally by the C++ API. This class holds the global +// variable that points to the OrtApi. +struct Global { + static const OrtApi* Api(const OrtApi* newValue = nullptr) noexcept { + // This block-level static will be initialized once when this function is + // first executed, delaying the call to DefaultInit() until it is first needed. + // + // When ORT_API_MANUAL_INIT is not defined, DefaultInit() calls + // OrtGetApiBase()->GetApi(), which may result in a shared library being + // loaded. + // + // Using a block-level static instead of a class-level static helps + // avoid issues with static initialization order and dynamic libraries + // loading other dynamic libraries. + // + // This makes it safe to include the C++ API headers in a shared library + // that is delay loaded or delay loads its dependencies. + // + // This DOES NOT make it safe to _use_ arbitrary ORT C++ APIs when + // initializing static members, however. + static const OrtApi* api = DefaultInit(); + + if (newValue) { + api = newValue; + } + + return api; + } + + private: + // Has different definitions based on ORT_API_MANUAL_INIT + static const OrtApi* DefaultInit() noexcept; + +#ifdef ORT_API_MANUAL_INIT + // Public APIs to set the OrtApi* to use. + friend void ::Ort::InitApi() noexcept; + friend void ::Ort::InitApi(const OrtApi*) noexcept; #endif +}; +} // namespace detail + +#ifdef ORT_API_MANUAL_INIT + +// See comments on declaration above for usage. +inline void InitApi(const OrtApi* api) noexcept { detail::Global::Api(api); } +inline void InitApi() noexcept { InitApi(OrtGetApiBase()->GetApi(ORT_API_VERSION)); } + +#ifdef _MSC_VER +// If you get a linker error about a mismatch here, you are trying to +// link two compilation units that have different definitions for +// ORT_API_MANUAL_INIT together. All compilation units must agree on the +// definition of ORT_API_MANUAL_INIT. +#pragma detect_mismatch("ORT_API_MANUAL_INIT", "enabled") #endif -/// This returns a reference to the OrtApi interface in use -inline const OrtApi& GetApi() noexcept { return *Global::api_; } +inline const OrtApi* detail::Global::DefaultInit() noexcept { + // When ORT_API_MANUAL_INIT is defined, there's no default init that can + // be done. + return nullptr; +} + +#else // ORT_API_MANUAL_INIT + +#ifdef _MSC_VER +// If you get a linker error about a mismatch here, you are trying to link +// two compilation units that have different definitions for +// ORT_API_MANUAL_INIT together. All compilation units must agree on the +// definition of ORT_API_MANUAL_INIT. +#pragma detect_mismatch("ORT_API_MANUAL_INIT", "disabled") +#endif + +inline const OrtApi* detail::Global::DefaultInit() noexcept { + return OrtGetApiBase()->GetApi(ORT_API_VERSION); +} +#endif // ORT_API_MANUAL_INIT + +/// This returns a reference to the ORT C API. +inline const OrtApi& GetApi() noexcept { return *detail::Global::Api(); } /// /// This function returns the onnxruntime version string @@ -143,6 +208,62 @@ std::string GetBuildInfoString(); /// vector of strings std::vector GetAvailableProviders(); +/// +/// This returns a reference to the ORT C Model Editor API. Used if building or augmenting a model at runtime. +/// +/// ORT C Model Editor API reference +inline const OrtModelEditorApi& GetModelEditorApi() { + auto* api = GetApi().GetModelEditorApi(); + if (api == nullptr) { + // minimal build + ORT_CXX_API_THROW("Model Editor API is not available in this build", ORT_FAIL); + } + + return *api; +} + +/// +/// This returns a reference to the ORT C Compile API. Used if compiling a model at runtime. +/// +/// ORT C Compile API reference +inline const OrtCompileApi& GetCompileApi() { + auto* api = GetApi().GetCompileApi(); + if (api == nullptr) { + // minimal build + ORT_CXX_API_THROW("Compile API is not available in this build", ORT_FAIL); + } + + return *api; +} + +/// +/// This returns a reference to the ORT C Interop API. Used for external resource import with EPs. +/// +/// ORT C Interop API reference +inline const OrtInteropApi& GetInteropApi() { + auto* api = GetApi().GetInteropApi(); + if (api == nullptr) { + // minimal build + ORT_CXX_API_THROW("Interop API is not available in this build", ORT_FAIL); + } + + return *api; +} + +/// +/// This returns a reference to the ORT C EP API. Used if authoring a plugin execution provider. +/// +/// ORT C EP API reference +inline const OrtEpApi& GetEpApi() { + auto* api = GetApi().GetEpApi(); + if (api == nullptr) { + // minimal build + ORT_CXX_API_THROW("EP API is not available in this build", ORT_FAIL); + } + + return *api; +} + /** \brief IEEE 754 half-precision floating point data type * * \details This struct is used for converting float to float16 and back @@ -152,7 +273,7 @@ std::vector GetAvailableProviders(); * uint16_t buffers to/from Ort::Float16_t to feed and retrieve data. * * \code{.unparsed} - * // This example demonstrates converion from float to float16 + * // This example demonstrates conversion from float to float16 * constexpr float values[] = {1.f, 2.f, 3.f, 4.f, 5.f}; * std::vector fp16_values; * fp16_values.reserve(std::size(values)); @@ -294,7 +415,7 @@ static_assert(sizeof(Float16_t) == sizeof(uint16_t), "Sizes must match"); * uint16_t buffers to/from Ort::BFloat16_t to feed and retrieve data. * * \code{.unparsed} - * // This example demonstrates converion from float to float16 + * // This example demonstrates conversion from float to float16 * constexpr float values[] = {1.f, 2.f, 3.f, 4.f, 5.f}; * std::vector bfp16_values; * bfp16_values.reserve(std::size(values)); @@ -502,29 +623,55 @@ namespace detail { #define ORT_DEFINE_RELEASE(NAME) \ inline void OrtRelease(Ort##NAME* ptr) { GetApi().Release##NAME(ptr); } +#define ORT_DEFINE_RELEASE_FROM_API_STRUCT(NAME, API_GETTER) \ + inline void OrtRelease(Ort##NAME* ptr) { API_GETTER().Release##NAME(ptr); } + ORT_DEFINE_RELEASE(Allocator); -ORT_DEFINE_RELEASE(MemoryInfo); +ORT_DEFINE_RELEASE(ArenaCfg); ORT_DEFINE_RELEASE(CustomOpDomain); -ORT_DEFINE_RELEASE(ThreadingOptions); +ORT_DEFINE_RELEASE(DeviceEpIncompatibilityDetails); ORT_DEFINE_RELEASE(Env); -ORT_DEFINE_RELEASE(RunOptions); +ORT_DEFINE_RELEASE(ExternalInitializerInfo); +ORT_DEFINE_RELEASE(Graph); +ORT_DEFINE_RELEASE(IoBinding); +ORT_DEFINE_RELEASE(KernelInfo); +ORT_DEFINE_RELEASE(KeyValuePairs); ORT_DEFINE_RELEASE(LoraAdapter); +ORT_DEFINE_RELEASE(MemoryInfo); +ORT_DEFINE_RELEASE(MapTypeInfo); +ORT_DEFINE_RELEASE(Model); +ORT_DEFINE_RELEASE(ModelMetadata); +ORT_DEFINE_RELEASE(Node); +ORT_DEFINE_RELEASE(Op); +ORT_DEFINE_RELEASE(OpAttr); +ORT_DEFINE_RELEASE(PrepackedWeightsContainer); +ORT_DEFINE_RELEASE(RunOptions); ORT_DEFINE_RELEASE(Session); ORT_DEFINE_RELEASE(SessionOptions); -ORT_DEFINE_RELEASE(TensorTypeAndShapeInfo); ORT_DEFINE_RELEASE(SequenceTypeInfo); -ORT_DEFINE_RELEASE(MapTypeInfo); +ORT_DEFINE_RELEASE(Status); +ORT_DEFINE_RELEASE(SyncStream); +ORT_DEFINE_RELEASE(TensorTypeAndShapeInfo); +ORT_DEFINE_RELEASE(ThreadingOptions); ORT_DEFINE_RELEASE(TypeInfo); ORT_DEFINE_RELEASE(Value); -ORT_DEFINE_RELEASE(ModelMetadata); -ORT_DEFINE_RELEASE(IoBinding); -ORT_DEFINE_RELEASE(ArenaCfg); -ORT_DEFINE_RELEASE(Status); -ORT_DEFINE_RELEASE(OpAttr); -ORT_DEFINE_RELEASE(Op); -ORT_DEFINE_RELEASE(KernelInfo); +ORT_DEFINE_RELEASE(ValueInfo); + +ORT_DEFINE_RELEASE_FROM_API_STRUCT(ModelCompilationOptions, GetCompileApi); +ORT_DEFINE_RELEASE_FROM_API_STRUCT(EpDevice, GetEpApi); +ORT_DEFINE_RELEASE_FROM_API_STRUCT(KernelDef, GetEpApi); +ORT_DEFINE_RELEASE_FROM_API_STRUCT(KernelDefBuilder, GetEpApi); +ORT_DEFINE_RELEASE_FROM_API_STRUCT(KernelRegistry, GetEpApi); +ORT_DEFINE_RELEASE_FROM_API_STRUCT(OpSchema, GetEpApi); +ORT_DEFINE_RELEASE_FROM_API_STRUCT(ProfilingEvent, GetEpApi); + +// This is defined explicitly since OrtTensorRTProviderOptionsV2 is not a C API type, +// but the struct has V2 in its name to indicate that it is the second version of the options. +inline void OrtRelease(OrtTensorRTProviderOptionsV2* ptr) { GetApi().ReleaseTensorRTProviderOptions(ptr); } +inline void OrtRelease(OrtCUDAProviderOptionsV2* ptr) { GetApi().ReleaseCUDAProviderOptions(ptr); } #undef ORT_DEFINE_RELEASE +#undef ORT_DEFINE_RELEASE_FROM_API_STRUCT /** \brief This is a tagging template type. Use it with Base to indicate that the C++ interface object * has no ownership of the underlying C object. @@ -559,7 +706,9 @@ struct Base { constexpr Base() = default; constexpr explicit Base(contained_type* p) noexcept : p_{p} {} - ~Base() { OrtRelease(p_); } + ~Base() { + OrtRelease(p_); + } Base(const Base&) = delete; Base& operator=(const Base&) = delete; @@ -572,6 +721,7 @@ struct Base { } constexpr operator contained_type*() const noexcept { return p_; } + constexpr contained_type& operator*() const noexcept { return *p_; } /// \brief Relinquishes ownership of the contained C object pointer /// The underlying object is not destroyed @@ -616,6 +766,7 @@ struct Base> { } constexpr operator contained_type*() const noexcept { return p_; } + constexpr contained_type& operator*() const noexcept { return *p_; } protected: contained_type* p_{}; @@ -635,9 +786,20 @@ struct AllocatedFree { struct AllocatorWithDefaultOptions; struct Env; +struct EpDevice; +struct ExternalInitializerInfo; +struct Graph; +struct Model; +struct Node; +struct ModelMetadata; struct TypeInfo; +struct PrepackedWeightsContainer; +struct Session; +struct SessionOptions; +struct SyncStream; +struct TensorRTProviderOptions; struct Value; -struct ModelMetadata; +struct ValueInfo; /** \brief unique_ptr typedef used to own strings allocated by OrtAllocators * and release them at the end of the scope. The lifespan of the given allocator @@ -650,14 +812,12 @@ using AllocatedStringPtr = std::unique_ptr; * constructors to construct an instance of a Status object from exceptions. */ struct Status : detail::Base { - using Base = detail::Base; - using Base::Base; - - explicit Status(std::nullptr_t) noexcept {} ///< Create an empty object, must be assigned a valid one to be used - explicit Status(OrtStatus* status) noexcept; ///< Takes ownership of OrtStatus instance returned from the C API. - explicit Status(const Exception&) noexcept; ///< Creates status instance out of exception - explicit Status(const std::exception&) noexcept; ///< Creates status instance out of exception - Status(const char* message, OrtErrorCode code) noexcept; ///< Creates status instance out of null-terminated string message. + Status() = default; // Same as with std::nullptr_t. But can be used in re-sizable containers and represent success. + explicit Status(std::nullptr_t) noexcept {} ///< Create an empty object, must be assigned a valid one to be used + explicit Status(OrtStatus* status) noexcept; ///< Takes ownership of OrtStatus instance returned from the C API. + explicit Status(const Exception&); ///< Creates status instance out of exception + explicit Status(const std::exception&); ///< Creates status instance out of exception + Status(const char* message, OrtErrorCode code); ///< Creates status instance out of null-terminated string message. std::string GetErrorMessage() const; OrtErrorCode GetErrorCode() const; bool IsOK() const noexcept; ///< Returns true if instance represents an OK (non-error) status. @@ -693,6 +853,503 @@ struct ThreadingOptions : detail::Base { ThreadingOptions& SetGlobalCustomJoinThreadFn(OrtCustomJoinThreadFn ort_custom_join_thread_fn); }; +/** \brief The TensorRTOptions (V2) + * + * Used to pass options to TRT EP + */ +struct TensorRTProviderOptions : detail::Base { + TensorRTProviderOptions(std::nullptr_t) {} + /// \brief Wraps OrtApi::CreateTensorRTProviderOptionsV2 + TensorRTProviderOptions(); + ///< Wrapper around OrtApi::UpdateTensorRTProviderOptions + void Update(const std::unordered_map& options); + ///< Wrapper around OrtApi::UpdateTensorRTProviderOptions + void UpdateWithValue(const char* key, void* value); + + ///< Wrapper around OrtApi::GetTensorRTProviderOptionsByName + void* GetOptionByName(const char* name) const; + ///< Wrapper around OrtApi::GetTensorRTProviderOptionsAsString + std::string GetTensorRTProviderOptionsAsString() const; +}; + +/** \brief The CUDAProviderOptions (V2) + * + * Used to pass options to CUDA EP + */ +struct CUDAProviderOptions : detail::Base { + CUDAProviderOptions(std::nullptr_t) {} + /// \brief Wraps OrtApi::CreateCUDAProviderOptions + CUDAProviderOptions(); + ///< Wrapper around OrtApi::UpdateCUDAProviderOptions + void Update(const std::unordered_map& options); + ///< Wrapper around OrtApi::GetCUDAProviderOptionsAsString + std::string GetCUDAProviderOptionsAsString() const; + ///< Wrapper around OrtApi::UpdateCUDAProviderOptionsWithValue + void UpdateWithValue(const char* key, void* value); + ///< Wrapper around OrtApi::GetCUDAProviderOptionsByName + void* GetOptionByName(const char* name) const; +}; + +/** \brief The PrepackedWeightsContainer + * + * Create only and pass to Ort::Session constructor for multiple sessions + * to share pre-packed weights. + */ +struct PrepackedWeightsContainer : detail::Base { + using Base = detail::Base; + ///< No instance is created + explicit PrepackedWeightsContainer(std::nullptr_t) {} + ///< Take ownership of a pointer created by C API + explicit PrepackedWeightsContainer(OrtPrepackedWeightsContainer* p) : Base{p} {} + /// \brief Wraps OrtApi::CreatePrepackedWeightsContainer + PrepackedWeightsContainer(); +}; + +namespace detail { +template +struct ConstExternalInitializerInfoImpl : Base { + using B = Base; + using B::B; + + // Wraps OrtApi::ExternalInitializerInfo_GetFilePath + const std::basic_string GetFilePath() const; + // Wraps OrtApi::ExternalInitializerInfo_GetFileOffset + int64_t GetFileOffset() const; + // Wraps OrtApi::ExternalInitializerInfo_GetByteSize + size_t GetByteSize() const; +}; +} // namespace detail + +// Const object holder that does not own the underlying object +using ConstExternalInitializerInfo = + detail::ConstExternalInitializerInfoImpl>; + +/** \brief Wrapper around ::OrtExternalInitializerInfo + * + */ +struct ExternalInitializerInfo : detail::ConstExternalInitializerInfoImpl { + using Base = detail::ConstExternalInitializerInfoImpl; + using Base::Base; + + explicit ExternalInitializerInfo(std::nullptr_t) {} + explicit ExternalInitializerInfo(OrtExternalInitializerInfo* p) + : detail::ConstExternalInitializerInfoImpl{p} {} + + ConstExternalInitializerInfo GetConst() const { return ConstExternalInitializerInfo{this->p_}; } + + ///< Wraps OrtApi::CreateExternalInitializerInfo + ExternalInitializerInfo(const ORTCHAR_T* filepath, int64_t file_offset, size_t byte_size); + + ///< Wrapper around CreateExternalInitializerInfo that does not throw an exception. + static Status Create(const ORTCHAR_T* filepath, int64_t file_offset, size_t byte_size, + /*out*/ ExternalInitializerInfo& out); +}; + +namespace detail { +template +struct KeyValuePairsImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + + const char* GetValue(const char* key) const; + + // get the pairs in unordered_map. needs to copy to std::string so the hash works as expected + std::unordered_map GetKeyValuePairs() const; + // get the pairs in two vectors. entries will be 1:1 between keys and values. avoids copying to std::string + void GetKeyValuePairs(std::vector& keys, std::vector& values) const; +}; +} // namespace detail + +// Const object holder that does not own the underlying object +using ConstKeyValuePairs = detail::KeyValuePairsImpl>; + +/** \brief Wrapper around ::OrtKeyValuePairs */ +struct KeyValuePairs : detail::KeyValuePairsImpl { + explicit KeyValuePairs(std::nullptr_t) {} ///< No instance is created + /// Take ownership of a pointer created by C API + explicit KeyValuePairs(OrtKeyValuePairs* p) : KeyValuePairsImpl{p} {} + + /// \brief Wraps OrtApi::CreateKeyValuePairs + explicit KeyValuePairs(); + + /// \brief Wraps OrtApi::CreateKeyValuePairs and OrtApi::AddKeyValuePair + explicit KeyValuePairs(const std::unordered_map& kv_pairs); + + /// \brief Wraps OrtApi::AddKeyValuePair + void Add(const char* key, const char* value); + + /// \brief Wraps OrtApi::RemoveKeyValuePair + void Remove(const char* key); + + ConstKeyValuePairs GetConst() const { return ConstKeyValuePairs{this->p_}; } +}; + +namespace detail { +template +struct MemoryInfoImpl : Base { + using B = Base; + using B::B; + + std::string GetAllocatorName() const; ///< Wrapper MemoryInfoGetName + OrtAllocatorType GetAllocatorType() const; ///< Wrapper MemoryInfoGetType + int GetDeviceId() const; ///< Wrapper MemoryInfoGetId + OrtMemoryInfoDeviceType GetDeviceType() const; ///< Wrapper MemoryInfoGetDeviceType + OrtMemType GetMemoryType() const; ///< Wrapper MemoryInfoGetMemType + OrtDeviceMemoryType GetDeviceMemoryType() const; ///< Wrapper MemoryInfoGetDeviceMemType + uint32_t GetVendorId() const; ///< Wrapper MemoryInfoGetVendorId + + template + bool operator==(const MemoryInfoImpl& o) const; +}; +} // namespace detail + +// Const object holder that does not own the underlying object +using ConstMemoryInfo = detail::MemoryInfoImpl>; + +/** \brief Wrapper around ::OrtMemoryInfo + * + */ +struct MemoryInfo : detail::MemoryInfoImpl { + static MemoryInfo CreateCpu(OrtAllocatorType type, OrtMemType mem_type1); + explicit MemoryInfo(std::nullptr_t) {} ///< No instance is created + explicit MemoryInfo(OrtMemoryInfo* p) : MemoryInfoImpl{p} {} ///< Take ownership of a pointer created by C API + MemoryInfo(const char* name, OrtAllocatorType type, int id, OrtMemType mem_type); + MemoryInfo(const char* name, OrtMemoryInfoDeviceType device_type, uint32_t vendor_id, uint32_t device_id, + OrtDeviceMemoryType mem_type, size_t alignment, OrtAllocatorType allocator_type); ///< Wrapper around CreateMemoryInfo_V2 + ConstMemoryInfo GetConst() const { return ConstMemoryInfo{this->p_}; } +}; + +/// +/// Represents native memory allocation coming from one of the +/// OrtAllocators registered with OnnxRuntime. +/// Use it to wrap an allocation made by an allocator +/// so it can be automatically released when no longer needed. +/// +struct MemoryAllocation { + MemoryAllocation(OrtAllocator* allocator, void* p, size_t size); + ~MemoryAllocation(); + MemoryAllocation(const MemoryAllocation&) = delete; + MemoryAllocation& operator=(const MemoryAllocation&) = delete; + MemoryAllocation(MemoryAllocation&&) noexcept; + MemoryAllocation& operator=(MemoryAllocation&&) noexcept; + + void* get() { return p_; } + size_t size() const { return size_; } + + private: + OrtAllocator* allocator_; + void* p_; + size_t size_; +}; + +namespace detail { +template +struct AllocatorImpl : Base { + using B = Base; + using B::B; + + void* Alloc(size_t size); + void* Reserve(size_t size); + MemoryAllocation GetAllocation(size_t size); + void Free(void* p); + ConstMemoryInfo GetInfo() const; + + /** \brief Function that returns the statistics of the allocator. + * + * \return A pointer to a KeyValuePairs object that will be filled with the allocator statistics. + */ + KeyValuePairs GetStats() const; + + /** \brief Release unused memory held by the allocator. + * + * Calls the optional Shrink function pointer if available; does nothing otherwise. + */ + void Shrink(); +}; +} // namespace detail + +/** \brief Wrapper around ::OrtAllocator default instance that is owned by Onnxruntime + * + */ +struct AllocatorWithDefaultOptions : detail::AllocatorImpl> { + explicit AllocatorWithDefaultOptions(std::nullptr_t) {} ///< Convenience to create a class member and then replace with an instance + AllocatorWithDefaultOptions(); +}; + +/** \brief Wrapper around ::OrtAllocator + * + */ + +struct Allocator : detail::AllocatorImpl { + explicit Allocator(std::nullptr_t) {} ///< Convenience to create a class member and then replace with an instance + Allocator(const Session& session, const OrtMemoryInfo*); + + ///< Take ownership of a pointer created by C API + explicit Allocator(OrtAllocator* p) : AllocatorImpl{p} {} +}; + +using UnownedAllocator = detail::AllocatorImpl>; + +/** \brief Wrapper around ::OrtSyncStream + * + */ + +namespace detail { +template +struct SyncStreamImpl : Base { + using B = Base; + using B::B; + // For some reason this is not a const method on the stream + void* GetHandle(); ///< Wraps SyncStream_GetHandle +}; +} // namespace detail + +struct SyncStream : detail::SyncStreamImpl { + ///< Create an empty SyncStream object, must be assigned a valid one to be used + explicit SyncStream(std::nullptr_t) {} + ///< Take ownership of a pointer created by C API + explicit SyncStream(OrtSyncStream* p) : SyncStreamImpl{p} {} +}; + +using UnownedSyncStream = detail::SyncStreamImpl>; + +namespace detail { +template +struct HardwareDeviceImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + + OrtHardwareDeviceType Type() const; + uint32_t VendorId() const; + uint32_t DeviceId() const; + const char* Vendor() const; + ConstKeyValuePairs Metadata() const; +}; +} // namespace detail + +/** \brief Wrapper around ::OrtHardwareDevice + * \remarks HardwareDevice is always read-only for API users. + */ +using ConstHardwareDevice = detail::HardwareDeviceImpl>; + +namespace detail { +template +struct DeviceEpIncompatibilityDetailsImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + + uint32_t GetReasonsBitmask() const; ///< Wraps DeviceEpIncompatibilityDetails_GetReasonsBitmask + const char* GetNotes() const; ///< Wraps DeviceEpIncompatibilityDetails_GetNotes + int32_t GetErrorCode() const; ///< Wraps DeviceEpIncompatibilityDetails_GetErrorCode +}; +} // namespace detail + +/** \brief Wrapper around ::OrtDeviceEpIncompatibilityDetails + * \remarks DeviceEpIncompatibilityDetails is always read-only for API users. + */ +struct DeviceEpIncompatibilityDetails : detail::DeviceEpIncompatibilityDetailsImpl { + explicit DeviceEpIncompatibilityDetails(std::nullptr_t) {} ///< No instance is created + explicit DeviceEpIncompatibilityDetails(OrtDeviceEpIncompatibilityDetails* p) + : DeviceEpIncompatibilityDetailsImpl{p} {} ///< Take ownership of a pointer created by C API +}; + +namespace detail { +template +struct EpDeviceImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + + const char* EpName() const; + const char* EpVendor() const; + ConstKeyValuePairs EpMetadata() const; + ConstKeyValuePairs EpOptions() const; + ConstHardwareDevice Device() const; + ConstMemoryInfo GetMemoryInfo(OrtDeviceMemoryType memory_type) const; ///< Wraps EpDevice_MemoryInfo + SyncStream CreateSyncStream(ConstKeyValuePairs stream_options = {}) const; /// Wraps EpDevice_CreateSyncStream +}; +} // namespace detail + +/** \brief Wrapper around ::OrtEpDevice + * \remarks EpDevice is always read-only for ORT API users. + */ +using ConstEpDevice = detail::EpDeviceImpl>; + +/** \brief Mutable EpDevice that is created by EpApi users. + */ +struct EpDevice : detail::EpDeviceImpl { + explicit EpDevice(std::nullptr_t) {} ///< No instance is created + explicit EpDevice(OrtEpDevice* p) : EpDeviceImpl{p} {} ///< Take ownership of a pointer created by C API + + /// \brief Wraps OrtEpApi::CreateEpDevice + EpDevice(OrtEpFactory& ep_factory, ConstHardwareDevice& hardware_device, + ConstKeyValuePairs ep_metadata = {}, ConstKeyValuePairs ep_options = {}); +}; + +/** \brief Validate a compiled model's compatibility for one or more EP devices. + * + * Throws on error. Returns the resulting compatibility status. + * /// \param ep_devices The EP devices to check compatibility against. + * /// \param compatibility_info The compatibility string from the precompiled model to validate. + */ +OrtCompiledModelCompatibility GetModelCompatibilityForEpDevices( + const std::vector& ep_devices, + const char* compatibility_info); + +/** \brief Extract EP compatibility info from a precompiled model file. + * + * Parses the model file to extract the compatibility info string for a specific execution provider + * from the model's metadata properties. This is only applicable to models that have been precompiled + * for an EP. Standard ONNX models do not contain this information. + * + * \note This operation parses the full ONNX ModelProto from disk. + * + * \param model_path Path to the ONNX model file. + * \param ep_type The execution provider type string. Must be non-empty. + * Use ConstEpDevice::EpName() to get this value. + * \param allocator Allocator to use for the output string. + * \return The compatibility info string, or nullptr if not found for this EP. Caller must free via allocator. + * \throws Ort::Exception on error. + */ +AllocatedStringPtr GetCompatibilityInfoFromModelAllocated(const ORTCHAR_T* model_path, const char* ep_type, + OrtAllocator* allocator); + +/** \brief Extract EP compatibility info from precompiled model bytes in memory. + * + * Same as GetCompatibilityInfoFromModelAllocated but reads from a memory buffer. + * Useful when precompiled models are loaded from encrypted storage, network, or other non-file sources. + * + * \param model_data Pointer to the model data in memory. + * \param model_data_length Size of the model data in bytes. + * \param ep_type The execution provider type string. Must be non-empty. + * \param allocator Allocator to use for the output string. + * \return The compatibility info string, or nullptr if not found for this EP. Caller must free via allocator. + * \throws Ort::Exception on error. + */ +AllocatedStringPtr GetCompatibilityInfoFromModelBytesAllocated(const void* model_data, size_t model_data_length, + const char* ep_type, OrtAllocator* allocator); + +namespace detail { +template +struct EpAssignedNodeImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + + std::string GetName() const; + std::string GetDomain() const; + std::string GetOperatorType() const; +}; +} // namespace detail + +/** \brief Constant wrapper around ::OrtEpAssignedNode + * \remarks EpAssignedNode is always read-only for ORT API users. + */ +using ConstEpAssignedNode = detail::EpAssignedNodeImpl>; + +namespace detail { +template +struct EpAssignedSubgraphImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + + std::string GetEpName() const; + std::vector GetNodes() const; +}; +} // namespace detail + +/** \brief Constant wrapper around ::OrtEpAssignedSubgraph + * \remarks EpAssignedSubgraph is always read-only for ORT API users. + */ +using ConstEpAssignedSubgraph = detail::EpAssignedSubgraphImpl>; + +namespace detail { +template +struct ConstProfilingEventImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + + /// \brief Get the event category. Wraps OrtEpApi::ProfilingEvent_GetCategory + OrtProfilingEventCategory GetCategory() const; + + /// \brief Get the event name. Wraps OrtEpApi::ProfilingEvent_GetName + /// \return Null-terminated UTF-8 string owned by the OrtProfilingEvent instance. Do not free. + const char* GetName() const; + + /// \brief Get the start timestamp in microseconds. Wraps OrtEpApi::ProfilingEvent_GetTimestampUs + int64_t GetTimestampUs() const; + + /// \brief Get the duration in microseconds. Wraps OrtEpApi::ProfilingEvent_GetDurationUs + int64_t GetDurationUs() const; + + /// \brief Get the value of an event argument by key. Wraps OrtEpApi::ProfilingEvent_GetArgValue + /// \param[in] key Null-terminated argument key to look up. + /// \return Null-terminated UTF-8 string owned by the OrtProfilingEvent, or nullptr if key not found. + const char* GetArgValue(const char* key) const; +}; +} // namespace detail + +/** \brief Non-owning const wrapper around ::OrtProfilingEvent. + * + * Use this to read fields from the OrtProfilingEvent pointer passed to OrtEpProfilerImpl::StopEvent. + * + * This is based on the Trace Event Format's "complete event". + * \since Version 1.25. + */ +using ConstProfilingEvent = detail::ConstProfilingEventImpl>; + +/** \brief Owning wrapper around ::OrtProfilingEvent. + * + * Use this to create profiling events via OrtEpApi::CreateProfilingEvent. The event is released + * automatically on destruction. + * \since Version 1.25. + */ +struct ProfilingEvent : detail::ConstProfilingEventImpl { + explicit ProfilingEvent(std::nullptr_t) {} ///< No instance is created + explicit ProfilingEvent(OrtProfilingEvent* p) + : ConstProfilingEventImpl{p} {} ///< Take ownership + + /// \brief Wraps OrtEpApi::CreateProfilingEvent + ProfilingEvent(OrtProfilingEventCategory category, + int32_t process_id, + int32_t thread_id, + const char* event_name, + int64_t timestamp_us, + int64_t duration_us, + const std::unordered_map& args = {}); + + /// \brief Wraps OrtEpApi::CreateProfilingEvent + ProfilingEvent(OrtProfilingEventCategory category, + int32_t process_id, + int32_t thread_id, + const char* event_name, + int64_t timestamp_us, + int64_t duration_us, + const char* const* arg_keys, + const char* const* arg_values, + size_t num_args); + + ConstProfilingEvent GetConst() const { return ConstProfilingEvent{this->p_}; } +}; + +namespace detail { +template +struct ProfilingEventsContainerImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + + /// \brief Adds profiling events to this container. Events are copied. + /// Wraps OrtEpApi::ProfilingEventsContainer_AddEvents. + Ort::Status AddEvents(const OrtProfilingEvent* const* events, size_t num_events); + Ort::Status AddEvents(const std::vector& events); +}; +} // namespace detail + +/** \brief Non-owning wrapper around ::OrtProfilingEventsContainer. + * + * Use this to add EP profiling events to a container owned by ORT during the call to OrtEpProfilerImpl::EndProfiling. + * \since Version 1.25. + */ +using UnownedProfilingEventsContainer = detail::ProfilingEventsContainerImpl>; + /** \brief The Env (Environment) * * The Env holds the logging state used by all other objects. @@ -714,6 +1371,9 @@ struct Env : detail::Base { Env(const OrtThreadingOptions* tp_options, OrtLoggingFunction logging_function, void* logger_param, OrtLoggingLevel logging_level = ORT_LOGGING_LEVEL_WARNING, _In_ const char* logid = ""); + /// \brief Wraps OrtApi::CreateEnvWithOptions + explicit Env(const OrtEnvCreationOptions* options); + /// \brief C Interop Helper explicit Env(OrtEnv* p) : Base{p} {} @@ -724,7 +1384,71 @@ struct Env : detail::Base { Env& CreateAndRegisterAllocator(const OrtMemoryInfo* mem_info, const OrtArenaCfg* arena_cfg); ///< Wraps OrtApi::CreateAndRegisterAllocator - Env& CreateAndRegisterAllocatorV2(const std::string& provider_type, const OrtMemoryInfo* mem_info, const std::unordered_map& options, const OrtArenaCfg* arena_cfg); ///< Wraps OrtApi::CreateAndRegisterAllocatorV2 + Env& CreateAndRegisterAllocatorV2(const std::string& provider_type, const OrtMemoryInfo* mem_info, + const std::unordered_map& options, + const OrtArenaCfg* arena_cfg); ///< Wraps OrtApi::CreateAndRegisterAllocatorV2 + + Env& RegisterAllocator(OrtAllocator* allocator); ///< Wraps OrtApi::RegisterAllocator + + Env& UnregisterAllocator(const OrtMemoryInfo* mem_info); ///< Wraps OrtApi::UnregisterAllocator + + UnownedAllocator CreateSharedAllocator(const OrtEpDevice* ep_device, OrtDeviceMemoryType mem_type, + OrtAllocatorType allocator_type, + const OrtKeyValuePairs* allocator_options); ///< Wraps OrtApi::CreateSharedAllocator + + // Result may be nullptr + UnownedAllocator GetSharedAllocator(const OrtMemoryInfo* mem_info); ///< Wraps OrtApi::GetSharedAllocator + + void ReleaseSharedAllocator(const OrtEpDevice* ep_device, + OrtDeviceMemoryType mem_type); ///< Wraps OrtApi::ReleaseSharedAllocator + + Env& RegisterExecutionProviderLibrary(const char* registration_name, const std::basic_string& path); ///< Wraps OrtApi::RegisterExecutionProviderLibrary + Env& UnregisterExecutionProviderLibrary(const char* registration_name); ///< Wraps OrtApi::UnregisterExecutionProviderLibrary + + std::vector GetEpDevices() const; + + /** \brief Get the number of available hardware devices. + * + * Returns the count of hardware devices discovered on the system. + * \return The number of hardware devices available. + * \throws Ort::Exception on error. + */ + size_t GetNumHardwareDevices() const; ///< Wraps OrtApi::GetNumHardwareDevices + + /** \brief Get the list of available hardware devices. + * + * Enumerates hardware devices available on the system. + * \return A vector of hardware devices. + * \throws Ort::Exception on error. + */ + std::vector GetHardwareDevices() const; ///< Wraps OrtApi::GetHardwareDevices + + /** \brief Check for known incompatibility issues between hardware device and a specific execution provider. + * + * If returned incompatibility details have non-zero reasons, it indicates the device is not compatible. + * However, if the returned details have reasons == 0, that does not guarantee 100% compatibility for all models. + * + * \param ep_name The name of the execution provider to check. + * \param hw The hardware device to check for incompatibility. + * \return DeviceEpIncompatibilityDetails containing reasons for incompatibility if any. + * \throws Ort::Exception on error. + */ + DeviceEpIncompatibilityDetails GetHardwareDeviceEpIncompatibilityDetails( + const char* ep_name, ConstHardwareDevice hw) const; ///< Wraps OrtApi::GetHardwareDeviceEpIncompatibilityDetails + + Status CopyTensors(const std::vector& src_tensors, + const std::vector& dst_tensors, + OrtSyncStream* stream) const; ///< Wraps OrtApi::CopyTensors + + /// Wraps OrtApi::CopyTensors + /// Copies only one src tensor to another dst tensor. + Status CopyTensor(const OrtValue* src_tensor, OrtValue* dst_tensor, OrtSyncStream* stream) const; + + /// \brief Wraps OrtApi::SetPerSessionThreadPoolCallbacks + /// Stores work callbacks on the Env for per-session thread pools. + /// Only affects sessions created after this call. Does not affect global thread pools. + /// Requires ORT built with --enable_session_threadpool_callbacks. + Env& SetPerSessionThreadPoolCallbacks(const OrtThreadPoolCallbacksConfig& config); }; /** \brief Custom Op Domain @@ -786,6 +1510,7 @@ struct RunOptions : detail::Base { const char* GetRunTag() const; ///< Wraps OrtApi::RunOptionsGetRunTag RunOptions& AddConfigEntry(const char* config_key, const char* config_value); ///< Wraps OrtApi::AddRunConfigEntry + const char* GetConfigEntry(const char* config_key); ///< Wraps OrtApi::GetRunConfigEntry /** \brief Terminates all currently executing Session::Run calls that were made using this RunOptions instance * @@ -807,6 +1532,28 @@ struct RunOptions : detail::Base { * \param adapter The LoraAdapter to be used as the active adapter */ RunOptions& AddActiveLoraAdapter(const LoraAdapter& adapter); + + /** \brief Associate a sync stream with the run options. + * + * When set, the EP uses this stream for execution, enabling proper + * synchronization with imported external semaphores. Wraps OrtApi::RunOptionsSetSyncStream. + * + * \param stream The OrtSyncStream to associate with these run options. May be nullptr to clear. + */ + RunOptions& SetSyncStream(OrtSyncStream* stream); + + /** \brief Enable profiling for this run + * + * Wraps OrtApi::RunOptionsEnableProfiling + * \param profile_file_prefix The prefix for the profile file + */ + RunOptions& EnableProfiling(const ORTCHAR_T* profile_file_prefix); + + /** \brief Disable profiling for this run + * + * Wraps OrtApi::RunOptionsDisableProfiling + */ + RunOptions& DisableProfiling(); }; namespace detail { @@ -861,8 +1608,6 @@ struct CustomOpConfigs { * Wraps ::OrtSessionOptions object and methods */ -struct SessionOptions; - namespace detail { // we separate const-only methods because passing const ptr to non-const methods // is only discovered when inline methods are compiled which is counter-intuitive @@ -875,7 +1620,10 @@ struct ConstSessionOptionsImpl : Base { std::string GetConfigEntry(const char* config_key) const; ///< Wraps OrtApi::GetSessionConfigEntry bool HasConfigEntry(const char* config_key) const; ///< Wraps OrtApi::HasSessionConfigEntry - std::string GetConfigEntryOrDefault(const char* config_key, const std::string& def); + std::string GetConfigEntryOrDefault(const char* config_key, const std::string& def) const; + + bool GetMemPatternEnabled() const; ///< Wraps OrtApi::GetMemPatternEnabled + ExecutionMode GetExecutionMode() const; ///< Wraps OrtApi::GetSessionExecutionMode }; template @@ -903,6 +1651,8 @@ struct SessionOptionsImpl : ConstSessionOptionsImpl { SessionOptionsImpl& SetExecutionMode(ExecutionMode execution_mode); ///< Wraps OrtApi::SetSessionExecutionMode + SessionOptionsImpl& SetLoadCancellationFlag(bool value); ///< Wraps OrtApi::SessionOptionsSetLoadCancellationFlag + SessionOptionsImpl& SetLogId(const char* logid); ///< Wraps OrtApi::SetSessionLogId SessionOptionsImpl& SetLogSeverityLevel(int level); ///< Wraps OrtApi::SetSessionLogSeverityLevel @@ -918,6 +1668,7 @@ struct SessionOptionsImpl : ConstSessionOptionsImpl { const std::vector& external_initializer_file_buffer_array, const std::vector& external_initializer_file_lengths); ///< Wraps OrtApi::AddExternalInitializersFromFilesInMemory + SessionOptionsImpl& AppendExecutionProvider_CPU(int use_arena); ///< Wraps OrtApi::SessionOptionsAppendExecutionProvider_CPU SessionOptionsImpl& AppendExecutionProvider_CUDA(const OrtCUDAProviderOptions& provider_options); ///< Wraps OrtApi::SessionOptionsAppendExecutionProvider_CUDA SessionOptionsImpl& AppendExecutionProvider_CUDA_V2(const OrtCUDAProviderOptionsV2& provider_options); ///< Wraps OrtApi::SessionOptionsAppendExecutionProvider_CUDA_V2 SessionOptionsImpl& AppendExecutionProvider_ROCM(const OrtROCMProviderOptions& provider_options); ///< Wraps OrtApi::SessionOptionsAppendExecutionProvider_ROCM @@ -927,14 +1678,29 @@ struct SessionOptionsImpl : ConstSessionOptionsImpl { SessionOptionsImpl& AppendExecutionProvider_TensorRT(const OrtTensorRTProviderOptions& provider_options); ///< Wraps OrtApi::SessionOptionsAppendExecutionProvider_TensorRT SessionOptionsImpl& AppendExecutionProvider_TensorRT_V2(const OrtTensorRTProviderOptionsV2& provider_options); ///< Wraps OrtApi::SessionOptionsAppendExecutionProvider_TensorRT SessionOptionsImpl& AppendExecutionProvider_MIGraphX(const OrtMIGraphXProviderOptions& provider_options); ///< Wraps OrtApi::SessionOptionsAppendExecutionProvider_MIGraphX - ///< Wraps OrtApi::SessionOptionsAppendExecutionProvider_CANN + /// Wraps OrtApi::SessionOptionsAppendExecutionProvider_CANN SessionOptionsImpl& AppendExecutionProvider_CANN(const OrtCANNProviderOptions& provider_options); - ///< Wraps OrtApi::SessionOptionsAppendExecutionProvider_Dnnl + /// Wraps OrtApi::SessionOptionsAppendExecutionProvider_Dnnl SessionOptionsImpl& AppendExecutionProvider_Dnnl(const OrtDnnlProviderOptions& provider_options); /// Wraps OrtApi::SessionOptionsAppendExecutionProvider. Currently supports QNN, SNPE and XNNPACK. SessionOptionsImpl& AppendExecutionProvider(const std::string& provider_name, const std::unordered_map& provider_options = {}); + /// Append EPs that have been registered previously with the OrtEnv. + /// Wraps OrtApi::SessionOptionsAppendExecutionProvider_V2 + SessionOptionsImpl& AppendExecutionProvider_V2(Env& env, const std::vector& ep_devices, + const KeyValuePairs& ep_options); + /// Append EPs that have been registered previously with the OrtEnv. + /// Wraps OrtApi::SessionOptionsAppendExecutionProvider_V2 + SessionOptionsImpl& AppendExecutionProvider_V2(Env& env, const std::vector& ep_devices, + const std::unordered_map& ep_options); + + /// Wraps OrtApi::SessionOptionsSetEpSelectionPolicy + SessionOptionsImpl& SetEpSelectionPolicy(OrtExecutionProviderDevicePolicy policy); + + /// Wraps OrtApi::SessionOptionsSetEpSelectionPolicyDelegate + SessionOptionsImpl& SetEpSelectionPolicy(EpSelectionDelegate delegate, void* state = nullptr); + SessionOptionsImpl& SetCustomCreateThreadFn(OrtCustomCreateThreadFn ort_custom_create_thread_fn); ///< Wraps OrtApi::SessionOptionsSetCustomCreateThreadFn SessionOptionsImpl& SetCustomThreadCreationOptions(void* ort_custom_thread_creation_options); ///< Wraps OrtApi::SessionOptionsSetCustomThreadCreationOptions SessionOptionsImpl& SetCustomJoinThreadFn(OrtCustomJoinThreadFn ort_custom_join_thread_fn); ///< Wraps OrtApi::SessionOptionsSetCustomJoinThreadFn @@ -948,6 +1714,12 @@ struct SessionOptionsImpl : ConstSessionOptionsImpl { ///< Wraps OrtApi::SessionOptionsAppendExecutionProvider_VitisAI SessionOptionsImpl& AppendExecutionProvider_VitisAI(const std::unordered_map& provider_options = {}); + + ///< Wraps OrtApi::AddFreeDimensionOverride + SessionOptionsImpl& AddFreeDimensionOverride(const char* dim_denotation, int64_t dim_value); + + ///< Wraps OrtApi::AddFreeDimensionOverrideByName + SessionOptionsImpl& AddFreeDimensionOverrideByName(const char* dim_name, int64_t dim_value); }; } // namespace detail @@ -965,6 +1737,55 @@ struct SessionOptions : detail::SessionOptionsImpl { ConstSessionOptions GetConst() const { return ConstSessionOptions{this->p_}; } }; +/** \brief Options object used when compiling a model. + * + * Wraps ::OrtModelCompilationOptions object and methods + */ +struct ModelCompilationOptions : detail::Base { + using Base = detail::Base; + using Base::Base; + + explicit ModelCompilationOptions(std::nullptr_t) {} ///< Create an empty ModelCompilationOptions object, must be assigned a valid one to be used. + + ModelCompilationOptions(const Env& env, const SessionOptions& session_options); ///< Wraps OrtApi::CreateModelCompilationOptionsFromSessionOptions + ModelCompilationOptions(const Env& env, ConstSessionOptions session_options); ///< Wraps OrtApi::CreateModelCompilationOptionsFromSessionOptions + + ModelCompilationOptions& SetInputModelPath(const ORTCHAR_T* input_model_path); ///< Wraps OrtApi::ModelCompilationOptions_SetInputModelPath + ModelCompilationOptions& SetInputModelFromBuffer(const void* input_model_data, + size_t input_model_data_size); ///< Wraps OrtApi::ModelCompilationOptions_SetInputModelFromBuffer + ModelCompilationOptions& SetEpContextEmbedMode(bool embed_ep_context_in_model); ///< Wraps OrtApi::ModelCompilationOptions_SetEpContextEmbedMode + ModelCompilationOptions& SetOutputModelPath(const ORTCHAR_T* output_model_path); ///< Wraps OrtApi::ModelCompilationOptions_SetOutputModelPath + ModelCompilationOptions& SetOutputModelExternalInitializersFile(const ORTCHAR_T* file_path, + size_t initializer_size_threshold); ///< Wraps OrtApi::ModelCompilationOptions_SetOutputModelExternalInitializersFile + + ///< Wraps OrtApi::ModelCompilationOptions_SetOutputModelGetInitializerLocationFunc + ModelCompilationOptions& SetOutputModelGetInitializerLocationFunc( + OrtGetInitializerLocationFunc get_initializer_location_func, + void* state); + + ModelCompilationOptions& SetOutputModelBuffer(OrtAllocator* allocator, void** output_model_buffer_ptr, + size_t* output_model_buffer_size_ptr); ///< Wraps OrtApi::ModelCompilationOptions_SetOutputModelBuffer + + ///< Wraps OrtApi::ModelCompilationOptions_SetOutputModelWriteFunc + ModelCompilationOptions& SetOutputModelWriteFunc(OrtWriteBufferFunc write_func, void* state); + + ModelCompilationOptions& SetEpContextBinaryInformation(const ORTCHAR_T* output_directory, + const ORTCHAR_T* model_name); ///< Wraps OrtApi::ModelCompilationOptions_SetEpContextBinaryInformation + ModelCompilationOptions& SetFlags(uint32_t flags); ///< Wraps OrtApi::ModelCompilationOptions_SetFlags + + ModelCompilationOptions& SetGraphOptimizationLevel(GraphOptimizationLevel graph_optimization_level); ///< Wraps OrtApi::ModelCompilationOptions_SetGraphOptimizationLevel + + ModelCompilationOptions& SetInputModel(const OrtModel* model); ///< Wraps OrtCompileApi::ModelCompilationOptions_SetInputModel +}; + +/** \brief Compiles an input model to generate a model with EPContext nodes that execute EP-specific kernels. Wraps OrtApi::CompileModels. + * + * \param env: ORT environment object. + * \param model_compilation_options: Compilation options for a model. + * \return A Status indicating success or failure. + */ +Status CompileModel(const Env& env, const ModelCompilationOptions& model_compilation_options); + /** \brief Wrapper around ::OrtModelMetadata * */ @@ -1051,6 +1872,15 @@ struct ConstSessionImpl : Base { size_t GetOutputCount() const; ///< Returns the number of model outputs size_t GetOverridableInitializerCount() const; ///< Returns the number of inputs that have defaults that can be overridden + std::vector GetInputNames() const; + std::vector GetOutputNames() const; + std::vector GetOverridableInitializerNames() const; + + std::vector GetMemoryInfoForInputs() const; ///< Wrapper for OrtApi::SessionGetMemoryInfoForInputs + std::vector GetMemoryInfoForOutputs() const; ///< Wrapper for OrtApi::SessionGetMemoryInfoForOutputs + std::vector GetEpDeviceForInputs() const; ///< Wrapper for OrtApi::SessionGetEpDeviceForInputs + std::vector GetEpDeviceForOutputs() const; ///< Wrapper for OrtApi::SessionGetEpDeviceForOutputs + /** \brief Returns a copy of input name at the specified index. * * \param index must less than the value returned by GetInputCount() @@ -1084,6 +1914,17 @@ struct ConstSessionImpl : Base { TypeInfo GetInputTypeInfo(size_t index) const; ///< Wraps OrtApi::SessionGetInputTypeInfo TypeInfo GetOutputTypeInfo(size_t index) const; ///< Wraps OrtApi::SessionGetOutputTypeInfo TypeInfo GetOverridableInitializerTypeInfo(size_t index) const; ///< Wraps OrtApi::SessionGetOverridableInitializerTypeInfo + + int GetOpset(const std::string& domain) const; ///< Wraps OrtApi::SessionGetOpsetForDomain + + std::vector GetInputs() const; + std::vector GetOutputs() const; + + /** \brief Returns information on the subgraph/nodes assigned to execution providers in the session. + * + * \return A list of ConstEpAssignedSubgraph instances. + */ + std::vector GetEpGraphAssignmentInfo() const; }; template @@ -1161,6 +2002,9 @@ struct SessionImpl : ConstSessionImpl { * \param[in] kv_len Number of elements in the keys and values arrays */ void SetEpDynamicOptions(const char* const* keys, const char* const* values, size_t kv_len); + + void FinalizeModelEditorSession(const Model& model, const SessionOptions& options, + OrtPrepackedWeightsContainer* prepacked_weights_container = nullptr); }; } // namespace detail @@ -1172,47 +2016,37 @@ using UnownedSession = detail::SessionImpl>; * */ struct Session : detail::SessionImpl { - explicit Session(std::nullptr_t) {} ///< Create an empty Session object, must be assigned a valid one to be used - Session(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options); ///< Wraps OrtApi::CreateSession - Session(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options, - OrtPrepackedWeightsContainer* prepacked_weights_container); ///< Wraps OrtApi::CreateSessionWithPrepackedWeightsContainer - Session(const Env& env, const void* model_data, size_t model_data_length, const SessionOptions& options); ///< Wraps OrtApi::CreateSessionFromArray - Session(const Env& env, const void* model_data, size_t model_data_length, const SessionOptions& options, - OrtPrepackedWeightsContainer* prepacked_weights_container); ///< Wraps OrtApi::CreateSessionFromArrayWithPrepackedWeightsContainer + /// Create an empty Session object, must be assigned a valid one to be used. Wraps OrtApi::CreateSession + explicit Session(std::nullptr_t) {} + explicit Session(OrtSession* p) : SessionImpl{p} {} ///< C API Interop - ConstSession GetConst() const { return ConstSession{this->p_}; } - UnownedSession GetUnowned() const { return UnownedSession{this->p_}; } -}; + Session(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options); -namespace detail { -template -struct MemoryInfoImpl : Base { - using B = Base; - using B::B; - - std::string GetAllocatorName() const; - OrtAllocatorType GetAllocatorType() const; - int GetDeviceId() const; - OrtMemoryInfoDeviceType GetDeviceType() const; - OrtMemType GetMemoryType() const; + /// Wraps OrtApi::CreateSessionWithPrepackedWeightsContainer + Session(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options, + OrtPrepackedWeightsContainer* prepacked_weights_container); - template - bool operator==(const MemoryInfoImpl& o) const; -}; -} // namespace detail + /// Wraps OrtApi::CreateSessionFromArray + Session(const Env& env, const void* model_data, size_t model_data_length, const SessionOptions& options); -// Const object holder that does not own the underlying object -using ConstMemoryInfo = detail::MemoryInfoImpl>; + /// Wraps OrtApi::CreateSessionFromArrayWithPrepackedWeightsContainer + Session(const Env& env, const void* model_data, size_t model_data_length, const SessionOptions& options, + OrtPrepackedWeightsContainer* prepacked_weights_container); -/** \brief Wrapper around ::OrtMemoryInfo - * - */ -struct MemoryInfo : detail::MemoryInfoImpl { - static MemoryInfo CreateCpu(OrtAllocatorType type, OrtMemType mem_type1); - explicit MemoryInfo(std::nullptr_t) {} ///< No instance is created - explicit MemoryInfo(OrtMemoryInfo* p) : MemoryInfoImpl{p} {} ///< Take ownership of a pointer created by C Api - MemoryInfo(const char* name, OrtAllocatorType type, int id, OrtMemType mem_type); - ConstMemoryInfo GetConst() const { return ConstMemoryInfo{this->p_}; } +#if !defined(ORT_MINIMAL_BUILD) + /// Wraps OrtModelEditorApi::CreateSessionFromModel + Session(const Env& env, const Model& model, const SessionOptions& options); + + /// Wraps OrtModelEditorApi::CreateModelEditorSession + static Session CreateModelEditorSession(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options); + + /// Wraps OrtModelEditorApi::CreateModelEditorSession + static Session CreateModelEditorSession(const Env& env, const void* model_data, size_t model_data_length, + const SessionOptions& options); +#endif // !defined(ORT_MINIMAL_BUILD) + + ConstSession GetConst() const { return ConstSession{this->p_}; } + UnownedSession GetUnowned() const { return UnownedSession{this->p_}; } }; namespace detail { @@ -1233,7 +2067,9 @@ struct TensorTypeAndShapeInfoImpl : Base { [[deprecated("use GetShape()")]] void GetDimensions(int64_t* values, size_t values_count) const; ///< Wraps OrtApi::GetDimensions void GetSymbolicDimensions(const char** values, size_t values_count) const; ///< Wraps OrtApi::GetSymbolicDimensions + std::vector GetSymbolicDimensions() const; + bool HasShape() const; ///< Wraps OrtApi::TensorTypeAndShape_HasShape std::vector GetShape() const; ///< Uses GetDimensionsCount & GetDimensions to return a std::vector of the shape }; @@ -1248,8 +2084,18 @@ struct TensorTypeAndShapeInfo : detail::TensorTypeAndShapeInfoImpl; using Base::Base; - explicit TensorTypeAndShapeInfo(std::nullptr_t) {} ///< Create an empty TensorTypeAndShapeInfo object, must be assigned a valid one to be used - explicit TensorTypeAndShapeInfo(OrtTensorTypeAndShapeInfo* p) : TensorTypeAndShapeInfoImpl{p} {} ///< Used for interop with the C API + /// Create an empty TensorTypeAndShapeInfo object, must be assigned a valid one to be used + explicit TensorTypeAndShapeInfo(std::nullptr_t) {} + /// Used for interop with the C API + explicit TensorTypeAndShapeInfo(OrtTensorTypeAndShapeInfo* p) : TensorTypeAndShapeInfoImpl{p} {} + + // Create a TensorTypeAndShapeInfo object with the specified element type and dimensions + // symbolic_dims are optional, but should be 1:1 with dims. + // The value in symbolic_dims will be used for all entries in dims that are -1. + explicit TensorTypeAndShapeInfo(ONNXTensorElementDataType element_type, + const std::vector& dims, + const std::vector* symbolic_dims = nullptr); + ConstTensorTypeAndShapeInfo GetConst() const { return ConstTensorTypeAndShapeInfo{this->p_}; } }; @@ -1344,9 +2190,18 @@ struct TypeInfo : detail::TypeInfoImpl { using Base = detail::TypeInfoImpl; using Base::Base; - explicit TypeInfo(std::nullptr_t) {} ///< Create an empty TypeInfo object, must be assigned a valid one to be used + /// Create an empty TypeInfo object, must be assigned a valid one to be used + explicit TypeInfo(std::nullptr_t) {} explicit TypeInfo(OrtTypeInfo* p) : TypeInfoImpl{p} {} ///< C API Interop +#if !defined(ORT_MINIMAL_BUILD) + static TypeInfo CreateTensorInfo(ConstTensorTypeAndShapeInfo tensor_info); + static TypeInfo CreateSparseTensorInfo(ConstTensorTypeAndShapeInfo sparse_tensor_info); + static TypeInfo CreateSequenceTypeInfo(ConstTypeInfo sequence_type); + static TypeInfo CreateMapTypeInfo(ONNXTensorElementDataType key_type, ConstTypeInfo value_type); + static TypeInfo CreateOptionalTypeInfo(ConstTypeInfo contained_type); +#endif // !defined(ORT_MINIMAL_BUILD) + ConstTypeInfo GetConst() const { return ConstTypeInfo{this->p_}; } }; @@ -1423,7 +2278,7 @@ struct ConstValueImpl : Base { /// /// const pointer to data, no copies made template - const R* GetTensorData() const; ///< Wraps OrtApi::GetTensorMutableData /// + const R* GetTensorData() const; ///< Wraps OrtApi::GetTensorData /// /// /// Returns a non-typed pointer to a tensor contained data. @@ -1479,6 +2334,14 @@ struct ConstValueImpl : Base { /// byte length for the specified string element size_t GetStringTensorElementLength(size_t element_index) const; + /// + /// Returns the total size of the tensor data in bytes. Throws an exception if the OrtValue + /// does not contain a tensor or if it contains a tensor that contains strings. + /// For numeric tensors, this is sizeof(element_type) * total_element_count. + /// + /// The total size of the tensor data in bytes + size_t GetTensorSizeInBytes() const; ///< Wraps OrtApi::GetTensorSizeInBytes + #if !defined(DISABLE_SPARSE_TENSORS) /// /// The API returns the sparse data format this OrtValue holds in a sparse tensor. @@ -1534,6 +2397,19 @@ struct ConstValueImpl : Base { const R* GetSparseTensorValues() const; #endif + + /// + /// Returns the tensor's element type and a reference to the tensor's internal shape data. The shape data is owned + /// by the Ort::Value and becomes invalid when the Ort::Value is destroyed or if the underlying shape data is + /// updated or reallocated. + /// + /// For a scalar, shape.shape is nullptr and shape.shape_len is 0. + /// + /// Wraps OrtApi::GetTensorElementTypeAndShapeDataReference. + /// + /// Output parameter set to the element's data type. + /// Output parameter set to the OrtValue instance's shape data and number of elements. + void GetTensorElementTypeAndShapeDataReference(ONNXTensorElementDataType& elem_type, Shape& shape) const; }; template @@ -1560,7 +2436,7 @@ struct ValueImpl : ConstValueImpl { /// by the vector of dims. /// /// - /// [in] expressed by a vecotr of dimensions offsets + /// [in] expressed by a vector of dimensions offsets /// template R& At(const std::vector& location); @@ -1685,7 +2561,7 @@ struct Value : detail::ValueImpl { using OrtSparseValuesParam = detail::OrtSparseValuesParam; using Shape = detail::Shape; - explicit Value(std::nullptr_t) {} ///< Create an empty Value object, must be assigned a valid one to be used + Value(std::nullptr_t) {} ///< Create an empty Value object, must be assigned a valid one to be used Value(Value&&) = default; Value& operator=(Value&&) = default; @@ -1701,7 +2577,8 @@ struct Value : detail::ValueImpl { * \param shape_len The number of tensor shape dimensions. */ template - static Value CreateTensor(const OrtMemoryInfo* info, T* p_data, size_t p_data_element_count, const int64_t* shape, size_t shape_len); + static Value CreateTensor(const OrtMemoryInfo* info, T* p_data, size_t p_data_element_count, + const int64_t* shape, size_t shape_len); /** \brief Creates a tensor with a user supplied buffer. Wraps OrtApi::CreateTensorWithDataAsOrtValue. * @@ -1712,11 +2589,25 @@ struct Value : detail::ValueImpl { * \param shape_len The number of tensor shape dimensions. * \param type The data type. */ - static Value CreateTensor(const OrtMemoryInfo* info, void* p_data, size_t p_data_byte_count, const int64_t* shape, size_t shape_len, + static Value CreateTensor(const OrtMemoryInfo* info, void* p_data, size_t p_data_byte_count, + const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type); + + /** \brief Creates a tensor with a user supplied buffer. Wraps OrtApi::CreateTensorWithDataAndDeleterAsOrtValue. + * + * \param deleter OrtAllocator that will be used to free the buffer when no longer required. + * \param p_data Pointer to the data buffer. + * \param p_data_byte_count The number of bytes in the data buffer. + * \param shape Pointer to the tensor shape dimensions. + * \param shape_len The number of tensor shape dimensions. + * \param type The data type. + */ + static Value CreateTensor(OrtAllocator* deleter, void* p_data, size_t p_data_byte_count, + const int64_t* shape, size_t shape_len, ONNXTensorElementDataType type); /** \brief Creates an OrtValue with a tensor using a supplied OrtAllocator. Wraps OrtApi::CreateTensorAsOrtValue. - * This overload will allocate the buffer for the tensor according to the supplied shape and data type. + * This overload will allocate the buffer for the tensor according to the supplied shape and data type. * The allocated buffer will be owned by the returned OrtValue and will be freed when the OrtValue is released. * The input data would need to be copied into the allocated buffer. * This API is not suitable for strings. @@ -1740,7 +2631,8 @@ struct Value : detail::ValueImpl { * \param shape_len The number of tensor shape dimensions. * \param type The data type. */ - static Value CreateTensor(OrtAllocator* allocator, const int64_t* shape, size_t shape_len, ONNXTensorElementDataType type); + static Value CreateTensor(OrtAllocator* allocator, const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type); /** \brief Creates an OrtValue with a Map Onnx type representation. * The API would ref-count the supplied OrtValues and they will be released @@ -1834,61 +2726,6 @@ struct Value : detail::ValueImpl { #endif // !defined(DISABLE_SPARSE_TENSORS) }; -/// -/// Represents native memory allocation coming from one of the -/// OrtAllocators registered with OnnxRuntime. -/// Use it to wrap an allocation made by an allocator -/// so it can be automatically released when no longer needed. -/// -struct MemoryAllocation { - MemoryAllocation(OrtAllocator* allocator, void* p, size_t size); - ~MemoryAllocation(); - MemoryAllocation(const MemoryAllocation&) = delete; - MemoryAllocation& operator=(const MemoryAllocation&) = delete; - MemoryAllocation(MemoryAllocation&&) noexcept; - MemoryAllocation& operator=(MemoryAllocation&&) noexcept; - - void* get() { return p_; } - size_t size() const { return size_; } - - private: - OrtAllocator* allocator_; - void* p_; - size_t size_; -}; - -namespace detail { -template -struct AllocatorImpl : Base { - using B = Base; - using B::B; - - void* Alloc(size_t size); - MemoryAllocation GetAllocation(size_t size); - void Free(void* p); - ConstMemoryInfo GetInfo() const; -}; - -} // namespace detail - -/** \brief Wrapper around ::OrtAllocator default instance that is owned by Onnxruntime - * - */ -struct AllocatorWithDefaultOptions : detail::AllocatorImpl> { - explicit AllocatorWithDefaultOptions(std::nullptr_t) {} ///< Convenience to create a class member and then replace with an instance - AllocatorWithDefaultOptions(); -}; - -/** \brief Wrapper around ::OrtAllocator - * - */ -struct Allocator : detail::AllocatorImpl { - explicit Allocator(std::nullptr_t) {} ///< Convenience to create a class member and then replace with an instance - Allocator(const Session& session, const OrtMemoryInfo*); -}; - -using UnownedAllocator = detail::AllocatorImpl>; - namespace detail { namespace binding_utils { // Bring these out of template @@ -1951,21 +2788,58 @@ struct ArenaCfg : detail::Base { * See docs/C_API.md for details on what the following parameters mean and how to choose these values */ ArenaCfg(size_t max_mem, int arena_extend_strategy, int initial_chunk_size_bytes, int max_dead_bytes_per_chunk); + + /** + * Wraps Ort::CreateArenaCfgV2 + * See C API for details on what the following parameters mean and how to choose these values + */ + explicit ArenaCfg(const std::unordered_map& arena_config); }; // // Custom OPs (only needed to implement custom OPs) // +namespace detail { +// Need to define a templated ConstOpAttr with const members +template +struct ConstOpAttrImpl : Base { + using B = detail::Base; + using B::B; + + // Wraps OrtApi::OpAttr_GetName + std::string GetName() const; + // Wraps OrtApi::OpAttr_GetType + OrtOpAttrType GetType() const; + + // Wraps OrtApi::ReadAttr for a single value + // This does not support Tensor Attribute + // Call GetTensorAttributeAsOrtValue() instead. + template + Status GetValue(R& out) const; + + // Wraps OrtApi::ReadAttr for an array of values + template + Status GetValueArray(std::vector& out) const; + // Wraps OrtApi::OpAttr_GetTensorAttributeAsOrtValue + Status GetTensorAttributeAsOrtValue(Value&) const; +}; +} // namespace detail + +using ConstOpAttr = detail::ConstOpAttrImpl>; + /// /// This struct provides life time management for custom op attribute /// -struct OpAttr : detail::Base { - using Base = detail::Base; +struct OpAttr : detail::ConstOpAttrImpl { + using Base = detail::ConstOpAttrImpl; using Base::Base; + OpAttr() = default; // Enable storing it in the container for resize() explicit OpAttr(std::nullptr_t) {} OpAttr(const char* name, const void* data, int len, OrtOpAttrType type); + + ConstOpAttr GetConst() const { return ConstOpAttr{this->p_}; } }; /** @@ -2139,7 +3013,7 @@ struct KernelContext { UnownedValue GetOutput(size_t index, const std::vector& dims) const; void* GetGPUComputeStream() const; Logger GetLogger() const; - OrtAllocator* GetAllocator(const OrtMemoryInfo& memory_info) const; + Ort::Allocator GetAllocator(const OrtMemoryInfo& memory_info) const; OrtKernelContext* GetOrtKernelContext() const { return ctx_; } void ParallelFor(void (*fn)(void*, size_t), size_t total, size_t num_batch, void* usr_data) const; @@ -2156,6 +3030,7 @@ void GetAttr(const OrtKernelInfo* p, const char* name, int64_t&); void GetAttr(const OrtKernelInfo* p, const char* name, std::string&); void GetAttrs(const OrtKernelInfo* p, const char* name, std::vector&); void GetAttrs(const OrtKernelInfo* p, const char* name, std::vector&); +void GetAttrs(const OrtKernelInfo* p, const char* name, std::vector&); } // namespace attr_utils template @@ -2172,7 +3047,7 @@ struct KernelInfoImpl : Base { return val; } - template // R is only implemented for std::vector, std::vector + template // R is only implemented for float, int64_t, and string std::vector GetAttributes(const char* name) const { std::vector result; attr_utils::GetAttrs(this->p_, name, result); @@ -2194,6 +3069,13 @@ struct KernelInfoImpl : Base { std::string GetNodeName() const; Logger GetLogger() const; + + KeyValuePairs GetConfigEntries() const; + + std::string GetOperatorDomain() const; ///< Wraps OrtApi::KernelInfo_GetOperatorDomain + std::string GetOperatorType() const; ///< Wraps OrtApi::KernelInfo_GetOperatorType + int GetOperatorSinceVersion() const; ///< Wraps OrtApi::KernelInfo_GetOperatorSinceVersion + const OrtEp* GetEp() const; ///< Wraps OrtEpApi::KernelInfo_GetEp }; } // namespace detail @@ -2311,7 +3193,7 @@ struct ShapeInferContext { Strings GetAttrStrings(const char* attr_name); private: - const OrtOpAttr* GetAttrHdl(const char* attr_name) const; + ConstOpAttr GetAttrHdl(const char* attr_name) const; const OrtApi* ort_api_; OrtShapeInferContext* ctx_; std::vector input_shapes_; @@ -2401,7 +3283,7 @@ struct CustomOpBase : OrtCustomOp { return OrtCustomOpInputOutputCharacteristic::INPUT_OUTPUT_REQUIRED; } - // Default implemention of GetInputMemoryType() that returns OrtMemTypeDefault + // Default implementation of GetInputMemoryType() that returns OrtMemTypeDefault OrtMemType GetInputMemoryType(size_t /*index*/) const { return OrtMemTypeDefault; } @@ -2437,6 +3319,9 @@ struct CustomOpBase : OrtCustomOp { return std::vector{}; } + // Ort::CustomOpBase derived class should provide the following static method with the type/shape inferencing + // implementation if needed: + // static OrtStatusPtr InferOutputShape(Ort::ShapeInferContext& context) template decltype(&C::InferOutputShape) SetShapeInferFn(decltype(&C::InferOutputShape)) { OrtCustomOp::InferOutputShapeFn = [](const OrtCustomOp*, OrtShapeInferContext* ort_ctx) -> OrtStatusPtr { @@ -2459,6 +3344,445 @@ struct CustomOpBase : OrtCustomOp { int end_ver_ = MAX_CUSTOM_OP_END_VER; }; -} // namespace Ort +// Forward declaration to resolve circular dependency +// on ConstNode +struct ValueInfoConsumerProducerInfo; + +namespace detail { +template +struct ConstValueInfoImpl : Base { + using B = Base; + using B::B; + + /// < A wrapper around OrtApi::GetValueInfoName + std::string GetName() const; + /// < A wrapper around OrtApi::GetValueInfoTypeInfo + ConstTypeInfo TypeInfo() const; + ///< Wraps OrtApi::ValueInfo_GetProducerNode + ValueInfoConsumerProducerInfo GetProducerNode() const; + /// < A wrapper around OrtApi::ValueInfo_GetValueConsumers + std::vector GetConsumers() const; + /// < A wrapper around OrtApi::ValueInfo_GetInitializerValue + Status GetInitializer(ConstValue& value) const; + /// < A wrapper around OrtApi::ValueInfo_GetExternalInitializerInfo + Status GetExternalInitializerInfo(ExternalInitializerInfo& info) const; + /// < A wrapper around OrtApi::ValueInfo_IsRequiredGraphInput + bool IsRequiredGraphInput() const; + /// < A wrapper around OrtApi::ValueInfo_IsOptionalGraphInput + bool IsOptionalGraphInput() const; + /// < A wrapper around OrtApi::ValueInfo_IsGraphOutput + bool IsGraphOutput() const; + /// < A wrapper around OrtApi::ValueInfo_IsConstantInitializer + bool IsConstantInitializer() const; + /// < A wrapper around OrtApi::ValueInfo_IsFromOuterScope + bool IsFromOuterScope() const; +}; +} // namespace detail + +// Const object holder that does not own the underlying object +using ConstValueInfo = detail::ConstValueInfoImpl>; + +/** \brief Wrapper around ::OrtValueInfo + * + */ +struct ValueInfo : detail::ConstValueInfoImpl { + ValueInfo() = default; // Same thing as with nullptr + explicit ValueInfo(std::nullptr_t) {} ///< No instance is created + /// Take ownership of a pointer created by C API + explicit ValueInfo(OrtValueInfo* p) : ConstValueInfoImpl{p} {} + +#if !defined(ORT_MINIMAL_BUILD) + // Create ValueInfo for a tensor + explicit ValueInfo(const std::string& name, const ConstTypeInfo& type_info); +#endif + ConstValueInfo GetConst() const { return ConstValueInfo{this->p_}; } +}; + +// Forward declaration +struct AttrNameSubgraph; + +namespace detail { +// Forward decl +template +struct ConstGraphImpl; + +template +struct ConstNodeImpl : Base { + using B = Base; + using B::B; + + // GetInputs() const; + // GetOutputs() const; + // GetImplicitInputs() const; + // GetAttributes() const; + // GetSubgraphs() const; + // > GetGraph() const; + // >; +/** \brief Wrapper around ::OrtNode + * + */ +struct Node : detail::ConstNodeImpl { + Node() = default; // Same thing as with nullptr + explicit Node(std::nullptr_t) {} ///< No instance is created + explicit Node(OrtNode* p) : ConstNodeImpl{p} {} ///< Take ownership of a pointer created by C API + +#if !defined(ORT_MINIMAL_BUILD) + Node(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names); + + /// + /// Wraps CreateNode. Node takes ownership of attributes on success and updates the OpAttr in `attributes` to do so. + /// + Node(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names, + std::vector& attributes); + + private: + static void Init(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names, + std::vector& attributes, + OrtNode*& node); +#endif // !defined(ORT_MINIMAL_BUILD) +}; + +// Return struct for some of ValueInfo APIs. +// Must be declared after ConstNode is available. +struct ValueInfoConsumerProducerInfo { + ConstNode node; + // either producer output or consumer output index + // producer is unsigned only, output can be -1 + int64_t index; +}; + +// Represents a return value for Graph::GetOperatorSets() +struct OperatorSet { + std::string domain; + int64_t version; +}; + +namespace detail { +template +struct ConstGraphImpl : Base { + using B = Base; + using B::B; + + // GetModelPath() const; + // GetOperatorSets() const; + // GetInputs() const; + // GetOutputs() const; + // GetInitializers() const; + // GetNodes() const; + // & nodes) const; + // +struct GraphImpl : ConstGraphImpl { + using B = ConstGraphImpl; + using B::B; + +#if !defined(ORT_MINIMAL_BUILD) + // & inputs); + // & outputs); + // >; + +// Return value for Node API +// Must be declared after ConstGraph +struct AttrNameSubgraph { + std::string attr_name; + ConstGraph sub_graph; +}; + +/** \brief Wrapper around ::OrtGraph + * + */ +struct Graph : detail::GraphImpl { + explicit Graph(std::nullptr_t) {} ///< No instance is created + explicit Graph(OrtGraph* p) : GraphImpl{p} {} ///< Take ownership of a pointer created by C API +#if !defined(ORT_MINIMAL_BUILD) + // +struct ModelImpl : detail::Base { + using B = Ort::detail::Base; + using B::B; + +#if !defined(ORT_MINIMAL_BUILD) + // >; + +/** \brief Wrapper around ::OrtModel + * + */ +struct Model : detail::ModelImpl { + using DomainOpsetPair = std::pair; + + explicit Model(std::nullptr_t) {} ///< No instance is created + explicit Model(OrtModel* p) : ModelImpl{p} {} ///< Take ownership of a pointer created by C API + +#if !defined(ORT_MINIMAL_BUILD) + //< Wraps GetModelEditorApi().CreateModel() + explicit Model(const std::vector& opsets); +#endif +}; + +namespace detail { +template +struct ConstKernelDefImpl : Base { + using B = Base; + using B::B; + + ///< Wraps OrtEpApi::KernelDef_GetOperatorType + const char* GetOperatorType() const; + + ///< Wraps OrtEpApi::KernelDef_GetDomain + const char* GetDomain() const; + + ///< Wraps OrtEpApi::KernelDef_GetSinceVersion + std::pair GetSinceVersion() const; + + ///< Wraps OrtEpApi::KernelDef_GetExecutionProvider + const char* GetExecutionProvider() const; + + ///< Wraps OrtEpApi::KernelDef_GetInputMemType + OrtMemType GetInputMemType(size_t input_index) const; + + ///< Wraps OrtEpApi::KernelDef_GetOutputMemType + OrtMemType GetOutputMemType(size_t output_index) const; +}; +} // namespace detail + +using ConstKernelDef = detail::ConstKernelDefImpl>; + +struct KernelDef : detail::ConstKernelDefImpl { + using Base = detail::ConstKernelDefImpl; + using Base::Base; + + explicit KernelDef(std::nullptr_t) {} + explicit KernelDef(OrtKernelDef* p) : detail::ConstKernelDefImpl{p} {} + + ConstKernelDef GetConst() const { return ConstKernelDef{this->p_}; } +}; + +/** \brief Builder for OrtKernelDef. + * + * Used by plugin EPs to build a kernel definition. + */ +struct KernelDefBuilder : detail::Base { + KernelDefBuilder(); ///< Wraps OrtEpApi::CreateKernelDefBuilder + explicit KernelDefBuilder(std::nullptr_t) {} ///< Create an empty object, must be assigned a valid one to be used + explicit KernelDefBuilder(OrtKernelDefBuilder* ort_kernel_def_builder); + + KernelDefBuilder& SetOperatorType(const char* op_type); + KernelDefBuilder& SetDomain(const char* domain); + KernelDefBuilder& SetSinceVersion(int since_version_start, int since_version_end); + KernelDefBuilder& SetExecutionProvider(const char* ep_name); + KernelDefBuilder& SetInputMemType(size_t input_index, OrtMemType mem_type); + KernelDefBuilder& SetOutputMemType(size_t output_index, OrtMemType mem_type); + KernelDefBuilder& AddTypeConstraint(const char* arg_name, const OrtDataType* data_type); + KernelDefBuilder& AddTypeConstraint(const char* arg_name, const std::vector& data_types); + KernelDefBuilder& AddInputOutputAlias(int input_index, int output_index); + KernelDefBuilder& AddInputOutputAliases(const std::vector& input_indices, + const std::vector& output_indices); + KernelDefBuilder& AddInputOutputMutableAlias(int input_index, int output_index); + KernelDefBuilder& AddInputOutputMutableAliases(const std::vector& input_indices, + const std::vector& output_indices); + + KernelDef Build(); +}; + +/** \brief Registry for kernels supported by an EP. + * + * Used by plugin EPs to register definitions for supported kernels. + */ +struct KernelRegistry : detail::Base { + ///< Wrapper around OrtEpApi::CreateKernelRegistry + KernelRegistry(); + + ///< Create an empty object, must be assigned a valid one to be used + explicit KernelRegistry(std::nullptr_t) {} + + ///< Take ownership of a pointer created with the C API. + explicit KernelRegistry(OrtKernelRegistry* ort_kernel_registry); + + ///< Wraps KernelRegistry_AddKernel + Status AddKernel(const OrtKernelDef* kernel_def, OrtKernelCreateFunc kernel_create_func, + void* kernel_create_func_state); +}; + +namespace detail { +template +struct OpSchemaTypeConstraintImpl : Base { + using B = Base; + using B::B; + + ///< Wraps OrtEpApi::OpSchemaTypeConstraint_GetTypeParamName + std::string GetTypeParamName() const; + + ///< Wraps OrtEpApi::OpSchemaTypeConstraint_GetAllowedTypes + std::vector GetAllowedTypes() const; + + ///< Wraps OrtEpApi::OpSchemaTypeConstraint_GetInputIndices + std::vector GetInputIndices() const; + + ///< Wraps OrtEpApi::OpSchemaTypeConstraint_GetOutputIndices + std::vector GetOutputIndices() const; +}; +} // namespace detail + +/// Non-owning wrapper around a `const OrtOpSchemaTypeConstraint*`. +/// Holds a single type constraint from an operator schema, providing access to +/// the constraint's name, allowed data types, and associated input/output indices. +using ConstOpSchemaTypeConstraint = detail::OpSchemaTypeConstraintImpl>; + +namespace detail { +template +struct OpSchemaImpl : Base { + using B = Base; + using B::B; + + ///< Wraps OrtEpApi::OpSchema_GetSinceVersion + int GetSinceVersion() const; + + ///< Wraps OrtEpApi::OpSchema_GetNumInputs + size_t GetNumInputs() const; + + ///< Wraps OrtEpApi::OpSchema_GetInputName + std::string GetInputName(size_t index) const; + + ///< Wraps OrtEpApi::OpSchema_GetInputTypeConstraint. Returns the type constraint for the given input, + ///< or a wrapper around nullptr if the input has no type constraint. + ConstOpSchemaTypeConstraint GetInputTypeConstraint(size_t index) const; + + ///< Wraps OrtEpApi::OpSchema_GetNumOutputs + size_t GetNumOutputs() const; + + ///< Wraps OrtEpApi::OpSchema_GetOutputName + std::string GetOutputName(size_t index) const; + + ///< Wraps OrtEpApi::OpSchema_GetOutputTypeConstraint. Returns the type constraint for the given output, + ///< or a wrapper around nullptr if the output has no type constraint. + ConstOpSchemaTypeConstraint GetOutputTypeConstraint(size_t index) const; + + ///< Wraps OrtEpApi::OpSchema_GetTypeConstraintCount + size_t GetTypeConstraintCount() const; + + ///< Wraps OrtEpApi::OpSchema_GetTypeConstraint. Returns the i-th type constraint. + ConstOpSchemaTypeConstraint GetTypeConstraint(size_t index) const; +}; +} // namespace detail + +/// Owning wrapper around an `OrtOpSchema*`. +/// Provides access to operator schema metadata such as version, input/output names, +/// and type constraints. The underlying OrtOpSchema is owned by this wrapper and +/// released automatically on destruction. +using OpSchema = detail::OpSchemaImpl; + +/// \brief Get an operator schema from the global schema registry. +/// +/// Wraps OrtEpApi::GetOpSchema. Returns an OpSchema that may wrap nullptr if the schema is not found. +/// Available schemas include standard ONNX ops (domain "" or "ai.onnx"), ONNX ML ops ("ai.onnx.ml"), +/// and ORT contrib ops ("com.microsoft"). +OpSchema GetOpSchema(const char* name, int max_inclusive_version, const char* domain); + +namespace detail { +template +struct SharedPrePackedWeightCacheImpl : Ort::detail::Base { + using B = Ort::detail::Base; + using B::B; + + //< Wraps SharedPrePackedWeightCache_StoreWeightData + Status StoreWeightData(void** buffer_data_ptrs, size_t* buffer_sizes, size_t num_buffers); +}; +} // namespace detail + +/** \brief Convenience C++ wrapper class around a ::OrtSharedPrePackedWeightCache instance owned by ORT. + * + * An `OrtSharedPrePackedWeightCache*` instance is passed as an argument to OrtKernelImpl::PrePackWeight. + * Example use: + * OrtStatus* MyKernel::PrePackWeightImpl(OrtKernelImpl*, ..., OrtSharedPrePackedWeightCache* c_cache, ...) { + * ... + * if (c_cache != nullptr) { + * Ort::UnownedSharedPrePackedWeightCache cpp_cache(c_cache); + * Ort::Status status = cpp_cache.StoreWeightData(...); + * } + * ... + * } + * + * \remarks OrtSharedPrePackedWeightCache is always unowned, but mutable, for EpApi users. + */ +using UnownedSharedPrePackedWeightCache = + detail::SharedPrePackedWeightCacheImpl>; + +///< Wraps OrtEpApi::GetEnvConfigEntries() +Ort::KeyValuePairs GetEnvConfigEntries(); + +} // namespace Ort #include "onnxruntime_cxx_inline.h" diff --git a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h index 3aeb9412f350e..99c606161c812 100644 --- a/include/onnxruntime/core/session/onnxruntime_cxx_inline.h +++ b/include/onnxruntime/core/session/onnxruntime_cxx_inline.h @@ -10,7 +10,10 @@ #include #include #include +#include #include +#include +#include // Convert OrtStatus to Ort::Status and return // instead of throwing @@ -54,15 +57,15 @@ inline void ThrowOnError(const Status& st) { inline Status::Status(OrtStatus* status) noexcept : detail::Base{status} { } -inline Status::Status(const std::exception& e) noexcept { +inline Status::Status(const std::exception& e) { p_ = GetApi().CreateStatus(ORT_FAIL, e.what()); } -inline Status::Status(const Exception& e) noexcept { +inline Status::Status(const Exception& e) { p_ = GetApi().CreateStatus(e.GetOrtErrorCode(), e.what()); } -inline Status::Status(const char* message, OrtErrorCode code) noexcept { +inline Status::Status(const char* message, OrtErrorCode code) { p_ = GetApi().CreateStatus(code, message); } @@ -221,6 +224,19 @@ inline void* AllocatorImpl::Alloc(size_t size) { return out; } +template +inline void* AllocatorImpl::Reserve(size_t size) { + // Reserve was added in version 18. For older allocators the field may be + // uninitialized, so we must not dereference it. + if (this->p_->version >= 18 && this->p_->Reserve) { + return this->p_->Reserve(this->p_, size); + } + // Fall back to Alloc() for allocators that don't implement Reserve, + // matching the ORT-core adapter behavior (IAllocatorImplWrappingOrtAllocator, + // IArenaImplWrappingOrtAllocator). + return this->p_->Alloc(this->p_, size); +} + template inline MemoryAllocation AllocatorImpl::GetAllocation(size_t size) { void* out; @@ -241,6 +257,21 @@ inline ConstMemoryInfo AllocatorImpl::GetInfo() const { return ConstMemoryInfo{out}; } +template +inline KeyValuePairs AllocatorImpl::GetStats() const { + OrtKeyValuePairs* out; + ThrowOnError(GetApi().AllocatorGetStats(this->p_, &out)); + return KeyValuePairs(out); +} + +template +inline void AllocatorImpl::Shrink() { + // Shrink was added in version 25. For older allocators the field may be + // uninitialized, so we must not dereference it. + if (this->p_->version >= 25 && this->p_->Shrink) { + ThrowOnError(this->p_->Shrink(this->p_)); + } +} } // namespace detail inline AllocatorWithDefaultOptions::AllocatorWithDefaultOptions() { @@ -288,6 +319,16 @@ inline OrtMemType MemoryInfoImpl::GetMemoryType() const { return type; } +template +inline OrtDeviceMemoryType MemoryInfoImpl::GetDeviceMemoryType() const { + return GetApi().MemoryInfoGetDeviceMemType(this->p_); +} + +template +inline uint32_t MemoryInfoImpl::GetVendorId() const { + return GetApi().MemoryInfoGetVendorId(this->p_); +} + template template inline bool MemoryInfoImpl::operator==(const MemoryInfoImpl& o) const { @@ -308,6 +349,12 @@ inline MemoryInfo::MemoryInfo(const char* name, OrtAllocatorType type, int id, O ThrowOnError(GetApi().CreateMemoryInfo(name, type, id, mem_type, &this->p_)); } +inline MemoryInfo::MemoryInfo(const char* name, OrtMemoryInfoDeviceType device_type, uint32_t vendor_id, uint32_t device_id, + OrtDeviceMemoryType mem_type, size_t alignment, OrtAllocatorType allocator_type) { + ThrowOnError(GetApi().CreateMemoryInfo_V2(name, device_type, vendor_id, device_id, mem_type, alignment, + allocator_type, &this->p_)); +} + namespace detail { template inline std::vector ConstIoBindingImpl::GetOutputNames() const { @@ -396,20 +443,7 @@ inline std::vector GetOutputNamesHelper(const OrtIoBinding* binding inline std::vector GetOutputValuesHelper(const OrtIoBinding* binding, OrtAllocator* allocator) { std::vector result; - size_t owned = 0; size_t output_count = 0; - // Lambda to release the buffer when no longer needed and - // make sure that we destroy all instances on exception - auto free_fn = [&owned, &output_count, allocator](OrtValue** buffer) { - if (buffer) { - while (owned < output_count) { - auto* p = buffer + owned++; - GetApi().ReleaseValue(*p); - } - allocator->Free(allocator, buffer); - } - }; - using Ptr = std::unique_ptr; OrtValue** output_buffer = nullptr; ThrowOnError(GetApi().GetBoundOutputValues(binding, allocator, &output_buffer, &output_count)); @@ -417,12 +451,11 @@ inline std::vector GetOutputValuesHelper(const OrtIoBinding* binding, Ort return result; } - Ptr buffer_g(output_buffer, free_fn); + std::unique_ptr buffer_g(output_buffer, AllocatedFree(allocator)); result.reserve(output_count); for (size_t i = 0; i < output_count; ++i) { result.emplace_back(output_buffer[i]); - ++owned; } return result; } @@ -438,6 +471,18 @@ inline ArenaCfg::ArenaCfg(size_t max_mem, int arena_extend_strategy, int initial ThrowOnError(GetApi().CreateArenaCfg(max_mem, arena_extend_strategy, initial_chunk_size_bytes, max_dead_bytes_per_chunk, &p_)); } +inline ArenaCfg::ArenaCfg(const std::unordered_map& arena_config) { + std::vector keys; + std::vector values; + keys.reserve(arena_config.size()); + values.reserve(arena_config.size()); + for (const auto& kv : arena_config) { + keys.push_back(kv.first.c_str()); + values.push_back(kv.second); + } + ThrowOnError(GetApi().CreateArenaCfgV2(keys.data(), values.data(), arena_config.size(), &p_)); +} + inline ThreadingOptions::ThreadingOptions() { ThrowOnError(GetApi().CreateThreadingOptions(&p_)); } @@ -477,1694 +522,3720 @@ inline ThreadingOptions& ThreadingOptions::SetGlobalCustomJoinThreadFn(OrtCustom return *this; } -inline Env::Env(OrtLoggingLevel logging_level, _In_ const char* logid) { - ThrowOnError(GetApi().CreateEnv(logging_level, logid, &p_)); - if (strcmp(logid, "onnxruntime-node") == 0) { - ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_NODEJS)); - } else { - ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_CPLUSPLUS)); - } +inline TensorRTProviderOptions::TensorRTProviderOptions() { + ThrowOnError(GetApi().CreateTensorRTProviderOptions(&this->p_)); } -inline Env::Env(OrtLoggingLevel logging_level, const char* logid, OrtLoggingFunction logging_function, void* logger_param) { - ThrowOnError(GetApi().CreateEnvWithCustomLogger(logging_function, logger_param, logging_level, logid, &p_)); - if (strcmp(logid, "onnxruntime-node") == 0) { - ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_NODEJS)); - } else { - ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_CPLUSPLUS)); +inline void TensorRTProviderOptions::Update(const std::unordered_map& options) { + std::vector keys; + std::vector values; + keys.reserve(options.size()); + values.reserve(options.size()); + for (const auto& kv : options) { + keys.push_back(kv.first.c_str()); + values.push_back(kv.second.c_str()); } + ThrowOnError(GetApi().UpdateTensorRTProviderOptions(p_, keys.data(), values.data(), options.size())); } -inline Env::Env(const OrtThreadingOptions* tp_options, OrtLoggingLevel logging_level, _In_ const char* logid) { - ThrowOnError(GetApi().CreateEnvWithGlobalThreadPools(logging_level, logid, tp_options, &p_)); - if (strcmp(logid, "onnxruntime-node") == 0) { - ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_NODEJS)); - } else { - ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_CPLUSPLUS)); - } +inline void TensorRTProviderOptions::UpdateWithValue(const char* key, void* value) { + ThrowOnError(GetApi().UpdateTensorRTProviderOptionsWithValue(p_, key, value)); } -inline Env::Env(const OrtThreadingOptions* tp_options, OrtLoggingFunction logging_function, void* logger_param, - OrtLoggingLevel logging_level, _In_ const char* logid) { - ThrowOnError(GetApi().CreateEnvWithCustomLoggerAndGlobalThreadPools(logging_function, logger_param, logging_level, logid, tp_options, &p_)); - if (strcmp(logid, "onnxruntime-node") == 0) { - ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_NODEJS)); - } else { - ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_CPLUSPLUS)); - } +inline void* TensorRTProviderOptions::GetOptionByName(const char* name) const { + void* value = nullptr; + ThrowOnError(GetApi().GetTensorRTProviderOptionsByName(p_, name, &value)); + return value; } -inline Env& Env::EnableTelemetryEvents() { - ThrowOnError(GetApi().EnableTelemetryEvents(p_)); - return *this; +inline std::string TensorRTProviderOptions::GetTensorRTProviderOptionsAsString() const { + AllocatorWithDefaultOptions allocator; + char* options_str = nullptr; + ThrowOnError(GetApi().GetTensorRTProviderOptionsAsString(p_, allocator, &options_str)); + std::unique_ptr options_str_g(options_str, detail::AllocatedFree(allocator)); + return std::string(options_str); } -inline Env& Env::DisableTelemetryEvents() { - ThrowOnError(GetApi().DisableTelemetryEvents(p_)); - return *this; +inline CUDAProviderOptions::CUDAProviderOptions() { + ThrowOnError(GetApi().CreateCUDAProviderOptions(&this->p_)); } -inline Env& Env::UpdateEnvWithCustomLogLevel(OrtLoggingLevel log_severity_level) { - ThrowOnError(GetApi().UpdateEnvWithCustomLogLevel(p_, log_severity_level)); - return *this; +inline void CUDAProviderOptions::Update(const std::unordered_map& options) { + std::vector keys; + std::vector values; + keys.reserve(options.size()); + values.reserve(options.size()); + for (const auto& kv : options) { + keys.push_back(kv.first.c_str()); + values.push_back(kv.second.c_str()); + } + ThrowOnError(GetApi().UpdateCUDAProviderOptions(p_, keys.data(), values.data(), options.size())); } -inline Env& Env::CreateAndRegisterAllocator(const OrtMemoryInfo* mem_info, const OrtArenaCfg* arena_cfg) { - ThrowOnError(GetApi().CreateAndRegisterAllocator(p_, mem_info, arena_cfg)); - return *this; +inline std::string CUDAProviderOptions::GetCUDAProviderOptionsAsString() const { + AllocatorWithDefaultOptions allocator; + char* options_str = nullptr; + ThrowOnError(GetApi().GetCUDAProviderOptionsAsString(p_, allocator, &options_str)); + std::unique_ptr options_str_g(options_str, detail::AllocatedFree(allocator)); + return std::string(options_str); } -inline Env& Env::CreateAndRegisterAllocatorV2(const std::string& provider_type, const OrtMemoryInfo* mem_info, const std::unordered_map& options, const OrtArenaCfg* arena_cfg) { - std::vector keys, values; - auto num_entries = options.size(); - if (num_entries > 0) { - keys.reserve(num_entries); - values.reserve(num_entries); - for (const auto& entry : options) { - keys.push_back(entry.first.c_str()); - values.push_back(entry.second.c_str()); - } - } - ThrowOnError(GetApi().CreateAndRegisterAllocatorV2(p_, provider_type.c_str(), mem_info, arena_cfg, keys.data(), values.data(), num_entries)); - return *this; +inline void CUDAProviderOptions::UpdateWithValue(const char* key, void* value) { + ThrowOnError(GetApi().UpdateCUDAProviderOptionsWithValue(p_, key, value)); } -inline CustomOpDomain::CustomOpDomain(const char* domain) { - ThrowOnError(GetApi().CreateCustomOpDomain(domain, &p_)); +inline void* CUDAProviderOptions::GetOptionByName(const char* name) const { + void* value = nullptr; + ThrowOnError(GetApi().GetCUDAProviderOptionsByName(p_, name, &value)); + return value; } -inline void CustomOpDomain::Add(const OrtCustomOp* op) { - ThrowOnError(GetApi().CustomOpDomain_Add(p_, op)); +inline PrepackedWeightsContainer::PrepackedWeightsContainer() { + ThrowOnError(GetApi().CreatePrepackedWeightsContainer(&this->p_)); } -inline LoraAdapter LoraAdapter::CreateLoraAdapter(const std::basic_string& adapter_path, - OrtAllocator* allocator) { - OrtLoraAdapter* p; - ThrowOnError(GetApi().CreateLoraAdapter(adapter_path.c_str(), allocator, &p)); - return LoraAdapter{p}; +namespace detail { + +template +inline const std::basic_string ConstExternalInitializerInfoImpl::GetFilePath() const { + return GetApi().ExternalInitializerInfo_GetFilePath(this->p_); } -inline LoraAdapter LoraAdapter::CreateLoraAdapterFromArray(const void* bytes, size_t num_bytes, - OrtAllocator* allocator) { - OrtLoraAdapter* p; - ThrowOnError(GetApi().CreateLoraAdapterFromArray(bytes, num_bytes, allocator, &p)); - return LoraAdapter{p}; +template +inline int64_t ConstExternalInitializerInfoImpl::GetFileOffset() const { + return GetApi().ExternalInitializerInfo_GetFileOffset(this->p_); } -inline RunOptions::RunOptions() { - ThrowOnError(GetApi().CreateRunOptions(&p_)); +template +inline size_t ConstExternalInitializerInfoImpl::GetByteSize() const { + return GetApi().ExternalInitializerInfo_GetByteSize(this->p_); } +} // namespace detail -inline RunOptions& RunOptions::SetRunLogVerbosityLevel(int level) { - ThrowOnError(GetApi().RunOptionsSetRunLogVerbosityLevel(p_, level)); - return *this; +inline ExternalInitializerInfo::ExternalInitializerInfo(const ORTCHAR_T* filepath, int64_t file_offset, + size_t byte_size) { + ThrowOnError(GetApi().CreateExternalInitializerInfo(filepath, file_offset, byte_size, &this->p_)); } -inline RunOptions& RunOptions::SetRunLogSeverityLevel(int level) { - ThrowOnError(GetApi().RunOptionsSetRunLogSeverityLevel(p_, level)); - return *this; +inline Status ExternalInitializerInfo::Create(const ORTCHAR_T* filepath, int64_t file_offset, size_t byte_size, + /*out*/ ExternalInitializerInfo& out) { + OrtExternalInitializerInfo* info = nullptr; + OrtStatus* status = GetApi().CreateExternalInitializerInfo(filepath, file_offset, byte_size, &info); + if (status != nullptr) { + return Status{status}; + } + + out = ExternalInitializerInfo(info); + + return Status{nullptr}; } -inline int RunOptions::GetRunLogVerbosityLevel() const { - int out; - ThrowOnError(GetApi().RunOptionsGetRunLogVerbosityLevel(p_, &out)); - return out; +namespace detail { +template +inline const char* KeyValuePairsImpl::GetValue(const char* key) const { + return GetApi().GetKeyValue(this->p_, key); } -inline int RunOptions::GetRunLogSeverityLevel() const { - int out; - ThrowOnError(GetApi().RunOptionsGetRunLogSeverityLevel(p_, &out)); +template +inline std::unordered_map KeyValuePairsImpl::GetKeyValuePairs() const { + std::unordered_map out; + + size_t num_pairs = 0; + const char* const* keys = nullptr; + const char* const* values = nullptr; + GetApi().GetKeyValuePairs(this->p_, &keys, &values, &num_pairs); + if (num_pairs > 0) { + out.reserve(num_pairs); + for (size_t i = 0; i < num_pairs; ++i) { + out.emplace(keys[i], values[i]); + } + } + return out; } -inline RunOptions& RunOptions::SetRunTag(const char* run_tag) { - ThrowOnError(GetApi().RunOptionsSetRunTag(p_, run_tag)); - return *this; -} +template +inline void KeyValuePairsImpl::GetKeyValuePairs(std::vector& keys, + std::vector& values) const { + keys.clear(); + values.clear(); -inline const char* RunOptions::GetRunTag() const { - const char* out; - ThrowOnError(GetApi().RunOptionsGetRunTag(p_, &out)); - return out; + size_t num_pairs = 0; + const char* const* keys_ptr = nullptr; + const char* const* values_ptr = nullptr; + GetApi().GetKeyValuePairs(this->p_, &keys_ptr, &values_ptr, &num_pairs); + if (num_pairs > 0) { + keys.resize(num_pairs); + values.resize(num_pairs); + std::copy(keys_ptr, keys_ptr + num_pairs, keys.begin()); + std::copy(values_ptr, values_ptr + num_pairs, values.begin()); + } } +} // namespace detail -inline RunOptions& RunOptions::AddConfigEntry(const char* config_key, const char* config_value) { - ThrowOnError(GetApi().AddRunConfigEntry(p_, config_key, config_value)); - return *this; +inline KeyValuePairs::KeyValuePairs() { + GetApi().CreateKeyValuePairs(&p_); } -inline RunOptions& RunOptions::SetTerminate() { - ThrowOnError(GetApi().RunOptionsSetTerminate(p_)); - return *this; +inline KeyValuePairs::KeyValuePairs(const std::unordered_map& kv_pairs) { + GetApi().CreateKeyValuePairs(&p_); + for (const auto& kv : kv_pairs) { + GetApi().AddKeyValuePair(this->p_, kv.first.c_str(), kv.second.c_str()); + } } -inline RunOptions& RunOptions::UnsetTerminate() { - ThrowOnError(GetApi().RunOptionsUnsetTerminate(p_)); - return *this; +inline void KeyValuePairs::Add(const char* key, const char* value) { + GetApi().AddKeyValuePair(this->p_, key, value); } -inline RunOptions& RunOptions::AddActiveLoraAdapter(const LoraAdapter& adapter) { - ThrowOnError(GetApi().RunOptionsAddActiveLoraAdapter(p_, adapter)); - return *this; +inline void KeyValuePairs::Remove(const char* key) { + GetApi().RemoveKeyValuePair(this->p_, key); } namespace detail { - template -inline Ort::SessionOptions ConstSessionOptionsImpl::Clone() const { - OrtSessionOptions* out; - ThrowOnError(GetApi().CloneSessionOptions(this->p_, &out)); - return SessionOptions{out}; +inline void* SyncStreamImpl::GetHandle() { + return GetApi().SyncStream_GetHandle(this->p_); } +} // namespace detail +namespace detail { template -inline std::string ConstSessionOptionsImpl::GetConfigEntry(const char* config_key) const { - size_t size = 0; - // Feed nullptr for the data buffer to query the true size of the string value - Ort::ThrowOnError(GetApi().GetSessionConfigEntry(this->p_, config_key, nullptr, &size)); - - std::string out; - out.resize(size); - Ort::ThrowOnError(GetApi().GetSessionConfigEntry(this->p_, config_key, &out[0], &size)); - out.resize(size - 1); // remove the terminating character '\0' - - return out; +inline OrtHardwareDeviceType HardwareDeviceImpl::Type() const { + return GetApi().HardwareDevice_Type(this->p_); } template -inline bool ConstSessionOptionsImpl::HasConfigEntry(const char* config_key) const { - int out = 0; - Ort::ThrowOnError(GetApi().HasSessionConfigEntry(this->p_, config_key, &out)); - return static_cast(out); +inline uint32_t HardwareDeviceImpl::VendorId() const { + return GetApi().HardwareDevice_VendorId(this->p_); } template -inline std::string ConstSessionOptionsImpl::GetConfigEntryOrDefault(const char* config_key, const std::string& def) { - if (!this->HasConfigEntry(config_key)) { - return def; - } - - return this->GetConfigEntry(config_key); +inline uint32_t HardwareDeviceImpl::DeviceId() const { + return GetApi().HardwareDevice_DeviceId(this->p_); } template -inline SessionOptionsImpl& SessionOptionsImpl::SetIntraOpNumThreads(int intra_op_num_threads) { - ThrowOnError(GetApi().SetIntraOpNumThreads(this->p_, intra_op_num_threads)); - return *this; +inline const char* HardwareDeviceImpl::Vendor() const { + return GetApi().HardwareDevice_Vendor(this->p_); } template -inline SessionOptionsImpl& SessionOptionsImpl::SetInterOpNumThreads(int inter_op_num_threads) { - ThrowOnError(GetApi().SetInterOpNumThreads(this->p_, inter_op_num_threads)); - return *this; +inline ConstKeyValuePairs HardwareDeviceImpl::Metadata() const { + return ConstKeyValuePairs{GetApi().HardwareDevice_Metadata(this->p_)}; } template -inline SessionOptionsImpl& SessionOptionsImpl::SetGraphOptimizationLevel(GraphOptimizationLevel graph_optimization_level) { - ThrowOnError(GetApi().SetSessionGraphOptimizationLevel(this->p_, graph_optimization_level)); - return *this; +inline const char* EpDeviceImpl::EpName() const { + return GetApi().EpDevice_EpName(this->p_); } template -inline SessionOptionsImpl& SessionOptionsImpl::SetDeterministicCompute(bool value) { - ThrowOnError(GetApi().SetDeterministicCompute(this->p_, value)); - return *this; +inline const char* EpDeviceImpl::EpVendor() const { + return GetApi().EpDevice_EpVendor(this->p_); } template -inline SessionOptionsImpl& SessionOptionsImpl::SetOptimizedModelFilePath(const ORTCHAR_T* optimized_model_filepath) { - ThrowOnError(GetApi().SetOptimizedModelFilePath(this->p_, optimized_model_filepath)); - return *this; +inline ConstKeyValuePairs EpDeviceImpl::EpMetadata() const { + return ConstKeyValuePairs(GetApi().EpDevice_EpMetadata(this->p_)); } template -inline SessionOptionsImpl& SessionOptionsImpl::EnableProfiling(const ORTCHAR_T* profile_file_prefix) { - ThrowOnError(GetApi().EnableProfiling(this->p_, profile_file_prefix)); - return *this; +inline ConstKeyValuePairs EpDeviceImpl::EpOptions() const { + return ConstKeyValuePairs(GetApi().EpDevice_EpOptions(this->p_)); } template -inline SessionOptionsImpl& SessionOptionsImpl::DisableProfiling() { - ThrowOnError(GetApi().DisableProfiling(this->p_)); - return *this; +inline ConstHardwareDevice EpDeviceImpl::Device() const { + return ConstHardwareDevice(GetApi().EpDevice_Device(this->p_)); } template -inline SessionOptionsImpl& SessionOptionsImpl::EnableOrtCustomOps() { - ThrowOnError(GetApi().EnableOrtCustomOps(this->p_)); - return *this; +inline ConstMemoryInfo EpDeviceImpl::GetMemoryInfo(OrtDeviceMemoryType memory_type) const { + const auto* mem_info = GetApi().EpDevice_MemoryInfo(this->p_, memory_type); + return ConstMemoryInfo{mem_info}; } template -inline SessionOptionsImpl& SessionOptionsImpl::EnableMemPattern() { - ThrowOnError(GetApi().EnableMemPattern(this->p_)); - return *this; +inline SyncStream EpDeviceImpl::CreateSyncStream(ConstKeyValuePairs stream_options) const { + OrtSyncStream* stream = nullptr; + ThrowOnError(GetApi().CreateSyncStreamForEpDevice(this->p_, stream_options, &stream)); + return SyncStream{stream}; } +} // namespace detail -template -inline SessionOptionsImpl& SessionOptionsImpl::DisableMemPattern() { - ThrowOnError(GetApi().DisableMemPattern(this->p_)); - return *this; +inline EpDevice::EpDevice(OrtEpFactory& ep_factory, ConstHardwareDevice& hardware_device, + ConstKeyValuePairs ep_metadata, ConstKeyValuePairs ep_options) { + ThrowOnError(GetEpApi().CreateEpDevice(&ep_factory, hardware_device, ep_metadata, ep_options, &p_)); } +namespace detail { template -inline SessionOptionsImpl& SessionOptionsImpl::EnableCpuMemArena() { - ThrowOnError(GetApi().EnableCpuMemArena(this->p_)); - return *this; +inline std::string EpAssignedSubgraphImpl::GetEpName() const { + const char* ep_name = nullptr; + + // Returned null-terminated string will not be null if API function returns successfully. + ThrowOnError(GetApi().EpAssignedSubgraph_GetEpName(this->p_, &ep_name)); + return std::string(ep_name); } template -inline SessionOptionsImpl& SessionOptionsImpl::DisableCpuMemArena() { - ThrowOnError(GetApi().DisableCpuMemArena(this->p_)); - return *this; +inline std::vector EpAssignedSubgraphImpl::GetNodes() const { + size_t num_ep_nodes = 0; + const OrtEpAssignedNode* const* ep_node_ptrs = nullptr; + ThrowOnError(GetApi().EpAssignedSubgraph_GetNodes(this->p_, &ep_node_ptrs, &num_ep_nodes)); + + std::vector ep_nodes; + if (num_ep_nodes > 0) { + ep_nodes.reserve(num_ep_nodes); + for (size_t i = 0; i < num_ep_nodes; ++i) { + ep_nodes.emplace_back(ep_node_ptrs[i]); + } + } + + return ep_nodes; } template -inline SessionOptionsImpl& SessionOptionsImpl::SetExecutionMode(ExecutionMode execution_mode) { - ThrowOnError(GetApi().SetSessionExecutionMode(this->p_, execution_mode)); - return *this; +inline std::string EpAssignedNodeImpl::GetName() const { + const char* node_name = nullptr; + + // Returned null-terminated string will not be null if API function returns successfully. + ThrowOnError(GetApi().EpAssignedNode_GetName(this->p_, &node_name)); + return std::string(node_name); } template -inline SessionOptionsImpl& SessionOptionsImpl::SetLogId(const char* logid) { - ThrowOnError(GetApi().SetSessionLogId(this->p_, logid)); - return *this; +inline std::string EpAssignedNodeImpl::GetDomain() const { + const char* domain = nullptr; + + // Returned null-terminated string will not be null if API function returns successfully. + ThrowOnError(GetApi().EpAssignedNode_GetDomain(this->p_, &domain)); + return std::string(domain); } template -inline SessionOptionsImpl& SessionOptionsImpl::SetLogSeverityLevel(int level) { - ThrowOnError(GetApi().SetSessionLogSeverityLevel(this->p_, level)); - return *this; +inline std::string EpAssignedNodeImpl::GetOperatorType() const { + const char* op_type = nullptr; + + // Returned null-terminated string will not be null if API function returns successfully. + ThrowOnError(GetApi().EpAssignedNode_GetOperatorType(this->p_, &op_type)); + return std::string(op_type); } +} // namespace detail +// ProfilingEvent implementations +namespace detail { template -inline SessionOptionsImpl& SessionOptionsImpl::Add(OrtCustomOpDomain* custom_op_domain) { - ThrowOnError(GetApi().AddCustomOpDomain(this->p_, custom_op_domain)); - return *this; +inline OrtProfilingEventCategory ConstProfilingEventImpl::GetCategory() const { + OrtProfilingEventCategory out{}; + ThrowOnError(GetEpApi().ProfilingEvent_GetCategory(this->p_, &out)); + return out; } template -inline SessionOptionsImpl& SessionOptionsImpl::AddConfigEntry(const char* config_key, const char* config_value) { - ThrowOnError(GetApi().AddSessionConfigEntry(this->p_, config_key, config_value)); - return *this; +inline const char* ConstProfilingEventImpl::GetName() const { + const char* name = nullptr; + ThrowOnError(GetEpApi().ProfilingEvent_GetName(this->p_, &name)); + return name; } template -inline SessionOptionsImpl& SessionOptionsImpl::AddInitializer(const char* name, const OrtValue* ort_val) { - ThrowOnError(GetApi().AddInitializer(this->p_, name, ort_val)); - return *this; +inline int64_t ConstProfilingEventImpl::GetTimestampUs() const { + int64_t out = 0; + ThrowOnError(GetEpApi().ProfilingEvent_GetTimestampUs(this->p_, &out)); + return out; } template -inline SessionOptionsImpl& SessionOptionsImpl::DisablePerSessionThreads() { - ThrowOnError(GetApi().DisablePerSessionThreads(this->p_)); - return *this; +inline int64_t ConstProfilingEventImpl::GetDurationUs() const { + int64_t out = 0; + ThrowOnError(GetEpApi().ProfilingEvent_GetDurationUs(this->p_, &out)); + return out; } template -inline SessionOptionsImpl& SessionOptionsImpl::AddExternalInitializers(const std::vector& names, - const std::vector& ort_values) { - const size_t inputs_num = names.size(); - if (inputs_num != ort_values.size()) { - ORT_CXX_API_THROW("Expecting names and ort_values to have the same length", ORT_INVALID_ARGUMENT); - } - std::vector names_ptr; - std::vector ort_values_ptrs; - names_ptr.reserve(inputs_num); - ort_values_ptrs.reserve(inputs_num); - for (size_t i = 0; i < inputs_num; ++i) { - names_ptr.push_back(names[i].c_str()); - ort_values_ptrs.push_back(ort_values[i]); - } - ThrowOnError(GetApi().AddExternalInitializers(this->p_, names_ptr.data(), ort_values_ptrs.data(), inputs_num)); - return *this; +inline const char* ConstProfilingEventImpl::GetArgValue(const char* key) const { + const char* value = nullptr; + ThrowOnError(GetEpApi().ProfilingEvent_GetArgValue(this->p_, key, &value)); + return value; } +} // namespace detail -template -inline SessionOptionsImpl& SessionOptionsImpl::AddExternalInitializersFromFilesInMemory(const std::vector>& file_names, - const std::vector& buffer_array, - const std::vector& file_lengths) { - const size_t inputs_num = file_names.size(); - if (inputs_num != buffer_array.size()) { - ORT_CXX_API_THROW("Expecting names and buffer_array to have the same length", ORT_INVALID_ARGUMENT); - } - if (inputs_num != file_lengths.size()) { - ORT_CXX_API_THROW("Expecting names and file_lengths to have the same length", ORT_INVALID_ARGUMENT); - } - std::vector names_ptr; - names_ptr.reserve(inputs_num); - for (size_t i = 0; i < inputs_num; ++i) { - names_ptr.push_back(file_names[i].c_str()); +inline ProfilingEvent::ProfilingEvent(OrtProfilingEventCategory category, + int32_t process_id, + int32_t thread_id, + const char* event_name, + int64_t timestamp_us, + int64_t duration_us, + const std::unordered_map& args) { + const size_t num_args = args.size(); + std::vector arg_keys; + std::vector arg_vals; + + arg_keys.reserve(num_args); + arg_vals.reserve(num_args); + for (const auto& [k, v] : args) { + arg_keys.push_back(k.c_str()); + arg_vals.push_back(v.c_str()); } - ThrowOnError(GetApi().AddExternalInitializersFromFilesInMemory(this->p_, names_ptr.data(), buffer_array.data(), - file_lengths.data(), inputs_num)); - return *this; + + ThrowOnError(GetEpApi().CreateProfilingEvent(category, process_id, thread_id, event_name, + timestamp_us, duration_us, + arg_keys.data(), arg_vals.data(), num_args, &p_)); } -template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_CUDA(const OrtCUDAProviderOptions& provider_options) { - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_CUDA(this->p_, &provider_options)); - return *this; +inline ProfilingEvent::ProfilingEvent(OrtProfilingEventCategory category, + int32_t process_id, + int32_t thread_id, + const char* event_name, + int64_t timestamp_us, + int64_t duration_us, + const char* const* arg_keys, + const char* const* arg_values, + size_t num_args) { + ThrowOnError(GetEpApi().CreateProfilingEvent(category, process_id, thread_id, event_name, + timestamp_us, duration_us, + arg_keys, arg_values, num_args, &p_)); } +// ProfilingEventsContainer implementations +namespace detail { template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_CUDA_V2(const OrtCUDAProviderOptionsV2& provider_options) { - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_CUDA_V2(this->p_, &provider_options)); - return *this; +inline Status ProfilingEventsContainerImpl::AddEvents(const OrtProfilingEvent* const* events, size_t num_events) { + return Status{GetEpApi().ProfilingEventsContainer_AddEvents(this->p_, events, num_events)}; } template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_ROCM(const OrtROCMProviderOptions& provider_options) { - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_ROCM(this->p_, &provider_options)); - return *this; +inline Status ProfilingEventsContainerImpl::AddEvents(const std::vector& events) { + static_assert(sizeof(ProfilingEvent) == sizeof(OrtProfilingEvent*) && + alignof(ProfilingEvent) == alignof(OrtProfilingEvent*), + "ProfilingEvent must have the same size and alignment as a raw pointer for reinterpret_cast"); + const auto* event_ptrs = reinterpret_cast(events.data()); + return AddEvents(event_ptrs, events.size()); } +} // namespace detail -template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_TensorRT(const OrtTensorRTProviderOptions& provider_options) { - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_TensorRT(this->p_, &provider_options)); - return *this; +inline Env::Env(OrtLoggingLevel logging_level, _In_ const char* logid) { + ThrowOnError(GetApi().CreateEnv(logging_level, logid, &p_)); + if (strcmp(logid, "onnxruntime-node") == 0) { + ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_NODEJS)); + } else { + ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_CPLUSPLUS)); + } } -template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_TensorRT_V2(const OrtTensorRTProviderOptionsV2& provider_options) { - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_TensorRT_V2(this->p_, &provider_options)); +inline Env::Env(OrtLoggingLevel logging_level, const char* logid, OrtLoggingFunction logging_function, void* logger_param) { + ThrowOnError(GetApi().CreateEnvWithCustomLogger(logging_function, logger_param, logging_level, logid, &p_)); + if (strcmp(logid, "onnxruntime-node") == 0) { + ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_NODEJS)); + } else { + ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_CPLUSPLUS)); + } +} + +inline Env::Env(const OrtThreadingOptions* tp_options, OrtLoggingLevel logging_level, _In_ const char* logid) { + ThrowOnError(GetApi().CreateEnvWithGlobalThreadPools(logging_level, logid, tp_options, &p_)); + if (strcmp(logid, "onnxruntime-node") == 0) { + ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_NODEJS)); + } else { + ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_CPLUSPLUS)); + } +} + +inline Env::Env(const OrtThreadingOptions* tp_options, OrtLoggingFunction logging_function, void* logger_param, + OrtLoggingLevel logging_level, _In_ const char* logid) { + ThrowOnError(GetApi().CreateEnvWithCustomLoggerAndGlobalThreadPools(logging_function, logger_param, logging_level, logid, tp_options, &p_)); + if (strcmp(logid, "onnxruntime-node") == 0) { + ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_NODEJS)); + } else { + ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_CPLUSPLUS)); + } +} + +inline Env::Env(const OrtEnvCreationOptions* options) { + ThrowOnError(GetApi().CreateEnvWithOptions(options, &p_)); + if (strcmp(options->log_id, "onnxruntime-node") == 0) { + ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_NODEJS)); + } else { + ThrowOnError(GetApi().SetLanguageProjection(p_, OrtLanguageProjection::ORT_PROJECTION_CPLUSPLUS)); + } +} + +inline Env& Env::EnableTelemetryEvents() { + ThrowOnError(GetApi().EnableTelemetryEvents(p_)); return *this; } -template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_MIGraphX(const OrtMIGraphXProviderOptions& provider_options) { - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_MIGraphX(this->p_, &provider_options)); +inline Env& Env::DisableTelemetryEvents() { + ThrowOnError(GetApi().DisableTelemetryEvents(p_)); return *this; } -template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_CANN(const OrtCANNProviderOptions& provider_options) { - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_CANN(this->p_, &provider_options)); +inline Env& Env::UpdateEnvWithCustomLogLevel(OrtLoggingLevel log_severity_level) { + ThrowOnError(GetApi().UpdateEnvWithCustomLogLevel(p_, log_severity_level)); return *this; } -template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_Dnnl(const OrtDnnlProviderOptions& provider_options) { - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_Dnnl(this->p_, &provider_options)); +inline Env& Env::CreateAndRegisterAllocator(const OrtMemoryInfo* mem_info, const OrtArenaCfg* arena_cfg) { + ThrowOnError(GetApi().CreateAndRegisterAllocator(p_, mem_info, arena_cfg)); return *this; } -template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider( - const std::string& provider_name, - const std::unordered_map& provider_options) { - auto num_entries = provider_options.size(); +inline Env& Env::CreateAndRegisterAllocatorV2(const std::string& provider_type, const OrtMemoryInfo* mem_info, const std::unordered_map& options, const OrtArenaCfg* arena_cfg) { std::vector keys, values; + auto num_entries = options.size(); if (num_entries > 0) { keys.reserve(num_entries); values.reserve(num_entries); - - for (const auto& entry : provider_options) { + for (const auto& entry : options) { keys.push_back(entry.first.c_str()); values.push_back(entry.second.c_str()); } } + ThrowOnError(GetApi().CreateAndRegisterAllocatorV2(p_, provider_type.c_str(), mem_info, arena_cfg, keys.data(), values.data(), num_entries)); + return *this; +} - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider(this->p_, provider_name.c_str(), - keys.data(), values.data(), num_entries)); - +inline Env& Env::RegisterAllocator(OrtAllocator* allocator) { + ThrowOnError(GetApi().RegisterAllocator(p_, allocator)); return *this; } -template -inline SessionOptionsImpl& SessionOptionsImpl::SetCustomCreateThreadFn(OrtCustomCreateThreadFn ort_custom_create_thread_fn) { - ThrowOnError(GetApi().SessionOptionsSetCustomCreateThreadFn(this->p_, ort_custom_create_thread_fn)); +inline Env& Env::UnregisterAllocator(const OrtMemoryInfo* mem_info) { + ThrowOnError(GetApi().UnregisterAllocator(p_, mem_info)); return *this; } -template -inline SessionOptionsImpl& SessionOptionsImpl::SetCustomThreadCreationOptions(void* ort_custom_thread_creation_options) { - ThrowOnError(GetApi().SessionOptionsSetCustomThreadCreationOptions(this->p_, ort_custom_thread_creation_options)); +inline Env& Env::RegisterExecutionProviderLibrary(const char* registration_name, + const std::basic_string& path) { + ThrowOnError(GetApi().RegisterExecutionProviderLibrary(p_, registration_name, path.c_str())); return *this; } -template -inline SessionOptionsImpl& SessionOptionsImpl::SetCustomJoinThreadFn(OrtCustomJoinThreadFn ort_custom_join_thread_fn) { - ThrowOnError(GetApi().SessionOptionsSetCustomJoinThreadFn(this->p_, ort_custom_join_thread_fn)); +inline Env& Env::UnregisterExecutionProviderLibrary(const char* registration_name) { + ThrowOnError(GetApi().UnregisterExecutionProviderLibrary(p_, registration_name)); return *this; } -template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_OpenVINO(const OrtOpenVINOProviderOptions& provider_options) { - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_OpenVINO(this->p_, &provider_options)); +inline Env& Env::SetPerSessionThreadPoolCallbacks(const OrtThreadPoolCallbacksConfig& config) { + ThrowOnError(GetApi().SetPerSessionThreadPoolCallbacks(p_, &config)); return *this; } -template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_OpenVINO_V2(const std::unordered_map& provider_options) { - auto num_entries = provider_options.size(); - std::vector keys, values; - if (num_entries > 0) { - keys.reserve(num_entries); - values.reserve(num_entries); +inline std::vector Env::GetEpDevices() const { + size_t num_devices = 0; + const OrtEpDevice* const* device_ptrs = nullptr; + ThrowOnError(GetApi().GetEpDevices(p_, &device_ptrs, &num_devices)); - for (const auto& entry : provider_options) { - keys.push_back(entry.first.c_str()); - values.push_back(entry.second.c_str()); + std::vector devices; + if (num_devices > 0) { + devices.reserve(num_devices); + for (size_t i = 0; i < num_devices; ++i) { + devices.emplace_back(device_ptrs[i]); } } - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_OpenVINO_V2(this->p_, - keys.data(), values.data(), num_entries)); + return devices; +} - return *this; +inline size_t Env::GetNumHardwareDevices() const { + size_t num_devices = 0; + ThrowOnError(GetApi().GetNumHardwareDevices(p_, &num_devices)); + return num_devices; } -template -inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_VitisAI(const std::unordered_map& provider_options) { - auto num_entries = provider_options.size(); - std::vector keys, values; - if (num_entries > 0) { - keys.reserve(num_entries); - values.reserve(num_entries); +inline std::vector Env::GetHardwareDevices() const { + size_t num_devices = 0; + ThrowOnError(GetApi().GetNumHardwareDevices(p_, &num_devices)); - for (const auto& entry : provider_options) { - keys.push_back(entry.first.c_str()); - values.push_back(entry.second.c_str()); + std::vector devices; + if (num_devices > 0) { + std::vector device_ptrs(num_devices); + ThrowOnError(GetApi().GetHardwareDevices(p_, device_ptrs.data(), num_devices)); + devices.reserve(num_devices); + for (size_t i = 0; i < num_devices; ++i) { + devices.emplace_back(device_ptrs[i]); } } - ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_VitisAI(this->p_, keys.data(), values.data(), num_entries)); + return devices; +} - return *this; +inline DeviceEpIncompatibilityDetails Env::GetHardwareDeviceEpIncompatibilityDetails( + const char* ep_name, ConstHardwareDevice hw) const { + OrtDeviceEpIncompatibilityDetails* details = nullptr; + ThrowOnError(GetApi().GetHardwareDeviceEpIncompatibilityDetails(p_, ep_name, hw, &details)); + return DeviceEpIncompatibilityDetails{details}; } template -inline SessionOptionsImpl& SessionOptionsImpl::RegisterCustomOpsLibrary(const ORTCHAR_T* library_name, - const CustomOpConfigs& custom_op_configs) { - // Add custom op config entries before registering the custom op library. Otherwise, the config entries _may_ be ignored by - // the custom op library. - for (const auto& config_iter : custom_op_configs.GetFlattenedConfigs()) { - AddConfigEntry(config_iter.first.c_str(), config_iter.second.c_str()); - } - - ThrowOnError(GetApi().RegisterCustomOpsLibrary_V2(this->p_, library_name)); - return *this; +inline uint32_t detail::DeviceEpIncompatibilityDetailsImpl::GetReasonsBitmask() const { + uint32_t reasons_bitmask = 0; + ThrowOnError(GetApi().DeviceEpIncompatibilityDetails_GetReasonsBitmask(this->p_, &reasons_bitmask)); + return reasons_bitmask; } template -inline SessionOptionsImpl& SessionOptionsImpl::RegisterCustomOpsUsingFunction(const char* registration_function_name) { - ThrowOnError(GetApi().RegisterCustomOpsUsingFunction(this->p_, registration_function_name)); - return *this; +inline const char* detail::DeviceEpIncompatibilityDetailsImpl::GetNotes() const { + const char* notes = nullptr; + ThrowOnError(GetApi().DeviceEpIncompatibilityDetails_GetNotes(this->p_, ¬es)); + return notes; } -/// Session template -inline size_t ConstSessionImpl::GetInputCount() const { - size_t out; - ThrowOnError(GetApi().SessionGetInputCount(this->p_, &out)); - return out; +inline int32_t detail::DeviceEpIncompatibilityDetailsImpl::GetErrorCode() const { + int32_t error_code = 0; + ThrowOnError(GetApi().DeviceEpIncompatibilityDetails_GetErrorCode(this->p_, &error_code)); + return error_code; } -template -inline size_t ConstSessionImpl::GetOutputCount() const { - size_t out; - ThrowOnError(GetApi().SessionGetOutputCount(this->p_, &out)); - return out; +inline Status Env::CopyTensors(const std::vector& src_tensors, + const std::vector& dst_tensors, + OrtSyncStream* stream) const { + if (src_tensors.size() != dst_tensors.size()) { + return Status("Source and destination tensor vectors must have the same size", ORT_INVALID_ARGUMENT); + } + if (src_tensors.empty()) { + return Status(nullptr); + } + + const OrtValue* const* src_tensors_ptr = reinterpret_cast(src_tensors.data()); + OrtValue* const* dst_tensors_ptr = reinterpret_cast(dst_tensors.data()); + OrtStatus* status = GetApi().CopyTensors(p_, src_tensors_ptr, dst_tensors_ptr, stream, src_tensors.size()); + return Status(status); } -template -inline size_t ConstSessionImpl::GetOverridableInitializerCount() const { - size_t out; - ThrowOnError(GetApi().SessionGetOverridableInitializerCount(this->p_, &out)); - return out; +inline Status Env::CopyTensor(const OrtValue* src_tensor, OrtValue* dst_tensor, OrtSyncStream* stream) const { + OrtStatus* status = GetApi().CopyTensors(p_, &src_tensor, &dst_tensor, stream, 1); + return Status(status); } -template -inline AllocatedStringPtr ConstSessionImpl::GetInputNameAllocated(size_t index, OrtAllocator* allocator) const { - char* out; - ThrowOnError(GetApi().SessionGetInputName(this->p_, index, allocator, &out)); - return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +inline UnownedAllocator Env::CreateSharedAllocator(const OrtEpDevice* ep_device, OrtDeviceMemoryType mem_type, + OrtAllocatorType allocator_type, + const OrtKeyValuePairs* allocator_options) { + OrtAllocator* p; + ThrowOnError(GetApi().CreateSharedAllocator(p_, ep_device, mem_type, allocator_type, allocator_options, &p)); + return UnownedAllocator{p}; } -template -inline AllocatedStringPtr ConstSessionImpl::GetOutputNameAllocated(size_t index, OrtAllocator* allocator) const { - char* out; - ThrowOnError(GetApi().SessionGetOutputName(this->p_, index, allocator, &out)); - return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +inline UnownedAllocator Env::GetSharedAllocator(const OrtMemoryInfo* mem_info) { + OrtAllocator* p; + ThrowOnError(GetApi().GetSharedAllocator(p_, mem_info, &p)); + return UnownedAllocator{p}; } -template -inline AllocatedStringPtr ConstSessionImpl::GetOverridableInitializerNameAllocated(size_t index, OrtAllocator* allocator) const { - char* out; - ThrowOnError(GetApi().SessionGetOverridableInitializerName(this->p_, index, allocator, &out)); - return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +inline void Env::ReleaseSharedAllocator(const OrtEpDevice* ep_device, + OrtDeviceMemoryType mem_type) { + ThrowOnError(GetApi().ReleaseSharedAllocator(p_, ep_device, mem_type)); } -template -inline uint64_t ConstSessionImpl::GetProfilingStartTimeNs() const { - uint64_t out; - ThrowOnError(GetApi().SessionGetProfilingStartTimeNs(this->p_, &out)); - return out; +inline CustomOpDomain::CustomOpDomain(const char* domain) { + ThrowOnError(GetApi().CreateCustomOpDomain(domain, &p_)); } -template -inline ModelMetadata ConstSessionImpl::GetModelMetadata() const { - OrtModelMetadata* out; - ThrowOnError(GetApi().SessionGetModelMetadata(this->p_, &out)); - return ModelMetadata{out}; +inline void CustomOpDomain::Add(const OrtCustomOp* op) { + ThrowOnError(GetApi().CustomOpDomain_Add(p_, op)); } -template -inline TypeInfo ConstSessionImpl::GetInputTypeInfo(size_t index) const { - OrtTypeInfo* out; - ThrowOnError(GetApi().SessionGetInputTypeInfo(this->p_, index, &out)); - return TypeInfo{out}; +inline OrtCompiledModelCompatibility GetModelCompatibilityForEpDevices( + const std::vector& ep_devices, + const char* compatibility_info) { + if (ep_devices.empty()) { + ORT_CXX_API_THROW("ep_devices is empty", ORT_INVALID_ARGUMENT); + } + + std::vector ptrs; + ptrs.reserve(ep_devices.size()); + for (const auto& d : ep_devices) ptrs.push_back(d); + + OrtCompiledModelCompatibility status = OrtCompiledModelCompatibility_EP_NOT_APPLICABLE; + ThrowOnError(GetApi().GetModelCompatibilityForEpDevices( + reinterpret_cast(ptrs.data()), + ptrs.size(), + compatibility_info, + &status)); + return status; } -template -inline TypeInfo ConstSessionImpl::GetOutputTypeInfo(size_t index) const { - OrtTypeInfo* out; - ThrowOnError(GetApi().SessionGetOutputTypeInfo(this->p_, index, &out)); - return TypeInfo{out}; +inline AllocatedStringPtr GetCompatibilityInfoFromModelAllocated(const ORTCHAR_T* model_path, const char* ep_type, + OrtAllocator* allocator) { + char* compat_info = nullptr; + ThrowOnError(GetApi().GetCompatibilityInfoFromModel(model_path, ep_type, allocator, &compat_info)); + return AllocatedStringPtr(compat_info, detail::AllocatedFree(allocator)); } -template -inline TypeInfo ConstSessionImpl::GetOverridableInitializerTypeInfo(size_t index) const { - OrtTypeInfo* out; - ThrowOnError(GetApi().SessionGetOverridableInitializerTypeInfo(this->p_, index, &out)); - return TypeInfo{out}; +inline AllocatedStringPtr GetCompatibilityInfoFromModelBytesAllocated(const void* model_data, size_t model_data_length, + const char* ep_type, OrtAllocator* allocator) { + char* compat_info = nullptr; + ThrowOnError(GetApi().GetCompatibilityInfoFromModelBytes(model_data, model_data_length, ep_type, allocator, &compat_info)); + return AllocatedStringPtr(compat_info, detail::AllocatedFree(allocator)); } -template -inline std::vector SessionImpl::Run(const RunOptions& run_options, const char* const* input_names, const Value* input_values, size_t input_count, - const char* const* output_names, size_t output_count) { - std::vector output_values; - output_values.reserve(output_count); - for (size_t i = 0; i < output_count; i++) - output_values.emplace_back(nullptr); - Run(run_options, input_names, input_values, input_count, output_names, output_values.data(), output_count); - return output_values; +inline LoraAdapter LoraAdapter::CreateLoraAdapter(const std::basic_string& adapter_path, + OrtAllocator* allocator) { + OrtLoraAdapter* p; + ThrowOnError(GetApi().CreateLoraAdapter(adapter_path.c_str(), allocator, &p)); + return LoraAdapter{p}; } -template -inline void SessionImpl::Run(const RunOptions& run_options, const char* const* input_names, const Value* input_values, size_t input_count, - const char* const* output_names, Value* output_values, size_t output_count) { - static_assert(sizeof(Value) == sizeof(OrtValue*), "Value is really just an array of OrtValue* in memory, so we can reinterpret_cast safely"); - auto ort_input_values = reinterpret_cast(input_values); - auto ort_output_values = reinterpret_cast(output_values); - ThrowOnError(GetApi().Run(this->p_, run_options, input_names, ort_input_values, input_count, output_names, output_count, ort_output_values)); +inline LoraAdapter LoraAdapter::CreateLoraAdapterFromArray(const void* bytes, size_t num_bytes, + OrtAllocator* allocator) { + OrtLoraAdapter* p; + ThrowOnError(GetApi().CreateLoraAdapterFromArray(bytes, num_bytes, allocator, &p)); + return LoraAdapter{p}; } -template -inline void SessionImpl::Run(const RunOptions& run_options, const IoBinding& io_binding) { - ThrowOnError(GetApi().RunWithBinding(this->p_, run_options, io_binding)); +inline RunOptions::RunOptions() { + ThrowOnError(GetApi().CreateRunOptions(&p_)); } -template -inline void SessionImpl::RunAsync(const RunOptions& run_options, const char* const* input_names, const Value* input_values, size_t input_count, - const char* const* output_names, Value* output_values, size_t output_count, RunAsyncCallbackFn callback, void* user_data) { - auto ort_input_values = reinterpret_cast(input_values); - auto ort_output_values = reinterpret_cast(output_values); - ThrowOnError(GetApi().RunAsync(this->p_, run_options, input_names, - ort_input_values, input_count, output_names, output_count, - ort_output_values, callback, user_data)); +inline RunOptions& RunOptions::SetRunLogVerbosityLevel(int level) { + ThrowOnError(GetApi().RunOptionsSetRunLogVerbosityLevel(p_, level)); + return *this; } -template -inline AllocatedStringPtr SessionImpl::EndProfilingAllocated(OrtAllocator* allocator) { - char* out = nullptr; - ThrowOnError(GetApi().SessionEndProfiling(this->p_, allocator, &out)); - return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +inline RunOptions& RunOptions::SetRunLogSeverityLevel(int level) { + ThrowOnError(GetApi().RunOptionsSetRunLogSeverityLevel(p_, level)); + return *this; } -template -inline void SessionImpl::SetEpDynamicOptions(const char* const* keys, const char* const* values, size_t kv_len) { - ThrowOnError(GetApi().SetEpDynamicOptions(this->p_, keys, values, kv_len)); +inline int RunOptions::GetRunLogVerbosityLevel() const { + int out; + ThrowOnError(GetApi().RunOptionsGetRunLogVerbosityLevel(p_, &out)); + return out; } -} // namespace detail +inline int RunOptions::GetRunLogSeverityLevel() const { + int out; + ThrowOnError(GetApi().RunOptionsGetRunLogSeverityLevel(p_, &out)); + return out; +} -inline SessionOptions::SessionOptions() { - ThrowOnError(GetApi().CreateSessionOptions(&this->p_)); +inline RunOptions& RunOptions::SetRunTag(const char* run_tag) { + ThrowOnError(GetApi().RunOptionsSetRunTag(p_, run_tag)); + return *this; } -/// CustomOpConfigs -inline std::string detail::MakeCustomOpConfigEntryKey(const char* custom_op_name, const char* config) { - std::string config_key = "custom_op."; +inline const char* RunOptions::GetRunTag() const { + const char* out; + ThrowOnError(GetApi().RunOptionsGetRunTag(p_, &out)); + return out; +} - config_key += custom_op_name; - config_key += "."; - config_key += config; +inline RunOptions& RunOptions::AddConfigEntry(const char* config_key, const char* config_value) { + ThrowOnError(GetApi().AddRunConfigEntry(p_, config_key, config_value)); + return *this; +} - return config_key; +inline const char* RunOptions::GetConfigEntry(const char* config_key) { + return GetApi().GetRunConfigEntry(p_, config_key); } -inline CustomOpConfigs& CustomOpConfigs::AddConfig(const char* custom_op_name, const char* config_key, const char* config_value) { - const std::string full_flat_key = detail::MakeCustomOpConfigEntryKey(custom_op_name, config_key); - flat_configs_[full_flat_key] = config_value; +inline RunOptions& RunOptions::SetTerminate() { + ThrowOnError(GetApi().RunOptionsSetTerminate(p_)); return *this; } -inline const std::unordered_map& CustomOpConfigs::GetFlattenedConfigs() const { - return flat_configs_; +inline RunOptions& RunOptions::UnsetTerminate() { + ThrowOnError(GetApi().RunOptionsUnsetTerminate(p_)); + return *this; } -inline Session::Session(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options) { - ThrowOnError(GetApi().CreateSession(env, model_path, options, &this->p_)); +inline RunOptions& RunOptions::AddActiveLoraAdapter(const LoraAdapter& adapter) { + ThrowOnError(GetApi().RunOptionsAddActiveLoraAdapter(p_, adapter)); + return *this; } -inline Session::Session(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options, - OrtPrepackedWeightsContainer* prepacked_weights_container) { - ThrowOnError(GetApi().CreateSessionWithPrepackedWeightsContainer(env, model_path, options, prepacked_weights_container, &this->p_)); +inline RunOptions& RunOptions::SetSyncStream(OrtSyncStream* stream) { + GetApi().RunOptionsSetSyncStream(p_, stream); + return *this; } -inline Session::Session(const Env& env, const void* model_data, size_t model_data_length, const SessionOptions& options) { - ThrowOnError(GetApi().CreateSessionFromArray(env, model_data, model_data_length, options, &this->p_)); +inline RunOptions& RunOptions::EnableProfiling(const ORTCHAR_T* profile_file_prefix) { + ThrowOnError(GetApi().RunOptionsEnableProfiling(p_, profile_file_prefix)); + return *this; } -inline Session::Session(const Env& env, const void* model_data, size_t model_data_length, - const SessionOptions& options, OrtPrepackedWeightsContainer* prepacked_weights_container) { - ThrowOnError(GetApi().CreateSessionFromArrayWithPrepackedWeightsContainer(env, model_data, model_data_length, options, - prepacked_weights_container, &this->p_)); +inline RunOptions& RunOptions::DisableProfiling() { + ThrowOnError(GetApi().RunOptionsDisableProfiling(p_)); + return *this; } -inline AllocatedStringPtr ModelMetadata::GetProducerNameAllocated(OrtAllocator* allocator) const { - char* out; - ThrowOnError(GetApi().ModelMetadataGetProducerName(p_, allocator, &out)); - return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +inline ModelCompilationOptions::ModelCompilationOptions(const Env& env, const SessionOptions& session_options) { + ThrowOnError(GetCompileApi().CreateModelCompilationOptionsFromSessionOptions(env, session_options, &this->p_)); } -inline AllocatedStringPtr ModelMetadata::GetGraphNameAllocated(OrtAllocator* allocator) const { - char* out; - ThrowOnError(GetApi().ModelMetadataGetGraphName(p_, allocator, &out)); - return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +inline ModelCompilationOptions::ModelCompilationOptions(const Env& env, ConstSessionOptions session_options) { + ThrowOnError(GetCompileApi().CreateModelCompilationOptionsFromSessionOptions(env, session_options, &this->p_)); } -inline AllocatedStringPtr ModelMetadata::GetDomainAllocated(OrtAllocator* allocator) const { - char* out; - ThrowOnError(GetApi().ModelMetadataGetDomain(p_, allocator, &out)); - return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +inline Status CompileModel(const Env& env, const ModelCompilationOptions& model_compilation_options) { + return Ort::Status(GetCompileApi().CompileModel(env, model_compilation_options)); } -inline AllocatedStringPtr Ort::ModelMetadata::GetDescriptionAllocated(OrtAllocator* allocator) const { - char* out; - ThrowOnError(GetApi().ModelMetadataGetDescription(p_, allocator, &out)); - return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +inline ModelCompilationOptions& ModelCompilationOptions::SetInputModelPath( + const ORTCHAR_T* input_model_path) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetInputModelPath(this->p_, input_model_path)); + return *this; } -inline AllocatedStringPtr ModelMetadata::GetGraphDescriptionAllocated(OrtAllocator* allocator) const { - char* out; - ThrowOnError(GetApi().ModelMetadataGetGraphDescription(p_, allocator, &out)); - return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +inline ModelCompilationOptions& ModelCompilationOptions::SetInputModelFromBuffer( + const void* input_model_data, size_t input_model_data_size) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetInputModelFromBuffer(this->p_, input_model_data, + input_model_data_size)); + return *this; } -inline AllocatedStringPtr ModelMetadata::LookupCustomMetadataMapAllocated(const char* key, OrtAllocator* allocator) const { - char* out; - ThrowOnError(GetApi().ModelMetadataLookupCustomMetadataMap(p_, allocator, key, &out)); - return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +inline ModelCompilationOptions& ModelCompilationOptions::SetOutputModelPath( + const ORTCHAR_T* output_model_path) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetOutputModelPath(this->p_, output_model_path)); + return *this; } -inline std::vector ModelMetadata::GetCustomMetadataMapKeysAllocated(OrtAllocator* allocator) const { - auto deletor = detail::AllocatedFree(allocator); - std::vector result; - - char** out = nullptr; - int64_t num_keys = 0; - ThrowOnError(GetApi().ModelMetadataGetCustomMetadataMapKeys(p_, allocator, &out, &num_keys)); - if (num_keys <= 0) { - return result; - } +inline ModelCompilationOptions& ModelCompilationOptions::SetEpContextBinaryInformation( + const ORTCHAR_T* output_directory, const ORTCHAR_T* model_name) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetEpContextBinaryInformation( + this->p_, + output_directory, + model_name)); + return *this; +} - // array of pointers will be freed - std::unique_ptr array_guard(out, deletor); - // reserve may throw - auto strings_deletor = [&deletor, num_keys](char** out) { for(int64_t i = 0; i < num_keys; ++i) deletor(out[i]); }; - std::unique_ptr strings_guard(out, strings_deletor); - result.reserve(static_cast(num_keys)); - strings_guard.release(); - for (int64_t i = 0; i < num_keys; ++i) { - result.push_back(AllocatedStringPtr(out[i], deletor)); - } +inline ModelCompilationOptions& ModelCompilationOptions::SetOutputModelExternalInitializersFile( + const ORTCHAR_T* file_path, size_t initializer_size_threshold) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetOutputModelExternalInitializersFile( + this->p_, + file_path, + initializer_size_threshold)); + return *this; +} - return result; +inline ModelCompilationOptions& +ModelCompilationOptions::SetOutputModelGetInitializerLocationFunc( + OrtGetInitializerLocationFunc get_initializer_location_func, void* state) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetOutputModelGetInitializerLocationFunc( + this->p_, + get_initializer_location_func, + state)); + return *this; } -inline int64_t ModelMetadata::GetVersion() const { - int64_t out; - ThrowOnError(GetApi().ModelMetadataGetVersion(p_, &out)); - return out; +inline ModelCompilationOptions& ModelCompilationOptions::SetOutputModelBuffer( + OrtAllocator* allocator, void** output_model_buffer_ptr, size_t* output_model_buffer_size_ptr) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetOutputModelBuffer(this->p_, allocator, + output_model_buffer_ptr, + output_model_buffer_size_ptr)); + return *this; } -namespace detail { +inline ModelCompilationOptions& ModelCompilationOptions::SetOutputModelWriteFunc(OrtWriteBufferFunc write_func, + void* state) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetOutputModelWriteFunc(this->p_, write_func, state)); + return *this; +} -template -inline ONNXTensorElementDataType TensorTypeAndShapeInfoImpl::GetElementType() const { - ONNXTensorElementDataType out; - ThrowOnError(GetApi().GetTensorElementType(this->p_, &out)); - return out; +inline ModelCompilationOptions& ModelCompilationOptions::SetEpContextEmbedMode( + bool embed_ep_context_in_model) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetEpContextEmbedMode( + this->p_, + embed_ep_context_in_model)); + return *this; } -template -inline size_t TensorTypeAndShapeInfoImpl::GetElementCount() const { - size_t out; - ThrowOnError(GetApi().GetTensorShapeElementCount(this->p_, &out)); - return static_cast(out); +inline ModelCompilationOptions& ModelCompilationOptions::SetFlags(uint32_t flags) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetFlags(this->p_, flags)); + return *this; } -template -inline size_t TensorTypeAndShapeInfoImpl::GetDimensionsCount() const { - size_t out; - ThrowOnError(GetApi().GetDimensionsCount(this->p_, &out)); - return out; +inline ModelCompilationOptions& ModelCompilationOptions::SetGraphOptimizationLevel( + GraphOptimizationLevel graph_optimization_level) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetGraphOptimizationLevel(this->p_, + graph_optimization_level)); + return *this; } -template -inline void TensorTypeAndShapeInfoImpl::GetDimensions(int64_t* values, size_t values_count) const { - ThrowOnError(GetApi().GetDimensions(this->p_, values, values_count)); +inline ModelCompilationOptions& ModelCompilationOptions::SetInputModel(const OrtModel* model) { + Ort::ThrowOnError(GetCompileApi().ModelCompilationOptions_SetInputModel(this->p_, model)); + return *this; } +namespace detail { + template -inline void TensorTypeAndShapeInfoImpl::GetSymbolicDimensions(const char** values, size_t values_count) const { - ThrowOnError(GetApi().GetSymbolicDimensions(this->p_, values, values_count)); +inline Ort::SessionOptions ConstSessionOptionsImpl::Clone() const { + OrtSessionOptions* out; + ThrowOnError(GetApi().CloneSessionOptions(this->p_, &out)); + return SessionOptions{out}; } template -inline std::vector TensorTypeAndShapeInfoImpl::GetShape() const { - std::vector out(GetDimensionsCount(), 0); - ThrowOnError(GetApi().GetDimensions(this->p_, out.data(), out.size())); +inline std::string ConstSessionOptionsImpl::GetConfigEntry(const char* config_key) const { + size_t size = 0; + // Feed nullptr for the data buffer to query the true size of the string value + Ort::ThrowOnError(GetApi().GetSessionConfigEntry(this->p_, config_key, nullptr, &size)); + + std::string out; + out.resize(size); + Ort::ThrowOnError(GetApi().GetSessionConfigEntry(this->p_, config_key, &out[0], &size)); + out.resize(size - 1); // remove the terminating character '\0' + return out; } template -inline ConstTensorTypeAndShapeInfo TypeInfoImpl::GetTensorTypeAndShapeInfo() const { - const OrtTensorTypeAndShapeInfo* out; - ThrowOnError(GetApi().CastTypeInfoToTensorInfo(this->p_, &out)); - return ConstTensorTypeAndShapeInfo{out}; +inline bool ConstSessionOptionsImpl::HasConfigEntry(const char* config_key) const { + int out = 0; + Ort::ThrowOnError(GetApi().HasSessionConfigEntry(this->p_, config_key, &out)); + return static_cast(out); } template -inline ConstSequenceTypeInfo TypeInfoImpl::GetSequenceTypeInfo() const { - const OrtSequenceTypeInfo* out; - ThrowOnError(GetApi().CastTypeInfoToSequenceTypeInfo(this->p_, &out)); - return ConstSequenceTypeInfo{out}; +inline std::string ConstSessionOptionsImpl::GetConfigEntryOrDefault(const char* config_key, + const std::string& def) const { + if (!this->HasConfigEntry(config_key)) { + return def; + } + + return this->GetConfigEntry(config_key); } template -inline ConstMapTypeInfo TypeInfoImpl::GetMapTypeInfo() const { - const OrtMapTypeInfo* out; - ThrowOnError(GetApi().CastTypeInfoToMapTypeInfo(this->p_, &out)); - return ConstMapTypeInfo{out}; +inline bool ConstSessionOptionsImpl::GetMemPatternEnabled() const { + int out = 0; + ThrowOnError(GetApi().GetMemPatternEnabled(this->p_, &out)); + return out != 0; } template -inline ONNXType TypeInfoImpl::GetONNXType() const { - ONNXType out; - ThrowOnError(GetApi().GetOnnxTypeFromTypeInfo(this->p_, &out)); +inline ExecutionMode ConstSessionOptionsImpl::GetExecutionMode() const { + ExecutionMode out{}; + ThrowOnError(GetApi().GetSessionExecutionMode(this->p_, &out)); return out; } template -inline TypeInfo SequenceTypeInfoImpl::GetSequenceElementType() const { - OrtTypeInfo* output; - ThrowOnError(GetApi().GetSequenceElementType(this->p_, &output)); - return TypeInfo{output}; +inline SessionOptionsImpl& SessionOptionsImpl::SetIntraOpNumThreads(int intra_op_num_threads) { + ThrowOnError(GetApi().SetIntraOpNumThreads(this->p_, intra_op_num_threads)); + return *this; } template -inline TypeInfo OptionalTypeInfoImpl::GetOptionalElementType() const { - OrtTypeInfo* info; - ThrowOnError(GetApi().GetOptionalContainedTypeInfo(this->p_, &info)); - return TypeInfo{info}; +inline SessionOptionsImpl& SessionOptionsImpl::SetInterOpNumThreads(int inter_op_num_threads) { + ThrowOnError(GetApi().SetInterOpNumThreads(this->p_, inter_op_num_threads)); + return *this; } template -inline ONNXTensorElementDataType MapTypeInfoImpl::GetMapKeyType() const { - ONNXTensorElementDataType out; - ThrowOnError(GetApi().GetMapKeyType(this->p_, &out)); - return out; +inline SessionOptionsImpl& SessionOptionsImpl::SetGraphOptimizationLevel(GraphOptimizationLevel graph_optimization_level) { + ThrowOnError(GetApi().SetSessionGraphOptimizationLevel(this->p_, graph_optimization_level)); + return *this; } template -inline TypeInfo MapTypeInfoImpl::GetMapValueType() const { - OrtTypeInfo* output; - ThrowOnError(GetApi().GetMapValueType(this->p_, &output)); - return TypeInfo{output}; +inline SessionOptionsImpl& SessionOptionsImpl::SetDeterministicCompute(bool value) { + ThrowOnError(GetApi().SetDeterministicCompute(this->p_, value)); + return *this; } template -inline ConstOptionalTypeInfo TypeInfoImpl::GetOptionalTypeInfo() const { - const OrtOptionalTypeInfo* info; - ThrowOnError(GetApi().CastTypeInfoToOptionalTypeInfo(this->p_, &info)); - return ConstOptionalTypeInfo{info}; +inline SessionOptionsImpl& SessionOptionsImpl::SetOptimizedModelFilePath(const ORTCHAR_T* optimized_model_filepath) { + ThrowOnError(GetApi().SetOptimizedModelFilePath(this->p_, optimized_model_filepath)); + return *this; } -} // namespace detail - -namespace detail { - template -template -inline void ConstValueImpl::GetOpaqueData(const char* domain, const char* type_name, R& out) const { - ThrowOnError(GetApi().GetOpaqueValue(domain, type_name, this->p_, &out, sizeof(R))); +inline SessionOptionsImpl& SessionOptionsImpl::EnableProfiling(const ORTCHAR_T* profile_file_prefix) { + ThrowOnError(GetApi().EnableProfiling(this->p_, profile_file_prefix)); + return *this; } template -inline bool ConstValueImpl::IsTensor() const { - int out; - ThrowOnError(GetApi().IsTensor(this->p_, &out)); - return out != 0; +inline SessionOptionsImpl& SessionOptionsImpl::DisableProfiling() { + ThrowOnError(GetApi().DisableProfiling(this->p_)); + return *this; } template -inline bool ConstValueImpl::HasValue() const { - int out; - ThrowOnError(GetApi().HasValue(this->p_, &out)); - return out != 0; +inline SessionOptionsImpl& SessionOptionsImpl::EnableOrtCustomOps() { + ThrowOnError(GetApi().EnableOrtCustomOps(this->p_)); + return *this; } template -inline size_t ConstValueImpl::GetCount() const { - size_t out; - ThrowOnError(GetApi().GetValueCount(this->p_, &out)); - return out; +inline SessionOptionsImpl& SessionOptionsImpl::EnableMemPattern() { + ThrowOnError(GetApi().EnableMemPattern(this->p_)); + return *this; } template -inline Value ConstValueImpl::GetValue(int index, OrtAllocator* allocator) const { - OrtValue* out; - ThrowOnError(GetApi().GetValue(this->p_, index, allocator, &out)); - return Value{out}; +inline SessionOptionsImpl& SessionOptionsImpl::DisableMemPattern() { + ThrowOnError(GetApi().DisableMemPattern(this->p_)); + return *this; } template -inline size_t ConstValueImpl::GetStringTensorDataLength() const { - size_t out; - ThrowOnError(GetApi().GetStringTensorDataLength(this->p_, &out)); - return out; +inline SessionOptionsImpl& SessionOptionsImpl::EnableCpuMemArena() { + ThrowOnError(GetApi().EnableCpuMemArena(this->p_)); + return *this; } template -inline size_t ConstValueImpl::GetStringTensorElementLength(size_t element_index) const { - size_t out; - ThrowOnError(GetApi().GetStringTensorElementLength(this->p_, element_index, &out)); - return out; +inline SessionOptionsImpl& SessionOptionsImpl::DisableCpuMemArena() { + ThrowOnError(GetApi().DisableCpuMemArena(this->p_)); + return *this; } template -template -inline const R* ConstValueImpl::GetTensorData() const { - R* out; - ThrowOnError(GetApi().GetTensorMutableData(const_cast(this->p_), (void**)&out)); - return out; +inline SessionOptionsImpl& SessionOptionsImpl::SetExecutionMode(ExecutionMode execution_mode) { + ThrowOnError(GetApi().SetSessionExecutionMode(this->p_, execution_mode)); + return *this; } template -inline const void* ConstValueImpl::GetTensorRawData() const { - void* out; - ThrowOnError(GetApi().GetTensorMutableData(const_cast(this->p_), &out)); - return out; +inline SessionOptionsImpl& SessionOptionsImpl::SetLoadCancellationFlag(bool value) { + ThrowOnError(GetApi().SessionOptionsSetLoadCancellationFlag(this->p_, value)); + return *this; } template -inline TypeInfo ConstValueImpl::GetTypeInfo() const { - OrtTypeInfo* output; - ThrowOnError(GetApi().GetTypeInfo(this->p_, &output)); - return TypeInfo{output}; +inline SessionOptionsImpl& SessionOptionsImpl::SetLogId(const char* logid) { + ThrowOnError(GetApi().SetSessionLogId(this->p_, logid)); + return *this; } template -inline TensorTypeAndShapeInfo ConstValueImpl::GetTensorTypeAndShapeInfo() const { - OrtTensorTypeAndShapeInfo* output; - ThrowOnError(GetApi().GetTensorTypeAndShape(this->p_, &output)); - return TensorTypeAndShapeInfo{output}; +inline SessionOptionsImpl& SessionOptionsImpl::SetLogSeverityLevel(int level) { + ThrowOnError(GetApi().SetSessionLogSeverityLevel(this->p_, level)); + return *this; } template -inline ConstMemoryInfo ConstValueImpl::GetTensorMemoryInfo() const { - const OrtMemoryInfo* mem_info; - ThrowOnError(GetApi().GetTensorMemoryInfo(this->p_, &mem_info)); - return ConstMemoryInfo(mem_info); +inline SessionOptionsImpl& SessionOptionsImpl::Add(OrtCustomOpDomain* custom_op_domain) { + ThrowOnError(GetApi().AddCustomOpDomain(this->p_, custom_op_domain)); + return *this; } template -inline void ConstValueImpl::GetStringTensorElement(size_t buffer_length, size_t element_index, void* buffer) const { - ThrowOnError(GetApi().GetStringTensorElement(this->p_, buffer_length, element_index, buffer)); +inline SessionOptionsImpl& SessionOptionsImpl::AddConfigEntry(const char* config_key, const char* config_value) { + ThrowOnError(GetApi().AddSessionConfigEntry(this->p_, config_key, config_value)); + return *this; } template -inline std::string ConstValueImpl::GetStringTensorElement(size_t element_index) const { - size_t buffer_length; - ThrowOnError(GetApi().GetStringTensorElementLength(this->p_, element_index, &buffer_length)); - - std::string s; - s.resize(buffer_length); - ThrowOnError(GetApi().GetStringTensorElement(this->p_, buffer_length, element_index, &s[0])); - return s; +inline SessionOptionsImpl& SessionOptionsImpl::AddInitializer(const char* name, const OrtValue* ort_val) { + ThrowOnError(GetApi().AddInitializer(this->p_, name, ort_val)); + return *this; } template -inline void ConstValueImpl::GetStringTensorContent(void* buffer, size_t buffer_length, size_t* offsets, size_t offsets_count) const { - ThrowOnError(GetApi().GetStringTensorContent(this->p_, buffer, buffer_length, offsets, offsets_count)); +inline SessionOptionsImpl& SessionOptionsImpl::DisablePerSessionThreads() { + ThrowOnError(GetApi().DisablePerSessionThreads(this->p_)); + return *this; } -#if !defined(DISABLE_SPARSE_TENSORS) template -inline OrtSparseFormat ConstValueImpl::GetSparseFormat() const { - OrtSparseFormat format; - ThrowOnError(GetApi().GetSparseTensorFormat(this->p_, &format)); - return format; +inline SessionOptionsImpl& SessionOptionsImpl::AddExternalInitializers(const std::vector& names, + const std::vector& ort_values) { + const size_t inputs_num = names.size(); + if (inputs_num != ort_values.size()) { + ORT_CXX_API_THROW("Expecting names and ort_values to have the same length", ORT_INVALID_ARGUMENT); + } + std::vector names_ptr; + std::vector ort_values_ptrs; + names_ptr.reserve(inputs_num); + ort_values_ptrs.reserve(inputs_num); + for (size_t i = 0; i < inputs_num; ++i) { + names_ptr.push_back(names[i].c_str()); + ort_values_ptrs.push_back(ort_values[i]); + } + ThrowOnError(GetApi().AddExternalInitializers(this->p_, names_ptr.data(), ort_values_ptrs.data(), inputs_num)); + return *this; } template -inline TensorTypeAndShapeInfo ConstValueImpl::GetSparseTensorValuesTypeAndShapeInfo() const { - OrtTensorTypeAndShapeInfo* output; - ThrowOnError(GetApi().GetSparseTensorValuesTypeAndShape(this->p_, &output)); - return TensorTypeAndShapeInfo{output}; +inline SessionOptionsImpl& SessionOptionsImpl::AddExternalInitializersFromFilesInMemory(const std::vector>& file_names, + const std::vector& buffer_array, + const std::vector& file_lengths) { + const size_t inputs_num = file_names.size(); + if (inputs_num != buffer_array.size()) { + ORT_CXX_API_THROW("Expecting names and buffer_array to have the same length", ORT_INVALID_ARGUMENT); + } + if (inputs_num != file_lengths.size()) { + ORT_CXX_API_THROW("Expecting names and file_lengths to have the same length", ORT_INVALID_ARGUMENT); + } + std::vector names_ptr; + names_ptr.reserve(inputs_num); + for (size_t i = 0; i < inputs_num; ++i) { + names_ptr.push_back(file_names[i].c_str()); + } + ThrowOnError(GetApi().AddExternalInitializersFromFilesInMemory(this->p_, names_ptr.data(), buffer_array.data(), + file_lengths.data(), inputs_num)); + return *this; } template -inline TensorTypeAndShapeInfo ConstValueImpl::GetSparseTensorIndicesTypeShapeInfo(OrtSparseIndicesFormat indices_format) const { - OrtTensorTypeAndShapeInfo* output; - ThrowOnError(GetApi().GetSparseTensorIndicesTypeShape(this->p_, indices_format, &output)); - return TensorTypeAndShapeInfo{output}; +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_CPU(int use_arena) { + ThrowOnError(OrtSessionOptionsAppendExecutionProvider_CPU(this->p_, use_arena)); + return *this; } template -template -inline const R* ConstValueImpl::GetSparseTensorIndicesData(OrtSparseIndicesFormat indices_format, size_t& num_indices) const { - const void* out; - ThrowOnError(GetApi().GetSparseTensorIndices(this->p_, indices_format, &num_indices, &out)); - return reinterpret_cast(out); +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_CUDA(const OrtCUDAProviderOptions& provider_options) { + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_CUDA(this->p_, &provider_options)); + return *this; } template -inline bool ConstValueImpl::IsSparseTensor() const { - int out; - ThrowOnError(GetApi().IsSparseTensor(this->p_, &out)); - return out != 0; +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_CUDA_V2(const OrtCUDAProviderOptionsV2& provider_options) { + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_CUDA_V2(this->p_, &provider_options)); + return *this; } template -template -inline const R* ConstValueImpl::GetSparseTensorValues() const { - const void* out; - ThrowOnError(GetApi().GetSparseTensorValues(this->p_, &out)); - return reinterpret_cast(out); +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_ROCM(const OrtROCMProviderOptions& provider_options) { + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_ROCM(this->p_, &provider_options)); + return *this; } -#endif - template -void ValueImpl::FillStringTensor(const char* const* s, size_t s_len) { - ThrowOnError(GetApi().FillStringTensor(this->p_, s, s_len)); +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_TensorRT(const OrtTensorRTProviderOptions& provider_options) { + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_TensorRT(this->p_, &provider_options)); + return *this; } template -void ValueImpl::FillStringTensorElement(const char* s, size_t index) { - ThrowOnError(GetApi().FillStringTensorElement(this->p_, s, index)); +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_TensorRT_V2(const OrtTensorRTProviderOptionsV2& provider_options) { + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_TensorRT_V2(this->p_, &provider_options)); + return *this; } template -inline char* ValueImpl::GetResizedStringTensorElementBuffer(size_t index, size_t buffer_length) { - char* result; - ThrowOnError(GetApi().GetResizedStringTensorElementBuffer(this->p_, index, buffer_length, &result)); - return result; +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_MIGraphX(const OrtMIGraphXProviderOptions& provider_options) { + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_MIGraphX(this->p_, &provider_options)); + return *this; } template -void* ValueImpl::GetTensorMutableRawData() { - void* out; - ThrowOnError(GetApi().GetTensorMutableData(this->p_, &out)); - return out; +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_CANN(const OrtCANNProviderOptions& provider_options) { + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_CANN(this->p_, &provider_options)); + return *this; } template -template -R* ValueImpl::GetTensorMutableData() { - R* out; - ThrowOnError(GetApi().GetTensorMutableData(this->p_, (void**)&out)); - return out; +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_Dnnl(const OrtDnnlProviderOptions& provider_options) { + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_Dnnl(this->p_, &provider_options)); + return *this; } template -template -R& ValueImpl::At(const std::vector& location) { - static_assert(!std::is_same::value, "this api does not support std::string"); - R* out; - ThrowOnError(GetApi().TensorAt(this->p_, location.data(), location.size(), (void**)&out)); - return *out; +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider( + const std::string& provider_name, + const std::unordered_map& provider_options) { + auto num_entries = provider_options.size(); + std::vector keys, values; + if (num_entries > 0) { + keys.reserve(num_entries); + values.reserve(num_entries); + + for (const auto& entry : provider_options) { + keys.push_back(entry.first.c_str()); + values.push_back(entry.second.c_str()); + } + } + + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider(this->p_, provider_name.c_str(), + keys.data(), values.data(), num_entries)); + + return *this; } -#if !defined(DISABLE_SPARSE_TENSORS) +namespace { template -void ValueImpl::UseCooIndices(int64_t* indices_data, size_t indices_num) { - ThrowOnError(GetApi().UseCooIndices(this->p_, indices_data, indices_num)); +void SessionOptionsAppendEP(detail::SessionOptionsImpl& session_options, + Env& env, const std::vector& ep_devices, + const std::vector& ep_options_keys, + const std::vector& ep_options_values) { + std::vector ep_devices_ptrs; + ep_devices_ptrs.reserve(ep_devices.size()); + for (const auto& ep_device : ep_devices) { + ep_devices_ptrs.push_back(ep_device); + } + + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_V2( + session_options, env, ep_devices_ptrs.data(), ep_devices_ptrs.size(), + ep_options_keys.data(), ep_options_values.data(), ep_options_keys.size())); } +} // namespace template -void ValueImpl::UseCsrIndices(int64_t* inner_data, size_t inner_num, int64_t* outer_data, size_t outer_num) { - ThrowOnError(GetApi().UseCsrIndices(this->p_, inner_data, inner_num, outer_data, outer_num)); +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_V2( + Env& env, const std::vector& ep_devices, const KeyValuePairs& ep_options) { + std::vector ep_options_keys, ep_options_values; + ep_options.GetKeyValuePairs(ep_options_keys, ep_options_values); + + SessionOptionsAppendEP(*this, env, ep_devices, ep_options_keys, ep_options_values); + + return *this; } template -void ValueImpl::UseBlockSparseIndices(const Shape& indices_shape, int32_t* indices_data) { - ThrowOnError(GetApi().UseBlockSparseIndices(this->p_, indices_shape.shape, indices_shape.shape_len, indices_data)); +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_V2( + Env& env, const std::vector& ep_devices, + const std::unordered_map& ep_options) { + std::vector ep_options_keys, ep_options_values; + ep_options_keys.reserve(ep_options.size()); + ep_options_values.reserve(ep_options.size()); + + for (const auto& [key, value] : ep_options) { + ep_options_keys.push_back(key.c_str()); + ep_options_values.push_back(value.c_str()); + } + + SessionOptionsAppendEP(*this, env, ep_devices, ep_options_keys, ep_options_values); + + return *this; } template -void ValueImpl::FillSparseTensorCoo(const OrtMemoryInfo* mem_info, const OrtSparseValuesParam& values_param, - const int64_t* indices_data, size_t indices_num) { - ThrowOnError(GetApi().FillSparseTensorCoo(this->p_, mem_info, values_param.values_shape, - values_param.values_shape_len, values_param.data.p_data, - indices_data, indices_num)); +inline SessionOptionsImpl& SessionOptionsImpl::SetEpSelectionPolicy(OrtExecutionProviderDevicePolicy policy) { + ThrowOnError(GetApi().SessionOptionsSetEpSelectionPolicy(this->p_, policy)); + return *this; } template -void ValueImpl::FillSparseTensorCsr(const OrtMemoryInfo* data_mem_info, - const OrtSparseValuesParam& values, - const int64_t* inner_indices_data, size_t inner_indices_num, - const int64_t* outer_indices_data, size_t outer_indices_num) { - ThrowOnError(GetApi().FillSparseTensorCsr(this->p_, data_mem_info, values.values_shape, values.values_shape_len, values.data.p_data, - inner_indices_data, inner_indices_num, - outer_indices_data, outer_indices_num)); +inline SessionOptionsImpl& SessionOptionsImpl::SetEpSelectionPolicy(EpSelectionDelegate delegate, void* state) { + ThrowOnError(GetApi().SessionOptionsSetEpSelectionPolicyDelegate(this->p_, delegate, state)); + return *this; } template -void ValueImpl::FillSparseTensorBlockSparse(const OrtMemoryInfo* data_mem_info, - const OrtSparseValuesParam& values, - const Shape& indices_shape, - const int32_t* indices_data) { - ThrowOnError(GetApi().FillSparseTensorBlockSparse(this->p_, data_mem_info, values.values_shape, values.values_shape_len, values.data.p_data, - indices_shape.shape, indices_shape.shape_len, - indices_data)); +inline SessionOptionsImpl& SessionOptionsImpl::SetCustomCreateThreadFn(OrtCustomCreateThreadFn ort_custom_create_thread_fn) { + ThrowOnError(GetApi().SessionOptionsSetCustomCreateThreadFn(this->p_, ort_custom_create_thread_fn)); + return *this; } -#endif // !defined(DISABLE_SPARSE_TENSORS) +template +inline SessionOptionsImpl& SessionOptionsImpl::SetCustomThreadCreationOptions(void* ort_custom_thread_creation_options) { + ThrowOnError(GetApi().SessionOptionsSetCustomThreadCreationOptions(this->p_, ort_custom_thread_creation_options)); + return *this; +} -} // namespace detail +template +inline SessionOptionsImpl& SessionOptionsImpl::SetCustomJoinThreadFn(OrtCustomJoinThreadFn ort_custom_join_thread_fn) { + ThrowOnError(GetApi().SessionOptionsSetCustomJoinThreadFn(this->p_, ort_custom_join_thread_fn)); + return *this; +} + +template +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_OpenVINO(const OrtOpenVINOProviderOptions& provider_options) { + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_OpenVINO(this->p_, &provider_options)); + return *this; +} + +template +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_OpenVINO_V2(const std::unordered_map& provider_options) { + auto num_entries = provider_options.size(); + std::vector keys, values; + if (num_entries > 0) { + keys.reserve(num_entries); + values.reserve(num_entries); + + for (const auto& entry : provider_options) { + keys.push_back(entry.first.c_str()); + values.push_back(entry.second.c_str()); + } + } + + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_OpenVINO_V2(this->p_, + keys.data(), values.data(), num_entries)); + + return *this; +} + +template +inline SessionOptionsImpl& SessionOptionsImpl::AppendExecutionProvider_VitisAI(const std::unordered_map& provider_options) { + auto num_entries = provider_options.size(); + std::vector keys, values; + if (num_entries > 0) { + keys.reserve(num_entries); + values.reserve(num_entries); + + for (const auto& entry : provider_options) { + keys.push_back(entry.first.c_str()); + values.push_back(entry.second.c_str()); + } + } + + ThrowOnError(GetApi().SessionOptionsAppendExecutionProvider_VitisAI(this->p_, keys.data(), values.data(), num_entries)); + + return *this; +} + +template +inline SessionOptionsImpl& SessionOptionsImpl::RegisterCustomOpsLibrary(const ORTCHAR_T* library_name, + const CustomOpConfigs& custom_op_configs) { + // Add custom op config entries before registering the custom op library. Otherwise, the config entries _may_ be ignored by + // the custom op library. + for (const auto& config_iter : custom_op_configs.GetFlattenedConfigs()) { + AddConfigEntry(config_iter.first.c_str(), config_iter.second.c_str()); + } + + ThrowOnError(GetApi().RegisterCustomOpsLibrary_V2(this->p_, library_name)); + return *this; +} + +template +inline SessionOptionsImpl& SessionOptionsImpl::RegisterCustomOpsUsingFunction(const char* registration_function_name) { + ThrowOnError(GetApi().RegisterCustomOpsUsingFunction(this->p_, registration_function_name)); + return *this; +} + +template +inline SessionOptionsImpl& SessionOptionsImpl::AddFreeDimensionOverride(const char* dim_denotation, int64_t dim_value) { + ThrowOnError(GetApi().AddFreeDimensionOverrideByName(this->p_, dim_denotation, dim_value)); + return *this; +} + +template +inline SessionOptionsImpl& SessionOptionsImpl::AddFreeDimensionOverrideByName(const char* dim_name, int64_t dim_value) { + ThrowOnError(GetApi().AddFreeDimensionOverrideByName(this->p_, dim_name, dim_value)); + return *this; +} + +/// Session +template +inline size_t ConstSessionImpl::GetInputCount() const { + size_t out; + ThrowOnError(GetApi().SessionGetInputCount(this->p_, &out)); + return out; +} + +template +inline size_t ConstSessionImpl::GetOutputCount() const { + size_t out; + ThrowOnError(GetApi().SessionGetOutputCount(this->p_, &out)); + return out; +} + +template +inline size_t ConstSessionImpl::GetOverridableInitializerCount() const { + size_t out; + ThrowOnError(GetApi().SessionGetOverridableInitializerCount(this->p_, &out)); + return out; +} + +template +inline std::vector ConstSessionImpl::GetInputNames() const { + AllocatorWithDefaultOptions allocator; + + auto num_inputs = GetInputCount(); + std::vector input_names; + input_names.reserve(num_inputs); + + for (size_t i = 0; i < num_inputs; ++i) { + char* name; + ThrowOnError(GetApi().SessionGetInputName(this->p_, i, allocator, &name)); + input_names.emplace_back(name); + allocator.Free(name); + } + + return input_names; +} + +template +inline std::vector ConstSessionImpl::GetOutputNames() const { + AllocatorWithDefaultOptions allocator; + + auto num_inputs = GetOutputCount(); + std::vector output_names; + output_names.reserve(num_inputs); + + for (size_t i = 0; i < num_inputs; ++i) { + char* name; + ThrowOnError(GetApi().SessionGetOutputName(this->p_, i, allocator, &name)); + output_names.emplace_back(name); + allocator.Free(name); + } + + return output_names; +} + +template +inline std::vector ConstSessionImpl::GetOverridableInitializerNames() const { + AllocatorWithDefaultOptions allocator; + + auto num_initializers = GetOverridableInitializerCount(); + std::vector initializer_names; + initializer_names.reserve(num_initializers); + + for (size_t i = 0; i < num_initializers; ++i) { + char* name; + ThrowOnError(GetApi().SessionGetOverridableInitializerName(this->p_, i, allocator, &name)); + initializer_names.emplace_back(name); + } + + return initializer_names; +} + +template +inline std::vector ConstSessionImpl::GetMemoryInfoForInputs() const { + static_assert(sizeof(ConstMemoryInfo) == sizeof(OrtMemoryInfo*), + "ConstMemoryInfo must be compatible with OrtMemoryInfo*"); + + auto num_inputs = GetInputCount(); + std::vector mem_infos; + if (num_inputs > 0) { + mem_infos.resize(num_inputs); + + ThrowOnError(GetApi().SessionGetMemoryInfoForInputs(this->p_, + reinterpret_cast(mem_infos.data()), + num_inputs)); + } + + return mem_infos; +} + +template +inline std::vector ConstSessionImpl::GetMemoryInfoForOutputs() const { + static_assert(sizeof(ConstMemoryInfo) == sizeof(OrtMemoryInfo*), + "ConstMemoryInfo must be compatible with OrtMemoryInfo*"); + + auto num_outputs = GetOutputCount(); + std::vector mem_infos; + if (num_outputs > 0) { + mem_infos.resize(num_outputs); + + ThrowOnError(GetApi().SessionGetMemoryInfoForOutputs(this->p_, + reinterpret_cast(mem_infos.data()), + num_outputs)); + } + return mem_infos; +} + +template +inline AllocatedStringPtr ConstSessionImpl::GetInputNameAllocated(size_t index, OrtAllocator* allocator) const { + char* out; + ThrowOnError(GetApi().SessionGetInputName(this->p_, index, allocator, &out)); + return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +} + +template +inline AllocatedStringPtr ConstSessionImpl::GetOutputNameAllocated(size_t index, OrtAllocator* allocator) const { + char* out; + ThrowOnError(GetApi().SessionGetOutputName(this->p_, index, allocator, &out)); + return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +} + +template +inline AllocatedStringPtr ConstSessionImpl::GetOverridableInitializerNameAllocated(size_t index, OrtAllocator* allocator) const { + char* out; + ThrowOnError(GetApi().SessionGetOverridableInitializerName(this->p_, index, allocator, &out)); + return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +} + +template +inline std::vector ConstSessionImpl::GetEpDeviceForInputs() const { + auto num_inputs = GetInputCount(); + std::vector input_devices; + if (num_inputs > 0) { + input_devices.resize(num_inputs); + ThrowOnError(GetApi().SessionGetEpDeviceForInputs(this->p_, + reinterpret_cast(input_devices.data()), + num_inputs)); + } + return input_devices; +} + +template +inline std::vector ConstSessionImpl::GetEpDeviceForOutputs() const { + auto num_outputs = GetOutputCount(); + std::vector output_devices; + if (num_outputs > 0) { + output_devices.resize(num_outputs); + ThrowOnError(GetApi().SessionGetEpDeviceForOutputs(this->p_, + reinterpret_cast(output_devices.data()), + num_outputs)); + } + return output_devices; +} + +template +inline uint64_t ConstSessionImpl::GetProfilingStartTimeNs() const { + uint64_t out; + ThrowOnError(GetApi().SessionGetProfilingStartTimeNs(this->p_, &out)); + return out; +} + +template +inline ModelMetadata ConstSessionImpl::GetModelMetadata() const { + OrtModelMetadata* out; + ThrowOnError(GetApi().SessionGetModelMetadata(this->p_, &out)); + return ModelMetadata{out}; +} + +template +inline TypeInfo ConstSessionImpl::GetInputTypeInfo(size_t index) const { + OrtTypeInfo* out; + ThrowOnError(GetApi().SessionGetInputTypeInfo(this->p_, index, &out)); + return TypeInfo{out}; +} + +template +inline TypeInfo ConstSessionImpl::GetOutputTypeInfo(size_t index) const { + OrtTypeInfo* out; + ThrowOnError(GetApi().SessionGetOutputTypeInfo(this->p_, index, &out)); + return TypeInfo{out}; +} + +template +inline TypeInfo ConstSessionImpl::GetOverridableInitializerTypeInfo(size_t index) const { + OrtTypeInfo* out; + ThrowOnError(GetApi().SessionGetOverridableInitializerTypeInfo(this->p_, index, &out)); + return TypeInfo{out}; +} + +#if !defined(ORT_MINIMAL_BUILD) +template +inline int ConstSessionImpl::GetOpset(const std::string& domain) const { + int opset; + ThrowOnError(GetModelEditorApi().SessionGetOpsetForDomain(this->p_, domain.c_str(), &opset)); + return opset; +} +#endif // !defined(ORT_MINIMAL_BUILD) + +template +std::vector ConstSessionImpl::GetInputs() const { + const std::vector input_names = GetInputNames(); + + std::vector inputs; + inputs.reserve(input_names.size()); + + for (size_t i = 0; i < input_names.size(); ++i) { + auto type_info = GetInputTypeInfo(i); + inputs.emplace_back(ValueInfo{input_names[i], type_info.GetConst()}); + } + + return inputs; +} + +template +std::vector ConstSessionImpl::GetOutputs() const { + const std::vector output_names = GetOutputNames(); + + std::vector outputs; + outputs.reserve(output_names.size()); + + for (size_t i = 0; i < output_names.size(); ++i) { + auto type_info = GetOutputTypeInfo(i); + outputs.emplace_back(ValueInfo{output_names[i], type_info.GetConst()}); + } + + return outputs; +} + +template +inline std::vector ConstSessionImpl::GetEpGraphAssignmentInfo() const { + size_t num_ep_subgraphs = 0; + const OrtEpAssignedSubgraph* const* ep_subgraph_ptrs = nullptr; + ThrowOnError(GetApi().Session_GetEpGraphAssignmentInfo(this->p_, &ep_subgraph_ptrs, &num_ep_subgraphs)); + + std::vector ep_subgraphs; + if (num_ep_subgraphs > 0) { + ep_subgraphs.reserve(num_ep_subgraphs); + for (size_t i = 0; i < num_ep_subgraphs; ++i) { + ep_subgraphs.emplace_back(ep_subgraph_ptrs[i]); + } + } + + return ep_subgraphs; +} + +template +inline std::vector SessionImpl::Run(const RunOptions& run_options, const char* const* input_names, const Value* input_values, size_t input_count, + const char* const* output_names, size_t output_count) { + std::vector output_values; + output_values.reserve(output_count); + for (size_t i = 0; i < output_count; i++) + output_values.emplace_back(nullptr); + Run(run_options, input_names, input_values, input_count, output_names, output_values.data(), output_count); + return output_values; +} + +template +inline void SessionImpl::Run(const RunOptions& run_options, const char* const* input_names, const Value* input_values, size_t input_count, + const char* const* output_names, Value* output_values, size_t output_count) { + static_assert(sizeof(Value) == sizeof(OrtValue*), "Value is really just an array of OrtValue* in memory, so we can reinterpret_cast safely"); + auto ort_input_values = reinterpret_cast(input_values); + auto ort_output_values = reinterpret_cast(output_values); + ThrowOnError(GetApi().Run(this->p_, run_options, input_names, ort_input_values, input_count, output_names, output_count, ort_output_values)); +} + +template +inline void SessionImpl::Run(const RunOptions& run_options, const IoBinding& io_binding) { + ThrowOnError(GetApi().RunWithBinding(this->p_, run_options, io_binding)); +} + +template +inline void SessionImpl::RunAsync(const RunOptions& run_options, const char* const* input_names, const Value* input_values, size_t input_count, + const char* const* output_names, Value* output_values, size_t output_count, RunAsyncCallbackFn callback, void* user_data) { + auto ort_input_values = reinterpret_cast(input_values); + auto ort_output_values = reinterpret_cast(output_values); + ThrowOnError(GetApi().RunAsync(this->p_, run_options, input_names, + ort_input_values, input_count, output_names, output_count, + ort_output_values, callback, user_data)); +} + +template +inline AllocatedStringPtr SessionImpl::EndProfilingAllocated(OrtAllocator* allocator) { + char* out = nullptr; + ThrowOnError(GetApi().SessionEndProfiling(this->p_, allocator, &out)); + return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +} + +template +inline void SessionImpl::SetEpDynamicOptions(const char* const* keys, const char* const* values, size_t kv_len) { + ThrowOnError(GetApi().SetEpDynamicOptions(this->p_, keys, values, kv_len)); +} + +#if !defined(ORT_MINIMAL_BUILD) +template +inline void SessionImpl::FinalizeModelEditorSession(const Model& model, const SessionOptions& options, + OrtPrepackedWeightsContainer* prepacked_weights_container) { + ThrowOnError(GetModelEditorApi().ApplyModelToModelEditorSession(this->p_, model)); + ThrowOnError(GetModelEditorApi().FinalizeModelEditorSession(this->p_, options, prepacked_weights_container)); +} +#endif // #if !defined(ORT_MINIMAL_BUILD) + +} // namespace detail + +inline SessionOptions::SessionOptions() { + ThrowOnError(GetApi().CreateSessionOptions(&this->p_)); +} + +/// CustomOpConfigs +inline std::string detail::MakeCustomOpConfigEntryKey(const char* custom_op_name, const char* config) { + std::string config_key = "custom_op."; + + config_key += custom_op_name; + config_key += "."; + config_key += config; + + return config_key; +} + +inline CustomOpConfigs& CustomOpConfigs::AddConfig(const char* custom_op_name, const char* config_key, const char* config_value) { + const std::string full_flat_key = detail::MakeCustomOpConfigEntryKey(custom_op_name, config_key); + flat_configs_[full_flat_key] = config_value; + return *this; +} + +inline const std::unordered_map& CustomOpConfigs::GetFlattenedConfigs() const { + return flat_configs_; +} + +inline Session::Session(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options) { + ThrowOnError(GetApi().CreateSession(env, model_path, options, &this->p_)); +} + +inline Session::Session(const Env& env, const ORTCHAR_T* model_path, const SessionOptions& options, + OrtPrepackedWeightsContainer* prepacked_weights_container) { + ThrowOnError(GetApi().CreateSessionWithPrepackedWeightsContainer(env, model_path, options, prepacked_weights_container, &this->p_)); +} + +inline Session::Session(const Env& env, const void* model_data, size_t model_data_length, const SessionOptions& options) { + ThrowOnError(GetApi().CreateSessionFromArray(env, model_data, model_data_length, options, &this->p_)); +} + +inline Session::Session(const Env& env, const void* model_data, size_t model_data_length, + const SessionOptions& options, OrtPrepackedWeightsContainer* prepacked_weights_container) { + ThrowOnError(GetApi().CreateSessionFromArrayWithPrepackedWeightsContainer(env, model_data, model_data_length, options, + prepacked_weights_container, &this->p_)); +} + +#if !defined(ORT_MINIMAL_BUILD) +inline Session::Session(const Env& env, const Model& model, const SessionOptions& options) { + ThrowOnError(GetModelEditorApi().CreateSessionFromModel(env, model, options, &this->p_)); +} + +// static +inline Session Session::CreateModelEditorSession(const Env& env, const ORTCHAR_T* model_path, + const SessionOptions& options) { + OrtSession* session = nullptr; + ThrowOnError(GetModelEditorApi().CreateModelEditorSession(env, model_path, options, &session)); + return Session(session); +} + +// static +inline Session Session::CreateModelEditorSession(const Env& env, const void* model_data, size_t model_data_length, + const SessionOptions& options) { + OrtSession* session = nullptr; + ThrowOnError(GetModelEditorApi().CreateModelEditorSessionFromArray(env, model_data, model_data_length, options, + &session)); + return Session(session); +} + +void FinalizeModelEditorSession(const Model& model, const SessionOptions& options, + OrtPrepackedWeightsContainer* prepacked_weights_container); +#endif // #if !defined(ORT_MINIMAL_BUILD) + +inline AllocatedStringPtr ModelMetadata::GetProducerNameAllocated(OrtAllocator* allocator) const { + char* out; + ThrowOnError(GetApi().ModelMetadataGetProducerName(p_, allocator, &out)); + return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +} + +inline AllocatedStringPtr ModelMetadata::GetGraphNameAllocated(OrtAllocator* allocator) const { + char* out; + ThrowOnError(GetApi().ModelMetadataGetGraphName(p_, allocator, &out)); + return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +} + +inline AllocatedStringPtr ModelMetadata::GetDomainAllocated(OrtAllocator* allocator) const { + char* out; + ThrowOnError(GetApi().ModelMetadataGetDomain(p_, allocator, &out)); + return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +} + +inline AllocatedStringPtr Ort::ModelMetadata::GetDescriptionAllocated(OrtAllocator* allocator) const { + char* out; + ThrowOnError(GetApi().ModelMetadataGetDescription(p_, allocator, &out)); + return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +} + +inline AllocatedStringPtr ModelMetadata::GetGraphDescriptionAllocated(OrtAllocator* allocator) const { + char* out; + ThrowOnError(GetApi().ModelMetadataGetGraphDescription(p_, allocator, &out)); + return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +} + +inline AllocatedStringPtr ModelMetadata::LookupCustomMetadataMapAllocated(const char* key, OrtAllocator* allocator) const { + char* out; + ThrowOnError(GetApi().ModelMetadataLookupCustomMetadataMap(p_, allocator, key, &out)); + return AllocatedStringPtr(out, detail::AllocatedFree(allocator)); +} + +inline std::vector ModelMetadata::GetCustomMetadataMapKeysAllocated(OrtAllocator* allocator) const { + auto deletor = detail::AllocatedFree(allocator); + std::vector result; + + char** out = nullptr; + int64_t num_keys = 0; + ThrowOnError(GetApi().ModelMetadataGetCustomMetadataMapKeys(p_, allocator, &out, &num_keys)); + if (num_keys <= 0) { + return result; + } + + // array of pointers will be freed + std::unique_ptr array_guard(out, deletor); + // reserve may throw + auto strings_deletor = [&deletor, num_keys](char** out) { for(int64_t i = 0; i < num_keys; ++i) deletor(out[i]); }; + std::unique_ptr strings_guard(out, strings_deletor); + result.reserve(static_cast(num_keys)); + strings_guard.release(); + for (int64_t i = 0; i < num_keys; ++i) { + result.push_back(AllocatedStringPtr(out[i], deletor)); + } + + return result; +} + +inline int64_t ModelMetadata::GetVersion() const { + int64_t out; + ThrowOnError(GetApi().ModelMetadataGetVersion(p_, &out)); + return out; +} + +inline TensorTypeAndShapeInfo::TensorTypeAndShapeInfo(ONNXTensorElementDataType element_type, + const std::vector& dims, + const std::vector* symbolic_dims) { + ThrowOnError(GetApi().CreateTensorTypeAndShapeInfo(&p_)); + ThrowOnError(GetApi().SetTensorElementType(p_, element_type)); + ThrowOnError(GetApi().SetDimensions(p_, dims.data(), dims.size())); + + if (symbolic_dims) { + std::vector symbolic_dims_cstr; + symbolic_dims_cstr.reserve(symbolic_dims->size()); + std::transform(symbolic_dims->begin(), symbolic_dims->end(), std::back_inserter(symbolic_dims_cstr), + [](const std::string& s) { return s.c_str(); }); + ThrowOnError(GetApi().SetSymbolicDimensions(p_, symbolic_dims_cstr.data(), symbolic_dims_cstr.size())); + } +} + +#if !defined(ORT_MINIMAL_BUILD) +// static +inline TypeInfo TypeInfo::CreateTensorInfo(ConstTensorTypeAndShapeInfo tensor_type_and_shape_info) { + OrtTypeInfo* output = nullptr; + ThrowOnError(GetModelEditorApi().CreateTensorTypeInfo(tensor_type_and_shape_info, &output)); + return TypeInfo{output}; +} + +// static +inline TypeInfo TypeInfo::CreateSparseTensorInfo(ConstTensorTypeAndShapeInfo sparse_tensor_type_and_shape_info) { + OrtTypeInfo* output = nullptr; + ThrowOnError(GetModelEditorApi().CreateSparseTensorTypeInfo(sparse_tensor_type_and_shape_info, &output)); + return TypeInfo{output}; +} + +// static +inline TypeInfo TypeInfo::CreateSequenceTypeInfo(ConstTypeInfo sequence_type) { + OrtTypeInfo* output; + ThrowOnError(GetModelEditorApi().CreateSequenceTypeInfo(sequence_type, &output)); + return TypeInfo{output}; +} + +// static +inline TypeInfo TypeInfo::CreateMapTypeInfo(ONNXTensorElementDataType key_type, ConstTypeInfo value_type) { + OrtTypeInfo* output; + ThrowOnError(GetModelEditorApi().CreateMapTypeInfo(key_type, value_type, &output)); + return TypeInfo{output}; +} + +// static +inline TypeInfo TypeInfo::CreateOptionalTypeInfo(ConstTypeInfo contained_type) { + OrtTypeInfo* output; + ThrowOnError(GetModelEditorApi().CreateOptionalTypeInfo(contained_type, &output)); + return TypeInfo{output}; +} +#endif // #if !defined(ORT_MINIMAL_BUILD) + +namespace detail { + +template +inline ONNXTensorElementDataType TensorTypeAndShapeInfoImpl::GetElementType() const { + ONNXTensorElementDataType out; + ThrowOnError(GetApi().GetTensorElementType(this->p_, &out)); + return out; +} + +template +inline size_t TensorTypeAndShapeInfoImpl::GetElementCount() const { + size_t out; + ThrowOnError(GetApi().GetTensorShapeElementCount(this->p_, &out)); + return out; +} + +template +inline bool TensorTypeAndShapeInfoImpl::HasShape() const { + return GetApi().TensorTypeAndShape_HasShape(this->p_); +} + +template +inline size_t TensorTypeAndShapeInfoImpl::GetDimensionsCount() const { + size_t out; + ThrowOnError(GetApi().GetDimensionsCount(this->p_, &out)); + return out; +} + +template +inline void TensorTypeAndShapeInfoImpl::GetDimensions(int64_t* values, size_t values_count) const { + ThrowOnError(GetApi().GetDimensions(this->p_, values, values_count)); +} + +template +inline void TensorTypeAndShapeInfoImpl::GetSymbolicDimensions(const char** values, size_t values_count) const { + ThrowOnError(GetApi().GetSymbolicDimensions(this->p_, values, values_count)); +} + +template +inline std::vector TensorTypeAndShapeInfoImpl::GetSymbolicDimensions() const { + std::vector out; + size_t dim_count = GetDimensionsCount(); + if (dim_count > 0) { + out.resize(dim_count, nullptr); + ThrowOnError(GetApi().GetSymbolicDimensions(this->p_, out.data(), out.size())); + } + return out; +} + +template +inline std::vector TensorTypeAndShapeInfoImpl::GetShape() const { + std::vector out(GetDimensionsCount(), -1); + ThrowOnError(GetApi().GetDimensions(this->p_, out.data(), out.size())); + return out; +} + +template +inline ConstTensorTypeAndShapeInfo TypeInfoImpl::GetTensorTypeAndShapeInfo() const { + const OrtTensorTypeAndShapeInfo* out; + ThrowOnError(GetApi().CastTypeInfoToTensorInfo(this->p_, &out)); + return ConstTensorTypeAndShapeInfo{out}; +} + +template +inline ConstSequenceTypeInfo TypeInfoImpl::GetSequenceTypeInfo() const { + const OrtSequenceTypeInfo* out; + ThrowOnError(GetApi().CastTypeInfoToSequenceTypeInfo(this->p_, &out)); + return ConstSequenceTypeInfo{out}; +} + +template +inline ConstMapTypeInfo TypeInfoImpl::GetMapTypeInfo() const { + const OrtMapTypeInfo* out; + ThrowOnError(GetApi().CastTypeInfoToMapTypeInfo(this->p_, &out)); + return ConstMapTypeInfo{out}; +} + +template +inline ONNXType TypeInfoImpl::GetONNXType() const { + ONNXType out; + ThrowOnError(GetApi().GetOnnxTypeFromTypeInfo(this->p_, &out)); + return out; +} + +template +inline TypeInfo SequenceTypeInfoImpl::GetSequenceElementType() const { + OrtTypeInfo* output; + ThrowOnError(GetApi().GetSequenceElementType(this->p_, &output)); + return TypeInfo{output}; +} + +template +inline TypeInfo OptionalTypeInfoImpl::GetOptionalElementType() const { + OrtTypeInfo* info; + ThrowOnError(GetApi().GetOptionalContainedTypeInfo(this->p_, &info)); + return TypeInfo{info}; +} + +template +inline ONNXTensorElementDataType MapTypeInfoImpl::GetMapKeyType() const { + ONNXTensorElementDataType out; + ThrowOnError(GetApi().GetMapKeyType(this->p_, &out)); + return out; +} + +template +inline TypeInfo MapTypeInfoImpl::GetMapValueType() const { + OrtTypeInfo* output; + ThrowOnError(GetApi().GetMapValueType(this->p_, &output)); + return TypeInfo{output}; +} + +template +inline ConstOptionalTypeInfo TypeInfoImpl::GetOptionalTypeInfo() const { + const OrtOptionalTypeInfo* info; + ThrowOnError(GetApi().CastTypeInfoToOptionalTypeInfo(this->p_, &info)); + return ConstOptionalTypeInfo{info}; +} + +} // namespace detail + +namespace detail { + +template +template +inline void ConstValueImpl::GetOpaqueData(const char* domain, const char* type_name, R& out) const { + ThrowOnError(GetApi().GetOpaqueValue(domain, type_name, this->p_, &out, sizeof(R))); +} + +template +inline bool ConstValueImpl::IsTensor() const { + int out; + ThrowOnError(GetApi().IsTensor(this->p_, &out)); + return out != 0; +} + +template +inline bool ConstValueImpl::HasValue() const { + int out; + ThrowOnError(GetApi().HasValue(this->p_, &out)); + return out != 0; +} + +template +inline size_t ConstValueImpl::GetCount() const { + size_t out; + ThrowOnError(GetApi().GetValueCount(this->p_, &out)); + return out; +} + +template +inline Value ConstValueImpl::GetValue(int index, OrtAllocator* allocator) const { + OrtValue* out; + ThrowOnError(GetApi().GetValue(this->p_, index, allocator, &out)); + return Value{out}; +} + +template +inline size_t ConstValueImpl::GetStringTensorDataLength() const { + size_t out; + ThrowOnError(GetApi().GetStringTensorDataLength(this->p_, &out)); + return out; +} + +template +inline size_t ConstValueImpl::GetStringTensorElementLength(size_t element_index) const { + size_t out; + ThrowOnError(GetApi().GetStringTensorElementLength(this->p_, element_index, &out)); + return out; +} + +template +inline size_t ConstValueImpl::GetTensorSizeInBytes() const { + size_t out; + ThrowOnError(GetApi().GetTensorSizeInBytes(this->p_, &out)); + return out; +} + +template +template +inline const R* ConstValueImpl::GetTensorData() const { + const R* out; + ThrowOnError(GetApi().GetTensorData(this->p_, reinterpret_cast(&out))); + return out; +} + +template +inline const void* ConstValueImpl::GetTensorRawData() const { + const void* out; + ThrowOnError(GetApi().GetTensorData(this->p_, &out)); + return out; +} + +template +inline TypeInfo ConstValueImpl::GetTypeInfo() const { + OrtTypeInfo* output; + ThrowOnError(GetApi().GetTypeInfo(this->p_, &output)); + return TypeInfo{output}; +} + +template +inline TensorTypeAndShapeInfo ConstValueImpl::GetTensorTypeAndShapeInfo() const { + OrtTensorTypeAndShapeInfo* output; + ThrowOnError(GetApi().GetTensorTypeAndShape(this->p_, &output)); + return TensorTypeAndShapeInfo{output}; +} + +template +inline ConstMemoryInfo ConstValueImpl::GetTensorMemoryInfo() const { + const OrtMemoryInfo* mem_info; + ThrowOnError(GetApi().GetTensorMemoryInfo(this->p_, &mem_info)); + return ConstMemoryInfo(mem_info); +} + +template +inline void ConstValueImpl::GetStringTensorElement(size_t buffer_length, size_t element_index, void* buffer) const { + ThrowOnError(GetApi().GetStringTensorElement(this->p_, buffer_length, element_index, buffer)); +} + +template +inline std::string ConstValueImpl::GetStringTensorElement(size_t element_index) const { + size_t buffer_length; + ThrowOnError(GetApi().GetStringTensorElementLength(this->p_, element_index, &buffer_length)); + + std::string s; + s.resize(buffer_length); + ThrowOnError(GetApi().GetStringTensorElement(this->p_, buffer_length, element_index, &s[0])); + return s; +} + +template +inline void ConstValueImpl::GetStringTensorContent(void* buffer, size_t buffer_length, size_t* offsets, size_t offsets_count) const { + ThrowOnError(GetApi().GetStringTensorContent(this->p_, buffer, buffer_length, offsets, offsets_count)); +} + +#if !defined(DISABLE_SPARSE_TENSORS) +template +inline OrtSparseFormat ConstValueImpl::GetSparseFormat() const { + OrtSparseFormat format; + ThrowOnError(GetApi().GetSparseTensorFormat(this->p_, &format)); + return format; +} + +template +inline TensorTypeAndShapeInfo ConstValueImpl::GetSparseTensorValuesTypeAndShapeInfo() const { + OrtTensorTypeAndShapeInfo* output; + ThrowOnError(GetApi().GetSparseTensorValuesTypeAndShape(this->p_, &output)); + return TensorTypeAndShapeInfo{output}; +} + +template +inline TensorTypeAndShapeInfo ConstValueImpl::GetSparseTensorIndicesTypeShapeInfo(OrtSparseIndicesFormat indices_format) const { + OrtTensorTypeAndShapeInfo* output; + ThrowOnError(GetApi().GetSparseTensorIndicesTypeShape(this->p_, indices_format, &output)); + return TensorTypeAndShapeInfo{output}; +} + +template +template +inline const R* ConstValueImpl::GetSparseTensorIndicesData(OrtSparseIndicesFormat indices_format, size_t& num_indices) const { + const void* out; + ThrowOnError(GetApi().GetSparseTensorIndices(this->p_, indices_format, &num_indices, &out)); + return reinterpret_cast(out); +} + +template +inline bool ConstValueImpl::IsSparseTensor() const { + int out; + ThrowOnError(GetApi().IsSparseTensor(this->p_, &out)); + return out != 0; +} + +template +template +inline const R* ConstValueImpl::GetSparseTensorValues() const { + const void* out; + ThrowOnError(GetApi().GetSparseTensorValues(this->p_, &out)); + return reinterpret_cast(out); +} + +#endif + +template +void ConstValueImpl::GetTensorElementTypeAndShapeDataReference(ONNXTensorElementDataType& elem_type, + Shape& shape) const { + ThrowOnError(GetApi().GetTensorElementTypeAndShapeDataReference(this->p_, &elem_type, &shape.shape, + &shape.shape_len)); +} + +template +void ValueImpl::FillStringTensor(const char* const* s, size_t s_len) { + ThrowOnError(GetApi().FillStringTensor(this->p_, s, s_len)); +} + +template +void ValueImpl::FillStringTensorElement(const char* s, size_t index) { + ThrowOnError(GetApi().FillStringTensorElement(this->p_, s, index)); +} + +template +inline char* ValueImpl::GetResizedStringTensorElementBuffer(size_t index, size_t buffer_length) { + char* result; + ThrowOnError(GetApi().GetResizedStringTensorElementBuffer(this->p_, index, buffer_length, &result)); + return result; +} + +template +void* ValueImpl::GetTensorMutableRawData() { + void* out; + ThrowOnError(GetApi().GetTensorMutableData(this->p_, &out)); + return out; +} + +template +template +R* ValueImpl::GetTensorMutableData() { + R* out; + ThrowOnError(GetApi().GetTensorMutableData(this->p_, (void**)&out)); + return out; +} + +template +template +R& ValueImpl::At(const std::vector& location) { + static_assert(!std::is_same::value, "this api does not support std::string"); + R* out; + ThrowOnError(GetApi().TensorAt(this->p_, location.data(), location.size(), (void**)&out)); + return *out; +} + +#if !defined(DISABLE_SPARSE_TENSORS) +template +void ValueImpl::UseCooIndices(int64_t* indices_data, size_t indices_num) { + ThrowOnError(GetApi().UseCooIndices(this->p_, indices_data, indices_num)); +} + +template +void ValueImpl::UseCsrIndices(int64_t* inner_data, size_t inner_num, int64_t* outer_data, size_t outer_num) { + ThrowOnError(GetApi().UseCsrIndices(this->p_, inner_data, inner_num, outer_data, outer_num)); +} + +template +void ValueImpl::UseBlockSparseIndices(const Shape& indices_shape, int32_t* indices_data) { + ThrowOnError(GetApi().UseBlockSparseIndices(this->p_, indices_shape.shape, indices_shape.shape_len, indices_data)); +} + +template +void ValueImpl::FillSparseTensorCoo(const OrtMemoryInfo* mem_info, const OrtSparseValuesParam& values_param, + const int64_t* indices_data, size_t indices_num) { + ThrowOnError(GetApi().FillSparseTensorCoo(this->p_, mem_info, values_param.values_shape, + values_param.values_shape_len, values_param.data.p_data, + indices_data, indices_num)); +} + +template +void ValueImpl::FillSparseTensorCsr(const OrtMemoryInfo* data_mem_info, + const OrtSparseValuesParam& values, + const int64_t* inner_indices_data, size_t inner_indices_num, + const int64_t* outer_indices_data, size_t outer_indices_num) { + ThrowOnError(GetApi().FillSparseTensorCsr(this->p_, data_mem_info, values.values_shape, values.values_shape_len, values.data.p_data, + inner_indices_data, inner_indices_num, + outer_indices_data, outer_indices_num)); +} + +template +void ValueImpl::FillSparseTensorBlockSparse(const OrtMemoryInfo* data_mem_info, + const OrtSparseValuesParam& values, + const Shape& indices_shape, + const int32_t* indices_data) { + ThrowOnError(GetApi().FillSparseTensorBlockSparse(this->p_, data_mem_info, values.values_shape, values.values_shape_len, values.data.p_data, + indices_shape.shape, indices_shape.shape_len, + indices_data)); +} + +#endif // !defined(DISABLE_SPARSE_TENSORS) + +} // namespace detail + +template +inline Value Value::CreateTensor(const OrtMemoryInfo* info, T* p_data, size_t p_data_element_count, + const int64_t* shape, size_t shape_len) { + return CreateTensor(info, p_data, p_data_element_count * sizeof(T), shape, shape_len, TypeToTensorType::type); +} + +inline Value Value::CreateTensor(const OrtMemoryInfo* info, void* p_data, size_t p_data_byte_count, + const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type) { + OrtValue* out; + ThrowOnError(GetApi().CreateTensorWithDataAsOrtValue(info, p_data, p_data_byte_count, shape, shape_len, type, &out)); + return Value{out}; +} + +inline Value Value::CreateTensor(OrtAllocator* deleter, void* p_data, size_t p_data_byte_count, + const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type) { + OrtValue* out; + ThrowOnError(GetApi().CreateTensorWithDataAndDeleterAsOrtValue(deleter, p_data, p_data_byte_count, + shape, shape_len, type, &out)); + return Value{out}; +} + +template +inline Value Value::CreateTensor(OrtAllocator* allocator, const int64_t* shape, size_t shape_len) { + return CreateTensor(allocator, shape, shape_len, TypeToTensorType::type); +} + +inline Value Value::CreateTensor(OrtAllocator* allocator, const int64_t* shape, size_t shape_len, + ONNXTensorElementDataType type) { + OrtValue* out; + ThrowOnError(GetApi().CreateTensorAsOrtValue(allocator, shape, shape_len, type, &out)); + return Value{out}; +} + +#if !defined(DISABLE_SPARSE_TENSORS) + +template +inline Value Value::CreateSparseTensor(const OrtMemoryInfo* info, T* p_data, const Shape& dense_shape, + const Shape& values_shape) { + return CreateSparseTensor(info, p_data, dense_shape, values_shape, TypeToTensorType::type); +} + +inline Value Value::CreateSparseTensor(const OrtMemoryInfo* info, void* p_data, const Shape& dense_shape, + const Shape& values_shape, ONNXTensorElementDataType type) { + OrtValue* out; + ThrowOnError(GetApi().CreateSparseTensorWithValuesAsOrtValue(info, p_data, dense_shape.shape, dense_shape.shape_len, + values_shape.shape, values_shape.shape_len, type, + &out)); + return Value{out}; +} + +template +inline Value Value::CreateSparseTensor(OrtAllocator* allocator, const Shape& dense_shape) { + return CreateSparseTensor(allocator, dense_shape, TypeToTensorType::type); +} + +inline Value Value::CreateSparseTensor(OrtAllocator* allocator, const Shape& dense_shape, + ONNXTensorElementDataType type) { + OrtValue* out; + ThrowOnError(GetApi().CreateSparseTensorAsOrtValue(allocator, dense_shape.shape, dense_shape.shape_len, type, &out)); + return Value{out}; +} +#endif // !defined(DISABLE_SPARSE_TENSORS) + +inline Value Value::CreateMap(const Value& keys, const Value& values) { + OrtValue* out; + const OrtValue* inputs[2] = {keys, values}; + ThrowOnError(GetApi().CreateValue(inputs, 2, ONNX_TYPE_MAP, &out)); + return Value{out}; +} + +inline Value Value::CreateSequence(const std::vector& values) { + OrtValue* out; + std::vector values_ort{values.data(), values.data() + values.size()}; + ThrowOnError(GetApi().CreateValue(values_ort.data(), values_ort.size(), ONNX_TYPE_SEQUENCE, &out)); + return Value{out}; +} + +template +inline Value Value::CreateOpaque(const char* domain, const char* type_name, const T& data_container) { + OrtValue* out; + ThrowOnError(GetApi().CreateOpaqueValue(domain, type_name, &data_container, sizeof(T), &out)); + return Value{out}; +} + +// +// Custom OP Inlines +// +inline Logger::Logger(const OrtLogger* logger) : logger_(logger) { + Ort::ThrowOnError(GetApi().Logger_GetLoggingSeverityLevel(this->logger_, &this->cached_severity_level_)); +} + +inline OrtLoggingLevel Logger::GetLoggingSeverityLevel() const noexcept { + return cached_severity_level_; +} + +inline Status Logger::LogMessage(OrtLoggingLevel log_severity_level, const ORTCHAR_T* file_path, int line_number, + const char* func_name, const char* message) const noexcept { + OrtStatus* status = GetApi().Logger_LogMessage(logger_, log_severity_level, message, file_path, line_number, + func_name); + return Status{status}; +} + +// Disable warnings about the format string not being a literal (-Wformat-nonliteral and -Wformat-security) +// for gcc and clang. The alternative is to use actual C-style variadic parameters and apply +// __attribute__(format(printf...)), which does not work with variadic templates. +#if defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wformat-nonliteral" +#pragma GCC diagnostic ignored "-Wformat-security" +#elif defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wformat-nonliteral" +#pragma clang diagnostic ignored "-Wformat-security" +#endif +template +inline Status Logger::LogFormattedMessage(OrtLoggingLevel log_severity_level, const ORTCHAR_T* file_path, + int line_number, const char* func_name, const char* format, + Args&&... args) const noexcept { + int msg_len = std::snprintf(nullptr, 0U, format, std::forward(args)...); + + if (msg_len < 0) { // Formatting error + return Status("Failed to log message due to formatting error", OrtErrorCode::ORT_FAIL); + } + + OrtStatus* status = nullptr; + const size_t buffer_size = static_cast(msg_len) + 1U; + + constexpr size_t kStackBufferSize = 1024; + + if (buffer_size < kStackBufferSize) { + char buffer[kStackBufferSize]; + snprintf(buffer, kStackBufferSize, format, std::forward(args)...); + status = GetApi().Logger_LogMessage(logger_, log_severity_level, buffer, file_path, line_number, func_name); + } else { + // std::make_unique is only supported starting at C++14. +#if (__cplusplus >= 201402L) || (_MSC_VER >= 1900) + auto buffer = std::make_unique(buffer_size); +#else + std::unique_ptr buffer(new char[buffer_size]); +#endif + std::snprintf(buffer.get(), buffer_size, format, std::forward(args)...); + status = GetApi().Logger_LogMessage(logger_, log_severity_level, buffer.get(), file_path, line_number, func_name); + } + + return Status{status}; +} +// Re-enable -Wformat-nonliteral and -Wformat-security +#if defined(__GNUC__) +#pragma GCC diagnostic pop +#elif defined(__clang__) +#pragma clang diagnostic pop +#endif + +inline KernelContext::KernelContext(OrtKernelContext* context) : ctx_(context) { +} + +inline size_t KernelContext::GetInputCount() const { + size_t out = 0; + Ort::ThrowOnError(GetApi().KernelContext_GetInputCount(ctx_, &out)); + return out; +} + +inline size_t KernelContext::GetOutputCount() const { + size_t out = 0; + Ort::ThrowOnError(GetApi().KernelContext_GetOutputCount(ctx_, &out)); + return out; +} + +inline ConstValue KernelContext::GetInput(size_t index) const { + const OrtValue* out = nullptr; + Ort::ThrowOnError(GetApi().KernelContext_GetInput(ctx_, index, &out)); + return ConstValue{out}; +} + +inline UnownedValue KernelContext::GetOutput(size_t index, const int64_t* dim_values, size_t dim_count) const { + OrtValue* out = nullptr; + Ort::ThrowOnError(GetApi().KernelContext_GetOutput(ctx_, index, dim_values, dim_count, &out)); + return UnownedValue(out); +} + +inline UnownedValue KernelContext::GetOutput(size_t index, const std::vector& dims) const { + OrtValue* out = nullptr; + Ort::ThrowOnError(GetApi().KernelContext_GetOutput(ctx_, index, dims.data(), dims.size(), &out)); + return UnownedValue(out); +} + +inline void* KernelContext::GetGPUComputeStream() const { + void* out = nullptr; + Ort::ThrowOnError(GetApi().KernelContext_GetGPUComputeStream(ctx_, &out)); + return out; +} + +inline Ort::Allocator KernelContext::GetAllocator(const OrtMemoryInfo& memory_info) const { + OrtAllocator* out = nullptr; + Ort::ThrowOnError(GetApi().KernelContext_GetAllocator(ctx_, &memory_info, &out)); + return Ort::Allocator{out}; +} + +inline Logger KernelContext::GetLogger() const { + const OrtLogger* out = nullptr; + ThrowOnError(GetApi().KernelContext_GetLogger(this->ctx_, &out)); + return Logger{out}; +} + +inline void KernelContext::ParallelFor(void (*fn)(void*, size_t), size_t total, size_t num_batch, void* usr_data) const { + ThrowOnError(GetApi().KernelContext_ParallelFor(ctx_, fn, total, num_batch, usr_data)); +} + +namespace detail { + +template +constexpr OrtOpAttrType TypeToAttrType(); + +template <> +inline constexpr OrtOpAttrType TypeToAttrType() { + return OrtOpAttrType::ORT_OP_ATTR_INT; +} + +template <> +inline constexpr OrtOpAttrType TypeToAttrType() { + return OrtOpAttrType::ORT_OP_ATTR_FLOAT; +} + +template +inline constexpr OrtOpAttrType TypeToAttrsType(); + +template <> +inline constexpr OrtOpAttrType TypeToAttrsType() { + return OrtOpAttrType::ORT_OP_ATTR_INTS; +} + +template <> +inline constexpr OrtOpAttrType TypeToAttrsType() { + return OrtOpAttrType::ORT_OP_ATTR_FLOATS; +} + +inline Status CheckAttrType(const OrtOpAttr* attr, OrtOpAttrType requested_type) { + OrtOpAttrType type; + Ort::Status status(GetApi().OpAttr_GetType(attr, &type)); + if (!status.IsOK()) return status; + if (requested_type != type) { + std::string msg = "Attribute type mismatch: expected " + std::to_string(requested_type) + + ", but got " + std::to_string(type); + return Ort::Status(msg.c_str(), OrtErrorCode::ORT_INVALID_ARGUMENT); + } + return Ort::Status{}; +} + +inline size_t GetDataSize(const OrtOpAttr* attr, OrtOpAttrType attr_type) { + size_t result{}; + // Ignore the status here because we check the data type so the error should only be about + // the size + [[maybe_unused]] Status status{GetApi().ReadOpAttr(attr, attr_type, nullptr, 0, &result)}; + return result; +} + +template +Ort::Status GetNumericValue(const OrtOpAttr* attr, T& out) { + static_assert(std::is_arithmetic::value, "T must be an arithmetic type"); + size_t size{}; + return Ort::Status{GetApi().ReadOpAttr(attr, TypeToAttrType(), &out, sizeof(out), &size)}; +} + +template +struct GetValueImpl { + static Status GetValue(const OrtOpAttr* attr, T& out) { + return GetNumericValue(attr, out); + } + static Status GetValues(const OrtOpAttr* attr, std::vector& out) { + // Api deficiency when it comes to value arrays. It is not possible + // to tell if the error is due to the type mismatch or the size + // so we check the type first, and then ignore the status of the size check + constexpr auto deduced_type = TypeToAttrsType(); + auto status = CheckAttrType(attr, deduced_type); + if (!status.IsOK()) return status; + auto size = GetDataSize(attr, deduced_type); + std::vector result; + if (size > 0) { + result.resize(size / sizeof(T)); + status = Status{GetApi().ReadOpAttr( + attr, deduced_type, result.data(), size, &size)}; + if (!status.IsOK()) return status; + } + out.swap(result); + return status; + } +}; + +// Create GetValueImpl specializations for std::string +template <> +struct GetValueImpl { + static Status GetValue(const OrtOpAttr* attr, std::string& out) { + // Api deficiency when it comes to value arrays. It is not possible + // to tell if the error is due to the type mismatch or the size + // so we check the type first, and then ignore the status of the size check + auto status = CheckAttrType(attr, OrtOpAttrType::ORT_OP_ATTR_STRING); + if (!status.IsOK()) return status; + auto size = GetDataSize(attr, OrtOpAttrType::ORT_OP_ATTR_STRING); + std::string result; + if (size > 0) { + result.resize(size); + // some compilers in use do not support std::string::data() non-const + auto* buffer = &result[0]; + status = Status{GetApi().ReadOpAttr( + attr, OrtOpAttrType::ORT_OP_ATTR_STRING, buffer, size, &size)}; + if (!status.IsOK()) return status; + } + out.swap(result); + return status; + } + static Status GetValues(const OrtOpAttr* attr, std::vector& out) { + auto status = CheckAttrType(attr, OrtOpAttrType::ORT_OP_ATTR_STRINGS); + if (!status.IsOK()) return status; + + std::vector result; + size_t total_buffer_size = GetDataSize(attr, OrtOpAttrType::ORT_OP_ATTR_STRINGS); + if (total_buffer_size > 0) { + // Create a temporary buffer to hold the string data + std::vector buffer(total_buffer_size); + status = Status{GetApi().ReadOpAttr(attr, OrtOpAttrType::ORT_OP_ATTR_STRINGS, buffer.data(), + total_buffer_size, &total_buffer_size)}; + if (!status.IsOK()) return status; + + const char* data = buffer.data(); + const char* end = data + total_buffer_size; + while (data < end) { + result.emplace_back(data); + data += result.back().size() + 1; // Move past the null terminator + } + } + out.swap(result); + return status; + } +}; + +template +template +inline Status ConstOpAttrImpl::GetValue(R& out) const { + return GetValueImpl::GetValue(this->p_, out); +} + +template +template +inline Status ConstOpAttrImpl::GetValueArray(std::vector& out) const { + return GetValueImpl::GetValues(this->p_, out); +} + +template +inline Status ConstOpAttrImpl::GetTensorAttributeAsOrtValue(Value& out) const { + OrtValue* tensor_value = nullptr; + auto status = Status(GetApi().OpAttr_GetTensorAttributeAsOrtValue(this->p_, &tensor_value)); + if (!status.IsOK()) return status; + out = Value{tensor_value}; + return status; +} + +template +inline std::string ConstOpAttrImpl::GetName() const { + const char* name = nullptr; + ThrowOnError(GetApi().OpAttr_GetName(this->p_, &name)); + if (name != nullptr) { + return name; + } + return {}; +} + +template +inline OrtOpAttrType ConstOpAttrImpl::GetType() const { + OrtOpAttrType type; + ThrowOnError(GetApi().OpAttr_GetType(this->p_, &type)); + return type; +} +} // namespace detail + +inline OpAttr::OpAttr(const char* name, const void* data, int len, OrtOpAttrType type) { + Ort::ThrowOnError(GetApi().CreateOpAttr(name, data, len, type, &p_)); +} + +namespace detail { +template +inline KernelInfo KernelInfoImpl::Copy() const { + OrtKernelInfo* info_copy = nullptr; + Ort::ThrowOnError(GetApi().CopyKernelInfo(this->p_, &info_copy)); + return KernelInfo{info_copy}; +} + +template +inline size_t KernelInfoImpl::GetInputCount() const { + size_t out = 0; + ThrowOnError(GetApi().KernelInfo_GetInputCount(this->p_, &out)); + return out; +} + +template +inline size_t KernelInfoImpl::GetOutputCount() const { + size_t out = 0; + ThrowOnError(GetApi().KernelInfo_GetOutputCount(this->p_, &out)); + return out; +} + +template +inline std::string KernelInfoImpl::GetInputName(size_t index) const { + size_t size = 0; + + // Feed nullptr for the data buffer to query the true size of the string value + Ort::ThrowOnError(GetApi().KernelInfo_GetInputName(this->p_, index, nullptr, &size)); + + std::string out; + out.resize(size); + Ort::ThrowOnError(GetApi().KernelInfo_GetInputName(this->p_, index, &out[0], &size)); + out.resize(size - 1); // remove the terminating character '\0' + + return out; +} + +template +inline std::string KernelInfoImpl::GetOutputName(size_t index) const { + size_t size = 0; + + // Feed nullptr for the data buffer to query the true size of the string value + Ort::ThrowOnError(GetApi().KernelInfo_GetOutputName(this->p_, index, nullptr, &size)); + + std::string out; + out.resize(size); + Ort::ThrowOnError(GetApi().KernelInfo_GetOutputName(this->p_, index, &out[0], &size)); + out.resize(size - 1); // remove the terminating character '\0' + + return out; +} + +template +inline TypeInfo KernelInfoImpl::GetInputTypeInfo(size_t index) const { + OrtTypeInfo* out = nullptr; + ThrowOnError(GetApi().KernelInfo_GetInputTypeInfo(this->p_, index, &out)); + return TypeInfo{out}; +} + +template +inline TypeInfo KernelInfoImpl::GetOutputTypeInfo(size_t index) const { + OrtTypeInfo* out = nullptr; + ThrowOnError(GetApi().KernelInfo_GetOutputTypeInfo(this->p_, index, &out)); + return TypeInfo{out}; +} + +template +inline Value KernelInfoImpl::GetTensorAttribute(const char* name, OrtAllocator* allocator) const { + OrtValue* out = nullptr; + ThrowOnError(GetApi().KernelInfoGetAttribute_tensor(this->p_, name, allocator, &out)); + return Value{out}; +} + +template +inline ConstValue KernelInfoImpl::GetTensorConstantInput(size_t index, int* is_constant) const { + const OrtValue* out = nullptr; + ThrowOnError(GetApi().KernelInfoGetConstantInput_tensor(this->p_, index, is_constant, &out)); + return ConstValue{out}; +} + +template +inline std::string KernelInfoImpl::GetNodeName() const { + size_t size = 0; + + // Feed nullptr for the data buffer to query the true size of the string value + Ort::ThrowOnError(GetApi().KernelInfo_GetNodeName(this->p_, nullptr, &size)); + + std::string out; + out.resize(size); + Ort::ThrowOnError(GetApi().KernelInfo_GetNodeName(this->p_, &out[0], &size)); + out.resize(size - 1); // remove the terminating character '\0' + + return out; +} + +template +inline Logger KernelInfoImpl::GetLogger() const { + const OrtLogger* out = nullptr; + ThrowOnError(GetApi().KernelInfo_GetLogger(this->p_, &out)); + return Logger{out}; +} + +template +inline KeyValuePairs KernelInfoImpl::GetConfigEntries() const { + OrtKeyValuePairs* out = nullptr; + Ort::ThrowOnError(GetApi().KernelInfo_GetConfigEntries(this->p_, &out)); + return KeyValuePairs{out}; +} + +template +inline std::string KernelInfoImpl::GetOperatorDomain() const { + size_t size = 0; + + // Feed nullptr for the data buffer to query the true size of the string value + Ort::ThrowOnError(GetApi().KernelInfo_GetOperatorDomain(this->p_, nullptr, &size)); + + std::string out; + out.resize(size); + Ort::ThrowOnError(GetApi().KernelInfo_GetOperatorDomain(this->p_, &out[0], &size)); + out.resize(size - 1); // remove the terminating character '\0' + + return out; +} + +template +inline std::string KernelInfoImpl::GetOperatorType() const { + size_t size = 0; + + // Feed nullptr for the data buffer to query the true size of the string value + Ort::ThrowOnError(GetApi().KernelInfo_GetOperatorType(this->p_, nullptr, &size)); + + std::string out; + out.resize(size); + Ort::ThrowOnError(GetApi().KernelInfo_GetOperatorType(this->p_, &out[0], &size)); + out.resize(size - 1); // remove the terminating character '\0' + + return out; +} + +template +inline int KernelInfoImpl::GetOperatorSinceVersion() const { + int out = 0; + Ort::ThrowOnError(GetApi().KernelInfo_GetOperatorSinceVersion(this->p_, &out)); + return out; +} + +template +inline const OrtEp* KernelInfoImpl::GetEp() const { + const OrtEp* ep = nullptr; + Ort::ThrowOnError(GetEpApi().KernelInfo_GetEp(this->p_, &ep)); + return ep; +} + +inline void attr_utils::GetAttr(const OrtKernelInfo* p, const char* name, float& out) { + Ort::ThrowOnError(GetApi().KernelInfoGetAttribute_float(p, name, &out)); +} + +inline void attr_utils::GetAttr(const OrtKernelInfo* p, const char* name, int64_t& out) { + Ort::ThrowOnError(GetApi().KernelInfoGetAttribute_int64(p, name, &out)); +} + +inline void attr_utils::GetAttr(const OrtKernelInfo* p, const char* name, std::string& result) { + size_t size = 0; + // Feed nullptr for the data buffer to query the true size of the string attribute + Ort::ThrowOnError(GetApi().KernelInfoGetAttribute_string(p, name, nullptr, &size)); + + std::string out; + out.resize(size); + Ort::ThrowOnError(GetApi().KernelInfoGetAttribute_string(p, name, &out[0], &size)); + out.resize(size - 1); // remove the terminating character '\0' + out.swap(result); +} + +inline void attr_utils::GetAttrs(const OrtKernelInfo* p, const char* name, std::vector& result) { + size_t size = 0; + // Feed nullptr for the data buffer to query the true size of the attribute + Ort::ThrowOnError(GetApi().KernelInfoGetAttributeArray_float(p, name, nullptr, &size)); + + std::vector out; + out.resize(size); + Ort::ThrowOnError(GetApi().KernelInfoGetAttributeArray_float(p, name, out.data(), &size)); + out.swap(result); +} + +inline void attr_utils::GetAttrs(const OrtKernelInfo* p, const char* name, std::vector& result) { + size_t size = 0; + + // Feed nullptr for the data buffer to query the true size of the attribute + Ort::ThrowOnError(GetApi().KernelInfoGetAttributeArray_int64(p, name, nullptr, &size)); + + std::vector out; + out.resize(size); + Ort::ThrowOnError(GetApi().KernelInfoGetAttributeArray_int64(p, name, out.data(), &size)); + out.swap(result); +} + +inline void attr_utils::GetAttrs(const OrtKernelInfo* p, const char* name, std::vector& result) { + AllocatorWithDefaultOptions allocator; + char** out = nullptr; + size_t size = 0; + + Ort::ThrowOnError(GetApi().KernelInfoGetAttributeArray_string(p, name, allocator, nullptr, &size)); + if (size == 0) { + result.clear(); + return; + } + + Ort::ThrowOnError(GetApi().KernelInfoGetAttributeArray_string(p, name, allocator, &out, &size)); + + auto deleter = detail::AllocatedFree(allocator); + std::unique_ptr array_guard(out, deleter); + auto strings_deleter = [&deleter, size](char** values) { + for (size_t i = 0; i < size; ++i) { + if (values[i] != nullptr) { + deleter(values[i]); + } + } + }; + std::unique_ptr strings_guard(out, strings_deleter); + + std::vector strings; + strings.reserve(size); + for (size_t i = 0; i < size; ++i) { + strings.emplace_back(out[i]); + } + + strings.swap(result); +} +} // namespace detail + +inline KernelInfo::KernelInfo(OrtKernelInfo* info) : detail::KernelInfoImpl{info} {} + +inline Op::Op(OrtOp* p) : detail::Base(p) {} + +inline Op Op::Create(const OrtKernelInfo* info, const char* op_name, const char* domain, int version, + const char** type_constraint_names, + const ONNXTensorElementDataType* type_constraint_values, + size_t type_constraint_count, + const OpAttr* attr_values, size_t attr_count, + size_t input_count, size_t output_count) { + static_assert(sizeof(OpAttr) == sizeof(OrtOpAttr*), + "OpAttr's is expected to be just an array of OrtOpAttr in memory so we can reinterpret safely"); + auto attr_input_values = reinterpret_cast(attr_values); + OrtOp* op; + Ort::ThrowOnError(GetApi().CreateOp(info, op_name, domain, version, type_constraint_names, type_constraint_values, + static_cast(type_constraint_count), + attr_input_values, + static_cast(attr_count), + static_cast(input_count), + static_cast(output_count), &op)); + return Op{op}; +} + +inline void Op::Invoke(const OrtKernelContext* context, + const Value* input_values, + size_t input_count, + Value* output_values, + size_t output_count) { + static_assert(sizeof(Value) == sizeof(OrtValue*), + "Value is really just an array of OrtValue* in memory, so we can reinterpret_cast safely"); + auto ort_input_values = reinterpret_cast(input_values); + auto ort_output_values = reinterpret_cast(output_values); + Ort::ThrowOnError(GetApi().InvokeOp(context, p_, ort_input_values, static_cast(input_count), + ort_output_values, static_cast(output_count))); +} + +inline void Op::Invoke(const OrtKernelContext* context, + const OrtValue* const* input_values, + size_t input_count, + OrtValue* const* output_values, + size_t output_count) { + Ort::ThrowOnError(GetApi().InvokeOp(context, p_, input_values, static_cast(input_count), + output_values, static_cast(output_count))); +} + +inline std::string GetVersionString() { + return OrtGetApiBase()->GetVersionString(); +} + +inline std::string GetBuildInfoString() { + return GetApi().GetBuildInfoString(); +} + +inline std::vector GetAvailableProviders() { + char** providers; + int len; + + auto release_fn = [&len](char** providers) { + // This should always return nullptr. + ThrowOnError(GetApi().ReleaseAvailableProviders(providers, len)); + }; + + ThrowOnError(GetApi().GetAvailableProviders(&providers, &len)); + std::unique_ptr guard(providers, release_fn); + std::vector available_providers; + available_providers.reserve(static_cast(len)); + for (int i = 0; i < len; ++i) { + available_providers.emplace_back(providers[i]); + } + return available_providers; +} + +template +void CustomOpBase::GetSessionConfigs(std::unordered_map& out, + ConstSessionOptions options) const { + const TOp* derived = static_cast(this); + std::vector keys = derived->GetSessionConfigKeys(); + + out.reserve(keys.size()); + + std::string config_entry_key = detail::MakeCustomOpConfigEntryKey(derived->GetName(), ""); + const size_t prefix_size = config_entry_key.length(); + + for (const auto& key : keys) { + config_entry_key.resize(prefix_size); + config_entry_key.append(key); + out[key] = options.GetConfigEntryOrDefault(config_entry_key.c_str(), ""); + } +} + +inline ShapeInferContext::ShapeInferContext(const OrtApi* ort_api, + OrtShapeInferContext* ctx) : ort_api_(ort_api), ctx_(ctx) { + size_t input_count = 0; + Ort::ThrowOnError(ort_api_->ShapeInferContext_GetInputCount(ctx_, &input_count)); + for (size_t ith_input = 0; ith_input < input_count; ++ith_input) { + OrtTensorTypeAndShapeInfo* info{}; + Ort::ThrowOnError(ort_api_->ShapeInferContext_GetInputTypeShape(ctx, ith_input, &info)); + TensorTypeAndShapeInfo type_shape_info(info); + auto integer_shape = type_shape_info.GetShape(); + std::vector symbolic_shape(integer_shape.size(), {}); + if (!integer_shape.empty()) { + type_shape_info.GetSymbolicDimensions(&symbolic_shape[0], integer_shape.size()); + } + Shape shape; + for (size_t ith = 0; ith < integer_shape.size(); ++ith) { + if (symbolic_shape[ith] && std::string{symbolic_shape[ith]}.size() > 0) { + shape.emplace_back(symbolic_shape[ith]); + } else { + shape.emplace_back(integer_shape[ith]); + } + } + input_shapes_.push_back(std::move(shape)); + type_shape_info.release(); + } +} + +inline Status ShapeInferContext::SetOutputShape(size_t indice, const Shape& shape, ONNXTensorElementDataType type) { + OrtTensorTypeAndShapeInfo* info = {}; + ORT_CXX_RETURN_ON_API_FAIL(ort_api_->CreateTensorTypeAndShapeInfo(&info)); + ORT_CXX_RETURN_ON_API_FAIL(ort_api_->SetTensorElementType(info, type)); + + using InfoPtr = std::unique_ptr>; + + InfoPtr info_ptr(info, [this](OrtTensorTypeAndShapeInfo* obj) { + ort_api_->ReleaseTensorTypeAndShapeInfo(obj); + }); + + std::vector integer_dims; + std::vector symbolic_dims; + + for (const auto dim : shape) { + if (dim.IsInt()) { + integer_dims.push_back(dim.AsInt()); + symbolic_dims.push_back(""); + } else { + if (!dim.AsSym() || std::string{dim.AsSym()}.empty()) { + ORT_CXX_API_THROW("Symbolic dim must not be an empty string", ORT_INVALID_ARGUMENT); + } + integer_dims.push_back(SymbolicInteger::INVALID_INT_DIM); + symbolic_dims.push_back(dim.AsSym()); + } + } + + ORT_CXX_RETURN_ON_API_FAIL(ort_api_->SetDimensions(info, integer_dims.data(), integer_dims.size())); + ORT_CXX_RETURN_ON_API_FAIL(ort_api_->SetSymbolicDimensions(info, symbolic_dims.data(), symbolic_dims.size())); + ORT_CXX_RETURN_ON_API_FAIL(ort_api_->ShapeInferContext_SetOutputTypeShape(ctx_, indice, info)); + return Status{nullptr}; +} + +inline int64_t ShapeInferContext::GetAttrInt(const char* attr_name) { + auto attr = GetAttrHdl(attr_name); + int64_t value; + Status status = attr.GetValue(value); + if (!status.IsOK()) { + ORT_CXX_API_THROW("Getting int attribute failed: " + status.GetErrorMessage(), status.GetErrorCode()); + } + return value; +} + +inline ShapeInferContext::Ints ShapeInferContext::GetAttrInts(const char* attr_name) { + auto attr = GetAttrHdl(attr_name); + ShapeInferContext::Ints result; + auto status = attr.GetValueArray(result); + if (!status.IsOK()) { + ORT_CXX_API_THROW("Getting ints attribute failed: " + status.GetErrorMessage(), status.GetErrorCode()); + } + return result; +} + +inline float ShapeInferContext::GetAttrFloat(const char* attr_name) { + auto attr = GetAttrHdl(attr_name); + float value; + Status status = attr.GetValue(value); + if (!status.IsOK()) { + ORT_CXX_API_THROW("Getting float attribute failed: " + status.GetErrorMessage(), status.GetErrorCode()); + } + return value; +} + +inline ShapeInferContext::Floats ShapeInferContext::GetAttrFloats(const char* attr_name) { + auto attr = GetAttrHdl(attr_name); + ShapeInferContext::Floats result; + auto status = attr.GetValueArray(result); + if (!status.IsOK()) { + ORT_CXX_API_THROW("Getting floats attribute failed: " + status.GetErrorMessage(), status.GetErrorCode()); + } + return result; +} + +inline std::string ShapeInferContext::GetAttrString(const char* attr_name) { + auto attr = GetAttrHdl(attr_name); + std::string value; + Status status = attr.GetValue(value); + if (!status.IsOK()) { + ORT_CXX_API_THROW("Getting string attribute failed: " + status.GetErrorMessage(), status.GetErrorCode()); + } + return value; +} + +inline ShapeInferContext::Strings ShapeInferContext::GetAttrStrings(const char* attr_name) { + auto attr = GetAttrHdl(attr_name); + ShapeInferContext::Strings result; + auto status = attr.GetValueArray(result); + if (!status.IsOK()) { + ORT_CXX_API_THROW("Getting strings attribute failed: " + status.GetErrorMessage(), status.GetErrorCode()); + } + return result; +} + +inline ConstOpAttr ShapeInferContext::GetAttrHdl(const char* attr_name) const { + const OrtOpAttr* attr_hdl = {}; + Ort::ThrowOnError(ort_api_->ShapeInferContext_GetAttribute(ctx_, attr_name, &attr_hdl)); + return ConstOpAttr{attr_hdl}; +} + +namespace detail { +inline std::vector StringsToCharPtrs(const std::vector& strings) { + std::vector ptrs; + ptrs.reserve(strings.size()); + std::transform(strings.begin(), strings.end(), std::back_inserter(ptrs), + [](const std::string& s) { return s.c_str(); }); + + return ptrs; +} +} // namespace detail + +namespace detail { +template +inline size_t ConstNodeImpl::GetId() const { + size_t id; + ThrowOnError(GetApi().Node_GetId(this->p_, &id)); + return id; +} + +template +inline std::string ConstNodeImpl::GetName() const { + const char* name; + ThrowOnError(GetApi().Node_GetName(this->p_, &name)); + return std::string(name); +} + +template +inline std::string ConstNodeImpl::GetOperatorType() const { + const char* type; + ThrowOnError(GetApi().Node_GetOperatorType(this->p_, &type)); + return std::string(type); +} template -inline Value Value::CreateTensor(const OrtMemoryInfo* info, T* p_data, size_t p_data_element_count, const int64_t* shape, size_t shape_len) { - return CreateTensor(info, p_data, p_data_element_count * sizeof(T), shape, shape_len, TypeToTensorType::type); +inline std::string ConstNodeImpl::GetDomain() const { + const char* domain; + ThrowOnError(GetApi().Node_GetDomain(this->p_, &domain)); + return std::string(domain); } -inline Value Value::CreateTensor(const OrtMemoryInfo* info, void* p_data, size_t p_data_byte_count, const int64_t* shape, size_t shape_len, - ONNXTensorElementDataType type) { - OrtValue* out; - ThrowOnError(GetApi().CreateTensorWithDataAsOrtValue(info, p_data, p_data_byte_count, shape, shape_len, type, &out)); - return Value{out}; +template +inline int ConstNodeImpl::GetSinceVersion() const { + int since_version; + ThrowOnError(GetApi().Node_GetSinceVersion(this->p_, &since_version)); + return since_version; } template -inline Value Value::CreateTensor(OrtAllocator* allocator, const int64_t* shape, size_t shape_len) { - return CreateTensor(allocator, shape, shape_len, TypeToTensorType::type); +inline std::vector ConstNodeImpl::GetInputs() const { + static_assert(sizeof(const OrtValueInfo*) == sizeof(ConstValueInfo)); + size_t num_vi; + ThrowOnError(GetApi().Node_GetNumInputs(this->p_, &num_vi)); + std::vector result; + if (num_vi > 0) { + result.resize(num_vi); + ThrowOnError(GetApi().Node_GetInputs(this->p_, reinterpret_cast(result.data()), num_vi)); + } + return result; } -inline Value Value::CreateTensor(OrtAllocator* allocator, const int64_t* shape, size_t shape_len, ONNXTensorElementDataType type) { - OrtValue* out; - ThrowOnError(GetApi().CreateTensorAsOrtValue(allocator, shape, shape_len, type, &out)); - return Value{out}; +template +inline std::vector ConstNodeImpl::GetOutputs() const { + static_assert(sizeof(const OrtValueInfo*) == sizeof(ConstValueInfo)); + size_t num_vi; + ThrowOnError(GetApi().Node_GetNumOutputs(this->p_, &num_vi)); + std::vector result; + if (num_vi > 0) { + result.resize(num_vi); + ThrowOnError(GetApi().Node_GetOutputs(this->p_, reinterpret_cast(result.data()), num_vi)); + } + return result; } -#if !defined(DISABLE_SPARSE_TENSORS) +template +inline std::vector ConstNodeImpl::GetImplicitInputs() const { + static_assert(sizeof(const OrtValueInfo*) == sizeof(ConstValueInfo)); + size_t num_vi; + ThrowOnError(GetApi().Node_GetNumImplicitInputs(this->p_, &num_vi)); + std::vector result; + if (num_vi > 0) { + result.resize(num_vi); + ThrowOnError(GetApi().Node_GetImplicitInputs(this->p_, reinterpret_cast(result.data()), + num_vi)); + } + return result; +} template -inline Value Value::CreateSparseTensor(const OrtMemoryInfo* info, T* p_data, const Shape& dense_shape, - const Shape& values_shape) { - return CreateSparseTensor(info, p_data, dense_shape, values_shape, TypeToTensorType::type); +inline std::vector ConstNodeImpl::GetAttributes() const { + static_assert(sizeof(const OrtOpAttr*) == sizeof(ConstOpAttr), "Must be the same size"); + size_t num_attrs; + ThrowOnError(GetApi().Node_GetNumAttributes(this->p_, &num_attrs)); + std::vector attrs; + if (num_attrs > 0) { + attrs.resize(num_attrs); + ThrowOnError(GetApi().Node_GetAttributes(this->p_, reinterpret_cast(attrs.data()), num_attrs)); + } + return attrs; } -inline Value Value::CreateSparseTensor(const OrtMemoryInfo* info, void* p_data, const Shape& dense_shape, - const Shape& values_shape, ONNXTensorElementDataType type) { - OrtValue* out; - ThrowOnError(GetApi().CreateSparseTensorWithValuesAsOrtValue(info, p_data, dense_shape.shape, dense_shape.shape_len, - values_shape.shape, values_shape.shape_len, type, &out)); - return Value{out}; +template +inline Status ConstNodeImpl::GetAttributeByName(const std::string& name, ConstOpAttr& out) const { + const OrtOpAttr* attr = nullptr; + auto status = Status(GetApi().Node_GetAttributeByName(this->p_, name.c_str(), &attr)); + out = ConstOpAttr{attr}; + return status; } template -inline Value Value::CreateSparseTensor(OrtAllocator* allocator, const Shape& dense_shape) { - return CreateSparseTensor(allocator, dense_shape, TypeToTensorType::type); +inline std::vector ConstNodeImpl::GetSubgraphs() const { + size_t num_graphs; + ThrowOnError(GetApi().Node_GetNumSubgraphs(this->p_, &num_graphs)); + std::vector result; + if (num_graphs > 0) { + std::vector sub_graphs(num_graphs); + std::vector attr_names(num_graphs); + ThrowOnError(GetApi().Node_GetSubgraphs(this->p_, sub_graphs.data(), num_graphs, attr_names.data())); + result.reserve(num_graphs); + for (size_t i = 0; i < num_graphs; ++i) { + result.push_back({std::string(attr_names[i]), ConstGraph{sub_graphs[i]}}); + } + } + return result; } -inline Value Value::CreateSparseTensor(OrtAllocator* allocator, const Shape& dense_shape, - ONNXTensorElementDataType type) { - OrtValue* out; - ThrowOnError(GetApi().CreateSparseTensorAsOrtValue(allocator, dense_shape.shape, dense_shape.shape_len, type, &out)); - return Value{out}; +template +inline ConstGraph ConstNodeImpl::GetGraph() const { + const OrtGraph* graph; + ThrowOnError(GetApi().Node_GetGraph(this->p_, &graph)); + return ConstGraph{graph}; } -#endif // !defined(DISABLE_SPARSE_TENSORS) -inline Value Value::CreateMap(const Value& keys, const Value& values) { - OrtValue* out; - const OrtValue* inputs[2] = {keys, values}; - ThrowOnError(GetApi().CreateValue(inputs, 2, ONNX_TYPE_MAP, &out)); - return Value{out}; +template +inline std::string ConstNodeImpl::GetEpName() const { + const char* name; + ThrowOnError(GetApi().Node_GetEpName(this->p_, &name)); + return std::string(name); } -inline Value Value::CreateSequence(const std::vector& values) { - OrtValue* out; - std::vector values_ort{values.data(), values.data() + values.size()}; - ThrowOnError(GetApi().CreateValue(values_ort.data(), values_ort.size(), ONNX_TYPE_SEQUENCE, &out)); - return Value{out}; +} // namespace detail + +#if !defined(ORT_MINIMAL_BUILD) +// static +inline void Node::Init(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names, + std::vector& attributes, + OrtNode*& node) { + auto inputs = detail::StringsToCharPtrs(input_names); + auto outputs = detail::StringsToCharPtrs(output_names); + + std::vector attributes_ptrs; + attributes_ptrs.reserve(attributes.size()); + std::transform(attributes.begin(), attributes.end(), std::back_inserter(attributes_ptrs), + [](OpAttr& attr) -> OrtOpAttr* { return attr; }); + + ThrowOnError(GetModelEditorApi().CreateNode(operator_name.c_str(), operator_domain.c_str(), node_name.c_str(), + inputs.data(), inputs.size(), + outputs.data(), outputs.size(), + attributes_ptrs.data(), attributes_ptrs.size(), + &node)); + + // Node now owns the attributes + std::for_each(attributes.begin(), attributes.end(), [](OpAttr& attr) { attr.release(); }); } -template -inline Value Value::CreateOpaque(const char* domain, const char* type_name, const T& data_container) { - OrtValue* out; - ThrowOnError(GetApi().CreateOpaqueValue(domain, type_name, &data_container, sizeof(T), &out)); - return Value{out}; +inline Node::Node(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names, + std::vector& attributes) { + Init(operator_name, operator_domain, node_name, input_names, output_names, attributes, p_); } -// -// Custom OP Inlines -// -inline Logger::Logger(const OrtLogger* logger) : logger_(logger) { - Ort::ThrowOnError(GetApi().Logger_GetLoggingSeverityLevel(this->logger_, &this->cached_severity_level_)); +inline Node::Node(const std::string& operator_name, const std::string& operator_domain, + const std::string& node_name, + const std::vector& input_names, + const std::vector& output_names) { + std::vector empty_attributes; + Init(operator_name, operator_domain, node_name, input_names, output_names, empty_attributes, p_); } +inline ValueInfo::ValueInfo(const std::string& name, const ConstTypeInfo& type_info) { + ThrowOnError(GetModelEditorApi().CreateValueInfo(name.c_str(), type_info, &p_)); +} +#endif // !defined(ORT_MINIMAL_BUILD) -inline OrtLoggingLevel Logger::GetLoggingSeverityLevel() const noexcept { - return cached_severity_level_; +namespace detail { +template +inline std::string ConstValueInfoImpl::GetName() const { + const char* p = nullptr; + ThrowOnError(GetApi().GetValueInfoName(this->p_, &p)); + return std::string(p); } -inline Status Logger::LogMessage(OrtLoggingLevel log_severity_level, const ORTCHAR_T* file_path, int line_number, - const char* func_name, const char* message) const noexcept { - OrtStatus* status = GetApi().Logger_LogMessage(logger_, log_severity_level, message, file_path, line_number, - func_name); - return Status{status}; +template +inline ConstTypeInfo ConstValueInfoImpl::TypeInfo() const { + const OrtTypeInfo* type_info = nullptr; + ThrowOnError(GetApi().GetValueInfoTypeInfo(this->p_, &type_info)); + return ConstTypeInfo{type_info}; } -// Disable warnings about the format string not being a literal (-Wformat-nonliteral and -Wformat-security) -// for gcc and clang. The alternative is to use actual C-style variadic parameters and apply -// __attribute__(format(printf...)), which does not work with variadic templates. -#if defined(__GNUC__) -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wformat-nonliteral" -#pragma GCC diagnostic ignored "-Wformat-security" -#elif defined(__clang__) -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wformat-nonliteral" -#pragma clang diagnostic ignored "-Wformat-security" -#endif -template -inline Status Logger::LogFormattedMessage(OrtLoggingLevel log_severity_level, const ORTCHAR_T* file_path, - int line_number, const char* func_name, const char* format, - Args&&... args) const noexcept { - int msg_len = std::snprintf(nullptr, 0U, format, std::forward(args)...); +template +inline ValueInfoConsumerProducerInfo ConstValueInfoImpl::GetProducerNode() const { + ValueInfoConsumerProducerInfo info; + const OrtNode* producer; + size_t index; + ThrowOnError(GetApi().ValueInfo_GetValueProducer(this->p_, &producer, &index)); + info.node = ConstNode(producer); + info.index = static_cast(index); + return info; +} - if (msg_len < 0) { // Formatting error - return Status("Failed to log message due to formatting error", OrtErrorCode::ORT_FAIL); +template +inline std::vector ConstValueInfoImpl::GetConsumers() const { + size_t num = 0; + ThrowOnError(GetApi().ValueInfo_GetValueNumConsumers(this->p_, &num)); + std::vector out; + if (num > 0) { + std::vector nodes(num); + std::vector indices(num); + ThrowOnError(GetApi().ValueInfo_GetValueConsumers(this->p_, nodes.data(), indices.data(), num)); + out.reserve(num); + for (size_t i = 0; i < num; ++i) { + out.push_back({ConstNode{nodes[i]}, indices[i]}); + } } + return out; +} - OrtStatus* status = nullptr; - const size_t buffer_size = static_cast(msg_len) + 1U; - - constexpr size_t kStackBufferSize = 1024; +template +inline Status ConstValueInfoImpl::GetInitializer(ConstValue& value) const { + const OrtValue* out = nullptr; + auto status = Status(GetApi().ValueInfo_GetInitializerValue(this->p_, &out)); + if (!status.IsOK()) return status; + value = ConstValue{out}; + return status; +} - if (buffer_size < kStackBufferSize) { - char buffer[kStackBufferSize]; - snprintf(buffer, kStackBufferSize, format, std::forward(args)...); - status = GetApi().Logger_LogMessage(logger_, log_severity_level, buffer, file_path, line_number, func_name); - } else { - // std::make_unique is only supported starting at C++14. -#if (__cplusplus >= 201402L) || (_MSC_VER >= 1900) - auto buffer = std::make_unique(buffer_size); -#else - std::unique_ptr buffer(new char[buffer_size]); -#endif - std::snprintf(buffer.get(), buffer_size, format, std::forward(args)...); - status = GetApi().Logger_LogMessage(logger_, log_severity_level, buffer.get(), file_path, line_number, func_name); - } +template +inline Status ConstValueInfoImpl::GetExternalInitializerInfo(ExternalInitializerInfo& info) const { + OrtExternalInitializerInfo* out = nullptr; + auto status = Status(GetApi().ValueInfo_GetExternalInitializerInfo(this->p_, &out)); + if (!status.IsOK()) return status; + info = ExternalInitializerInfo{out}; + return status; +} - return Status{status}; +template +inline bool ConstValueInfoImpl::IsRequiredGraphInput() const { + bool out = false; + ThrowOnError(GetApi().ValueInfo_IsRequiredGraphInput(this->p_, &out)); + return out; } -// Re-enable -Wformat-nonliteral and -Wformat-security -#if defined(__GNUC__) -#pragma GCC diagnostic pop -#elif defined(__clang__) -#pragma clang diagnostic pop -#endif -inline KernelContext::KernelContext(OrtKernelContext* context) : ctx_(context) { +template +inline bool ConstValueInfoImpl::IsOptionalGraphInput() const { + bool out = false; + ThrowOnError(GetApi().ValueInfo_IsOptionalGraphInput(this->p_, &out)); + return out; } -inline size_t KernelContext::GetInputCount() const { - size_t out = 0; - Ort::ThrowOnError(GetApi().KernelContext_GetInputCount(ctx_, &out)); +template +inline bool ConstValueInfoImpl::IsGraphOutput() const { + bool out = false; + ThrowOnError(GetApi().ValueInfo_IsGraphOutput(this->p_, &out)); return out; } -inline size_t KernelContext::GetOutputCount() const { - size_t out = 0; - Ort::ThrowOnError(GetApi().KernelContext_GetOutputCount(ctx_, &out)); +template +inline bool ConstValueInfoImpl::IsConstantInitializer() const { + bool out = false; + ThrowOnError(GetApi().ValueInfo_IsConstantInitializer(this->p_, &out)); return out; } -inline ConstValue KernelContext::GetInput(size_t index) const { - const OrtValue* out = nullptr; - Ort::ThrowOnError(GetApi().KernelContext_GetInput(ctx_, index, &out)); - return ConstValue{out}; +template +inline bool ConstValueInfoImpl::IsFromOuterScope() const { + bool out = false; + ThrowOnError(GetApi().ValueInfo_IsFromOuterScope(this->p_, &out)); + return out; } -inline UnownedValue KernelContext::GetOutput(size_t index, const int64_t* dim_values, size_t dim_count) const { - OrtValue* out = nullptr; - Ort::ThrowOnError(GetApi().KernelContext_GetOutput(ctx_, index, dim_values, dim_count, &out)); - return UnownedValue(out); +template +inline ModelMetadata ConstGraphImpl::GetModelMetadata() const { + OrtModelMetadata* out; + ThrowOnError(GetApi().Graph_GetModelMetadata(this->p_, &out)); + return ModelMetadata{out}; } -inline UnownedValue KernelContext::GetOutput(size_t index, const std::vector& dims) const { - OrtValue* out = nullptr; - Ort::ThrowOnError(GetApi().KernelContext_GetOutput(ctx_, index, dims.data(), dims.size(), &out)); - return UnownedValue(out); +template +inline std::string ConstGraphImpl::GetName() const { + const char* name; + ThrowOnError(GetApi().Graph_GetName(this->p_, &name)); + return std::string(name); } -inline void* KernelContext::GetGPUComputeStream() const { - void* out = nullptr; - Ort::ThrowOnError(GetApi().KernelContext_GetGPUComputeStream(ctx_, &out)); - return out; +template +inline std::basic_string ConstGraphImpl::GetModelPath() const { + const ORTCHAR_T* path; + ThrowOnError(GetApi().Graph_GetModelPath(this->p_, &path)); + return std::basic_string(path); } -inline OrtAllocator* KernelContext::GetAllocator(const OrtMemoryInfo& memory_info) const { - OrtAllocator* out = nullptr; - Ort::ThrowOnError(GetApi().KernelContext_GetAllocator(ctx_, &memory_info, &out)); - return out; +template +inline int64_t ConstGraphImpl::GetOnnxIRVersion() const { + int64_t version; + ThrowOnError(GetApi().Graph_GetOnnxIRVersion(this->p_, &version)); + return version; } -inline Logger KernelContext::GetLogger() const { - const OrtLogger* out = nullptr; - ThrowOnError(GetApi().KernelContext_GetLogger(this->ctx_, &out)); - return Logger{out}; +template +inline std::vector ConstGraphImpl::GetOperatorSets() const { + size_t num_opsets; + ThrowOnError(GetApi().Graph_GetNumOperatorSets(this->p_, &num_opsets)); + std::vector result; + if (num_opsets > 0) { + std::vector domains; + std::vector versions; + domains.resize(num_opsets); + versions.resize(num_opsets); + ThrowOnError(GetApi().Graph_GetOperatorSets(this->p_, domains.data(), versions.data(), num_opsets)); + result.reserve(num_opsets); + for (size_t i = 0; i < num_opsets; ++i) { + result.push_back({domains[i], versions[i]}); + } + } + return result; } -inline void KernelContext::ParallelFor(void (*fn)(void*, size_t), size_t total, size_t num_batch, void* usr_data) const { - ThrowOnError(GetApi().KernelContext_ParallelFor(ctx_, fn, total, num_batch, usr_data)); +template +inline std::vector ConstGraphImpl::GetInputs() const { + static_assert(sizeof(const OrtValueInfo*) == sizeof(ConstValueInfo)); + size_t num_vi; + ThrowOnError(GetApi().Graph_GetNumInputs(this->p_, &num_vi)); + std::vector result; + if (num_vi > 0) { + result.resize(num_vi); + ThrowOnError(GetApi().Graph_GetInputs(this->p_, reinterpret_cast(result.data()), num_vi)); + } + return result; } -inline OpAttr::OpAttr(const char* name, const void* data, int len, OrtOpAttrType type) { - Ort::ThrowOnError(GetApi().CreateOpAttr(name, data, len, type, &p_)); +template +inline std::vector ConstGraphImpl::GetOutputs() const { + static_assert(sizeof(const OrtValueInfo*) == sizeof(ConstValueInfo)); + size_t num_vi; + ThrowOnError(GetApi().Graph_GetNumOutputs(this->p_, &num_vi)); + std::vector result; + if (num_vi > 0) { + result.resize(num_vi); + ThrowOnError(GetApi().Graph_GetOutputs(this->p_, reinterpret_cast(result.data()), num_vi)); + } + return result; } -namespace detail { template -inline KernelInfo KernelInfoImpl::Copy() const { - OrtKernelInfo* info_copy = nullptr; - Ort::ThrowOnError(GetApi().CopyKernelInfo(this->p_, &info_copy)); - return KernelInfo{info_copy}; +inline std::vector ConstGraphImpl::GetInitializers() const { + static_assert(sizeof(const OrtValueInfo*) == sizeof(ConstValueInfo)); + size_t num_vi; + ThrowOnError(GetApi().Graph_GetNumInitializers(this->p_, &num_vi)); + std::vector result; + if (num_vi > 0) { + result.resize(num_vi); + ThrowOnError(GetApi().Graph_GetInitializers(this->p_, reinterpret_cast(result.data()), + num_vi)); + } + return result; } template -inline size_t KernelInfoImpl::GetInputCount() const { - size_t out = 0; - ThrowOnError(GetApi().KernelInfo_GetInputCount(this->p_, &out)); - return out; +inline std::vector ConstGraphImpl::GetNodes() const { + static_assert(sizeof(const OrtNode*) == sizeof(ConstNode)); + size_t num_nodes; + ThrowOnError(GetApi().Graph_GetNumNodes(this->p_, &num_nodes)); + std::vector result; + if (num_nodes > 0) { + result.resize(num_nodes); + ThrowOnError(GetApi().Graph_GetNodes(this->p_, reinterpret_cast(result.data()), num_nodes)); + } + return result; } template -inline size_t KernelInfoImpl::GetOutputCount() const { - size_t out = 0; - ThrowOnError(GetApi().KernelInfo_GetOutputCount(this->p_, &out)); - return out; +inline ConstNode ConstGraphImpl::GetParentNode() const { + const OrtNode* parent; + ThrowOnError(GetApi().Graph_GetParentNode(this->p_, &parent)); + return ConstNode{parent}; } template -inline std::string KernelInfoImpl::GetInputName(size_t index) const { - size_t size = 0; +inline Graph ConstGraphImpl::GetGraphView(const std::vector& nodes) const { + OrtGraph* graph_viewer; + std::vector inputs_ptrs; + inputs_ptrs.reserve(nodes.size()); + std::transform(nodes.begin(), nodes.end(), std::back_inserter(inputs_ptrs), + [](ConstNode n) -> const OrtNode* { return n; }); + ThrowOnError(GetApi().Graph_GetGraphView(this->p_, inputs_ptrs.data(), + nodes.size(), &graph_viewer)); + return Graph{graph_viewer}; +} - // Feed nullptr for the data buffer to query the true size of the string value - Ort::ThrowOnError(GetApi().KernelInfo_GetInputName(this->p_, index, nullptr, &size)); +#if !defined(ORT_MINIMAL_BUILD) +template +inline void GraphImpl::SetInputs(std::vector& inputs) { + std::vector inputs_ptrs; + inputs_ptrs.reserve(inputs.size()); + std::transform(inputs.begin(), inputs.end(), std::back_inserter(inputs_ptrs), + [](ValueInfo& vi) -> OrtValueInfo* { return vi; }); - std::string out; - out.resize(size); - Ort::ThrowOnError(GetApi().KernelInfo_GetInputName(this->p_, index, &out[0], &size)); - out.resize(size - 1); // remove the terminating character '\0' + ThrowOnError(GetModelEditorApi().SetGraphInputs(this->p_, inputs_ptrs.data(), inputs_ptrs.size())); - return out; + // Graph now owns the inputs + std::for_each(inputs.begin(), inputs.end(), [](ValueInfo& vi) { vi.release(); }); } template -inline std::string KernelInfoImpl::GetOutputName(size_t index) const { - size_t size = 0; +inline void GraphImpl::SetOutputs(std::vector& outputs) { + std::vector outputs_ptrs; + outputs_ptrs.reserve(outputs.size()); + std::transform(outputs.begin(), outputs.end(), std::back_inserter(outputs_ptrs), + [](ValueInfo& vi) -> OrtValueInfo* { return vi; }); - // Feed nullptr for the data buffer to query the true size of the string value - Ort::ThrowOnError(GetApi().KernelInfo_GetOutputName(this->p_, index, nullptr, &size)); + ThrowOnError(GetModelEditorApi().SetGraphOutputs(this->p_, outputs_ptrs.data(), outputs_ptrs.size())); - std::string out; - out.resize(size); - Ort::ThrowOnError(GetApi().KernelInfo_GetOutputName(this->p_, index, &out[0], &size)); - out.resize(size - 1); // remove the terminating character '\0' + // Graph now owns the outputs + std::for_each(outputs.begin(), outputs.end(), [](ValueInfo& vi) { vi.release(); }); +} - return out; +template +inline void GraphImpl::AddInitializer(const std::string& name, const Value& initializer, bool data_is_external) { + // Graph copies the OrtValue internally. Caller retains ownership of initializer. + ThrowOnError(GetModelEditorApi().AddInitializerToGraph(this->p_, name.c_str(), initializer, data_is_external)); } template -inline TypeInfo KernelInfoImpl::GetInputTypeInfo(size_t index) const { - OrtTypeInfo* out = nullptr; - ThrowOnError(GetApi().KernelInfo_GetInputTypeInfo(this->p_, index, &out)); - return TypeInfo{out}; +inline void GraphImpl::AddNode(Node& node) { + // Graph takes ownership of `node` + ThrowOnError(GetModelEditorApi().AddNodeToGraph(this->p_, node.release())); } template -inline TypeInfo KernelInfoImpl::GetOutputTypeInfo(size_t index) const { - OrtTypeInfo* out = nullptr; - ThrowOnError(GetApi().KernelInfo_GetOutputTypeInfo(this->p_, index, &out)); - return TypeInfo{out}; +inline void ModelImpl::AddGraph(Graph& graph) { + // Model takes ownership of `graph` + ThrowOnError(GetModelEditorApi().AddGraphToModel(this->p_, graph.release())); +} +#endif // !defined(ORT_MINIMAL_BUILD) + +} // namespace detail + +#if !defined(ORT_MINIMAL_BUILD) +inline Graph::Graph() { + ThrowOnError(GetModelEditorApi().CreateGraph(&p_)); +} + +inline Model::Model(const std::vector& opsets) { + std::vector domains; + std::vector versions; + domains.reserve(opsets.size()); + versions.reserve(opsets.size()); + + for (const auto& pair : opsets) { + domains.push_back(pair.first.c_str()); + versions.push_back(pair.second); + } + + ThrowOnError(GetModelEditorApi().CreateModel(domains.data(), versions.data(), opsets.size(), &p_)); +} +#endif + +namespace detail { +template +inline const char* ConstKernelDefImpl::GetOperatorType() const { + return GetEpApi().KernelDef_GetOperatorType(this->p_); } template -inline Value KernelInfoImpl::GetTensorAttribute(const char* name, OrtAllocator* allocator) const { - OrtValue* out = nullptr; - ThrowOnError(GetApi().KernelInfoGetAttribute_tensor(this->p_, name, allocator, &out)); - return Value{out}; +inline const char* ConstKernelDefImpl::GetDomain() const { + return GetEpApi().KernelDef_GetDomain(this->p_); } template -inline ConstValue KernelInfoImpl::GetTensorConstantInput(size_t index, int* is_constant) const { - const OrtValue* out = nullptr; - ThrowOnError(GetApi().KernelInfoGetConstantInput_tensor(this->p_, index, is_constant, &out)); - return ConstValue{out}; +inline std::pair ConstKernelDefImpl::GetSinceVersion() const { + int start = 0; + int end = 0; + + ThrowOnError(GetEpApi().KernelDef_GetSinceVersion(this->p_, &start, &end)); + return std::pair(start, end); } template -inline std::string KernelInfoImpl::GetNodeName() const { - size_t size = 0; - - // Feed nullptr for the data buffer to query the true size of the string value - Ort::ThrowOnError(GetApi().KernelInfo_GetNodeName(this->p_, nullptr, &size)); +inline const char* ConstKernelDefImpl::GetExecutionProvider() const { + return GetEpApi().KernelDef_GetExecutionProvider(this->p_); +} - std::string out; - out.resize(size); - Ort::ThrowOnError(GetApi().KernelInfo_GetNodeName(this->p_, &out[0], &size)); - out.resize(size - 1); // remove the terminating character '\0' +template +inline OrtMemType ConstKernelDefImpl::GetInputMemType(size_t input_index) const { + OrtMemType mem_type{}; + ThrowOnError(GetEpApi().KernelDef_GetInputMemType(this->p_, input_index, &mem_type)); - return out; + return mem_type; } template -inline Logger KernelInfoImpl::GetLogger() const { - const OrtLogger* out = nullptr; - ThrowOnError(GetApi().KernelInfo_GetLogger(this->p_, &out)); - return Logger{out}; -} +inline OrtMemType ConstKernelDefImpl::GetOutputMemType(size_t output_index) const { + OrtMemType mem_type{}; + ThrowOnError(GetEpApi().KernelDef_GetOutputMemType(this->p_, output_index, &mem_type)); -inline void attr_utils::GetAttr(const OrtKernelInfo* p, const char* name, float& out) { - Ort::ThrowOnError(GetApi().KernelInfoGetAttribute_float(p, name, &out)); + return mem_type; } +} // namespace detail -inline void attr_utils::GetAttr(const OrtKernelInfo* p, const char* name, int64_t& out) { - Ort::ThrowOnError(GetApi().KernelInfoGetAttribute_int64(p, name, &out)); +inline KernelDefBuilder::KernelDefBuilder() { + ThrowOnError(GetEpApi().CreateKernelDefBuilder(&p_)); } -inline void attr_utils::GetAttr(const OrtKernelInfo* p, const char* name, std::string& result) { - size_t size = 0; - // Feed nullptr for the data buffer to query the true size of the string attribute - Ort::ThrowOnError(GetApi().KernelInfoGetAttribute_string(p, name, nullptr, &size)); - - std::string out; - out.resize(size); - Ort::ThrowOnError(GetApi().KernelInfoGetAttribute_string(p, name, &out[0], &size)); - out.resize(size - 1); // remove the terminating character '\0' - out.swap(result); +inline KernelDefBuilder::KernelDefBuilder(OrtKernelDefBuilder* p) : detail::Base{p} { } -inline void attr_utils::GetAttrs(const OrtKernelInfo* p, const char* name, std::vector& result) { - size_t size = 0; - // Feed nullptr for the data buffer to query the true size of the attribute - Ort::ThrowOnError(GetApi().KernelInfoGetAttributeArray_float(p, name, nullptr, &size)); +inline KernelDefBuilder& KernelDefBuilder::SetOperatorType(const char* op_type) { + ThrowOnError(GetEpApi().KernelDefBuilder_SetOperatorType(p_, op_type)); + return *this; +} - std::vector out; - out.resize(size); - Ort::ThrowOnError(GetApi().KernelInfoGetAttributeArray_float(p, name, out.data(), &size)); - out.swap(result); +inline KernelDefBuilder& KernelDefBuilder::SetDomain(const char* domain) { + ThrowOnError(GetEpApi().KernelDefBuilder_SetDomain(p_, domain)); + return *this; } -inline void attr_utils::GetAttrs(const OrtKernelInfo* p, const char* name, std::vector& result) { - size_t size = 0; +inline KernelDefBuilder& KernelDefBuilder::SetSinceVersion(int since_version_start, int since_version_end) { + ThrowOnError(GetEpApi().KernelDefBuilder_SetSinceVersion(p_, since_version_start, since_version_end)); + return *this; +} - // Feed nullptr for the data buffer to query the true size of the attribute - Ort::ThrowOnError(GetApi().KernelInfoGetAttributeArray_int64(p, name, nullptr, &size)); +inline KernelDefBuilder& KernelDefBuilder::SetExecutionProvider(const char* ep_name) { + ThrowOnError(GetEpApi().KernelDefBuilder_SetExecutionProvider(p_, ep_name)); + return *this; +} - std::vector out; - out.resize(size); - Ort::ThrowOnError(GetApi().KernelInfoGetAttributeArray_int64(p, name, out.data(), &size)); - out.swap(result); +inline KernelDefBuilder& KernelDefBuilder::SetInputMemType(size_t input_index, OrtMemType mem_type) { + ThrowOnError(GetEpApi().KernelDefBuilder_SetInputMemType(p_, input_index, mem_type)); + return *this; } -} // namespace detail -inline KernelInfo::KernelInfo(OrtKernelInfo* info) : detail::KernelInfoImpl{info} {} +inline KernelDefBuilder& KernelDefBuilder::SetOutputMemType(size_t output_index, OrtMemType mem_type) { + ThrowOnError(GetEpApi().KernelDefBuilder_SetOutputMemType(p_, output_index, mem_type)); + return *this; +} -inline Op::Op(OrtOp* p) : detail::Base(p) {} +inline KernelDefBuilder& KernelDefBuilder::AddTypeConstraint(const char* arg_name, + const OrtDataType* data_type) { + ThrowOnError(GetEpApi().KernelDefBuilder_AddTypeConstraint(p_, arg_name, &data_type, 1)); + return *this; +} -inline Op Op::Create(const OrtKernelInfo* info, const char* op_name, const char* domain, int version, - const char** type_constraint_names, - const ONNXTensorElementDataType* type_constraint_values, - size_t type_constraint_count, - const OpAttr* attr_values, size_t attr_count, - size_t input_count, size_t output_count) { - static_assert(sizeof(OpAttr) == sizeof(OrtOpAttr*), - "OpAttr's is expected to be just an array of OrtOpAttr in memory so we can reinterpret safely"); - auto attr_input_values = reinterpret_cast(attr_values); - OrtOp* op; - Ort::ThrowOnError(GetApi().CreateOp(info, op_name, domain, version, type_constraint_names, type_constraint_values, - static_cast(type_constraint_count), - attr_input_values, - static_cast(attr_count), - static_cast(input_count), - static_cast(output_count), &op)); - return Op{op}; +inline KernelDefBuilder& KernelDefBuilder::AddTypeConstraint(const char* arg_name, + const std::vector& data_types) { + ThrowOnError(GetEpApi().KernelDefBuilder_AddTypeConstraint(p_, arg_name, data_types.data(), data_types.size())); + return *this; } -inline void Op::Invoke(const OrtKernelContext* context, - const Value* input_values, - size_t input_count, - Value* output_values, - size_t output_count) { - static_assert(sizeof(Value) == sizeof(OrtValue*), - "Value is really just an array of OrtValue* in memory, so we can reinterpret_cast safely"); - auto ort_input_values = reinterpret_cast(input_values); - auto ort_output_values = reinterpret_cast(output_values); - Ort::ThrowOnError(GetApi().InvokeOp(context, p_, ort_input_values, static_cast(input_count), - ort_output_values, static_cast(output_count))); +inline KernelDefBuilder& KernelDefBuilder::AddInputOutputAlias(int input_index, int output_index) { + ThrowOnError(GetEpApi().KernelDefBuilder_AddInputOutputAliases(p_, &input_index, &output_index, 1)); + return *this; } -inline void Op::Invoke(const OrtKernelContext* context, - const OrtValue* const* input_values, - size_t input_count, - OrtValue* const* output_values, - size_t output_count) { - Ort::ThrowOnError(GetApi().InvokeOp(context, p_, input_values, static_cast(input_count), - output_values, static_cast(output_count))); +inline KernelDefBuilder& KernelDefBuilder::AddInputOutputAliases(const std::vector& input_indices, + const std::vector& output_indices) { + if (input_indices.size() != output_indices.size()) { + ORT_CXX_API_THROW("Expecting input and output indices to have the same element count", ORT_INVALID_ARGUMENT); + } + + ThrowOnError(GetEpApi().KernelDefBuilder_AddInputOutputAliases(p_, input_indices.data(), output_indices.data(), + input_indices.size())); + return *this; } -inline std::string GetVersionString() { - return OrtGetApiBase()->GetVersionString(); +inline KernelDefBuilder& KernelDefBuilder::AddInputOutputMutableAlias(int input_index, int output_index) { + ThrowOnError(GetEpApi().KernelDefBuilder_AddInputOutputMutableAliases(p_, &input_index, &output_index, 1)); + return *this; } -inline std::string GetBuildInfoString() { - return GetApi().GetBuildInfoString(); +inline KernelDefBuilder& KernelDefBuilder::AddInputOutputMutableAliases(const std::vector& input_indices, + const std::vector& output_indices) { + if (input_indices.size() != output_indices.size()) { + ORT_CXX_API_THROW("Expecting input and output indices to have the same element count", ORT_INVALID_ARGUMENT); + } + + ThrowOnError(GetEpApi().KernelDefBuilder_AddInputOutputMutableAliases(p_, input_indices.data(), output_indices.data(), + input_indices.size())); + return *this; } -inline std::vector GetAvailableProviders() { - char** providers; - int len; +inline KernelDef KernelDefBuilder::Build() { + OrtKernelDef* kernel_def = nullptr; + ThrowOnError(GetEpApi().KernelDefBuilder_Build(p_, &kernel_def)); + return KernelDef(kernel_def); +} - auto release_fn = [&len](char** providers) { - // This should always return nullptr. - ThrowOnError(GetApi().ReleaseAvailableProviders(providers, len)); - }; +inline KernelRegistry::KernelRegistry() { + ThrowOnError(GetEpApi().CreateKernelRegistry(&p_)); +} - ThrowOnError(GetApi().GetAvailableProviders(&providers, &len)); - std::unique_ptr guard(providers, release_fn); - std::vector available_providers; - available_providers.reserve(static_cast(len)); - for (int i = 0; i < len; ++i) { - available_providers.emplace_back(providers[i]); - } - return available_providers; +inline KernelRegistry::KernelRegistry(OrtKernelRegistry* p) : detail::Base{p} { } -template -void CustomOpBase::GetSessionConfigs(std::unordered_map& out, - ConstSessionOptions options) const { - const TOp* derived = static_cast(this); - std::vector keys = derived->GetSessionConfigKeys(); +inline Status KernelRegistry::AddKernel(const OrtKernelDef* kernel_def, OrtKernelCreateFunc kernel_create_func, + void* kernel_create_func_state) { + return Status{GetEpApi().KernelRegistry_AddKernel(p_, kernel_def, kernel_create_func, kernel_create_func_state)}; +} - out.reserve(keys.size()); +namespace detail { +template +inline Status SharedPrePackedWeightCacheImpl::StoreWeightData(void** buffer_data_ptrs, size_t* buffer_sizes, + size_t num_buffers) { + return Status{GetEpApi().SharedPrePackedWeightCache_StoreWeightData(this->p_, buffer_data_ptrs, buffer_sizes, + num_buffers)}; +} +} // namespace detail - std::string config_entry_key = detail::MakeCustomOpConfigEntryKey(derived->GetName(), ""); - const size_t prefix_size = config_entry_key.length(); +inline Ort::KeyValuePairs GetEnvConfigEntries() { + OrtKeyValuePairs* entries = nullptr; + Ort::ThrowOnError(GetEpApi().GetEnvConfigEntries(&entries)); - for (const auto& key : keys) { - config_entry_key.resize(prefix_size); - config_entry_key.append(key); - out[key] = options.GetConfigEntryOrDefault(config_entry_key.c_str(), ""); - } + return Ort::KeyValuePairs{entries}; } -inline ShapeInferContext::ShapeInferContext(const OrtApi* ort_api, - OrtShapeInferContext* ctx) : ort_api_(ort_api), ctx_(ctx) { - size_t input_count = 0; - Ort::ThrowOnError(ort_api_->ShapeInferContext_GetInputCount(ctx_, &input_count)); - for (size_t ith_input = 0; ith_input < input_count; ++ith_input) { - OrtTensorTypeAndShapeInfo* info{}; - Ort::ThrowOnError(ort_api_->ShapeInferContext_GetInputTypeShape(ctx, ith_input, &info)); - TensorTypeAndShapeInfo type_shape_info(info); - auto integer_shape = type_shape_info.GetShape(); - std::vector symbolic_shape(integer_shape.size(), {}); - if (!integer_shape.empty()) { - type_shape_info.GetSymbolicDimensions(&symbolic_shape[0], integer_shape.size()); - } - Shape shape; - for (size_t ith = 0; ith < integer_shape.size(); ++ith) { - if (symbolic_shape[ith] && std::string{symbolic_shape[ith]}.size() > 0) { - shape.emplace_back(symbolic_shape[ith]); - } else { - shape.emplace_back(integer_shape[ith]); - } - } - input_shapes_.push_back(std::move(shape)); - type_shape_info.release(); - } +namespace detail { +template +inline int OpSchemaImpl::GetSinceVersion() const { + int version = 0; + ThrowOnError(GetEpApi().OpSchema_GetSinceVersion(this->p_, &version)); + return version; } -inline Status ShapeInferContext::SetOutputShape(size_t indice, const Shape& shape, ONNXTensorElementDataType type) { - OrtTensorTypeAndShapeInfo* info = {}; - ORT_CXX_RETURN_ON_API_FAIL(ort_api_->CreateTensorTypeAndShapeInfo(&info)); - ORT_CXX_RETURN_ON_API_FAIL(ort_api_->SetTensorElementType(info, type)); +template +inline size_t OpSchemaImpl::GetNumInputs() const { + size_t num = 0; + ThrowOnError(GetEpApi().OpSchema_GetNumInputs(this->p_, &num)); + return num; +} - using InfoPtr = std::unique_ptr>; +template +inline std::string OpSchemaImpl::GetInputName(size_t index) const { + const char* name = nullptr; + ThrowOnError(GetEpApi().OpSchema_GetInputName(this->p_, index, &name)); + return std::string(name); +} - InfoPtr info_ptr(info, [this](OrtTensorTypeAndShapeInfo* obj) { - ort_api_->ReleaseTensorTypeAndShapeInfo(obj); - }); +template +inline Ort::ConstOpSchemaTypeConstraint OpSchemaImpl::GetInputTypeConstraint(size_t index) const { + const OrtOpSchemaTypeConstraint* tc = nullptr; + ThrowOnError(GetEpApi().OpSchema_GetInputTypeConstraint(this->p_, index, &tc)); + return Ort::ConstOpSchemaTypeConstraint{tc}; +} - std::vector integer_dims; - std::vector symbolic_dims; +template +inline size_t OpSchemaImpl::GetNumOutputs() const { + size_t num = 0; + ThrowOnError(GetEpApi().OpSchema_GetNumOutputs(this->p_, &num)); + return num; +} - for (const auto dim : shape) { - if (dim.IsInt()) { - integer_dims.push_back(dim.AsInt()); - symbolic_dims.push_back(""); - } else { - if (!dim.AsSym() || std::string{dim.AsSym()}.empty()) { - ORT_CXX_API_THROW("Symbolic dim must not be an empty string", ORT_INVALID_ARGUMENT); - } - integer_dims.push_back(SymbolicInteger::INVALID_INT_DIM); - symbolic_dims.push_back(dim.AsSym()); - } - } +template +inline std::string OpSchemaImpl::GetOutputName(size_t index) const { + const char* name = nullptr; + ThrowOnError(GetEpApi().OpSchema_GetOutputName(this->p_, index, &name)); + return std::string(name); +} - ORT_CXX_RETURN_ON_API_FAIL(ort_api_->SetDimensions(info, integer_dims.data(), integer_dims.size())); - ORT_CXX_RETURN_ON_API_FAIL(ort_api_->SetSymbolicDimensions(info, symbolic_dims.data(), symbolic_dims.size())); - ORT_CXX_RETURN_ON_API_FAIL(ort_api_->ShapeInferContext_SetOutputTypeShape(ctx_, indice, info)); - return Status{nullptr}; +template +inline Ort::ConstOpSchemaTypeConstraint OpSchemaImpl::GetOutputTypeConstraint(size_t index) const { + const OrtOpSchemaTypeConstraint* tc = nullptr; + ThrowOnError(GetEpApi().OpSchema_GetOutputTypeConstraint(this->p_, index, &tc)); + return Ort::ConstOpSchemaTypeConstraint{tc}; } -inline int64_t ShapeInferContext::GetAttrInt(const char* attr_name) { - const auto* attr = GetAttrHdl(attr_name); - int64_t i = {}; - size_t out = {}; - Ort::ThrowOnError(ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_INT, &i, sizeof(i), &out)); - return i; +template +inline size_t OpSchemaImpl::GetTypeConstraintCount() const { + size_t count = 0; + ThrowOnError(GetEpApi().OpSchema_GetTypeConstraintCount(this->p_, &count)); + return count; } -inline ShapeInferContext::Ints ShapeInferContext::GetAttrInts(const char* attr_name) { - const auto* attr = GetAttrHdl(attr_name); - int64_t i = {}; - size_t out = {}; - // first call to get the bytes needed - // 1. A status == nullptr means that ReadOpAttr was successful. A status != nullptr means failure. - // 2. The ReadOpAttr function should normally be called twice: once to get the needed buffer size (returns a status != nullptr), and a second time to actually read the ints (returns status == null on success). - // 3. This code tries a subtle optimization in the first call to ReadOpAttr. It passes in a buffer (&i) of size 1 just in case there is only 1 int. In this case, status == nullptr and we need to return {i}. - auto status = ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_INTS, &i, sizeof(i), &out); - if (status) { - size_t num_i = out / sizeof(int64_t); - ShapeInferContext::Ints ints(num_i, 0); - Ort::ThrowOnError(ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_INTS, ints.data(), out, &out)); - return ints; - } else { - if (out == 0u) { - return {}; - } - return {i}; - } +template +inline Ort::ConstOpSchemaTypeConstraint OpSchemaImpl::GetTypeConstraint(size_t index) const { + const OrtOpSchemaTypeConstraint* tc = nullptr; + ThrowOnError(GetEpApi().OpSchema_GetTypeConstraint(this->p_, index, &tc)); + return Ort::ConstOpSchemaTypeConstraint{tc}; } -inline float ShapeInferContext::GetAttrFloat(const char* attr_name) { - const auto* attr = GetAttrHdl(attr_name); - float f = {}; - size_t out = {}; - Ort::ThrowOnError(ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_FLOAT, &f, sizeof(f), &out)); - return f; +template +inline std::string OpSchemaTypeConstraintImpl::GetTypeParamName() const { + const char* name = nullptr; + ThrowOnError(GetEpApi().OpSchemaTypeConstraint_GetTypeParamName(this->p_, &name)); + return std::string(name); } -inline ShapeInferContext::Floats ShapeInferContext::GetAttrFloats(const char* attr_name) { - const auto* attr = GetAttrHdl(attr_name); - float f = {}; - size_t out = {}; - // first call to get the bytes needed - // 1. A status == nullptr means that ReadOpAttr was successful. A status != nullptr means failure. - // 2. The ReadOpAttr function should normally be called twice: once to get the needed buffer size (returns a status != nullptr), and a second time to actually read the ints (returns status == null on success). - // 3. This code tries a subtle optimization in the first call to ReadOpAttr. It passes in a buffer (&i) of size 1 just in case there is only 1 int. In this case, status == nullptr and we need to return {i}. - auto status = ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_FLOATS, &f, sizeof(f), &out); - if (status) { - size_t num_f = out / sizeof(float); - ShapeInferContext::Floats floats(num_f, 0); - Ort::ThrowOnError(ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_FLOATS, floats.data(), out, &out)); - return floats; - } else { - if (out == 0u) { - return {}; - } - return {f}; +template +inline std::vector OpSchemaTypeConstraintImpl::GetAllowedTypes() const { + const char* const* types = nullptr; + size_t num_types = 0; + ThrowOnError(GetEpApi().OpSchemaTypeConstraint_GetAllowedTypes(this->p_, &types, &num_types)); + std::vector result; + result.reserve(num_types); + for (size_t i = 0; i < num_types; ++i) { + result.emplace_back(types[i]); } + return result; } -inline std::string ShapeInferContext::GetAttrString(const char* attr_name) { - const auto* attr = GetAttrHdl(attr_name); - char c = {}; - size_t out = {}; - // first call to get the bytes needed - auto status = ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_STRING, &c, sizeof(char), &out); - if (status) { - std::vector chars(out, '\0'); - Ort::ThrowOnError(ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_STRING, chars.data(), out, &out)); - return {chars.data()}; - } else { - return {c}; - } +template +inline std::vector OpSchemaTypeConstraintImpl::GetInputIndices() const { + const size_t* indices = nullptr; + size_t count = 0; + ThrowOnError(GetEpApi().OpSchemaTypeConstraint_GetInputIndices(this->p_, &indices, &count)); + if (count == 0) return {}; + return std::vector(indices, indices + count); } -inline ShapeInferContext::Strings ShapeInferContext::GetAttrStrings(const char* attr_name) { - const auto* attr = GetAttrHdl(attr_name); - char c = {}; - size_t out = {}; - // first call to get the bytes needed - // 1. A status == nullptr means that ReadOpAttr was successful. A status != nullptr means failure. - // 2. The ReadOpAttr function should normally be called twice: once to get the needed buffer size (returns a status != nullptr), and a second time to actually read the ints (returns status == null on success). - // 3. This code tries a subtle optimization in the first call to ReadOpAttr. It passes in a buffer (&i) of size 1 just in case there is only 1 int. In this case, status == nullptr and we need to return {i}. - auto status = ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_STRINGS, &c, sizeof(char), &out); - if (status) { - std::vector chars(out, '\0'); - Ort::ThrowOnError(ort_api_->ReadOpAttr(attr, ORT_OP_ATTR_STRINGS, chars.data(), out, &out)); - ShapeInferContext::Strings strings; - char* char_st = chars.data(); - char* char_ed = char_st + out; - while (char_st < char_ed) { - strings.emplace_back(char_st); - while (*char_st != '\0') { - char_st++; - } - char_st++; - } - return strings; - } else { - if (out == 0u) { - return {}; - } - return {std::string{c}}; - } +template +inline std::vector OpSchemaTypeConstraintImpl::GetOutputIndices() const { + const size_t* indices = nullptr; + size_t count = 0; + ThrowOnError(GetEpApi().OpSchemaTypeConstraint_GetOutputIndices(this->p_, &indices, &count)); + if (count == 0) return {}; + return std::vector(indices, indices + count); } +} // namespace detail -inline const OrtOpAttr* ShapeInferContext::GetAttrHdl(const char* attr_name) const { - const OrtOpAttr* attr_hdl = {}; - Ort::ThrowOnError(ort_api_->ShapeInferContext_GetAttribute(ctx_, attr_name, &attr_hdl)); - return attr_hdl; +inline OpSchema GetOpSchema(const char* name, int max_inclusive_version, const char* domain) { + OrtOpSchema* schema = nullptr; + ThrowOnError(GetEpApi().GetOpSchema(name, max_inclusive_version, domain, &schema)); + return OpSchema{schema}; } } // namespace Ort diff --git a/include/onnxruntime/core/session/onnxruntime_env_config_keys.h b/include/onnxruntime/core/session/onnxruntime_env_config_keys.h new file mode 100644 index 0000000000000..b603765ad3428 --- /dev/null +++ b/include/onnxruntime/core/session/onnxruntime_env_config_keys.h @@ -0,0 +1,24 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +// This file contains well-known keys for OrtEnv configuration entries, which may be used to configure EPs or +// other global settings. +// Refer to OrtEnvCreationOptions::config_entries and OrtApi::CreateEnvWithOptions. +// This file does NOT specify all available keys as EPs may accept custom entries with the prefix "ep..". + +// Key for a boolean option that, when enabled, allows EP factories to create virtual OrtHardwareDevice +// instances via OrtEpApi::CreateHardwareDevice(). +// +// This config entry is automatically set to "1" by ORT if an application registers an EP library with a registration +// name that ends in the suffix ".virtual". See OrtApi::RegisterExecutionProviderLibrary(). +// +// Note: A virtual OrtHardwareDevice does not represent actual hardware on the device, and is identified via the +// metadata entry "is_virtual" with a value of "1". +// +// Allowed values: +// - "0": Default. Creation of virtual devices is not allowed. +// This is the assumed default value if this key is not present in the environment's configuration entries. +// - "1": Creation of virtual devices is allowed. +static const char* const kOrtEnvAllowVirtualDevices = "allow_virtual_devices"; diff --git a/include/onnxruntime/core/session/onnxruntime_ep_c_api.h b/include/onnxruntime/core/session/onnxruntime_ep_c_api.h new file mode 100644 index 0000000000000..76fb7ce93b600 --- /dev/null +++ b/include/onnxruntime/core/session/onnxruntime_ep_c_api.h @@ -0,0 +1,2988 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// Do not include this file directly. Please include "onnxruntime_c_api.h" instead. + +#if defined(__DOXYGEN__) +// When running a Doxygen build, include onnxruntime_c_api.h. Doxygen expects header files to be self-contained. +#include "onnxruntime_c_api.h" +#else +// In normal usage, do not include onnxruntime_c_api.h. This file is explicitly included in onnxruntime_c_api.h. +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** \addtogroup Global + * @{ + */ +ORT_RUNTIME_CLASS(Ep); +ORT_RUNTIME_CLASS(EpFactory); +ORT_RUNTIME_CLASS(EpGraphSupportInfo); +ORT_RUNTIME_CLASS(MemoryDevice); // opaque class to wrap onnxruntime::OrtDevice +ORT_RUNTIME_CLASS(NodeComputeContext); + +ORT_RUNTIME_CLASS(DataTransferImpl); +ORT_RUNTIME_CLASS(SyncNotificationImpl); +ORT_RUNTIME_CLASS(SyncStreamImpl); + +ORT_RUNTIME_CLASS(ExternalResourceImporterImpl); + +ORT_RUNTIME_CLASS(OpSchema); +ORT_RUNTIME_CLASS(OpSchemaTypeConstraint); +ORT_RUNTIME_CLASS(ProfilingEventsContainer); +ORT_RUNTIME_CLASS(ProfilingEvent); // Based on the Trace Event Format's "complete event" +/// @} + +/** \brief Base struct for imported external memory handles. + * + * EPs derive from this struct to add EP-specific fields (e.g., CUdeviceptr for CUDA). + * EP is responsible for creating and releasing instances of the derived type. + * + * Example derived type for CUDA EP: + * \code + * struct MyCudaExternalMemoryHandle : OrtExternalMemoryHandle { + * CUexternalMemory ext_memory; + * CUdeviceptr mapped_ptr; + * bool is_dedicated; + * }; + * \endcode + * + * \since Version 1.24. + */ +struct OrtExternalMemoryHandle { + uint32_t version; ///< Must be ORT_API_VERSION + const OrtEpDevice* ep_device; ///< EP device that created this handle + OrtExternalMemoryDescriptor descriptor; ///< External memory descriptor + + /** \brief Release callback for this handle. EP sets this to its release function. + * + * ORT calls this when ReleaseExternalMemoryHandle is invoked. The EP's callback + * should cast the handle to its derived type and delete it. + */ + void(ORT_API_CALL* Release)(_In_ OrtExternalMemoryHandle* handle); +}; + +/** \brief Base struct for imported external semaphore handles. + * + * EPs derive from this struct to add EP-specific fields (e.g., CUexternalSemaphore for CUDA). + * EP is responsible for creating and releasing instances of the derived type. + * + * Example derived type for CUDA EP: + * \code + * struct MyCudaExternalSemaphoreHandle : OrtExternalSemaphoreHandle { + * CUexternalSemaphore ext_semaphore; + * }; + * \endcode + * + * \since Version 1.24. + */ +struct OrtExternalSemaphoreHandle { + uint32_t version; ///< Must be ORT_API_VERSION + const OrtEpDevice* ep_device; ///< EP device that created this handle + OrtExternalSemaphoreDescriptor descriptor; ///< External semaphore descriptor + + /** \brief Release callback for this handle. EP sets this to its release function. + * + * ORT calls this when ReleaseExternalSemaphoreHandle is invoked. The EP's callback + * should cast the handle to its derived type and delete it. + */ + void(ORT_API_CALL* Release)(_In_ OrtExternalSemaphoreHandle* handle); +}; + +// Opaque types for kernel-based EPs +ORT_RUNTIME_CLASS(KernelRegistry); +ORT_RUNTIME_CLASS(KernelDefBuilder); +ORT_RUNTIME_CLASS(KernelDef); +ORT_RUNTIME_CLASS(DataType); // combination of ONNXType (e.g., Tensor, Map, Sequence) and ONNXTensorElementDataType +ORT_RUNTIME_CLASS(SharedPrePackedWeightCache); + +/** \brief Struct that an EP implements for IDataTransfer to copy between devices it uses and CPU. + * + * \since Version 1.23. + */ +struct OrtDataTransferImpl { + uint32_t ort_version_supported; ///< Must be initialized to ORT_API_VERSION + + /** \brief Release the OrtDataTransferImpl instance. + * + * This is called by ORT when the OrtDataTransferImpl instance is no longer needed. + * The implementation should release any resources held by the instance. + * + * \param[in] this_ptr Pointer to the OrtDataTransferImpl instance. + * + * \since Version 1.23. + */ + ORT_API_T(void, Release, _In_ OrtDataTransferImpl* this_ptr); + + /** \brief Check if the implementation can copy between the source and destination memory devices. + * + * \param[in] this_ptr Pointer to the OrtDataTransferImpl instance. + * \param[in] src_memory_device Source OrtMemoryDevice to copy from. + * \param[in] dst_memory_device Destination OrtMemoryDevice to copy to. + * \return True if the implementation can copy between the devices. + * + * \since Version 1.23. + */ + ORT_API_T(bool, CanCopy, _In_ const OrtDataTransferImpl* this_ptr, + _In_ const OrtMemoryDevice* src_memory_device, _In_ const OrtMemoryDevice* dst_memory_device); + + /** \brief Copy tensors from src_tensors to dst_tensors using the provided streams. + * + * The implementation can use the provided streams to perform asynchronous copies if supported. + * If a stream is not available, the copy is performed synchronously. + * + * \param[in] this_ptr Pointer to the OrtDataTransferImpl instance. + * \param[in] src_tensors Array of source OrtValue pointers to copy from. + * \param[in] dst_tensors Array of destination OrtValue pointers to copy to. + * \param[in] streams Array of OrtSyncStream pointers for the copy operations, if the execution provider is stream + * aware. nullptr if it is not. + * \param[in] num_tensors Number of tensors to copy. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(CopyTensors, _In_ OrtDataTransferImpl* this_ptr, + _In_reads_(num_tensors) const OrtValue** src_tensors, + _In_reads_(num_tensors) OrtValue** dst_tensors, + _In_reads_(num_tensors) OrtSyncStream** streams, + _In_ size_t num_tensors); +}; + +/** \brief Struct that an EP implements for Stream Notifications. + * + * \since Version 1.23. + */ +struct OrtSyncNotificationImpl { + uint32_t ort_version_supported; ///< Must be initialized to ORT_API_VERSION + + /** \brief Release the OrtSyncNotificationImpl instance. + * + * This is called by ORT when the OrtSyncNotificationImpl instance is no longer needed. + * The implementation should release any resources held by the instance. + * + * \param[in] this_ptr Pointer to the OrtSyncNotificationImpl instance. + * + * \since Version 1.23. + */ + ORT_API_T(void, Release, _In_ OrtSyncNotificationImpl* this_ptr); + + /** \brief Called by ORT to activate the notification. + * + * \param[in] this_ptr Pointer to the OrtSyncNotificationImpl instance. + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Activate, _In_ OrtSyncNotificationImpl* this_ptr); + + /** \brief Wait for a device to device operation to complete. + * + * \param[in] this_ptr Pointer to the OrtSyncNotificationImpl instance. + * \param[in] consumer_stream The OrtSyncStream instance that will wait on this notification to be activated. + * + * \since Version 1.23. + */ + ORT_API2_STATUS(WaitOnDevice, _In_ OrtSyncNotificationImpl* this_ptr, _In_ OrtSyncStream* consumer_stream); + + /** \brief Wait for a device to host operation to complete. + * + * \param[in] this_ptr Pointer to the OrtSyncNotificationImpl instance. + * + * \since Version 1.23. + */ + ORT_API2_STATUS(WaitOnHost, _In_ OrtSyncNotificationImpl* this_ptr); +}; + +/** \brief Struct that an EP implements if it wishes to implement Stream support. + * + * This struct provides the overrides for onnxruntime::Stream's virtual methods. + * + * \since Version 1.23. + */ +struct OrtSyncStreamImpl { + uint32_t ort_version_supported; ///< Must be initialized to ORT_API_VERSION + + /** \brief Release the OrtSyncStreamImpl instance. + * + * This is called by ORT when the OrtSyncStreamImpl instance is no longer needed. + * The implementation should release any resources held by the instance. + * + * \param[in] this_ptr Pointer to the OrtSyncStreamImpl instance. + * + * \since Version 1.23. + */ + ORT_API_T(void, Release, _In_ OrtSyncStreamImpl* this_ptr); + + /** \brief Get the handle of the stream. + * + * This returns the native handle for the stream. e.g. cudaStream_t for CUDA streams. + * + * \param[in] this_ptr Pointer to the OrtSyncStreamImpl instance. + * \return The handle of the stream. + * + * \since Version 1.23. + */ + ORT_API_T(void*, GetHandle, _In_ OrtSyncStreamImpl* this_ptr); + + /** \brief Create an OrtSyncNotificationImpl for the OrtSyncStreamImpl instance. + * + * \param[in] this_ptr Pointer to the OrtSyncStreamImpl instance + * \param[out] notification The new OrtSyncNotificationImpl instance. + * + * \since Version 1.23. + */ + ORT_API2_STATUS(CreateNotification, _In_ OrtSyncStreamImpl* this_ptr, + _Outptr_ OrtSyncNotificationImpl** notification); + + /** \brief Flush the stream. + * + * This is called by ORT to flush the stream, ensuring that all operations submitted to the stream are completed. + * + * \param[in] this_ptr Pointer to the OrtSyncStreamImpl instance. + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Flush, _In_ OrtSyncStreamImpl* this_ptr); + + /** \brief Notify the stream that a session run has ended. + * + * This is called by ORT to notify the stream that a session run has ended, allowing the stream to perform any + * necessary cleanup or finalization. + * + * \param[in] this_ptr Pointer to the OrtSyncStreamImpl instance. + * + * \since Version 1.23. + */ + ORT_API2_STATUS(OnSessionRunEnd, _In_ OrtSyncStreamImpl* this_ptr); +}; + +/** \brief Struct that an EP implements for external resource import (memory + semaphore import). + * + * This capability object provides methods for importing external GPU memory and semaphores + * for zero-copy import. EPs that support D3D12, CUDA, HIP, or Vulkan external resource APIs + * can implement this interface. + * + * \since Version 1.24. + */ +struct OrtExternalResourceImporterImpl { + uint32_t ort_version_supported; ///< Must be initialized to ORT_API_VERSION + + // Memory operations (stream-independent) + + /** \brief Check if the implementation can import external memory of the given handle type. + * + * \param[in] this_ptr Pointer to the OrtExternalResourceImporterImpl instance. + * \param[in] handle_type The type of external memory handle to check. + * \return True if the handle type is supported. + * + * \since Version 1.24. + */ + ORT_API_T(bool, CanImportMemory, + _In_ const OrtExternalResourceImporterImpl* this_ptr, + _In_ OrtExternalMemoryHandleType handle_type); + + /** \brief Import external memory. + * + * The EP creates a derived type of OrtExternalMemoryHandle and returns a pointer to the base. + * EP is responsible for the lifetime of the handle (release via ReleaseMemory). + * + * \param[in] this_ptr Pointer to the OrtExternalResourceImporterImpl instance. + * \param[in] desc Descriptor containing the external memory handle and properties. + * \param[out] out_handle Output parameter set to the created OrtExternalMemoryHandle (EP's derived type). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(ImportMemory, + _In_ OrtExternalResourceImporterImpl* this_ptr, + _In_ const OrtExternalMemoryDescriptor* desc, + _Outptr_ OrtExternalMemoryHandle** out_handle); + + /** \brief Release an imported external memory handle. + * + * The EP deletes its derived type instance. + * + * \param[in] this_ptr Pointer to the OrtExternalResourceImporterImpl instance. + * \param[in] handle The OrtExternalMemoryHandle to release (EP casts to its derived type). + * + * \since Version 1.24. + */ + ORT_API_T(void, ReleaseMemory, + _In_ OrtExternalResourceImporterImpl* this_ptr, + _In_ OrtExternalMemoryHandle* handle); + + /** \brief Create a tensor backed by imported external memory. + * + * The created tensor is a view over the imported memory and does not copy data. + * + * \param[in] this_ptr Pointer to the OrtExternalResourceImporterImpl instance. + * \param[in] mem_handle The imported external memory handle (EP casts to its derived type). + * \param[in] tensor_desc Descriptor specifying tensor element type, shape, and optional offset. + * \param[out] out_tensor Output parameter set to the created OrtValue containing the tensor. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(CreateTensorFromMemory, + _In_ OrtExternalResourceImporterImpl* this_ptr, + _In_ const OrtExternalMemoryHandle* mem_handle, + _In_ const OrtExternalTensorDescriptor* tensor_desc, + _Outptr_ OrtValue** out_tensor); + + // Semaphore operations (require stream) + + /** \brief Check if the implementation can import external semaphores of the given type. + * + * \param[in] this_ptr Pointer to the OrtExternalResourceImporterImpl instance. + * \param[in] type The type of external semaphore to check. + * \return True if the semaphore type is supported. + * + * \since Version 1.24. + */ + ORT_API_T(bool, CanImportSemaphore, + _In_ const OrtExternalResourceImporterImpl* this_ptr, + _In_ OrtExternalSemaphoreType type); + + /** \brief Import an external semaphore. + * + * The EP creates a derived type of OrtExternalSemaphoreHandle and returns a pointer to the base. + * EP is responsible for the lifetime of the handle (release via ReleaseSemaphore). + * + * \param[in] this_ptr Pointer to the OrtExternalResourceImporterImpl instance. + * \param[in] desc Descriptor containing the external semaphore handle and type. + * \param[out] out_handle Output parameter set to the created OrtExternalSemaphoreHandle (EP's derived type). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(ImportSemaphore, + _In_ OrtExternalResourceImporterImpl* this_ptr, + _In_ const OrtExternalSemaphoreDescriptor* desc, + _Outptr_ OrtExternalSemaphoreHandle** out_handle); + + /** \brief Release an imported external semaphore handle. + * + * The EP deletes its derived type instance. + * + * \param[in] this_ptr Pointer to the OrtExternalResourceImporterImpl instance. + * \param[in] handle The OrtExternalSemaphoreHandle to release (EP casts to its derived type). + * + * \since Version 1.24. + */ + ORT_API_T(void, ReleaseSemaphore, + _In_ OrtExternalResourceImporterImpl* this_ptr, + _In_ OrtExternalSemaphoreHandle* handle); + + /** \brief Wait on an external semaphore on the EP's stream. + * + * Inserts a wait operation into the EP's stream that blocks until the semaphore + * reaches the specified value. + * + * \param[in] this_ptr Pointer to the OrtExternalResourceImporterImpl instance. + * \param[in] handle The imported external semaphore (EP casts to its derived type). + * \param[in] stream The OrtSyncStream to wait on. + * \param[in] value The fence/semaphore value to wait for. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(WaitSemaphore, + _In_ OrtExternalResourceImporterImpl* this_ptr, + _In_ OrtExternalSemaphoreHandle* handle, + _In_ OrtSyncStream* stream, + _In_ uint64_t value); + + /** \brief Signal an external semaphore from the EP's stream. + * + * Inserts a signal operation into the EP's stream that sets the semaphore + * to the specified value when reached. + * + * \param[in] this_ptr Pointer to the OrtExternalResourceImporterImpl instance. + * \param[in] handle The imported external semaphore (EP casts to its derived type). + * \param[in] stream The OrtSyncStream to signal from. + * \param[in] value The fence/semaphore value to signal. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(SignalSemaphore, + _In_ OrtExternalResourceImporterImpl* this_ptr, + _In_ OrtExternalSemaphoreHandle* handle, + _In_ OrtSyncStream* stream, + _In_ uint64_t value); + + // Release the capability object itself + + /** \brief Release the OrtExternalResourceImporterImpl instance. + * + * This is called by ORT when the OrtExternalResourceImporterImpl instance is no longer needed. + * The implementation should release any resources held by the instance. + * + * \param[in] this_ptr Pointer to the OrtExternalResourceImporterImpl instance. + * + * \since Version 1.24. + */ + ORT_API_T(void, Release, _In_ OrtExternalResourceImporterImpl* this_ptr); +}; + +/** \brief The event category for profiling events reported by an execution provider. + * + * \since Version 1.25. + */ +typedef enum OrtProfilingEventCategory { + OrtProfilingEventCategory_SESSION = 0, ///< Session-level event + OrtProfilingEventCategory_NODE = 1, ///< Node-level event + OrtProfilingEventCategory_KERNEL = 2, ///< Kernel-level event + OrtProfilingEventCategory_API = 3, ///< API-level event +} OrtProfilingEventCategory; + +struct OrtEpProfilerImpl; +typedef struct OrtEpProfilerImpl OrtEpProfilerImpl; + +/** \brief Struct that an EP implements for profiling support. + * + * An execution provider optionally implements this struct to participate in ONNX Runtime's profiling system. + * The EP creates and returns an instance of this struct via OrtEp::CreateProfiler. + * + * ORT calls the function pointers at appropriate times during a profiling session: + * - StartProfiling once when profiling begins. + * - [Optional] StartEvent / StopEvent around each ORT event (operator executions, session events, etc.). + * - EndProfiling once when profiling ends to collect EP events. + * - Release when ORT no longer needs the profiler. + * + * Profiling scenarios: + * - ORT session profiling: Captures session initialization and one or more runs with a single ORT session. + * - Enabled via OrtApi::EnableProfiling(session_options). + * - There is one ORT session, one OrtEp, and one OrtEpProfilerImpl + * - Concurrency notes: An application may use a single ORT session (and the single OrtEpProfilerImpl) to run + * multiple inferences concurrently. The OrtEpProfilerImpl::StartEvent and OrtEpProfilerImpl::StopEvent + * functions will be called with ORT events from multiple concurrent runs. The OrtEpProfilerImpl::EndProfiling + * function is expected to return all EP events from all runs with correct correlations with the original ORT + * events. + * - ORT run profiling: Captures events for a given run. An application can either enable session profiling or run + * profiling, but not both at the same time. + * - Enabled via OrtApi::RunOptionsEnableProfiling(run_options). + * - There is one ORT session, one OrtEp, and multiple OrtEpProfilerImpl instances (one per profiled run). + * - Concurrency notes: each OrtEpProfilerImpl only receives calls for its specific run. + * OrtEpProfilerImpl::EndProfiling must only return EP events for its specific run. + * + * \since Version 1.25. + */ +struct OrtEpProfilerImpl { + uint32_t ort_version_supported; ///< Must be initialized to ORT_API_VERSION. + + /** \brief Release the OrtEpProfilerImpl instance. + * + * Called by ORT when the profiler is no longer needed. + * The implementation should release any resources held by the instance. + * + * \param[in] this_ptr Pointer to the OrtEpProfilerImpl instance. + * + * \note Implementation of this function is required. + * + * \since Version 1.25. + */ + ORT_API_T(void, Release, _In_ OrtEpProfilerImpl* this_ptr); + + /** \brief Called when profiling starts. + * + * Allows the EP profiler to initialize profiling utilities and record the profiling start time. + * + * An EP profiler should record its own clock's current time when this function is called. This allows the EP to + * later compute ORT-relative event timestamps by combining `ep_profiling_start_offset_ns` with the EP's own + * elapsed time since this call. The formula is: + * + * event_timestamp_us = (ep_profiling_start_offset_ns + (ep_event_time_ns - ep_profiling_start_time_ns)) / 1000 + * + * where `ep_event_time_ns` and `ep_profiling_start_time_ns` are measured using the EP's own clock. + * + * \param[in] this_ptr Pointer to the OrtEpProfilerImpl instance. + * \param[in] ep_profiling_start_offset_ns The elapsed time in nanoseconds (using ORT's profiling clock) between + * ORT's profiling start and this call to StartProfiling. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note An error OrtStatus returned from this function is logged by ORT (does not end execution). + * \note Implementation of this function is required. + * + * \since Version 1.25. + */ + ORT_API2_STATUS(StartProfiling, _In_ OrtEpProfilerImpl* this_ptr, _In_ int64_t ep_profiling_start_offset_ns); + + /** \brief Called when an ORT event (e.g., session initialization, node kernel execution, etc.) begins. + * + * ORT pairs every StartEvent call with a corresponding call to StopEvent with the same ORT event correlation ID. + * EP profiler implementations may use the calls to StartEvent and StopEvent to maintain a stack of ORT event + * correlation IDs that can be correlated with EP events (e.g., GPU kernel events). For example: + * + * OrtEpProfilerImpl::StartEvent(x) -> EP ort event stack: [x] <- top of stack + * [EP events are tagged with 'x'] + * OrtEpProfilerImpl::StartEvent(y) -> EP ort event stack: [x, y] <- top of stack + * [EP events are tagged with 'y'] + * OrtEpProfilerImpl::StopEvent(y) -> EP ort event stack: [x] <- top of stack + * OrtEpProfilerImpl::StartEvent(z) -> EP ort event stack: [x, z] <- top of stack + * [EP events are tagged with 'z'] + * OrtEpProfilerImpl::StopEvent(z) -> EP ort event stack: [x] <- top of stack + * OrtEpProfilerImpl::StopEvent(x) -> EP ort event stack: [ ] <- top of stack + * + * Tagging EP events with the ORT event correlation ID enables the EP to annotate its own events + * with metadata from the parent ORT event (e.g., operator name). + * + * \note **Threading:** For a given ORT event, StartEvent, the kernel's Compute() entry point, and StopEvent + * are all invoked on the same CPU thread (Compute() may asynchronously launch device work). + * Different ORT events may run on different threads (e.g., inter-op parallelism), so correlation + * stacks (e.g., for CUPTI) should use thread-local storage. + * + * \note The ORT event correlation ID is an absolute, epoch-based timestamp in microseconds. It is computed + * from the ORT event's start time using std::chrono::high_resolution_clock (platform-defined epoch). + * Because it is absolute rather than relative to profiling start, it is practically unique across + * concurrent profiling sessions within the same process (collisions require sub-microsecond event + * concurrency) and can be used directly as a correlation ID for EP profiling utilities + * (e.g., CUPTI or ROCTracer). + * + * \param[in] this_ptr Pointer to the OrtEpProfilerImpl instance. + * \param[in] ort_event_correlation_id Absolute, epoch-based correlation ID for the ORT event that is starting. + * The same value is passed to the corresponding StopEvent call. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note An error OrtStatus returned from this function is logged by ORT (does not end execution). + * \note Implementation of this function is optional. If set to NULL, it is not called. + * + * \since Version 1.25. + */ + ORT_API2_STATUS(StartEvent, _In_ OrtEpProfilerImpl* this_ptr, _In_ uint64_t ort_event_correlation_id); + + /** \brief Called when a profiled ORT event (e.g., session initialization, node kernel execution, etc.) ends. + * + * ORT pairs every StartEvent call with a corresponding call to StopEvent with the same ORT event correlation ID. + * EP profiler implementations may use the calls to StartEvent and StopEvent to maintain a stack of ORT event + * correlation IDs that can be correlated with EP events (e.g., GPU kernel events). For example: + * + * OrtEpProfilerImpl::StartEvent(x) -> EP ort event stack: [x] <- top of stack + * [EP events are tagged with 'x'] + * OrtEpProfilerImpl::StartEvent(y) -> EP ort event stack: [x, y] <- top of stack + * [EP events are tagged with 'y'] + * OrtEpProfilerImpl::StopEvent(y) -> EP ort event stack: [x] <- top of stack + * OrtEpProfilerImpl::StartEvent(z) -> EP ort event stack: [x, z] <- top of stack + * [EP events are tagged with 'z'] + * OrtEpProfilerImpl::StopEvent(z) -> EP ort event stack: [x] <- top of stack + * OrtEpProfilerImpl::StopEvent(x) -> EP ort event stack: [ ] <- top of stack + * + * Tagging EP events with the ORT event correlation ID enables the EP to annotate its own events + * with metadata from the parent ORT event (e.g., operator name). + * + * \note **Threading:** For a given ORT event, StartEvent, the kernel's Compute() entry point, and StopEvent + * are all invoked on the same CPU thread (Compute() may asynchronously launch device work). + * Different ORT events may run on different threads (e.g., inter-op parallelism), so correlation + * stacks (e.g., for CUPTI) should use thread-local storage. + * + * \note The ORT event correlation ID is an absolute, epoch-based timestamp in microseconds. It is computed + * from the ORT event's start time using std::chrono::high_resolution_clock (platform-defined epoch). + * Because it is absolute rather than relative to profiling start, it is practically unique across + * concurrent profiling sessions within the same process (collisions require sub-microsecond event + * concurrency) and can be used directly as a correlation ID for EP profiling utilities + * (e.g., CUPTI or ROCTracer). + * + * \param[in] this_ptr Pointer to the OrtEpProfilerImpl instance. + * \param[in] ort_event_correlation_id Absolute, epoch-based correlation ID for the ORT event that is ending. + * The same value was passed to the corresponding StartEvent call. + * \param[in] ort_event Opaque pointer to the ORT profiling event. Valid only during this call. + * Use OrtEpApi accessor functions to read event fields. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note An error OrtStatus returned from this function is logged by ORT (does not end execution). + * \note Implementation of this function is optional. If set to NULL, it is not called. + * + * \since Version 1.25. + */ + ORT_API2_STATUS(StopEvent, _In_ OrtEpProfilerImpl* this_ptr, _In_ uint64_t ort_event_correlation_id, + _In_ const OrtProfilingEvent* ort_event); + + /** \brief Called when profiling ends to collect the EP's new profiling events since the call to StartProfiling. + * + * An EP profiler converts its events to OrtProfilingEvent instances and adds them into the provided + * OrtProfilingEventsContainer container. Call OrtEpApi::CreateProfilingEvent to create a new + * OrtProfilingEvent instance. Then call OrtEpApi::ProfilingEventsContainer_AddEvents to add one or more + * events to the container. + * + * After this function returns, ORT appends the EP's events to the profiling timeline. + * + * \param[in] this_ptr The OrtEpProfilerImpl instance. + * \param[in] events_container Event container to which the EP profiler adds its new events. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note An error OrtStatus returned from this function is logged by ORT (does not end execution). + * \note Implementation of this function is required. + * + * \since Version 1.25. + */ + ORT_API2_STATUS(EndProfiling, _In_ OrtEpProfilerImpl* this_ptr, + _In_ OrtProfilingEventsContainer* events_container); +}; + +struct OrtNodeFusionOptions; +typedef struct OrtNodeFusionOptions OrtNodeFusionOptions; + +struct OrtNodeComputeInfo; +typedef struct OrtNodeComputeInfo OrtNodeComputeInfo; + +/** + * \brief The OrtNodeFusionOptions struct specifies options for fusing nodes supported by an execution provider. + * + * Refer to OrtEpApi::EpGraphSupportInfo_AddNodesToFuse. + * + * \since Version 1.23. + */ +struct OrtNodeFusionOptions { + /** \brief The ONNX Runtime version the OrtNodeFusionOptions was compiled with. + * + * Implementation should set to ORT_API_VERSION. + * ORT will use this to ensure it does not use members that were not available when the EP library was compiled. + * + * \since Version 1.23. + */ + uint32_t ort_version_supported; + + /** \brief If set to true, specify that the execution provider does not require ONNX Runtime to provide constant + * initializers as inputs to the fused node during model inference. This is used when the execution + * provider saves a copy of constant initializers, and allows ONNX Runtime to release constant initializers that + * are not used by any execution provider. + * + * If not specified, defaults to false. That is, ONNX Runtime provides constant initializers as inputs to + * the fused node by default. + * + * \since Version 1.23. + */ + bool drop_constant_initializers; + + // const OrtNode* fused_node_schema; +}; + +/** + * \brief The OrtNodeComputeInfo struct provides functions that an OrtEp implements to specify the compute + * function for a compiled OrtGraph instance. + * \since Version 1.23. + */ +struct OrtNodeComputeInfo { + /** \brief The ONNX Runtime version the OrtNodeComputeInfo was compiled with. + * + * Implementation should set to ORT_API_VERSION. + * ORT will use this to ensure it does not call functions that were not available when the EP library was compiled. + * + * \since Version 1.23. + */ + uint32_t ort_version_supported; + + /** \brief Creates an opaque compute state object that is then passed to the Compute() function during inference. + * \param[in] this_ptr The OrtNodeComputeInfo instance. + * \param[in] compute_context OrtNodeComputeContext instance that contains compiled/fused node's name and host + * memory allocation functions. Can optionally be used to build the compute state. + * \param[out] compute_state Output parameter that is assigned the opaque computation state. ONNX Runtime calls + * ReleaseState() (after calling Compute()) to allow the implementer to release the + * compute state. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + OrtStatus*(ORT_API_CALL* CreateState)(_In_ OrtNodeComputeInfo* this_ptr, + _In_ OrtNodeComputeContext* compute_context, + _Outptr_ void** compute_state); + + /** \brief Computation function called to execute the fused node compiled by an OrtEp instance. + * \param[in] this_ptr The OrtNodeComputeInfo instance. + * \param[in] compute_state The opaque computation state returned by CreateState(). + * \param[in] kernel_context The OrtKernelContext instance used to access inputs/outputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + OrtStatus*(ORT_API_CALL* Compute)(_In_ OrtNodeComputeInfo* this_ptr, _In_ void* compute_state, + _In_ OrtKernelContext* kernel_context); + + /** \brief Releases the compute state returned by CreateState(). + * \param[in] this_ptr The OrtNodeComputeInfo instance. + * \param[inout] compute_state The opaque compute state returned by CreateState(). + * + * \since Version 1.23. + */ + void(ORT_API_CALL* ReleaseState)(_In_ OrtNodeComputeInfo* this_ptr, _Frees_ptr_opt_ void* compute_state); +}; + +struct OrtKernelImpl; +typedef struct OrtKernelImpl OrtKernelImpl; + +/** + * \brief Contains functions that an OrtEp implements to specify the computation for an operator kernel. + * \since Version 1.24. + */ +struct OrtKernelImpl { + uint32_t ort_version_supported; ///< Must be initialized to ORT_API_VERSION + uint32_t flags; ///< EP must initialize to 0. Used internally by ORT. + + /** \brief Computation function called to execute the kernel on an EP. + * + * \note Implementation of this function is required. + * + * \param[in] this_ptr The OrtKernelImpl instance. + * \param[in] context The OrtKernelContext instance that provides access to the inputs and outputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(Compute, _In_ OrtKernelImpl* this_ptr, _In_ OrtKernelContext* context); + + /** \brief Called by ORT to release the OrtKernelImpl instance and its resources. + * + * \note Implementation of this function is required. + * + * \param[in] this_ptr The OrtKernelImpl instance. + * + * \since Version 1.24. + */ + ORT_API_T(void, Release, _In_ OrtKernelImpl* this_ptr); + + /** \brief Optional function to pre-pack a constant tensor (i.e., a weight) to the kernel's preferred data layout. + * + * For example, a Conv kernel can define this function to pack input W to the channel-last data layout + * before inference. + * + * Pre-packing can operate in three different modes: no pre-packing mode, sharing mode, and non-sharing mode. + * 1) No pre-packing mode: The kernel can forgo any weight pre-packing for the given `input_index` by setting + * `is_packed` to false and returning a successful OrtStatus. In this mode, the kernel's + * OrtKernelImpl::SetSharedPrePackedWeight() function is not called for that specific + * `input_index`. + * 2) Sharing mode: Sharing is allowed if the `prepacked_weight_cache` argument is not NULL and the EP stores + * weight data in CPU-accessible memory. In this case, the kernel can optionally choose + * to share the packed weight with other kernels that use the same weight + * (compared by content hash). To do so, the kernel must allocate the packed weight with the + * provided `allocator`, then it stores the packed weight data into `prepacked_weight_cache` + * via SharedPrePackedWeightCache_StoreWeightData(), sets `is_packed` to true, and returns a + * successful OrtStatus. ORT will subsequently call OrtKernelImpl::SetSharedPrePackedWeight() + * to provide this kernel with the actual shared weight data, whose memory location could + * differ (i.e., if shared data was allocated by a previously processed kernel). + * 3) Non-sharing mode: In non-sharing mode, the `prepacked_weight_cache` argument is ignored. In this mode, + * the implementation allocates the packed data with the provided `allocator`, sets + * `is_packed` to true, and returns a successful OrtStatus. The kernel is ultimately + * responsible for releasing the packed data for the weight with `allocator`. + * ORT may release the original (unpacked) weight, which must not be accessed in + * OrtKernelImpl::Compute(). Note that in this mode, the kernel's + * OrtKernelImpl::SetSharedPrePackedWeight() function is not called by ORT for that specific + * `input_index`. + * + * \note This function is based on the internal OpKernel::PrePack() virtual function used within ORT. + * + * \param[in] this_ptr The OrtKernelImpl instance. + * \param[in] tensor The OrtValue instance representing the constant tensor (weight). Do not cache in the kernel. + * \param[in] input_index The input index of the tensor in this kernel. + * \param[in] allocator Allocator for allocating the pre-packed data. Its use is required in sharing mode and + * recommended, but not required, in the non-sharing mode. This will be an allocator set by + * the application for the session/environment (e.g., via CreateAndRegisterAllocator[V2] + * or RegisterAllocator), or an allocator on the OrtEpDevice (read-only or default) otherwise. + * The allocator remains valid throughout the lifetime of the OrtKernelImpl instance. + * \param[in] prepacked_weight_cache May be NULL. If not NULL, the kernel may choose to share a packed weight by + * first storing it in the OrtSharedPrePackedWeightCache instance and then + * receiving the actual shared weight data in the call to + * OrtKernelImpl::SetSharedPrePackedWeight(). See the above description for + * "sharing mode". + * \param[out] is_packed Output parameter that the implementation sets to true if the kernel packed the tensor data. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note Implementation of this function is optional. If not implemented (set to NULL), ORT assumes the kernel + * does not pre-pack weight data (i.e., `is_packed` defaults to false). + * + * \since Version 1.24. + */ + ORT_API2_STATUS(PrePackWeight, _In_ OrtKernelImpl* this_ptr, _In_ const OrtValue* tensor, + _In_ int input_index, _Inout_ OrtAllocator* allocator, + _In_opt_ OrtSharedPrePackedWeightCache* prepacked_weight_cache, _Out_ bool* is_packed); + + /** \brief Optional function that receives data for a shared pre-packed weight from ORT. + * + * ORT calls this function after calling OrtKernelImpl::PrePackWeight for a specific `input_index` if: + * - OrtKernelImpl::PrePackWeight set the output parameter `is_packed` to true. + * - OrtKernelImpl::PrePackWeight stored weight data to share into the provided OrtSharedPrePackedWeightCache + * parameter (`prepacked_weight_cache`) via the API SharedPrePackedWeightCache_StoreWeightData. + * + * Refer to the description of the "sharing-mode" in the documentation for OrtKernelImpl::PrePackWeight(). + * + * \note ORT will not call this function for an `input_index` that a previous call to + * OrtKernelImpl::PrePackWeight() did not elect to pre-pack and share. + * + * \note This function is based on the internal OpKernel::UseSharedPrePackedBuffers() virtual function used + * within ORT. + * + * \param[in] this_ptr The OrtKernelImpl instance. + * \param[in] buffer_data_ptrs An array of buffer data pointers that collectively hold the pre-packed data for a + * single shared weight. The buffers are provided in the same order and with the same + * contents (in a potentially different memory location) as the buffers + * passed into SharedPrePackedWeightCache_StoreWeightData() within the + * OrtKernelImpl::PrePackWeight() call for the same `input_index`. + * \param[in] buffer_data_sizes An array of buffer byte sizes, one per element in `buffer_data_ptrs`. + * \param[in] num_buffers The number of buffers used to store the data for the shared pre-packed weight. + * Specifies the number of elements in the `buffer_data_ptrs` and `buffer_data_sizes` arrays. + * \param[in] input_index The input index of the tensor in this kernel. This index identifies the identity of + * the weight. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note Implementation of this function is generally optional. It is only required if OrtKernelImpl::PrePack() + * elects to share pre-packed weights. + * + * \since Version 1.24. + */ + ORT_API2_STATUS(SetSharedPrePackedWeight, _In_ OrtKernelImpl* this_ptr, + _In_reads_(num_buffers) const void* const* buffer_data_ptrs, + _In_reads_(num_buffers) const size_t* buffer_data_sizes, + _In_ size_t num_buffers, _In_ int input_index); +}; + +/** \brief Type definition for a function that creates an OrtKernelImpl instance for an operator kernel. + * + * \param[in] kernel_create_func_state Opaque state initially provided by the EP that registered the kernel. + * Refer to OrtEpApi::KernelRegistry_AddKernel(). May be null. + * \param[in] info The OrtKernelInfo instance that provides access to the kernel's input and output characteristics. + * \param[out] kernel_out Output parameter set to the new OrtKernelImpl instance. On success, ownership of this + * OrtKernelImpl instance transfers to ORT, which will call OrtKernelImpl::Release() to + * release the instance when it is no longer used. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ +typedef OrtStatus*(ORT_API_CALL* OrtKernelCreateFunc)(_In_ void* kernel_create_func_state, + _In_ const OrtKernelInfo* info, + _Outptr_result_maybenull_ OrtKernelImpl** kernel_out); + +struct OrtLoopKernelHelper; +typedef struct OrtLoopKernelHelper OrtLoopKernelHelper; + +/** + * \brief Contains helper functions for a Loop OrtKernelImpl created via OrtEpApi::CreateLoopKernel. + * \since Version 1.24. + */ +struct OrtLoopKernelHelper { + uint32_t ort_version_supported; ///< Must be initialized to ORT_API_VERSION + + /** \brief Called by ORT to release the OrtLoopKernelHelper instance and its resources. + * + * \param[in] this_ptr The OrtLoopKernelHelper instance. + * + * \since Version 1.24. + */ + ORT_API_T(void, Release, _In_ OrtLoopKernelHelper* this_ptr); + + /** \brief Helper function that concatenates OrtValue instances from each loop iteration into a single + * pre-allocated output buffer. + * + * \note Implementing this function is required for all Loop opset versions. + * + * \param[in] this_ptr The OrtLoopKernelHelper instance. + * \param[in] stream_handle Optional native stream handle that enables asynchronous operations. May be NULL. + * \param[in] per_iteration_outputs Array of OrtValue instances from each iteration. All OrtValue elements have the + * same shape. + * \param[in] num_per_iteration_outputs The number of OrtValue* elements in the `per_iteration_outputs` array. + * \param[out] output The pre-allocated output buffer. Memory is allocated on the device for the EP running the + * Loop node. + * \param[in] output_size_in_bytes The size in bytes of the `output` buffer. It is guaranteed to be large enough + * to hold the concatenated data of each element in `per_iteration_outputs`. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(ConcatOutput, _In_ OrtLoopKernelHelper* this_ptr, _In_opt_ void* stream_handle, + _In_reads_(num_per_iteration_outputs) const OrtValue* const* per_iteration_outputs, + _In_ size_t num_per_iteration_outputs, _Out_writes_bytes_all_(output_size_in_bytes) void* output, + _In_ size_t output_size_in_bytes); +}; + +struct OrtScanKernelHelper; +typedef struct OrtScanKernelHelper OrtScanKernelHelper; + +/** + * \brief Contains helper functions for a Scan OrtKernelImpl created via OrtEpApi::CreateScanKernel. + * \since Version 1.24. + */ +struct OrtScanKernelHelper { + uint32_t ort_version_supported; ///< Must be initialized to ORT_API_VERSION + + /** \brief Called by ORT to release the OrtScanKernelHelper instance and its resources. + * + * \param[in] this_ptr The OrtScanKernelHelper instance. + * + * \since Version 1.24. + */ + ORT_API_T(void, Release, _In_ OrtScanKernelHelper* this_ptr); + + /** \brief Helper function that transposes an OrtValue instance during execution of a Scan kernel. + * + * \note Called for Scan (opset >= 9) when the 'scan_input_axes' or 'scan_output_axes' attributes contain + * non-zero values. Implementing this function is required for Scan opset versions >= 9. + * + * \param[in] this_ptr The OrtScanKernelHelper instance. + * \param[in] permutation An array of integers that defines how the input tensor's axes should be permuted. + * \param[in] num_permutation_elems The number of integer elements in the `permutation` array. + * \param[in] input The input OrtValue tensor to transpose. + * \param[in] stream An optional OrtSyncStream instance to be used for asynchronous operations. May be NULL. + * \param[out] output The pre-allocated output OrtValue instance into which to store the results of the + * transpose operation. Must not be released as it is owned by ORT. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(Transpose, _In_ OrtScanKernelHelper* this_ptr, + _In_reads_(num_permutation_elems) const size_t* permutation, _In_ size_t num_permutation_elems, + _In_ const OrtValue* input, _In_opt_ OrtSyncStream* stream, _Inout_ OrtValue* output); +}; + +/** + * \brief Discriminator for the resource count type stored in an OrtResourceCount. + * + * New resource accounting types can be added by appending new enum values. + * The OrtResourceCount union storage is large enough to hold all current and future types. + * + * \since Version 1.26. + */ +typedef enum OrtResourceCountKind { + OrtResourceCountKind_None = 0, ///< Unset / zero-cost sentinel. + OrtResourceCountKind_TotalBytes = 1, ///< Single uint64_t: byte count (cost or budget). +} OrtResourceCountKind; + +/** + * \brief ABI-stable tagged union representing a resource cost or budget. + * + * This struct is a C-safe variant that can be passed by value across the plugin DLL boundary. + * The `kind` field selects which member of the `value` union is active. The + * `value.reserved_words` storage reserves space for future resource types without changing + * the struct layout. + * + * Adding new resource types requires only: (a) a new OrtResourceCountKind enum value, + * (b) a new union member. No new C API functions are needed. + * + * \since Version 1.26. + */ +typedef struct OrtResourceCount { + uint32_t kind; /**< OrtResourceCountKind discriminator. */ + uint32_t reserved; /**< Must be zero. Ensures natural alignment for the value union. */ + + union { + uint64_t total_bytes; /**< Active when kind == OrtResourceCountKind_TotalBytes. */ + uint64_t reserved_words[6]; /**< 48 bytes fixed storage for future resource types. */ + } value; + +#ifdef __cplusplus + /** Default-construct a None (unset) resource count. */ + OrtResourceCount() noexcept : kind{OrtResourceCountKind_None}, reserved{0}, value{} {} + + /** Construct a zero/unset resource count. */ + static OrtResourceCount None() noexcept { + return OrtResourceCount{}; + } + + /** Construct a resource count representing total bytes. */ + static OrtResourceCount FromTotalBytes(uint64_t bytes) noexcept { + OrtResourceCount rc{}; + rc.kind = OrtResourceCountKind_TotalBytes; + rc.value.total_bytes = bytes; + return rc; + } + + /** Read the total_bytes value (caller must check kind first). */ + uint64_t AsTotalBytes() const noexcept { + return value.total_bytes; + } +#endif +} OrtResourceCount; + +#ifdef __cplusplus +static_assert(sizeof(OrtResourceCount) == 56, "OrtResourceCount size must not change to maintain ABI stability"); +#endif + +/** + * \brief The OrtEpApi struct provides functions that are relevant to the implementation of an execution provider. + * + * \since Version 1.22. + */ +struct OrtEpApi { + /** \brief Create an OrtEpDevice for the EP and an OrtHardwareDevice. + * \param[in] ep_factory Execution provider factory that is creating the instance. + * \param[in] hardware_device Hardware device that the EP can utilize. + * \param[in] ep_metadata Optional OrtKeyValuePairs instance for execution provider metadata that may be used + * during execution provider selection and passed to CreateEp. + * ep_device will copy this instance and the user should call ReleaseKeyValuePairs. + * \param[in] ep_options Optional OrtKeyValuePairs instance for execution provider options that will be added + * to the Session configuration options if the execution provider is selected. + * ep_device will copy this instance and the user should call ReleaseKeyValuePairs. + * \param ep_device OrtExecutionDevice that is created. + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateEpDevice, _In_ OrtEpFactory* ep_factory, + _In_ const OrtHardwareDevice* hardware_device, + _In_opt_ const OrtKeyValuePairs* ep_metadata, + _In_opt_ const OrtKeyValuePairs* ep_options, + _Out_ OrtEpDevice** ep_device); + + ORT_CLASS_RELEASE(EpDevice); + + /** \brief Specify nodes that are supported by an OrtEp and should be fused into one node. + * + * Because the nodes will be fused into one "fused node", there must not exist an unsupported node in + * a path between two of the provided nodes. Otherwise, the graph will become invalid. + * + * This function can be called multiple times. A subsequent call to this function will force the next set of + * nodes to be fused into a different node. + * + * \param[in] graph_support_info OrtEpGraphSupportInfo instance to which to add the supported nodes. + * \param[in] nodes Array of nodes supported by the EP that should be fused/compiled. + * \param[in] num_nodes The number of supported nodes. + * \param[in] node_fusion_options Optional node fusion options. Ignored if set to NULL. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(EpGraphSupportInfo_AddNodesToFuse, _In_ OrtEpGraphSupportInfo* graph_support_info, + _In_reads_(num_nodes) const OrtNode* const* nodes, _In_ size_t num_nodes, + _In_opt_ const OrtNodeFusionOptions* node_fusion_options); + + /** \brief Specify a node that is supported by an OrtEp and should be run with a registered EP kernel. + * + * \param[in] graph_support_info OrtEpGraphSupportInfo instance to which to add the supported node. + * \param[in] node The supported OrtNode instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(EpGraphSupportInfo_AddSingleNode, _In_ OrtEpGraphSupportInfo* graph_support_info, + _In_ const OrtNode* node); + + /** \brief Query a OrtNodeComputeContext for the name of the node that encapsulates the compiled/fused node. + * + * Used in OrtNodeComputeInfo::CreateComputeState(). + * + * \param[in] context The OrtNodeComputeContext instance to query. + * \return The node's name. + * + * \note Returned string is owned by ORT and valid only while OrtNodeComputeInfo::CreateComputeState() is called. + * + * \since Version 1.23. + */ + ORT_API_T(const char*, NodeComputeContext_NodeName, _In_ const OrtNodeComputeContext* context); + + /** \brief Register an allocator with the OrtEpDevice. + * + * This allows an EP to provide OrtMemoryInfo for DEFAULT and HOST_ACCESSIBLE memory type as needed. + * The registered values will be used in calls to OrtEpFactory::CreateAllocator to ensure the required allocator/s + * are available for EP usage. + * + * Multiple calls for the same entry type will replace a previous entry. + * + * Available entries: + * - OrtDeviceAllocator with type of OrtDeviceMemoryType_DEFAULT + * - OrtDeviceAllocator with type of OrtDeviceMemoryType_HOST_ACCESSIBLE + * - OrtReadOnlyAllocator with type of OrtDeviceMemoryType_DEFAULT + * - if provided this allocator will only be used to copy initializers to the device the EP uses. + * ORT will use the OrtDeviceAllocator if not provided. + * + * \param[in] ep_device The OrtEpDevice instance to register the OrtMemoryInfo with. + * \param[in] allocator_memory_info The OrtMemoryInfo information for the allocator. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(EpDevice_AddAllocatorInfo, _In_ OrtEpDevice* ep_device, + _In_ const OrtMemoryInfo* allocator_memory_info); + + /** \brief Get the OrtMemoryDevice from an OrtMemoryInfo instance. + * + * This is required for OrtDataTransferImpl (which implements onnxruntime::IDataTransfer) where the OrtMemoryDevice + * is used in the CanCopy and CopyTensors functions. + * + * \param[in] memory_info The OrtMemoryInfo instance to get the memory device from. + * \return The OrtMemoryDevice associated with the OrtMemoryInfo instance. + * + * \since Version 1.23. + */ + ORT_API_T(const OrtMemoryDevice*, MemoryInfo_GetMemoryDevice, _In_ const OrtMemoryInfo* memory_info); + + /** \brief Get the OrtMemoryDevice from an OrtValue instance if it contains a Tensor. + * + * \param[in] value The OrtValue instance to get the memory device from. + * \return Memory device if OrtValue contains a Tensor, nullptr otherwise. + * + * \since Version 1.23. + */ + ORT_API_T(const OrtMemoryDevice*, Value_GetMemoryDevice, _In_ const OrtValue* value); + + /** \brief Compare two OrtMemoryDevice instances for equality. + * + * This is used to check if two memory devices are the same. + * Used to implement DataTransferImpl::CanCopy. + * + * \param[in] a The first OrtMemoryDevice instance to compare. + * \param[in] b The second OrtMemoryDevice instance to compare. + * \return True if the two OrtMemoryDevice instances are equal, false otherwise. + * + * \since Version 1.23. + */ + ORT_API_T(bool, MemoryDevice_AreEqual, _In_ const OrtMemoryDevice* a, _In_ const OrtMemoryDevice* b); + + /** \brief Get the OrtMemoryInfoDeviceType value from an OrtMemoryDevice instance. + * + * \param[in] memory_device OrtMemoryDevice instance. + * \return The OrtMemoryInfoDeviceType value. + * + * \since Version 1.23. + */ + ORT_API_T(OrtMemoryInfoDeviceType, MemoryDevice_GetDeviceType, _In_ const OrtMemoryDevice* memory_device); + + /** \brief Get the OrtDeviceMemoryType value from an OrtMemoryDevice instance. + * + * \param[in] memory_device OrtMemoryDevice instance. + * \return The OrtDeviceMemoryType value. + * + * \since Version 1.23. + */ + ORT_API_T(OrtDeviceMemoryType, MemoryDevice_GetMemoryType, _In_ const OrtMemoryDevice* memory_device); + + /** \brief Get the vendor ID from an OrtMemoryDevice instance. + * + * The vendor ID is used to identify the vendor of the device, and is typically set to the PCI vendor ID. + * + * If the device is not vendor specific (e.g. CPU memory) the vendor ID is set to 0. + * + * \param[in] memory_device OrtMemoryDevice instance. + * \return The vendor ID value. + * + * \since Version 1.23. + */ + ORT_API_T(uint32_t, MemoryDevice_GetVendorId, _In_ const OrtMemoryDevice* memory_device); + + /** \brief Get the device ID from an OrtMemoryDevice instance. + * + * \param[in] memory_device OrtMemoryDevice instance. + * \return The device ID. + * + * \since Version 1.23. + */ + ORT_API_T(uint32_t, MemoryDevice_GetDeviceId, _In_ const OrtMemoryDevice* memory_device); + + /** \brief Get the OrtSyncStreamImpl associated with an OrtSyncStream instance. + * + * This allows an the plugin library to connect its OrtSyncStreamImpl instance with an OrtSyncStream if needed. + * + * \param[in] stream The OrtSyncStream instance to find an OrtSyncStreamImpl for. + * \return The associated OrtSyncStreamImpl if found. nullptr otherwise. + * + * \since Version 1.23. + * + * \remarks There should always be an OrtSyncStreamImpl associated with an OrtSyncStream instance that the EP gets. + */ + ORT_API_T(const OrtSyncStreamImpl*, SyncStream_GetImpl, _In_ const OrtSyncStream* stream); + + /** \brief Get the current sync ID for a stream. + * + * \param[in] stream The OrtSyncStream to get the sync ID for. + * \return Current sync ID. + * + * \since Version 1.23. + */ + ORT_API_T(uint64_t, SyncStream_GetSyncId, _In_ const OrtSyncStream* stream); + + /** \brief Get the sync ID for the last time the consumer_stream waited on the producer_stream. + * + * When two streams are synchronized, the sync id represents the event used in that synchronization. + * + * \param[in] producer_stream The OrtSyncStream that produced the data. + * \param[in] consumer_stream The OrtSyncStream that waited on the producer_stream. + * \return ID for last sync. 0 if no sync has occurred between the two streams. + * + * \since Version 1.23. + */ + ORT_API_T(uint64_t, GetSyncIdForLastWaitOnSyncStream, + _In_ const OrtSyncStream* producer_stream, _In_ const OrtSyncStream* consumer_stream); + + /** \brief Create an OrtHardwareDevice. + * + * \note Called within OrtEpFactory::GetSupportedDevices to create a new hardware device (e.g., virtual). + * + * \param[in] type The hardware device type. + * \param[in] vendor_id The hardware device's vendor identifier. + * \param[in] device_id The hardware device's identifier. + * \param[in] vendor_name The hardware device's vendor name as a null-terminated string. Copied by ORT. + * \param[in] metadata Optional OrtKeyValuePairs instance for hardware device metadata that may be queried by + * applications via OrtApi::GetEpDevices(). + * Refer to onnxruntime_ep_device_ep_metadata_keys.h for common OrtHardwareDevice metadata keys. + * \param[out] hardware_device Output parameter set to the new OrtHardwareDevice instance that is created. + * Must be release with ReleaseHardwareDevice(). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(CreateHardwareDevice, _In_ OrtHardwareDeviceType type, + _In_ uint32_t vendor_id, + _In_ uint32_t device_id, + _In_ const char* vendor_name, + _In_opt_ const OrtKeyValuePairs* metadata, + _Out_ OrtHardwareDevice** hardware_device); + + ORT_CLASS_RELEASE(HardwareDevice); + + /** \brief Creates an empty kernel registry. A kernel registry contains kernel creation information for + * every operator kernel supported by an EP. + * + * \remarks Refer to OrtEp::GetKernelRegistry, which returns an EP's kernel registry to ORT. + * + * \param[out] kernel_registry Output parameter set to the new OrtKernelRegistry instance. + * Must be released with OrtEpApi::ReleaseKernelRegistry. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(CreateKernelRegistry, _Outptr_ OrtKernelRegistry** kernel_registry); + + ORT_CLASS_RELEASE(KernelRegistry); + + /** \brief Adds kernel creation information for a supported operator kernel to the given kernel registry. + * + * \remarks Refer to OrtEp::GetKernelRegistry, which returns an EP's kernel registry to ORT. + * + * \param[in] kernel_registry The OrtKernelRegistry instance. + * \param[in] kernel_def The kernel definition, which includes operator type, version, EP name, type constraints, etc. + * \param[in] kernel_create_func Function that creates an instance of the operator kernel as a OrtKernelImpl instance. + * \param[in] kernel_create_func_state Custom state passed to the kernel creation function. Can be null. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelRegistry_AddKernel, _In_ OrtKernelRegistry* kernel_registry, + _In_ const OrtKernelDef* kernel_def, _In_ OrtKernelCreateFunc kernel_create_func, + _In_ void* kernel_create_func_state); + + /** \brief Creates a kernel definition builder used to create instances of OrtKernelDef. + * + * \param[out] kernel_def_builder_out Output parameter set to the new OrtKernelDefBuilder instance. + * Must be released with OrtEpApi::ReleaseKernelDefBuilder(). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(CreateKernelDefBuilder, _Outptr_ OrtKernelDefBuilder** kernel_def_builder_out); + + ORT_CLASS_RELEASE(KernelDefBuilder); + + /** \brief Sets the kernel's operator type. + * + * \param[in] kernel_def_builder The OrtKernelDefBuilder instance. + * \param[in] op_type A null-terminated string representing the operator type. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDefBuilder_SetOperatorType, _In_ OrtKernelDefBuilder* kernel_def_builder, + _In_ const char* op_type); + + /** \brief Sets the kernel's domain. + * + * \param[in] kernel_def_builder The OrtKernelDefBuilder instance. + * \param[in] domain A null-terminated string representing the operator's domain. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDefBuilder_SetDomain, _In_ OrtKernelDefBuilder* kernel_def_builder, _In_ const char* domain); + + /** \brief Sets the kernel's opset version range that is supported. + * + * \param[in] kernel_def_builder The OrtKernelDefBuilder instance. + * \param[in] since_version_start The starting opset version that is supported. + * \param[in] since_version_end The ending opset version (inclusive) that is supported. + * Can be set equal to the starting version to indicate that only one + * version is supported. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDefBuilder_SetSinceVersion, _In_ OrtKernelDefBuilder* kernel_def_builder, + _In_ int since_version_start, _In_ int since_version_end); + + /** \brief Sets the name of the kernel's intended execution provider. + * + * \param[in] kernel_def_builder The OrtKernelDefBuilder instance. + * \param[in] ep_name A null-terminated string representing the execution provider's name. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDefBuilder_SetExecutionProvider, _In_ OrtKernelDefBuilder* kernel_def_builder, + _In_ const char* ep_name); + + /** \brief Sets the memory type for a kernel input. + * + * \param[in] kernel_def_builder The OrtKernelDefBuilder instance. + * \param[in] input_index The index of the input. + * \param[in] mem_type The input's memory type. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDefBuilder_SetInputMemType, _In_ OrtKernelDefBuilder* kernel_def_builder, + _In_ size_t input_index, _In_ OrtMemType mem_type); + + /** \brief Sets the memory type for a kernel output. + * + * \param[in] kernel_def_builder The OrtKernelDefBuilder instance. + * \param[in] output_index The index of the output. + * \param[in] mem_type The output's memory type. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDefBuilder_SetOutputMemType, _In_ OrtKernelDefBuilder* kernel_def_builder, + _In_ size_t output_index, _In_ OrtMemType mem_type); + + /** \brief Adds type constraints for a kernel argument represented as a string (e.g., "T"). + * + * \param[in] kernel_def_builder The OrtKernelDefBuilder instance. + * \param[in] arg_name A null-terminated string representing the argument to constrain (e.g., "T"). + * \param[in] types Array of OrtDataType instances representing allowed types for the argument. + * Must contain `num_types` elements. + * \param[in] num_types The number of OrtDataType elements in the `types` array. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDefBuilder_AddTypeConstraint, _In_ OrtKernelDefBuilder* kernel_def_builder, + _In_ const char* arg_name, _In_reads_(num_types) const OrtDataType* const* types, + _In_ size_t num_types); + + /** \brief Adds aliases for the given input and output pairs. + * + * \note Used for operators like Identity and Reshape to allow ORT to reuse the input buffer for the output + * without modification. + * + * \param[in] kernel_def_builder The OrtKernelDefBuilder instance. + * \param[in] input_indices Array of input indices. Array must contain `num_io_indices` elements. + * \param[in] output_indices Array of output indices. Each output index is aliased with a corresponding + * input index in `input_indices`. Array must contain `num_io_indices` elements. + * \param[in] num_io_indices The number of input/output index pairs to alias. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDefBuilder_AddInputOutputAliases, _In_ OrtKernelDefBuilder* kernel_def_builder, + _In_reads_(num_io_indices) int const* input_indices, + _In_reads_(num_io_indices) int const* output_indices, + _In_ size_t num_io_indices); + + /** \brief Adds mutable aliases for the given input and output pairs. + * + * \note Allows ORT to reuse and *modify* an input buffer (in-place) for the output buffer. + * This is also known as "MayInplace" within the ORT codebase. + * + * \param[in] kernel_def_builder The OrtKernelDefBuilder instance. + * \param[in] input_indices Array of input indices. Array must contain `num_io_indices` elements. + * \param[in] output_indices Array of output indices. Each output index is aliased with a corresponding + * input index in `input_indices`. Array must contain `num_io_indices` elements. + * \param[in] num_io_indices The number of input/output index pairs to alias. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDefBuilder_AddInputOutputMutableAliases, _In_ OrtKernelDefBuilder* kernel_def_builder, + _In_reads_(num_io_indices) int const* input_indices, + _In_reads_(num_io_indices) int const* output_indices, + _In_ size_t num_io_indices); + + /** \brief Creates a OrtKernelDef instance from the given kernel definition builder. + * + * \param[in] kernel_def_builder The OrtKernelDefBuilder instance. + * \param[out] kernel_def_out The new OrtKernelDef instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDefBuilder_Build, _In_ OrtKernelDefBuilder* kernel_def_builder, + _Outptr_ OrtKernelDef** kernel_def_out); + + ORT_CLASS_RELEASE(KernelDef); + + /** \brief Returns the operator type from the kernel definition. + * + * \param[in] kernel_def The OrtKernelDef instance. + * \return A null-terminated string representing the operator type. + * + * \since Version 1.24. + */ + ORT_API_T(const char*, KernelDef_GetOperatorType, _In_ const OrtKernelDef* kernel_def); + + /** \brief Returns the operator's domain from the kernel definition. + * + * \param[in] kernel_def The OrtKernelDef instance. + * \return A null-terminated string representing the operator's domain. + * + * \since Version 1.24. + */ + ORT_API_T(const char*, KernelDef_GetDomain, _In_ const OrtKernelDef* kernel_def); + + /** \brief Gets the kernel's opset version range that is supported. + * + * \param[in] kernel_def The OrtKernelDef instance. + * \param[out] start_version Output parameter set to the starting opset version that is supported. + * \param[out] end_version Output parameter set to the ending opset version (inclusive) that is supported. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDef_GetSinceVersion, _In_ const OrtKernelDef* kernel_def, + _Out_ int* start_version, _Out_ int* end_version); + + /** \brief Returns the name of the kernel's intended execution provider. + * + * \param[in] kernel_def The OrtKernelDef instance. + * \return A null-terminated string representing the name of the execution provider. + * + * \since Version 1.24. + */ + ORT_API_T(const char*, KernelDef_GetExecutionProvider, _In_ const OrtKernelDef* kernel_def); + + /** \brief Gets the memory type for a kernel input. + * + * \param[in] kernel_def The OrtKernelDef instance. + * \param[in] input_index The index of the input. + * \param[out] mem_type Output parameter set to the input's memory type. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDef_GetInputMemType, _In_ const OrtKernelDef* kernel_def, + _In_ size_t input_index, _Out_ OrtMemType* mem_type); + + /** \brief Gets the memory type for a kernel output. + * + * \param[in] kernel_def The OrtKernelDef instance. + * \param[in] output_index The index of the output. + * \param[out] mem_type Output parameter set to the output's memory type. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(KernelDef_GetOutputMemType, _In_ const OrtKernelDef* kernel_def, + _In_ size_t output_index, _Out_ OrtMemType* mem_type); + + /** \brief Gets the OrtDataType that represents the data type for a tensor of the given element type. + * + * \param[in] elem_type The tensor's element type. + * \param[out] out Output parameter set to the OrtDataType. Owned by ORT and must not be released. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(GetTensorDataType, _In_ ONNXTensorElementDataType elem_type, + _Outptr_ const OrtDataType** out); + + /** \brief Gets the kernel definition for a given node, if any exists for the calling execution provider. + * + * Used within OrtEp::GetCapability() to get the registered kernel definition for the given node. + * The kernel definition is set to NULL if there is no registered kernel definition for the node + * and execution provider. + * + * \param[in] graph_support_info The OrtEpGraphSupportInfo instance to query. + * \param[in] node The node for which to look up a kernel definition. + * \param[out] out_kernel_def Output parameter set to the OrtKernelDef or NULL. + * Owned by ORT and must not be released. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(EpGraphSupportInfo_LookUpKernel, _In_ OrtEpGraphSupportInfo* graph_support_info, + _In_ const OrtNode* node, _Outptr_result_maybenull_ const OrtKernelDef** out_kernel_def); + + /** \brief Sets one or more data buffers that collectively hold the pre-packed data for a single shared weight. + * + * \note Used within the implementation of OrtKernelImpl::PrePackWeight() when the kernel wants to share pre-packed + * weight data with other kernels. The buffer data MUST be allocated with the OrtAllocator provided to + * OrtKernelImpl::PrePack. + * + * \note Ownership of weight data transfers to the OrtSharedPrePackedWeightCache instance on success. + * If this function returns an error status, the caller retains ownership of the weight data. + * + * \note Subsequent calls with the same OrtSharedPrePackedWeightCache instance release and replace the old data. + * + * \param[in] prepacked_weight_cache The OrtSharedPrePackedWeightCache instance. + * \param[in] buffer_data_ptrs An array of buffer data pointers that collectively hold the pre-packed data for a + * single shared weight. Note that sometimes a single weight may have multiple pre-packed + * buffers and it is up to the kernel implementation to determine how to split the data + * into multiple buffers (if desired). + * \param[in] buffer_data_sizes An array of buffer byte sizes, one per element in `buffer_data_ptrs`. + * \param[in] num_buffers The number of buffers used to store the data for the shared pre-packed weight. + * Specifies the number of elements in the `buffer_data_ptrs` and `buffer_data_sizes` arrays. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(SharedPrePackedWeightCache_StoreWeightData, + _In_ OrtSharedPrePackedWeightCache* prepacked_weight_cache, + _In_reads_(num_buffers) void** buffer_data_ptrs, _In_reads_(num_buffers) size_t* buffer_data_sizes, + _In_ size_t num_buffers); + + /** \brief Get the OrtEp instance to which the node is assigned from the OrtKernelInfo. + * + * \note Used within OrtKernelImpl implementations to obtain a reference to the OrtEp. + * + * \param[in] info The ::OrtKernelInfo instance. + * \param[out] ep Output parameter set to the OrtEp instance associated with the OrtKernelInfo. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.24 + */ + ORT_API2_STATUS(KernelInfo_GetEp, _In_ const OrtKernelInfo* info, _Outptr_ const OrtEp** ep); + + /** \brief Set the details of an OrtDeviceEpIncompatibilityDetails instance. + * + * Used by execution provider factories to set incompatibility details in their + * GetHardwareDeviceIncompatibilityDetails implementation. ORT creates and initializes the object + * before passing it to the EP, so calling this function is optional. The EP uses this function + * to set incompatibility information when the device is not compatible. + * + * \param[in,out] details The OrtDeviceEpIncompatibilityDetails instance to update. + * \param[in] reasons_bitmask Bitmask of OrtDeviceEpIncompatibilityReason values. (0 = no incompatibility). + * \param[in] error_code Optional EP-specific error code (0 = no error). + * \param[in] notes Optional human-readable notes. Can be null. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(DeviceEpIncompatibilityDetails_SetDetails, _Inout_ OrtDeviceEpIncompatibilityDetails* details, + _In_ uint32_t reasons_bitmask, + _In_ int32_t error_code, + _In_opt_z_ const char* notes); + + /** \brief Creates an OrtKernelImpl instance for an If operator. + * + * Control flow operators require access to ORT session internals to orchestrate subgraph operations. + * This function allows an EP to create a properly configured OrtKernelImpl with access to ORT internals that + * the EP can add to its kernel registry. + * + * An EP is required to create an OrtKernelDef that keeps input[0] ('cond') on the CPU (i.e., OrtMemTypeCPUInput) + * as this input is used by CPU logic. The output should remain on the device (i.e., OrtMemTypeDefault), which is + * the default setting, to avoid copying to/from CPU. + * + * Example kernel definition (CXX API): + * Ort::KernelDef kernel_def = Ort::KernelDefBuilder() + * .SetDomain("").SetOperatorType("If").SetSinceVersion(21, 22) + * .SetExecutionProvider("MyEp") + * .SetInputMemType(0, OrtMemTypeCPUInput) // 'cond' on CPU + * .SetOutputMemType(0, OrtMemTypeDefault) // output on EP device + * .AddTypeConstraint("B", ...) + * .AddTypeConstraint("V", ...).Build(); + * + * \param[in] kernel_info The ::OrtKernelInfo instance for an If node. This function returns error ORT_FAIL + * if the opset version specified by `kernel_info` is unsupported. + * \param[out] kernel_out Output parameter set to the OrtKernelImpl instance for the If node. + * Must be released via OrtEpApi::ReleaseKernelImpl, unless ownership is transferred + * to ORT (see OrtKernelCreateFunc and OrtEpApi::KernelRegistry_AddKernel). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.24 + */ + ORT_API2_STATUS(CreateIfKernel, _In_ const OrtKernelInfo* kernel_info, _Outptr_ OrtKernelImpl** kernel_out); + + /** \brief Creates an OrtKernelImpl instance for a Loop operator. + * + * Control flow operators require access to ORT session internals to orchestrate subgraph operations. + * This function allows an EP to create a properly configured OrtKernelImpl with access to ORT internals that + * the EP can add to its kernel registry. + * + * An EP is required to create an OrtKernelDef that keeps input[0] ('M') and input[1] ('cond') on the CPU + * (i.e., OrtMemTypeCPUInput) as these inputs are used by CPU logic. Input[2] ('v_initial') and the output should + * remain on the device (i.e., OrtMemTypeDefault), which is the default setting, to avoid copying to/from CPU. + * + * Example kernel definition (CXX API): + * Ort::KernelDef kernel_def = Ort::KernelDefBuilder() + * .SetDomain("").SetOperatorType("Loop").SetSinceVersion(21, 22) + * .SetExecutionProvider("MyEp") + * .SetInputMemType(0, OrtMemTypeCPUInput) // 'M' on CPU + * .SetInputMemType(1, OrtMemTypeCPUInput) // 'cond' on CPU + * .SetInputMemType(2, OrtMemTypeDefault) // 'v_initial' on EP device + * .SetOutputMemType(0, OrtMemTypeDefault) // output on EP device + * .AddTypeConstraint("I", ...) + * .AddTypeConstraint("B", ...) + * .AddTypeConstraint("V", ...).Build(); + * + * \param[in] kernel_info The ::OrtKernelInfo instance for a Loop node. This function returns error ORT_FAIL + * if the opset version specified by `kernel_info` is unsupported. + * \param[in] helper A OrtLoopKernelHelper instance that contains helper functions that ORT calls during kernel + * execution to operate on tensors allocated with the EP's device memory. + * ORT will call OrtLoopKernelHelper::Release() to release the helper and its resources. + * \param[out] kernel_out Output parameter set to the OrtKernelImpl instance for the Loop node. + * Must be released via OrtEpApi::ReleaseKernelImpl, unless ownership is transferred + * to ORT (see OrtKernelCreateFunc and OrtEpApi::KernelRegistry_AddKernel). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.24 + */ + ORT_API2_STATUS(CreateLoopKernel, _In_ const OrtKernelInfo* kernel_info, _In_ OrtLoopKernelHelper* helper, + _Outptr_ OrtKernelImpl** kernel_out); + + /** \brief Creates an OrtKernelImpl instance for a Scan operator. Does not support opset versions older than 9. + * + * Control flow operators require access to ORT session internals to orchestrate subgraph operations. + * This function allows an EP to create a properly configured OrtKernelImpl with access to ORT internals that + * the EP can add to its kernel registry. + * + * It is recommended that an EP create an OrtKernelDef that keeps the inputs and outputs on the EP's + * device (i.e., OrtMemTypeDefault), which is the default setting, to avoid copying to/from CPU. + * + * Example kernel definition (CXX API): + * Ort::KernelDef kernel_def = Ort::KernelDefBuilder() + * .SetDomain("").SetOperatorType("Scan").SetSinceVersion(21, 22) + * .SetExecutionProvider("MyEp") + * .SetInputMemType(0, OrtMemTypeDefault) // input[0] on EP device + * .SetOutputMemType(0, OrtMemTypeDefault) // output[0] on EP device + * .AddTypeConstraint("V", ...).Build(); + * + * \param[in] kernel_info The ::OrtKernelInfo instance for a Scan node. This function returns error ORT_FAIL + * if the opset version specified by `kernel_info` is unsupported. + * \param[in] helper A OrtScanKernelHelper instance that contains helper functions that ORT calls during kernel + * execution to operate on tensors allocated with the EP's device memory. + * ORT will call OrtScanKernelHelper::Release() to release the helper and its resources. + * \param[out] kernel_out Output parameter set to the OrtKernelImpl instance for the Scan node. + * Must be released via OrtEpApi::ReleaseKernelImpl, unless ownership is transferred + * to ORT (see OrtKernelCreateFunc and OrtEpApi::KernelRegistry_AddKernel). + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.24 + */ + ORT_API2_STATUS(CreateScanKernel, _In_ const OrtKernelInfo* kernel_info, _In_ OrtScanKernelHelper* helper, + _Outptr_ OrtKernelImpl** kernel_out); + + ORT_CLASS_RELEASE(KernelImpl); + + /** \brief Gets a new OrtKeyValuePairs instance containing a copy of all configuration entries set on the environment. + * + * \note An application provides environment-level configuration options for execution provider libraries by + * using keys with the prefix 'ep_factory.\\.'. Ex: the key 'ep_factory.my_ep.some_ep_key' represents + * a key named 'some_ep_key' that is meant to be consumed by an execution provider named 'my_ep'. Refer to + * the specific execution provider's documentation for valid keys and values. + * + * \note Refer to onnxruntime_env_config_keys.h for common configuration entry keys and their supported values. + * + * \param[out] config_entries Output parameter set to the OrtKeyValuePairs instance containing all configuration entries. + * Must be released via OrtApi::ReleaseKeyValuePairs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.24 + */ + ORT_API2_STATUS(GetEnvConfigEntries, _Outptr_ OrtKeyValuePairs** config_entries); + + /** \brief Get an operator schema from the global schema registry. + * + * Looks up a schema by name, maximum inclusive version, and domain. + * The returned pointer is owned by the caller and must be released via ReleaseOpSchema. + * If the schema is not found, *out_schema is set to nullptr (no allocation occurs). + * + * Available schemas include standard ONNX operators (domain "" or "ai.onnx"), ONNX ML operators + * (domain "ai.onnx.ml"), and ORT contrib operators (domain "com.microsoft"). + * + * \param[in] name A null-terminated string for the operator name. + * \param[in] max_inclusive_version The maximum inclusive opset version. + * \param[in] domain A null-terminated string for the operator domain. + * \param[out] out_schema Output parameter set to the schema pointer, or nullptr if not found. + * Must be released via OrtEpApi::ReleaseOpSchema. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(GetOpSchema, _In_ const char* name, _In_ int max_inclusive_version, + _In_ const char* domain, _Outptr_result_maybenull_ OrtOpSchema** out_schema); + + ORT_CLASS_RELEASE(OpSchema); + + /** \brief Get the first ONNX opset version that introduced this operator schema. + * + * If an operator has had no changes that break backwards compatibility, the `since_version` is + * just the first opset version that introduced the operator. However, if the operator has had breaking changes, + * then `since_version` corresponds to the opset version that introduced the breaking change. + * + * For example, suppose operator "Foo" was added in version 3 and had a breaking change in version 6. + * Then, there will be an operator schema entry for "Foo" with a since_version of 3 and another updated + * operator schema entry for "Foo" with a since_version of 6. + * + * \param[in] schema The OrtOpSchema instance. + * \param[out] out Output parameter set to the ONNX opset version. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchema_GetSinceVersion, _In_ const OrtOpSchema* schema, _Out_ int* out); + + /** \brief Get the number of inputs defined by the operator schema. + * + * \param[in] schema The OrtOpSchema instance. + * \param[out] out Output parameter set to the number of inputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchema_GetNumInputs, _In_ const OrtOpSchema* schema, _Out_ size_t* out); + + /** \brief Get the name of the i-th input formal parameter from an operator schema. + * + * \param[in] schema The OrtOpSchema instance. + * \param[in] index Zero-based index of the input parameter. + * \param[out] out Output parameter set to the name of the input parameter (null-terminated UTF8 string). + * Valid as long as the OrtOpSchema exists. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchema_GetInputName, _In_ const OrtOpSchema* schema, _In_ size_t index, + _Outptr_ const char** out); + + /** \brief Get the type constraint for the i-th input formal parameter from an operator schema. + * + * Returns a non-owning pointer to the OrtOpSchemaTypeConstraint associated with the given input. + * The returned pointer is valid as long as the parent OrtOpSchema is alive. + * If the input has no type constraint, *out is set to nullptr. + * + * Multiple inputs sharing the same type constraint (e.g., both using "T") return the same pointer. + * + * \param[in] schema The OrtOpSchema instance. + * \param[in] index Zero-based index of the input parameter. + * \param[out] out Output parameter set to the type constraint, or NULL if the input has no type constraint. + * Valid as long as the OrtOpSchema exists. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchema_GetInputTypeConstraint, _In_ const OrtOpSchema* schema, _In_ size_t index, + _Outptr_result_maybenull_ const OrtOpSchemaTypeConstraint** out); + + /** \brief Get the number of outputs defined by the operator schema. + * + * \param[in] schema The OrtOpSchema instance. + * \param[out] out Output parameter set to the number of outputs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchema_GetNumOutputs, _In_ const OrtOpSchema* schema, _Out_ size_t* out); + + /** \brief Get the name of the i-th output formal parameter from an operator schema. + * + * \param[in] schema The OrtOpSchema instance. + * \param[in] index Zero-based index of the output parameter. + * \param[out] out Output parameter set to the name of the output parameter (null-terminated UTF8 string). + * Valid as long as the OrtOpSchema exists. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchema_GetOutputName, _In_ const OrtOpSchema* schema, _In_ size_t index, + _Outptr_ const char** out); + + /** \brief Get the type constraint for the i-th output formal parameter from an operator schema. + * + * Returns a non-owning pointer to the OrtOpSchemaTypeConstraint associated with the given output. + * The returned pointer is valid as long as the parent OrtOpSchema is alive. + * If the output has no type constraint, *out is set to nullptr. + * + * Multiple outputs sharing the same type constraint return the same pointer. + * Pointer equality can be used to check if two outputs share a type constraint. + * + * \param[in] schema The OrtOpSchema instance. + * \param[in] index Zero-based index of the output parameter. + * \param[out] out Output parameter set to the type constraint, or NULL if the output has no type constraint. + * Valid as long as the OrtOpSchema exists. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchema_GetOutputTypeConstraint, _In_ const OrtOpSchema* schema, _In_ size_t index, + _Outptr_result_maybenull_ const OrtOpSchemaTypeConstraint** out); + + /** \brief Get the number of unique type constraints in the operator schema. + * + * \param[in] schema The OrtOpSchema instance. + * \param[out] out Output set to the number of type constraints. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchema_GetTypeConstraintCount, _In_ const OrtOpSchema* schema, _Out_ size_t* out); + + /** \brief Get the i-th type constraint from the operator schema. + * + * Returns a non-owning pointer to the OrtOpSchemaTypeConstraint at the given index. + * The returned pointer is valid as long as the parent OrtOpSchema is alive. + * + * Constraints are returned in the order they are declared in the ONNX operator schema + * definition. The order is stable but has no semantic significance. + * + * Use this API to iterate all type constraints (e.g., to register allowed types for + * each constraint). Use OpSchema_GetInputTypeConstraint / OpSchema_GetOutputTypeConstraint + * to look up the constraint for a specific input or output. + * + * \param[in] schema The OrtOpSchema instance. + * \param[in] index Zero-based index of the type constraint. + * \param[out] out Output parameter set to the type constraint. + * Valid as long as the OrtOpSchema exists. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchema_GetTypeConstraint, _In_ const OrtOpSchema* schema, _In_ size_t index, + _Outptr_ const OrtOpSchemaTypeConstraint** out); + + /** \brief Get the type parameter name of a type constraint (e.g., "T", "T1"). + * + * \param[in] type_constraint The OrtOpSchemaTypeConstraint instance. + * \param[out] out Output parameter set to the type parameter name. + * Valid as long as the parent OrtOpSchema exists. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchemaTypeConstraint_GetTypeParamName, _In_ const OrtOpSchemaTypeConstraint* type_constraint, + _Outptr_ const char** out); + + /** \brief Get the allowed type strings for a type constraint. + * + * Returns an array of null-terminated strings representing the allowed data types + * (e.g., "tensor(float)", "tensor(double)"). The array and its contents are valid + * as long as the parent OrtOpSchema exists. + * + * \param[in] type_constraint The OrtOpSchemaTypeConstraint instance. + * \param[out] out_types Output parameter set to the output array of type strings. + * Valid as long as the parent OrtOpSchema exists. + * \param[out] num_types Output parameter set to the number of elements in the output array. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchemaTypeConstraint_GetAllowedTypes, _In_ const OrtOpSchemaTypeConstraint* type_constraint, + _Outptr_ const char* const** out_types, _Out_ size_t* num_types); + + /** \brief Get the input indices that use a type constraint. + * + * Returns an array of zero-based input indices whose formal parameter type string + * matches this type constraint. The array is valid as long as the parent OrtOpSchema exists. + * + * \param[in] type_constraint The OrtOpSchemaTypeConstraint instance. + * \param[out] out_indices Output parameter set to the output array of input indices. + * \param[out] count Output parameter set to the number of elements in the output array. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchemaTypeConstraint_GetInputIndices, _In_ const OrtOpSchemaTypeConstraint* type_constraint, + _Outptr_ const size_t** out_indices, _Out_ size_t* count); + + /** \brief Get the output indices that use a type constraint. + * + * Returns an array of zero-based output indices whose formal parameter type string + * matches this type constraint. The array is valid as long as the parent OrtOpSchema exists. + * + * \param[in] type_constraint The OrtOpSchemaTypeConstraint instance. + * \param[out] out_indices Output parameter set to the output array of output indices. + * \param[out] count Output parameter set to the number of elements in the output array. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(OpSchemaTypeConstraint_GetOutputIndices, _In_ const OrtOpSchemaTypeConstraint* type_constraint, + _Outptr_ const size_t** out_indices, _Out_ size_t* count); + + /** \brief Create a profiling event. + * + * An EP profiler calls this to create an event to pass to OrtEpApi::ProfilingEventsContainer_AddEvents. + * The returned event must be released via OrtEpApi::ReleaseProfilingEvent after it has been added. + * + * \param[in] category The event category (e.g., session, node, kernel, or API). + * \param[in] process_id Process ID. Set to -1 if does not apply. + * \param[in] thread_id Thread ID. Set to -1 if does not apply. + * \param[in] event_name Null-terminated string representing the event name. ORT copies this string. + * \param[in] timestamp_us Starting timestamp in microseconds relative to the profiling start time. + * An OrtEpProfilerImpl should record its own clock's profiling start time and + * use the `ep_profiling_start_offset_ns` value passed to OrtEpProfilerImpl::StartProfiling + * to compute this value as: + * timestamp_us = (ep_profiling_start_offset_ns + + * (ep_event_time_ns - ep_profiling_start_time_ns)) / 1000 + * \param[in] duration_us Duration in microseconds. + * \param[in] arg_keys Array of null-terminated argument key strings. Can be NULL if num_args is 0. + * ORT copies these strings. + * \param[in] arg_values Array of null-terminated argument value strings. Can be NULL if num_args is 0. + * ORT copies these strings. + * \param[in] num_args Number of key-value argument pairs. + * \param[out] out Output parameter set to the created profiling event. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(CreateProfilingEvent, + _In_ OrtProfilingEventCategory category, + _In_ int32_t process_id, + _In_ int32_t thread_id, + _In_ const char* event_name, + _In_ int64_t timestamp_us, + _In_ int64_t duration_us, + _In_reads_(num_args) const char* const* arg_keys, + _In_reads_(num_args) const char* const* arg_values, + _In_ size_t num_args, + _Outptr_ OrtProfilingEvent** out); + + /** \brief Release an opaque profiling event created via CreateProfilingEvent. + * + * \since Version 1.25. + */ + ORT_CLASS_RELEASE(ProfilingEvent); + + /** \brief Get the event category of a profiling event. + * + * \param[in] event The OrtProfilingEvent instance. + * \param[out] out Output parameter set to the event category. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(ProfilingEvent_GetCategory, _In_ const OrtProfilingEvent* event, + _Out_ OrtProfilingEventCategory* out); + + /** \brief Get the event name of a profiling event. + * + * \param[in] event The OrtProfilingEvent instance. + * \param[out] out Output parameter set to the event name as a null-terminated UTF-8 string. + * Do not free as it is owned by the OrtProfilingEvent instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(ProfilingEvent_GetName, _In_ const OrtProfilingEvent* event, + _Outptr_ const char** out); + + /** \brief Get the start timestamp of a profiling event in microseconds. + * + * \param[in] event The OrtProfilingEvent instance. + * \param[out] out Output parameter set to the start timestamp of the profiling event in microseconds relative to + * the profiling start time. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(ProfilingEvent_GetTimestampUs, _In_ const OrtProfilingEvent* event, + _Out_ int64_t* out); + + /** \brief Get the duration of a profiling event in microseconds. + * + * \param[in] event The OrtProfilingEvent instance. + * \param[out] out Output parameter set to the event duration in microseconds. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(ProfilingEvent_GetDurationUs, _In_ const OrtProfilingEvent* event, + _Out_ int64_t* out); + + /** \brief Get the value of an event argument by its key. + * + * The value is set to NULL if the key is not found. + * + * \param[in] event The OrtProfilingEvent instance. + * \param[in] key Null-terminated argument key to look up. + * \param[out] out Output parameter set to the argument value string, or NULL if not found. + * The value is a null-terminated UTF-8 string. + * Do not free as the string is owned by the OrtProfilingEvent instance. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * \since Version 1.25. + */ + ORT_API2_STATUS(ProfilingEvent_GetArgValue, _In_ const OrtProfilingEvent* event, _In_ const char* key, + _Outptr_result_maybenull_ const char** out); + + /** \brief Add EP profiling events to an events container. + * + * An EP profiler calls this function to report new EP profiling events (e.g., GPU kernel timings) during + * OrtEpProfilerImpl::EndProfiling(). ORT copies the EP event data during this call. The EP retains ownership of the + * OrtProfilingEvent instances and must release them via ReleaseProfilingEvent after this call returns. + * This function may be called multiple times within a single EndProfiling call to add EP events in batches. + * + * \param[in] events_container The OrtProfilingEventsContainer instance provided by ORT + * to OrtEpProfilerImpl::EndProfiling(). + * \param[in] events Array of pointers to opaque OrtProfilingEvent instances. + * \param[in] num_events Number of events in the `events` array. Must be greater than 0. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(ProfilingEventsContainer_AddEvents, _In_ OrtProfilingEventsContainer* events_container, + _In_reads_(num_events) const OrtProfilingEvent* const* events, + _In_ size_t num_events); +}; + +/** + * \brief The data layout type. + * + * EPs may specify a preferred data layout type. ORT's default layout type is OrtEpDataLayout_NCHW, or + * OrtEpDataLayout_Default. + * + * \since Version 1.23. + */ +typedef enum OrtEpDataLayout { + OrtEpDataLayout_NCHW = 0, + OrtEpDataLayout_NHWC, + + OrtEpDataLayout_Default = OrtEpDataLayout_NCHW, +} OrtEpDataLayout; + +/** + * \brief Node assignment policies for graph capture validation. + * + * When graph capture is enabled, ORT validates that nodes are assigned to EPs in a way that is + * compatible with graph capture. An EP can specify which validation policy ORT should apply. + * + * \since Version 1.26. + */ +typedef enum OrtGraphCaptureNodeAssignmentPolicy { + /** All nodes in the main graph must be assigned to this EP. No CPU fallback is allowed. */ + OrtGraphCaptureNodeAssignmentPolicy_ALL_NODES_ON_EP = 0, + + /** Compute nodes must be on this EP. CPU nodes are allowed for shape computation as long as + * no memory copy nodes exist. */ + OrtGraphCaptureNodeAssignmentPolicy_ALLOW_CPU_FOR_SHAPES = 1, +} OrtGraphCaptureNodeAssignmentPolicy; + +/** + * \brief The OrtEp struct provides functions to implement for an execution provider. + * \since Version 1.22. + */ +struct OrtEp { + /** \brief The ONNX Runtime version the execution provider was compiled with. + * + * Implementation should set to ORT_API_VERSION. + * ORT will use this to ensure it does not call functions that were not available when the library was compiled. + * + * \since Version 1.22. + */ + uint32_t ort_version_supported; + + /** \brief Get the execution provider name. + * + * The returned string should be a null-terminated, UTF-8 encoded string. ORT will copy it. + * + * \param[in] this_ptr The OrtEp instance. + * \return The execution provider name. + * + * \since Version 1.22. + */ + ORT_API_T(const char*, GetName, _In_ const OrtEp* this_ptr); + + /** \brief Get information about the nodes supported by the OrtEp instance. + * + * IMPORTANT: This is not the final version of this API function. This is currently experimental but will + * be stabilized by the ONNX Runtime 1.23 release. + * + * \param[in] this_ptr The OrtEp instance. + * \param[in] graph The OrtGraph instance for which to populate node support. The OrtGraph could be a nested subgraph + * contained by a node (e.g., an If or Loop node). ONNX Runtime calls this function separately + * for each nested subgraph. + * \param[inout] graph_support_info OrtEpGraphSupportInfo instance that the implementer must fill out in order to + * specify the supported nodes. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(GetCapability, _In_ OrtEp* this_ptr, _In_ const OrtGraph* graph, + _Inout_ OrtEpGraphSupportInfo* graph_support_info); + + /** \brief Compile OrtGraph instances assigned to the OrtEp. Implementer must set a OrtNodeComputeInfo instance + * for each OrtGraph in order to define its computation function. + * + * If the session is configured to generate a pre-compiled model, the execution provider must return EPContext nodes, + * as OrtNode instances, that ONNX Runtime uses to create a pre-compiled model, known as an "EPContext model". + * An EPContext model contains EPContext nodes. Each EPContext node encapsulates the pre-compiled binary data for a + * OrtGraph compiled for a specific execution provider. For more details about the EPContext design, refer to: + * \htmlonly + * EPContext design document. + * \endhtmlonly + * + * \param[in] this_ptr The OrtEp instance. + * \param[in] graphs Array of `count` OrtGraph instances to compile. Each graph contains only the nodes for + * which the execution provider indicated support. Nested subgraphs contained by a + * node, such as an If or Loop, have separate OrtGraph instances. + * \param[in] fused_nodes Array of `count` fused nodes that will replace the compiled graphs. + * Each fused node is an OrtNode initialized with the intended fused node name and + * input/output information. + * \param[in] count The number of OrtGraph instances to compile. + * \param[out] node_compute_infos Array of `count` OrtNodeComputeInfo instances that define each OrtGraph instance's + * computation function. The implementer allocates the OrtNodeComputeInfo instances. + * ORT calls ReleaseNodeComputeInfos() to release multiple instances in a batch. + * \param[out] ep_context_nodes Output array of `count` OrtNode instances, each representing an EPContext + * node for a compiled OrtGraph. The execution provider must use + * OrtModelEditorApi::CreateNode to create the OrtNode instances. ONNX Runtime takes + * ownership of the OrtNode instances, so the execution provider must NOT call + * OrtApi::ReleaseNode. Should be ignored if the session is not configured to generate an + * EPContext model. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note Do NOT cache the provided OrtGraph instances in any of the OrtNodeComputeInfo functions because the + * graphs are only valid for the duration of the call to Compile. Any graph/node/input/output + * names that are needed by the OrtNodeComputeInfo functions must be copied and stored by the OrtEp. + * + * \note As of version 1.24, implementation of this function is optional if the EP does not compile nodes and + * uses a kernel registry instead. + * + * \since Version 1.23. + */ + ORT_API2_STATUS(Compile, _In_ OrtEp* this_ptr, _In_ const OrtGraph** graphs, + _In_ const OrtNode** fused_nodes, _In_ size_t count, + _Out_writes_all_(count) OrtNodeComputeInfo** node_compute_infos, + _Out_writes_(count) OrtNode** ep_context_nodes); + + /** \brief Release OrtNodeComputeInfo instances. + * + * \param[in] this_ptr The OrtEp instance. + * \param[inout] node_compute_infos The OrtNodeComputeInfo instances to release. + * \param[in] num_node_compute_infos The number of OrtNodeComputeInfo instances. + * + * \note As of version 1.24, implementation of this function is optional if the EP does not compile nodes and + * uses a kernel registry instead. + * + * \since Version 1.23. + */ + ORT_API_T(void, ReleaseNodeComputeInfos, _In_ OrtEp* this_ptr, + OrtNodeComputeInfo** node_compute_infos, + _In_ size_t num_node_compute_infos); + + /** \brief Get the EP's preferred data layout. + * + * \note Implementation of this function is optional. + * If not implemented, ORT will assume that this EP prefers the data layout `OrtEpDataLayout::NCHW`. + * + * \param[in] this_ptr The OrtEp instance. + * \param[out] preferred_data_layout The EP's preferred data layout. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(GetPreferredDataLayout, _In_ OrtEp* this_ptr, _Out_ OrtEpDataLayout* preferred_data_layout); + + /** \brief Given an op with domain `domain` and type `op_type`, determine whether an associated node's data layout + * should be converted to `target_data_layout`. + * If the EP prefers a non-default data layout (see `GetPreferredDataLayout()`), this function will be called + * during layout transformation with `target_data_layout` set to the EP's preferred data layout. + * + * \note Implementation of this function is optional. + * If an EP prefers a non-default data layout, it may implement this to customize the specific op data layout + * preferences at a finer granularity. + * + * \param[in] this_ptr The OrtEp instance. + * \param[in] domain The op domain. An empty string means the ONNX domain. + * \param[in] op_type The op type. + * \param[in] target_data_layout The target data layout. + * \param[out] should_convert Whether the associated node's data layout should be converted to `target_data_layout`. + * If greater than 0, convert. + * If 0, don't convert. + * Otherwise, if less than 0, leave the decision to ORT. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ShouldConvertDataLayoutForOp, _In_ OrtEp* this_ptr, + _In_z_ const char* domain, _In_z_ const char* op_type, + _In_ OrtEpDataLayout target_data_layout, + _Outptr_ int* should_convert); + + /** \brief Set dynamic options on this EP. + * + * Dynamic options can be set by the user at any time after session creation with `OrtApi::SetEpDynamicOptions()`. + * + * \param[in] this_ptr The OrtEp instance. + * \param[in] option_keys The dynamic option keys. + * \param[in] option_values The dynamic option values. + * \param[in] num_options The number of dynamic options. + * + * \note Implementation of this function is optional. + * An EP should only implement this if it needs to handle any dynamic options. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(SetDynamicOptions, _In_ OrtEp* this_ptr, + _In_reads_(num_options) const char* const* option_keys, + _In_reads_(num_options) const char* const* option_values, + _In_ size_t num_options); + + /** \brief Called by ORT to notify the EP of the start of a run. + * + * \param[in] this_ptr The OrtEp instance. + * \param[in] run_options The run options for this run. + * + * \note Implementation of this function is optional. + * When graph capture/replay is enabled and a graph has already been captured, ORT skips + * normal execution and calls ReplayGraph() directly, so this callback is not invoked for replay runs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(OnRunStart, _In_ OrtEp* this_ptr, _In_ const OrtRunOptions* run_options); + + /** \brief Called by ORT to notify the EP of the end of a run. + * + * \param[in] this_ptr The OrtEp instance. + * \param[in] run_options The run options for this run. + * \param[in] sync_stream Whether any associated stream should be synchronized during this call. + * Only applicable if there is such a stream. + * + * \note Implementation of this function is optional. + * When graph capture/replay is enabled and a graph has already been captured, ORT skips + * normal execution and calls ReplayGraph() directly, so this callback is not invoked for replay runs. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(OnRunEnd, _In_ OrtEp* this_ptr, _In_ const OrtRunOptions* run_options, _In_ bool sync_stream); + + /** \brief Create an OrtAllocator for the given OrtMemoryInfo for an OrtSession. + * + * The OrtMemoryInfo instance will match one of the values set in the OrtEpDevice using EpDevice_AddAllocatorInfo. + * Any allocator specific options should be read from the session options. + * + * If nullptr OrtEpFactory::CreateAllocator will be used. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[in] memory_info The OrtMemoryInfo to create the allocator for. May be nullptr. + * \param[out] allocator The created OrtAllocator instance. Set to nullptr if the default CPU allocator is used. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(CreateAllocator, _In_ OrtEp* this_ptr, + _In_ const OrtMemoryInfo* memory_info, + _Outptr_result_maybenull_ OrtAllocator** allocator); + + /** \brief Create a synchronization stream for the given memory device for an OrtSession. + * + * This is used to create a synchronization stream for the execution provider and is used to synchronize + * operations on the device during model execution. + * Any stream specific options should be read from the session options. + * + * If nullptr OrtEpFactory::CreateSyncStreamForDevice will be used. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[in] memory_device The OrtMemoryDevice to create the synchronization stream for. + * \param[out] stream The created OrtSyncStreamImpl instance. nullptr if the execution provider is not stream aware. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(CreateSyncStreamForDevice, _In_ OrtEp* this_ptr, + _In_ const OrtMemoryDevice* memory_device, + _Outptr_ OrtSyncStreamImpl** stream); + + /** \brief Get a string with details about the EP stack used to produce a compiled model. + * + * This function gets a compatibility information string that contains details about the execution provider + * used to compile a given model. This string can later be used with ValidateCompiledModelCompatibilityInfo + * to determine if a compiled model is compatible with the EP. + * + * The returned string should be a null-terminated, UTF-8 encoded string. ORT will copy it. + * + * \param[in] this_ptr The OrtEp instance. + * \param[in] graph The OrtGraph instance for which to generate compatibility information. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API_T(const char*, GetCompiledModelCompatibilityInfo, _In_ OrtEp* this_ptr, + _In_ const OrtGraph* graph); + + /** \brief Gets the execution provider's kernel registry, if any. + * + * A kernel registry contains kernel creation information for operator kernels supported by an EP. + * + * \param[in] this_ptr The OrtEp instance. + * \param[out] kernel_registry Output parameter set to the EP's kernel registry, which must remain valid throughout + * the lifetime of the EP. Can be NULL if the EP doesn't use a kernel registry. + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note Implementation of this function is optional. If set to NULL, ORT assumes the EP compiles nodes. + * + * \since Version 1.24. + */ + ORT_API2_STATUS(GetKernelRegistry, _In_ OrtEp* this_ptr, + _Outptr_result_maybenull_ const OrtKernelRegistry** kernel_registry); + + /** \brief Gets whether the execution provider supports concurrent run calls made on the session. + * + * \param[in] this_ptr The OrtEp instance. + * \param[out] is_supported Whether concurrent runs are supported. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note Implementation of this function is optional and it may be set to NULL. + * If not implemented, ORT assumes that concurrent runs are supported. + * + * \since Version 1.24. + */ + ORT_API2_STATUS(IsConcurrentRunSupported, _In_ OrtEp* this_ptr, _Outptr_ bool* is_supported); + + /** \brief Called by ORT to block until the device has completed all preceding requested tasks. + * + * Currently this is primarily used by the IOBinding object to ensure that all inputs have been copied + * to the device before execution begins. + * + * \param[in] this_ptr The OrtEp instance. + * + * \note Implementation of this function is optional. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.25. + */ + ORT_API2_STATUS(Sync, _In_ OrtEp* this_ptr); + + /** \brief Return a new profiler for the execution provider. + * + * If the EP supports profiling, it should create and return an OrtEpProfilerImpl instance. + * ORT takes ownership of each non-NULL instance returned and will call OrtEpProfilerImpl::Release when + * it is no longer needed. + * + * ORT may call this function multiple times over the lifetime of a single OrtEp instance, for example + * during EP registration and again per run if run-level profiling is enabled. Each call is independent and + * the EP must return a new profiler instance (or NULL if profiling is not supported). + * + * \param[in] this_ptr The OrtEp instance. + * \param[out] profiler Output parameter set to a new OrtEpProfilerImpl instance created by the EP. + * Set to NULL if the EP does not support profiling. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note Implementation of this function is optional. If set to NULL, ORT assumes the EP does not + * support profiling. + * + * \since Version 1.25. + */ + ORT_API2_STATUS(CreateProfiler, _In_ OrtEp* this_ptr, + _Outptr_result_maybenull_ OrtEpProfilerImpl** profiler); + + /** \brief Indicate whether the graph capturing mode (e.g., CUDA graph) is enabled for the provider. + * + * Graph capture allows an EP to record a sequence of device (e.g., GPU) operations during an initial run and replay + * them on subsequent runs, bypassing per-kernel CPU launch overhead. + * + * Applications enable graph capture via EP-specific provider options (e.g., `enable_cuda_graph=1` + * for the CUDA EP). An EP should return true from this function if it has been configured to enable + * graph capture/replay. + * + * **ORT graph capture/replay summary:** + * During OrtSession initialization, ORT calls OrtEp::IsGraphCaptureEnabled() on each EP in the order specified during + * provider registration with the session. If an EP returns true, ORT validates that the graph is suitable for + * graph capture, and if so, caches the EP for graph capture during the next run. The graph validation ensures + * that there are no control flow nodes and that node-to-EP assignments are compatible with the policy specified + * by the EP via OrtEp::GetGraphCaptureNodeAssignmentPolicy(). + * Note that an OrtSession only supports graph capture for one EP (i.e., the first EP to claim support). + * + * During the first call to OrtApi::Run() for the OrtSession, ORT performs multiple internal runs of the model + * until the EP indicates that the graph has been captured by returning `true` from `OrtEp::IsGraphCaptured()`. + * If the EP is unable to capture the graph within 8 runs, the call to OrtApi::Run() returns an error OrtStatus. + * Each internal run invokes `OrtEp::OnRunStart()`, normal execution, and `OrtEp::OnRunEnd()`. EPs should use + * these run callbacks to track the number of necessary warm-up runs and begin/end graph capture when ready. + * + * After successful graph capture, subsequent calls to OrtApi::Run() skip normal execution and ORT instead calls + * `OrtEp::ReplayGraph()` directly. + * + * Applications can capture and replay multiple graphs (e.g., one per distinct input shape) by setting the + * `"gpu_graph_id"` run config entry via `OrtApi::AddRunConfigEntry()` to different integer values. ORT passes + * the value as the `graph_annotation_id` parameter to `OrtEp::IsGraphCaptured()` and `OrtEp::ReplayGraph()`. + * + * \param[in] this_ptr The OrtEp instance. + * \return true if graph capture mode is enabled, false otherwise. + * + * \note Implementation of this function is optional. If set to NULL, ORT assumes graph capture is not enabled. + * \note If this function returns true, `OrtEp::IsGraphCaptured` and `OrtEp::ReplayGraph` must also be implemented. + * If either is NULL, ORT will log a warning and ignore this EP for graph capture. + * + * \since Version 1.26. + */ + ORT_API_T(bool, IsGraphCaptureEnabled, _In_ const OrtEp* this_ptr); + + /** \brief Indicate whether a graph has been captured and instantiated. + * + * ORT calls this before each `Session::Run()`. If true, ORT calls `ReplayGraph()` instead of + * normal execution. After a run where this returns false, ORT automatically retries until it + * returns true (handling warm-up runs transparently). + * + * \param[in] this_ptr The OrtEp instance. + * \param[in] graph_annotation_id Identifies which captured graph to query. + * Applications can set this value via `OrtApi::AddRunConfigEntry()` with the key `"gpu_graph_id"`. + * The default value is 0 when the run config entry is not set. + * Setting different IDs allows the EP to capture and manage multiple graphs (e.g., one per + * distinct input shape). A value of -1 means graph capture/replay should be skipped for this run. + * \return true if the graph has been captured, false otherwise. + * + * \note This function must be implemented if `OrtEp::IsGraphCaptureEnabled` is implemented and may return true. + * + * \since Version 1.26. + */ + ORT_API_T(bool, IsGraphCaptured, _In_ const OrtEp* this_ptr, _In_ int graph_annotation_id); + + /** \brief Run the instantiated (captured) graph. + * + * Called by ORT instead of normal execution when `IsGraphCaptured()` returns true. + * + * \param[in] this_ptr The OrtEp instance. + * \param[in] graph_annotation_id Identifies which captured graph to replay. + * Applications can set this value via `OrtApi::AddRunConfigEntry()` with the key `"gpu_graph_id"`. + * The default value is 0 when the run config entry is not set. + * A value of -1 means graph replay should be skipped for this run. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note This function must be implemented if `OrtEp::IsGraphCaptureEnabled` is implemented and may return true. + * + * \since Version 1.26. + */ + ORT_API2_STATUS(ReplayGraph, _In_ OrtEp* this_ptr, _In_ int graph_annotation_id); + + /** \brief Get the node assignment validation policy for graph capture. + * + * When graph capture is enabled, ORT validates that nodes are assigned to EPs in a way that is + * compatible with graph capture. This function tells ORT which validation policy to apply. + * + * \param[in] this_ptr The OrtEp instance. + * \return The node assignment policy for graph capture. + * + * \note Implementation of this function is optional. If set to NULL, ORT uses + * OrtGraphCaptureNodeAssignmentPolicy_ALL_NODES_ON_EP (strictest validation). + * + * \since Version 1.26. + */ + ORT_API_T(OrtGraphCaptureNodeAssignmentPolicy, GetGraphCaptureNodeAssignmentPolicy, + _In_ const OrtEp* this_ptr); + + /** \brief Query the available device resource for partitioning budget. + * + * Called by ORT during graph partitioning when no explicit resource budget threshold + * has been configured via session options. The EP should query its device for the + * currently available resource (e.g., free GPU memory) and return it as an OrtResourceCount. + * + * If the EP does not support resource querying, set this function pointer to NULL. + * ORT will skip threshold-based budget enforcement in that case. + * + * \param[in] this_ptr The OrtEp instance. + * \param[out] available The available device resource. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note Implementation of this function is optional. If set to NULL, no automatic + * resource threshold is established and budget enforcement requires an explicit + * threshold from session options. + * + * \since Version 1.26. + */ + ORT_API2_STATUS(GetAvailableResource, _In_ const OrtEp* this_ptr, _Out_ OrtResourceCount* available); + + /** \brief Called by ORT when session initialization is complete. + * + * This provides an opportunity for execution providers to optionally synchronize and + * clean up temporary resources to reduce memory usage and ensure the first inference run is fast. + * + * \param[in] this_ptr The OrtEp instance. + * + * \note Implementation of this function is optional. If set to NULL, ORT assumes no + * post-initialization work is needed and treats it as a no-op success. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.27. + */ + ORT_API2_STATUS(OnSessionInitializationEnd, _In_ OrtEp* this_ptr); +}; + +/** \brief The function signature that ORT will call to create OrtEpFactory instances. + * + * This must be available in a function called 'CreateEpFactories' in the execution provider library. + * + * \param[in] registered_name The name the execution library is registered with by RegisterExecutionProviderLibrary + * \param[in] ort_api_base The OrtApiBase instance that is used by the factory to get the OrtApi instance for the + * version of ORT that the library was compiled against. + * \param[in] default_logger The default ORT logger that can be used for logging outside of an inference session. + * \param[in,out] factories The implementation should create and add OrtEpFactory instances to this + * pre-allocated array. + * i.e. usage is `factories[0] = new MyEpFactory();` + * \param[in] max_factories The maximum number of OrtEpFactory instances that can be added to `factories`. + * Current default is to allow 4 factories. This can be increased in the future if needed. + * \param[out] num_factories The number of OrtEpFactory instances created by the factory and added to `factories`. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ +typedef OrtStatus* (*CreateEpApiFactoriesFn)(_In_ const char* registered_name, _In_ const OrtApiBase* ort_api_base, + _In_ const OrtLogger* default_logger, + _Inout_ OrtEpFactory** factories, _In_ size_t max_factories, + _Out_ size_t* num_factories); + +/** \brief The function signature that ORT will call to release an OrtEpFactory instance. + * + * This must be available in a function called 'ReleaseEpFactory' in the execution provider library. + * + * \param[in] factory The OrtEpFactory instance to release. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ +typedef OrtStatus* (*ReleaseEpApiFactoryFn)(_In_ OrtEpFactory* factory); + +/** + * \brief The OrtEpFactory provides functions to create and manage execution providers. + * \since Version 1.22. + */ +struct OrtEpFactory { + /** \brief The ONNX Runtime version the execution provider was compiled with. + * + * Implementation should set to ORT_API_VERSION. + * ORT will use this to ensure it does not call functions that were not available when the library was compiled. + * + * \since Version 1.22. + */ + uint32_t ort_version_supported; + + /** \brief Get the name of the execution provider that the factory creates. + * + * The returned string should be a null-terminated, UTF-8 encoded string. ORT will copy it. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \return The name of the execution provider the factory creates. + * + * \since Version 1.22. + */ + ORT_API_T(const char*, GetName, const OrtEpFactory* this_ptr); + + /** \brief Get the name of vendor who owns the execution provider that the factory creates. + * + * The returned string should be a null-terminated, UTF-8 encoded string. ORT will copy it. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \return vendor The vendor name of the execution provider the factory creates. + * + * \since Version 1.22. + */ + ORT_API_T(const char*, GetVendor, const OrtEpFactory* this_ptr); // return EP vendor + + /** \brief Get information from the execution provider about OrtHardwareDevice support. + * + * \param[in] this_ptr The OrtEpFactory instance. + * Non-const as the factory is passed through to the CreateEp call via the OrtEpDevice. + * \param[in] devices The OrtHardwareDevice instances that are available. + * \param[in] num_devices The number of OrtHardwareDevice instances. + * \param[out] ep_devices OrtEpDevice instances for each OrtHardwareDevice that the EP can use. + * The implementation should call OrtEpApi::CreateEpDevice to create, and add the OrtEpDevice + * instances to this pre-allocated array. ORT will take ownership of the values returned. + * i.e. usage is `ep_devices[0] = ;` + * \param[in] max_ep_devices The maximum number of OrtEpDevices that can be added to ep_devices. + * Current default is 8. This can be increased if needed. + * \param[out] num_ep_devices The number of EP devices added to ep_devices. + * \return true if the factory can create an execution provider that uses `device`. + * + * \since Version 1.22. + */ + ORT_API2_STATUS(GetSupportedDevices, _In_ OrtEpFactory* this_ptr, + _In_reads_(num_devices) const OrtHardwareDevice* const* devices, + _In_ size_t num_devices, + _Inout_ OrtEpDevice** ep_devices, + _In_ size_t max_ep_devices, + _Out_ size_t* num_ep_devices); + + /** \brief Function to create an OrtEp instance for use in a Session. + * + * ORT will call ReleaseEp to release the instance when it is no longer needed. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[in] devices The OrtHardwareDevice instances that the execution provider was selected to use. + * May be a subset of the OrtHardwareDevice instances that the execution provider's factory + * set as supported in the call to OrtEpFactory::GetSupportedDevices. + * \param[in] ep_metadata_pairs Execution provider metadata that was provided to OrtEpApi::CreateEpDevice, for each + * device. + * \param[in] num_devices The number of devices the execution provider was selected for. + * \param[in] session_options The OrtSessionOptions instance that contains the configuration options for the + * session. This will include ep_options from GetSupportedDevices as well as any + * user provided overrides. + * Execution provider options will have been added with a prefix of 'ep.[ep name].'. + * The OrtSessionOptions instance will NOT be valid after this call and should not be + * stored for later use. + * \param[in] logger The OrtLogger instance for the session that the execution provider should use for logging. + * \param[out] ep The OrtEp instance created by the factory. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.22. + */ + ORT_API2_STATUS(CreateEp, _In_ OrtEpFactory* this_ptr, + _In_reads_(num_devices) const OrtHardwareDevice* const* devices, + _In_reads_(num_devices) const OrtKeyValuePairs* const* ep_metadata_pairs, + _In_ size_t num_devices, + _In_ const OrtSessionOptions* session_options, + _In_ const OrtLogger* logger, _Outptr_ OrtEp** ep); + + /** \brief Release the OrtEp instance. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[in] ep The OrtEp instance to release. + * + * \since Version 1.22. + */ + ORT_API_T(void, ReleaseEp, OrtEpFactory* this_ptr, struct OrtEp* ep); + + /** \brief Get the vendor id who owns the execution provider that the factory creates. + * + * This is typically the PCI vendor ID. See https://pcisig.com/membership/member-companies + * + * \param[in] this_ptr The OrtEpFactory instance. + * \return vendor_id The vendor ID of the execution provider the factory creates. + * + * \since Version 1.23. + */ + ORT_API_T(uint32_t, GetVendorId, const OrtEpFactory* this_ptr); + + /** \brief Get the version of the execution provider that the factory creates. + * + * The version string should adhere to the Semantic Versioning 2.0 specification + * (https://github.com/semver/semver/blob/v2.0.0/semver.md). + * + * The returned string should be a null-terminated, UTF-8 encoded string. ORT will copy it. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \return The execution provider version string. + * + * \since Version 1.23. + */ + ORT_API_T(const char*, GetVersion, _In_ const OrtEpFactory* this_ptr); + + /** \brief Validate the compatibility of a compiled model with the execution provider factory for one or more devices. + * + * Given a compatibility info string produced during model compilation, the EP factory should determine whether the + * compiled model is compatible with the EP factory when targeting the provided hardware devices. All devices provided + * must belong to the same execution provider instance that this factory creates. + * + * The EP factory implementation should consider the set of devices (e.g., multi-adapter or multi-GPU scenarios) when + * evaluating compatibility and set `model_compatibility` accordingly. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[in] devices Array of OrtHardwareDevice pointers that the EP would run on. All must map to this EP. + * \param[in] num_devices Number of entries in `devices`. + * \param[in] compatibility_info The compatibility information string produced when the model was compiled. + * \param[out] model_compatibility OrtCompiledModelCompatibility value describing the compatibility of the model with the EP. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(ValidateCompiledModelCompatibilityInfo, _In_ OrtEpFactory* this_ptr, + _In_reads_(num_devices) const OrtHardwareDevice* const* devices, + _In_ size_t num_devices, + _In_ const char* compatibility_info, + _Out_ OrtCompiledModelCompatibility* model_compatibility); + + /** \brief Create an OrtAllocator that can be shared across sessions for the given OrtMemoryInfo. + * + * The factory that creates the EP is responsible for providing the allocators required by the EP. + * The OrtMemoryInfo instance will match one of the values set in the OrtEpDevice using EpDevice_AddAllocatorInfo. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[in] memory_info The OrtMemoryInfo to create the allocator for. May be nullptr. + * \param[in] allocator_options Optional key-value pairs for allocator options, can be nullptr. + * \param[out] allocator The created OrtAllocator instance. Set to nullptr if the default CPU allocator is used. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(CreateAllocator, _In_ OrtEpFactory* this_ptr, + _In_ const OrtMemoryInfo* memory_info, + _In_opt_ const OrtKeyValuePairs* allocator_options, + _Outptr_result_maybenull_ OrtAllocator** allocator); + + /** \brief Release an OrtAllocator created by the factory. + * + * \since Version 1.23. + */ + ORT_API_T(void, ReleaseAllocator, _In_ OrtEpFactory* this_ptr, _In_ OrtAllocator* allocator); + + /** \brief Create an OrtDataTransferImpl instance for the factory. + * + * This is used to create an IDataTransfer implementation that can be used to copy data between devices + * that the execution provider supports. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[out] data_transfer The created OrtDataTransferImpl instance. Set to nullptr if not required. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(CreateDataTransfer, _In_ OrtEpFactory* this_ptr, + _Outptr_result_maybenull_ OrtDataTransferImpl** data_transfer); + + /** \brief Check if execution providers created by the factory are stream aware. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \return True if the factory creates execution providers that are stream aware and it implements CreateSyncStreamForDevice. + * + * \since Version 1.23. + */ + ORT_API_T(bool, IsStreamAware, _In_ const OrtEpFactory* this_ptr); + + /** \brief Create a synchronization stream for the given memory device. + * + * This is used to create a synchronization stream for the memory device that can be used for operations outside of + * a session. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[in] memory_device The OrtMemoryDevice to create the synchronization stream for. + * \param[in] stream_options Options for stream creation. May be nullptr. + * \param[out] stream The created OrtSyncStreamImpl instance. nullptr if the execution provider is not stream aware. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.23. + */ + ORT_API2_STATUS(CreateSyncStreamForDevice, _In_ OrtEpFactory* this_ptr, + _In_ const OrtMemoryDevice* memory_device, + _In_opt_ const OrtKeyValuePairs* stream_options, + _Outptr_ OrtSyncStreamImpl** stream); + + /** \brief Check for known incompatibility reasons between a hardware device and this execution provider. + * + * This function allows an execution provider to check if a specific hardware device is compatible + * with the execution provider. The EP can set specific incompatibility reasons via the + * OrtDeviceEpIncompatibilityDetails parameter using OrtEpApi::DeviceEpIncompatibilityDetails_SetDetails. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[in] hw The hardware device to check for incompatibility. + * \param[in,out] details Pre-allocated incompatibility details object created and initialized by ORT. + * The EP can use OrtEpApi::DeviceEpIncompatibilityDetails_SetDetails to set + * incompatibility information. If the device is compatible, the EP can + * leave the object unchanged (it defaults to no incompatibility). + * + * \note Implementation of this function is optional. + * If not implemented, ORT will assume the device is compatible with this EP. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(GetHardwareDeviceIncompatibilityDetails, _In_ OrtEpFactory* this_ptr, + _In_ const OrtHardwareDevice* hw, + _Inout_ OrtDeviceEpIncompatibilityDetails* details); + + /** \brief Create an OrtExternalResourceImporterImpl for external resource import. + * + * This is used to create an external resource importer that enables zero-copy import of + * external GPU memory (e.g., D3D12 shared resources) and synchronization primitives + * (e.g., D3D12 timeline fences). + * + * EPs that support external resource import (via CUDA, HIP, Vulkan, or D3D12 APIs) can + * implement this to allow applications to share GPU resources without copies. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[in] ep_device The OrtEpDevice to create the external resource importer for. + * \param[out] out_importer The created OrtExternalResourceImporterImpl instance. + * Set to nullptr if external resource import is not supported. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note Implementation of this function is optional. + * An EP factory should only implement this if it supports external resource import. + * If not implemented or not supported, return ORT_NOT_IMPLEMENTED or set out_importer to nullptr. + * + * \since Version 1.24. + */ + ORT_API2_STATUS(CreateExternalResourceImporterForDevice, _In_ OrtEpFactory* this_ptr, + _In_ const OrtEpDevice* ep_device, + _Outptr_result_maybenull_ OrtExternalResourceImporterImpl** out_importer); + + /** \brief Returns the number of OrtCustomOpDomains that this factory provides. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[out] num_domains Output parameter set to the number of provided OrtCustomOpDomain instances. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(GetNumCustomOpDomains, _In_ OrtEpFactory* this_ptr, _Out_ size_t* num_domains); + + /** \brief Gets the EP-specific OrtCustomOpDomains. + * + * This function is used when running inference on a model that contains EP-specific custom operations. + * + * Workflow: + * 1. The EP factory implements this function to supply a list of OrtCustomOpDomain instances. + * 2. The application either 1) calls SessionOptionsAppendExecutionProvider_V2() with an OrtEpDevice containing + * the plugin EP's factory or 2) enables auto ep selection. + * 3. 1) SessionOptionsAppendExecutionProvider_V2() appends the provided OrtCustomOpDomains to the + * session options or 2) ORT registers the OrtCustomOpDomains provided by the EP devices + * that could be potentially selected. + * + * As a result, any session created from these session options will have these custom op domains registered + * in ORT, ensuring that the custom ops are properly recognized and validated when the model is loaded. + * + * Plugin EPs can provide two types of custom ops: + * 1. A full OrtCustomOp with a concrete kernel implementation + * - A Plugin EP can supply an OrtCustomOp and a corresponding CustomKernel::Compute() implementation. + * - In GetCapability(), it calls EpGraphSupportInfo_AddSingleNode() to inform ORT + * that the custom node should NOT be fused or compiled. Instead, ORT should invoke + * the custom node's Compute() function at runtime. + * + * 2. A "placeholder" OrtCustomOp with an empty kernel implementation + * - A compile-based Plugin EP can supply an OrtCustomOp whose CustomKernel::Compute() + * does nothing. The purpose is to satisfy model validation during model loading by + * registering the custom op as a valid operator in the session. + * - In GetCapability(), the EP should call EpGraphSupportInfo_AddNodesToFuse() to + * notify ORT that this custom node should be fused and compiled by the EP. + * - In Compile(), the EP executes its compiled bits to perform inference for + * the fused custom node. + * + * Note: The OrtCustomOpDomain instances must be valid while any session is using them. + EP factory has the responsibility to release OrtCustomOpDomain instances it creates. It happens + * automatically if using the C++ Ort::CustomOpDomain class. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[out] domains Array of `num_domains` elements pre-allocated by ORT that should be filled with + OrtCustomOpDomain instances created by the EP. The `num_domains` is the value returned by + GetNumCustomOpDomains(). + * \param[in] num_domains The size of the `domains` array pre-allocated by ORT. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \since Version 1.24. + */ + ORT_API2_STATUS(GetCustomOpDomains, _In_ OrtEpFactory* this_ptr, + _Out_writes_all_(num_domains) OrtCustomOpDomain** domains, _In_ size_t num_domains); + + /** \brief Initialize graphics interop for the EP factory. + * + * This function sets up graphics interop context that enables synchronization between + * external graphics API workloads (D3D12, Vulkan) and ONNX Runtime inference. + * + * The factory stores the graphics context configuration and uses it when creating + * synchronization streams via CreateSyncStreamForDevice. This approach + * is more graceful than passing the command queue directly during stream creation. + * + * The implementation is EP-specific. EPs may create a specialized interop context using + * platform-specific APIs to enable GPU-GPU synchronization. + * + * Key design points: + * - Single init function with all required params (avoids multiple init signatures) + * - Factory stores context and uses it in stream creation + * - Paired with DeinitGraphicsInterop for cleanup + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[in] ep_device The OrtEpDevice to initialize graphics interop for. + * \param[in] config Configuration specifying the graphics API and required handles. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note Implementation of this function is optional. + * EPs that don't support graphics interop should set this to nullptr or return ORT_NOT_IMPLEMENTED. + * + * \since Version 1.25. + */ + ORT_API2_STATUS(InitGraphicsInterop, _In_ OrtEpFactory* this_ptr, + _In_ const OrtEpDevice* ep_device, + _In_ const OrtGraphicsInteropConfig* config); + + /** \brief Deinitialize graphics interop for the EP factory. + * + * This function cleans up any graphics interop context that was set up by InitGraphicsInterop. + * Should be called when graphics interop is no longer needed. + * + * \param[in] this_ptr The OrtEpFactory instance. + * \param[in] ep_device The OrtEpDevice to deinitialize graphics interop for. + * + * \snippet{doc} snippets.dox OrtStatus Return Value + * + * \note Implementation of this function is optional. + * EPs that don't support graphics interop should set this to nullptr or return ORT_NOT_IMPLEMENTED. + * + * \since Version 1.25. + */ + ORT_API2_STATUS(DeinitGraphicsInterop, _In_ OrtEpFactory* this_ptr, + _In_ const OrtEpDevice* ep_device); +}; + +#ifdef __cplusplus +} +#endif diff --git a/include/onnxruntime/core/session/onnxruntime_ep_device_ep_metadata_keys.h b/include/onnxruntime/core/session/onnxruntime_ep_device_ep_metadata_keys.h new file mode 100644 index 0000000000000..5ea4261840299 --- /dev/null +++ b/include/onnxruntime/core/session/onnxruntime_ep_device_ep_metadata_keys.h @@ -0,0 +1,28 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +// This file contains well-known keys for OrtEpDevice and OrtHardwareDevice metadata entries. +// It does NOT specify all available metadata keys. + +// Key for the execution provider version string. This should be available for all plugin EPs. +static const char* const kOrtEpDevice_EpMetadataKey_Version = "version"; + +// Key for the execution provider OS driver version. +static const char* const kOrtEpDevice_EpMetadataKey_OSDriverVersion = "os_driver_version"; + +// Prefix for execution provider compatibility information stored in model metadata. +// Used when generating EP context models to store compatibility strings for each EP. +// Full key format: "ep_compatibility_info." +static const char* const kOrtModelMetadata_EpCompatibilityInfoPrefix = "ep_compatibility_info."; + +// Key for the execution provider library path (for dynamically loaded EPs) +static const char* const kOrtEpDevice_EpMetadataKey_LibraryPath = "library_path"; + +// Optional metadata key to determine if a OrtHardwareDevice represents a virtual (non-hardware) device. +// Possible values: +// - "0": OrtHardwareDevice is not virtual (i.e., actual hardware device). This is the assumed default value +// if this metadata key is not present. +// - "1": OrtHardwareDevice is virtual. +static const char* const kOrtHardwareDevice_MetadataKey_IsVirtual = "is_virtual"; diff --git a/include/onnxruntime/core/session/onnxruntime_float16.h b/include/onnxruntime/core/session/onnxruntime_float16.h index 408d3ccfb2416..625a1e82a6504 100644 --- a/include/onnxruntime/core/session/onnxruntime_float16.h +++ b/include/onnxruntime/core/session/onnxruntime_float16.h @@ -76,6 +76,7 @@ struct Float16Impl { static constexpr uint16_t kPositiveQNaNBits = 0x7E00U; static constexpr uint16_t kNegativeQNaNBits = 0xFE00U; static constexpr uint16_t kMaxValueBits = 0x7BFFU; // Largest normal number + static constexpr uint16_t kMinValueBits = 0xFBFFU; // Lowest normal number static constexpr uint16_t kOneBits = 0x3C00U; static constexpr uint16_t kMinusOneBits = 0xBC00U; @@ -363,6 +364,7 @@ struct BFloat16Impl { static constexpr uint16_t kPositiveQNaNBits = 0x7FC1U; static constexpr uint16_t kNegativeQNaNBits = 0xFFC1U; static constexpr uint16_t kMaxValueBits = 0x7F7FU; + static constexpr uint16_t kMinValueBits = 0xFF7FU; static constexpr uint16_t kRoundToNearest = 0x7FFFU; static constexpr uint16_t kOneBits = 0x3F80U; static constexpr uint16_t kMinusOneBits = 0xBF80U; diff --git a/include/onnxruntime/core/session/onnxruntime_lite_custom_op.h b/include/onnxruntime/core/session/onnxruntime_lite_custom_op.h index ce87d8c56d3fe..81c20768c3120 100644 --- a/include/onnxruntime/core/session/onnxruntime_lite_custom_op.h +++ b/include/onnxruntime/core/session/onnxruntime_lite_custom_op.h @@ -361,7 +361,7 @@ struct TensorArray : public ArgBase { tensor = std::make_unique>(ctx, ith_input, true); break; default: - ORT_CXX_API_THROW("unknow input type", ORT_RUNTIME_EXCEPTION); + ORT_CXX_API_THROW("unknown input type", ORT_RUNTIME_EXCEPTION); break; } tensors_.emplace_back(tensor.release()); @@ -447,18 +447,6 @@ struct OrtLiteCustomOp : public OrtCustomOp { } #endif -#ifdef ORT_ROCM_CTX - template - static typename std::enable_if::value, std::tuple>::type - CreateTuple(OrtKernelContext* context, ArgPtrs& args, size_t num_input, size_t num_output, const std::string& ep) { - thread_local RocmContext rocm_context; - rocm_context.Init(*context); - std::tuple current = std::tuple{rocm_context}; - auto next = CreateTuple(context, args, num_input, num_output, ep); - return std::tuple_cat(current, next); - } -#endif - template static typename std::enable_if::value, std::tuple>::type CreateTuple(OrtKernelContext* context, ArgPtrs& args, size_t num_input, size_t num_output, const std::string& ep) { @@ -674,14 +662,6 @@ struct OrtLiteCustomOp : public OrtCustomOp { } #endif -#ifdef ORT_ROCM_CTX - template - static typename std::enable_if<0 <= sizeof...(Ts) && std::is_same::value>::type - ParseArgs(std::vector& input_types, std::vector& output_types) { - ParseArgs(input_types, output_types); - } -#endif - template static typename std::enable_if<0 <= sizeof...(Ts) && std::is_same::value>::type ParseArgs(std::vector& input_types, std::vector& output_types) { diff --git a/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h b/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h index c80b8c0c164b6..f40ea6591059e 100644 --- a/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h +++ b/include/onnxruntime/core/session/onnxruntime_run_options_config_keys.h @@ -43,6 +43,9 @@ static const char* const kOrtRunOptionsConfigQnnPerfModePostRun = "qnn.htp_perf_ // Set RPC control latency for QNN HTP backend static const char* const kOrtRunOptionsConfigQnnRpcControlLatency = "qnn.rpc_control_latency"; +// Set QNN Lora Config File for apply Lora in QNN context binary +static const char* const kOrtRunOptionsConfigQnnLoraConfig = "qnn.lora_config"; + // Set graph annotation id for CUDA EP. Use with enable_cuda_graph=true. // The value should be an integer. If the value is not set, the default value is 0 and // ORT session only captures one cuda graph before another capture is requested. diff --git a/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h b/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h index 89a87a02276db..24557bb81bce3 100644 --- a/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h +++ b/include/onnxruntime/core/session/onnxruntime_session_options_config_keys.h @@ -10,10 +10,10 @@ * "[Area][.[SubArea1].[SubArea2]...].[Keyname]" * Such as "ep.cuda.use_arena" * The Config Key cannot be empty - * The maximum length of the Config Key is 128 + * The maximum length of the Config Key is 1024 * * The string format of a SessionOptions Config Value is defined individually for each Config. - * The maximum length of the Config Value is 1024 + * The maximum length of the Config Value is 8192 */ // Key for disable PrePacking, @@ -47,6 +47,19 @@ static const char* const kOrtSessionOptionsConfigSetDenormalAsZero = "session.se // Its default value is "0" unless the DirectML execution provider is registered, in which case it defaults to "1". static const char* const kOrtSessionOptionsDisableQuantQDQ = "session.disable_quant_qdq"; +// This controls whether to prevent constant folding from folding DequantizeLinear nodes: +// "0": (default) DequantizeLinear constant folding is determined solely by session.disable_quant_qdq. +// "1": DequantizeLinear nodes are never individually constant folded. +// When session.disable_quant_qdq is "0" (default), DequantizeLinear nodes are already protected from +// constant folding to preserve QDQ node units for downstream QDQ fusion optimizers. +// When session.disable_quant_qdq is "1", then DequantizeLinear nodes are normally allowed to be +// constant folded, but setting this option to "1" still preserves DequantizeLinear nodes. +// This is useful for execution providers like WebNN that disable QDQ fusion, but which +// still need the original DQ/Q nodes to be preserved for their own quantization handling. + +static const char* const kOrtSessionOptionsDisableQDQConstantFolding = + "session.disable_qdq_constant_folding"; + // It controls whether to enable Double QDQ remover and Identical Children Consolidation // "0": not to disable. ORT does remove the middle 2 Nodes from a Q->(QD->Q)->QD pairs // "1": disable. ORT doesn't remove the middle 2 Nodes from a Q->(QD->Q)->QD pairs @@ -67,6 +80,10 @@ static const char* const kOrtSessionOptionsEnableQuantQDQCleanup = "session.enab // GeluApproximation has side effects which may change the inference results. It is disabled by default due to this. static const char* const kOrtSessionOptionsEnableGeluApproximation = "optimization.enable_gelu_approximation"; +// Enable or disable Cast chain elimination in graph optimization. "0": disable; "1": enable. The default is "0". +// CastElimination with chain elimination has side effects which may change the inference results. It is disabled by default due to this. +static const char* const kOrtSessionOptionsEnableCastChainElimination = "optimization.enable_cast_chain_elimination"; + // This setting controls whether to enable AheadOfTime function inlining. // AOT function inlining examines the graph and attempts to inline as many locally defined functions in the model // as possible with the help of enabled execution providers. @@ -107,16 +124,82 @@ static const char* const kOrtSessionOptionsMemoryOptimizerProbeConfig = "optimiz // Default is an empty string which means no optimizers are disabled. static const char* const kOrtSessionOptionsDisableSpecifiedOptimizers = "optimization.disable_specified_optimizers"; +// It controls whether to run graph optimizations in loop or not. +// +// "0": disable. Graph Optimization Loop is disabled. +// ``` +// Level 2 --> Level 3 --> InsertCastTransforms --> Level 4 +// ^ | +// | "No Loop" | +// | | +// X xxxxxxxxxxx X +// ``` +// "1": enable. Graph Optimization Loop is enabled, such that, if optimizations at Level 4 are applied then +// the loop will check for any other valid optimization that can happen. +// ``` +// Level 2 --> Level 3 --> InsertCastTransforms --> Level 4 +// ^ | +// | "Loop only depending on Level 4" | +// | | +// --------------------------------------------------- +// ``` +// "2": enable. Graph Optimization Loop is enabled, such that, if optimizations at Level 2 or above are applied then +// The loop will check for any other valid optimization that can happen. +// ``` +// Level 2 --> Level 3 --> InsertCastTransforms --> Level 4 +// ^ | +// | "Loop" | +// | | +// --------------------------------------------------- +// ``` +// Default value is set to "1". +static const char* const kOrtSessionOptionsGraphOptimizationsLoopLevel = "session.graph_optimizations_loop_level"; + // Enable or disable using device allocator for allocating initialized tensor memory. "1": enable; "0": disable. The default is "0". // Using device allocators means the memory allocation is made using malloc/new. static const char* const kOrtSessionOptionsUseDeviceAllocatorForInitializers = "session.use_device_allocator_for_initializers"; // Configure whether to allow the inter_op/intra_op threads spinning a number of times before blocking // "0": thread will block if found no job to run -// "1": default, thread will spin a number of times before blocking +// "1": thread will spin a number of times before blocking +// The default is "0" when ORT is built with "ORT_CLIENT_PACKAGE_BUILD" and "1" otherwise. +// Thread spinning is disabled by default for client/on-device workloads to reduce cpu utilization and improve power efficiency. static const char* const kOrtSessionOptionsConfigAllowInterOpSpinning = "session.inter_op.allow_spinning"; static const char* const kOrtSessionOptionsConfigAllowIntraOpSpinning = "session.intra_op.allow_spinning"; +// Configure the duration in microseconds that threads spin waiting for work before blocking. +// This setting is subordinate to the allow_spinning flags (session.intra_op.allow_spinning / +// session.inter_op.allow_spinning). When allow_spinning is "0", spinning is disabled and +// the spin duration is forced to 0 regardless of this setting. +// By default (when this option is not set), the thread pool uses an iteration-count-based spin loop +// whose wall-clock duration varies by CPU architecture and pause instruction latency. This provides +// the best throughput but may result in high CPU utilization. +// Setting a positive value switches to calibrated iteration-based spinning that targets +// the specified duration. The actual spin time is a best-effort approximation based on a +// one-time measurement of the pause instruction latency; it may vary with CPU frequency +// changes. Recommended for power-sensitive or client/on-device workloads. +// Common values: 500-2000 (0.5-2ms). +// Setting to "0" with spinning enabled effectively disables spinning (equivalent to allow_spinning = false). +static const char* const kOrtSessionOptionsConfigIntraOpSpinDurationUs = "session.intra_op.spin_duration_us"; +static const char* const kOrtSessionOptionsConfigInterOpSpinDurationUs = "session.inter_op.spin_duration_us"; + +// Configure the maximum exponential-backoff cap for the thread pool spin loop. +// When > 1, each idle spin iteration emits a growing number of SpinPause() calls +// (1, 2, 4, ..., up to this cap), which reduces the density of pause instructions +// during the spin window and lowers CPU/power usage compared to emitting one +// SpinPause() per iteration. The total wall-clock spin duration targeted by +// session.{intra,inter}_op.spin_duration_us is preserved by scaling the iteration +// count against the backoff cap. +// "1" (default) = no backoff, one SpinPause() per iteration (original behavior). +// ">= 2" = enable exponential backoff capped at this value. Typical +// values: 4 (hybrid/E-core friendly) or 8 (desktop/server). +// Values above 64 are clamped to 64. +// This setting is subordinate to allow_spinning and spin_duration_us: when +// spinning is disabled or spin_duration_us forces zero iterations, this value +// has no effect. +static const char* const kOrtSessionOptionsConfigIntraOpSpinBackoffMax = "session.intra_op.spin_backoff_max"; +static const char* const kOrtSessionOptionsConfigInterOpSpinBackoffMax = "session.inter_op.spin_backoff_max"; + // Key for using model bytes directly for ORT format // If a session is created using an input byte array contains the ORT format model data, // By default we will copy the model bytes at the time of session creation to ensure the model bytes @@ -128,13 +211,23 @@ static const char* const kOrtSessionOptionsConfigUseORTModelBytesDirectly = "ses /// /// Key for using the ORT format model flatbuffer bytes directly for initializers. /// This avoids copying the bytes and reduces peak memory usage during model loading and initialization. -/// Requires `session.use_ort_model_bytes_directly` to be true. +/// Requires `session.use_ort_model_bytes_directly` or `session.use_memory_mapped_ort_model` to be true. /// If set, the flatbuffer bytes provided when creating the InferenceSession MUST remain valid for the entire /// duration of the InferenceSession. /// static const char* const kOrtSessionOptionsConfigUseORTModelBytesForInitializers = "session.use_ort_model_bytes_for_initializers"; +/// +/// Key for using memory-mapped I/O to load ORT format model files. +/// When set to "1" and the session is created from a file path, ORT will use memory-mapped I/O +/// to load the .ort model file instead of reading it into a heap-allocated buffer. +/// Usage with session.use_ort_model_bytes_for_initializers will ensure Tensors point directly to the mapped bytes, +/// although the mapping must remain valid and model weights will be immutable. +/// The model load will fail if the mapping fails; fallbacks should be caller-handled. +/// +static const char* const kOrtSessionOptionsConfigUseMemoryMappedOrtModel = "session.use_memory_mapped_ort_model"; + // This should only be specified when exporting an ORT format model for use on a different platform. // If the ORT format model will be used on ARM platforms set to "1". For other platforms set to "0" // Available since version 1.11. @@ -250,6 +343,12 @@ static const char* const kOrtSessionOptionsOptimizedModelExternalInitializersFil static const char* const kOrtSessionOptionsOptimizedModelExternalInitializersMinSizeInBytes = "session.optimized_model_external_initializers_min_size_in_bytes"; +// When loading model from memory buffer and the model has external initializers +// Use this config to set the external data file folder path +// All external data files should be in the same folder +static const char* const kOrtSessionOptionsModelExternalInitializersFileFolderPath = + "session.model_external_initializers_file_folder_path"; + // Use this config when saving pre-packed constant initializers to an external data file. // This allows you to memory map pre-packed initializers on model load and leave it to // to the OS the amount of memory consumed by the pre-packed initializers. Otherwise, @@ -261,6 +360,54 @@ static const char* const kOrtSessionOptionsOptimizedModelExternalInitializersMin static const char* const kOrtSessionOptionsSavePrePackedConstantInitializers = "session.save_external_prepacked_constant_initializers"; +// Use this config when you want to collect memory stats for each node in the graph. +// The file format is a CSV file with the following columns: +// The file will be created if it does not exist, and will be overwritten if it does. +// +// The content of the file can be used to estimate memory requirements at run time including +// the temporary allocations. This operation is preferably done on a CPU device, as the model may exceed +// device memory limits in constrained environments. When enabling this option, it is important to disable +// memory patterns, as they tend to allocate large blocks to avoid fragmentation and accommodate needs of multiple +// kernels. Memory patterns may make it difficult to allocate on a device with limited memory. +// +// The collected stats then can be used to partition the graph among the devices in a way that only the +// required memory is allocated on each device. +// +// node_name, initializers_memory, dynamic_outputs_sizes, temp_allocations_size +// +// - "full path to file": there is not a default for this option. If the file can not be opened for writing, an error will be returned. +static const char* const kOrtSessionOptionsCollectNodeMemoryStatsToFile = "session.collect_node_memory_stats_to_file"; + +/// This is a composite CSV setting formatted as "memory limit in kb,file name for collected stats" +/// "limit > 0": enables Capacity Aware Partitioning for Cuda EP. `limit` is optional and when absent +/// the provider may attempt to figure out the memory available automatically. +/// The setting with no pre-recorded stats is expected to look like: "limit > 0,". +/// In this case, the EP will calculate memory using the initializers referenced by the node. +/// This enables an ad-hoc and flexible scenarios with no pre-recorded stats, but may be less accurate. +/// The setting with no limit is expected to look like: ",file name for collected stats" +/// Finally a setting with both limit and pre-recorded stats absent can contain a single comma: ",". +/// The EP will attempt to place nodes on device (currently only CUDA is supported) : +/// this file is expected to be found at the same folder with the model. The file contains +/// pre-recorded stats collected when running with kOrtSessionOptionsCollectNodeMemoryStatsToFile enforce (see above) +static const char* const kOrtSessionOptionsResourceCudaPartitioningSettings = + "session.resource_cuda_partitioning_settings"; + +/// +/// This is a setting that contains string annotations or annotation prefixes to be matched +/// against individual nodes metadata entry 'layer_ann' to guide layer assignment during partitioning. +/// The value is a semicolon separated list of strings or string prefixes per device. +/// Format: device1(annotation1, annotation2, ...); device2(annotation1, =annotation3, ...);... +/// Where: +/// - device1, device2, ... are the recognized device names to be matched against EPs configured in +/// the given session. +/// - annotation1, annotation2, ... are annotation prefixes to be matched against node annotations. Any +/// node annotation that starts with one of these prefixes will be matched. +/// - =annotation3 indicates an exact match for annotation3. Only node annotations that are exactly +/// equal to 'annotation3' will be matched. +/// TODO: add a list of recognized devices here. +/// +static const char* const kOrtSessionOptionsLayerAssignmentSettings = "session.layer_assignment_settings"; + // Enable EP context feature to dump the partitioned graph which includes the EP context into Onnx file. // The dumped Onnx model with EP context can be used for future inference to avoid the EP graph partitioning/compile overhead. // "0": disable. (default) @@ -269,6 +416,7 @@ static const char* const kOrtSessionOptionEpContextEnable = "ep.context_enable"; // Specify the file path for the Onnx model which has EP context. // Default to original_file_name_ctx.onnx if not specified +// Folder is not a valid option static const char* const kOrtSessionOptionEpContextFilePath = "ep.context_file_path"; // Flag to specify whether to dump the EP context into the Onnx model. @@ -280,11 +428,19 @@ static const char* const kOrtSessionOptionEpContextEmbedMode = "ep.context_embed // in case user need to merge/connect multiple EPContext nodes in one model static const char* const kOrtSessionOptionEpContextNodeNamePrefix = "ep.context_node_name_prefix"; -// Share EP related resources across EPs +// Share EP related resources across sessions static const char* const kOrtSessionOptionShareEpContexts = "ep.share_ep_contexts"; -// Use this config when dumping EP context model with an external initializers file -// All initializers will be inside the external data file if specified, otherwise all in Onnx file +// Stop to share EP related resources across sessions from then on +static const char* const kOrtSessionOptionStopShareEpContexts = "ep.stop_share_ep_contexts"; + +// Used only for context model generation. +// This configuration is used when some nodes are partitioned on the CPU EP and those nodes have external initializers. +// When generating the EP context model, the new model should not rely on the old external data file used by the source ONNX model. +// Use this setting when dumping the EP context model with an external initializers file. +// If specified, all initializers will be placed inside the external data file. +// Otherwise, all initializers will be embedded inside the generated ONNX file. +// By default, this option is not set, meaning all initializers will be included within the ONNX file. static const char* const kOrtSessionOptionsEpContextModelExternalInitializersFileName = "ep.context_model_external_initializers_file_name"; @@ -294,14 +450,90 @@ static const char* const kOrtSessionOptionsEpContextModelExternalInitializersFil // - "1": Gemm FastMath mode is enabled. static const char* const kOrtSessionOptionsMlasGemmFastMathArm64Bfloat16 = "mlas.enable_gemm_fastmath_arm64_bfloat16"; +// Use LUT (Lookup Table) based GEMM for quantized models when available. +// Option values: +// - "0": Do not use LUT based GEMM. [DEFAULT] +// - "1": Use LUT based GEMM when available. +static const char* const kOrtSessionOptionsMlasLutGemm = "mlas.use_lut_gemm"; + +// Use KleidiAI kernels in MLAS if available. +// Option values: +// - "0": Use KleidiAI kernels when available. [DEFAULT] +// - "1": Disable KleidiAI kernels even if available. +static const char* const kOrtSessionOptionsMlasDisableKleidiAi = "mlas.disable_kleidiai"; + // When converting DQ + MatMul -> MatMulNBits, the accuracy level of the MatMulNBits is controlled by this option. // Refer to MatMulNBits op schema for more details. // If not provided, default is 4. static const char* const kOrtSessionOptionsQDQMatMulNBitsAccuracyLevel = "session.qdq_matmulnbits_accuracy_level"; +// Block size used when converting per-tensor or per-axis DQ + MatMul to MatMulNBits. +// Only applies to DQ nodes without an existing block_size attribute (i.e., per-tensor or per-axis quantization). +// Positive value: explicit block_size (must be power-of-2 and >= 16, e.g., 16, 32, 64, 128). +// "0" or not provided: use default block_size of 32. +// "-1": heuristic - largest power-of-2 <= min(K, 256) that minimizes padding. +static const char* const kOrtSessionOptionsQDQMatMulNBitsBlockSize = "session.qdq_matmulnbits_block_size"; + +// Enable the DQ->MatMulNBits fusion graph transformer. +// "0": disabled (default). "1": enabled. +// This is typically set automatically by InferenceSession when the NvTensorRTRTX EP is registered. +static const char* const kOrtSessionOptionsEnableDQMatMulNBitsFusion = "session.enable_dq_matmulnbits_fusion"; + // THIS OPTION IS NOT A REGULAR SESSION OPTION SINCE IT CAN BE MODIFIED AT ANY TIME // Meant to be used with SetEpDynamicOptions // Specify the type of workload for this session. -// “Default”: OS determines the scheduling priority and processor performance to service this workload. [Default] -// “Efficient”: OS treats this workload is efficiency oriented with low scheduling priority and efficient processor performance. +// "Default": OS determines the scheduling priority and processor performance to service this workload. [Default] +// "Efficient": OS treats this workload is efficiency oriented with low scheduling priority and efficient processor performance. static const char* const kOrtEpDynamicOptionsWorkloadType = "ep.dynamic.workload_type"; + +// Disables model compilation during session initialization. +// +// If this option is set to "1", inference session creation will fail with error code ORT_MODEL_REQUIRES_COMPILATION +// if compilation is required to run the model on any Execution Provider added to the session. +// Only the following kinds of models are valid when this option is set to "1": +// - Pre-compiled models that have EPContext nodes for the compiling Execution Providers in the session. +// - Non-compiled models that run only on non-compiling Execution Providers, like CPU EP. +// +// See \href https://onnxruntime.ai/docs/execution-providers/EP-Context-Design.html for details about +// compiled models with EPContext nodes. +// +// Option values: +// - "0": EP compile is not disabled. [DEFAULT] +// - "1": EP compile is disabled. +static const char* const kOrtSessionOptionsDisableModelCompile = "session.disable_model_compile"; + +// Controls behavior when compiled model compatibility is SUPPORTED_PREFER_RECOMPILATION. +// "0": Allow execution with suboptimal performance. [DEFAULT] +// "1": Fail session creation to require recompilation for optimal performance. +// Note: UNSUPPORTED models always fail regardless of this setting. +static const char* const kOrtSessionOptionsFailOnSuboptimalCompiledModel = + "session.fail_on_suboptimal_compiled_model"; + +// THIS OPTION IS NOT A REGULAR SESSION OPTION SINCE IT CAN BE MODIFIED AT ANY TIME +// Meant to be used with SetEpDynamicOptions +// options for HTP performance mode: "burst", "balanced", "default", "high_performance", +// "high_power_saver", "low_balanced", "extreme_power_saver", "low_power_saver", "power_saver", +// "sustained_high_performance". Default to "default". +static const char* const kOrtEpDynamicOptionsQnnHtpPerformanceMode = "ep.dynamic.qnn_htp_performance_mode"; + +// Enables the session to record information about the subgraphs/nodes assigned to execution providers. +// When enabled, an application may call Session_GetEpGraphAssignmentInfo() to retrieve the information. +// +// Option values: +// - "0": Recording of EP graph assignment information is disabled. [DEFAULT] +// - "1": Recording of EP graph assignment information is enabled. +static const char* const kOrtSessionOptionsRecordEpGraphAssignmentInfo = "session.record_ep_graph_assignment_info"; + +// An application enables this option to request that EPs create compiled models (i.e., EPContext models) with EPContext +// nodes that do not store model weights internally. Instead, the weights should be provided by ONNX Runtime as +// explicit inputs to the EPContext nodes. +// +// This option is ignored by an EP if "ep.context_enable" is not set to "1". +// +// If the weights are originally stored in an external file, this allows multiple models to share the same +// external weights file. +// +// Option values: +// - "0": disable. (default) +// - "1": enable. +static const char* const kOrtSessionOptionEpEnableWeightlessEpContextNodes = "ep.enable_weightless_ep_context_nodes"; diff --git a/include/onnxruntime/ep/README.md b/include/onnxruntime/ep/README.md new file mode 100644 index 0000000000000..e7fe6b498b7ab --- /dev/null +++ b/include/onnxruntime/ep/README.md @@ -0,0 +1,21 @@ +## EP adapter + +This folder contains a set of C++ header files. They are used specifically for allowing ONNX Runtime internal kernel-based EPs to use the plugin-style EP API while keep minimal changes to existing code. + +### Folder Structure + +There are 2 types of header files: + +- General header files for plugin EP. This may include utilities, macros and shared routines that depending on ONNX Runtime public API only. There are multiple places for header files of this category (which we are going to unify them to one place. There is an ongoing discussion about unifying shared headers for plugin EPs): + - `include/onnxruntime/ep/` (#26919) + - `onnxruntime/test/autoep/library/plugin_ep_utils.h` + - `include/onnxruntime/core/providers/utils/` (#25753) + +- Header files specifically used for supporting WebGPU EP and CUDA EP to use EP APIs. These header files do not only depend on ONNX Runtime public API, but also depend on ONNX Runtime internal headers. They define adapter classes that replace their compatible, internal ONNX Runtime equivalents. + - `include/onnxruntime/ep/adapter/` + +### Usage + +Make sure to include "ep/adapters.h" to include all adapter implementation code. This file brings the adapter classes into the EP's namespace, so it should be included before other EP code that relies on the adapter classes. Using "ep/adapters.h" as a pre-compiled header is the recommended way to include it first. + +`ep/adapters.h` has conflicts with shared provider. Shared provider should be disabled when using these adapters. diff --git a/include/onnxruntime/ep/adapter/allocator.h b/include/onnxruntime/ep/adapter/allocator.h new file mode 100644 index 0000000000000..1798be23e4ed0 --- /dev/null +++ b/include/onnxruntime/ep/adapter/allocator.h @@ -0,0 +1,136 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED) +#error "This header should not be included directly. Include ep/adapters.h instead." +#endif + +#include +#include + +#include "core/framework/allocator.h" + +namespace onnxruntime { +namespace ep { +namespace adapter { + +// Wraps an OrtAllocator* exposed by the C API as an IAllocator. +// Takes ownership of the wrapped Ort::Allocator and releases it on destruction. +class IAllocatorWrappingOrtAllocator final : public IAllocator { + public: + explicit IAllocatorWrappingOrtAllocator(Ort::Allocator ort_allocator) + : IAllocator(*(EnsureOrtAllocatorHasValue(ort_allocator).GetInfo())), + ort_allocator_(std::move(ort_allocator)) { + } + + void* Alloc(size_t size) override { + return ort_allocator_.Alloc(size); + } + + void Free(void* p) override { + ort_allocator_.Free(p); + } + + void* Reserve(size_t size) override { + return ort_allocator_.Reserve(size); + } + + bool IsStreamAware() const override { + return false; + + // TODO: Enable once AllocOnStream() is implemented. + // static constexpr uint32_t kOrtAllocatorAllocOnStreamMinVersion = 23; + // const OrtAllocator* raw = ort_allocator_; + // return raw->version >= kOrtAllocatorAllocOnStreamMinVersion && raw->AllocOnStream != nullptr; + } + + void* AllocOnStream(size_t /*size*/, Stream* /*stream*/) override { + // TODO: Implement AllocOnStream(). + // The internal `onnxruntime::IAllocator::AllocOnStream` signature takes an internal `onnxruntime::Stream*` + // argument, while the public `::OrtAllocator::AllocOnStream` signature takes an `::OrtSyncStream*` argument. + // We need to properly map from one to the other. + // `::OrtSyncStream*` should be treated as an opaque type from the plugin EP's perspective. + ORT_NOT_IMPLEMENTED("IAllocatorWrappingOrtAllocator::AllocOnStream is not implemented yet."); + } + + private: + static const Ort::Allocator& EnsureOrtAllocatorHasValue(const Ort::Allocator& ort_allocator) { + ORT_ENFORCE(ort_allocator != nullptr, "Ort::Allocator must contain a non-nullptr OrtAllocator."); + return ort_allocator; + } + + // TODO: Consider adding GetStats() override. Requires parsing OrtKeyValuePairs from the C API + // into AllocatorStats; see GetStatsFromOrtAllocator() in allocator_adapters.cc for reference. + + Ort::Allocator ort_allocator_; + + ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(IAllocatorWrappingOrtAllocator); +}; + +/// +/// A bridge class between the EP API OrtAllocator and an IAllocator implementation. +/// +class Allocator : public OrtAllocator { + public: + /** + * Create from an existing AllocatorPtr. + */ + explicit Allocator(const OrtMemoryInfo* memory_info, AllocatorPtr impl) + : Allocator{memory_info} { + ORT_ENFORCE(impl != nullptr, "Allocator implementation cannot be null."); + impl_ = impl; + } + + using AllocatorFactory = AllocatorPtr (*)(const OrtMemoryInfo& memory_info); + + /** + * Create from an AllocatorFactory, which will be called lazily when the first allocation is made. + */ + explicit Allocator(const OrtMemoryInfo* memory_info, AllocatorFactory get_allocator_impl) + : Allocator{memory_info} { + get_allocator_impl_ = get_allocator_impl; + } + + private: + explicit Allocator(const OrtMemoryInfo* memory_info) + : OrtAllocator{}, memory_info_(memory_info), get_allocator_impl_(nullptr) { + version = ORT_API_VERSION; + Alloc = AllocImpl; + Free = FreeImpl; + Info = InfoImpl; + } + AllocatorPtr GetImpl() { + if (!impl_) { + std::call_once(init_flag_, [this]() { + impl_ = get_allocator_impl_(*memory_info_); + }); + } + return impl_; + } + + static void* ORT_API_CALL AllocImpl(OrtAllocator* this_ptr, size_t size) noexcept { + auto* allocator = static_cast(this_ptr); + return allocator->GetImpl()->Alloc(size); + } + + static void ORT_API_CALL FreeImpl(OrtAllocator* this_ptr, void* p) noexcept { + auto* allocator = static_cast(this_ptr); + allocator->GetImpl()->Free(p); + } + + static const OrtMemoryInfo* ORT_API_CALL InfoImpl(const OrtAllocator* this_ptr) noexcept { + auto* allocator = static_cast(this_ptr); + return allocator->memory_info_; + } + + const OrtMemoryInfo* memory_info_; + AllocatorPtr impl_; + AllocatorFactory get_allocator_impl_; + std::once_flag init_flag_; +}; + +} // namespace adapter +} // namespace ep +} // namespace onnxruntime diff --git a/include/onnxruntime/ep/adapter/data_transfer_manager.h b/include/onnxruntime/ep/adapter/data_transfer_manager.h new file mode 100644 index 0000000000000..7730ec706a3aa --- /dev/null +++ b/include/onnxruntime/ep/adapter/data_transfer_manager.h @@ -0,0 +1,54 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED) +#error "This header should not be included directly. Include ep/adapters.h instead." +#endif + +#include "core/common/status.h" +#include "core/common/common.h" +#include "core/framework/data_transfer.h" +#include "core/framework/tensor.h" + +namespace onnxruntime { +namespace ep { +namespace adapter { + +/// +/// An adapter class partially implementing the interface of `onnxruntime::DataTransferManager`. +/// +struct DataTransferManager { + explicit DataTransferManager(std::unique_ptr impl) : impl_{std::move(impl)} {} + + common::Status CopyTensor(const Tensor& src, Tensor& dst) const { + if (src.Shape().Size() != dst.Shape().Size()) { + return ORT_MAKE_STATUS(ONNXRUNTIME, + FAIL, + "Tensor size mismatch: source tensor size is ", + src.Shape().Size(), + ", destination tensor size is ", + dst.Shape().Size()); + } + + if (impl_->CanCopy(src.Location().device, dst.Location().device)) { + return impl_->CopyTensor(src, dst); + } + + return ORT_MAKE_STATUS(ONNXRUNTIME, + FAIL, + "There's no data transfer registered for copying tensors from ", + src.Location().device.ToString(), + " to ", + dst.Location().device.ToString()); + } + + private: + ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(DataTransferManager); + std::unique_ptr impl_; +}; + +} // namespace adapter +} // namespace ep +} // namespace onnxruntime diff --git a/include/onnxruntime/ep/adapter/ep.h b/include/onnxruntime/ep/adapter/ep.h new file mode 100644 index 0000000000000..ca0a8c9599eda --- /dev/null +++ b/include/onnxruntime/ep/adapter/ep.h @@ -0,0 +1,59 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED) +#error "This header should not be included directly. Include ep/adapters.h instead." +#endif + +#include "data_transfer_manager.h" + +#include "core/framework/execution_provider.h" + +namespace onnxruntime { +namespace ep { +namespace adapter { + +/// +/// Wrapper around IExecutionProvider to expose via OrtEp. +/// +class Ep : public OrtEp { + protected: + explicit Ep(std::unique_ptr impl, AllocatorPtr temp_space_cpu_allocator, AllocatorPtr temp_space_allocator) + : OrtEp{}, + impl_(std::move(impl)), + data_transfer_manager_{impl_->GetDataTransfer()}, + profiler_{impl_->GetProfiler()}, + temp_space_cpu_allocator_{temp_space_cpu_allocator}, + temp_space_allocator_{temp_space_allocator} { + ort_version_supported = ORT_API_VERSION; + } + + public: + inline IExecutionProvider* EpImpl() const noexcept { + return impl_.get(); + } + inline const DataTransferManager& GetDataTransferManager() const noexcept { + return data_transfer_manager_; + } + Status GetTempSpaceCPUAllocator(AllocatorPtr* output) const { + *output = temp_space_cpu_allocator_; + return Status::OK(); + } + Status GetTempSpaceAllocator(AllocatorPtr* output) const { + *output = temp_space_allocator_; + return Status::OK(); + } + + private: + std::unique_ptr impl_; + DataTransferManager data_transfer_manager_; + std::unique_ptr profiler_; + AllocatorPtr temp_space_cpu_allocator_; + AllocatorPtr temp_space_allocator_; +}; + +} // namespace adapter +} // namespace ep +} // namespace onnxruntime diff --git a/include/onnxruntime/ep/adapter/kernel_def.h b/include/onnxruntime/ep/adapter/kernel_def.h new file mode 100644 index 0000000000000..11bf368c95b0a --- /dev/null +++ b/include/onnxruntime/ep/adapter/kernel_def.h @@ -0,0 +1,37 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED) +#error "This header should not be included directly. Include ep/adapters.h instead." +#endif + +#include + +namespace onnxruntime { +namespace ep { +namespace adapter { + +/// +/// An adapter class partially implementing the interface of `onnxruntime::KernelDef`. +/// +class KernelDef { + public: + explicit KernelDef(const OrtKernelInfo* kernel_info) : kernel_info_{kernel_info} {} + + const std::string OpName() const { + return kernel_info_.GetNodeName(); + } + + const std::string Domain() const { + return kernel_info_.GetOperatorDomain(); + } + + private: + const Ort::ConstKernelInfo kernel_info_; +}; + +} // namespace adapter +} // namespace ep +} // namespace onnxruntime diff --git a/include/onnxruntime/ep/adapter/kernel_def_builder.h b/include/onnxruntime/ep/adapter/kernel_def_builder.h new file mode 100644 index 0000000000000..276c793a4311c --- /dev/null +++ b/include/onnxruntime/ep/adapter/kernel_def_builder.h @@ -0,0 +1,145 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED) +#error "This header should not be included directly. Include ep/adapters.h instead." +#endif + +#include + +#include "core/framework/data_types.h" + +namespace onnxruntime { +namespace ep { +namespace adapter { + +/// +/// Gets an OrtMLDataType for a tensor type. Throws on error. +/// +/// +/// +inline const OrtDataType* GetTensorType(ONNXTensorElementDataType elem_type) { + const OrtEpApi& ep_api = Ort::GetEpApi(); + const OrtDataType* result = nullptr; + + Ort::ThrowOnError(ep_api.GetTensorDataType(elem_type, &result)); + return result; +} + +inline const OrtDataType* MLDataTypeToOrtDataType(MLDataType ml_type) { + auto tensor_type = ml_type->AsTensorType(); + EP_ENFORCE(tensor_type != nullptr, "EP Kernel registration only supports tensor types."); + auto elem_type = tensor_type->GetElementType(); + auto primitive_type = static_cast(elem_type); + auto onnx_type = static_cast(primitive_type->GetDataType()); + return GetTensorType(onnx_type); +} + +/// +/// An adapter class partially implementing the interface of `onnxruntime::KernelDefBuilder`. +/// +struct KernelDefBuilder { + static std::unique_ptr Create() { return std::make_unique(); } + + explicit KernelDefBuilder() {} + + KernelDefBuilder& SetName(const char* op_name) { + builder_.SetOperatorType(op_name); + return *this; + } + + KernelDefBuilder& SetDomain(const char* domain) { + builder_.SetDomain(domain); + return *this; + } + + KernelDefBuilder& SinceVersion(int since_version) { + return SinceVersion(since_version, INT_MAX); + } + + KernelDefBuilder& SinceVersion(int since_version_start, int since_version_end) { + builder_.SetSinceVersion(since_version_start, since_version_end); + return *this; + } + + KernelDefBuilder& Provider(const char* provider_type) { + builder_.SetExecutionProvider(provider_type); + return *this; + } + + KernelDefBuilder& TypeConstraint(const char* arg_name, std::vector types) { + std::vector ort_types; + ort_types.reserve(types.size()); + for (const auto& type : types) { + ort_types.push_back(MLDataTypeToOrtDataType(type)); + } + builder_.AddTypeConstraint(arg_name, ort_types); + return *this; + } + + KernelDefBuilder& TypeConstraint(const char* arg_name, MLDataType type) { + builder_.AddTypeConstraint(arg_name, MLDataTypeToOrtDataType(type)); + return *this; + } + + KernelDefBuilder& MayInplace(const std::vector>& inplaces) { + for (const auto& pair : inplaces) { + builder_.AddInputOutputMutableAlias(pair.first, pair.second); + } + return *this; + } + KernelDefBuilder& MayInplace(int input_index, int output_index) { + builder_.AddInputOutputMutableAlias(input_index, output_index); + return *this; + } + + KernelDefBuilder& Alias(const std::vector>& aliases) { + for (const auto& pair : aliases) { + builder_.AddInputOutputAlias(pair.first, pair.second); + } + return *this; + } + KernelDefBuilder& Alias(int input_index, int output_index) { + builder_.AddInputOutputAlias(input_index, output_index); + return *this; + } + + KernelDefBuilder& InputMemoryType(OrtMemType type, int input_index) { + builder_.SetInputMemType(input_index, type); + return *this; + } + + KernelDefBuilder& InputMemoryType(OrtMemType type, const std::vector& input_indexes) { + for (int input_index : input_indexes) { + builder_.SetInputMemType(input_index, type); + } + return *this; + } + + KernelDefBuilder& OutputMemoryType(OrtMemType type, int output_index) { + builder_.SetOutputMemType(output_index, type); + return *this; + } + + KernelDefBuilder& OutputMemoryType(OrtMemType type, const std::vector& output_indexes) { + for (int output_index : output_indexes) { + builder_.SetOutputMemType(output_index, type); + } + return *this; + } + + // ExecQueueId is intentionally a no-op. The plugin EP manages stream + // assignment externally; the queue id hint is not needed. + KernelDefBuilder& ExecQueueId(int /*queue_id*/) { return *this; } + + Ort::KernelDef Build() { return builder_.Build(); } + + private: + Ort::KernelDefBuilder builder_; +}; + +} // namespace adapter +} // namespace ep +} // namespace onnxruntime diff --git a/include/onnxruntime/ep/adapter/kernel_registry.h b/include/onnxruntime/ep/adapter/kernel_registry.h new file mode 100644 index 0000000000000..e654f57488f84 --- /dev/null +++ b/include/onnxruntime/ep/adapter/kernel_registry.h @@ -0,0 +1,118 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED) +#error "This header should not be included directly. Include ep/adapters.h instead." +#endif + +#include + +#include "kernel_def_builder.h" +#include "op_kernel_info.h" +#include "op_kernel.h" + +#include "core/graph/basic_types.h" +#include "core/framework/error_code_helper.h" + +namespace onnxruntime { +namespace ep { +namespace adapter { + +struct FuncManager {}; +using KernelCreatePtrFn = std::add_pointer& out)>::type; + +/// +/// An adapter class partially implementing the interface of `onnxruntime::KernelCreateInfo`. +/// +struct KernelCreateInfo { + Ort::KernelDef kernel_def; + KernelCreatePtrFn kernel_create_func; + Status status; + + KernelCreateInfo(Ort::KernelDef definition, + KernelCreatePtrFn create_func) + : kernel_def(std::move(definition)), + kernel_create_func(create_func) { + assert(kernel_def != nullptr); + } + + KernelCreateInfo(KernelCreateInfo&& other) noexcept + : kernel_def(std::move(other.kernel_def)), + kernel_create_func(std::move(other.kernel_create_func)) {} + + KernelCreateInfo() = default; +}; + +/// +/// An adapter class partially implementing the interface of `onnxruntime::KernelRegistry`. +/// +struct KernelRegistry { + KernelRegistry() = default; + + static OrtStatus* CreateKernel(void* kernel_create_func_state, const OrtKernelInfo* info, OrtKernelImpl** out) noexcept { + try { + FuncManager func_mgr; // not used + std::unique_ptr kernel; + KernelCreatePtrFn create_func = reinterpret_cast(kernel_create_func_state); + Status status = create_func(func_mgr, OpKernelInfo(info), kernel); + if (!status.IsOK()) { + return ToOrtStatus(status); + } + *out = nullptr; + + // Try to create a control flow kernel implementation if applicable. + // For kernel based plugin EPs, the implementation should create the control flow kernel directly using one of the + // following APIs: + // - `OrtEpApi::CreateIfKernel` + // - `OrtEpApi::CreateLoopKernel` + // - `OrtEpApi::CreateScanKernel` + // + // If the kernel being created is one of the control flow kernels, `CreateControlFlowKernelImpl` should be overriden + // to write the value of `out` to the created `OrtKernelImpl`, and the returned status should be OK. + status = kernel->CreateControlFlowKernelImpl(info, out); + if (!status.IsOK()) { + return ToOrtStatus(status); + } + if (*out == nullptr) { + // If the kernel is not a control flow kernel, create a regular kernel implementation. + *out = new KernelImpl(std::move(kernel)); + } + return nullptr; + } catch (const Ort::Exception& ex) { + Ort::Status ort_status(ex); + return ort_status.release(); + } catch (const std::exception& ex) { + Ort::Status ort_status(ex.what(), ORT_EP_FAIL); + return ort_status.release(); + } catch (...) { + Ort::Status ort_status("Unknown exception in CreateKernel", ORT_EP_FAIL); + return ort_status.release(); + } + } + + Status Register(KernelCreateInfo&& create_info) { + registry_.AddKernel(create_info.kernel_def, + KernelRegistry::CreateKernel, + reinterpret_cast(create_info.kernel_create_func)); + return Status::OK(); + } + + // Implicit conversion to OrtKernelRegistry* for compatibility with C API + operator OrtKernelRegistry*() const noexcept { + return registry_.operator OrtKernelRegistry*(); + } + + // Release ownership of the underlying OrtKernelRegistry* + OrtKernelRegistry* release() { + return registry_.release(); + } + + private: + Ort::KernelRegistry registry_; +}; + +} // namespace adapter +} // namespace ep +} // namespace onnxruntime diff --git a/include/onnxruntime/ep/adapter/logging.h b/include/onnxruntime/ep/adapter/logging.h new file mode 100644 index 0000000000000..6e4b984611161 --- /dev/null +++ b/include/onnxruntime/ep/adapter/logging.h @@ -0,0 +1,117 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED) +#error "This header should not be included directly. Include ep/adapters.h instead." +#endif + +#include "core/common/logging/logging.h" +#include "core/common/path_string.h" + +namespace onnxruntime { +namespace ep { +namespace adapter { + +struct Logger { + Logger(const OrtLogger* logger) : logger_(logger) {} + + bool OutputIsEnabled(logging::Severity severity, logging::DataType /* data_type */) const noexcept { + return ((OrtLoggingLevel)severity >= logger_.GetLoggingSeverityLevel()); + } + + void Log(logging::Severity severity, + const char* file_path, + int line_number, + const char* func_name, + const char* message) const noexcept { + auto path_string = onnxruntime::ToPathString(file_path); + logger_.LogMessage((OrtLoggingLevel)severity, + path_string.c_str(), + line_number, + func_name, + message); + } + + private: + Ort::Logger logger_; +}; + +class LoggingManager final { + public: + static bool HasDefaultLogger() { return nullptr != instance_; } + static const Logger& DefaultLogger() { return *instance_; } + static void CreateDefaultLogger(const OrtLogger* logger) { + instance_ = new Logger(logger); + } + static void DestroyDefaultLogger() { + delete instance_; + instance_ = nullptr; + } + + private: + inline static Logger* instance_ = nullptr; +}; + +namespace detail { +struct LoggerCapture { + LoggerCapture(const Logger& logger, + logging::Severity severity, + const char* category, + logging::DataType dataType, + const CodeLocation& location) : logger_{logger}, + severity_{severity}, + category_{category}, + data_type_{dataType}, + location_{location} {} + + ~LoggerCapture() { + logger_.Log(severity_, location_.file_and_path.c_str(), location_.line_num, + location_.function.c_str(), stream_.str().c_str()); + } + + std::ostream& Stream() noexcept { + return stream_; + } + + const Logger& logger_; + logging::Severity severity_; + const char* category_; + logging::DataType data_type_; + const CodeLocation& location_; + std::ostringstream stream_; +}; + +// Helper functions to dispatch to the correct Capture type based on logger type +inline ::onnxruntime::logging::Capture CreateMessageCapture( + const ::onnxruntime::logging::Logger& logger, + ::onnxruntime::logging::Severity severity, + const char* category, + ::onnxruntime::logging::DataType datatype, + const CodeLocation& location) { + return ::onnxruntime::logging::Capture(logger, severity, category, datatype, location); +} + +inline detail::LoggerCapture CreateMessageCapture( + const Logger& logger, + ::onnxruntime::logging::Severity severity, + const char* category, + ::onnxruntime::logging::DataType datatype, + const CodeLocation& location) { + return detail::LoggerCapture(logger, severity, category, datatype, location); +} + +} // namespace detail +} // namespace adapter +} // namespace ep +} // namespace onnxruntime + +// Undefine and redefine logging macros +#undef LOGS_DEFAULT_CATEGORY +#define LOGS_DEFAULT_CATEGORY(severity, category) \ + LOGS_CATEGORY(::onnxruntime::ep::adapter::LoggingManager::DefaultLogger(), severity, category) + +#undef CREATE_MESSAGE +#define CREATE_MESSAGE(logger, severity, category, datatype) \ + ::onnxruntime::ep::adapter::detail::CreateMessageCapture(logger, ::onnxruntime::logging::Severity::k##severity, category, datatype, ORT_WHERE) diff --git a/include/onnxruntime/ep/adapter/node.h b/include/onnxruntime/ep/adapter/node.h new file mode 100644 index 0000000000000..91aff7d670b2f --- /dev/null +++ b/include/onnxruntime/ep/adapter/node.h @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED) +#error "This header should not be included directly. Include ep/adapters.h instead." +#endif + +namespace onnxruntime { +namespace ep { +namespace adapter { + +/// +/// An adapter class partially implementing the interface of `onnxruntime::Node`. +/// +struct Node { + explicit Node(const OrtKernelInfo* kernel_info) : kernel_info_{kernel_info} {} + /** Gets the Node's name. */ + std::string Name() const noexcept { + return kernel_info_.GetNodeName(); + } + + /** Gets the Node's operator type. */ + std::string OpType() const noexcept { + return kernel_info_.GetOperatorType(); + } + + /** Gets the Node's domain. */ + std::string Domain() const { + return kernel_info_.GetOperatorDomain(); + } + + /** Gets the since version of the operator. */ + int SinceVersion() const noexcept { + return kernel_info_.GetOperatorSinceVersion(); + } + + /** Gets the number of outputs. */ + size_t OutputCount() const noexcept { + return kernel_info_.GetOutputCount(); + } + + /** Gets whether an output exists or is an omitted optional output. */ + bool OutputExists(size_t index) const { + // KernelInfo_GetOutputName returns an empty string for omitted optional + // outputs, which lets adapter consumers mirror NodeArg::Exists() without + // pulling in full NodeArg metadata. + return index < OutputCount() && !kernel_info_.GetOutputName(index).empty(); + } + + private: + const Ort::ConstKernelInfo kernel_info_; +}; + +} // namespace adapter +} // namespace ep +} // namespace onnxruntime diff --git a/include/onnxruntime/ep/adapter/op_kernel.h b/include/onnxruntime/ep/adapter/op_kernel.h new file mode 100644 index 0000000000000..27a46cc10e306 --- /dev/null +++ b/include/onnxruntime/ep/adapter/op_kernel.h @@ -0,0 +1,245 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED) +#error "This header should not be included directly. Include ep/adapters.h instead." +#endif + +#include +#include +#include + +#include "core/framework/allocator.h" +#include "core/framework/tensor.h" + +#include "node.h" +#include "op_kernel_info.h" +#include "tensor_helper.h" + +namespace onnxruntime { +struct PrePackedWeights; +class TensorShape; +} // namespace onnxruntime + +namespace onnxruntime { +namespace ep { +namespace adapter { + +struct OpKernelContext; + +/// +/// An adapter class partially implementing the interface of `onnxruntime::OpKernel`. +/// +struct OpKernel { + explicit OpKernel(const OpKernelInfo& info) : op_kernel_info_{info} {} + virtual ~OpKernel() {} + + adapter::Node Node() const { + return op_kernel_info_.node(); + } + const OpKernelInfo& Info() const { + return op_kernel_info_; + } + + virtual Status CreateControlFlowKernelImpl(const OrtKernelInfo* /*info*/, OrtKernelImpl** /*impl*/) { + return Status::OK(); + } + + virtual Status Compute(OpKernelContext* p_op_kernel_context) const = 0; + virtual Status PrePack(const Tensor& /*tensor*/, + int /*input_idx*/, + AllocatorPtr /*alloc*/, + /*out*/ bool& is_packed, + /*out*/ PrePackedWeights* /*prepacked_weights*/) { + is_packed = false; + return Status::OK(); + } + + ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(OpKernel); + OpKernelInfo op_kernel_info_; +}; + +/// +/// An adapter class partially implementing the interface of `onnxruntime::OpKernelContext`. +/// +struct OpKernelContext { + explicit OpKernelContext(OrtKernelContext* context, const OpKernel& op_kernel) : context_{context}, + op_kernel_{op_kernel}, + constant_input_tensors_{op_kernel.Info().GetConstantInputTensors()} { + input_tensors_.resize(context_.GetInputCount()); + output_tensors_.resize(context_.GetOutputCount()); + } + + template >> + const T* Input(int index) const { + if (index < 0 || static_cast(index) >= input_tensors_.size()) { + return nullptr; + } + if (input_tensors_[index].DataRaw() != nullptr) { + return &input_tensors_[index]; + } + + if (static_cast(index) < constant_input_tensors_.size() && constant_input_tensors_[index].DataRaw() != nullptr) { + return &constant_input_tensors_[index]; + } + + auto input = context_.GetInput(index); + if (input == nullptr || !input.IsTensor()) { + return nullptr; + } + + input_tensors_[index] = CreateTensorFromApiValue(const_cast(static_cast(input))); + return &input_tensors_[index]; + } + /// Get a required (non-optional) input tensor. Throws if the input is null. + /// Use Input() for optional inputs that may legitimately be absent. + template >> + const T& RequiredInput(int index) const { + auto* input = Input(index); + ORT_ENFORCE(input != nullptr, "Required input ", index, " is null"); + return *input; + } + Tensor* Output(int index, const TensorShape& shape) { + if (index < 0 || static_cast(index) >= output_tensors_.size()) { + return nullptr; + } + if (output_tensors_[index].DataRaw() != nullptr) { + return &output_tensors_[index]; + } + + auto output = context_.GetOutput(index, shape.GetDims().data(), shape.GetDims().size()); + if (output == nullptr) { + return nullptr; + } + + output_tensors_[index] = CreateTensorFromApiValue(output); + return &output_tensors_[index]; + } + /// Get a required (non-optional) output tensor. Throws if the output is null. + Tensor& RequiredOutput(int index, const TensorShape& shape) { + auto* output = Output(index, shape); + ORT_ENFORCE(output != nullptr, "Required output ", index, " is null"); + return *output; + } + Tensor* Output(int index, const std::vector& shape) { + return Output(index, TensorShape{shape}); + } + Tensor* Output(int index, const std::initializer_list& shape) { + return Output(index, TensorShape{shape}); + } + [[nodiscard]] Status GetTempSpaceCPUAllocator(AllocatorPtr* output) const { + // Use GetOrtEp() directly from the cached KernelInfoCache rather than going through + // GetExecutionProvider()->GetOrtEp(). GetExecutionProvider() returns the native EP impl + // (e.g. WebGpuExecutionProvider), which doesn't override GetOrtEp() and returns nullptr. + // The cached ort_ep_ is resolved from the plugin wrapper's IExecutionProvider during + // KernelInfoCache construction, so it correctly holds the OrtEp instance. + const auto* ort_ep = op_kernel_.Info().GetOrtEp(); + ORT_ENFORCE(ort_ep != nullptr, "Kernel execution provider is not associated with an OrtEp instance."); + return static_cast(ort_ep)->GetTempSpaceCPUAllocator(output); + } + [[nodiscard]] Status GetTempSpaceAllocator(AllocatorPtr* output) const { + // See comment in GetTempSpaceCPUAllocator for why we use GetOrtEp() directly. + const auto* ort_ep = op_kernel_.Info().GetOrtEp(); + ORT_ENFORCE(ort_ep != nullptr, "Kernel execution provider is not associated with an OrtEp instance."); + return static_cast(ort_ep)->GetTempSpaceAllocator(output); + } + int InputCount() const { + return static_cast(input_tensors_.size()); + } + int OutputCount() const { + return static_cast(output_tensors_.size()); + } + bool GetUseDeterministicCompute() const { + // TODO(fs-eire): Implement GetUseDeterministicCompute(). + // if (CurrentOrtApiVersion() >= 25) { + // return /* TBD: wait for GetUseDeterministicCompute to be added in ORT API v25 */; + // } else { + return false; + // } + } + void* GetGPUComputeStream() const { + return context_.GetGPUComputeStream(); + } + + private: + ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(OpKernelContext); + Ort::KernelContext context_; + const OpKernel& op_kernel_; + const std::vector& constant_input_tensors_; + mutable std::vector input_tensors_; + std::vector output_tensors_; +}; + +/// +/// A bridge class between `onnxruntime::ep::adapter::OpKernel` and `onnxruntime::OrtKernelImpl`. +/// +struct KernelImpl : OrtKernelImpl { + explicit KernelImpl(std::unique_ptr impl) + : OrtKernelImpl{}, impl_(std::move(impl)) { + ort_version_supported = ORT_API_VERSION; + Compute = ComputeImpl; + Release = ReleaseImpl; + PrePackWeight = PrePackWeightImpl; + } + + private: + static OrtStatus* ORT_API_CALL ComputeImpl(_In_ OrtKernelImpl* this_ptr, + _In_ OrtKernelContext* context) noexcept { + Status status; + ORT_TRY { + const auto* kernel_impl = static_cast(this_ptr)->impl_.get(); + OpKernelContext ctx{context, *kernel_impl}; + status = kernel_impl->Compute(&ctx); + } + ORT_CATCH(const std::exception& ex) { + ORT_HANDLE_EXCEPTION([&]() { + status = ORT_MAKE_STATUS(ONNXRUNTIME, RUNTIME_EXCEPTION, ex.what()); + }); + } + if (status.IsOK()) { + return nullptr; + } else { + return Ort::Status{status.ErrorMessage().c_str(), static_cast(status.Code())}.release(); + } + } + + static void ORT_API_CALL ReleaseImpl(_In_ OrtKernelImpl* this_ptr) noexcept { + delete static_cast(this_ptr); + } + + static OrtStatus* ORT_API_CALL PrePackWeightImpl(_In_ OrtKernelImpl* this_ptr, + _In_ const OrtValue* weight, + int input_index, + _In_ OrtAllocator* /* allocator */, + _In_opt_ OrtSharedPrePackedWeightCache* /* prepacked_weight_cache */, + _Out_ bool* is_packed) noexcept { + Status status; + ORT_TRY { + auto* kernel_impl = static_cast(this_ptr)->impl_.get(); + const auto tensor = CreateTensorFromApiValue(const_cast(weight)); + status = kernel_impl->PrePack(tensor, input_index, AllocatorPtr{}, *is_packed, nullptr); + } + ORT_CATCH(const std::exception& ex) { + ORT_HANDLE_EXCEPTION([&]() { + status = ORT_MAKE_STATUS(ONNXRUNTIME, RUNTIME_EXCEPTION, ex.what()); + }); + } + if (!status.IsOK()) { + return Ort::Status{status.ErrorMessage().c_str(), static_cast(status.Code())}.release(); + } + return nullptr; + } + + ~KernelImpl() = default; + + private: + std::unique_ptr impl_; +}; + +} // namespace adapter +} // namespace ep +} // namespace onnxruntime diff --git a/include/onnxruntime/ep/adapter/op_kernel_info.h b/include/onnxruntime/ep/adapter/op_kernel_info.h new file mode 100644 index 0000000000000..417ebd4adf7a2 --- /dev/null +++ b/include/onnxruntime/ep/adapter/op_kernel_info.h @@ -0,0 +1,219 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED) +#error "This header should not be included directly. Include ep/adapters.h instead." +#endif + +#include +#include + +#include "core/common/inlined_containers.h" +#include "core/common/narrow.h" +#include "core/common/status.h" +#include "core/framework/config_options.h" +#include "core/framework/tensor_shape.h" +#include "core/framework/tensor.h" + +#include "allocator.h" +#include "node.h" +#include "kernel_def.h" +#include "tensor_helper.h" + +namespace onnxruntime { +class DataTransferManager; +class IExecutionProvider; +} // namespace onnxruntime + +namespace onnxruntime { +namespace ep { +namespace adapter { + +/// +/// An adapter class partially implementing the interface of `onnxruntime::OpKernelInfo`. +/// +struct OpKernelInfo { + // + // A helper struct to cache kernel info data + // + // Because `KernelCreatePtrFn` is defined to use `const OpKernelInfo&` as parameter type of the kernel creation function, `OpKernelInfo` has to be copyable. + // This means we cannot store cached data like `constant_input_tensors_` in `OpKernelInfo` directly to avoid ownership issues. + // + // As a workaround, we define this struct `KernelInfoCache` here to represent the cached data. We use a shared pointer to `KernelInfoCache` in `OpKernelInfo` + // to manage the lifetime of the cached data. + struct KernelInfoCache { + explicit KernelInfoCache(const OrtKernelInfo* kernel_info) : kernel_info_(kernel_info) { + Ort::ConstKernelInfo info{kernel_info}; + ort_ep_ = info.GetEp(); + ORT_ENFORCE(ort_ep_ != nullptr, "Plugin EP adapter requires a non-null OrtEp"); + ep_impl_ = static_cast(ort_ep_)->EpImpl(); + + const size_t input_count = info.GetInputCount(); + constant_input_tensors.resize(input_count); + for (size_t i = 0; i < input_count; ++i) { + int is_constant = 0; + Ort::ConstValue const_input = info.GetTensorConstantInput(gsl::narrow_cast(i), &is_constant); + if (is_constant && const_input != nullptr && const_input.IsTensor()) { + constant_input_tensors[i] = CreateTensorFromApiValue(const_cast(static_cast(const_input))); + } + } + } + const OrtKernelInfo* kernel_info_; + const OrtEp* ort_ep_{}; + const ::onnxruntime::IExecutionProvider* ep_impl_{}; + std::vector constant_input_tensors; + + mutable std::shared_mutex allocator_cache_mutex_; + mutable InlinedHashMap allocator_cache_; + + ORT_DISALLOW_COPY_ASSIGNMENT_AND_MOVE(KernelInfoCache); + }; + + explicit OpKernelInfo(const OrtKernelInfo* info) : info_(info), cache_{std::make_shared(info)} { + } + + const DataTransferManager& GetDataTransferManager() const noexcept { + return (static_cast(cache_->ort_ep_))->GetDataTransferManager(); + } + + AllocatorPtr GetAllocator(OrtMemType mem_type) const { + { + std::shared_lock lock(cache_->allocator_cache_mutex_); + auto it = cache_->allocator_cache_.find(mem_type); + if (it != cache_->allocator_cache_.end()) { + return it->second; + } + } + + std::unique_lock lock(cache_->allocator_cache_mutex_); + // Double-check after acquiring exclusive lock + auto it = cache_->allocator_cache_.find(mem_type); + if (it != cache_->allocator_cache_.end()) { + return it->second; + } + + OrtAllocator* ort_allocator_raw = nullptr; + Ort::Status status(Ort::GetApi().KernelInfoGetAllocator(cache_->kernel_info_, mem_type, &ort_allocator_raw)); + + if (!status.IsOK() || ort_allocator_raw == nullptr) { + cache_->allocator_cache_.emplace(mem_type, nullptr); + return nullptr; + } + + Ort::Allocator ort_allocator{ort_allocator_raw}; + auto allocator = std::make_shared(std::move(ort_allocator)); + cache_->allocator_cache_.emplace(mem_type, allocator); + return allocator; + } + + Node node() const noexcept { + return Node{cache_->kernel_info_}; + } + const IExecutionProvider* GetExecutionProvider() const noexcept { + return cache_->ep_impl_; + } + const OrtEp* GetOrtEp() const noexcept { + return cache_->ort_ep_; + } + + KernelDef GetKernelDef() const noexcept { + return KernelDef{cache_->kernel_info_}; + } + + const Ort::ConstKernelInfo GetKernelInfo() const noexcept { + return Ort::ConstKernelInfo{cache_->kernel_info_}; + } + + ConfigOptions GetConfigOptions() const noexcept { + ConfigOptions config_options; + config_options.configurations = info_.GetConfigEntries().GetKeyValuePairs(); + return config_options; + } + + int GetInputCount() const noexcept { + return gsl::narrow_cast(info_.GetInputCount()); + } + + const std::vector& GetConstantInputTensors() const noexcept { + return cache_->constant_input_tensors; + } + + bool TryGetConstantInput(int input_index, const Tensor** constant_input_value) const { + if (input_index < 0 || static_cast(input_index) >= cache_->constant_input_tensors.size()) { + return false; + } + const Tensor& tensor = cache_->constant_input_tensors[input_index]; + if (tensor.DataRaw() != nullptr) { + *constant_input_value = &tensor; + return true; + } + return false; + } + + template + [[nodiscard]] T GetAttrOrDefault(const std::string& name, const T& default_value) const { + T tmp; + return GetAttr(name, &tmp).IsOK() ? tmp : default_value; + } + template + void GetAttrOrDefault(const std::string& name, T* value, const T& default_value) const { + if (!GetAttr(name, value).IsOK()) + *value = default_value; + } + template + [[nodiscard]] T GetAttr(const std::string& name) const { + T value; + ORT_THROW_IF_ERROR(GetAttr(name, &value)); + return value; + } + template + Status GetAttr(const std::string& name, T* value) const { + try { + *value = info_.GetAttribute(name.c_str()); + return Status::OK(); + } catch (const Ort::Exception& ex) { + return Status(onnxruntime::common::ONNXRUNTIME, ex.GetOrtErrorCode(), ex.what()); + } + } + template + Status GetAttrs(const std::string& name, std::vector& values) const { + try { + values = info_.GetAttributes(name.c_str()); + return Status::OK(); + } catch (const Ort::Exception& ex) { + return Status(onnxruntime::common::ONNXRUNTIME, ex.GetOrtErrorCode(), ex.what()); + } + } + + Status GetAttrs(const std::string& name, TensorShapeVector& out) const { + std::vector shape; + Status status = GetAttrs(name, shape); + if (status.IsOK()) { + out.reserve(shape.size()); + out.assign(shape.begin(), shape.end()); + } + return status; + } + + template + [[nodiscard]] std::vector GetAttrsOrDefault(const std::string& name, + const std::vector& default_value = {}) const { + std::vector tmp; + return GetAttrs(name, tmp).IsOK() ? tmp : default_value; + } + [[nodiscard]] TensorShapeVector GetAttrsOrDefault(const std::string& name, + const TensorShapeVector& default_value = {}) const { + TensorShapeVector tmp; + return GetAttrs(name, tmp).IsOK() ? tmp : default_value; + } + + private: + const Ort::ConstKernelInfo info_; + std::shared_ptr cache_; +}; + +} // namespace adapter +} // namespace ep +} // namespace onnxruntime diff --git a/include/onnxruntime/ep/adapter/tensor_helper.h b/include/onnxruntime/ep/adapter/tensor_helper.h new file mode 100644 index 0000000000000..3a027926b3517 --- /dev/null +++ b/include/onnxruntime/ep/adapter/tensor_helper.h @@ -0,0 +1,52 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#if !defined(ORT_EP_API_ADAPTER_HEADER_INCLUDED) +#error "This header should not be included directly. Include ep/adapters.h instead." +#endif + +#include +#include + +#include "core/framework/tensor.h" + +namespace onnxruntime { +namespace ep { +namespace adapter { + +/// +/// Create an unowned onnxruntime::Tensor from a tensor OrtValue from C API. +/// +inline onnxruntime::Tensor CreateTensorFromApiValue(OrtValue* ort_value) { + Ort::UnownedValue value{ort_value}; + EP_ENFORCE(value.IsTensor(), "Only tensor OrtValue is supported."); + + ONNXTensorElementDataType element_type; + Ort::Value::Shape shape{}; + value.GetTensorElementTypeAndShapeDataReference(element_type, shape); + + auto memory_info = value.GetTensorMemoryInfo(); + MLDataType data_type = DataTypeImpl::TensorTypeFromONNXEnum(element_type)->GetElementType(); + + OrtMemoryInfo tensor_memory_info{memory_info.GetAllocatorName(), + memory_info.GetAllocatorType(), + OrtDevice{ + static_cast(memory_info.GetDeviceType()), + static_cast(memory_info.GetMemoryType()), + static_cast(memory_info.GetVendorId()), + static_cast(memory_info.GetDeviceId()), + + }, + memory_info.GetMemoryType()}; + + return Tensor(data_type, + TensorShape{shape.shape, shape.shape_len}, + value.GetTensorMutableRawData(), + tensor_memory_info); +} + +} // namespace adapter +} // namespace ep +} // namespace onnxruntime diff --git a/include/onnxruntime/ep/adapters.h b/include/onnxruntime/ep/adapters.h new file mode 100644 index 0000000000000..306f009ff01f7 --- /dev/null +++ b/include/onnxruntime/ep/adapters.h @@ -0,0 +1,69 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +// This header is only used when building WebGPU/CUDA EP as a plugin EP library. +// +// This header file is used as a precompiled header so it is always included first. + +#if !defined(ORT_USE_EP_API_ADAPTERS) +#error "This header should only be included when building with EP API adapters (i.e. plugin EP shared library). Please make sure ORT_USE_EP_API_ADAPTERS is defined." +#endif + +#include "api.h" +#include "common.h" + +#pragma push_macro("ORT_EP_API_ADAPTER_HEADER_INCLUDED") +#undef ORT_EP_API_ADAPTER_HEADER_INCLUDED +#define ORT_EP_API_ADAPTER_HEADER_INCLUDED + +#include "adapter/allocator.h" +#include "adapter/logging.h" +#include "adapter/ep.h" +#include "adapter/kernel_registry.h" + +#pragma pop_macro("ORT_EP_API_ADAPTER_HEADER_INCLUDED") + +// +// EP specific using declarations +// + +#define EP_SPECIFIC_USING_DECLARATIONS \ + using FuncManager = onnxruntime::ep::adapter::FuncManager; \ + using KernelCreatePtrFn = onnxruntime::ep::adapter::KernelCreatePtrFn; \ + using KernelDefBuilder = onnxruntime::ep::adapter::KernelDefBuilder; \ + using KernelRegistry = onnxruntime::ep::adapter::KernelRegistry; \ + using KernelCreateInfo = onnxruntime::ep::adapter::KernelCreateInfo; \ + using BuildKernelCreateInfoFn = onnxruntime::ep::adapter::KernelCreateInfo (*)(); \ + using OpKernelInfo = onnxruntime::ep::adapter::OpKernelInfo; \ + using OpKernelContext = onnxruntime::ep::adapter::OpKernelContext; \ + using OpKernel = onnxruntime::ep::adapter::OpKernel; \ + using DataTransferManager = onnxruntime::ep::adapter::DataTransferManager; \ + namespace logging { \ + using Logger = onnxruntime::ep::adapter::Logger; \ + using LoggingManager = onnxruntime::ep::adapter::LoggingManager; \ + } + +namespace onnxruntime { +namespace webgpu { +EP_SPECIFIC_USING_DECLARATIONS +} // namespace webgpu +namespace cuda { +EP_SPECIFIC_USING_DECLARATIONS +} // namespace cuda + +#ifndef DISABLE_CONTRIB_OPS +namespace contrib { +namespace webgpu { +EP_SPECIFIC_USING_DECLARATIONS +} // namespace webgpu +namespace cuda { +EP_SPECIFIC_USING_DECLARATIONS +} // namespace cuda +} // namespace contrib +#endif + +} // namespace onnxruntime + +#undef EP_SPECIFIC_USING_DECLARATIONS diff --git a/include/onnxruntime/ep/api.h b/include/onnxruntime/ep/api.h new file mode 100644 index 0000000000000..60f6b8613bb49 --- /dev/null +++ b/include/onnxruntime/ep/api.h @@ -0,0 +1,127 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include +#include +#include +#include + +#pragma push_macro("ORT_API_MANUAL_INIT") +#undef ORT_API_MANUAL_INIT +#define ORT_API_MANUAL_INIT +#include "onnxruntime_cxx_api.h" +#pragma pop_macro("ORT_API_MANUAL_INIT") + +namespace onnxruntime { +namespace ep { + +struct ApiPtrs { + ApiPtrs(const OrtApi& ort_, const OrtEpApi& ep_, const OrtModelEditorApi& model_editor_) + : ort(ort_), ep(ep_), model_editor(model_editor_) {} + const OrtApi& ort; + const OrtEpApi& ep; + const OrtModelEditorApi& model_editor; +}; + +namespace detail { +inline std::optional g_api_ptrs; + +inline bool TryGetAPIVersionFromVersionString(const char* version_str, uint32_t& api_version) { + // A valid version string should always be in the format of "1.{API_VERSION}.*". + if (!version_str || version_str[0] != '1' || version_str[1] != '.') { + return false; + } + const char* begin = version_str + 2; + const char* end = std::strchr(begin, '.'); + if (!end) { + return false; + } + uint32_t version = 0; + auto [ptr, ec] = std::from_chars(begin, end, version); + if (ec != std::errc{} || ptr != end) { + return false; + } + api_version = version; + return true; +} + +inline uint32_t g_current_ort_api_version{}; + +} // namespace detail + +/// +/// Get the global instance of ApiPtrs. +/// +inline const ApiPtrs& Api() { + if (!detail::g_api_ptrs.has_value()) { + throw std::logic_error("onnxruntime::ep::Api() called before ApiInit()."); + } + return *detail::g_api_ptrs; +} + +/// +/// Initialize the EP API pointers and global OrtEnv if not already done. +/// Thread-safe via std::call_once. +/// +inline void ApiInit(const OrtApiBase* ort_api_base) { + static std::once_flag init_flag; + std::call_once(init_flag, [&]() { + // The following initialization process is composed of 3 steps: + // 1) Get the ORT API version string + // 2) Try to parse the ORT API version from the version string. If parsing fails, we assume the version is 24. + // 3) Get the ORT API for the parsed version and initialize the global API instance with it. + constexpr uint32_t ORT_BASE_API_VERSION = 24; + const char* version_str = ort_api_base->GetVersionString(); + if (!version_str) { + version_str = "unknown"; + } + uint32_t current_ort_version = 0; + if (!detail::TryGetAPIVersionFromVersionString(version_str, current_ort_version)) { + // If we fail to parse the version string, we can still try to get the API for the base version and hope it works. + current_ort_version = ORT_BASE_API_VERSION; + } + if (current_ort_version < ORT_BASE_API_VERSION) { + throw std::runtime_error("Failed to initialize EP API: the minimum required ORT API version is " + std::to_string(ORT_BASE_API_VERSION) + + ", but the current version is \"" + version_str + + "\" (parsed API version: " + std::to_string(current_ort_version) + ")."); + } + + const OrtApi* ort_api = ort_api_base->GetApi(current_ort_version); + if (!ort_api) { + throw std::runtime_error("Failed to initialize EP API: the current ORT version is \"" + std::string(version_str) + + "\" but it does not support the parsed API version " + std::to_string(current_ort_version) + "."); + } + + detail::g_current_ort_api_version = current_ort_version; + + const OrtEpApi* ep_api = ort_api->GetEpApi(); + const OrtModelEditorApi* model_editor_api = ort_api->GetModelEditorApi(); + if (!ep_api || !model_editor_api) { + throw std::runtime_error("Failed to initialize EP API: GetEpApi or GetModelEditorApi returned null."); + } + + // Manual init for the C++ API + Ort::InitApi(ort_api); + + // Initialize the global API instance + detail::g_api_ptrs.emplace(*ort_api, *ep_api, *model_editor_api); + }); +} + +/// +/// Get the current ORT API version that the EP API has been initialized with. +/// +/// This function should be called after ApiInit() to get the actual API version. +/// +inline uint32_t CurrentOrtApiVersion() { + if (!detail::g_api_ptrs.has_value()) { + throw std::logic_error("onnxruntime::ep::CurrentOrtApiVersion() called before ApiInit()."); + } + return detail::g_current_ort_api_version; +} + +} // namespace ep +} // namespace onnxruntime diff --git a/include/onnxruntime/ep/common.h b/include/onnxruntime/ep/common.h new file mode 100644 index 0000000000000..0e779ba3d4081 --- /dev/null +++ b/include/onnxruntime/ep/common.h @@ -0,0 +1,64 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include + +#include "api.h" + +#define RETURN_IF_ERROR(fn) \ + do { \ + OrtStatus* _status = (fn); \ + if (_status != nullptr) { \ + return _status; \ + } \ + } while (0) + +#define RETURN_IF(cond, ort_api, msg) \ + do { \ + if ((cond)) { \ + return (ort_api).CreateStatus(ORT_EP_FAIL, (msg)); \ + } \ + } while (0) + +// see ORT_ENFORCE for implementations that also capture a stack trace and work in builds with exceptions disabled +// NOTE: In this simplistic implementation you must provide an argument, even it if's an empty string +#define EP_ENFORCE(condition, ...) \ + do { \ + if (!(condition)) { \ + std::ostringstream oss; \ + oss << "EP_ENFORCE failed: " << #condition << " "; \ + oss << __VA_ARGS__; \ + throw std::runtime_error(oss.str()); \ + } \ + } while (false) + +// Ignores an OrtStatus* while taking ownership of it so that it does not get leaked. +#define IGNORE_ORTSTATUS(status_expr) \ + do { \ + OrtStatus* _status = (status_expr); \ + Ort::Status _ignored{_status}; \ + } while (false) + +// Helper macros to convert exceptions to OrtStatus* return values. +// Usage: +// EXCEPTION_TO_RETURNED_STATUS_BEGIN +// ... code that may throw ... +// EXCEPTION_TO_RETURNED_STATUS_END +#define EXCEPTION_TO_RETURNED_STATUS_BEGIN try { +#define EXCEPTION_TO_RETURNED_STATUS_END \ + } \ + catch (const Ort::Exception& ex) { \ + Ort::Status status(ex); \ + return status.release(); \ + } \ + catch (const std::exception& ex) { \ + Ort::Status status(ex.what(), ORT_EP_FAIL); \ + return status.release(); \ + } \ + catch (...) { \ + Ort::Status status("Unknown exception", ORT_EP_FAIL); \ + return status.release(); \ + } diff --git a/include/onnxruntime/ep/get_capability_utils.h b/include/onnxruntime/ep/get_capability_utils.h new file mode 100644 index 0000000000000..ecfe0510e412a --- /dev/null +++ b/include/onnxruntime/ep/get_capability_utils.h @@ -0,0 +1,234 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include +#include +#include +#include + +namespace onnxruntime { +namespace ep { + +using NodeId = size_t; +constexpr int64_t kSmallInitializerThreshold = 100; + +constexpr inline bool MemTypeOnCpuExplicitly(OrtMemType mem_type) { + return mem_type == OrtMemTypeCPUInput || mem_type == OrtMemTypeCPUOutput; +} + +// Get all output nodes that consume an output from the given node. +inline std::vector GetOutputNodes(gsl::span node_outputs) { + std::vector output_nodes; + output_nodes.reserve(node_outputs.size()); // May have more + + // Gather the OrtNode consumers of every output. + for (Ort::ConstValueInfo output : node_outputs) { + if (output == nullptr) continue; // Skip missing optional output + + auto consumers_info = output.GetConsumers(); + for (const auto& consumer : consumers_info) { + output_nodes.push_back(consumer.node); + } + } + + return output_nodes; +} + +// Returns nodes that should be assigned to CPU EP instead of this example EP to avoid costly I/O copies. +// Based on GetCpuPreferredNodes from onnxruntime/core/framework/fallback_cpu_capability.cc +inline OrtStatus* GetCpuPreferredNodes(const OrtGraph& ort_graph, OrtEpGraphSupportInfo& graph_support_info, + const OrtLogger& logger, gsl::span tentative_nodes, + /*out*/ std::unordered_set& cpu_preferred_nodes) noexcept { + try { + const OrtApi& ort_api = Ort::GetApi(); + const OrtEpApi& ep_api = Ort::GetEpApi(); + Ort::ConstGraph graph{&ort_graph}; + std::vector ordered_nodes = graph.GetNodes(); + + if (ordered_nodes.empty()) { + return nullptr; + } + + std::unordered_map node_id_to_node; + std::unordered_map node_id_to_order_map; + for (size_t i = 0, num_nodes = ordered_nodes.size(); i < num_nodes; i++) { + NodeId node_id = ordered_nodes[i].GetId(); + node_id_to_node[node_id] = ordered_nodes[i]; + node_id_to_order_map[node_id] = i; + } + + // If return false, n1 will be output first; If return true, n2 will be output first + auto greater_order_comp = [&](const NodeId node_id1, const NodeId node_id2) { + return node_id_to_order_map[node_id1] > node_id_to_order_map[node_id2]; + }; + std::priority_queue, decltype(greater_order_comp)> candidates(greater_order_comp); + std::unordered_set cpu_output_args; + + std::unordered_set provider_nodes; + provider_nodes.reserve(tentative_nodes.size()); + + std::unordered_map node_to_kernel; + node_to_kernel.reserve(tentative_nodes.size()); + + for (const OrtNode* ort_node : tentative_nodes) { + Ort::ConstNode node(ort_node); + NodeId node_id = node.GetId(); + + provider_nodes.insert(node_id); + + // Expect at least one registry has a target provider's kernel for this node. + const OrtKernelDef* ort_kernel_def = nullptr; + RETURN_IF_ERROR(ep_api.EpGraphSupportInfo_LookUpKernel(&graph_support_info, node, &ort_kernel_def)); + RETURN_IF(ort_kernel_def == nullptr, ort_api, "Must have a registered kernel definition on the target EP"); + + Ort::ConstKernelDef kernel_def(ort_kernel_def); + node_to_kernel.insert({node_id, kernel_def}); + + // Find all the direct consumers of CPU tensors. + std::vector outputs = node.GetOutputs(); + for (size_t out_index = 0; out_index < outputs.size(); out_index++) { + Ort::ConstValueInfo output = outputs[out_index]; + if (output == nullptr) continue; // Skip missing optional output + + bool is_output_on_cpu = MemTypeOnCpuExplicitly(kernel_def.GetOutputMemType(out_index)); + if (is_output_on_cpu) { + cpu_output_args.insert(output); + + auto consumer_infos = output.GetConsumers(); + for (const auto& consumer_info : consumer_infos) { + candidates.push(consumer_info.node.GetId()); + ORT_CXX_LOGF(Ort::Logger(&logger), ORT_LOGGING_LEVEL_INFO, "Candidate for fallback CPU execution: %s\n", + consumer_info.node.GetName().c_str()); + } + } + } + } + + std::unordered_set visited; + visited.reserve(candidates.size()); + + std::unordered_set cpu_nodes; + cpu_nodes.reserve(candidates.size()); + + // The algo below is trying to identity a subgraph that only depends on cpu tensors. + // Usually it is a subgraph that doing shape calculation based on a GPU tensor, then reshape it back. + // The detail: + // for each candidate, if one of its input is a cpu tensor and the Non-CPU kernel doesn't mark it as cpu input, + // force the node to CPU to avoid memory cpu and add its output to the small cpu tensors. + while (!candidates.empty()) { + NodeId cur = candidates.top(); + candidates.pop(); + + auto p = visited.insert(cur); + if (!p.second) { + continue; + } + + auto node_iter = node_id_to_node.find(cur); + RETURN_IF(node_iter == node_id_to_node.end(), ort_api, "Unable to get OrtNode for a given node ID"); + Ort::ConstNode node = node_iter->second; + + if (provider_nodes.find(cur) == provider_nodes.end()) { + // Nodes not in provider_nodes are either have EP assigned or no kernel found on target EP. + // we assume these nodes will fallback to CPU, so add all direct consumers of all outputs to candidates. + std::string ep_name = node.GetEpName(); + if (ep_name.empty() || ep_name == "CPUExecutionProvider") { + std::vector outputs = node.GetOutputs(); + + for (Ort::ConstValueInfo output : outputs) { + if (output == nullptr) continue; // Skip missing optional output + cpu_output_args.insert(output); + } + + for (Ort::ConstNode downstream_node : GetOutputNodes(outputs)) { + candidates.push(downstream_node.GetId()); + } + } + continue; + } + + std::vector inputs = node.GetInputs(); + bool place_in_cpu = true; + + for (size_t i = 0; i < inputs.size(); i++) { + Ort::ConstValueInfo input = inputs[i]; + if (input == nullptr) continue; // Skip missing optional input + + // skip placing on CPU if the data types is float16 or bfloat16 or + // float8e4m3fn, float8e4m3fnuz, float8e5m2, float8e5m2fnuz or float4e2m1 + Ort::ConstTypeInfo type_info = input.TypeInfo(); + auto type_shape_info = type_info.GetTensorTypeAndShapeInfo(); + auto elem_type = type_shape_info.GetElementType(); + if (elem_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16 || + elem_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_BFLOAT16 || + elem_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT8E4M3FN || + elem_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT8E4M3FNUZ || + elem_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT8E5M2 || + elem_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT8E5M2FNUZ || + elem_type == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT4E2M1) { + place_in_cpu = false; + break; + } + + bool is_small_initializer = input.IsConstantInitializer() && + type_shape_info.GetElementCount() <= kSmallInitializerThreshold; + + // Allow placing on CPU if it's a small initializer or graph input + if (is_small_initializer || input.IsRequiredGraphInput() || input.IsOptionalGraphInput()) { + continue; + } + + // the input is not a CPU tensor + if (cpu_output_args.find(input) == cpu_output_args.end()) { + place_in_cpu = false; + break; + } + + // input is a CPU tensor, but it's intended to be consumed as CPU input by the target EP + bool is_input_on_cpu = MemTypeOnCpuExplicitly(node_to_kernel[cur].GetInputMemType(i)); + if (is_input_on_cpu) { + place_in_cpu = false; + break; + } + } + + if (place_in_cpu) { + cpu_nodes.insert(node); + ORT_CXX_LOGF(Ort::Logger(&logger), ORT_LOGGING_LEVEL_WARNING, + "EP optimization: Force fallback to CPU execution for node %s because the CPU execution path " + "is deemed faster than overhead involved with execution on other EPs capable of executing " + "this node.\n", + node.GetName().c_str()); + + std::vector outputs = node.GetOutputs(); + for (Ort::ConstValueInfo output : outputs) { + if (output == nullptr) continue; // Skip missing optional output + cpu_output_args.insert(output); + } + + for (Ort::ConstNode downstream_node : GetOutputNodes(outputs)) { + candidates.push(downstream_node.GetId()); + } + } + } + + cpu_preferred_nodes = std::move(cpu_nodes); + + return nullptr; + } catch (const Ort::Exception& ex) { + Ort::Status status(ex); + return status.release(); + } catch (const std::exception& ex) { + Ort::Status status(ex.what(), ORT_EP_FAIL); + return status.release(); + } catch (...) { + Ort::Status status("Unknown exception", ORT_EP_FAIL); + return status.release(); + } +} + +} // namespace ep +} // namespace onnxruntime diff --git a/java/build-android.gradle b/java/build-android.gradle index 9c4275b74f626..610625cf02e54 100644 --- a/java/build-android.gradle +++ b/java/build-android.gradle @@ -147,7 +147,7 @@ artifacts { dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-api:5.7.0' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.7.0' - testImplementation 'com.google.protobuf:protobuf-java:3.21.7' + testImplementation 'com.google.protobuf:protobuf-java:3.25.5' } publishing { diff --git a/java/build.gradle b/java/build.gradle index 845121dd17a48..0bae81fe52901 100644 --- a/java/build.gradle +++ b/java/build.gradle @@ -3,8 +3,7 @@ plugins { id 'maven-publish' id 'signing' id 'jacoco' - id "com.diffplug.spotless" version "6.25.0" - id "net.linguica.maven-settings" version "0.5" + id "com.diffplug.spotless" version "7.2.1" } allprojects { @@ -14,17 +13,9 @@ allprojects { } project.group = "com.microsoft.onnxruntime" -version = rootProject.file('../VERSION_NUMBER').text.trim() - // cmake runs will inform us of the build directory of the current run def cmakeBuildDir = System.properties['cmakeBuildDir'] def useCUDA = System.properties['USE_CUDA'] -def useROCM = System.properties['USE_ROCM'] - -def adoArtifact = project.findProperty('adoArtifact') -def adoAccessToken = project.findProperty('adoAccessToken') -// Only publish to ADO feed if all two properties are set -def publishToAdo = adoArtifact != null && adoAccessToken != null boolean enableTrainingApis = (System.properties['ENABLE_TRAINING_APIS'] ?: "0") == "1" def cmakeJavaDir = "${cmakeBuildDir}/java" @@ -33,21 +24,14 @@ def cmakeNativeJniDir = "${cmakeJavaDir}/native-jni" def cmakeNativeTestDir = "${cmakeJavaDir}/native-test" def cmakeBuildOutputDir = "${cmakeJavaDir}/build" -def mavenUser = System.properties['mavenUser'] -def mavenPwd = System.properties['mavenPwd'] - def tmpArtifactId = enableTrainingApis ? project.name + "-training" : project.name -def mavenArtifactId = (useCUDA == null && useROCM == null) ? tmpArtifactId : tmpArtifactId + "_gpu" +def mavenArtifactId = (useCUDA == null) ? tmpArtifactId : tmpArtifactId + "_gpu" def defaultDescription = 'ONNX Runtime is a performance-focused inference engine for ONNX (Open Neural Network Exchange) models.' def trainingDescription = 'ONNX Runtime Training is a training and inference package for ONNX ' + '(Open Neural Network Exchange) models. This package is targeted for Learning on The Edge aka On-Device Training ' + 'See https://github.com/microsoft/onnxruntime-training-examples/tree/master/on_device_training for more details.' -// We need to have a custom settings.xml so codeql can bypass the need for settings.security.xml -mavenSettings { - userSettingsFileName = "${projectDir}/settings.xml" -} java { sourceCompatibility = JavaVersion.VERSION_17 @@ -179,7 +163,7 @@ if (cmakeBuildDir != null) { dependencies { testImplementation 'org.junit.jupiter:junit-jupiter-api:5.9.2' testRuntimeOnly 'org.junit.jupiter:junit-jupiter-engine:5.9.2' - testImplementation 'com.google.protobuf:protobuf-java:3.21.7' + testImplementation 'com.google.protobuf:protobuf-java:3.25.5' } processTestResources { @@ -202,14 +186,25 @@ test { systemProperties System.getProperties().subMap([ 'ENABLE_TRAINING_APIS', 'JAVA_FULL_TEST', + 'USE_ACL', + 'USE_AZURE', + 'USE_CANN', 'USE_COREML', 'USE_CUDA', 'USE_DML', 'USE_DNNL', + 'USE_MIGRAPHX', + 'USE_NNAPI', + 'USE_NV', 'USE_OPENVINO', - 'USE_ROCM', - 'USE_TENSORRT', 'USE_QNN', + 'USE_RKNPU', + 'USE_SNPE', + 'USE_TENSORRT', + 'USE_VITISAI', + 'USE_VSINPU', + 'USE_WEBGPU', + 'USE_WEBNN', 'USE_XNNPACK', ]) testLogging { @@ -232,13 +227,9 @@ publishing { publications { maven(MavenPublication) { groupId = project.group - if(publishToAdo) { - artifactId = 'onnxruntime_gpu' - artifact (adoArtifact) - } else { - artifactId = mavenArtifactId - from components.java - } + artifactId = mavenArtifactId + from components.java + version = project.version pom { name = enableTrainingApis ? 'onnxruntime-training' : 'onnx-runtime' @@ -269,29 +260,6 @@ publishing { } } } - repositories { - if (publishToAdo) { - maven { - url "https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/${System.getenv('ADOFeedName')}/maven/v1" - name System.getenv('ADOFeedName') - authentication { - basic(BasicAuthentication) - } - credentials { - username 'aiinfra' - password "${project.findProperty('adoAccessToken')}" - } - } - } else { - maven { - url 'https://oss.sonatype.org/service/local/staging/deploy/maven2/' - credentials { - username mavenUser - password mavenPwd - } - } - } - } } // Generates a task signMavenPublication that will // build all artifacts. @@ -299,12 +267,17 @@ signing { // Queries env vars: // ORG_GRADLE_PROJECT_signingKey // ORG_GRADLE_PROJECT_signingPassword but can be changed to properties - def signingKey = findProperty("signingKey") - def signingPassword = findProperty("signingPassword") - // Skip signing if no key is provided - if (signingKey != null && signingPassword != null) { - useInMemoryPgpKeys(signingKey, signingPassword) - sign publishing.publications.maven - sign publishing.publications.mavenAdo - } + def signingKey = findProperty("signingKey") + def signingPassword = findProperty("signingPassword") + // Skip signing if no key is provided + if (signingKey != null && signingPassword != null) { + useInMemoryPgpKeys(signingKey, signingPassword) + sign publishing.publications.maven + } +} + +tasks.named('generatePomFileForMavenPublication') { + doFirst { + println "AGENT_LOG: Generating POM for version: ${project.version}" + } } diff --git a/java/src/main/java/ai/onnxruntime/OnnxRuntime.java b/java/src/main/java/ai/onnxruntime/OnnxRuntime.java index c28c79f1e723e..0a1b6ca45f65b 100644 --- a/java/src/main/java/ai/onnxruntime/OnnxRuntime.java +++ b/java/src/main/java/ai/onnxruntime/OnnxRuntime.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * Licensed under the MIT License. */ package ai.onnxruntime; @@ -42,6 +42,8 @@ final class OnnxRuntime { private static final int ORT_API_VERSION_13 = 13; // Post 1.13 builds of the ORT API private static final int ORT_API_VERSION_14 = 14; + // Post 1.22 builds of the ORT API + private static final int ORT_API_VERSION_23 = 23; // The initial release of the ORT training API. private static final int ORT_TRAINING_API_VERSION_1 = 1; @@ -79,6 +81,15 @@ final class OnnxRuntime { /** The short name of the ONNX runtime QNN provider library */ static final String ONNXRUNTIME_LIBRARY_QNN_NAME = "onnxruntime_providers_qnn"; + /** The short name of the WebGPU DAWN library */ + static final String ONNXRUNTIME_LIBRARY_WEBGPU_DAWN_NAME = "webgpu_dawn"; + + /** The short name of the WebGPU DXC library "dxil.dll" */ + static final String ONNXRUNTIME_LIBRARY_WEBGPU_DXC_DXIL_NAME = "dxil"; + + /** The short name of the WebGPU DXC library "dxcompiler.dll" */ + static final String ONNXRUNTIME_LIBRARY_WEBGPU_DXC_DXCOMPILER_NAME = "dxcompiler"; + /** The OS & CPU architecture string */ private static final String OS_ARCH_STR = initOsArch(); @@ -100,6 +111,9 @@ final class OnnxRuntime { /** The Training API handle. */ static long ortTrainingApiHandle; + /** The Compile API handle. */ + static long ortCompileApiHandle; + /** Is training enabled in the native library */ static boolean trainingEnabled; @@ -137,6 +151,8 @@ private static String initOsArch() { detectedArch = "aarch64"; } else if (arch.startsWith("ppc64")) { detectedArch = "ppc64"; + } else if (arch.startsWith("loongarch64")) { + detectedArch = "loongarch64"; } else if (isAndroid()) { detectedArch = arch; } else { @@ -162,17 +178,24 @@ static synchronized void init() throws IOException { // the ONNX Runtime native library will load it extractProviderLibrary(ONNXRUNTIME_LIBRARY_SHARED_NAME); + // Extract and prepare the Dawn shared libraries (if present) but don't try to load them, + // the ONNX Runtime native library will load them + extractProviderLibrary(ONNXRUNTIME_LIBRARY_WEBGPU_DAWN_NAME); + extractProviderLibrary(ONNXRUNTIME_LIBRARY_WEBGPU_DXC_DXIL_NAME); + extractProviderLibrary(ONNXRUNTIME_LIBRARY_WEBGPU_DXC_DXCOMPILER_NAME); + if (!isAndroid()) { load(ONNXRUNTIME_LIBRARY_NAME); } load(ONNXRUNTIME_JNI_LIBRARY_NAME); - ortApiHandle = initialiseAPIBase(ORT_API_VERSION_14); + ortApiHandle = initialiseAPIBase(ORT_API_VERSION_23); if (ortApiHandle == 0L) { throw new IllegalStateException( "There is a mismatch between the ORT class files and the ORT native library, and the native library could not be loaded"); } - ortTrainingApiHandle = initialiseTrainingAPIBase(ortApiHandle, ORT_API_VERSION_14); + ortTrainingApiHandle = initialiseTrainingAPIBase(ortApiHandle, ORT_API_VERSION_23); + ortCompileApiHandle = initialiseCompileAPIBase(ortApiHandle); trainingEnabled = ortTrainingApiHandle != 0L; providers = initialiseProviders(ortApiHandle); version = initialiseVersion(); @@ -284,26 +307,22 @@ static synchronized boolean extractProviderLibrary(String libraryName) { if (extractedSharedProviders.contains(libraryName)) { return true; } - // Otherwise extract the file from the classpath resources + // If a native library directory is configured, prefer it and skip extraction when present. + if (libraryDirPathProperty != null) { + String libraryFileName = mapLibraryName(libraryName); + File libraryFile = Paths.get(libraryDirPathProperty, libraryFileName).toFile(); + if (libraryFile.exists()) { + extractedSharedProviders.add(libraryName); + return true; + } + } + // Otherwise extract the file from the classpath resources. Optional file = extractFromResources(libraryName); if (file.isPresent()) { extractedSharedProviders.add(libraryName); return true; } else { - // If we failed to extract it, check if there is a valid cache directory - // that contains it - if (libraryDirPathProperty != null) { - String libraryFileName = mapLibraryName(libraryName); - File libraryFile = Paths.get(libraryDirPathProperty, libraryFileName).toFile(); - if (libraryFile.exists()) { - extractedSharedProviders.add(libraryName); - return true; - } else { - return false; - } - } else { - return false; - } + return false; } } @@ -490,6 +509,14 @@ private static EnumSet initialiseProviders(long ortApiHandle) { */ private static native long initialiseTrainingAPIBase(long apiHandle, int apiVersionNumber); + /** + * Get a reference to the compile API struct. + * + * @param apiHandle The ORT API struct pointer. + * @return A pointer to the compile API struct. + */ + private static native long initialiseCompileAPIBase(long apiHandle); + /** * Gets the array of available providers. * diff --git a/java/src/main/java/ai/onnxruntime/OnnxSparseTensor.java b/java/src/main/java/ai/onnxruntime/OnnxSparseTensor.java index 8400ef53ff6d7..3901df19d0570 100644 --- a/java/src/main/java/ai/onnxruntime/OnnxSparseTensor.java +++ b/java/src/main/java/ai/onnxruntime/OnnxSparseTensor.java @@ -927,7 +927,7 @@ public BlockSparseTensor( } if (indicesShape.length < 2) { throw new IllegalArgumentException( - "Expected [numBlocks, co-ordinates] or larger, but indices shape was " + "Expected [numBlocks, coordinates] or larger, but indices shape was " + Arrays.toString(indicesShape)); } } diff --git a/java/src/main/java/ai/onnxruntime/OrtEnvironment.java b/java/src/main/java/ai/onnxruntime/OrtEnvironment.java index 8382ef06e26e5..2a9d4876c4c1a 100644 --- a/java/src/main/java/ai/onnxruntime/OrtEnvironment.java +++ b/java/src/main/java/ai/onnxruntime/OrtEnvironment.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved. * Licensed under the MIT License. */ package ai.onnxruntime; @@ -8,7 +8,11 @@ import ai.onnxruntime.OrtTrainingSession.OrtCheckpointState; import java.io.IOException; import java.nio.ByteBuffer; +import java.util.ArrayList; +import java.util.Collections; import java.util.EnumSet; +import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.logging.Logger; @@ -442,6 +446,72 @@ public static EnumSet getAvailableProviders() { return OnnxRuntime.providers.clone(); } + /** + * Registers an execution provider library with this OrtEnvironment. + * + * @param registrationName The name to register the library with (used to remove it later with + * {@link #unregisterExecutionProviderLibrary(String)}). + * @param libraryPath The path to the library binary on disk. + * @throws OrtException If the library could not be registered. + */ + public void registerExecutionProviderLibrary(String registrationName, String libraryPath) + throws OrtException { + registerExecutionProviderLibrary( + OnnxRuntime.ortApiHandle, nativeHandle, registrationName, libraryPath); + } + + /** + * Unregisters an execution provider library from this OrtEnvironment. + * + * @param registrationName The name the library was registered under. + * @throws OrtException If the library could not be removed. + */ + public void unregisterExecutionProviderLibrary(String registrationName) throws OrtException { + unregisterExecutionProviderLibrary(OnnxRuntime.ortApiHandle, nativeHandle, registrationName); + } + + /** + * Get the list of all execution provider and device combinations that are available. + * + * @see OrtSession.SessionOptions#addExecutionProvider(List, Map) + * @return The list of execution provider and device combinations. + * @throws OrtException If the devices could not be listed. + */ + public List getEpDevices() throws OrtException { + long[] deviceHandles = getEpDevices(OnnxRuntime.ortApiHandle, nativeHandle); + + List devicesList = new ArrayList<>(); + for (long deviceHandle : deviceHandles) { + devicesList.add(new OrtEpDevice(deviceHandle)); + } + + return Collections.unmodifiableList(devicesList); + } + + /** + * Checks the supplied model info string against the list of {@link OrtEpDevice}s to see if the + * model is compatible. + * + * @param epDevices The EP-Device tuples to use. + * @param modelInfo The model info string to check. + * @return The model compatibility. + * @throws OrtException If the call failed. + */ + public OrtCompiledModelCompatibility getModelCompatibilityForEpDevices( + List epDevices, String modelInfo) throws OrtException { + if (epDevices == null || epDevices.isEmpty()) { + throw new IllegalArgumentException("Must supply at least one OrtEpDevice"); + } + long[] deviceHandles = new long[epDevices.size()]; + for (int i = 0; i < epDevices.size(); i++) { + deviceHandles[i] = epDevices.get(i).getNativeHandle(); + } + + int output = + getModelCompatibilityForEpDevices(OnnxRuntime.ortApiHandle, deviceHandles, modelInfo); + return OrtCompiledModelCompatibility.mapFromInt(output); + } + /** * Creates the native object. * @@ -476,6 +546,52 @@ private static native long createHandle( */ private static native long getDefaultAllocator(long apiHandle) throws OrtException; + /** + * Registers the specified execution provider with this OrtEnvironment. + * + * @param apiHandle The API handle. + * @param nativeHandle The OrtEnvironment handle. + * @param registrationName The name of the execution provider. + * @param libraryPath The path to the execution provider binary. + * @throws OrtException If the registration failed. + */ + private static native void registerExecutionProviderLibrary( + long apiHandle, long nativeHandle, String registrationName, String libraryPath) + throws OrtException; + + /** + * Removes the specified execution provider from this OrtEnvironment. + * + * @param apiHandle The API handle. + * @param nativeHandle The OrtEnvironment handle. + * @param registrationName The name of the execution provider. + * @throws OrtException If the removal failed. + */ + private static native void unregisterExecutionProviderLibrary( + long apiHandle, long nativeHandle, String registrationName) throws OrtException; + + /** + * Gets handles for the EP device tuples available in this OrtEnvironment. + * + * @param apiHandle The API handle to use. + * @param nativeHandle The OrtEnvironment handle. + * @return An array of OrtEpDevice handles. + * @throws OrtException If the call failed. + */ + private static native long[] getEpDevices(long apiHandle, long nativeHandle) throws OrtException; + + /** + * Checks if a model is compatible with the supplied list of EP device handles. + * + * @param apiHandle The API handle to use. + * @param epHandles An array of OrtEpDevice handles. + * @param modelInfo The model info string. + * @return An int representing the {@link OrtCompiledModelCompatibility} value. + * @throws OrtException If the call failed. + */ + private static native int getModelCompatibilityForEpDevices( + long apiHandle, long[] epHandles, String modelInfo) throws OrtException; + /** * Closes the OrtEnvironment, frees the handle. * @@ -500,6 +616,59 @@ private static native void setTelemetry(long apiHandle, long nativeHandle, boole @Override public void close() {} + /** Enum representing a compiled model's compatibility with a set of {@link OrtEpDevice}s. */ + public enum OrtCompiledModelCompatibility { + /** The EP is not applicable for the model. */ + EP_NOT_APPLICABLE(0), + /** The EP supports the model optimally. */ + EP_SUPPORTED_OPTIMAL(1), + /** The EP supports the model, but the model would perform better if recompiled. */ + EP_SUPPORTED_PREFER_RECOMPILATION(2), + /** The EP does not support the model. */ + EP_UNSUPPORTED(3); + + private final int value; + + private static final Logger logger = + Logger.getLogger(OrtCompiledModelCompatibility.class.getName()); + private static final OrtCompiledModelCompatibility[] values = + new OrtCompiledModelCompatibility[4]; + + static { + for (OrtCompiledModelCompatibility ot : OrtCompiledModelCompatibility.values()) { + values[ot.value] = ot; + } + } + + OrtCompiledModelCompatibility(int value) { + this.value = value; + } + + /** + * Gets the native value associated with this model compatibility value. + * + * @return The native value. + */ + public int getValue() { + return value; + } + + /** + * Maps from the C API's int enum to the Java enum. + * + * @param logLevel The index of the Java enum. + * @return The Java enum. + */ + public static OrtCompiledModelCompatibility mapFromInt(int logLevel) { + if ((logLevel >= 0) && (logLevel < values.length)) { + return values[logLevel]; + } else { + logger.warning("Unknown model compatibility " + logLevel + " setting to EP_UNSUPPORTED"); + return EP_UNSUPPORTED; + } + } + } + /** * Controls the global thread pools in the environment. Only used if the session is constructed * using an options with {@link OrtSession.SessionOptions#disablePerSessionThreads()} set. diff --git a/java/src/main/java/ai/onnxruntime/OrtEpDevice.java b/java/src/main/java/ai/onnxruntime/OrtEpDevice.java new file mode 100644 index 0000000000000..338c907fc81da --- /dev/null +++ b/java/src/main/java/ai/onnxruntime/OrtEpDevice.java @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Licensed under the MIT License. + */ +package ai.onnxruntime; + +import java.util.Map; + +/** A tuple of Execution Provider information and the hardware device. */ +public final class OrtEpDevice { + + private final long nativeHandle; + + private final String epName; + private final String epVendor; + private final Map epMetadata; + private final Map epOptions; + private final OrtHardwareDevice device; + + /** + * Construct an OrtEpDevice tuple from the native pointer. + * + * @param nativeHandle The native pointer. + */ + OrtEpDevice(long nativeHandle) { + this.nativeHandle = nativeHandle; + this.epName = getEpName(OnnxRuntime.ortApiHandle, nativeHandle); + this.epVendor = getEpVendor(OnnxRuntime.ortApiHandle, nativeHandle); + String[][] metadata = getEpMetadata(OnnxRuntime.ortApiHandle, nativeHandle); + this.epMetadata = OrtUtil.convertToMap(metadata); + String[][] options = getEpOptions(OnnxRuntime.ortApiHandle, nativeHandle); + this.epOptions = OrtUtil.convertToMap(options); + this.device = new OrtHardwareDevice(getDeviceHandle(OnnxRuntime.ortApiHandle, nativeHandle)); + } + + /** + * Return the native pointer. + * + * @return The native pointer. + */ + long getNativeHandle() { + return nativeHandle; + } + + /** + * Gets the Execution Provider name. + * + * @return The EP name. + */ + public String getEpName() { + return epName; + } + + /** + * Gets the Execution Provider vendor name. + * + * @return The EP vendor name. + */ + public String getEpVendor() { + return epVendor; + } + + /** + * Gets an unmodifiable view on the Execution Provider metadata. + * + * @return The EP metadata. + */ + public Map getEpMetadata() { + return epMetadata; + } + + /** + * Gets an unmodifiable view on the Execution Provider options. + * + * @return The EP options. + */ + public Map getEpOptions() { + return epOptions; + } + + /** + * Gets the device information. + * + * @return The device information. + */ + public OrtHardwareDevice getDevice() { + return device; + } + + @Override + public String toString() { + return "OrtEpDevice{" + + "epName='" + + epName + + '\'' + + ", epVendor='" + + epVendor + + '\'' + + ", epMetadata=" + + epMetadata + + ", epOptions=" + + epOptions + + ", device=" + + device + + '}'; + } + + private static native String getEpName(long apiHandle, long nativeHandle); + + private static native String getEpVendor(long apiHandle, long nativeHandle); + + private static native String[][] getEpMetadata(long apiHandle, long nativeHandle); + + private static native String[][] getEpOptions(long apiHandle, long nativeHandle); + + private static native long getDeviceHandle(long apiHandle, long nativeHandle); +} diff --git a/java/src/main/java/ai/onnxruntime/OrtException.java b/java/src/main/java/ai/onnxruntime/OrtException.java index 5ec58ea137124..06c3d3cbc770c 100644 --- a/java/src/main/java/ai/onnxruntime/OrtException.java +++ b/java/src/main/java/ai/onnxruntime/OrtException.java @@ -81,11 +81,17 @@ public enum OrtErrorCode { /** The ONNX graph is invalid. */ ORT_INVALID_GRAPH(10), /** The ORT execution provider failed. */ - ORT_EP_FAIL(11); + ORT_EP_FAIL(11), + /** Model load was canceled. */ + ORT_MODEL_LOAD_CANCELED(12), + /** Model requires compilation. */ + ORT_MODEL_REQUIRES_COMPILATION(13), + /** Item was not found. */ + ORT_NOT_FOUND(14); private final int value; - private static final OrtErrorCode[] values = new OrtErrorCode[12]; + private static final OrtErrorCode[] values = new OrtErrorCode[15]; static { for (OrtErrorCode ot : OrtErrorCode.values()) { diff --git a/java/src/main/java/ai/onnxruntime/providers/OrtFlags.java b/java/src/main/java/ai/onnxruntime/OrtFlags.java similarity index 88% rename from java/src/main/java/ai/onnxruntime/providers/OrtFlags.java rename to java/src/main/java/ai/onnxruntime/OrtFlags.java index 73d3eeae6499c..f57fd945dbeec 100644 --- a/java/src/main/java/ai/onnxruntime/providers/OrtFlags.java +++ b/java/src/main/java/ai/onnxruntime/OrtFlags.java @@ -1,8 +1,8 @@ /* - * Copyright (c) 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. * Licensed under the MIT License. */ -package ai.onnxruntime.providers; +package ai.onnxruntime; import java.util.EnumSet; diff --git a/java/src/main/java/ai/onnxruntime/OrtHardwareDevice.java b/java/src/main/java/ai/onnxruntime/OrtHardwareDevice.java new file mode 100644 index 0000000000000..bd99f5599fd14 --- /dev/null +++ b/java/src/main/java/ai/onnxruntime/OrtHardwareDevice.java @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Licensed under the MIT License. + */ +package ai.onnxruntime; + +import java.util.Map; +import java.util.logging.Logger; + +/** Hardware information for a specific device. */ +public final class OrtHardwareDevice { + + /** The hardware device types. */ + // Must be updated in concert with the native OrtHardwareDeviceType enum in the C API + public enum OrtHardwareDeviceType { + /** A CPU device. */ + CPU(0), + /** A GPU device. */ + GPU(1), + /** A NPU (Neural Processing Unit) device. */ + NPU(2); + private final int value; + + private static final Logger logger = Logger.getLogger(OrtHardwareDeviceType.class.getName()); + private static final OrtHardwareDeviceType[] values = new OrtHardwareDeviceType[3]; + + static { + for (OrtHardwareDeviceType ot : OrtHardwareDeviceType.values()) { + values[ot.value] = ot; + } + } + + OrtHardwareDeviceType(int value) { + this.value = value; + } + + /** + * Gets the native value associated with this device type. + * + * @return The native value. + */ + public int getValue() { + return value; + } + + /** + * Maps from the C API's int enum to the Java enum. + * + * @param deviceType The index of the Java enum. + * @return The Java enum. + */ + public static OrtHardwareDeviceType mapFromInt(int deviceType) { + if ((deviceType >= 0) && (deviceType < values.length)) { + return values[deviceType]; + } else { + logger.warning("Unknown device type '" + deviceType + "' setting to CPU"); + return CPU; + } + } + } + + private final long nativeHandle; + + private final OrtHardwareDeviceType type; + private final int vendorId; + private final String vendor; + private final int deviceId; + private final Map metadata; + + OrtHardwareDevice(long nativeHandle) { + this.nativeHandle = nativeHandle; + this.type = + OrtHardwareDeviceType.mapFromInt(getDeviceType(OnnxRuntime.ortApiHandle, nativeHandle)); + this.vendorId = getVendorId(OnnxRuntime.ortApiHandle, nativeHandle); + this.vendor = getVendor(OnnxRuntime.ortApiHandle, nativeHandle); + this.deviceId = getDeviceId(OnnxRuntime.ortApiHandle, nativeHandle); + String[][] metadata = getMetadata(OnnxRuntime.ortApiHandle, nativeHandle); + this.metadata = OrtUtil.convertToMap(metadata); + } + + long getNativeHandle() { + return nativeHandle; + } + + /** + * Gets the device type. + * + * @return The device type. + */ + public OrtHardwareDeviceType getType() { + return type; + } + + /** + * Gets the vendor ID number. + * + * @return The vendor ID number. + */ + public int getVendorId() { + return vendorId; + } + + /** + * Gets the device ID number. + * + * @return The device ID number. + */ + public int getDeviceId() { + return deviceId; + } + + /** + * Gets an unmodifiable view on the device metadata. + * + * @return The device metadata. + */ + public Map getMetadata() { + return metadata; + } + + /** + * Gets the vendor name. + * + * @return The vendor name. + */ + public String getVendor() { + return vendor; + } + + @Override + public String toString() { + return "OrtHardwareDevice{" + + "type=" + + type + + ", vendorId=" + + vendorId + + ", vendor='" + + vendor + + '\'' + + ", deviceId=" + + deviceId + + ", metadata=" + + metadata + + '}'; + } + + private static native String getVendor(long apiHandle, long nativeHandle); + + private static native String[][] getMetadata(long apiHandle, long nativeHandle); + + private static native int getDeviceType(long apiHandle, long nativeHandle); + + private static native int getDeviceId(long apiHandle, long nativeHandle); + + private static native int getVendorId(long apiHandle, long nativeHandle); +} diff --git a/java/src/main/java/ai/onnxruntime/OrtModelCompilationOptions.java b/java/src/main/java/ai/onnxruntime/OrtModelCompilationOptions.java new file mode 100644 index 0000000000000..09b3064b72b93 --- /dev/null +++ b/java/src/main/java/ai/onnxruntime/OrtModelCompilationOptions.java @@ -0,0 +1,280 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Licensed under the MIT License. + */ +package ai.onnxruntime; + +import java.nio.ByteBuffer; +import java.util.EnumSet; + +/** Configuration options for compiling ONNX models. */ +public final class OrtModelCompilationOptions implements AutoCloseable { + /** Flags representing options when compiling a model. */ + public enum OrtCompileApiFlags implements OrtFlags { + /** Default. Do not enable any additional compilation options. */ + NONE(0), + + /** + * Force compilation to return an error (ORT_FAIL) if no nodes were compiled. Otherwise, a model + * with basic optimizations (ORT_ENABLE_BASIC) is still generated by default. + */ + ERROR_IF_NO_NODES_COMPILED(1), + + /** + * Force compilation to return an error (ORT_FAIL) if a file with the same filename as the + * output model exists. Otherwise, compilation will automatically overwrite the output file if + * it exists. + */ + ERROR_IF_OUTPUT_FILE_EXISTS(1 << 1); + + /** The native value of the enum. */ + public final int value; + + OrtCompileApiFlags(int value) { + this.value = value; + } + + @Override + public int getValue() { + return value; + } + } + + private final long nativeHandle; + private boolean closed = false; + + // Used to ensure the byte buffer doesn't get GC'd before the model is compiled. + private ByteBuffer buffer; + + OrtModelCompilationOptions(long nativeHandle) { + this.nativeHandle = nativeHandle; + } + + /** + * Creates a model compilation options from an existing SessionOptions. + * + *

An OrtModelCompilationOptions object contains the settings used to generate a compiled ONNX + * model. The OrtSessionOptions object has the execution providers with which the model will be + * compiled. + * + * @param env The OrtEnvironment. + * @param sessionOptions The session options to use. + * @return A constructed model compilation options instance. + * @throws OrtException If the construction failed. + */ + public static OrtModelCompilationOptions createFromSessionOptions( + OrtEnvironment env, OrtSession.SessionOptions sessionOptions) throws OrtException { + long handle = + createFromSessionOptions( + OnnxRuntime.ortApiHandle, + OnnxRuntime.ortCompileApiHandle, + env.getNativeHandle(), + sessionOptions.getNativeHandle()); + return new OrtModelCompilationOptions(handle); + } + + /** + * Checks if the OrtModelCompilationOptions is closed, if so throws {@link IllegalStateException}. + */ + private void checkClosed() { + if (closed) { + throw new IllegalStateException("Trying to use a closed OrtModelCompilationOptions."); + } + } + + @Override + public void close() { + if (!closed) { + close(OnnxRuntime.ortCompileApiHandle, nativeHandle); + closed = true; + } else { + throw new IllegalStateException("Trying to close a closed OrtModelCompilationOptions."); + } + } + + /** + * Sets the file path to the input ONNX model. + * + *

The input model's location must be set either to a path on disk with this method, or by + * supplying an in-memory reference with {@link #setInputModelFromBuffer}. + * + * @param inputModelPath The path to the model on disk. + * @throws OrtException If the set failed. + */ + public void setInputModelPath(String inputModelPath) throws OrtException { + checkClosed(); + setInputModelPath( + OnnxRuntime.ortApiHandle, OnnxRuntime.ortCompileApiHandle, nativeHandle, inputModelPath); + } + + /** + * Uses the supplied buffer as the input ONNX model. + * + *

The input model's location must be set either to an in-memory reference with this method, or + * by supplying a path on disk with {@link #setInputModelPath(String)}. + * + *

If the {@link ByteBuffer} is not direct it is copied into a direct buffer. In either case + * this object holds a reference to the buffer to prevent it from being GC'd. + * + * @param inputModelBuffer The buffer. + * @throws OrtException If the buffer could not be set. + */ + public void setInputModelFromBuffer(ByteBuffer inputModelBuffer) throws OrtException { + checkClosed(); + if (!inputModelBuffer.isDirect()) { + // if it's not a direct buffer, copy it. + buffer = ByteBuffer.allocateDirect(inputModelBuffer.remaining()); + int tmpPos = inputModelBuffer.position(); + buffer.put(inputModelBuffer); + buffer.rewind(); + inputModelBuffer.position(tmpPos); + } else { + buffer = inputModelBuffer; + } + int bufferPos = buffer.position(); + int bufferRemaining = buffer.remaining(); + setInputModelFromBuffer( + OnnxRuntime.ortApiHandle, + OnnxRuntime.ortCompileApiHandle, + nativeHandle, + buffer, + bufferPos, + bufferRemaining); + } + + /** + * Sets the file path for the output compiled ONNX model. + * + *

If this is unset it will append `_ctx` to the file name, e.g., my_model.onnx becomes + * my_model_ctx.onnx. + * + * @param outputModelPath The output model path. + * @throws OrtException If the path could not be set. + */ + public void setOutputModelPath(String outputModelPath) throws OrtException { + checkClosed(); + setOutputModelPath( + OnnxRuntime.ortApiHandle, OnnxRuntime.ortCompileApiHandle, nativeHandle, outputModelPath); + } + + /** + * Optionally sets the file that stores initializers for the compiled ONNX model. If unset then + * initializers are stored inside the model. + * + *

Only initializers for nodes that were not compiled are stored in the external initializers + * file. Compiled nodes contain their initializer data within the `ep_cache_context` attribute of + * EPContext nodes. + * + * @see OrtModelCompilationOptions#setEpContextEmbedMode + * @param outputExternalInitializersPath Path to the file. + * @param sizeThreshold Initializers larger than this threshold are stored in the file. + * @throws OrtException If the path could not be set. + */ + public void setOutputExternalInitializersPath( + String outputExternalInitializersPath, long sizeThreshold) throws OrtException { + checkClosed(); + // check positive + setOutputExternalInitializersPath( + OnnxRuntime.ortApiHandle, + OnnxRuntime.ortCompileApiHandle, + nativeHandle, + outputExternalInitializersPath, + sizeThreshold); + } + + /** + * Enables or disables the embedding of EPContext binary data into the ep_cache_context attribute + * of EPContext nodes. + * + *

Defaults to false. When enabled, the `ep_cache_context` attribute of EPContext nodes will + * store the context binary data, which may include weights for compiled subgraphs. When disabled, + * the `ep_cache_context` attribute of EPContext nodes will contain the path to the file + * containing the context binary data. The path is set by the execution provider creating the + * EPContext node. + * + *

For more details see the EPContext design + * document. + * + * @param embedEpContext True to embed EPContext binary data into the EPContext node's + * ep_cache_context attribute. + * @throws OrtException If the set operation failed. + */ + public void setEpContextEmbedMode(boolean embedEpContext) throws OrtException { + checkClosed(); + setEpContextEmbedMode( + OnnxRuntime.ortApiHandle, OnnxRuntime.ortCompileApiHandle, nativeHandle, embedEpContext); + } + + /** + * Sets the specified compilation flags. + * + * @param flags The compilation flags. + * @throws OrtException If the set operation failed. + */ + public void setCompilationFlags(EnumSet flags) throws OrtException { + checkClosed(); + setCompilationFlags( + OnnxRuntime.ortApiHandle, + OnnxRuntime.ortCompileApiHandle, + nativeHandle, + OrtFlags.aggregateToInt(flags)); + } + + /** + * Compiles the ONNX model with the configuration described by this instance of + * OrtModelCompilationOptions. + * + * @throws OrtException If the compilation failed. + */ + public void compileModel() throws OrtException { + checkClosed(); + // Safe as the environment must exist to create one of these objects. + OrtEnvironment env = OrtEnvironment.getEnvironment(); + compileModel( + OnnxRuntime.ortApiHandle, + OnnxRuntime.ortCompileApiHandle, + env.getNativeHandle(), + nativeHandle); + } + + private static native long createFromSessionOptions( + long apiHandle, long compileApiHandle, long envHandle, long nativeHandle) throws OrtException; + + private static native void close(long compileApiHandle, long nativeHandle); + + private static native void setInputModelPath( + long apiHandle, long compileApiHandle, long nativeHandle, String inputModelPath) + throws OrtException; + + private static native void setInputModelFromBuffer( + long apiHandle, + long compileApiHandle, + long nativeHandle, + ByteBuffer inputBuffer, + long bufferPos, + long bufferRemaining) + throws OrtException; + + private static native void setOutputModelPath( + long apiHandle, long compileApiHandle, long nativeHandle, String outputModelPath) + throws OrtException; + + private static native void setOutputExternalInitializersPath( + long apiHandle, + long compileApiHandle, + long nativeHandle, + String externalInitializersPath, + long sizeThreshold) + throws OrtException; + + private static native void setEpContextEmbedMode( + long apiHandle, long compileApiHandle, long nativeHandle, boolean embedEpContext) + throws OrtException; + + private static native void setCompilationFlags( + long apiHandle, long compileApiHandle, long nativeHandle, int flags) throws OrtException; + + private static native void compileModel( + long apiHandle, long compileApiHandle, long envHandle, long nativeHandle) throws OrtException; +} diff --git a/java/src/main/java/ai/onnxruntime/OrtProvider.java b/java/src/main/java/ai/onnxruntime/OrtProvider.java index 1740ac7eeef00..2f2f94ea63406 100644 --- a/java/src/main/java/ai/onnxruntime/OrtProvider.java +++ b/java/src/main/java/ai/onnxruntime/OrtProvider.java @@ -31,8 +31,6 @@ public enum OrtProvider { MI_GRAPH_X("MIGraphXExecutionProvider"), /** The ARM Compute Library execution provider. */ ACL("ACLExecutionProvider"), - /** The ARM NN execution provider. */ - ARM_NN("ArmNNExecutionProvider"), /** The AMD ROCm execution provider. */ ROCM("ROCMExecutionProvider"), /** The Apple CoreML execution provider. */ diff --git a/java/src/main/java/ai/onnxruntime/OrtSession.java b/java/src/main/java/ai/onnxruntime/OrtSession.java index bd988e2bb7468..c9178980f242f 100644 --- a/java/src/main/java/ai/onnxruntime/OrtSession.java +++ b/java/src/main/java/ai/onnxruntime/OrtSession.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * SPDX-FileCopyrightText: Copyright 2024 Arm Limited and/or its affiliates * Licensed under the MIT License. */ @@ -8,7 +8,6 @@ import ai.onnxruntime.providers.CoreMLFlags; import ai.onnxruntime.providers.NNAPIFlags; import ai.onnxruntime.providers.OrtCUDAProviderOptions; -import ai.onnxruntime.providers.OrtFlags; import ai.onnxruntime.providers.OrtTensorRTProviderOptions; import java.io.IOException; import java.nio.ByteBuffer; @@ -624,6 +623,10 @@ private native OnnxModelMetadata constructMetadata( *

Used to set the number of threads, optimisation level, computation backend and other * options. * + *

The order execution providers are added to an options instance is the order they will be + * considered for op node assignment, with the EP added first having priority. The CPU EP is a + * fallback and added by default. + * *

Modifying this after the session has been constructed will have no effect. * *

The SessionOptions object must not be closed until all sessions which use it are closed, as @@ -652,6 +655,8 @@ public enum OptLevel { * graph. */ EXTENDED_OPT(2), + /** Applies all the layout optimizations like NCHW and NCHWC to the ONNX graph. */ + LAYOUT_OPT(3), /** Applies all available optimizations to the ONNX graph. */ ALL_OPT(99); @@ -728,7 +733,7 @@ public SessionOptions() { @Override public void close() { if (!closed) { - if (customLibraryHandles.size() > 0) { + if (!customLibraryHandles.isEmpty()) { long[] longArray = new long[customLibraryHandles.size()]; for (int i = 0; i < customLibraryHandles.size(); i++) { longArray[i] = customLibraryHandles.get(i); @@ -915,10 +920,10 @@ public void registerCustomOpLibrary(String path) throws OrtException { * *

 OrtStatus* (*fn)(OrtSessionOptions* options, const OrtApiBase* api); * - *

See https://onnxruntime.ai/docs/reference/operators/add-custom-op.html for more - * information on custom ops. See - * https://github.com/microsoft/onnxruntime/blob/342a5bf2b756d1a1fc6fdc582cfeac15182632fe/onnxruntime/test/testdata/custom_op_library/custom_op_library.cc#L115 - * for an example of a custom op library registration function. + *

See Add + * Custom Op for more information on custom ops. See an example of a custom op library + * registration function here. * * @param registrationFuncName The name of the registration function to call. * @throws OrtException If there was an error finding or calling the registration function. @@ -1240,17 +1245,6 @@ public void addACL(boolean enableFastMath) throws OrtException { addACL(OnnxRuntime.ortApiHandle, nativeHandle, enableFastMath); } - /** - * Adds the ARM Neural Net library as an execution backend. - * - * @param useArena If true use the arena memory allocator. - * @throws OrtException If there was an error in native code. - */ - public void addArmNN(boolean useArena) throws OrtException { - checkClosed(); - addArmNN(OnnxRuntime.ortApiHandle, nativeHandle, useArena ? 1 : 0); - } - /** * Adds Apple's CoreML as an execution backend. Uses the default empty flag. * @@ -1271,10 +1265,47 @@ public void addCoreML(EnumSet flags) throws OrtException { addCoreML(OnnxRuntime.ortApiHandle, nativeHandle, OrtFlags.aggregateToInt(flags)); } + /** + * Adds the specified execution provider and device tuples as an execution backend. + * + *

Execution provider priority is in the order added, i.e., the first provider added to a + * session options will be used first for op node assignment. + * + * @param devices The EP and device tuples. Each element must use the same EP, though they can + * use different devices. + * @param providerOptions Configuration options for the execution provider. Refer to the + * specific execution provider's documentation. + * @throws OrtException If there was an error in native code. + */ + public void addExecutionProvider(List devices, Map providerOptions) + throws OrtException { + checkClosed(); + if (devices.isEmpty()) { + throw new IllegalArgumentException("Must supply at least one OrtEpDevice"); + } + long[] deviceHandles = new long[devices.size()]; + for (int i = 0; i < devices.size(); i++) { + deviceHandles[i] = devices.get(i).getNativeHandle(); + } + String[][] optsArray = OrtUtil.unpackMap(providerOptions); + // This is valid as the environment must have been created to create the OrtEpDevice list. + long envHandle = OrtEnvironment.getEnvironment().getNativeHandle(); + addExecutionProvider( + OnnxRuntime.ortApiHandle, + envHandle, + nativeHandle, + deviceHandles, + optsArray[0], + optsArray[1]); + } + /** * Adds the named execution provider (backend) as an execution backend. This generic function * only allows a subset of execution providers. * + *

Execution provider priority is in the order added, i.e., the first provider added to a + * session options will be used first for op node assignment. + * * @param providerName The name of the execution provider. * @param providerOptions Configuration options for the execution provider. Refer to the * specific execution provider's documentation. @@ -1283,20 +1314,9 @@ public void addCoreML(EnumSet flags) throws OrtException { private void addExecutionProvider(String providerName, Map providerOptions) throws OrtException { checkClosed(); - String[] providerOptionKey = new String[providerOptions.size()]; - String[] providerOptionVal = new String[providerOptions.size()]; - int i = 0; - for (Map.Entry entry : providerOptions.entrySet()) { - providerOptionKey[i] = entry.getKey(); - providerOptionVal[i] = entry.getValue(); - i++; - } + String[][] optsArray = OrtUtil.unpackMap(providerOptions); addExecutionProvider( - OnnxRuntime.ortApiHandle, - nativeHandle, - providerName, - providerOptionKey, - providerOptionVal); + OnnxRuntime.ortApiHandle, nativeHandle, providerName, optsArray[0], optsArray[1]); } /** @@ -1339,6 +1359,18 @@ public void addCoreML(Map providerOptions) throws OrtException { addExecutionProvider(CoreMLProviderName, providerOptions); } + /** + * Adds WebGPU as an execution backend. + * + * @param providerOptions Configuration options for the WebGPU backend. Refer to the WebGPU + * execution provider's documentation. + * @throws OrtException If there was an error in native code. + */ + public void addWebGPU(Map providerOptions) throws OrtException { + String webGpuProviderName = "WebGPU"; + addExecutionProvider(webGpuProviderName, providerOptions); + } + private native void setExecutionMode(long apiHandle, long nativeHandle, int mode) throws OrtException; @@ -1457,9 +1489,6 @@ private native void addDirectML(long apiHandle, long nativeHandle, int deviceId) private native void addACL(long apiHandle, long nativeHandle, boolean enableFastMath) throws OrtException; - private native void addArmNN(long apiHandle, long nativeHandle, int useArena) - throws OrtException; - private native void addCoreML(long apiHandle, long nativeHandle, int coreMLFlags) throws OrtException; @@ -1470,6 +1499,15 @@ private native void addExecutionProvider( String[] providerOptionKey, String[] providerOptionVal) throws OrtException; + + private native void addExecutionProvider( + long apiHandle, + long envHandle, + long nativeHandle, + long[] deviceHandles, + String[] providerOptionKey, + String[] providerOptionVal) + throws OrtException; } /** Used to control logging and termination of a call to {@link OrtSession#run}. */ diff --git a/java/src/main/java/ai/onnxruntime/OrtUtil.java b/java/src/main/java/ai/onnxruntime/OrtUtil.java index 2f44236e4ef67..ee91fdb292baa 100644 --- a/java/src/main/java/ai/onnxruntime/OrtUtil.java +++ b/java/src/main/java/ai/onnxruntime/OrtUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. */ @@ -16,6 +16,9 @@ import java.nio.ShortBuffer; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; import java.util.logging.Logger; /** Util code for interacting with Java arrays. */ @@ -370,6 +373,52 @@ public static boolean validateShape(long[] shape) { return valid && shape.length <= TensorInfo.MAX_DIMENSIONS; } + /** + * Converts the output of a OrtKeyValuePairs into a Java unmodifiable HashMap. + * + * @param zippedString The zipped keys and values. + * @return An unmodifiable Map. + */ + static Map convertToMap(String[][] zippedString) { + if (zippedString.length != 2) { + throw new IllegalArgumentException("Invalid zipped string, must have two arrays."); + } else if (zippedString[0].length != zippedString[1].length) { + throw new IllegalArgumentException( + "Invalid zipped string, must have two arrays of the same length."); + } + Map map = new HashMap<>(capacityFromSize(zippedString[0].length)); + for (int i = 0; i < zippedString[0].length; i++) { + map.put(zippedString[0][i], zippedString[1][i]); + } + return Collections.unmodifiableMap(map); + } + + /** + * Converts a Java string map into a pair of arrays suitable for constructing a native + * OrtKeyValuePairs object. + * + * @param map A map from string to string, with no null keys or values. + * @return A pair of String arrays. + */ + static String[][] unpackMap(Map map) { + String[] keys = new String[map.size()]; + String[] values = new String[map.size()]; + int i = 0; + for (Map.Entry entry : map.entrySet()) { + if (entry.getKey() == null || entry.getValue() == null) { + throw new IllegalArgumentException( + "Invalid map, keys and values must not be null, found key = " + + entry.getKey() + + ", value = " + + entry.getValue()); + } + keys[i] = entry.getKey(); + values[i] = entry.getValue(); + i++; + } + return new String[][] {keys, values}; + } + /** * Flatten a multidimensional String array into a single dimensional String array, reading it in a * multidimensional row-major order. diff --git a/java/src/main/java/ai/onnxruntime/providers/CoreMLFlags.java b/java/src/main/java/ai/onnxruntime/providers/CoreMLFlags.java index 22bf940844774..15fe459dad7c8 100644 --- a/java/src/main/java/ai/onnxruntime/providers/CoreMLFlags.java +++ b/java/src/main/java/ai/onnxruntime/providers/CoreMLFlags.java @@ -1,9 +1,11 @@ /* - * Copyright (c) 2021, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * Licensed under the MIT License. */ package ai.onnxruntime.providers; +import ai.onnxruntime.OrtFlags; + /** Flags for the CoreML provider. */ public enum CoreMLFlags implements OrtFlags { /** diff --git a/java/src/main/java/ai/onnxruntime/providers/NNAPIFlags.java b/java/src/main/java/ai/onnxruntime/providers/NNAPIFlags.java index eeaf6cc8d53bc..dd30684078717 100644 --- a/java/src/main/java/ai/onnxruntime/providers/NNAPIFlags.java +++ b/java/src/main/java/ai/onnxruntime/providers/NNAPIFlags.java @@ -1,9 +1,11 @@ /* - * Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2025, Oracle and/or its affiliates. All rights reserved. * Licensed under the MIT License. */ package ai.onnxruntime.providers; +import ai.onnxruntime.OrtFlags; + /** Flags for the NNAPI provider. */ public enum NNAPIFlags implements OrtFlags { /** Enables fp16 support. */ diff --git a/java/src/main/native/OrtJniUtil.c b/java/src/main/native/OrtJniUtil.c index 6a3c279073860..eef4b731d106e 100644 --- a/java/src/main/native/OrtJniUtil.c +++ b/java/src/main/native/OrtJniUtil.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025 Oracle and/or its affiliates. All rights reserved. * Licensed under the MIT License. */ #include @@ -47,6 +47,8 @@ GraphOptimizationLevel convertOptimizationLevel(jint level) { return ORT_ENABLE_BASIC; case 2: return ORT_ENABLE_EXTENDED; + case 3: + return ORT_ENABLE_LAYOUT; case 99: return ORT_ENABLE_ALL; default: @@ -107,6 +109,42 @@ jint convertFromOrtSparseFormat(OrtSparseFormat format) { } } +/** + * Must be kept in sync with convertToCompiledModelCompatibility. + */ +jint convertFromCompiledModelCompatibility(OrtCompiledModelCompatibility compat) { + switch (compat) { + case OrtCompiledModelCompatibility_EP_NOT_APPLICABLE: + return 0; + case OrtCompiledModelCompatibility_EP_SUPPORTED_OPTIMAL: + return 1; + case OrtCompiledModelCompatibility_EP_SUPPORTED_PREFER_RECOMPILATION: + return 2; + case OrtCompiledModelCompatibility_EP_UNSUPPORTED: + return 3; + default: + // if this value is observed the enum has changed and the code should be updated. + return -1; + } +} + +/** + * Must be kept in sync with convertFromCompiledModelCompatibility. + */ +OrtCompiledModelCompatibility convertToCompiledModelCompatibility(jint compat) { + switch (compat) { + case 0: + return OrtCompiledModelCompatibility_EP_NOT_APPLICABLE; + case 1: + return OrtCompiledModelCompatibility_EP_SUPPORTED_OPTIMAL; + case 2: + return OrtCompiledModelCompatibility_EP_SUPPORTED_PREFER_RECOMPILATION; + case 3: + default: + return OrtCompiledModelCompatibility_EP_UNSUPPORTED; + } +} + /** * Must be kept in sync with convertToONNXDataFormat */ @@ -1012,6 +1050,36 @@ jobject convertOrtValueToONNXValue(JNIEnv *jniEnv, const OrtApi * api, OrtAlloca } } +jobjectArray convertOrtKeyValuePairsToArrays(JNIEnv *jniEnv, const OrtApi * api, const OrtKeyValuePairs * kvp) { + // extract pair arrays + const char* const* keys = NULL; + const char* const* values = NULL; + size_t numKeys = 0; + api->GetKeyValuePairs(kvp, &keys, &values, &numKeys); + jsize jNumKeys = safecast_size_t_to_jsize(numKeys); + + // create Java String[] + jclass stringClazz = (*jniEnv)->FindClass(jniEnv, "java/lang/String"); + jobjectArray keyArray = (*jniEnv)->NewObjectArray(jniEnv, jNumKeys, stringClazz, NULL); + jobjectArray valueArray = (*jniEnv)->NewObjectArray(jniEnv, jNumKeys, stringClazz, NULL); + + // populate Java arrays + for (jsize i = 0; i < jNumKeys; i++) { + jstring key = (*jniEnv)->NewStringUTF(jniEnv, keys[i]); + (*jniEnv)->SetObjectArrayElement(jniEnv, keyArray, i, key); + jstring value = (*jniEnv)->NewStringUTF(jniEnv, values[i]); + (*jniEnv)->SetObjectArrayElement(jniEnv, valueArray, i, value); + } + + // create Java String[][] + jclass stringArrClazz = (*jniEnv)->GetObjectClass(jniEnv, keyArray); + jobjectArray pair = (*jniEnv)->NewObjectArray(jniEnv, 2, stringArrClazz, 0); + (*jniEnv)->SetObjectArrayElement(jniEnv, pair, 0, keyArray); + (*jniEnv)->SetObjectArrayElement(jniEnv, pair, 1, valueArray); + + return pair; +} + jint throwOrtException(JNIEnv *jniEnv, int messageId, const char *message) { jstring messageStr = (*jniEnv)->NewStringUTF(jniEnv, message); @@ -1049,6 +1117,12 @@ jint convertErrorCode(OrtErrorCode code) { return 10; case ORT_EP_FAIL: return 11; + case ORT_MODEL_LOAD_CANCELED: + return 12; + case ORT_MODEL_REQUIRES_COMPILATION: + return 13; + case ORT_NOT_FOUND: + return 14; default: return -1; // Unknown error code } diff --git a/java/src/main/native/OrtJniUtil.h b/java/src/main/native/OrtJniUtil.h index 7f41e06371f2a..f9f4717597831 100644 --- a/java/src/main/native/OrtJniUtil.h +++ b/java/src/main/native/OrtJniUtil.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * Licensed under the MIT License. */ #include @@ -34,6 +34,10 @@ OrtSparseFormat convertToOrtSparseFormat(jint format); jint convertFromOrtSparseFormat(OrtSparseFormat format); +jint convertFromCompiledModelCompatibility(OrtCompiledModelCompatibility compat); + +OrtCompiledModelCompatibility convertToCompiledModelCompatibility(jint compat); + jint convertFromONNXDataFormat(ONNXTensorElementDataType type); ONNXTensorElementDataType convertToONNXDataFormat(jint type); @@ -78,6 +82,8 @@ jobject createMapInfoFromValue(JNIEnv *jniEnv, const OrtApi * api, OrtAllocator jobject convertOrtValueToONNXValue(JNIEnv *jniEnv, const OrtApi * api, OrtAllocator* allocator, OrtValue* onnxValue); +jobjectArray convertOrtKeyValuePairsToArrays(JNIEnv *jniEnv, const OrtApi * api, const OrtKeyValuePairs * kvp); + jint throwOrtException(JNIEnv *env, int messageId, const char *message); jint convertErrorCode(OrtErrorCode code); diff --git a/java/src/main/native/ai_onnxruntime_OnnxRuntime.c b/java/src/main/native/ai_onnxruntime_OnnxRuntime.c index 659f34e1fb66f..d8f5f1a3cb2db 100644 --- a/java/src/main/native/ai_onnxruntime_OnnxRuntime.c +++ b/java/src/main/native/ai_onnxruntime_OnnxRuntime.c @@ -32,6 +32,19 @@ JNIEXPORT jlong JNICALL Java_ai_onnxruntime_OnnxRuntime_initialiseTrainingAPIBas return (jlong) trainingApi; } +/* + * Class: ai_onnxruntime_OnnxRuntime + * Method: initialiseCompileAPIBase + * Signature: (J)J + */ +JNIEXPORT jlong JNICALL Java_ai_onnxruntime_OnnxRuntime_initialiseCompileAPIBase + (JNIEnv * jniEnv, jclass clazz, jlong apiHandle) { + (void)jniEnv; (void)clazz; // required JNI parameters not needed by functions which don't call back into Java. + const OrtApi* api = (const OrtApi*)apiHandle; + const OrtCompileApi* compileApi = api->GetCompileApi(); + return (jlong) compileApi; +} + /* * Class: ai_onnxruntime_OnnxRuntime * Method: getAvailableProviders diff --git a/java/src/main/native/ai_onnxruntime_OrtEnvironment.c b/java/src/main/native/ai_onnxruntime_OrtEnvironment.c index e1b1ff1c05fe1..8061c6454ef47 100644 --- a/java/src/main/native/ai_onnxruntime_OrtEnvironment.c +++ b/java/src/main/native/ai_onnxruntime_OrtEnvironment.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2019, 2025, Oracle and/or its affiliates. All rights reserved. * Licensed under the MIT License. */ #include @@ -60,6 +60,112 @@ JNIEXPORT jlong JNICALL Java_ai_onnxruntime_OrtEnvironment_getDefaultAllocator return (jlong)allocator; } +/* + * Class: ai_onnxruntime_OrtEnvironment + * Method: registerExecutionProviderLibrary + * Signature: (JJLjava/lang/String;Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtEnvironment_registerExecutionProviderLibrary + (JNIEnv * jniEnv, jclass jobj, jlong apiHandle, jlong nativeHandle, jstring name, jstring libraryPath) { + (void) jobj; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtEnv* env = (OrtEnv*) nativeHandle; + const char* cName = (*jniEnv)->GetStringUTFChars(jniEnv, name, NULL); +#ifdef _WIN32 + const jchar* cPath = (*jniEnv)->GetStringChars(jniEnv, libraryPath, NULL); + size_t stringLength = (*jniEnv)->GetStringLength(jniEnv, libraryPath); + wchar_t* newString = (wchar_t*)calloc(stringLength + 1, sizeof(wchar_t)); + if (newString == NULL) { + (*jniEnv)->ReleaseStringChars(jniEnv, libraryPath, cPath); + throwOrtException(jniEnv, 1, "Not enough memory"); + return; + } + wcsncpy_s(newString, stringLength + 1, (const wchar_t*)cPath, stringLength); + checkOrtStatus(jniEnv, api, api->RegisterExecutionProviderLibrary(env, cName, newString)); + free(newString); + (*jniEnv)->ReleaseStringChars(jniEnv, libraryPath, cPath); +#else + const char* cPath = (*jniEnv)->GetStringUTFChars(jniEnv, libraryPath, NULL); + checkOrtStatus(jniEnv, api, api->RegisterExecutionProviderLibrary(env, cName, cPath)); + (*jniEnv)->ReleaseStringUTFChars(jniEnv, libraryPath, cPath); +#endif + (*jniEnv)->ReleaseStringUTFChars(jniEnv, name, cName); +} + +/* + * Class: ai_onnxruntime_OrtEnvironment + * Method: unregisterExecutionProviderLibrary + * Signature: (JJLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtEnvironment_unregisterExecutionProviderLibrary + (JNIEnv * jniEnv, jclass jobj, jlong apiHandle, jlong nativeHandle, jstring name) { + (void) jobj; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtEnv* env = (OrtEnv*) nativeHandle; + const char* cName = (*jniEnv)->GetStringUTFChars(jniEnv, name, NULL); + checkOrtStatus(jniEnv, api, api->UnregisterExecutionProviderLibrary(env, cName)); + (*jniEnv)->ReleaseStringUTFChars(jniEnv, name, cName); +} + +/* + * Class: ai_onnxruntime_OrtEnvironment + * Method: getEpDevices + * Signature: (JJ)[J + */ +JNIEXPORT jlongArray JNICALL Java_ai_onnxruntime_OrtEnvironment_getEpDevices + (JNIEnv * jniEnv, jclass jobj, jlong apiHandle, jlong nativeHandle) { + (void) jobj; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtEnv* env = (OrtEnv*) nativeHandle; + size_t numDevices = 0; + const OrtEpDevice* const* devicesArr = NULL; + OrtErrorCode code = checkOrtStatus(jniEnv, api, api->GetEpDevices(env, &devicesArr, &numDevices)); + if (code != ORT_OK) { + return NULL; + } else { + jsize numDevicesInt = safecast_size_t_to_jsize(numDevices); + jlongArray outputArr = (*jniEnv)->NewLongArray(jniEnv, numDevicesInt); + (*jniEnv)->SetLongArrayRegion(jniEnv, outputArr, 0, numDevicesInt, (jlong*)devicesArr); + return outputArr; + } +} + +/* + * Class: ai_onnxruntime_OrtEnvironment + * Method: getModelCompatibilityForEpDevices + * Signature: (J[JLjava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_ai_onnxruntime_OrtEnvironment_getModelCompatibilityForEpDevices + (JNIEnv * jniEnv, jclass jobj, jlong apiHandle, jlongArray epHandles, jstring modelInfo) { + (void) jobj; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + + // convert pointers for EpDevice handles + jsize deviceCount = (*jniEnv)->GetArrayLength(jniEnv, epHandles); + const OrtEpDevice** devicePtrs = allocarray(deviceCount, sizeof(OrtEpDevice *)); + jlong* deviceHandleElements = (*jniEnv)->GetLongArrayElements(jniEnv, epHandles, NULL); + for (jsize i = 0; i < deviceCount; i++) { + devicePtrs[i] = (OrtEpDevice*) deviceHandleElements[i]; + } + (*jniEnv)->ReleaseLongArrayElements(jniEnv, epHandles, deviceHandleElements, JNI_ABORT); + + // get utf-8 string + const char* modelStr = (*jniEnv)->GetStringUTFChars(jniEnv, modelInfo, NULL); + + OrtCompiledModelCompatibility compatibility; + OrtErrorCode code = checkOrtStatus(jniEnv, api, api->GetModelCompatibilityForEpDevices(devicePtrs, deviceCount, modelStr, &compatibility)); + + // cleanup + (*jniEnv)->ReleaseStringUTFChars(jniEnv, modelInfo, modelStr); + free((void*)devicePtrs); + if (code != ORT_OK) { + return -1; + } else { + jint returnVal = convertFromCompiledModelCompatibility(compatibility); + return returnVal; + } +} + /* * Class: ai_onnxruntime_OrtEnvironment * Method: close diff --git a/java/src/main/native/ai_onnxruntime_OrtEpDevice.c b/java/src/main/native/ai_onnxruntime_OrtEpDevice.c new file mode 100644 index 0000000000000..168c0534aaffd --- /dev/null +++ b/java/src/main/native/ai_onnxruntime_OrtEpDevice.c @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved. + * Licensed under the MIT License. + */ +#include +#include "onnxruntime/core/session/onnxruntime_c_api.h" +#include "OrtJniUtil.h" +#include "ai_onnxruntime_OrtEpDevice.h" + +/* + * Class: ai_onnxruntime_OrtEpDevice + * Method: getName + * Signature: (JJ)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_ai_onnxruntime_OrtEpDevice_getEpName + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong nativeHandle) { + (void) jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtEpDevice* epDevice = (OrtEpDevice*) nativeHandle; + const char* name = api->EpDevice_EpName(epDevice); + jstring nameStr = (*jniEnv)->NewStringUTF(jniEnv, name); + return nameStr; +} + +/* + * Class: ai_onnxruntime_OrtEpDevice + * Method: getVendor + * Signature: (JJ)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_ai_onnxruntime_OrtEpDevice_getEpVendor + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong nativeHandle) { + (void) jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtEpDevice* epDevice = (OrtEpDevice*) nativeHandle; + const char* vendor = api->EpDevice_EpVendor(epDevice); + jstring vendorStr = (*jniEnv)->NewStringUTF(jniEnv, vendor); + return vendorStr; +} + +/* + * Class: ai_onnxruntime_OrtEpDevice + * Method: getMetadata + * Signature: (JJ)[[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_ai_onnxruntime_OrtEpDevice_getEpMetadata + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong nativeHandle) { + (void) jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtEpDevice* epDevice = (OrtEpDevice*) nativeHandle; + const OrtKeyValuePairs* kvp = api->EpDevice_EpMetadata(epDevice); + jobjectArray pair = convertOrtKeyValuePairsToArrays(jniEnv, api, kvp); + return pair; +} + +/* + * Class: ai_onnxruntime_OrtEpDevice + * Method: getOptions + * Signature: (JJ)[[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_ai_onnxruntime_OrtEpDevice_getEpOptions + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong nativeHandle) { + (void) jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtEpDevice* epDevice = (OrtEpDevice*) nativeHandle; + const OrtKeyValuePairs* kvp = api->EpDevice_EpOptions(epDevice); + jobjectArray pair = convertOrtKeyValuePairsToArrays(jniEnv, api, kvp); + return pair; +} + +/* + * Class: ai_onnxruntime_OrtEpDevice + * Method: getDeviceHandle + * Signature: (JJ)J + */ +JNIEXPORT jlong JNICALL Java_ai_onnxruntime_OrtEpDevice_getDeviceHandle + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong nativeHandle) { + (void) jniEnv; (void) jclazz; // Required JNI parameters not needed by functions which don't need to access their host object or the JVM. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtEpDevice* epDevice = (OrtEpDevice*) nativeHandle; + const OrtHardwareDevice* device = api->EpDevice_Device(epDevice); + return (jlong) device; +} diff --git a/java/src/main/native/ai_onnxruntime_OrtHardwareDevice.c b/java/src/main/native/ai_onnxruntime_OrtHardwareDevice.c new file mode 100644 index 0000000000000..3191a89c26ba1 --- /dev/null +++ b/java/src/main/native/ai_onnxruntime_OrtHardwareDevice.c @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved. + * Licensed under the MIT License. + */ +#include +#include "onnxruntime/core/session/onnxruntime_c_api.h" +#include "OrtJniUtil.h" +#include "ai_onnxruntime_OrtHardwareDevice.h" + +/* + * Class: ai_onnxruntime_OrtHardwareDevice + * Method: getVendor + * Signature: (JJ)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_ai_onnxruntime_OrtHardwareDevice_getVendor + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong nativeHandle) { + (void) jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtHardwareDevice* device = (OrtHardwareDevice*) nativeHandle; + const char* vendor = api->HardwareDevice_Vendor(device); + jstring vendorStr = (*jniEnv)->NewStringUTF(jniEnv, vendor); + return vendorStr; +} + +/* + * Class: ai_onnxruntime_OrtHardwareDevice + * Method: getMetadata + * Signature: (JJ)[[Ljava/lang/String; + */ +JNIEXPORT jobjectArray JNICALL Java_ai_onnxruntime_OrtHardwareDevice_getMetadata + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong nativeHandle) { + (void) jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtHardwareDevice* device = (OrtHardwareDevice*) nativeHandle; + const OrtKeyValuePairs* kvp = api->HardwareDevice_Metadata(device); + jobjectArray pair = convertOrtKeyValuePairsToArrays(jniEnv, api, kvp); + return pair; +} + +/* + * Class: ai_onnxruntime_OrtHardwareDevice + * Method: getDeviceType + * Signature: (JJ)I + */ +JNIEXPORT jint JNICALL Java_ai_onnxruntime_OrtHardwareDevice_getDeviceType + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong nativeHandle) { + (void) jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtHardwareDevice* device = (OrtHardwareDevice*) nativeHandle; + OrtHardwareDeviceType type = api->HardwareDevice_Type(device); + jint output = 0; + // Must be kept aligned with the Java OrtHardwareDeviceType enum. + switch (type) { + case OrtHardwareDeviceType_CPU: + output = 0; + break; + case OrtHardwareDeviceType_GPU: + output = 1; + break; + case OrtHardwareDeviceType_NPU: + output = 2; + break; + default: + throwOrtException(jniEnv, convertErrorCode(ORT_NOT_IMPLEMENTED), "Unexpected device type found. Only CPU, GPU and NPU are supported."); + break; + } + return output; +} + +/* + * Class: ai_onnxruntime_OrtHardwareDevice + * Method: getDeviceId + * Signature: (JJ)I + */ +JNIEXPORT jint JNICALL Java_ai_onnxruntime_OrtHardwareDevice_getDeviceId + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong nativeHandle) { + (void) jniEnv; (void) jclazz; // Required JNI parameters not needed by functions which don't need to access their host object or the JVM. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtHardwareDevice* device = (OrtHardwareDevice*) nativeHandle; + uint32_t id = api->HardwareDevice_DeviceId(device); + return (jint) id; +} + +/* + * Class: ai_onnxruntime_OrtHardwareDevice + * Method: getVendorId + * Signature: (JJ)I + */ +JNIEXPORT jint JNICALL Java_ai_onnxruntime_OrtHardwareDevice_getVendorId + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong nativeHandle) { + (void) jniEnv; (void) jclazz; // Required JNI parameters not needed by functions which don't need to access their host object or the JVM. + const OrtApi* api = (const OrtApi*) apiHandle; + OrtHardwareDevice* device = (OrtHardwareDevice*) nativeHandle; + uint32_t id = api->HardwareDevice_VendorId(device); + return (jint) id; +} diff --git a/java/src/main/native/ai_onnxruntime_OrtModelCompilationOptions.c b/java/src/main/native/ai_onnxruntime_OrtModelCompilationOptions.c new file mode 100644 index 0000000000000..4f79383d09766 --- /dev/null +++ b/java/src/main/native/ai_onnxruntime_OrtModelCompilationOptions.c @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2025 Oracle and/or its affiliates. All rights reserved. + * Licensed under the MIT License. + */ +#include +#include "onnxruntime/core/session/onnxruntime_c_api.h" +#include "OrtJniUtil.h" +#include "ai_onnxruntime_OrtModelCompilationOptions.h" + +/* + * Class: ai_onnxruntime_OrtModelCompilationOptions + * Method: createFromSessionOptions + * Signature: (JJJJ)J + */ +JNIEXPORT jlong JNICALL Java_ai_onnxruntime_OrtModelCompilationOptions_createFromSessionOptions + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong compileApiHandle, jlong envHandle, jlong sessionOptionsHandle) { + (void)jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*)apiHandle; + const OrtCompileApi* compileApi = (const OrtCompileApi*)compileApiHandle; + const OrtEnv* env = (const OrtEnv*)envHandle; + const OrtSessionOptions* sessionOptions = (const OrtSessionOptions*) sessionOptionsHandle; + OrtModelCompilationOptions* output = NULL; + checkOrtStatus(jniEnv, api, compileApi->CreateModelCompilationOptionsFromSessionOptions(env, sessionOptions, &output)); + return (jlong) output; +} + +/* + * Class: ai_onnxruntime_OrtModelCompilationOptions + * Method: close + * Signature: (JJ)V + */ +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtModelCompilationOptions_close + (JNIEnv * jniEnv, jclass jclazz, jlong compileApiHandle, jlong nativeHandle) { + (void)jniEnv; (void)jclazz; // Required JNI parameters not needed by functions which don't need to access their host object or the JVM. + const OrtCompileApi* compileApi = (const OrtCompileApi*)compileApiHandle; + compileApi->ReleaseModelCompilationOptions((OrtModelCompilationOptions *)nativeHandle); +} + +/* + * Class: ai_onnxruntime_OrtModelCompilationOptions + * Method: setInputModelPath + * Signature: (JJJLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtModelCompilationOptions_setInputModelPath + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong compileApiHandle, jlong nativeHandle, jstring modelPath) { + (void) jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + const OrtCompileApi* compileApi = (const OrtCompileApi*) compileApiHandle; + OrtModelCompilationOptions* compOpts = (OrtModelCompilationOptions *) nativeHandle; +#ifdef _WIN32 + const jchar* cPath = (*jniEnv)->GetStringChars(jniEnv, modelPath, NULL); + size_t stringLength = (*jniEnv)->GetStringLength(jniEnv, modelPath); + wchar_t* newString = (wchar_t*)calloc(stringLength + 1, sizeof(wchar_t)); + if (newString == NULL) { + (*jniEnv)->ReleaseStringChars(jniEnv, modelPath, cPath); + throwOrtException(jniEnv, 1, "Not enough memory"); + return; + } + wcsncpy_s(newString, stringLength + 1, (const wchar_t*)cPath, stringLength); + checkOrtStatus(jniEnv, api, compileApi->ModelCompilationOptions_SetInputModelPath(compOpts, newString)); + free(newString); + (*jniEnv)->ReleaseStringChars(jniEnv, modelPath, cPath); +#else + const char* cPath = (*jniEnv)->GetStringUTFChars(jniEnv, modelPath, NULL); + checkOrtStatus(jniEnv, api, compileApi->ModelCompilationOptions_SetInputModelPath(compOpts, cPath)); + (*jniEnv)->ReleaseStringUTFChars(jniEnv, modelPath, cPath); +#endif +} + +/* + * Class: ai_onnxruntime_OrtModelCompilationOptions + * Method: setInputModelFromBuffer + * Signature: (JJJLjava/nio/ByteBuffer;JJ)V + */ +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtModelCompilationOptions_setInputModelFromBuffer + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong compileApiHandle, jlong nativeHandle, jobject buffer, jlong bufferPos, jlong bufferRemaining) { + (void)jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + // Cast to pointers + const OrtApi* api = (const OrtApi*)apiHandle; + const OrtCompileApi* compileApi = (const OrtCompileApi*)compileApiHandle; + OrtModelCompilationOptions* compOpts = (OrtModelCompilationOptions *) nativeHandle; + + // Extract the buffer + char* bufferArr = (char*)(*jniEnv)->GetDirectBufferAddress(jniEnv, buffer); + // Increment by bufferPos bytes + bufferArr = bufferArr + bufferPos; + checkOrtStatus(jniEnv, api, compileApi->ModelCompilationOptions_SetInputModelFromBuffer(compOpts, bufferArr, bufferRemaining)); +} + +/* + * Class: ai_onnxruntime_OrtModelCompilationOptions + * Method: setOutputModelPath + * Signature: (JJJLjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtModelCompilationOptions_setOutputModelPath + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong compileApiHandle, jlong nativeHandle, jstring outputPath) { + (void) jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + const OrtCompileApi* compileApi = (const OrtCompileApi*) compileApiHandle; + OrtModelCompilationOptions* compOpts = (OrtModelCompilationOptions *) nativeHandle; +#ifdef _WIN32 + const jchar* cPath = (*jniEnv)->GetStringChars(jniEnv, outputPath, NULL); + size_t stringLength = (*jniEnv)->GetStringLength(jniEnv, outputPath); + wchar_t* newString = (wchar_t*)calloc(stringLength + 1, sizeof(wchar_t)); + if (newString == NULL) { + (*jniEnv)->ReleaseStringChars(jniEnv, outputPath, cPath); + throwOrtException(jniEnv, 1, "Not enough memory"); + return; + } + wcsncpy_s(newString, stringLength + 1, (const wchar_t*)cPath, stringLength); + checkOrtStatus(jniEnv, api, compileApi->ModelCompilationOptions_SetOutputModelPath(compOpts, newString)); + free(newString); + (*jniEnv)->ReleaseStringChars(jniEnv, outputPath, cPath); +#else + const char* cPath = (*jniEnv)->GetStringUTFChars(jniEnv, outputPath, NULL); + checkOrtStatus(jniEnv, api, compileApi->ModelCompilationOptions_SetOutputModelPath(compOpts, cPath)); + (*jniEnv)->ReleaseStringUTFChars(jniEnv, outputPath, cPath); +#endif +} + +/* + * Class: ai_onnxruntime_OrtModelCompilationOptions + * Method: setOutputExternalInitializersPath + * Signature: (JJJLjava/lang/String;J)V + */ +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtModelCompilationOptions_setOutputExternalInitializersPath + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong compileApiHandle, jlong nativeHandle, jstring initializersPath, jlong threshold) { + (void) jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*) apiHandle; + const OrtCompileApi* compileApi = (const OrtCompileApi*) compileApiHandle; + OrtModelCompilationOptions* compOpts = (OrtModelCompilationOptions *) nativeHandle; +#ifdef _WIN32 + const jchar* cPath = (*jniEnv)->GetStringChars(jniEnv, initializersPath, NULL); + size_t stringLength = (*jniEnv)->GetStringLength(jniEnv, initializersPath); + wchar_t* newString = (wchar_t*)calloc(stringLength + 1, sizeof(wchar_t)); + if (newString == NULL) { + (*jniEnv)->ReleaseStringChars(jniEnv, initializersPath, cPath); + throwOrtException(jniEnv, 1, "Not enough memory"); + return; + } + wcsncpy_s(newString, stringLength + 1, (const wchar_t*)cPath, stringLength); + checkOrtStatus(jniEnv, api, compileApi->ModelCompilationOptions_SetOutputModelExternalInitializersFile(compOpts, newString, threshold)); + free(newString); + (*jniEnv)->ReleaseStringChars(jniEnv, initializersPath, cPath); +#else + const char* cPath = (*jniEnv)->GetStringUTFChars(jniEnv, initializersPath, NULL); + checkOrtStatus(jniEnv, api, compileApi->ModelCompilationOptions_SetOutputModelExternalInitializersFile(compOpts, cPath, threshold)); + (*jniEnv)->ReleaseStringUTFChars(jniEnv, initializersPath, cPath); +#endif +} + +/* + * Class: ai_onnxruntime_OrtModelCompilationOptions + * Method: setEpContextEmbedMode + * Signature: (JJJZ)V + */ +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtModelCompilationOptions_setEpContextEmbedMode + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong compileApiHandle, jlong nativeHandle, jboolean embedMode) { + (void)jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*)apiHandle; + const OrtCompileApi* compileApi = (const OrtCompileApi*)compileApiHandle; + OrtModelCompilationOptions* compOpts = (OrtModelCompilationOptions *) nativeHandle; + checkOrtStatus(jniEnv, api, compileApi->ModelCompilationOptions_SetEpContextEmbedMode(compOpts, (bool) embedMode)); +} + +/* + * Class: ai_onnxruntime_OrtModelCompilationOptions + * Method: setCompilationFlags + * Signature: (JJJI)V + */ +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtModelCompilationOptions_setCompilationFlags + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong compileApiHandle, jlong nativeHandle, jint flags) { + (void)jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*)apiHandle; + const OrtCompileApi* compileApi = (const OrtCompileApi*)compileApiHandle; + OrtModelCompilationOptions* compOpts = (OrtModelCompilationOptions *) nativeHandle; + checkOrtStatus(jniEnv, api, compileApi->ModelCompilationOptions_SetFlags(compOpts, flags)); +} + +/* + * Class: ai_onnxruntime_OrtModelCompilationOptions + * Method: compileModel + * Signature: (JJJJ)V + */ +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtModelCompilationOptions_compileModel + (JNIEnv * jniEnv, jclass jclazz, jlong apiHandle, jlong compileApiHandle, jlong envHandle, jlong nativeHandle) { + (void)jclazz; // Required JNI parameter not needed by functions which don't need to access their host object. + const OrtApi* api = (const OrtApi*)apiHandle; + const OrtCompileApi* compileApi = (const OrtCompileApi*)compileApiHandle; + const OrtEnv* env = (const OrtEnv*)envHandle; + OrtModelCompilationOptions* compOpts = (OrtModelCompilationOptions *) nativeHandle; + checkOrtStatus(jniEnv, api, compileApi->CompileModel(env, compOpts)); +} diff --git a/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c b/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c index ff6b7fa703e6e..25a459a0befee 100644 --- a/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c +++ b/java/src/main/native/ai_onnxruntime_OrtSession_SessionOptions.c @@ -21,7 +21,6 @@ #include "onnxruntime/core/providers/tvm/tvm_provider_factory.h" #include "onnxruntime/core/providers/openvino/openvino_provider_factory.h" #include "onnxruntime/core/providers/acl/acl_provider_factory.h" -#include "onnxruntime/core/providers/armnn/armnn_provider_factory.h" #include "onnxruntime/core/providers/coreml/coreml_provider_factory.h" #ifdef USE_DML #include "onnxruntime/core/providers/dml/dml_provider_factory.h" @@ -669,22 +668,6 @@ JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtSession_00024SessionOptions_addACL #endif } -/* - * Class: ai_onnxruntime_OrtSession_SessionOptions - * Method: addArmNN - * Signature: (JJI)V - */ -JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtSession_00024SessionOptions_addArmNN - (JNIEnv * jniEnv, jobject jobj, jlong apiHandle, jlong handle, jint useArena) { - (void)jobj; - #ifdef USE_ARMNN - checkOrtStatus(jniEnv,(const OrtApi*)apiHandle,OrtSessionOptionsAppendExecutionProvider_ArmNN((OrtSessionOptions*) handle,useArena)); - #else - (void)apiHandle;(void)handle;(void)useArena; // Parameters used when ARMNN is defined. - throwOrtException(jniEnv,convertErrorCode(ORT_INVALID_ARGUMENT),"This binary was not compiled with ArmNN support."); - #endif -} - /* * Class: ai_onnxruntime_OrtSession_SessionOptions * Method: addCoreML @@ -718,11 +701,11 @@ JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtSession_00024SessionOptions_addROC } /* - * Class:: ai_onnxruntime_OrtSession_SessionOptions + * Class: ai_onnxruntime_OrtSession_SessionOptions * Method: addExecutionProvider - * Signature: (JILjava/lang/String)V + * Signature: (JJLjava/lang/String;[Ljava/lang/String;[Ljava/lang/String;)V */ -JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtSession_00024SessionOptions_addExecutionProvider( +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtSession_00024SessionOptions_addExecutionProvider__JJLjava_lang_String_2_3Ljava_lang_String_2_3Ljava_lang_String_2( JNIEnv* jniEnv, jobject jobj, jlong apiHandle, jlong optionsHandle, jstring jepName, jobjectArray configKeyArr, jobjectArray configValueArr) { (void)jobj; @@ -756,3 +739,50 @@ JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtSession_00024SessionOptions_addExe free((void*)jkeyArray); free((void*)jvalueArray); } + +/* + * Class: ai_onnxruntime_OrtSession_SessionOptions + * Method: addExecutionProvider + * Signature: (JJJ[J[Ljava/lang/String;[Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_ai_onnxruntime_OrtSession_00024SessionOptions_addExecutionProvider__JJJ_3J_3Ljava_lang_String_2_3Ljava_lang_String_2 + (JNIEnv * jniEnv, jobject jobj, jlong apiHandle, jlong envHandle, jlong optionsHandle, jlongArray deviceHandleArr, jobjectArray configKeyArr, jobjectArray configValueArr) { + (void)jobj; + + const OrtApi* api = (const OrtApi*)apiHandle; + OrtEnv* env = (OrtEnv*) envHandle; + OrtSessionOptions* options = (OrtSessionOptions*)optionsHandle; + jsize deviceCount = (*jniEnv)->GetArrayLength(jniEnv, deviceHandleArr); + jsize keyCount = (*jniEnv)->GetArrayLength(jniEnv, configKeyArr); + + const char** keyArray = (const char**)allocarray(keyCount, sizeof(const char*)); + const char** valueArray = (const char**)allocarray(keyCount, sizeof(const char*)); + jstring* jkeyArray = (jstring*)allocarray(keyCount, sizeof(jstring)); + jstring* jvalueArray = (jstring*)allocarray(keyCount, sizeof(jstring)); + const OrtEpDevice** devicePtrs = allocarray(deviceCount, sizeof(OrtEpDevice *)); + + jlong* deviceHandleElements = (*jniEnv)->GetLongArrayElements(jniEnv, deviceHandleArr, NULL); + for (jsize i = 0; i < deviceCount; i++) { + devicePtrs[i] = (OrtEpDevice*) deviceHandleElements[i]; + } + (*jniEnv)->ReleaseLongArrayElements(jniEnv, deviceHandleArr, deviceHandleElements, JNI_ABORT); + + for (jsize i = 0; i < keyCount; i++) { + jkeyArray[i] = (jstring)((*jniEnv)->GetObjectArrayElement(jniEnv, configKeyArr, i)); + jvalueArray[i] = (jstring)((*jniEnv)->GetObjectArrayElement(jniEnv, configValueArr, i)); + keyArray[i] = (*jniEnv)->GetStringUTFChars(jniEnv, jkeyArray[i], NULL); + valueArray[i] = (*jniEnv)->GetStringUTFChars(jniEnv, jvalueArray[i], NULL); + } + + checkOrtStatus(jniEnv, api, api->SessionOptionsAppendExecutionProvider_V2(options, env, devicePtrs, deviceCount, keyArray, valueArray, keyCount)); + + for (jsize i = 0; i < keyCount; i++) { + (*jniEnv)->ReleaseStringUTFChars(jniEnv, jkeyArray[i], keyArray[i]); + (*jniEnv)->ReleaseStringUTFChars(jniEnv, jvalueArray[i], valueArray[i]); + } + free((void*)devicePtrs); + free((void*)keyArray); + free((void*)valueArray); + free((void*)jkeyArray); + free((void*)jvalueArray); +} diff --git a/java/src/test/android/app/src/androidTest/java/ai/onnxruntime/example/javavalidator/SimpleTest.kt b/java/src/test/android/app/src/androidTest/java/ai/onnxruntime/example/javavalidator/SimpleTest.kt index 5e6bee6cac9f4..6e8957d05c49b 100644 --- a/java/src/test/android/app/src/androidTest/java/ai/onnxruntime/example/javavalidator/SimpleTest.kt +++ b/java/src/test/android/app/src/androidTest/java/ai/onnxruntime/example/javavalidator/SimpleTest.kt @@ -52,6 +52,11 @@ class SimpleTest { runSigmoidModelTestImpl(1, OrtProvider.QNN) } + @Test + fun runSigmoidModelTestWEBGPU() { + runSigmoidModelTestImpl(1, OrtProvider.WEBGPU) + } + @Throws(IOException::class) private fun readModel(fileName: String): ByteArray { return InstrumentationRegistry.getInstrumentation().context.assets.open(fileName) @@ -82,9 +87,7 @@ class SimpleTest { OrtProvider.QNN -> { if (OrtEnvironment.getAvailableProviders().contains(OrtProvider.QNN)) { - // Since this is running in an Android environment, we use the .so library - val qnnLibrary = "libQnnHtp.so" - val providerOptions = Collections.singletonMap("backend_path", qnnLibrary) + val providerOptions = Collections.singletonMap("backend_type", "htp") opts.addQnn(providerOptions) } else { Log.println(Log.INFO, TAG, "NO QNN EP available, skip the test") @@ -92,6 +95,16 @@ class SimpleTest { } } + OrtProvider.WEBGPU -> { + if (OrtEnvironment.getAvailableProviders().contains(OrtProvider.WEBGPU)) { + val providerOptions = Collections.emptyMap() + opts.addWebGPU(providerOptions) + } else { + Log.println(Log.INFO, TAG, "NO WEBGPU EP available, skip the test") + return + } + } + OrtProvider.CPU -> { // No additional configuration is needed for CPU } diff --git a/java/src/test/java/ai/onnxruntime/CompileApiTest.java b/java/src/test/java/ai/onnxruntime/CompileApiTest.java new file mode 100644 index 0000000000000..b70f4dca5cbd0 --- /dev/null +++ b/java/src/test/java/ai/onnxruntime/CompileApiTest.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Licensed under the MIT License. + */ +package ai.onnxruntime; + +import ai.onnxruntime.OrtSession.SessionOptions; +import java.io.File; +import java.io.IOException; +import java.nio.ByteBuffer; +import java.nio.file.Files; +import java.nio.file.Path; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +/** Test for the compilation API. */ +public class CompileApiTest { + private final OrtEnvironment env = OrtEnvironment.getEnvironment(); + + @Test + public void basicUsage() throws OrtException, IOException { + SessionOptions so = new SessionOptions(); + try (OrtModelCompilationOptions compileOptions = + OrtModelCompilationOptions.createFromSessionOptions(env, so)) { + // mainly checking these don't throw which ensures all the plumbing for the binding works. + compileOptions.setInputModelPath("model.onnx"); + compileOptions.setOutputModelPath("compiled_model.onnx"); + + compileOptions.setOutputExternalInitializersPath("external_data.bin", 512); + compileOptions.setEpContextEmbedMode(true); + } + + try (OrtModelCompilationOptions compileOptions = + OrtModelCompilationOptions.createFromSessionOptions(env, so)) { + Path modelPath = TestHelpers.getResourcePath("/squeezenet.onnx"); + byte[] modelBytes = Files.readAllBytes(modelPath); + ByteBuffer modelBuffer = ByteBuffer.wrap(modelBytes); + compileOptions.setInputModelFromBuffer(modelBuffer); + compileOptions.setOutputModelPath("compiled_model.onnx"); + + File f = new File("compiled_model.onnx"); + + compileOptions.compileModel(); + + // Check the compiled model is valid + try (OrtSession session = env.createSession(f.toString(), so)) { + Assertions.assertNotNull(session); + } + + f.delete(); + } + } +} diff --git a/java/src/test/java/ai/onnxruntime/EpDeviceTest.java b/java/src/test/java/ai/onnxruntime/EpDeviceTest.java new file mode 100644 index 0000000000000..25a21eae35be6 --- /dev/null +++ b/java/src/test/java/ai/onnxruntime/EpDeviceTest.java @@ -0,0 +1,153 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * Licensed under the MIT License. + */ +package ai.onnxruntime; + +import ai.onnxruntime.OrtHardwareDevice.OrtHardwareDeviceType; +import ai.onnxruntime.OrtSession.SessionOptions; +import java.io.File; +import java.nio.file.Path; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.function.Consumer; +import java.util.function.Supplier; +import java.util.stream.Collectors; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.condition.EnabledOnOs; +import org.junit.jupiter.api.condition.OS; + +/** Tests for {@link OrtEpDevice} and {@link OrtHardwareDevice}. */ +@EnabledOnOs(value = OS.WINDOWS) +public class EpDeviceTest { + private final OrtEnvironment ortEnv = OrtEnvironment.getEnvironment(); + + private void readHardwareDeviceValues(OrtHardwareDevice device) { + OrtHardwareDeviceType type = device.getType(); + + Assertions.assertTrue( + type == OrtHardwareDeviceType.CPU + || type == OrtHardwareDeviceType.GPU + || type == OrtHardwareDeviceType.NPU); + + if (type == OrtHardwareDeviceType.CPU) { + Assertions.assertFalse(device.getVendor().isEmpty()); + } else { + Assertions.assertTrue(device.getVendorId() != 0); + Assertions.assertTrue(device.getDeviceId() != 0); + } + + Map metadata = device.getMetadata(); + Assertions.assertNotNull(metadata); + for (Map.Entry kvp : metadata.entrySet()) { + Assertions.assertFalse(kvp.getKey().isEmpty()); + } + } + + @Test + public void getEpDevices() throws OrtException { + List epDevices = ortEnv.getEpDevices(); + Assertions.assertNotNull(epDevices); + Assertions.assertFalse(epDevices.isEmpty()); + for (OrtEpDevice epDevice : epDevices) { + Assertions.assertFalse(epDevice.getEpName().isEmpty()); + Assertions.assertFalse(epDevice.getEpVendor().isEmpty()); + Map metadata = epDevice.getEpMetadata(); + Assertions.assertNotNull(metadata); + Map options = epDevice.getEpOptions(); + Assertions.assertNotNull(options); + readHardwareDeviceValues(epDevice.getDevice()); + } + } + + @Test + public void registerUnregisterLibrary() throws OrtException { + String libFullPath = TestHelpers.getResourcePath("/example_plugin_ep.dll").toString(); + Assertions.assertTrue( + new File(libFullPath).exists(), "Expected lib " + libFullPath + " does not exist."); + + // example plugin ep uses the registration name as the ep name + String epName = "java_ep"; + + // register. shouldn't throw + ortEnv.registerExecutionProviderLibrary(epName, libFullPath); + + // check OrtEpDevice was found + List epDevices = ortEnv.getEpDevices(); + boolean found = epDevices.stream().anyMatch(a -> a.getEpName().equals(epName)); + Assertions.assertTrue(found); + + // unregister + ortEnv.unregisterExecutionProviderLibrary(epName); + } + + @Test + public void appendToSessionOptionsV2() { + Consumer>> runTest = + (Supplier> options) -> { + try (SessionOptions sessionOptions = new SessionOptions()) { + sessionOptions.setSessionLogLevel(OrtLoggingLevel.ORT_LOGGING_LEVEL_VERBOSE); + + List epDevices = ortEnv.getEpDevices(); + + // cpu ep ignores the provider options so we can use any value in epOptions and it won't + // break. + List selectedEpDevices = + epDevices.stream() + .filter(a -> a.getEpName().equals("CPUExecutionProvider")) + .collect(Collectors.toList()); + + Map epOptions = options.get(); + sessionOptions.addExecutionProvider(selectedEpDevices, epOptions); + + Path model = TestHelpers.getResourcePath("/squeezenet.onnx"); + String modelPath = model.toString(); + + // session should load successfully + try (OrtSession session = ortEnv.createSession(modelPath, sessionOptions)) { + Assertions.assertNotNull(session); + } + } catch (OrtException e) { + throw new RuntimeException(e); + } + }; + + // empty options + runTest.accept(Collections::emptyMap); + + // dummy options + runTest.accept(() -> Collections.singletonMap("random_key", "value")); + } + + @Test + public void GetEpCompatibilityInvalidArgs() { + Assertions.assertThrows( + IllegalArgumentException.class, + () -> ortEnv.getModelCompatibilityForEpDevices(null, "info")); + Assertions.assertThrows( + IllegalArgumentException.class, + () -> ortEnv.getModelCompatibilityForEpDevices(Collections.emptyList(), "info")); + } + + @Test + public void GetEpCompatibilitySingleDeviceCpuProvider() throws OrtException { + List epDevices = ortEnv.getEpDevices(); + String someInfo = "arbitrary-compat-string"; + + // Use CPU device + OrtEpDevice cpu = + epDevices.stream() + .filter(d -> d.getEpName().equals("CPUExecutionProvider")) + .findFirst() + .get(); + Assertions.assertNotNull(cpu); + List selected = Collections.singletonList(cpu); + OrtEnvironment.OrtCompiledModelCompatibility status = + ortEnv.getModelCompatibilityForEpDevices(selected, someInfo); + + // CPU defaults to not applicable in this scenario + Assertions.assertEquals(OrtEnvironment.OrtCompiledModelCompatibility.EP_NOT_APPLICABLE, status); + } +} diff --git a/java/src/test/java/ai/onnxruntime/InferenceTest.java b/java/src/test/java/ai/onnxruntime/InferenceTest.java index e11537492d3a7..dcae98263b338 100644 --- a/java/src/test/java/ai/onnxruntime/InferenceTest.java +++ b/java/src/test/java/ai/onnxruntime/InferenceTest.java @@ -693,12 +693,6 @@ public void testCUDA() throws OrtException { runProvider(OrtProvider.CUDA); } - @Test - @EnabledIfSystemProperty(named = "USE_ROCM", matches = "1") - public void testROCM() throws OrtException { - runProvider(OrtProvider.ROCM); - } - @Test @EnabledIfSystemProperty(named = "USE_TENSORRT", matches = "1") public void testTensorRT() throws OrtException { @@ -725,6 +719,18 @@ public void testDNNL() throws OrtException { runProvider(OrtProvider.DNNL); } + @Test + @EnabledIfSystemProperty(named = "USE_MIGRAPHX", matches = "1") + public void testMIGRAPHX() throws OrtException { + runProvider(OrtProvider.MI_GRAPH_X); + } + + @Test + @EnabledIfSystemProperty(named = "USE_NNAPI", matches = "1") + public void testNNAPI() throws OrtException { + runProvider(OrtProvider.NNAPI); + } + @Test @EnabledIfSystemProperty(named = "USE_XNNPACK", matches = "1") public void testXNNPACK() throws OrtException { @@ -749,6 +755,12 @@ public void testQNN() throws OrtException { runProvider(OrtProvider.QNN); } + @Test + @EnabledIfSystemProperty(named = "USE_WEBGPU", matches = "1") + public void testWEBGPU() throws OrtException { + runProvider(OrtProvider.WEBGPU); + } + private void runProvider(OrtProvider provider) throws OrtException { EnumSet providers = OrtEnvironment.getAvailableProviders(); assertTrue(providers.size() > 1); @@ -1139,7 +1151,7 @@ public void testPreTrainedModel(String opset, String modelName) throws IOExcepti try (OrtSession session = env.createSession(onnxModelFileName)) { String testDataDirNamePattern; if (opset.equals("opset9") && modelName.equals("LSTM_Seq_lens_unpacked")) { - testDataDirNamePattern = "seq_lens"; // discrepency in data directory + testDataDirNamePattern = "seq_lens"; // discrepancy in data directory } else { testDataDirNamePattern = "test_data"; } @@ -2112,12 +2124,6 @@ private static SqueezeNetTuple openSessionSqueezeNet(EnumSet provid case ACL: options.addACL(false); break; - case ARM_NN: - options.addArmNN(false); - break; - case ROCM: - options.addROCM(); - break; case CORE_ML: options.addCoreML(); break; @@ -2125,13 +2131,11 @@ private static SqueezeNetTuple openSessionSqueezeNet(EnumSet provid options.addXnnpack(Collections.emptyMap()); break; case QNN: - { - String backendPath = OS.WINDOWS.isCurrentOs() ? "/QnnCpu.dll" : "/libQnnCpu.so"; - options.addQnn( - Collections.singletonMap( - "backend_path", TestHelpers.getResourcePath(backendPath).toString())); - break; - } + options.addQnn(Collections.singletonMap("backend_type", "cpu")); + break; + case WEBGPU: + options.addWebGPU(Collections.emptyMap()); + break; case VITIS_AI: case RK_NPU: case MI_GRAPH_X: diff --git a/java/src/test/java/ai/onnxruntime/OnnxMl.java b/java/src/test/java/ai/onnxruntime/OnnxMl.java index d96c6ccba6e31..1347fb5e1a259 100644 --- a/java/src/test/java/ai/onnxruntime/OnnxMl.java +++ b/java/src/test/java/ai/onnxruntime/OnnxMl.java @@ -18317,7 +18317,7 @@ public interface TensorProtoOrBuilder * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -18333,7 +18333,7 @@ public interface TensorProtoOrBuilder * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -18349,7 +18349,7 @@ public interface TensorProtoOrBuilder * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -18663,7 +18663,7 @@ public interface TensorProtoOrBuilder * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -18679,7 +18679,7 @@ public interface TensorProtoOrBuilder * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -18695,7 +18695,7 @@ public interface TensorProtoOrBuilder * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -20167,7 +20167,7 @@ public OnnxMl.TensorProto.SegmentOrBuilder getSegmentOrBuilder() { * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -20185,7 +20185,7 @@ public java.util.List getFloatDataList() { * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -20203,7 +20203,7 @@ public int getFloatDataCount() { * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -20621,7 +20621,7 @@ public OnnxMl.TensorProto.DataLocation getDataLocation() { * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -20639,7 +20639,7 @@ public java.util.List getDoubleDataList() { * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -20657,7 +20657,7 @@ public int getDoubleDataCount() { * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -21732,7 +21732,7 @@ private void ensureFloatDataIsMutable() { * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -21750,7 +21750,7 @@ public java.util.List getFloatDataList() { * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -21768,7 +21768,7 @@ public int getFloatDataCount() { * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -21786,7 +21786,7 @@ public float getFloatData(int index) { * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -21807,7 +21807,7 @@ public Builder setFloatData(int index, float value) { * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -21828,7 +21828,7 @@ public Builder addFloatData(float value) { * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -21849,7 +21849,7 @@ public Builder addAllFloatData(java.lang.Iterable val * For float and complex64 values * Complex64 tensors are encoded as a single array of floats, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be FLOAT or COMPLEX64. @@ -23107,7 +23107,7 @@ private void ensureDoubleDataIsMutable() { * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -23125,7 +23125,7 @@ public java.util.List getDoubleDataList() { * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -23143,7 +23143,7 @@ public int getDoubleDataCount() { * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -23161,7 +23161,7 @@ public double getDoubleData(int index) { * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -23182,7 +23182,7 @@ public Builder setDoubleData(int index, double value) { * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -23203,7 +23203,7 @@ public Builder addDoubleData(double value) { * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 @@ -23224,7 +23224,7 @@ public Builder addAllDoubleData(java.lang.Iterable v * For double * Complex128 tensors are encoded as a single array of doubles, * with the real components appearing in odd numbered positions, - * and the corresponding imaginary component apparing in the + * and the corresponding imaginary component appearing in the * subsequent even numbered position. (e.g., [1.0 + 2.0i, 3.0 + 4.0i] * is encoded as [1.0, 2.0 ,3.0 ,4.0] * When this field is present, the data_type field MUST be DOUBLE or COMPLEX128 diff --git a/js/.eslintrc.js b/js/.eslintrc.js deleted file mode 100644 index 462e417df1d66..0000000000000 --- a/js/.eslintrc.js +++ /dev/null @@ -1,267 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -'use strict'; - -module.exports = { - root: true, - ignorePatterns: [ - '**/*.js', - 'node_modules/', - 'ort-schema/', - 'common/test/type-tests/', - 'web/types.d.ts', - 'test/data/', - 'dist/', - ], - env: { es6: true }, - parser: '@typescript-eslint/parser', - parserOptions: { project: true, sourceType: 'module' }, - plugins: ['@typescript-eslint', 'prefer-arrow', 'header', 'import', 'unicorn', 'jsdoc'], - rules: { - 'unicorn/filename-case': 'error', - 'header/header': [ - 2, - 'line', - [' Copyright (c) Microsoft Corporation. All rights reserved.', ' Licensed under the MIT License.'], - 2, - ], - 'import/no-extraneous-dependencies': ['error', { devDependencies: false }], - 'import/no-internal-modules': [ - 'error', - { - allow: ['**/lib/**'], - }, - ], - 'import/no-unassigned-import': 'error', - '@typescript-eslint/array-type': ['error', { default: 'array-simple' }], - '@typescript-eslint/await-thenable': 'error', - '@typescript-eslint/ban-types': [ - 'error', - { - types: { - Object: { message: 'Use {} instead.' }, - String: { message: "Use 'string' instead." }, - Number: { message: "Use 'number' instead." }, - Boolean: { message: "Use 'boolean' instead." }, - }, - }, - ], - '@typescript-eslint/naming-convention': 'error', - '@typescript-eslint/consistent-type-assertions': 'error', - '@typescript-eslint/member-delimiter-style': [ - 'error', - { - multiline: { delimiter: 'semi', requireLast: true }, - singleline: { delimiter: 'semi', requireLast: false }, - }, - ], - '@typescript-eslint/no-empty-function': 'error', - '@typescript-eslint/no-explicit-any': 'error', - '@typescript-eslint/no-floating-promises': 'error', - '@typescript-eslint/no-for-in-array': 'error', - '@typescript-eslint/no-inferrable-types': 'error', - '@typescript-eslint/no-misused-new': 'error', - '@typescript-eslint/no-namespace': ['error', { allowDeclarations: true }], - '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/no-require-imports': ['error', { allow: ['^node:'] }], - '@typescript-eslint/no-var-requires': ['error', { allow: ['^node:'] }], - '@typescript-eslint/no-unnecessary-type-assertion': 'error', - '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }], - '@typescript-eslint/promise-function-async': 'error', - '@typescript-eslint/restrict-plus-operands': 'error', - '@typescript-eslint/semi': ['error', 'always'], - '@typescript-eslint/triple-slash-reference': ['error', { path: 'always', types: 'prefer-import', lib: 'always' }], - 'arrow-body-style': 'error', - camelcase: 'error', - 'constructor-super': 'error', - curly: 'error', - 'default-case': 'error', - 'dot-notation': 'error', - eqeqeq: ['error', 'smart'], - 'guard-for-in': 'error', - 'id-match': 'error', - 'new-parens': 'error', - 'no-bitwise': 'error', - 'no-caller': 'error', - 'no-cond-assign': 'error', - 'no-console': 'error', - 'no-constant-condition': 'error', - 'no-control-regex': 'error', - 'no-debugger': 'error', - 'no-duplicate-case': 'error', - 'no-empty': 'error', - 'no-eval': 'error', - 'no-extra-bind': 'error', - 'no-invalid-regexp': 'error', - 'no-invalid-this': 'error', - 'no-multiple-empty-lines': 'error', - 'no-new-func': 'error', - 'no-new-wrappers': 'error', - 'no-octal': 'error', - 'no-octal-escape': 'error', - 'no-param-reassign': 'error', - 'no-redeclare': 'off', - '@typescript-eslint/no-redeclare': ['error'], - 'no-regex-spaces': 'error', - 'no-return-await': 'error', - 'no-sparse-arrays': 'error', - 'no-template-curly-in-string': 'error', - 'no-throw-literal': 'error', - 'no-undef-init': 'error', - 'no-underscore-dangle': 'error', - 'no-unsafe-finally': 'error', - 'no-unused-expressions': 'error', - 'no-unused-labels': 'error', - 'no-use-before-define': 'off', - '@typescript-eslint/no-use-before-define': 'error', - 'no-var': 'error', - 'object-shorthand': 'error', - 'prefer-arrow/prefer-arrow-functions': 'error', - 'prefer-const': 'error', - radix: 'error', - 'use-isnan': 'error', - }, - overrides: [ - { - files: ['node/**/*.ts'], - env: { es6: true, node: true }, - }, - { - files: ['common/lib/**/*.ts', 'node/lib/**/*.ts'], - rules: { - 'jsdoc/check-alignment': 'error', - 'jsdoc/check-indentation': 'error', - }, - }, - { - files: ['common/test/**/*.ts'], - rules: { - '@typescript-eslint/naming-convention': 'off', - 'import/no-extraneous-dependencies': 'off', - }, - }, - { - files: ['node/script/**/*.ts', 'node/test/**/*.ts', 'web/script/**/*.ts', 'web/test/**/*.ts'], - rules: { - '@typescript-eslint/naming-convention': 'off', - '@typescript-eslint/no-empty-function': 'off', - '@typescript-eslint/no-explicit-any': 'off', - '@typescript-eslint/no-require-imports': 'off', - '@typescript-eslint/no-var-requires': 'off', - '@typescript-eslint/no-unnecessary-type-assertion': 'off', - camelcase: 'off', - 'prefer-arrow/prefer-arrow-functions': 'off', - 'import/no-extraneous-dependencies': 'off', - 'import/no-unassigned-import': 'off', - 'import/no-internal-modules': 'off', - 'no-console': 'off', - 'no-empty': 'off', - 'no-unused-expressions': 'off', - }, - }, - { - files: ['web/lib/**/*.ts'], - rules: { - 'no-underscore-dangle': [ - 'error', - { - allow: [ - '_free', - '_malloc', - '_JsepGetNodeName', - '_JsepOutput', - '_OrtAddFreeDimensionOverride', - '_OrtAddRunConfigEntry', - '_OrtAddSessionConfigEntry', - '_OrtAppendExecutionProvider', - '_OrtBindInput', - '_OrtBindOutput', - '_OrtClearBoundOutputs', - '_OrtCreateBinding', - '_OrtCreateRunOptions', - '_OrtCreateSession', - '_OrtCreateSessionOptions', - '_OrtCreateTensor', - '_OrtEndProfiling', - '_OrtFree', - '_OrtGetInputName', - '_OrtGetInputOutputCount', - '_OrtGetLastError', - '_OrtGetOutputName', - '_OrtGetTensorData', - '_OrtInit', - '_OrtReleaseBinding', - '_OrtReleaseRunOptions', - '_OrtReleaseSession', - '_OrtReleaseSessionOptions', - '_OrtReleaseTensor', - '_OrtRun', - '_OrtRunWithBinding', - ], - }, - ], - }, - }, - { - files: ['web/lib/onnxjs/**/*.ts'], - rules: { - // TODO: those rules are useful. should turn on them in future (webgl refactor) - '@typescript-eslint/no-empty-function': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - '@typescript-eslint/no-use-before-define': 'off', - '@typescript-eslint/no-unnecessary-type-assertion': 'off', - '@typescript-eslint/restrict-plus-operands': 'off', - 'import/no-internal-modules': 'off', - 'prefer-arrow/prefer-arrow-functions': 'off', - 'no-param-reassign': 'off', - 'no-underscore-dangle': 'off', - 'guard-for-in': 'off', - }, - }, - { - files: ['react_native/e2e/src/**/*.ts', 'react_native/e2e/src/**/*.tsx'], - rules: { - '@typescript-eslint/no-non-null-assertion': 'off', - '@typescript-eslint/no-unnecessary-type-assertion': 'off', - 'unicorn/filename-case': 'off', - 'no-invalid-this': 'off', - 'no-console': 'off', - }, - }, - { - files: ['react_native/lib/**/*.ts'], - rules: { - '@typescript-eslint/naming-convention': 'off', - }, - }, - { - files: ['react_native/scripts/**/*.ts'], - rules: { - 'import/no-extraneous-dependencies': 'off', - 'prefer-arrow/prefer-arrow-functions': 'off', - 'no-console': 'off', - }, - }, - { - files: ['scripts/**/*.ts'], - rules: { - 'import/no-extraneous-dependencies': 'off', - 'no-console': 'off', - }, - }, - { - files: ['web/lib/**/3rd-party/**/*.ts'], - rules: { - 'header/header': 'off', - 'unicorn/filename-case': 'off', - '@typescript-eslint/explicit-module-boundary-types': 'off', - }, - }, - ], - extends: [ - 'eslint:recommended', - 'plugin:@typescript-eslint/eslint-recommended', - 'plugin:@typescript-eslint/recommended', - ], -}; diff --git a/js/.nvmrc b/js/.nvmrc new file mode 100644 index 0000000000000..0a39d73000b91 --- /dev/null +++ b/js/.nvmrc @@ -0,0 +1 @@ +v24.9.0 \ No newline at end of file diff --git a/js/.vscode/launch.json b/js/.vscode/launch.json index 5fd79872cf07b..6fd4c855054bc 100644 --- a/js/.vscode/launch.json +++ b/js/.vscode/launch.json @@ -16,6 +16,15 @@ "sourceMaps": true, "preLaunchTask": "tsc: build - common/test/tsconfig.json" }, + { + "name": "[node] Launch installation script", + "program": "${workspaceFolder}/node/script/install.js", + "request": "launch", + "skipFiles": ["/**"], + "type": "node", + "cwd": "${workspaceFolder}/node", + "args": ["--onnxruntime-node-install"] + }, { "name": "[web] Launch Build script in Node.js", "program": "${workspaceFolder}/web/script/build.js", diff --git a/js/README.md b/js/README.md index 635f5faa54981..4fc1af240852f 100644 --- a/js/README.md +++ b/js/README.md @@ -24,9 +24,9 @@ Please follow the steps described below to setup development environment. ### Prerequisites -- Node.js (16.0+): https://nodejs.org/ - (Optional) Use nvm ([Windows](https://github.com/coreybutler/nvm-windows) / [Mac/Linux](https://github.com/creationix/nvm)) to install Node.js +- Node.js (20.0+): https://nodejs.org/ - (Optional) Use nvm ([Windows](https://github.com/coreybutler/nvm-windows) / [Mac/Linux](https://github.com/creationix/nvm)) to install Node.js -- Python (2.7 or 3.6+): https://www.python.org/downloads/ +- Python (3.9+): https://www.python.org/downloads/ - python should be added to the PATH environment variable @@ -72,7 +72,7 @@ This project is designed to include all "common" code, which are pure javascript ### Requirements -Node.js v12+ (recommended v14+) +Node.js v20+ ### Build @@ -108,7 +108,7 @@ Document will be generated in folder `/js/common/docs`. > language: typescript/C++ -> dependency: onnxruntime-common, ONNXRuntime.dll +> dependency: onnxruntime-common, ONNXRuntime shared library(.so/dll/dylib) > folder: /js/node @@ -116,7 +116,7 @@ This project is designed to be used as a NPM package to enable Node.js users to ### Requirements -Node.js v12+ (recommended v14+) +Node.js v20+ ### Build @@ -307,7 +307,7 @@ From ORT v1.19 onwards, the ONNX Runtime Mobile packages are no longer published 3. In ``, run the below python script to build the ONNX Runtime Android archive file. On a Windows machine, this requires an admin account to build. - You can build a 'full' package that supports all operators and types, or a reduced size package that supports a limited set of operators and types based on your model/s to miminize the binary size. + You can build a 'full' package that supports all operators and types, or a reduced size package that supports a limited set of operators and types based on your model/s to minimize the binary size. See [here](https://onnxruntime.ai/docs/build/custom.html) for information about how the reduced build works, including creating the configuration file using your model/s. The instructions here show how to build a 'full' package. @@ -361,7 +361,7 @@ From ORT v1.19 onwards, the ONNX Runtime Mobile packages are no longer published From `/js/react_native, ```sh - yarn bootstrap + npm run bootstrap ``` When testing with a custom built ONNX Runtime Android package, copy `/aar_out/MinSizeRel/com/microsoft/onnxruntime/onnxruntime-android//onnxruntime-android-.aar` into the `/js/react_native/e2e/android/app/libs` directory. @@ -377,7 +377,7 @@ From ORT v1.19 onwards, the ONNX Runtime Mobile packages are no longer published Install detox command line tools: ``` - yarn global add detox-cli + npm install -g detox-cli ``` Install applesimutils which is required by Detox to work with iOS simulators. (Requires a MacOS device) @@ -439,13 +439,13 @@ From ORT v1.19 onwards, the ONNX Runtime Mobile packages are no longer published To record logs for testing results, add `--record-logs`. Output logs and test results will be produced in the `e2e/artifacts/` folder. See: [Detox/logger#artifacts](https://wix.github.io/Detox/docs/api/logger#artifacts) - **_`yarn bootstrap` changes `packages.json` and `yarn.lock` files. Once testing is done, restore changes to avoid unwanted commit._** + **_`npm run bootstrap` changes `packages.json` and `package-lock.json` files. Once testing is done, restore changes to avoid unwanted commit._** 5. Run Android and iOS apps. ```sh - yarn e2e android - yarn e2e ios + npm run e2e:android + npm run e2e:ios ``` ### NPM Packaging @@ -460,4 +460,4 @@ From ORT v1.19 onwards, the ONNX Runtime Mobile packages are no longer published ### Distribution -It should be able to consumed by React Native projects that uses Yarn packages through `yarn add onnxruntime-react-native`. +It should be able to consumed by React Native projects that uses npm packages through `npm install onnxruntime-react-native`. diff --git a/js/build_jsep.bat b/js/build_jsep.bat index ace96e978d934..fb94f0841ee01 100644 --- a/js/build_jsep.bat +++ b/js/build_jsep.bat @@ -64,8 +64,21 @@ popd set PATH=C:\Program Files\Git\usr\bin;%PATH% -call %ROOT%build.bat --config %CONFIG% %CONFIG_EXTRA_FLAG% --skip_submodule_sync --build_wasm --skip_tests^ - --enable_wasm_simd --enable_wasm_threads --use_jsep --use_webnn --target onnxruntime_webassembly --build_dir %BUILD_DIR% +call %ROOT%build.bat^ + --config %CONFIG%^ + %CONFIG_EXTRA_FLAG%^ + --parallel^ + --skip_submodule_sync^ + --build_wasm^ + --target onnxruntime_webassembly^ + --skip_tests^ + --enable_wasm_simd^ + --enable_wasm_threads^ + --use_jsep^ + --use_webnn^ + --build_dir %BUILD_DIR%^ + --include_ops_by_config %ROOT%onnxruntime\wasm\reduced_types.config^ + --enable_reduced_operator_type_support IF NOT "%ERRORLEVEL%" == "0" ( exit /b %ERRORLEVEL% diff --git a/js/build_webgpu.bat b/js/build_webgpu.bat new file mode 100644 index 0000000000000..5d017edbfa22b --- /dev/null +++ b/js/build_webgpu.bat @@ -0,0 +1,93 @@ +@echo off + +rem build_webgpu.bat --- build onnxruntime-web with WebGPU EP +rem +rem Usage: +rem build_webgpu.bat config [clean] +rem +rem Options: +rem config Build configuration, "d" or "r" +rem clean Perform a clean build, "clean" or empty + +setlocal enabledelayedexpansion + +set ROOT=%~dp0..\ +set BUILD_DIR=%ROOT%build_webgpu + +:arg1 +if ["%~1"]==["d"] ( + set CONFIG=Debug + set CONFIG_EXTRA_FLAG= + @rem --enable_wasm_profiling --wasm_run_tests_in_browser + @rem --cmake_extra_defines onnxruntime_ENABLE_WEBASSEMBLY_OUTPUT_OPTIMIZED_MODEL=1 + @rem --enable_wasm_debug_info + goto :arg2 +) +if ["%~1"]==["r"] ( + set CONFIG=Release + set CONFIG_EXTRA_FLAG= + @rem --enable_wasm_api_exception_catching --disable_rtti + goto :arg2 +) +echo Invalid configuration "%~1", must be "d"(Debug) or "r"(Release) +exit /b 1 + +:arg2 +if ["%~2"]==["clean"] ( + goto :clean +) +if not exist "%ROOT%js\web\dist" ( + goto :npm_ci +) + +goto :build_wasm + +:clean +if exist "%BUILD_DIR%" ( + rd /s /q %BUILD_DIR% +) + +pushd %ROOT% +git submodule sync --recursive +git submodule update --init --recursive +popd + +:npm_ci +pushd %ROOT%js +call npm ci +popd +pushd %ROOT%js\common +call npm ci +popd +pushd %ROOT%js\web +call npm ci +call npm run pull:wasm +popd + +:build_wasm + +set PATH=C:\Program Files\Git\usr\bin;%PATH% + +call %ROOT%build.bat^ + --config %CONFIG%^ + %CONFIG_EXTRA_FLAG%^ + --parallel^ + --skip_submodule_sync^ + --build_wasm^ + --target onnxruntime_webassembly^ + --skip_tests^ + --enable_wasm_simd^ + --enable_wasm_threads^ + --use_webnn^ + --use_webgpu^ + --enable_wasm_jspi^ + --build_dir %BUILD_DIR%^ + --include_ops_by_config %ROOT%onnxruntime\wasm\reduced_types.config^ + --enable_reduced_operator_type_support + +IF NOT "%ERRORLEVEL%" == "0" ( + exit /b %ERRORLEVEL% +) + +copy /Y %BUILD_DIR%\%CONFIG%\ort-wasm-simd-threaded.jspi.wasm %ROOT%js\web\dist\ +copy /Y %BUILD_DIR%\%CONFIG%\ort-wasm-simd-threaded.jspi.mjs %ROOT%js\web\dist\ diff --git a/js/build_webgpu.sh b/js/build_webgpu.sh new file mode 100755 index 0000000000000..1e9492d818680 --- /dev/null +++ b/js/build_webgpu.sh @@ -0,0 +1,121 @@ +#!/bin/bash +# Exit immediately if a command exits with a non-zero status. +set -e + +# build_webgpu.sh --- build onnxruntime-web with WebGPU EP +# +# Usage: +# build_webgpu.sh config [clean] +# +# Options: +# config Build configuration, "d" (Debug) or "r" (Release) +# clean Perform a clean build (optional) + +# Determine the root directory of the project (one level up from the script's directory) +ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" +BUILD_DIR="$ROOT_DIR/build_webgpu" + +CONFIG="" +CONFIG_EXTRA_FLAG="" # This will be empty by default + +# Parse config argument +if [ "$1" = "d" ]; then + CONFIG="Debug" + CONFIG_EXTRA_FLAG="--enable_wasm_profiling --wasm_run_tests_in_browser --cmake_extra_defines onnxruntime_ENABLE_WEBASSEMBLY_OUTPUT_OPTIMIZED_MODEL=1 --enable_wasm_debug_info" +elif [ "$1" = "r" ]; then + CONFIG="Release" + # CONFIG_EXTRA_FLAG="--enable_wasm_api_exception_catching --disable_rtti" + CONFIG_EXTRA_FLAG="--disable_rtti" +else + echo "Error: Invalid configuration \"$1\"." + echo "Configuration must be 'd' (Debug) or 'r' (Release)." + echo "Usage: $0 [d|r] [clean]" + exit 1 +fi + +CLEAN_BUILD_REQUESTED=false +if [ "$2" = "clean" ]; then + CLEAN_BUILD_REQUESTED=true +fi + +# Perform clean if requested +if [ "$CLEAN_BUILD_REQUESTED" = true ]; then + echo "--- Performing clean build ---" + if [ -d "$BUILD_DIR" ]; then + echo "Removing build directory: $BUILD_DIR" + rm -rf "$BUILD_DIR" + fi + + echo "Synchronizing and updating submodules..." + pushd "$ROOT_DIR" > /dev/null + git submodule sync --recursive + git submodule update --init --recursive + popd > /dev/null +fi + +# Determine if npm ci needs to be run +# It needs to run if: +# 1. A clean build was requested (which implies js/web/dist will be missing or stale) +# 2. The js/web/dist directory does not exist (e.g., first build or manually removed) +PERFORM_NPM_CI=false +if [ "$CLEAN_BUILD_REQUESTED" = true ]; then + PERFORM_NPM_CI=true +elif [ ! -d "$ROOT_DIR/js/web/dist" ]; then + echo "Directory $ROOT_DIR/js/web/dist not found." + PERFORM_NPM_CI=true +fi + +if [ "$PERFORM_NPM_CI" = true ]; then + echo "--- Running npm ci and pulling WASM artifacts ---" + echo "Running npm ci in $ROOT_DIR/js" + pushd "$ROOT_DIR/js" > /dev/null + npm ci + popd > /dev/null + + echo "Running npm ci in $ROOT_DIR/js/common" + pushd "$ROOT_DIR/js/common" > /dev/null + npm ci + popd > /dev/null + + echo "Running npm ci and pull:wasm in $ROOT_DIR/js/web" + pushd "$ROOT_DIR/js/web" > /dev/null + npm ci + npm run pull:wasm + popd > /dev/null +fi + +echo "--- Building WebAssembly modules ---" + +echo "Calling $ROOT_DIR/build.sh to build WebAssembly..." +# Note: If $CONFIG_EXTRA_FLAG is empty, it will be omitted from the command due to shell expansion. +"$ROOT_DIR/build.sh" \ + --config "$CONFIG" \ + --parallel \ + ${CONFIG_EXTRA_FLAG} \ + --skip_submodule_sync \ + --build_wasm \ + --target onnxruntime_webassembly \ + --skip_tests \ + --enable_wasm_simd \ + --enable_wasm_threads \ + --use_webnn \ + --use_webgpu \ + --enable_wasm_jspi \ + --build_dir "$BUILD_DIR" \ + --include_ops_by_config "$ROOT_DIR/onnxruntime/wasm/reduced_types.config" \ + --enable_reduced_operator_type_support + +# The 'set -e' command at the beginning of the script ensures that the script will exit +# immediately if the build.sh command (or any other command) fails. + +echo "--- Copying build artifacts ---" +# Ensure the dist directory exists before copying files +mkdir -p "$ROOT_DIR/js/web/dist" + +echo "Copying ort-wasm-simd-threaded.jspi.wasm to $ROOT_DIR/js/web/dist/" +cp -f "$BUILD_DIR/$CONFIG/ort-wasm-simd-threaded.jspi.wasm" "$ROOT_DIR/js/web/dist/" + +echo "Copying ort-wasm-simd-threaded.jspi.mjs to $ROOT_DIR/js/web/dist/" +cp -f "$BUILD_DIR/$CONFIG/ort-wasm-simd-threaded.jspi.mjs" "$ROOT_DIR/js/web/dist/" + +echo "--- WebGPU build process completed successfully ---" diff --git a/js/common/lib/backend.ts b/js/common/lib/backend.ts index e63f9c6c9147f..9b7c1db219188 100644 --- a/js/common/lib/backend.ts +++ b/js/common/lib/backend.ts @@ -23,6 +23,9 @@ interface SessionHandler { readonly inputNames: readonly string[]; readonly outputNames: readonly string[]; + + readonly inputMetadata: readonly InferenceSession.ValueMetadata[]; + readonly outputMetadata: readonly InferenceSession.ValueMetadata[]; } /** diff --git a/js/common/lib/env.ts b/js/common/lib/env.ts index d6d9f7fa48790..d41e0936f7fac 100644 --- a/js/common/lib/env.ts +++ b/js/common/lib/env.ts @@ -15,6 +15,8 @@ export declare namespace Env { * If not modified, the filename of the .wasm file is: * - `ort-wasm-simd-threaded.wasm` for default build * - `ort-wasm-simd-threaded.jsep.wasm` for JSEP build (with WebGPU and WebNN) + * - `ort-wasm-simd-threaded.asyncify.wasm` for WebGPU build with Asyncify (with WebNN) + * - `ort-wasm-simd-threaded.jspi.wasm` for WebGPU build with JSPI support (with WebNN) */ wasm?: URL | string; /** @@ -25,6 +27,8 @@ export declare namespace Env { * If not modified, the filename of the .mjs file is: * - `ort-wasm-simd-threaded.mjs` for default build * - `ort-wasm-simd-threaded.jsep.mjs` for JSEP build (with WebGPU and WebNN) + * - `ort-wasm-simd-threaded.asyncify.mjs` for WebGPU build with Asyncify (with WebNN) + * - `ort-wasm-simd-threaded.jspi.mjs` for WebGPU build with JSPI support (with WebNN) */ mjs?: URL | string; } @@ -41,16 +45,22 @@ export declare namespace Env { numThreads?: number; /** - * set or get a boolean value indicating whether to enable SIMD. If set to false, SIMD will be forcely disabled. + * set a value indicating whether to enable SIMD. + * + * ONNX Runtime will perform feature detection based on the value of this property. Specifically, when the value is + * set to: + * - `undefined`, `true` or `"fixed"`: will check availability of Fixed-width SIMD. + * - `"relaxed"`: will check availability of Relaxed SIMD. + * - `false`: will not perform SIMD feature checking. + * + * Setting this property does not make ONNX Runtime to switch to the corresponding runtime automatically. User need + * to set `wasmPaths` or `wasmBinary` property to load the corresponding runtime. * * This setting is available only when WebAssembly SIMD feature is available in current context. * * @defaultValue `true` - * - * @deprecated This property is deprecated. Since SIMD is supported by all major JavaScript engines, non-SIMD - * build is no longer provided. This property will be removed in future release. */ - simd?: boolean; + simd?: boolean | 'fixed' | 'relaxed'; /** * set or get a boolean value indicating whether to enable trace. diff --git a/js/common/lib/inference-session-impl.ts b/js/common/lib/inference-session-impl.ts index d47ed7a331045..877c595bffd15 100644 --- a/js/common/lib/inference-session-impl.ts +++ b/js/common/lib/inference-session-impl.ts @@ -6,7 +6,7 @@ import { InferenceSessionHandler } from './backend.js'; import { InferenceSession as InferenceSessionInterface } from './inference-session.js'; import { OnnxValue } from './onnx-value.js'; import { Tensor } from './tensor.js'; -import { TRACE_FUNC_BEGIN, TRACE_FUNC_END } from './trace.js'; +import { TRACE_FUNC_BEGIN, TRACE_FUNC_END, TRACE_EVENT_BEGIN, TRACE_EVENT_END } from './trace.js'; type SessionOptions = InferenceSessionInterface.SessionOptions; type RunOptions = InferenceSessionInterface.RunOptions; @@ -22,6 +22,7 @@ export class InferenceSession implements InferenceSessionInterface { run(feeds: FeedsType, fetches: FetchesType, options?: RunOptions): Promise; async run(feeds: FeedsType, arg1?: FetchesType | RunOptions, arg2?: RunOptions): Promise { TRACE_FUNC_BEGIN(); + TRACE_EVENT_BEGIN('InferenceSession.run'); const fetches: { [name: string]: OnnxValue | null } = {}; let options: RunOptions = {}; // check inputs @@ -120,6 +121,7 @@ export class InferenceSession implements InferenceSessionInterface { } } } + TRACE_EVENT_END('InferenceSession.run'); TRACE_FUNC_END(); return returnValue; } @@ -144,6 +146,7 @@ export class InferenceSession implements InferenceSessionInterface { arg3?: SessionOptions, ): Promise { TRACE_FUNC_BEGIN(); + TRACE_EVENT_BEGIN('InferenceSession.create'); // either load from a file or buffer let filePathOrUint8Array: string | Uint8Array; let options: SessionOptions = {}; @@ -207,6 +210,7 @@ export class InferenceSession implements InferenceSessionInterface { // resolve backend, update session options with validated EPs, and create session handler const [backend, optionsWithValidatedEPs] = await resolveBackendAndExecutionProviders(options); const handler = await backend.createInferenceSessionHandler(filePathOrUint8Array, optionsWithValidatedEPs); + TRACE_EVENT_END('InferenceSession.create'); TRACE_FUNC_END(); return new InferenceSession(handler); } @@ -225,5 +229,13 @@ export class InferenceSession implements InferenceSessionInterface { return this.handler.outputNames; } + get inputMetadata(): readonly InferenceSessionInterface.ValueMetadata[] { + return this.handler.inputMetadata; + } + + get outputMetadata(): readonly InferenceSessionInterface.ValueMetadata[] { + return this.handler.outputMetadata; + } + private handler: InferenceSessionHandler; } diff --git a/js/common/lib/inference-session.ts b/js/common/lib/inference-session.ts index e62c6579e8333..9503127006966 100644 --- a/js/common/lib/inference-session.ts +++ b/js/common/lib/inference-session.ts @@ -4,6 +4,7 @@ import { InferenceSession as InferenceSessionImpl } from './inference-session-impl.js'; import { OnnxModelOptions } from './onnx-model.js'; import { OnnxValue, OnnxValueDataLocation } from './onnx-value.js'; +import type { Tensor } from './tensor.js'; import { TryGetGlobalType } from './type-helper.js'; /* eslint-disable @typescript-eslint/no-redeclare */ @@ -80,7 +81,7 @@ export declare namespace InferenceSession { * * This setting is available only in ONNXRuntime (Node.js binding and react-native) or WebAssembly backend */ - graphOptimizationLevel?: 'disabled' | 'basic' | 'extended' | 'all'; + graphOptimizationLevel?: 'disabled' | 'basic' | 'extended' | 'layout' | 'all'; /** * Whether enable CPU memory arena. @@ -244,7 +245,37 @@ export declare namespace InferenceSession { } export interface WebGpuExecutionProviderOption extends ExecutionProviderOption { readonly name: 'webgpu'; + + /** + * Specify the preferred layout when running layout sensitive operators. + * + * @default 'NCHW' + */ preferredLayout?: 'NCHW' | 'NHWC'; + + /** + * Specify a list of node names that should be executed on CPU even when WebGPU EP is used. + */ + forceCpuNodeNames?: readonly string[]; + + /** + * Specify the validation mode for WebGPU execution provider. + * - 'disabled': Disable all validation. + * When used in Node.js, disable validation may cause process crash if WebGPU errors occur. Be cautious when using + * this mode. + * When used in web, this mode is equivalent to 'wgpuOnly'. + * - 'wgpuOnly': Perform WebGPU internal validation only. + * - 'basic': Perform basic validation including WebGPU internal validation. This is the default mode. + * - 'full': Perform full validation. This mode may have performance impact. Use it for debugging purpose. + * + * @default 'basic' + */ + validationMode?: 'disabled' | 'wgpuOnly' | 'basic' | 'full'; + + /** + * Specify an optional WebGPU device to be used by the WebGPU execution provider. + */ + device?: TryGetGlobalType<'GPUDevice'>; } // #region WebNN options @@ -308,7 +339,24 @@ export declare namespace InferenceSession { export interface QnnExecutionProviderOption extends ExecutionProviderOption { readonly name: 'qnn'; - // TODO add flags + /** + * Specify the QNN backend type. E.g., 'cpu' or 'htp'. + * Mutually exclusive with `backendPath`. + * + * @default 'htp' + */ + backendType?: string; + /** + * Specify a path to the QNN backend library. + * Mutually exclusive with `backendType`. + */ + backendPath?: string; + /** + * Specify whether to enable HTP FP16 precision. + * + * @default true + */ + enableFp16Precision?: boolean; } export interface CoreMLExecutionProviderOption extends ExecutionProviderOption { readonly name: 'coreml'; @@ -419,11 +467,53 @@ export declare namespace InferenceSession { // #region value metadata - // eslint-disable-next-line @typescript-eslint/no-empty-interface - interface ValueMetadata { - // TBD + /** + * The common part of the value metadata type for both tensor and non-tensor values. + */ + export interface ValueMetadataBase { + /** + * The name of the specified input or output. + */ + readonly name: string; + } + + /** + * Represents the metadata of a non-tensor value. + */ + export interface NonTensorValueMetadata extends ValueMetadataBase { + /** + * Get a value indicating whether the value is a tensor. + */ + readonly isTensor: false; } + /** + * Represents the metadata of a tensor value. + */ + export interface TensorValueMetadata extends ValueMetadataBase { + /** + * Get a value indicating whether the value is a tensor. + */ + readonly isTensor: true; + /** + * Get the data type of the tensor. + */ + readonly type: Tensor.Type; + /** + * Get the shape of the tensor. + * + * If the shape is not defined, the value will an empty array. Otherwise, it will be an array representing the shape + * of the tensor. Each element in the array can be a number or a string. If the element is a number, it represents + * the corresponding dimension size. If the element is a string, it represents a symbolic dimension. + */ + readonly shape: ReadonlyArray; + } + + /** + * Represents the metadata of a value. + */ + export type ValueMetadata = NonTensorValueMetadata | TensorValueMetadata; + // #endregion } @@ -494,15 +584,15 @@ export interface InferenceSession { */ readonly outputNames: readonly string[]; - // /** - // * Get input metadata of the loaded model. - // */ - // readonly inputMetadata: ReadonlyArray>; + /** + * Get input metadata of the loaded model. + */ + readonly inputMetadata: readonly InferenceSession.ValueMetadata[]; - // /** - // * Get output metadata of the loaded model. - // */ - // readonly outputMetadata: ReadonlyArray>; + /** + * Get output metadata of the loaded model. + */ + readonly outputMetadata: readonly InferenceSession.ValueMetadata[]; // #endregion } diff --git a/js/common/lib/tensor-conversion-impl.ts b/js/common/lib/tensor-conversion-impl.ts index 743d0e6b352c6..7d34fc723a43d 100644 --- a/js/common/lib/tensor-conversion-impl.ts +++ b/js/common/lib/tensor-conversion-impl.ts @@ -88,7 +88,7 @@ export const tensorToDataURL = (tensor: Tensor, options?: TensorToDataUrlOptions const G = ((tensor.data[gTensorPointer++] as number) - normBias[1]) * normMean[1]; // G value const B = ((tensor.data[bTensorPointer++] as number) - normBias[2]) * normMean[2]; // B value const A = aTensorPointer === -1 ? 255 : ((tensor.data[aTensorPointer++] as number) - normBias[3]) * normMean[3]; // A value - // eslint-disable-next-line @typescript-eslint/restrict-plus-operands + pixels2DContext.fillStyle = 'rgba(' + R + ',' + G + ',' + B + ',' + A + ')'; pixels2DContext.fillRect(j, i, 1, 1); } diff --git a/js/common/lib/tensor-impl-type-mapping.ts b/js/common/lib/tensor-impl-type-mapping.ts index 14dbdca707220..58f4cc6281b09 100644 --- a/js/common/lib/tensor-impl-type-mapping.ts +++ b/js/common/lib/tensor-impl-type-mapping.ts @@ -44,12 +44,6 @@ export const NUMERIC_TENSOR_TYPEDARRAY_TO_TYPE_MAP = new Map { isTypedArrayChecked = true; const isBigInt64ArrayAvailable = typeof BigInt64Array !== 'undefined' && BigInt64Array.from; const isBigUint64ArrayAvailable = typeof BigUint64Array !== 'undefined' && BigUint64Array.from; + + // eslint-disable-next-line @typescript-eslint/naming-convention, @typescript-eslint/no-explicit-any + const Float16Array = (globalThis as any).Float16Array; const isFloat16ArrayAvailable = typeof Float16Array !== 'undefined' && Float16Array.from; if (isBigInt64ArrayAvailable) { diff --git a/js/common/lib/tensor-impl.ts b/js/common/lib/tensor-impl.ts index 8feb8d7205fa1..2c54bdbfb6874 100644 --- a/js/common/lib/tensor-impl.ts +++ b/js/common/lib/tensor-impl.ts @@ -261,6 +261,13 @@ export class Tensor implements TensorInterface { } else { throw new TypeError(`A Uint8ClampedArray tensor's data must be type of uint8`); } + } else if (arg0 === 'float16' && arg1 instanceof Uint16Array && typedArrayConstructor !== Uint16Array) { + // when Float16Array is available and data is of type Uint16Array. + // We allow Uint16Array to be passed in as data for 'float16' tensor until Float16Array is generally + // supported in JavaScript environment. + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + data = new (globalThis as any).Float16Array(arg1.buffer, arg1.byteOffset, arg1.length); } else { throw new TypeError(`A ${type} tensor's data must be type of ${typedArrayConstructor}`); } diff --git a/js/common/lib/trace.ts b/js/common/lib/trace.ts index 25d178f15a29d..0f20dd39935ac 100644 --- a/js/common/lib/trace.ts +++ b/js/common/lib/trace.ts @@ -51,3 +51,25 @@ export const TRACE_FUNC_END = (extraMsg?: string) => { } TRACE_FUNC('END', extraMsg); }; + +/** + * @ignore + */ +export const TRACE_EVENT_BEGIN = (extraMsg?: string) => { + if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) { + return; + } + // eslint-disable-next-line no-console + console.time(`ORT::${extraMsg}`); +}; + +/** + * @ignore + */ +export const TRACE_EVENT_END = (extraMsg?: string) => { + if (typeof env.trace === 'undefined' ? !env.wasm.trace : !env.trace) { + return; + } + // eslint-disable-next-line no-console + console.timeEnd(`ORT::${extraMsg}`); +}; diff --git a/js/common/lib/version.ts b/js/common/lib/version.ts index 475dfe0d4888b..1c679620af4b1 100644 --- a/js/common/lib/version.ts +++ b/js/common/lib/version.ts @@ -4,4 +4,4 @@ // This file is generated by /js/scripts/update-version.ts // Do not modify file content manually. -export const version = '1.21.0'; +export const version = '1.27.0'; diff --git a/js/common/package-lock.json b/js/common/package-lock.json index 4d92e0f73aa69..0c63997a2b8fa 100644 --- a/js/common/package-lock.json +++ b/js/common/package-lock.json @@ -1,17 +1,69 @@ { "name": "onnxruntime-common", - "version": "1.21.0", + "version": "1.27.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "onnxruntime-common", - "version": "1.21.0", + "version": "1.27.0", "license": "MIT", "devDependencies": { + "globby": "^15.0.0", "typedoc": "^0.25.7" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-sequence-parser": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", @@ -25,14 +77,145 @@ "dev": true }, "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/globby": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-15.0.0.tgz", + "integrity": "sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/merge-streams": "^4.0.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.5", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/jsonc-parser": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", @@ -57,13 +240,38 @@ "node": ">= 12" } }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, "node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -72,6 +280,87 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/shiki": { "version": "0.14.7", "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.7.tgz", @@ -84,6 +373,32 @@ "vscode-textmate": "^8.0.0" } }, + "node_modules/slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/typedoc": { "version": "0.25.7", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.7.tgz", @@ -119,6 +434,19 @@ "node": ">=14.17" } }, + "node_modules/unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", @@ -133,6 +461,38 @@ } }, "dependencies": { + "@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + } + }, + "@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true + }, + "@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "requires": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + } + }, + "@sindresorhus/merge-streams": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/merge-streams/-/merge-streams-4.0.0.tgz", + "integrity": "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ==", + "dev": true + }, "ansi-sequence-parser": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", @@ -146,14 +506,104 @@ "dev": true }, "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "requires": { "balanced-match": "^1.0.0" } }, + "braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "requires": { + "fill-range": "^7.1.1" + } + }, + "fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "requires": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + } + }, + "fastq": { + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", + "dev": true, + "requires": { + "reusify": "^1.0.4" + } + }, + "fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "requires": { + "to-regex-range": "^5.0.1" + } + }, + "glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "requires": { + "is-glob": "^4.0.1" + } + }, + "globby": { + "version": "15.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-15.0.0.tgz", + "integrity": "sha512-oB4vkQGqlMl682wL1IlWd02tXCbquGWM4voPEI85QmNKCaw8zGTm1f1rubFgkg3Eli2PtKlFgrnmUqasbQWlkw==", + "dev": true, + "requires": { + "@sindresorhus/merge-streams": "^4.0.0", + "fast-glob": "^3.3.3", + "ignore": "^7.0.5", + "path-type": "^6.0.0", + "slash": "^5.1.0", + "unicorn-magic": "^0.3.0" + } + }, + "ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true + }, + "is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true + }, + "is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "requires": { + "is-extglob": "^2.1.1" + } + }, + "is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true + }, "jsonc-parser": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", @@ -172,13 +622,62 @@ "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true }, + "merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true + }, + "micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "requires": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + } + }, "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "requires": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" + } + }, + "path-type": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-6.0.0.tgz", + "integrity": "sha512-Vj7sf++t5pBD637NSfkxpHSMfWaeig5+DKWLhcqIYx6mWQz5hdJTGDVMQiJcw1ZYkhs7AazKDGpRVji1LJCZUQ==", + "dev": true + }, + "picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "dev": true + }, + "queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true + }, + "reusify": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true + }, + "run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "requires": { + "queue-microtask": "^1.2.2" } }, "shiki": { @@ -193,6 +692,21 @@ "vscode-textmate": "^8.0.0" } }, + "slash": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-5.1.0.tgz", + "integrity": "sha512-ZA6oR3T/pEyuqwMgAKT0/hAv8oAXckzbkmR0UkUosQ+Mc4RxGoJkRmwHgHufaenlyAgE1Mxgpdcrf75y6XcnDg==", + "dev": true + }, + "to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "requires": { + "is-number": "^7.0.0" + } + }, "typedoc": { "version": "0.25.7", "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.7.tgz", @@ -212,6 +726,12 @@ "dev": true, "peer": true }, + "unicorn-magic": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/unicorn-magic/-/unicorn-magic-0.3.0.tgz", + "integrity": "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA==", + "dev": true + }, "vscode-oniguruma": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", diff --git a/js/common/package.json b/js/common/package.json index 2e2161c74158c..c038faeb1b6cd 100644 --- a/js/common/package.json +++ b/js/common/package.json @@ -2,7 +2,7 @@ "license": "MIT", "type": "module", "name": "onnxruntime-common", - "version": "1.21.0", + "version": "1.27.0", "repository": { "url": "https://github.com/Microsoft/onnxruntime.git", "type": "git" @@ -15,9 +15,11 @@ "build": "node ./build.js", "prepare": "npm run build", "pretest": "tsc --build ./test", - "test": "mocha ./test/**/*.js --timeout 30000" + "test": "mocha \"./test/**/*.js\" --timeout 30000", + "test:f16": "mocha -n js-float16array \"./test/**/*.js\" --timeout 30000" }, "devDependencies": { + "globby": "^15.0.0", "typedoc": "^0.25.7" }, "main": "dist/cjs/index.js", diff --git a/js/common/test/type-tests.ts b/js/common/test/type-tests.ts index 70681bb420e5f..a4bab8a804eeb 100644 --- a/js/common/test/type-tests.ts +++ b/js/common/test/type-tests.ts @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -import globby from 'globby'; +import { globbySync } from 'globby'; import assert from 'node:assert'; import { readFileSync } from 'node:fs'; import { dirname, join, normalize, relative } from 'node:path'; @@ -47,7 +47,7 @@ const TYPE_TESTS_DIR = join(dirname(fileURLToPath(import.meta.url)), './type-tes */ const prepareTestFileList = () => // - globby.sync('**/*.ts', { + globbySync('**/*.ts', { cwd: TYPE_TESTS_DIR, absolute: true, }); diff --git a/js/common/test/unit-tests/common.ts b/js/common/test/unit-tests/common.ts index 0a6e4e5dd6ebd..bbbceed605bd4 100644 --- a/js/common/test/unit-tests/common.ts +++ b/js/common/test/unit-tests/common.ts @@ -29,9 +29,10 @@ export const NUMBER_COMPATIBLE_NUMERICAL_TYPES = [ export const BIGINT_TYPES = [['int64', BigInt64Array, true] as const, ['uint64', BigUint64Array, true] as const]; /** - * float16 type, data represented by Uint16Array + * float16 type, data represented by Uint16Array/Float16Array */ -export const FLOAT16_TYPE = ['float16', Uint16Array, false] as const; +// eslint-disable-next-line @typescript-eslint/no-explicit-any +export const FLOAT16_TYPE = ['float16', (globalThis as any).Float16Array ?? Uint16Array, false] as const; /** * A list of all numerical types. diff --git a/js/common/test/unit-tests/tensor/constructor-f16.ts b/js/common/test/unit-tests/tensor/constructor-f16.ts new file mode 100644 index 0000000000000..38c6ac037c5f9 --- /dev/null +++ b/js/common/test/unit-tests/tensor/constructor-f16.ts @@ -0,0 +1,62 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import assert from 'assert/strict'; +import { Tensor } from 'onnxruntime-common'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const globalF16 = (globalThis as any).Float16Array; + +(globalF16 ? describe : describe.skip)('Tensor Constructor Tests - check type float16 (Float16Array available)', () => { + it("[float16] new Tensor('float16', numbers, dims): allow number array when Float16Array is available", () => { + const tensor = new Tensor('float16', [1, 2, 3, 4], [2, 2]); + assert.equal(tensor.type, 'float16', "tensor.type should be 'float16'"); + assert(tensor.data instanceof globalF16, "tensor.data should be an instance of 'Float16Array'"); + assert.equal(tensor.data[0], 1, 'tensor.data[0] should be 1'); + assert.equal(tensor.data[1], 2, 'tensor.data[1] should be 2'); + assert.equal(tensor.data[2], 3, 'tensor.data[2] should be 3'); + assert.equal(tensor.data[3], 4, 'tensor.data[3] should be 4'); + assert.equal(tensor.data.length, 4, 'tensor.data.length should be 4'); + }); + + it("[float16] new Tensor('float16', float16array, dims): allow Float16Array when Float16Array is available", () => { + const tensor = new Tensor('float16', new globalF16([1, 2, 3, 4]), [2, 2]); + assert.equal(tensor.type, 'float16', "tensor.type should be 'float16'"); + assert(tensor.data instanceof globalF16, "tensor.data should be an instance of 'Float16Array'"); + assert.equal(tensor.data[0], 1, 'tensor.data[0] should be 1'); + assert.equal(tensor.data[1], 2, 'tensor.data[1] should be 2'); + assert.equal(tensor.data[2], 3, 'tensor.data[2] should be 3'); + assert.equal(tensor.data[3], 4, 'tensor.data[3] should be 4'); + assert.equal(tensor.data.length, 4, 'tensor.data.length should be 4'); + }); + + it("[float16] new Tensor('float16', uint16array, dims): allow Uint16Array when Float16Array is available", () => { + const tensor = new Tensor('float16', new Uint16Array([15360, 16384, 16896, 17408]), [2, 2]); + assert.equal(tensor.type, 'float16', "tensor.type should be 'float16'"); + assert(tensor.data instanceof globalF16, "tensor.data should be an instance of 'Float16Array'"); + assert.equal(tensor.data[0], 1, 'tensor.data[0] should be 1'); + assert.equal(tensor.data[1], 2, 'tensor.data[1] should be 2'); + assert.equal(tensor.data[2], 3, 'tensor.data[2] should be 3'); + assert.equal(tensor.data[3], 4, 'tensor.data[3] should be 4'); + assert.equal(tensor.data.length, 4, 'tensor.data.length should be 4'); + }); +}); + +(globalF16 ? describe.skip : describe)( + 'Tensor Constructor Tests - check type float16 (Float16Array not available)', + () => { + it( + "[float16] new Tensor('float16', numbers, dims): " + + "expect to throw because it's not allowed to construct 'float16' tensor from number array", + () => { + assert.throws(() => new Tensor('float16', [1, 2, 3, 4], [2, 2]), TypeError); + }, + ); + + it("[float16] new Tensor('float16', uint16array, dims): allow Uint16Array", () => { + const tensor = new Tensor('float16', new Uint16Array([15360, 16384, 16896, 17408]), [2, 2]); + assert.equal(tensor.type, 'float16', "tensor.type should be 'float16'"); + assert(tensor.data instanceof Uint16Array, "tensor.data should be an instance of 'Uint16Array'"); + }); + }, +); diff --git a/js/common/test/unit-tests/tensor/constructor-type.ts b/js/common/test/unit-tests/tensor/constructor-type.ts index 02390800e8611..d86e18ba744b8 100644 --- a/js/common/test/unit-tests/tensor/constructor-type.ts +++ b/js/common/test/unit-tests/tensor/constructor-type.ts @@ -105,14 +105,6 @@ describe('Tensor Constructor Tests - check types', () => { assert(tensor.data instanceof Uint8Array, "tensor.data should be an instance of 'Uint8Array'"); }); - it( - "[float16] new Tensor('float16', numbers, dims): " + - "expect to throw because it's not allowed to construct 'float16' tensor from number array", - () => { - assert.throws(() => new Tensor('float16', [1, 2, 3, 4], [2, 2]), TypeError); - }, - ); - it("[badtype] new Tensor('a', numbers, dims): expect to throw because 'a' is an invalid type", () => { assert.throws(() => new TensorAny('a', [1, 2, 3, 4], [2, 2]), TypeError); }); diff --git a/js/eslint.config.mjs b/js/eslint.config.mjs new file mode 100644 index 0000000000000..dde4a4dd76eca --- /dev/null +++ b/js/eslint.config.mjs @@ -0,0 +1,364 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import typescriptEslint from '@typescript-eslint/eslint-plugin'; +import preferArrow from 'eslint-plugin-prefer-arrow'; +import header from 'eslint-plugin-header'; +import _import from 'eslint-plugin-import'; +import unicorn from 'eslint-plugin-unicorn'; +import jsdoc from 'eslint-plugin-jsdoc'; +import { fixupPluginRules } from '@eslint/compat'; +import tsParser from '@typescript-eslint/parser'; +import globals from 'globals'; +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import js from '@eslint/js'; +import { FlatCompat } from '@eslint/eslintrc'; + +const __filename = fileURLToPath(import.meta.url); +const __dirname = path.dirname(__filename); +const compat = new FlatCompat({ + baseDirectory: __dirname, + recommendedConfig: js.configs.recommended, + allConfig: js.configs.all, +}); + +// eslint-plugin-header does not support ESLint 9 yet, but the following workaround is available: +// https://github.com/Stuk/eslint-plugin-header/issues/57#issuecomment-2378485611 +header.rules.header.meta.schema = false; + +export default [ + { + ignores: [ + '**/*.js', + '**/*.mjs', + 'eslint.config.mjs', + '**/node_modules/', + '**/ort-schema/', + 'common/test/type-tests/', + 'web/types.d.ts', + 'test/data/', + '**/dist/', + ], + }, + ...compat.extends( + 'eslint:recommended', + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + ), + { + plugins: { + '@typescript-eslint': typescriptEslint, + 'prefer-arrow': preferArrow, + header, + import: fixupPluginRules(_import), + unicorn, + jsdoc, + }, + + languageOptions: { + globals: {}, + parser: tsParser, + ecmaVersion: 5, + sourceType: 'module', + + parserOptions: { + project: true, + }, + }, + + rules: { + 'unicorn/filename-case': 'error', + + 'header/header': [ + 2, + 'line', + [' Copyright (c) Microsoft Corporation. All rights reserved.', ' Licensed under the MIT License.'], + 2, + ], + + 'import/no-extraneous-dependencies': [ + 'error', + { + devDependencies: false, + }, + ], + + 'import/no-internal-modules': [ + 'error', + { + allow: ['**/lib/**'], + }, + ], + + 'import/no-unassigned-import': 'error', + + '@typescript-eslint/array-type': [ + 'error', + { + default: 'array-simple', + }, + ], + + '@typescript-eslint/await-thenable': 'error', + + '@typescript-eslint/no-empty-object-type': 'error', + + '@typescript-eslint/no-wrapper-object-types': 'error', + + '@typescript-eslint/naming-convention': 'error', + '@typescript-eslint/consistent-type-assertions': 'error', + + '@typescript-eslint/no-empty-function': 'error', + '@typescript-eslint/no-explicit-any': 'error', + '@typescript-eslint/no-floating-promises': 'error', + '@typescript-eslint/no-for-in-array': 'error', + '@typescript-eslint/no-inferrable-types': 'error', + '@typescript-eslint/no-misused-new': 'error', + + '@typescript-eslint/no-namespace': [ + 'error', + { + allowDeclarations: true, + }, + ], + + '@typescript-eslint/no-non-null-assertion': 'off', + + '@typescript-eslint/no-require-imports': [ + 'error', + { + allow: ['^node:'], + }, + ], + + '@typescript-eslint/no-var-requires': [ + 'error', + { + allow: ['^node:'], + }, + ], + + '@typescript-eslint/no-unnecessary-type-assertion': 'error', + + '@typescript-eslint/no-unused-vars': [ + 'error', + { + argsIgnorePattern: '^_', + }, + ], + + '@typescript-eslint/promise-function-async': 'error', + '@typescript-eslint/restrict-plus-operands': 'error', + + '@typescript-eslint/triple-slash-reference': [ + 'error', + { + path: 'always', + types: 'prefer-import', + lib: 'always', + }, + ], + + 'arrow-body-style': 'error', + camelcase: 'error', + 'constructor-super': 'error', + curly: 'error', + 'default-case': 'error', + 'dot-notation': 'error', + eqeqeq: ['error', 'smart'], + 'guard-for-in': 'error', + 'id-match': 'error', + 'new-parens': 'error', + 'no-bitwise': 'error', + 'no-caller': 'error', + 'no-cond-assign': 'error', + 'no-console': 'error', + 'no-constant-condition': 'error', + 'no-control-regex': 'error', + 'no-debugger': 'error', + 'no-duplicate-case': 'error', + 'no-empty': 'error', + 'no-eval': 'error', + 'no-extra-bind': 'error', + 'no-invalid-regexp': 'error', + 'no-invalid-this': 'error', + 'no-multiple-empty-lines': 'error', + 'no-new-func': 'error', + 'no-new-wrappers': 'error', + 'no-octal': 'error', + 'no-octal-escape': 'error', + 'no-param-reassign': 'error', + 'no-redeclare': 'off', + '@typescript-eslint/no-redeclare': ['error'], + 'no-regex-spaces': 'error', + 'no-return-await': 'error', + 'no-sparse-arrays': 'error', + 'no-template-curly-in-string': 'error', + 'no-throw-literal': 'error', + 'no-undef-init': 'error', + 'no-underscore-dangle': 'error', + 'no-unsafe-finally': 'error', + 'no-unused-expressions': 'error', + 'no-unused-labels': 'error', + 'no-use-before-define': 'off', + '@typescript-eslint/no-use-before-define': 'error', + 'no-var': 'error', + 'object-shorthand': 'error', + 'prefer-arrow/prefer-arrow-functions': 'error', + 'prefer-const': 'error', + radix: 'error', + 'use-isnan': 'error', + }, + }, + { + files: ['node/**/*.ts'], + + languageOptions: { + globals: { + ...globals.node, + }, + }, + }, + { + files: ['common/lib/**/*.ts', 'node/lib/**/*.ts'], + + rules: { + 'jsdoc/check-alignment': 'error', + 'jsdoc/check-indentation': 'error', + }, + }, + { + files: ['common/test/**/*.ts'], + + rules: { + '@typescript-eslint/naming-convention': 'off', + 'import/no-extraneous-dependencies': 'off', + }, + }, + { + files: ['node/script/**/*.ts', 'node/test/**/*.ts', 'web/script/**/*.ts', 'web/test/**/*.ts'], + + rules: { + '@typescript-eslint/naming-convention': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-require-imports': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-unnecessary-type-assertion': 'off', + camelcase: 'off', + 'prefer-arrow/prefer-arrow-functions': 'off', + 'import/no-extraneous-dependencies': 'off', + 'import/no-unassigned-import': 'off', + 'import/no-internal-modules': 'off', + 'no-console': 'off', + 'no-empty': 'off', + 'no-unused-expressions': 'off', + }, + }, + { + files: ['web/lib/**/*.ts'], + + rules: { + 'no-underscore-dangle': [ + 'error', + { + allow: [ + '_free', + '_malloc', + '_JsepGetNodeName', + '_JsepOutput', + '_OrtAddFreeDimensionOverride', + '_OrtAddRunConfigEntry', + '_OrtAddSessionConfigEntry', + '_OrtAppendExecutionProvider', + '_OrtBindInput', + '_OrtBindOutput', + '_OrtClearBoundOutputs', + '_OrtCreateBinding', + '_OrtCreateRunOptions', + '_OrtCreateSession', + '_OrtCreateSessionOptions', + '_OrtCreateTensor', + '_OrtEndProfiling', + '_OrtFree', + '_OrtGetInputName', + '_OrtGetInputOutputCount', + '_OrtGetInputOutputMetadata', + '_OrtGetLastError', + '_OrtGetOutputName', + '_OrtGetTensorData', + '_OrtInit', + '_OrtReleaseBinding', + '_OrtReleaseRunOptions', + '_OrtReleaseSession', + '_OrtReleaseSessionOptions', + '_OrtReleaseTensor', + '_OrtRun', + '_OrtRunWithBinding', + ], + }, + ], + }, + }, + { + files: ['web/lib/onnxjs/**/*.ts'], + + rules: { + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-use-before-define': 'off', + '@typescript-eslint/no-unnecessary-type-assertion': 'off', + '@typescript-eslint/restrict-plus-operands': 'off', + 'import/no-internal-modules': 'off', + 'prefer-arrow/prefer-arrow-functions': 'off', + 'no-param-reassign': 'off', + 'no-underscore-dangle': 'off', + 'guard-for-in': 'off', + }, + }, + { + files: ['react_native/e2e/src/**/*.ts', 'react_native/e2e/src/**/*.tsx'], + + rules: { + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/no-unnecessary-type-assertion': 'off', + 'unicorn/filename-case': 'off', + 'no-invalid-this': 'off', + 'no-console': 'off', + }, + }, + { + files: ['react_native/lib/**/*.ts'], + + rules: { + '@typescript-eslint/naming-convention': 'off', + }, + }, + { + files: ['react_native/scripts/**/*.ts'], + + rules: { + 'import/no-extraneous-dependencies': 'off', + 'prefer-arrow/prefer-arrow-functions': 'off', + 'no-console': 'off', + }, + }, + { + files: ['scripts/**/*.ts'], + + rules: { + 'import/no-extraneous-dependencies': 'off', + 'no-console': 'off', + }, + }, + { + files: ['web/lib/**/3rd-party/**/*.ts'], + + rules: { + 'header/header': 'off', + 'unicorn/filename-case': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + }, + }, +]; diff --git a/js/node/CMakeLists.txt b/js/node/CMakeLists.txt index c78b40a3e7429..845d1a80b7b8f 100644 --- a/js/node/CMakeLists.txt +++ b/js/node/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.11) project (onnxruntime-node) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) add_compile_definitions(NAPI_VERSION=${napi_build_version}) add_compile_definitions(ORT_API_MANUAL_INIT) @@ -12,7 +12,7 @@ execute_process(COMMAND node -e "console.log(process.platform)" OUTPUT_VARIABLE node_platform OUTPUT_STRIP_TRAILING_WHITESPACE) file(READ ${CMAKE_SOURCE_DIR}/../../VERSION_NUMBER ort_version) string(STRIP "${ort_version}" ort_version) -set(dist_folder "${CMAKE_SOURCE_DIR}/bin/napi-v3/${node_platform}/${NODE_ARCH}/") +set(dist_folder "${CMAKE_SOURCE_DIR}/bin/napi-v6/${node_platform}/${NODE_ARCH}/") # onnxruntime.dll dir if(NOT ONNXRUNTIME_BUILD_DIR) @@ -92,9 +92,21 @@ if (WIN32) endif() message(STATUS "onnxruntime dist dir: ${ONNXRUNTIME_WIN_BIN_DIR}") endif() + +if (APPLE) + if (${ONNXRUNTIME_GENERATOR} MATCHES "Xcode") + set(ONNXRUNTIME_MAC_BIN_DIR ${ONNXRUNTIME_BUILD_DIR}/${CMAKE_BUILD_TYPE}) + else() + set(ONNXRUNTIME_MAC_BIN_DIR ${ONNXRUNTIME_BUILD_DIR}) + endif() + message(STATUS "onnxruntime dist dir: ${ONNXRUNTIME_MAC_BIN_DIR}") +endif() + # add libraries if (WIN32) target_link_directories(onnxruntime_binding PRIVATE ${ONNXRUNTIME_WIN_BIN_DIR}) +elseif (APPLE) + target_link_directories(onnxruntime_binding PRIVATE ${ONNXRUNTIME_MAC_BIN_DIR}) else() target_link_directories(onnxruntime_binding PRIVATE ${ONNXRUNTIME_BUILD_DIR}) endif() @@ -113,14 +125,8 @@ endif() if (WIN32) file(COPY ${ONNXRUNTIME_WIN_BIN_DIR}/onnxruntime.dll DESTINATION ${dist_folder}) - if (ORT_NODEJS_DLL_DEPS) - foreach(dll ${ORT_NODEJS_DLL_DEPS}) - file(COPY ${dll} DESTINATION ${dist_folder}) - endforeach() - endif() - elseif (APPLE) - file(COPY ${ONNXRUNTIME_BUILD_DIR}/libonnxruntime.dylib + file(COPY ${ONNXRUNTIME_MAC_BIN_DIR}/libonnxruntime.dylib DESTINATION ${dist_folder} FOLLOW_SYMLINK_CHAIN) elseif (UNIX) file(COPY ${ONNXRUNTIME_BUILD_DIR}/libonnxruntime.so @@ -128,3 +134,9 @@ elseif (UNIX) else() message(FATAL_ERROR "Platform not supported.") endif() + +if (ORT_NODEJS_DLL_DEPS) + foreach(dll ${ORT_NODEJS_DLL_DEPS}) + file(COPY ${dll} DESTINATION ${dist_folder}) + endforeach() +endif() diff --git a/js/node/README.md b/js/node/README.md index abb91bf05ddf1..272ec6ef561c2 100644 --- a/js/node/README.md +++ b/js/node/README.md @@ -10,6 +10,12 @@ Install the latest stable version: npm install onnxruntime-node ``` +Install the nightly version: + +``` +npm install onnxruntime-node@dev +``` + Refer to [ONNX Runtime JavaScript examples](https://github.com/microsoft/onnxruntime-inference-examples/tree/main/js) for samples and tutorials. ## Requirements @@ -18,33 +24,33 @@ ONNXRuntime works on Node.js v16.x+ (recommend v20.x+) or Electron v15.x+ (recom The following table lists the supported versions of ONNX Runtime Node.js binding provided with pre-built binaries. -| EPs/Platforms | Windows x64 | Windows arm64 | Linux x64 | Linux arm64 | MacOS x64 | MacOS arm64 | -| ------------- | ----------- | ------------- | ----------------- | ----------- | --------- | ----------- | -| CPU | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | -| DirectML | ✔️ | ✔️ | ❌ | ❌ | ❌ | ❌ | -| CUDA | ❌ | ❌ | ✔️\[1] | ❌ | ❌ | ❌ | +| EPs/Platforms | Windows x64 | Windows arm64 | Linux x64 | Linux arm64 | MacOS x64 | MacOS arm64 | +| ------------- | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | ------------------ | +| CPU | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | ✔️ | +| WebGPU | ✔️ \[1] | ✔️ \[1] | ✔️ \[1] | ❌ \[2] | ✔️ \[1] | ✔️ \[1] | +| DirectML | ✔️ | ✔️ | ❌ | ❌ | ❌ | ❌ | +| CUDA | ❌ | ❌ | ✔️\[3] | ❌ | ❌ | ❌ | +| CoreML | ❌ | ❌ | ❌ | ❌ | ✔️ | ✔️ | -- \[1]: CUDA v11.8. +- \[1]: WebGPU support is currently experimental. +- \[2]: WebGPU support is not available on Linux arm64 yet in the pre-built binaries. +- \[3]: CUDA v12. See [CUDA EP Installation](#cuda-ep-installation) for details. To use on platforms without pre-built binaries, you can build Node.js binding from source and consume it by `npm install /js/node/`. See also [instructions](https://onnxruntime.ai/docs/build/inferencing.html#apis-and-language-bindings) for building ONNX Runtime Node.js binding locally. # GPU Support -Right now, the Windows version supports only the DML provider. Linux x64 can use CUDA and TensorRT. +Right now, the Windows version supports WebGPU execution provider and DML execution provider. Linux x64 can use CUDA and TensorRT. ## CUDA EP Installation -To use CUDA EP, you need to install the CUDA EP binaries. By default, the CUDA EP binaries are installed automatically when you install the package. If you want to skip the installation, you can pass the `--onnxruntime-node-install-cuda=skip` flag to the installation command. +To use CUDA EP, you need to install the CUDA EP binaries. By default, the CUDA EP binaries are installed automatically when you install the package. If you want to skip the installation, you can pass the `--onnxruntime-node-install=skip` flag to the installation command. ``` -npm install onnxruntime-node --onnxruntime-node-install-cuda=skip +npm install onnxruntime-node --onnxruntime-node-install=skip ``` -You can also use this flag to specify the version of the CUDA: (v11 or v12) - -``` -npm install onnxruntime-node --onnxruntime-node-install-cuda=v12 -``` +~~You can also use this flag to specify the version of the CUDA: (v11 or v12)~~ CUDA v11 is no longer supported since v1.22. ## License diff --git a/js/node/lib/backend.ts b/js/node/lib/backend.ts index 004a3c890a7e4..bea9debcfdd4d 100644 --- a/js/node/lib/backend.ts +++ b/js/node/lib/backend.ts @@ -5,6 +5,32 @@ import { Backend, InferenceSession, InferenceSessionHandler, SessionHandler } fr import { Binding, binding, initOrt } from './binding'; +const dataTypeStrings = [ + undefined, // 0 + 'float32', + 'uint8', + 'int8', + 'uint16', + 'int16', + 'int32', + 'int64', + 'string', + 'bool', + 'float16', + 'float64', + 'uint32', + 'uint64', + undefined, // 14 + undefined, // 15 + undefined, // 16 + undefined, // 17 + undefined, // 18 + undefined, // 19 + undefined, // 20 + 'uint4', + 'int4', +] as const; + class OnnxruntimeSessionHandler implements InferenceSessionHandler { #inferenceSession: Binding.InferenceSession; @@ -17,8 +43,56 @@ class OnnxruntimeSessionHandler implements InferenceSessionHandler { } else { this.#inferenceSession.loadModel(pathOrBuffer.buffer, pathOrBuffer.byteOffset, pathOrBuffer.byteLength, options); } - this.inputNames = this.#inferenceSession.inputNames; - this.outputNames = this.#inferenceSession.outputNames; + + // prepare input/output names and metadata + this.inputNames = []; + this.outputNames = []; + this.inputMetadata = []; + this.outputMetadata = []; + + // this function takes raw metadata from binding and returns a tuple of the following 2 items: + // - an array of string representing names + // - an array of converted InferenceSession.ValueMetadata + const fillNamesAndMetadata = ( + rawMetadata: readonly Binding.ValueMetadata[], + ): [names: string[], metadata: InferenceSession.ValueMetadata[]] => { + const names: string[] = []; + const metadata: InferenceSession.ValueMetadata[] = []; + + for (const m of rawMetadata) { + names.push(m.name); + if (!m.isTensor) { + metadata.push({ name: m.name, isTensor: false }); + } else { + const type = dataTypeStrings[m.type]; + if (type === undefined) { + throw new Error(`Unsupported data type: ${m.type}`); + } + const shape: Array = []; + for (let i = 0; i < m.shape.length; ++i) { + const dim = m.shape[i]; + if (dim === -1) { + shape.push(m.symbolicDimensions[i]); + } else if (dim >= 0) { + shape.push(dim); + } else { + throw new Error(`Invalid dimension: ${dim}`); + } + } + metadata.push({ + name: m.name, + isTensor: m.isTensor, + type, + shape, + }); + } + } + + return [names, metadata]; + }; + + [this.inputNames, this.inputMetadata] = fillNamesAndMetadata(this.#inferenceSession.inputMetadata); + [this.outputNames, this.outputMetadata] = fillNamesAndMetadata(this.#inferenceSession.outputMetadata); } async dispose(): Promise { @@ -28,6 +102,9 @@ class OnnxruntimeSessionHandler implements InferenceSessionHandler { readonly inputNames: string[]; readonly outputNames: string[]; + readonly inputMetadata: InferenceSession.ValueMetadata[]; + readonly outputMetadata: InferenceSession.ValueMetadata[]; + startProfiling(): void { // startProfiling is a no-op. // diff --git a/js/node/lib/binding.ts b/js/node/lib/binding.ts index 56203f5a5ca02..fc1a69e15a65e 100644 --- a/js/node/lib/binding.ts +++ b/js/node/lib/binding.ts @@ -1,6 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +import { isMainThread } from 'worker_threads'; + import { InferenceSession, OnnxValue, Tensor, TensorConstructor, env } from 'onnxruntime-common'; type SessionOptions = InferenceSession.SessionOptions; @@ -19,12 +21,19 @@ type RunOptions = InferenceSession.RunOptions; * Binding exports a simple synchronized inference session object wrap. */ export declare namespace Binding { + export interface ValueMetadata { + name: string; + isTensor: boolean; + symbolicDimensions: string[]; + shape: number[]; + type: number; + } export interface InferenceSession { loadModel(modelPath: string, options: SessionOptions): void; loadModel(buffer: ArrayBuffer, byteOffset: number, byteLength: number, options: SessionOptions): void; - readonly inputNames: string[]; - readonly outputNames: string[]; + readonly inputMetadata: ValueMetadata[]; + readonly outputMetadata: ValueMetadata[]; run(feeds: FeedsType, fetches: FetchesType, options: RunOptions): ReturnType; @@ -46,11 +55,11 @@ export declare namespace Binding { // export native binding export const binding = // eslint-disable-next-line @typescript-eslint/no-require-imports, @typescript-eslint/no-var-requires - require(`../bin/napi-v3/${process.platform}/${process.arch}/onnxruntime_binding.node`) as { + require(`../bin/napi-v6/${process.platform}/${process.arch}/onnxruntime_binding.node`) as { // eslint-disable-next-line @typescript-eslint/naming-convention InferenceSession: Binding.InferenceSessionConstructor; listSupportedBackends: () => Binding.SupportedBackend[]; - initOrtOnce: (logLevel: number, tensorConstructor: TensorConstructor) => void; + initOrtOnce: (logLevel: number, tensorConstructor: TensorConstructor, isMainThread: boolean) => void; }; let ortInitialized = false; @@ -79,6 +88,6 @@ export const initOrt = (): void => { throw new Error(`Unsupported log level: ${env.logLevel}`); } } - binding.initOrtOnce(logLevel, Tensor); + binding.initOrtOnce(logLevel, Tensor, isMainThread); } }; diff --git a/js/node/lib/version.ts b/js/node/lib/version.ts index 475dfe0d4888b..1c679620af4b1 100644 --- a/js/node/lib/version.ts +++ b/js/node/lib/version.ts @@ -4,4 +4,4 @@ // This file is generated by /js/scripts/update-version.ts // Do not modify file content manually. -export const version = '1.21.0'; +export const version = '1.27.0'; diff --git a/js/node/package-lock.json b/js/node/package-lock.json index a18b7bb14feb5..fc25230249bc8 100644 --- a/js/node/package-lock.json +++ b/js/node/package-lock.json @@ -1,12 +1,12 @@ { "name": "onnxruntime-node", - "version": "1.21.0", + "version": "1.27.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "onnxruntime-node", - "version": "1.21.0", + "version": "1.27.0", "hasInstallScript": true, "license": "MIT", "os": [ @@ -15,13 +15,13 @@ "linux" ], "dependencies": { - "global-agent": "^3.0.0", - "onnxruntime-common": "file:../common", - "tar": "^7.0.1" + "adm-zip": "^0.5.16", + "global-agent": "^4.1.3", + "onnxruntime-common": "file:../common" }, "devDependencies": { "@types/minimist": "^1.2.2", - "cmake-js": "^7.2.1", + "cmake-js": "^8.0.0", "jsonc": "^2.0.0", "minimist": "^1.2.8", "node-addon-api": "^6.0.0", @@ -30,105 +30,18 @@ }, "../common": { "name": "onnxruntime-common", - "version": "1.21.0", + "version": "1.27.0", "license": "MIT", "devDependencies": { + "globby": "^15.0.0", "typedoc": "^0.25.7" } }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, "node_modules/@isaacs/fs-minipass": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.0.tgz", - "integrity": "sha512-S00nN1Qt3z3dSP6Db45fj/mksrAq5XWNIJ/SWXGP8XPT2jrzEuYRCSEx08JpJwBcG2F1xgiOtBMGDU0AZHmxew==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, "dependencies": { "minipass": "^7.0.4" }, @@ -136,23 +49,6 @@ "node": ">=18.0.0" } }, - "node_modules/@isaacs/fs-minipass/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true, - "engines": { - "node": ">=14" - } - }, "node_modules/@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -229,10 +125,20 @@ "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==", "dev": true }, + "node_modules/adm-zip": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==", + "license": "MIT", + "engines": { + "node": ">=12.0" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, "engines": { "node": ">=8" } @@ -241,6 +147,7 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, "dependencies": { "color-convert": "^2.0.1" }, @@ -251,65 +158,11 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "node_modules/are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "node_modules/axios": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", - "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", - "dev": true, - "dependencies": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info." - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, "node_modules/chownr": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, "engines": { "node": ">=18" } @@ -329,99 +182,33 @@ } }, "node_modules/cmake-js": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-7.2.1.tgz", - "integrity": "sha512-AdPSz9cSIJWdKvm0aJgVu3X8i0U3mNTswJkSHzZISqmYVjZk7Td4oDFg0mCBA383wO+9pG5Ix7pEP1CZH9x2BA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-8.0.0.tgz", + "integrity": "sha512-YbUP88RDwCvoQkZhRtGURYm9RIpWdtvZuhT87fKNoLjk8kIFIFeARpKfuZQGdwfH99GZpUmqSfcDrK62X7lTgg==", "dev": true, "dependencies": { - "axios": "^1.3.2", - "debug": "^4", - "fs-extra": "^10.1.0", - "lodash.isplainobject": "^4.0.6", - "memory-stream": "^1.0.0", - "node-api-headers": "^0.0.2", - "npmlog": "^6.0.2", - "rc": "^1.2.7", - "semver": "^7.3.8", - "tar": "^6.1.11", + "debug": "^4.4.3", + "fs-extra": "^11.3.3", + "node-api-headers": "^1.8.0", + "rc": "1.2.8", + "semver": "^7.7.3", + "tar": "^7.5.6", "url-join": "^4.0.1", - "which": "^2.0.2", - "yargs": "^17.6.0" + "which": "^6.0.0", + "yargs": "^17.7.2" }, "bin": { "cmake-js": "bin/cmake-js" }, "engines": { - "node": ">= 14.15.0" - } - }, - "node_modules/cmake-js/node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true, - "engines": { - "node": ">=10" - } - }, - "node_modules/cmake-js/node_modules/minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/cmake-js/node_modules/minizlib/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cmake-js/node_modules/mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true, - "bin": { - "mkdirp": "bin/cmd.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/cmake-js/node_modules/tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "dependencies": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" + "node": "^20.17.0 || >=22.9.0" } }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "dependencies": { "color-name": "~1.1.4" }, @@ -432,55 +219,16 @@ "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "node_modules/color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true, - "bin": { - "color-support": "bin.js" - } - }, - "node_modules/combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "dependencies": { - "delayed-stream": "~1.0.0" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "dependencies": { - "ms": "2.1.2" + "ms": "^2.1.3" }, "engines": { "node": ">=6.0" @@ -504,6 +252,7 @@ "version": "1.1.4", "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0", "es-errors": "^1.3.0", @@ -520,6 +269,7 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "license": "MIT", "dependencies": { "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", @@ -532,35 +282,11 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true - }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "node_modules/error-ex": { "version": "1.3.2", @@ -575,6 +301,7 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -583,19 +310,15 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", "engines": { "node": ">= 0.4" } }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" - }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "engines": { "node": ">=6" @@ -605,6 +328,7 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -618,70 +342,10 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "dev": true }, - "node_modules/follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "engines": { - "node": ">=4.0" - }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } - } - }, - "node_modules/foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", + "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", "dev": true, "dependencies": { "graceful-fs": "^4.2.0", @@ -689,50 +353,7 @@ "universalify": "^2.0.0" }, "engines": { - "node": ">=12" - } - }, - "node_modules/fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "dependencies": { - "minipass": "^3.0.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/fs-minipass/node_modules/minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "dependencies": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": ">=14.14" } }, "node_modules/get-caller-file": { @@ -744,46 +365,16 @@ "node": "6.* || 8.* || >= 10.*" } }, - "node_modules/glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.6", - "minimatch": "^9.0.1", - "minipass": "^7.0.4", - "path-scurry": "^1.10.2" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-4.1.3.tgz", + "integrity": "sha512-KUJEViiuFT3I97t+GYMikLPJS2Lfo/S2F+DQuBWzuzaMPnvt5yyZePzArx36fBzpGTxZjIpDbXLeySLgh+k76g==", + "license": "BSD-3-Clause", "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" + "globalthis": "^1.0.2", + "matcher": "^4.0.0", + "semver": "^7.3.5", + "serialize-error": "^8.1.0" }, "engines": { "node": ">=10.0" @@ -793,6 +384,7 @@ "version": "1.0.4", "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "license": "MIT", "dependencies": { "define-properties": "^1.2.1", "gopd": "^1.0.1" @@ -808,6 +400,7 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -825,6 +418,7 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "license": "MIT", "dependencies": { "es-define-property": "^1.0.0" }, @@ -832,18 +426,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "node_modules/ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", @@ -860,30 +442,18 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, "engines": { "node": ">=8" } }, "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "node_modules/jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true, "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "node": ">=16" } }, "node_modules/json-parse-better-errors": { @@ -892,11 +462,6 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, "node_modules/jsonc": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/jsonc/-/jsonc-2.0.0.tgz", @@ -915,9 +480,9 @@ } }, "node_modules/jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "dependencies": { "universalify": "^2.0.0" @@ -926,82 +491,25 @@ "graceful-fs": "^4.1.6" } }, - "node_modules/lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true - }, "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", "dev": true }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-4.0.0.tgz", + "integrity": "sha512-S6x5wmcDmsDRRU/c2dkccDwQPXoFczc5+HpQ2lON8pnvHlnvHAHj5WlLVvw6n6vNyHuVugYrFohYxbS+pvFpKQ==", + "license": "MIT", "dependencies": { "escape-string-regexp": "^4.0.0" }, "engines": { "node": ">=10" - } - }, - "node_modules/memory-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-1.0.0.tgz", - "integrity": "sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww==", - "dev": true, - "dependencies": { - "readable-stream": "^3.4.0" - } - }, - "node_modules/mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "dependencies": { - "mime-db": "1.52.0" - }, - "engines": { - "node": ">= 0.6" - } - }, - "node_modules/minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/minimist": { @@ -1014,33 +522,26 @@ } }, "node_modules/minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" } }, "node_modules/minizlib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", - "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, "dependencies": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" + "minipass": "^7.1.2" }, "engines": { "node": ">= 18" } }, - "node_modules/minizlib/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, "node_modules/mkdirp": { "version": "0.5.6", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", @@ -1054,9 +555,9 @@ } }, "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node_modules/node-addon-api": { @@ -1066,30 +567,16 @@ "dev": true }, "node_modules/node-api-headers": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/node-api-headers/-/node-api-headers-0.0.2.tgz", - "integrity": "sha512-YsjmaKGPDkmhoNKIpkChtCsPVaRE0a274IdERKnuc/E8K1UJdBZ4/mvI006OijlQZHCfpRNOH3dfHQs92se8gg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.8.0.tgz", + "integrity": "sha512-jfnmiKWjRAGbdD1yQS28bknFM1tbHC1oucyuMPjmkEs+kpiu76aRs40WlTmBmyEgzDM76ge1DQ7XJ3R5deiVjQ==", "dev": true }, - "node_modules/npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "dependencies": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - }, - "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" - } - }, "node_modules/object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "license": "MIT", "engines": { "node": ">= 0.4" } @@ -1111,37 +598,6 @@ "node": ">=4" } }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-scurry/node_modules/lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==", - "engines": { - "node": "14 || >=16.14" - } - }, "node_modules/protobufjs": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", @@ -1166,12 +622,6 @@ "node": ">=12.0.0" } }, - "node_modules/proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, "node_modules/rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -1196,20 +646,6 @@ "node": ">=0.10.0" } }, - "node_modules/readable-stream": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", - "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", - "dev": true, - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -1219,66 +655,10 @@ "node": ">=0.10.0" } }, - "node_modules/rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ] - }, "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "bin": { "semver": "bin/semver.js" }, @@ -1286,17 +666,13 @@ "node": ">=10" } }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==" - }, "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", + "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", + "license": "MIT", "dependencies": { - "type-fest": "^0.13.1" + "type-fest": "^0.20.2" }, "engines": { "node": ">=10" @@ -1305,69 +681,11 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "engines": { - "node": ">=8" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, "node_modules/string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -1381,18 +699,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "dependencies": { "ansi-regex": "^5.0.1" }, @@ -1422,47 +729,26 @@ } }, "node_modules/tar": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.0.1.tgz", - "integrity": "sha512-IjMhdQMZFpKsHEQT3woZVxBtCQY+0wk3CVxdRkGXEgyGa0dNS/ehPvOMr2nmfC7x5Zj2N+l6yZUpmICjLGS35w==", + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz", + "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==", + "dev": true, "dependencies": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", - "minipass": "^5.0.0", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", "yallist": "^5.0.0" }, "engines": { "node": ">=18" } }, - "node_modules/tar/node_modules/mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==", - "bin": { - "mkdirp": "dist/cjs/src/bin.js" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/tar/node_modules/yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", - "engines": { - "node": ">=18" - } - }, "node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -1471,9 +757,9 @@ } }, "node_modules/universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, "engines": { "node": ">= 10.0.0" @@ -1485,57 +771,26 @@ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", + "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", + "dev": true, "dependencies": { - "isexe": "^2.0.0" + "isexe": "^3.1.1" }, "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", - "dev": true, - "dependencies": { - "string-width": "^1.0.2 || 2 || 3 || 4" - } - }, - "node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" + "node-which": "bin/which.js" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + "node": "^20.17.0 || >=22.9.0" } }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", + "node_modules/wrap-ansi": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -1558,14 +813,18 @@ } }, "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "engines": { + "node": ">=18" + } }, "node_modules/yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "dependencies": { "cliui": "^8.0.1", @@ -1580,7 +839,7 @@ "node": ">=12" } }, - "node_modules/yargs/node_modules/yargs-parser": { + "node_modules/yargs-parser": { "version": "21.1.1", "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", @@ -1591,85 +850,15 @@ } }, "dependencies": { - "@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "requires": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "dependencies": { - "ansi-regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", - "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==" - }, - "ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==" - }, - "emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" - }, - "string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "requires": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - } - }, - "strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "requires": { - "ansi-regex": "^6.0.1" - } - }, - "wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "requires": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - } - } - } - }, "@isaacs/fs-minipass": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.0.tgz", - "integrity": "sha512-S00nN1Qt3z3dSP6Db45fj/mksrAq5XWNIJ/SWXGP8XPT2jrzEuYRCSEx08JpJwBcG2F1xgiOtBMGDU0AZHmxew==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, "requires": { "minipass": "^7.0.4" - }, - "dependencies": { - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - } } }, - "@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "optional": true - }, "@protobufjs/aspromise": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", @@ -1746,74 +935,31 @@ "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==", "dev": true }, + "adm-zip": { + "version": "0.5.16", + "resolved": "https://registry.npmjs.org/adm-zip/-/adm-zip-0.5.16.tgz", + "integrity": "sha512-TGw5yVi4saajsSEgz25grObGHEUaDrniwvA2qwSC060KfqGPdglhvPMA2lPIoxs3PQIItj2iag35fONcQqgUaQ==" + }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==" + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true }, "ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "requires": { - "color-convert": "^2.0.1" - } - }, - "aproba": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", - "integrity": "sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==", - "dev": true - }, - "are-we-there-yet": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz", - "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==", - "dev": true, - "requires": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - } - }, - "asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", - "dev": true - }, - "axios": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", - "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", "dev": true, "requires": { - "follow-redirects": "^1.15.6", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" - } - }, - "balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" - }, - "boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==" - }, - "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "requires": { - "balanced-match": "^1.0.0" + "color-convert": "^2.0.1" } }, "chownr": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", - "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==" + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true }, "cliui": { "version": "8.0.1", @@ -1827,79 +973,27 @@ } }, "cmake-js": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-7.2.1.tgz", - "integrity": "sha512-AdPSz9cSIJWdKvm0aJgVu3X8i0U3mNTswJkSHzZISqmYVjZk7Td4oDFg0mCBA383wO+9pG5Ix7pEP1CZH9x2BA==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/cmake-js/-/cmake-js-8.0.0.tgz", + "integrity": "sha512-YbUP88RDwCvoQkZhRtGURYm9RIpWdtvZuhT87fKNoLjk8kIFIFeARpKfuZQGdwfH99GZpUmqSfcDrK62X7lTgg==", "dev": true, "requires": { - "axios": "^1.3.2", - "debug": "^4", - "fs-extra": "^10.1.0", - "lodash.isplainobject": "^4.0.6", - "memory-stream": "^1.0.0", - "node-api-headers": "^0.0.2", - "npmlog": "^6.0.2", - "rc": "^1.2.7", - "semver": "^7.3.8", - "tar": "^6.1.11", + "debug": "^4.4.3", + "fs-extra": "^11.3.3", + "node-api-headers": "^1.8.0", + "rc": "1.2.8", + "semver": "^7.7.3", + "tar": "^7.5.6", "url-join": "^4.0.1", - "which": "^2.0.2", - "yargs": "^17.6.0" - }, - "dependencies": { - "chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "dev": true - }, - "minizlib": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", - "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", - "dev": true, - "requires": { - "minipass": "^3.0.0", - "yallist": "^4.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "mkdirp": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", - "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", - "dev": true - }, - "tar": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", - "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", - "dev": true, - "requires": { - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "minipass": "^5.0.0", - "minizlib": "^2.1.1", - "mkdirp": "^1.0.3", - "yallist": "^4.0.0" - } - } + "which": "^6.0.0", + "yargs": "^17.7.2" } }, "color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, "requires": { "color-name": "~1.1.4" } @@ -1907,46 +1001,16 @@ "color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" - }, - "color-support": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", - "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", - "dev": true - }, - "combined-stream": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", - "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", - "dev": true, - "requires": { - "delayed-stream": "~1.0.0" - } - }, - "console-control-strings": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", - "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, - "cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "requires": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - } - }, "debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "requires": { - "ms": "2.1.2" + "ms": "^2.1.3" } }, "deep-extend": { @@ -1975,32 +1039,11 @@ "object-keys": "^1.1.1" } }, - "delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", - "dev": true - }, - "delegates": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", - "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", - "dev": true - }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==" - }, - "eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" - }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true }, "error-ex": { "version": "1.3.2", @@ -2021,15 +1064,10 @@ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==" }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==" - }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true }, "escape-string-regexp": { @@ -2043,43 +1081,10 @@ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", "dev": true }, - "follow-redirects": { - "version": "1.15.6", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", - "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", - "dev": true - }, - "foreground-child": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", - "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", - "requires": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" - }, - "dependencies": { - "signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==" - } - } - }, - "form-data": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", - "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", - "dev": true, - "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" - } - }, "fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "version": "11.3.3", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.3.tgz", + "integrity": "sha512-VWSRii4t0AFm6ixFFmLLx1t7wS1gh+ckoa84aOeapGum0h+EZd1EhEumSB+ZdDLnEPuucsVB9oB7cxJHap6Afg==", "dev": true, "requires": { "graceful-fs": "^4.2.0", @@ -2087,78 +1092,21 @@ "universalify": "^2.0.0" } }, - "fs-minipass": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", - "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", - "dev": true, - "requires": { - "minipass": "^3.0.0" - }, - "dependencies": { - "minipass": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", - "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - } - } - }, - "gauge": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz", - "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==", - "dev": true, - "requires": { - "aproba": "^1.0.3 || ^2.0.0", - "color-support": "^1.1.3", - "console-control-strings": "^1.1.0", - "has-unicode": "^2.0.1", - "signal-exit": "^3.0.7", - "string-width": "^4.2.3", - "strip-ansi": "^6.0.1", - "wide-align": "^1.1.5" - } - }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true }, - "glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^2.3.6", - "minimatch": "^9.0.1", - "minipass": "^7.0.4", - "path-scurry": "^1.10.2" - }, - "dependencies": { - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - } - } - }, "global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-4.1.3.tgz", + "integrity": "sha512-KUJEViiuFT3I97t+GYMikLPJS2Lfo/S2F+DQuBWzuzaMPnvt5yyZePzArx36fBzpGTxZjIpDbXLeySLgh+k76g==", "requires": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" + "globalthis": "^1.0.2", + "matcher": "^4.0.0", + "semver": "^7.3.5", + "serialize-error": "^8.1.0" } }, "globalthis": { @@ -2189,18 +1137,6 @@ "es-define-property": "^1.0.0" } }, - "has-unicode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", - "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", - "dev": true - }, - "inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true - }, "ini": { "version": "1.3.8", "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", @@ -2216,21 +1152,14 @@ "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==" + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true }, "isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" - }, - "jackspeak": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", - "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", - "requires": { - "@isaacs/cliui": "^8.0.2", - "@pkgjs/parseargs": "^0.11.0" - } + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.1.tgz", + "integrity": "sha512-LpB/54B+/2J5hqQ7imZHfdU31OlgQqx7ZicVlkm9kzg9/w8GKLEcFfJl/t7DCEDueOyBAD6zCCwTO6Fzs0NoEQ==", + "dev": true }, "json-parse-better-errors": { "version": "1.0.2", @@ -2238,11 +1167,6 @@ "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==" - }, "jsonc": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/jsonc/-/jsonc-2.0.0.tgz", @@ -2258,75 +1182,29 @@ } }, "jsonfile": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", - "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.0.tgz", + "integrity": "sha512-FGuPw30AdOIUTRMC2OMRtQV+jkVj2cfPqSeWXv1NEAJ1qZ5zb1X6z1mFhbfOB/iy3ssJCD+3KuZ8r8C3uVFlAg==", "dev": true, "requires": { "graceful-fs": "^4.1.6", "universalify": "^2.0.0" } }, - "lodash.isplainobject": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", - "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "dev": true - }, "long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==", "dev": true }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "requires": { - "yallist": "^4.0.0" - } - }, "matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-4.0.0.tgz", + "integrity": "sha512-S6x5wmcDmsDRRU/c2dkccDwQPXoFczc5+HpQ2lON8pnvHlnvHAHj5WlLVvw6n6vNyHuVugYrFohYxbS+pvFpKQ==", "requires": { "escape-string-regexp": "^4.0.0" } }, - "memory-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/memory-stream/-/memory-stream-1.0.0.tgz", - "integrity": "sha512-Wm13VcsPIMdG96dzILfij09PvuS3APtcKNh7M28FsCA/w6+1mjR7hhPmfFNoilX9xU7wTdhsH5lJAm6XNzdtww==", - "dev": true, - "requires": { - "readable-stream": "^3.4.0" - } - }, - "mime-db": { - "version": "1.52.0", - "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", - "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", - "dev": true - }, - "mime-types": { - "version": "2.1.35", - "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", - "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", - "dev": true, - "requires": { - "mime-db": "1.52.0" - } - }, - "minimatch": { - "version": "9.0.4", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.4.tgz", - "integrity": "sha512-KqWh+VchfxcMNRAJjj2tnsSJdNbHsVgnkBhTNrW7AjVo6OvLtxw8zfT9oLw1JSohlFzJ8jCoTgaoXvJ+kHt6fw==", - "requires": { - "brace-expansion": "^2.0.1" - } - }, "minimist": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", @@ -2334,24 +1212,18 @@ "dev": true }, "minipass": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", - "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==" + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true }, "minizlib": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.1.tgz", - "integrity": "sha512-umcy022ILvb5/3Djuu8LWeqUa8D68JaBzlttKeMWen48SjabqS3iY5w/vzeMzMUNhLDifyhbOwKDSznB1vvrwg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, "requires": { - "minipass": "^7.0.4", - "rimraf": "^5.0.5" - }, - "dependencies": { - "minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==" - } + "minipass": "^7.1.2" } }, "mkdirp": { @@ -2364,9 +1236,9 @@ } }, "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, "node-addon-api": { @@ -2376,23 +1248,11 @@ "dev": true }, "node-api-headers": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/node-api-headers/-/node-api-headers-0.0.2.tgz", - "integrity": "sha512-YsjmaKGPDkmhoNKIpkChtCsPVaRE0a274IdERKnuc/E8K1UJdBZ4/mvI006OijlQZHCfpRNOH3dfHQs92se8gg==", + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/node-api-headers/-/node-api-headers-1.8.0.tgz", + "integrity": "sha512-jfnmiKWjRAGbdD1yQS28bknFM1tbHC1oucyuMPjmkEs+kpiu76aRs40WlTmBmyEgzDM76ge1DQ7XJ3R5deiVjQ==", "dev": true }, - "npmlog": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz", - "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==", - "dev": true, - "requires": { - "are-we-there-yet": "^3.0.0", - "console-control-strings": "^1.1.0", - "gauge": "^4.0.3", - "set-blocking": "^2.0.0" - } - }, "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", @@ -2401,6 +1261,7 @@ "onnxruntime-common": { "version": "file:../common", "requires": { + "globby": "^15.0.0", "typedoc": "^0.25.7" } }, @@ -2414,27 +1275,6 @@ "json-parse-better-errors": "^1.0.1" } }, - "path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==" - }, - "path-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", - "requires": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "dependencies": { - "lru-cache": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.2.0.tgz", - "integrity": "sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q==" - } - } - }, "protobufjs": { "version": "7.2.5", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-7.2.5.tgz", @@ -2455,12 +1295,6 @@ "long": "^5.0.0" } }, - "proxy-from-env": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", - "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", - "dev": true - }, "rc": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", @@ -2481,124 +1315,30 @@ } } }, - "readable-stream": { - "version": "3.6.1", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.1.tgz", - "integrity": "sha512-+rQmrWMYGA90yenhTYsLWAsLsqVC8osOw6PKE1HDYiO0gdPeKe/xDHNzIAIn4C91YQ6oenEhfYqqc1883qHbjQ==", - "dev": true, - "requires": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - } - }, "require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, - "rimraf": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz", - "integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==", - "requires": { - "glob": "^10.3.7" - } - }, - "roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "requires": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - } - }, - "safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true - }, "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", - "requires": { - "lru-cache": "^6.0.0" - } - }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==" + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==" }, "serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", - "requires": { - "type-fest": "^0.13.1" - } - }, - "set-blocking": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", - "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", - "dev": true - }, - "shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "requires": { - "shebang-regex": "^3.0.0" - } - }, - "shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==" - }, - "signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true - }, - "sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==" - }, - "string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", + "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", "requires": { - "safe-buffer": "~5.2.0" + "type-fest": "^0.20.2" } }, "string-width": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "requires": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - } - }, - "string-width-cjs": { - "version": "npm:string-width@4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "requires": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -2609,14 +1349,7 @@ "version": "6.0.1", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "requires": { - "ansi-regex": "^5.0.1" - } - }, - "strip-ansi-cjs": { - "version": "npm:strip-ansi@6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, "requires": { "ansi-regex": "^5.0.1" } @@ -2634,39 +1367,27 @@ "dev": true }, "tar": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/tar/-/tar-7.0.1.tgz", - "integrity": "sha512-IjMhdQMZFpKsHEQT3woZVxBtCQY+0wk3CVxdRkGXEgyGa0dNS/ehPvOMr2nmfC7x5Zj2N+l6yZUpmICjLGS35w==", + "version": "7.5.11", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.11.tgz", + "integrity": "sha512-ChjMH33/KetonMTAtpYdgUFr0tbz69Fp2v7zWxQfYZX4g5ZN2nOBXm1R2xyA+lMIKrLKIoKAwFj93jE/avX9cQ==", + "dev": true, "requires": { "@isaacs/fs-minipass": "^4.0.0", "chownr": "^3.0.0", - "minipass": "^5.0.0", - "minizlib": "^3.0.1", - "mkdirp": "^3.0.1", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", "yallist": "^5.0.0" - }, - "dependencies": { - "mkdirp": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz", - "integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==" - }, - "yallist": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", - "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==" - } } }, "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==" + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==" }, "universalify": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", - "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true }, "url-join": { @@ -2675,27 +1396,13 @@ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==", "dev": true }, - "util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true - }, "which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "requires": { - "isexe": "^2.0.0" - } - }, - "wide-align": { - "version": "1.1.5", - "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz", - "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/which/-/which-6.0.0.tgz", + "integrity": "sha512-f+gEpIKMR9faW/JgAgPK1D7mekkFoqbmiwvNzuhsHetni20QSgzg9Vhn0g2JSJkkfehQnqdUAx7/e15qS1lPxg==", "dev": true, "requires": { - "string-width": "^1.0.2 || 2 || 3 || 4" + "isexe": "^3.1.1" } }, "wrap-ansi": { @@ -2709,16 +1416,6 @@ "strip-ansi": "^6.0.0" } }, - "wrap-ansi-cjs": { - "version": "npm:wrap-ansi@7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "requires": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - } - }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", @@ -2726,14 +1423,15 @@ "dev": true }, "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true }, "yargs": { - "version": "17.7.1", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.1.tgz", - "integrity": "sha512-cwiTb08Xuv5fqF4AovYacTFNxk62th7LKJ6BL9IGUpTJrWoU7/7WdQGTP2SjKf1dUNBGzDd28p/Yfs/GI6JrLw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { "cliui": "^8.0.1", @@ -2743,15 +1441,13 @@ "string-width": "^4.2.3", "y18n": "^5.0.5", "yargs-parser": "^21.1.1" - }, - "dependencies": { - "yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true - } } + }, + "yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "dev": true } } } diff --git a/js/node/package.json b/js/node/package.json index e5c5d8cbf6abc..c0403665c1a90 100644 --- a/js/node/package.json +++ b/js/node/package.json @@ -7,17 +7,15 @@ }, "author": "fs-eire", "binary": { - "module_path": "./bin", - "host": "https://onnxruntimetestdata.blob.core.windows.net/onnxruntime-node-prebuild/", "napi_versions": [ - 3 + 6 ] }, - "version": "1.21.0", + "version": "1.27.0", "dependencies": { - "global-agent": "^3.0.0", - "onnxruntime-common": "file:../common", - "tar": "^7.0.1" + "adm-zip": "^0.5.16", + "global-agent": "^4.1.3", + "onnxruntime-common": "file:../common" }, "scripts": { "postinstall": "node ./script/install", @@ -39,7 +37,7 @@ ], "devDependencies": { "@types/minimist": "^1.2.2", - "cmake-js": "^7.2.1", + "cmake-js": "^8.0.0", "jsonc": "^2.0.0", "minimist": "^1.2.8", "node-addon-api": "^6.0.0", diff --git a/js/node/script/install-metadata-versions.js b/js/node/script/install-metadata-versions.js new file mode 100644 index 0000000000000..81c5671cac9a3 --- /dev/null +++ b/js/node/script/install-metadata-versions.js @@ -0,0 +1,7 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +// This file is generated by /js/scripts/update-version.ts +// Do not modify file content manually. + +module.exports = { nuget: [{ feed: 'nuget', version: '1.27.0' }] }; diff --git a/js/node/script/install-metadata.js b/js/node/script/install-metadata.js new file mode 100644 index 0000000000000..41b905ba88eaf --- /dev/null +++ b/js/node/script/install-metadata.js @@ -0,0 +1,58 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +'use strict'; + +const metadataVersions = require('./install-metadata-versions.js'); + +const metadata = { + // Requirements defines a list of manifest to install for a specific platform/architecture combination. + requirements: { + 'win32/x64': [], + 'win32/arm64': [], + 'linux/x64': ['cuda12'], + 'linux/arm64': [], + 'darwin/x64': [], + 'darwin/arm64': [], + }, + // Each manifest defines a list of files to install + manifests: { + 'linux/x64:cuda12': { + './libonnxruntime_providers_cuda.so': { + package: 'nuget:linux/x64:cuda12', + path: 'runtimes/linux-x64/native/libonnxruntime_providers_cuda.so', + }, + './libonnxruntime_providers_shared.so': { + package: 'nuget:linux/x64:cuda12', + path: 'runtimes/linux-x64/native/libonnxruntime_providers_shared.so', + }, + './libonnxruntime_providers_tensorrt.so': { + package: 'nuget:linux/x64:cuda12', + path: 'runtimes/linux-x64/native/libonnxruntime_providers_tensorrt.so', + }, + }, + }, + // Each package defines a list of package metadata. The first available package will be used. + packages: { + 'nuget:win32/x64:cuda12': { + name: 'Microsoft.ML.OnnxRuntime.Gpu.Windows', + versions: metadataVersions.nuget, + }, + 'nuget:linux/x64:cuda12': { + name: 'Microsoft.ML.OnnxRuntime.Gpu.Linux', + versions: metadataVersions.nuget, + }, + }, + feeds: { + nuget: { + type: 'nuget', + index: 'https://api.nuget.org/v3/index.json', + }, + nuget_nightly: { + type: 'nuget', + index: 'https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/ORT-Nightly/nuget/v3/index.json', + }, + }, +}; + +module.exports = metadata; diff --git a/js/node/script/install-utils.js b/js/node/script/install-utils.js new file mode 100644 index 0000000000000..abfacce881600 --- /dev/null +++ b/js/node/script/install-utils.js @@ -0,0 +1,306 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +'use strict'; + +const fs = require('fs'); +const https = require('https'); +const { execFileSync } = require('child_process'); +const path = require('path'); +const os = require('os'); +const AdmZip = require('adm-zip'); // Use adm-zip instead of spawn + +async function downloadFile(url, dest) { + return new Promise((resolve, reject) => { + const file = fs.createWriteStream(dest); + https + .get(url, (res) => { + if (res.statusCode !== 200) { + file.close(); + fs.unlinkSync(dest); + reject(new Error(`Failed to download from ${url}. HTTP status code = ${res.statusCode}`)); + return; + } + + res.pipe(file); + file.on('finish', () => { + file.close(); + resolve(); + }); + file.on('error', (err) => { + fs.unlinkSync(dest); + reject(err); + }); + }) + .on('error', (err) => { + fs.unlinkSync(dest); + reject(err); + }); + }); +} + +async function downloadJson(url) { + return new Promise((resolve, reject) => { + https + .get(url, (res) => { + const { statusCode } = res; + const contentType = res.headers['content-type']; + + if (!statusCode) { + reject(new Error('No response statud code from server.')); + return; + } + if (statusCode >= 400 && statusCode < 500) { + resolve(null); + return; + } else if (statusCode !== 200) { + reject(new Error(`Failed to download build list. HTTP status code = ${statusCode}`)); + return; + } + if (!contentType || !/^application\/json/.test(contentType)) { + reject(new Error(`unexpected content type: ${contentType}`)); + return; + } + res.setEncoding('utf8'); + let rawData = ''; + res.on('data', (chunk) => { + rawData += chunk; + }); + res.on('end', () => { + try { + resolve(JSON.parse(rawData)); + } catch (e) { + reject(e); + } + }); + res.on('error', (err) => { + reject(err); + }); + }) + .on('error', (err) => { + reject(err); + }); + }); +} + +async function installPackages(packages, manifests, feeds) { + // Step.1: resolve packages + const resolvedPackages = new Map(); + for (const packageCandidates of packages) { + // iterate all candidates from packagesInfo and try to find the first one that exists + for (const { feed, version } of packageCandidates.versions) { + const { type, index } = feeds[feed]; + const pkg = await resolvePackage(type, index, packageCandidates.name, version); + if (pkg) { + resolvedPackages.set(packageCandidates, pkg); + break; + } + } + if (!resolvedPackages.has(packageCandidates)) { + throw new Error(`Failed to resolve package. No package exists for: ${JSON.stringify(packageCandidates)}`); + } + } + + // Step.2: download packages + for (const [pkgInfo, pkg] of resolvedPackages) { + const manifestsForPackage = manifests.filter((x) => x.packagesInfo === pkgInfo); + await pkg.download(manifestsForPackage); + } +} + +async function resolvePackage(type, index, packageName, version) { + // https://learn.microsoft.com/en-us/nuget/api/overview + const nugetPackageUrlResolver = async (index, packageName, version) => { + // STEP.1 - get Nuget package index + const nugetIndex = await downloadJson(index); + if (!nugetIndex) { + throw new Error(`Failed to download Nuget index from ${index}`); + } + + // STEP.2 - get the base url of "PackageBaseAddress/3.0.0" + const packageBaseUrl = nugetIndex.resources.find((x) => x['@type'] === 'PackageBaseAddress/3.0.0')?.['@id']; + if (!packageBaseUrl) { + throw new Error(`Failed to find PackageBaseAddress in Nuget index`); + } + + // STEP.3 - get the package version info + const packageInfo = await downloadJson(`${packageBaseUrl}${packageName.toLowerCase()}/index.json`); + if (!packageInfo.versions.includes(version.toLowerCase())) { + throw new Error(`Failed to find specific package versions for ${packageName} in ${index}`); + } + + // STEP.4 - generate the package URL + const packageUrl = `${packageBaseUrl}${packageName.toLowerCase()}/${version.toLowerCase()}/${packageName.toLowerCase()}.${version.toLowerCase()}.nupkg`; + const packageFileName = `${packageName.toLowerCase()}.${version.toLowerCase()}.nupkg`; + + return { + download: async (manifests) => { + if (manifests.length === 0) { + return; + } + + // Create a temporary directory + const tempDir = path.join(os.tmpdir(), `onnxruntime-node-pkgs_${Date.now()}`); + fs.mkdirSync(tempDir, { recursive: true }); + + try { + const packageFilePath = path.join(tempDir, packageFileName); + + // Download the NuGet package + console.log(`Downloading ${packageUrl}`); + await downloadFile(packageUrl, packageFilePath); + + // Load the NuGet package (which is a ZIP file) + let zip; + try { + zip = new AdmZip(packageFilePath); + } catch (err) { + throw new Error(`Failed to open NuGet package: ${err.message}`); + } + + // Extract only the needed files from the package + const extractDir = path.join(tempDir, 'extracted'); + fs.mkdirSync(extractDir, { recursive: true }); + + // Process each manifest and extract/copy files to their destinations + for (const manifest of manifests) { + const { filepath, pathInPackage } = manifest; + + // Create directory for the target file + const targetDir = path.dirname(filepath); + fs.mkdirSync(targetDir, { recursive: true }); + + // Check if the file exists directly in the zip + const zipEntry = zip.getEntry(pathInPackage); + if (!zipEntry) { + throw new Error(`Failed to find ${pathInPackage} in NuGet package`); + } + + console.log(`Extracting ${pathInPackage} to ${filepath}`); + + // Extract just this entry to a temporary location + const extractedFilePath = path.join(extractDir, path.basename(pathInPackage)); + zip.extractEntryTo(zipEntry, extractDir, false, true); + + // Copy to the final destination + fs.copyFileSync(extractedFilePath, filepath); + } + } finally { + // Clean up the temporary directory - always runs even if an error occurs + try { + fs.rmSync(tempDir, { recursive: true }); + } catch (e) { + console.warn(`Failed to clean up temporary directory: ${tempDir}`, e); + // Don't rethrow this error as it would mask the original error + } + } + }, + }; + }; + + switch (type) { + case 'nuget': + return await nugetPackageUrlResolver(index, packageName, version); + default: + throw new Error(`Unsupported package type: ${type}`); + } +} + +function tryGetCudaVersion() { + // Should only return 11 or 12. + + // try to get the CUDA version from the system ( `nvcc --version` ) + let ver = 12; + try { + const nvccVersion = execFileSync('nvcc', ['--version'], { encoding: 'utf8' }); + const match = nvccVersion.match(/release (\d+)/); + if (match) { + ver = parseInt(match[1]); + if (ver !== 11 && ver !== 12) { + throw new Error(`Unsupported CUDA version: ${ver}`); + } + } + } catch (e) { + if (e?.code === 'ENOENT') { + console.warn('`nvcc` not found. Assuming CUDA 12.'); + } else { + console.warn('Failed to detect CUDA version from `nvcc --version`:', e.message); + } + } + + // assume CUDA 12 if failed to detect + return ver; +} + +function parseInstallFlag() { + let flag = process.env.ONNXRUNTIME_NODE_INSTALL || process.env.npm_config_onnxruntime_node_install; + if (!flag) { + for (let i = 0; i < process.argv.length; i++) { + if (process.argv[i].startsWith('--onnxruntime-node-install=')) { + flag = process.argv[i].split('=')[1]; + break; + } else if (process.argv[i] === '--onnxruntime-node-install') { + flag = 'true'; + } + } + } + switch (flag) { + case 'true': + case '1': + case 'ON': + return true; + case 'skip': + return false; + case undefined: { + flag = parseInstallCudaFlag(); + if (flag === 'skip') { + return false; + } + if (flag === 11) { + throw new Error('CUDA 11 is no longer supported. Please consider using CPU or upgrade to CUDA 12.'); + } + if (flag === 12) { + return 'cuda12'; + } + return undefined; + } + default: + if (!flag || typeof flag !== 'string') { + throw new Error(`Invalid value for --onnxruntime-node-install: ${flag}`); + } + } +} + +function parseInstallCudaFlag() { + let flag = process.env.ONNXRUNTIME_NODE_INSTALL_CUDA || process.env.npm_config_onnxruntime_node_install_cuda; + if (!flag) { + for (let i = 0; i < process.argv.length; i++) { + if (process.argv[i].startsWith('--onnxruntime-node-install-cuda=')) { + flag = process.argv[i].split('=')[1]; + break; + } else if (process.argv[i] === '--onnxruntime-node-install-cuda') { + flag = 'true'; + } + } + } + switch (flag) { + case 'true': + case '1': + case 'ON': + return tryGetCudaVersion(); + case 'v11': + return 11; + case 'v12': + return 12; + case 'skip': + case undefined: + return flag; + default: + throw new Error(`Invalid value for --onnxruntime-node-install-cuda: ${flag}`); + } +} + +module.exports = { + installPackages, + parseInstallFlag, +}; diff --git a/js/node/script/install.js b/js/node/script/install.js index 7fdaeb9586278..aa9d16c2bfb72 100644 --- a/js/node/script/install.js +++ b/js/node/script/install.js @@ -8,192 +8,127 @@ // not always available. // The purpose of this script is to download the required binaries for the platform and architecture. -// Currently, most of the binaries are already bundled in the package, except for the following: -// - Linux/x64/CUDA 11 -// - Linux/x64/CUDA 12 +// Currently, most of the binaries are already bundled in the package, except for the files that described in the file +// install-metadata.js. // -// The CUDA binaries are not bundled because they are too large to be allowed in the npm registry. Instead, they are -// downloaded from the GitHub release page of ONNX Runtime. The script will download the binaries if they are not -// already present in the package. +// Some files (eg. the CUDA EP binaries) are not bundled because they are too large to be allowed in the npm registry. +// Instead, they are downloaded from the Nuget feed. The script will download the binaries if they are not already +// present in the NPM package. // Step.1: Check if we should exit early const os = require('os'); -const fs = require('fs'); -const https = require('https'); const path = require('path'); -const tar = require('tar'); -const { execFileSync } = require('child_process'); const { bootstrap: globalAgentBootstrap } = require('global-agent'); +const { installPackages, parseInstallFlag } = require('./install-utils.js'); + +const INSTALL_METADATA = require('./install-metadata.js'); // Bootstrap global-agent to honor the proxy settings in // environment variables, e.g. GLOBAL_AGENT_HTTPS_PROXY. -// See https://github.com/gajus/global-agent/blob/v3.0.0/README.md#environment-variables for details. +// See the https://github.com/gajus/global-agent ReadMe.md regarding environment variables. globalAgentBootstrap(); // commandline flag: -// --onnxruntime-node-install-cuda Force install the CUDA EP binaries. Try to detect the CUDA version. -// --onnxruntime-node-install-cuda=v11 Force install the CUDA EP binaries for CUDA 11. -// --onnxruntime-node-install-cuda=v12 Force install the CUDA EP binaries for CUDA 12. +// +// --onnxruntime-node-install Force install the files that are not bundled in the package. +// +// --onnxruntime-node-install=skip Skip the installation of the files that are not bundled in the package. +// +// --onnxruntime-node-install=cuda12 Force install the CUDA EP binaries for CUDA 12. +// +// --onnxruntime-node-install-cuda Force install the CUDA EP binaries. +// (deprecated, use --onnxruntime-node-install=cuda12) +// // --onnxruntime-node-install-cuda=skip Skip the installation of the CUDA EP binaries. +// (deprecated, use --onnxruntime-node-install=skip) // -// Alternatively, use environment variable "ONNXRUNTIME_NODE_INSTALL_CUDA" // -// If the flag is not provided, the script will only install the CUDA EP binaries when: -// - The platform is Linux/x64. -// - The binaries are not already present in the package. -// - The installation is not a local install (when used inside ONNX Runtime repo). +// Alternatively, use environment variable "ONNXRUNTIME_NODE_INSTALL" or "ONNXRUNTIME_NODE_INSTALL_CUDA" (deprecated). // -const INSTALL_CUDA_FLAG = parseInstallCudaFlag(); -const NO_INSTALL = INSTALL_CUDA_FLAG === 'skip'; -const FORCE_INSTALL = !NO_INSTALL && INSTALL_CUDA_FLAG; - -const IS_LINUX_X64 = os.platform() === 'linux' && os.arch() === 'x64'; -const BIN_FOLDER = path.join(__dirname, '..', 'bin/napi-v3/linux/x64'); -const BIN_FOLDER_EXISTS = fs.existsSync(BIN_FOLDER); -const CUDA_DLL_EXISTS = fs.existsSync(path.join(BIN_FOLDER, 'libonnxruntime_providers_cuda.so')); -const ORT_VERSION = require('../package.json').version; - -const npm_config_local_prefix = process.env.npm_config_local_prefix; -const npm_package_json = process.env.npm_package_json; -const SKIP_LOCAL_INSTALL = - npm_config_local_prefix && npm_package_json && path.dirname(npm_package_json) === npm_config_local_prefix; - -const shouldInstall = FORCE_INSTALL || (!SKIP_LOCAL_INSTALL && IS_LINUX_X64 && BIN_FOLDER_EXISTS && !CUDA_DLL_EXISTS); -if (NO_INSTALL || !shouldInstall) { +// If the flag is not provided, the script will look up the metadata file to determine the manifest. +// + +/** + * Possible values: + * - undefined: the default behavior. This is the value when no installation flag is specified. + * + * - false: skip installation. This is the value when the installation flag is set to "skip": + * --onnxruntime-node-install=skip + * + * - true: force installation. This is the value when the installation flag is set with no value: + * --onnxruntime-node-install + * + * - string: the installation flag is set to a specific value: + * --onnxruntime-node-install=cuda12 + */ +const INSTALL_FLAG = parseInstallFlag(); + +// if installation is skipped, exit early +if (INSTALL_FLAG === false) { process.exit(0); } - -// Step.2: Download the required binaries -const artifactUrl = { - get 11() { - // TODO: support ORT Cuda v11 binaries - throw new Error(`CUDA 11 binaries are not supported by this script yet. - -To use ONNX Runtime Node.js binding with CUDA v11 support, please follow the manual steps: - -1. Use "--onnxruntime-node-install-cuda=skip" to skip the auto installation. -2. Navigate to https://aiinfra.visualstudio.com/PublicPackages/_artifacts/feed/onnxruntime-cuda-11 -3. Download the binaries for your platform and architecture -4. Extract the following binaries to "node_modules/onnxruntime-node/bin/napi-v3/linux/x64: - - libonnxruntime_providers_tensorrt.so - - libonnxruntime_providers_shared.so - - libonnxruntime.so.${ORT_VERSION} - - libonnxruntime_providers_cuda.so -`); - }, - 12: `https://github.com/microsoft/onnxruntime/releases/download/v${ORT_VERSION}/onnxruntime-linux-x64-gpu-${ - ORT_VERSION - }.tgz`, -}[INSTALL_CUDA_FLAG || tryGetCudaVersion()]; -console.log(`Downloading "${artifactUrl}"...`); - -const FILES = new Set([ - 'libonnxruntime_providers_tensorrt.so', - 'libonnxruntime_providers_shared.so', - `libonnxruntime.so.${ORT_VERSION}`, - 'libonnxruntime_providers_cuda.so', -]); - -downloadAndExtract(artifactUrl, BIN_FOLDER, FILES); - -async function downloadAndExtract(url, dest, files) { - return new Promise((resolve, reject) => { - https.get(url, (res) => { - const { statusCode } = res; - const contentType = res.headers['content-type']; - - if (statusCode === 301 || statusCode === 302) { - downloadAndExtract(res.headers.location, dest, files).then( - (value) => resolve(value), - (reason) => reject(reason), - ); - return; - } else if (statusCode !== 200) { - throw new Error(`Failed to download the binaries: ${res.statusCode} ${res.statusMessage}. - -Use "--onnxruntime-node-install-cuda=skip" to skip the installation. You will still be able to use ONNX Runtime, but the CUDA EP will not be available.`); - } - - if (!contentType || !/^application\/octet-stream/.test(contentType)) { - throw new Error(`unexpected content type: ${contentType}`); - } - - res - .pipe( - tar.t({ - strict: true, - onentry: (entry) => { - const filename = path.basename(entry.path); - if (entry.type === 'File' && files.has(filename)) { - console.log(`Extracting "${filename}" to "${dest}"...`); - entry.pipe(fs.createWriteStream(path.join(dest, filename))); - entry.on('finish', () => { - console.log(`Finished extracting "${filename}".`); - }); - } - }, - }), - ) - .on('error', (err) => { - throw new Error(`Failed to extract the binaries: ${err.message}. - -Use "--onnxruntime-node-install-cuda=skip" to skip the installation. You will still be able to use ONNX Runtime, but the CUDA EP will not be available.`); - }); - }); - }); +// if installation is not specified, exit early when the installation is local (e.g. `npm ci` in /js/node/) +if (INSTALL_FLAG === undefined) { + const npm_config_local_prefix = process.env.npm_config_local_prefix; + const npm_package_json = process.env.npm_package_json; + const IS_LOCAL_INSTALL = + npm_config_local_prefix && npm_package_json && path.dirname(npm_package_json) === npm_config_local_prefix; + if (IS_LOCAL_INSTALL) { + process.exit(0); + } } -function tryGetCudaVersion() { - // Should only return 11 or 12. - - // try to get the CUDA version from the system ( `nvcc --version` ) - let ver = 12; - try { - const nvccVersion = execFileSync('nvcc', ['--version'], { encoding: 'utf8' }); - const match = nvccVersion.match(/release (\d+)/); - if (match) { - ver = parseInt(match[1]); - if (ver !== 11 && ver !== 12) { - throw new Error(`Unsupported CUDA version: ${ver}`); - } - } - } catch (e) { - if (e?.code === 'ENOENT') { - console.warn('`nvcc` not found. Assuming CUDA 12.'); - } else { - console.warn('Failed to detect CUDA version from `nvcc --version`:', e.message); +const PLATFORM = `${os.platform()}/${os.arch()}`; +let INSTALL_MANIFEST_NAMES = INSTALL_METADATA.requirements[PLATFORM] ?? []; + +// if installation is specified explicitly, validate the manifest +if (typeof INSTALL_FLAG === 'string') { + const installations = INSTALL_FLAG.split(',').map((x) => x.trim()); + for (const installation of installations) { + if (INSTALL_MANIFEST_NAMES.indexOf(installation) === -1) { + throw new Error(`Invalid installation: ${installation} for platform: ${PLATFORM}`); } } + INSTALL_MANIFEST_NAMES = installations; +} + +const BIN_FOLDER = path.join(__dirname, '..', 'bin/napi-v6', PLATFORM); +const INSTALL_MANIFESTS = []; + +const PACKAGES = new Set(); +for (const name of INSTALL_MANIFEST_NAMES) { + const manifest = INSTALL_METADATA.manifests[`${PLATFORM}:${name}`]; + if (!manifest) { + throw new Error(`Manifest not found: ${name} for platform: ${PLATFORM}`); + } - // assume CUDA 12 if failed to detect - return ver; + for (const [filename, { package: pkg, path: pathInPackage }] of Object.entries(manifest)) { + const packageCandidates = INSTALL_METADATA.packages[pkg]; + if (!packageCandidates) { + throw new Error(`Package information not found: ${pkg}`); + } + PACKAGES.add(packageCandidates); + + INSTALL_MANIFESTS.push({ + filepath: path.normalize(path.join(BIN_FOLDER, filename)), + packagesInfo: packageCandidates, + pathInPackage, + }); + } } -function parseInstallCudaFlag() { - let flag = process.env.ONNXRUNTIME_NODE_INSTALL_CUDA || process.env.npm_config_onnxruntime_node_install_cuda; - if (!flag) { - for (let i = 0; i < process.argv.length; i++) { - if (process.argv[i].startsWith('--onnxruntime-node-install-cuda=')) { - flag = process.argv[i].split('=')[1]; - break; - } else if (process.argv[i] === '--onnxruntime-node-install-cuda') { - flag = 'true'; - } +// If the installation flag is not specified, we do a check to see if the files are already installed. +if (INSTALL_FLAG === undefined) { + let hasMissingFiles = false; + for (const { filepath } of INSTALL_MANIFESTS) { + if (!require('fs').existsSync(filepath)) { + hasMissingFiles = true; + break; } } - switch (flag) { - case 'true': - case '1': - case 'ON': - return tryGetCudaVersion(); - case 'v11': - return 11; - case 'v12': - return 12; - case 'skip': - case undefined: - return flag; - default: - throw new Error(`Invalid value for --onnxruntime-node-install-cuda: ${flag}`); + if (!hasMissingFiles) { + process.exit(0); } } + +void installPackages(PACKAGES, INSTALL_MANIFESTS, INSTALL_METADATA.feeds); diff --git a/js/node/src/inference_session_wrap.cc b/js/node/src/inference_session_wrap.cc index 04ab71dc48ec2..648a4586ababc 100644 --- a/js/node/src/inference_session_wrap.cc +++ b/js/node/src/inference_session_wrap.cc @@ -5,25 +5,16 @@ #include "common.h" #include "inference_session_wrap.h" +#include "ort_instance_data.h" +#include "ort_singleton_data.h" #include "run_options_helper.h" #include "session_options_helper.h" #include "tensor_helper.h" #include -Napi::FunctionReference InferenceSessionWrap::wrappedSessionConstructor; -Napi::FunctionReference InferenceSessionWrap::ortTensorConstructor; - -Napi::FunctionReference& InferenceSessionWrap::GetTensorConstructor() { - return InferenceSessionWrap::ortTensorConstructor; -} - Napi::Object InferenceSessionWrap::Init(Napi::Env env, Napi::Object exports) { // create ONNX runtime env Ort::InitApi(); - ORT_NAPI_THROW_ERROR_IF( - Ort::Global::api_ == nullptr, env, - "Failed to initialize ONNX Runtime API. It could happen when this nodejs binding was built with a higher version " - "ONNX Runtime but now runs with a lower version ONNX Runtime DLL(or shared library)."); // initialize binding Napi::HandleScope scope(env); @@ -34,11 +25,11 @@ Napi::Object InferenceSessionWrap::Init(Napi::Env env, Napi::Object exports) { InstanceMethod("run", &InferenceSessionWrap::Run), InstanceMethod("dispose", &InferenceSessionWrap::Dispose), InstanceMethod("endProfiling", &InferenceSessionWrap::EndProfiling), - InstanceAccessor("inputNames", &InferenceSessionWrap::GetInputNames, nullptr, napi_default, nullptr), - InstanceAccessor("outputNames", &InferenceSessionWrap::GetOutputNames, nullptr, napi_default, nullptr)}); + InstanceAccessor("inputMetadata", &InferenceSessionWrap::GetMetadata, nullptr, napi_default, reinterpret_cast(true)), + InstanceAccessor("outputMetadata", &InferenceSessionWrap::GetMetadata, nullptr, napi_default, reinterpret_cast(false))}); + + OrtInstanceData::Create(env, func); - wrappedSessionConstructor = Napi::Persistent(func); - wrappedSessionConstructor.SuppressDestruct(); exports.Set("InferenceSession", func); Napi::Function listSupportedBackends = Napi::Function::New(env, InferenceSessionWrap::ListSupportedBackends); @@ -55,22 +46,32 @@ Napi::Value InferenceSessionWrap::InitOrtOnce(const Napi::CallbackInfo& info) { Napi::HandleScope scope(env); int log_level = info[0].As().Int32Value(); - - Ort::Env* ortEnv = env.GetInstanceData(); - if (ortEnv == nullptr) { - ortEnv = new Ort::Env{OrtLoggingLevel(log_level), "onnxruntime-node"}; - env.SetInstanceData(ortEnv); - } - Napi::Function tensorConstructor = info[1].As(); - ortTensorConstructor = Napi::Persistent(tensorConstructor); - ortTensorConstructor.SuppressDestruct(); + bool is_main_thread = info[2].As().Value(); + + OrtInstanceData::InitOrt(env, log_level, tensorConstructor, is_main_thread); return env.Undefined(); } InferenceSessionWrap::InferenceSessionWrap(const Napi::CallbackInfo& info) - : Napi::ObjectWrap(info), initialized_(false), disposed_(false), session_(nullptr), defaultRunOptions_(nullptr) {} + : Napi::ObjectWrap(info), initialized_(false), disposed_(false), session_(nullptr) {} + +InferenceSessionWrap::~InferenceSessionWrap() { + // If the ORT singleton has already been destroyed (e.g. during process shutdown when the + // cleanup hook fires before N-API finalizers run), we must not call into ORT to + // release owned ORT objects — doing so would crash. Intentionally leak in that case. + if (!OrtSingletonData::GetOrtObjects()) { + for (auto& type_info : inputTypes_) { + (void)type_info.release(); + } + for (auto& type_info : outputTypes_) { + (void)type_info.release(); + } + (void)ioBinding_.release(); + (void)session_.release(); + } +} Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); @@ -83,14 +84,13 @@ Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo& info) { ORT_NAPI_THROW_TYPEERROR_IF(argsLength == 0, env, "Expect argument: model file path or buffer."); try { - defaultRunOptions_.reset(new Ort::RunOptions{}); Ort::SessionOptions sessionOptions; if (argsLength == 2 && info[0].IsString() && info[1].IsObject()) { Napi::String value = info[0].As(); ParseSessionOptions(info[1].As(), sessionOptions); - this->session_.reset(new Ort::Session(*env.GetInstanceData(), + this->session_.reset(new Ort::Session(OrtSingletonData::GetOrtObjects()->env, #ifdef _WIN32 reinterpret_cast(value.Utf16Value().c_str()), #else @@ -105,7 +105,7 @@ Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo& info) { int64_t bytesLength = info[2].As().Int64Value(); ParseSessionOptions(info[3].As(), sessionOptions); - this->session_.reset(new Ort::Session(*env.GetInstanceData(), + this->session_.reset(new Ort::Session(OrtSingletonData::GetOrtObjects()->env, reinterpret_cast(buffer) + bytesOffset, bytesLength, sessionOptions)); } else { @@ -120,27 +120,17 @@ Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo& info) { size_t count = session_->GetInputCount(); inputNames_.reserve(count); for (size_t i = 0; i < count; i++) { - auto inp_name = session_->GetInputNameAllocated(i, allocator); - inputNames_.emplace_back(inp_name.get()); - auto typeInfo = session_->GetInputTypeInfo(i); - auto onnxType = typeInfo.GetONNXType(); - inputTypes_.emplace_back(onnxType); - inputTensorElementDataTypes_.emplace_back(onnxType == ONNX_TYPE_TENSOR - ? typeInfo.GetTensorTypeAndShapeInfo().GetElementType() - : ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED); + auto input_name = session_->GetInputNameAllocated(i, allocator); + inputNames_.emplace_back(input_name.get()); + inputTypes_.push_back(session_->GetInputTypeInfo(i)); } count = session_->GetOutputCount(); outputNames_.reserve(count); for (size_t i = 0; i < count; i++) { - auto out_name = session_->GetOutputNameAllocated(i, allocator); - outputNames_.emplace_back(out_name.get()); - auto typeInfo = session_->GetOutputTypeInfo(i); - auto onnxType = typeInfo.GetONNXType(); - outputTypes_.emplace_back(onnxType); - outputTensorElementDataTypes_.emplace_back(onnxType == ONNX_TYPE_TENSOR - ? typeInfo.GetTensorTypeAndShapeInfo().GetElementType() - : ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED); + auto output_name = session_->GetOutputNameAllocated(i, allocator); + outputNames_.emplace_back(output_name.get()); + outputTypes_.push_back(session_->GetOutputTypeInfo(i)); } // cache preferred output locations @@ -157,22 +147,32 @@ Napi::Value InferenceSessionWrap::LoadModel(const Napi::CallbackInfo& info) { return env.Undefined(); } -Napi::Value InferenceSessionWrap::GetInputNames(const Napi::CallbackInfo& info) { +Napi::Value InferenceSessionWrap::GetMetadata(const Napi::CallbackInfo& info) { Napi::Env env = info.Env(); ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized."); ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed."); Napi::EscapableHandleScope scope(env); - return scope.Escape(CreateNapiArrayFrom(env, inputNames_)); -} - -Napi::Value InferenceSessionWrap::GetOutputNames(const Napi::CallbackInfo& info) { - Napi::Env env = info.Env(); - ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized."); - ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed."); - - Napi::EscapableHandleScope scope(env); - return scope.Escape(CreateNapiArrayFrom(env, outputNames_)); + auto& names = info.Data() != nullptr ? inputNames_ : outputNames_; + auto& types = info.Data() != nullptr ? inputTypes_ : outputTypes_; + auto array = Napi::Array::New(env, types.size()); + for (uint32_t i = 0; i < types.size(); i++) { + Napi::Object obj = Napi::Object::New(env); + obj.Set("name", names[i]); + auto& typeInfo = types[i]; + if (typeInfo.GetONNXType() == ONNX_TYPE_TENSOR) { + obj.Set("isTensor", true); + + auto tensorInfo = typeInfo.GetTensorTypeAndShapeInfo(); + obj.Set("type", static_cast>(tensorInfo.GetElementType())); + obj.Set("symbolicDimensions", CreateNapiArrayFrom(env, tensorInfo.GetSymbolicDimensions())); + obj.Set("shape", CreateNapiArrayFrom(env, tensorInfo.GetShape())); + } else { + obj.Set("isTensor", false); + } + array.Set(i, Napi::Value::From(env, obj)); + } + return scope.Escape(array); } Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo& info) { @@ -198,7 +198,7 @@ Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo& info) { size_t inputIndex = 0; size_t outputIndex = 0; Ort::MemoryInfo cpuMemoryInfo = Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeDefault); - Ort::MemoryInfo gpuBufferMemoryInfo{"WebGPU_Buffer", OrtDeviceAllocator, 0, OrtMemTypeDefault}; + Ort::MemoryInfo gpuBufferMemoryInfo{"WebGPU_Buf", OrtDeviceAllocator, 0, OrtMemTypeDefault}; try { for (auto& name : inputNames_) { @@ -225,7 +225,7 @@ Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo& info) { ParseRunOptions(info[2].As(), runOptions); } if (preferredOutputLocations_.size() == 0) { - session_->Run(runOptions == nullptr ? *defaultRunOptions_.get() : runOptions, + session_->Run(runOptions == nullptr ? OrtSingletonData::GetOrtObjects()->default_run_options : runOptions, inputIndex == 0 ? nullptr : &inputNames_cstr[0], inputIndex == 0 ? nullptr : &inputValues[0], inputIndex, outputIndex == 0 ? nullptr : &outputNames_cstr[0], outputIndex == 0 ? nullptr : &outputValues[0], outputIndex); @@ -233,7 +233,7 @@ Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo& info) { Napi::Object result = Napi::Object::New(env); for (size_t i = 0; i < outputIndex; i++) { - result.Set(outputNames_[i], OrtValueToNapiValue(env, std::move(outputValues[i]))); + result.Set(outputNames_cstr[i], OrtValueToNapiValue(env, std::move(outputValues[i]))); } return scope.Escape(result); } else { @@ -254,14 +254,14 @@ Napi::Value InferenceSessionWrap::Run(const Napi::CallbackInfo& info) { } } - session_->Run(runOptions == nullptr ? *defaultRunOptions_.get() : runOptions, *ioBinding_); + session_->Run(runOptions == nullptr ? OrtSingletonData::GetOrtObjects()->default_run_options : runOptions, *ioBinding_); auto outputs = ioBinding_->GetOutputValues(); ORT_NAPI_THROW_ERROR_IF(outputs.size() != outputIndex, env, "Output count mismatch."); Napi::Object result = Napi::Object::New(env); for (size_t i = 0; i < outputIndex; i++) { - result.Set(outputNames_[i], OrtValueToNapiValue(env, std::move(outputs[i]))); + result.Set(outputNames_cstr[i], OrtValueToNapiValue(env, std::move(outputs[i]))); } return scope.Escape(result); } @@ -277,9 +277,10 @@ Napi::Value InferenceSessionWrap::Dispose(const Napi::CallbackInfo& info) { ORT_NAPI_THROW_ERROR_IF(!this->initialized_, env, "Session is not initialized."); ORT_NAPI_THROW_ERROR_IF(this->disposed_, env, "Session already disposed."); - this->ioBinding_.reset(nullptr); + this->inputTypes_.clear(); + this->outputTypes_.clear(); - this->defaultRunOptions_.reset(nullptr); + this->ioBinding_.reset(nullptr); this->session_.reset(nullptr); this->disposed_ = true; diff --git a/js/node/src/inference_session_wrap.h b/js/node/src/inference_session_wrap.h index 0b3dd1178c807..13132a8a2d744 100644 --- a/js/node/src/inference_session_wrap.h +++ b/js/node/src/inference_session_wrap.h @@ -12,9 +12,9 @@ class InferenceSessionWrap : public Napi::ObjectWrap { public: static Napi::Object Init(Napi::Env env, Napi::Object exports); - static Napi::FunctionReference& GetTensorConstructor(); InferenceSessionWrap(const Napi::CallbackInfo& info); + ~InferenceSessionWrap(); private: /** @@ -45,19 +45,12 @@ class InferenceSessionWrap : public Napi::ObjectWrap { // following functions have to be called after model is loaded. /** - * [sync] get input names. + * [sync] get metadata of the model's inputs or outputs. * @param nothing - * @returns a string array. + * @returns an array of objects with keys: name, isTensor, type, symbolicDimensions, shape * @throw nothing */ - Napi::Value GetInputNames(const Napi::CallbackInfo& info); - /** - * [sync] get output names. - * @param nothing - * @returns a string array. - * @throw nothing - */ - Napi::Value GetOutputNames(const Napi::CallbackInfo& info); + Napi::Value GetMetadata(const Napi::CallbackInfo& info); /** * [sync] run the model. @@ -86,23 +79,16 @@ class InferenceSessionWrap : public Napi::ObjectWrap { // private members - // persistent constructor - static Napi::FunctionReference wrappedSessionConstructor; - static Napi::FunctionReference ortTensorConstructor; - // session objects bool initialized_; bool disposed_; std::unique_ptr session_; - std::unique_ptr defaultRunOptions_; // input/output metadata std::vector inputNames_; - std::vector inputTypes_; - std::vector inputTensorElementDataTypes_; + std::vector inputTypes_; std::vector outputNames_; - std::vector outputTypes_; - std::vector outputTensorElementDataTypes_; + std::vector outputTypes_; // preferred output locations std::vector preferredOutputLocations_; diff --git a/js/node/src/ort_instance_data.cc b/js/node/src/ort_instance_data.cc new file mode 100644 index 0000000000000..8b9d5743feb5d --- /dev/null +++ b/js/node/src/ort_instance_data.cc @@ -0,0 +1,35 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include "common.h" +#include "ort_instance_data.h" +#include "ort_singleton_data.h" +#include "onnxruntime_cxx_api.h" + +OrtInstanceData::OrtInstanceData() { +} + +void OrtInstanceData::Create(Napi::Env env, Napi::Function inferenceSessionWrapperFunction) { + ORT_NAPI_THROW_ERROR_IF(env.GetInstanceData() != nullptr, env, "OrtInstanceData already created."); + auto data = new OrtInstanceData{}; + data->wrappedSessionConstructor = Napi::Persistent(inferenceSessionWrapperFunction); + env.SetInstanceData(data); +} + +void OrtInstanceData::InitOrt(Napi::Env env, int log_level, Napi::Function tensorConstructor, bool is_main_thread) { + auto data = env.GetInstanceData(); + ORT_NAPI_THROW_ERROR_IF(data == nullptr, env, "OrtInstanceData not created."); + + data->ortTensorConstructor = Napi::Persistent(tensorConstructor); + + // Initialize ORT singleton and register cleanup hook for this env. + // The first call creates the OrtObjects; subsequent calls increment the ref count. + OrtSingletonData::InitOrtObjects(env, log_level, is_main_thread); +} + +const Napi::FunctionReference& OrtInstanceData::TensorConstructor(Napi::Env env) { + auto data = env.GetInstanceData(); + ORT_NAPI_THROW_ERROR_IF(data == nullptr, env, "OrtInstanceData not created."); + + return data->ortTensorConstructor; +} diff --git a/js/node/src/ort_instance_data.h b/js/node/src/ort_instance_data.h new file mode 100644 index 0000000000000..5945d98fb0022 --- /dev/null +++ b/js/node/src/ort_instance_data.h @@ -0,0 +1,32 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include "onnxruntime_cxx_api.h" + +/** + * The OrtInstanceData class is designed to manage the lifecycle of necessary instance data, including: + * - The Object reference of the InferenceSessionWrap class and the Tensor constructor. + * This is a per-env data that has the same lifecycle as the Napi::Env. If there are worker threads, each thread will + * have its own handle to the InferenceSessionWrap class and the Tensor constructor. + * + * The OrtInstanceData class is bind to the Napi::Env using environment life cycle APIs. + * see https://nodejs.org/api/n-api.html#environment-life-cycle-apis + */ +struct OrtInstanceData { + // Create a new OrtInstanceData object related to the Napi::Env + static void Create(Napi::Env env, Napi::Function inferenceSessionWrapperFunction); + // Initialize Ort for the Napi::Env + static void InitOrt(Napi::Env env, int log_level, Napi::Function tensorConstructor, bool is_main_thread); + // Get the Tensor constructor reference for the Napi::Env + static const Napi::FunctionReference& TensorConstructor(Napi::Env env); + + private: + OrtInstanceData(); + + // per env persistent constructors + Napi::FunctionReference wrappedSessionConstructor; + Napi::FunctionReference ortTensorConstructor; +}; diff --git a/js/node/src/ort_singleton_data.cc b/js/node/src/ort_singleton_data.cc new file mode 100644 index 0000000000000..d1d57a10340c5 --- /dev/null +++ b/js/node/src/ort_singleton_data.cc @@ -0,0 +1,49 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#include +#include + +#include "ort_singleton_data.h" + +namespace { +std::mutex ort_singleton_mutex; +std::atomic ort_objects{nullptr}; +std::atomic ref_count{0}; +} // namespace + +OrtSingletonData::OrtObjects::OrtObjects(int log_level) + : env{OrtLoggingLevel(log_level), "onnxruntime-node"}, + default_run_options{} { +} + +void OrtSingletonData::InitOrtObjects(napi_env env, int log_level, + bool is_main_thread) { + { + std::lock_guard lock(ort_singleton_mutex); + if (!ort_objects.load(std::memory_order_relaxed)) { + ort_objects.store(new OrtObjects(log_level), std::memory_order_release); + } + ref_count++; + } + + // Register a cleanup hook for this napi_env. The hook will be called when this env is torn down. + // We encode the is_main_thread flag directly into the void* arg to avoid a heap allocation. + napi_add_env_cleanup_hook(env, CleanupHook, reinterpret_cast(static_cast(is_main_thread))); +} + +void OrtSingletonData::CleanupHook(void* arg) { + bool is_main_thread = static_cast(reinterpret_cast(arg)); + + std::lock_guard lock(ort_singleton_mutex); + ref_count--; + + if (ref_count == 0 && is_main_thread) { + delete ort_objects.load(std::memory_order_relaxed); + ort_objects.store(nullptr, std::memory_order_release); + } +} + +OrtSingletonData::OrtObjects* OrtSingletonData::GetOrtObjects() { + return ort_objects.load(std::memory_order_acquire); +} diff --git a/js/node/src/ort_singleton_data.h b/js/node/src/ort_singleton_data.h new file mode 100644 index 0000000000000..a0577cb71e98b --- /dev/null +++ b/js/node/src/ort_singleton_data.h @@ -0,0 +1,57 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +#pragma once + +#include +#include "onnxruntime_cxx_api.h" + +/** + * The OrtSingletonData class is designed to manage the lifecycle of necessary singleton instance data, including: + * + * - The Ort::Env singleton instance. + * This is a global singleton that is shared across all InferenceSessionWrap instances. It is created when the first + * time `InferenceSession.initOrtOnce()` is called. + * + * - The Ort::RunOptions singleton instance. + * This is an empty default RunOptions instance. It is created once to allow reuse across all session inference runs. + * + * The OrtSingletonData class uses a ref-counted, heap-allocated singleton with best-effort cleanup. + * + * Each napi_env (one per thread) that initializes ORT increments a ref count and registers a cleanup hook via + * napi_add_env_cleanup_hook. When the hook fires, the ref count is decremented. The singleton is only deleted when: + * 1. The ref count reaches 0, AND + * 2. The cleanup hook is running on the main thread (determined by the isMainThread flag from worker_threads). + * + * This ensures: + * - On normal single-threaded usage, the singleton is properly destroyed (no leak). + * - On multi-threaded usage where workers exit before the main thread, the main thread's hook fires last with + * ref count 0 and performs the cleanup. + * - If cleanup hooks don't fire (e.g., uncaught exception — see https://github.com/nodejs/node/issues/58341), + * the ref count stays >0 and the singleton safely leaks, avoiding crashes from calling into an already-unloaded + * onnxruntime shared library. + * - If the main thread's hook fires but workers are still alive (e.g., process.exit()), the ref count is >0 and + * the singleton safely leaks. + */ +struct OrtSingletonData { + struct OrtObjects { + Ort::Env env; + Ort::RunOptions default_run_options; + + private: + // The following pattern ensures that OrtObjects can only be created by OrtSingletonData + OrtObjects(int log_level); + friend struct OrtSingletonData; + }; + + // Initialize ORT objects and register a cleanup hook for the given napi_env. + // Each napi_env (thread) should call this once. + // is_main_thread should be set to true if the calling thread is the main thread (from worker_threads.isMainThread). + static void InitOrtObjects(napi_env env, int log_level, bool is_main_thread); + + // Get the ORT singleton objects. Returns nullptr if the singleton has been destroyed. + static OrtObjects* GetOrtObjects(); + + private: + static void CleanupHook(void* arg); +}; diff --git a/js/node/src/session_options_helper.cc b/js/node/src/session_options_helper.cc index 8c1d7ca06b8c3..bd469d81f1603 100644 --- a/js/node/src/session_options_helper.cc +++ b/js/node/src/session_options_helper.cc @@ -31,6 +31,7 @@ const std::unordered_map GRAPH_OPT_LEVEL_NA {"disabled", ORT_DISABLE_ALL}, {"basic", ORT_ENABLE_BASIC}, {"extended", ORT_ENABLE_EXTENDED}, + {"layout", ORT_ENABLE_LAYOUT}, {"all", ORT_ENABLE_ALL}}; const std::unordered_map EXECUTION_MODE_NAME_TO_ID_MAP = {{"sequential", ORT_SEQUENTIAL}, @@ -46,6 +47,9 @@ void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions& sess #endif #ifdef USE_WEBGPU std::unordered_map webgpu_options; +#endif +#ifdef USE_QNN + std::unordered_map qnn_options; #endif if (epValue.IsString()) { name = epValue.As().Utf8Value(); @@ -60,21 +64,76 @@ void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions& sess deviceId = obj.Get("deviceId").As(); } #ifdef USE_COREML - if (obj.Has("coreMlFlags")) { + if (name == "coreml" && obj.Has("coreMlFlags")) { coreMlFlags = obj.Get("coreMlFlags").As(); } #endif #ifdef USE_WEBGPU - for (const auto& nameIter : obj.GetPropertyNames()) { - Napi::Value nameVar = nameIter.second; - std::string name = nameVar.As().Utf8Value(); - if (name != "name") { + if (name == "webgpu") { + for (const auto& nameIter : obj.GetPropertyNames()) { + Napi::Value nameVar = nameIter.second; + std::string name = nameVar.As().Utf8Value(); Napi::Value valueVar = obj.Get(nameVar); - ORT_NAPI_THROW_TYPEERROR_IF(!valueVar.IsString(), epList.Env(), "Invalid argument: sessionOptions.executionProviders must be a string or an object with property 'name'."); - std::string value = valueVar.As().Utf8Value(); + std::string value; + if (name == "preferredLayout" || + name == "validationMode" || + name == "storageBufferCacheMode" || + name == "uniformBufferCacheMode" || + name == "queryResolveBufferCacheMode" || + name == "defaultBufferCacheMode") { + ORT_NAPI_THROW_TYPEERROR_IF(!valueVar.IsString(), epList.Env(), + "Invalid argument: \"", name, "\" must be a string."); + value = valueVar.As().Utf8Value(); + } else if (name == "forceCpuNodeNames") { + ORT_NAPI_THROW_TYPEERROR_IF(!valueVar.IsArray(), epList.Env(), + "Invalid argument: \"forceCpuNodeNames\" must be a string array."); + auto arr = valueVar.As(); + for (uint32_t i = 0; i < arr.Length(); i++) { + Napi::Value v = arr[i]; + ORT_NAPI_THROW_TYPEERROR_IF(!v.IsString(), epList.Env(), + "Invalid argument: elements of \"forceCpuNodeNames\" must be strings."); + if (i > 0) { + value += '\n'; + } + value += v.As().Utf8Value(); + } + } else { + // unrecognized option + ORT_NAPI_THROW_TYPEERROR_IF(name != "name", epList.Env(), + "Invalid argument: WebGPU EP has an unrecognized option: '", name, "'."); + continue; + } webgpu_options[name] = value; } } +#endif +#ifdef USE_QNN + if (name == "qnn") { + Napi::Value backend_type = obj.Get("backendType"); + if (!backend_type.IsUndefined()) { + if (backend_type.IsString()) { + qnn_options["backend_type"] = backend_type.As().Utf8Value(); + } else { + ORT_NAPI_THROW_TYPEERROR(epList.Env(), "Invalid argument: backendType must be a string."); + } + } + Napi::Value backend_path = obj.Get("backendPath"); + if (!backend_path.IsUndefined()) { + if (backend_path.IsString()) { + qnn_options["backend_path"] = backend_path.As().Utf8Value(); + } else { + ORT_NAPI_THROW_TYPEERROR(epList.Env(), "Invalid argument: backendPath must be a string."); + } + } + Napi::Value enable_htp_fp16_precision = obj.Get("enableFp16Precision"); + if (!enable_htp_fp16_precision.IsUndefined()) { + if (enable_htp_fp16_precision.IsBoolean()) { + qnn_options["enable_htp_fp16_precision"] = enable_htp_fp16_precision.As().Value() ? "1" : "0"; + } else { + ORT_NAPI_THROW_TYPEERROR(epList.Env(), "Invalid argument: enableFp16Precision must be a boolean."); + } + } + } #endif } @@ -84,7 +143,7 @@ void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions& sess #ifdef USE_CUDA } else if (name == "cuda") { OrtCUDAProviderOptionsV2* options; - Ort::GetApi().CreateCUDAProviderOptions(&options); + Ort::ThrowOnError(Ort::GetApi().CreateCUDAProviderOptions(&options)); options->device_id = deviceId; sessionOptions.AppendExecutionProvider_CUDA_V2(*options); Ort::GetApi().ReleaseCUDAProviderOptions(options); @@ -92,7 +151,7 @@ void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions& sess #ifdef USE_TENSORRT } else if (name == "tensorrt") { OrtTensorRTProviderOptionsV2* options; - Ort::GetApi().CreateTensorRTProviderOptions(&options); + Ort::ThrowOnError(Ort::GetApi().CreateTensorRTProviderOptions(&options)); options->device_id = deviceId; sessionOptions.AppendExecutionProvider_TensorRT_V2(*options); Ort::GetApi().ReleaseTensorRTProviderOptions(options); @@ -111,9 +170,6 @@ void ParseExecutionProviders(const Napi::Array epList, Ort::SessionOptions& sess #endif #ifdef USE_QNN } else if (name == "qnn") { - std::unordered_map qnn_options; - qnn_options["backend_path"] = "QnnHtp.dll"; - qnn_options["enable_htp_fp16_precision"] = "1"; sessionOptions.AppendExecutionProvider("QNN", qnn_options); #endif } else { @@ -291,44 +347,46 @@ void ParseSessionOptions(const Napi::Object options, Ort::SessionOptions& sessio // external data if (options.Has("externalData")) { auto externalDataValue = options.Get("externalData"); - ORT_NAPI_THROW_TYPEERROR_IF(!externalDataValue.IsArray(), options.Env(), - "Invalid argument: sessionOptions.externalData must be an array."); - auto externalData = externalDataValue.As(); - std::vector> paths; - std::vector buffs; - std::vector sizes; + if (!externalDataValue.IsNull() && !externalDataValue.IsUndefined()) { + ORT_NAPI_THROW_TYPEERROR_IF(!externalDataValue.IsArray(), options.Env(), + "Invalid argument: sessionOptions.externalData must be an array."); + auto externalData = externalDataValue.As(); + std::vector> paths; + std::vector buffs; + std::vector sizes; - for (const auto& kvp : externalData) { - Napi::Value value = kvp.second; - ORT_NAPI_THROW_TYPEERROR_IF(!value.IsObject(), options.Env(), - "Invalid argument: sessionOptions.externalData value must be an object in Node.js binding."); - Napi::Object obj = value.As(); - ORT_NAPI_THROW_TYPEERROR_IF(!obj.Has("path") || !obj.Get("path").IsString(), options.Env(), - "Invalid argument: sessionOptions.externalData value must have a 'path' property of type string in Node.js binding."); + for (const auto& kvp : externalData) { + Napi::Value value = kvp.second; + ORT_NAPI_THROW_TYPEERROR_IF(!value.IsObject(), options.Env(), + "Invalid argument: sessionOptions.externalData value must be an object in Node.js binding."); + Napi::Object obj = value.As(); + ORT_NAPI_THROW_TYPEERROR_IF(!obj.Has("path") || !obj.Get("path").IsString(), options.Env(), + "Invalid argument: sessionOptions.externalData value must have a 'path' property of type string in Node.js binding."); #ifdef _WIN32 - auto path = obj.Get("path").As().Utf16Value(); - paths.push_back(std::wstring{path.begin(), path.end()}); + auto path = obj.Get("path").As().Utf16Value(); + paths.push_back(std::wstring{path.begin(), path.end()}); #else - auto path = obj.Get("path").As().Utf8Value(); - paths.push_back(path); + auto path = obj.Get("path").As().Utf8Value(); + paths.push_back(path); #endif - ORT_NAPI_THROW_TYPEERROR_IF(!obj.Has("data") || - !obj.Get("data").IsBuffer() || - !(obj.Get("data").IsTypedArray() && obj.Get("data").As().TypedArrayType() == napi_uint8_array), - options.Env(), - "Invalid argument: sessionOptions.externalData value must have an 'data' property of type buffer or typed array in Node.js binding."); + ORT_NAPI_THROW_TYPEERROR_IF(!obj.Has("data") || + !obj.Get("data").IsBuffer() || + !(obj.Get("data").IsTypedArray() && obj.Get("data").As().TypedArrayType() == napi_uint8_array), + options.Env(), + "Invalid argument: sessionOptions.externalData value must have an 'data' property of type buffer or typed array in Node.js binding."); - auto data = obj.Get("data"); - if (data.IsBuffer()) { - buffs.push_back(data.As>().Data()); - sizes.push_back(data.As>().Length()); - } else { - auto typedArray = data.As(); - buffs.push_back(reinterpret_cast(typedArray.ArrayBuffer().Data()) + typedArray.ByteOffset()); - sizes.push_back(typedArray.ByteLength()); + auto data = obj.Get("data"); + if (data.IsBuffer()) { + buffs.push_back(data.As>().Data()); + sizes.push_back(data.As>().Length()); + } else { + auto typedArray = data.As(); + buffs.push_back(reinterpret_cast(typedArray.ArrayBuffer().Data()) + typedArray.ByteOffset()); + sizes.push_back(typedArray.ByteLength()); + } } + sessionOptions.AddExternalInitializersFromFilesInMemory(paths, buffs, sizes); } - sessionOptions.AddExternalInitializersFromFilesInMemory(paths, buffs, sizes); } } diff --git a/js/node/src/tensor_helper.cc b/js/node/src/tensor_helper.cc index 12b1a79793ff3..c4bf5628ce6fe 100644 --- a/js/node/src/tensor_helper.cc +++ b/js/node/src/tensor_helper.cc @@ -7,9 +7,16 @@ #include #include "common.h" +#include "ort_instance_data.h" #include "tensor_helper.h" #include "inference_session_wrap.h" +// napi_float16_array was added in Node.js 23 (N-API version 10). +// Define it for older Node.js versions to support Float16Array input tensors. +#ifndef napi_float16_array +#define napi_float16_array static_cast(11) +#endif + // make sure consistent with origin definition static_assert(ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED == 0, "definition not consistent with OnnxRuntime"); static_assert(ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT == 1, "definition not consistent with OnnxRuntime"); @@ -195,9 +202,20 @@ Ort::Value NapiValueToOrtValue(Napi::Env env, Napi::Value value, OrtMemoryInfo* auto tensorDataTypedArray = tensorDataValue.As(); std::underlying_type_t typedArrayType = tensorDataValue.As().TypedArrayType(); - ORT_NAPI_THROW_TYPEERROR_IF(DATA_TYPE_TYPEDARRAY_MAP[elemType] != typedArrayType, env, - "Tensor.data must be a typed array (", DATA_TYPE_TYPEDARRAY_MAP[elemType], ") for ", - tensorTypeString, " tensors, but got typed array (", typedArrayType, ")."); + + // For float16 tensors, accept both Uint16Array and Float16Array. + // Float16Array is a newer JavaScript type (ES2024) that may be passed by users. + // Both use 16-bit storage, so they are compatible at the binary level. + bool isValidTypedArray = (DATA_TYPE_TYPEDARRAY_MAP[elemType] == typedArrayType); + if (!isValidTypedArray && elemType == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16) { + // Accept Float16Array (napi_float16_array = 11) for float16 tensors + isValidTypedArray = (typedArrayType == napi_float16_array); + } + + ORT_NAPI_THROW_TYPEERROR_IF(!isValidTypedArray, env, + "Tensor.data must be a typed array (", DATA_TYPE_TYPEDARRAY_MAP[elemType], + elemType == ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16 ? " or Float16Array" : "", + ") for ", tensorTypeString, " tensors, but got typed array (", typedArrayType, ")."); char* buffer = reinterpret_cast(tensorDataTypedArray.ArrayBuffer().Data()); size_t bufferByteOffset = tensorDataTypedArray.ByteOffset(); @@ -250,7 +268,7 @@ Napi::Value OrtValueToNapiValue(Napi::Env env, Ort::Value&& value) { // location auto memoryInfo = value.GetTensorMemoryInfo(); bool isGpuBuffer = memoryInfo.GetDeviceType() == OrtMemoryInfoDeviceType_GPU && - memoryInfo.GetAllocatorName() == "WebGPU_Buffer"; + memoryInfo.GetAllocatorName() == "WebGPU_Buf"; // size auto size = tensorTypeAndShapeInfo.GetElementCount(); @@ -275,12 +293,18 @@ Napi::Value OrtValueToNapiValue(Napi::Env env, Ort::Value&& value) { } // new Tensor("string", stringArray /* string[] */, dims /* number[] */) - return scope.Escape(InferenceSessionWrap::GetTensorConstructor().New({Napi::String::New(env, "string"), stringArray, dims})); + return scope.Escape(OrtInstanceData::TensorConstructor(env) + .New({Napi::String::New(env, "string"), + stringArray, + dims})); } else { // number data if (isGpuBuffer) { // Tensor.fromGpuBuffer(buffer, options) - Napi::Function tensorFromGpuBuffer = InferenceSessionWrap::GetTensorConstructor().Value().Get("fromGpuBuffer").As(); + Napi::Function tensorFromGpuBuffer = OrtInstanceData::TensorConstructor(env) + .Value() + .Get("fromGpuBuffer") + .As(); OrtValue* underlyingOrtValue = value.release(); auto options = Napi::Object::New(env); @@ -311,10 +335,10 @@ Napi::Value OrtValueToNapiValue(Napi::Env env, Ort::Value&& value) { NAPI_THROW_IF_FAILED(env, status, Napi::Value); // new Tensor(type, typedArrayData, dims) - return scope.Escape(InferenceSessionWrap::GetTensorConstructor().New( - {type, - Napi::Value(env, typedArrayData), - dims})); + return scope.Escape(OrtInstanceData::TensorConstructor(env) + .New({type, + Napi::Value(env, typedArrayData), + dims})); } } } diff --git a/js/node/test/e2e/inference-session-run.ts b/js/node/test/api/inference-session-run.ts similarity index 93% rename from js/node/test/e2e/inference-session-run.ts rename to js/node/test/api/inference-session-run.ts index 820dec0945a8e..7a4cc25410330 100644 --- a/js/node/test/e2e/inference-session-run.ts +++ b/js/node/test/api/inference-session-run.ts @@ -6,7 +6,7 @@ import * as path from 'path'; import { assertTensorEqual, SQUEEZENET_INPUT0_DATA, SQUEEZENET_OUTPUT0_DATA, TEST_DATA_ROOT } from '../test-utils'; -describe('E2E Tests - InferenceSession.run()', async () => { +describe('API Tests - InferenceSession.run()', async () => { let session: InferenceSession; const input0 = new Tensor('float32', SQUEEZENET_INPUT0_DATA, [1, 3, 224, 224]); const expectedOutput0 = new Tensor('float32', SQUEEZENET_OUTPUT0_DATA, [1, 1000, 1, 1]); diff --git a/js/node/test/api/simple-api-tests.ts b/js/node/test/api/simple-api-tests.ts new file mode 100644 index 0000000000000..da7adecc3d4e4 --- /dev/null +++ b/js/node/test/api/simple-api-tests.ts @@ -0,0 +1,113 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import assert from 'assert'; +import { InferenceSession, Tensor } from 'onnxruntime-common'; +import * as path from 'path'; + +import { assertDataEqual, TEST_DATA_ROOT } from '../test-utils'; + +const MODEL_TEST_TYPES_CASES: Array<{ + model: string; + type: Tensor.Type; + input0: Tensor.DataType; + expectedOutput0: Tensor.DataType; +}> = [ + { + model: path.join(TEST_DATA_ROOT, 'test_types_bool.onnx'), + type: 'bool', + input0: Uint8Array.from([1, 0, 0, 1, 0]), + expectedOutput0: Uint8Array.from([1, 0, 0, 1, 0]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_double.onnx'), + type: 'float64', + input0: Float64Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), + expectedOutput0: Float64Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_float.onnx'), + type: 'float32', + input0: Float32Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), + expectedOutput0: Float32Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_int8.onnx'), + type: 'int8', + input0: Int8Array.from([1, -2, 3, 4, -5]), + expectedOutput0: Int8Array.from([1, -2, 3, 4, -5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_int16.onnx'), + type: 'int16', + input0: Int16Array.from([1, -2, 3, 4, -5]), + expectedOutput0: Int16Array.from([1, -2, 3, 4, -5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_int32.onnx'), + type: 'int32', + input0: Int32Array.from([1, -2, 3, 4, -5]), + expectedOutput0: Int32Array.from([1, -2, 3, 4, -5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_int64.onnx'), + type: 'int64', + input0: BigInt64Array.from([BigInt(1), BigInt(-2), BigInt(3), BigInt(4), BigInt(-5)]), + expectedOutput0: BigInt64Array.from([BigInt(1), BigInt(-2), BigInt(3), BigInt(4), BigInt(-5)]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_string.onnx'), + type: 'string', + input0: ['a', 'b', 'c', 'd', 'e'], + expectedOutput0: ['a', 'b', 'c', 'd', 'e'], + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_uint8.onnx'), + type: 'uint8', + input0: Uint8Array.from([1, 2, 3, 4, 5]), + expectedOutput0: Uint8Array.from([1, 2, 3, 4, 5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_uint16.onnx'), + type: 'uint16', + input0: Uint16Array.from([1, 2, 3, 4, 5]), + expectedOutput0: Uint16Array.from([1, 2, 3, 4, 5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_uint32.onnx'), + type: 'uint32', + input0: Uint32Array.from([1, 2, 3, 4, 5]), + expectedOutput0: Uint32Array.from([1, 2, 3, 4, 5]), + }, + { + model: path.join(TEST_DATA_ROOT, 'test_types_uint64.onnx'), + type: 'uint64', + input0: BigUint64Array.from([BigInt(1), BigInt(2), BigInt(3), BigInt(4), BigInt(5)]), + expectedOutput0: BigUint64Array.from([BigInt(1), BigInt(2), BigInt(3), BigInt(4), BigInt(5)]), + }, +]; + +describe('API Tests - simple API tests', () => { + MODEL_TEST_TYPES_CASES.forEach((testCase) => { + it(`${testCase.model}`, async () => { + const session = await InferenceSession.create(testCase.model); + const output = await session.run({ input: new Tensor(testCase.type, testCase.input0, [1, 5]) }); + assert(Object.prototype.hasOwnProperty.call(output, 'output'), "'output' should be in the result object."); + assert(output.output instanceof Tensor, 'result[output] should be a Tensor object.'); + assert.strictEqual(output.output.size, 5, `output size expected 5, got ${output.output.size}.`); + assert.strictEqual( + output.output.type, + testCase.type, + `tensor type expected ${testCase.type}, got ${output.output.type}.`, + ); + assert.strictEqual( + Object.getPrototypeOf(output.output.data), + Object.getPrototypeOf(testCase.expectedOutput0), + `tensor data expected ${Object.getPrototypeOf(testCase.expectedOutput0).constructor.name}, got ${ + Object.getPrototypeOf(output.output.data).constructor.name + }`, + ); + assertDataEqual(testCase.type, output.output.data, testCase.expectedOutput0); + }); + }); +}); diff --git a/js/node/test/api/worker-test.ts b/js/node/test/api/worker-test.ts new file mode 100644 index 0000000000000..1e4907db9fd5b --- /dev/null +++ b/js/node/test/api/worker-test.ts @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { Worker, isMainThread, parentPort } from 'node:worker_threads'; +import { InferenceSession, Tensor } from 'onnxruntime-common'; +import { assertTensorEqual, SQUEEZENET_INPUT0_DATA, SQUEEZENET_OUTPUT0_DATA, TEST_DATA_ROOT } from '../test-utils'; +import * as path from 'path'; + +if (isMainThread) { + describe('API Tests - worker test', () => { + it('should run in worker', (done) => { + const worker = new Worker(__filename, { + stdout: true, + stderr: true, + }); + worker.on('message', (msg) => { + if (msg.result === 'success') { + done(); + } else { + done(new Error(`Worker failed: ${msg.error}`)); + } + }); + worker.on('error', (err) => { + console.error(`Worker error: ${err}`); + done(err); + }); + }); + }); +} else { + const workerMain = async () => { + // require onnxruntime-node. + require('../..'); + + const input0 = new Tensor('float32', SQUEEZENET_INPUT0_DATA, [1, 3, 224, 224]); + const expectedOutput0 = new Tensor('float32', SQUEEZENET_OUTPUT0_DATA, [1, 1000, 1, 1]); + + const session = await InferenceSession.create(path.join(TEST_DATA_ROOT, 'squeezenet.onnx')); + + const result = await session!.run({ data_0: input0 }, ['softmaxout_1']); + console.log('result:', result); + assertTensorEqual(result.softmaxout_1, expectedOutput0); + }; + workerMain().then( + () => { + parentPort?.postMessage({ result: 'success' }); + }, + (err) => { + parentPort?.postMessage({ result: 'failed', error: err }); + }, + ); +} diff --git a/js/node/test/e2e/simple-e2e-tests.ts b/js/node/test/e2e/simple-e2e-tests.ts deleted file mode 100644 index 6841dae316304..0000000000000 --- a/js/node/test/e2e/simple-e2e-tests.ts +++ /dev/null @@ -1,113 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -import assert from 'assert'; -import { InferenceSession, Tensor } from 'onnxruntime-common'; -import * as path from 'path'; - -import { assertDataEqual, TEST_DATA_ROOT } from '../test-utils'; - -const MODEL_TEST_TYPES_CASES: Array<{ - model: string; - type: Tensor.Type; - input0: Tensor.DataType; - expectedOutput0: Tensor.DataType; -}> = [ - { - model: path.join(TEST_DATA_ROOT, 'test_types_bool.onnx'), - type: 'bool', - input0: Uint8Array.from([1, 0, 0, 1, 0]), - expectedOutput0: Uint8Array.from([1, 0, 0, 1, 0]), - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_double.onnx'), - type: 'float64', - input0: Float64Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), - expectedOutput0: Float64Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_float.onnx'), - type: 'float32', - input0: Float32Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), - expectedOutput0: Float32Array.from([1.0, 2.0, 3.0, 4.0, 5.0]), - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_int8.onnx'), - type: 'int8', - input0: Int8Array.from([1, -2, 3, 4, -5]), - expectedOutput0: Int8Array.from([1, -2, 3, 4, -5]), - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_int16.onnx'), - type: 'int16', - input0: Int16Array.from([1, -2, 3, 4, -5]), - expectedOutput0: Int16Array.from([1, -2, 3, 4, -5]), - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_int32.onnx'), - type: 'int32', - input0: Int32Array.from([1, -2, 3, 4, -5]), - expectedOutput0: Int32Array.from([1, -2, 3, 4, -5]), - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_int64.onnx'), - type: 'int64', - input0: BigInt64Array.from([BigInt(1), BigInt(-2), BigInt(3), BigInt(4), BigInt(-5)]), - expectedOutput0: BigInt64Array.from([BigInt(1), BigInt(-2), BigInt(3), BigInt(4), BigInt(-5)]), - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_string.onnx'), - type: 'string', - input0: ['a', 'b', 'c', 'd', 'e'], - expectedOutput0: ['a', 'b', 'c', 'd', 'e'], - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_uint8.onnx'), - type: 'uint8', - input0: Uint8Array.from([1, 2, 3, 4, 5]), - expectedOutput0: Uint8Array.from([1, 2, 3, 4, 5]), - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_uint16.onnx'), - type: 'uint16', - input0: Uint16Array.from([1, 2, 3, 4, 5]), - expectedOutput0: Uint16Array.from([1, 2, 3, 4, 5]), - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_uint32.onnx'), - type: 'uint32', - input0: Uint32Array.from([1, 2, 3, 4, 5]), - expectedOutput0: Uint32Array.from([1, 2, 3, 4, 5]), - }, - { - model: path.join(TEST_DATA_ROOT, 'test_types_uint64.onnx'), - type: 'uint64', - input0: BigUint64Array.from([BigInt(1), BigInt(2), BigInt(3), BigInt(4), BigInt(5)]), - expectedOutput0: BigUint64Array.from([BigInt(1), BigInt(2), BigInt(3), BigInt(4), BigInt(5)]), - }, -]; - -describe('E2E Tests - simple E2E tests', () => { - MODEL_TEST_TYPES_CASES.forEach((testCase) => { - it(`${testCase.model}`, async () => { - const session = await InferenceSession.create(testCase.model); - const output = await session.run({ input: new Tensor(testCase.type, testCase.input0, [1, 5]) }); - assert(Object.prototype.hasOwnProperty.call(output, 'output'), "'output' should be in the result object."); - assert(output.output instanceof Tensor, 'result[output] should be a Tensor object.'); - assert.strictEqual(output.output.size, 5, `output size expected 5, got ${output.output.size}.`); - assert.strictEqual( - output.output.type, - testCase.type, - `tensor type expected ${testCase.type}, got ${output.output.type}.`, - ); - assert.strictEqual( - Object.getPrototypeOf(output.output.data), - Object.getPrototypeOf(testCase.expectedOutput0), - `tensor data expected ${Object.getPrototypeOf(testCase.expectedOutput0).constructor.name}, got ${ - Object.getPrototypeOf(output.output.data).constructor.name - }`, - ); - assertDataEqual(testCase.type, output.output.data, testCase.expectedOutput0); - }); - }); -}); diff --git a/js/node/test/standalone/README.md b/js/node/test/standalone/README.md new file mode 100644 index 0000000000000..dbd184471452d --- /dev/null +++ b/js/node/test/standalone/README.md @@ -0,0 +1,23 @@ +# Process Exit Tests + +These tests verify that the ORT Node.js binding handles various process exit scenarios without crashing, specifically addressing the mutex crash issue reported in [#24579](https://github.com/microsoft/onnxruntime/issues/24579). + +## What This Tests + +- **Normal process exit** - Verifies clean shutdown without mutex crashes +- **`process.exit()` calls** - Tests the primary crash scenario that was fixed +- **Uncaught exceptions** - Ensures crashes don't occur during unexpected exits +- **Session cleanup** - Tests both explicit `session.release()` and automatic cleanup +- **Stability** - Multiple runs to ensure consistent behavior + +## How It Works + +Each test runs in a separate Node.js process to isolate the test environment. Tests use command-line flags to control behavior: + +- `--process-exit`: Triggers `process.exit(0)` +- `--throw-exception`: Throws an uncaught exception +- `--release`: Calls `session.release()` before exit + +## Expected Result + +All tests should pass without `mutex lock failed` or `std::__1::system_error` messages in stderr. diff --git a/js/node/test/standalone/index.ts b/js/node/test/standalone/index.ts new file mode 100644 index 0000000000000..3125d9d51466c --- /dev/null +++ b/js/node/test/standalone/index.ts @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import { spawn } from 'child_process'; +import * as assert from 'assert'; +import * as path from 'path'; + +describe('Standalone Process Tests', () => { + // Helper function to run test script in a separate process + const runTest = async (args: string[] = []): Promise<{ code: number; stdout: string; stderr: string }> => + new Promise((resolve, reject) => { + // Use the compiled main.js file from the lib directory + const testFile = path.join(__dirname, './main.js'); + + const child = spawn('node', [testFile, ...args], { stdio: 'pipe' }); + + let stdout = ''; + let stderr = ''; + + child.stdout.on('data', (data) => (stdout += data.toString())); + child.stderr.on('data', (data) => (stderr += data.toString())); + + child.on('close', (code) => { + resolve({ code: code || 0, stdout, stderr }); + }); + + child.on('error', reject); + }); + + // Helper function to check basic success criteria + const assertSuccess = (result: { code: number; stdout: string; stderr: string }) => { + assert.strictEqual(result.code, 0); + assert.ok(result.stdout.includes('SUCCESS: Inference completed')); + assert.ok(!result.stderr.includes('mutex lock failed')); + }; + + // Helper function to check that no mutex crashes occurred + const assertNoMutexErrors = (stderr: string) => { + assert.ok(!stderr.includes('mutex lock failed')); + assert.ok(!stderr.includes('std::__1::system_error')); + }; + + it('should handle normal process exit', async () => { + const result = await runTest([]); + assertSuccess(result); + }); + + it('should handle process.exit() call', async () => { + const result = await runTest(['--process-exit']); + assertSuccess(result); + }); + + it('should handle uncaught exceptions', async () => { + const result = await runTest(['--throw-exception']); + + assert.notStrictEqual(result.code, 0); + assert.ok(result.stdout.includes('SUCCESS: Inference completed')); + assert.ok(result.stderr.includes('Test exception')); + assertNoMutexErrors(result.stderr); + }); + + it('should handle multiple process exits consistently', async () => { + for (let i = 0; i < 3; i++) { + const result = await runTest(['--process-exit']); + assertSuccess(result); + } + }); + + it('should handle session.release() before normal exit', async () => { + const result = await runTest(['--release']); + assertSuccess(result); + assert.ok(result.stdout.includes('Session released')); + }); + + it('should handle session.release() before process.exit()', async () => { + const result = await runTest(['--release', '--process-exit']); + assertSuccess(result); + assert.ok(result.stdout.includes('Session released')); + }); + + it('should handle no session.release() before process.exit()', async () => { + const result = await runTest(['--process-exit']); + assertSuccess(result); + assert.ok(result.stdout.includes('Session NOT released')); + }); +}); diff --git a/js/node/test/standalone/main.ts b/js/node/test/standalone/main.ts new file mode 100644 index 0000000000000..dceb7ceff3ef0 --- /dev/null +++ b/js/node/test/standalone/main.ts @@ -0,0 +1,51 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import * as path from 'path'; +const ort = require(path.join(__dirname, '../../')); +import * as process from 'process'; + +const modelData = + 'CAMSDGJhY2tlbmQtdGVzdDpiChEKAWEKAWISAWMiBk1hdE11bBIOdGVzdF9tYXRtdWxfMmRaEwoBYRIOCgwIARIICgIIAwoCCARaEwoBYhIOCgwIARIICgIIBAoCCANiEwoBYxIOCgwIARIICgIIAwoCCANCAhAJ'; +const shouldProcessExit = process.argv.includes('--process-exit'); +const shouldThrowException = process.argv.includes('--throw-exception'); +const shouldRelease = process.argv.includes('--release'); + +async function main() { + try { + const modelBuffer = Buffer.from(modelData, 'base64'); + const session = await ort.InferenceSession.create(modelBuffer); + + const dataA = Float32Array.from([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]); + const dataB = Float32Array.from([10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110, 120]); + const tensorA = new ort.Tensor('float32', dataA, [3, 4]); + const tensorB = new ort.Tensor('float32', dataB, [4, 3]); + + const results = await session.run({ a: tensorA, b: tensorB }); + console.log('SUCCESS: Inference completed'); + console.log(`Result: ${results.c.data}`); + + if (shouldRelease) { + await session.release(); + console.log('Session released'); + } else { + console.log('Session NOT released (testing cleanup behavior)'); + } + + if (shouldThrowException) { + setTimeout(() => { + throw new Error('Test exception'); + }, 10); + return; + } + + if (shouldProcessExit) { + process.exit(0); + } + } catch (e) { + console.error(`ERROR: ${e}`); + process.exit(1); + } +} + +void main(); diff --git a/js/node/test/test-main.ts b/js/node/test/test-main.ts index fc792179d3373..d4599eecf7253 100644 --- a/js/node/test/test-main.ts +++ b/js/node/test/test-main.ts @@ -15,11 +15,16 @@ warmup(); // unittests require('./unittests/lib/index'); require('./unittests/lib/inference-session'); +require('./unittests/lib/model-metadata'); require('./unittests/lib/tensor'); -// E2E tests -require('./e2e/simple-e2e-tests'); -require('./e2e/inference-session-run'); +// API tests +require('./api/simple-api-tests'); +require('./api/inference-session-run'); +require('./api/worker-test'); + +// standalone tests +require('./standalone/index'); // Test ONNX spec tests import { run as runTestRunner } from './test-runner'; diff --git a/js/node/test/test-utils.ts b/js/node/test/test-utils.ts index 72ed2c3db2b6e..eecb8f1da0133 100644 --- a/js/node/test/test-utils.ts +++ b/js/node/test/test-utils.ts @@ -88,7 +88,7 @@ export function warmup(): void { try { const session = await InferenceSession.create(path.join(TEST_DATA_ROOT, 'test_types_int32.onnx')); await session.run({ input: new Tensor(new Float32Array(5), [1, 5]) }, { output: null }, {}); - } catch (e) {} + } catch {} }); } diff --git a/js/node/test/unittests/lib/inference-session.ts b/js/node/test/unittests/lib/inference-session.ts index 645f62cece135..89b37d2479397 100644 --- a/js/node/test/unittests/lib/inference-session.ts +++ b/js/node/test/unittests/lib/inference-session.ts @@ -95,7 +95,7 @@ describe('UnitTests - InferenceSession.create()', () => { async () => { await InferenceSession.create(new Uint8Array(0)); }, - { name: 'Error', message: /No graph was found in the protobuf/ }, + { name: 'Error', message: /Model data pointer is null./ }, ); }); // #endregion diff --git a/js/node/test/unittests/lib/model-metadata.ts b/js/node/test/unittests/lib/model-metadata.ts new file mode 100644 index 0000000000000..e58c86d39a742 --- /dev/null +++ b/js/node/test/unittests/lib/model-metadata.ts @@ -0,0 +1,86 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +import * as assert from 'assert'; +import { InferenceSession } from 'onnxruntime-common'; + +const ONNX_MODEL_TEST_ABS_NO_SHAPE = Uint8Array.from([ + 8, 9, 58, 73, 10, 31, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 8, 111, 117, 116, 112, 117, 116, 95, 48, 26, 3, 65, + 98, 115, 34, 3, 65, 98, 115, 58, 0, 18, 3, 97, 98, 115, 90, 15, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 4, 10, 2, + 8, 1, 98, 16, 10, 8, 111, 117, 116, 112, 117, 116, 95, 48, 18, 4, 10, 2, 8, 1, 66, 4, 10, 0, 16, 21, +]); + +const ONNX_MODEL_TEST_ABS_SYMBOL = Uint8Array.from([ + 8, 9, 58, 105, 10, 31, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 8, 111, 117, 116, 112, 117, 116, 95, 48, 26, 3, 65, + 98, 115, 34, 3, 65, 98, 115, 58, 0, 18, 3, 97, 98, 115, 90, 47, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 36, 10, + 34, 8, 1, 18, 30, 10, 13, 18, 11, 95, 105, 110, 112, 117, 116, 95, 48, 95, 100, 48, 10, 13, 18, 11, 95, 105, 110, 112, + 117, 116, 95, 48, 95, 100, 49, 98, 16, 10, 8, 111, 117, 116, 112, 117, 116, 95, 48, 18, 4, 10, 2, 8, 1, 66, 4, 10, 0, + 16, 21, +]); + +const ONNX_MODEL_TEST_ABS_STATIC = Uint8Array.from([ + 8, 9, 58, 83, 10, 31, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 8, 111, 117, 116, 112, 117, 116, 95, 48, 26, 3, 65, + 98, 115, 34, 3, 65, 98, 115, 58, 0, 18, 3, 97, 98, 115, 90, 25, 10, 7, 105, 110, 112, 117, 116, 95, 48, 18, 14, 10, + 12, 8, 1, 18, 8, 10, 2, 8, 2, 10, 2, 8, 4, 98, 16, 10, 8, 111, 117, 116, 112, 117, 116, 95, 48, 18, 4, 10, 2, 8, 1, + 66, 4, 10, 0, 16, 21, +]); + +const testModelMetadata = async ( + model: Uint8Array, + expectedInputNames: string[], + expectedOutputNames: string[], + expectedInputMetadata: InferenceSession.ValueMetadata[], + expectedOutputMetadata: InferenceSession.ValueMetadata[], +) => { + const session = await InferenceSession.create(model); + assert.deepStrictEqual(session.inputNames, expectedInputNames); + assert.deepStrictEqual(session.outputNames, expectedOutputNames); + assert.deepStrictEqual(session.inputMetadata, expectedInputMetadata); + assert.deepStrictEqual(session.outputMetadata, expectedOutputMetadata); +}; + +describe('#UnitTest# - test model input/output metadata', () => { + it('model input/output with no shape', async () => { + await testModelMetadata( + ONNX_MODEL_TEST_ABS_NO_SHAPE, + ['input_0'], + ['output_0'], + [{ name: 'input_0', isTensor: true, type: 'float32', shape: [] }], + [{ name: 'output_0', isTensor: true, type: 'float32', shape: [] }], + ); + }); + + it('model input/output with symbol shape', async () => { + await testModelMetadata( + ONNX_MODEL_TEST_ABS_SYMBOL, + ['input_0'], + ['output_0'], + [ + { + name: 'input_0', + isTensor: true, + type: 'float32', + shape: ['_input_0_d0', '_input_0_d1'], + }, + ], + [ + { + name: 'output_0', + isTensor: true, + type: 'float32', + shape: ['_input_0_d0', '_input_0_d1'], + }, + ], + ); + }); + + it('model input/output with static shape', async () => { + await testModelMetadata( + ONNX_MODEL_TEST_ABS_STATIC, + ['input_0'], + ['output_0'], + [{ name: 'input_0', isTensor: true, type: 'float32', shape: [2, 4] }], + [{ name: 'output_0', isTensor: true, type: 'float32', shape: [2, 4] }], + ); + }); +}); diff --git a/js/node/test/unittests/lib/tensor.ts b/js/node/test/unittests/lib/tensor.ts index 9e09c4e816fba..844292df076a2 100644 --- a/js/node/test/unittests/lib/tensor.ts +++ b/js/node/test/unittests/lib/tensor.ts @@ -72,7 +72,11 @@ describe('UnitTests - tensor', () => { assert.throws( () => { const badDims = {}; - passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); + if (passtypeParam) { + new TensorAny(type, data, badDims); + } else { + new TensorAny(data, badDims); + } }, { name: 'TypeError', message: /must be a number array/ }, ); @@ -82,7 +86,11 @@ describe('UnitTests - tensor', () => { assert.throws( () => { const badDims = [1, 2, '']; - passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); + if (passtypeParam) { + new TensorAny(type, data, badDims); + } else { + new TensorAny(data, badDims); + } }, { name: 'TypeError', message: /must be an integer/ }, ); @@ -92,7 +100,11 @@ describe('UnitTests - tensor', () => { assert.throws( () => { const badDims = [1, 2, -1]; - passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); + if (passtypeParam) { + new TensorAny(type, data, badDims); + } else { + new TensorAny(data, badDims); + } }, { name: 'RangeError', message: /must be a non-negative integer/ }, ); @@ -102,7 +114,11 @@ describe('UnitTests - tensor', () => { assert.throws( () => { const badDims = [1, 2, 1.5]; - passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); + if (passtypeParam) { + new TensorAny(type, data, badDims); + } else { + new TensorAny(data, badDims); + } }, { name: 'TypeError', message: /must be an integer/ }, ); @@ -113,7 +129,11 @@ describe('UnitTests - tensor', () => { assert.throws( () => { const badDims = [10, 8]; - passtypeParam ? new TensorAny(type, data, badDims) : new TensorAny(data, badDims); + if (passtypeParam) { + new TensorAny(type, data, badDims); + } else { + new TensorAny(data, badDims); + } }, { name: 'Error', message: /does not match data length/ }, ); diff --git a/js/package-lock.json b/js/package-lock.json index e915c001655d1..01f3c359cc4c5 100644 --- a/js/package-lock.json +++ b/js/package-lock.json @@ -6,25 +6,29 @@ "": { "license": "MIT", "devDependencies": { + "@eslint/compat": "^1.4.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.38.0", "@types/fs-extra": "^11.0.4", - "@types/global-agent": "^2.1.3", + "@types/global-agent": "^3.0.0", "@types/mocha": "^10.0.2", - "@types/node": "^18.14.6", + "@types/node": "^20.10.0", "@types/npmlog": "^4.1.4", - "@typescript-eslint/eslint-plugin": "^7.4.0", - "@typescript-eslint/parser": "^7.4.0", + "@typescript-eslint/eslint-plugin": "^8.46.2", + "@typescript-eslint/parser": "^8.46.2", "dir-compare": "^4.2.0", - "esbuild": "^0.19.3", + "esbuild": "^0.25.0", "esbuild-plugin-polyfill-node": "^0.3.0", - "eslint": "^8.51.0", + "eslint": "^9.38.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-header": "^3.1.1", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsdoc": "^46.8.2", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsdoc": "^61.1.9", "eslint-plugin-prefer-arrow": "^1.2.3", - "eslint-plugin-unicorn": "^48.0.1", + "eslint-plugin-unicorn": "^62.0.0", "fs-extra": "^11.2.0", - "global-agent": "^3.0", + "global-agent": "^4.1.3", + "globals": "^16.4.0", "jszip": "^3.10.1", "mocha": "^11.0.1", "npmlog": "^7.0.1", @@ -42,512 +46,570 @@ "node": ">=0.10.0" } }, - "node_modules/@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "dependencies": { - "@babel/highlight": "^7.18.6" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", - "dev": true, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true, - "dependencies": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, + "license": "MIT", "engines": { "node": ">=6.9.0" } }, - "node_modules/@babel/highlight/node_modules/ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "dependencies": { - "color-convert": "^1.9.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "node_modules/@es-joy/jsdoccomment": { + "version": "0.76.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.76.0.tgz", + "integrity": "sha512-g+RihtzFgGTx2WYCuTHbdOXJeAlGnROws0TeALx9ow/ZmOROOZkVg5wp/B44n0WJgI4SQFP1eWM2iRPlU2Y14w==", "dev": true, + "license": "MIT", "dependencies": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" + "@types/estree": "^1.0.8", + "@typescript-eslint/types": "^8.46.0", + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~6.10.0" }, "engines": { - "node": ">=4" - } - }, - "node_modules/@babel/highlight/node_modules/color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "dependencies": { - "color-name": "1.1.3" - } - }, - "node_modules/@babel/highlight/node_modules/color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "node_modules/@babel/highlight/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, - "engines": { - "node": ">=0.8.0" - } - }, - "node_modules/@babel/highlight/node_modules/has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true, - "engines": { - "node": ">=4" + "node": ">=20.11.0" } }, - "node_modules/@babel/highlight/node_modules/supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "node_modules/@es-joy/resolve.exports": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@es-joy/resolve.exports/-/resolve.exports-1.0.0.tgz", + "integrity": "sha512-bbrmzsAZ9GA/3oBS6r8PWMtZarEhKHr413hak8ArwMEZ5DtaLErnkcyEWUsXy7urBcmVu/TpDzHPDVM5uIbx9A==", "dev": true, - "dependencies": { - "has-flag": "^3.0.0" - }, + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=10" } }, - "node_modules/@es-joy/jsdoccomment": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz", - "integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", + "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", + "cpu": [ + "ppc64" + ], "dev": true, - "dependencies": { - "comment-parser": "1.4.0", - "esquery": "^1.5.0", - "jsdoc-type-pratt-parser": "~4.0.0" - }, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=16" + "node": ">=18" } }, "node_modules/@esbuild/android-arm": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.3.tgz", - "integrity": "sha512-Lemgw4io4VZl9GHJmjiBGzQ7ONXRfRPHcUEerndjwiSkbxzrpq0Uggku5MxxrXdwJ+pTj1qyw4jwTu7hkPsgIA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.3.tgz", - "integrity": "sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/android-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.3.tgz", - "integrity": "sha512-FKQJKkK5MXcBHoNZMDNUAg1+WcZlV/cuXrWCoGF/TvdRiYS4znA0m5Il5idUwfxrE20bG/vU1Cr5e1AD6IEIjQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "android" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.3.tgz", - "integrity": "sha512-kw7e3FXU+VsJSSSl2nMKvACYlwtvZB8RUIeVShIEY6PVnuZ3c9+L9lWB2nWeeKWNNYDdtL19foCQ0ZyUL7nqGw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/darwin-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.3.tgz", - "integrity": "sha512-tPfZiwF9rO0jW6Jh9ipi58N5ZLoSjdxXeSrAYypy4psA2Yl1dAMhM71KxVfmjZhJmxRjSnb29YlRXXhh3GqzYw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "darwin" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.3.tgz", - "integrity": "sha512-ERDyjOgYeKe0Vrlr1iLrqTByB026YLPzTytDTz1DRCYM+JI92Dw2dbpRHYmdqn6VBnQ9Bor6J8ZlNwdZdxjlSg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/freebsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.3.tgz", - "integrity": "sha512-nXesBZ2Ad1qL+Rm3crN7NmEVJ5uvfLFPLJev3x1j3feCQXfAhoYrojC681RhpdOph8NsvKBBwpYZHR7W0ifTTA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "freebsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.3.tgz", - "integrity": "sha512-zr48Cg/8zkzZCzDHNxXO/89bf9e+r4HtzNUPoz4GmgAkF1gFAFmfgOdCbR8zMbzFDGb1FqBBhdXUpcTQRYS1cQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", "cpu": [ "arm" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.3.tgz", - "integrity": "sha512-qXvYKmXj8GcJgWq3aGvxL/JG1ZM3UR272SdPU4QSTzD0eymrM7leiZH77pvY3UetCy0k1xuXZ+VPvoJNdtrsWQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ia32": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.3.tgz", - "integrity": "sha512-7XlCKCA0nWcbvYpusARWkFjRQNWNGlt45S+Q18UeS///K6Aw8bB2FKYe9mhVWy/XLShvCweOLZPrnMswIaDXQA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-loong64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.3.tgz", - "integrity": "sha512-qGTgjweER5xqweiWtUIDl9OKz338EQqCwbS9c2Bh5jgEH19xQ1yhgGPNesugmDFq+UUSDtWgZ264st26b3de8A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", "cpu": [ "loong64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-mips64el": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.3.tgz", - "integrity": "sha512-gy1bFskwEyxVMFRNYSvBauDIWNggD6pyxUksc0MV9UOBD138dKTzr8XnM2R4mBsHwVzeuIH8X5JhmNs2Pzrx+A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", "cpu": [ "mips64el" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-ppc64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.3.tgz", - "integrity": "sha512-UrYLFu62x1MmmIe85rpR3qou92wB9lEXluwMB/STDzPF9k8mi/9UvNsG07Tt9AqwPQXluMQ6bZbTzYt01+Ue5g==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", "cpu": [ "ppc64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-riscv64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.3.tgz", - "integrity": "sha512-9E73TfyMCbE+1AwFOg3glnzZ5fBAFK4aawssvuMgCRqCYzE0ylVxxzjEfut8xjmKkR320BEoMui4o/t9KA96gA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", "cpu": [ "riscv64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-s390x": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.3.tgz", - "integrity": "sha512-LlmsbuBdm1/D66TJ3HW6URY8wO6IlYHf+ChOUz8SUAjVTuaisfuwCOAgcxo3Zsu3BZGxmI7yt//yGOxV+lHcEA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", "cpu": [ "s390x" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/linux-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.3.tgz", - "integrity": "sha512-ogV0+GwEmvwg/8ZbsyfkYGaLACBQWDvO0Kkh8LKBGKj9Ru8VM39zssrnu9Sxn1wbapA2qNS6BiLdwJZGouyCwQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", + "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "linux" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", + "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/netbsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.3.tgz", - "integrity": "sha512-o1jLNe4uzQv2DKXMlmEzf66Wd8MoIhLNO2nlQBHLtWyh2MitDG7sMpfCO3NTcoTMuqHjfufgUQDFRI5C+xsXQw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "netbsd" ], "engines": { - "node": ">=12" + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", + "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" } }, "node_modules/@esbuild/openbsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.3.tgz", - "integrity": "sha512-AZJCnr5CZgZOdhouLcfRdnk9Zv6HbaBxjcyhq0StNcvAdVZJSKIdOiPB9az2zc06ywl0ePYJz60CjdKsQacp5Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "openbsd" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/sunos-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.3.tgz", - "integrity": "sha512-Acsujgeqg9InR4glTRvLKGZ+1HMtDm94ehTIHKhJjFpgVzZG9/pIcWW/HA/DoMfEyXmANLDuDZ2sNrWcjq1lxw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "sunos" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.3.tgz", - "integrity": "sha512-FSrAfjVVy7TifFgYgliiJOyYynhQmqgPj15pzLyJk8BUsnlWNwP/IAy6GAiB1LqtoivowRgidZsfpoYLZH586A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", "cpu": [ "arm64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-ia32": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.3.tgz", - "integrity": "sha512-xTScXYi12xLOWZ/sc5RBmMN99BcXp/eEf7scUC0oeiRoiT5Vvo9AycuqCp+xdpDyAU+LkrCqEpUS9fCSZF8J3Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", "cpu": [ "ia32" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@esbuild/win32-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.3.tgz", - "integrity": "sha512-FbUN+0ZRXsypPyWE2IwIkVjDkDnJoMJARWOcFZn4KPPli+QnKqF0z1anvfaYe3ev5HFCpRDLLBDHyOALLppWHw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", "cpu": [ "x64" ], "dev": true, + "license": "MIT", "optional": true, "os": [ "win32" ], "engines": { - "node": ">=12" + "node": ">=18" } }, "node_modules/@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, + "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, + "funding": { + "url": "https://opencollective.com/eslint" + }, "peerDependencies": { "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, "node_modules/@eslint-community/regexpp": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", - "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true, + "license": "MIT", "engines": { "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, + "node_modules/@eslint/compat": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.4.0.tgz", + "integrity": "sha512-DEzm5dKeDBPm3r08Ixli/0cmxr8LkRdwxMRUIJBlSCpAwSrvFEJpVBzV+66JhDxiaqKxnRzCXhtiMiczF7Hglg==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "peerDependencies": { + "eslint": "^8.40 || 9" + }, + "peerDependenciesMeta": { + "eslint": { + "optional": true + } + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.1.tgz", + "integrity": "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.16.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, "node_modules/@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, + "license": "MIT", "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", @@ -555,33 +617,84 @@ "strip-json-comments": "^3.1.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.38.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.38.0.tgz", + "integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==", "dev": true, + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" } }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "node_modules/@eslint/plugin-kit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", + "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", "dev": true, + "license": "Apache-2.0", "dependencies": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@eslint/core": "^0.16.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" }, "engines": { - "node": ">=10.10.0" + "node": ">=18.18.0" } }, "node_modules/@humanwhocodes/module-importer": { @@ -597,11 +710,19 @@ "url": "https://github.com/sponsors/nzakas" } }, - "node_modules/@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", - "dev": true + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } }, "node_modules/@isaacs/cliui": { "version": "8.0.2", @@ -775,6 +896,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" @@ -788,6 +910,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -797,6 +920,7 @@ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" @@ -816,6 +940,33 @@ "node": ">=14" } }, + "node_modules/@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true, + "license": "MIT" + }, + "node_modules/@sindresorhus/base62": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/base62/-/base62-1.0.0.tgz", + "integrity": "sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/fs-extra": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", @@ -828,9 +979,9 @@ } }, "node_modules/@types/global-agent": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@types/global-agent/-/global-agent-2.1.3.tgz", - "integrity": "sha512-rGtZZcgZcKWuKNTkGBGsqyOQ7Nn2MjXh4+xeZbf+5b5KMUx8H1rTqLRackxos7pUlreszbYjQcop5JvqCnZlLw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-OmvaPJtTaY/wd1hxelLJmf8oKQpmKZdrlfQ+MWL59eKSEHJDDEifIo69248bdJ0yLIN+iMNQ6sKMtnwU6AxajA==", "dev": true, "license": "MIT" }, @@ -838,13 +989,15 @@ "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/json5": { "version": "0.0.29", "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz", "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/@types/jsonfile": { "version": "6.1.1", @@ -862,16 +1015,14 @@ "dev": true }, "node_modules/@types/node": { - "version": "18.14.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", - "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==", - "dev": true - }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true + "version": "20.19.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.23.tgz", + "integrity": "sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "undici-types": "~6.21.0" + } }, "node_modules/@types/npmlog": { "version": "4.1.4", @@ -879,126 +1030,161 @@ "integrity": "sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==", "dev": true }, - "node_modules/@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz", - "integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz", + "integrity": "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/type-utils": "7.4.0", - "@typescript-eslint/utils": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/type-utils": "8.46.2", + "@typescript-eslint/utils": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@typescript-eslint/parser": "^7.0.0", - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "@typescript-eslint/parser": "^8.46.2", + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" } }, "node_modules/@typescript-eslint/parser": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz", - "integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.2.tgz", + "integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" + } + }, + "node_modules/@typescript-eslint/project-service": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.2.tgz", + "integrity": "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/tsconfig-utils": "^8.46.2", + "@typescript-eslint/types": "^8.46.2", + "debug": "^4.3.4" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.2.tgz", + "integrity": "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/tsconfig-utils": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.2.tgz", + "integrity": "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==", + "dev": true, + "license": "MIT", "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/type-utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz", - "integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.2.tgz", + "integrity": "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/utils": "7.4.0", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2", + "@typescript-eslint/utils": "8.46.2", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.2.tgz", + "integrity": "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==", "dev": true, + "license": "MIT", "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", @@ -1006,49 +1192,52 @@ } }, "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.2.tgz", + "integrity": "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/project-service": "8.46.2", + "@typescript-eslint/tsconfig-utils": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "peerDependencies": { + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, + "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -1058,52 +1247,59 @@ } }, "node_modules/@typescript-eslint/utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", - "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.2.tgz", + "integrity": "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", - "semver": "^7.5.4" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "eslint": "^8.56.0" + "eslint": "^8.57.0 || ^9.0.0", + "typescript": ">=4.8.4 <6.0.0" } }, "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.2.tgz", + "integrity": "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==", "dev": true, + "license": "MIT", "dependencies": { - "@typescript-eslint/types": "7.4.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "8.46.2", + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^18.18.0 || >=20.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } }, "node_modules/abort-controller": { "version": "3.0.0", @@ -1118,10 +1314,11 @@ } }, "node_modules/acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, + "license": "MIT", "bin": { "acorn": "bin/acorn" }, @@ -1134,15 +1331,17 @@ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", "dev": true, + "license": "MIT", "peerDependencies": { "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, + "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", @@ -1154,16 +1353,6 @@ "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -1188,19 +1377,6 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, "node_modules/aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -1251,29 +1427,37 @@ "dev": true }, "node_modules/array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -1282,26 +1466,20 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -1311,15 +1489,16 @@ } }, "node_modules/array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -1329,15 +1508,16 @@ } }, "node_modules/array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -1347,18 +1527,19 @@ } }, "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" }, "engines": { "node": ">= 0.4" @@ -1367,11 +1548,25 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -1405,28 +1600,22 @@ } ] }, - "node_modules/binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "node_modules/baseline-browser-mapping": { + "version": "2.8.20", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.20.tgz", + "integrity": "sha512-JMWsdF+O8Orq3EMukbUN1QfbLK9mX2CkUmQBcW2T0s8OmdAUL5LLM/6wFwSrqXzlXB13yhyK9gTKS1rIizOduQ==", "dev": true, - "engines": { - "node": ">=8" + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.js" } }, - "node_modules/boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", - "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", - "dev": true, - "license": "MIT" - }, "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, + "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" @@ -1450,6 +1639,40 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "node_modules/browserslist": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -1481,25 +1704,63 @@ "dev": true }, "node_modules/builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-5.0.0.tgz", + "integrity": "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=18.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -1526,6 +1787,27 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001751", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz", + "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1542,49 +1824,33 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "node_modules/chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "node_modules/change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } + "license": "MIT" }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, + "license": "MIT", "dependencies": { - "is-glob": "^4.0.1" + "readdirp": "^4.0.1" }, "engines": { - "node": ">= 6" + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, "node_modules/ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", "dev": true, "funding": [ { @@ -1592,6 +1858,7 @@ "url": "https://github.com/sponsors/sibiraj-s" } ], + "license": "MIT", "engines": { "node": ">=8" } @@ -1618,14 +1885,18 @@ } }, "node_modules/cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, + "license": "ISC", "dependencies": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" } }, "node_modules/color-convert": { @@ -1662,10 +1933,11 @@ "dev": true }, "node_modules/comment-parser": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz", - "integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 12.0.0" } @@ -1682,6 +1954,20 @@ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "dev": true }, + "node_modules/core-js-compat": { + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz", + "integrity": "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==", + "dev": true, + "license": "MIT", + "dependencies": { + "browserslist": "^4.26.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, "node_modules/core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -1702,34 +1988,88 @@ "node": ">= 8" } }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" }, "engines": { - "node": ">=6.0" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/decamelize": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", + "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/deep-is": { @@ -1739,25 +2079,31 @@ "dev": true }, "node_modules/define-data-property": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", - "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, + "license": "MIT", "dependencies": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" }, @@ -1774,17 +2120,10 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, - "node_modules/detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true, - "license": "MIT" - }, "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true, "license": "BSD-3-Clause", "engines": { @@ -1801,28 +2140,19 @@ "p-limit": "^3.1.0 " } }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" }, "engines": { - "node": ">=6.0.0" + "node": ">= 0.4" } }, "node_modules/eastasianwidth": { @@ -1832,66 +2162,80 @@ "dev": true, "license": "MIT" }, + "node_modules/electron-to-chromium": { + "version": "1.5.240", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.240.tgz", + "integrity": "sha512-OBwbZjWgrCOH+g6uJsA2/7Twpas2OlepS9uvByJjR2datRDuKGYeD+nP8lBBks2qnB7bGJNHDUx7c/YLaT3QMQ==", + "dev": true, + "license": "ISC" + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "dependencies": { - "is-arrayish": "^0.2.1" - } - }, "node_modules/es-abstract": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", - "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", "dev": true, + "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.11" + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" }, "engines": { "node": ">= 0.4" @@ -1900,38 +2244,78 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" }, "engines": { "node": ">= 0.4" @@ -1940,48 +2324,45 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true, - "license": "MIT" - }, "node_modules/esbuild": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.3.tgz", - "integrity": "sha512-UlJ1qUUA2jL2nNib1JTSkifQTcYTroFqRjwCFW4QYEKEsixXD5Tik9xML7zh2gTxkYTBKGHNH9y7txMwVyPbjw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", + "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", "dev": true, "hasInstallScript": true, + "license": "MIT", "bin": { "esbuild": "bin/esbuild" }, "engines": { - "node": ">=12" + "node": ">=18" }, "optionalDependencies": { - "@esbuild/android-arm": "0.19.3", - "@esbuild/android-arm64": "0.19.3", - "@esbuild/android-x64": "0.19.3", - "@esbuild/darwin-arm64": "0.19.3", - "@esbuild/darwin-x64": "0.19.3", - "@esbuild/freebsd-arm64": "0.19.3", - "@esbuild/freebsd-x64": "0.19.3", - "@esbuild/linux-arm": "0.19.3", - "@esbuild/linux-arm64": "0.19.3", - "@esbuild/linux-ia32": "0.19.3", - "@esbuild/linux-loong64": "0.19.3", - "@esbuild/linux-mips64el": "0.19.3", - "@esbuild/linux-ppc64": "0.19.3", - "@esbuild/linux-riscv64": "0.19.3", - "@esbuild/linux-s390x": "0.19.3", - "@esbuild/linux-x64": "0.19.3", - "@esbuild/netbsd-x64": "0.19.3", - "@esbuild/openbsd-x64": "0.19.3", - "@esbuild/sunos-x64": "0.19.3", - "@esbuild/win32-arm64": "0.19.3", - "@esbuild/win32-ia32": "0.19.3", - "@esbuild/win32-x64": "0.19.3" + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" } }, "node_modules/esbuild-plugin-polyfill-node": { @@ -1998,10 +2379,11 @@ } }, "node_modules/escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, + "license": "MIT", "engines": { "node": ">=6" } @@ -2019,58 +2401,63 @@ } }, "node_modules/eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", + "version": "9.38.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.38.0.tgz", + "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", "dev": true, + "license": "MIT", "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.1", + "@eslint/core": "^0.16.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.38.0", + "@eslint/plugin-kit": "^0.4.0", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" }, "bin": { "eslint": "bin/eslint.js" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } } }, "node_modules/eslint-config-prettier": { @@ -2086,14 +2473,15 @@ } }, "node_modules/eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" } }, "node_modules/eslint-import-resolver-node/node_modules/debug": { @@ -2101,15 +2489,17 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } }, "node_modules/eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, + "license": "MIT", "dependencies": { "debug": "^3.2.7" }, @@ -2127,6 +2517,7 @@ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", "dev": true, + "license": "MIT", "dependencies": { "ms": "^2.1.1" } @@ -2141,34 +2532,37 @@ } }, "node_modules/eslint-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, + "license": "MIT", "dependencies": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" }, "engines": { "node": ">=4" }, "peerDependencies": { - "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8" + "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9" } }, "node_modules/eslint-plugin-import/node_modules/debug": { @@ -2202,26 +2596,32 @@ } }, "node_modules/eslint-plugin-jsdoc": { - "version": "46.8.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.8.2.tgz", - "integrity": "sha512-5TSnD018f3tUJNne4s4gDWQflbsgOycIKEUBoCLn6XtBMgNHxQFmV8vVxUtiPxAQq8lrX85OaSG/2gnctxw9uQ==", + "version": "61.1.9", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-61.1.9.tgz", + "integrity": "sha512-X2AzSGbq1CzBRgKcVAu2qzOV9ogqygkUDk5AX6eNK5G+kY3I5Op5E5b99fE+FN0/bGnk2KGcsMIG6ZLF+di69A==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@es-joy/jsdoccomment": "~0.40.1", + "@es-joy/jsdoccomment": "~0.76.0", + "@es-joy/resolve.exports": "1.0.0", "are-docs-informative": "^0.0.2", - "comment-parser": "1.4.0", - "debug": "^4.3.4", + "comment-parser": "1.4.1", + "debug": "^4.4.3", "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "is-builtin-module": "^3.2.1", - "semver": "^7.5.4", - "spdx-expression-parse": "^3.0.1" + "espree": "^10.4.0", + "esquery": "^1.6.0", + "html-entities": "^2.6.0", + "object-deep-merge": "^2.0.0", + "parse-imports-exports": "^0.2.4", + "semver": "^7.7.3", + "spdx-expression-parse": "^4.0.0", + "to-valid-identifier": "^1.0.0" }, "engines": { - "node": ">=16" + "node": ">=20.11.0" }, "peerDependencies": { - "eslint": "^7.0.0 || ^8.0.0" + "eslint": "^7.0.0 || ^8.0.0 || ^9.0.0" } }, "node_modules/eslint-plugin-prefer-arrow": { @@ -2234,48 +2634,53 @@ } }, "node_modules/eslint-plugin-unicorn": { - "version": "48.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz", - "integrity": "sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==", + "version": "62.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-62.0.0.tgz", + "integrity": "sha512-HIlIkGLkvf29YEiS/ImuDZQbP12gWyx5i3C6XrRxMvVdqMroCI9qoVYCoIl17ChN+U89pn9sVwLxhIWj5nEc7g==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/helper-validator-identifier": "^7.22.5", - "@eslint-community/eslint-utils": "^4.4.0", - "ci-info": "^3.8.0", + "@babel/helper-validator-identifier": "^7.28.5", + "@eslint-community/eslint-utils": "^4.9.0", + "@eslint/plugin-kit": "^0.4.0", + "change-case": "^5.4.4", + "ci-info": "^4.3.1", "clean-regexp": "^1.0.0", - "esquery": "^1.5.0", - "indent-string": "^4.0.0", - "is-builtin-module": "^3.2.1", - "jsesc": "^3.0.2", - "lodash": "^4.17.21", + "core-js-compat": "^3.46.0", + "esquery": "^1.6.0", + "find-up-simple": "^1.0.1", + "globals": "^16.4.0", + "indent-string": "^5.0.0", + "is-builtin-module": "^5.0.0", + "jsesc": "^3.1.0", "pluralize": "^8.0.0", - "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", - "regjsparser": "^0.10.0", - "semver": "^7.5.4", - "strip-indent": "^3.0.0" + "regjsparser": "^0.13.0", + "semver": "^7.7.3", + "strip-indent": "^4.1.1" }, "engines": { - "node": ">=16" + "node": "^20.10.0 || >=21.0.0" }, "funding": { "url": "https://github.com/sindresorhus/eslint-plugin-unicorn?sponsor=1" }, "peerDependencies": { - "eslint": ">=8.44.0" + "eslint": ">=9.38.0" } }, "node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^5.2.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" @@ -2286,6 +2691,7 @@ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, + "license": "Apache-2.0", "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, @@ -2293,28 +2699,56 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "acorn": "^8.9.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" }, "funding": { "url": "https://opencollective.com/eslint" } }, "node_modules/esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { "estraverse": "^5.1.0" }, @@ -2327,6 +2761,7 @@ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, @@ -2377,16 +2812,17 @@ "dev": true }, "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, + "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "engines": { "node": ">=8.6.0" @@ -2397,6 +2833,7 @@ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, + "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, @@ -2417,24 +2854,26 @@ "dev": true }, "node_modules/fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, + "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, + "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16.0.0" } }, "node_modules/fill-range": { @@ -2465,6 +2904,19 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -2475,31 +2927,39 @@ } }, "node_modules/flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, + "license": "MIT", "dependencies": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "flatted": "^3.2.9", + "keyv": "^4.5.4" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">=16" } }, "node_modules/flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true }, "node_modules/for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, + "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/foreground-child": { @@ -2547,42 +3007,29 @@ "node": ">=14.14" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true - }, "node_modules/function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" }, "engines": { "node": ">= 0.4" @@ -2596,6 +3043,7 @@ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2619,64 +3067,102 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", "dev": true, + "license": "ISC", "engines": { "node": "6.* || 8.* || >= 10.*" } }, "node_modules/get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, + "license": "MIT", "dependencies": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, + "license": "MIT", "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" }, "engines": { - "node": "*" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { @@ -2691,81 +3177,86 @@ "node": ">=10.13.0" } }, - "node_modules/global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" - }, - "engines": { - "node": ">=10.0" + "balanced-match": "^1.0.0" } }, - "node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, + "license": "ISC", "dependencies": { - "type-fest": "^0.20.2" + "brace-expansion": "^2.0.2" }, "engines": { - "node": ">=8" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "node_modules/global-agent": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-4.1.3.tgz", + "integrity": "sha512-KUJEViiuFT3I97t+GYMikLPJS2Lfo/S2F+DQuBWzuzaMPnvt5yyZePzArx36fBzpGTxZjIpDbXLeySLgh+k76g==", "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "define-properties": "^1.1.3" + "globalthis": "^1.0.2", + "matcher": "^4.0.0", + "semver": "^7.3.5", + "serialize-error": "^8.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10.0" + } + }, + "node_modules/globals": { + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, + "license": "MIT", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "dev": true, - "dependencies": { - "get-intrinsic": "^1.1.3" + "license": "MIT", + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -2783,23 +3274,15 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "node_modules/has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "dependencies": { - "function-bind": "^1.1.1" - }, - "engines": { - "node": ">= 0.4.0" - } - }, "node_modules/has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -2814,22 +3297,27 @@ } }, "node_modules/has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, "engines": { "node": ">= 0.4" }, @@ -2838,10 +3326,11 @@ } }, "node_modules/has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -2850,12 +3339,13 @@ } }, "node_modules/has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -2870,6 +3360,19 @@ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "dev": true }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", @@ -2879,11 +3382,22 @@ "he": "bin/he" } }, - "node_modules/hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", - "dev": true + "node_modules/html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/mdevils" + }, + { + "type": "patreon", + "url": "https://patreon.com/mdevils" + } + ], + "license": "MIT" }, "node_modules/ieee754": { "version": "1.2.1", @@ -2956,22 +3470,16 @@ } }, "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "dev": true, + "license": "MIT", "engines": { - "node": ">=8" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/inherits": { @@ -2981,71 +3489,83 @@ "dev": true }, "node_modules/internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, + "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" }, "engines": { "node": ">= 0.4" } }, "node_modules/is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "node_modules/is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, + "license": "MIT", "dependencies": { - "has-bigints": "^1.0.1" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, + "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "has-bigints": "^1.0.2" }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3055,15 +3575,16 @@ } }, "node_modules/is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-5.0.0.tgz", + "integrity": "sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==", "dev": true, + "license": "MIT", "dependencies": { - "builtin-modules": "^3.3.0" + "builtin-modules": "^5.0.0" }, "engines": { - "node": ">=6" + "node": ">=18.20" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -3074,6 +3595,7 @@ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3082,24 +3604,48 @@ } }, "node_modules/is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, + "license": "MIT", "dependencies": { - "has": "^1.0.3" + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3117,6 +3663,22 @@ "node": ">=0.10.0" } }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", @@ -3126,6 +3688,26 @@ "node": ">=8" } }, + "node_modules/is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -3138,11 +3720,25 @@ "node": ">=0.10.0" } }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -3160,12 +3756,14 @@ } }, "node_modules/is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3179,6 +3777,7 @@ "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, + "license": "MIT", "engines": { "node": ">=8" } @@ -3193,13 +3792,16 @@ } }, "node_modules/is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -3208,25 +3810,44 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, + "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -3236,12 +3857,15 @@ } }, "node_modules/is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, + "license": "MIT", "dependencies": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" }, "engines": { "node": ">= 0.4" @@ -3251,12 +3875,13 @@ } }, "node_modules/is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, + "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.16" }, "engines": { "node": ">= 0.4" @@ -3277,13 +3902,47 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -3317,16 +3976,10 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "dependencies": { "argparse": "^2.0.1" @@ -3336,19 +3989,21 @@ } }, "node_modules/jsdoc-type-pratt-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", - "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-6.10.0.tgz", + "integrity": "sha512-+LexoTRyYui5iOhJGn13N9ZazL23nAHGkXsa1p/C8yeq79WRfLBag6ZZ0FQG2aRoc9yfo59JT9EYCQonOkHKkQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=12.0.0" + "node": ">=20.0.0" } }, "node_modules/jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true, + "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, @@ -3356,11 +4011,12 @@ "node": ">=6" } }, - "node_modules/json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", - "dev": true + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", @@ -3374,18 +4030,12 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "license": "ISC" - }, "node_modules/json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==", "dev": true, + "license": "MIT", "dependencies": { "minimist": "^1.2.0" }, @@ -3417,6 +4067,16 @@ "setimmediate": "^1.0.5" } }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3439,12 +4099,6 @@ "immediate": "~3.0.5" } }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -3460,12 +4114,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, "node_modules/lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -3488,29 +4136,30 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", + "node_modules/matcher": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-4.0.0.tgz", + "integrity": "sha512-S6x5wmcDmsDRRU/c2dkccDwQPXoFczc5+HpQ2lON8pnvHlnvHAHj5WlLVvw6n6vNyHuVugYrFohYxbS+pvFpKQ==", "dev": true, + "license": "MIT", "dependencies": { - "yallist": "^4.0.0" + "escape-string-regexp": "^4.0.0" }, "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^4.0.0" - }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 0.4" } }, "node_modules/merge2": { @@ -3518,6 +4167,7 @@ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, + "license": "MIT", "engines": { "node": ">= 8" } @@ -3527,6 +4177,7 @@ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, + "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" @@ -3535,19 +4186,10 @@ "node": ">=8.6" } }, - "node_modules/min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true, - "engines": { - "node": ">=4" - } - }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.4.tgz", + "integrity": "sha512-twmL+S8+7yIsE9wsqgzU3E8/LumN3M3QELrBZ20OdmQ9jB2JvW5oZtBEmft84k/Gs5CG9mqtWc6Y9vW+JEzGxw==", "dev": true, "dependencies": { "brace-expansion": "^1.1.7" @@ -3561,6 +4203,7 @@ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3576,31 +4219,32 @@ } }, "node_modules/mocha": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.0.1.tgz", - "integrity": "sha512-+3GkODfsDG71KSCQhc4IekSW+ItCK/kiez1Z28ksWvYhKXV/syxMlerR/sC7whDp7IyreZ4YxceMLdTs5hQE8A==", + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", "dev": true, "license": "MIT", "dependencies": { - "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", + "chokidar": "^4.0.1", "debug": "^4.3.5", - "diff": "^5.2.0", + "diff": "^7.0.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", "glob": "^10.4.5", "he": "^1.2.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", + "minimatch": "^9.0.5", "ms": "^2.1.3", + "picocolors": "^1.1.1", "serialize-javascript": "^6.0.2", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "bin": { @@ -3612,44 +4256,23 @@ } }, "node_modules/mocha/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } }, - "node_modules/mocha/node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/mocha/node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "node_modules/mocha/node_modules/minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "license": "ISC", "dependencies": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" }, "engines": { "node": ">=16 || 14 >=14.17" @@ -3658,19 +4281,6 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/mocha/node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mocha/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", @@ -3699,35 +4309,12 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "node_modules/normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "dependencies": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - } - }, - "node_modules/normalize-package-data/node_modules/semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true, - "bin": { - "semver": "bin/semver" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node_modules/node-releases": { + "version": "2.0.26", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.26.tgz", + "integrity": "sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==", "dev": true, - "engines": { - "node": ">=0.10.0" - } + "license": "MIT" }, "node_modules/npmlog": { "version": "7.0.1", @@ -3744,11 +4331,22 @@ "node": "^14.17.0 || ^16.13.0 || >=18.0.0" } }, + "node_modules/object-deep-merge": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-2.0.0.tgz", + "integrity": "sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg==", + "dev": true, + "license": "MIT" + }, "node_modules/object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -3763,14 +4361,17 @@ } }, "node_modules/object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" }, "engines": { @@ -3781,14 +4382,16 @@ } }, "node_modules/object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -3798,26 +4401,31 @@ } }, "node_modules/object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" + }, + "engines": { + "node": ">= 0.4" } }, "node_modules/object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -3826,15 +4434,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "dependencies": { - "wrappy": "1" - } - }, "node_modules/optionator": { "version": "0.9.3", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.3.tgz", @@ -3852,6 +4451,24 @@ "node": ">= 0.8.0" } }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -3882,15 +4499,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, "node_modules/package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -3916,24 +4524,23 @@ "node": ">=6" } }, - "node_modules/parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "node_modules/parse-imports-exports": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz", + "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==", "dev": true, + "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "parse-statements": "1.0.11" } }, + "node_modules/parse-statements": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz", + "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==", + "dev": true, + "license": "MIT" + }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", @@ -3943,15 +4550,6 @@ "node": ">=8" } }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -3965,7 +4563,8 @@ "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/path-scurry": { "version": "1.11.1", @@ -3991,19 +4590,17 @@ "dev": true, "license": "ISC" }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true, - "engines": { - "node": ">=8" - } + "license": "ISC" }, "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true, "engines": { "node": ">=8.6" @@ -4021,6 +4618,16 @@ "node": ">=4" } }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, "node_modules/prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -4087,7 +4694,8 @@ "type": "consulting", "url": "https://feross.org/support" } - ] + ], + "license": "MIT" }, "node_modules/randombytes": { "version": "2.1.0", @@ -4099,108 +4707,6 @@ "safe-buffer": "^5.1.0" } }, - "node_modules/read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "dependencies": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "dependencies": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "dependencies": { - "p-locate": "^4.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "dependencies": { - "p-try": "^2.0.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg-up/node_modules/type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true, - "engines": { - "node": ">=8" - } - }, - "node_modules/read-pkg/node_modules/type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -4217,15 +4723,40 @@ } }, "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, + "license": "MIT", "dependencies": { - "picomatch": "^2.2.1" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" }, "engines": { - "node": ">=8.10.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/regexp-tree": { @@ -4238,14 +4769,18 @@ } }, "node_modules/regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" }, "engines": { "node": ">= 0.4" @@ -4255,48 +4790,58 @@ } }, "node_modules/regjsparser": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", - "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", + "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "jsesc": "~0.5.0" + "jsesc": "~3.1.0" }, "bin": { "regjsparser": "bin/parser" } }, - "node_modules/regjsparser/node_modules/jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true, - "bin": { - "jsesc": "bin/jsesc" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true, + "license": "MIT", "engines": { "node": ">=0.10.0" } }, + "node_modules/reserved-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/reserved-identifiers/-/reserved-identifiers-1.2.0.tgz", + "integrity": "sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, + "license": "MIT", "dependencies": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, + "engines": { + "node": ">= 0.4" + }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -4311,46 +4856,14 @@ } }, "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "dependencies": { - "glob": "^7.1.3" - }, - "bin": { - "rimraf": "bin.js" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - }, + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", + "dev": true, + "license": "MIT", "engines": { - "node": ">=8.0" + "iojs": ">=1.0.0", + "node": ">=0.10.0" } }, "node_modules/run-parallel": { @@ -4372,19 +4885,22 @@ "url": "https://feross.org/support" } ], + "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "engines": { @@ -4398,7 +4914,8 @@ "version": "2.0.5", "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "dev": true + "dev": true, + "license": "MIT" }, "node_modules/safe-buffer": { "version": "5.1.2", @@ -4406,28 +4923,54 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "node_modules/safe-regex-test": { + "node_modules/safe-push-apply": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, + "license": "MIT", "dependencies": { - "lru-cache": "^6.0.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "license": "ISC", "bin": { "semver": "bin/semver.js" }, @@ -4435,35 +4978,15 @@ "node": ">=10" } }, - "node_modules/semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", - "dev": true, - "license": "MIT" - }, "node_modules/serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", + "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", "dev": true, "license": "MIT", "dependencies": { - "type-fest": "^0.13.1" - }, - "engines": { - "node": ">=10" + "type-fest": "^0.20.2" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/serialize-error/node_modules/type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true, - "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -4487,15 +5010,50 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, + "license": "MIT", "dependencies": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -4529,14 +5087,76 @@ } }, "node_modules/side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4548,15 +5168,6 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "engines": { - "node": ">=8" - } - }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -4576,44 +5187,44 @@ "source-map": "^0.6.0" } }, - "node_modules/spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "dependencies": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, "node_modules/spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", - "dev": true + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", + "dev": true, + "license": "CC-BY-3.0" }, "node_modules/spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "dev": true, + "license": "MIT", "dependencies": { "spdx-exceptions": "^2.1.0", "spdx-license-ids": "^3.0.0" } }, "node_modules/spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", - "dev": true + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", + "dev": true, + "license": "CC0-1.0" }, - "node_modules/sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", + "node_modules/stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", "dev": true, - "license": "BSD-3-Clause" + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } }, "node_modules/string_decoder": { "version": "1.1.1", @@ -4655,14 +5266,19 @@ } }, "node_modules/string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -4672,28 +5288,37 @@ } }, "node_modules/string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4730,20 +5355,22 @@ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true, + "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.1.1.tgz", + "integrity": "sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==", "dev": true, - "dependencies": { - "min-indent": "^1.0.0" - }, + "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/strip-json-comments": { @@ -4775,6 +5402,7 @@ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, + "license": "MIT", "engines": { "node": ">= 0.4" }, @@ -4800,12 +5428,6 @@ "node": ">=10" } }, - "node_modules/text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -4818,23 +5440,42 @@ "node": ">=8.0" } }, + "node_modules/to-valid-identifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-valid-identifier/-/to-valid-identifier-1.0.0.tgz", + "integrity": "sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@sindresorhus/base62": "^1.0.0", + "reserved-identifiers": "^1.0.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, + "license": "MIT", "engines": { - "node": ">=16" + "node": ">=18.12" }, "peerDependencies": { - "typescript": ">=4.2.0" + "typescript": ">=4.8.4" } }, "node_modules/tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, + "license": "MIT", "dependencies": { "@types/json5": "^0.0.29", "json5": "^1.0.2", @@ -4859,6 +5500,7 @@ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { "node": ">=10" }, @@ -4867,29 +5509,32 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" }, "engines": { "node": ">= 0.4" @@ -4899,16 +5544,19 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" }, "engines": { "node": ">= 0.4" @@ -4918,14 +5566,21 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -4945,20 +5600,31 @@ } }, "node_modules/unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, + "license": "MIT", "dependencies": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true, + "license": "MIT" + }, "node_modules/universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", @@ -4968,6 +5634,37 @@ "node": ">= 10.0.0" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4983,58 +5680,109 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "node_modules/validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", "dev": true, + "license": "MIT", "dependencies": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", "dev": true, + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" }, "engines": { - "node": ">= 8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/which-boxed-primitive": { + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, + "license": "MIT", "dependencies": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, + "license": "MIT", "dependencies": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" }, "engines": { "node": ">= 0.4" @@ -5053,9 +5801,9 @@ } }, "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", "dev": true, "license": "Apache-2.0" }, @@ -5064,6 +5812,7 @@ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^4.0.0", "string-width": "^4.1.0", @@ -5095,53 +5844,43 @@ "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, "node_modules/y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true, + "license": "ISC", "engines": { "node": ">=10" } }, - "node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "node_modules/yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, + "license": "MIT", "dependencies": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" }, "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true, "license": "ISC", "engines": { - "node": ">=10" + "node": ">=12" } }, "node_modules/yargs-unparser": { @@ -5179,302 +5918,320 @@ "integrity": "sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA==", "dev": true }, - "@babel/code-frame": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.18.6.tgz", - "integrity": "sha512-TDCmlK5eOvH+eH7cdAFlNXeVJqWIQ7gW9tY1GJIpUtFb6CmjVyq2VM3u71bOyR8CRihcCgMUYoDNyLXao3+70Q==", - "dev": true, - "requires": { - "@babel/highlight": "^7.18.6" - } - }, "@babel/helper-validator-identifier": { - "version": "7.22.20", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz", - "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==", + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", "dev": true }, - "@babel/highlight": { - "version": "7.18.6", - "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.18.6.tgz", - "integrity": "sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==", + "@es-joy/jsdoccomment": { + "version": "0.76.0", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.76.0.tgz", + "integrity": "sha512-g+RihtzFgGTx2WYCuTHbdOXJeAlGnROws0TeALx9ow/ZmOROOZkVg5wp/B44n0WJgI4SQFP1eWM2iRPlU2Y14w==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.18.6", - "chalk": "^2.0.0", - "js-tokens": "^4.0.0" - }, - "dependencies": { - "ansi-styles": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", - "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", - "dev": true, - "requires": { - "color-convert": "^1.9.0" - } - }, - "chalk": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", - "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", - "dev": true, - "requires": { - "ansi-styles": "^3.2.1", - "escape-string-regexp": "^1.0.5", - "supports-color": "^5.3.0" - } - }, - "color-convert": { - "version": "1.9.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", - "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", - "dev": true, - "requires": { - "color-name": "1.1.3" - } - }, - "color-name": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", - "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", - "dev": true - }, - "escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true - }, - "has-flag": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", - "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", - "dev": true - }, - "supports-color": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", - "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", - "dev": true, - "requires": { - "has-flag": "^3.0.0" - } - } + "@types/estree": "^1.0.8", + "@typescript-eslint/types": "^8.46.0", + "comment-parser": "1.4.1", + "esquery": "^1.6.0", + "jsdoc-type-pratt-parser": "~6.10.0" } }, - "@es-joy/jsdoccomment": { - "version": "0.40.1", - "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz", - "integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==", + "@es-joy/resolve.exports": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@es-joy/resolve.exports/-/resolve.exports-1.0.0.tgz", + "integrity": "sha512-bbrmzsAZ9GA/3oBS6r8PWMtZarEhKHr413hak8ArwMEZ5DtaLErnkcyEWUsXy7urBcmVu/TpDzHPDVM5uIbx9A==", + "dev": true + }, + "@esbuild/aix-ppc64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.0.tgz", + "integrity": "sha512-O7vun9Sf8DFjH2UtqK8Ku3LkquL9SZL8OLY1T5NZkA34+wG3OQF7cl4Ql8vdNzM6fzBbYfLaiRLIOZ+2FOCgBQ==", "dev": true, - "requires": { - "comment-parser": "1.4.0", - "esquery": "^1.5.0", - "jsdoc-type-pratt-parser": "~4.0.0" - } + "optional": true }, "@esbuild/android-arm": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.19.3.tgz", - "integrity": "sha512-Lemgw4io4VZl9GHJmjiBGzQ7ONXRfRPHcUEerndjwiSkbxzrpq0Uggku5MxxrXdwJ+pTj1qyw4jwTu7hkPsgIA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.0.tgz", + "integrity": "sha512-PTyWCYYiU0+1eJKmw21lWtC+d08JDZPQ5g+kFyxP0V+es6VPPSUhM6zk8iImp2jbV6GwjX4pap0JFbUQN65X1g==", "dev": true, "optional": true }, "@esbuild/android-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.19.3.tgz", - "integrity": "sha512-w+Akc0vv5leog550kjJV9Ru+MXMR2VuMrui3C61mnysim0gkFCPOUTAfzTP0qX+HpN9Syu3YA3p1hf3EPqObRw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.0.tgz", + "integrity": "sha512-grvv8WncGjDSyUBjN9yHXNt+cq0snxXbDxy5pJtzMKGmmpPxeAmAhWxXI+01lU5rwZomDgD3kJwulEnhTRUd6g==", "dev": true, "optional": true }, "@esbuild/android-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.19.3.tgz", - "integrity": "sha512-FKQJKkK5MXcBHoNZMDNUAg1+WcZlV/cuXrWCoGF/TvdRiYS4znA0m5Il5idUwfxrE20bG/vU1Cr5e1AD6IEIjQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.0.tgz", + "integrity": "sha512-m/ix7SfKG5buCnxasr52+LI78SQ+wgdENi9CqyCXwjVR2X4Jkz+BpC3le3AoBPYTC9NHklwngVXvbJ9/Akhrfg==", "dev": true, "optional": true }, "@esbuild/darwin-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.19.3.tgz", - "integrity": "sha512-kw7e3FXU+VsJSSSl2nMKvACYlwtvZB8RUIeVShIEY6PVnuZ3c9+L9lWB2nWeeKWNNYDdtL19foCQ0ZyUL7nqGw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.0.tgz", + "integrity": "sha512-mVwdUb5SRkPayVadIOI78K7aAnPamoeFR2bT5nszFUZ9P8UpK4ratOdYbZZXYSqPKMHfS1wdHCJk1P1EZpRdvw==", "dev": true, "optional": true }, "@esbuild/darwin-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.19.3.tgz", - "integrity": "sha512-tPfZiwF9rO0jW6Jh9ipi58N5ZLoSjdxXeSrAYypy4psA2Yl1dAMhM71KxVfmjZhJmxRjSnb29YlRXXhh3GqzYw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.0.tgz", + "integrity": "sha512-DgDaYsPWFTS4S3nWpFcMn/33ZZwAAeAFKNHNa1QN0rI4pUjgqf0f7ONmXf6d22tqTY+H9FNdgeaAa+YIFUn2Rg==", "dev": true, "optional": true }, "@esbuild/freebsd-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.3.tgz", - "integrity": "sha512-ERDyjOgYeKe0Vrlr1iLrqTByB026YLPzTytDTz1DRCYM+JI92Dw2dbpRHYmdqn6VBnQ9Bor6J8ZlNwdZdxjlSg==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.0.tgz", + "integrity": "sha512-VN4ocxy6dxefN1MepBx/iD1dH5K8qNtNe227I0mnTRjry8tj5MRk4zprLEdG8WPyAPb93/e4pSgi1SoHdgOa4w==", "dev": true, "optional": true }, "@esbuild/freebsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.19.3.tgz", - "integrity": "sha512-nXesBZ2Ad1qL+Rm3crN7NmEVJ5uvfLFPLJev3x1j3feCQXfAhoYrojC681RhpdOph8NsvKBBwpYZHR7W0ifTTA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.0.tgz", + "integrity": "sha512-mrSgt7lCh07FY+hDD1TxiTyIHyttn6vnjesnPoVDNmDfOmggTLXRv8Id5fNZey1gl/V2dyVK1VXXqVsQIiAk+A==", "dev": true, "optional": true }, "@esbuild/linux-arm": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.19.3.tgz", - "integrity": "sha512-zr48Cg/8zkzZCzDHNxXO/89bf9e+r4HtzNUPoz4GmgAkF1gFAFmfgOdCbR8zMbzFDGb1FqBBhdXUpcTQRYS1cQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.0.tgz", + "integrity": "sha512-vkB3IYj2IDo3g9xX7HqhPYxVkNQe8qTK55fraQyTzTX/fxaDtXiEnavv9geOsonh2Fd2RMB+i5cbhu2zMNWJwg==", "dev": true, "optional": true }, "@esbuild/linux-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.19.3.tgz", - "integrity": "sha512-qXvYKmXj8GcJgWq3aGvxL/JG1ZM3UR272SdPU4QSTzD0eymrM7leiZH77pvY3UetCy0k1xuXZ+VPvoJNdtrsWQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.0.tgz", + "integrity": "sha512-9QAQjTWNDM/Vk2bgBl17yWuZxZNQIF0OUUuPZRKoDtqF2k4EtYbpyiG5/Dk7nqeK6kIJWPYldkOcBqjXjrUlmg==", "dev": true, "optional": true }, "@esbuild/linux-ia32": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.19.3.tgz", - "integrity": "sha512-7XlCKCA0nWcbvYpusARWkFjRQNWNGlt45S+Q18UeS///K6Aw8bB2FKYe9mhVWy/XLShvCweOLZPrnMswIaDXQA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.0.tgz", + "integrity": "sha512-43ET5bHbphBegyeqLb7I1eYn2P/JYGNmzzdidq/w0T8E2SsYL1U6un2NFROFRg1JZLTzdCoRomg8Rvf9M6W6Gg==", "dev": true, "optional": true }, "@esbuild/linux-loong64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.19.3.tgz", - "integrity": "sha512-qGTgjweER5xqweiWtUIDl9OKz338EQqCwbS9c2Bh5jgEH19xQ1yhgGPNesugmDFq+UUSDtWgZ264st26b3de8A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.0.tgz", + "integrity": "sha512-fC95c/xyNFueMhClxJmeRIj2yrSMdDfmqJnyOY4ZqsALkDrrKJfIg5NTMSzVBr5YW1jf+l7/cndBfP3MSDpoHw==", "dev": true, "optional": true }, "@esbuild/linux-mips64el": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.19.3.tgz", - "integrity": "sha512-gy1bFskwEyxVMFRNYSvBauDIWNggD6pyxUksc0MV9UOBD138dKTzr8XnM2R4mBsHwVzeuIH8X5JhmNs2Pzrx+A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.0.tgz", + "integrity": "sha512-nkAMFju7KDW73T1DdH7glcyIptm95a7Le8irTQNO/qtkoyypZAnjchQgooFUDQhNAy4iu08N79W4T4pMBwhPwQ==", "dev": true, "optional": true }, "@esbuild/linux-ppc64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.19.3.tgz", - "integrity": "sha512-UrYLFu62x1MmmIe85rpR3qou92wB9lEXluwMB/STDzPF9k8mi/9UvNsG07Tt9AqwPQXluMQ6bZbTzYt01+Ue5g==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.0.tgz", + "integrity": "sha512-NhyOejdhRGS8Iwv+KKR2zTq2PpysF9XqY+Zk77vQHqNbo/PwZCzB5/h7VGuREZm1fixhs4Q/qWRSi5zmAiO4Fw==", "dev": true, "optional": true }, "@esbuild/linux-riscv64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.19.3.tgz", - "integrity": "sha512-9E73TfyMCbE+1AwFOg3glnzZ5fBAFK4aawssvuMgCRqCYzE0ylVxxzjEfut8xjmKkR320BEoMui4o/t9KA96gA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.0.tgz", + "integrity": "sha512-5S/rbP5OY+GHLC5qXp1y/Mx//e92L1YDqkiBbO9TQOvuFXM+iDqUNG5XopAnXoRH3FjIUDkeGcY1cgNvnXp/kA==", "dev": true, "optional": true }, "@esbuild/linux-s390x": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.19.3.tgz", - "integrity": "sha512-LlmsbuBdm1/D66TJ3HW6URY8wO6IlYHf+ChOUz8SUAjVTuaisfuwCOAgcxo3Zsu3BZGxmI7yt//yGOxV+lHcEA==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.0.tgz", + "integrity": "sha512-XM2BFsEBz0Fw37V0zU4CXfcfuACMrppsMFKdYY2WuTS3yi8O1nFOhil/xhKTmE1nPmVyvQJjJivgDT+xh8pXJA==", "dev": true, "optional": true }, "@esbuild/linux-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.19.3.tgz", - "integrity": "sha512-ogV0+GwEmvwg/8ZbsyfkYGaLACBQWDvO0Kkh8LKBGKj9Ru8VM39zssrnu9Sxn1wbapA2qNS6BiLdwJZGouyCwQ==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.0.tgz", + "integrity": "sha512-9yl91rHw/cpwMCNytUDxwj2XjFpxML0y9HAOH9pNVQDpQrBxHy01Dx+vaMu0N1CKa/RzBD2hB4u//nfc+Sd3Cw==", + "dev": true, + "optional": true + }, + "@esbuild/netbsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.0.tgz", + "integrity": "sha512-RuG4PSMPFfrkH6UwCAqBzauBWTygTvb1nxWasEJooGSJ/NwRw7b2HOwyRTQIU97Hq37l3npXoZGYMy3b3xYvPw==", "dev": true, "optional": true }, "@esbuild/netbsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.19.3.tgz", - "integrity": "sha512-o1jLNe4uzQv2DKXMlmEzf66Wd8MoIhLNO2nlQBHLtWyh2MitDG7sMpfCO3NTcoTMuqHjfufgUQDFRI5C+xsXQw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.0.tgz", + "integrity": "sha512-jl+qisSB5jk01N5f7sPCsBENCOlPiS/xptD5yxOx2oqQfyourJwIKLRA2yqWdifj3owQZCL2sn6o08dBzZGQzA==", + "dev": true, + "optional": true + }, + "@esbuild/openbsd-arm64": { + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.0.tgz", + "integrity": "sha512-21sUNbq2r84YE+SJDfaQRvdgznTD8Xc0oc3p3iW/a1EVWeNj/SdUCbm5U0itZPQYRuRTW20fPMWMpcrciH2EJw==", "dev": true, "optional": true }, "@esbuild/openbsd-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.19.3.tgz", - "integrity": "sha512-AZJCnr5CZgZOdhouLcfRdnk9Zv6HbaBxjcyhq0StNcvAdVZJSKIdOiPB9az2zc06ywl0ePYJz60CjdKsQacp5Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.0.tgz", + "integrity": "sha512-2gwwriSMPcCFRlPlKx3zLQhfN/2WjJ2NSlg5TKLQOJdV0mSxIcYNTMhk3H3ulL/cak+Xj0lY1Ym9ysDV1igceg==", "dev": true, "optional": true }, "@esbuild/sunos-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.19.3.tgz", - "integrity": "sha512-Acsujgeqg9InR4glTRvLKGZ+1HMtDm94ehTIHKhJjFpgVzZG9/pIcWW/HA/DoMfEyXmANLDuDZ2sNrWcjq1lxw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.0.tgz", + "integrity": "sha512-bxI7ThgLzPrPz484/S9jLlvUAHYMzy6I0XiU1ZMeAEOBcS0VePBFxh1JjTQt3Xiat5b6Oh4x7UC7IwKQKIJRIg==", "dev": true, "optional": true }, "@esbuild/win32-arm64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.19.3.tgz", - "integrity": "sha512-FSrAfjVVy7TifFgYgliiJOyYynhQmqgPj15pzLyJk8BUsnlWNwP/IAy6GAiB1LqtoivowRgidZsfpoYLZH586A==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.0.tgz", + "integrity": "sha512-ZUAc2YK6JW89xTbXvftxdnYy3m4iHIkDtK3CLce8wg8M2L+YZhIvO1DKpxrd0Yr59AeNNkTiic9YLf6FTtXWMw==", "dev": true, "optional": true }, "@esbuild/win32-ia32": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.19.3.tgz", - "integrity": "sha512-xTScXYi12xLOWZ/sc5RBmMN99BcXp/eEf7scUC0oeiRoiT5Vvo9AycuqCp+xdpDyAU+LkrCqEpUS9fCSZF8J3Q==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.0.tgz", + "integrity": "sha512-eSNxISBu8XweVEWG31/JzjkIGbGIJN/TrRoiSVZwZ6pkC6VX4Im/WV2cz559/TXLcYbcrDN8JtKgd9DJVIo8GA==", "dev": true, "optional": true }, "@esbuild/win32-x64": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.19.3.tgz", - "integrity": "sha512-FbUN+0ZRXsypPyWE2IwIkVjDkDnJoMJARWOcFZn4KPPli+QnKqF0z1anvfaYe3ev5HFCpRDLLBDHyOALLppWHw==", + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.0.tgz", + "integrity": "sha512-ZENoHJBxA20C2zFzh6AI4fT6RraMzjYw4xKWemRTRmRVtN9c5DcH9r/f2ihEkMjOW5eGgrwCslG/+Y/3bL+DHQ==", "dev": true, "optional": true }, "@eslint-community/eslint-utils": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz", - "integrity": "sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA==", + "version": "4.9.0", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz", + "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==", "dev": true, "requires": { - "eslint-visitor-keys": "^3.3.0" + "eslint-visitor-keys": "^3.4.3" } }, "@eslint-community/regexpp": { - "version": "4.9.1", - "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.9.1.tgz", - "integrity": "sha512-Y27x+MBLjXa+0JWDhykM3+JE+il3kHKAEqabfEWq3SDhZjLYb6/BHL/JKFnH3fe207JaXkyDo685Oc2Glt6ifA==", + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", "dev": true }, + "@eslint/compat": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@eslint/compat/-/compat-1.4.0.tgz", + "integrity": "sha512-DEzm5dKeDBPm3r08Ixli/0cmxr8LkRdwxMRUIJBlSCpAwSrvFEJpVBzV+66JhDxiaqKxnRzCXhtiMiczF7Hglg==", + "dev": true, + "requires": { + "@eslint/core": "^0.16.0" + } + }, + "@eslint/config-array": { + "version": "0.21.1", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz", + "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==", + "dev": true, + "requires": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.2" + } + }, + "@eslint/config-helpers": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.1.tgz", + "integrity": "sha512-csZAzkNhsgwb0I/UAV6/RGFTbiakPCf0ZrGmrIxQpYvGZ00PhTkSnyKNolphgIvmnJeGw6rcGVEXfTzUnFuEvw==", + "dev": true, + "requires": { + "@eslint/core": "^0.16.0" + } + }, + "@eslint/core": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.16.0.tgz", + "integrity": "sha512-nmC8/totwobIiFcGkDza3GIKfAw1+hLiYVrh3I1nIomQ8PEr5cxg34jnkmGawul/ep52wGRAcyeDCNtWKSOj4Q==", + "dev": true, + "requires": { + "@types/json-schema": "^7.0.15" + } + }, "@eslint/eslintrc": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", - "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz", + "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.6.0", - "globals": "^13.19.0", + "espree": "^10.0.1", + "globals": "^14.0.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", "js-yaml": "^4.1.0", "minimatch": "^3.1.2", "strip-json-comments": "^3.1.1" + }, + "dependencies": { + "globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true + } } }, "@eslint/js": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.0.tgz", - "integrity": "sha512-Ys+3g2TaW7gADOJzPt83SJtCDhMjndcDMFVQ/Tj9iA1BfJzFKD9mAUXT3OenpuPHbI6P/myECxRJrofUsDx/5g==", + "version": "9.38.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.38.0.tgz", + "integrity": "sha512-UZ1VpFvXf9J06YG9xQBdnzU+kthors6KjhMAl6f4gH4usHyh31rUf2DLGInT8RFYIReYXNSydgPY0V2LuWgl7A==", "dev": true }, - "@humanwhocodes/config-array": { - "version": "0.11.14", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.11.14.tgz", - "integrity": "sha512-3T8LkOmg45BV5FICb15QQMsyUSWrQ8AygVfC7ZG32zOalnqrilm018ZVCw0eapXux8FtA33q8PSRSstjee3jSg==", + "@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true + }, + "@eslint/plugin-kit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.0.tgz", + "integrity": "sha512-sB5uyeq+dwCWyPi31B2gQlVlo+j5brPlWx4yZBrEaRo/nhdDE8Xke1gsGgtiBdaBTxuTkceLVuVt/pclrasb0A==", "dev": true, "requires": { - "@humanwhocodes/object-schema": "^2.0.2", - "debug": "^4.3.1", - "minimatch": "^3.0.5" + "@eslint/core": "^0.16.0", + "levn": "^0.4.1" + } + }, + "@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true + }, + "@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "requires": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" } }, "@humanwhocodes/module-importer": { @@ -5483,10 +6240,10 @@ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", "dev": true }, - "@humanwhocodes/object-schema": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.2.tgz", - "integrity": "sha512-6EwiSjwWYP7pTckG6I5eyFANjPhmPjUX9JRLUSfNPC7FX7zK9gyZAfUEaECL6ALTpGX5AjnBq3C9XmVWPitNpw==", + "@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", "dev": true }, "@isaacs/cliui": { @@ -5642,6 +6399,24 @@ "dev": true, "optional": true }, + "@rtsao/scc": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz", + "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==", + "dev": true + }, + "@sindresorhus/base62": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/base62/-/base62-1.0.0.tgz", + "integrity": "sha512-TeheYy0ILzBEI/CO55CP6zJCSdSWeRtGnHy8U8dWSUH4I68iqTsy7HkMktR4xakThc9jotkPQUXT4ITdbV7cHA==", + "dev": true + }, + "@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true + }, "@types/fs-extra": { "version": "11.0.4", "resolved": "https://registry.npmjs.org/@types/fs-extra/-/fs-extra-11.0.4.tgz", @@ -5653,9 +6428,9 @@ } }, "@types/global-agent": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/@types/global-agent/-/global-agent-2.1.3.tgz", - "integrity": "sha512-rGtZZcgZcKWuKNTkGBGsqyOQ7Nn2MjXh4+xeZbf+5b5KMUx8H1rTqLRackxos7pUlreszbYjQcop5JvqCnZlLw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@types/global-agent/-/global-agent-3.0.0.tgz", + "integrity": "sha512-OmvaPJtTaY/wd1hxelLJmf8oKQpmKZdrlfQ+MWL59eKSEHJDDEifIo69248bdJ0yLIN+iMNQ6sKMtnwU6AxajA==", "dev": true }, "@types/json-schema": { @@ -5686,16 +6461,13 @@ "dev": true }, "@types/node": { - "version": "18.14.6", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.6.tgz", - "integrity": "sha512-93+VvleD3mXwlLI/xASjw0FzKcwzl3OdTCzm1LaRfqgS21gfFtK3zDXM5Op9TeeMsJVOaJ2VRDpT9q4Y3d0AvA==", - "dev": true - }, - "@types/normalize-package-data": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz", - "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==", - "dev": true + "version": "20.19.23", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.23.tgz", + "integrity": "sha512-yIdlVVVHXpmqRhtyovZAcSy0MiPcYWGkoO4CGe/+jpP0hmNuihm4XhHbADpK++MsiLHP5MVlv+bcgdF99kSiFQ==", + "dev": true, + "requires": { + "undici-types": "~6.21.0" + } }, "@types/npmlog": { "version": "4.1.4", @@ -5703,139 +6475,159 @@ "integrity": "sha512-WKG4gTr8przEZBiJ5r3s8ZIAoMXNbOgQ+j/d5O4X3x6kZJRLNvyUJuUK/KoG3+8BaOHPhp2m7WC6JKKeovDSzQ==", "dev": true }, - "@types/semver": { - "version": "7.5.8", - "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", - "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", - "dev": true - }, "@typescript-eslint/eslint-plugin": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-7.4.0.tgz", - "integrity": "sha512-yHMQ/oFaM7HZdVrVm/M2WHaNPgyuJH4WelkSVEWSSsir34kxW2kDJCxlXRhhGWEsMN0WAW/vLpKfKVcm8k+MPw==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.46.2.tgz", + "integrity": "sha512-ZGBMToy857/NIPaaCucIUQgqueOiq7HeAKkhlvqVV4lm089zUFW6ikRySx2v+cAhKeUCPuWVHeimyk6Dw1iY3w==", "dev": true, "requires": { - "@eslint-community/regexpp": "^4.5.1", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/type-utils": "7.4.0", - "@typescript-eslint/utils": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", - "debug": "^4.3.4", + "@eslint-community/regexpp": "^4.10.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/type-utils": "8.46.2", + "@typescript-eslint/utils": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", "graphemer": "^1.4.0", - "ignore": "^5.2.4", + "ignore": "^7.0.0", "natural-compare": "^1.4.0", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^2.1.0" + }, + "dependencies": { + "ignore": { + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz", + "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==", + "dev": true + } } }, "@typescript-eslint/parser": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-7.4.0.tgz", - "integrity": "sha512-ZvKHxHLusweEUVwrGRXXUVzFgnWhigo4JurEj0dGF1tbcGh6buL+ejDdjxOQxv6ytcY1uhun1p2sm8iWStlgLQ==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.46.2.tgz", + "integrity": "sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==", + "dev": true, + "requires": { + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", + "debug": "^4.3.4" + } + }, + "@typescript-eslint/project-service": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.46.2.tgz", + "integrity": "sha512-PULOLZ9iqwI7hXcmL4fVfIsBi6AN9YxRc0frbvmg8f+4hQAjQ5GYNKK0DIArNo+rOKmR/iBYwkpBmnIwin4wBg==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/tsconfig-utils": "^8.46.2", + "@typescript-eslint/types": "^8.46.2", "debug": "^4.3.4" } }, "@typescript-eslint/scope-manager": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-7.4.0.tgz", - "integrity": "sha512-68VqENG5HK27ypafqLVs8qO+RkNc7TezCduYrx8YJpXq2QGZ30vmNZGJJJC48+MVn4G2dCV8m5ZTVnzRexTVtw==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.46.2.tgz", + "integrity": "sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0" + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2" } }, + "@typescript-eslint/tsconfig-utils": { + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.46.2.tgz", + "integrity": "sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==", + "dev": true, + "requires": {} + }, "@typescript-eslint/type-utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-7.4.0.tgz", - "integrity": "sha512-247ETeHgr9WTRMqHbbQdzwzhuyaJ8dPTuyuUEMANqzMRB1rj/9qFIuIXK7l0FX9i9FXbHeBQl/4uz6mYuCE7Aw==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.46.2.tgz", + "integrity": "sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "7.4.0", - "@typescript-eslint/utils": "7.4.0", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2", + "@typescript-eslint/utils": "8.46.2", "debug": "^4.3.4", - "ts-api-utils": "^1.0.1" + "ts-api-utils": "^2.1.0" } }, "@typescript-eslint/types": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.4.0.tgz", - "integrity": "sha512-mjQopsbffzJskos5B4HmbsadSJQWaRK0UxqQ7GuNA9Ga4bEKeiO6b2DnB6cM6bpc8lemaPseh0H9B/wyg+J7rw==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.46.2.tgz", + "integrity": "sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.4.0.tgz", - "integrity": "sha512-A99j5AYoME/UBQ1ucEbbMEmGkN7SE0BvZFreSnTd1luq7yulcHdyGamZKizU7canpGDWGJ+Q6ZA9SyQobipePg==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.46.2.tgz", + "integrity": "sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/visitor-keys": "7.4.0", + "@typescript-eslint/project-service": "8.46.2", + "@typescript-eslint/tsconfig-utils": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/visitor-keys": "8.46.2", "debug": "^4.3.4", - "globby": "^11.1.0", + "fast-glob": "^3.3.2", "is-glob": "^4.0.3", - "minimatch": "9.0.3", - "semver": "^7.5.4", - "ts-api-utils": "^1.0.1" + "minimatch": "^9.0.4", + "semver": "^7.6.0", + "ts-api-utils": "^2.1.0" }, "dependencies": { "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "requires": { "balanced-match": "^1.0.0" } }, "minimatch": { - "version": "9.0.3", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", - "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "requires": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" } } } }, "@typescript-eslint/utils": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-7.4.0.tgz", - "integrity": "sha512-NQt9QLM4Tt8qrlBVY9lkMYzfYtNz8/6qwZg8pI3cMGlPnj6mOpRxxAm7BMJN9K0AiY+1BwJ5lVC650YJqYOuNg==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.46.2.tgz", + "integrity": "sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==", "dev": true, "requires": { - "@eslint-community/eslint-utils": "^4.4.0", - "@types/json-schema": "^7.0.12", - "@types/semver": "^7.5.0", - "@typescript-eslint/scope-manager": "7.4.0", - "@typescript-eslint/types": "7.4.0", - "@typescript-eslint/typescript-estree": "7.4.0", - "semver": "^7.5.4" + "@eslint-community/eslint-utils": "^4.7.0", + "@typescript-eslint/scope-manager": "8.46.2", + "@typescript-eslint/types": "8.46.2", + "@typescript-eslint/typescript-estree": "8.46.2" } }, "@typescript-eslint/visitor-keys": { - "version": "7.4.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.4.0.tgz", - "integrity": "sha512-0zkC7YM0iX5Y41homUUeW1CHtZR01K3ybjM1l6QczoMuay0XKtrb93kv95AxUGwdjGr64nNqnOCwmEl616N8CA==", + "version": "8.46.2", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.46.2.tgz", + "integrity": "sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==", "dev": true, "requires": { - "@typescript-eslint/types": "7.4.0", - "eslint-visitor-keys": "^3.4.1" + "@typescript-eslint/types": "8.46.2", + "eslint-visitor-keys": "^4.2.1" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true + } } }, - "@ungap/structured-clone": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.2.0.tgz", - "integrity": "sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==", - "dev": true - }, "abort-controller": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", @@ -5846,9 +6638,9 @@ } }, "acorn": { - "version": "8.11.3", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", - "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true }, "acorn-jsx": { @@ -5859,9 +6651,9 @@ "requires": {} }, "ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -5870,12 +6662,6 @@ "uri-js": "^4.2.2" } }, - "ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true - }, "ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -5891,16 +6677,6 @@ "color-convert": "^2.0.1" } }, - "anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "requires": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - } - }, "aproba": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.0.0.tgz", @@ -5944,92 +6720,100 @@ "dev": true }, "array-buffer-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", - "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "is-array-buffer": "^3.0.1" + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" } }, "array-includes": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.6.tgz", - "integrity": "sha512-sgTbLvL6cNnw24FnbaDyjmvddQ2ML8arZsgaJhoABMoplz/4QRhtrYS+alr1BUM1Bwp6dhx8vVCBSLG+StwOFw==", + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz", + "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "get-intrinsic": "^1.1.3", - "is-string": "^1.0.7" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.24.0", + "es-object-atoms": "^1.1.1", + "get-intrinsic": "^1.3.0", + "is-string": "^1.1.1", + "math-intrinsics": "^1.1.0" } }, - "array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true - }, "array.prototype.findlastindex": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz", - "integrity": "sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA==", + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.6.tgz", + "integrity": "sha512-F/TKATkzseUExPlfvmwQKGITM3DGTK+vkAsCZoDc5daVygbJBnjEUCbgkAvVFsgfXfX4YIqZ/27G3k3tdXrTxQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "es-shim-unscopables": "^1.0.0", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-shim-unscopables": "^1.1.0" } }, "array.prototype.flat": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.1.tgz", - "integrity": "sha512-roTU0KWIOmJ4DRLmwKd19Otg0/mT3qPNt0Qb3GWW8iObuZXxrjB/pzn0R3hqpRSWg4HCwqx+0vwOnWnvlOyeIA==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" } }, "array.prototype.flatmap": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.1.tgz", - "integrity": "sha512-8UGn9O1FDVvMNB0UlLv4voxRMze7+FpHyF5mSMRjWHUMlpoDViniy05870VlxhfgTnLbpuwTzvD76MTtWxB/mQ==", + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4", - "es-shim-unscopables": "^1.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" } }, "arraybuffer.prototype.slice": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", - "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", "dev": true, "requires": { - "array-buffer-byte-length": "^1.0.0", - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1", - "is-array-buffer": "^3.0.2", - "is-shared-array-buffer": "^1.0.2" + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" } }, - "available-typed-arrays": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", - "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", "dev": true }, + "available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "requires": { + "possible-typed-array-names": "^1.0.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -6042,22 +6826,16 @@ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", "dev": true }, - "binary-extensions": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", - "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", - "dev": true - }, - "boolean": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/boolean/-/boolean-3.2.0.tgz", - "integrity": "sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==", + "baseline-browser-mapping": { + "version": "2.8.20", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.20.tgz", + "integrity": "sha512-JMWsdF+O8Orq3EMukbUN1QfbLK9mX2CkUmQBcW2T0s8OmdAUL5LLM/6wFwSrqXzlXB13yhyK9gTKS1rIizOduQ==", "dev": true }, "brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -6079,6 +6857,19 @@ "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", "dev": true }, + "browserslist": { + "version": "4.27.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.27.0.tgz", + "integrity": "sha512-AXVQwdhot1eqLihwasPElhX2tAZiBjWdJ9i/Zcj2S6QYIjkx62OKSfnobkriB81C3l4w0rVy3Nt4jaTBltYEpw==", + "dev": true, + "requires": { + "baseline-browser-mapping": "^2.8.19", + "caniuse-lite": "^1.0.30001751", + "electron-to-chromium": "^1.5.238", + "node-releases": "^2.0.26", + "update-browserslist-db": "^1.1.4" + } + }, "buffer": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", @@ -6096,19 +6887,41 @@ "dev": true }, "builtin-modules": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", - "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-5.0.0.tgz", + "integrity": "sha512-bkXY9WsVpY7CvMhKSR6pZilZu9Ln5WDrKVBUXf2S443etkmEO4V58heTecXcUIsNsi4Rx8JUO4NfX1IcQl4deg==", "dev": true }, "call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "requires": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + } + }, + "call-bind-apply-helpers": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", - "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + } + }, + "call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "get-intrinsic": "^1.0.2" + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" } }, "callsites": { @@ -6123,6 +6936,12 @@ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true }, + "caniuse-lite": { + "version": "1.0.30001751", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001751.tgz", + "integrity": "sha512-A0QJhug0Ly64Ii3eIqHu5X51ebln3k4yTUkY1j8drqpWHVreg/VLijN48cZ1bYPiqOQuqpkIKnzr/Ul8V+p6Cw==", + "dev": true + }, "chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -6133,37 +6952,25 @@ "supports-color": "^7.1.0" } }, + "change-case": { + "version": "5.4.4", + "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz", + "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==", + "dev": true + }, "chokidar": { - "version": "3.5.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", - "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", "dev": true, "requires": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "fsevents": "~2.3.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "dependencies": { - "glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "requires": { - "is-glob": "^4.0.1" - } - } + "readdirp": "^4.0.1" } }, "ci-info": { - "version": "3.8.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz", - "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", + "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", "dev": true }, "clean-regexp": { @@ -6184,13 +6991,13 @@ } }, "cliui": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", - "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", "dev": true, "requires": { "string-width": "^4.2.0", - "strip-ansi": "^6.0.0", + "strip-ansi": "^6.0.1", "wrap-ansi": "^7.0.0" } }, @@ -6222,9 +7029,9 @@ "dev": true }, "comment-parser": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz", - "integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.1.tgz", + "integrity": "sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==", "dev": true }, "concat-map": { @@ -6239,6 +7046,15 @@ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==", "dev": true }, + "core-js-compat": { + "version": "3.46.0", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.46.0.tgz", + "integrity": "sha512-p9hObIIEENxSV8xIu+V68JjSeARg6UVMG5mR+JEUguG3sI6MsiS1njz2jHmyJDvA+8jX/sytkBHup6kxhM9law==", + "dev": true, + "requires": { + "browserslist": "^4.26.3" + } + }, "core-util-is": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", @@ -6256,10 +7072,43 @@ "which": "^2.0.1" } }, + "data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "requires": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + } + }, + "data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "requires": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + } + }, + "data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + } + }, "debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", "dev": true, "requires": { "ms": "^2.1.3" @@ -6278,22 +7127,23 @@ "dev": true }, "define-data-property": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.0.tgz", - "integrity": "sha512-UzGwzcjyv3OtAvolTj1GoyNYzfFR+iqbGjcnBEENZVCpM4/Ng1yhGNvS3lR/xDS74Tb2wGG9WzNSNIOS9UVb2g==", + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", "dev": true, "requires": { - "get-intrinsic": "^1.2.1", - "gopd": "^1.0.1", - "has-property-descriptors": "^1.0.0" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" } }, "define-properties": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.0.tgz", - "integrity": "sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, "requires": { + "define-data-property": "^1.0.1", "has-property-descriptors": "^1.0.0", "object-keys": "^1.1.1" } @@ -6304,16 +7154,10 @@ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", "dev": true }, - "detect-node": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz", - "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==", - "dev": true - }, "diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", + "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", "dev": true }, "dir-compare": { @@ -6326,22 +7170,15 @@ "p-limit": "^3.1.0 " } }, - "dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "requires": { - "path-type": "^4.0.0" - } - }, - "doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", "dev": true, "requires": { - "esutils": "^2.0.2" + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" } }, "eastasianwidth": { @@ -6350,133 +7187,164 @@ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "dev": true }, + "electron-to-chromium": { + "version": "1.5.240", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.240.tgz", + "integrity": "sha512-OBwbZjWgrCOH+g6uJsA2/7Twpas2OlepS9uvByJjR2datRDuKGYeD+nP8lBBks2qnB7bGJNHDUx7c/YLaT3QMQ==", + "dev": true + }, "emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", "dev": true }, - "error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", - "dev": true, - "requires": { - "is-arrayish": "^0.2.1" - } - }, "es-abstract": { - "version": "1.22.2", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.2.tgz", - "integrity": "sha512-YoxfFcDmhjOgWPWsV13+2RNjq1F6UQnfs+8TftwNqtzlmFzEXvlUwdrNrYeaizfjQzRMxkZ6ElWMOJIFKdVqwA==", - "dev": true, - "requires": { - "array-buffer-byte-length": "^1.0.0", - "arraybuffer.prototype.slice": "^1.0.2", - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "es-set-tostringtag": "^2.0.1", - "es-to-primitive": "^1.2.1", - "function.prototype.name": "^1.1.6", - "get-intrinsic": "^1.2.1", - "get-symbol-description": "^1.0.0", - "globalthis": "^1.0.3", - "gopd": "^1.0.1", - "has": "^1.0.3", - "has-property-descriptors": "^1.0.0", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3", - "internal-slot": "^1.0.5", - "is-array-buffer": "^3.0.2", + "version": "1.24.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.0.tgz", + "integrity": "sha512-WSzPgsdLtTcQwm4CROfS5ju2Wa1QQcVeT37jFjYzdFz1r9ahadC8B8/a4qxJxM+09F18iumCdRmlr96ZYkQvEg==", + "dev": true, + "requires": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.3.0", + "get-proto": "^1.0.1", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", "is-callable": "^1.2.7", - "is-negative-zero": "^2.0.2", - "is-regex": "^1.1.4", - "is-shared-array-buffer": "^1.0.2", - "is-string": "^1.0.7", - "is-typed-array": "^1.1.12", - "is-weakref": "^1.0.2", - "object-inspect": "^1.12.3", + "is-data-view": "^1.0.2", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.2.1", + "is-set": "^2.0.3", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.1", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.4", "object-keys": "^1.1.1", - "object.assign": "^4.1.4", - "regexp.prototype.flags": "^1.5.1", - "safe-array-concat": "^1.0.1", - "safe-regex-test": "^1.0.0", - "string.prototype.trim": "^1.2.8", - "string.prototype.trimend": "^1.0.7", - "string.prototype.trimstart": "^1.0.7", - "typed-array-buffer": "^1.0.0", - "typed-array-byte-length": "^1.0.0", - "typed-array-byte-offset": "^1.0.0", - "typed-array-length": "^1.0.4", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.11" + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.4", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "stop-iteration-iterator": "^1.1.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.19" + } + }, + "es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true + }, + "es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true + }, + "es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0" } }, "es-set-tostringtag": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz", - "integrity": "sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", "dev": true, "requires": { - "get-intrinsic": "^1.1.3", - "has": "^1.0.3", - "has-tostringtag": "^1.0.0" + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" } }, "es-shim-unscopables": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz", - "integrity": "sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", "dev": true, "requires": { - "has": "^1.0.3" + "hasown": "^2.0.2" } }, "es-to-primitive": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", - "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", "dev": true, "requires": { - "is-callable": "^1.1.4", - "is-date-object": "^1.0.1", - "is-symbol": "^1.0.2" + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" } }, - "es6-error": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz", - "integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==", - "dev": true - }, "esbuild": { - "version": "0.19.3", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.19.3.tgz", - "integrity": "sha512-UlJ1qUUA2jL2nNib1JTSkifQTcYTroFqRjwCFW4QYEKEsixXD5Tik9xML7zh2gTxkYTBKGHNH9y7txMwVyPbjw==", - "dev": true, - "requires": { - "@esbuild/android-arm": "0.19.3", - "@esbuild/android-arm64": "0.19.3", - "@esbuild/android-x64": "0.19.3", - "@esbuild/darwin-arm64": "0.19.3", - "@esbuild/darwin-x64": "0.19.3", - "@esbuild/freebsd-arm64": "0.19.3", - "@esbuild/freebsd-x64": "0.19.3", - "@esbuild/linux-arm": "0.19.3", - "@esbuild/linux-arm64": "0.19.3", - "@esbuild/linux-ia32": "0.19.3", - "@esbuild/linux-loong64": "0.19.3", - "@esbuild/linux-mips64el": "0.19.3", - "@esbuild/linux-ppc64": "0.19.3", - "@esbuild/linux-riscv64": "0.19.3", - "@esbuild/linux-s390x": "0.19.3", - "@esbuild/linux-x64": "0.19.3", - "@esbuild/netbsd-x64": "0.19.3", - "@esbuild/openbsd-x64": "0.19.3", - "@esbuild/sunos-x64": "0.19.3", - "@esbuild/win32-arm64": "0.19.3", - "@esbuild/win32-ia32": "0.19.3", - "@esbuild/win32-x64": "0.19.3" + "version": "0.25.0", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.0.tgz", + "integrity": "sha512-BXq5mqc8ltbaN34cDqWuYKyNhX8D/Z0J1xdtdQ8UcIIIyJyz+ZMKUt58tF3SrZ85jcfN/PZYhjR5uDQAYNVbuw==", + "dev": true, + "requires": { + "@esbuild/aix-ppc64": "0.25.0", + "@esbuild/android-arm": "0.25.0", + "@esbuild/android-arm64": "0.25.0", + "@esbuild/android-x64": "0.25.0", + "@esbuild/darwin-arm64": "0.25.0", + "@esbuild/darwin-x64": "0.25.0", + "@esbuild/freebsd-arm64": "0.25.0", + "@esbuild/freebsd-x64": "0.25.0", + "@esbuild/linux-arm": "0.25.0", + "@esbuild/linux-arm64": "0.25.0", + "@esbuild/linux-ia32": "0.25.0", + "@esbuild/linux-loong64": "0.25.0", + "@esbuild/linux-mips64el": "0.25.0", + "@esbuild/linux-ppc64": "0.25.0", + "@esbuild/linux-riscv64": "0.25.0", + "@esbuild/linux-s390x": "0.25.0", + "@esbuild/linux-x64": "0.25.0", + "@esbuild/netbsd-arm64": "0.25.0", + "@esbuild/netbsd-x64": "0.25.0", + "@esbuild/openbsd-arm64": "0.25.0", + "@esbuild/openbsd-x64": "0.25.0", + "@esbuild/sunos-x64": "0.25.0", + "@esbuild/win32-arm64": "0.25.0", + "@esbuild/win32-ia32": "0.25.0", + "@esbuild/win32-x64": "0.25.0" } }, "esbuild-plugin-polyfill-node": { @@ -6490,9 +7358,9 @@ } }, "escalade": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", - "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true }, "escape-string-regexp": { @@ -6502,49 +7370,53 @@ "dev": true }, "eslint": { - "version": "8.57.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.0.tgz", - "integrity": "sha512-dZ6+mexnaTIbSBZWgou51U6OmzIhYM2VcNdtiTtI7qPNZm35Akpr0f6vtw3w1Kmn5PYo+tZVfh13WrhpS6oLqQ==", - "dev": true, - "requires": { - "@eslint-community/eslint-utils": "^4.2.0", - "@eslint-community/regexpp": "^4.6.1", - "@eslint/eslintrc": "^2.1.4", - "@eslint/js": "8.57.0", - "@humanwhocodes/config-array": "^0.11.14", + "version": "9.38.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.38.0.tgz", + "integrity": "sha512-t5aPOpmtJcZcz5UJyY2GbvpDlsK5E8JqRqoKtfiKE3cNh437KIqfJr3A3AKf5k64NPx6d0G3dno6XDY05PqPtw==", + "dev": true, + "requires": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.1", + "@eslint/config-helpers": "^0.4.1", + "@eslint/core": "^0.16.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "9.38.0", + "@eslint/plugin-kit": "^0.4.0", + "@humanfs/node": "^0.16.6", "@humanwhocodes/module-importer": "^1.0.1", - "@nodelib/fs.walk": "^1.2.8", - "@ungap/structured-clone": "^1.2.0", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", "ajv": "^6.12.4", "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", + "cross-spawn": "^7.0.6", "debug": "^4.3.2", - "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.2.2", - "eslint-visitor-keys": "^3.4.3", - "espree": "^9.6.1", - "esquery": "^1.4.2", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", + "file-entry-cache": "^8.0.0", "find-up": "^5.0.0", "glob-parent": "^6.0.2", - "globals": "^13.19.0", - "graphemer": "^1.4.0", "ignore": "^5.2.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", - "is-path-inside": "^3.0.3", - "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", "lodash.merge": "^4.6.2", "minimatch": "^3.1.2", "natural-compare": "^1.4.0", - "optionator": "^0.9.3", - "strip-ansi": "^6.0.1", - "text-table": "^0.2.0" + "optionator": "^0.9.3" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true + } } }, "eslint-config-prettier": { @@ -6555,14 +7427,14 @@ "requires": {} }, "eslint-import-resolver-node": { - "version": "0.3.7", - "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.7.tgz", - "integrity": "sha512-gozW2blMLJCeFpBwugLTGyvVjNoeo1knonXAcatC6bjPBZitotxdWf7Gimr25N4c0AAOo4eOUfaG82IJPDpqCA==", + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz", + "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==", "dev": true, "requires": { "debug": "^3.2.7", - "is-core-module": "^2.11.0", - "resolve": "^1.22.1" + "is-core-module": "^2.13.0", + "resolve": "^1.22.4" }, "dependencies": { "debug": { @@ -6577,9 +7449,9 @@ } }, "eslint-module-utils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz", - "integrity": "sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==", + "version": "2.12.1", + "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.1.tgz", + "integrity": "sha512-L8jSWTze7K2mTg0vos/RuLRS5soomksDPoJLXIslC7c8Wmut3bx7CPpJijDcBZtxQ5lrbUdM+s0OlNbz0DCDNw==", "dev": true, "requires": { "debug": "^3.2.7" @@ -6604,28 +7476,30 @@ "requires": {} }, "eslint-plugin-import": { - "version": "2.28.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.28.1.tgz", - "integrity": "sha512-9I9hFlITvOV55alzoKBI+K9q74kv0iKMeY6av5+umsNwayt59fz692daGyjR+oStBQgx6nwR9rXldDev3Clw+A==", + "version": "2.32.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.32.0.tgz", + "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "requires": { - "array-includes": "^3.1.6", - "array.prototype.findlastindex": "^1.2.2", - "array.prototype.flat": "^1.3.1", - "array.prototype.flatmap": "^1.3.1", + "@rtsao/scc": "^1.1.0", + "array-includes": "^3.1.9", + "array.prototype.findlastindex": "^1.2.6", + "array.prototype.flat": "^1.3.3", + "array.prototype.flatmap": "^1.3.3", "debug": "^3.2.7", "doctrine": "^2.1.0", - "eslint-import-resolver-node": "^0.3.7", - "eslint-module-utils": "^2.8.0", - "has": "^1.0.3", - "is-core-module": "^2.13.0", + "eslint-import-resolver-node": "^0.3.9", + "eslint-module-utils": "^2.12.1", + "hasown": "^2.0.2", + "is-core-module": "^2.16.1", "is-glob": "^4.0.3", "minimatch": "^3.1.2", - "object.fromentries": "^2.0.6", - "object.groupby": "^1.0.0", - "object.values": "^1.1.6", + "object.fromentries": "^2.0.8", + "object.groupby": "^1.0.3", + "object.values": "^1.2.1", "semver": "^6.3.1", - "tsconfig-paths": "^3.14.2" + "string.prototype.trimend": "^1.0.9", + "tsconfig-paths": "^3.15.0" }, "dependencies": { "debug": { @@ -6655,20 +7529,25 @@ } }, "eslint-plugin-jsdoc": { - "version": "46.8.2", - "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.8.2.tgz", - "integrity": "sha512-5TSnD018f3tUJNne4s4gDWQflbsgOycIKEUBoCLn6XtBMgNHxQFmV8vVxUtiPxAQq8lrX85OaSG/2gnctxw9uQ==", + "version": "61.1.9", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-61.1.9.tgz", + "integrity": "sha512-X2AzSGbq1CzBRgKcVAu2qzOV9ogqygkUDk5AX6eNK5G+kY3I5Op5E5b99fE+FN0/bGnk2KGcsMIG6ZLF+di69A==", "dev": true, "requires": { - "@es-joy/jsdoccomment": "~0.40.1", + "@es-joy/jsdoccomment": "~0.76.0", + "@es-joy/resolve.exports": "1.0.0", "are-docs-informative": "^0.0.2", - "comment-parser": "1.4.0", - "debug": "^4.3.4", + "comment-parser": "1.4.1", + "debug": "^4.4.3", "escape-string-regexp": "^4.0.0", - "esquery": "^1.5.0", - "is-builtin-module": "^3.2.1", - "semver": "^7.5.4", - "spdx-expression-parse": "^3.0.1" + "espree": "^10.4.0", + "esquery": "^1.6.0", + "html-entities": "^2.6.0", + "object-deep-merge": "^2.0.0", + "parse-imports-exports": "^0.2.4", + "semver": "^7.7.3", + "spdx-expression-parse": "^4.0.0", + "to-valid-identifier": "^1.0.0" } }, "eslint-plugin-prefer-arrow": { @@ -6679,32 +7558,35 @@ "requires": {} }, "eslint-plugin-unicorn": { - "version": "48.0.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-48.0.1.tgz", - "integrity": "sha512-FW+4r20myG/DqFcCSzoumaddKBicIPeFnTrifon2mWIzlfyvzwyqZjqVP7m4Cqr/ZYisS2aiLghkUWaPg6vtCw==", + "version": "62.0.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-unicorn/-/eslint-plugin-unicorn-62.0.0.tgz", + "integrity": "sha512-HIlIkGLkvf29YEiS/ImuDZQbP12gWyx5i3C6XrRxMvVdqMroCI9qoVYCoIl17ChN+U89pn9sVwLxhIWj5nEc7g==", "dev": true, "requires": { - "@babel/helper-validator-identifier": "^7.22.5", - "@eslint-community/eslint-utils": "^4.4.0", - "ci-info": "^3.8.0", + "@babel/helper-validator-identifier": "^7.28.5", + "@eslint-community/eslint-utils": "^4.9.0", + "@eslint/plugin-kit": "^0.4.0", + "change-case": "^5.4.4", + "ci-info": "^4.3.1", "clean-regexp": "^1.0.0", - "esquery": "^1.5.0", - "indent-string": "^4.0.0", - "is-builtin-module": "^3.2.1", - "jsesc": "^3.0.2", - "lodash": "^4.17.21", + "core-js-compat": "^3.46.0", + "esquery": "^1.6.0", + "find-up-simple": "^1.0.1", + "globals": "^16.4.0", + "indent-string": "^5.0.0", + "is-builtin-module": "^5.0.0", + "jsesc": "^3.1.0", "pluralize": "^8.0.0", - "read-pkg-up": "^7.0.1", "regexp-tree": "^0.1.27", - "regjsparser": "^0.10.0", - "semver": "^7.5.4", - "strip-indent": "^3.0.0" + "regjsparser": "^0.13.0", + "semver": "^7.7.3", + "strip-indent": "^4.1.1" } }, "eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", "dev": true, "requires": { "esrecurse": "^4.3.0", @@ -6718,20 +7600,28 @@ "dev": true }, "espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", "dev": true, "requires": { - "acorn": "^8.9.0", + "acorn": "^8.15.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "eslint-visitor-keys": "^4.2.1" + }, + "dependencies": { + "eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true + } } }, "esquery": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.5.0.tgz", - "integrity": "sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg==", + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, "requires": { "estraverse": "^5.1.0" @@ -6777,16 +7667,16 @@ "dev": true }, "fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", "dev": true, "requires": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", - "micromatch": "^4.0.4" + "micromatch": "^4.0.8" }, "dependencies": { "glob-parent": { @@ -6813,21 +7703,21 @@ "dev": true }, "fastq": { - "version": "1.15.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.15.0.tgz", - "integrity": "sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw==", + "version": "1.19.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", + "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", "dev": true, "requires": { "reusify": "^1.0.4" } }, "file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", "dev": true, "requires": { - "flat-cache": "^3.0.4" + "flat-cache": "^4.0.0" } }, "fill-range": { @@ -6849,6 +7739,12 @@ "path-exists": "^4.0.0" } }, + "find-up-simple": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/find-up-simple/-/find-up-simple-1.0.1.tgz", + "integrity": "sha512-afd4O7zpqHeRyg4PfDQsXmlDe2PfdHtJt6Akt8jOWaApLOZk5JXs6VMR29lz03pRe9mpykrRCYIYxaJYcfpncQ==", + "dev": true + }, "flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", @@ -6856,28 +7752,28 @@ "dev": true }, "flat-cache": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.0.4.tgz", - "integrity": "sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg==", + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", "dev": true, "requires": { - "flatted": "^3.1.0", - "rimraf": "^3.0.2" + "flatted": "^3.2.9", + "keyv": "^4.5.4" } }, "flatted": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", - "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==", + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", "dev": true }, "for-each": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", - "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", "dev": true, "requires": { - "is-callable": "^1.1.3" + "is-callable": "^1.2.7" } }, "foreground-child": { @@ -6909,35 +7805,24 @@ "universalify": "^2.0.0" } }, - "fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true - }, - "fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "optional": true - }, "function-bind": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true }, "function.prototype.name": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", - "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "functions-have-names": "^1.2.3" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" } }, "functions-have-names": { @@ -6962,6 +7847,12 @@ "wide-align": "^1.1.5" } }, + "generator-function": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz", + "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==", + "dev": true + }, "get-caller-file": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", @@ -6969,39 +7860,76 @@ "dev": true }, "get-intrinsic": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", - "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", "dev": true, "requires": { - "function-bind": "^1.1.1", - "has": "^1.0.3", - "has-proto": "^1.0.1", - "has-symbols": "^1.0.3" + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + } + }, + "get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "requires": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" } }, "get-symbol-description": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", - "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.1" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" } }, "glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "version": "10.5.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz", + "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "dependencies": { + "brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dev": true, + "requires": { + "balanced-match": "^1.0.0" + } + }, + "minimatch": { + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", + "dev": true, + "requires": { + "brace-expansion": "^2.0.2" + } + } } }, "glob-parent": { @@ -7014,59 +7942,38 @@ } }, "global-agent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-3.0.0.tgz", - "integrity": "sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==", + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/global-agent/-/global-agent-4.1.3.tgz", + "integrity": "sha512-KUJEViiuFT3I97t+GYMikLPJS2Lfo/S2F+DQuBWzuzaMPnvt5yyZePzArx36fBzpGTxZjIpDbXLeySLgh+k76g==", "dev": true, "requires": { - "boolean": "^3.0.1", - "es6-error": "^4.1.1", - "matcher": "^3.0.0", - "roarr": "^2.15.3", - "semver": "^7.3.2", - "serialize-error": "^7.0.1" + "globalthis": "^1.0.2", + "matcher": "^4.0.0", + "semver": "^7.3.5", + "serialize-error": "^8.1.0" } }, "globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "requires": { - "type-fest": "^0.20.2" - } + "version": "16.4.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.4.0.tgz", + "integrity": "sha512-ob/2LcVVaVGCYN+r14cnwnoDPUufjiYgSqRhiFD0Q1iI4Odora5RE8Iv1D24hAz5oMophRGkGz+yuvQmmUMnMw==", + "dev": true }, "globalthis": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", - "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", - "dev": true, - "requires": { - "define-properties": "^1.1.3" - } - }, - "globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, "requires": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" } }, "gopd": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", - "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", - "dev": true, - "requires": { - "get-intrinsic": "^1.1.3" - } + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true }, "graceful-fs": { "version": "4.2.10", @@ -7080,19 +7987,10 @@ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", "dev": true }, - "has": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", - "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, - "requires": { - "function-bind": "^1.1.1" - } - }, "has-bigints": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", - "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", "dev": true }, "has-flag": { @@ -7102,33 +8000,36 @@ "dev": true }, "has-property-descriptors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz", - "integrity": "sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "dev": true, "requires": { - "get-intrinsic": "^1.1.1" + "es-define-property": "^1.0.0" } }, "has-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", - "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", - "dev": true + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "requires": { + "dunder-proto": "^1.0.0" + } }, "has-symbols": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", - "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", "dev": true }, "has-tostringtag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", - "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "has-symbols": "^1.0.3" } }, "has-unicode": { @@ -7137,16 +8038,25 @@ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==", "dev": true }, + "hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dev": true, + "requires": { + "function-bind": "^1.1.2" + } + }, "he": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", "dev": true }, - "hosted-git-info": { - "version": "2.8.9", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz", - "integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==", + "html-entities": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz", + "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==", "dev": true }, "ieee754": { @@ -7190,21 +8100,11 @@ "dev": true }, "indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-5.0.0.tgz", + "integrity": "sha512-m6FAo/spmsW2Ab2fU35JTYwtOKa2yAwXSwgjSv1TJzh4Mh7mC3lzAOVLBprb72XsTrgkEIsl7YrFNAiDiRhIGg==", "dev": true }, - "inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "dev": true, - "requires": { - "once": "^1.3.0", - "wrappy": "1" - } - }, "inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", @@ -7212,68 +8112,66 @@ "dev": true }, "internal-slot": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.5.tgz", - "integrity": "sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", "dev": true, "requires": { - "get-intrinsic": "^1.2.0", - "has": "^1.0.3", - "side-channel": "^1.0.4" + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" } }, "is-array-buffer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", - "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.0", - "is-typed-array": "^1.1.10" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" } }, - "is-arrayish": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", - "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", - "dev": true - }, - "is-bigint": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", - "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", "dev": true, "requires": { - "has-bigints": "^1.0.1" + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" } }, - "is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", "dev": true, "requires": { - "binary-extensions": "^2.0.0" + "has-bigints": "^1.0.2" } }, "is-boolean-object": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", - "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" } }, "is-builtin-module": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", - "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-5.0.0.tgz", + "integrity": "sha512-f4RqJKBUe5rQkJ2eJEJBXSticB3hGbN9j0yxxMQFqIW89Jp9WYFtzfTcRlstDKVUTRzSOTLKRfO9vIztenwtxA==", "dev": true, "requires": { - "builtin-modules": "^3.3.0" + "builtin-modules": "^5.0.0" } }, "is-callable": { @@ -7283,21 +8181,33 @@ "dev": true }, "is-core-module": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.13.0.tgz", - "integrity": "sha512-Z7dk6Qo8pOCp3l4tsX2C5ZVas4V+UxwQodwZhLopL91TX8UyyHEXafPcyoeeWuLrwzHcr3igO78wNLwHJHsMCQ==", + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", "dev": true, "requires": { - "has": "^1.0.3" + "hasown": "^2.0.2" + } + }, + "is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" } }, "is-date-object": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", - "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" } }, "is-extglob": { @@ -7306,12 +8216,34 @@ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true }, + "is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "requires": { + "call-bound": "^1.0.3" + } + }, "is-fullwidth-code-point": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "dev": true }, + "is-generator-function": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz", + "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==", + "dev": true, + "requires": { + "call-bound": "^1.0.4", + "generator-function": "^2.0.0", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + } + }, "is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", @@ -7321,10 +8253,16 @@ "is-extglob": "^2.1.1" } }, + "is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true + }, "is-negative-zero": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", - "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true }, "is-number": { @@ -7334,12 +8272,13 @@ "dev": true }, "is-number-object": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", - "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" } }, "is-path-inside": { @@ -7355,49 +8294,60 @@ "dev": true }, "is-regex": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", - "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" } }, + "is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true + }, "is-shared-array-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", - "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3" } }, "is-string": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", - "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", "dev": true, "requires": { - "has-tostringtag": "^1.0.0" + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" } }, "is-symbol": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", - "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", "dev": true, "requires": { - "has-symbols": "^1.0.2" + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" } }, "is-typed-array": { - "version": "1.1.12", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", - "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", "dev": true, "requires": { - "which-typed-array": "^1.1.11" + "which-typed-array": "^1.1.16" } }, "is-unicode-supported": { @@ -7406,13 +8356,29 @@ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", "dev": true }, + "is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true + }, "is-weakref": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", - "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "requires": { + "call-bound": "^1.0.3" + } + }, + "is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", "dev": true, "requires": { - "call-bind": "^1.0.2" + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" } }, "isarray": { @@ -7437,37 +8403,31 @@ "@pkgjs/parseargs": "^0.11.0" } }, - "js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "dev": true - }, "js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", "dev": true, "requires": { "argparse": "^2.0.1" } }, "jsdoc-type-pratt-parser": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", - "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-6.10.0.tgz", + "integrity": "sha512-+LexoTRyYui5iOhJGn13N9ZazL23nAHGkXsa1p/C8yeq79WRfLBag6ZZ0FQG2aRoc9yfo59JT9EYCQonOkHKkQ==", "dev": true }, "jsesc": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", - "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "dev": true }, - "json-parse-even-better-errors": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", - "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", "dev": true }, "json-schema-traverse": { @@ -7482,12 +8442,6 @@ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", "dev": true }, - "json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true - }, "json5": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz", @@ -7519,6 +8473,15 @@ "setimmediate": "^1.0.5" } }, + "keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "requires": { + "json-buffer": "3.0.1" + } + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -7538,12 +8501,6 @@ "immediate": "~3.0.5" } }, - "lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true - }, "locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -7553,12 +8510,6 @@ "p-locate": "^5.0.0" } }, - "lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "dev": true - }, "lodash.merge": { "version": "4.6.2", "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", @@ -7575,24 +8526,21 @@ "is-unicode-supported": "^0.1.0" } }, - "lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dev": true, - "requires": { - "yallist": "^4.0.0" - } - }, "matcher": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/matcher/-/matcher-3.0.0.tgz", - "integrity": "sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/matcher/-/matcher-4.0.0.tgz", + "integrity": "sha512-S6x5wmcDmsDRRU/c2dkccDwQPXoFczc5+HpQ2lON8pnvHlnvHAHj5WlLVvw6n6vNyHuVugYrFohYxbS+pvFpKQ==", "dev": true, "requires": { "escape-string-regexp": "^4.0.0" } }, + "math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true + }, "merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", @@ -7609,16 +8557,10 @@ "picomatch": "^2.3.1" } }, - "min-indent": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", - "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==", - "dev": true - }, "minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.4.tgz", + "integrity": "sha512-twmL+S8+7yIsE9wsqgzU3E8/LumN3M3QELrBZ20OdmQ9jB2JvW5oZtBEmft84k/Gs5CG9mqtWc6Y9vW+JEzGxw==", "dev": true, "requires": { "brace-expansion": "^1.1.7" @@ -7637,74 +8579,50 @@ "dev": true }, "mocha": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.0.1.tgz", - "integrity": "sha512-+3GkODfsDG71KSCQhc4IekSW+ItCK/kiez1Z28ksWvYhKXV/syxMlerR/sC7whDp7IyreZ4YxceMLdTs5hQE8A==", + "version": "11.7.5", + "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.7.5.tgz", + "integrity": "sha512-mTT6RgopEYABzXWFx+GcJ+ZQ32kp4fMf0xvpZIIfSq9Z8lC/++MtcCnQ9t5FP2veYEP95FIYSvW+U9fV4xrlig==", "dev": true, "requires": { - "ansi-colors": "^4.1.3", "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", + "chokidar": "^4.0.1", "debug": "^4.3.5", - "diff": "^5.2.0", + "diff": "^7.0.0", "escape-string-regexp": "^4.0.0", "find-up": "^5.0.0", "glob": "^10.4.5", "he": "^1.2.0", + "is-path-inside": "^3.0.3", "js-yaml": "^4.1.0", "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", + "minimatch": "^9.0.5", "ms": "^2.1.3", + "picocolors": "^1.1.1", "serialize-javascript": "^6.0.2", "strip-json-comments": "^3.1.1", "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^16.2.0", - "yargs-parser": "^20.2.9", + "workerpool": "^9.2.0", + "yargs": "^17.7.2", + "yargs-parser": "^21.1.1", "yargs-unparser": "^2.0.0" }, "dependencies": { "brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", "dev": true, "requires": { "balanced-match": "^1.0.0" } }, - "glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "requires": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "dependencies": { - "minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "requires": { - "brace-expansion": "^2.0.1" - } - } - } - }, "minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "version": "9.0.9", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", + "integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "dev": true, "requires": { - "brace-expansion": "^2.0.1" + "brace-expansion": "^2.0.2" } }, "supports-color": { @@ -7730,30 +8648,10 @@ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", "dev": true }, - "normalize-package-data": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz", - "integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==", - "dev": true, - "requires": { - "hosted-git-info": "^2.1.4", - "resolve": "^1.10.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" - }, - "dependencies": { - "semver": { - "version": "5.7.2", - "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", - "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", - "dev": true - } - } - }, - "normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "node-releases": { + "version": "2.0.26", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.26.tgz", + "integrity": "sha512-S2M9YimhSjBSvYnlr5/+umAnPHE++ODwt5e2Ij6FoX45HA/s4vHdkDx1eax2pAPeAOqu4s9b7ppahsyEFdVqQA==", "dev": true }, "npmlog": { @@ -7768,10 +8666,16 @@ "set-blocking": "^2.0.0" } }, + "object-deep-merge": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object-deep-merge/-/object-deep-merge-2.0.0.tgz", + "integrity": "sha512-3DC3UMpeffLTHiuXSy/UG4NOIYTLlY9u3V82+djSCLYClWobZiS4ivYzpIUWrRY/nfsJ8cWsKyG3QfyLePmhvg==", + "dev": true + }, "object-inspect": { - "version": "1.12.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", - "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", "dev": true }, "object-keys": { @@ -7781,58 +8685,52 @@ "dev": true }, "object.assign": { - "version": "4.1.4", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.4.tgz", - "integrity": "sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ==", + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", "object-keys": "^1.1.1" } }, "object.fromentries": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.7.tgz", - "integrity": "sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA==", + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" } }, "object.groupby": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.1.tgz", - "integrity": "sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz", + "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1", - "get-intrinsic": "^1.2.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2" } }, "object.values": { - "version": "1.1.6", - "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.6.tgz", - "integrity": "sha512-FVVTkD1vENCsAcwNs9k6jea2uHC/X0+JcjG8YA60FN5CMaJmG95wT9jek/xX9nornqGRrBkKtzuAu2wuHpKqvw==", - "dev": true, - "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.1.4", - "es-abstract": "^1.20.4" - } - }, - "once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", "dev": true, "requires": { - "wrappy": "1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "optionator": { @@ -7849,6 +8747,17 @@ "type-check": "^0.4.0" } }, + "own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "requires": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + } + }, "p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -7867,12 +8776,6 @@ "p-limit": "^3.0.2" } }, - "p-try": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", - "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", - "dev": true - }, "package-json-from-dist": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", @@ -7894,30 +8797,27 @@ "callsites": "^3.0.0" } }, - "parse-json": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", - "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "parse-imports-exports": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/parse-imports-exports/-/parse-imports-exports-0.2.4.tgz", + "integrity": "sha512-4s6vd6dx1AotCx/RCI2m7t7GCh5bDRUtGNvRfHSP2wbBQdMi67pPe7mtzmgwcaQ8VKK/6IB7Glfyu3qdZJPybQ==", "dev": true, "requires": { - "@babel/code-frame": "^7.0.0", - "error-ex": "^1.3.1", - "json-parse-even-better-errors": "^2.3.0", - "lines-and-columns": "^1.1.6" + "parse-statements": "1.0.11" } }, + "parse-statements": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/parse-statements/-/parse-statements-1.0.11.tgz", + "integrity": "sha512-HlsyYdMBnbPQ9Jr/VgJ1YF4scnldvJpJxCVx6KgqPL4dxppsWrJHCIIxQXMJrqGnsRkNPATbeMJ8Yxu7JMsYcA==", + "dev": true + }, "path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true }, - "path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true - }, "path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", @@ -7948,16 +8848,16 @@ } } }, - "path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "dev": true }, "picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", "dev": true }, "pluralize": { @@ -7966,6 +8866,12 @@ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", "dev": true }, + "possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true + }, "prelude-ls": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", @@ -8011,82 +8917,6 @@ "safe-buffer": "^5.1.0" } }, - "read-pkg": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz", - "integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==", - "dev": true, - "requires": { - "@types/normalize-package-data": "^2.4.0", - "normalize-package-data": "^2.5.0", - "parse-json": "^5.0.0", - "type-fest": "^0.6.0" - }, - "dependencies": { - "type-fest": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz", - "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==", - "dev": true - } - } - }, - "read-pkg-up": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz", - "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==", - "dev": true, - "requires": { - "find-up": "^4.1.0", - "read-pkg": "^5.2.0", - "type-fest": "^0.8.1" - }, - "dependencies": { - "find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", - "dev": true, - "requires": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - } - }, - "locate-path": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", - "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", - "dev": true, - "requires": { - "p-locate": "^4.1.0" - } - }, - "p-limit": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", - "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", - "dev": true, - "requires": { - "p-try": "^2.0.0" - } - }, - "p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "requires": { - "p-limit": "^2.2.0" - } - }, - "type-fest": { - "version": "0.8.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz", - "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==", - "dev": true - } - } - }, "readable-stream": { "version": "2.3.8", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz", @@ -8103,12 +8933,25 @@ } }, "readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true + }, + "reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", "dev": true, "requires": { - "picomatch": "^2.2.1" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" } }, "regexp-tree": { @@ -8118,31 +8961,26 @@ "dev": true }, "regexp.prototype.flags": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", - "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "set-function-name": "^2.0.0" + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" } }, "regjsparser": { - "version": "0.10.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.10.0.tgz", - "integrity": "sha512-qx+xQGZVsy55CH0a1hiVwHmqjLryfh7wQyF5HO07XJ9f7dQMY/gPQHhlyDkIzJKC+x2fUCpCcUODUUUFrm7SHA==", + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.0.tgz", + "integrity": "sha512-NZQZdC5wOE/H3UT28fVGL+ikOZcEzfMGk/c3iN9UGxzWHMa1op7274oyiUVrAG4B2EuFhus8SvkaYnhvW92p9Q==", "dev": true, "requires": { - "jsesc": "~0.5.0" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", - "dev": true - } + "jsesc": "~3.1.0" } }, "require-directory": { @@ -8151,13 +8989,19 @@ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", "dev": true }, + "reserved-identifiers": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/reserved-identifiers/-/reserved-identifiers-1.2.0.tgz", + "integrity": "sha512-yE7KUfFvaBFzGPs5H3Ops1RevfUEsDc5Iz65rOwWg4lE8HJSYtle77uul3+573457oHvBKuHYDl/xqUkKpEEdw==", + "dev": true + }, "resolve": { - "version": "1.22.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.1.tgz", - "integrity": "sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw==", + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", "dev": true, "requires": { - "is-core-module": "^2.9.0", + "is-core-module": "^2.16.1", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" } @@ -8169,34 +9013,11 @@ "dev": true }, "reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", + "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", "dev": true }, - "rimraf": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", - "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", - "dev": true, - "requires": { - "glob": "^7.1.3" - } - }, - "roarr": { - "version": "2.15.4", - "resolved": "https://registry.npmjs.org/roarr/-/roarr-2.15.4.tgz", - "integrity": "sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==", - "dev": true, - "requires": { - "boolean": "^3.0.1", - "detect-node": "^2.0.4", - "globalthis": "^1.0.1", - "json-stringify-safe": "^5.0.1", - "semver-compare": "^1.0.0", - "sprintf-js": "^1.1.2" - } - }, "run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -8207,14 +9028,15 @@ } }, "safe-array-concat": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.0.1.tgz", - "integrity": "sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q==", + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "has-symbols": "^1.0.3", + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", "isarray": "^2.0.5" }, "dependencies": { @@ -8232,47 +9054,48 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "dev": true }, - "safe-regex-test": { + "safe-push-apply": { "version": "1.0.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.0.tgz", - "integrity": "sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA==", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.1.3", - "is-regex": "^1.1.4" + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } } }, - "semver": { - "version": "7.5.4", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", - "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", "dev": true, "requires": { - "lru-cache": "^6.0.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" } }, - "semver-compare": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/semver-compare/-/semver-compare-1.0.0.tgz", - "integrity": "sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==", + "semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", "dev": true }, "serialize-error": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-7.0.1.tgz", - "integrity": "sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==", + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-8.1.0.tgz", + "integrity": "sha512-3NnuWfM6vBYoy5gZFvHiYsVbafvI9vZv/+jlIigFn4oP4zjNPK3LhcY0xSCgeb1a5L8jO71Mit9LlNoi2UfDDQ==", "dev": true, "requires": { - "type-fest": "^0.13.1" - }, - "dependencies": { - "type-fest": { - "version": "0.13.1", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.13.1.tgz", - "integrity": "sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==", - "dev": true - } + "type-fest": "^0.20.2" } }, "serialize-javascript": { @@ -8290,15 +9113,41 @@ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", "dev": true }, + "set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "requires": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + } + }, "set-function-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", - "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", "dev": true, "requires": { - "define-data-property": "^1.0.1", + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", "functions-have-names": "^1.2.3", - "has-property-descriptors": "^1.0.0" + "has-property-descriptors": "^1.0.2" + } + }, + "set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "requires": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" } }, "setimmediate": { @@ -8323,14 +9172,51 @@ "dev": true }, "side-channel": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", - "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + } + }, + "side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + } + }, + "side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + } + }, + "side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", "dev": true, "requires": { - "call-bind": "^1.0.0", - "get-intrinsic": "^1.0.2", - "object-inspect": "^1.9.0" + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" } }, "signal-exit": { @@ -8339,12 +9225,6 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true }, - "slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true - }, "source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", @@ -8361,26 +9241,16 @@ "source-map": "^0.6.0" } }, - "spdx-correct": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz", - "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==", - "dev": true, - "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" - } - }, "spdx-exceptions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz", - "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz", + "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==", "dev": true }, "spdx-expression-parse": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz", - "integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-4.0.0.tgz", + "integrity": "sha512-Clya5JIij/7C6bRR22+tnGXbc4VKlibKSVj2iHvVeX5iMW7s1SIQlqu699JkODJJIhh/pUu8L0/VLh8xflD+LQ==", "dev": true, "requires": { "spdx-exceptions": "^2.1.0", @@ -8388,16 +9258,20 @@ } }, "spdx-license-ids": { - "version": "3.0.12", - "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.12.tgz", - "integrity": "sha512-rr+VVSXtRhO4OHbXUiAF7xW3Bo9DuuF6C5jH+q/x15j2jniycgKbxU09Hr0WqlSLUs4i4ltHGXqTe7VHclYWyA==", + "version": "3.0.22", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.22.tgz", + "integrity": "sha512-4PRT4nh1EImPbt2jASOKHX7PB7I+e4IWNLvkKFDxNhJlfjbYlleYQh285Z/3mPTHSAK/AvdMmw5BNNuYH8ShgQ==", "dev": true }, - "sprintf-js": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", - "integrity": "sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==", - "dev": true + "stop-iteration-iterator": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz", + "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==", + "dev": true, + "requires": { + "es-errors": "^1.3.0", + "internal-slot": "^1.1.0" + } }, "string_decoder": { "version": "1.1.1", @@ -8431,36 +9305,41 @@ } }, "string.prototype.trim": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", - "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" } }, "string.prototype.trimend": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", - "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "string.prototype.trimstart": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", - "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "define-properties": "^1.2.0", - "es-abstract": "^1.22.1" + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" } }, "strip-ansi": { @@ -8488,13 +9367,10 @@ "dev": true }, "strip-indent": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz", - "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==", - "dev": true, - "requires": { - "min-indent": "^1.0.0" - } + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-4.1.1.tgz", + "integrity": "sha512-SlyRoSkdh1dYP0PzclLE7r0M9sgbFKKMFXpFRUMNuKhQSbC6VQIGzq3E0qsfvGJaUFJPGv6Ws1NZ/haTAjfbMA==", + "dev": true }, "strip-json-comments": { "version": "3.1.1", @@ -8529,12 +9405,6 @@ "source-map-support": "~0.5.20" } }, - "text-table": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", - "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", - "dev": true - }, "to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -8544,17 +9414,27 @@ "is-number": "^7.0.0" } }, + "to-valid-identifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/to-valid-identifier/-/to-valid-identifier-1.0.0.tgz", + "integrity": "sha512-41wJyvKep3yT2tyPqX/4blcfybknGB4D+oETKLs7Q76UiPqRpUJK3hr1nxelyYO0PHKVzJwlu0aCeEAsGI6rpw==", + "dev": true, + "requires": { + "@sindresorhus/base62": "^1.0.0", + "reserved-identifiers": "^1.0.0" + } + }, "ts-api-utils": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", - "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz", + "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==", "dev": true, "requires": {} }, "tsconfig-paths": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.14.2.tgz", - "integrity": "sha512-o/9iXgCYc5L/JxCHPe3Hvh8Q/2xm5Z+p18PESBU6Ff33695QnCHBEjcytY2q19ua7Mbl/DavtBOLq+oG0RCL+g==", + "version": "3.15.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz", + "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==", "dev": true, "requires": { "@types/json5": "^0.0.29", @@ -8579,50 +9459,56 @@ "dev": true }, "typed-array-buffer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", - "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", "dev": true, "requires": { - "call-bind": "^1.0.2", - "get-intrinsic": "^1.2.1", - "is-typed-array": "^1.1.10" + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" } }, "typed-array-byte-length": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", - "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" } }, "typed-array-byte-offset": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", - "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", "for-each": "^0.3.3", - "has-proto": "^1.0.1", - "is-typed-array": "^1.1.10" + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" } }, "typed-array-length": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", - "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "is-typed-array": "^1.1.9" + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" } }, "typescript": { @@ -8632,23 +9518,39 @@ "dev": true }, "unbox-primitive": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", - "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", "dev": true, "requires": { - "call-bind": "^1.0.2", + "call-bound": "^1.0.3", "has-bigints": "^1.0.2", - "has-symbols": "^1.0.3", - "which-boxed-primitive": "^1.0.2" + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" } }, + "undici-types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz", + "integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==", + "dev": true + }, "universalify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz", "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==", "dev": true }, + "update-browserslist-db": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", + "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", + "dev": true, + "requires": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + } + }, "uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -8664,16 +9566,6 @@ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true }, - "validate-npm-package-license": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", - "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", - "dev": true, - "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" - } - }, "which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", @@ -8684,29 +9576,72 @@ } }, "which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "requires": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + } + }, + "which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "requires": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "dependencies": { + "isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true + } + } + }, + "which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", - "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", "dev": true, "requires": { - "is-bigint": "^1.0.1", - "is-boolean-object": "^1.1.0", - "is-number-object": "^1.0.4", - "is-string": "^1.0.5", - "is-symbol": "^1.0.3" + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" } }, "which-typed-array": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.11.tgz", - "integrity": "sha512-qe9UWWpkeG5yzZ0tNYxDmd7vo58HDBc39mZ0xWWpolAGADdFOzkfamWLDxkOWcvHQKVmdTyQdLD4NOfjLWTKew==", + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", "dev": true, "requires": { - "available-typed-arrays": "^1.0.5", - "call-bind": "^1.0.2", - "for-each": "^0.3.3", - "gopd": "^1.0.1", - "has-tostringtag": "^1.0.0" + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" } }, "wide-align": { @@ -8719,9 +9654,9 @@ } }, "workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", + "version": "9.3.4", + "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.3.4.tgz", + "integrity": "sha512-TmPRQYYSAnnDiEB0P/Ytip7bFGvqnSU6I2BcuSw7Hx+JSg/DsUi5ebYfc8GYaSdpuvOcEs6dXxPurOYpe9QFwg==", "dev": true }, "wrap-ansi": { @@ -8746,43 +9681,31 @@ "strip-ansi": "^6.0.0" } }, - "wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true - }, "y18n": { "version": "5.0.8", "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", "dev": true }, - "yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true - }, "yargs": { - "version": "16.2.0", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", - "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", "dev": true, "requires": { - "cliui": "^7.0.2", + "cliui": "^8.0.1", "escalade": "^3.1.1", "get-caller-file": "^2.0.5", "require-directory": "^2.1.1", - "string-width": "^4.2.0", + "string-width": "^4.2.3", "y18n": "^5.0.5", - "yargs-parser": "^20.2.2" + "yargs-parser": "^21.1.1" } }, "yargs-parser": { - "version": "20.2.9", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", - "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", "dev": true }, "yargs-unparser": { diff --git a/js/package.json b/js/package.json index 15cbe12e2742f..65cfa4a59e4e3 100644 --- a/js/package.json +++ b/js/package.json @@ -1,24 +1,28 @@ { "devDependencies": { + "@eslint/compat": "^1.4.0", + "@eslint/eslintrc": "^3.3.1", + "@eslint/js": "^9.38.0", "@types/fs-extra": "^11.0.4", - "@types/global-agent": "^2.1.3", + "@types/global-agent": "^3.0.0", "@types/mocha": "^10.0.2", - "@types/node": "^18.14.6", + "@types/node": "^20.10.0", "@types/npmlog": "^4.1.4", - "@typescript-eslint/eslint-plugin": "^7.4.0", - "@typescript-eslint/parser": "^7.4.0", + "@typescript-eslint/eslint-plugin": "^8.46.2", + "@typescript-eslint/parser": "^8.46.2", "dir-compare": "^4.2.0", - "esbuild": "^0.19.3", + "esbuild": "^0.25.0", "esbuild-plugin-polyfill-node": "^0.3.0", - "eslint": "^8.51.0", + "eslint": "^9.38.0", "eslint-config-prettier": "^9.1.0", "eslint-plugin-header": "^3.1.1", - "eslint-plugin-import": "^2.28.1", - "eslint-plugin-jsdoc": "^46.8.2", + "eslint-plugin-import": "^2.32.0", + "eslint-plugin-jsdoc": "^61.1.9", "eslint-plugin-prefer-arrow": "^1.2.3", - "eslint-plugin-unicorn": "^48.0.1", + "eslint-plugin-unicorn": "^62.0.0", "fs-extra": "^11.2.0", - "global-agent": "^3.0", + "global-agent": "^4.1.3", + "globals": "^16.4.0", "jszip": "^3.10.1", "mocha": "^11.0.1", "npmlog": "^7.0.1", diff --git a/js/react_native/README.md b/js/react_native/README.md index b45182d16a3fc..d57dbad2b37f8 100644 --- a/js/react_native/README.md +++ b/js/react_native/README.md @@ -13,9 +13,21 @@ With ONNX Runtime React Native, React Native developers can score pre-trained ON ### Installation ```sh -yarn add onnxruntime-react-native +npm install onnxruntime-react-native ``` +React Native's autolinking registers the native Android and iOS modules automatically. No manual changes to `settings.gradle`, `build.gradle`, or `MainApplication` are required for bare React Native projects. + +For Expo managed/prebuild workflows, add the config plugin to your `app.json`/`app.config.js`: + +```json +{ + "plugins": ["onnxruntime-react-native"] +} +``` + +Then run `npx expo prebuild` to apply the native changes. + ### Usage ```js diff --git a/js/react_native/android/CMakeLists.txt b/js/react_native/android/CMakeLists.txt index 98f30daac6372..a23f5ba7cd8ab 100644 --- a/js/react_native/android/CMakeLists.txt +++ b/js/react_native/android/CMakeLists.txt @@ -1,37 +1,102 @@ -project(OnnxruntimeJSIHelper) -cmake_minimum_required(VERSION 3.9.0) +cmake_minimum_required(VERSION 3.13) +project(OnnxruntimeJSI) -set (PACKAGE_NAME "onnxruntime-react-native") -set (BUILD_DIR ${CMAKE_SOURCE_DIR}/build) +set(PACKAGE_NAME "onnxruntime-react-native") +set(BUILD_DIR ${CMAKE_SOURCE_DIR}/build) set(CMAKE_VERBOSE_MAKEFILE ON) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) -file(TO_CMAKE_PATH "${NODE_MODULES_DIR}/react-native/ReactCommon/jsi/jsi/jsi.cpp" libPath) +option(ORT_EXTENSIONS_ENABLED "Enable Ort Extensions" NO) +option(USE_NNAPI "Use NNAPI" YES) +option(USE_QNN "Use QNN" NO) + +file(GLOB libfbjni_link_DIRS "${BUILD_DIR}/fbjni-*.aar/jni/${ANDROID_ABI}") +file(GLOB libfbjni_include_DIRS "${BUILD_DIR}/fbjni-*-headers.jar/") + +file(GLOB onnxruntime_include_DIRS + "${BUILD_DIR}/onnxruntime-android-*.aar/headers") +file(GLOB onnxruntime_link_DIRS + "${BUILD_DIR}/onnxruntime-android-*.aar/jni/${ANDROID_ABI}/") + +if(ORT_EXTENSIONS_ENABLED) + add_definitions(-DORT_ENABLE_EXTENSIONS) +endif() + +if(USE_QNN) + add_definitions(-DUSE_QNN) +endif() + +if(USE_NNAPI) + add_definitions(-DUSE_NNAPI) +endif() + +file(TO_CMAKE_PATH + "${NODE_MODULES_DIR}/react-native/ReactCommon/jsi/jsi/jsi.cpp" libPath) + +find_package(fbjni REQUIRED CONFIG) +find_package(ReactAndroid REQUIRED CONFIG) + +find_library( + onnxruntime-lib onnxruntime + PATHS ${onnxruntime_link_DIRS} + NO_CMAKE_FIND_ROOT_PATH) + +set(RN_INCLUDES + "${NODE_MODULES_DIR}/react-native/React" + "${NODE_MODULES_DIR}/react-native/React/Base" + "${NODE_MODULES_DIR}/react-native/ReactCommon" + "${NODE_MODULES_DIR}/react-native/ReactCommon/jsi" + "${NODE_MODULES_DIR}/react-native/ReactCommon/callinvoker") + +if(${REACT_NATIVE_VERSION} VERSION_GREATER_EQUAL "0.76") + set(RN_LIBS + ReactAndroid::reactnative + ReactAndroid::jsi) +else() + list( + APPEND + RN_INCLUDES + "${NODE_MODULES_DIR}/react-native/ReactAndroid/src/main/java/com/facebook/react/turbomodule/core/jni" + ) + set(RN_LIBS + ReactAndroid::jsi + ReactAndroid::react_nativemodule_core + ReactAndroid::turbomodulejsijni) +endif() include_directories( - "${NODE_MODULES_DIR}/react-native/React" - "${NODE_MODULES_DIR}/react-native/React/Base" - "${NODE_MODULES_DIR}/react-native/ReactCommon/jsi" -) + ../cpp + ${RN_INCLUDES} + ${onnxruntime_include_DIRS} + ${libfbjni_include_DIRS}) -add_library(onnxruntimejsihelper - SHARED - ${libPath} - src/main/cpp/cpp-adapter.cpp -) +add_library( + onnxruntimejsi SHARED + ${libPath} + src/main/cpp/cpp-adapter.cpp + ../cpp/JsiMain.cpp + ../cpp/InferenceSessionHostObject.cpp + ../cpp/JsiUtils.cpp + ../cpp/SessionUtils.cpp + ../cpp/TensorUtils.cpp) -# Configure C++ 17 +# Configure C++20 set_target_properties( - onnxruntimejsihelper PROPERTIES - CXX_STANDARD 17 - CXX_EXTENSIONS OFF - POSITION_INDEPENDENT_CODE ON -) + onnxruntimejsi + PROPERTIES CXX_STANDARD 20 + CXX_EXTENSIONS OFF + POSITION_INDEPENDENT_CODE ON) find_library(log-lib log) target_link_libraries( - onnxruntimejsihelper - ${log-lib} # <-- Logcat logger - android # <-- Android JNI core + onnxruntimejsi + ${onnxruntime-lib} + fbjni::fbjni + ${RN_LIBS} + ${log-lib} # <-- Logcat logger + android # <-- Android JNI core ) + +# 16KB page size support (Android 15+ requirement) +target_link_options(onnxruntimejsi PRIVATE "-Wl,-z,max-page-size=16384") diff --git a/js/react_native/android/build.gradle b/js/react_native/android/build.gradle index 2f5b5adc7a1fa..d13e98a9f3487 100644 --- a/js/react_native/android/build.gradle +++ b/js/react_native/android/build.gradle @@ -48,26 +48,30 @@ static def findNodeModules(baseDir) { def nodeModules = findNodeModules(projectDir); -def checkIfOrtExtensionsEnabled() { +def readPackageJsonField(field) { // locate user's project dir def reactnativeRootDir = project.rootDir.parentFile // get package.json file in root directory def packageJsonFile = new File(reactnativeRootDir, 'package.json') - // read field 'onnxruntimeExtensionsEnabled' if (packageJsonFile.exists()) { def packageJsonContents = packageJsonFile.getText() def packageJson = new groovy.json.JsonSlurper().parseText(packageJsonContents) - return packageJson.onnxruntimeExtensionsEnabled == "true" + return packageJson.get(field) } else { - logger.warn("Could not find package.json file in the expected directory: ${reactnativeRootDir}. ONNX Runtime Extensions will not be enabled.") + logger.warn("Could not find package.json file in the expected directory: ${reactnativeRootDir}. ${field} will not be enabled.") } - return false } -boolean ortExtensionsEnabled = checkIfOrtExtensionsEnabled() +boolean ortExtensionsEnabled = readPackageJsonField('onnxruntimeExtensionsEnabled') == "true" +boolean useQnn = readPackageJsonField('onnxruntimeUseQnn') == "true" def REACT_NATIVE_VERSION = ['node', '--print', "JSON.parse(require('fs').readFileSync(require.resolve('react-native/package.json'), 'utf-8')).version"].execute(null, rootDir).text.trim() -def REACT_NATIVE_MINOR_VERSION = REACT_NATIVE_VERSION.split("\\.")[1].toInteger() +def versionParts = REACT_NATIVE_VERSION.split("\\.") +if (versionParts.length < 2) { + throw new GradleException("Invalid React Native version format: ${REACT_NATIVE_VERSION}. Expected format: major.minor[.patch]") +} +def REACT_NATIVE_MAJOR_VERSION = versionParts[0].toInteger() +def REACT_NATIVE_MINOR_VERSION = versionParts[1].toInteger() android { // This is needed by the new AndroidManifestNew.xml @@ -83,11 +87,20 @@ android { externalNativeBuild { cmake { cppFlags "-O2 -frtti -fexceptions -Wall -Wno-unused-variable -fstack-protector-all" - if (REACT_NATIVE_MINOR_VERSION >= 71) { + if (REACT_NATIVE_MAJOR_VERSION > 0 || REACT_NATIVE_MINOR_VERSION >= 71) { // fabricjni required c++_shared - arguments "-DANDROID_STL=c++_shared", "-DNODE_MODULES_DIR=${nodeModules}", "-DORT_EXTENSIONS_ENABLED=${ortExtensionsEnabled}" + arguments "-DANDROID_STL=c++_shared", + "-DNODE_MODULES_DIR=${nodeModules}", + "-DORT_EXTENSIONS_ENABLED=${ortExtensionsEnabled}", + "-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}", + "-DUSE_QNN=${useQnn}", + "-DUSE_NNAPI=${!useQnn}" } else { - arguments "-DNODE_MODULES_DIR=${nodeModules}", "-DORT_EXTENSIONS_ENABLED=${ortExtensionsEnabled}" + arguments "-DNODE_MODULES_DIR=${nodeModules}", + "-DORT_EXTENSIONS_ENABLED=${ortExtensionsEnabled}", + "-DREACT_NATIVE_VERSION=${REACT_NATIVE_VERSION}", + "-DUSE_QNN=${useQnn}", + "-DUSE_NNAPI=${!useQnn}" } abiFilters (*reactNativeArchitectures()) } @@ -119,6 +132,9 @@ android { "META-INF", "META-INF/**", "**/libjsi.so", + "**/libfbjni.so", + "**/libreact_nativemodule_core.so", + "**/libturbomodulejsijni.so" ] } @@ -147,6 +163,10 @@ android { } } } + + configurations { + extractLibs + } } repositories { @@ -217,10 +237,6 @@ repositories { "Ensure you have you installed React Native as a dependency in your project and try again." ) } - - flatDir { - dir 'libs' - } } dependencies { @@ -228,16 +244,47 @@ dependencies { implementation "com.facebook.react:react-android:"+ REACT_NATIVE_VERSION api "org.mockito:mockito-core:2.28.2" - androidTestImplementation "androidx.test:runner:1.5.2" - androidTestImplementation "androidx.test:rules:1.5.0" implementation "junit:junit:4.12" - androidTestImplementation "com.linkedin.dexmaker:dexmaker-mockito-inline-extended:2.28.1" + if (useQnn) { + extractLibs "com.microsoft.onnxruntime:onnxruntime-android-qnn:latest.integration@aar" + } else { + extractLibs "com.microsoft.onnxruntime:onnxruntime-android:latest.integration@aar" + } - implementation "com.microsoft.onnxruntime:onnxruntime-android:latest.integration@aar" + if (REACT_NATIVE_MAJOR_VERSION == 0 && REACT_NATIVE_MINOR_VERSION < 71) { + extractLibs "com.facebook.fbjni:fbjni:+:headers" + extractLibs "com.facebook.fbjni:fbjni:+" + } // By default it will just include onnxruntime full aar package if (ortExtensionsEnabled) { implementation "com.microsoft.onnxruntime:onnxruntime-extensions-android:latest.integration@aar" } -} \ No newline at end of file +} + +task extractLibs { + doLast { + configurations.extractLibs.files.each { + def file = it.absoluteFile + copy { + from zipTree(file) + into "$buildDir/$file.name" + include "**/*.h", "**/*.so" + } + } + } +} + +def nativeBuildDependsOn(dependsOnTask, variant) { + def buildTasks = tasks.findAll({ task -> + !task.name.contains("Clean") && (task.name.contains("externalNative") || task.name.contains("CMake")) }) + if (variant != null) { + buildTasks = buildTasks.findAll({ task -> task.name.contains(variant) }) + } + buildTasks.forEach { task -> task.dependsOn(dependsOnTask) } +} + +afterEvaluate { + nativeBuildDependsOn(extractLibs, null) +} diff --git a/js/react_native/android/gradle.properties b/js/react_native/android/gradle.properties index 3461ce4919d38..6f0e50c7151a8 100644 --- a/js/react_native/android/gradle.properties +++ b/js/react_native/android/gradle.properties @@ -4,7 +4,7 @@ # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. # Default value: -Xmx1024m -XX:MaxPermSize=256m -org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Djavax.xml.accessExternalSchema=all -Djavax.xml.accessExternalDTD=all +org.gradle.jvmargs=-Xmx8192m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 -Djavax.xml.accessExternalSchema=all -Djavax.xml.accessExternalDTD=all # # When configured, Gradle will run in incubating parallel mode. # This option should only be used with decoupled projects. More details, visit @@ -13,7 +13,7 @@ org.gradle.jvmargs=-Xmx4096m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF #Tue Jan 26 17:36:02 PST 2021 android.enableJetifier=true android.useAndroidX=true -OnnxruntimeModule_buildToolsVersion=33.0.0 +OnnxruntimeModule_buildToolsVersion=34.0.0 OnnxruntimeModule_compileSdkVersion=34 OnnxruntimeModule_minSdkVersion=24 OnnxruntimeModule_targetSdkVersion=34 diff --git a/js/react_native/android/src/androidTest/Readme.md b/js/react_native/android/src/androidTest/Readme.md deleted file mode 100644 index b0376602af908..0000000000000 --- a/js/react_native/android/src/androidTest/Readme.md +++ /dev/null @@ -1 +0,0 @@ -Please see [here](/js/react_native/test_types_models.readme.md) for information on the test models. diff --git a/js/react_native/android/src/androidTest/java/ai/onnxruntime/reactnative/FakeBlobModule.java b/js/react_native/android/src/androidTest/java/ai/onnxruntime/reactnative/FakeBlobModule.java deleted file mode 100644 index 82d063ad51e3f..0000000000000 --- a/js/react_native/android/src/androidTest/java/ai/onnxruntime/reactnative/FakeBlobModule.java +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package ai.onnxruntime.reactnative; - -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.JavaOnlyMap; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.modules.blob.BlobModule; - -public class FakeBlobModule extends BlobModule { - - public FakeBlobModule(ReactApplicationContext context) { super(null); } - - @Override - public String getName() { - return "BlobModule"; - } - - public JavaOnlyMap testCreateData(byte[] bytes) { - String blobId = store(bytes); - JavaOnlyMap data = new JavaOnlyMap(); - data.putString("blobId", blobId); - data.putInt("offset", 0); - data.putInt("size", bytes.length); - return data; - } - - public byte[] testGetData(ReadableMap data) { - String blobId = data.getString("blobId"); - int offset = data.getInt("offset"); - int size = data.getInt("size"); - return resolve(blobId, offset, size); - } -} diff --git a/js/react_native/android/src/androidTest/java/ai/onnxruntime/reactnative/OnnxruntimeModuleTest.java b/js/react_native/android/src/androidTest/java/ai/onnxruntime/reactnative/OnnxruntimeModuleTest.java deleted file mode 100644 index b15b1a468ae29..0000000000000 --- a/js/react_native/android/src/androidTest/java/ai/onnxruntime/reactnative/OnnxruntimeModuleTest.java +++ /dev/null @@ -1,203 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package ai.onnxruntime.reactnative; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; -import static org.mockito.Mockito.when; - -import ai.onnxruntime.TensorInfo; -import android.util.Base64; -import androidx.test.platform.app.InstrumentationRegistry; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.CatalystInstance; -import com.facebook.react.bridge.JavaOnlyArray; -import com.facebook.react.bridge.JavaOnlyMap; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.modules.blob.BlobModule; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.FloatBuffer; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoSession; - -public class OnnxruntimeModuleTest { - private ReactApplicationContext reactContext = - new ReactApplicationContext(InstrumentationRegistry.getInstrumentation().getContext()); - - private FakeBlobModule blobModule; - - private static byte[] getInputModelBuffer(InputStream modelStream) throws Exception { - ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); - - int bufferSize = 1024; - byte[] buffer = new byte[bufferSize]; - - int len; - while ((len = modelStream.read(buffer)) != -1) { - byteBuffer.write(buffer, 0, len); - } - - byte[] modelBuffer = byteBuffer.toByteArray(); - - return modelBuffer; - } - - @Before - public void setUp() { - blobModule = new FakeBlobModule(reactContext); - } - - @Test - public void getName() throws Exception { - OnnxruntimeModule ortModule = new OnnxruntimeModule(reactContext); - ortModule.blobModule = blobModule; - String name = "Onnxruntime"; - Assert.assertEquals(ortModule.getName(), name); - } - - @Test - public void onnxruntime_module() throws Exception { - MockitoSession mockSession = mockitoSession().mockStatic(Arguments.class).startMocking(); - try { - when(Arguments.createMap()).thenAnswer(i -> new JavaOnlyMap()); - when(Arguments.createArray()).thenAnswer(i -> new JavaOnlyArray()); - - OnnxruntimeModule ortModule = new OnnxruntimeModule(reactContext); - ortModule.blobModule = blobModule; - String sessionKey = ""; - - // test loadModel() - { - try (InputStream modelStream = - reactContext.getResources().openRawResource(ai.onnxruntime.reactnative.test.R.raw.test_types_float);) { - byte[] modelBuffer = getInputModelBuffer(modelStream); - - JavaOnlyMap options = new JavaOnlyMap(); - try { - ReadableMap resultMap = ortModule.loadModel(modelBuffer, options); - sessionKey = resultMap.getString("key"); - ReadableArray inputNames = resultMap.getArray("inputNames"); - ReadableArray outputNames = resultMap.getArray("outputNames"); - - Assert.assertEquals(inputNames.size(), 1); - Assert.assertEquals(inputNames.getString(0), "input"); - Assert.assertEquals(outputNames.size(), 1); - Assert.assertEquals(outputNames.getString(0), "output"); - } catch (Exception e) { - Assert.fail(e.getMessage()); - } - } - } - - int[] dims = new int[] {1, 5}; - float[] inputData = new float[] {1.0f, 2.0f, -3.0f, Float.MIN_VALUE, Float.MAX_VALUE}; - - // test run() - { - JavaOnlyMap inputDataMap = new JavaOnlyMap(); - { - JavaOnlyMap inputTensorMap = new JavaOnlyMap(); - - JavaOnlyArray dimsArray = new JavaOnlyArray(); - for (int dim : dims) { - dimsArray.pushInt(dim); - } - inputTensorMap.putArray("dims", dimsArray); - - inputTensorMap.putString("type", TensorHelper.JsTensorTypeFloat); - - ByteBuffer buffer = ByteBuffer.allocate(5 * Float.BYTES).order(ByteOrder.nativeOrder()); - FloatBuffer floatBuffer = buffer.asFloatBuffer(); - for (float value : inputData) { - floatBuffer.put(value); - } - floatBuffer.rewind(); - inputTensorMap.putMap("data", blobModule.testCreateData(buffer.array())); - - inputDataMap.putMap("input", inputTensorMap); - } - - JavaOnlyArray outputNames = new JavaOnlyArray(); - outputNames.pushString("output"); - - JavaOnlyMap options = new JavaOnlyMap(); - options.putBoolean("encodeTensorData", true); - - try { - ReadableMap resultMap = ortModule.run(sessionKey, inputDataMap, outputNames, options); - - ReadableMap outputMap = resultMap.getMap("output"); - for (int i = 0; i < 2; ++i) { - Assert.assertEquals(outputMap.getArray("dims").getInt(i), dims[i]); - } - Assert.assertEquals(outputMap.getString("type"), TensorHelper.JsTensorTypeFloat); - ReadableMap data = outputMap.getMap("data"); - FloatBuffer buffer = - ByteBuffer.wrap(blobModule.testGetData(data)).order(ByteOrder.nativeOrder()).asFloatBuffer(); - for (int i = 0; i < 5; ++i) { - Assert.assertEquals(buffer.get(i), inputData[i], 1e-6f); - } - } catch (Exception e) { - Assert.fail(e.getMessage()); - } - } - - // test dispose - ortModule.dispose(sessionKey); - } finally { - mockSession.finishMocking(); - } - } - - @Test - public void onnxruntime_module_append_nnapi() throws Exception { - MockitoSession mockSession = mockitoSession().mockStatic(Arguments.class).startMocking(); - try { - when(Arguments.createMap()).thenAnswer(i -> new JavaOnlyMap()); - when(Arguments.createArray()).thenAnswer(i -> new JavaOnlyArray()); - - OnnxruntimeModule ortModule = new OnnxruntimeModule(reactContext); - ortModule.blobModule = blobModule; - String sessionKey = ""; - - // test loadModel() with nnapi ep options - - try (InputStream modelStream = - reactContext.getResources().openRawResource(ai.onnxruntime.reactnative.test.R.raw.test_types_float);) { - - byte[] modelBuffer = getInputModelBuffer(modelStream); - - // register with nnapi ep options - JavaOnlyMap options = new JavaOnlyMap(); - JavaOnlyArray epArray = new JavaOnlyArray(); - epArray.pushString("nnapi"); - options.putArray("executionProviders", epArray); - - try { - ReadableMap resultMap = ortModule.loadModel(modelBuffer, options); - sessionKey = resultMap.getString("key"); - ReadableArray inputNames = resultMap.getArray("inputNames"); - ReadableArray outputNames = resultMap.getArray("outputNames"); - - Assert.assertEquals(inputNames.size(), 1); - Assert.assertEquals(inputNames.getString(0), "input"); - Assert.assertEquals(outputNames.size(), 1); - Assert.assertEquals(outputNames.getString(0), "output"); - } catch (Exception e) { - Assert.fail(e.getMessage()); - } - } - ortModule.dispose(sessionKey); - } finally { - mockSession.finishMocking(); - } - } -} diff --git a/js/react_native/android/src/androidTest/java/ai/onnxruntime/reactnative/TensorHelperTest.java b/js/react_native/android/src/androidTest/java/ai/onnxruntime/reactnative/TensorHelperTest.java deleted file mode 100644 index 72518488e6682..0000000000000 --- a/js/react_native/android/src/androidTest/java/ai/onnxruntime/reactnative/TensorHelperTest.java +++ /dev/null @@ -1,565 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package ai.onnxruntime.reactnative; - -import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; -import static org.mockito.Mockito.when; - -import ai.onnxruntime.OnnxJavaType; -import ai.onnxruntime.OnnxTensor; -import ai.onnxruntime.OnnxValue; -import ai.onnxruntime.OrtEnvironment; -import ai.onnxruntime.OrtSession; -import ai.onnxruntime.OrtUtil; -import ai.onnxruntime.TensorInfo; -import android.content.Context; -import android.util.Base64; -import androidx.test.filters.SmallTest; -import androidx.test.platform.app.InstrumentationRegistry; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.JavaOnlyArray; -import com.facebook.react.bridge.JavaOnlyMap; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.modules.blob.BlobModule; -import java.io.ByteArrayOutputStream; -import java.io.InputStream; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.DoubleBuffer; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.nio.LongBuffer; -import java.nio.ShortBuffer; -import java.util.HashMap; -import java.util.Map; -import org.junit.Assert; -import org.junit.Before; -import org.junit.Test; -import org.mockito.MockitoSession; - -@SmallTest -public class TensorHelperTest { - private ReactApplicationContext reactContext = - new ReactApplicationContext(InstrumentationRegistry.getInstrumentation().getContext()); - - private OrtEnvironment ortEnvironment; - - private FakeBlobModule blobModule; - - @Before - public void setUp() { - ortEnvironment = OrtEnvironment.getEnvironment("TensorHelperTest"); - blobModule = new FakeBlobModule(reactContext); - } - - @Test - public void createInputTensor_float32() throws Exception { - OnnxTensor outputTensor = - OnnxTensor.createTensor(ortEnvironment, new float[] {Float.MIN_VALUE, 2.0f, Float.MAX_VALUE}); - - JavaOnlyMap inputTensorMap = new JavaOnlyMap(); - - JavaOnlyArray dims = new JavaOnlyArray(); - dims.pushInt(3); - inputTensorMap.putArray("dims", dims); - - inputTensorMap.putString("type", TensorHelper.JsTensorTypeFloat); - - ByteBuffer dataByteBuffer = ByteBuffer.allocate(3 * 4).order(ByteOrder.nativeOrder()); - FloatBuffer dataFloatBuffer = dataByteBuffer.asFloatBuffer(); - dataFloatBuffer.put(Float.MIN_VALUE); - dataFloatBuffer.put(2.0f); - dataFloatBuffer.put(Float.MAX_VALUE); - inputTensorMap.putMap("data", blobModule.testCreateData(dataByteBuffer.array())); - - OnnxTensor inputTensor = TensorHelper.createInputTensor(blobModule, inputTensorMap, ortEnvironment); - - Assert.assertEquals(inputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT); - Assert.assertEquals(outputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT); - Assert.assertEquals(inputTensor.toString(), outputTensor.toString()); - Assert.assertArrayEquals(inputTensor.getFloatBuffer().array(), outputTensor.getFloatBuffer().array(), 1e-6f); - - inputTensor.close(); - outputTensor.close(); - } - - @Test - public void createInputTensor_int8() throws Exception { - OnnxTensor outputTensor = OnnxTensor.createTensor(ortEnvironment, new byte[] {Byte.MIN_VALUE, 2, Byte.MAX_VALUE}); - - JavaOnlyMap inputTensorMap = new JavaOnlyMap(); - - JavaOnlyArray dims = new JavaOnlyArray(); - dims.pushInt(3); - inputTensorMap.putArray("dims", dims); - - inputTensorMap.putString("type", TensorHelper.JsTensorTypeByte); - - ByteBuffer dataByteBuffer = ByteBuffer.allocate(3); - dataByteBuffer.put(Byte.MIN_VALUE); - dataByteBuffer.put((byte)2); - dataByteBuffer.put(Byte.MAX_VALUE); - inputTensorMap.putMap("data", blobModule.testCreateData(dataByteBuffer.array())); - - OnnxTensor inputTensor = TensorHelper.createInputTensor(blobModule, inputTensorMap, ortEnvironment); - - Assert.assertEquals(inputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8); - Assert.assertEquals(outputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8); - Assert.assertEquals(inputTensor.toString(), outputTensor.toString()); - Assert.assertArrayEquals(inputTensor.getByteBuffer().array(), outputTensor.getByteBuffer().array()); - - inputTensor.close(); - outputTensor.close(); - } - - @Test - public void createInputTensor_uint8() throws Exception { - OnnxTensor outputTensor = OnnxTensor.createTensor(ortEnvironment, ByteBuffer.wrap(new byte[] {0, 2, (byte)255}), - new long[] {3}, OnnxJavaType.UINT8); - - JavaOnlyMap inputTensorMap = new JavaOnlyMap(); - - JavaOnlyArray dims = new JavaOnlyArray(); - dims.pushInt(3); - inputTensorMap.putArray("dims", dims); - - inputTensorMap.putString("type", TensorHelper.JsTensorTypeUnsignedByte); - - ByteBuffer dataByteBuffer = ByteBuffer.allocate(3); - dataByteBuffer.put((byte)0); - dataByteBuffer.put((byte)2); - dataByteBuffer.put((byte)255); - inputTensorMap.putMap("data", blobModule.testCreateData(dataByteBuffer.array())); - - OnnxTensor inputTensor = TensorHelper.createInputTensor(blobModule, inputTensorMap, ortEnvironment); - - Assert.assertEquals(inputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8); - Assert.assertEquals(outputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8); - Assert.assertEquals(inputTensor.toString(), outputTensor.toString()); - Assert.assertArrayEquals(inputTensor.getByteBuffer().array(), outputTensor.getByteBuffer().array()); - - inputTensor.close(); - outputTensor.close(); - } - - @Test - public void createInputTensor_int32() throws Exception { - OnnxTensor outputTensor = - OnnxTensor.createTensor(ortEnvironment, new int[] {Integer.MIN_VALUE, 2, Integer.MAX_VALUE}); - - JavaOnlyMap inputTensorMap = new JavaOnlyMap(); - - JavaOnlyArray dims = new JavaOnlyArray(); - dims.pushInt(3); - inputTensorMap.putArray("dims", dims); - - inputTensorMap.putString("type", TensorHelper.JsTensorTypeInt); - - ByteBuffer dataByteBuffer = ByteBuffer.allocate(3 * 4).order(ByteOrder.nativeOrder()); - IntBuffer dataIntBuffer = dataByteBuffer.asIntBuffer(); - dataIntBuffer.put(Integer.MIN_VALUE); - dataIntBuffer.put(2); - dataIntBuffer.put(Integer.MAX_VALUE); - inputTensorMap.putMap("data", blobModule.testCreateData(dataByteBuffer.array())); - - OnnxTensor inputTensor = TensorHelper.createInputTensor(blobModule, inputTensorMap, ortEnvironment); - - Assert.assertEquals(inputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32); - Assert.assertEquals(outputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32); - Assert.assertEquals(inputTensor.toString(), outputTensor.toString()); - Assert.assertArrayEquals(inputTensor.getIntBuffer().array(), outputTensor.getIntBuffer().array()); - - inputTensor.close(); - outputTensor.close(); - } - - @Test - public void createInputTensor_int64() throws Exception { - OnnxTensor outputTensor = - OnnxTensor.createTensor(ortEnvironment, new long[] {Long.MIN_VALUE, 15000000001L, Long.MAX_VALUE}); - - JavaOnlyMap inputTensorMap = new JavaOnlyMap(); - - JavaOnlyArray dims = new JavaOnlyArray(); - dims.pushInt(3); - inputTensorMap.putArray("dims", dims); - - inputTensorMap.putString("type", TensorHelper.JsTensorTypeLong); - - ByteBuffer dataByteBuffer = ByteBuffer.allocate(3 * 8).order(ByteOrder.nativeOrder()); - LongBuffer dataLongBuffer = dataByteBuffer.asLongBuffer(); - dataLongBuffer.put(Long.MIN_VALUE); - dataLongBuffer.put(15000000001L); - dataLongBuffer.put(Long.MAX_VALUE); - inputTensorMap.putMap("data", blobModule.testCreateData(dataByteBuffer.array())); - - OnnxTensor inputTensor = TensorHelper.createInputTensor(blobModule, inputTensorMap, ortEnvironment); - - Assert.assertEquals(inputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64); - Assert.assertEquals(outputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64); - Assert.assertEquals(inputTensor.toString(), outputTensor.toString()); - Assert.assertArrayEquals(inputTensor.getLongBuffer().array(), outputTensor.getLongBuffer().array()); - - inputTensor.close(); - outputTensor.close(); - } - - @Test - public void createInputTensor_double() throws Exception { - OnnxTensor outputTensor = - OnnxTensor.createTensor(ortEnvironment, new double[] {Double.MIN_VALUE, 1.8e+30, Double.MAX_VALUE}); - - JavaOnlyMap inputTensorMap = new JavaOnlyMap(); - - JavaOnlyArray dims = new JavaOnlyArray(); - dims.pushInt(3); - inputTensorMap.putArray("dims", dims); - - inputTensorMap.putString("type", TensorHelper.JsTensorTypeDouble); - - ByteBuffer dataByteBuffer = ByteBuffer.allocate(3 * 8).order(ByteOrder.nativeOrder()); - DoubleBuffer dataDoubleBuffer = dataByteBuffer.asDoubleBuffer(); - dataDoubleBuffer.put(Double.MIN_VALUE); - dataDoubleBuffer.put(1.8e+30); - dataDoubleBuffer.put(Double.MAX_VALUE); - inputTensorMap.putMap("data", blobModule.testCreateData(dataByteBuffer.array())); - - OnnxTensor inputTensor = TensorHelper.createInputTensor(blobModule, inputTensorMap, ortEnvironment); - - Assert.assertEquals(inputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE); - Assert.assertEquals(outputTensor.getInfo().onnxType, - TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE); - Assert.assertEquals(inputTensor.toString(), outputTensor.toString()); - Assert.assertArrayEquals(inputTensor.getDoubleBuffer().array(), outputTensor.getDoubleBuffer().array(), 1e-6f); - - inputTensor.close(); - outputTensor.close(); - } - - @Test - public void createInputTensor_bool() throws Exception { - OnnxTensor outputTensor = OnnxTensor.createTensor(ortEnvironment, new boolean[] {false, true}); - - JavaOnlyMap inputTensorMap = new JavaOnlyMap(); - - JavaOnlyArray dims = new JavaOnlyArray(); - dims.pushInt(2); - inputTensorMap.putArray("dims", dims); - - inputTensorMap.putString("type", TensorHelper.JsTensorTypeBool); - - ByteBuffer dataByteBuffer = ByteBuffer.allocate(2); - dataByteBuffer.put((byte)0); - dataByteBuffer.put((byte)1); - inputTensorMap.putMap("data", blobModule.testCreateData(dataByteBuffer.array())); - - OnnxTensor inputTensor = TensorHelper.createInputTensor(blobModule, inputTensorMap, ortEnvironment); - - Assert.assertEquals(inputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL); - Assert.assertEquals(outputTensor.getInfo().onnxType, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL); - Assert.assertEquals(inputTensor.toString(), outputTensor.toString()); - Assert.assertArrayEquals(inputTensor.getByteBuffer().array(), outputTensor.getByteBuffer().array()); - - inputTensor.close(); - outputTensor.close(); - } - - @Test - public void createOutputTensor_bool() throws Exception { - MockitoSession mockSession = mockitoSession().mockStatic(Arguments.class).startMocking(); - try { - when(Arguments.createMap()).thenAnswer(i -> new JavaOnlyMap()); - when(Arguments.createArray()).thenAnswer(i -> new JavaOnlyArray()); - - OrtSession.SessionOptions options = new OrtSession.SessionOptions(); - byte[] modelData = readBytesFromResourceFile(ai.onnxruntime.reactnative.test.R.raw.test_types_bool); - OrtSession session = ortEnvironment.createSession(modelData, options); - - long[] dims = new long[] {1, 5}; - boolean[] inputData = new boolean[] {true, false, false, true, false}; - - String inputName = session.getInputNames().iterator().next(); - Map container = new HashMap<>(); - Object tensorInput = OrtUtil.reshape(inputData, dims); - OnnxTensor onnxTensor = OnnxTensor.createTensor(ortEnvironment, tensorInput); - container.put(inputName, onnxTensor); - - OrtSession.Result result = session.run(container); - - ReadableMap resultMap = TensorHelper.createOutputTensor(blobModule, result); - ReadableMap outputMap = resultMap.getMap("output"); - for (int i = 0; i < 2; ++i) { - Assert.assertEquals(outputMap.getArray("dims").getInt(i), dims[i]); - } - Assert.assertEquals(outputMap.getString("type"), TensorHelper.JsTensorTypeBool); - ReadableMap data = outputMap.getMap("data"); - ByteBuffer buffer = ByteBuffer.wrap(blobModule.testGetData(data)); - for (int i = 0; i < 5; ++i) { - Assert.assertEquals(buffer.get(i) == 1, inputData[i]); - } - - OnnxValue.close(container); - } finally { - mockSession.finishMocking(); - } - } - - @Test - public void createOutputTensor_double() throws Exception { - MockitoSession mockSession = mockitoSession().mockStatic(Arguments.class).startMocking(); - try { - when(Arguments.createMap()).thenAnswer(i -> new JavaOnlyMap()); - when(Arguments.createArray()).thenAnswer(i -> new JavaOnlyArray()); - - OrtSession.SessionOptions options = new OrtSession.SessionOptions(); - byte[] modelData = readBytesFromResourceFile(ai.onnxruntime.reactnative.test.R.raw.test_types_double); - OrtSession session = ortEnvironment.createSession(modelData, options); - - long[] dims = new long[] {1, 5}; - double[] inputData = new double[] {1.0f, 2.0f, -3.0f, Double.MIN_VALUE, Double.MAX_VALUE}; - - String inputName = session.getInputNames().iterator().next(); - Map container = new HashMap<>(); - Object tensorInput = OrtUtil.reshape(inputData, dims); - OnnxTensor onnxTensor = OnnxTensor.createTensor(ortEnvironment, tensorInput); - container.put(inputName, onnxTensor); - - OrtSession.Result result = session.run(container); - - ReadableMap resultMap = TensorHelper.createOutputTensor(blobModule, result); - ReadableMap outputMap = resultMap.getMap("output"); - for (int i = 0; i < 2; ++i) { - Assert.assertEquals(outputMap.getArray("dims").getInt(i), dims[i]); - } - Assert.assertEquals(outputMap.getString("type"), TensorHelper.JsTensorTypeDouble); - ReadableMap data = outputMap.getMap("data"); - DoubleBuffer buffer = - ByteBuffer.wrap(blobModule.testGetData(data)).order(ByteOrder.nativeOrder()).asDoubleBuffer(); - for (int i = 0; i < 5; ++i) { - Assert.assertEquals(buffer.get(i), inputData[i], 1e-6f); - } - - OnnxValue.close(container); - } finally { - mockSession.finishMocking(); - } - } - - @Test - public void createOutputTensor_float() throws Exception { - MockitoSession mockSession = mockitoSession().mockStatic(Arguments.class).startMocking(); - try { - when(Arguments.createMap()).thenAnswer(i -> new JavaOnlyMap()); - when(Arguments.createArray()).thenAnswer(i -> new JavaOnlyArray()); - - OrtSession.SessionOptions options = new OrtSession.SessionOptions(); - byte[] modelData = readBytesFromResourceFile(ai.onnxruntime.reactnative.test.R.raw.test_types_float); - OrtSession session = ortEnvironment.createSession(modelData, options); - - long[] dims = new long[] {1, 5}; - float[] inputData = new float[] {1.0f, 2.0f, -3.0f, Float.MIN_VALUE, Float.MAX_VALUE}; - - String inputName = session.getInputNames().iterator().next(); - Map container = new HashMap<>(); - Object tensorInput = OrtUtil.reshape(inputData, dims); - OnnxTensor onnxTensor = OnnxTensor.createTensor(ortEnvironment, tensorInput); - container.put(inputName, onnxTensor); - - OrtSession.Result result = session.run(container); - - ReadableMap resultMap = TensorHelper.createOutputTensor(blobModule, result); - ReadableMap outputMap = resultMap.getMap("output"); - for (int i = 0; i < 2; ++i) { - Assert.assertEquals(outputMap.getArray("dims").getInt(i), dims[i]); - } - Assert.assertEquals(outputMap.getString("type"), TensorHelper.JsTensorTypeFloat); - ReadableMap data = outputMap.getMap("data"); - FloatBuffer buffer = ByteBuffer.wrap(blobModule.testGetData(data)).order(ByteOrder.nativeOrder()).asFloatBuffer(); - for (int i = 0; i < 5; ++i) { - Assert.assertEquals(buffer.get(i), inputData[i], 1e-6f); - } - - OnnxValue.close(container); - } finally { - mockSession.finishMocking(); - } - } - - @Test - public void createOutputTensor_int8() throws Exception { - MockitoSession mockSession = mockitoSession().mockStatic(Arguments.class).startMocking(); - try { - when(Arguments.createMap()).thenAnswer(i -> new JavaOnlyMap()); - when(Arguments.createArray()).thenAnswer(i -> new JavaOnlyArray()); - - OrtSession.SessionOptions options = new OrtSession.SessionOptions(); - byte[] modelData = readBytesFromResourceFile(ai.onnxruntime.reactnative.test.R.raw.test_types_int8); - OrtSession session = ortEnvironment.createSession(modelData, options); - - long[] dims = new long[] {1, 5}; - byte[] inputData = new byte[] {1, 2, -3, Byte.MAX_VALUE, Byte.MAX_VALUE}; - - String inputName = session.getInputNames().iterator().next(); - Map container = new HashMap<>(); - Object tensorInput = OrtUtil.reshape(inputData, dims); - OnnxTensor onnxTensor = OnnxTensor.createTensor(ortEnvironment, tensorInput); - container.put(inputName, onnxTensor); - - OrtSession.Result result = session.run(container); - - ReadableMap resultMap = TensorHelper.createOutputTensor(blobModule, result); - ReadableMap outputMap = resultMap.getMap("output"); - for (int i = 0; i < 2; ++i) { - Assert.assertEquals(outputMap.getArray("dims").getInt(i), dims[i]); - } - Assert.assertEquals(outputMap.getString("type"), TensorHelper.JsTensorTypeByte); - ReadableMap data = outputMap.getMap("data"); - ByteBuffer buffer = ByteBuffer.wrap(blobModule.testGetData(data)); - for (int i = 0; i < 5; ++i) { - Assert.assertEquals(buffer.get(i), inputData[i]); - } - - OnnxValue.close(container); - } finally { - mockSession.finishMocking(); - } - } - - @Test - public void createOutputTensor_int32() throws Exception { - MockitoSession mockSession = mockitoSession().mockStatic(Arguments.class).startMocking(); - try { - when(Arguments.createMap()).thenAnswer(i -> new JavaOnlyMap()); - when(Arguments.createArray()).thenAnswer(i -> new JavaOnlyArray()); - - OrtSession.SessionOptions options = new OrtSession.SessionOptions(); - byte[] modelData = readBytesFromResourceFile(ai.onnxruntime.reactnative.test.R.raw.test_types_int32); - OrtSession session = ortEnvironment.createSession(modelData, options); - - long[] dims = new long[] {1, 5}; - int[] inputData = new int[] {1, 2, -3, Integer.MIN_VALUE, Integer.MAX_VALUE}; - - String inputName = session.getInputNames().iterator().next(); - Map container = new HashMap<>(); - Object tensorInput = OrtUtil.reshape(inputData, dims); - OnnxTensor onnxTensor = OnnxTensor.createTensor(ortEnvironment, tensorInput); - container.put(inputName, onnxTensor); - - OrtSession.Result result = session.run(container); - - ReadableMap resultMap = TensorHelper.createOutputTensor(blobModule, result); - ReadableMap outputMap = resultMap.getMap("output"); - for (int i = 0; i < 2; ++i) { - Assert.assertEquals(outputMap.getArray("dims").getInt(i), dims[i]); - } - Assert.assertEquals(outputMap.getString("type"), TensorHelper.JsTensorTypeInt); - ReadableMap data = outputMap.getMap("data"); - IntBuffer buffer = ByteBuffer.wrap(blobModule.testGetData(data)).order(ByteOrder.nativeOrder()).asIntBuffer(); - for (int i = 0; i < 5; ++i) { - Assert.assertEquals(buffer.get(i), inputData[i]); - } - - OnnxValue.close(container); - } finally { - mockSession.finishMocking(); - } - } - - @Test - public void createOutputTensor_int64() throws Exception { - MockitoSession mockSession = mockitoSession().mockStatic(Arguments.class).startMocking(); - try { - when(Arguments.createMap()).thenAnswer(i -> new JavaOnlyMap()); - when(Arguments.createArray()).thenAnswer(i -> new JavaOnlyArray()); - - OrtSession.SessionOptions options = new OrtSession.SessionOptions(); - byte[] modelData = readBytesFromResourceFile(ai.onnxruntime.reactnative.test.R.raw.test_types_int64); - OrtSession session = ortEnvironment.createSession(modelData, options); - - long[] dims = new long[] {1, 5}; - long[] inputData = new long[] {1, 2, -3, Long.MIN_VALUE, Long.MAX_VALUE}; - - String inputName = session.getInputNames().iterator().next(); - Map container = new HashMap<>(); - Object tensorInput = OrtUtil.reshape(inputData, dims); - OnnxTensor onnxTensor = OnnxTensor.createTensor(ortEnvironment, tensorInput); - container.put(inputName, onnxTensor); - - OrtSession.Result result = session.run(container); - - ReadableMap resultMap = TensorHelper.createOutputTensor(blobModule, result); - ReadableMap outputMap = resultMap.getMap("output"); - for (int i = 0; i < 2; ++i) { - Assert.assertEquals(outputMap.getArray("dims").getInt(i), dims[i]); - } - Assert.assertEquals(outputMap.getString("type"), TensorHelper.JsTensorTypeLong); - ReadableMap data = outputMap.getMap("data"); - LongBuffer buffer = ByteBuffer.wrap(blobModule.testGetData(data)).order(ByteOrder.nativeOrder()).asLongBuffer(); - for (int i = 0; i < 5; ++i) { - Assert.assertEquals(buffer.get(i), inputData[i]); - } - - OnnxValue.close(container); - } finally { - mockSession.finishMocking(); - } - } - - @Test - public void createOutputTensor_uint8() throws Exception { - MockitoSession mockSession = mockitoSession().mockStatic(Arguments.class).startMocking(); - try { - when(Arguments.createMap()).thenAnswer(i -> new JavaOnlyMap()); - when(Arguments.createArray()).thenAnswer(i -> new JavaOnlyArray()); - - OrtSession.SessionOptions options = new OrtSession.SessionOptions(); - byte[] modelData = readBytesFromResourceFile(ai.onnxruntime.reactnative.test.R.raw.test_types_uint8); - OrtSession session = ortEnvironment.createSession(modelData, options); - - long[] dims = new long[] {1, 5}; - byte[] inputData = new byte[] {1, 2, -3, Byte.MAX_VALUE, Byte.MAX_VALUE}; - - String inputName = session.getInputNames().iterator().next(); - Map container = new HashMap<>(); - ByteBuffer inputBuffer = ByteBuffer.wrap(inputData); - OnnxTensor onnxTensor = OnnxTensor.createTensor(ortEnvironment, inputBuffer, dims, OnnxJavaType.UINT8); - container.put(inputName, onnxTensor); - - OrtSession.Result result = session.run(container); - - ReadableMap resultMap = TensorHelper.createOutputTensor(blobModule, result); - ReadableMap outputMap = resultMap.getMap("output"); - for (int i = 0; i < 2; ++i) { - Assert.assertEquals(outputMap.getArray("dims").getInt(i), dims[i]); - } - Assert.assertEquals(outputMap.getString("type"), TensorHelper.JsTensorTypeUnsignedByte); - ReadableMap data = outputMap.getMap("data"); - ByteBuffer buffer = ByteBuffer.wrap(blobModule.testGetData(data)); - for (int i = 0; i < 5; ++i) { - Assert.assertEquals(buffer.get(i), inputData[i]); - } - - OnnxValue.close(container); - } finally { - mockSession.finishMocking(); - } - } - - private byte[] readBytesFromResourceFile(int resourceId) throws Exception { - Context context = InstrumentationRegistry.getInstrumentation().getContext(); - InputStream inputStream = context.getResources().openRawResource(resourceId); - ByteArrayOutputStream byteBuffer = new ByteArrayOutputStream(); - - int bufferSize = 1024; - byte[] buffer = new byte[bufferSize]; - - int len; - while ((len = inputStream.read(buffer)) != -1) { - byteBuffer.write(buffer, 0, len); - } - - return byteBuffer.toByteArray(); - } -} diff --git a/js/react_native/android/src/androidTest/res/raw/test_types_float.ort b/js/react_native/android/src/androidTest/res/raw/test_types_float.ort deleted file mode 100644 index e5c40742843d5..0000000000000 Binary files a/js/react_native/android/src/androidTest/res/raw/test_types_float.ort and /dev/null differ diff --git a/js/react_native/android/src/androidTest/res/raw/test_types_int32.ort b/js/react_native/android/src/androidTest/res/raw/test_types_int32.ort deleted file mode 100644 index 6135c9a4aca7c..0000000000000 Binary files a/js/react_native/android/src/androidTest/res/raw/test_types_int32.ort and /dev/null differ diff --git a/js/react_native/android/src/androidTest/res/raw/test_types_int64.ort b/js/react_native/android/src/androidTest/res/raw/test_types_int64.ort deleted file mode 100644 index a9892d9ec598d..0000000000000 Binary files a/js/react_native/android/src/androidTest/res/raw/test_types_int64.ort and /dev/null differ diff --git a/js/react_native/android/src/androidTest/res/raw/test_types_int8.ort b/js/react_native/android/src/androidTest/res/raw/test_types_int8.ort deleted file mode 100644 index f1bf199e488e1..0000000000000 Binary files a/js/react_native/android/src/androidTest/res/raw/test_types_int8.ort and /dev/null differ diff --git a/js/react_native/android/src/androidTest/res/raw/test_types_uint8.ort b/js/react_native/android/src/androidTest/res/raw/test_types_uint8.ort deleted file mode 100644 index 9f5310803323a..0000000000000 Binary files a/js/react_native/android/src/androidTest/res/raw/test_types_uint8.ort and /dev/null differ diff --git a/js/react_native/android/src/main/AndroidManifest.xml b/js/react_native/android/src/main/AndroidManifest.xml index c6e3cb45e16e5..8713bb2c6b8cd 100644 --- a/js/react_native/android/src/main/AndroidManifest.xml +++ b/js/react_native/android/src/main/AndroidManifest.xml @@ -1,3 +1,3 @@ + package="ai.onnxruntime.reactnative"> diff --git a/js/react_native/android/src/main/cpp/cpp-adapter.cpp b/js/react_native/android/src/main/cpp/cpp-adapter.cpp index d75a2f9c99d8b..50434b71ec2ed 100644 --- a/js/react_native/android/src/main/cpp/cpp-adapter.cpp +++ b/js/react_native/android/src/main/cpp/cpp-adapter.cpp @@ -1,126 +1,43 @@ +#include "JsiMain.h" +#include +#include +#include +#include #include #include -#include using namespace facebook; -typedef u_int8_t byte; - -std::string jstring2string(JNIEnv* env, jstring jStr) { - if (!jStr) return ""; - - jclass stringClass = env->GetObjectClass(jStr); - jmethodID getBytes = env->GetMethodID(stringClass, "getBytes", "(Ljava/lang/String;)[B"); - const auto stringJbytes = (jbyteArray)env->CallObjectMethod(jStr, getBytes, env->NewStringUTF("UTF-8")); - - auto length = (size_t)env->GetArrayLength(stringJbytes); - jbyte* pBytes = env->GetByteArrayElements(stringJbytes, nullptr); - - std::string ret = std::string((char*)pBytes, length); - env->ReleaseByteArrayElements(stringJbytes, pBytes, JNI_ABORT); - - env->DeleteLocalRef(stringJbytes); - env->DeleteLocalRef(stringClass); - return ret; -} - -byte* getBytesFromBlob(JNIEnv* env, jobject instanceGlobal, const std::string& blobId, int offset, int size) { - if (!env) throw std::runtime_error("JNI Environment is gone!"); - - // get java class - jclass clazz = env->GetObjectClass(instanceGlobal); - // get method in java class - jmethodID getBufferJava = env->GetMethodID(clazz, "getBlobBuffer", "(Ljava/lang/String;II)[B"); - // call method - auto jstring = env->NewStringUTF(blobId.c_str()); - auto boxedBytes = (jbyteArray)env->CallObjectMethod(instanceGlobal, - getBufferJava, - // arguments - jstring, - offset, - size); - env->DeleteLocalRef(jstring); - - jboolean isCopy = true; - jbyte* bytes = env->GetByteArrayElements(boxedBytes, &isCopy); - env->DeleteLocalRef(boxedBytes); - return reinterpret_cast(bytes); -}; - -std::string createBlob(JNIEnv* env, jobject instanceGlobal, byte* bytes, size_t size) { - if (!env) throw std::runtime_error("JNI Environment is gone!"); - - // get java class - jclass clazz = env->GetObjectClass(instanceGlobal); - // get method in java class - jmethodID getBufferJava = env->GetMethodID(clazz, "createBlob", "([B)Ljava/lang/String;"); - // call method - auto byteArray = env->NewByteArray(size); - env->SetByteArrayRegion(byteArray, 0, size, reinterpret_cast(bytes)); - auto blobId = (jstring)env->CallObjectMethod(instanceGlobal, getBufferJava, byteArray); - env->DeleteLocalRef(byteArray); - - return jstring2string(env, blobId); +static std::shared_ptr env; + +class OnnxruntimeModule + : public jni::JavaClass { + public: + static constexpr auto kJavaDescriptor = + "Lai/onnxruntime/reactnative/OnnxruntimeModule;"; + + static void registerNatives() { + javaClassStatic()->registerNatives( + {makeNativeMethod("nativeInstall", + OnnxruntimeModule::nativeInstall), + makeNativeMethod("nativeCleanup", + OnnxruntimeModule::nativeCleanup)}); + } + + private: + static void nativeInstall(jni::alias_ref thiz, + jlong jsContextNativePointer, + jni::alias_ref + jsCallInvokerHolder) { + auto runtime = reinterpret_cast(jsContextNativePointer); + auto jsCallInvoker = jsCallInvokerHolder->cthis()->getCallInvoker(); + env = onnxruntimejsi::install(*runtime, jsCallInvoker); + } + + static void nativeCleanup(jni::alias_ref thiz) { env.reset(); } }; -extern "C" JNIEXPORT void JNICALL -Java_ai_onnxruntime_reactnative_OnnxruntimeJSIHelper_nativeInstall(JNIEnv* env, jclass _, jlong jsiPtr, jobject instance) { - auto jsiRuntime = reinterpret_cast(jsiPtr); - - auto& runtime = *jsiRuntime; - - auto instanceGlobal = env->NewGlobalRef(instance); - - auto resolveArrayBuffer = jsi::Function::createFromHostFunction(runtime, - jsi::PropNameID::forAscii(runtime, "jsiOnnxruntimeResolveArrayBuffer"), - 1, - [=](jsi::Runtime& runtime, - const jsi::Value& thisValue, - const jsi::Value* arguments, - size_t count) -> jsi::Value { - if (count != 1) { - throw jsi::JSError(runtime, "jsiOnnxruntimeResolveArrayBuffer(..) expects one argument (object)!"); - } - - jsi::Object data = arguments[0].asObject(runtime); - auto blobId = data.getProperty(runtime, "blobId").asString(runtime); - auto offset = data.getProperty(runtime, "offset").asNumber(); - auto size = data.getProperty(runtime, "size").asNumber(); - - auto bytes = getBytesFromBlob(env, instanceGlobal, blobId.utf8(runtime), offset, size); - - size_t totalSize = size - offset; - jsi::Function arrayBufferCtor = runtime.global().getPropertyAsFunction(runtime, "ArrayBuffer"); - jsi::Object o = arrayBufferCtor.callAsConstructor(runtime, (int)totalSize).getObject(runtime); - jsi::ArrayBuffer buf = o.getArrayBuffer(runtime); - memcpy(buf.data(runtime), reinterpret_cast(bytes), totalSize); - - return buf; - }); - runtime.global().setProperty(runtime, "jsiOnnxruntimeResolveArrayBuffer", std::move(resolveArrayBuffer)); - - auto storeArrayBuffer = jsi::Function::createFromHostFunction(runtime, - jsi::PropNameID::forAscii(runtime, "jsiOnnxruntimeStoreArrayBuffer"), - 1, - [=](jsi::Runtime& runtime, - const jsi::Value& thisValue, - const jsi::Value* arguments, - size_t count) -> jsi::Value { - if (count != 1) { - throw jsi::JSError(runtime, "jsiOnnxruntimeStoreArrayBuffer(..) expects one argument (object)!"); - } - - auto arrayBuffer = arguments[0].asObject(runtime).getArrayBuffer(runtime); - auto size = arrayBuffer.size(runtime); - - std::string blobId = createBlob(env, instanceGlobal, arrayBuffer.data(runtime), size); - - jsi::Object result(runtime); - auto blobIdString = jsi::String::createFromUtf8(runtime, blobId); - result.setProperty(runtime, "blobId", blobIdString); - result.setProperty(runtime, "offset", jsi::Value(0)); - result.setProperty(runtime, "size", jsi::Value(static_cast(size))); - return result; - }); - runtime.global().setProperty(runtime, "jsiOnnxruntimeStoreArrayBuffer", std::move(storeArrayBuffer)); +JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void*) { + return jni::initialize( + vm, [] { OnnxruntimeModule::registerNatives(); }); } diff --git a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeExtensionsDisabled.java b/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeExtensionsDisabled.java index de4c880981881..cacc382e29230 100644 --- a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeExtensionsDisabled.java +++ b/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeExtensionsDisabled.java @@ -3,14 +3,13 @@ package ai.onnxruntime.reactnative; -import ai.onnxruntime.OrtSession.SessionOptions; import android.util.Log; class OnnxruntimeExtensions { - public void registerOrtExtensionsIfEnabled(SessionOptions sessionOptions) { + static public String getLibraryPath() { Log.i("OnnxruntimeExtensions", "ORT Extensions is not enabled in the current configuration. If you want to enable this support, " + "please add \"onnxruntimeEnableExtensions\": \"true\" in your project root directory package.json."); - return; + return null; } } diff --git a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeExtensionsEnabled.java b/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeExtensionsEnabled.java index 9bbf41c8f1671..d41163fdb53e9 100644 --- a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeExtensionsEnabled.java +++ b/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeExtensionsEnabled.java @@ -3,12 +3,10 @@ package ai.onnxruntime.reactnative; -import ai.onnxruntime.OrtException; -import ai.onnxruntime.OrtSession.SessionOptions; import ai.onnxruntime.extensions.OrtxPackage; class OnnxruntimeExtensions { - public void registerOrtExtensionsIfEnabled(SessionOptions sessionOptions) throws OrtException { - sessionOptions.registerCustomOpLibrary(OrtxPackage.getLibraryPath()); + static public String getLibraryPath() { + return OrtxPackage.getLibraryPath(); } } diff --git a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeJSIHelper.java b/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeJSIHelper.java deleted file mode 100644 index 93b37df0768b4..0000000000000 --- a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeJSIHelper.java +++ /dev/null @@ -1,70 +0,0 @@ -package ai.onnxruntime.reactnative; - -import androidx.annotation.NonNull; -import com.facebook.react.bridge.JavaScriptContextHolder; -import com.facebook.react.bridge.ReactApplicationContext; -import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.module.annotations.ReactModule; -import com.facebook.react.modules.blob.BlobModule; - -@ReactModule(name = OnnxruntimeJSIHelper.NAME) -public class OnnxruntimeJSIHelper extends ReactContextBaseJavaModule { - public static final String NAME = "OnnxruntimeJSIHelper"; - - private static ReactApplicationContext reactContext; - protected BlobModule blobModule; - - public OnnxruntimeJSIHelper(ReactApplicationContext context) { - super(context); - reactContext = context; - } - - @Override - @NonNull - public String getName() { - return NAME; - } - - public void checkBlobModule() { - if (blobModule == null) { - blobModule = getReactApplicationContext().getNativeModule(BlobModule.class); - if (blobModule == null) { - throw new RuntimeException("BlobModule is not initialized"); - } - } - } - - @ReactMethod(isBlockingSynchronousMethod = true) - public boolean install() { - try { - System.loadLibrary("onnxruntimejsihelper"); - JavaScriptContextHolder jsContext = getReactApplicationContext().getJavaScriptContextHolder(); - nativeInstall(jsContext.get(), this); - return true; - } catch (Exception exception) { - return false; - } - } - - public byte[] getBlobBuffer(String blobId, int offset, int size) { - checkBlobModule(); - byte[] bytes = blobModule.resolve(blobId, offset, size); - blobModule.remove(blobId); - if (bytes == null) { - throw new RuntimeException("Failed to resolve Blob #" + blobId + "! Not found."); - } - return bytes; - } - - public String createBlob(byte[] buffer) { - checkBlobModule(); - String blobId = blobModule.store(buffer); - if (blobId == null) { - throw new RuntimeException("Failed to create Blob!"); - } - return blobId; - } - - public static native void nativeInstall(long jsiPointer, OnnxruntimeJSIHelper instance); -} diff --git a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeModule.java b/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeModule.java index 1be8c22b40da8..c362e6ad71bbe 100644 --- a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeModule.java +++ b/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimeModule.java @@ -3,65 +3,21 @@ package ai.onnxruntime.reactnative; -import ai.onnxruntime.OnnxTensor; -import ai.onnxruntime.OnnxValue; -import ai.onnxruntime.OrtEnvironment; -import ai.onnxruntime.OrtException; -import ai.onnxruntime.OrtLoggingLevel; -import ai.onnxruntime.OrtSession; -import ai.onnxruntime.OrtSession.Result; -import ai.onnxruntime.OrtSession.RunOptions; -import ai.onnxruntime.OrtSession.SessionOptions; -import ai.onnxruntime.providers.NNAPIFlags; -import android.net.Uri; +import java.util.Map; +import java.util.HashMap; import android.os.Build; -import android.util.Log; import androidx.annotation.NonNull; import androidx.annotation.RequiresApi; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.LifecycleEventListener; -import com.facebook.react.bridge.Promise; +import com.facebook.react.bridge.JavaScriptContextHolder; +import com.facebook.react.bridge.ReactMethod; import com.facebook.react.bridge.ReactApplicationContext; import com.facebook.react.bridge.ReactContextBaseJavaModule; -import com.facebook.react.bridge.ReactMethod; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.ReadableType; -import com.facebook.react.bridge.WritableArray; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.modules.blob.BlobModule; -import java.io.BufferedReader; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.math.BigInteger; -import java.util.Collections; -import java.util.EnumSet; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import com.facebook.react.turbomodule.core.CallInvokerHolderImpl; @RequiresApi(api = Build.VERSION_CODES.N) -public class OnnxruntimeModule extends ReactContextBaseJavaModule implements LifecycleEventListener { +public class OnnxruntimeModule extends ReactContextBaseJavaModule { private static ReactApplicationContext reactContext; - private static OrtEnvironment ortEnvironment = OrtEnvironment.getEnvironment(); - private static Map sessionMap = new HashMap<>(); - - private static BigInteger nextSessionId = new BigInteger("0"); - private static String getNextSessionKey() { - String key = nextSessionId.toString(); - nextSessionId = nextSessionId.add(BigInteger.valueOf(1)); - return key; - } - - protected BlobModule blobModule; - public OnnxruntimeModule(ReactApplicationContext context) { super(context); reactContext = context; @@ -73,392 +29,37 @@ public String getName() { return "Onnxruntime"; } - public void checkBlobModule() { - if (blobModule == null) { - blobModule = getReactApplicationContext().getNativeModule(BlobModule.class); - if (blobModule == null) { - throw new RuntimeException("BlobModule is not initialized"); - } - } - } + native void nativeInstall(long jsiPointer, CallInvokerHolderImpl jsCallInvokerHolder); - /** - * React native binding API to load a model using given uri. - * - * @param uri a model file location - * @param options onnxruntime session options - * @param promise output returning back to react native js - * @note the value provided to `promise` includes a key representing the session. - * when run() is called, the key must be passed into the first parameter. - */ - @ReactMethod - public void loadModel(String uri, ReadableMap options, Promise promise) { - try { - WritableMap resultMap = loadModel(uri, options); - promise.resolve(resultMap); - } catch (Exception e) { - promise.reject("Failed to load model \"" + uri + "\": " + e.getMessage(), e); - } - } + native void nativeCleanup(); - /** - * React native binding API to load a model using blob object that data stored in BlobModule. - * - * @param data the blob object - * @param options onnxruntime session options - * @param promise output returning back to react native js - * @note the value provided to `promise` includes a key representing the session. - * when run() is called, the key must be passed into the first parameter. - */ - @ReactMethod - public void loadModelFromBlob(ReadableMap data, ReadableMap options, Promise promise) { - try { - checkBlobModule(); - String blobId = data.getString("blobId"); - byte[] bytes = blobModule.resolve(blobId, data.getInt("offset"), data.getInt("size")); - blobModule.remove(blobId); - WritableMap resultMap = loadModel(bytes, options); - promise.resolve(resultMap); - } catch (Exception e) { - promise.reject("Failed to load model from buffer: " + e.getMessage(), e); - } - } - - /** - * React native binding API to dispose a session. - * - * @param key session key representing a session given at loadModel() - * @param promise output returning back to react native js - */ - @ReactMethod - public void dispose(String key, Promise promise) { - try { - dispose(key); - promise.resolve(null); - } catch (OrtException e) { - promise.reject("Failed to dispose session: " + e.getMessage(), e); - } + @Override + public void invalidate() { + super.invalidate(); + nativeCleanup(); } /** - * React native binding API to run a model using given uri. - * - * @param key session key representing a session given at loadModel() - * @param input an input tensor - * @param output an output names to be returned - * @param options onnxruntime run options - * @param promise output returning back to react native js + * Install onnxruntime JSI API */ - @ReactMethod - public void run(String key, ReadableMap input, ReadableArray output, ReadableMap options, Promise promise) { + @ReactMethod(isBlockingSynchronousMethod = true) + public boolean install() { try { - WritableMap resultMap = run(key, input, output, options); - promise.resolve(resultMap); + System.loadLibrary("onnxruntimejsi"); + JavaScriptContextHolder jsContext = getReactApplicationContext().getJavaScriptContextHolder(); + CallInvokerHolderImpl jsCallInvokerHolder = + (CallInvokerHolderImpl) getReactApplicationContext().getCatalystInstance().getJSCallInvokerHolder(); + nativeInstall(jsContext.get(), jsCallInvokerHolder); + return true; } catch (Exception e) { - promise.reject("Fail to inference: " + e.getMessage(), e); - } - } - - /** - * Load a model from raw resource directory. - * - * @param uri uri parameter from react native loadModel() - * @param options onnxruntime session options - * @return model loading information, such as key, input names, and output names - */ - public WritableMap loadModel(String uri, ReadableMap options) throws Exception { - return loadModelImpl(uri, null, options); - } - - /** - * Load a model from buffer. - * - * @param modelData the model data buffer - * @param options onnxruntime session options - * @return model loading information, such as key, input names, and output names - */ - public WritableMap loadModel(byte[] modelData, ReadableMap options) throws Exception { - return loadModelImpl("", modelData, options); - } - - /** - * Load model implementation method for either from model path or model data buffer. - * - * @param uri uri parameter from react native loadModel() - * @param modelData model data buffer - * @param options onnxruntime session options - * @return model loading information map, such as key, input names, and output names - */ - private WritableMap loadModelImpl(String uri, byte[] modelData, ReadableMap options) throws Exception { - OrtSession ortSession; - SessionOptions sessionOptions = parseSessionOptions(options); - - // optional call for registering custom ops when ort extensions enabled - OnnxruntimeExtensions ortExt = new OnnxruntimeExtensions(); - ortExt.registerOrtExtensionsIfEnabled(sessionOptions); - - if (modelData != null && modelData.length > 0) { - // load model via model data array - ortSession = ortEnvironment.createSession(modelData, sessionOptions); - } else if (uri.startsWith("file://") || uri.startsWith("/")) { - // load model from local - if (uri.startsWith("file://")) { - uri = uri.substring(7); - } - ortSession = ortEnvironment.createSession(uri, sessionOptions); - } else { - // load model via model path string uri - InputStream modelStream = - reactContext.getApplicationContext().getContentResolver().openInputStream(Uri.parse(uri)); - Reader reader = new BufferedReader(new InputStreamReader(modelStream)); - byte[] modelArray = new byte[modelStream.available()]; - modelStream.read(modelArray); - modelStream.close(); - ortSession = ortEnvironment.createSession(modelArray, sessionOptions); - } - - String key = getNextSessionKey(); - sessionMap.put(key, ortSession); - - WritableMap resultMap = Arguments.createMap(); - resultMap.putString("key", key); - WritableArray inputNames = Arguments.createArray(); - for (String inputName : ortSession.getInputNames()) { - inputNames.pushString(inputName); - } - resultMap.putArray("inputNames", inputNames); - WritableArray outputNames = Arguments.createArray(); - for (String outputName : ortSession.getOutputNames()) { - outputNames.pushString(outputName); - } - resultMap.putArray("outputNames", outputNames); - - return resultMap; - } - - /** - * Dispose a model using given key. - * - * @param key a session key representing the session given at loadModel() - */ - public void dispose(String key) throws OrtException { - OrtSession ortSession = sessionMap.get(key); - if (ortSession != null) { - ortSession.close(); - sessionMap.remove(key); - } - } - - /** - * Run a model using given uri. - * - * @param key a session key representing the session given at loadModel() - * @param input an input tensor - * @param output an output names to be returned - * @param options onnxruntime run options - * @return inference result - */ - public WritableMap run(String key, ReadableMap input, ReadableArray output, ReadableMap options) throws Exception { - OrtSession ortSession = sessionMap.get(key); - if (ortSession == null) { - throw new Exception("Model is not loaded."); - } - - RunOptions runOptions = parseRunOptions(options); - - checkBlobModule(); - - long startTime = System.currentTimeMillis(); - Map feed = new HashMap<>(); - Iterator iterator = ortSession.getInputNames().iterator(); - Result result = null; - try { - while (iterator.hasNext()) { - String inputName = iterator.next(); - - ReadableMap inputMap = input.getMap(inputName); - if (inputMap == null) { - throw new Exception("Can't find input: " + inputName); - } - - OnnxTensor onnxTensor = TensorHelper.createInputTensor(blobModule, inputMap, ortEnvironment); - feed.put(inputName, onnxTensor); - } - - Set requestedOutputs = null; - if (output.size() > 0) { - requestedOutputs = new HashSet<>(); - for (int i = 0; i < output.size(); ++i) { - requestedOutputs.add(output.getString(i)); - } - } - - long duration = System.currentTimeMillis() - startTime; - Log.d("Duration", "createInputTensor: " + duration); - - startTime = System.currentTimeMillis(); - if (requestedOutputs != null) { - result = ortSession.run(feed, requestedOutputs, runOptions); - } else { - result = ortSession.run(feed, runOptions); - } - duration = System.currentTimeMillis() - startTime; - Log.d("Duration", "inference: " + duration); - - startTime = System.currentTimeMillis(); - WritableMap resultMap = TensorHelper.createOutputTensor(blobModule, result); - duration = System.currentTimeMillis() - startTime; - Log.d("Duration", "createOutputTensor: " + duration); - - return resultMap; - - } finally { - OnnxValue.close(feed); - if (result != null) { - result.close(); - } - } - } - - private static final Map graphOptimizationLevelTable = - Stream - .of(new Object[][] { - {"disabled", SessionOptions.OptLevel.NO_OPT}, - {"basic", SessionOptions.OptLevel.BASIC_OPT}, - {"extended", SessionOptions.OptLevel.EXTENDED_OPT}, - {"all", SessionOptions.OptLevel.ALL_OPT}, - }) - .collect(Collectors.toMap(p -> (String)p[0], p -> (SessionOptions.OptLevel)p[1])); - - private static final Map executionModeTable = - Stream - .of(new Object[][] {{"sequential", SessionOptions.ExecutionMode.SEQUENTIAL}, - {"parallel", SessionOptions.ExecutionMode.PARALLEL}}) - .collect(Collectors.toMap(p -> (String)p[0], p -> (SessionOptions.ExecutionMode)p[1])); - - private SessionOptions parseSessionOptions(ReadableMap options) throws OrtException { - SessionOptions sessionOptions = new SessionOptions(); - - if (options.hasKey("intraOpNumThreads")) { - int intraOpNumThreads = options.getInt("intraOpNumThreads"); - if (intraOpNumThreads > 0 && intraOpNumThreads < Integer.MAX_VALUE) { - sessionOptions.setIntraOpNumThreads(intraOpNumThreads); - } - } - - if (options.hasKey("interOpNumThreads")) { - int interOpNumThreads = options.getInt("interOpNumThreads"); - if (interOpNumThreads > 0 && interOpNumThreads < Integer.MAX_VALUE) { - sessionOptions.setInterOpNumThreads(interOpNumThreads); - } + return false; } - - if (options.hasKey("graphOptimizationLevel")) { - String graphOptimizationLevel = options.getString("graphOptimizationLevel"); - if (graphOptimizationLevelTable.containsKey(graphOptimizationLevel)) { - sessionOptions.setOptimizationLevel(graphOptimizationLevelTable.get(graphOptimizationLevel)); - } - } - - if (options.hasKey("enableCpuMemArena")) { - boolean enableCpuMemArena = options.getBoolean("enableCpuMemArena"); - sessionOptions.setCPUArenaAllocator(enableCpuMemArena); - } - - if (options.hasKey("enableMemPattern")) { - boolean enableMemPattern = options.getBoolean("enableMemPattern"); - sessionOptions.setMemoryPatternOptimization(enableMemPattern); - } - - if (options.hasKey("executionMode")) { - String executionMode = options.getString("executionMode"); - if (executionModeTable.containsKey(executionMode)) { - sessionOptions.setExecutionMode(executionModeTable.get(executionMode)); - } - } - - if (options.hasKey("executionProviders")) { - ReadableArray executionProviders = options.getArray("executionProviders"); - for (int i = 0; i < executionProviders.size(); ++i) { - String epName = null; - ReadableMap epOptions = null; - if (executionProviders.getType(i) == ReadableType.String) { - epName = executionProviders.getString(i); - } else { - epOptions = executionProviders.getMap(i); - epName = epOptions.getString("name"); - } - if (epName.equals("nnapi")) { - EnumSet flags = EnumSet.noneOf(NNAPIFlags.class); - if (epOptions != null) { - if (epOptions.hasKey("useFP16") && epOptions.getBoolean("useFP16")) { - flags.add(NNAPIFlags.USE_FP16); - } - if (epOptions.hasKey("useNCHW") && epOptions.getBoolean("useNCHW")) { - flags.add(NNAPIFlags.USE_NCHW); - } - if (epOptions.hasKey("cpuDisabled") && epOptions.getBoolean("cpuDisabled")) { - flags.add(NNAPIFlags.CPU_DISABLED); - } - if (epOptions.hasKey("cpuOnly") && epOptions.getBoolean("cpuOnly")) { - flags.add(NNAPIFlags.CPU_ONLY); - } - } - sessionOptions.addNnapi(flags); - } else if (epName.equals("xnnpack")) { - sessionOptions.addXnnpack(Collections.emptyMap()); - } else if (epName.equals("cpu")) { - continue; - } else { - throw new OrtException("Unsupported execution provider: " + epName); - } - } - } - - if (options.hasKey("logId")) { - String logId = options.getString("logId"); - sessionOptions.setLoggerId(logId); - } - - if (options.hasKey("logSeverityLevel")) { - int logSeverityLevel = options.getInt("logSeverityLevel"); - sessionOptions.setSessionLogLevel(OrtLoggingLevel.mapFromInt(logSeverityLevel)); - } - - return sessionOptions; } - private RunOptions parseRunOptions(ReadableMap options) throws OrtException { - RunOptions runOptions = new RunOptions(); - - if (options.hasKey("logSeverityLevel")) { - int logSeverityLevel = options.getInt("logSeverityLevel"); - runOptions.setLogLevel(OrtLoggingLevel.mapFromInt(logSeverityLevel)); - } - - if (options.hasKey("tag")) { - String tag = options.getString("tag"); - runOptions.setRunTag(tag); - } - - return runOptions; - } - - @Override - public void onHostResume() {} - @Override - public void onHostPause() {} - - @Override - public void onHostDestroy() { - for (String key : sessionMap.keySet()) { - try { - dispose(key); - } catch (Exception e) { - Log.e("onHostDestroy", "Failed to dispose session: " + key, e); - } - } - sessionMap.clear(); + public Map getConstants() { + final Map constants = new HashMap(); + constants.put("ORT_EXTENSIONS_PATH", OnnxruntimeExtensions.getLibraryPath()); + return constants; } } diff --git a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimePackage.java b/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimePackage.java index bb4386a0953f3..9171641e6e68a 100644 --- a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimePackage.java +++ b/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/OnnxruntimePackage.java @@ -22,7 +22,6 @@ public class OnnxruntimePackage implements ReactPackage { public List createNativeModules(@NonNull ReactApplicationContext reactContext) { List modules = new ArrayList<>(); modules.add(new OnnxruntimeModule(reactContext)); - modules.add(new OnnxruntimeJSIHelper(reactContext)); return modules; } diff --git a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/TensorHelper.java b/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/TensorHelper.java deleted file mode 100644 index 63cddace36640..0000000000000 --- a/js/react_native/android/src/main/java/ai/onnxruntime/reactnative/TensorHelper.java +++ /dev/null @@ -1,289 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package ai.onnxruntime.reactnative; - -import ai.onnxruntime.OnnxJavaType; -import ai.onnxruntime.OnnxTensor; -import ai.onnxruntime.OnnxValue; -import ai.onnxruntime.OrtEnvironment; -import ai.onnxruntime.OrtSession; -import ai.onnxruntime.OrtUtil; -import ai.onnxruntime.TensorInfo; -import android.util.Base64; -import com.facebook.react.bridge.Arguments; -import com.facebook.react.bridge.ReadableArray; -import com.facebook.react.bridge.ReadableMap; -import com.facebook.react.bridge.WritableArray; -import com.facebook.react.bridge.WritableMap; -import com.facebook.react.modules.blob.BlobModule; -import java.nio.ByteBuffer; -import java.nio.ByteOrder; -import java.nio.DoubleBuffer; -import java.nio.FloatBuffer; -import java.nio.IntBuffer; -import java.nio.LongBuffer; -import java.nio.ShortBuffer; -import java.util.Iterator; -import java.util.Map; -import java.util.Objects; -import java.util.stream.Collectors; -import java.util.stream.Stream; - -public class TensorHelper { - /** - * Supported tensor data type - */ - public static final String JsTensorTypeBool = "bool"; - public static final String JsTensorTypeByte = "int8"; - public static final String JsTensorTypeUnsignedByte = "uint8"; - public static final String JsTensorTypeShort = "int16"; - public static final String JsTensorTypeInt = "int32"; - public static final String JsTensorTypeLong = "int64"; - public static final String JsTensorTypeFloat = "float32"; - public static final String JsTensorTypeDouble = "float64"; - public static final String JsTensorTypeString = "string"; - - /** - * It creates an input tensor from a map passed by react native js. - * 'data' is blob object and the buffer is stored in BlobModule. It first resolve it and creates a tensor. - */ - public static OnnxTensor createInputTensor(BlobModule blobModule, ReadableMap inputTensor, - OrtEnvironment ortEnvironment) throws Exception { - // shape - ReadableArray dimsArray = inputTensor.getArray("dims"); - long[] dims = new long[dimsArray.size()]; - for (int i = 0; i < dimsArray.size(); ++i) { - dims[i] = dimsArray.getInt(i); - } - - // type - TensorInfo.OnnxTensorType tensorType = getOnnxTensorType(inputTensor.getString("type")); - - // data - OnnxTensor onnxTensor = null; - if (tensorType == TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING) { - ReadableArray values = inputTensor.getArray("data"); - String[] buffer = new String[values.size()]; - for (int i = 0; i < values.size(); ++i) { - buffer[i] = values.getString(i); - } - onnxTensor = OnnxTensor.createTensor(ortEnvironment, buffer, dims); - } else { - ReadableMap data = inputTensor.getMap("data"); - String blobId = data.getString("blobId"); - byte[] bytes = blobModule.resolve(blobId, data.getInt("offset"), data.getInt("size")); - blobModule.remove(blobId); - ByteBuffer values = ByteBuffer.wrap(bytes).order(ByteOrder.nativeOrder()); - onnxTensor = createInputTensor(tensorType, dims, values, ortEnvironment); - } - - return onnxTensor; - } - - /** - * It creates an output map from an output tensor. - * a data array is store in BlobModule. - */ - public static WritableMap createOutputTensor(BlobModule blobModule, OrtSession.Result result) throws Exception { - WritableMap outputTensorMap = Arguments.createMap(); - - Iterator> iterator = result.iterator(); - while (iterator.hasNext()) { - Map.Entry entry = iterator.next(); - String outputName = entry.getKey(); - OnnxValue onnxValue = (OnnxValue)entry.getValue(); - if (onnxValue.getType() != OnnxValue.OnnxValueType.ONNX_TYPE_TENSOR) { - throw new Exception("Not supported type: " + onnxValue.getType().toString()); - } - - OnnxTensor onnxTensor = (OnnxTensor)onnxValue; - WritableMap outputTensor = Arguments.createMap(); - - // dims - WritableArray outputDims = Arguments.createArray(); - long[] dims = onnxTensor.getInfo().getShape(); - for (long dim : dims) { - outputDims.pushInt((int)dim); - } - outputTensor.putArray("dims", outputDims); - - // type - outputTensor.putString("type", getJsTensorType(onnxTensor.getInfo().onnxType)); - - // data - if (onnxTensor.getInfo().onnxType == TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING) { - String[] buffer = (String[])onnxTensor.getValue(); - WritableArray dataArray = Arguments.createArray(); - for (String value : buffer) { - dataArray.pushString(value); - } - outputTensor.putArray("data", dataArray); - } else { - // Store in BlobModule then create a blob object as data - byte[] bufferArray = createOutputTensor(onnxTensor); - WritableMap data = Arguments.createMap(); - data.putString("blobId", blobModule.store(bufferArray)); - data.putInt("offset", 0); - data.putInt("size", bufferArray.length); - outputTensor.putMap("data", data); - } - - outputTensorMap.putMap(outputName, outputTensor); - } - - return outputTensorMap; - } - - private static OnnxTensor createInputTensor(TensorInfo.OnnxTensorType tensorType, long[] dims, ByteBuffer values, - OrtEnvironment ortEnvironment) throws Exception { - OnnxTensor tensor = null; - switch (tensorType) { - case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: { - FloatBuffer buffer = values.asFloatBuffer(); - tensor = OnnxTensor.createTensor(ortEnvironment, buffer, dims); - break; - } - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: { - ByteBuffer buffer = values; - tensor = OnnxTensor.createTensor(ortEnvironment, buffer, dims); - break; - } - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16: { - ShortBuffer buffer = values.asShortBuffer(); - tensor = OnnxTensor.createTensor(ortEnvironment, buffer, dims); - break; - } - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: { - IntBuffer buffer = values.asIntBuffer(); - tensor = OnnxTensor.createTensor(ortEnvironment, buffer, dims); - break; - } - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: { - LongBuffer buffer = values.asLongBuffer(); - tensor = OnnxTensor.createTensor(ortEnvironment, buffer, dims); - break; - } - case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE: { - DoubleBuffer buffer = values.asDoubleBuffer(); - tensor = OnnxTensor.createTensor(ortEnvironment, buffer, dims); - break; - } - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: { - ByteBuffer buffer = values; - tensor = OnnxTensor.createTensor(ortEnvironment, buffer, dims, OnnxJavaType.UINT8); - break; - } - case ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL: { - ByteBuffer buffer = values; - tensor = OnnxTensor.createTensor(ortEnvironment, buffer, dims, OnnxJavaType.BOOL); - break; - } - case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING: - default: - throw new IllegalStateException("Unexpected value: " + tensorType.toString()); - } - - return tensor; - } - - private static byte[] createOutputTensor(OnnxTensor onnxTensor) throws Exception { - TensorInfo tensorInfo = onnxTensor.getInfo(); - ByteBuffer buffer = null; - - int capacity = (int)OrtUtil.elementCount(onnxTensor.getInfo().getShape()); - - switch (tensorInfo.onnxType) { - case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT: - buffer = ByteBuffer.allocate(capacity * 4).order(ByteOrder.nativeOrder()); - buffer.asFloatBuffer().put(onnxTensor.getFloatBuffer()); - break; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8: - buffer = ByteBuffer.allocate(capacity).order(ByteOrder.nativeOrder()); - buffer.put(onnxTensor.getByteBuffer()); - break; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16: - buffer = ByteBuffer.allocate(capacity * 2).order(ByteOrder.nativeOrder()); - buffer.asShortBuffer().put(onnxTensor.getShortBuffer()); - break; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32: - buffer = ByteBuffer.allocate(capacity * 4).order(ByteOrder.nativeOrder()); - buffer.asIntBuffer().put(onnxTensor.getIntBuffer()); - break; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64: - buffer = ByteBuffer.allocate(capacity * 8).order(ByteOrder.nativeOrder()); - buffer.asLongBuffer().put(onnxTensor.getLongBuffer()); - break; - case ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE: { - buffer = ByteBuffer.allocate(capacity * 8).order(ByteOrder.nativeOrder()); - buffer.asDoubleBuffer().put(onnxTensor.getDoubleBuffer()); - break; - } - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8: { - buffer = ByteBuffer.allocate(capacity).order(ByteOrder.nativeOrder()); - buffer.put(onnxTensor.getByteBuffer()); - break; - } - case ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32: - case ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64: - default: - throw new IllegalStateException("Unexpected type: " + tensorInfo.onnxType.toString()); - } - - return buffer.array(); - } - - private static final Map JsTensorTypeToOnnxTensorTypeMap = - Stream - .of(new Object[][] { - {JsTensorTypeFloat, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT}, - {JsTensorTypeByte, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8}, - {JsTensorTypeUnsignedByte, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8}, - {JsTensorTypeShort, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16}, - {JsTensorTypeInt, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32}, - {JsTensorTypeLong, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64}, - {JsTensorTypeString, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING}, - {JsTensorTypeBool, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL}, - {JsTensorTypeDouble, TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE}, - }) - .collect(Collectors.toMap(p -> (String)p[0], p -> (TensorInfo.OnnxTensorType)p[1])); - - private static TensorInfo.OnnxTensorType getOnnxTensorType(String type) { - if (JsTensorTypeToOnnxTensorTypeMap.containsKey(type)) { - return JsTensorTypeToOnnxTensorTypeMap.get(type); - } else { - return TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED; - } - } - - private static final Map OnnxTensorTypeToJsTensorTypeMap = - Stream - .of(new Object[][] { - {TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, JsTensorTypeFloat}, - {TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8, JsTensorTypeByte}, - {TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8, JsTensorTypeUnsignedByte}, - {TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16, JsTensorTypeShort}, - {TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32, JsTensorTypeInt}, - {TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64, JsTensorTypeLong}, - {TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING, JsTensorTypeString}, - {TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL, JsTensorTypeBool}, - {TensorInfo.OnnxTensorType.ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE, JsTensorTypeDouble}, - }) - .collect(Collectors.toMap(p -> (TensorInfo.OnnxTensorType)p[0], p -> (String)p[1])); - - private static String getJsTensorType(TensorInfo.OnnxTensorType type) { - if (OnnxTensorTypeToJsTensorTypeMap.containsKey(type)) { - return OnnxTensorTypeToJsTensorTypeMap.get(type); - } else { - return "undefined"; - } - } -} diff --git a/js/react_native/app.plugin.js b/js/react_native/app.plugin.js index 2fa117b1a14e5..7f6bd8b55dae3 100644 --- a/js/react_native/app.plugin.js +++ b/js/react_native/app.plugin.js @@ -23,6 +23,56 @@ const withOrt = (config) => { return config; }); + // Register OnnxruntimePackage in MainApplication for New Architecture / Expo prebuild + config = configPlugin.withMainApplication(config, (config) => { + const lang = config.modResults.language; + if (lang === 'kt') { + config.modResults.contents = generateCode.mergeContents({ + src: config.modResults.contents, + newSrc: 'import ai.onnxruntime.reactnative.OnnxruntimePackage', + tag: 'onnxruntime-react-native-import', + anchor: /^import /m, + offset: 0, + comment: '//', + }).contents; + config.modResults.contents = generateCode.mergeContents({ + src: config.modResults.contents, + newSrc: ' add(OnnxruntimePackage())', + tag: 'onnxruntime-react-native-package', + anchor: /override fun getPackages\(\)/, + offset: 2, + comment: '//', + }).contents; + } else if (lang === 'java') { + config.modResults.contents = generateCode.mergeContents({ + src: config.modResults.contents, + newSrc: 'import ai.onnxruntime.reactnative.OnnxruntimePackage;', + tag: 'onnxruntime-react-native-import', + anchor: /^import /m, + offset: 0, + comment: '//', + }).contents; + if (!config.modResults.contents.includes('packages.add(new OnnxruntimePackage())')) { + if (/return\s+new PackageList\(this\)\.getPackages\(\);/.test(config.modResults.contents)) { + config.modResults.contents = config.modResults.contents.replace( + /(\s*)return\s+new PackageList\(this\)\.getPackages\(\);/, + '$1List packages = new PackageList(this).getPackages();\n$1packages.add(new OnnxruntimePackage());\n$1return packages;', + ); + } else { + config.modResults.contents = generateCode.mergeContents({ + src: config.modResults.contents, + newSrc: ' packages.add(new OnnxruntimePackage());', + tag: 'onnxruntime-react-native-package', + anchor: /^\s*List\s+packages\s*=\s*new PackageList\(this\)\.getPackages\(\);\s*$/m, + offset: 1, + comment: '//', + }).contents; + } + } + } + return config; + }); + // Add build dependency to pod file config = configPlugin.withDangerousMod(config, [ 'ios', diff --git a/js/react_native/babel.config.js b/js/react_native/babel.config.js deleted file mode 100644 index e2240f1f51f8b..0000000000000 --- a/js/react_native/babel.config.js +++ /dev/null @@ -1,5 +0,0 @@ -'use strict'; - -module.exports = { - presets: ['module:metro-react-native-babel-preset'], -}; diff --git a/js/react_native/cpp/AsyncWorker.h b/js/react_native/cpp/AsyncWorker.h new file mode 100644 index 0000000000000..ceca5c0ac203e --- /dev/null +++ b/js/react_native/cpp/AsyncWorker.h @@ -0,0 +1,131 @@ +#pragma once + +#include "Env.h" +#include +#include +#include +#include +#include +#include + +using namespace facebook::jsi; + +namespace onnxruntimejsi { + +/** + * @brief AsyncWorker is a helper class to run a function asynchronously and + * return a promise. + * + * @param rt The runtime to use. + * @param env The environment to use. + */ +class AsyncWorker : public HostObject, public std::enable_shared_from_this { + public: + AsyncWorker(Runtime& rt, std::shared_ptr env) : rt_(rt), env_(env), cancel_(false) {} + + ~AsyncWorker() { + if (worker_.joinable()) { + if (worker_.get_id() != std::this_thread::get_id()) { + cancel_ = true; + onAbort(); + worker_.join(); + } else { + worker_.detach(); + } + } + } + + /** + * @brief Make sure the value won't be garbage collected during the async + * operation. + * + * @param rt The runtime to use. + * @param value The value to keep. + */ + void keepValue(Runtime& rt, const Value& value) { + keptValues_.push_back(std::make_shared(rt, value)); + } + + /** + * @brief Create a promise to be used in the async operation. + * + * @param rt The runtime to use. + * @return The promise. + */ + Value toPromise(Runtime& rt) { + auto promiseCtor = rt.global().getPropertyAsFunction(rt, "Promise"); + + auto promise = promiseCtor.callAsConstructor( + rt, Function::createFromHostFunction( + rt, PropNameID::forAscii(rt, "executor"), 2, + [this](Runtime& rt, const Value& thisVal, const Value* args, + size_t count) -> Value { + resolveFunc_ = std::make_shared(rt, args[0]); + rejectFunc_ = std::make_shared(rt, args[1]); + cancel_ = false; + worker_ = std::thread([this]() { + if (cancel_) return; + try { + execute(); + dispatchResolve(); + } catch (const std::exception& e) { + dispatchReject(e.what()); + } + }); + return Value::undefined(); + })); + promise.asObject(rt).setProperty(rt, "__nativeWorker", Object::createFromHostObject(rt, shared_from_this())); + return promise; + } + + protected: + virtual void execute() = 0; + + virtual Value onResolve(Runtime& rt) = 0; + virtual Value onReject(Runtime& rt, const std::string& err) { + return String::createFromUtf8(rt, err); + } + + virtual void onAbort() {} + + private: + void dispatchResolve() { + if (cancel_) return; + auto self = shared_from_this(); + env_->runOnJsThread([self]() { + auto resVal = self->onResolve(self->rt_); + self->resolveFunc_->asObject(self->rt_) + .asFunction(self->rt_) + .call(self->rt_, resVal); + self->clearKeeps(); + }); + } + + void dispatchReject(const std::string& err) { + if (cancel_) return; + auto self = shared_from_this(); + env_->runOnJsThread([self, err]() { + auto resVal = self->onReject(self->rt_, err); + self->rejectFunc_->asObject(self->rt_) + .asFunction(self->rt_) + .call(self->rt_, resVal); + self->clearKeeps(); + }); + } + + void clearKeeps() { + keptValues_.clear(); + resolveFunc_.reset(); + rejectFunc_.reset(); + } + + Runtime& rt_; + std::shared_ptr env_; + std::atomic cancel_; + std::vector> keptValues_; + std::shared_ptr resolveFunc_; + std::shared_ptr rejectFunc_; + std::thread worker_; +}; + +} // namespace onnxruntimejsi diff --git a/js/react_native/cpp/Env.h b/js/react_native/cpp/Env.h new file mode 100644 index 0000000000000..9e7b7651a971f --- /dev/null +++ b/js/react_native/cpp/Env.h @@ -0,0 +1,50 @@ +#pragma once + +#include +#include +#include +#include +#include +#include "onnxruntime_cxx_api.h" +#include + +namespace onnxruntimejsi { + +class Env : public std::enable_shared_from_this { + public: + Env(std::shared_ptr jsInvoker) + : jsInvoker_(jsInvoker) {} + + ~Env() {} + + inline void initOrtEnv(OrtLoggingLevel logLevel, const char* logid) { + if (ortEnv_) { + return; + } + ortEnv_ = std::make_shared(logLevel, logid); + } + + inline void setTensorConstructor( + std::shared_ptr tensorConstructor) { + tensorConstructor_ = tensorConstructor; + } + + inline facebook::jsi::Value + getTensorConstructor(facebook::jsi::Runtime& runtime) const { + return tensorConstructor_->lock(runtime); + } + + inline Ort::Env& getOrtEnv() const { return *ortEnv_; } + + inline void runOnJsThread(std::function&& func) { + if (!jsInvoker_) return; + jsInvoker_->invokeAsync(std::move(func)); + } + + private: + std::shared_ptr jsInvoker_; + std::shared_ptr tensorConstructor_; + std::shared_ptr ortEnv_; +}; + +} // namespace onnxruntimejsi diff --git a/js/react_native/cpp/InferenceSessionHostObject.cpp b/js/react_native/cpp/InferenceSessionHostObject.cpp new file mode 100644 index 0000000000000..c8efd49e6d669 --- /dev/null +++ b/js/react_native/cpp/InferenceSessionHostObject.cpp @@ -0,0 +1,312 @@ +#include "InferenceSessionHostObject.h" +#include "AsyncWorker.h" +#include "JsiUtils.h" +#include "SessionUtils.h" +#include "TensorUtils.h" +#include + +using namespace facebook::jsi; + +namespace onnxruntimejsi { + +class InferenceSessionHostObject::LoadModelAsyncWorker : public AsyncWorker { + public: + LoadModelAsyncWorker(Runtime& runtime, const Value* arguments, size_t count, + std::shared_ptr session) + : AsyncWorker(runtime, session->env_), session_(session) { + if (count < 1) + throw JSError(runtime, "loadModel requires at least 1 argument"); + if (arguments[0].isString()) { + modelPath_ = arguments[0].asString(runtime).utf8(runtime); + if (modelPath_.find("file:/") == 0) { + modelPath_ = modelPath_.substr(5); + if (modelPath_.find("//") == 0) { + modelPath_ = modelPath_.substr(2); + } + } + } else if (arguments[0].isObject() && + arguments[0].asObject(runtime).isArrayBuffer(runtime)) { + auto arrayBufferObj = arguments[0].asObject(runtime); + auto arrayBuffer = arrayBufferObj.getArrayBuffer(runtime); + modelData_ = arrayBuffer.data(runtime); + modelDataLength_ = arrayBuffer.size(runtime); + } else { + throw JSError(runtime, "Model path or buffer is required"); + } + keepValue(runtime, arguments[0]); + if (count > 1) { + parseSessionOptions(runtime, arguments[1], sessionOptions_); + } + } + + protected: + void execute() { + if (modelPath_.empty()) { + session_->session_ = std::make_shared( + session_->env_->getOrtEnv(), modelData_, modelDataLength_, + sessionOptions_); + } else { + session_->session_ = std::make_shared( + session_->env_->getOrtEnv(), modelPath_.c_str(), sessionOptions_); + } + } + + Value onResolve(Runtime& rt) { return Value::undefined(); } + + private: + std::string error_; + std::string modelPath_; + void* modelData_; + size_t modelDataLength_; + std::shared_ptr session_; + Ort::SessionOptions sessionOptions_; + std::shared_ptr weakResolve_; + std::shared_ptr weakReject_; + std::thread thread_; +}; + +DEFINE_METHOD(InferenceSessionHostObject::loadModel) { + auto self = shared_from_this(); + auto worker = + std::make_shared(runtime, arguments, count, self); + return worker->toPromise(runtime); +} + +class InferenceSessionHostObject::RunAsyncWorker : public AsyncWorker { + public: + RunAsyncWorker(Runtime& runtime, const Value* arguments, size_t count, + std::shared_ptr session) + : AsyncWorker(runtime, session->env_), + env_(session->env_), + session_(session->session_), + memoryInfo_(Ort::MemoryInfo::CreateCpu(OrtDeviceAllocator, OrtMemTypeDefault)) { + if (count < 1) + throw JSError(runtime, "run requires at least 1 argument"); + if (count > 2 && !arguments[2].isUndefined()) { + parseRunOptions(runtime, arguments[2], runOptions_); + } + forEach(runtime, arguments[0].asObject(runtime), + [&](const std::string& key, const Value& value, size_t index) { + inputNames_.push_back(key); + inputValues_.push_back(TensorUtils::createOrtValueFromJSTensor( + runtime, value.asObject(runtime), memoryInfo_)); + keepValue(runtime, value); + }); + forEach(runtime, arguments[1].asObject(runtime), + [&](const std::string& key, const Value& value, size_t index) { + outputNames_.push_back(key); + if (value.isObject() && + TensorUtils::isTensor(runtime, value.asObject(runtime))) { + outputValues_.push_back(TensorUtils::createOrtValueFromJSTensor( + runtime, value.asObject(runtime), memoryInfo_)); + jsOutputValues_.push_back(std::make_shared( + runtime, value.asObject(runtime))); + keepValue(runtime, value); + } else { + outputValues_.push_back(Ort::Value()); + jsOutputValues_.push_back(nullptr); + } + }); + } + + protected: + void execute() { + auto inputNames = std::vector(inputNames_.size()); + std::transform(inputNames_.begin(), inputNames_.end(), inputNames.begin(), + [](const std::string& name) { return name.c_str(); }); + auto outputNames = std::vector(outputNames_.size()); + std::transform(outputNames_.begin(), outputNames_.end(), + outputNames.begin(), + [](const std::string& name) { return name.c_str(); }); + auto session = session_.lock(); + if (!session) { + throw std::runtime_error("Session is released"); + } + session->Run(runOptions_, inputNames.data(), inputValues_.data(), + inputValues_.size(), outputNames.data(), + outputValues_.data(), outputValues_.size()); + } + + Value onResolve(Runtime& rt) { + auto resultObject = Object(rt); + auto tensorConstructor = + env_->getTensorConstructor(rt).asObject(rt); + for (size_t i = 0; i < outputValues_.size(); ++i) { + if (jsOutputValues_[i] != nullptr && outputValues_[i].IsTensor()) { + resultObject.setProperty(rt, outputNames_[i].c_str(), + jsOutputValues_[i]->lock(rt)); + } else { + auto tensorObj = TensorUtils::createJSTensorFromOrtValue( + rt, outputValues_[i], tensorConstructor); + resultObject.setProperty(rt, outputNames_[i].c_str(), + Value(rt, tensorObj)); + } + } + return Value(rt, resultObject); + } + + void onAbort() { + runOptions_.SetTerminate(); + } + + private: + std::shared_ptr env_; + std::weak_ptr session_; + Ort::MemoryInfo memoryInfo_; + Ort::RunOptions runOptions_; + std::vector inputNames_; + std::vector inputValues_; + std::vector outputNames_; + std::vector outputValues_; + std::vector> jsOutputValues_; +}; + +DEFINE_METHOD(InferenceSessionHostObject::run) { + auto self = shared_from_this(); + auto worker = + std::make_shared(runtime, arguments, count, self); + return worker->toPromise(runtime); +} + +DEFINE_METHOD(InferenceSessionHostObject::dispose) { + session_.reset(); + return Value::undefined(); +} + +DEFINE_METHOD(InferenceSessionHostObject::endProfiling) { + try { + Ort::AllocatorWithDefaultOptions allocator; + auto filename = session_->EndProfilingAllocated(allocator); + return String::createFromUtf8(runtime, std::string(filename.get())); + } catch (const std::exception& e) { + throw JSError(runtime, std::string(e.what())); + } +} + +DEFINE_GETTER(InferenceSessionHostObject::inputMetadata) { + if (!session_) { + return Array(runtime, 0); + } + try { + Ort::AllocatorWithDefaultOptions allocator; + size_t numInputs = session_->GetInputCount(); + auto array = Array(runtime, numInputs); + + for (size_t i = 0; i < numInputs; i++) { + auto item = Object(runtime); + auto inputName = session_->GetInputNameAllocated(i, allocator); + item.setProperty( + runtime, "name", + String::createFromUtf8(runtime, std::string(inputName.get()))); + + try { + auto typeInfo = session_->GetInputTypeInfo(i); + auto tensorInfo = typeInfo.GetTensorTypeAndShapeInfo(); + + // Get data type + auto dataType = tensorInfo.GetElementType(); + item.setProperty(runtime, "type", static_cast(dataType)); + + // Get shape + auto shape = tensorInfo.GetShape(); + auto shapeArray = Array(runtime, shape.size()); + for (size_t j = 0; j < shape.size(); j++) { + shapeArray.setValueAtIndex(runtime, j, + Value(static_cast(shape[j]))); + } + item.setProperty(runtime, "shape", shapeArray); + + item.setProperty(runtime, "isTensor", Value(true)); + + // symbolicDimensions + auto symbolicDimensions = tensorInfo.GetSymbolicDimensions(); + auto symbolicDimensionsArray = + Array(runtime, symbolicDimensions.size()); + for (size_t j = 0; j < symbolicDimensions.size(); j++) { + symbolicDimensionsArray.setValueAtIndex( + runtime, j, + String::createFromUtf8(runtime, symbolicDimensions[j])); + } + item.setProperty(runtime, "symbolicDimensions", + symbolicDimensionsArray); + } catch (const std::exception&) { + // Fallback for unknown types + item.setProperty(runtime, "type", + String::createFromUtf8(runtime, "unknown")); + item.setProperty(runtime, "shape", Array(runtime, 0)); + item.setProperty(runtime, "isTensor", Value(false)); + } + + array.setValueAtIndex(runtime, i, Value(runtime, item)); + } + + return Value(runtime, array); + } catch (const Ort::Exception& e) { + throw JSError(runtime, std::string(e.what())); + } +} + +DEFINE_GETTER(InferenceSessionHostObject::outputMetadata) { + if (!session_) { + return Array(runtime, 0); + } + try { + Ort::AllocatorWithDefaultOptions allocator; + size_t numOutputs = session_->GetOutputCount(); + auto array = Array(runtime, numOutputs); + + for (size_t i = 0; i < numOutputs; i++) { + auto item = Object(runtime); + auto outputName = session_->GetOutputNameAllocated(i, allocator); + item.setProperty( + runtime, "name", + String::createFromUtf8(runtime, std::string(outputName.get()))); + + try { + auto typeInfo = session_->GetOutputTypeInfo(i); + auto tensorInfo = typeInfo.GetTensorTypeAndShapeInfo(); + + // Get data type + auto dataType = tensorInfo.GetElementType(); + item.setProperty(runtime, "type", static_cast(dataType)); + + // Get shape + auto shape = tensorInfo.GetShape(); + auto shapeArray = Array(runtime, shape.size()); + for (size_t j = 0; j < shape.size(); j++) { + shapeArray.setValueAtIndex(runtime, j, + Value(static_cast(shape[j]))); + } + item.setProperty(runtime, "shape", shapeArray); + + item.setProperty(runtime, "isTensor", Value(true)); + + // symbolicDimensions + auto symbolicDimensions = tensorInfo.GetSymbolicDimensions(); + auto symbolicDimensionsArray = + Array(runtime, symbolicDimensions.size()); + for (size_t j = 0; j < symbolicDimensions.size(); j++) { + symbolicDimensionsArray.setValueAtIndex( + runtime, j, + String::createFromUtf8(runtime, symbolicDimensions[j])); + } + item.setProperty(runtime, "symbolicDimensions", + symbolicDimensionsArray); + } catch (const std::exception&) { + // Fallback for unknown types + item.setProperty(runtime, "type", + String::createFromUtf8(runtime, "unknown")); + item.setProperty(runtime, "shape", Array(runtime, 0)); + item.setProperty(runtime, "isTensor", Value(false)); + } + + array.setValueAtIndex(runtime, i, Value(runtime, item)); + } + + return Value(runtime, array); + } catch (const Ort::Exception& e) { + throw JSError(runtime, std::string(e.what())); + } +} + +} // namespace onnxruntimejsi diff --git a/js/react_native/cpp/InferenceSessionHostObject.h b/js/react_native/cpp/InferenceSessionHostObject.h new file mode 100644 index 0000000000000..f13a8d46d4048 --- /dev/null +++ b/js/react_native/cpp/InferenceSessionHostObject.h @@ -0,0 +1,55 @@ +#pragma once + +#include "Env.h" +#include "JsiHelper.h" +#include +#include +#include "onnxruntime_cxx_api.h" +#include + +using namespace facebook::jsi; + +namespace onnxruntimejsi { + +class InferenceSessionHostObject + : public HostObjectHelper, + public std::enable_shared_from_this { + public: + InferenceSessionHostObject(std::shared_ptr env) : HostObjectHelper({ + METHOD_INFO(InferenceSessionHostObject, loadModel, 2), + METHOD_INFO(InferenceSessionHostObject, run, 2), + METHOD_INFO(InferenceSessionHostObject, dispose, 0), + METHOD_INFO(InferenceSessionHostObject, endProfiling, 0), + }, + { + GETTER_INFO(InferenceSessionHostObject, inputMetadata), + GETTER_INFO(InferenceSessionHostObject, outputMetadata), + }), + env_(env) {} + + static inline facebook::jsi::Value + constructor(std::shared_ptr env, facebook::jsi::Runtime& runtime, + const facebook::jsi::Value& thisValue, + const facebook::jsi::Value* arguments, size_t count) { + return facebook::jsi::Object::createFromHostObject( + runtime, std::make_shared(env)); + } + + protected: + class LoadModelAsyncWorker; + class RunAsyncWorker; + + private: + std::shared_ptr env_; + std::shared_ptr session_; + + DEFINE_METHOD(loadModel); + DEFINE_METHOD(run); + DEFINE_METHOD(dispose); + DEFINE_METHOD(endProfiling); + + DEFINE_GETTER(inputMetadata); + DEFINE_GETTER(outputMetadata); +}; + +} // namespace onnxruntimejsi diff --git a/js/react_native/cpp/JsiHelper.h b/js/react_native/cpp/JsiHelper.h new file mode 100644 index 0000000000000..953429e2c26d5 --- /dev/null +++ b/js/react_native/cpp/JsiHelper.h @@ -0,0 +1,116 @@ +#pragma once + +#include +#include +#include +#include +#include + +#define BIND_METHOD(method) \ + std::bind(&method, std::placeholders::_1, std::placeholders::_2, \ + std::placeholders::_3, std::placeholders::_4) + +#define BIND_GETTER(method) std::bind(&method, std::placeholders::_1) + +#define BIND_SETTER(method) \ + std::bind(&method, std::placeholders::_1, std::placeholders::_2) + +#define BIND_THIS_METHOD(cls, name) \ + std::bind(&cls::name##_method, this, std::placeholders::_1, \ + std::placeholders::_2, std::placeholders::_3, \ + std::placeholders::_4) + +#define BIND_THIS_GETTER(cls, name) \ + std::bind(&cls::name##_get, this, std::placeholders::_1) + +#define BIND_THIS_SETTER(cls, name) \ + std::bind(&cls::name##_set, this, std::placeholders::_1, \ + std::placeholders::_2) + +#define METHOD_INFO(cls, name, count) \ + { \ + #name, { BIND_THIS_METHOD(cls, name), count } \ + } + +#define GETTER_INFO(cls, name) \ + {#name, BIND_THIS_GETTER(cls, name)} + +#define DEFINE_METHOD(name) \ + Value name##_method(Runtime& runtime, const Value& thisValue, \ + const Value* arguments, size_t count) + +#define DEFINE_GETTER(name) Value name##_get(Runtime& runtime) + +#define DEFINE_SETTER(name) \ + void name##_set(Runtime& runtime, const Value& value) + +typedef std::function + JsiMethod; +typedef std::function + JsiGetter; +typedef std::function + JsiSetter; + +struct JsiMethodInfo { + JsiMethod method; + size_t count; +}; + +typedef std::unordered_map JsiMethodMap; +typedef std::unordered_map JsiGetterMap; +typedef std::unordered_map JsiSetterMap; + +class HostObjectHelper : public facebook::jsi::HostObject { + public: + HostObjectHelper( + JsiMethodMap methods = {}, + JsiGetterMap getters = {}, + JsiSetterMap setters = {}) + : methods_(methods), + getters_(getters), + setters_(setters) {} + + std::vector + getPropertyNames(facebook::jsi::Runtime& runtime) override { + std::vector names; + for (auto& [name, _] : methods_) { + names.push_back(facebook::jsi::PropNameID::forUtf8(runtime, name)); + } + for (auto& [name, _] : getters_) { + names.push_back(facebook::jsi::PropNameID::forUtf8(runtime, name)); + } + return names; + } + + facebook::jsi::Value get(facebook::jsi::Runtime& runtime, + const facebook::jsi::PropNameID& name) override { + auto method = methods_.find(name.utf8(runtime)); + if (method != methods_.end()) { + return facebook::jsi::Function::createFromHostFunction(runtime, name, method->second.count, + method->second.method); + } + + auto getter = getters_.find(name.utf8(runtime)); + if (getter != getters_.end()) { + return getter->second(runtime); + } + + return facebook::jsi::Value::undefined(); + } + + void set(facebook::jsi::Runtime& runtime, const facebook::jsi::PropNameID& name, + const facebook::jsi::Value& value) override { + auto setter = setters_.find(name.utf8(runtime)); + if (setter != setters_.end()) { + setter->second(runtime, value); + } + } + + private: + JsiMethodMap methods_; + JsiGetterMap getters_; + JsiSetterMap setters_; +}; diff --git a/js/react_native/cpp/JsiMain.cpp b/js/react_native/cpp/JsiMain.cpp new file mode 100644 index 0000000000000..26e8842b32793 --- /dev/null +++ b/js/react_native/cpp/JsiMain.cpp @@ -0,0 +1,98 @@ +#include "JsiMain.h" +#include "InferenceSessionHostObject.h" +#include "JsiHelper.h" +#include "SessionUtils.h" +#include + +using namespace facebook::jsi; + +namespace onnxruntimejsi { + +std::shared_ptr +install(Runtime& runtime, + std::shared_ptr jsInvoker) { + auto env = std::make_shared(jsInvoker); + try { + auto ortApi = Object(runtime); + + auto initOrtOnceMethod = Function::createFromHostFunction( + runtime, PropNameID::forAscii(runtime, "initOrtOnce"), 2, + [env](Runtime& runtime, const Value& thisValue, const Value* arguments, + size_t count) -> Value { + try { + OrtLoggingLevel logLevel = ORT_LOGGING_LEVEL_WARNING; + if (count > 0 && arguments[0].isNumber()) { + int level = static_cast(arguments[0].asNumber()); + switch (level) { + case 0: + logLevel = ORT_LOGGING_LEVEL_VERBOSE; + break; + case 1: + logLevel = ORT_LOGGING_LEVEL_INFO; + break; + case 2: + logLevel = ORT_LOGGING_LEVEL_WARNING; + break; + case 3: + logLevel = ORT_LOGGING_LEVEL_ERROR; + break; + case 4: + logLevel = ORT_LOGGING_LEVEL_FATAL; + break; + default: + logLevel = ORT_LOGGING_LEVEL_WARNING; + break; + } + } + env->setTensorConstructor(std::make_shared( + runtime, arguments[1].asObject(runtime))); + env->initOrtEnv(logLevel, "onnxruntime-react-native-jsi"); + return Value::undefined(); + } catch (const std::exception& e) { + throw JSError(runtime, "Failed to initialize ONNX Runtime: " + + std::string(e.what())); + } + }); + + ortApi.setProperty(runtime, "initOrtOnce", initOrtOnceMethod); + + auto createInferenceSessionMethod = Function::createFromHostFunction( + runtime, PropNameID::forAscii(runtime, "createInferenceSession"), 0, + std::bind(InferenceSessionHostObject::constructor, env, + std::placeholders::_1, std::placeholders::_2, + std::placeholders::_3, std::placeholders::_4)); + ortApi.setProperty(runtime, "createInferenceSession", + createInferenceSessionMethod); + + auto listSupportedBackendsMethod = Function::createFromHostFunction( + runtime, PropNameID::forAscii(runtime, "listSupportedBackends"), 0, + [](Runtime& runtime, const Value& thisValue, const Value* arguments, + size_t count) -> Value { + auto backends = Array(runtime, supportedBackends.size()); + for (size_t i = 0; i < supportedBackends.size(); i++) { + auto backend = Object(runtime); + backend.setProperty( + runtime, "name", + String::createFromUtf8(runtime, supportedBackends[i])); + backends.setValueAtIndex(runtime, i, Value(runtime, backend)); + } + return Value(runtime, backends); + }); + + ortApi.setProperty(runtime, "listSupportedBackends", + listSupportedBackendsMethod); + + ortApi.setProperty( + runtime, "version", + String::createFromUtf8(runtime, OrtGetApiBase()->GetVersionString())); + + runtime.global().setProperty(runtime, "OrtApi", ortApi); + } catch (const std::exception& e) { + throw JSError(runtime, "Failed to install ONNX Runtime JSI bindings: " + + std::string(e.what())); + } + + return env; +} + +} // namespace onnxruntimejsi diff --git a/js/react_native/cpp/JsiMain.h b/js/react_native/cpp/JsiMain.h new file mode 100644 index 0000000000000..15c8da084c746 --- /dev/null +++ b/js/react_native/cpp/JsiMain.h @@ -0,0 +1,13 @@ +#pragma once + +#include "Env.h" +#include +#include + +namespace onnxruntimejsi { + +std::shared_ptr +install(facebook::jsi::Runtime& runtime, + std::shared_ptr jsInvoker = nullptr); + +} // namespace onnxruntimejsi diff --git a/js/react_native/cpp/JsiUtils.cpp b/js/react_native/cpp/JsiUtils.cpp new file mode 100644 index 0000000000000..a5c802f36ef30 --- /dev/null +++ b/js/react_native/cpp/JsiUtils.cpp @@ -0,0 +1,32 @@ +#include "JsiUtils.h" + +using namespace facebook::jsi; + +bool isTypedArray(Runtime& runtime, const Object& jsObj) { + if (!jsObj.hasProperty(runtime, "buffer")) + return false; + if (!jsObj.getProperty(runtime, "buffer") + .asObject(runtime) + .isArrayBuffer(runtime)) + return false; + return true; +} + +void forEach(Runtime& runtime, const Object& object, + const std::function& callback) { + auto names = object.getPropertyNames(runtime); + for (size_t i = 0; i < names.size(runtime); i++) { + auto key = + names.getValueAtIndex(runtime, i).asString(runtime).utf8(runtime); + auto value = object.getProperty(runtime, key.c_str()); + callback(key, value, i); + } +} + +void forEach(Runtime& runtime, const Array& array, + const std::function& callback) { + for (size_t i = 0; i < array.size(runtime); i++) { + callback(array.getValueAtIndex(runtime, i), i); + } +} diff --git a/js/react_native/cpp/JsiUtils.h b/js/react_native/cpp/JsiUtils.h new file mode 100644 index 0000000000000..be38d67868df4 --- /dev/null +++ b/js/react_native/cpp/JsiUtils.h @@ -0,0 +1,17 @@ +#pragma once + +#include +#include +#include + +bool isTypedArray(facebook::jsi::Runtime& runtime, + const facebook::jsi::Object& jsObj); + +void forEach( + facebook::jsi::Runtime& runtime, const facebook::jsi::Object& object, + const std::function& callback); + +void forEach( + facebook::jsi::Runtime& runtime, const facebook::jsi::Array& array, + const std::function& callback); diff --git a/js/react_native/cpp/SessionUtils.cpp b/js/react_native/cpp/SessionUtils.cpp new file mode 100644 index 0000000000000..3e6672ec546fb --- /dev/null +++ b/js/react_native/cpp/SessionUtils.cpp @@ -0,0 +1,450 @@ +#include "SessionUtils.h" +#include "JsiUtils.h" +#include "cpu_provider_factory.h" +#include +#include "onnxruntime_cxx_api.h" +#ifdef USE_NNAPI +#include "nnapi_provider_factory.h" +#endif +#ifdef USE_COREML +#include "coreml_provider_factory.h" +#endif + +// Note: Using below syntax for including ort c api and ort extensions headers to resolve a compiling error happened +// in an expo react native ios app when ort extensions enabled (a redefinition error of multiple object types defined +// within ORT C API header). It's an edge case that compiler allows both ort c api headers to be included when #include +// syntax doesn't match. For the case when extensions not enabled, it still requires a onnxruntime prefix directory for +// searching paths. Also in general, it's a convention to use #include for C/C++ headers rather then #import. See: +// https://google.github.io/styleguide/objcguide.html#import-and-include +// https://microsoft.github.io/objc-guide/Headers/ImportAndInclude.html +#if defined(ORT_ENABLE_EXTENSIONS) && defined(__APPLE__) +#include +#endif + +using namespace facebook::jsi; + +namespace onnxruntimejsi { + +const std::vector supportedBackends = { + "cpu", + "xnnpack", +#ifdef USE_COREML + "coreml", +#endif +#ifdef USE_NNAPI + "nnapi", +#endif +#ifdef USE_QNN + "qnn", +#endif +}; + +class ExtendedSessionOptions : public Ort::SessionOptions { + public: + ExtendedSessionOptions() = default; + + void AppendExecutionProvider_CPU(int use_arena) { + Ort::ThrowOnError( + OrtSessionOptionsAppendExecutionProvider_CPU(this->p_, use_arena)); + } + + void AddFreeDimensionOverrideByName(const char* name, int64_t value) { + Ort::ThrowOnError( + Ort::GetApi().AddFreeDimensionOverrideByName(this->p_, name, value)); + } +#ifdef USE_NNAPI + void AppendExecutionProvider_Nnapi(uint32_t nnapi_flags) { + Ort::ThrowOnError( + OrtSessionOptionsAppendExecutionProvider_Nnapi(this->p_, nnapi_flags)); + } +#endif +#ifdef USE_COREML + void AppendExecutionProvider_CoreML(int flags) { + Ort::ThrowOnError( + OrtSessionOptionsAppendExecutionProvider_CoreML(this->p_, flags)); + } +#endif +}; + +void parseSessionOptions(Runtime& runtime, const Value& optionsValue, + Ort::SessionOptions& sessionOptions) { + if (!optionsValue.isObject()) + return; + + auto options = optionsValue.asObject(runtime); + + try { +#ifdef ORT_ENABLE_EXTENSIONS + // ortExtLibPath + if (options.hasProperty(runtime, "ortExtLibPath")) { +#ifdef __APPLE__ + Ort::ThrowOnError(RegisterCustomOps(sessionOptions, OrtGetApiBase())); +#endif +#ifdef __ANDROID__ + auto prop = options.getProperty(runtime, "ortExtLibPath"); + if (prop.isString()) { + std::string libraryPath = prop.asString(runtime).utf8(runtime); + sessionOptions.RegisterCustomOpsLibrary(libraryPath.c_str()); + } +#endif + } +#endif + + // intraOpNumThreads + if (options.hasProperty(runtime, "intraOpNumThreads")) { + auto prop = options.getProperty(runtime, "intraOpNumThreads"); + if (prop.isNumber()) { + int numThreads = static_cast(prop.asNumber()); + if (numThreads > 0) { + sessionOptions.SetIntraOpNumThreads(numThreads); + } + } + } + + // interOpNumThreads + if (options.hasProperty(runtime, "interOpNumThreads")) { + auto prop = options.getProperty(runtime, "interOpNumThreads"); + if (prop.isNumber()) { + int numThreads = static_cast(prop.asNumber()); + if (numThreads > 0) { + sessionOptions.SetInterOpNumThreads(numThreads); + } + } + } + + // freeDimensionOverrides + if (options.hasProperty(runtime, "freeDimensionOverrides")) { + auto prop = options.getProperty(runtime, "freeDimensionOverrides"); + if (prop.isObject()) { + auto overrides = prop.asObject(runtime); + forEach(runtime, overrides, + [&](const std::string& key, const Value& value, size_t index) { + reinterpret_cast(sessionOptions) + .AddFreeDimensionOverrideByName( + key.c_str(), static_cast(value.asNumber())); + }); + } + } + + // graphOptimizationLevel + if (options.hasProperty(runtime, "graphOptimizationLevel")) { + auto prop = options.getProperty(runtime, "graphOptimizationLevel"); + if (prop.isString()) { + std::string level = prop.asString(runtime).utf8(runtime); + if (level == "disabled") { + sessionOptions.SetGraphOptimizationLevel(ORT_DISABLE_ALL); + } else if (level == "basic") { + sessionOptions.SetGraphOptimizationLevel(ORT_ENABLE_BASIC); + } else if (level == "extended") { + sessionOptions.SetGraphOptimizationLevel(ORT_ENABLE_EXTENDED); + } else if (level == "all") { + sessionOptions.SetGraphOptimizationLevel(ORT_ENABLE_ALL); + } + } + } + + // enableCpuMemArena + if (options.hasProperty(runtime, "enableCpuMemArena")) { + auto prop = options.getProperty(runtime, "enableCpuMemArena"); + if (prop.isBool()) { + if (prop.asBool()) { + sessionOptions.EnableCpuMemArena(); + } else { + sessionOptions.DisableCpuMemArena(); + } + } + } + + // enableMemPattern + if (options.hasProperty(runtime, "enableMemPattern")) { + auto prop = options.getProperty(runtime, "enableMemPattern"); + if (prop.isBool()) { + if (prop.asBool()) { + sessionOptions.EnableMemPattern(); + } else { + sessionOptions.DisableMemPattern(); + } + } + } + + // executionMode + if (options.hasProperty(runtime, "executionMode")) { + auto prop = options.getProperty(runtime, "executionMode"); + if (prop.isString()) { + std::string mode = prop.asString(runtime).utf8(runtime); + if (mode == "sequential") { + sessionOptions.SetExecutionMode(ORT_SEQUENTIAL); + } else if (mode == "parallel") { + sessionOptions.SetExecutionMode(ORT_PARALLEL); + } + } + } + + // optimizedModelFilePath + if (options.hasProperty(runtime, "optimizedModelFilePath")) { + auto prop = options.getProperty(runtime, "optimizedModelFilePath"); + if (prop.isString()) { + std::string path = prop.asString(runtime).utf8(runtime); + sessionOptions.SetOptimizedModelFilePath(path.c_str()); + } + } + + // enableProfiling + if (options.hasProperty(runtime, "enableProfiling")) { + auto prop = options.getProperty(runtime, "enableProfiling"); + if (prop.isBool() && prop.asBool()) { + sessionOptions.EnableProfiling("onnxruntime_profile_"); + } + } + + // profileFilePrefix + if (options.hasProperty(runtime, "profileFilePrefix")) { + auto enableProfilingProp = + options.getProperty(runtime, "enableProfiling"); + if (enableProfilingProp.isBool() && enableProfilingProp.asBool()) { + auto prop = options.getProperty(runtime, "profileFilePrefix"); + if (prop.isString()) { + std::string prefix = prop.asString(runtime).utf8(runtime); + sessionOptions.EnableProfiling(prefix.c_str()); + } + } + } + + // logId + if (options.hasProperty(runtime, "logId")) { + auto prop = options.getProperty(runtime, "logId"); + if (prop.isString()) { + std::string logId = prop.asString(runtime).utf8(runtime); + sessionOptions.SetLogId(logId.c_str()); + } + } + + // logSeverityLevel + if (options.hasProperty(runtime, "logSeverityLevel")) { + auto prop = options.getProperty(runtime, "logSeverityLevel"); + if (prop.isNumber()) { + int level = static_cast(prop.asNumber()); + if (level >= 0 && level <= 4) { + sessionOptions.SetLogSeverityLevel(level); + } + } + } + + // externalData + if (options.hasProperty(runtime, "externalData")) { + auto prop = + options.getProperty(runtime, "externalData").asObject(runtime); + if (prop.isArray(runtime)) { + auto externalDataArray = prop.asArray(runtime); + std::vector paths; + std::vector buffs; + std::vector sizes; + forEach( + runtime, externalDataArray, [&](const Value& value, size_t index) { + if (value.isObject()) { + auto externalDataObject = value.asObject(runtime); + if (externalDataObject.hasProperty(runtime, "path")) { + auto pathValue = + externalDataObject.getProperty(runtime, "path"); + if (pathValue.isString()) { + paths.push_back(pathValue.asString(runtime).utf8(runtime)); + } + } + if (externalDataObject.hasProperty(runtime, "data")) { + auto dataValue = + externalDataObject.getProperty(runtime, "data") + .asObject(runtime); + if (isTypedArray(runtime, dataValue)) { + auto arrayBuffer = dataValue.getProperty(runtime, "buffer") + .asObject(runtime) + .getArrayBuffer(runtime); + buffs.push_back( + reinterpret_cast(arrayBuffer.data(runtime))); + sizes.push_back(arrayBuffer.size(runtime)); + } + } + } + }); + sessionOptions.AddExternalInitializersFromFilesInMemory(paths, buffs, + sizes); + } + } + + // executionProviders + if (options.hasProperty(runtime, "executionProviders")) { + auto prop = options.getProperty(runtime, "executionProviders"); + if (prop.isObject() && prop.asObject(runtime).isArray(runtime)) { + auto providers = prop.asObject(runtime).asArray(runtime); + forEach(runtime, providers, [&](const Value& epValue, size_t index) { + std::string epName; + std::unique_ptr providerObj; + if (epValue.isString()) { + epName = epValue.asString(runtime).utf8(runtime); + } else if (epValue.isObject()) { + providerObj = std::make_unique(epValue.asObject(runtime)); + epName = providerObj->getProperty(runtime, "name") + .asString(runtime) + .utf8(runtime); + } + + // Apply execution providers + if (epName == "cpu") { + int use_arena = 0; + if (providerObj && providerObj->hasProperty(runtime, "useArena")) { + auto useArena = providerObj->getProperty(runtime, "useArena"); + if (useArena.isBool() && useArena.asBool()) { + use_arena = 1; + } + } + reinterpret_cast(sessionOptions) + .AppendExecutionProvider_CPU(use_arena); + } else if (epName == "xnnpack") { + sessionOptions.AppendExecutionProvider("XNNPACK"); + } +#ifdef USE_COREML + else if (epName == "coreml") { + int flags = 0; + if (providerObj && + providerObj->hasProperty(runtime, "coreMlFlags")) { + auto flagsValue = + providerObj->getProperty(runtime, "coreMlFlags"); + if (flagsValue.isNumber()) { + flags = static_cast(flagsValue.asNumber()); + } + } + reinterpret_cast(sessionOptions) + .AppendExecutionProvider_CoreML(flags); + } +#endif +#ifdef USE_NNAPI + else if (epName == "nnapi") { + uint32_t nnapi_flags = 0; + if (providerObj && providerObj->hasProperty(runtime, "useFP16")) { + auto useFP16 = providerObj->getProperty(runtime, "useFP16"); + if (useFP16.isBool() && useFP16.asBool()) { + nnapi_flags |= NNAPI_FLAG_USE_FP16; + } + } + if (providerObj && providerObj->hasProperty(runtime, "useNCHW")) { + auto useNCHW = providerObj->getProperty(runtime, "useNCHW"); + if (useNCHW.isBool() && useNCHW.asBool()) { + nnapi_flags |= NNAPI_FLAG_USE_NCHW; + } + } + if (providerObj && + providerObj->hasProperty(runtime, "cpuDisabled")) { + auto cpuDisabled = + providerObj->getProperty(runtime, "cpuDisabled"); + if (cpuDisabled.isBool() && cpuDisabled.asBool()) { + nnapi_flags |= NNAPI_FLAG_CPU_DISABLED; + } + } + if (providerObj && providerObj->hasProperty(runtime, "cpuOnly")) { + auto cpuOnly = providerObj->getProperty(runtime, "cpuOnly"); + if (cpuOnly.isBool() && cpuOnly.asBool()) { + nnapi_flags |= NNAPI_FLAG_CPU_ONLY; + } + } + reinterpret_cast(sessionOptions) + .AppendExecutionProvider_Nnapi(nnapi_flags); + } +#endif +#ifdef USE_QNN + else if (epName == "qnn") { + std::unordered_map options; + if (providerObj && + providerObj->hasProperty(runtime, "backendType")) { + options["backendType"] = + providerObj->getProperty(runtime, "backendType") + .asString(runtime) + .utf8(runtime); + } + if (providerObj && + providerObj->hasProperty(runtime, "backendPath")) { + options["backendPath"] = + providerObj->getProperty(runtime, "backendPath") + .asString(runtime) + .utf8(runtime); + } + if (providerObj && + providerObj->hasProperty(runtime, "enableFp16Precision")) { + auto enableFp16Precision = + providerObj->getProperty(runtime, "enableFp16Precision"); + if (enableFp16Precision.isBool() && + enableFp16Precision.asBool()) { + options["enableFp16Precision"] = "1"; + } else { + options["enableFp16Precision"] = "0"; + } + } + sessionOptions.AppendExecutionProvider("QNN", options); + } +#endif + else { + throw JSError(runtime, "Unsupported execution provider: " + epName); + } + }); + } + } + } catch (const JSError& e) { + throw e; + } catch (const std::exception& e) { + throw JSError(runtime, + "Failed to parse session options: " + std::string(e.what())); + } +} + +void parseRunOptions(Runtime& runtime, const Value& optionsValue, + Ort::RunOptions& runOptions) { + if (!optionsValue.isObject()) + return; + + auto options = optionsValue.asObject(runtime); + + try { + // tag + if (options.hasProperty(runtime, "tag")) { + auto prop = options.getProperty(runtime, "tag"); + if (prop.isString()) { + std::string tag = prop.asString(runtime).utf8(runtime); + runOptions.SetRunTag(tag.c_str()); + } + } + + // logSeverityLevel + if (options.hasProperty(runtime, "logSeverityLevel")) { + auto prop = options.getProperty(runtime, "logSeverityLevel"); + if (prop.isNumber()) { + int level = static_cast(prop.asNumber()); + if (level >= 0 && level <= 4) { + runOptions.SetRunLogSeverityLevel(level); + } + } + } + + // logVerbosityLevel + if (options.hasProperty(runtime, "logVerbosityLevel")) { + auto prop = options.getProperty(runtime, "logVerbosityLevel"); + if (prop.isNumber()) { + int level = static_cast(prop.asNumber()); + if (level >= 0) { + runOptions.SetRunLogVerbosityLevel(level); + } + } + } + + // terminate + if (options.hasProperty(runtime, "terminate")) { + auto prop = options.getProperty(runtime, "terminate"); + if (prop.isBool() && prop.asBool()) { + runOptions.SetTerminate(); + } + } + + } catch (const std::exception& e) { + throw JSError(runtime, + "Failed to parse run options: " + std::string(e.what())); + } +} + +} // namespace onnxruntimejsi diff --git a/js/react_native/cpp/SessionUtils.h b/js/react_native/cpp/SessionUtils.h new file mode 100644 index 0000000000000..4dafcd01ab845 --- /dev/null +++ b/js/react_native/cpp/SessionUtils.h @@ -0,0 +1,18 @@ +#pragma once + +#include +#include "onnxruntime_cxx_api.h" + +namespace onnxruntimejsi { + +extern const std::vector supportedBackends; + +void parseSessionOptions(facebook::jsi::Runtime& runtime, + const facebook::jsi::Value& optionsValue, + Ort::SessionOptions& sessionOptions); + +void parseRunOptions(facebook::jsi::Runtime& runtime, + const facebook::jsi::Value& optionsValue, + Ort::RunOptions& runOptions); + +} // namespace onnxruntimejsi diff --git a/js/react_native/cpp/TensorUtils.cpp b/js/react_native/cpp/TensorUtils.cpp new file mode 100644 index 0000000000000..658e98491e17b --- /dev/null +++ b/js/react_native/cpp/TensorUtils.cpp @@ -0,0 +1,236 @@ +#include "TensorUtils.h" +#include "JsiUtils.h" +#include +#include +#include + +using namespace facebook::jsi; + +namespace onnxruntimejsi { + +static const std::unordered_map + dataTypeToStringMap = { + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, "float32"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8, "uint8"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8, "int8"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16, "uint16"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16, "int16"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32, "int32"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64, "int64"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING, "string"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL, "bool"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16, "float16"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE, "float64"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32, "uint32"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64, "uint64"}, +}; + +static const std::unordered_map + elementSizeMap = { + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, sizeof(float)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8, sizeof(uint8_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8, sizeof(int8_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16, sizeof(uint16_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16, sizeof(int16_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32, sizeof(int32_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64, sizeof(int64_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING, sizeof(char*)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL, sizeof(bool)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16, 2}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE, sizeof(double)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32, sizeof(uint32_t)}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64, sizeof(uint64_t)}, +}; + +static const std::unordered_map + dataTypeToTypedArrayMap = { + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT, "Float32Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_DOUBLE, "Float64Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT32, "Int32Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT64, "BigInt64Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT32, "Uint32Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT64, "BigUint64Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT8, "Uint8Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT8, "Int8Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_UINT16, "Uint16Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_INT16, "Int16Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_FLOAT16, "Uint16Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING, "Array"}, + {ONNX_TENSOR_ELEMENT_DATA_TYPE_BOOL, "Uint8Array"}, +}; + +inline size_t getElementSize(ONNXTensorElementDataType dataType) { + auto it = elementSizeMap.find(dataType); + if (it != elementSizeMap.end()) { + return it->second; + } + throw std::invalid_argument("Unsupported or unknown tensor data type: " + + std::to_string(static_cast(dataType))); +} + +bool TensorUtils::isTensor(Runtime& runtime, const Object& obj) { + return obj.hasProperty(runtime, "cpuData") && + obj.hasProperty(runtime, "dims") && obj.hasProperty(runtime, "type"); +} + +inline Object getTypedArrayConstructor(Runtime& runtime, + const ONNXTensorElementDataType type) { + auto it = dataTypeToTypedArrayMap.find(type); + if (it != dataTypeToTypedArrayMap.end()) { + auto prop = runtime.global().getProperty(runtime, it->second); + if (prop.isObject()) { + return prop.asObject(runtime); + } else { + throw JSError(runtime, "TypedArray constructor not found: " + + std::string(it->second)); + } + } + throw JSError(runtime, + "Unsupported tensor data type for TypedArray creation: " + + std::to_string(static_cast(type))); +} + +size_t getElementCount(const std::vector& shape) { + size_t count = 1; + for (auto dim : shape) { + count *= dim; + } + return count; +} + +Ort::Value +TensorUtils::createOrtValueFromJSTensor(Runtime& runtime, + const Object& tensorObj, + const Ort::MemoryInfo& memoryInfo) { + if (!isTensor(runtime, tensorObj)) { + throw JSError( + runtime, + "Invalid tensor object: missing cpuData, dims, or type properties"); + } + + auto dataProperty = tensorObj.getProperty(runtime, "cpuData"); + auto dimsProperty = tensorObj.getProperty(runtime, "dims"); + auto typeProperty = tensorObj.getProperty(runtime, "type"); + + if (!dimsProperty.isObject() || + !dimsProperty.asObject(runtime).isArray(runtime)) { + throw JSError(runtime, "Tensor dims must be array"); + } + + if (!typeProperty.isString()) { + throw JSError(runtime, "Tensor type must be string"); + } + + ONNXTensorElementDataType type = ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED; + auto typeStr = typeProperty.asString(runtime).utf8(runtime); + for (auto it = dataTypeToStringMap.begin(); it != dataTypeToStringMap.end(); + ++it) { + if (it->second == typeStr) { + type = it->first; + break; + } + } + if (type == ONNX_TENSOR_ELEMENT_DATA_TYPE_UNDEFINED) { + throw JSError(runtime, "Unsupported tensor data type: " + typeStr); + } + + void* data = nullptr; + auto dataObj = dataProperty.asObject(runtime); + + if (type == ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING) { + if (!dataObj.isArray(runtime)) { + throw JSError(runtime, "Tensor data must be an array of strings"); + } + auto array = dataObj.asArray(runtime); + auto size = array.size(runtime); + data = new char*[size]; + for (size_t i = 0; i < size; ++i) { + auto item = array.getValueAtIndex(runtime, i); + static_cast(data)[i] = + strdup(item.toString(runtime).utf8(runtime).c_str()); + } + } else { + if (!isTypedArray(runtime, dataObj)) { + throw JSError(runtime, "Tensor data must be a TypedArray"); + } + auto buffer = dataObj.getProperty(runtime, "buffer") + .asObject(runtime) + .getArrayBuffer(runtime); + data = buffer.data(runtime); + } + + std::vector shape; + auto dimsArray = dimsProperty.asObject(runtime).asArray(runtime); + for (size_t i = 0; i < dimsArray.size(runtime); ++i) { + auto dim = dimsArray.getValueAtIndex(runtime, i); + if (dim.isNumber()) { + shape.push_back(static_cast(dim.asNumber())); + } + } + + return Ort::Value::CreateTensor(memoryInfo, data, + getElementCount(shape) * getElementSize(type), + shape.data(), shape.size(), type); +} + +Object +TensorUtils::createJSTensorFromOrtValue(Runtime& runtime, Ort::Value& ortValue, + const Object& tensorConstructor) { + auto typeInfo = ortValue.GetTensorTypeAndShapeInfo(); + auto shape = typeInfo.GetShape(); + auto elementType = typeInfo.GetElementType(); + + std::string typeStr; + auto it = dataTypeToStringMap.find(elementType); + if (it != dataTypeToStringMap.end()) { + typeStr = it->second; + } else { + throw JSError(runtime, + "Unsupported tensor data type for TypedArray creation: " + + std::to_string(static_cast(elementType))); + } + + auto dimsArray = Array(runtime, shape.size()); + for (size_t j = 0; j < shape.size(); ++j) { + dimsArray.setValueAtIndex(runtime, j, Value(static_cast(shape[j]))); + } + + if (elementType != ONNX_TENSOR_ELEMENT_DATA_TYPE_STRING) { + void* rawData = ortValue.GetTensorMutableRawData(); + size_t elementCount = + ortValue.GetTensorTypeAndShapeInfo().GetElementCount(); + size_t elementSize = getElementSize(elementType); + size_t dataSize = elementCount * elementSize; + + auto typedArrayCtor = getTypedArrayConstructor(runtime, elementType); + auto typedArrayInstance = + typedArrayCtor.asFunction(runtime).callAsConstructor( + runtime, static_cast(elementCount)); + + auto buffer = typedArrayInstance.asObject(runtime) + .getProperty(runtime, "buffer") + .asObject(runtime) + .getArrayBuffer(runtime); + memcpy(buffer.data(runtime), rawData, dataSize); + + auto tensorInstance = + tensorConstructor.asFunction(runtime).callAsConstructor( + runtime, typeStr, typedArrayInstance, dimsArray); + + return tensorInstance.asObject(runtime); + } else { + auto strArray = Array(runtime, shape.size()); + for (size_t j = 0; j < shape.size(); ++j) { + strArray.setValueAtIndex( + runtime, j, Value(runtime, String::createFromUtf8(runtime, ""))); + } + + auto tensorInstance = + tensorConstructor.asFunction(runtime).callAsConstructor( + runtime, typeStr, strArray, dimsArray); + + return tensorInstance.asObject(runtime); + } +} + +} // namespace onnxruntimejsi diff --git a/js/react_native/cpp/TensorUtils.h b/js/react_native/cpp/TensorUtils.h new file mode 100644 index 0000000000000..5361f5cb1101f --- /dev/null +++ b/js/react_native/cpp/TensorUtils.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include "onnxruntime_cxx_api.h" +#include +#include + +namespace onnxruntimejsi { + +class TensorUtils { + public: + static Ort::Value + createOrtValueFromJSTensor(facebook::jsi::Runtime& runtime, + const facebook::jsi::Object& tensorObj, + const Ort::MemoryInfo& memoryInfo); + + static facebook::jsi::Object + createJSTensorFromOrtValue(facebook::jsi::Runtime& runtime, + Ort::Value& ortValue, + const facebook::jsi::Object& tensorConstructor); + + static bool isTensor(facebook::jsi::Runtime& runtime, + const facebook::jsi::Object& obj); +}; + +} // namespace onnxruntimejsi diff --git a/js/react_native/e2e/.detoxrc.js b/js/react_native/e2e/.detoxrc.js index e886a363d378b..f286940f5af7d 100644 --- a/js/react_native/e2e/.detoxrc.js +++ b/js/react_native/e2e/.detoxrc.js @@ -14,13 +14,13 @@ module.exports = { type: 'ios.app', binaryPath: 'ios/build/Build/Products/Debug-iphonesimulator/OnnxruntimeModuleExample.app', build: - 'xcodebuild ARCHS=x86_64 ONLY_ACTIVE_ARCH=NO -workspace ios/OnnxruntimeModuleExample.xcworkspace -scheme OnnxruntimeModuleExample -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build', + 'xcodebuild ARCHS=arm64 ONLY_ACTIVE_ARCH=NO -workspace ios/OnnxruntimeModuleExample.xcworkspace -scheme OnnxruntimeModuleExample -configuration Debug -sdk iphonesimulator -derivedDataPath ios/build', }, 'ios.release': { type: 'ios.app', binaryPath: 'ios/build/Build/Products/Release-iphonesimulator/OnnxruntimeModuleExample.app', build: - 'xcodebuild ARCHS=x86_64 ONLY_ACTIVE_ARCH=NO -workspace ios/OnnxruntimeModuleExample.xcworkspace -scheme OnnxruntimeModuleExample -configuration Release -sdk iphonesimulator -derivedDataPath ios/build', + 'xcodebuild ARCHS=arm64 ONLY_ACTIVE_ARCH=NO -workspace ios/OnnxruntimeModuleExample.xcworkspace -scheme OnnxruntimeModuleExample -configuration Release -sdk iphonesimulator -derivedDataPath ios/build', }, 'android.debug': { type: 'android.apk', @@ -38,8 +38,15 @@ module.exports = { simulator: { type: 'ios.simulator', device: { - type: 'iPhone 14', - os: 'iOS 16.4', + type: 'iPhone 15', + os: 'iOS 17.4', + }, + }, + simulator_ios_18_6: { + type: 'ios.simulator', + device: { + type: 'iPhone 16', + os: 'iOS 18.6', }, }, attached: { @@ -64,6 +71,10 @@ module.exports = { device: 'simulator', app: 'ios.release', }, + 'ios.sim_18_6.release': { + device: 'simulator_ios_18_6', + app: 'ios.release', + }, 'android.att.debug': { device: 'attached', app: 'android.debug', diff --git a/js/react_native/e2e/android/app/build.gradle b/js/react_native/e2e/android/app/build.gradle index 68eaacc1908c3..54d5e55a209d8 100644 --- a/js/react_native/e2e/android/app/build.gradle +++ b/js/react_native/e2e/android/app/build.gradle @@ -1,8 +1,7 @@ apply plugin: "com.android.application" +apply plugin: "org.jetbrains.kotlin.android" apply plugin: "com.facebook.react" -import com.android.build.OutputFile - /** * This is the configuration block to customize your React Native Android app. * By default you don't need to apply any configuration, just uncomment the lines you need. @@ -13,8 +12,8 @@ react { // root = file("../") // The folder where the react-native NPM package is. Default is ../node_modules/react-native // reactNativeDir = file("../node_modules/react-native") - // The folder where the react-native Codegen package is. Default is ../node_modules/react-native-codegen - // codegenDir = file("../node_modules/react-native-codegen") + // The folder where the react-native Codegen package is. Default is ../node_modules/@react-native/codegen + // codegenDir = file("../node_modules/@react-native/codegen") // The cli.js file which is the React Native CLI entrypoint. Default is ../node_modules/react-native/cli.js // cliFile = file("../node_modules/react-native/cli.js") @@ -52,14 +51,6 @@ react { // hermesFlags = ["-O", "-output-source-map"] } -/** - * Set this to true to create four separate APKs instead of one, - * one for each native architecture. This is useful if you don't - * use App Bundles (https://developer.android.com/guide/app-bundle/) - * and want to have separate APKs to upload to the Play Store. - */ -def enableSeparateBuildPerCPUArchitecture = false - /** * Set this to true to Run Proguard on Release builds to minify the Java bytecode. */ @@ -78,20 +69,12 @@ def enableProguardInReleaseBuilds = false */ def jscFlavor = 'org.webkit:android-jsc:+' -/** - * Private function to get the list of Native Architectures you want to build. - * This reads the value from reactNativeArchitectures in your gradle.properties - * file and works together with the --active-arch-only flag of react-native run-android. - */ -def reactNativeArchitectures() { - def value = project.getProperties().get("reactNativeArchitectures") - return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"] -} android { + buildToolsVersion rootProject.ext.buildToolsVersion compileSdkVersion rootProject.ext.compileSdkVersion - namespace "com.example.reactnativeonnxruntimemodule" + namespace "com.reactnativeonnxruntimemodule" compileOptions { sourceCompatibility JavaVersion.VERSION_17 targetCompatibility JavaVersion.VERSION_17 @@ -99,9 +82,13 @@ android { packagingOptions { pickFirst '**/libc++_shared.so' pickFirst '**/libfbjni.so' + excludes = [ + "META-INF", + "META-INF/**", + ] } defaultConfig { - applicationId "com.example.reactnativeonnxruntimemodule" + applicationId "com.reactnativeonnxruntimemodule" minSdkVersion rootProject.ext.minSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion versionCode 1 @@ -109,14 +96,6 @@ android { testBuildType System.getProperty('testBuildType', 'debug') testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } - splits { - abi { - reset() - enable enableSeparateBuildPerCPUArchitecture - universalApk false // If true, also generate a universal APK - include "armeabi-v7a", "x86", "arm64-v8a", "x86_64" - } - } signingConfigs { debug { storeFile rootProject.file('debug.keystore') @@ -135,48 +114,16 @@ android { proguardFile "${rootProject.projectDir}/../node_modules/detox/android/detox/proguard-rules-app.pro" } } - // applicationVariants are e.g. debug, release - applicationVariants.all { variant -> - variant.outputs.each { output -> - // For each separate APK per architecture, set a unique version code as described here: - // https://developer.android.com/studio/build/configure-apk-splits.html - def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4] - def abi = output.getFilter(OutputFile.ABI) - if (abi != null) { // null for the universal-debug, universal-release variants - output.versionCodeOverride = - versionCodes.get(abi) * 1048576 + defaultConfig.versionCode - } - - } - } -} - -repositories { - flatDir { - dir 'libs' - } } dependencies { androidTestImplementation('com.wix:detox:+') implementation 'androidx.appcompat:appcompat:1.1.0' - implementation fileTree(dir: "libs", include: ["*.jar"]) // The version of react-native is set by the React Native Gradle Plugin implementation("com.facebook.react:react-android") - - implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.0.0" + implementation("com.facebook.react:flipper-integration") implementation 'androidx.test.ext:junit:1.1.5' - debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") { - exclude group:'com.facebook.fbjni' - } - debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") { - exclude group:'com.facebook.flipper' - exclude group:'com.squareup.okhttp3', module:'okhttp' - } - debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") { - exclude group:'com.facebook.flipper' - } if (hermesEnabled.toBoolean()) { implementation("com.facebook.react:hermes-android") @@ -188,9 +135,7 @@ dependencies { androidTestImplementation "androidx.test:runner:1.5.2" androidTestImplementation "androidx.test:rules:1.5.0" - implementation project(':onnxruntime-react-native') - // specify ORT dependency here so it can be found in libs flatDir repository - implementation "com.microsoft.onnxruntime:onnxruntime-android:latest.integration@aar" + implementation (project(':onnxruntime-react-native')) } // Run this once to be able to run the application with BUCK diff --git a/js/react_native/e2e/android/app/src/androidTest/java/com/example/reactnativeonnxruntimemodule/DetoxTest.java b/js/react_native/e2e/android/app/src/androidTest/java/com/reactnativeonnxruntimemodule/DetoxTest.java similarity index 96% rename from js/react_native/e2e/android/app/src/androidTest/java/com/example/reactnativeonnxruntimemodule/DetoxTest.java rename to js/react_native/e2e/android/app/src/androidTest/java/com/reactnativeonnxruntimemodule/DetoxTest.java index 9425e1365fedf..4a5142a60ebc6 100644 --- a/js/react_native/e2e/android/app/src/androidTest/java/com/example/reactnativeonnxruntimemodule/DetoxTest.java +++ b/js/react_native/e2e/android/app/src/androidTest/java/com/reactnativeonnxruntimemodule/DetoxTest.java @@ -2,7 +2,7 @@ // Detox requires the project to have a single dummy native Android Test with some special content, // which will be picked up by the testRunner. -package com.example.reactnativeonnxruntimemodule; +package com.reactnativeonnxruntimemodule; import android.content.Intent; diff --git a/js/react_native/e2e/android/app/src/debug/AndroidManifest.xml b/js/react_native/e2e/android/app/src/debug/AndroidManifest.xml deleted file mode 100644 index fa26aa56e1c14..0000000000000 --- a/js/react_native/e2e/android/app/src/debug/AndroidManifest.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - - - - diff --git a/js/react_native/e2e/android/app/src/debug/java/com/example/reactnativeonnxruntimemodule/ReactNativeFlipper.java b/js/react_native/e2e/android/app/src/debug/java/com/example/reactnativeonnxruntimemodule/ReactNativeFlipper.java deleted file mode 100644 index 3cacb2d5d4bf0..0000000000000 --- a/js/react_native/e2e/android/app/src/debug/java/com/example/reactnativeonnxruntimemodule/ReactNativeFlipper.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - *

This source code is licensed under the MIT license found in the LICENSE file in the root - * directory of this source tree. - */ -package com.reactnativeonnxruntimemodule; - -import android.content.Context; -import com.facebook.flipper.android.AndroidFlipperClient; -import com.facebook.flipper.android.utils.FlipperUtils; -import com.facebook.flipper.core.FlipperClient; -import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin; -import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin; -import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin; -import com.facebook.flipper.plugins.inspector.DescriptorMapping; -import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin; -import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor; -import com.facebook.flipper.plugins.network.NetworkFlipperPlugin; -import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin; -import com.facebook.react.ReactInstanceEventListener; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.bridge.ReactContext; -import com.facebook.react.modules.network.NetworkingModule; -import okhttp3.OkHttpClient; - -/** - * Class responsible of loading Flipper inside your React Native application. This is the debug - * flavor of it. Here you can add your own plugins and customize the Flipper setup. - */ -public class ReactNativeFlipper { - public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { - if (FlipperUtils.shouldEnableFlipper(context)) { - final FlipperClient client = AndroidFlipperClient.getInstance(context); - - client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults())); - client.addPlugin(new DatabasesFlipperPlugin(context)); - client.addPlugin(new SharedPreferencesFlipperPlugin(context)); - client.addPlugin(CrashReporterPlugin.getInstance()); - - NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin(); - NetworkingModule.setCustomClientBuilder( - new NetworkingModule.CustomClientBuilder() { - @Override - public void apply(OkHttpClient.Builder builder) { - builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); - } - }); - client.addPlugin(networkFlipperPlugin); - client.start(); - - // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized - // Hence we run if after all native modules have been initialized - ReactContext reactContext = reactInstanceManager.getCurrentReactContext(); - if (reactContext == null) { - reactInstanceManager.addReactInstanceEventListener( - new ReactInstanceEventListener() { - @Override - public void onReactContextInitialized(ReactContext reactContext) { - reactInstanceManager.removeReactInstanceEventListener(this); - reactContext.runOnNativeModulesQueueThread( - new Runnable() { - @Override - public void run() { - client.addPlugin(new FrescoFlipperPlugin()); - } - }); - } - }); - } else { - client.addPlugin(new FrescoFlipperPlugin()); - } - } - } -} \ No newline at end of file diff --git a/js/react_native/e2e/android/app/src/main/AndroidManifest.xml b/js/react_native/e2e/android/app/src/main/AndroidManifest.xml index d219c7c18f3c2..a44d8099522a9 100644 --- a/js/react_native/e2e/android/app/src/main/AndroidManifest.xml +++ b/js/react_native/e2e/android/app/src/main/AndroidManifest.xml @@ -24,7 +24,6 @@ - diff --git a/js/react_native/android/src/androidTest/res/raw/test_types_bool.onnx b/js/react_native/e2e/android/app/src/main/assets/test_types_bool.onnx similarity index 100% rename from js/react_native/android/src/androidTest/res/raw/test_types_bool.onnx rename to js/react_native/e2e/android/app/src/main/assets/test_types_bool.onnx diff --git a/js/react_native/android/src/androidTest/res/raw/test_types_double.onnx b/js/react_native/e2e/android/app/src/main/assets/test_types_double.onnx similarity index 100% rename from js/react_native/android/src/androidTest/res/raw/test_types_double.onnx rename to js/react_native/e2e/android/app/src/main/assets/test_types_double.onnx diff --git a/js/react_native/e2e/android/app/src/main/assets/test_types_float.ort b/js/react_native/e2e/android/app/src/main/assets/test_types_float.ort new file mode 100644 index 0000000000000..2e8377a4afc1f Binary files /dev/null and b/js/react_native/e2e/android/app/src/main/assets/test_types_float.ort differ diff --git a/js/react_native/e2e/android/app/src/main/assets/test_types_float16.ort b/js/react_native/e2e/android/app/src/main/assets/test_types_float16.ort new file mode 100644 index 0000000000000..c691bc264d7ca Binary files /dev/null and b/js/react_native/e2e/android/app/src/main/assets/test_types_float16.ort differ diff --git a/js/react_native/e2e/android/app/src/main/assets/test_types_int32.ort b/js/react_native/e2e/android/app/src/main/assets/test_types_int32.ort new file mode 100644 index 0000000000000..15d3cc1f8903f Binary files /dev/null and b/js/react_native/e2e/android/app/src/main/assets/test_types_int32.ort differ diff --git a/js/react_native/e2e/android/app/src/main/assets/test_types_int64.ort b/js/react_native/e2e/android/app/src/main/assets/test_types_int64.ort new file mode 100644 index 0000000000000..e0cbaa9d86392 Binary files /dev/null and b/js/react_native/e2e/android/app/src/main/assets/test_types_int64.ort differ diff --git a/js/react_native/e2e/android/app/src/main/assets/test_types_int8.ort b/js/react_native/e2e/android/app/src/main/assets/test_types_int8.ort new file mode 100644 index 0000000000000..9d2ef52138cfc Binary files /dev/null and b/js/react_native/e2e/android/app/src/main/assets/test_types_int8.ort differ diff --git a/js/react_native/e2e/android/app/src/main/assets/test_types_uint8.ort b/js/react_native/e2e/android/app/src/main/assets/test_types_uint8.ort new file mode 100644 index 0000000000000..a0a5d6a1d0177 Binary files /dev/null and b/js/react_native/e2e/android/app/src/main/assets/test_types_uint8.ort differ diff --git a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainActivity.java b/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainActivity.java deleted file mode 100644 index e2e48633ddb6e..0000000000000 --- a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainActivity.java +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.example.reactnativeonnxruntimemodule; - -import com.facebook.react.ReactActivity; - -public class MainActivity extends ReactActivity { - /** - * Returns the name of the main component registered from JavaScript. This is used to schedule - * rendering of the component. - */ - @Override - protected String getMainComponentName() { - return "OnnxruntimeModuleExample"; - } -} diff --git a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainApplication.java b/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainApplication.java deleted file mode 100644 index 2c59e5dd3d3b1..0000000000000 --- a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MainApplication.java +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT License. - -package com.example.reactnativeonnxruntimemodule; - -import ai.onnxruntime.reactnative.OnnxruntimePackage; -import android.app.Application; -import android.content.Context; -import com.facebook.react.PackageList; -import com.facebook.react.ReactApplication; -import com.facebook.react.ReactInstanceManager; -import com.facebook.react.ReactNativeHost; -import com.facebook.react.ReactPackage; -import com.facebook.soloader.SoLoader; -import java.lang.reflect.InvocationTargetException; -import java.util.List; - -public class MainApplication extends Application implements ReactApplication { - private static Context appContext; - - private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) { - @Override - public boolean getUseDeveloperSupport() { - return BuildConfig.DEBUG; - } - - @Override - protected List getPackages() { - @SuppressWarnings("UnnecessaryLocalVariable") List packages = new PackageList(this).getPackages(); - packages.add(new DataHandlerPackage()); - - return packages; - } - - @Override - protected String getJSMainModuleName() { - return "index"; - } - }; - - @Override - public ReactNativeHost getReactNativeHost() { - return mReactNativeHost; - } - - @Override - public void onCreate() { - super.onCreate(); - appContext = getApplicationContext(); - SoLoader.init(this, /* native exopackage */ false); - initializeFlipper( - this, getReactNativeHost().getReactInstanceManager()); // Remove this line if you don't want Flipper enabled - } - - public static Context getAppContext() { return appContext; } - - /** - * Loads Flipper in React Native templates. - * - * @param context - */ - private static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) { - if (BuildConfig.DEBUG) { - try { - /* - We use reflection here to pick up the class that initializes Flipper, - since Flipper library is not available in release mode - */ - Class aClass = Class.forName("com.onnxruntimereactnativeExample.ReactNativeFlipper"); - aClass.getMethod("initializeFlipper", Context.class, ReactInstanceManager.class) - .invoke(null, context, reactInstanceManager); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } catch (IllegalAccessException e) { - e.printStackTrace(); - } catch (InvocationTargetException e) { - e.printStackTrace(); - } - } - } -} diff --git a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/DataHandlerPackage.java b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/DataHandlerPackage.java similarity index 94% rename from js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/DataHandlerPackage.java rename to js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/DataHandlerPackage.java index fa321e15c615b..adfd4e0bb755a 100644 --- a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/DataHandlerPackage.java +++ b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/DataHandlerPackage.java @@ -1,7 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -package com.example.reactnativeonnxruntimemodule; +package com.reactnativeonnxruntimemodule; import com.facebook.react.ReactPackage; import com.facebook.react.bridge.NativeModule; diff --git a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MNISTDataHandler.java b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTDataHandler.java similarity index 95% rename from js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MNISTDataHandler.java rename to js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTDataHandler.java index a458901b5314c..72f27b3291a8c 100644 --- a/js/react_native/e2e/android/app/src/main/java/com/example/reactnativeonnxruntimemodule/MNISTDataHandler.java +++ b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTDataHandler.java @@ -1,12 +1,10 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. -package com.example.reactnativeonnxruntimemodule; +package com.reactnativeonnxruntimemodule; import static java.util.stream.Collectors.joining; -import ai.onnxruntime.reactnative.OnnxruntimeModule; -import ai.onnxruntime.reactnative.TensorHelper; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; @@ -114,7 +112,7 @@ private WritableMap preprocess(String uri) throws Exception { final int imageHeight = 28; final int imageWidth = 28; - InputStream is = MainApplication.getAppContext().getContentResolver().openInputStream(Uri.parse(uri)); + InputStream is = reactContext.getContentResolver().openInputStream(Uri.parse(uri)); BufferedInputStream bis = new BufferedInputStream(is); byte[] imageArray = new byte[bis.available()]; bis.read(imageArray); @@ -149,7 +147,7 @@ private WritableMap preprocess(String uri) throws Exception { inputTensorMap.putArray("dims", dims); // type - inputTensorMap.putString("type", TensorHelper.JsTensorTypeFloat); + inputTensorMap.putString("type", "float32"); // data encoded as Base64 imageByteBuffer.rewind(); diff --git a/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTPackage.java b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTPackage.java new file mode 100644 index 0000000000000..5b09a4b8aeea1 --- /dev/null +++ b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MNISTPackage.java @@ -0,0 +1,28 @@ +package com.reactnativeonnxruntimemodule; + +import com.facebook.react.ReactPackage; +import com.facebook.react.bridge.NativeModule; +import com.facebook.react.bridge.ReactApplicationContext; +import com.facebook.react.uimanager.ViewManager; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +public class MNISTPackage implements ReactPackage { + @Override + public List createNativeModules(ReactApplicationContext reactContext) { + List modules = new ArrayList<>(); + try { + modules.add(new MNISTDataHandler(reactContext)); + } catch (Exception e) { + throw new RuntimeException("Failed to initialize MNISTDataHandler", e); + } + return modules; + } + + @Override + public List createViewManagers(ReactApplicationContext reactContext) { + return Collections.emptyList(); + } +} \ No newline at end of file diff --git a/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainActivity.kt b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainActivity.kt new file mode 100644 index 0000000000000..e572f50dfdab1 --- /dev/null +++ b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainActivity.kt @@ -0,0 +1,22 @@ +package com.reactnativeonnxruntimemodule + +import com.facebook.react.ReactActivity +import com.facebook.react.ReactActivityDelegate +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.fabricEnabled +import com.facebook.react.defaults.DefaultReactActivityDelegate + +class MainActivity : ReactActivity() { + + /** + * Returns the name of the main component registered from JavaScript. This is used to schedule + * rendering of the component. + */ + override fun getMainComponentName(): String = "OnnxruntimeModuleExample" + + /** + * Returns the instance of the [ReactActivityDelegate]. We use [DefaultReactActivityDelegate] + * which allows you to enable New Architecture with a single boolean flags [fabricEnabled] + */ + override fun createReactActivityDelegate(): ReactActivityDelegate = + DefaultReactActivityDelegate(this, mainComponentName, fabricEnabled) +} \ No newline at end of file diff --git a/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainApplication.kt b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainApplication.kt new file mode 100644 index 0000000000000..f28660d9915e5 --- /dev/null +++ b/js/react_native/e2e/android/app/src/main/java/com/reactnativeonnxruntimemodule/MainApplication.kt @@ -0,0 +1,53 @@ +package com.reactnativeonnxruntimemodule + +import android.app.Application +import android.content.Context +import com.facebook.react.PackageList +import com.facebook.react.ReactApplication +import com.facebook.react.ReactHost +import com.facebook.react.ReactNativeHost +import com.facebook.react.ReactPackage +import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load +import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost +import com.facebook.react.defaults.DefaultReactNativeHost +import com.facebook.react.flipper.ReactNativeFlipper +import com.facebook.soloader.SoLoader + +class MainApplication : Application(), ReactApplication { + companion object { + private lateinit var appContext: Context + + fun getAppContext(): Context { + return appContext + } + } + override val reactNativeHost: ReactNativeHost = + object : DefaultReactNativeHost(this) { + override fun getPackages(): List = + PackageList(this).packages.apply { + // Packages that cannot be autolinked yet can be added manually here, for example: + // add(MyReactNativePackage()) + add(MNISTPackage()) + } + + override fun getJSMainModuleName(): String = "index" + + override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG + + override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED + override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED + } + + override val reactHost: ReactHost + get() = getDefaultReactHost(this.applicationContext, reactNativeHost) + override fun onCreate() { + super.onCreate() + appContext = applicationContext + SoLoader.init(this, false) + if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) { + // If you opted-in for the New Architecture, we load the native entry point for this app. + load() + } + ReactNativeFlipper.initializeFlipper(this, reactNativeHost.reactInstanceManager) + } +} \ No newline at end of file diff --git a/js/react_native/e2e/android/build.gradle b/js/react_native/e2e/android/build.gradle index 1178791f48982..8d1f9d59d8649 100644 --- a/js/react_native/e2e/android/build.gradle +++ b/js/react_native/e2e/android/build.gradle @@ -2,21 +2,23 @@ buildscript { ext { - buildToolsVersion = "33.0.0" + buildToolsVersion = "34.0.0" minSdkVersion = 24 compileSdkVersion = 34 targetSdkVersion = 34 - kotlinVersion = "1.5.30" + kotlinVersion = "1.8.0" } repositories { google() mavenCentral() } dependencies { - classpath('com.android.tools.build:gradle:7.2.1') - classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlinVersion") + classpath('com.android.tools.build:gradle:7.4.2') + classpath("org.jetbrains.kotlin:kotlin-gradle-plugin") classpath("com.facebook.react:react-native-gradle-plugin") + + // NOTE: Do not place your application dependencies here; they belong // in the individual module build.gradle files } @@ -37,9 +39,15 @@ allprojects { // Add Detox as a precompiled native dependency url("$rootDir/../node_modules/detox/Detox-android") } + maven { + // Local onnxruntime-android package + url("$rootDir/app/libs") + } google() mavenCentral() maven { url 'https://www.jitpack.io' } } } + +apply plugin: "com.facebook.react.rootproject" diff --git a/js/react_native/e2e/android/gradle.properties b/js/react_native/e2e/android/gradle.properties index a2541138f1ba9..a8840c7b7d214 100644 --- a/js/react_native/e2e/android/gradle.properties +++ b/js/react_native/e2e/android/gradle.properties @@ -19,9 +19,9 @@ android.useAndroidX=true android.enableJetifier=true -FLIPPER_VERSION=0.125.0 -org.gradle.jvmargs=-Xmx4096M - +org.gradle.jvmargs=-Xmx8192m -XX:MaxMetaspaceSize=2048m -Dkotlin.daemon.jvm.options=-Xmx8192m # Use this property to enable or disable the Hermes JS engine. # If set to false, you will be using JSC instead. -hermesEnabled=false +hermesEnabled=true + +reactNativeArchitectures=x86_64 diff --git a/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.jar b/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.jar index 62d4c053550b9..ccebba7710dea 100644 Binary files a/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.jar and b/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.jar differ diff --git a/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.properties b/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.properties index f7189a776c1a0..d11cdd907dd9d 100644 --- a/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.properties +++ b/js/react_native/e2e/android/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,7 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists -distributionSha256Sum=db9c8211ed63f61f60292c69e80d89196f9eb36665e369e7f00ac4cc841c2219 -distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-all.zip +networkTimeout=10000 +validateDistributionUrl=true zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/js/react_native/e2e/android/gradlew b/js/react_native/e2e/android/gradlew index fbd7c515832da..79a61d421cc4e 100755 --- a/js/react_native/e2e/android/gradlew +++ b/js/react_native/e2e/android/gradlew @@ -1,7 +1,7 @@ -#!/usr/bin/env sh +#!/bin/sh # -# Copyright 2015 the original author or authors. +# Copyright © 2015-2021 the original authors. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -17,67 +17,101 @@ # ############################################################################## -## -## Gradle start up script for UN*X -## +# +# Gradle start up script for POSIX generated by Gradle. +# +# Important for running: +# +# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is +# noncompliant, but you have some other compliant shell such as ksh or +# bash, then to run this script, type that shell name before the whole +# command line, like: +# +# ksh Gradle +# +# Busybox and similar reduced shells will NOT work, because this script +# requires all of these POSIX shell features: +# * functions; +# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», +# «${var#prefix}», «${var%suffix}», and «$( cmd )»; +# * compound commands having a testable exit status, especially «case»; +# * various built-in commands including «command», «set», and «ulimit». +# +# Important for patching: +# +# (2) This script targets any POSIX shell, so it avoids extensions provided +# by Bash, Ksh, etc; in particular arrays are avoided. +# +# The "traditional" practice of packing multiple parameters into a +# space-separated string is a well documented source of bugs and security +# problems, so this is (mostly) avoided, by progressively accumulating +# options in "$@", and eventually passing that to Java. +# +# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, +# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; +# see the in-line comments for details. +# +# There are tweaks for specific operating systems such as AIX, CygWin, +# Darwin, MinGW, and NonStop. +# +# (3) This script is generated from the Groovy template +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# within the Gradle project. +# +# You can find Gradle at https://github.com/gradle/gradle/. +# ############################################################################## # Attempt to set APP_HOME + # Resolve links: $0 may be a link -PRG="$0" -# Need this for relative symlinks. -while [ -h "$PRG" ] ; do - ls=`ls -ld "$PRG"` - link=`expr "$ls" : '.*-> \(.*\)$'` - if expr "$link" : '/.*' > /dev/null; then - PRG="$link" - else - PRG=`dirname "$PRG"`"/$link" - fi +app_path=$0 + +# Need this for daisy-chained symlinks. +while + APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path + [ -h "$app_path" ] +do + ls=$( ls -ld "$app_path" ) + link=${ls#*' -> '} + case $link in #( + /*) app_path=$link ;; #( + *) app_path=$APP_HOME$link ;; + esac done -SAVED="`pwd`" -cd "`dirname \"$PRG\"`/" >/dev/null -APP_HOME="`pwd -P`" -cd "$SAVED" >/dev/null -APP_NAME="Gradle" -APP_BASE_NAME=`basename "$0"` +# This is normally unused +# shellcheck disable=SC2034 +APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD="maximum" +MAX_FD=maximum warn () { echo "$*" -} +} >&2 die () { echo echo "$*" echo exit 1 -} +} >&2 # OS specific support (must be 'true' or 'false'). cygwin=false msys=false darwin=false nonstop=false -case "`uname`" in - CYGWIN* ) - cygwin=true - ;; - Darwin* ) - darwin=true - ;; - MINGW* ) - msys=true - ;; - NONSTOP* ) - nonstop=true - ;; +case "$( uname )" in #( + CYGWIN* ) cygwin=true ;; #( + Darwin* ) darwin=true ;; #( + MSYS* | MINGW* ) msys=true ;; #( + NONSTOP* ) nonstop=true ;; esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar @@ -87,9 +121,9 @@ CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then # IBM's JDK on AIX uses strange locations for the executables - JAVACMD="$JAVA_HOME/jre/sh/java" + JAVACMD=$JAVA_HOME/jre/sh/java else - JAVACMD="$JAVA_HOME/bin/java" + JAVACMD=$JAVA_HOME/bin/java fi if [ ! -x "$JAVACMD" ] ; then die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME @@ -98,7 +132,7 @@ Please set the JAVA_HOME variable in your environment to match the location of your Java installation." fi else - JAVACMD="java" + JAVACMD=java which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the @@ -106,80 +140,105 @@ location of your Java installation." fi # Increase the maximum file descriptors if we can. -if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then - MAX_FD_LIMIT=`ulimit -H -n` - if [ $? -eq 0 ] ; then - if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then - MAX_FD="$MAX_FD_LIMIT" - fi - ulimit -n $MAX_FD - if [ $? -ne 0 ] ; then - warn "Could not set maximum file descriptor limit: $MAX_FD" - fi - else - warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT" - fi +if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then + case $MAX_FD in #( + max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + MAX_FD=$( ulimit -H -n ) || + warn "Could not query maximum file descriptor limit" + esac + case $MAX_FD in #( + '' | soft) :;; #( + *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 + ulimit -n "$MAX_FD" || + warn "Could not set maximum file descriptor limit to $MAX_FD" + esac fi -# For Darwin, add options to specify how the application appears in the dock -if $darwin; then - GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" -fi +# Collect all arguments for the java command, stacking in reverse order: +# * args from the command line +# * the main class name +# * -classpath +# * -D...appname settings +# * --module-path (only if needed) +# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. # For Cygwin or MSYS, switch paths to Windows format before running java -if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then - APP_HOME=`cygpath --path --mixed "$APP_HOME"` - CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` - - JAVACMD=`cygpath --unix "$JAVACMD"` - - # We build the pattern for arguments to be converted via cygpath - ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` - SEP="" - for dir in $ROOTDIRSRAW ; do - ROOTDIRS="$ROOTDIRS$SEP$dir" - SEP="|" - done - OURCYGPATTERN="(^($ROOTDIRS))" - # Add a user-defined pattern to the cygpath arguments - if [ "$GRADLE_CYGPATTERN" != "" ] ; then - OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" - fi +if "$cygwin" || "$msys" ; then + APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) + CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" ) + + JAVACMD=$( cygpath --unix "$JAVACMD" ) + # Now convert the arguments - kludge to limit ourselves to /bin/sh - i=0 - for arg in "$@" ; do - CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` - CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option - - if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition - eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` - else - eval `echo args$i`="\"$arg\"" + for arg do + if + case $arg in #( + -*) false ;; # don't mess with options #( + /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath + [ -e "$t" ] ;; #( + *) false ;; + esac + then + arg=$( cygpath --path --ignore --mixed "$arg" ) fi - i=`expr $i + 1` + # Roll the args list around exactly as many times as the number of + # args, so each arg winds up back in the position where it started, but + # possibly modified. + # + # NB: a `for` loop captures its iteration list before it begins, so + # changing the positional parameters here affects neither the number of + # iterations, nor the values presented in `arg`. + shift # remove old arg + set -- "$@" "$arg" # push replacement arg done - case $i in - 0) set -- ;; - 1) set -- "$args0" ;; - 2) set -- "$args0" "$args1" ;; - 3) set -- "$args0" "$args1" "$args2" ;; - 4) set -- "$args0" "$args1" "$args2" "$args3" ;; - 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; - esac fi -# Escape application args -save () { - for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done - echo " " -} -APP_ARGS=`save "$@"` +# Collect all arguments for the java command; +# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of +# shell script including quotes and variable substitutions, so put them in +# double quotes to make sure that they get re-expanded; and +# * put everything else in single quotes, so that it's not re-expanded. + +set -- \ + "-Dorg.gradle.appname=$APP_BASE_NAME" \ + -classpath "$CLASSPATH" \ + org.gradle.wrapper.GradleWrapperMain \ + "$@" + +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + +# Use "xargs" to parse quoted args. +# +# With -n1 it outputs one arg per line, with the quotes and backslashes removed. +# +# In Bash we could simply go: +# +# readarray ARGS < <( xargs -n1 <<<"$var" ) && +# set -- "${ARGS[@]}" "$@" +# +# but POSIX shell has neither arrays nor command substitution, so instead we +# post-process each arg (as a line of input to sed) to backslash-escape any +# character that might be a shell metacharacter, then use eval to reverse +# that process (while maintaining the separation between arguments), and wrap +# the whole thing up as a single "set" statement. +# +# This will of course break if any of these variables contains a newline or +# an unmatched quote. +# -# Collect all arguments for the java command, following the shell quoting and substitution rules -eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" +eval "set -- $( + printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | + xargs -n1 | + sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | + tr '\n' ' ' + )" '"$@"' exec "$JAVACMD" "$@" diff --git a/js/react_native/e2e/android/gradlew.bat b/js/react_native/e2e/android/gradlew.bat index 5093609d512a9..93e3f59f135dd 100644 --- a/js/react_native/e2e/android/gradlew.bat +++ b/js/react_native/e2e/android/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -54,7 +55,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -64,21 +65,6 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line @@ -86,17 +72,19 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/js/react_native/e2e/android/settings.gradle b/js/react_native/e2e/android/settings.gradle index b12a36f91dcae..2ee78a591a609 100644 --- a/js/react_native/e2e/android/settings.gradle +++ b/js/react_native/e2e/android/settings.gradle @@ -1,4 +1,4 @@ rootProject.name = 'OnnxruntimeModuleExample' apply from: file("../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesSettingsGradle(settings) include ':app' -includeBuild('../node_modules/react-native-gradle-plugin') \ No newline at end of file +includeBuild('../node_modules/@react-native/gradle-plugin') \ No newline at end of file diff --git a/js/react_native/e2e/babel.config.js b/js/react_native/e2e/babel.config.js deleted file mode 100644 index 96ef381f7825d..0000000000000 --- a/js/react_native/e2e/babel.config.js +++ /dev/null @@ -1,18 +0,0 @@ -'use strict'; - -const path = require('path'); -const pak = require('../package.json'); - -module.exports = { - presets: ['module:metro-react-native-babel-preset'], - plugins: [ - [ - 'module-resolver', - { - alias: { - [pak.name]: path.join(__dirname, '..', pak.source), - }, - }, - ], - ], -}; diff --git a/js/react_native/e2e/ios/MNISTDataHandler.h b/js/react_native/e2e/ios/MNISTDataHandler.h index da05843e8a41f..595cae82ea91c 100644 --- a/js/react_native/e2e/ios/MNISTDataHandler.h +++ b/js/react_native/e2e/ios/MNISTDataHandler.h @@ -4,7 +4,7 @@ #ifndef MNISTDataHandler_h #define MNISTDataHandler_h -#import +#import @interface MNISTDataHandler : NSObject @end diff --git a/js/react_native/e2e/ios/MNISTDataHandler.mm b/js/react_native/e2e/ios/MNISTDataHandler.mm index 1a79b66ca5d2f..6c27607eff1ed 100644 --- a/js/react_native/e2e/ios/MNISTDataHandler.mm +++ b/js/react_native/e2e/ios/MNISTDataHandler.mm @@ -2,10 +2,9 @@ // Licensed under the MIT License. #import "MNISTDataHandler.h" -#import "OnnxruntimeModule.h" -#import "TensorHelper.h" #import #import +#include NS_ASSUME_NONNULL_BEGIN @@ -119,7 +118,7 @@ - (NSDictionary*)preprocess:(NSString*)uri { inputTensorMap[@"dims"] = dims; // type - inputTensorMap[@"type"] = JsTensorTypeFloat; + inputTensorMap[@"type"] = @"float32"; // encoded data NSString* data = [byteBufferRef base64EncodedStringWithOptions:0]; diff --git a/js/react_native/e2e/ios/OnnxruntimeModuleExample.xcodeproj/project.pbxproj b/js/react_native/e2e/ios/OnnxruntimeModuleExample.xcodeproj/project.pbxproj index b8c9d9ab90cc1..57e12e9bbdcef 100644 --- a/js/react_native/e2e/ios/OnnxruntimeModuleExample.xcodeproj/project.pbxproj +++ b/js/react_native/e2e/ios/OnnxruntimeModuleExample.xcodeproj/project.pbxproj @@ -10,13 +10,21 @@ 13B07FBC1A68108700A75B9A /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB01A68108700A75B9A /* AppDelegate.m */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; 13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; }; - 81411D106EB3E14586DBF352 /* libPods-OnnxruntimeModuleExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = A98DB3380F37BDA06AFF9005 /* libPods-OnnxruntimeModuleExample.a */; }; + 3ADD0A3C2EBB64D200761D6F /* ../src/test_types_int8.ort in Resources */ = {isa = PBXBuildFile; fileRef = 3ADD0A382EBB64D200761D6F /* ../src/test_types_int8.ort */; }; + 3ADD0A3D2EBB64D200761D6F /* ../src/test_types_int64.ort in Resources */ = {isa = PBXBuildFile; fileRef = 3ADD0A3A2EBB64D200761D6F /* ../src/test_types_int64.ort */; }; + 3ADD0A3E2EBB64D200761D6F /* ../src/test_types_int32.ort in Resources */ = {isa = PBXBuildFile; fileRef = 3ADD0A392EBB64D200761D6F /* ../src/test_types_int32.ort */; }; + 3ADD0A3F2EBB64D200761D6F /* ../src/test_types_float.ort in Resources */ = {isa = PBXBuildFile; fileRef = 3ADD0A372EBB64D200761D6F /* ../src/test_types_float.ort */; }; + 3ADD0A402EBB64D200761D6F /* ../src/test_types_uint8.ort in Resources */ = {isa = PBXBuildFile; fileRef = 3ADD0A3B2EBB64D200761D6F /* ../src/test_types_uint8.ort */; }; + 3ADD0A462EBB64D200761D6F /* ../src/test_types_float16.ort in Resources */ = {isa = PBXBuildFile; fileRef = 3ADD0A452EBB64D200761D6F /* ../src/test_types_float16.ort */; }; + 3ADD0A422EBB677300761D6F /* test_types_double.onnx in Resources */ = {isa = PBXBuildFile; fileRef = 3ADD0A412EBB677300761D6F /* test_types_double.onnx */; }; + 3ADD0A442EBB679A00761D6F /* test_types_bool.onnx in Resources */ = {isa = PBXBuildFile; fileRef = 3ADD0A432EBB679A00761D6F /* test_types_bool.onnx */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; DB61BA27278684FB0096C971 /* OnnxruntimeModuleExampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = DB61BA26278684FB0096C971 /* OnnxruntimeModuleExampleUITests.m */; }; DBA8BA87267293C4008CC55A /* mnist.ort in Resources */ = {isa = PBXBuildFile; fileRef = DBA8BA86267293C4008CC55A /* mnist.ort */; }; DBBF7412263B8C7100487C77 /* MNISTDataHandler.mm in Sources */ = {isa = PBXBuildFile; fileRef = DBBF7411263B8C7100487C77 /* MNISTDataHandler.mm */; }; DBBF7414263B8CCB00487C77 /* 3.jpg in Resources */ = {isa = PBXBuildFile; fileRef = DBBF7413263B8CCB00487C77 /* 3.jpg */; }; E329E1162D3728940016B599 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = E329E1142D3728940016B599 /* PrivacyInfo.xcprivacy */; }; + EFD33FB526BB0C93D01CB530 /* Pods_OnnxruntimeModuleExample.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BD7F8CBE63AF4B718C53FB54 /* Pods_OnnxruntimeModuleExample.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -50,10 +58,18 @@ 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = OnnxruntimeModuleExample/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = OnnxruntimeModuleExample/Info.plist; sourceTree = ""; }; 13B07FB71A68108700A75B9A /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = main.m; path = OnnxruntimeModuleExample/main.m; sourceTree = ""; }; + 3ADD0A372EBB64D200761D6F /* ../src/test_types_float.ort */ = {isa = PBXFileReference; lastKnownFileType = file; path = ../src/test_types_float.ort; sourceTree = ""; }; + 3ADD0A382EBB64D200761D6F /* ../src/test_types_int8.ort */ = {isa = PBXFileReference; lastKnownFileType = file; path = ../src/test_types_int8.ort; sourceTree = ""; }; + 3ADD0A392EBB64D200761D6F /* ../src/test_types_int32.ort */ = {isa = PBXFileReference; lastKnownFileType = file; path = ../src/test_types_int32.ort; sourceTree = ""; }; + 3ADD0A3A2EBB64D200761D6F /* ../src/test_types_int64.ort */ = {isa = PBXFileReference; lastKnownFileType = file; path = ../src/test_types_int64.ort; sourceTree = ""; }; + 3ADD0A3B2EBB64D200761D6F /* ../src/test_types_uint8.ort */ = {isa = PBXFileReference; lastKnownFileType = file; path = ../src/test_types_uint8.ort; sourceTree = ""; }; + 3ADD0A452EBB64D200761D6F /* ../src/test_types_float16.ort */ = {isa = PBXFileReference; lastKnownFileType = file; path = ../src/test_types_float16.ort; sourceTree = ""; }; + 3ADD0A412EBB677300761D6F /* test_types_double.onnx */ = {isa = PBXFileReference; lastKnownFileType = file; path = ../src/test_types_double.onnx; sourceTree = ""; }; + 3ADD0A432EBB679A00761D6F /* test_types_bool.onnx */ = {isa = PBXFileReference; lastKnownFileType = file; path = ../src/test_types_bool.onnx; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = OnnxruntimeModuleExample/LaunchScreen.storyboard; sourceTree = ""; }; 9D58C0FCCF00905433F4ED74 /* Pods-OnnxruntimeModuleExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OnnxruntimeModuleExample.debug.xcconfig"; path = "Target Support Files/Pods-OnnxruntimeModuleExample/Pods-OnnxruntimeModuleExample.debug.xcconfig"; sourceTree = ""; }; - A98DB3380F37BDA06AFF9005 /* libPods-OnnxruntimeModuleExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-OnnxruntimeModuleExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; B70FCE6DFAB320E9051DA321 /* Pods-OnnxruntimeModuleExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-OnnxruntimeModuleExample.release.xcconfig"; path = "Target Support Files/Pods-OnnxruntimeModuleExample/Pods-OnnxruntimeModuleExample.release.xcconfig"; sourceTree = ""; }; + BD7F8CBE63AF4B718C53FB54 /* Pods_OnnxruntimeModuleExample.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_OnnxruntimeModuleExample.framework; sourceTree = BUILT_PRODUCTS_DIR; }; DB61BA24278684FB0096C971 /* OnnxruntimeModuleExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = OnnxruntimeModuleExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; DB61BA26278684FB0096C971 /* OnnxruntimeModuleExampleUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = OnnxruntimeModuleExampleUITests.m; sourceTree = ""; }; DBA8BA86267293C4008CC55A /* mnist.ort */ = {isa = PBXFileReference; lastKnownFileType = file; name = mnist.ort; path = ../src/mnist.ort; sourceTree = ""; }; @@ -69,7 +85,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 81411D106EB3E14586DBF352 /* libPods-OnnxruntimeModuleExample.a in Frameworks */, + EFD33FB526BB0C93D01CB530 /* Pods_OnnxruntimeModuleExample.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -104,7 +120,7 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - A98DB3380F37BDA06AFF9005 /* libPods-OnnxruntimeModuleExample.a */, + BD7F8CBE63AF4B718C53FB54 /* Pods_OnnxruntimeModuleExample.framework */, ); name = Frameworks; sourceTree = ""; @@ -128,6 +144,14 @@ 83CBB9F61A601CBA00E9B192 = { isa = PBXGroup; children = ( + 3ADD0A432EBB679A00761D6F /* test_types_bool.onnx */, + 3ADD0A412EBB677300761D6F /* test_types_double.onnx */, + 3ADD0A372EBB64D200761D6F /* ../src/test_types_float.ort */, + 3ADD0A382EBB64D200761D6F /* ../src/test_types_int8.ort */, + 3ADD0A392EBB64D200761D6F /* ../src/test_types_int32.ort */, + 3ADD0A3A2EBB64D200761D6F /* ../src/test_types_int64.ort */, + 3ADD0A3B2EBB64D200761D6F /* ../src/test_types_uint8.ort */, + 3ADD0A452EBB64D200761D6F /* ../src/test_types_float16.ort */, DBA8BA86267293C4008CC55A /* mnist.ort */, DBBF7413263B8CCB00487C77 /* 3.jpg */, 13B07FAE1A68108700A75B9A /* OnnxruntimeModuleExample */, @@ -173,7 +197,7 @@ 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, DB8FCD9C25C3404B00C72F26 /* Embed Libraries */, - 9BBEFBEFBEE7FC814F312449 /* [CP] Copy Pods Resources */, + 6B3DE710B60DDDB8E8CFF989 /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -247,6 +271,14 @@ DBA8BA87267293C4008CC55A /* mnist.ort in Resources */, DBBF7414263B8CCB00487C77 /* 3.jpg in Resources */, 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, + 3ADD0A422EBB677300761D6F /* test_types_double.onnx in Resources */, + 3ADD0A3C2EBB64D200761D6F /* ../src/test_types_int8.ort in Resources */, + 3ADD0A442EBB679A00761D6F /* test_types_bool.onnx in Resources */, + 3ADD0A3D2EBB64D200761D6F /* ../src/test_types_int64.ort in Resources */, + 3ADD0A3E2EBB64D200761D6F /* ../src/test_types_int32.ort in Resources */, + 3ADD0A3F2EBB64D200761D6F /* ../src/test_types_float.ort in Resources */, + 3ADD0A402EBB64D200761D6F /* ../src/test_types_uint8.ort in Resources */, + 3ADD0A462EBB64D200761D6F /* ../src/test_types_float16.ort in Resources */, E329E1162D3728940016B599 /* PrivacyInfo.xcprivacy in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, ); @@ -277,22 +309,106 @@ shellPath = /bin/sh; shellScript = "if [ \"$CONFIGURATION\" == \"Release\" ]; then\n export NODE_BINARY=$(which node)\n export ENTRY_FILE=\"index.tsx\"\n export EXTRA_PACKAGER_ARGS=\"--reset-cache\"\n\n ../node_modules/react-native/scripts/react-native-xcode.sh\n echo \"copying bundle file from $CONFIGURATION_BUILD_DIR/main.jsbundlecd to $CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/\"\n echo \"This cp might not need it post 0.7.15 because it is a bug from facebook\" \n cp $CONFIGURATION_BUILD_DIR/main.jsbundle $CONFIGURATION_BUILD_DIR/$UNLOCALIZED_RESOURCES_FOLDER_PATH/\nfi\n"; }; - 9BBEFBEFBEE7FC814F312449 /* [CP] Copy Pods Resources */ = { + 6B3DE710B60DDDB8E8CFF989 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-OnnxruntimeModuleExample/Pods-OnnxruntimeModuleExample-resources.sh", - "${PODS_CONFIGURATION_BUILD_DIR}/React-Core/AccessibilityResources.bundle", - ); - name = "[CP] Copy Pods Resources"; + "${PODS_ROOT}/Target Support Files/Pods-OnnxruntimeModuleExample/Pods-OnnxruntimeModuleExample-frameworks.sh", + "${BUILT_PRODUCTS_DIR}/DoubleConversion/DoubleConversion.framework", + "${BUILT_PRODUCTS_DIR}/RCT-Folly/folly.framework", + "${BUILT_PRODUCTS_DIR}/RCTTypeSafety/RCTTypeSafety.framework", + "${BUILT_PRODUCTS_DIR}/RNFS/RNFS.framework", + "${BUILT_PRODUCTS_DIR}/React-Codegen/React_Codegen.framework", + "${BUILT_PRODUCTS_DIR}/React-Core/React.framework", + "${BUILT_PRODUCTS_DIR}/React-CoreModules/CoreModules.framework", + "${BUILT_PRODUCTS_DIR}/React-Fabric/React_Fabric.framework", + "${BUILT_PRODUCTS_DIR}/React-FabricImage/React_FabricImage.framework", + "${BUILT_PRODUCTS_DIR}/React-ImageManager/React_ImageManager.framework", + "${BUILT_PRODUCTS_DIR}/React-Mapbuffer/React_Mapbuffer.framework", + "${BUILT_PRODUCTS_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTAnimation/RCTAnimation.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTAppDelegate/React_RCTAppDelegate.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTBlob/RCTBlob.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTFabric/RCTFabric.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTImage/RCTImage.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTLinking/RCTLinking.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTNetwork/RCTNetwork.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTSettings/RCTSettings.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTText/RCTText.framework", + "${BUILT_PRODUCTS_DIR}/React-RCTVibration/RCTVibration.framework", + "${BUILT_PRODUCTS_DIR}/React-cxxreact/cxxreact.framework", + "${BUILT_PRODUCTS_DIR}/React-debug/React_debug.framework", + "${BUILT_PRODUCTS_DIR}/React-graphics/React_graphics.framework", + "${BUILT_PRODUCTS_DIR}/React-hermes/reacthermes.framework", + "${BUILT_PRODUCTS_DIR}/React-jserrorhandler/React_jserrorhandler.framework", + "${BUILT_PRODUCTS_DIR}/React-jsi/jsi.framework", + "${BUILT_PRODUCTS_DIR}/React-jsiexecutor/jsireact.framework", + "${BUILT_PRODUCTS_DIR}/React-jsinspector/jsinspector.framework", + "${BUILT_PRODUCTS_DIR}/React-logger/logger.framework", + "${BUILT_PRODUCTS_DIR}/React-nativeconfig/React_nativeconfig.framework", + "${BUILT_PRODUCTS_DIR}/React-perflogger/reactperflogger.framework", + "${BUILT_PRODUCTS_DIR}/React-rendererdebug/React_rendererdebug.framework", + "${BUILT_PRODUCTS_DIR}/React-runtimescheduler/React_runtimescheduler.framework", + "${BUILT_PRODUCTS_DIR}/React-utils/React_utils.framework", + "${BUILT_PRODUCTS_DIR}/ReactCommon/ReactCommon.framework", + "${BUILT_PRODUCTS_DIR}/SocketRocket/SocketRocket.framework", + "${BUILT_PRODUCTS_DIR}/Yoga/yoga.framework", + "${BUILT_PRODUCTS_DIR}/fmt/fmt.framework", + "${BUILT_PRODUCTS_DIR}/glog/glog.framework", + "${BUILT_PRODUCTS_DIR}/libevent/libevent.framework", + "${PODS_XCFRAMEWORKS_BUILD_DIR}/hermes-engine/Pre-built/hermes.framework/hermes", + ); + name = "[CP] Embed Pods Frameworks"; outputPaths = ( - "${TARGET_BUILD_DIR}/${UNLOCALIZED_RESOURCES_FOLDER_PATH}/AccessibilityResources.bundle", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DoubleConversion.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/folly.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTTypeSafety.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RNFS.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_Codegen.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/CoreModules.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_Fabric.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_FabricImage.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_ImageManager.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_Mapbuffer.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_NativeModulesApple.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTAnimation.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_RCTAppDelegate.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTBlob.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTFabric.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTImage.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTLinking.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTNetwork.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTSettings.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTText.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/RCTVibration.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/cxxreact.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_debug.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_graphics.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/reacthermes.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_jserrorhandler.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsi.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsireact.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/jsinspector.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/logger.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_nativeconfig.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/reactperflogger.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_rendererdebug.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_runtimescheduler.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/React_utils.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/ReactCommon.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/SocketRocket.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/yoga.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/fmt.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/glog.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/libevent.framework", + "${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/hermes.framework", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-OnnxruntimeModuleExample/Pods-OnnxruntimeModuleExample-resources.sh\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-OnnxruntimeModuleExample/Pods-OnnxruntimeModuleExample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; FD10A7F022414F080027D42C /* Start Packager */ = { @@ -385,7 +501,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.reactnativeonnxruntimemodule; + PRODUCT_BUNDLE_IDENTIFIER = com.reactnativeonnxruntimemodule; PRODUCT_NAME = OnnxruntimeModuleExample; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -409,7 +525,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = com.example.reactnativeonnxruntimemodule; + PRODUCT_BUNDLE_IDENTIFIER = com.reactnativeonnxruntimemodule; PRODUCT_NAME = OnnxruntimeModuleExample; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -422,7 +538,7 @@ ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD)"; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -449,7 +565,7 @@ COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_NO_COMMON_BLOCKS = YES; @@ -466,6 +582,17 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + ); "HEADER_SEARCH_PATHS[arch=*]" = ""; IPHONEOS_DEPLOYMENT_TARGET = 15.1; LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; @@ -476,9 +603,12 @@ ); MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; + OTHER_CFLAGS = "$(inherited)"; + OTHER_CPLUSPLUSFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; + USE_HERMES = true; }; name = Debug; }; @@ -488,7 +618,7 @@ ALWAYS_SEARCH_USER_PATHS = NO; ARCHS = "$(ARCHS_STANDARD)"; CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; - CLANG_CXX_LANGUAGE_STANDARD = "c++17"; + CLANG_CXX_LANGUAGE_STANDARD = "c++20"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; CLANG_ENABLE_OBJC_ARC = YES; @@ -515,7 +645,7 @@ COPY_PHASE_STRIP = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; - "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = ""; + "EXCLUDED_ARCHS[sdk=iphonesimulator*]" = i386; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_NO_COMMON_BLOCKS = YES; GCC_PREPROCESSOR_DEFINITIONS = ( @@ -528,6 +658,17 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; + HEADER_SEARCH_PATHS = ( + "$(inherited)", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers/react/nativemodule/core", + "${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon-Samples/ReactCommon_Samples.framework/Headers/platform/ios", + "${PODS_CONFIGURATION_BUILD_DIR}/React-NativeModulesApple/React_NativeModulesApple.framework/Headers", + "${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers/react/renderer/graphics/platform/ios", + " ${PODS_CONFIGURATION_BUILD_DIR}/ReactCommon/ReactCommon.framework/Headers", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-Fabric/React_Fabric.framework/Headers/react/renderer/components/view/platform/cxx", + " ${PODS_CONFIGURATION_BUILD_DIR}/React-graphics/React_graphics.framework/Headers", + ); IPHONEOS_DEPLOYMENT_TARGET = 15.1; LD_RUNPATH_SEARCH_PATHS = "/usr/lib/swift $(inherited)"; LIBRARY_SEARCH_PATHS = ( @@ -536,9 +677,12 @@ "\"$(inherited)\"", ); MTL_ENABLE_DEBUG_INFO = NO; + OTHER_CFLAGS = "$(inherited)"; + OTHER_CPLUSPLUSFLAGS = "$(inherited)"; OTHER_LDFLAGS = "$(inherited)"; REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; + USE_HERMES = true; VALIDATE_PRODUCT = YES; }; name = Release; @@ -554,6 +698,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = ""; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = dwarf; GCC_C_LANGUAGE_STANDARD = gnu11; @@ -581,6 +726,7 @@ CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_STYLE = Automatic; + CODE_SIGN_IDENTITY = ""; COPY_PHASE_STRIP = NO; CURRENT_PROJECT_VERSION = 1; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; diff --git a/js/react_native/e2e/ios/OnnxruntimeModuleExample/Info.plist b/js/react_native/e2e/ios/OnnxruntimeModuleExample/Info.plist index d73af62336182..b8b2ff3059eb7 100644 --- a/js/react_native/e2e/ios/OnnxruntimeModuleExample/Info.plist +++ b/js/react_native/e2e/ios/OnnxruntimeModuleExample/Info.plist @@ -28,15 +28,12 @@ NSAllowsArbitraryLoads - NSExceptionDomains - - localhost - - NSExceptionAllowsInsecureHTTPLoads + + NSAllowsArbitraryLoads + + NSAllowsLocalNetworking - - NSLocationWhenInUseUsageDescription UILaunchStoryboardName diff --git a/js/react_native/e2e/ios/Podfile b/js/react_native/e2e/ios/Podfile index 78886dd3541e2..95c915cb41dca 100644 --- a/js/react_native/e2e/ios/Podfile +++ b/js/react_native/e2e/ios/Podfile @@ -1,24 +1,17 @@ -require_relative '../node_modules/react-native/scripts/react_native_pods' -require_relative '../node_modules/@react-native-community/cli-platform-ios/native_modules' +# Resolve react_native_pods.rb with node to allow for hoisting +require Pod::Executable.execute_command('node', ['-p', + 'require.resolve( + "react-native/scripts/react_native_pods.rb", + {paths: [process.argv[1]]}, + )', __dir__]).strip + platform :ios, '15.1' prepare_react_native_project! +# use_frameworks need to be loaded before use_react_native! for now +use_frameworks! -linkage = ENV['USE_FRAMEWORKS'] -if linkage != nil - Pod::UI.puts "Configuring Pod with #{linkage}ally linked Frameworks".green - use_frameworks! :linkage => linkage.to_sym -end - -pre_install do |installer| - # Custom pre-install script or commands - puts "Running pre-install script..." - - # Recommended fix for https://github.com/facebook/react-native/issues/32483 - # from https://github.com/facebook/react-native/issues/32483#issuecomment-966784501 - system("sed -i '' 's/typedef uint8_t clockid_t;//' \"./Pods/RCT-Folly/folly/portability/Time.h\"") -end target 'OnnxruntimeModuleExample' do config = use_native_modules! @@ -26,11 +19,6 @@ target 'OnnxruntimeModuleExample' do use_react_native!( :path => config[:reactNativePath], - # Hermes is now enabled by default. Disable by setting this flag to false. - # Upcoming versions of React Native may rely on get_default_flags(), but - # we make it explicit here to aid in the React Native upgrade process. - - :hermes_enabled => false, # :flipper_configuration => FlipperConfiguration.enabled, :app_path => "#{Pod::Config.instance.installation_root}/.." ) @@ -48,10 +36,7 @@ target 'OnnxruntimeModuleExample' do react_native_post_install( installer, config[:reactNativePath], - # Set `mac_catalyst_enabled` to `true` in order to apply patches - # necessary for Mac Catalyst builds :mac_catalyst_enabled => false, ) - __apply_Xcode_12_5_M1_post_install_workaround(installer) end end diff --git a/js/react_native/e2e/ios/PrivacyInfo.xcprivacy b/js/react_native/e2e/ios/PrivacyInfo.xcprivacy index 549cd5d8b600f..41b8317f0652b 100644 --- a/js/react_native/e2e/ios/PrivacyInfo.xcprivacy +++ b/js/react_native/e2e/ios/PrivacyInfo.xcprivacy @@ -2,8 +2,6 @@ - NSPrivacyCollectedDataTypes - NSPrivacyAccessedAPITypes @@ -31,6 +29,8 @@ + NSPrivacyCollectedDataTypes + NSPrivacyTracking diff --git a/js/react_native/e2e/ios/test_types_bool.ort b/js/react_native/e2e/ios/test_types_bool.ort new file mode 100644 index 0000000000000..ee955dcc6fe54 Binary files /dev/null and b/js/react_native/e2e/ios/test_types_bool.ort differ diff --git a/js/react_native/e2e/ios/test_types_double.ort b/js/react_native/e2e/ios/test_types_double.ort new file mode 100644 index 0000000000000..0259d0eae66ab Binary files /dev/null and b/js/react_native/e2e/ios/test_types_double.ort differ diff --git a/js/react_native/e2e/metro.config.js b/js/react_native/e2e/metro.config.js index 9e7fb1c73d9cf..e9ef3a02f075a 100644 --- a/js/react_native/e2e/metro.config.js +++ b/js/react_native/e2e/metro.config.js @@ -1,39 +1,18 @@ -'use strict'; - +const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config'); const path = require('path'); -const exclusionlist = require('metro-config/src/defaults/exclusionList'); -const escape = require('escape-string-regexp'); -const pak = require('../package.json'); - -const root = path.resolve(__dirname, '..'); - -const modules = Object.keys({ - ...pak.peerDependencies, -}); - -module.exports = { - projectRoot: __dirname, - watchFolders: [root], - - // We need to make sure that only one version is loaded for peerDependencies - // So we exclusionlist them at the root, and alias them to the versions in example's node_modules +/** + * Metro configuration + * https://facebook.github.io/metro/docs/configuration + * + * @type {import('metro-config').MetroConfig} + */ +const config = { + watchFolders: [ + path.resolve(__dirname, '..'), // Ensure Metro watches the lib folder + ], resolver: { - exclusionlistRE: exclusionlist( - modules.map((m) => new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)), - ), - - extraNodeModules: modules.reduce((acc, name) => { - acc[name] = path.join(__dirname, 'node_modules', name); - return acc; - }, {}), - }, - - transformer: { - getTransformOptions: async () => ({ - transform: { - experimentalImportSupport: false, - inlineRequires: true, - }, - }), + sourceExts: ['tsx', 'ts', 'jsx', 'js', 'json'], // Ensure TypeScript files are recognized + assetExts: ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'tiff', 'ico', 'webp', 'svg', 'ort', 'onnx'], }, }; +module.exports = mergeConfig(getDefaultConfig(__dirname), config); diff --git a/js/react_native/e2e/package-lock.json b/js/react_native/e2e/package-lock.json new file mode 100644 index 0000000000000..907e9cf72b59c --- /dev/null +++ b/js/react_native/e2e/package-lock.json @@ -0,0 +1,12871 @@ +{ + "name": "onnxruntime-reactnative-example", + "version": "0.5.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "onnxruntime-reactnative-example", + "version": "0.5.0", + "dependencies": { + "react": "^18.2.0", + "react-native": "^0.73.11", + "react-native-fs": "^2.20.0" + }, + "devDependencies": { + "@babel/core": "^7.20.0", + "@babel/preset-env": "^7.20.0", + "@babel/runtime": "^7.28.3", + "@react-native/babel-preset": "0.73.21", + "@react-native/eslint-config": "^0.73.2", + "@react-native/metro-config": "^0.73.5", + "@react-native/typescript-config": "0.73.1", + "@types/react": "^18.2.6", + "@types/react-test-renderer": "^18.0.0", + "babel-jest": "^29.6.3", + "detox": "20.11.4", + "eslint": "^8.19.0", + "jest": "^29.6.3", + "jest-junit": "16.0.0", + "prettier": "^2.8.8", + "react-test-renderer": "18.2.0", + "typescript": "5.0.4" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@ampproject/remapping": { + "version": "2.2.0", + "license": "Apache-2.0", + "dependencies": { + "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/trace-mapping": "^0.3.9" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@ampproject/remapping/node_modules/@jridgewell/gen-mapping": { + "version": "0.1.1", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.0.0", + "@jridgewell/sourcemap-codec": "^1.4.10" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", + "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.27.1", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.25.4.tgz", + "integrity": "sha512-+LGRog6RAsCJrrrg/IO6LGmpphNe5DiK30dGjCoxxeGv49B10/3XYGxPsAwrDlMFcFEvdAUavDT8r9k/hSyQqQ==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.25.2.tgz", + "integrity": "sha512-BBt3opiCOxUr9euZ5/ro/Xv8/V7yJ5bjYMqG/C1YAo8MIKAnumZalCN+msbci3Pigy4lIQfPUpfMM27HMGaYEA==", + "license": "MIT", + "dependencies": { + "@ampproject/remapping": "^2.2.0", + "@babel/code-frame": "^7.24.7", + "@babel/generator": "^7.25.0", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-module-transforms": "^7.25.2", + "@babel/helpers": "^7.25.0", + "@babel/parser": "^7.25.0", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.2", + "@babel/types": "^7.25.2", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/core/node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/core/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/@babel/eslint-parser": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.26.8.tgz", + "integrity": "sha512-3tBctaHRW6xSub26z7n8uyOTwwUsCdvIug/oxBH9n6yCO5hMj2vwDJAo7RbBMKrM7P+W2j61zLKviJQFGOYKMg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", + "eslint-visitor-keys": "^2.1.0", + "semver": "^6.3.1" + }, + "engines": { + "node": "^10.13.0 || ^12.13.0 || >=14.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.11.0", + "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" + } + }, + "node_modules/@babel/generator": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.9.tgz", + "integrity": "sha512-kEWdzjOAUMW4hAyrzJ0ZaTOu9OmpyDIQicIh0zg0EEcEkYXZb2TjtBhnHi2ViX7PKwZqF4xwqfAm299/QMP3lg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.26.9", + "@babel/types": "^7.26.9", + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-annotate-as-pure": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz", + "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.24.7.tgz", + "integrity": "sha512-xZeCVVdwb4MsDBkkyZ64tReWYrLRHlMN72vP7Bdm3OUOuyFZExhsHUUnuWnm2/XOlAJzR0LfPpB56WXZn0X/lA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.24.7", + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.2.tgz", + "integrity": "sha512-U2U5LsSaZ7TAt3cfaymQ8WHh0pxvdHoEk6HVpaexxixjyEquMh0L0YNJNM6CTGKMXV1iksi0iZkGw4AcFkPaaw==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.2", + "@babel/helper-validator-option": "^7.24.8", + "browserslist": "^4.23.1", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/@babel/helper-compilation-targets/node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "license": "ISC" + }, + "node_modules/@babel/helper-create-class-features-plugin": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.26.9.tgz", + "integrity": "sha512-ubbUqCofvxPRurw5L8WTsCLSkQiVpov4Qx0WMA+jUN+nXBK8ADPlJO1grkFw5CWKC5+sZSOfuGMdX1aI1iT9Sg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/helper-replace-supers": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/traverse": "^7.26.9", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-create-regexp-features-plugin": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.2.tgz", + "integrity": "sha512-+wqVGP+DFmqwFD3EH6TMTfUNeqDehV3E/dl+Sd54eaXqm17tEUNbEIn4sVivVowbvUpOtIGxdo3GoXyDH9N/9g==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "regexpu-core": "^5.3.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.13.0", + "@babel/helper-module-imports": "^7.12.13", + "@babel/helper-plugin-utils": "^7.13.0", + "@babel/traverse": "^7.13.0", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2", + "semver": "^6.1.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0-0" + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/helper-define-polyfill-provider/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/@babel/helper-environment-visitor": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz", + "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-member-expression-to-functions": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", + "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz", + "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz", + "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9", + "@babel/traverse": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-optimise-call-expression": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz", + "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz", + "integrity": "sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-remap-async-to-generator": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.0.tgz", + "integrity": "sha512-NhavI2eWEIz/H9dbrG0TuOicDhNexze43i5z7lEqwYm0WEZVTwnPpA0EafUTP7+6/W79HWIP2cTe3Z5NiSTVpw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-wrap-function": "^7.25.0", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-replace-supers": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.26.5.tgz", + "integrity": "sha512-bJ6iIVdYX1YooY2X7w1q6VITt+LnUILtNk7zT78ykuwStx8BauCzxvFqFaHjOpW1bVnSUM1PN1f0p5P21wHxvg==", + "license": "MIT", + "dependencies": { + "@babel/helper-member-expression-to-functions": "^7.25.9", + "@babel/helper-optimise-call-expression": "^7.25.9", + "@babel/traverse": "^7.26.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-skip-transparent-expression-wrappers": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz", + "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.25.9", + "@babel/types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", + "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz", + "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-wrap-function": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.0.tgz", + "integrity": "sha512-s6Q1ebqutSiZnEjaofc/UKDyC4SbzV5n5SrA2Gq8UawLycr3i04f1dX4OzoQVnexm6aOCh37SQNYlJ/8Ku+PMQ==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.0", + "@babel/types": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.3.tgz", + "integrity": "sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw==", + "license": "MIT", + "dependencies": { + "@babel/template": "^7.27.2", + "@babel/types": "^7.28.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", + "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "version": "7.25.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.3.tgz", + "integrity": "sha512-wUrcsxZg6rqBXG05HG1FPYgsP6EvwF4WpBbxIpWIIYnH8wG0gzx3yZY3dtEHas4sTAOGkbTsc9EGPxwff8lRoA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.0.tgz", + "integrity": "sha512-Bm4bH2qsX880b/3ziJ8KD711LT7z4u8CFudmjqle65AZj/HNUFhEf90dqYv6O86buWvSBmeQDjv0Tn2aF/bIBA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.0.tgz", + "integrity": "sha512-lXwdNZtTmeVOOFtwM/WDe7yg1PL8sYhRk/XH0FzbR2HDQ0xC+EnQ/JHeoMYSavtU115tnUk0q9CDyq8si+LMAA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.24.7.tgz", + "integrity": "sha512-+izXIbke1T33mY4MSNnrqhPXDz01WYhEf3yF5NbnUtkiNnm+XBZJl3kNfoK6NKmYlz/D07+l2GWVK/QfDkNCuQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.13.0" + } + }, + "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.0.tgz", + "integrity": "sha512-tggFrk1AIShG/RUQbEwt2Tr/E+ObkfwrPjR6BjbRvsx24+PSjK8zrq0GWPNCjo8qpRx4DuJzlcvWJqlm+0h3kw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-proposal-async-generator-functions": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.20.7.tgz", + "integrity": "sha512-xMbiLsn/8RK7Wq7VeVytytS2L6qE69bXPB10YCmMdDZbKF4okCqY74pI/jJQ/8U0b/F6NrT2+14b8/P9/3AMGA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-environment-visitor": "^7.18.9", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-remap-async-to-generator": "^7.18.9", + "@babel/plugin-syntax-async-generators": "^7.8.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-class-properties": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz", + "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-export-default-from": { + "version": "7.17.12", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-export-default-from": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.18.6.tgz", + "integrity": "sha512-wQxQzxYeJqHcfppzBDnm1yAY0jSRkUXR2z8RePZYrKwMKgMlE8+Z6LUno+bd6LvbGh8Gltvy74+9pIYkr+XkKA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-numeric-separator": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.18.6.tgz", + "integrity": "sha512-ozlZFogPqoLm8WBr5Z8UckIoE4YQ5KESVcNudyXOR8uqIkliTEgJ3RoketfG6pmzLdeZF0H/wjE9/cCEitBl7Q==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.18.6", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-object-rest-spread": { + "version": "7.20.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.20.7.tgz", + "integrity": "sha512-d2S98yCiLxDVmBmE8UjGcfPvNEUbA1U5q5WxaWFUGRzJSVAZqm5W6MbPct0jxnegUZ0niLeNX+IOzEs7wYg9Dg==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.20.5", + "@babel/helper-compilation-targets": "^7.20.7", + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.20.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-catch-binding": { + "version": "7.16.7", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-optional-chaining": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.21.0.tgz", + "integrity": "sha512-p4zeefM72gpmEe2fkUr/OnOXpWEf8nAgk7ZYVqqfFiyIG7oFfVZcCrU64hWn5xp4tQ9LkV4bTIa5rD0KANpKNA==", + "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.20.2", + "@babel/helper-skip-transparent-expression-wrappers": "^7.20.0", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-proposal-private-property-in-object": { + "version": "7.21.0-placeholder-for-preset-env.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz", + "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-async-generators": { + "version": "7.8.4", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-bigint": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", + "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-properties": { + "version": "7.12.13", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.12.13" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-class-static-block": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz", + "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-dynamic-import": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-default-from": { + "version": "7.16.7", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-export-namespace-from": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz", + "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.3" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-flow": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.26.0.tgz", + "integrity": "sha512-B+O2DnPc0iG+YXFqOxv2WNuNU97ToWjOomUQ78DouOENWUaM5sVrmet9mcomUGQFwpJd//gvUagXBSdzO1fRKg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-assertions": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.25.6.tgz", + "integrity": "sha512-aABl0jHw9bZ2karQ/uUD6XP4u0SG22SJrOHFoL6XB1R7dTovOP4TzTlsxOYC5yQ1pdscVK2JTUnF6QL3ARoAiQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.25.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.25.6.tgz", + "integrity": "sha512-sXaDXaJN9SNLymBdlWFA+bjzBhFD617ZaFiY13dGt7TVslVvVgA6fkZOP7Ki3IGElC45lwHdOTrCtKZGVAWeLQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-json-strings": { + "version": "7.8.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz", + "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-jsx": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-logical-assignment-operators": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", + "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-numeric-separator": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz", + "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.10.4" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-object-rest-spread": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-catch-binding": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-optional-chaining": { + "version": "7.8.3", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.8.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-private-property-in-object": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz", + "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-top-level-await": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz", + "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-syntax-unicode-sets-regex": { + "version": "7.18.6", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz", + "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.18.6", + "@babel/helper-plugin-utils": "^7.18.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-arrow-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.24.7.tgz", + "integrity": "sha512-Dt9LQs6iEY++gXUwY03DNFat5C2NbO48jj+j/bSAz6b3HgPs39qcPiYt77fDObIcFwj3/C2ICX9YMwGflUoSHQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-generator-functions": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.4.tgz", + "integrity": "sha512-jz8cV2XDDTqjKPwVPJBIjORVEmSGYhdRa8e5k5+vN+uwcjSrSxUaebBRa4ko1jqNF2uxyg8G6XYk30Jv285xzg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-remap-async-to-generator": "^7.25.0", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/traverse": "^7.25.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-async-to-generator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.24.7.tgz", + "integrity": "sha512-SQY01PcJfmQ+4Ash7NE+rpbLFbmqA2GPIgqzxfFTL4t1FKRq4zTms/7htKpoCUI9OcFYgzqfmCdH53s6/jn5fA==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-remap-async-to-generator": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoped-functions": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.24.7.tgz", + "integrity": "sha512-yO7RAz6EsVQDaBH18IDJcMB1HnrUn2FJ/Jslc/WtPPWcjhpUJXU/rjbwmluzp7v/ZzWcEhTMXELnnsz8djWDwQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-block-scoping": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.0.tgz", + "integrity": "sha512-yBQjYoOjXlFv9nlXb3f1casSHOZkWr29NX+zChVanLg5Nc157CrbEX9D7hxxtTpuFy7Q0YzmmWfJxzvps4kXrQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-properties": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.4.tgz", + "integrity": "sha512-nZeZHyCWPfjkdU5pA/uHiTaDAFUEqkpzf1YoQT2NeSynCGYq9rxfyI3XpQbfx/a0hSnFH6TGlEXvae5Vi7GD8g==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-class-static-block": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.24.7.tgz", + "integrity": "sha512-HMXK3WbBPpZQufbMG4B46A90PkuuhN9vBCb5T8+VAHqvAqvcLi+2cKoukcpmUYkszLhScU3l1iudhrks3DggRQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-class-static-block": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.12.0" + } + }, + "node_modules/@babel/plugin-transform-classes": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.4.tgz", + "integrity": "sha512-oexUfaQle2pF/b6E0dwsxQtAol9TLSO88kQvym6HHBWFliV2lGdrPieX+WgMRLSJDVzdYywk7jXbLPuO2KLTLg==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-replace-supers": "^7.25.0", + "@babel/traverse": "^7.25.4", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-computed-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.24.7.tgz", + "integrity": "sha512-25cS7v+707Gu6Ds2oY6tCkUwsJ9YIDbggd9+cu9jzzDgiNq7hR/8dkzxWfKWnTic26vsI3EsCXNd4iEB6e8esQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/template": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-destructuring": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.24.8.tgz", + "integrity": "sha512-36e87mfY8TnRxc7yc6M9g9gOB7rKgSahqkIKwLpz4Ppk2+zC2Cy1is0uwtuSG6AE4zlTOUa+7JGz9jCJGLqQFQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-dotall-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.24.7.tgz", + "integrity": "sha512-ZOA3W+1RRTSWvyqcMJDLqbchh7U4NRGqwRfFSVbOLS/ePIP4vHB5e8T8eXcuqyN1QkgKyj5wuW0lcS85v4CrSw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-keys": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.24.7.tgz", + "integrity": "sha512-JdYfXyCRihAe46jUIliuL2/s0x0wObgwwiGxw/UbgJBr20gQBThrokO4nYKgWkD7uBaqM7+9x5TU7NkExZJyzw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.0.tgz", + "integrity": "sha512-YLpb4LlYSc3sCUa35un84poXoraOiQucUTTu8X1j18JV+gNa8E0nyUf/CjZ171IRGr4jEguF+vzJU66QZhn29g==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-dynamic-import": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.24.7.tgz", + "integrity": "sha512-sc3X26PhZQDb3JhORmakcbvkeInvxz+A8oda99lj7J60QRuPZvNAk9wQlTBS1ZynelDrDmTU4pw1tyc5d5ZMUg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-dynamic-import": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-exponentiation-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.24.7.tgz", + "integrity": "sha512-Rqe/vSc9OYgDajNIK35u7ot+KeCoetqQYFXM4Epf7M7ez3lWlOjrDjrwMei6caCVhfdw+mIKD4cgdGNy5JQotQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-builder-binary-assignment-operator-visitor": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-export-namespace-from": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.24.7.tgz", + "integrity": "sha512-v0K9uNYsPL3oXZ/7F9NNIbAj2jv1whUEtyA6aujhekLs56R++JDQuzRcP2/z4WX5Vg/c5lE9uWZA0/iUoFhLTA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-flow-strip-types": { + "version": "7.26.5", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-flow-strip-types/-/plugin-transform-flow-strip-types-7.26.5.tgz", + "integrity": "sha512-eGK26RsbIkYUns3Y8qKl362juDDYK+wEdPGHGrhzUl6CewZFo55VZ7hg+CyMFU4dd5QQakBN86nBMpRsFpRvbQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/plugin-syntax-flow": "^7.26.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-for-of": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.24.7.tgz", + "integrity": "sha512-wo9ogrDG1ITTTBsy46oGiN1dS9A7MROBTcYsfS8DtsImMkHk9JXJ3EWQM6X2SUw4x80uGPlwj0o00Uoc6nEE3g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-function-name": { + "version": "7.25.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.1.tgz", + "integrity": "sha512-TVVJVdW9RKMNgJJlLtHsKDTydjZAbwIsn6ySBPQaEAUU5+gVvlJt/9nRmqVbsV/IBanRjzWoaAQKLoamWVOUuA==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.8", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/traverse": "^7.25.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-json-strings": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.24.7.tgz", + "integrity": "sha512-2yFnBGDvRuxAaE/f0vfBKvtnvvqU8tGpMHqMNpTN2oWMKIR3NqFkjaAgGwawhqK/pIN2T3XdjGPdaG0vDhOBGw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-json-strings": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-literals": { + "version": "7.25.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.2.tgz", + "integrity": "sha512-HQI+HcTbm9ur3Z2DkO+jgESMAMcYLuN/A7NRw9juzxAezN9AvqvUTnpKP/9kkYANz6u7dFlAyOu44ejuGySlfw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-logical-assignment-operators": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.24.7.tgz", + "integrity": "sha512-4D2tpwlQ1odXmTEIFWy9ELJcZHqrStlzK/dAOWYyxX3zT0iXQB6banjgeOJQXzEc4S0E0a5A+hahxPaEFYftsw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-member-expression-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.24.7.tgz", + "integrity": "sha512-T/hRC1uqrzXMKLQ6UCwMT85S3EvqaBXDGf0FaMf4446Qx9vKwlghvee0+uuZcDUCZU5RuNi4781UQ7R308zzBw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-amd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.24.7.tgz", + "integrity": "sha512-9+pB1qxV3vs/8Hdmz/CulFB8w2tuu6EB94JZFsjdqxQokwGa9Unap7Bo2gGBGIvPmDIVvQrom7r5m/TCDMURhg==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-commonjs": { + "version": "7.26.3", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", + "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.26.0", + "@babel/helper-plugin-utils": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-systemjs": { + "version": "7.25.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.0.tgz", + "integrity": "sha512-YPJfjQPDXxyQWg/0+jHKj1llnY5f/R6a0p/vP4lPymxLu7Lvl4k2WMitqi08yxwQcCVUUdG9LCUj4TNEgAp3Jw==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.25.0", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-identifier": "^7.24.7", + "@babel/traverse": "^7.25.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-modules-umd": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.24.7.tgz", + "integrity": "sha512-3aytQvqJ/h9z4g8AsKPLvD4Zqi2qT+L3j7XoFFu1XBlZWEl2/1kWnhmAbxpLgPrHSY0M6UA02jyTiwUVtiKR6A==", + "license": "MIT", + "dependencies": { + "@babel/helper-module-transforms": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.24.7.tgz", + "integrity": "sha512-/jr7h/EWeJtk1U/uz2jlsCioHkZk1JJZVcc8oQsJ1dUlaJD83f4/6Zeh2aHt9BIFokHIsSeDfhUmju0+1GPd6g==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/plugin-transform-new-target": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.24.7.tgz", + "integrity": "sha512-RNKwfRIXg4Ls/8mMTza5oPF5RkOW8Wy/WgMAp1/F1yZ8mMbtwXW+HDoJiOsagWrAhI5f57Vncrmr9XeT4CVapA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.24.7.tgz", + "integrity": "sha512-Ts7xQVk1OEocqzm8rHMXHlxvsfZ0cEF2yomUqpKENHWMF4zKk175Y4q8H5knJes6PgYad50uuRmt3UJuhBw8pQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-numeric-separator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.24.7.tgz", + "integrity": "sha512-e6q1TiVUzvH9KRvicuxdBTUj4AdKSRwzIyFFnfnezpCfP2/7Qmbb8qbU2j7GODbl4JMkblitCQjKYUaX/qkkwA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-numeric-separator": "^7.10.4" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-rest-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.24.7.tgz", + "integrity": "sha512-4QrHAr0aXQCEFni2q4DqKLD31n2DL+RxcwnNjDFkSG0eNQ/xCavnRkfCUjsyqGC2OviNJvZOF/mQqZBw7i2C5Q==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-transform-parameters": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-object-super": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.24.7.tgz", + "integrity": "sha512-A/vVLwN6lBrMFmMDmPPz0jnE6ZGx7Jq7d6sT/Ev4H65RER6pZ+kczlf1DthF5N0qaPHBsI7UXiE8Zy66nmAovg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-replace-supers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-catch-binding": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.24.7.tgz", + "integrity": "sha512-uLEndKqP5BfBbC/5jTwPxLh9kqPWWgzN/f8w6UwAIirAEqiIVJWWY312X72Eub09g5KF9+Zn7+hT7sDxmhRuKA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-optional-chaining": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.24.8.tgz", + "integrity": "sha512-5cTOLSMs9eypEy8JUVvIKOu6NgvbJMnpG62VpIHrTmROdQ+L5mDAaI40g25k5vXti55JWNX5jCkq3HZxXBQANw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7", + "@babel/plugin-syntax-optional-chaining": "^7.8.3" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-parameters": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.24.7.tgz", + "integrity": "sha512-yGWW5Rr+sQOhK0Ot8hjDJuxU3XLRQGflvT4lhlSY0DFvdb3TwKaY26CJzHtYllU0vT9j58hc37ndFPsqT1SrzA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-methods": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.4.tgz", + "integrity": "sha512-ao8BG7E2b/URaUQGqN3Tlsg+M3KlHY6rJ1O1gXAEUnZoyNQnvKyH87Kfg+FoxSeyWUB8ISZZsC91C44ZuBFytw==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.4", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-private-property-in-object": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.24.7.tgz", + "integrity": "sha512-9z76mxwnwFxMyxZWEgdgECQglF2Q7cFLm0kMf8pGwt+GSJsY0cONKj/UuO4bOH0w/uAel3ekS4ra5CEAyJRmDA==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.24.7", + "@babel/helper-create-class-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-property-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.24.7.tgz", + "integrity": "sha512-EMi4MLQSHfd2nrCqQEWxFdha2gBCqU4ZcCng4WBGZ5CJL4bBRW0ptdqqDdeirGZcpALazVVNJqRmsO8/+oNCBA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-display-name": { + "version": "7.16.7", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx": { + "version": "7.17.12", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.16.7", + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.17.12", + "@babel/plugin-syntax-jsx": "^7.17.12", + "@babel/types": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.17.12", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.17.12" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.16.7", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.16.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-regenerator": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.24.7.tgz", + "integrity": "sha512-lq3fvXPdimDrlg6LWBoqj+r/DEWgONuwjuOuQCSYgRroXDH/IdM1C0IZf59fL5cHLpjEH/O6opIRBbqv7ELnuA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "regenerator-transform": "^0.15.2" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-reserved-words": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.24.7.tgz", + "integrity": "sha512-0DUq0pHcPKbjFZCfTss/pGkYMfy3vFWydkUBd9r0GHpIyfs2eCDENvqadMycRS9wZCXR41wucAfJHJmwA0UmoQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-runtime": { + "version": "7.18.5", + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.16.7", + "@babel/helper-plugin-utils": "^7.17.12", + "babel-plugin-polyfill-corejs2": "^0.3.0", + "babel-plugin-polyfill-corejs3": "^0.5.0", + "babel-plugin-polyfill-regenerator": "^0.3.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-shorthand-properties": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.24.7.tgz", + "integrity": "sha512-KsDsevZMDsigzbA09+vacnLpmPH4aWjcZjXdyFKGzpplxhbeB4wYtury3vglQkg6KM/xEPKt73eCjPPf1PgXBA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-spread": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.24.7.tgz", + "integrity": "sha512-x96oO0I09dgMDxJaANcRyD4ellXFLLiWhuwDxKZX5g2rWP1bTPkBSwCYv96VDXVT1bD9aPj8tppr5ITIh8hBng==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7", + "@babel/helper-skip-transparent-expression-wrappers": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-sticky-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.24.7.tgz", + "integrity": "sha512-kHPSIJc9v24zEml5geKg9Mjx5ULpfncj0wRpYtxbvKyTtHCYDkVE3aHQ03FrpEo4gEe2vrJJS1Y9CJTaThA52g==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-template-literals": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.24.7.tgz", + "integrity": "sha512-AfDTQmClklHCOLxtGoP7HkeMw56k1/bTQjwsfhL6pppo/M4TOBSq+jjBUBLmV/4oeFg4GWMavIl44ZeCtmmZTw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typeof-symbol": { + "version": "7.24.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.24.8.tgz", + "integrity": "sha512-adNTUpDCVnmAE58VEqKlAA6ZBlNkMnWD0ZcW76lyNFN3MJniyGFZfNwERVk8Ap56MCnXztmDr19T4mPTztcuaw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.26.8", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.26.8.tgz", + "integrity": "sha512-bME5J9AC8ChwA7aEPJ6zym3w7aObZULHhbNLU0bKUhKsAkylkzUdq+0kdymh9rzi8nlNFl2bmldFBCKNJBUpuw==", + "license": "MIT", + "dependencies": { + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.26.5", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-escapes": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.24.7.tgz", + "integrity": "sha512-U3ap1gm5+4edc2Q/P+9VrBNhGkfnf+8ZqppY71Bo/pzZmXhhLdqgaUl6cuB07O1+AQJtCLfaOmswiNbSQ9ivhw==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-property-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.24.7.tgz", + "integrity": "sha512-uH2O4OV5M9FZYQrwc7NdVmMxQJOCCzFeYudlZSzUAHRFeOujQefa92E74TQDVskNHCzOXoigEuoyzHDhaEaK5w==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-regex": { + "version": "7.24.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.24.7.tgz", + "integrity": "sha512-hlQ96MBZSAXUq7ltkjtu3FJCCSMx/j629ns3hA3pXnBXjanNP0LHi+JpPeA81zaWgVK1VGH95Xuy7u0RyQ8kMg==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.7" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-unicode-sets-regex": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.4.tgz", + "integrity": "sha512-qesBxiWkgN1Q+31xUE9RcMk79eOXXDCv6tfyGMRSs4RGlioSg2WVyQAm07k726cSE56pa+Kb0y9epX2qaXzTvA==", + "license": "MIT", + "dependencies": { + "@babel/helper-create-regexp-features-plugin": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/preset-env": { + "version": "7.25.4", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.25.4.tgz", + "integrity": "sha512-W9Gyo+KmcxjGahtt3t9fb14vFRWvPpu5pT6GBlovAK6BTBcxgjfVMSQCfJl4oi35ODrxP6xx2Wr8LNST57Mraw==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.25.4", + "@babel/helper-compilation-targets": "^7.25.2", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/helper-validator-option": "^7.24.8", + "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.3", + "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.0", + "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.0", + "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.24.7", + "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.0", + "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-dynamic-import": "^7.8.3", + "@babel/plugin-syntax-export-namespace-from": "^7.8.3", + "@babel/plugin-syntax-import-assertions": "^7.24.7", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5", + "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", + "@babel/plugin-transform-arrow-functions": "^7.24.7", + "@babel/plugin-transform-async-generator-functions": "^7.25.4", + "@babel/plugin-transform-async-to-generator": "^7.24.7", + "@babel/plugin-transform-block-scoped-functions": "^7.24.7", + "@babel/plugin-transform-block-scoping": "^7.25.0", + "@babel/plugin-transform-class-properties": "^7.25.4", + "@babel/plugin-transform-class-static-block": "^7.24.7", + "@babel/plugin-transform-classes": "^7.25.4", + "@babel/plugin-transform-computed-properties": "^7.24.7", + "@babel/plugin-transform-destructuring": "^7.24.8", + "@babel/plugin-transform-dotall-regex": "^7.24.7", + "@babel/plugin-transform-duplicate-keys": "^7.24.7", + "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.0", + "@babel/plugin-transform-dynamic-import": "^7.24.7", + "@babel/plugin-transform-exponentiation-operator": "^7.24.7", + "@babel/plugin-transform-export-namespace-from": "^7.24.7", + "@babel/plugin-transform-for-of": "^7.24.7", + "@babel/plugin-transform-function-name": "^7.25.1", + "@babel/plugin-transform-json-strings": "^7.24.7", + "@babel/plugin-transform-literals": "^7.25.2", + "@babel/plugin-transform-logical-assignment-operators": "^7.24.7", + "@babel/plugin-transform-member-expression-literals": "^7.24.7", + "@babel/plugin-transform-modules-amd": "^7.24.7", + "@babel/plugin-transform-modules-commonjs": "^7.24.8", + "@babel/plugin-transform-modules-systemjs": "^7.25.0", + "@babel/plugin-transform-modules-umd": "^7.24.7", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.24.7", + "@babel/plugin-transform-new-target": "^7.24.7", + "@babel/plugin-transform-nullish-coalescing-operator": "^7.24.7", + "@babel/plugin-transform-numeric-separator": "^7.24.7", + "@babel/plugin-transform-object-rest-spread": "^7.24.7", + "@babel/plugin-transform-object-super": "^7.24.7", + "@babel/plugin-transform-optional-catch-binding": "^7.24.7", + "@babel/plugin-transform-optional-chaining": "^7.24.8", + "@babel/plugin-transform-parameters": "^7.24.7", + "@babel/plugin-transform-private-methods": "^7.25.4", + "@babel/plugin-transform-private-property-in-object": "^7.24.7", + "@babel/plugin-transform-property-literals": "^7.24.7", + "@babel/plugin-transform-regenerator": "^7.24.7", + "@babel/plugin-transform-reserved-words": "^7.24.7", + "@babel/plugin-transform-shorthand-properties": "^7.24.7", + "@babel/plugin-transform-spread": "^7.24.7", + "@babel/plugin-transform-sticky-regex": "^7.24.7", + "@babel/plugin-transform-template-literals": "^7.24.7", + "@babel/plugin-transform-typeof-symbol": "^7.24.8", + "@babel/plugin-transform-unicode-escapes": "^7.24.7", + "@babel/plugin-transform-unicode-property-regex": "^7.24.7", + "@babel/plugin-transform-unicode-regex": "^7.24.7", + "@babel/plugin-transform-unicode-sets-regex": "^7.25.4", + "@babel/preset-modules": "0.1.6-no-external-plugins", + "babel-plugin-polyfill-corejs2": "^0.4.10", + "babel-plugin-polyfill-corejs3": "^0.10.6", + "babel-plugin-polyfill-regenerator": "^0.6.1", + "core-js-compat": "^3.37.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-env/node_modules/@babel/helper-define-polyfill-provider": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz", + "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-compilation-targets": "^7.22.6", + "@babel/helper-plugin-utils": "^7.22.5", + "debug": "^4.1.1", + "lodash.debounce": "^4.0.8", + "resolve": "^1.14.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.4.11", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", + "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.22.6", + "@babel/helper-define-polyfill-provider": "^0.6.2", + "semver": "^6.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.10.6", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", + "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2", + "core-js-compat": "^3.38.0" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz", + "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.6.2" + }, + "peerDependencies": { + "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-env/node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/preset-env/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/@babel/preset-flow": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/preset-flow/-/preset-flow-7.25.9.tgz", + "integrity": "sha512-EASHsAhE+SSlEzJ4bzfusnXSHiU+JfAYzj+jbw2vgQKgq5HrUr8qs+vgtiEL5dOH6sEweI+PNt2D7AqrDSHyqQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-transform-flow-strip-types": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/preset-modules": { + "version": "0.1.6-no-external-plugins", + "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz", + "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/types": "^7.4.4", + "esutils": "^2.0.2" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + } + }, + "node_modules/@babel/preset-typescript": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz", + "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==", + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-validator-option": "^7.25.9", + "@babel/plugin-syntax-jsx": "^7.25.9", + "@babel/plugin-transform-modules-commonjs": "^7.25.9", + "@babel/plugin-transform-typescript": "^7.25.9" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.25.9.tgz", + "integrity": "sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==", + "license": "MIT", + "dependencies": { + "clone-deep": "^4.0.1", + "find-cache-dir": "^2.0.0", + "make-dir": "^2.1.0", + "pirates": "^4.0.6", + "source-map-support": "^0.5.16" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/register/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "license": "MIT", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@babel/register/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/@babel/register/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/@babel/regjsgen": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/@babel/regjsgen/-/regjsgen-0.8.0.tgz", + "integrity": "sha512-x/rqGMdzj+fWZvCOYForTghzbtqPDZ5gPwaoNGHdgDfF2QA/XZbCBp4Moo5scrkAMPhB7z26XM/AaHuIJdgauA==", + "license": "MIT" + }, + "node_modules/@babel/runtime": { + "version": "7.28.3", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz", + "integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/template": { + "version": "7.27.2", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", + "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.27.1", + "@babel/parser": "^7.27.2", + "@babel/types": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.26.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.9.tgz", + "integrity": "sha512-ZYW7L+pL8ahU5fXmNbPF+iZFHCv5scFak7MZ9bwaRPLUhHh7QQEMjZUg0HevihoqCM5iSYHN61EyCoZvqC+bxg==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.26.2", + "@babel/generator": "^7.26.9", + "@babel/parser": "^7.26.9", + "@babel/template": "^7.26.9", + "@babel/types": "^7.26.9", + "debug": "^4.3.1", + "globals": "^11.1.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse/node_modules/debug": { + "version": "4.3.4", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@babel/traverse/node_modules/ms": { + "version": "2.1.2", + "license": "MIT" + }, + "node_modules/@babel/types": { + "version": "7.28.2", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", + "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@bcoe/v8-coverage": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", + "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.1", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz", + "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.1.4.tgz", + "integrity": "sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.6.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/@eslint/eslintrc/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/@eslint/eslintrc/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/eslintrc/node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/eslintrc/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@eslint/js": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.57.1.tgz", + "integrity": "sha512-d9zaMRSTIKDLhctzH12MtXvJKSSUhaHcjV+2Z+GK+EEY7XKpP5yR4x+N3TAcHTcu963nIr+TMcCb4DBCYX1z6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@humanwhocodes/config-array": { + "version": "0.13.0", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.13.0.tgz", + "integrity": "sha512-DZLEEqFWQFiyK6h5YIeynKx7JlvCYWL0cImfSRXZ9l4Sg2efkFGTuFf6vzXjK1cq6IYkU+Eg/JizXw+TD2vRNw==", + "deprecated": "Use @eslint/config-array instead", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanwhocodes/object-schema": "^2.0.3", + "debug": "^4.3.1", + "minimatch": "^3.0.5" + }, + "engines": { + "node": ">=10.10.0" + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@humanwhocodes/config-array/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/object-schema": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-2.0.3.tgz", + "integrity": "sha512-93zYdMES/c1D69yZiKDBj0V24vqNzB/koF26KPaagAfd3P/4gUlh3Dys5ogAK+Exi9QyzlD8x/08Zt7wIKcDcA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@isaacs/ttlcache": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@isaacs/ttlcache/-/ttlcache-1.4.1.tgz", + "integrity": "sha512-RQgQ4uQ+pLbqXfOmieB91ejmLwvSgv9nLx6sT6sD83s7umBypgg+OIBOBbEUiJXrfpnp9j0mRhYYdzp9uqq3lA==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/@istanbuljs/load-nyc-config": { + "version": "1.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "camelcase": "^5.3.1", + "find-up": "^4.1.0", + "get-package-type": "^0.1.0", + "js-yaml": "^3.13.1", + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": { + "version": "5.3.1", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@istanbuljs/schema": { + "version": "0.1.3", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@jest/console": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz", + "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/core": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz", + "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/reporters": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-changed-files": "^29.7.0", + "jest-config": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-resolve-dependencies": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "jest-watcher": "^29.7.0", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/create-cache-key-function": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/create-cache-key-function/-/create-cache-key-function-29.7.0.tgz", + "integrity": "sha512-4QqS3LY5PBmTRHj9sAg1HLoPzqAI0uOX6wI/TRqHIcOxlFidy6YEmCQJk6FSZjNLGCeubDMfmkWL+qaLKhSGQA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/environment": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", + "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", + "license": "MIT", + "dependencies": { + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "expect": "^29.7.0", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/expect-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz", + "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/fake-timers": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz", + "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@sinonjs/fake-timers": "^10.0.2", + "@types/node": "*", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/globals": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz", + "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/types": "^29.6.3", + "jest-mock": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/reporters": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz", + "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@bcoe/v8-coverage": "^0.2.3", + "@jest/console": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "@types/node": "*", + "chalk": "^4.0.0", + "collect-v8-coverage": "^1.0.0", + "exit": "^0.1.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "istanbul-lib-coverage": "^3.0.0", + "istanbul-lib-instrument": "^6.0.0", + "istanbul-lib-report": "^3.0.0", + "istanbul-lib-source-maps": "^4.0.0", + "istanbul-reports": "^3.1.3", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "slash": "^3.0.0", + "string-length": "^4.0.1", + "strip-ansi": "^6.0.0", + "v8-to-istanbul": "^9.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/@jest/reporters/node_modules/istanbul-lib-instrument": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", + "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.23.9", + "@babel/parser": "^7.23.9", + "@istanbuljs/schema": "^0.1.3", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^7.5.4" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/reporters/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@jest/schemas": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", + "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", + "license": "MIT", + "dependencies": { + "@sinclair/typebox": "^0.27.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/source-map": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz", + "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.18", + "callsites": "^3.0.0", + "graceful-fs": "^4.2.9" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-result": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz", + "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "collect-v8-coverage": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/test-sequencer": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz", + "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/transform": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz", + "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/types": "^29.6.3", + "@jridgewell/trace-mapping": "^0.3.18", + "babel-plugin-istanbul": "^6.1.1", + "chalk": "^4.0.0", + "convert-source-map": "^2.0.0", + "fast-json-stable-stringify": "^2.1.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "micromatch": "^4.0.4", + "pirates": "^4.0.4", + "slash": "^3.0.0", + "write-file-atomic": "^4.0.2" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jest/types": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz", + "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^17.0.8", + "chalk": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.13", + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.14", + "license": "MIT" + }, + "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { + "version": "5.1.1-v1", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", + "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-scope": "5.1.1" + } + }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@react-native-community/cli": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli/-/cli-12.3.7.tgz", + "integrity": "sha512-7+mOhk+3+X3BjSJZZvYrDJynA00gPYTlvT28ZjiLlbuVGfqfNiBKaxuF7rty+gjjpch4iKGvLhIhSN5cuOsdHQ==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-clean": "12.3.7", + "@react-native-community/cli-config": "12.3.7", + "@react-native-community/cli-debugger-ui": "12.3.7", + "@react-native-community/cli-doctor": "12.3.7", + "@react-native-community/cli-hermes": "12.3.7", + "@react-native-community/cli-plugin-metro": "12.3.7", + "@react-native-community/cli-server-api": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", + "@react-native-community/cli-types": "12.3.7", + "chalk": "^4.1.2", + "commander": "^9.4.1", + "deepmerge": "^4.3.0", + "execa": "^5.0.0", + "find-up": "^4.1.0", + "fs-extra": "^8.1.0", + "graceful-fs": "^4.1.3", + "prompts": "^2.4.2", + "semver": "^7.5.2" + }, + "bin": { + "react-native": "build/bin.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native-community/cli-clean": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-clean/-/cli-clean-12.3.7.tgz", + "integrity": "sha512-BCYW77QqyxfhiMEBOoHyciJRNV6Rhz1RvclReIKnCA9wAwmoJBeu4Mu+AwiECA2bUITX16fvPt3NwDsSd1jwfQ==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "12.3.7", + "chalk": "^4.1.2", + "execa": "^5.0.0" + } + }, + "node_modules/@react-native-community/cli-config": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-config/-/cli-config-12.3.7.tgz", + "integrity": "sha512-IU2UhO9yj1rEBNhHWGzIXpPDzha4hizLP/PUOrhR4BUf6RVPUWEp+e1PXNGR0qjIf6esu7OC7t6mLOhH0NUJEw==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "12.3.7", + "chalk": "^4.1.2", + "cosmiconfig": "^5.1.0", + "deepmerge": "^4.3.0", + "glob": "^7.1.3", + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli-debugger-ui": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-debugger-ui/-/cli-debugger-ui-12.3.7.tgz", + "integrity": "sha512-UHUFrRdcjWSCdWG9KIp2QjuRIahBQnb9epnQI7JCq6NFbFHYfEI4rI7msjMn+gG8/tSwKTV2PTPuPmZ5wWlE7Q==", + "license": "MIT", + "dependencies": { + "serve-static": "^1.13.1" + } + }, + "node_modules/@react-native-community/cli-doctor": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-doctor/-/cli-doctor-12.3.7.tgz", + "integrity": "sha512-gCamZztRoAyhciuQPqdz4Xe4t3gOdNsaADNd+rva+Rx8W2PoPeNv60i7/et06wlsn6B6Sh0/hMiAftJbiHDFkg==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-config": "12.3.7", + "@react-native-community/cli-platform-android": "12.3.7", + "@react-native-community/cli-platform-ios": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", + "chalk": "^4.1.2", + "command-exists": "^1.2.8", + "deepmerge": "^4.3.0", + "envinfo": "^7.10.0", + "execa": "^5.0.0", + "hermes-profile-transformer": "^0.0.6", + "node-stream-zip": "^1.9.1", + "ora": "^5.4.1", + "semver": "^7.5.2", + "strip-ansi": "^5.2.0", + "wcwidth": "^1.0.1", + "yaml": "^2.2.1" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli-doctor/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/@react-native-community/cli-hermes": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-hermes/-/cli-hermes-12.3.7.tgz", + "integrity": "sha512-ezzeiSKjRXK2+i1AAe7NhhN9CEHrgtRmTn2MAdBpE++N8fH5EQZgxFcGgGdwGvns2fm9ivyyeVnI5eAYwvM+jg==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-platform-android": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", + "chalk": "^4.1.2", + "hermes-profile-transformer": "^0.0.6" + } + }, + "node_modules/@react-native-community/cli-platform-android": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-android/-/cli-platform-android-12.3.7.tgz", + "integrity": "sha512-mOltF3cpjNdJb3WSFwEHc1GH4ibCcnOvQ34OdWyblKy9ijuvG5SjNTlYR/UW/CURaDi3OUKAhxQMTY5d27bzGQ==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "12.3.7", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-xml-parser": "^4.2.4", + "glob": "^7.1.3", + "logkitty": "^0.7.1" + } + }, + "node_modules/@react-native-community/cli-platform-ios": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-platform-ios/-/cli-platform-ios-12.3.7.tgz", + "integrity": "sha512-2WnVsMH4ORZIhBm/5nCms1NeeKG4KarNC7PMLmrXWXB/bibDcaNsjrJiqnmCUcpTEvTQTokRfoO7Aj6NM0Cqow==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-tools": "12.3.7", + "chalk": "^4.1.2", + "execa": "^5.0.0", + "fast-xml-parser": "^4.0.12", + "glob": "^7.1.3", + "ora": "^5.4.1" + } + }, + "node_modules/@react-native-community/cli-plugin-metro": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-plugin-metro/-/cli-plugin-metro-12.3.7.tgz", + "integrity": "sha512-ahEw0Vfnv2Nv/jdZ2QDuGjQ9l2SczO4lXjb3ubu5vEYNLyTw3jYsLMK6iES7YQ/ApQmKdG476HU1O9uZdpaYPg==", + "license": "MIT" + }, + "node_modules/@react-native-community/cli-server-api": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-server-api/-/cli-server-api-12.3.7.tgz", + "integrity": "sha512-LYETs3CCjrLn1ZU0kYv44TywiIl5IPFHZGeXhAh2TtgOk4mo3kvXxECDil9CdO3bmDra6qyiG61KHvzr8IrHdg==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-debugger-ui": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", + "compression": "^1.7.1", + "connect": "^3.6.5", + "errorhandler": "^1.5.1", + "nocache": "^3.0.1", + "pretty-format": "^26.6.2", + "serve-static": "^1.13.1", + "ws": "^7.5.1" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@jest/types": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@jest/types/-/types-26.6.2.tgz", + "integrity": "sha512-fC6QCp7Sc5sX6g8Tvbmj4XUTbyrik0akgRy03yjXbQaBWWNWGE7SGtJk98m0N8nzegD/7SggrUlivxo5ax4KWQ==", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/@types/yargs": { + "version": "15.0.19", + "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-15.0.19.tgz", + "integrity": "sha512-2XUaGVmyQjgyAZldf0D0c14vvo/yv0MhQBSTJcejMMaitsn3nxCB6TmH4G0ZQf+uxROOa9mpanoSm8h6SG/1ZA==", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/pretty-format": { + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-26.6.2.tgz", + "integrity": "sha512-7AeGuCYNGmycyQbCqd/3PWH4eOoX/OiCa0uphp57NVTeAGdJGaAliecxwBDHYQCIvrW7aDBZCYeNTP/WX69mkg==", + "license": "MIT", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/@react-native-community/cli-server-api/node_modules/react-is": { + "version": "17.0.2", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", + "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==", + "license": "MIT" + }, + "node_modules/@react-native-community/cli-tools": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-tools/-/cli-tools-12.3.7.tgz", + "integrity": "sha512-7NL/1/i+wzd4fBr/FSr3ypR05tiU/Kv9l/M1sL1c6jfcDtWXAL90R161gQkQFK7shIQ8Idp0dQX1rq49tSyfQw==", + "license": "MIT", + "dependencies": { + "appdirsjs": "^1.2.4", + "chalk": "^4.1.2", + "find-up": "^5.0.0", + "mime": "^2.4.1", + "node-fetch": "^2.6.0", + "open": "^6.2.0", + "ora": "^5.4.1", + "semver": "^7.5.2", + "shell-quote": "^1.7.3", + "sudo-prompt": "^9.0.0" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native-community/cli-tools/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli-types": { + "version": "12.3.7", + "resolved": "https://registry.npmjs.org/@react-native-community/cli-types/-/cli-types-12.3.7.tgz", + "integrity": "sha512-NFtUMyIrNfi3A5C1cjVKDVvYHvvOF7MnOMwdD8jm2NQKewQJrehKBh1eMuykKdqhWyZmuemD4KKhL8f4FxgG0w==", + "license": "MIT", + "dependencies": { + "joi": "^17.2.1" + } + }, + "node_modules/@react-native-community/cli/node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/@react-native-community/cli/node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "license": "MIT", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/@react-native-community/cli/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@react-native-community/cli/node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "license": "MIT", + "engines": { + "node": ">= 4.0.0" + } + }, + "node_modules/@react-native/assets-registry": { + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/assets-registry/-/assets-registry-0.73.1.tgz", + "integrity": "sha512-2FgAbU7uKM5SbbW9QptPPZx8N9Ke2L7bsHb+EhAanZjFZunA9PaYtyjUQ1s7HD+zDVqOQIvjkpXSv7Kejd2tqg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-plugin-codegen": { + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/babel-plugin-codegen/-/babel-plugin-codegen-0.73.4.tgz", + "integrity": "sha512-XzRd8MJGo4Zc5KsphDHBYJzS1ryOHg8I2gOZDAUCGcwLFhdyGu1zBNDJYH2GFyDrInn9TzAbRIf3d4O+eltXQQ==", + "license": "MIT", + "dependencies": { + "@react-native/codegen": "0.73.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/babel-preset": { + "version": "0.73.21", + "resolved": "https://registry.npmjs.org/@react-native/babel-preset/-/babel-preset-0.73.21.tgz", + "integrity": "sha512-WlFttNnySKQMeujN09fRmrdWqh46QyJluM5jdtDNrkl/2Hx6N4XeDUGhABvConeK95OidVO7sFFf7sNebVXogA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/plugin-proposal-async-generator-functions": "^7.0.0", + "@babel/plugin-proposal-class-properties": "^7.18.0", + "@babel/plugin-proposal-export-default-from": "^7.0.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.18.0", + "@babel/plugin-proposal-numeric-separator": "^7.0.0", + "@babel/plugin-proposal-object-rest-spread": "^7.20.0", + "@babel/plugin-proposal-optional-catch-binding": "^7.0.0", + "@babel/plugin-proposal-optional-chaining": "^7.20.0", + "@babel/plugin-syntax-dynamic-import": "^7.8.0", + "@babel/plugin-syntax-export-default-from": "^7.0.0", + "@babel/plugin-syntax-flow": "^7.18.0", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.0.0", + "@babel/plugin-syntax-optional-chaining": "^7.0.0", + "@babel/plugin-transform-arrow-functions": "^7.0.0", + "@babel/plugin-transform-async-to-generator": "^7.20.0", + "@babel/plugin-transform-block-scoping": "^7.0.0", + "@babel/plugin-transform-classes": "^7.0.0", + "@babel/plugin-transform-computed-properties": "^7.0.0", + "@babel/plugin-transform-destructuring": "^7.20.0", + "@babel/plugin-transform-flow-strip-types": "^7.20.0", + "@babel/plugin-transform-function-name": "^7.0.0", + "@babel/plugin-transform-literals": "^7.0.0", + "@babel/plugin-transform-modules-commonjs": "^7.0.0", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.0.0", + "@babel/plugin-transform-parameters": "^7.0.0", + "@babel/plugin-transform-private-methods": "^7.22.5", + "@babel/plugin-transform-private-property-in-object": "^7.22.11", + "@babel/plugin-transform-react-display-name": "^7.0.0", + "@babel/plugin-transform-react-jsx": "^7.0.0", + "@babel/plugin-transform-react-jsx-self": "^7.0.0", + "@babel/plugin-transform-react-jsx-source": "^7.0.0", + "@babel/plugin-transform-runtime": "^7.0.0", + "@babel/plugin-transform-shorthand-properties": "^7.0.0", + "@babel/plugin-transform-spread": "^7.0.0", + "@babel/plugin-transform-sticky-regex": "^7.0.0", + "@babel/plugin-transform-typescript": "^7.5.0", + "@babel/plugin-transform-unicode-regex": "^7.0.0", + "@babel/template": "^7.0.0", + "@react-native/babel-plugin-codegen": "0.73.4", + "babel-plugin-transform-flow-enums": "^0.0.2", + "react-refresh": "^0.14.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/babel-preset/node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/@react-native/codegen": { + "version": "0.73.3", + "resolved": "https://registry.npmjs.org/@react-native/codegen/-/codegen-0.73.3.tgz", + "integrity": "sha512-sxslCAAb8kM06vGy9Jyh4TtvjhcP36k/rvj2QE2Jdhdm61KvfafCATSIsOfc0QvnduWFcpXUPvAVyYwuv7PYDg==", + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.0", + "flow-parser": "^0.206.0", + "glob": "^7.1.1", + "invariant": "^2.2.4", + "jscodeshift": "^0.14.0", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/@react-native/community-cli-plugin": { + "version": "0.73.18", + "resolved": "https://registry.npmjs.org/@react-native/community-cli-plugin/-/community-cli-plugin-0.73.18.tgz", + "integrity": "sha512-RN8piDh/eF+QT6YYmrj3Zd9uiaDsRY/kMT0FYR42j8/M/boE4hs4Xn0u91XzT8CAkU9q/ilyo3wJsXIJo2teww==", + "license": "MIT", + "dependencies": { + "@react-native-community/cli-server-api": "12.3.7", + "@react-native-community/cli-tools": "12.3.7", + "@react-native/dev-middleware": "0.73.8", + "@react-native/metro-babel-transformer": "0.73.15", + "chalk": "^4.0.0", + "execa": "^5.1.1", + "metro": "^0.80.3", + "metro-config": "^0.80.3", + "metro-core": "^0.80.3", + "node-fetch": "^2.2.0", + "readline": "^1.3.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/debugger-frontend": { + "version": "0.73.3", + "resolved": "https://registry.npmjs.org/@react-native/debugger-frontend/-/debugger-frontend-0.73.3.tgz", + "integrity": "sha512-RgEKnWuoo54dh7gQhV7kvzKhXZEhpF9LlMdZolyhGxHsBqZ2gXdibfDlfcARFFifPIiaZ3lXuOVVa4ei+uPgTw==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware": { + "version": "0.73.8", + "resolved": "https://registry.npmjs.org/@react-native/dev-middleware/-/dev-middleware-0.73.8.tgz", + "integrity": "sha512-oph4NamCIxkMfUL/fYtSsE+JbGOnrlawfQ0kKtDQ5xbOjPKotKoXqrs1eGwozNKv7FfQ393stk1by9a6DyASSg==", + "license": "MIT", + "dependencies": { + "@isaacs/ttlcache": "^1.4.1", + "@react-native/debugger-frontend": "0.73.3", + "chrome-launcher": "^0.15.2", + "chromium-edge-launcher": "^1.0.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "node-fetch": "^2.2.0", + "open": "^7.0.3", + "serve-static": "^1.13.1", + "temp-dir": "^2.0.0", + "ws": "^6.2.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/open": { + "version": "7.4.2", + "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz", + "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0", + "is-wsl": "^2.1.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/temp-dir": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-2.0.0.tgz", + "integrity": "sha512-aoBAniQmmwtcKp/7BzsH8Cxzv8OL736p7v1ihGb5e9DJ9kTwGWHrQrVB5+lfVDzfGrdRzXch+ig7LHaY1JTOrg==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/@react-native/dev-middleware/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/@react-native/eslint-config": { + "version": "0.73.2", + "resolved": "https://registry.npmjs.org/@react-native/eslint-config/-/eslint-config-0.73.2.tgz", + "integrity": "sha512-YzMfes19loTfbrkbYNAfHBDXX4oRBzc5wnvHs4h2GIHUj6YKs5ZK5lldqSrBJCdZAI3nuaO9Qj+t5JRwou571w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/eslint-parser": "^7.20.0", + "@react-native/eslint-plugin": "0.73.1", + "@typescript-eslint/eslint-plugin": "^5.57.1", + "@typescript-eslint/parser": "^5.57.1", + "eslint-config-prettier": "^8.5.0", + "eslint-plugin-eslint-comments": "^3.2.0", + "eslint-plugin-ft-flow": "^2.0.1", + "eslint-plugin-jest": "^26.5.3", + "eslint-plugin-prettier": "^4.2.1", + "eslint-plugin-react": "^7.30.1", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-react-native": "^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": ">=8", + "prettier": ">=2" + } + }, + "node_modules/@react-native/eslint-plugin": { + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/eslint-plugin/-/eslint-plugin-0.73.1.tgz", + "integrity": "sha512-8BNMFE8CAI7JLWLOs3u33wcwcJ821LYs5g53Xyx9GhSg0h8AygTwDrwmYb/pp04FkCNCPjKPBoaYRthQZmxgwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/gradle-plugin": { + "version": "0.73.5", + "resolved": "https://registry.npmjs.org/@react-native/gradle-plugin/-/gradle-plugin-0.73.5.tgz", + "integrity": "sha512-Orrn8J/kqzEuXudl96XcZk84ZcdIpn1ojjwGSuaSQSXNcCYbOXyt0RwtW5kjCqjgSzGnOMsJNZc5FDXHVq/WzA==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/js-polyfills": { + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/js-polyfills/-/js-polyfills-0.73.1.tgz", + "integrity": "sha512-ewMwGcumrilnF87H4jjrnvGZEaPFCAC4ebraEK+CurDDmwST/bIicI4hrOAv+0Z0F7DEK4O4H7r8q9vH7IbN4g==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/metro-babel-transformer": { + "version": "0.73.15", + "resolved": "https://registry.npmjs.org/@react-native/metro-babel-transformer/-/metro-babel-transformer-0.73.15.tgz", + "integrity": "sha512-LlkSGaXCz+xdxc9819plmpsl4P4gZndoFtpjN3GMBIu6f7TBV0GVbyJAU4GE8fuAWPVSVL5ArOcdkWKSbI1klw==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@react-native/babel-preset": "0.73.21", + "hermes-parser": "0.15.0", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "@babel/core": "*" + } + }, + "node_modules/@react-native/metro-config": { + "version": "0.73.5", + "resolved": "https://registry.npmjs.org/@react-native/metro-config/-/metro-config-0.73.5.tgz", + "integrity": "sha512-3bNWoHzOzP/+qoLJtRhOVXrnxKmSY3i4y5PXyMQlIvvOI/GQbXulPpEZxK/yUrf1MmeXHLLFufFbQWlfDEDoxA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@react-native/js-polyfills": "0.73.1", + "@react-native/metro-babel-transformer": "0.73.15", + "metro-config": "^0.80.3", + "metro-runtime": "^0.80.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@react-native/normalize-colors": { + "version": "0.73.2", + "resolved": "https://registry.npmjs.org/@react-native/normalize-colors/-/normalize-colors-0.73.2.tgz", + "integrity": "sha512-bRBcb2T+I88aG74LMVHaKms2p/T8aQd8+BZ7LuuzXlRfog1bMWWn/C5i0HVuvW4RPtXQYgIlGiXVDy9Ir1So/w==", + "license": "MIT" + }, + "node_modules/@react-native/typescript-config": { + "version": "0.73.1", + "resolved": "https://registry.npmjs.org/@react-native/typescript-config/-/typescript-config-0.73.1.tgz", + "integrity": "sha512-7Wrmdp972ZO7xvDid+xRGtvX6xz47cpGj7Y7VKlUhSVFFqbOGfB5WCpY1vMr6R/fjl+Og2fRw+TETN2+JnJi0w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@react-native/virtualized-lists": { + "version": "0.73.4", + "resolved": "https://registry.npmjs.org/@react-native/virtualized-lists/-/virtualized-lists-0.73.4.tgz", + "integrity": "sha512-HpmLg1FrEiDtrtAbXiwCgXFYyloK/dOIPIuWW3fsqukwJEWAiTzm1nXGJ7xPU5XTHiWZ4sKup5Ebaj8z7iyWog==", + "license": "MIT", + "dependencies": { + "invariant": "^2.2.4", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react-native": "*" + } + }, + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.0.0" + } + }, + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "license": "BSD-3-Clause" + }, + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", + "license": "BSD-3-Clause" + }, + "node_modules/@sinclair/typebox": { + "version": "0.27.8", + "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", + "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", + "license": "MIT" + }, + "node_modules/@sinonjs/commons": { + "version": "2.0.0", + "license": "BSD-3-Clause", + "dependencies": { + "type-detect": "4.0.8" + } + }, + "node_modules/@sinonjs/fake-timers": { + "version": "10.0.2", + "license": "BSD-3-Clause", + "dependencies": { + "@sinonjs/commons": "^2.0.0" + } + }, + "node_modules/@types/babel__core": { + "version": "7.20.0", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.6.4", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.1", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.18.3", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.3.0" + } + }, + "node_modules/@types/graceful-fs": { + "version": "4.1.9", + "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", + "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/istanbul-lib-coverage": { + "version": "2.0.4", + "license": "MIT" + }, + "node_modules/@types/istanbul-lib-report": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "*" + } + }, + "node_modules/@types/istanbul-reports": { + "version": "3.0.1", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-report": "*" + } + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "18.0.0", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.14", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.14.tgz", + "integrity": "sha512-gNMvNH49DJ7OJYv+KAKn0Xp45p8PLl6zo2YnvDIbTd4J6MER2BmWN49TG7n9LvkyihINxeKW8+3bfS2yDC9dzQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "18.3.18", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.18.tgz", + "integrity": "sha512-t4yC+vtgnkYjNSKlFx1jkAhH8LgTo2N/7Qvi83kdEaUtMDiwpbLAktKDaAMlRcJ5eSxZkH74eEGt1ky31d7kfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/prop-types": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-test-renderer": { + "version": "18.3.1", + "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.3.1.tgz", + "integrity": "sha512-vAhnk0tG2eGa37lkU9+s5SoroCsRI08xnsWFiAXOuPH2jqzMbcXvKExXViPi1P5fIklDeCvXqyrdmipFaSkZrA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/react": "^18" + } + }, + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/stack-utils": { + "version": "2.0.1", + "license": "MIT" + }, + "node_modules/@types/yargs": { + "version": "17.0.24", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/@types/yargs-parser": { + "version": "21.0.0", + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/parser/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/scope-manager": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", + "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/type-utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz", + "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/typescript-estree": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "*" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/types": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", + "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/typescript-estree": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz", + "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/visitor-keys": "5.62.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/utils/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/@typescript-eslint/visitor-keys": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", + "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/types": "5.62.0", + "eslint-visitor-keys": "^3.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + } + }, + "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@ungap/structured-clone": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", + "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", + "dev": true, + "license": "ISC" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "license": "MIT", + "dependencies": { + "event-target-shim": "^5.0.0" + }, + "engines": { + "node": ">=6.5" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "license": "MIT", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.12.1", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", + "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "8.12.0", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/anser": { + "version": "1.4.10", + "license": "MIT" + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-fragments": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/ansi-fragments/-/ansi-fragments-0.2.1.tgz", + "integrity": "sha512-DykbNHxuXQwUDRv5ibc2b0x7uw7wmwOGLBUd5RmaQ5z8Lhx19vwvKV+FAsM5rEA6dEcHxX+/Ad5s9eF2k2bB+w==", + "license": "MIT", + "dependencies": { + "colorette": "^1.0.7", + "slice-ansi": "^2.0.0", + "strip-ansi": "^5.0.0" + } + }, + "node_modules/ansi-fragments/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-fragments/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "license": "MIT", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-regex": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/anymatch": { + "version": "3.1.2", + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/appdirsjs": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/appdirsjs/-/appdirsjs-1.2.7.tgz", + "integrity": "sha512-Quji6+8kLBC3NnBeo14nPDq0+2jUs5s3/xEye+udFHumHhRk4M7aAMXp/PBJqkKYGuuyR9M/6Dq7d2AViiGmhw==", + "license": "MIT" + }, + "node_modules/argparse": { + "version": "1.0.10", + "license": "MIT", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", + "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "is-array-buffer": "^3.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-includes": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz", + "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.4", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/array.prototype.findlast": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz", + "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flat": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz", + "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.flatmap": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz", + "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/array.prototype.tosorted": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz", + "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.3", + "es-errors": "^1.3.0", + "es-shim-unscopables": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", + "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asap": { + "version": "2.0.6", + "license": "MIT" + }, + "node_modules/ast-types": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/ast-types/-/ast-types-0.15.2.tgz", + "integrity": "sha512-c27loCv9QkZinsa5ProX751khO9DJl/AcB5c2KNtA6NRvHKS0PgLfcftz72KVq504vB0Gku5s2kUZzDBvQWvHg==", + "license": "MIT", + "dependencies": { + "tslib": "^2.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/astral-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz", + "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/async-function": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz", + "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/async-limiter": { + "version": "1.0.1", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "possible-typed-array-names": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/babel-core": { + "version": "7.0.0-bridge.0", + "resolved": "https://registry.npmjs.org/babel-core/-/babel-core-7.0.0-bridge.0.tgz", + "integrity": "sha512-poPX9mZH/5CSanm50Q+1toVci6pv5KSRv/5TWCwtzQS5XEwn40BcCrgIeMFWP9CKKIniKXNxoIOnOq4VVlGXhg==", + "license": "MIT", + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz", + "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/transform": "^29.7.0", + "@types/babel__core": "^7.1.14", + "babel-plugin-istanbul": "^6.1.1", + "babel-preset-jest": "^29.6.3", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.8.0" + } + }, + "node_modules/babel-plugin-istanbul": { + "version": "6.1.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/helper-plugin-utils": "^7.0.0", + "@istanbuljs/load-nyc-config": "^1.0.0", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-instrument": "^5.0.4", + "test-exclude": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/babel-plugin-jest-hoist": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz", + "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.3.3", + "@babel/types": "^7.3.3", + "@types/babel__core": "^7.1.14", + "@types/babel__traverse": "^7.0.6" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/babel-plugin-polyfill-corejs2": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.13.11", + "@babel/helper-define-polyfill-provider": "^0.3.1", + "semver": "^6.1.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-corejs3": { + "version": "0.5.2", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1", + "core-js-compat": "^3.21.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-polyfill-regenerator": { + "version": "0.3.1", + "license": "MIT", + "dependencies": { + "@babel/helper-define-polyfill-provider": "^0.3.1" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/babel-plugin-transform-flow-enums": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/babel-plugin-transform-flow-enums/-/babel-plugin-transform-flow-enums-0.0.2.tgz", + "integrity": "sha512-g4aaCrDDOsWjbm0PUUeVnkcVd6AKJsVc/MbnPhEotEpkeJQP6b8nzewohQi7+QS8UyPehOhGWn0nOwjvWpmMvQ==", + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-flow": "^7.12.1" + } + }, + "node_modules/babel-preset-current-node-syntax": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", + "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/plugin-syntax-async-generators": "^7.8.4", + "@babel/plugin-syntax-bigint": "^7.8.3", + "@babel/plugin-syntax-class-properties": "^7.12.13", + "@babel/plugin-syntax-class-static-block": "^7.14.5", + "@babel/plugin-syntax-import-attributes": "^7.24.7", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-syntax-json-strings": "^7.8.3", + "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", + "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", + "@babel/plugin-syntax-numeric-separator": "^7.10.4", + "@babel/plugin-syntax-object-rest-spread": "^7.8.3", + "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", + "@babel/plugin-syntax-optional-chaining": "^7.8.3", + "@babel/plugin-syntax-private-property-in-object": "^7.14.5", + "@babel/plugin-syntax-top-level-await": "^7.14.5" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/babel-preset-jest": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz", + "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==", + "dev": true, + "license": "MIT", + "dependencies": { + "babel-plugin-jest-hoist": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/base-64": { + "version": "0.1.0" + }, + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "license": "MIT", + "dependencies": { + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" + } + }, + "node_modules/bl/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "license": "MIT", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/bluebird": { + "version": "3.7.2", + "dev": true, + "license": "MIT" + }, + "node_modules/brace-expansion": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", + "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browser-process-hrtime": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", + "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==", + "dev": true, + "license": "BSD-2-Clause" + }, + "node_modules/browserslist": { + "version": "4.23.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", + "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001646", + "electron-to-chromium": "^1.5.4", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/bser": { + "version": "2.1.1", + "license": "Apache-2.0", + "dependencies": { + "node-int64": "^0.4.0" + } + }, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "license": "MIT" + }, + "node_modules/bunyan": { + "version": "1.8.15", + "resolved": "https://registry.npmjs.org/bunyan/-/bunyan-1.8.15.tgz", + "integrity": "sha512-0tECWShh6wUysgucJcBAoYegf3JJoZWibxdqhTm7OHPeT42qdjkZ29QCMcKwbgU1kiH+auSIasNRXMLWXafXig==", + "dev": true, + "engines": [ + "node >=0.10.0" + ], + "license": "MIT", + "bin": { + "bunyan": "bin/bunyan" + }, + "optionalDependencies": { + "dtrace-provider": "~0.8", + "moment": "^2.19.3", + "mv": "~2", + "safe-json-stringify": "~1" + } + }, + "node_modules/bunyan-debug-stream": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/bunyan-debug-stream/-/bunyan-debug-stream-3.1.1.tgz", + "integrity": "sha512-LfMcz4yKM6s9BP5dfT63Prb5B2hAjReLAfQzLbNQF7qBHtn3P1v+/yn0SZ6UAr4PC3VZRX/QzK7HYkkY0ytokQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2" + }, + "engines": { + "node": ">=0.12.0" + }, + "peerDependencies": { + "bunyan": "*" + }, + "peerDependenciesMeta": { + "bunyan": { + "optional": true + } + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/caf": { + "version": "15.0.1", + "dev": true, + "license": "MIT" + }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caller-callsite": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz", + "integrity": "sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==", + "license": "MIT", + "dependencies": { + "callsites": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-callsite/node_modules/callsites": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz", + "integrity": "sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/caller-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz", + "integrity": "sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==", + "license": "MIT", + "dependencies": { + "caller-callsite": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/camelcase": { + "version": "6.3.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001660", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001660.tgz", + "integrity": "sha512-GacvNTTuATm26qC74pt+ad1fW15mlQ/zuTzzY1ZoIzECTP8HURDfF43kNxPgf7H1jmelCBQTTbBNxdSXOA7Bqg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/char-regex": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz", + "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/child-process-promise": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/child-process-promise/-/child-process-promise-2.2.1.tgz", + "integrity": "sha512-Fi4aNdqBsr0mv+jgWxcZ/7rAIC2mgihrptyVI4foh/rrjY/3BNjfP9+oaiFx/fzim+1ZyCNBae0DlyfQhSugog==", + "dev": true, + "license": "MIT", + "dependencies": { + "cross-spawn": "^4.0.2", + "node-version": "^1.0.0", + "promise-polyfill": "^6.0.1" + } + }, + "node_modules/child-process-promise/node_modules/cross-spawn": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-4.0.2.tgz", + "integrity": "sha512-yAXz/pA1tD8Gtg2S98Ekf/sewp3Lcp3YoFKJ4Hkp5h5yLWnKVTDU0kwjKJ8NDCYcfTLfyGkzTikst+jWypT1iA==", + "dev": true, + "license": "MIT", + "dependencies": { + "lru-cache": "^4.0.1", + "which": "^1.2.9" + } + }, + "node_modules/child-process-promise/node_modules/lru-cache": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz", + "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==", + "dev": true, + "license": "ISC", + "dependencies": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "node_modules/child-process-promise/node_modules/yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==", + "dev": true, + "license": "ISC" + }, + "node_modules/chrome-launcher": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/chrome-launcher/-/chrome-launcher-0.15.2.tgz", + "integrity": "sha512-zdLEwNo3aUVzIhKhTtXfxhdvZhUghrnmkvcAq2NoDd+LeOHKf03H5jwZ8T/STsAlzyALkBVK552iaG1fGf1xVQ==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0" + }, + "bin": { + "print-chrome-path": "bin/print-chrome-path.js" + }, + "engines": { + "node": ">=12.13.0" + } + }, + "node_modules/chrome-launcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chromium-edge-launcher": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/chromium-edge-launcher/-/chromium-edge-launcher-1.0.0.tgz", + "integrity": "sha512-pgtgjNKZ7i5U++1g1PWv75umkHvhVTDOQIZ+sjeUX9483S7Y6MUvO0lrd7ShGlQlFHMN4SwKTCq/X8hWrbv2KA==", + "license": "Apache-2.0", + "dependencies": { + "@types/node": "*", + "escape-string-regexp": "^4.0.0", + "is-wsl": "^2.2.0", + "lighthouse-logger": "^1.0.0", + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" + } + }, + "node_modules/chromium-edge-launcher/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/chromium-edge-launcher/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/ci-info": { + "version": "3.3.2", + "license": "MIT" + }, + "node_modules/cjs-module-lexer": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.3.tgz", + "integrity": "sha512-9z8TZaGM1pfswYeXrUpzPrkx8UnWYdhJclsiYMm6x/w5+nN+8Tf/LnAgfLGQCm59qAOxU8WwHEq2vNwF6i4j+Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "license": "MIT", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/clone-deep": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", + "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", + "license": "MIT", + "dependencies": { + "is-plain-object": "^2.0.4", + "kind-of": "^6.0.2", + "shallow-clone": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">= 1.0.0", + "node": ">= 0.12.0" + } + }, + "node_modules/collect-v8-coverage": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz", + "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/color-convert": { + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "license": "MIT" + }, + "node_modules/colorette": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz", + "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==", + "license": "MIT" + }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "license": "MIT" + }, + "node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", + "license": "MIT" + }, + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "license": "MIT", + "dependencies": { + "mime-db": ">= 1.43.0 < 2" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz", + "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==", + "license": "MIT", + "dependencies": { + "bytes": "3.1.2", + "compressible": "~2.0.18", + "debug": "2.6.9", + "negotiator": "~0.6.4", + "on-headers": "~1.1.0", + "safe-buffer": "5.2.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/compression/node_modules/negotiator": { + "version": "0.6.4", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", + "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/compression/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "license": "MIT" + }, + "node_modules/connect": { + "version": "3.7.0", + "resolved": "https://registry.npmjs.org/connect/-/connect-3.7.0.tgz", + "integrity": "sha512-ZqRXc+tZukToSNmh5C2iWMSoV3X1YUcPbqEM4DkEG5tNQXrQUZCNVGGv3IuicnkMtPfGf3Xtp8WCXs295iQ1pQ==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "finalhandler": "1.1.2", + "parseurl": "~1.3.3", + "utils-merge": "1.0.1" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "license": "MIT" + }, + "node_modules/core-js-compat": { + "version": "3.38.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz", + "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==", + "license": "MIT", + "dependencies": { + "browserslist": "^4.23.3" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" + } + }, + "node_modules/core-util-is": { + "version": "1.0.3", + "license": "MIT" + }, + "node_modules/cosmiconfig": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz", + "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==", + "license": "MIT", + "dependencies": { + "import-fresh": "^2.0.0", + "is-directory": "^0.3.1", + "js-yaml": "^3.13.1", + "parse-json": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/import-fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz", + "integrity": "sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==", + "license": "MIT", + "dependencies": { + "caller-path": "^2.0.0", + "resolve-from": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/parse-json": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz", + "integrity": "sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==", + "license": "MIT", + "dependencies": { + "error-ex": "^1.3.1", + "json-parse-better-errors": "^1.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cosmiconfig/node_modules/resolve-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz", + "integrity": "sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/create-jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz", + "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "exit": "^0.1.2", + "graceful-fs": "^4.2.9", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "prompts": "^2.0.1" + }, + "bin": { + "create-jest": "bin/create-jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/cross-spawn/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, + "license": "MIT" + }, + "node_modules/data-view-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", + "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/data-view-byte-length": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", + "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/inspect-js" + } + }, + "node_modules/data-view-byte-offset": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", + "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/dedent": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", + "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "babel-plugin-macros": "^3.1.0" + }, + "peerDependenciesMeta": { + "babel-plugin-macros": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/denodeify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/denodeify/-/denodeify-1.2.1.tgz", + "integrity": "sha512-KNTihKNmQENUZeKu5fzfpzRqR5S2VMp4gl9RFHiWzj9DfvYQPMJ6XHKNaQxaGCXwPk6y9yme3aUoaiAe+KX+vg==", + "license": "MIT" + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/deprecated-react-native-prop-types": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-5.0.0.tgz", + "integrity": "sha512-cIK8KYiiGVOFsKdPMmm1L3tA/Gl+JopXL6F5+C7x39MyPsQYnP57Im/D6bNUzcborD7fcMwiwZqcBdBXXZucYQ==", + "license": "MIT", + "dependencies": { + "@react-native/normalize-colors": "^0.73.0", + "invariant": "^2.2.4", + "prop-types": "^15.8.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/detect-newline": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz", + "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detox": { + "version": "20.11.4", + "resolved": "https://registry.npmjs.org/detox/-/detox-20.11.4.tgz", + "integrity": "sha512-P48KAtK8qIDOxJKUl4q/syPkuHz67kAeFlNodBZg5aO4hJiH+RsbEkQfJSYkTCeZV800EcmUQwZK2M5amLoYaw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.6.3", + "bunyan": "^1.8.12", + "bunyan-debug-stream": "^3.1.0", + "caf": "^15.0.1", + "chalk": "^4.0.0", + "child-process-promise": "^2.2.0", + "execa": "^5.1.1", + "find-up": "^5.0.0", + "fs-extra": "^11.0.0", + "funpermaproxy": "^1.1.0", + "glob": "^8.0.3", + "ini": "^1.3.4", + "json-cycle": "^1.3.0", + "lodash": "^4.17.11", + "multi-sort-stream": "^1.0.3", + "multipipe": "^4.0.0", + "node-ipc": "9.2.1", + "proper-lockfile": "^3.0.2", + "resolve-from": "^5.0.0", + "sanitize-filename": "^1.6.1", + "semver": "^7.0.0", + "serialize-error": "^8.0.1", + "shell-quote": "^1.7.2", + "signal-exit": "^3.0.3", + "stream-json": "^1.7.4", + "strip-ansi": "^6.0.1", + "telnet-client": "1.2.8", + "tempfile": "^2.0.0", + "trace-event-lib": "^1.3.1", + "which": "^1.3.1", + "ws": "^7.0.0", + "yargs": "^17.0.0", + "yargs-parser": "^21.0.0", + "yargs-unparser": "^2.0.0" + }, + "bin": { + "detox": "local-cli/cli.js" + }, + "engines": { + "node": ">=14.5.0" + }, + "peerDependencies": { + "jest": "29.x.x || 28.x.x || ^27.2.5" + }, + "peerDependenciesMeta": { + "jest": { + "optional": true + } + } + }, + "node_modules/detox/node_modules/brace-expansion": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", + "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/detox/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/detox/node_modules/glob": { + "version": "8.1.0", + "dev": true, + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/detox/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/detox/node_modules/minimatch": { + "version": "5.1.6", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/detox/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/detox/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/detox/node_modules/semver": { + "version": "7.5.4", + "dev": true, + "license": "ISC", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/diff-sequences": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz", + "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/dtrace-provider": { + "version": "0.8.8", + "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", + "integrity": "sha512-b7Z7cNtHPhH9EJhNNbbeqTcXB8LGFFZhq1PGgEvpeHlzd36bhbdTWoE/Ba/YguqpBSlAPKnARWhVlhunCMwfxg==", + "dev": true, + "hasInstallScript": true, + "license": "BSD-2-Clause", + "optional": true, + "dependencies": { + "nan": "^2.14.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/duplexer2": { + "version": "0.1.4", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "readable-stream": "^2.0.2" + } + }, + "node_modules/easy-stack": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz", + "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.24", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.24.tgz", + "integrity": "sha512-0x0wLCmpdKFCi9ulhvYZebgcPmHTkFVUfU2wzDykadkslKwT4oAmDTHEKLnlrDsMGZe4B+ksn8quZfZjYsBetA==", + "license": "ISC" + }, + "node_modules/emittery": { + "version": "0.13.1", + "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz", + "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sindresorhus/emittery?sponsor=1" + } + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/envinfo": { + "version": "7.14.0", + "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz", + "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==", + "license": "MIT", + "bin": { + "envinfo": "dist/cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/error-ex": { + "version": "1.3.2", + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, + "node_modules/error-stack-parser": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz", + "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==", + "license": "MIT", + "dependencies": { + "stackframe": "^1.3.4" + } + }, + "node_modules/errorhandler": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/errorhandler/-/errorhandler-1.5.1.tgz", + "integrity": "sha512-rcOwbfvP1WTViVoUjcfZicVzjhjTuhSMntHh6mW3IrEiyE6mJyXvsToJUJGlGlw/2xU9P5whlWNGlIDVeCiT4A==", + "license": "MIT", + "dependencies": { + "accepts": "~1.3.7", + "escape-html": "~1.0.3" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/es-abstract": { + "version": "1.23.9", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.9.tgz", + "integrity": "sha512-py07lI0wjxAC/DcfK1S6G7iANonniZwTISvdPzk9hzeH0IZIshbuuFxLIU96OyF89Yb9hiqWn8M/bY83KY5vzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.2", + "arraybuffer.prototype.slice": "^1.0.4", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "data-view-buffer": "^1.0.2", + "data-view-byte-length": "^1.0.2", + "data-view-byte-offset": "^1.0.1", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.1.0", + "es-to-primitive": "^1.3.0", + "function.prototype.name": "^1.1.8", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.0", + "get-symbol-description": "^1.1.0", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "internal-slot": "^1.1.0", + "is-array-buffer": "^3.0.5", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.2", + "is-regex": "^1.2.1", + "is-shared-array-buffer": "^1.0.4", + "is-string": "^1.1.1", + "is-typed-array": "^1.1.15", + "is-weakref": "^1.1.0", + "math-intrinsics": "^1.1.0", + "object-inspect": "^1.13.3", + "object-keys": "^1.1.1", + "object.assign": "^4.1.7", + "own-keys": "^1.0.1", + "regexp.prototype.flags": "^1.5.3", + "safe-array-concat": "^1.1.3", + "safe-push-apply": "^1.0.0", + "safe-regex-test": "^1.1.0", + "set-proto": "^1.0.0", + "string.prototype.trim": "^1.2.10", + "string.prototype.trimend": "^1.0.9", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.3", + "typed-array-byte-length": "^1.0.3", + "typed-array-byte-offset": "^1.0.4", + "typed-array-length": "^1.0.7", + "unbox-primitive": "^1.1.0", + "which-typed-array": "^1.1.18" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-iterator-helpers": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.1.tgz", + "integrity": "sha512-uDn+FE1yrDzyC0pCo961B2IHbdM8y/ACZsKD4dG6WqrjV53BADjwa7D+1aom2rsNVfLyDgU/eigvlJGJ08OQ4w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-set-tostringtag": "^2.0.3", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.6", + "globalthis": "^1.0.4", + "gopd": "^1.2.0", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "iterator.prototype": "^1.1.4", + "safe-array-concat": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz", + "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-shim-unscopables": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz", + "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", + "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7", + "is-date-object": "^1.0.5", + "is-symbol": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "license": "MIT" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/eslint": { + "version": "8.57.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.57.1.tgz", + "integrity": "sha512-ypowyDxpVSYpkXr9WPv2PAZCtNip1Mv5KTW0SCurXv/9iOpcrH9PaqUElksqEB6pChqHGDRCFTyrZlGhnLNGiA==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@eslint-community/regexpp": "^4.6.1", + "@eslint/eslintrc": "^2.1.4", + "@eslint/js": "8.57.1", + "@humanwhocodes/config-array": "^0.13.0", + "@humanwhocodes/module-importer": "^1.0.1", + "@nodelib/fs.walk": "^1.2.8", + "@ungap/structured-clone": "^1.2.0", + "ajv": "^6.12.4", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.2.2", + "eslint-visitor-keys": "^3.4.3", + "espree": "^9.6.1", + "esquery": "^1.4.2", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "globals": "^13.19.0", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "is-path-inside": "^3.0.3", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.2", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3", + "strip-ansi": "^6.0.1", + "text-table": "^0.2.0" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-config-prettier": { + "version": "8.10.0", + "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz", + "integrity": "sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==", + "dev": true, + "license": "MIT", + "bin": { + "eslint-config-prettier": "bin/cli.js" + }, + "peerDependencies": { + "eslint": ">=7.0.0" + } + }, + "node_modules/eslint-plugin-eslint-comments": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-eslint-comments/-/eslint-plugin-eslint-comments-3.2.0.tgz", + "integrity": "sha512-0jkOl0hfojIHHmEHgmNdqv4fmh7300NdpA9FFpF7zaoLvB/QeXOGNLIo86oAveJFrfB1p05kC8hpEMHM8DwWVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5", + "ignore": "^5.0.5" + }, + "engines": { + "node": ">=6.5.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=4.19.1" + } + }, + "node_modules/eslint-plugin-ft-flow": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/eslint-plugin-ft-flow/-/eslint-plugin-ft-flow-2.0.3.tgz", + "integrity": "sha512-Vbsd/b+LYA99jUbsL6viEUWShFaYQt2YQs3QN3f+aeszOhh2sgdcU0mjzDyD4yyBvMc8qy2uwvBBWfMzEX06tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21", + "string-natural-compare": "^3.0.1" + }, + "engines": { + "node": ">=12.22.0" + }, + "peerDependencies": { + "@babel/eslint-parser": "^7.12.0", + "eslint": "^8.1.0" + } + }, + "node_modules/eslint-plugin-jest": { + "version": "26.9.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-jest/-/eslint-plugin-jest-26.9.0.tgz", + "integrity": "sha512-TWJxWGp1J628gxh2KhaH1H1paEdgE2J61BBF1I59c6xWeL5+D1BzMxGDN/nXAfX+aSkR5u80K+XhskK6Gwq9ng==", + "dev": true, + "license": "MIT", + "dependencies": { + "@typescript-eslint/utils": "^5.10.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "peerDependencies": { + "@typescript-eslint/eslint-plugin": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "@typescript-eslint/eslint-plugin": { + "optional": true + }, + "jest": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-prettier": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-4.2.1.tgz", + "integrity": "sha512-f/0rXLXUt0oFYs8ra4w49wYZBG5GKZpAYsJSm6rnYL5uVDjd+zowwMwVZHnAjf4edNrKpCDYfXDgmRE/Ak7QyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prettier-linter-helpers": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "eslint": ">=7.28.0", + "prettier": ">=2.0.0" + }, + "peerDependenciesMeta": { + "eslint-config-prettier": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react": { + "version": "7.37.4", + "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.4.tgz", + "integrity": "sha512-BGP0jRmfYyvOyvMoRX/uoUeW+GqNj9y16bPQzqAHf3AYII/tDs+jMN0dBVkl88/OZwNGwrVFxE7riHsXVfy/LQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.8", + "array.prototype.findlast": "^1.2.5", + "array.prototype.flatmap": "^1.3.3", + "array.prototype.tosorted": "^1.1.4", + "doctrine": "^2.1.0", + "es-iterator-helpers": "^1.2.1", + "estraverse": "^5.3.0", + "hasown": "^2.0.2", + "jsx-ast-utils": "^2.4.1 || ^3.0.0", + "minimatch": "^3.1.2", + "object.entries": "^1.1.8", + "object.fromentries": "^2.0.8", + "object.values": "^1.2.1", + "prop-types": "^15.8.1", + "resolve": "^2.0.0-next.5", + "semver": "^6.3.1", + "string.prototype.matchall": "^4.0.12", + "string.prototype.repeat": "^1.0.0" + }, + "engines": { + "node": ">=4" + }, + "peerDependencies": { + "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7" + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.2.tgz", + "integrity": "sha512-QzliNJq4GinDBcD8gPB5v0wh6g8q3SUi6EFF0x8N/BL9PoVs0atuGc47ozMRyOWAKdwaZ5OnbOEa3WR+dSGKuQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0" + } + }, + "node_modules/eslint-plugin-react-native": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-native/-/eslint-plugin-react-native-4.1.0.tgz", + "integrity": "sha512-QLo7rzTBOl43FvVqDdq5Ql9IoElIuTdjrz9SKAXCvULvBoRZ44JGSkx9z4999ZusCsb4rK3gjS8gOGyeYqZv2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-plugin-react-native-globals": "^0.1.1" + }, + "peerDependencies": { + "eslint": "^3.17.0 || ^4 || ^5 || ^6 || ^7 || ^8" + } + }, + "node_modules/eslint-plugin-react-native-globals": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-native-globals/-/eslint-plugin-react-native-globals-0.1.2.tgz", + "integrity": "sha512-9aEPf1JEpiTjcFAmmyw8eiIXmcNZOqaZyHO77wgm0/dWfT/oxC1SrIq8ET38pMxHYrcB6Uew+TzUVsBeczF88g==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint-plugin-react/node_modules/doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/eslint-plugin-react/node_modules/resolve": { + "version": "2.0.0-next.5", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz", + "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-core-module": "^2.13.0", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-scope/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=10" + } + }, + "node_modules/eslint/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/eslint/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/eslint/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/eslint/node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint/node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/eslint/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/eslint/node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint/node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esprima": { + "version": "4.0.1", + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/event-pubsub": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz", + "integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==", + "dev": true, + "license": "Unlicense", + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/event-target-shim": { + "version": "5.0.1", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/execa": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", + "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "license": "MIT", + "dependencies": { + "cross-spawn": "^7.0.3", + "get-stream": "^6.0.0", + "human-signals": "^2.1.0", + "is-stream": "^2.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^4.0.1", + "onetime": "^5.1.2", + "signal-exit": "^3.0.3", + "strip-final-newline": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/execa?sponsor=1" + } + }, + "node_modules/exit": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", + "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "dev": true, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/expect": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz", + "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/expect-utils": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/exponential-backoff": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/exponential-backoff/-/exponential-backoff-3.1.1.tgz", + "integrity": "sha512-dX7e/LHVJ6W3DE1MHWi9S1EYzDESENfLrYohG2G++ovZrYOkm4Knwa0mc1cn84xJOR4KEU0WSchhLbd0UklbHw==", + "license": "Apache-2.0" + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-diff": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz", + "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/fast-glob": { + "version": "3.3.3", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", + "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.8" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-xml-parser": { + "version": "4.5.6", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.5.6.tgz", + "integrity": "sha512-Yd4vkROfJf8AuJrDIVMVmYfULKmIJszVsMv7Vo71aocsKgFxpdlpSHXSaInvyYfgw2PRuObQSW2GFpVMUjxu9A==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT", + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fb-watchman": { + "version": "2.0.1", + "license": "Apache-2.0", + "dependencies": { + "bser": "2.1.1" + } + }, + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/fill-range": { + "version": "7.1.1", + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/find-cache-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz", + "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==", + "license": "MIT", + "dependencies": { + "commondir": "^1.0.1", + "make-dir": "^2.0.0", + "pkg-dir": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/find-up": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz", + "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==", + "license": "MIT", + "dependencies": { + "locate-path": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/locate-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz", + "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==", + "license": "MIT", + "dependencies": { + "p-locate": "^3.0.0", + "path-exists": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/make-dir": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz", + "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==", + "license": "MIT", + "dependencies": { + "pify": "^4.0.1", + "semver": "^5.6.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/find-cache-dir/node_modules/p-locate": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz", + "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==", + "license": "MIT", + "dependencies": { + "p-limit": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/pkg-dir": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz", + "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==", + "license": "MIT", + "dependencies": { + "find-up": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/find-cache-dir/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "license": "ISC", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/find-up": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/find-up/node_modules/path-exists": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/flat": { + "version": "5.0.2", + "dev": true, + "license": "BSD-3-Clause", + "bin": { + "flat": "cli.js" + } + }, + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" + }, + "engines": { + "node": "^10.12.0 || >=12.0.0" + } + }, + "node_modules/flatted": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz", + "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==", + "dev": true, + "license": "ISC" + }, + "node_modules/flow-enums-runtime": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/flow-enums-runtime/-/flow-enums-runtime-0.0.6.tgz", + "integrity": "sha512-3PYnM29RFXwvAN6Pc/scUfkI7RwhQ/xqyLUyPNlXUp9S40zI8nup9tUSrTLSVnWGBN38FNiGWbwZOB6uR4OGdw==", + "license": "MIT" + }, + "node_modules/flow-parser": { + "version": "0.206.0", + "resolved": "https://registry.npmjs.org/flow-parser/-/flow-parser-0.206.0.tgz", + "integrity": "sha512-HVzoK3r6Vsg+lKvlIZzaWNBVai+FXTX1wdYhz/wVlH13tb/gOdLXmlTqy6odmTBhT5UoWUbq0k8263Qhr9d88w==", + "license": "MIT", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/for-each": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz", + "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "11.3.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.3.0.tgz", + "integrity": "sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.2", + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", + "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "functions-have-names": "^1.2.3", + "hasown": "^2.0.2", + "is-callable": "^1.2.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/funpermaproxy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/funpermaproxy/-/funpermaproxy-1.1.0.tgz", + "integrity": "sha512-2Sp1hWuO8m5fqeFDusyhKqYPT+7rGLw34N3qonDcdRP8+n7M7Gl/yKp/q7oCxnnJ6pWCectOmLFJpsMU/++KrQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=8.3.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/get-caller-file": { + "version": "2.0.5", + "license": "ISC", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-package-type": { + "version": "0.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-symbol-description": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", + "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "7.2.3", + "license": "ISC", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.2.1", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.10", + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/has-bigints": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", + "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-proto": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", + "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-symbols": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "license": "MIT", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/hermes-estree": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.15.0.tgz", + "integrity": "sha512-lLYvAd+6BnOqWdnNbP/Q8xfl8LOGw4wVjfrNd9Gt8eoFzhNBRVD95n4l2ksfMVOoxuVyegs85g83KS9QOsxbVQ==", + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.15.0.tgz", + "integrity": "sha512-Q1uks5rjZlE9RjMMjSUCkGrEIPI5pKJILeCtK1VmTj7U4pf3wVPoo+cxfu+s4cBAPy2JzikIIdCZgBoR6x7U1Q==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.15.0" + } + }, + "node_modules/hermes-profile-transformer": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/hermes-profile-transformer/-/hermes-profile-transformer-0.0.6.tgz", + "integrity": "sha512-cnN7bQUm65UWOy6cbGcCcZ3rpwW8Q/j4OP5aWRhEry4Z2t2aR1cjrbp0BS+KiBN0smvP1caBgAuxutvyvJILzQ==", + "license": "MIT", + "dependencies": { + "source-map": "^0.7.3" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/hermes-profile-transformer/node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "node_modules/html-escaper": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz", + "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==", + "dev": true, + "license": "MIT" + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/http-errors/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/human-signals": { + "version": "2.1.0", + "license": "Apache-2.0", + "engines": { + "node": ">=10.17.0" + } + }, + "node_modules/ieee754": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", + "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "BSD-3-Clause" + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/image-size": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/image-size/-/image-size-1.2.1.tgz", + "integrity": "sha512-rH+46sQJ2dlwfjfhCyNx5thzrv+dtmBIhPHk0zgRUukHzZ/kRueTJXoYYsclBaKcSMBWuGbOFXtioLpzTb5euw==", + "license": "MIT", + "dependencies": { + "queue": "6.0.2" + }, + "bin": { + "image-size": "bin/image-size.js" + }, + "engines": { + "node": ">=16.x" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/import-fresh/node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/import-local": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", + "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "pkg-dir": "^4.2.0", + "resolve-cwd": "^3.0.0" + }, + "bin": { + "import-local-fixture": "fixtures/cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "license": "ISC", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "license": "ISC" + }, + "node_modules/ini": { + "version": "1.3.8", + "dev": true, + "license": "ISC" + }, + "node_modules/internal-slot": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", + "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "hasown": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/invariant": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz", + "integrity": "sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", + "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "license": "MIT" + }, + "node_modules/is-async-function": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz", + "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "async-function": "^1.0.0", + "call-bound": "^1.0.3", + "get-proto": "^1.0.1", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", + "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-bigints": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-boolean-object": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz", + "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-data-view": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", + "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "is-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", + "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-directory": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz", + "integrity": "sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "license": "MIT", + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-finalizationregistry": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", + "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-generator-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", + "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/is-generator-function": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz", + "integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-proto": "^1.0.0", + "has-tostringtag": "^1.0.2", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", + "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number-object": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", + "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-path-inside": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", + "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-obj": { + "version": "2.1.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-plain-object": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", + "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", + "license": "MIT", + "dependencies": { + "isobject": "^3.0.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-regex": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", + "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", + "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", + "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-string": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", + "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", + "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "has-symbols": "^1.1.0", + "safe-regex-test": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", + "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-weakmap": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", + "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz", + "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakset": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", + "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "get-intrinsic": "^1.2.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "license": "MIT", + "dependencies": { + "is-docker": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/isarray": { + "version": "1.0.0", + "license": "MIT" + }, + "node_modules/isexe": { + "version": "2.0.0", + "license": "ISC" + }, + "node_modules/isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/istanbul-lib-coverage": { + "version": "3.2.0", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-instrument": { + "version": "5.2.1", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "@babel/core": "^7.12.3", + "@babel/parser": "^7.14.7", + "@istanbuljs/schema": "^0.1.2", + "istanbul-lib-coverage": "^3.2.0", + "semver": "^6.3.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/istanbul-lib-report": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", + "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "istanbul-lib-coverage": "^3.0.0", + "make-dir": "^4.0.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz", + "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "debug": "^4.1.1", + "istanbul-lib-coverage": "^3.0.0", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/debug": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", + "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/istanbul-lib-source-maps/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/istanbul-reports": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", + "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "html-escaper": "^2.0.0", + "istanbul-lib-report": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/iterator.prototype": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz", + "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "get-proto": "^1.0.0", + "has-symbols": "^1.1.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/jest": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz", + "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/types": "^29.6.3", + "import-local": "^3.0.2", + "jest-cli": "^29.7.0" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-changed-files": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz", + "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "execa": "^5.0.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-circus": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz", + "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/expect": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "co": "^4.6.0", + "dedent": "^1.0.0", + "is-generator-fn": "^2.0.0", + "jest-each": "^29.7.0", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "p-limit": "^3.1.0", + "pretty-format": "^29.7.0", + "pure-rand": "^6.0.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-cli": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz", + "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/core": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "create-jest": "^29.7.0", + "exit": "^0.1.2", + "import-local": "^3.0.2", + "jest-config": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "yargs": "^17.3.1" + }, + "bin": { + "jest": "bin/jest.js" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" + }, + "peerDependenciesMeta": { + "node-notifier": { + "optional": true + } + } + }, + "node_modules/jest-config": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz", + "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@jest/test-sequencer": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-jest": "^29.7.0", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "deepmerge": "^4.2.2", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-circus": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-runner": "^29.7.0", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "micromatch": "^4.0.4", + "parse-json": "^5.2.0", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "peerDependencies": { + "@types/node": "*", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/jest-diff": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz", + "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "diff-sequences": "^29.6.3", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-docblock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz", + "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "detect-newline": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-each": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz", + "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "jest-util": "^29.7.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-environment-node": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz", + "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==", + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-mock": "^29.7.0", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-get-type": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz", + "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==", + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-haste-map": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz", + "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/graceful-fs": "^4.1.3", + "@types/node": "*", + "anymatch": "^3.0.3", + "fb-watchman": "^2.0.0", + "graceful-fs": "^4.2.9", + "jest-regex-util": "^29.6.3", + "jest-util": "^29.7.0", + "jest-worker": "^29.7.0", + "micromatch": "^4.0.4", + "walker": "^1.0.8" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/jest-junit": { + "version": "16.0.0", + "resolved": "https://registry.npmjs.org/jest-junit/-/jest-junit-16.0.0.tgz", + "integrity": "sha512-A94mmw6NfJab4Fg/BlvVOUXzXgF0XIH6EmTgJ5NDPp4xoKq0Kr7sErb+4Xs9nZvu58pJojz5RFGpqnZYJTrRfQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "mkdirp": "^1.0.4", + "strip-ansi": "^6.0.1", + "uuid": "^8.3.2", + "xml": "^1.0.1" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/jest-junit/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "dev": true, + "license": "MIT", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-leak-detector": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz", + "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-matcher-utils": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz", + "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-message-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", + "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.12.13", + "@jest/types": "^29.6.3", + "@types/stack-utils": "^2.0.0", + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "micromatch": "^4.0.4", + "pretty-format": "^29.7.0", + "slash": "^3.0.0", + "stack-utils": "^2.0.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-mock": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz", + "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "jest-util": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-pnp-resolver": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz", + "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "peerDependencies": { + "jest-resolve": "*" + }, + "peerDependenciesMeta": { + "jest-resolve": { + "optional": true + } + } + }, + "node_modules/jest-regex-util": { + "version": "29.6.3", + "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz", + "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz", + "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.0.0", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-pnp-resolver": "^1.2.2", + "jest-util": "^29.7.0", + "jest-validate": "^29.7.0", + "resolve": "^1.20.0", + "resolve.exports": "^2.0.0", + "slash": "^3.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-resolve-dependencies": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz", + "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==", + "dev": true, + "license": "MIT", + "dependencies": { + "jest-regex-util": "^29.6.3", + "jest-snapshot": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runner": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", + "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/console": "^29.7.0", + "@jest/environment": "^29.7.0", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "graceful-fs": "^4.2.9", + "jest-docblock": "^29.7.0", + "jest-environment-node": "^29.7.0", + "jest-haste-map": "^29.7.0", + "jest-leak-detector": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-resolve": "^29.7.0", + "jest-runtime": "^29.7.0", + "jest-util": "^29.7.0", + "jest-watcher": "^29.7.0", + "jest-worker": "^29.7.0", + "p-limit": "^3.1.0", + "source-map-support": "0.5.13" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-runtime": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", + "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/environment": "^29.7.0", + "@jest/fake-timers": "^29.7.0", + "@jest/globals": "^29.7.0", + "@jest/source-map": "^29.6.3", + "@jest/test-result": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "cjs-module-lexer": "^1.0.0", + "collect-v8-coverage": "^1.0.0", + "glob": "^7.1.3", + "graceful-fs": "^4.2.9", + "jest-haste-map": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-mock": "^29.7.0", + "jest-regex-util": "^29.6.3", + "jest-resolve": "^29.7.0", + "jest-snapshot": "^29.7.0", + "jest-util": "^29.7.0", + "slash": "^3.0.0", + "strip-bom": "^4.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", + "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.11.6", + "@babel/generator": "^7.7.2", + "@babel/plugin-syntax-jsx": "^7.7.2", + "@babel/plugin-syntax-typescript": "^7.7.2", + "@babel/types": "^7.3.3", + "@jest/expect-utils": "^29.7.0", + "@jest/transform": "^29.7.0", + "@jest/types": "^29.6.3", + "babel-preset-current-node-syntax": "^1.0.0", + "chalk": "^4.0.0", + "expect": "^29.7.0", + "graceful-fs": "^4.2.9", + "jest-diff": "^29.7.0", + "jest-get-type": "^29.6.3", + "jest-matcher-utils": "^29.7.0", + "jest-message-util": "^29.7.0", + "jest-util": "^29.7.0", + "natural-compare": "^1.4.0", + "pretty-format": "^29.7.0", + "semver": "^7.5.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-snapshot/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/jest-util": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz", + "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "@types/node": "*", + "chalk": "^4.0.0", + "ci-info": "^3.2.0", + "graceful-fs": "^4.2.9", + "picomatch": "^2.2.3" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-validate": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz", + "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==", + "license": "MIT", + "dependencies": { + "@jest/types": "^29.6.3", + "camelcase": "^6.2.0", + "chalk": "^4.0.0", + "jest-get-type": "^29.6.3", + "leven": "^3.1.0", + "pretty-format": "^29.7.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-watcher": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz", + "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jest/test-result": "^29.7.0", + "@jest/types": "^29.6.3", + "@types/node": "*", + "ansi-escapes": "^4.2.1", + "chalk": "^4.0.0", + "emittery": "^0.13.1", + "jest-util": "^29.7.0", + "string-length": "^4.0.1" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", + "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "jest-util": "^29.7.0", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, + "node_modules/joi": { + "version": "17.13.3", + "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", + "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==", + "license": "BSD-3-Clause", + "dependencies": { + "@hapi/hoek": "^9.3.0", + "@hapi/topo": "^5.1.0", + "@sideway/address": "^4.1.5", + "@sideway/formula": "^3.0.1", + "@sideway/pinpoint": "^2.0.0" + } + }, + "node_modules/js-message": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz", + "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/js-queue": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.2.tgz", + "integrity": "sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA==", + "dev": true, + "license": "MIT", + "dependencies": { + "easy-stack": "^1.0.1" + }, + "engines": { + "node": ">=1.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "3.14.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", + "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "license": "MIT", + "dependencies": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsc-android": { + "version": "250231.0.0", + "resolved": "https://registry.npmjs.org/jsc-android/-/jsc-android-250231.0.0.tgz", + "integrity": "sha512-rS46PvsjYmdmuz1OAWXY/1kCYG7pnf1TBqeTiOJr1iDz7s5DLxxC9n/ZMknLDxzYzNVfI7R95MH10emSSG1Wuw==", + "license": "BSD-2-Clause" + }, + "node_modules/jsc-safe-url": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/jsc-safe-url/-/jsc-safe-url-0.2.4.tgz", + "integrity": "sha512-0wM3YBWtYePOjfyXQH5MWQ8H7sdk5EXSwZvmSLKk2RboVQ2Bu239jycHDz5J/8Blf3K0Qnoy2b6xD+z10MFB+Q==", + "license": "0BSD" + }, + "node_modules/jscodeshift": { + "version": "0.14.0", + "resolved": "https://registry.npmjs.org/jscodeshift/-/jscodeshift-0.14.0.tgz", + "integrity": "sha512-7eCC1knD7bLUPuSCwXsMZUH51O8jIcoVyKtI6P0XM0IVzlGjckPy3FIwQlorzbN0Sg79oK+RlohN32Mqf/lrYA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.13.16", + "@babel/parser": "^7.13.16", + "@babel/plugin-proposal-class-properties": "^7.13.0", + "@babel/plugin-proposal-nullish-coalescing-operator": "^7.13.8", + "@babel/plugin-proposal-optional-chaining": "^7.13.12", + "@babel/plugin-transform-modules-commonjs": "^7.13.8", + "@babel/preset-flow": "^7.13.13", + "@babel/preset-typescript": "^7.13.0", + "@babel/register": "^7.13.16", + "babel-core": "^7.0.0-bridge.0", + "chalk": "^4.1.2", + "flow-parser": "0.*", + "graceful-fs": "^4.2.4", + "micromatch": "^4.0.4", + "neo-async": "^2.5.0", + "node-dir": "^0.1.17", + "recast": "^0.21.0", + "temp": "^0.8.4", + "write-file-atomic": "^2.3.0" + }, + "bin": { + "jscodeshift": "bin/jscodeshift.js" + }, + "peerDependencies": { + "@babel/preset-env": "^7.1.6" + } + }, + "node_modules/jscodeshift/node_modules/write-file-atomic": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", + "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", + "license": "ISC", + "dependencies": { + "graceful-fs": "^4.1.11", + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.2" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-cycle": { + "version": "1.4.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/json-parse-better-errors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", + "integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==", + "license": "MIT" + }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/jsx-ast-utils": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz", + "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-includes": "^3.1.6", + "array.prototype.flat": "^1.3.1", + "object.assign": "^4.1.4", + "object.values": "^1.1.6" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/kind-of": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", + "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/kleur": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", + "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/leven": { + "version": "3.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/lighthouse-logger": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/lighthouse-logger/-/lighthouse-logger-1.4.2.tgz", + "integrity": "sha512-gPWxznF6TKmUHrOQjlVo2UbaL2EJ71mb2CCeRs/2qBpi4L/g4LUVc9+3lKQ6DTUZwJswfM7ainGrLO1+fOqa2g==", + "license": "Apache-2.0", + "dependencies": { + "debug": "^2.6.9", + "marky": "^1.2.2" + } + }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/locate-path": { + "version": "5.0.0", + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/lodash": { + "version": "4.18.1", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", + "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.debounce": { + "version": "4.0.8", + "license": "MIT" + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lodash.throttle": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/lodash.throttle/-/lodash.throttle-4.1.1.tgz", + "integrity": "sha512-wIkUCfVKpVsWo3JSZlc+8MB5it+2AN5W8J7YVMST30UrvcQNZ1Okbj+rbVniijTWE6FGYy4XJq/rHkas8qJMLQ==", + "license": "MIT" + }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/logkitty": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/logkitty/-/logkitty-0.7.1.tgz", + "integrity": "sha512-/3ER20CTTbahrCrpYfPn7Xavv9diBROZpoXGVZDWMw4b/X4uuUwAC0ki85tgsdMRONURyIJbcOvS94QsUBYPbQ==", + "license": "MIT", + "dependencies": { + "ansi-fragments": "^0.2.1", + "dayjs": "^1.8.15", + "yargs": "^15.1.0" + }, + "bin": { + "logkitty": "bin/logkitty.js" + } + }, + "node_modules/logkitty/node_modules/camelcase": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", + "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/logkitty/node_modules/cliui": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", + "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==", + "license": "ISC", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^6.2.0" + } + }, + "node_modules/logkitty/node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/y18n": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz", + "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==", + "license": "ISC" + }, + "node_modules/logkitty/node_modules/yargs": { + "version": "15.4.1", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz", + "integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==", + "license": "MIT", + "dependencies": { + "cliui": "^6.0.0", + "decamelize": "^1.2.0", + "find-up": "^4.1.0", + "get-caller-file": "^2.0.1", + "require-directory": "^2.1.1", + "require-main-filename": "^2.0.0", + "set-blocking": "^2.0.0", + "string-width": "^4.2.0", + "which-module": "^2.0.0", + "y18n": "^4.0.0", + "yargs-parser": "^18.1.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/logkitty/node_modules/yargs-parser": { + "version": "18.1.3", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz", + "integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==", + "license": "ISC", + "dependencies": { + "camelcase": "^5.0.0", + "decamelize": "^1.2.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/make-dir": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz", + "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==", + "dev": true, + "license": "MIT", + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/make-dir/node_modules/semver": { + "version": "7.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.1.tgz", + "integrity": "sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/makeerror": { + "version": "1.0.12", + "license": "BSD-3-Clause", + "dependencies": { + "tmpl": "1.0.5" + } + }, + "node_modules/marky": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/marky/-/marky-1.2.5.tgz", + "integrity": "sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==", + "license": "Apache-2.0" + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/memoize-one": { + "version": "5.2.1", + "license": "MIT" + }, + "node_modules/merge-stream": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 8" + } + }, + "node_modules/metro": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro/-/metro-0.80.12.tgz", + "integrity": "sha512-1UsH5FzJd9quUsD1qY+zUG4JY3jo3YEMxbMYH9jT6NK3j4iORhlwTK8fYTfAUBhDKjgLfKjAh7aoazNE23oIRA==", + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "accepts": "^1.3.7", + "chalk": "^4.0.0", + "ci-info": "^2.0.0", + "connect": "^3.6.5", + "debug": "^2.2.0", + "denodeify": "^1.2.1", + "error-stack-parser": "^2.0.6", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "hermes-parser": "0.23.1", + "image-size": "^1.0.2", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "jsc-safe-url": "^0.2.2", + "lodash.throttle": "^4.1.1", + "metro-babel-transformer": "0.80.12", + "metro-cache": "0.80.12", + "metro-cache-key": "0.80.12", + "metro-config": "0.80.12", + "metro-core": "0.80.12", + "metro-file-map": "0.80.12", + "metro-resolver": "0.80.12", + "metro-runtime": "0.80.12", + "metro-source-map": "0.80.12", + "metro-symbolicate": "0.80.12", + "metro-transform-plugins": "0.80.12", + "metro-transform-worker": "0.80.12", + "mime-types": "^2.1.27", + "nullthrows": "^1.1.1", + "serialize-error": "^2.1.0", + "source-map": "^0.5.6", + "strip-ansi": "^6.0.0", + "throat": "^5.0.0", + "ws": "^7.5.10", + "yargs": "^17.6.2" + }, + "bin": { + "metro": "src/cli.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-babel-transformer": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-babel-transformer/-/metro-babel-transformer-0.80.12.tgz", + "integrity": "sha512-YZziRs0MgA3pzCkkvOoQRXjIoVjvrpi/yRlJnObyIvMP6lFdtyG4nUGIwGY9VXnBvxmXD6mPY2e+NSw6JAyiRg==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "hermes-parser": "0.23.1", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-babel-transformer/node_modules/hermes-estree": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", + "integrity": "sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==", + "license": "MIT" + }, + "node_modules/metro-babel-transformer/node_modules/hermes-parser": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.23.1.tgz", + "integrity": "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.23.1" + } + }, + "node_modules/metro-cache": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-cache/-/metro-cache-0.80.12.tgz", + "integrity": "sha512-p5kNHh2KJ0pbQI/H7ZBPCEwkyNcSz7OUkslzsiIWBMPQGFJ/xArMwkV7I+GJcWh+b4m6zbLxE5fk6fqbVK1xGA==", + "license": "MIT", + "dependencies": { + "exponential-backoff": "^3.1.1", + "flow-enums-runtime": "^0.0.6", + "metro-core": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-cache-key": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-cache-key/-/metro-cache-key-0.80.12.tgz", + "integrity": "sha512-o4BspKnugg/pE45ei0LGHVuBJXwRgruW7oSFAeSZvBKA/sGr0UhOGY3uycOgWInnS3v5yTTfiBA9lHlNRhsvGA==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-config": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-config/-/metro-config-0.80.12.tgz", + "integrity": "sha512-4rwOWwrhm62LjB12ytiuR5NgK1ZBNr24/He8mqCsC+HXZ+ATbrewLNztzbAZHtFsrxP4D4GLTGgh96pCpYLSAQ==", + "license": "MIT", + "dependencies": { + "connect": "^3.6.5", + "cosmiconfig": "^5.0.5", + "flow-enums-runtime": "^0.0.6", + "jest-validate": "^29.6.3", + "metro": "0.80.12", + "metro-cache": "0.80.12", + "metro-core": "0.80.12", + "metro-runtime": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-core": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-core/-/metro-core-0.80.12.tgz", + "integrity": "sha512-QqdJ/yAK+IpPs2HU/h5v2pKEdANBagSsc6DRSjnwSyJsCoHlmyJKCaCJ7KhWGx+N4OHxh37hoA8fc2CuZbx0Fw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "lodash.throttle": "^4.1.1", + "metro-resolver": "0.80.12" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-file-map": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-file-map/-/metro-file-map-0.80.12.tgz", + "integrity": "sha512-sYdemWSlk66bWzW2wp79kcPMzwuG32x1ZF3otI0QZTmrnTaaTiGyhE66P1z6KR4n2Eu5QXiABa6EWbAQv0r8bw==", + "license": "MIT", + "dependencies": { + "anymatch": "^3.0.3", + "debug": "^2.2.0", + "fb-watchman": "^2.0.0", + "flow-enums-runtime": "^0.0.6", + "graceful-fs": "^4.2.4", + "invariant": "^2.2.4", + "jest-worker": "^29.6.3", + "micromatch": "^4.0.4", + "node-abort-controller": "^3.1.1", + "nullthrows": "^1.1.1", + "walker": "^1.0.7" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "fsevents": "^2.3.2" + } + }, + "node_modules/metro-minify-terser": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-minify-terser/-/metro-minify-terser-0.80.12.tgz", + "integrity": "sha512-muWzUw3y5k+9083ZoX9VaJLWEV2Jcgi+Oan0Mmb/fBNMPqP9xVDuy4pOMn/HOiGndgfh/MK7s4bsjkyLJKMnXQ==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "terser": "^5.15.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-resolver": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-resolver/-/metro-resolver-0.80.12.tgz", + "integrity": "sha512-PR24gYRZnYHM3xT9pg6BdbrGbM/Cu1TcyIFBVlAk7qDAuHkUNQ1nMzWumWs+kwSvtd9eZGzHoucGJpTUEeLZAw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-runtime": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-runtime/-/metro-runtime-0.80.12.tgz", + "integrity": "sha512-LIx7+92p5rpI0i6iB4S4GBvvLxStNt6fF0oPMaUd1Weku7jZdfkCZzmrtDD9CSQ6EPb0T9NUZoyXIxlBa3wOCw==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.25.0", + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-source-map": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-source-map/-/metro-source-map-0.80.12.tgz", + "integrity": "sha512-o+AXmE7hpvM8r8MKsx7TI21/eerYYy2DCDkWfoBkv+jNkl61khvDHlQn0cXZa6lrcNZiZkl9oHSMcwLLIrFmpw==", + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.20.0", + "@babel/types": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-symbolicate": "0.80.12", + "nullthrows": "^1.1.1", + "ob1": "0.80.12", + "source-map": "^0.5.6", + "vlq": "^1.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-source-map/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-symbolicate": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-symbolicate/-/metro-symbolicate-0.80.12.tgz", + "integrity": "sha512-/dIpNdHksXkGHZXARZpL7doUzHqSNxgQ8+kQGxwpJuHnDhGkENxB5PS2QBaTDdEcmyTMjS53CN1rl9n1gR6fmw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "metro-source-map": "0.80.12", + "nullthrows": "^1.1.1", + "source-map": "^0.5.6", + "through2": "^2.0.1", + "vlq": "^1.0.0" + }, + "bin": { + "metro-symbolicate": "src/index.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-symbolicate/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro-transform-plugins": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-transform-plugins/-/metro-transform-plugins-0.80.12.tgz", + "integrity": "sha512-WQWp00AcZvXuQdbjQbx1LzFR31IInlkCDYJNRs6gtEtAyhwpMMlL2KcHmdY+wjDO9RPcliZ+Xl1riOuBecVlPA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/template": "^7.0.0", + "@babel/traverse": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro-transform-worker": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/metro-transform-worker/-/metro-transform-worker-0.80.12.tgz", + "integrity": "sha512-KAPFN1y3eVqEbKLx1I8WOarHPqDMUa8WelWxaJCNKO/yHCP26zELeqTJvhsQup+8uwB6EYi/sp0b6TGoh6lOEA==", + "license": "MIT", + "dependencies": { + "@babel/core": "^7.20.0", + "@babel/generator": "^7.20.0", + "@babel/parser": "^7.20.0", + "@babel/types": "^7.20.0", + "flow-enums-runtime": "^0.0.6", + "metro": "0.80.12", + "metro-babel-transformer": "0.80.12", + "metro-cache": "0.80.12", + "metro-cache-key": "0.80.12", + "metro-minify-terser": "0.80.12", + "metro-source-map": "0.80.12", + "metro-transform-plugins": "0.80.12", + "nullthrows": "^1.1.1" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/metro/node_modules/ci-info": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-2.0.0.tgz", + "integrity": "sha512-5tK7EtrZ0N+OLFMthtqOj4fI2Jeb88C4CAZPu25LDVUgXJ0A3Js4PMGqrn0JU1W0Mh1/Z8wZzYPxqUrXeBboCQ==", + "license": "MIT" + }, + "node_modules/metro/node_modules/hermes-estree": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.23.1.tgz", + "integrity": "sha512-eT5MU3f5aVhTqsfIReZ6n41X5sYn4IdQL0nvz6yO+MMlPxw49aSARHLg/MSehQftyjnrE8X6bYregzSumqc6cg==", + "license": "MIT" + }, + "node_modules/metro/node_modules/hermes-parser": { + "version": "0.23.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.23.1.tgz", + "integrity": "sha512-oxl5h2DkFW83hT4DAUJorpah8ou4yvmweUzLJmmr6YV2cezduCdlil1AvU/a/xSsAFo4WUcNA4GoV5Bvq6JffA==", + "license": "MIT", + "dependencies": { + "hermes-estree": "0.23.1" + } + }, + "node_modules/metro/node_modules/serialize-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/serialize-error/-/serialize-error-2.1.0.tgz", + "integrity": "sha512-ghgmKt5o4Tly5yEG/UJp8qTd0AN7Xalw4XBtDEKP655B699qMEtra1WlXeE6WIvdEG481JvRxULKsInq/iNysw==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/metro/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "license": "MIT", + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/mime-db": { + "version": "1.53.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.53.0.tgz", + "integrity": "sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/minimatch": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.4.tgz", + "integrity": "sha512-twmL+S8+7yIsE9wsqgzU3E8/LumN3M3QELrBZ20OdmQ9jB2JvW5oZtBEmft84k/Gs5CG9mqtWc6Y9vW+JEzGxw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.6", + "license": "MIT" + }, + "node_modules/mkdirp": { + "version": "0.5.6", + "license": "MIT", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/moment": { + "version": "2.30.1", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz", + "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/multi-sort-stream": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/multi-sort-stream/-/multi-sort-stream-1.0.4.tgz", + "integrity": "sha512-hAZ8JOEQFbgdLe8HWZbb7gdZg0/yAIHF00Qfo3kd0rXFv96nXe+/bPTrKHZ2QMHugGX4FiAyET1Lt+jiB+7Qlg==", + "dev": true, + "license": "bsd" + }, + "node_modules/multipipe": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "duplexer2": "^0.1.2", + "object-assign": "^4.1.0" + } + }, + "node_modules/mv": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/mv/-/mv-2.1.1.tgz", + "integrity": "sha512-at/ZndSy3xEGJ8i0ygALh8ru9qy7gWW1cmkaqBN29JmMlIvM//MEO9y1sk/avxuwnPcfhkejkLsuPxH81BrkSg==", + "dev": true, + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "~0.5.1", + "ncp": "~2.0.0", + "rimraf": "~2.4.0" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/mv/node_modules/glob": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/glob/-/glob-6.0.4.tgz", + "integrity": "sha512-MKZeRNyYZAVVVG1oZeLaWie1uweH40m9AZwIwxyPbTSX4hHrVYSzLg0Ro5Z5R7XKkIX+Cc6oD1rqeDJnwsB8/A==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + } + }, + "node_modules/mv/node_modules/rimraf": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.4.5.tgz", + "integrity": "sha512-J5xnxTyqaiw06JjMftq7L9ouA448dw/E7dKghkP9WpKNuwmARNNg+Gk8/u5ryb9N/Yo2+z3MCwuqFK/+qPOPfQ==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "dev": true, + "license": "ISC", + "optional": true, + "dependencies": { + "glob": "^6.0.1" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/nan": { + "version": "2.23.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.23.0.tgz", + "integrity": "sha512-1UxuyYGdoQHcGg87Lkqm3FzefucTa0NAiOcuRsDmysep3c1LVCRK2krrUDafMWtjSG04htvAmvg96+SDknOmgQ==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "dev": true, + "license": "MIT" + }, + "node_modules/natural-compare-lite": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz", + "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==", + "dev": true, + "license": "MIT" + }, + "node_modules/ncp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ncp/-/ncp-2.0.0.tgz", + "integrity": "sha512-zIdGUrPRFTUELUvr3Gmc7KZ2Sw/h1PiVM0Af/oHB6zgnV1ikqSfRk+TOufi79aHYCW3NiOXmr1BP5nWbzojLaA==", + "dev": true, + "license": "MIT", + "optional": true, + "bin": { + "ncp": "bin/ncp" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", + "license": "MIT" + }, + "node_modules/nocache": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-3.0.4.tgz", + "integrity": "sha512-WDD0bdg9mbq6F4mRxEYcPWwfA1vxd0mrvKOyxI7Xj/atfRHVeutzuWByG//jfm4uPzp0y4Kj051EORCBSQMycw==", + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "license": "MIT" + }, + "node_modules/node-dir": { + "version": "0.1.17", + "resolved": "https://registry.npmjs.org/node-dir/-/node-dir-0.1.17.tgz", + "integrity": "sha512-tmPX422rYgofd4epzrNoOXiE8XFZYOcCq1vD7MAXCDO+O+zndlA2ztdKKMa+EeuBG5tHETpr4ml4RGgpqDCCAg==", + "license": "MIT", + "dependencies": { + "minimatch": "^3.0.2" + }, + "engines": { + "node": ">= 0.10.5" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "license": "MIT", + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/node-int64": { + "version": "0.4.0", + "license": "MIT" + }, + "node_modules/node-ipc": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.2.1.tgz", + "integrity": "sha512-mJzaM6O3xHf9VT8BULvJSbdVbmHUKRNOH7zDDkCrA1/T+CVjq2WVIDfLt0azZRXpgArJtl3rtmEozrbXPZ9GaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "event-pubsub": "4.3.0", + "js-message": "1.0.7", + "js-queue": "2.0.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/node-releases": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", + "license": "MIT" + }, + "node_modules/node-stream-zip": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/node-stream-zip/-/node-stream-zip-1.15.0.tgz", + "integrity": "sha512-LN4fydt9TqhZhThkZIVQnF9cwjU3qmUH9h78Mx/K7d3VvfRqqwthLwJEUOEL0QPZ0XQmNN7be5Ggit5+4dq3Bw==", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/antelle" + } + }, + "node_modules/node-version": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/node-version/-/node-version-1.2.0.tgz", + "integrity": "sha512-ma6oU4Sk0qOoKEAymVoTvk8EdXEobdS7m/mAGhDJ8Rouugho48crHBORAmy5BoOcv8wraPM6xumapQp5hl4iIQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/npm-run-path": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz", + "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==", + "license": "MIT", + "dependencies": { + "path-key": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/nullthrows": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/nullthrows/-/nullthrows-1.1.1.tgz", + "integrity": "sha512-2vPPEi+Z7WqML2jZYddDIfy5Dqb0r2fze2zTxNNknZaFpVHU3mFB3R+DWeJWGVx0ecvttSGlJTI+WG+8Z4cDWw==", + "license": "MIT" + }, + "node_modules/ob1": { + "version": "0.80.12", + "resolved": "https://registry.npmjs.org/ob1/-/ob1-0.80.12.tgz", + "integrity": "sha512-VMArClVT6LkhUGpnuEoBuyjG9rzUyEzg4PDkav6wK1cLhOK02gPCYFxoiB4mqVnrMhDpIzJcrGNAMVi9P+hXrw==", + "license": "MIT", + "dependencies": { + "flow-enums-runtime": "^0.0.6" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.7", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", + "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0", + "has-symbols": "^1.1.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.entries": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.8.tgz", + "integrity": "sha512-cmopxi8VwRIAw/fkijJohSfpef5PdN0pMQJN6VC/ZKvn0LIknWD8KtgY6KlQdEc4tIjcQ3HxSMmnvtzIscdaYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.fromentries": { + "version": "2.0.8", + "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz", + "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.2", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object.values": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz", + "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/on-headers": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz", + "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "license": "ISC", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "5.1.2", + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/open": { + "version": "6.4.0", + "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz", + "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==", + "license": "MIT", + "dependencies": { + "is-wsl": "^1.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/open/node_modules/is-wsl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz", + "integrity": "sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/own-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz", + "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.6", + "object-keys": "^1.1.1", + "safe-push-apply": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "4.1.0", + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/p-locate/node_modules/p-limit": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-try": { + "version": "2.2.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-exists": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/path-is-absolute": { + "version": "1.0.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "license": "MIT" + }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", + "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz", + "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/pkg-dir": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", + "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "find-up": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/possible-typed-array-names": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz", + "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/prettier": { + "version": "2.8.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz", + "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==", + "dev": true, + "license": "MIT", + "bin": { + "prettier": "bin-prettier.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/prettier-linter-helpers": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz", + "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-diff": "^1.1.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/pretty-format": { + "version": "29.7.0", + "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", + "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", + "license": "MIT", + "dependencies": { + "@jest/schemas": "^29.6.3", + "ansi-styles": "^5.0.0", + "react-is": "^18.0.0" + }, + "engines": { + "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + } + }, + "node_modules/pretty-format/node_modules/ansi-styles": { + "version": "5.2.0", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "license": "MIT" + }, + "node_modules/promise": { + "version": "8.3.0", + "license": "MIT", + "dependencies": { + "asap": "~2.0.6" + } + }, + "node_modules/promise-polyfill": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-6.1.0.tgz", + "integrity": "sha512-g0LWaH0gFsxovsU7R5LrrhHhWAWiHRnh1GPrhXnPgYsDkIqjRYUYSZEsej/wtleDrz5xVSIDbeKfidztp2XHFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/prompts": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", + "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", + "license": "MIT", + "dependencies": { + "kleur": "^3.0.3", + "sisteransi": "^1.0.5" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", + "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/prop-types/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/proper-lockfile": { + "version": "3.2.0", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.1.11", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/punycode": { + "version": "2.3.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/pure-rand": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", + "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/dubzzz" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/fast-check" + } + ], + "license": "MIT" + }, + "node_modules/queue": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/queue/-/queue-6.0.2.tgz", + "integrity": "sha512-iHZWu+q3IdFZFX36ro/lKBkSvfkztY5Y7HMiPlOUjhupPcG2JMfst2KKEpu5XndviX/3UhFbRngUPNKtgvtZiA==", + "license": "MIT", + "dependencies": { + "inherits": "~2.0.3" + } + }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/react": { + "version": "18.2.0", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-devtools-core": { + "version": "4.28.5", + "resolved": "https://registry.npmjs.org/react-devtools-core/-/react-devtools-core-4.28.5.tgz", + "integrity": "sha512-cq/o30z9W2Wb4rzBefjv5fBalHU0rJGZCHAkf/RHSBWSSYwh8PlQTqqOJmgIIbBtpj27T6FIPXeomIjZtCNVqA==", + "license": "MIT", + "dependencies": { + "shell-quote": "^1.6.1", + "ws": "^7" + } + }, + "node_modules/react-is": { + "version": "18.2.0", + "license": "MIT" + }, + "node_modules/react-native": { + "version": "0.73.11", + "resolved": "https://registry.npmjs.org/react-native/-/react-native-0.73.11.tgz", + "integrity": "sha512-yvQIX+ZXOHMFnhmwZ1fBpRI/53k+iLN8DxVf24Fx4ABU63RGAYfyCZC0/3W+5OUVx4KSIZUv4Tv+/NGIieBOwg==", + "license": "MIT", + "dependencies": { + "@jest/create-cache-key-function": "^29.6.3", + "@react-native-community/cli": "12.3.7", + "@react-native-community/cli-platform-android": "12.3.7", + "@react-native-community/cli-platform-ios": "12.3.7", + "@react-native/assets-registry": "0.73.1", + "@react-native/codegen": "0.73.3", + "@react-native/community-cli-plugin": "0.73.18", + "@react-native/gradle-plugin": "0.73.5", + "@react-native/js-polyfills": "0.73.1", + "@react-native/normalize-colors": "0.73.2", + "@react-native/virtualized-lists": "0.73.4", + "abort-controller": "^3.0.0", + "anser": "^1.4.9", + "ansi-regex": "^5.0.0", + "base64-js": "^1.5.1", + "chalk": "^4.0.0", + "deprecated-react-native-prop-types": "^5.0.0", + "event-target-shim": "^5.0.1", + "flow-enums-runtime": "^0.0.6", + "invariant": "^2.2.4", + "jest-environment-node": "^29.6.3", + "jsc-android": "^250231.0.0", + "memoize-one": "^5.0.0", + "metro-runtime": "^0.80.3", + "metro-source-map": "^0.80.3", + "mkdirp": "^0.5.1", + "nullthrows": "^1.1.1", + "pretty-format": "^26.5.2", + "promise": "^8.3.0", + "react-devtools-core": "^4.27.7", + "react-refresh": "^0.14.0", + "react-shallow-renderer": "^16.15.0", + "regenerator-runtime": "^0.13.2", + "scheduler": "0.24.0-canary-efb381bbf-20230505", + "stacktrace-parser": "^0.1.10", + "whatwg-fetch": "^3.0.0", + "ws": "^6.2.2", + "yargs": "^17.6.2" + }, + "bin": { + "react-native": "cli.js" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "react": "18.2.0" + } + }, + "node_modules/react-native-fs": { + "version": "2.20.0", + "license": "MIT", + "dependencies": { + "base-64": "^0.1.0", + "utf8": "^3.0.0" + }, + "peerDependencies": { + "react-native": "*", + "react-native-windows": "*" + }, + "peerDependenciesMeta": { + "react-native-windows": { + "optional": true + } + } + }, + "node_modules/react-native/node_modules/@jest/types": { + "version": "26.6.2", + "license": "MIT", + "dependencies": { + "@types/istanbul-lib-coverage": "^2.0.0", + "@types/istanbul-reports": "^3.0.0", + "@types/node": "*", + "@types/yargs": "^15.0.0", + "chalk": "^4.0.0" + }, + "engines": { + "node": ">= 10.14.2" + } + }, + "node_modules/react-native/node_modules/@types/yargs": { + "version": "15.0.14", + "license": "MIT", + "dependencies": { + "@types/yargs-parser": "*" + } + }, + "node_modules/react-native/node_modules/pretty-format": { + "version": "26.6.2", + "license": "MIT", + "dependencies": { + "@jest/types": "^26.6.2", + "ansi-regex": "^5.0.0", + "ansi-styles": "^4.0.0", + "react-is": "^17.0.1" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/react-native/node_modules/react-is": { + "version": "17.0.2", + "license": "MIT" + }, + "node_modules/react-native/node_modules/react-refresh": { + "version": "0.14.2", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz", + "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-native/node_modules/ws": { + "version": "6.2.3", + "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz", + "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==", + "license": "MIT", + "dependencies": { + "async-limiter": "~1.0.0" + } + }, + "node_modules/react-shallow-renderer": { + "version": "16.15.0", + "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz", + "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==", + "license": "MIT", + "dependencies": { + "object-assign": "^4.1.1", + "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0" + }, + "peerDependencies": { + "react": "^16.0.0 || ^17.0.0 || ^18.0.0" + } + }, + "node_modules/react-test-renderer": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.2.0.tgz", + "integrity": "sha512-JWD+aQ0lh2gvh4NM3bBM42Kx+XybOxCpgYK7F8ugAlpaTSnWsX+39Z4XkOykGZAHrjwwTZT3x3KxswVWxHPUqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "react-is": "^18.2.0", + "react-shallow-renderer": "^16.15.0", + "scheduler": "^0.23.0" + }, + "peerDependencies": { + "react": "^18.2.0" + } + }, + "node_modules/react-test-renderer/node_modules/scheduler": { + "version": "0.23.2", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", + "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/readable-stream": { + "version": "2.3.8", + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readline": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/readline/-/readline-1.3.0.tgz", + "integrity": "sha512-k2d6ACCkiNYz222Fs/iNze30rRJ1iIicW7JuX/7/cozvih6YCkFZH+J6mAFDVgv0dRBaAyr4jDqC95R2y4IADg==", + "license": "BSD" + }, + "node_modules/recast": { + "version": "0.21.5", + "resolved": "https://registry.npmjs.org/recast/-/recast-0.21.5.tgz", + "integrity": "sha512-hjMmLaUXAm1hIuTqOdeYObMslq/q+Xff6QE3Y2P+uoHAg2nmVlLBps2hzh1UJDdMtDTMXOFewK6ky51JQIeECg==", + "license": "MIT", + "dependencies": { + "ast-types": "0.15.2", + "esprima": "~4.0.0", + "source-map": "~0.6.1", + "tslib": "^2.0.1" + }, + "engines": { + "node": ">= 4" + } + }, + "node_modules/reflect.getprototypeof": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz", + "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.9", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.7", + "get-proto": "^1.0.1", + "which-builtin-type": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regenerate": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", + "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", + "license": "MIT" + }, + "node_modules/regenerate-unicode-properties": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", + "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", + "license": "MIT", + "dependencies": { + "regenerate": "^1.4.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regenerator-runtime": { + "version": "0.13.9", + "license": "MIT" + }, + "node_modules/regenerator-transform": { + "version": "0.15.2", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz", + "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==", + "license": "MIT", + "dependencies": { + "@babel/runtime": "^7.8.4" + } + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz", + "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "define-properties": "^1.2.1", + "es-errors": "^1.3.0", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "set-function-name": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/regexpu-core": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-5.3.2.tgz", + "integrity": "sha512-RAM5FlZz+Lhmo7db9L298p2vHP5ZywrVXmVXpmAD9GuL5MPH6t9ROw1iA/wfHkQ76Qe7AaPF0nGuim96/IrQMQ==", + "license": "MIT", + "dependencies": { + "@babel/regjsgen": "^0.8.0", + "regenerate": "^1.4.2", + "regenerate-unicode-properties": "^10.1.0", + "regjsparser": "^0.9.1", + "unicode-match-property-ecmascript": "^2.0.0", + "unicode-match-property-value-ecmascript": "^2.1.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/regjsparser": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.9.1.tgz", + "integrity": "sha512-dQUtn90WanSNl+7mQKcXAgZxvUe7Z0SqXlgzv0za4LwiUhyzBC58yQO3liFoUgu8GiJVInAhJjkj1N0EtQ5nkQ==", + "license": "BSD-2-Clause", + "dependencies": { + "jsesc": "~0.5.0" + }, + "bin": { + "regjsparser": "bin/parser" + } + }, + "node_modules/regjsparser/node_modules/jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==", + "bin": { + "jsesc": "bin/jsesc" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/require-main-filename": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz", + "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==", + "license": "ISC" + }, + "node_modules/resolve": { + "version": "1.22.0", + "license": "MIT", + "dependencies": { + "is-core-module": "^2.8.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/resolve-cwd": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", + "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve-from": { + "version": "5.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/retry": { + "version": "0.12.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "license": "MIT", + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, + "node_modules/rimraf": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", + "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", + "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "get-intrinsic": "^1.2.6", + "has-symbols": "^1.1.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-array-concat/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "license": "MIT" + }, + "node_modules/safe-json-stringify": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/safe-json-stringify/-/safe-json-stringify-1.2.0.tgz", + "integrity": "sha512-gH8eh2nZudPQO6TytOvbxnuhYBOvDBBLW52tz5q6X58lJcd/tkmqFR+5Z9adS8aJtURSXWThWy/xJtJwixErvg==", + "dev": true, + "license": "MIT", + "optional": true + }, + "node_modules/safe-push-apply": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz", + "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-push-apply/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/safe-regex-test": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", + "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "is-regex": "^1.2.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sanitize-filename": { + "version": "1.6.3", + "dev": true, + "license": "WTFPL OR ISC", + "dependencies": { + "truncate-utf8-bytes": "^1.0.0" + } + }, + "node_modules/scheduler": { + "version": "0.24.0-canary-efb381bbf-20230505", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.24.0-canary-efb381bbf-20230505.tgz", + "integrity": "sha512-ABvovCDe/k9IluqSh4/ISoq8tIJnW8euVAWYt5j/bg6dRnqwQwiGO1F/V4AyK96NGF/FB04FhOUDuWj8IKfABA==", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.1.0" + } + }, + "node_modules/semver": { + "version": "6.3.1", + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/send": { + "version": "0.19.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", + "integrity": "sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw==", + "license": "MIT", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "license": "MIT", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/send/node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "license": "MIT", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/send/node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/serialize-error": { + "version": "8.1.0", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.20.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/serve-static": { + "version": "1.16.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", + "integrity": "sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw==", + "license": "MIT", + "dependencies": { + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.19.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/serve-static/node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==", + "license": "ISC" + }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", + "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-proto": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz", + "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "dunder-proto": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "license": "ISC" + }, + "node_modules/shallow-clone": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", + "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", + "license": "MIT", + "dependencies": { + "kind-of": "^6.0.2" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/shell-quote": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/signal-exit": { + "version": "3.0.7", + "license": "ISC" + }, + "node_modules/sisteransi": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", + "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "license": "MIT" + }, + "node_modules/slash": { + "version": "3.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/slice-ansi": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz", + "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==", + "license": "MIT", + "dependencies": { + "ansi-styles": "^3.2.0", + "astral-regex": "^1.0.0", + "is-fullwidth-code-point": "^2.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/slice-ansi/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "license": "MIT", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/slice-ansi/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "license": "MIT", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/slice-ansi/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", + "license": "MIT" + }, + "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.13", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz", + "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "license": "BSD-3-Clause" + }, + "node_modules/stack-utils": { + "version": "2.0.6", + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^2.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/stack-utils/node_modules/escape-string-regexp": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/stackframe": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", + "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==", + "license": "MIT" + }, + "node_modules/stacktrace-parser": { + "version": "0.1.10", + "license": "MIT", + "dependencies": { + "type-fest": "^0.7.1" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/stacktrace-parser/node_modules/type-fest": { + "version": "0.7.1", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=8" + } + }, + "node_modules/statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/stream-chain": { + "version": "2.2.5", + "resolved": "https://registry.npmjs.org/stream-chain/-/stream-chain-2.2.5.tgz", + "integrity": "sha512-1TJmBx6aSWqZ4tx7aTpBDXK0/e2hhcNSTV8+CbFJtDjbb+I1mZ8lHit0Grw9GRT+6JbIrrDd8esncgBi8aBXGA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/stream-json": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/stream-json/-/stream-json-1.9.1.tgz", + "integrity": "sha512-uWkjJ+2Nt/LO9Z/JyKZbMusL8Dkh97uUBTv3AJQ74y07lVahLY4eEFsPsE97pxYBwr8nnjMAIch5eqI0gPShyw==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "stream-chain": "^2.2.5" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string-length": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", + "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "char-regex": "^1.0.2", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/string-natural-compare": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/string-natural-compare/-/string-natural-compare-3.0.1.tgz", + "integrity": "sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw==", + "dev": true, + "license": "MIT" + }, + "node_modules/string-width": { + "version": "4.2.3", + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.matchall": { + "version": "4.0.12", + "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz", + "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.3", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.6", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "get-intrinsic": "^1.2.6", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "internal-slot": "^1.1.0", + "regexp.prototype.flags": "^1.5.3", + "set-function-name": "^2.0.2", + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.repeat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz", + "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-properties": "^1.1.3", + "es-abstract": "^1.17.5" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.10", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", + "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-data-property": "^1.1.4", + "define-properties": "^1.2.1", + "es-abstract": "^1.23.5", + "es-object-atoms": "^1.0.0", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", + "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "call-bound": "^1.0.2", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", + "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "6.0.1", + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", + "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-final-newline": { + "version": "2.0.0", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/strnum": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.1.2.tgz", + "integrity": "sha512-vrN+B7DBIoTTZjnPNewwhx6cBA/H+IS7rfW68n7XxC1y7uoiGQBxaKzqucGUgavX15dJgiGztLJ8vxuEzwqBdA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "license": "MIT" + }, + "node_modules/sudo-prompt": { + "version": "9.2.1", + "resolved": "https://registry.npmjs.org/sudo-prompt/-/sudo-prompt-9.2.1.tgz", + "integrity": "sha512-Mu7R0g4ig9TUuGSxJavny5Rv0egCEtpZRNMrZaYS1vxkiIxGiGUwoezU3LazIQ+KE04hTrTfNPgxU5gzi7F5Pw==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, + "node_modules/supports-color": { + "version": "7.2.0", + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "license": "MIT", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/telnet-client": { + "version": "1.2.8", + "dev": true, + "license": "MIT", + "dependencies": { + "bluebird": "^3.5.4" + }, + "funding": { + "type": "paypal", + "url": "https://paypal.me/kozjak" + } + }, + "node_modules/temp": { + "version": "0.8.4", + "resolved": "https://registry.npmjs.org/temp/-/temp-0.8.4.tgz", + "integrity": "sha512-s0ZZzd0BzYv5tLSptZooSjK8oj6C+c19p7Vqta9+6NPOf7r+fxq0cJe6/oN4LTC79sy5NY8ucOJNgwsKCSbfqg==", + "license": "MIT", + "dependencies": { + "rimraf": "~2.6.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha512-xZFXEGbG7SNC3itwBzI3RYjq/cEhBkx2hJuKGIUOcEULmkQExXiHat2z/qkISYsuR+IKumhEfKKbV5qXmhICFQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/temp/node_modules/rimraf": { + "version": "2.6.3", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz", + "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==", + "deprecated": "Rimraf versions prior to v4 are no longer supported", + "license": "ISC", + "dependencies": { + "glob": "^7.1.3" + }, + "bin": { + "rimraf": "bin.js" + } + }, + "node_modules/tempfile": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", + "integrity": "sha512-ZOn6nJUgvgC09+doCEF3oB+r3ag7kUvlsXEGX069QRD60p+P3uP7XG9N2/at+EyIRGSN//ZY3LyEotA1YpmjuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "temp-dir": "^1.0.0", + "uuid": "^3.0.1" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/tempfile/node_modules/uuid": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz", + "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==", + "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "bin/uuid" + } + }, + "node_modules/terser": { + "version": "5.33.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.33.0.tgz", + "integrity": "sha512-JuPVaB7s1gdFKPKTelwUyRq5Sid2A3Gko2S0PncwdBq7kN9Ti9HPWDQ06MPsEDGsZeVESjKEnyGy68quBk1w6g==", + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", + "license": "MIT" + }, + "node_modules/terser/node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/test-exclude": { + "version": "6.0.0", + "dev": true, + "license": "ISC", + "dependencies": { + "@istanbuljs/schema": "^0.1.2", + "glob": "^7.1.4", + "minimatch": "^3.0.4" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==", + "dev": true, + "license": "MIT" + }, + "node_modules/throat": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/throat/-/throat-5.0.0.tgz", + "integrity": "sha512-fcwX4mndzpLQKBS1DVYhGAcYaYt7vsHNIvQV+WXMvnow5cgjPphq5CaayLaGsjRdSCKZFNGt7/GYAuXaNOiYCA==", + "license": "MIT" + }, + "node_modules/through2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz", + "integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==", + "license": "MIT", + "dependencies": { + "readable-stream": "~2.3.6", + "xtend": "~4.0.1" + } + }, + "node_modules/tmpl": { + "version": "1.0.5", + "license": "BSD-3-Clause" + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/to-regex-range/node_modules/is-number": { + "version": "7.0.0", + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "license": "MIT", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "license": "MIT" + }, + "node_modules/trace-event-lib": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/trace-event-lib/-/trace-event-lib-1.4.1.tgz", + "integrity": "sha512-TOgFolKG8JFY+9d5EohGWMvwvteRafcyfPWWNIqcuD1W/FUvxWcy2MSCZ/beYHM63oYPHYHCd3tkbgCctHVP7w==", + "dev": true, + "license": "MIT", + "dependencies": { + "browser-process-hrtime": "^1.0.0" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/truncate-utf8-bytes": { + "version": "1.0.2", + "dev": true, + "license": "WTFPL", + "dependencies": { + "utf8-byte-length": "^1.0.1" + } + }, + "node_modules/tslib": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", + "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "license": "0BSD" + }, + "node_modules/tsutils": { + "version": "3.21.0", + "resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz", + "integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==", + "dev": true, + "license": "MIT", + "dependencies": { + "tslib": "^1.8.1" + }, + "engines": { + "node": ">= 6" + }, + "peerDependencies": { + "typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta" + } + }, + "node_modules/tsutils/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "dev": true, + "license": "0BSD" + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/type-detect": { + "version": "4.0.8", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/type-fest": { + "version": "0.20.2", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/typed-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", + "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "es-errors": "^1.3.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", + "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.14" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", + "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "for-each": "^0.3.3", + "gopd": "^1.2.0", + "has-proto": "^1.2.0", + "is-typed-array": "^1.1.15", + "reflect.getprototypeof": "^1.0.9" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", + "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "is-typed-array": "^1.1.13", + "possible-typed-array-names": "^1.0.0", + "reflect.getprototypeof": "^1.0.6" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typescript": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", + "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=12.20" + } + }, + "node_modules/unbox-primitive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", + "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.3", + "has-bigints": "^1.0.2", + "has-symbols": "^1.1.0", + "which-boxed-primitive": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/unicode-canonical-property-names-ecmascript": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", + "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-ecmascript": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", + "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", + "license": "MIT", + "dependencies": { + "unicode-canonical-property-names-ecmascript": "^2.0.0", + "unicode-property-aliases-ecmascript": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-match-property-value-ecmascript": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", + "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/unicode-property-aliases-ecmascript": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", + "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", + "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.1.2", + "picocolors": "^1.0.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/utf8": { + "version": "3.0.0", + "license": "MIT" + }, + "node_modules/utf8-byte-length": { + "version": "1.0.4", + "dev": true, + "license": "WTFPL" + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "license": "MIT" + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "license": "MIT", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "dev": true, + "license": "MIT", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-to-istanbul": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", + "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", + "dev": true, + "license": "ISC", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.12", + "@types/istanbul-lib-coverage": "^2.0.1", + "convert-source-map": "^2.0.0" + }, + "engines": { + "node": ">=10.12.0" + } + }, + "node_modules/vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/vlq": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/vlq/-/vlq-1.0.1.tgz", + "integrity": "sha512-gQpnTgkubC6hQgdIcRdYGDSDc+SaujOdyesZQMv6JlfQee/9Mp0Qhnys6WxDWvQnL5WZdT7o2Ul187aSt0Rq+w==", + "license": "MIT" + }, + "node_modules/walker": { + "version": "1.0.8", + "license": "Apache-2.0", + "dependencies": { + "makeerror": "1.0.12" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "license": "BSD-2-Clause" + }, + "node_modules/whatwg-fetch": { + "version": "3.6.2", + "license": "MIT" + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "license": "MIT", + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", + "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-bigint": "^1.1.0", + "is-boolean-object": "^1.2.1", + "is-number-object": "^1.1.1", + "is-string": "^1.1.1", + "is-symbol": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", + "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bound": "^1.0.2", + "function.prototype.name": "^1.1.6", + "has-tostringtag": "^1.0.2", + "is-async-function": "^2.0.0", + "is-date-object": "^1.1.0", + "is-finalizationregistry": "^1.1.0", + "is-generator-function": "^1.0.10", + "is-regex": "^1.2.1", + "is-weakref": "^1.0.2", + "isarray": "^2.0.5", + "which-boxed-primitive": "^1.1.0", + "which-collection": "^1.0.2", + "which-typed-array": "^1.1.16" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-builtin-type/node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", + "dev": true, + "license": "MIT" + }, + "node_modules/which-collection": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", + "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-map": "^2.0.3", + "is-set": "^2.0.3", + "is-weakmap": "^2.0.2", + "is-weakset": "^2.0.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-module": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz", + "integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==", + "license": "ISC" + }, + "node_modules/which-typed-array": { + "version": "1.1.19", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz", + "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==", + "dev": true, + "license": "MIT", + "dependencies": { + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.8", + "call-bound": "^1.0.4", + "for-each": "^0.3.5", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-tostringtag": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/wrap-ansi": { + "version": "7.0.0", + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "license": "ISC" + }, + "node_modules/write-file-atomic": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", + "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "dev": true, + "license": "ISC", + "dependencies": { + "imurmurhash": "^0.1.4", + "signal-exit": "^3.0.7" + }, + "engines": { + "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + } + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "license": "MIT", + "engines": { + "node": ">=8.3.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": "^5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } + } + }, + "node_modules/xml": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz", + "integrity": "sha512-huCv9IH9Tcf95zuYCsQraZtWnJvBtLVE0QHMOs8bWyZAFZNDcYjsPq1nEx8jKA9y+Beo9v+7OBPRisQTjinQMw==", + "dev": true, + "license": "MIT" + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "license": "MIT", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "license": "ISC", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "dev": true, + "license": "ISC" + }, + "node_modules/yaml": { + "version": "2.8.3", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", + "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14.6" + }, + "funding": { + "url": "https://github.com/sponsors/eemeli" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "license": "MIT", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "license": "ISC", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-unparser": { + "version": "2.0.0", + "dev": true, + "license": "MIT", + "dependencies": { + "camelcase": "^6.0.0", + "decamelize": "^4.0.0", + "flat": "^5.0.2", + "is-plain-obj": "^2.1.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/yargs-unparser/node_modules/decamelize": { + "version": "4.0.0", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + } + } +} diff --git a/js/react_native/e2e/package.json b/js/react_native/e2e/package.json index d68b4ef2dabe2..f44c5fce13d5c 100644 --- a/js/react_native/e2e/package.json +++ b/js/react_native/e2e/package.json @@ -6,31 +6,35 @@ "scripts": { "android": "react-native run-android", "ios": "react-native run-ios", - "start": "react-native start", "lint": "eslint .", + "start": "react-native start", "test": "jest" }, "dependencies": { "react": "^18.2.0", - "react-native": "^0.71.19", + "react-native": "^0.73.11", "react-native-fs": "^2.20.0" }, "devDependencies": { "@babel/core": "^7.20.0", "@babel/preset-env": "^7.20.0", - "@babel/runtime": "^7.20.0", - "@react-native-community/eslint-config": "^3.2.0", - "@tsconfig/react-native": "^2.0.2", - "@types/jest": "^29.2.1", - "@types/react": "^18.0.24", + "@babel/runtime": "^7.28.3", + "@react-native/babel-preset": "0.73.21", + "@react-native/eslint-config": "^0.73.2", + "@react-native/metro-config": "^0.73.5", + "@react-native/typescript-config": "0.73.1", + "@types/react": "^18.2.6", "@types/react-test-renderer": "^18.0.0", - "babel-jest": "^29.2.1", - "babel-plugin-module-resolver": "^4.0.0", - "detox": "20.10.0", - "jest": "^29.2.1", - "metro-react-native-babel-preset": "0.73.10", - "prettier": "^2.4.1", + "babel-jest": "^29.6.3", + "detox": "20.11.4", + "eslint": "^8.19.0", + "jest": "^29.6.3", + "jest-junit": "16.0.0", + "prettier": "^2.8.8", "react-test-renderer": "18.2.0", - "typescript": "4.8.4" + "typescript": "5.0.4" + }, + "engines": { + "node": ">=18" } } diff --git a/js/react_native/e2e/src/App.tsx b/js/react_native/e2e/src/App.tsx index 8a76edabc613e..438073f864c42 100644 --- a/js/react_native/e2e/src/App.tsx +++ b/js/react_native/e2e/src/App.tsx @@ -2,128 +2,155 @@ // Licensed under the MIT License. import * as React from 'react'; -import { Image, Text, TextInput, View } from 'react-native'; -// onnxruntime-react-native package is installed when bootstraping -// eslint-disable-next-line import/no-extraneous-dependencies -import { InferenceSession, Tensor } from 'onnxruntime-react-native'; -import MNIST, { MNISTInput, MNISTOutput, MNISTResult, } from './mnist-data-handler'; -import { Buffer } from 'buffer'; -import { readFile } from 'react-native-fs'; +import { Button, SafeAreaView, ScrollView, StyleSheet, Text, View } from 'react-native'; +import MNISTTest from './MNISTTest'; +import BasicTypesTest from './BasicTypesTest'; + +type Page = 'home' | 'mnist' | 'basic-types'; interface State { - session: - InferenceSession | null; - output: - string | null; - imagePath: - string | null; + currentPage: Page; } -// eslint-disable-next-line @typescript-eslint/ban-types +const styles = StyleSheet.create({ + container: { + flex: 1, + backgroundColor: '#f5f5f5', + }, + scrollContent: { + padding: 20, + alignItems: 'center', + }, + title: { + fontSize: 28, + fontWeight: 'bold', + marginTop: 20, + marginBottom: 10, + color: '#333', + textAlign: 'center', + }, + subtitle: { + fontSize: 18, + marginBottom: 30, + color: '#666', + textAlign: 'center', + }, + buttonContainer: { + width: '100%', + marginBottom: 30, + alignItems: 'center', + }, + buttonWrapper: { + width: '80%', + marginBottom: 10, + }, + description: { + fontSize: 14, + color: '#888', + textAlign: 'center', + paddingHorizontal: 20, + }, + header: { + padding: 10, + backgroundColor: '#fff', + borderBottomWidth: 1, + borderBottomColor: '#ddd', + }, + testContent: { + flex: 1, + }, +}); + +// eslint-disable-next-line @typescript-eslint/no-empty-object-type export default class App extends React.PureComponent<{}, State> { - // eslint-disable-next-line @typescript-eslint/ban-types + // eslint-disable-next-line @typescript-eslint/no-empty-object-type constructor(props: {} | Readonly<{}>) { super(props); this.state = { - session: null, - output: null, - imagePath: null, + currentPage: 'home', }; } - // Load a model when an app is loading - async componentDidMount(): Promise { - if (!this.state.session) { - try { - const imagePath = await MNIST.getImagePath(); - this.setState({ imagePath }); - - const modelPath = await MNIST.getLocalModelPath(); - - // test creating session with path - console.log('Creating with path'); - const pathSession: InferenceSession = await InferenceSession.create(modelPath); - pathSession.release(); - - // and with bytes - console.log('Creating with bytes'); - const base64Str = await readFile(modelPath, 'base64'); - const bytes = Buffer.from(base64Str, 'base64'); - const session: InferenceSession = await InferenceSession.create(bytes); - this.setState({ session }); - - console.log('Test session created'); - void await this.infer(); - } catch (err) { - console.log(err.message); - } - } + navigateTo = (page: Page) => { + this.setState({ currentPage: page }); + }; + + renderHome(): React.JSX.Element { + return ( + + + ONNX Runtime E2E Tests + Select a test to run: + + + +