SYCL is a specification, which means to use it we need to pick a particular implementation. The SYCL ecosystem is…rapidly evolving and a bit confusing. Here’s an image from a helpful online tutorial that was made in 2021:

As far as I can tell codeplay — which still has a lot of online training materials — doesn’t exist anymore, neoSYCL was last updated in 2022, triSYCL explicitly tells people that it “should not be used by a normal end-user,” and hipSYCL had to change its name under (what I assume was) external legal pressure.
This all made me somewhat hesitant about committing time to learning more about SYCL, but I was still sufficiently intrigued to put aside these small qualms. The two main compiler choices left seem to be Intel’s Data parallel C++ compiler or a community-driven implementation from AdaptiveCpp. I’m sure either is a perfectly reasonable choice. There is some data suggesting that AdaptiveCpp performs better on some benchmarks, but it’s also the open-source choice of the two. For the purpose of this learning project, that was good enough for me.
Setting up AdaptiveCpp
Getting set up with AdaptiveCpp is shockingly straightforward. Maybe I’m just scarred from an age where setting up external packages with complicated dependencies on other external packages was a complete (rather than just relative) nightmare, but AdaptiveCpp basically just works out of the box.
LLVM
I made things easy for myself by starting with a fresh installation of Ubuntu 24.04, and then installing the LLVM dependencies using the recommended installation scripts that is recommended, and then apt-getting a bunch of packages:
apt-get install clang-format clang-tidy clang-tools clang clangd libc++-dev libc++1 libc++abi-dev libc++abi1 libclang-dev libclang1 liblldb-dev libllvm-ocaml-dev libomp-dev libomp5 lld lldb llvm-dev llvm-runtime llvm python3-clang
AdaptiveCpp
From there, the installation instructions for AdaptiveCpp just work as documented. I did a quick export CC=/path/to/clang
and export CXX=/path/to/clang++
, followed by:
git clone https://github.com/AdaptiveCpp/AdaptiveCpp
cd AdaptiveCpp
mkdir build && cd build
cmake ..
make install
…and voila! Nothing else to it.
Integration with the CMake build system
It is similarly easy to use the AdaptiveCpp compiler in a C++ codebase. Essentially following along with the recommendations on the AdaptiveCpp repo, the core additions to an existing CMakeLists.txt
file are
cmake_minimum_required(VERSION 3.22)
set(CMAKE_CXX_COMPILER clang++)
project(acppTest VERSION 0.0 LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23)
find_package(AdaptiveCpp CONFIG REQUIRED)
add_executable(${PROJECT_NAME}
main.cpp)
add_sycl_to_target(
TARGET ${PROJECT_NAME}
SOURCES main.cpp
)
From the documentation one needs at least LLVM 14, and a standard set to C++13 (Since I was starting with a fresh install I used a more recent standard, but that isn’t important). Otherwise: using AdaptiveCpp is as simple as a single find_package
command and the novel add_sycl_to_target
applied to an already-declared target (where that target can be an executable or a library, allowing you to selectively compile some parts of the code using AdaptiveCpp on others without it). I did find that explicitly setting clang++
as the compiler was helpful (either in the main CMakeLists file or as a command-line argument during the invocation of the cmake
command) — when using gcc
/g++
instead there were some extra linking steps for targeted libraries I had to jump through. There is a convenient list of other environment variables that can be set during compilation, but which I won’t get into here.