Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,16 @@ jobs:
include:
- os: ubuntu-latest
cuda-version: "12.9"
cross-arch: "armv8" # test x86_64 -> arm64 cross-building, in addition to native
run-cross-test: false # the x86_64 runner cannot execute arm64 binaries
- os: ubuntu-latest
cuda-version: "13.0"
- os: ubuntu-latest
cuda-version: "13.2"
- os: ubuntu-24.04-arm
cuda-version: "13.2"
- os: ubuntu-latest
cuda-version: "13.3"
- os: ubuntu-24.04-arm
cuda-version: "13.2"
- os: ubuntu-24.04-arm
cuda-version: "13.3"
# Windows:
Expand All @@ -36,12 +38,11 @@ jobs:
- os: windows-latest
cuda-version: "13.3"
# 13.4.0-preview developer preview: Windows x86_64 and arm64
- os: windows-latest
cuda-version: "13.4"
cross-arch: "armv8" # test x86_64 -> arm64 cross-building, in addition to native
- os: windows-11-arm
cuda-version: "13.4"
cross-arch: "x86_64" # test arm64 -> x86_64 cross-building, in addition to native
run-cross-test: true # Windows arm64 can execute x86_64 binaries
package-ref: "cuda-toolkit/13.4.0-preview"

runs-on: ${{ matrix.os }}

Expand All @@ -63,13 +64,15 @@ jobs:
- name: conan create cuda-toolkit
run: conan create recipes/cuda-toolkit/${{ matrix.cuda-version }} && conan cache clean "*"

# test_package is skipped here: it is only built when a host compiler able to
# target ${{ matrix.cross-arch }} is available, in the dedicated step below
- name: conan create cuda-toolkit (cross-building for ${{ matrix.cross-arch }})
if: matrix.cross-arch != ''
run: conan create recipes/cuda-toolkit/${{ matrix.cuda-version }} -s arch=${{ matrix.cross-arch }} && conan cache clean "*"
run: conan create recipes/cuda-toolkit/${{ matrix.cuda-version }} -s arch=${{ matrix.cross-arch }} --test-folder="" && conan cache clean "*"

- name: conan test cuda-toolkit (cross-building for ${{ matrix.cross-arch }})
if: matrix.cross-arch != ''
run: conan test recipes/cuda-toolkit/${{ matrix.cuda-version }}/test_package cuda-toolkit/13.4.0-preview -s arch=${{ matrix.cross-arch }} -c tools.cmake.cmaketoolchain:generator=Ninja
if: matrix.run-cross-test
run: conan test recipes/cuda-toolkit/${{ matrix.cuda-version }}/test_package ${{ matrix.package-ref }} -s arch=${{ matrix.cross-arch }} -c tools.cmake.cmaketoolchain:generator=Ninja

- name: build cuda-samples
if: (matrix.cuda-version == '13.2' || (matrix.cuda-version == '13.4' && startsWith(matrix.os, 'windows')))
Expand Down
51 changes: 43 additions & 8 deletions recipes/cuda-toolkit/12.9/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@

from conan import ConanFile
from conan.errors import ConanInvalidConfiguration
from conan.tools.files import copy, download, get, load, rename
from conan.tools.files import copy, download, get, load, rename, replace_in_file

class CudaToolkitConan(ConanFile):
name = "cuda-toolkit"
Expand All @@ -15,13 +15,39 @@ class CudaToolkitConan(ConanFile):
homepage = "https://developer.nvidia.com/cuda-toolkit"
description = "A development environment for creating high performance GPU-accelerated applications"
settings = "os", "arch", "compiler", "build_type"
options = {
# Linux armv8 only: SBSA (Arm servers) vs Jetson/Tegra (linux-aarch64)
"arm_target": ["sbsa", "jetson"],
}
default_options = {
"arm_target": "sbsa",
}

def config_options(self):
if self.settings.os != "Linux" or self.settings.arch != "armv8":
del self.options.arm_target

def validate(self):
if self.settings.os not in ["Windows", "Linux"]:
raise ConanInvalidConfiguration("Operating system not supported")


# CUDA 12.9 redistributables: linux-x86_64, linux-sbsa, linux-aarch64, windows-x86_64
supported_archs = ["x86_64", "armv8"] if self.settings.os == "Linux" else ["x86_64"]
if self.settings.arch not in supported_archs:
raise ConanInvalidConfiguration(f"{self.settings.arch} is not supported on {self.settings.os}")

