forked from elixir-nx/ortex
-
Notifications
You must be signed in to change notification settings - Fork 0
223 lines (203 loc) · 8.5 KB
/
release.yml
File metadata and controls
223 lines (203 loc) · 8.5 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
name: Build precompiled NIFs
on:
push:
branches:
- main
paths:
# Only run on main when the native crate or this workflow itself
# changes. Tag pushes always run (via the tags trigger below).
- "native/**"
- ".github/workflows/release.yml"
tags:
- "v*"
pull_request:
paths:
- "native/**"
- ".github/workflows/release.yml"
# softprops/action-gh-release creates the GitHub release on tag
# pushes, which requires write access to repository contents. Since
# 2023 the default GITHUB_TOKEN scope has been read-only, so the
# permission must be granted explicitly.
permissions:
contents: write
jobs:
build_release:
name: NIF ${{ matrix.nif }} - ${{ matrix.job.target }} (${{ matrix.job.os }})
runs-on: ${{ matrix.job.os }}
strategy:
fail-fast: false
matrix:
# NIF version 2.16 covers OTP 24-26; 2.17 covers OTP 27-28.
# Both contemporary versions are built so consumers across the
# range get a precompiled artifact.
nif: ["2.16", "2.17"]
job:
# Apple Silicon. macos-14 runners are arm64 natively.
- { target: aarch64-apple-darwin, os: macos-14 }
# Intel Mac. macos-13 was retired by GitHub on Dec 4 2025;
# macos-15-intel is the replacement and is the last available
# Intel-architecture macOS runner (supported through Aug 2027).
# See https://github.com/actions/runner-images/issues/13045.
- { target: x86_64-apple-darwin, os: macos-15-intel }
# Linux x86_64. Built on ubuntu-22.04 — produces a binary
# that requires glibc >= 2.35. See the comment below about
# tightening this with a manylinux container if older distro
# support becomes a goal.
- { target: x86_64-unknown-linux-gnu, os: ubuntu-22.04 }
# Linux ARM64 via cross-rs (cross-compiled from x86_64 runner).
- { target: aarch64-unknown-linux-gnu, os: ubuntu-22.04, use-cross: true }
# Windows x86_64 (MSVC ABI). Covers >95% of Windows users.
- { target: x86_64-pc-windows-msvc, os: windows-2022 }
steps:
- name: Checkout source
uses: actions/checkout@v6
- name: Extract project version from mix.exs
id: version
shell: bash
run: |
version=$(sed -n 's/^ @version "\(.*\)"$/\1/p' mix.exs | head -1)
if [ -z "$version" ]; then
echo "Failed to extract @version from mix.exs" >&2
exit 1
fi
echo "version=${version}" >> "$GITHUB_OUTPUT"
echo "Project version: ${version}"
- name: Install Rust toolchain
uses: dtolnay/rust-toolchain@stable
with:
targets: ${{ matrix.job.target }}
- name: Install cross (Linux ARM64)
if: matrix.job.use-cross
shell: bash
run: cargo install --git https://github.com/cross-rs/cross --tag v0.2.5 cross
# Build the NIF directly with cargo. With the rust-toolchain
# action's stable rustc, the `ort` 2.0.0-rc.x crate links
# onnxruntime statically into the NIF on every platform — the
# output is a single self-contained shared library (~20-25 MB).
# No `libonnxruntime` sidecar exists in target/release/ or
# anywhere else on disk after this step; the packaging step
# below correctly produces a single-file tarball as a result.
- name: Build NIF
shell: bash
working-directory: native/ortex
env:
RUSTLER_NIF_VERSION: ${{ matrix.nif }}
run: |
set -euo pipefail
if [ "${{ matrix.job.use-cross }}" = "true" ]; then
# Cross-compilation needs explicit --target. Output goes
# to target/<triple>/release/.
cross build --release --target "${{ matrix.job.target }}"
else
# Native build. The runner's host arch matches
# matrix.job.target by design, so default cargo behaviour
# produces the right binary. Output goes to target/release/.
cargo build --release
fi
# Stage the right files into a tarball matching RustlerPrecompiled's
# expected layout. Naming and contents follow the conventions in
# rustler_precompiled.ex (lib_name_with_ext/2 + lib_prefix/1):
#
# * Tarball name: lib<crate>-v<ver>-nif-<nif>-<target>.so.tar.gz
# on Linux/macOS, <crate>-v<ver>-nif-<nif>-<target>.dll.tar.gz
# on Windows. macOS keeps the .so suffix even though the NIF
# is a Mach-O dylib — RustlerPrecompiled normalises on .so.
#
# * Top-level files in the tarball: the renamed NIF, plus any
# libonnxruntime sidecars cargo produced. With the current
# `ort 2.0.0-rc.x` build under stable rustc, onnxruntime is
# statically linked on every platform, so the sidecar loop
# finds nothing and the tarball is single-file. The loop
# still runs as forward compatibility — if a future ort
# version reverts to dynamic linking we'll auto-bundle the
# runtime alongside the NIF without code changes.
#
# The loop deliberately EXCLUDES libonnxruntime_providers_cuda
# and ..._tensorrt — those are >450 MB and only useful with
# the matching cargo features enabled. CPU-only is the default
# precompile target; GPU users opt into source build via
# ORTEX_BUILD=true.
- name: Package artifact
id: pkg
shell: bash
env:
VERSION: ${{ steps.version.outputs.version }}
TARGET: ${{ matrix.job.target }}
NIF: ${{ matrix.nif }}
run: |
set -euo pipefail
case "$TARGET" in
*-pc-windows-msvc|*-pc-windows-gnu)
prefix=""
nif_src_ext="dll"
tarball_ext="dll"
runtime_ext="dll"
;;
*-apple-darwin)
prefix="lib"
nif_src_ext="dylib"
tarball_ext="so"
runtime_ext="dylib"
;;
*-unknown-linux-*)
prefix="lib"
nif_src_ext="so"
tarball_ext="so"
runtime_ext="so"
;;
*)
echo "Unsupported target: $TARGET" >&2
exit 1
;;
esac
NAME="${prefix}ortex-v${VERSION}-nif-${NIF}-${TARGET}"
TARBALL="${NAME}.${tarball_ext}.tar.gz"
# Build output location depends on whether --target was used.
# Native builds (cargo build --release) land in target/release/.
# Cross builds (cross build --release --target X) land in
# target/<X>/release/. The "Build NIF" step controls which.
if [ "${{ matrix.job.use-cross }}" = "true" ]; then
BUILD_DIR="native/ortex/target/${TARGET}/release"
else
BUILD_DIR="native/ortex/target/release"
fi
mkdir -p pkg
cd pkg
rm -f -- *
# Copy the NIF, renaming to the long versioned filename
# RustlerPrecompiled expects. -L follows symlinks (cargo
# sometimes leaves the .so as a symlink into deps/).
cp -L "../${BUILD_DIR}/${prefix}ortex.${nif_src_ext}" "${NAME}.${tarball_ext}"
# Bundle libonnxruntime sidecars if present. Exclude GPU
# provider libraries (huge; not used by CPU-only NIFs).
shopt -s nullglob
for src in "../${BUILD_DIR}/${prefix}onnxruntime"*."${runtime_ext}"*; do
base="$(basename "$src")"
case "$base" in
*providers_cuda*|*providers_tensorrt*)
echo "Excluding GPU provider library: $base"
;;
*)
echo "Bundling: $base"
cp -L "$src" "$base"
;;
esac
done
tar -czf "$TARBALL" -- *
echo "=== Final tarball contents ==="
tar -tzvf "$TARBALL"
echo "=== Tarball size ==="
ls -lh "$TARBALL"
echo "tarball=pkg/${TARBALL}" >> "$GITHUB_OUTPUT"
echo "tarball-name=${TARBALL}" >> "$GITHUB_OUTPUT"
- name: Upload artifact (workflow run)
uses: actions/upload-artifact@v7
with:
name: ${{ steps.pkg.outputs.tarball-name }}
path: ${{ steps.pkg.outputs.tarball }}
- name: Attach to GitHub release
if: startsWith(github.ref, 'refs/tags/')
uses: softprops/action-gh-release@v3
with:
draft: true
files: ${{ steps.pkg.outputs.tarball }}