Skip to content

Commit 7d5ae9a

Browse files
fix: cuda: create valid bottles (#303)
* fix: cuda: create valid bottles * cuda@12.9: update 12.9.1_1 bottle. * cuda@13.0: update 13.0.2_1 bottle. * cuda@13.1: update 13.1.1_1 bottle. * cuda@13.2: update 13.2.1_1 bottle. --------- Co-authored-by: LizardByte-bot <108553330+LizardByte-bot@users.noreply.github.com>
1 parent 1b92934 commit 7d5ae9a

7 files changed

Lines changed: 100 additions & 18 deletions

File tree

.github/workflows/tests.yml

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ jobs:
2525
platforms: ${{ steps.detect.outputs.platforms }}
2626
has-formulae: ${{ steps.detect.outputs.has-formulae }}
2727
changed-files: ${{ steps.detect.outputs.changed-files }}
28+
testing-formulae: ${{ steps.detect.outputs.testing-formulae }}
2829
disable-failfast: ${{ steps.detect.outputs.disable-failfast }}
2930
steps:
3031
- name: Set up Homebrew
@@ -121,6 +122,7 @@ jobs:
121122
echo "has-formulae=false"
122123
echo "platforms=[]"
123124
echo "changed-files="
125+
echo "testing-formulae="
124126
} >> "${GITHUB_OUTPUT}"
125127
exit 0
126128
fi
@@ -136,6 +138,10 @@ jobs:
136138
echo "EOF"
137139
} >> "${GITHUB_OUTPUT}"
138140
141+
TESTING_FORMULAE=$(echo "${CHANGED_FILES}" | sed '/^$/d; s|.*/||; s|\.rb$||' | paste -sd, -)
142+
echo "Formula names to test: ${TESTING_FORMULAE}"
143+
echo "testing-formulae=${TESTING_FORMULAE}" >> "${GITHUB_OUTPUT}"
144+
139145
# Check if any changed formula is in the failfast skiplist
140146
DISABLE_FAILFAST=false
141147
SKIPLIST_FILE="${TAP_PATH}/ci_config/failfast_skiplist.json"
@@ -385,7 +391,19 @@ jobs:
385391
if: github.event_name == 'pull_request'
386392
env:
387393
HOMEBREW_DOCKER_REGISTRY_TOKEN: ${{ steps.base64-encode.outputs.token }}
388-
run: brew test-bot --fail-fast --only-formulae --root-url=https://ghcr.io/v2/lizardbyte/homebrew
394+
TESTING_FORMULAE: ${{ needs.setup.outputs.testing-formulae }}
395+
run: |
396+
test_bot_args=(
397+
--fail-fast
398+
--only-formulae
399+
--root-url=https://ghcr.io/v2/lizardbyte/homebrew
400+
)
401+
402+
if [ -n "${TESTING_FORMULAE}" ]; then
403+
test_bot_args+=("--testing-formulae=${TESTING_FORMULAE}")
404+
fi
405+
406+
brew test-bot "${test_bot_args[@]}"
389407
390408
- name: Upload bottles as artifact
391409
if: always() && github.event_name == 'pull_request'

Formula/c/cuda@12.9.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class CudaAT129 < Formula
1111
INTEL_SHA256 = "0f6d806ddd87230d2adbe8a6006a9d20144fdbda9de2d6acc677daa5d036417a".freeze
1212
ARM_SHA256 = "64f47ab791a76b6889702425e0755385f5fa216c5a9f061875c7deed5f08cdb6".freeze
1313

14+
revision 1
15+
1416
# Set up version-specific livecheck
1517
CudaFormula.setup_livecheck(self)
1618

@@ -24,6 +26,7 @@ class CudaAT129 < Formula
2426

