mirror of
https://github.com/ROCm/ROCm.git
synced 2026-01-08 22:28:06 -05:00
408 lines
17 KiB
ReStructuredText
408 lines
17 KiB
ReStructuredText
.. meta::
|
|
:description: Using CMake
|
|
:keywords: CMake, dependencies, HIP, C++, AMD, ROCm
|
|
|
|
*********************************
|
|
Using CMake
|
|
*********************************
|
|
|
|
Most components in ROCm support CMake. Projects depending on header-only or
|
|
library components typically require CMake 3.5 or higher whereas those wanting
|
|
to make use of the CMake HIP language support will require CMake 3.21 or higher.
|
|
|
|
Finding dependencies
|
|
====================
|
|
|
|
.. note::
|
|
|
|
For a complete
|
|
reference on how to deal with dependencies in CMake, refer to the CMake docs
|
|
on `find_package
|
|
<https://cmake.org/cmake/help/latest/command/find_package.html>`_ and the
|
|
`Using Dependencies Guide
|
|
<https://cmake.org/cmake/help/latest/guide/using-dependencies/index.html>`_
|
|
to get an overview of CMake related facilities.
|
|
|
|
In short, CMake supports finding dependencies in two ways:
|
|
|
|
* In Module mode, it consults a file ``Find<PackageName>.cmake`` which tries to find the component
|
|
in typical install locations and layouts. CMake ships a few dozen such scripts, but users and projects
|
|
may ship them as well.
|
|
|
|
* In Config mode, it locates a file named ``<packagename>-config.cmake`` or
|
|
``<PackageName>Config.cmake`` which describes the installed component in all regards needed to
|
|
consume it.
|
|
|
|
ROCm predominantly relies on Config mode, one notable exception being the Module
|
|
driving the compilation of HIP programs on NVIDIA runtimes. As such, when
|
|
dependencies are not found in standard system locations, one either has to
|
|
instruct CMake to search for package config files in additional folders using
|
|
the ``CMAKE_PREFIX_PATH`` variable (a semi-colon separated list of file system
|
|
paths), or using ``<PackageName>_ROOT`` variable on a project-specific basis.
|
|
|
|
There are nearly a dozen ways to set these variables. One may be more convenient
|
|
over the other depending on your workflow. Conceptually the simplest is adding
|
|
it to your CMake configuration command on the command line via
|
|
``-D CMAKE_PREFIX_PATH=....`` . AMD packaged ROCm installs can typically be
|
|
added to the config file search paths such as:
|
|
|
|
* Windows: ``-D CMAKE_PREFIX_PATH=${env:HIP_PATH}``
|
|
|
|
* Linux: ``-D CMAKE_PREFIX_PATH=/opt/rocm``
|
|
|
|
ROCm provides the respective *config-file* packages, and this enables
|
|
``find_package`` to be used directly. ROCm does not require any Find module as
|
|
the *config-file* packages are shipped with the upstream projects, such as
|
|
rocPRIM and other ROCm libraries.
|
|
|
|
For a complete guide on where and how ROCm may be installed on a system, refer
|
|
to the installation guides for
|
|
`Linux <https://rocm.docs.amd.com/projects/install-on-linux/en/latest/tutorial/quick-start.html>`_
|
|
and
|
|
`Windows <https://rocm.docs.amd.com/projects/install-on-windows/en/latest/index.html>`_.
|
|
|
|
Using HIP in CMake
|
|
==================
|
|
|
|
ROCm components providing a C/C++ interface support consumption via any
|
|
C/C++ toolchain that CMake knows how to drive. ROCm also supports the CMake HIP
|
|
language features, allowing users to program using the HIP single-source
|
|
programming model. When a program (or translation-unit) uses the HIP API without
|
|
compiling any GPU device code, HIP can be treated in CMake as a simple C/C++
|
|
library.
|
|
|
|
Using the HIP single-source programming model
|
|
---------------------------------------------
|
|
|
|
Source code written in the HIP dialect of C++ typically uses the `.hip`
|
|
extension. When the HIP CMake language is enabled, it will automatically
|
|
associate such source files with the HIP toolchain being used.
|
|
|
|
.. code-block:: cmake
|
|
|
|
cmake_minimum_required(VERSION 3.21) # HIP language support requires 3.21
|
|
cmake_policy(VERSION 3.21.3...3.27)
|
|
project(MyProj LANGUAGES HIP)
|
|
add_executable(MyApp Main.hip)
|
|
|
|
Should you have existing CUDA code that is from the source compatible subset of
|
|
HIP, you can tell CMake that despite their `.cu` extension, they're HIP sources.
|
|
Do note that this mostly facilitates compiling kernel code-only source files,
|
|
as host-side CUDA API won't compile in this fashion.
|
|
|
|
.. code-block:: cmake
|
|
|
|
add_library(MyLib MyLib.cu)
|
|
set_source_files_properties(MyLib.cu PROPERTIES LANGUAGE HIP)
|
|
|
|
CMake itself only hosts part of the HIP language support, such as defining
|
|
HIP-specific properties, etc. while the other half ships with the HIP
|
|
implementation, such as ROCm. CMake will search for a file
|
|
`hip-lang-config.cmake` describing how the the properties defined by CMake
|
|
translate to toolchain invocations. If one installs ROCm using non-standard
|
|
methods or layouts and CMake can't locate this file or detect parts of the SDK,
|
|
there's a catch-all, last resort variable consulted locating this file,
|
|
``-D CMAKE_HIP_COMPILER_ROCM_ROOT:PATH=`` which should be set the root of the
|
|
ROCm installation.
|
|
|
|
.. note::
|
|
Imported targets defined by `hip-lang-config.cmake` are for internal use
|
|
only.
|
|
|
|
If the user doesn't provide a semi-colon delimited list of device architectures
|
|
via ``CMAKE_HIP_ARCHITECTURES``, CMake will select some sensible default. It is
|
|
advised though that if a user knows what devices they wish to target, then set
|
|
this variable explicitly.
|
|
|
|
Consuming ROCm C/C++ libraries
|
|
------------------------------
|
|
|
|
Libraries such as rocBLAS, rocFFT, MIOpen, etc. behave as C/C++ libraries.
|
|
Illustrated in the example below is a C++ application using MIOpen from CMake.
|
|
It calls ``find_package(miopen)``, which provides the ``MIOpen`` imported
|
|
target. This can be linked with ``target_link_libraries``
|
|
|
|
.. code-block:: cmake
|
|
|
|
cmake_minimum_required(VERSION 3.5) # find_package(miopen) requires 3.5
|
|
cmake_policy(VERSION 3.5...3.27)
|
|
project(MyProj LANGUAGES CXX)
|
|
find_package(miopen)
|
|
add_library(MyLib ...)
|
|
target_link_libraries(MyLib PUBLIC MIOpen)
|
|
|
|
.. note::
|
|
|
|
Most libraries are designed as host-only API, so using a GPU device
|
|
compiler is not necessary for downstream projects unless they use GPU device
|
|
code.
|
|
|
|
Consuming the HIP API in C++ code
|
|
---------------------------------
|
|
|
|
Consuming the HIP API without compiling single-source GPU device code can be
|
|
done using any C++ compiler. The ``find_package(hip)`` provides the
|
|
``hip::host`` imported target to use HIP in this scenario.
|
|
|
|
.. code-block:: cmake
|
|
|
|
cmake_minimum_required(VERSION 3.5) # find_package(hip) requires 3.5
|
|
cmake_policy(VERSION 3.5...3.27)
|
|
project(MyProj LANGUAGES CXX)
|
|
find_package(hip REQUIRED)
|
|
add_executable(MyApp ...)
|
|
target_link_libraries(MyApp PRIVATE hip::host)
|
|
|
|
When mixing such ``CXX`` sources with ``HIP`` sources holding device-code, link
|
|
only to `hip::host`. If HIP sources don't have `.hip` as their extension, use
|
|
`set_source_files_properties(<hip_sources>... PROPERTIES LANGUAGE HIP)` on them.
|
|
Linking to `hip::host` will set all the necessary flags for the ``CXX`` sources
|
|
while ``HIP`` sources inherit all flags from the built-in language support.
|
|
Having HIP sources in a target will turn the |LINK_LANG|_ into ``HIP``.
|
|
|
|
.. |LINK_LANG| replace:: ``LINKER_LANGUAGE``
|
|
.. _LINK_LANG: https://cmake.org/cmake/help/latest/prop_tgt/LINKER_LANGUAGE.html
|
|
|
|
Compiling device code in C++ language mode
|
|
------------------------------------------
|
|
|
|
.. attention::
|
|
|
|
The workflow detailed here is considered legacy and is shown for
|
|
understanding's sake. It pre-dates the existence of HIP language support in
|
|
CMake. If source code has HIP device code in it, it is a HIP source file
|
|
and should be compiled as such. Only resort to the method below if your
|
|
HIP-enabled CMake code path can't mandate CMake version 3.21.
|
|
|
|
If code uses the HIP API and compiles GPU device code, it requires using a
|
|
device compiler. The compiler for CMake can be set using either the
|
|
``CMAKE_C_COMPILER`` and ``CMAKE_CXX_COMPILER`` variable or using the ``CC``
|
|
and ``CXX`` environment variables. This can be set when configuring CMake or
|
|
put into a CMake toolchain file. The device compiler must be set to a
|
|
compiler that supports AMD GPU targets, which is usually Clang.
|
|
|
|
The ``find_package(hip)`` provides the ``hip::device`` imported target to add
|
|
all the flags necessary for device compilation.
|
|
|
|
.. code-block:: cmake
|
|
|
|
cmake_minimum_required(VERSION 3.8) # cxx_std_11 requires 3.8
|
|
cmake_policy(VERSION 3.8...3.27)
|
|
project(MyProj LANGUAGES CXX)
|
|
find_package(hip REQUIRED)
|
|
add_library(MyLib ...)
|
|
target_link_libraries(MyLib PRIVATE hip::device)
|
|
target_compile_features(MyLib PRIVATE cxx_std_11)
|
|
|
|
.. note::
|
|
|
|
Compiling for the GPU device requires at least C++11.
|
|
|
|
This project can then be configured with the following CMake commands:
|
|
|
|
* Windows: ``cmake -D CMAKE_CXX_COMPILER:PATH=${env:HIP_PATH}\bin\clang++.exe``
|
|
* Linux: ``cmake -D CMAKE_CXX_COMPILER:PATH=/opt/rocm/bin/amdclang++``
|
|
|
|
Which use the device compiler provided from the binary packages of
|
|
`ROCm HIP SDK <https://www.amd.com/en/developer/resources/rocm-hub/hip-sdk.html>`_ and
|
|
`repo.radeon.com <https://repo.radeon.com>`_ respectively.
|
|
|
|
When using the ``CXX`` language support to compile HIP device code, selecting the
|
|
target GPU architectures is done via setting the ``GPU_TARGETS`` variable.
|
|
``CMAKE_HIP_ARCHITECTURES`` only exists when the HIP language is enabled. By
|
|
default, this is set to some subset of the currently supported architectures of
|
|
AMD ROCm. It can be set to the CMake option ``-D GPU_TARGETS="gfx1032;gfx1035"``.
|
|
|
|
ROCm CMake packages
|
|
-------------------
|
|
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| Component | Package | Targets |
|
|
+===========+==========+========================================================+
|
|
| HIP | hip | ``hip::host``, ``hip::device`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| rocPRIM | rocprim | ``roc::rocprim`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| rocThrust | rocthrust| ``roc::rocthrust`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| hipCUB | hipcub | ``hip::hipcub`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| rocRAND | rocrand | ``roc::rocrand`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| rocBLAS | rocblas | ``roc::rocblas`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| rocSOLVER | rocsolver| ``roc::rocsolver`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| hipBLAS | hipblas | ``roc::hipblas`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| rocFFT | rocfft | ``roc::rocfft`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| hipFFT | hipfft | ``hip::hipfft`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| rocSPARSE | rocsparse| ``roc::rocsparse`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| hipSPARSE | hipsparse| ``roc::hipsparse`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| rocALUTION|rocalution| ``roc::rocalution`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| RCCL | rccl | ``rccl`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| MIOpen | miopen | ``MIOpen`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
| MIGraphX | migraphx | ``migraphx::migraphx``, ``migraphx::migraphx_c``, |
|
|
| | | ``migraphx::migraphx_cpu``, ``migraphx::migraphx_gpu``,|
|
|
| | | ``migraphx::migraphx_onnx``, ``migraphx::migraphx_tf`` |
|
|
+-----------+----------+--------------------------------------------------------+
|
|
|
|
Using CMake presets
|
|
===================
|
|
|
|
CMake command lines depending on how specific users like to be when compiling
|
|
code can grow to unwieldy lengths. This is the primary reason why projects tend
|
|
to bake script snippets into their build definitions controlling compiler
|
|
warning levels, changing CMake defaults (``CMAKE_BUILD_TYPE`` or
|
|
``BUILD_SHARED_LIBS`` just to name a few) and all sorts anti-patterns, all in
|
|
the name of convenience.
|
|
|
|
Load on the command-line interface (CLI) starts immediately by selecting a
|
|
toolchain, the set of utilities used to compile programs. To ease some of the
|
|
toolchain related pains, CMake does consult the ``CC`` and ``CXX`` environmental
|
|
variables when setting a default ``CMAKE_C[XX]_COMPILER`` respectively, but that
|
|
is just the tip of the iceberg. There's a fair number of variables related to
|
|
just the toolchain itself (typically supplied using
|
|
`toolchain files <https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html>`_
|
|
), and then we still haven't talked about user preference or project-specific
|
|
options.
|
|
|
|
IDEs supporting CMake (Visual Studio, Visual Studio Code, CLion, etc.) all came
|
|
up with their own way to register command-line fragments of different purpose in
|
|
a setup-and-forget fashion for quick assembly using graphical front-ends. This is
|
|
all nice, but configurations aren't portable, nor can they be reused in
|
|
Continuous Integration (CI) pipelines. CMake has condensed existing practice
|
|
into a portable JSON format that works in all IDEs and can be invoked from any
|
|
command line. This is
|
|
`CMake Presets <https://cmake.org/cmake/help/latest/manual/cmake-presets.7.html>`_.
|
|
|
|
There are two types of preset files: one supplied by the project, called
|
|
``CMakePresets.json`` which is meant to be committed to version control,
|
|
typically used to drive CI; and one meant for the user to provide, called
|
|
``CMakeUserPresets.json``, typically used to house user preference and adapting
|
|
the build to the user's environment. These JSON files are allowed to include
|
|
other JSON files and the user presets always implicitly includes the non-user
|
|
variant.
|
|
|
|
Using HIP with presets
|
|
----------------------
|
|
|
|
Following is an example ``CMakeUserPresets.json`` file which actually compiles
|
|
the `amd/rocm-examples <https://github.com/amd/rocm-examples>`_ suite of sample
|
|
applications on a typical ROCm installation:
|
|
|
|
.. code-block:: json
|
|
|
|
{
|
|
"version": 3,
|
|
"cmakeMinimumRequired": {
|
|
"major": 3,
|
|
"minor": 21,
|
|
"patch": 0
|
|
},
|
|
"configurePresets": [
|
|
{
|
|
"name": "layout",
|
|
"hidden": true,
|
|
"binaryDir": "${sourceDir}/build/${presetName}",
|
|
"installDir": "${sourceDir}/install/${presetName}"
|
|
},
|
|
{
|
|
"name": "generator-ninja-multi-config",
|
|
"hidden": true,
|
|
"generator": "Ninja Multi-Config"
|
|
},
|
|
{
|
|
"name": "toolchain-makefiles-c/c++-amdclang",
|
|
"hidden": true,
|
|
"cacheVariables": {
|
|
"CMAKE_C_COMPILER": "/opt/rocm/bin/amdclang",
|
|
"CMAKE_CXX_COMPILER": "/opt/rocm/bin/amdclang++",
|
|
"CMAKE_HIP_COMPILER": "/opt/rocm/bin/amdclang++"
|
|
}
|
|
},
|
|
{
|
|
"name": "clang-strict-iso-high-warn",
|
|
"hidden": true,
|
|
"cacheVariables": {
|
|
"CMAKE_C_FLAGS": "-Wall -Wextra -pedantic",
|
|
"CMAKE_CXX_FLAGS": "-Wall -Wextra -pedantic",
|
|
"CMAKE_HIP_FLAGS": "-Wall -Wextra -pedantic"
|
|
}
|
|
},
|
|
{
|
|
"name": "ninja-mc-rocm",
|
|
"displayName": "Ninja Multi-Config ROCm",
|
|
"inherits": [
|
|
"layout",
|
|
"generator-ninja-multi-config",
|
|
"toolchain-makefiles-c/c++-amdclang",
|
|
"clang-strict-iso-high-warn"
|
|
]
|
|
}
|
|
],
|
|
"buildPresets": [
|
|
{
|
|
"name": "ninja-mc-rocm-debug",
|
|
"displayName": "Debug",
|
|
"configuration": "Debug",
|
|
"configurePreset": "ninja-mc-rocm"
|
|
},
|
|
{
|
|
"name": "ninja-mc-rocm-release",
|
|
"displayName": "Release",
|
|
"configuration": "Release",
|
|
"configurePreset": "ninja-mc-rocm"
|
|
},
|
|
{
|
|
"name": "ninja-mc-rocm-debug-verbose",
|
|
"displayName": "Debug (verbose)",
|
|
"configuration": "Debug",
|
|
"configurePreset": "ninja-mc-rocm",
|
|
"verbose": true
|
|
},
|
|
{
|
|
"name": "ninja-mc-rocm-release-verbose",
|
|
"displayName": "Release (verbose)",
|
|
"configuration": "Release",
|
|
"configurePreset": "ninja-mc-rocm",
|
|
"verbose": true
|
|
}
|
|
],
|
|
"testPresets": [
|
|
{
|
|
"name": "ninja-mc-rocm-debug",
|
|
"displayName": "Debug",
|
|
"configuration": "Debug",
|
|
"configurePreset": "ninja-mc-rocm",
|
|
"execution": {
|
|
"jobs": 0
|
|
}
|
|
},
|
|
{
|
|
"name": "ninja-mc-rocm-release",
|
|
"displayName": "Release",
|
|
"configuration": "Release",
|
|
"configurePreset": "ninja-mc-rocm",
|
|
"execution": {
|
|
"jobs": 0
|
|
}
|
|
}
|
|
]
|
|
}
|
|
|
|
.. note::
|
|
|
|
Getting presets to work reliably on Windows requires some CMake improvements
|
|
and/or support from compiler vendors. (Refer to
|
|
`Add support to the Visual Studio generators <https://gitlab.kitware.com/cmake/cmake/-/issues/24245>`_
|
|
and `Sourcing environment scripts <https://gitlab.kitware.com/cmake/cmake/-/issues/21619>`_
|
|
.)
|