diff --git a/.gitignore b/.gitignore index 15d329f5c..1e8a54b93 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .cache build*/ *.pyc +CMakeUserPresets.json \ No newline at end of file diff --git a/README.md b/README.md index 0fd2716d9..576cb8c31 100644 --- a/README.md +++ b/README.md @@ -133,6 +133,32 @@ system. With the package installed you can use ``find_package`` as follows: find_package(matx CONFIG REQUIRED) ``` +#### 3. MatX via Conan +MatX includes a local Conan package recipe in the repository root with a package name of ``matx`` and a package version placeholder ```` (for example ``1.0.0``). +Because this recipe is local to the MatX repository, the repository must be cloned and the Conan package created locally before a consumer +project can require it. + +From the root of the MatX repository run: + +```sh +conan create . +``` + +That command publishes ``matx/`` to your local Conan cache. A consumer project can then use: + +```python +self.requires("matx/") # e.g. "matx/1.0.0" +``` + +and still rely on CMake to find MatX with: + +```cmake +find_package(matx CONFIG REQUIRED) +target_link_libraries(MyProject PRIVATE matx::matx) +``` + +The ``test_package/`` directory contains a sample consumer CMake project and Conan test recipe showing how to build and run an application against the locally-created MatX Conan package. + #### MatX CMake Targets **Once either of the two methods above are done**, you can use the transitive target ``matx::matx`` in your library inside of ``target_link_libraries``, e.g: diff --git a/conanfile.py b/conanfile.py new file mode 100644 index 000000000..dec6df159 --- /dev/null +++ b/conanfile.py @@ -0,0 +1,50 @@ +from conan import ConanFile +from conan.tools.cmake import CMake + +class MatxConan(ConanFile): + """ + MatX Conan recipe for GPU-accelerated numerical computing. + + NOTE: Network Dependency During Package Creation + ================================================== + During 'conan create .', the package() method runs CMake's configure phase, which + automatically fetches CCCL (CUDA C++ Core Libraries) from GitHub via CPM. This means + internet access is required for packaging, even in offline scenarios. + + For offline/air-gapped deployments: + 1. On an internet-enabled system, export CPM_SOURCE_CACHE and run 'conan create .' + 2. Transfer the populated CPM cache to the offline system + 3. Set CPM_SOURCE_CACHE before using the offline package + + See the build documentation for detailed offline deployment instructions. + """ + name = "matx" + version = "1.0.0" + license = "BSD 3-Clause License" + homepage = "https://github.com/NVIDIA/MatX/" + topics = ("hpc", "gpu", "cuda", "gpgpu", "gpu-computing") + + package_type = "header-library" + no_copy_source = True + description = ( + "MatX is a modern C++ library for numerical computing on NVIDIA GPUs and CPUs. " + "Near-native performance can be achieved while using a simple syntax common in higher-level languages such as Python or MATLAB." + ) + + settings = "os", "compiler", "build_type", "arch" + exports_sources = "CMakeLists.txt", "include/*", "cmake/*", "public/*", "LICENSE" + + generators = "CMakeToolchain" + + def package(self): + cmake = CMake(self) + cmake.configure() + cmake.install() + + def package_info(self): + self.cpp_info.set_property("cmake_target_name", "matx::matx") + self.cpp_info.set_property("cmake_find_mode", "none") + self.cpp_info.builddirs = ["lib/cmake/matx"] + self.cpp_info.includedirs = ["include"] + self.cpp_info.bindirs = [] + self.cpp_info.libdirs = [] diff --git a/docs_input/build.rst b/docs_input/build.rst index e55cb9865..cb3239761 100644 --- a/docs_input/build.rst +++ b/docs_input/build.rst @@ -16,6 +16,40 @@ from the internet. Alternatively, the option ``CPM_USE_LOCAL_PACKAGES`` can be u or offline environment. Choosing local versions of packages uses the typical ``find_packages`` CMake search methods. Please see the CPM documentation or the documentation for each package for more information. +Conan Package Support +--------------------- +MatX also includes a local Conan package recipe at the repository root. To use MatX from a consumer project via Conan, clone the +MatX repository and create the package locally from the repository root: + +.. code-block:: shell + + conan create . + +That command registers the local ``matx/`` package in your Conan cache. Because the package recipe is part of the MatX repository, +this package must be created locally before a consumer project can require it. + +A consumer project can then require MatX in its Conan recipe and use CMake to locate the package: + +.. code-block:: python + + self.requires("matx/") # e.g. "matx/1.0.0" + +.. code-block:: cmake + + find_package(matx CONFIG REQUIRED) + target_link_libraries(MyProject PRIVATE matx::matx) + +The example project in ``test_package/`` demonstrates a Conan test package that builds a sample CMake application using ``CMakeDeps`` and +``VirtualRunEnv`` and links against the locally-created MatX Conan package. + +.. note:: Network Dependency During Conan Create + + During ``conan create .``, the package recipe's ``package()`` method runs CMake's configure phase, + which automatically fetches CCCL (CUDA C++ Core Libraries) from GitHub via CPM. This means **internet + access is required** even when using Conan for offline or air-gapped environments. + + For offline deployments, pre-populate the CPM cache on an internet-enabled system before transferring + to the offline environment (see :ref:`Conan in Offline Environments` below). System Requirements ------------------- @@ -378,3 +412,58 @@ and building on the offline system. - Build your MatX project per your standard process, CPM will automatically use the cache + +.. _conan-offline: + +Conan in Offline Environments +============================== + +When using Conan to deploy MatX in offline or air-gapped environments, follow these steps to pre-cache dependencies: + +**On an internet-enabled system:** + +1. Clone the MatX repository and prepare the CPM cache as described in the previous section + +2. Create the MatX Conan package with the pre-populated cache: + + .. code-block:: shell + + export CPM_SOURCE_CACHE=$HOME_ONLINE/matx_cpm_cache + conan create . + + This ensures CCCL and other dependencies are cached during the package creation process. + +3. Export the Conan package to a portable format for transfer: + + .. code-block:: shell + + conan cache clean "*" --build=missing + # Optionally, package the Conan cache directory + tar -czvf matx_conan_cache.tar.gz ~/.conan2/p/ + +4. Transfer both the CPM cache and Conan cache to your offline system: + + .. code-block:: shell + + tar -czvf matx_offline_package.tar.gz $HOME_ONLINE/matx_cpm_cache matx_conan_cache.tar.gz MatX/ + +**On the offline system:** + +1. Extract both caches: + + .. code-block:: shell + + tar -xzvf matx_offline_package.tar.gz -C $HOME_OFFLINE/ + +2. Set environment variables before using Conan: + + .. code-block:: shell + + export CPM_SOURCE_CACHE=$HOME_OFFLINE/matx_cpm_cache + export CONAN_USER_HOME=$HOME_OFFLINE/.conan2 + +3. Your consumer project can now require MatX without network access: + + .. code-block:: shell + + conan install . --lockfile-partial diff --git a/test_package/CMakeLists.txt b/test_package/CMakeLists.txt new file mode 100644 index 000000000..a23b7eea7 --- /dev/null +++ b/test_package/CMakeLists.txt @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.25.2) + +if(NOT DEFINED CMAKE_CUDA_ARCHITECTURES) + set(CMAKE_CUDA_ARCHITECTURES "native") + message(STATUS "Using native GPU architecture since CMAKE_CUDA_ARCHITECTURES not defined") +endif() + +project(test_package LANGUAGES CXX CUDA) + +find_package(matx CONFIG REQUIRED) + +add_executable(${PROJECT_NAME} test_package.cu) + +target_link_libraries(${PROJECT_NAME} PRIVATE matx::matx) diff --git a/test_package/conanfile.py b/test_package/conanfile.py new file mode 100644 index 000000000..3fcff950e --- /dev/null +++ b/test_package/conanfile.py @@ -0,0 +1,30 @@ +import os + +from conan import ConanFile +from conan.tools.build import can_run +from conan.tools.cmake import CMake, CMakeToolchain, cmake_layout + +class TestPackageConan(ConanFile): + settings = "os", "compiler", "build_type", "arch" + generators = "CMakeDeps", "VirtualRunEnv" + test_type = "explicit" + + def requirements(self): + self.requires(self.tested_reference_str) + + def layout(self): + cmake_layout(self) + + def generate(self): + tc = CMakeToolchain(self) + tc.generate() + + def build(self): + cmake = CMake(self) + cmake.configure() + cmake.build() + + def test(self): + if can_run(self): + bin_path = os.path.join(self.cpp.build.bindirs[0], "test_package") + self.run(bin_path, env="conanrun") diff --git a/test_package/test_package.cu b/test_package/test_package.cu new file mode 100644 index 000000000..2676b358f --- /dev/null +++ b/test_package/test_package.cu @@ -0,0 +1,15 @@ +#include "matx.h" + +#include +#include +#include + +int main([[maybe_unused]] int argc, [[maybe_unused]] char **argv) +{ + auto a = matx::make_tensor({10}); + a.SetVals({1, 2, 3, 4, 5, 6, 7, 8, 9, 10}); + + matx::print(a); + + return 0; +}