2527
bottle do
2628
root_url "https://ghcr.io/v2/lizardbyte/homebrew"
27-
sha256 cellar: :any_skip_relocation, x86_64_linux: "8dec532464bca7a342fe8a72d0aae08ce6163d15ebd32137d0037c08eff89e60"
29+
sha256 cellar: :any, arm64_linux: "9f427fcb4bcd3e5eb2736b502287474ebbfe2988bf0b9c92bfba615febad8db5"
30+
sha256 cellar: :any, x86_64_linux: "10763e20564695a9dbb6573d45a4e9671e68c6cffeaa9fb0cfca0e67575fbf6d"
2831
end
2932
end

Formula/c/cuda@13.0.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class CudaAT130 < Formula
1111
INTEL_SHA256 = "81a5d0d0870ba2022efb0a531dcc60adbdc2bbff7b3ef19d6fd6d8105406c775".freeze
1212
ARM_SHA256 = "93ab4c77ae2bc0f1f600ef48ccd3ff25a3203a6a6161a84511a33cbf5b5621fc".freeze
1313

14+
revision 1
15+
1416
# Set up version-specific livecheck
1517
CudaFormula.setup_livecheck(self)
1618

@@ -24,6 +26,7 @@ class CudaAT130 < Formula
2426

2527
bottle do
2628
root_url "https://ghcr.io/v2/lizardbyte/homebrew"
27-
sha256 cellar: :any_skip_relocation, x86_64_linux: "99bdba97c1abdd7f83a90c6f383766c6cd6e9ac22c5da12806164929c96669cf"
29+
sha256 cellar: :any, arm64_linux: "99ed824a06e23a53939d36ea1cb2dc8ce6e84c832d7f351d4703ce49cee38317"
30+
sha256 cellar: :any, x86_64_linux: "c18b139fcc9127bd657c5addf5dc876fc6dc1957e105426aa32c5c13fc96abcc"
2831
end
2932
end

Formula/c/cuda@13.1.rb

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class CudaAT131 < Formula
1111
INTEL_SHA256 = "24ff323723722781436804b392a48f691cb40de9808095d3e2192d0db6dfb8e4".freeze
1212
ARM_SHA256 = "8adcd5d4b3e1e70f7420959b97514c0c97ec729da248d54902174c4d229bfd2c".freeze
1313

14+
revision 1
15+
1416
# Set up version-specific livecheck
1517
CudaFormula.setup_livecheck(self)
1618

@@ -24,6 +26,7 @@ class CudaAT131 < Formula
2426

2527
bottle do
2628
root_url "https://ghcr.io/v2/lizardbyte/homebrew"
27-
sha256 cellar: :any_skip_relocation, x86_64_linux: "0b78c36d6ccb5cb9f52d0d3aeb553ed7eed444595756a5d71d24bfd6a7ce1b48"
29+
sha256 cellar: :any, arm64_linux: "e4810b4ed3b724056898248f3a276d4fd90ab08d45d7232019d85fefc72b867f"
30+
sha256 cellar: :any, x86_64_linux: "3d9f716aaf64a96a8b68ca53bd6bf860aad7f05b9571e678406e4a88ec29a378"
2831
end
2932
end

Formula/c/cuda@13.2.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@ class CudaAT132 < Formula
1111
INTEL_SHA256 = "5514a3fe7bcea92b25073c7c100c3e64e7961a7e1dbad6955adb8b59806053f0".freeze
1212
ARM_SHA256 = "38560e0c48eba793c883ea1ada6ad4c37b744cb5284034d16fd7ee57f95dda04".freeze
1313

14+
revision 1
15+
1416
# Set up version-specific livecheck
1517
CudaFormula.setup_livecheck(self)
1618

@@ -24,7 +26,7 @@ class CudaAT132 < Formula
2426

2527
bottle do
2628
root_url "https://ghcr.io/v2/lizardbyte/homebrew"
27-
sha256 cellar: :any_skip_relocation, arm64_linux: "e8c8578bee5c2512fec6642822222a55f658b8c68a7d580e52a492a1952bc1cd"
28-
sha256 cellar: :any_skip_relocation, x86_64_linux: "d88eb646e3d856b5e60ae68400faa762e4aeb844e56d4e30934e427d69cb9c85"
29+
sha256 cellar: :any, arm64_linux: "22fb1befa9a6e7357f21df0258e790d508ee0ff86638e6205915cd65a635b33d"
30+
sha256 cellar: :any, x86_64_linux: "a11ab7d98090e2bb46536db09ca874c8fc861d597d24cf002d60a8ec3e072145"
2931
end
3032
end

