# CMake system description

The project uses CMake for integration and testing purposes.

Configuration phase can be customized by passing additional variables: `cmake -D<var1>=<val1> -D<var2>=<val2> ... -D<varN>=<valN> <sources-dir>`

The following variables are provided for oneDPL configuration:

| Variable                                 | Type   | Description                                                                                   | Default value |
|------------------------------------------|--------|-----------------------------------------------------------------------------------------------|---------------|
| ONEDPL_BACKEND                           | STRING | Threading backend; supported values: tbb, dpcpp, dpcpp_only, serial, ...; the default value is defined by compiler: dpcpp for DPC++ and tbb for others | tbb/dpcpp |
| ONEDPL_USE_UNNAMED_LAMBDA                | BOOL   | Pass `-fsycl-unnamed-lambda`, `-fno-sycl-unnamed-lambda` compile options or nothing           |               |
| ONEDPL_ENABLE_SIMD                       | BOOL   | Enable SIMD vectorization by passing an OpenMP SIMD flag to the compiler if supported; the flag is passed to user project compilation string if enabled | ON           |
| ONEDPL_CMAKE_QUIET_CHECKS                | BOOL   | Silence compiler/header check output during CMake configuration. Set to OFF to see verbose output for debugging | ON            |
| ONEDPL_TEST_EXPLICIT_KERNEL_NAMES   | STRING | Control kernel naming. Affects only oneDPL test targets. Supported values: AUTO, ALWAYS. AUTO: rely on the compiler if "Unnamed SYCL lambda kernels" feature is on, otherwise provide kernel names explicitly; ALWAYS: provide kernel names explicitly | AUTO          |
| ONEDPL_TEST_WIN_ICX_FIXES     | BOOL   | Affects only oneDPL test targets.  Enable icx, icx-cl workarounds to fix issues in CMake for Windows.                      | ON            |
| ONEDPL_WORKAROUND_FOR_IGPU_64BIT_REDUCTION | BOOL | Use as a workaround for incorrect results, which may be produced by reduction algorithms with 64-bit data types compiled by the Intel&reg; oneAPI DPC++/C++ Compiler and executed on GPU devices. |               |

