## SYCL in CMake
## Learning Objectives * Learn how CMake 4.5 treats SYCL as a language * Learn how to build a SYCL hello world with a `FILE_SET` * Learn how to pick a SYCL compiler and pass SYCL-only flags
#### Before CMake 4.5
* Each implementation shipped its own CMake integration: * DPC++: `find_package(IntelSYCL)` + `add_sycl_to_target(...)` * AdaptiveCpp: `find_package(AdaptiveCpp)` + `add_sycl_to_target(...)` * or `-fsycl` added by hand to `CMAKE_CXX_FLAGS` * Every C++ file in the project was then compiled as SYCL, even files with no kernels
#### SYCL is a CMake language
* Since CMake 4.5, SYCL is a language like `CXX`, `CUDA` or `HIP` * CMake finds `icpx` / `acpp` and adds `-fsycl` for you * Use `CMAKE_SYCL_COMPILER` and `CMAKE_SYCL_FLAGS`, the same way you use `CMAKE_CXX_COMPILER` and `CMAKE_CXX_FLAGS` * The feature is still experimental: you opt in with a UUID before `project()`
#### Hello world: one SYCL file, one C++ file
`main.cpp` (SYCL)

#include <cassert>
#include <cstdio>

#include <sycl/sycl.hpp>

int answer();  // defined in answer.cpp

int main() {
  sycl::queue q;
  int* x = sycl::malloc_shared<int>(1, q);
  q.single_task([=] { *x = 42; }).wait();
  assert(*x == answer());
  std::printf("x = %d\n", *x);
  sycl::free(x, q);
}
              
`answer.cpp` (plain C++)

int answer() { return 42; }
              
* Only `main.cpp` has a kernel, so only `main.cpp` needs the SYCL compiler
#### Hello world: CMakeLists.txt
```cmake cmake_minimum_required(VERSION 4.5) set(CMAKE_EXPERIMENTAL_SYCL "c0d1fb10-2ece-420e-9d29-7d7f2b300f25") project(hello LANGUAGES CXX SYCL) add_executable(hello) target_sources(hello PRIVATE FILE_SET SYCL FILES main.cpp) target_sources(hello PRIVATE answer.cpp) # plain C++ ```
* `LANGUAGES CXX SYCL`: enable SYCL next to C++ * `FILE_SET SYCL`: compile `main.cpp` as SYCL, even though it is a `.cpp` file * `answer.cpp` is outside the set: it stays plain C++ * Files with the `.sycl` extension are compiled as SYCL automatically
#### Build and run
For example, with `icpx` the build looks something like:
```sh $ cmake -B build -- The CXX compiler identification is IntelLLVM 2026.1.0 -- The SYCL compiler identification is IntelLLVM 2026.1.0 $ cmake --build build -v icpx -o answer.cpp.o -c answer.cpp # note: no -fsycl icpx -fsycl -x c++ -fno-gpu-rdc -o main.cpp.o -c main.cpp icpx -fsycl answer.cpp.o main.cpp.o -o hello -lsycl -lsycl-devicelib-host $ ./build/hello x = 42 ```
* `answer.cpp` is compiled **without** `-fsycl` * SYCL compilation does extra work compared to pure C++, so it is slower: only the files in the SYCL set pay that cost
#### Compiler and flags
```sh $ cmake -B build -DCMAKE_SYCL_FLAGS=-fsycl-targets=spir64 $ cmake --build build -v icpx -o answer.cpp.o -c answer.cpp icpx -fsycl -fsycl-targets=spir64 -x c++ -fno-gpu-rdc -o main.cpp.o -c main.cpp ```
* Pick a compiler: `-DCMAKE_SYCL_COMPILER=icpx` * `CMAKE_SYCL_FLAGS` only reaches SYCL sources, not plain C++ files
## Questions