ci_config/failfast_skiplist.json

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,4 @@
11
{
22
"formulas": [
3-
"cuda@12.9",
4-
"cuda@13.0",
5-
"cuda@13.1"
63
]
74
}

lib/cuda_formula.rb

Lines changed: 65 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
module CudaFormula
66
def self.included(base)
77
base.class_eval do
8+
depends_on "patchelf" => :build
89
depends_on "cmake" => :test
910
depends_on :linux
11+
keg_only :versioned_formula
1012

1113
# Default livecheck - will be overridden by setup_livecheck if CUDA_VERSION is defined
1214
livecheck do
@@ -55,22 +57,73 @@ def install
5557
"--toolkit",
5658
"--toolkitpath=#{libexec}"
5759

60+
prune_nonportable_payload
61+
patch_elf_rpaths
62+
5863
# NOTE: We do not symlink lib64 or include to avoid conflicts and hacks
5964
# Dependent formulae should use CMAKE_CUDA_TOOLKIT_ROOT_DIR=#{libexec}
6065
# or set CUDA_HOME=#{libexec} to find libraries and headers
6166

67+
library_paths = [
68+
"#{libexec}/lib64",
69+
*Dir[libexec/"extras/CUPTI/lib64"].map(&:to_s),
70+
*Dir[libexec/"targets/*/lib"].map(&:to_s),
71+
].uniq
72+
6273
# Create wrapper scripts for CUDA binaries
6374
# This ensures they can find cuda_runtime.h, nvcc.profile, and other dependencies
75+
wrapper_bin = libexec/"homebrew/bin"
76+
wrapper_bin.mkpath
77+
6478
Dir[libexec/"bin/*"].select { |f| File.file?(f) && File.executable?(f) }.each do |exe|
6579
binary_name = File.basename(exe)
66-
(bin/binary_name).write <<~EOS
80+
(wrapper_bin/binary_name).write <<~EOS
6781
#!/bin/bash
6882
export CUDA_HOME="#{libexec}"
6983
export PATH="#{libexec}/bin:$PATH"
70-
export LD_LIBRARY_PATH="#{libexec}/lib64:$LD_LIBRARY_PATH"
84+
export LD_LIBRARY_PATH="#{library_paths.join(":")}:$LD_LIBRARY_PATH"
7185
exec "#{libexec}/bin/#{binary_name}" "$@"
7286
EOS
73-
chmod 0755, bin/binary_name
87+
chmod 0755, wrapper_bin/binary_name
88+
end
89+
end
90+
91+
def prune_nonportable_payload
92+
# These bundled GUI/profiler/debugger/GDS tools link host libraries that
93+
# Homebrew cannot validate as portable bottle dependencies.
94+
FileUtils.rm_rf(Dir[libexec/"nsight-compute-*"])
95+
FileUtils.rm_rf(Dir[libexec/"nsight-systems-*"])
96+
FileUtils.rm_rf(libexec/"extras/demo_suite")
97+
FileUtils.rm_rf(libexec/"gds")
98+
FileUtils.rm_rf(libexec/"libnvvp")
99+
100+
FileUtils.rm_f(Dir[libexec/"bin/{ctadvisor,cuda-gdb*,cuda-uninstaller,ncu,ncu-ui,nsight*,nsys,nsys-ui}"])
101+
FileUtils.rm_f(Dir[libexec/"bin/{nvprof,nvvp}"])
102+
FileUtils.rm_f(Dir[libexec/"pkgconfig/cuobjclient-*.pc"])
103+
FileUtils.rm_f(Dir[libexec/"targets/*/lib/lib{acc,cu}inj64*"])
104+
FileUtils.rm_f(Dir[libexec/"targets/*/lib/libcufile_rdma*"])
105+
FileUtils.rm_f(Dir[libexec/"targets/*/lib/libcuobjclient*"])
106+
end
107+
108+
def patch_elf_rpaths
109+
library_roots = [
110+
libexec/"lib64",
111+
libexec/"extras/CUPTI/lib64",
112+
*Dir[libexec/"targets/*/lib"].map { |path| Pathname.new(path) },
113+
].select(&:directory?)
114+
115+
Dir[libexec/"**/*"].map { |path| Pathname.new(path) }.select(&:file?).each do |file|
116+
next unless File.open(file, "rb") { |f| f.read(4) == "\x7FELF".b }
117+
118+
file_dir = file.dirname
119+
rpaths = library_roots.filter_map do |root|
120+
relative_path = root.relative_path_from(file_dir).to_s
121+
next "$ORIGIN" if relative_path == "."
122+
123+
"$ORIGIN/#{relative_path}"
124+
end
125+
126+
system "patchelf", "--set-rpath", rpaths.unshift("$ORIGIN").uniq.join(":"), file
74127
end
75128
end
76129