# TODO: Add checks for supported compilers as per https://docs.nvidia.com/cuda/cuda-installation-guide-linux/index.html#id56

def _cuda_platform(self):
if self.settings.os == "Linux" and self.settings.arch == "armv8":
return "linux-aarch64" if self.options.arm_target == "jetson" else "linux-sbsa"
return f"{str(self.settings.os).lower()}-{self.settings.arch}"

def _targets_arch(self):
if self.settings.os == "Linux" and self.settings.arch == "armv8":
return "aarch64" if self.options.arm_target == "jetson" else "sbsa"
return str(self.settings.arch)

def build(self):
base_url = "https://developer.download.nvidia.com/compute/cuda/redist"
distrib = f"redistrib_{self.version}.json"
Expand All @@ -30,8 +56,7 @@ def build(self):
json_content = load(self, distrib)
cuda_distrib = json.loads(json_content)

arch = "x86_64"
cuda_platform = f"{str(self.settings.os).lower()}-{arch}"
cuda_platform = self._cuda_platform()
self.output.info(f"About to download CUDA toolkit components for {cuda_platform}")

components = [
Expand All @@ -58,7 +83,8 @@ def build(self):

platform_components = {
"linux-x86_64": ["libcufile", "cuda_sandbox_dev", "cuda_opencl"],
"linux-aarch64": ["libcufile", "cuda_compat", "libcudla",],
"linux-sbsa": ["libcufile"],
"linux-aarch64": ["libcufile", "cuda_compat", "libcudla"],
"windows-x86_64": ["cuda_opencl", "visual_studio_integration"],
}
components += platform_components.get(cuda_platform, [])
Expand All @@ -75,14 +101,20 @@ def build(self):
get(self, url, sha256=checksum, destination="cuda", strip_root=True, keep_permissions=False)
rename(self, f"{self.build_folder}/cuda/LICENSE", f"LICENSE_{component_name}")

if self.settings.os == "Linux":
# When crossbuilding, point nvcc to the target directory in the "host" package (for the target architecture),
# rather than have it look relative to itself (which is the current architecture of the build machine)
replace_in_file(self, "cuda/bin/nvcc.profile", '$(TOP)/$(_TARGET_DIR_)/', '$(CONAN_CUDA_TARGET_DIR)/')
replace_in_file(self, "cuda/bin/nvcc.profile", "lib$(_TARGET_SIZE_)", "lib" )

def package(self):
copy(self, "LICENSE*", src=self.build_folder, dst=os.path.join(self.package_folder, "licenses"))

for folder in ["bin", "nvml", "nvvm", "compat"]:
copy(self, "*", src=os.path.join(self.build_folder, "cuda", folder), dst=os.path.join(self.package_folder, folder))

if self.settings.os == "Linux" and not self.settings_target:
arch = "x86_64"
if self.settings.os == "Linux":
arch = self._targets_arch()
targets_folder = f"targets/{arch}-linux"
copy(self, "*", src=os.path.join(self.build_folder, "cuda", "lib"), dst=os.path.join(self.package_folder, targets_folder, "lib"))
copy(self, "*", src=os.path.join(self.build_folder, "cuda", "include"), dst=os.path.join(self.package_folder, targets_folder, "include"))
Expand All @@ -105,7 +137,7 @@ def package(self):
dst=os.path.join(self.package_folder, "extras", "visual_studio_integration") )

def package_id(self):
# only os and arch matter for this package
# only os, arch, and arm_target (when set) matter for this package
self.info.settings.rm_safe("compiler")
self.info.settings.rm_safe("build_type")

Expand All @@ -118,7 +150,10 @@ def package_info(self):
self.buildenv_info.define_path("CUDACXX", os.path.join(self.package_folder, "bin", nvcc))

if not self.settings_target:
arch = self._targets_arch() if self.settings.os == "Linux" else str(self.settings.arch)
self.buildenv_info.define_path("CUDAToolkit_ROOT", self.package_folder)
if self.settings.os == "Linux":
self.buildenv_info.define_path("CONAN_CUDA_TARGET_DIR", os.path.join(self.package_folder, "targets", f"{arch}-linux"))

if self.settings.os == "Linux":
self.cpp_info.libdirs = ["lib64"]
Expand Down