Repository navigation
1102 lines (1030 loc) · 47.5 KB
/
Copy pathrelease-atomic.yml
File metadata and controls
1102 lines (1030 loc) · 47.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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
name: Release (Atomic)
# Builds every stable-diffusion.cpp engine Atomic Chat ships, from an unmodified upstream tag plus
# the patch series in atomic/patches, and publishes them as one release of that tag here:
#
# upstream parity (same flags as leejet's build.yml at the tag)
# macos-arm64 universal (arm64 + x86_64), Metal
# win-cpu-x64 win-vulkan-x64 win-cuda12-x64 (+ cudart-sd-bin-win-cu12-x64 companion) win-rocm-x64
# linux-cpu-x64 linux-vulkan-x64 linux-rocm-x64
# Atomic additions
# linux-cpu-arm64 linux-cuda13-arm64 (DGX Spark / GB10) win-cpu-arm64 win-cuda13-arm64 (RTX Spark / N1X)
# linux-cuda12-x64 win-cuda13-x64
#
# Asset names follow upstream's pattern (sd-master-<sha7>-bin-...), so atomic-chat-conf's
# mirror-sdcpp.yml matches them by pattern. `targets` rebuilds a subset while fixing one; a release
# needs `all`. See atomic/README.md.
on:
workflow_dispatch:
inputs:
upstream_tag:
description: "leejet/stable-diffusion.cpp release tag to build (e.g. master-883-137f740)"
required: true
type: string
targets:
description: "Backend ids to build, comma-separated, or 'all' (publishing needs all)"
required: false
default: all
type: string
publish:
description: "Create or update the release of that tag in this repository"
required: false
default: false
type: boolean
concurrency:
group: release-atomic-${{ inputs.upstream_tag }}-${{ inputs.targets }}
cancel-in-progress: false
permissions:
contents: read
env:
UPSTREAM_REPO: leejet/stable-diffusion.cpp
TAG: ${{ inputs.upstream_tag }}
PNPM_VERSION: "10.15.1"
VS_VCVARS: C:\Program Files\Microsoft Visual Studio\2022\Enterprise\VC\Auxiliary\Build\vcvarsall.bat
# Upstream parity: keep in step with leejet's .github/workflows/build.yml at the tag.
WIN_CUDA12: "12.8.1"
CUDA_ARCHS_WIN_CUDA12: "61;70;75;80;86;89;90;100;120"
VULKAN_VERSION_WIN: "1.4.328.1"
ROCM_VERSION: "7.14.0"
ROCM_TARGETS_LINUX: "gfx900;gfx906;gfx908;gfx90a;gfx90c;gfx942;gfx950;gfx1010;gfx1011;gfx1012;gfx1030;gfx1031;gfx1032;gfx1033;gfx1034;gfx1035;gfx1036;gfx1100;gfx1101;gfx1102;gfx1103;gfx1150;gfx1151;gfx1152;gfx1153;gfx1200;gfx1201"
ROCM_TARGETS_WIN: "gfx1010;gfx1011;gfx1012;gfx1030;gfx1031;gfx1032;gfx1033;gfx1034;gfx1035;gfx1036;gfx1100;gfx1101;gfx1102;gfx1103;gfx1150;gfx1151;gfx1152;gfx1153;gfx1200;gfx1201"
# Atomic additions. CUDA 13.4 is the first with Windows on Arm; ggml rewrites 12x to 12xa itself.
WIN_CUDA13: "13.4.2"
CUDA_ARCHS_WIN_CUDA13_X64: "75-virtual;80-virtual;86-real;89-real;120-real"
SMOKE_MODEL_URL: https://huggingface.co/Green-Sky/SD-Turbo-GGUF/resolve/main/sd_turbo-f16-q8_0.gguf
SMOKE_MODEL_SHA256: d50be7655f0a554cf8041c145d88b210bd5f3c545423119dee62ae08cae51580
jobs:
prepare:
runs-on: ubuntu-latest
outputs:
short: ${{ steps.tag.outputs.short }}
sha: ${{ steps.tag.outputs.sha }}
selected: ${{ steps.plan.outputs.selected }}
all: ${{ steps.plan.outputs.all }}
linux: ${{ steps.plan.outputs.linux }}
windows_x64: ${{ steps.plan.outputs.windows_x64 }}
smoke_linux: ${{ steps.plan.outputs.smoke_linux }}
smoke_windows: ${{ steps.plan.outputs.smoke_windows }}
steps:
- name: Resolve the upstream tag
id: tag
run: |
set -euo pipefail
if ! [[ "$TAG" =~ ^master-[0-9]+-([0-9a-f]{7})$ ]]; then
echo "::error::upstream_tag must look like master-883-137f740"
exit 1
fi
short="${BASH_REMATCH[1]}"
refs="$(git ls-remote "https://github.com/$UPSTREAM_REPO.git" "refs/tags/$TAG" "refs/tags/$TAG^{}")"
sha="$(printf '%s\n' "$refs" | awk '/\^\{\}$/ {print $1}' | head -1)"
[ -n "$sha" ] || sha="$(printf '%s\n' "$refs" | awk '{print $1}' | head -1)"
if [ -z "$sha" ]; then echo "::error::$UPSTREAM_REPO has no tag $TAG"; exit 1; fi
case "$sha" in "$short"*) ;; *) echo "::error::$TAG points at $sha, not $short"; exit 1 ;; esac
echo "short=$short" >> "$GITHUB_OUTPUT"
echo "sha=$sha" >> "$GITHUB_OUTPUT"
echo "$TAG -> $sha"
- name: Plan the build
id: plan
env:
TARGETS: ${{ inputs.targets }}
run: |
python3 - <<'EOF'
import json, os, sys
def linux(id, arch, variant, suffix, cuda_ver="", cuda_archs="", check_sm=""):
arm = arch == "arm64"
return dict(id=id, arch=arch, variant=variant, suffix=suffix,
runner="ubuntu-24.04-arm" if arm else "ubuntu-24.04",
gcc="14" if arm else "", elf="ARM aarch64" if arm else "x86-64",
cuda_repo=("sbsa" if arm else "x86_64") if cuda_ver else "",
cuda_ver=cuda_ver, cuda_archs=cuda_archs, check_sm=check_sm)
LINUX = [
linux("linux-cpu-x64", "x64", "cpu", ""),
linux("linux-vulkan-x64", "x64", "vulkan", "-vulkan"),
# Pascal through Blackwell: SASS for Ampere/Ada/Blackwell, PTX floors below.
linux("linux-cuda12-x64", "x64", "cuda12", "-cuda12", "12-8",
"61-virtual;75-virtual;80-virtual;86-real;89-real;120-real", "sm_86"),
linux("linux-cpu-arm64", "arm64", "cpu", ""),
# GB10 SASS plus a Hopper PTX floor (GH200, GB200, Thor JIT).
linux("linux-cuda13-arm64", "arm64", "cuda13", "-cuda13", "13-0", "90-virtual;121-real", "sm_121"),
]
WIN_X64 = [dict(id=f"win-{v}-x64", variant=v) for v in ("cpu", "vulkan", "cuda12", "cuda13")]
SINGLE = ["macos-arm64", "linux-rocm-x64", "win-rocm-x64", "win-cpu-arm64", "win-cuda13-arm64"]
ALL = [e["id"] for e in LINUX] + [e["id"] for e in WIN_X64] + SINGLE
raw = os.environ.get("TARGETS", "").strip()
sel = list(ALL) if raw in ("", "all") else [t.strip() for t in raw.split(",") if t.strip()]
unknown = sorted(set(sel) - set(ALL))
if unknown:
print(f"::error::unknown targets {unknown}; known: {ALL}")
sys.exit(1)
build = set(sel)
if "win-cuda13-arm64" in build:
build.add("win-cpu-arm64") # its tree is what ggml-cuda.dll is merged into
win_runner = {"x64": ("windows-2022", "x64"), "arm64": ("windows-11-arm", "arm64")}
smoke_windows = []
for id in ["win-cpu-x64", "win-vulkan-x64", "win-cuda12-x64", "win-cuda13-x64", "win-cpu-arm64", "win-cuda13-arm64"]:
if id in sel:
runner, py = win_runner[id.rsplit("-", 1)[1]]
smoke_windows.append(dict(id=id, runner=runner, py_arch=py))
out = {
"selected": "," + ",".join(sorted(build)) + ",",
"all": json.dumps(set(sel) == set(ALL)),
"linux": json.dumps([e for e in LINUX if e["id"] in build]),
"windows_x64": json.dumps([e for e in WIN_X64 if e["id"] in build]),
"smoke_linux": json.dumps([dict(id=e["id"], runner=e["runner"], stub_repo=e["cuda_repo"], stub_ver=e["cuda_ver"])
for e in LINUX if e["id"] in sel]),
"smoke_windows": json.dumps(smoke_windows),
}
with open(os.environ["GITHUB_OUTPUT"], "a") as f:
for k, v in out.items():
f.write(f"{k}={v}\n")
print(f"{k}={v}")
EOF
# ----------------------------------------------------------------------------------- macOS
macos-arm64:
needs: prepare
if: contains(needs.prepare.outputs.selected, ',macos-arm64,')
runs-on: macos-latest
timeout-minutes: 120
env:
SHORT: ${{ needs.prepare.outputs.short }}
steps:
- name: Clone upstream tag
uses: actions/checkout@v4
with:
repository: ${{ env.UPSTREAM_REPO }}
ref: ${{ needs.prepare.outputs.sha }}
submodules: recursive
- name: Clone Atomic build files
uses: actions/checkout@v4
with:
path: _atomic
sparse-checkout: atomic
- name: Apply Atomic patches
run: bash _atomic/atomic/ci/apply-patches.sh
- name: ccache
uses: ggml-org/ccache-action@v1.2.21
with:
key: release-atomic-macos-arm64
max-size: 1G
evict-old-files: job
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
# Upstream's flags: a universal binary whose x86_64 slice targets AVX2.
- name: Build
run: |
cmake -S . -B build -DGGML_AVX2=ON -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64" -DSD_BUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
cmake --build build --config Release -j "$(sysctl -n hw.ncpu)"
- name: Package and verify
run: |
set -euo pipefail
cp ggml/LICENSE build/bin/ggml.txt
cp LICENSE build/bin/stable-diffusion.cpp.txt
for f in sd-cli sd-server; do lipo -archs "build/bin/$f" | tee /dev/stderr | grep -q arm64; done
# otool prints a "<file> (architecture ...):" header per slice of a universal binary.
bad="$(for f in build/bin/sd-cli build/bin/sd-server build/bin/*.dylib; do otool -L "$f" | grep -v ':$' | awk '{print $1}'; done \
| grep -v -E '^(/usr/lib/|/System/Library/|@rpath/|@loader_path/|@executable_path/)' | sort -u || true)"
if [ -n "$bad" ]; then echo "$bad"; echo "::error::links outside the archive and the OS"; exit 1; fi
asset="sd-master-$SHORT-bin-Darwin-macOS-$(sw_vers -productVersion)-arm64.zip"
zip -j -X -9 -q "$asset" build/bin/*
ls -l "$asset"
echo "ASSET=$asset" >> "$GITHUB_ENV"
- uses: actions/upload-artifact@v4
with:
name: archive-macos-arm64
path: ${{ env.ASSET }}
if-no-files-found: error
retention-days: 14
# ----------------------------------------------------------------------------------- Linux
linux:
name: ${{ matrix.id }}
needs: prepare
if: needs.prepare.outputs.linux != '[]'
runs-on: ${{ matrix.runner }}
timeout-minutes: 300
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.prepare.outputs.linux) }}
env:
SHORT: ${{ needs.prepare.outputs.short }}
VARIANT: ${{ matrix.variant }}
SUFFIX: ${{ matrix.suffix }}
steps:
- name: Clone upstream tag
uses: actions/checkout@v4
with:
repository: ${{ env.UPSTREAM_REPO }}
ref: ${{ needs.prepare.outputs.sha }}
submodules: recursive
- name: Clone Atomic build files
uses: actions/checkout@v4
with:
path: _atomic
sparse-checkout: atomic
- name: Apply Atomic patches
run: bash _atomic/atomic/ci/apply-patches.sh
- name: ccache
uses: ggml-org/ccache-action@v1.2.21
with:
key: release-atomic-${{ matrix.id }}
max-size: ${{ matrix.cuda_ver != '' && '2G' || '1G' }}
evict-old-files: job
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
# GCC 14 on arm64: GGML_CPU_ALL_VARIANTS builds armv9.2+SME variants that GCC 13 cannot
# assemble (same workaround as llama.cpp's arm64 jobs).
- name: Toolchain
run: |
set -euo pipefail
sudo apt-get update -y
sudo apt-get install -y build-essential ninja-build zip file
if [ "${{ matrix.gcc }}" = 14 ]; then
sudo apt-get install -y gcc-14 g++-14
echo "CC=gcc-14" >> "$GITHUB_ENV"
echo "CXX=g++-14" >> "$GITHUB_ENV"
fi
if [ "$VARIANT" = vulkan ]; then
sudo apt-get install -y libvulkan-dev glslc spirv-headers
fi
# x86_64 repo for x64, SBSA for arm64 (the `arm64` repo is Jetson/L4T). cuda-driver-dev brings
# the libcuda stub stable-diffusion links (CUDA::cuda_driver) when SD_CUDA is on.
- name: Install CUDA toolkit
if: matrix.cuda_ver != ''
run: |
set -euo pipefail
v="${{ matrix.cuda_ver }}"
wget -q "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/${{ matrix.cuda_repo }}/cuda-keyring_1.1-1_all.deb"
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt-get update -y
sudo apt-get install -y "cuda-nvcc-$v" "cuda-cccl-$v" "cuda-cudart-dev-$v" \
"libcublas-dev-$v" "cuda-driver-dev-$v" "cuda-cuobjdump-$v"
cuda_home="/usr/local/cuda-${v/-/.}"
echo "$cuda_home/bin" >> "$GITHUB_PATH"
echo "CUDA_HOME=$cuda_home" >> "$GITHUB_ENV"
- name: Build
run: |
set -euo pipefail
args=(
-G Ninja -DCMAKE_BUILD_TYPE=Release
-DSD_BUILD_SHARED_LIBS=ON -DSD_BUILD_SHARED_GGML_LIB=ON
-DGGML_NATIVE=OFF -DGGML_BACKEND_DL=ON -DGGML_CPU_ALL_VARIANTS=ON
-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON '-DCMAKE_INSTALL_RPATH=$ORIGIN'
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache
)
case "$VARIANT" in
vulkan) args+=(-DSD_VULKAN=ON) ;;
cuda*)
args+=(-DSD_CUDA=ON "-DCMAKE_CUDA_ARCHITECTURES=${{ matrix.cuda_archs }}" -DCMAKE_CUDA_FLAGS=-compress-mode=size
-DCMAKE_CUDA_COMPILER_LAUNCHER=ccache)
if [ "${{ matrix.gcc }}" = 14 ]; then args+=(-DCMAKE_CUDA_HOST_COMPILER=g++-14); fi
;;
esac
cmake -S . -B build "${args[@]}"
cmake --build build -j "$(nproc)"
- name: Package
run: |
set -euo pipefail
asset="sd-master-$SHORT-bin-Linux-$(lsb_release -si)-$(lsb_release -sr)-$(uname -m)$SUFFIX.zip"
bash _atomic/atomic/ci/package-linux.sh build/bin "$RUNNER_TEMP/pkg" "${CUDA_HOME:-}"
(cd "$RUNNER_TEMP/pkg" && zip -X -9 -q -r "$GITHUB_WORKSPACE/$asset" .)
ls -l "$asset"
echo "ASSET=$asset" >> "$GITHUB_ENV"
- name: Verify the archive
run: |
set -euo pipefail
pkg="$RUNNER_TEMP/pkg"
# Atomic Chat's unzip writes a symlink out as a plain file.
if [ -n "$(find "$pkg" -type l)" ]; then find "$pkg" -type l; echo "::error::symlinks in the archive"; exit 1; fi
for f in sd-cli sd-server; do test -x "$pkg/$f" || { echo "::error::$f missing"; exit 1; }; done
for f in "$pkg"/*; do
if file -b "$f" | grep -q '^ELF'; then
file -b "$f" | grep -q "${{ matrix.elf }}" || { echo "::error::$(basename "$f") is not ${{ matrix.elf }}"; exit 1; }
fi
done
missing="$(for f in "$pkg"/*; do file -b "$f" | grep -q '^ELF' && LD_LIBRARY_PATH="$pkg" ldd "$f" | sed "s|^|$(basename "$f"): |" | grep 'not found'; done | grep -v -E 'lib(cuda|vulkan)\.so\.1 ' || true)"
if [ -n "$missing" ]; then echo "$missing"; echo "::error::unresolved libraries"; exit 1; fi
if [ -n "${{ matrix.check_sm }}" ]; then
cuobjdump --list-elf "$pkg/libggml-cuda.so" | tee "$RUNNER_TEMP/elf.txt" | tail -3
grep -q "${{ matrix.check_sm }}" "$RUNNER_TEMP/elf.txt" || { echo "::error::no ${{ matrix.check_sm }} code in libggml-cuda.so"; exit 1; }
fi
ls -l "$pkg"
- uses: actions/upload-artifact@v4
with:
name: archive-${{ matrix.id }}
path: ${{ env.ASSET }}
if-no-files-found: error
retention-days: 14
# Upstream's ROCm job (TheRock wheels). The ROCm runtime is not bundled, as upstream: users
# install it; the archive is made flat and symlink-free like every other Linux one here.
linux-rocm-x64:
needs: prepare
if: contains(needs.prepare.outputs.selected, ',linux-rocm-x64,')
runs-on: ubuntu-24.04
timeout-minutes: 300
env:
SHORT: ${{ needs.prepare.outputs.short }}
steps:
- name: Clone upstream tag
uses: actions/checkout@v4
with:
repository: ${{ env.UPSTREAM_REPO }}
ref: ${{ needs.prepare.outputs.sha }}
submodules: recursive
- name: Clone Atomic build files
uses: actions/checkout@v4
with:
path: _atomic
sparse-checkout: atomic
- name: Apply Atomic patches
run: bash _atomic/atomic/ci/apply-patches.sh
- name: ccache
uses: ggml-org/ccache-action@v1.2.21
with:
key: release-atomic-linux-rocm-x64
max-size: 2G
evict-old-files: job
- name: Dependencies
run: sudo apt-get install -y build-essential git cmake wget ninja-build zip file
- name: Free disk space
run: |
df -h
sudo rm -rf /usr/share/dotnet /usr/local/lib/android /opt/ghc /usr/local/.ghcup /opt/hostedtoolcache /usr/share/swift /usr/local/share/boost || true
docker system prune -af || true
sudo apt clean
df -h
- name: Setup TheRock with wheels
run: |
set -euo pipefail
python3 -m venv .venv
source .venv/bin/activate
python -m pip install --upgrade pip
python -m pip install --index-url https://repo.amd.com/rocm/whl-multi-arch/ "rocm[libraries,devel]==$ROCM_VERSION"
ROCM_PATH=$(rocm-sdk path --root)
echo "ROCM_PATH=$ROCM_PATH" >> "$GITHUB_ENV"
echo "CMAKE_PREFIX_PATH=$(rocm-sdk path --cmake)" >> "$GITHUB_ENV"
echo "HIP_PATH=$ROCM_PATH" >> "$GITHUB_ENV"
echo "PATH=$(rocm-sdk path --bin):${PATH}" >> "$GITHUB_ENV"
echo "LD_LIBRARY_PATH=$ROCM_PATH/lib:${LD_LIBRARY_PATH:-}" >> "$GITHUB_ENV"
echo "$(pwd)/.venv/bin" >> "$GITHUB_PATH"
# setup-node installs into /opt/hostedtoolcache, removed above, so it comes after the cleanup.
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- name: Build
run: |
cmake -S . -B build -G Ninja \
-DCMAKE_HIP_COMPILER="$(hipconfig -l)/clang" \
-DCMAKE_HIP_FLAGS="-mllvm --amdgpu-unroll-threshold-local=600" \
-DCMAKE_BUILD_TYPE=Release \
-DSD_HIPBLAS=ON \
-DHIP_PLATFORM=amd \
-DGPU_TARGETS="$ROCM_TARGETS_LINUX" \
-DCMAKE_BUILD_WITH_INSTALL_RPATH=ON \
-DCMAKE_POSITION_INDEPENDENT_CODE=ON \
'-DCMAKE_INSTALL_RPATH=$ORIGIN' \
-DGGML_NATIVE=OFF \
-DSD_BUILD_SHARED_GGML_LIB=ON \
-DGGML_BACKEND_DL=ON \
-DGGML_CPU_ALL_VARIANTS=ON \
-DSD_BUILD_SHARED_LIBS=ON \
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_HIP_COMPILER_LAUNCHER=ccache
cmake --build build --config Release -j "$(nproc)"
- name: Package and verify
run: |
set -euo pipefail
EXTERNAL_DIRS="$(find "$ROCM_PATH" -name 'lib*.so*' -printf '%h\n' | sort -u | paste -sd:)"
export EXTERNAL_DIRS
bash _atomic/atomic/ci/package-linux.sh build/bin "$RUNNER_TEMP/pkg" ""
if [ -n "$(find "$RUNNER_TEMP/pkg" -type l)" ]; then echo "::error::symlinks in the archive"; exit 1; fi
for f in sd-cli sd-server; do test -x "$RUNNER_TEMP/pkg/$f" || { echo "::error::$f missing"; exit 1; }; done
asset="sd-master-$SHORT-bin-Linux-Ubuntu-$(lsb_release -sr)-x86_64-rocm-$ROCM_VERSION.zip"
(cd "$RUNNER_TEMP/pkg" && zip -X -9 -q -r "$GITHUB_WORKSPACE/$asset" .)
ls -l "$asset" "$RUNNER_TEMP/pkg"
echo "ASSET=$asset" >> "$GITHUB_ENV"
- uses: actions/upload-artifact@v4
with:
name: archive-linux-rocm-x64
path: ${{ env.ASSET }}
if-no-files-found: error
retention-days: 14
# ------------------------------------------------------------------------- Windows x64 (MSVC)
windows-x64:
name: ${{ matrix.id }}
needs: prepare
if: needs.prepare.outputs.windows_x64 != '[]'
runs-on: windows-2022
timeout-minutes: 330
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.prepare.outputs.windows_x64) }}
env:
SHORT: ${{ needs.prepare.outputs.short }}
VARIANT: ${{ matrix.variant }}
steps:
- name: Clone upstream tag
uses: actions/checkout@v4
with:
repository: ${{ env.UPSTREAM_REPO }}
ref: ${{ needs.prepare.outputs.sha }}
submodules: recursive
- name: Clone Atomic build files
uses: actions/checkout@v4
with:
path: _atomic
sparse-checkout: atomic
- name: Apply Atomic patches
shell: bash
run: bash _atomic/atomic/ci/apply-patches.sh
- name: ccache
uses: ggml-org/ccache-action@v1.2.21
with:
key: release-atomic-${{ matrix.id }}
max-size: ${{ startsWith(matrix.variant, 'cuda') && '2G' || '1G' }}
evict-old-files: job
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- name: Install CUDA 12 (upstream's toolkit)
id: cuda12
if: matrix.variant == 'cuda12'
uses: Jimver/cuda-toolkit@v0.2.22
with:
cuda: ${{ env.WIN_CUDA12 }}
method: "network"
sub-packages: '["nvcc", "cudart", "cublas", "cublas_dev", "thrust", "visual_studio_integration"]'
- name: Install CUDA 13
if: matrix.variant == 'cuda13'
shell: pwsh
run: |
& _atomic/atomic/ci/install-cuda-windows.ps1 -Version $env:WIN_CUDA13 -Root "C:\cuda-$env:WIN_CUDA13" -TargetArch x64
- name: Install Vulkan SDK
if: matrix.variant == 'vulkan'
shell: pwsh
run: |
curl.exe -o $env:RUNNER_TEMP/VulkanSDK-Installer.exe -L "https://sdk.lunarg.com/sdk/download/${env:VULKAN_VERSION_WIN}/windows/vulkansdk-windows-X64-${env:VULKAN_VERSION_WIN}.exe"
& "$env:RUNNER_TEMP\VulkanSDK-Installer.exe" --accept-licenses --default-answer --confirm-command install
Add-Content $env:GITHUB_ENV "VULKAN_SDK=C:\VulkanSDK\${env:VULKAN_VERSION_WIN}"
Add-Content $env:GITHUB_PATH "C:\VulkanSDK\${env:VULKAN_VERSION_WIN}\bin"
- name: Activate MSVC
uses: ilammy/msvc-dev-cmd@v1
with:
arch: x64
- name: Install Ninja
run: choco install ninja -y
# Upstream's flags, plus the DLL CRT stated explicitly (sd.cpp's CMake 3.12 floor leaves
# CMP0091 OLD): sd-cli frees buffers stable-diffusion.dll allocated. With SD_CUDA,
# stable-diffusion.dll imports the driver's nvcuda.dll (CUDA::cuda_driver); delay-loading it
# lets the engine start and fall back to the CPU without an NVIDIA driver. The driver API is
# only called on the CUDA backend, which needs the driver anyway.
- name: Build
shell: pwsh
run: |
$common = @('-DGGML_NATIVE=OFF', '-DSD_BUILD_SHARED_LIBS=ON', '-DSD_BUILD_SHARED_GGML_LIB=ON',
'-DGGML_BACKEND_DL=ON', '-DGGML_CPU_ALL_VARIANTS=ON',
'-DCMAKE_C_COMPILER_LAUNCHER=ccache', '-DCMAKE_CXX_COMPILER_LAUNCHER=ccache')
# @(...): a one-element result would otherwise unroll to a string, and splatting a string
# passes it character by character.
$extra = @(switch ($env:VARIANT) {
'vulkan' { '-DSD_VULKAN=ON' }
'cuda12' { '-DSD_CUDA=ON', "-DCMAKE_CUDA_ARCHITECTURES=$env:CUDA_ARCHS_WIN_CUDA12", '-DCMAKE_CUDA_COMPILER_LAUNCHER=ccache',
'-DCMAKE_SHARED_LINKER_FLAGS=/DELAYLOAD:nvcuda.dll delayimp.lib' }
'cuda13' { '-DSD_CUDA=ON', "-DCMAKE_CUDA_ARCHITECTURES=$env:CUDA_ARCHS_WIN_CUDA13_X64", '-DCMAKE_CUDA_FLAGS=-compress-mode=size', '-DCMAKE_CUDA_COMPILER_LAUNCHER=ccache',
'-DCMAKE_SHARED_LINKER_FLAGS=/DELAYLOAD:nvcuda.dll delayimp.lib' }
})
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=cl.exe -DCMAKE_CXX_COMPILER=cl.exe `
'-DCMAKE_CXX_FLAGS=/bigobj' -DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL `
@common @extra
if ($LASTEXITCODE -ne 0) { throw "cmake configure failed" }
cmake --build build -j $env:NUMBER_OF_PROCESSORS
if ($LASTEXITCODE -ne 0) { throw "cmake build failed" }
# win-cuda12 keeps upstream's layout: its CUDA runtime ships in the cudart companion the app
# unpacks beside it. win-cuda13 carries its runtime inside.
- name: Package
shell: pwsh
run: |
$pkg = Join-Path $env:RUNNER_TEMP 'pkg'
$opts = @{ BinDir = 'build\bin'; OutDir = $pkg; VcVars = $env:VS_VCVARS; Arch = 'x64' }
if ($env:VARIANT -eq 'cuda12') { $opts.AllowMissing = @('cudart64_*.dll', 'cublas64_*.dll', 'cublasLt64_*.dll') }
if ($env:VARIANT -eq 'cuda13') { $opts.CudaRoot = $env:CUDA_PATH; $opts.CheckSm = 'sm_86' }
& _atomic/atomic/ci/package-windows.ps1 @opts
$asset = "sd-master-$env:SHORT-bin-win-$env:VARIANT-x64.zip"
7z a -tzip -mx=9 $asset "$pkg\*" | Out-Null
if ($LASTEXITCODE -ne 0) { throw "7z failed" }
Get-Item $asset | Format-List Name, Length
if ($env:VARIANT -eq 'cuda12') {
$dst = Join-Path $env:RUNNER_TEMP 'cudart'
robocopy "${{ steps.cuda12.outputs.CUDA_PATH }}\bin" $dst cudart64_*.dll cublas64_*.dll cublasLt64_*.dll | Out-Null
7z a -tzip cudart-sd-bin-win-cu12-x64.zip "$dst\*" | Out-Null
if ($LASTEXITCODE -ne 0) { throw "7z failed on the cudart companion" }
Get-Item cudart-sd-bin-win-cu12-x64.zip | Format-List Name, Length
}
exit 0
- uses: actions/upload-artifact@v4
with:
name: archive-${{ matrix.id }}
path: |
sd-master-*-bin-win-*-x64.zip
cudart-sd-bin-win-cu12-x64.zip
if-no-files-found: error
retention-days: 14
# Upstream's Windows ROCm job (TheRock wheels). amdhip64 comes with the AMD driver, which no
# runner has, so unresolved imports are reported, not fatal.
windows-rocm-x64:
needs: prepare
if: contains(needs.prepare.outputs.selected, ',win-rocm-x64,')
runs-on: windows-2022
timeout-minutes: 330
env:
SHORT: ${{ needs.prepare.outputs.short }}
steps:
- name: Clone upstream tag
uses: actions/checkout@v4
with:
repository: ${{ env.UPSTREAM_REPO }}
ref: ${{ needs.prepare.outputs.sha }}
submodules: recursive
- name: Clone Atomic build files
uses: actions/checkout@v4
with:
path: _atomic
sparse-checkout: atomic
- name: Apply Atomic patches
shell: bash
run: bash _atomic/atomic/ci/apply-patches.sh
- name: ccache
uses: ggml-org/ccache-action@v1.2.21
with:
key: release-atomic-win-rocm-x64
max-size: 2G
evict-old-files: job
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- name: Cache ROCm installation
id: cache-rocm
uses: actions/cache@v4
with:
path: C:\TheRock\build
key: rocm-wheels-${{ env.ROCM_VERSION }}-${{ runner.os }}
- name: Install ROCm with wheels
if: steps.cache-rocm.outputs.cache-hit != 'true'
run: |
$ErrorActionPreference = "Stop"
New-Item -Path "C:\TheRock\build" -ItemType Directory -Force | Out-Null
python -m venv C:\TheRock\build\.venv
& C:\TheRock\build\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install --index-url https://repo.amd.com/rocm/whl-multi-arch/ "rocm[libraries,devel]==${{ env.ROCM_VERSION }}"
rocm-sdk init
if ($LASTEXITCODE -ne 0) { throw "rocm-sdk init failed with exit code $LASTEXITCODE" }
- name: Setup ROCm environment
run: |
$ErrorActionPreference = "Stop"
& C:\TheRock\build\.venv\Scripts\Activate.ps1
rocm-sdk init
if ($LASTEXITCODE -ne 0) { throw "rocm-sdk init failed with exit code $LASTEXITCODE" }
$rocmPath = (rocm-sdk path --root).Trim()
$cmakePath = (rocm-sdk path --cmake).Trim()
$binPath = (rocm-sdk path --bin).Trim()
echo "HIP_PATH=$rocmPath" >> $env:GITHUB_ENV
echo "CMAKE_PREFIX_PATH=$cmakePath" >> $env:GITHUB_ENV
echo "HIP_DEVICE_LIB_PATH=$rocmPath\lib\llvm\amdgcn\bitcode" >> $env:GITHUB_ENV
echo "HIP_PLATFORM=amd" >> $env:GITHUB_ENV
echo "LLVM_PATH=$rocmPath\lib\llvm" >> $env:GITHUB_ENV
echo "$binPath" >> $env:GITHUB_PATH
echo "C:\TheRock\build\.venv\Scripts" >> $env:GITHUB_PATH
- name: Build
run: |
cmake -S . -B build `
-G "Unix Makefiles" `
-DCMAKE_PREFIX_PATH="${env:HIP_PATH}" `
-DSD_HIPBLAS=ON `
-DSD_BUILD_SHARED_LIBS=ON `
-DGGML_NATIVE=OFF `
-DCMAKE_C_COMPILER="${env:HIP_PATH}\lib\llvm\bin\clang.exe" `
-DCMAKE_CXX_COMPILER="${env:HIP_PATH}\lib\llvm\bin\clang++.exe" `
-DCMAKE_HIP_COMPILER="${env:HIP_PATH}\lib\llvm\bin\clang.exe" `
-DHIP_PATH="${env:HIP_PATH}" `
-DCMAKE_BUILD_TYPE=Release `
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_HIP_COMPILER_LAUNCHER=ccache `
-DGPU_TARGETS="${env:ROCM_TARGETS_WIN}"
if ($LASTEXITCODE -ne 0) { throw "cmake configure failed" }
cmake --build build --config Release --parallel ${env:NUMBER_OF_PROCESSORS}
if ($LASTEXITCODE -ne 0) { throw "cmake build failed" }
- name: Package
shell: pwsh
run: |
$pkg = Join-Path $env:RUNNER_TEMP 'pkg'
& _atomic/atomic/ci/package-windows.ps1 -BinDir build\bin -OutDir $pkg -VcVars $env:VS_VCVARS -Arch x64 -ReportOnly
$asset = "sd-master-$env:SHORT-bin-win-rocm-$env:ROCM_VERSION-x64.zip"
7z a -tzip -mx=9 $asset "$pkg\*" | Out-Null
if ($LASTEXITCODE -ne 0) { throw "7z failed" }
Get-Item $asset | Format-List Name, Length
"ASSET=$asset" | Out-File -Append -Encoding utf8 $env:GITHUB_ENV
- uses: actions/upload-artifact@v4
with:
name: archive-win-rocm-x64
path: ${{ env.ASSET }}
if-no-files-found: error
retention-days: 14
# ---------------------------------------------------------------------- Windows on Arm (arm64)
# ggml-cpu refuses MSVC on ARM, so the tree is built with clang targeting arm64-pc-windows-msvc
# (llama.cpp's toolchain); -march=armv8.7-a covers Snapdragon X and N1X. OpenMP is off: there is
# no arm64 libomp on the x64 host. The DLL CRT is explicit: ggml-cuda.dll (MSVC) shares its heap.
windows-arm64-cpu:
needs: prepare
if: contains(needs.prepare.outputs.selected, ',win-cpu-arm64,')
runs-on: windows-2022
timeout-minutes: 120
env:
SHORT: ${{ needs.prepare.outputs.short }}
steps:
- name: Clone upstream tag
uses: actions/checkout@v4
with:
repository: ${{ env.UPSTREAM_REPO }}
ref: ${{ needs.prepare.outputs.sha }}
submodules: recursive
- name: Clone Atomic build files
uses: actions/checkout@v4
with:
path: _atomic
sparse-checkout: atomic
- name: Apply Atomic patches
shell: bash
run: bash _atomic/atomic/ci/apply-patches.sh
- name: ccache
uses: ggml-org/ccache-action@v1.2.21
with:
key: release-atomic-win-cpu-arm64
max-size: 1G
evict-old-files: job
- uses: actions/setup-node@v4
with:
node-version: 20
- uses: pnpm/action-setup@v4
with:
version: ${{ env.PNPM_VERSION }}
- name: Install Ninja
run: choco install ninja -y
- name: Build
shell: cmd
run: |
call "%VS_VCVARS%" amd64_arm64 || exit /b 1
cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_TOOLCHAIN_FILE=_atomic/atomic/cmake/arm64-windows-llvm.cmake ^
-DGGML_NATIVE=OFF -DGGML_BACKEND_DL=ON -DGGML_CPU_ALL_VARIANTS=OFF -DGGML_OPENMP=OFF ^
-DSD_BUILD_SHARED_LIBS=ON -DSD_BUILD_SHARED_GGML_LIB=ON ^
-DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL ^
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache || exit /b 1
cmake --build build -j %NUMBER_OF_PROCESSORS% || exit /b 1
- name: Package
shell: pwsh
run: |
$pkg = Join-Path $env:RUNNER_TEMP 'pkg'
& _atomic/atomic/ci/package-windows.ps1 -BinDir build\bin -OutDir $pkg -VcVars $env:VS_VCVARS -Arch arm64
$asset = "sd-master-$env:SHORT-bin-win-cpu-arm64.zip"
7z a -tzip -mx=9 $asset "$pkg\*" | Out-Null
if ($LASTEXITCODE -ne 0) { throw "7z failed" }
Get-Item $asset | Format-List Name, Length
"ASSET=$asset" | Out-File -Append -Encoding utf8 $env:GITHUB_ENV
- uses: actions/upload-artifact@v4
with:
name: archive-win-cpu-arm64
path: ${{ env.ASSET }}
if-no-files-found: error
retention-days: 14
- uses: actions/upload-artifact@v4
with:
name: tree-win-cpu-arm64
path: ${{ runner.temp }}/pkg/
if-no-files-found: error
retention-days: 3
# llama.cpp's split: the x64-hosted nvcc and MSVC cross-compile ggml-cuda.dll against NVIDIA's
# arm64 libraries, inside sd.cpp's own CMake tree (sd.cpp compiles ggml with GGML_MAX_NAME=160 and
# a standalone ggml would disagree on the ggml_tensor layout); it is dropped into the clang tree.
# The clang stable-diffusion.dll lacks SD_USE_CUDA: no head padding for d_head < 64 (speed only).
windows-arm64-cuda13:
needs: [prepare, windows-arm64-cpu]
if: contains(needs.prepare.outputs.selected, ',win-cuda13-arm64,')
runs-on: windows-2022
timeout-minutes: 240
env:
SHORT: ${{ needs.prepare.outputs.short }}
steps:
- name: Clone upstream tag
uses: actions/checkout@v4
with:
repository: ${{ env.UPSTREAM_REPO }}
ref: ${{ needs.prepare.outputs.sha }}
submodules: recursive
- name: Clone Atomic build files
uses: actions/checkout@v4
with:
path: _atomic
sparse-checkout: atomic
- name: Apply Atomic patches
shell: bash
run: bash _atomic/atomic/ci/apply-patches.sh
- name: ccache
uses: ggml-org/ccache-action@v1.2.21
with:
key: release-atomic-win-cuda13-arm64
max-size: 2G
evict-old-files: job
- name: Install CUDA (x64 compiler, arm64 target libraries)
shell: pwsh
run: |
& _atomic/atomic/ci/install-cuda-windows.ps1 -Version $env:WIN_CUDA13 -Root "C:\cuda-$env:WIN_CUDA13" -TargetArch arm64
- name: Install Ninja
run: choco install ninja -y
- name: Build ggml-cuda
shell: cmd
run: |
call "%VS_VCVARS%" amd64_arm64 || exit /b 1
cmake -S . -B build-cuda -G Ninja -DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_TOOLCHAIN_FILE=_atomic/atomic/cmake/arm64-windows-msvc-cuda.cmake ^
-DSD_CUDA=ON -DGGML_CPU=OFF -DGGML_NATIVE=OFF -DGGML_BACKEND_DL=ON ^
-DSD_BUILD_SHARED_LIBS=ON -DSD_BUILD_SHARED_GGML_LIB=ON ^
-DSD_BUILD_EXAMPLES=OFF -DSD_SERVER_BUILD_FRONTEND=OFF ^
-DCMAKE_POLICY_DEFAULT_CMP0091=NEW -DCMAKE_MSVC_RUNTIME_LIBRARY=MultiThreadedDLL ^
-DCMAKE_C_COMPILER_LAUNCHER=ccache -DCMAKE_CXX_COMPILER_LAUNCHER=ccache -DCMAKE_CUDA_COMPILER_LAUNCHER=ccache ^
"-DCMAKE_CUDA_ARCHITECTURES=90-virtual;121-real" || exit /b 1
cmake --build build-cuda --target ggml-cuda -j %NUMBER_OF_PROCESSORS% || exit /b 1
- name: Download the clang tree
uses: actions/download-artifact@v4
with:
name: tree-win-cpu-arm64
path: ${{ runner.temp }}/pkg
- name: Package
shell: pwsh
run: |
$pkg = Join-Path $env:RUNNER_TEMP 'pkg'
$dll = Get-ChildItem build-cuda -Recurse -Filter ggml-cuda.dll | Select-Object -First 1
if (-not $dll) { throw "ggml-cuda.dll was not built" }
& _atomic/atomic/ci/package-windows.ps1 -OutDir $pkg -VcVars $env:VS_VCVARS -Arch arm64 `
-CudaDll $dll.FullName -CudaRoot $env:CUDA_PATH -CheckSm 'sm_121'
$asset = "sd-master-$env:SHORT-bin-win-cuda13-arm64.zip"
7z a -tzip -mx=9 $asset "$pkg\*" | Out-Null
if ($LASTEXITCODE -ne 0) { throw "7z failed" }
Get-Item $asset | Format-List Name, Length
"ASSET=$asset" | Out-File -Append -Encoding utf8 $env:GITHUB_ENV
- uses: actions/upload-artifact@v4
with:
name: archive-win-cuda13-arm64
path: ${{ env.ASSET }}
if-no-files-found: error
retention-days: 14
# ------------------------------------------------------------------------------------- Smoke
# On machines without a GPU, every archive (ROCm excepted: no AMD driver anywhere) must start,
# list its devices and generate a real image through sd-server's HTTP API, the way the core
# drives it. Linux runs inside a bare python:3.12-slim container, not on the runner, whose build
# tools would hide a missing runtime library (a GB10 check caught exactly that with libgomp).
smoke-linux:
name: smoke ${{ matrix.id }}
needs: [prepare, linux]
if: always() && needs.prepare.outputs.smoke_linux != '[]' && needs.linux.result == 'success'
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.prepare.outputs.smoke_linux) }}
steps:
- name: Clone Atomic build files
uses: actions/checkout@v4
with:
sparse-checkout: atomic
- uses: actions/download-artifact@v4
with:
name: archive-${{ matrix.id }}
path: dist
- name: Unpack
run: |
mkdir -p "$RUNNER_TEMP/sd"
unzip -q dist/*.zip -d "$RUNNER_TEMP/sd"
ls -l "$RUNNER_TEMP/sd"
# libstable-diffusion.so links libcuda.so.1, which only an NVIDIA driver provides; the
# toolkit's stub stands in: cuInit fails cleanly and the CPU device remains.
- name: libcuda stub
if: matrix.stub_ver != ''
run: |
set -euo pipefail
wget -q "https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2404/${{ matrix.stub_repo }}/cuda-keyring_1.1-1_all.deb"
sudo dpkg -i cuda-keyring_1.1-1_all.deb
sudo apt-get update -y
sudo apt-get install -y "cuda-driver-dev-${{ matrix.stub_ver }}"
mkdir -p "$RUNNER_TEMP/stub"
cp -L "$(find /usr/local/cuda-*/ -path '*stubs/libcuda.so' | head -1)" "$RUNNER_TEMP/stub/libcuda.so.1"
echo "STUB_ARGS=--lib-dir $RUNNER_TEMP/stub" >> "$GITHUB_ENV"
- uses: actions/cache@v4
with:
path: ~/sd-smoke-model
key: sd-smoke-${{ runner.os }}-${{ env.SMOKE_MODEL_SHA256 }}
- name: Smoke (bare container)
run: |
mkdir -p "$HOME/sd-smoke-model"
docker run --rm --user "$(id -u):$(id -g)" -e GITHUB_ACTIONS \
-v "$RUNNER_TEMP:$RUNNER_TEMP" -v "$HOME/sd-smoke-model:$HOME/sd-smoke-model" \
-v "$PWD/atomic:/atomic:ro" python:3.12-slim \
python /atomic/ci/smoke.py --dir "$RUNNER_TEMP/sd" \
--model "$HOME/sd-smoke-model/sd_turbo-f16-q8_0.gguf" \
--model-url "$SMOKE_MODEL_URL" --model-sha256 "$SMOKE_MODEL_SHA256" \
--out "$RUNNER_TEMP/smoke.png" ${STUB_ARGS:-}
- if: always()
uses: actions/upload-artifact@v4
with:
name: smoke-${{ matrix.id }}
path: ${{ runner.temp }}/smoke.png
if-no-files-found: ignore
retention-days: 7
smoke-windows:
name: smoke ${{ matrix.id }}
needs: [prepare, windows-x64, windows-arm64-cpu, windows-arm64-cuda13]
if: >-
always() && needs.prepare.outputs.smoke_windows != '[]' &&
!contains(needs.*.result, 'failure') && !contains(needs.*.result, 'cancelled')
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include: ${{ fromJSON(needs.prepare.outputs.smoke_windows) }}
steps:
- name: Clone Atomic build files
uses: actions/checkout@v4
with:
sparse-checkout: atomic
- uses: actions/setup-python@v5
with:
python-version: "3.12"
architecture: ${{ matrix.py_arch }}
- uses: actions/download-artifact@v4
with:
name: archive-${{ matrix.id }}
path: dist
# Every zip of the artifact goes into one folder, the way the app unpacks win-cuda12 and its
# cudart companion side by side.
- name: Unpack and check PE machine types
shell: pwsh
run: |
$dir = Join-Path $env:RUNNER_TEMP 'sd'
foreach ($zip in Get-ChildItem dist\*.zip) { Expand-Archive $zip.FullName $dir -Force }
& atomic/ci/check-pe.ps1 -Dir $dir -Machine ${{ matrix.py_arch }}
- uses: actions/cache@v4
with:
path: ~/sd-smoke-model
key: sd-smoke-${{ runner.os }}-${{ matrix.py_arch }}-${{ env.SMOKE_MODEL_SHA256 }}
# No NVIDIA driver: ggml-cuda.dll fails to load (no nvcuda.dll) and the CPU device remains,
# which is what a machine without NVIDIA sees.
- name: Smoke
shell: pwsh
run: |
python atomic/ci/smoke.py --dir (Join-Path $env:RUNNER_TEMP 'sd') `
--model (Join-Path $HOME 'sd-smoke-model\sd_turbo-f16-q8_0.gguf') `
--model-url $env:SMOKE_MODEL_URL --model-sha256 $env:SMOKE_MODEL_SHA256 `
--out (Join-Path $env:RUNNER_TEMP 'smoke.png')
if ($LASTEXITCODE -ne 0) { exit $LASTEXITCODE }
- if: always()
uses: actions/upload-artifact@v4
with:
name: smoke-${{ matrix.id }}
path: ${{ runner.temp }}/smoke.png
if-no-files-found: ignore
retention-days: 7
smoke-macos:
needs: [prepare, macos-arm64]
if: always() && needs.macos-arm64.result == 'success'
runs-on: macos-latest
timeout-minutes: 60
steps:
- name: Clone Atomic build files
uses: actions/checkout@v4
with:
sparse-checkout: atomic
- uses: actions/download-artifact@v4
with:
name: archive-macos-arm64
path: dist
- name: Unpack
run: |
mkdir -p "$RUNNER_TEMP/sd"
unzip -q dist/*.zip -d "$RUNNER_TEMP/sd"
ls -l "$RUNNER_TEMP/sd"
- uses: actions/cache@v4