@@ -80,18 +133,18 @@ def caveats
80133
#{opt_libexec}
81134
82135
Wrapper scripts for CUDA binaries are available at:
83-
#{opt_bin}/nvcc
136+
#{opt_libexec}/homebrew/bin/nvcc
84137
85138
These wrappers automatically set CUDA_HOME for you.
86139
87140
For CMake projects (sunshine-beta example):
88141
cuda_path = Formula["lizardbyte/homebrew/cuda@13.1"]
89-
args << "-DCMAKE_CUDA_COMPILER=\#{cuda_path.opt_bin}/nvcc"
142+
args << "-DCMAKE_CUDA_COMPILER=\#{cuda_path.opt_libexec}/homebrew/bin/nvcc"
90143
args << "-DCMAKE_CUDA_TOOLKIT_ROOT_DIR=\#{cuda_path.opt_libexec}"
91144
92145
For shell/manual configuration:
93146
export CUDA_HOME=#{opt_libexec}
94-
export PATH=#{opt_bin}:$PATH
147+
export PATH=#{opt_libexec}/homebrew/bin:$PATH
95148
export LD_LIBRARY_PATH=#{opt_libexec}/lib64:$LD_LIBRARY_PATH
96149
97150
This formula only installs the CUDA Toolkit (compiler and libraries).
@@ -103,8 +156,11 @@ def caveats
103156
end
104157

105158
def test
159+
cuda_nvcc = libexec/"homebrew/bin/nvcc"
160+
106161
# Test that nvcc is available and can report its version
107-
assert_match version.to_s, shell_output("#{bin}/nvcc --version")
162+
cuda_release = version.to_s[/^\d+\.\d+/]
163+
assert_match "release #{cuda_release}", shell_output("#{cuda_nvcc} --version")
108164

109165
# Test compiling a simple CUDA program
110166
(testpath/"test.cu").write <<~EOS
@@ -121,7 +177,7 @@ def test
121177
EOS
122178

123179
# Compile the test program
124-
system bin/"nvcc", "test.cu", "-o", "test"
180+
system cuda_nvcc, "test.cu", "-o", "test"
125181
assert_path_exists testpath/"test"
126182

127183
# Test that CMake can find the CUDA toolkit
@@ -139,7 +195,7 @@ def test
139195
# Try to configure the CMake project
140196
# This will fail if CMake cannot find a working CUDA compiler
141197
system "cmake", "-S", testpath, "-B", testpath/"build",
142-
"-DCMAKE_CUDA_COMPILER=#{bin}/nvcc"
198+
"-DCMAKE_CUDA_COMPILER=#{cuda_nvcc}"
143199

144200
# Verify CMake found the CUDA toolkit
145201
assert_path_exists testpath/"build/CMakeCache.txt"

0 commit comments

Comments
 (0)