Some useful CMake variables ([here](https://cmake.org/cmake/help/latest/manual/cmake-variables.7.html) you can find a full list of CMake variables for the latest version):

- [`CMAKE_CXX_COMPILER`](https://cmake.org/cmake/help/latest/variable/CMAKE_LANG_COMPILER.html) - C++ compiler used for build, e.g. `CMAKE_CXX_COMPILER=dpcpp`.
- [`CMAKE_BUILD_TYPE`](https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html) - build type that affects optimization level and debug options, values: `RelWithDebInfo`, `Debug`, `Release`, ...; e.g. `CMAKE_BUILD_TYPE=RelWithDebInfo`.
- [`CMAKE_CXX_STANDARD`](https://cmake.org/cmake/help/latest/variable/CMAKE_CXX_STANDARD.html) - C++ standard, e.g. `CMAKE_CXX_STANDARD=17`.

## Testing

Steps:

1. Configure project using CMake.
2. Perform build [and run] using build system (e.g. `make build-onedpl-tests`).
3. (optional) Run tests using CTest.

**NOTE**: tests are not added to `all` target, so they are not built/run by default.
The following targets are available for build system after configuration:

- `<test-name>` - build specific test, e.g. `for_each.pass`;
- `run-<test-name>` - build and run specific test, e.g. `run-for_each.pass`;
- `build-onedpl-<tests-subdir>-tests` - build all tests from specific subdirectory under `<root>/test`, e.g. `build-onedpl-general-tests`;
- `run-onedpl-<tests-subdir>-tests` - build and run all tests from specific subdirectory under `<root>/test`, e.g. `run-onedpl-general-tests`;
- `build-onedpl-tests` - build all tests;
- `run-onedpl-tests` - build and run all tests.

Sudirectories are added as labels for each test and can be used with `ctest -L <label>`.
For example, `<root>/test/path/to/test.pass.cpp` will have `path` and `to` labels.

## Using oneDPL with NVIDIA and AMD GPUs with the oneAPI DPC++ compiler

[Codeplay® oneAPI Plugins for NVIDIA® & AMD](https://codeplay.com/solutions/oneapi/plugins/) may be installed to
compile Ahead of Time (AOT) for NVIDIA and AMD GPUs. For a guide on AOT compilation options, please refer to
[Use DPC++ to Target AMD GPUs](https://developer.codeplay.com/products/oneapi/amd/latest/guides/get-started-guide-amd.html#use-dpc-to-target-amd-gpus)
and [Use DPC++ to Target NVIDIA GPUs](https://developer.codeplay.com/products/oneapi/nvidia/latest/guides/get-started-guide-nvidia.html#use-dpc-to-target-nvidia-gpus).
A full list of AOT compile target options may be found at
[oneAPI DPC++ Compiler documentation Users Manual](https://intel.github.io/llvm/UsersManual.html). To compile AOT with
oneDPL, use standard CMake means such as `CMAKE_CXX_FLAGS` to pass relevant options.

If you are not using the oneAPI DPC++ compiler, then please refer to your SYCL compiler's documentation regarding
support of this feature.

## Using oneDPL with FPGA devices with the oneAPI DPC++ compiler

oneDPL provides macros to enable FPGA-tailored policies and algorithms.
Define them to target an FPGA hardware or emulator:

```cmake
# Hardware
target_compile_definitions(foo PRIVATE ONEDPL_FPGA_DEVICE)

# Emulator
target_compile_definitions(foo PRIVATE ONEDPL_FPGA_DEVICE ONEDPL_FPGA_EMULATOR)
```

Pass the compiler options relevant to your target, which are described in the
[Targeting Multiple Platforms](https://www.intel.com/content/www/us/en/docs/oneapi-fpga-add-on/developer-guide/2025-0/targeting-multiple-platforms.html)
chapter of the Intel® oneAPI DPC++/C++ Compiler Handbook for FPGAs.

**NOTE**: The oneAPI DPC++/C++ Compiler has dropped FPGA support.
In oneDPL, FPGA-tailored policies and algorithms are deprecated,
but they can still be used with older oneAPI DPC++/C++ Compiler versions.

## How to use oneDPL from CMake
### Using oneDPL source files

Using oneDPL source files allows you to integrate oneDPL source code into your project with the [add_subdirectory](https://cmake.org/cmake/help/latest/command/add_subdirectory.html) command. `add_subdirectory(<oneDPL_root_dir> [<oneDPL_output_dir>])` adds oneDPL to the user project build.
* `<oneDPL_root_dir>` is a relative or absolute path to oneDPL root directory
* `<oneDPL_output_dir>` is a relative or absolute path to directory for holding output files for oneDPL
* If `<oneDPL_root_dir>` is the relative path, then `<oneDPL_output_dir>` is optional.

The variables from the table above can be specified before the `add_subdirectory` call to customize your oneDPL configuration and build.

For example:

```cmake
project(Foo)
add_executable(foo foo.cpp)

# Specify oneDPL backend
set(ONEDPL_BACKEND tbb)

# Add oneDPL to the build.
add_subdirectory(/path/to/oneDPL build_oneDPL)
```

oneDPL tests are not configured if oneDPL in such scenario. So they can't be built and run in this case.

### Using oneDPL package

oneDPLConfig.cmake and oneDPLConfigVersion.cmake are included into oneDPL distribution.

These files allow to integrate oneDPL into user project with the [find_package](https://cmake.org/cmake/help/latest/command/find_package.html) command. Successful invocation of `find_package(oneDPL <options>)` creates imported target `oneDPL` that can be passed to the [target_link_libraries](https://cmake.org/cmake/help/latest/command/target_link_libraries.html) command.

For example:

```cmake
project(Foo)
add_executable(foo foo.cpp)

# Search for oneDPL
find_package(oneDPL REQUIRED)

# Connect oneDPL to foo
target_link_libraries(foo oneDPL)
```

Use `ONEDPL_PAR_BACKEND` variable before the invocation of `find_package(oneDPL <options>)` to control standard host (par) backend:

- Supported values:
  - `tbb` for oneTBB backend;
  - `openmp` for OpenMP backend;
  - `serial` for serial backend.
- If this variable is not set then the first suitable backend is chosen among oneTBB, OpenMP and serial, they are considered in the order as specified.
- oneDPL is considered as not found (`oneDPL_FOUND=FALSE`) if `ONEDPL_PAR_BACKEND` is specified, but not found or not supported.
- Macro `ONEDPL_USE_OPENMP_BACKEND` is set to `0` if oneTBB backend is chosen.
- Macro `ONEDPL_USE_TBB_BACKEND` is set to `0` if OpenMP backend is chosen.
- Macro `ONEDPL_USE_TBB_BACKEND` is set to `0` and `ONEDPL_USE_OPENMP_BACKEND` is set to `0` if serial backend is chosen.

### Using oneDPL package on Windows
On Windows, CMake requires some workarounds to use icx[-cl] successfully.  A CMake package has been provided 'oneDPLWindowsIntelLLVM' to apply these required workarounds.
Some workarounds are provided for icpx, but it is not fully supported on Windows at this time.  We also recommend updating to the most recent version of CMake, as they are actively improving support for Intel compilers (https://gitlab.kitware.com/cmake/cmake/-/issues/24314).
To enable the workarounds, please add `find_package(oneDPLWindowsIntelLLVM)` to your cmake file before you call `project()`.  If using oneDPL from source files, you must add oneDPL's cmake directory to your `CMAKE_PREFIX_PATH` to allow CMake to find `oneDPLWindowsIntelLLVM`.

For example:

```cmake
list(APPEND CMAKE_PREFIX_PATH /path/to/oneDPL/cmake)
find_package(oneDPLWindowsIntelLLVM)
project(Foo)
add_executable(foo foo.cpp)

# Specify oneDPL backend
set(ONEDPL_BACKEND tbb)

# Add oneDPL to the build.
add_subdirectory(/path/to/oneDPL build_oneDPL)
```

Finally, the supported generator in the Windows environment is Ninja, we recommend using `-GNinja` in your cmake configuration.

### oneDPLConfig files generation

This section is applicable for oneDPL packaging creation process, but not for usual development flow.

`cmake/scripts/generate_config.cmake` is provided to generate oneDPLConfig files for oneDPL package.

How to use:

`cmake [-DSKIP_HEADERS_SUBDIR=<TRUE|FALSE>] [-DOUTPUT_DIR=<output_dir>] -P cmake/scripts/generate_config.cmake`

When `SKIP_HEADERS_SUBDIR` is set to false or not defined (by default), the script adds the subdirectories:
- `windows` and `linux` for headers in `<prefix></subdirectory>/include` pattern.
- `pkgconfig-win` and `pkgconfig-lin` for pkg-config files in `<prefix></subdirectory>/dpl.pc` pattern.
