OpenCL is not native to the Windows operating system, and as such isn't supported across the board of UWP (Universal Windows Platform) platforms (XBox, Hololens, IoT, PC) and the Microsoft Store. Windows as a traditional content creating platform however can build and execute OpenCL applications when built as traditional Win32 GUI or console applications.
(NOTE: Nothing prevents from using advanced WinRT capabilities to use the ICD in packaged applications (APPX/MSIX), however such applications will most certainly not be able to load a functioning OpenCL runtime on platforms other than PC and a few IoT devices.)
In this guide we're minimally going to use the following tools:
- The command-line
- C/C++ compiler
And depending on which ways one extends the bare minimum:
- CMake (Cross-platform Make)
- Git
- Vcpkg (Cross-platform pacakge management)
- Visual Studio Code
Steps will be provided to obtain a minimal and productive environment.
In this guide we'll be using latest (at the time of writing) Windows 10. Installation for the most part will happen via winget, the 1st party command-line tool for installing software on Windows. If for whatever reason you do not have the winget
client on your PATH, it is bundled with the App Installer package in the Microsoft Store. Updating this component should also install the command-line tool.
(NOTE: installation commands if not issued from a shell with Administrator privileges, UAC prompts will pop up. If you are in an automated scenario where that's an issue, make sure to work in such a shell.)
After installing everything, open a new shell, otherwise the tools will not be available on the PATH for convenient invocation.
Open your favorite shell in your favorite terminal and issue:
winget install "Visual Studio Build Tools 2022"
In automated scenarios with no GUI available, please consult the VS docs on specifying the required workloads. A minimal configuration which may be imported using the GUI or specfied on the command-line is as:
& "C:\Program Files (x86)\Microsoft Visual Studio\Installer\setup.exe" install --passive --norestart --productId Microsoft.VisualStudio.Product.BuildTools --channelId VisualStudio.17.Release --add Microsoft.VisualStudio.Component.VC.Tools.x86.x64 --add Microsoft.VisualStudio.Component.VC.Redist.14.Latest
Developers targeting Windows 10 will need to add
--add Microsoft.VisualStudio.Component.Windows10SDK.19041
to the command-line while targeting Windows 11 requires--add Microsoft.VisualStudio.Component.Windows11SDK.22000
You most likely already have Git installed. If not, we'll install it, because this is what Vcpkg uses to keep it's repository up-to-date. Open your favorite shell in your faovrite terminal and issue:
winget install Git.Git
If you do not have CMake installed yet, we'll install it, as it's the primary supported build system, as it will make our builds much simpler. Open your favorite shell in your faovrite terminal and issue:
winget install Kitware.CMake
While IDEs are highly opinionated, for an IDE with widespread adoption and small footprint, VS Code has everything (and more) to get off the ground.
winget install "Visual Studio Code" --source msstore
To build native OpenCL applications, one will minimally need:
- C or C++ compiler
- The OpenCL headers
- The C and optionally the C++ headers
- An Installable Client Driver (ICD) Loader
- Dynamic library (OpenCL.dll)
- Export library (OpenCL.lib)
The SDK can be installed from a package manager like Vcpkg or can be built on-demand from their canonical repositories.
GitHub
If you want to build an SDK from source, the recommended way is cloning the OpenCL-SDK repo.
git clone --recursive https://github.com/KhronosGroup/OpenCL-SDK.git
cmake -G "Visual Studio 17 2022" -A x64 -T v143 -D CMAKE_INSTALL_PREFIX=./OpenCL-SDK/install -B ./OpenCL-SDK/build -S ./OpenCL-SDK
cmake --build OpenCL-SDK/build --config Release --target install -- /m /v:minimal
Vcpkg
UX for obtaining dependencies for C/C++ projects has improved dramatically in the past few years. This guide will make use of Vcpkg, a community maintained repo of build scripts for a rapidly growing number of open-source libraries.
Navigate to the folder where you want to install Vcpkg and issue on the command-line (almost any shell):
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
This should build the Vcpkg command-line utility that will take care of the all installations. The utility let's us discover the OpenCL SDK in its repository (beside other packages mentioning OpenCL).
.\vcpkg.exe search opencl
...
opencl 2.2 (2017.07.... C/C++ headers and ICD loader (Installable Client Driver) for OpenCL
We can install it by issuing:
.\vcpkg.exe --triplet=x64-windows install opencl
(Note: if you are targeting 64-bit ARM, use --triplet=arm64-windows
instead. For more information on triplets, refer to Triplet Files in the Vcpkg docs.)
On Windows the default system command interpreter is cmd.exe
. (This is analogous to /bin/sh
in Linux.) The default shell however is PowerShell which provides better user-experience overall. (Much like Linux defaults to /bin/bash
.) PowerShell provides a better CLI experience overall.
Unlike compilers native to *nix OS flavors, MSVC relies on a few environmental variables to function properly. Such environments are referred to as Developer Command Prompt or Developer PowerShell, which are nothing more than ordinary shells with these environmental variables setup.)
To build applications on the command-line using cmd.exe
on Windows, one needs to open a Developer Command Prompt for VS 2022
. This can be done in the Start Menu or by invoking vcvarsall.bat
from the installation folder.
"C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\VC\Auxiliary\Build\vcvarsall.bat" amd64
(Note: for all combinations of available host-target toolset variables, consult vcvarsall.bat help
)
Inheriting environments set up by batch scripts is not trivial, hence VS provides a PowerShell module doing the same thing. The module is inside an assembly shipping with VS. To have the utility available in all shells, invoke the following from PowerShell:
if (-not (Test-Path ~\Documents\PowerShell)) { New-Item -Type Directory ~\Documents\PowerShell }
'Import-Module "C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\Common7\Tools\Microsoft.VisualStudio.DevShell.dll"' >> $PROFILE
function devshell { Enter-VsDevShell -InstallPath "C:\Kellekek\Microsoft\VisualStudio\2019\BuildTools" -SkipAutomaticLocation -DevCmdArguments "-arch=x64 -no_logo" }
Opening a new shell, one now can enter a Developer PowerShell by issuing:
devshell -VsInstallPath 'C:\Program Files (x86)\Microsoft Visual Studio\2022\BuildTools\' -DevCmdArguments '-arch=x64 -no_logo'
Inside a Developer Command Prompt navigate to the folder where you wish to build your application. Our application will have a single Main.c
source file:
// C standard includes
#include <stdio.h>
// OpenCL includes
#include <CL/cl.h>
int main()
{
cl_int CL_err = CL_SUCCESS;
cl_uint numPlatforms = 0;
CL_err = clGetPlatformIDs( 0, NULL, &numPlatforms );
if (CL_err == CL_SUCCESS)
printf_s("%u platform(s) found\n", numPlatforms);
else
printf_s("clGetPlatformIDs(%i)\n", CL_err);
return 0;
}
Then invoke the compiler to build our source file as such:
GitHub
cl.exe /nologo /TC /W4 /DCL_TARGET_OPENCL_VERSION=100 /I<SDKINSTALLROOT>\include\ Main.c /Fe:HelloOpenCL /link /LIBPATH:<SDKINSTALLROOT>\lib OpenCL.lib
Vcpkg
cl.exe /nologo /TC /W4 /DCL_TARGET_OPENCL_VERSION=100 /I<VCPKGROOT>\installed\x64-windows\include\ Main.c /Fe:HelloOpenCL /link /LIBPATH:<VCPKGROOT>\installed\x64-windows\lib OpenCL.lib
What do the command-line arguments mean?
/nologo
makes the compiler omit printing a banner to the console/TC
tells it to treat all source files as C/W4
turns on Warning level 4 (highest sensible level)/D
instructs the preprocessor to create a define with NAME:VALUECL_TARGET_OPENCL_VERSION
enables/disables API functions corresponding to the defined version. Setting it to 100 will disable all API functions in the header that are newer than OpenCL 1.0
/I
sets additional paths to the include directory search pathsMain.c
is the name of the input source file/Fe:
sets the name of the output executable (default would beMain.exe
)/link
allows passing arguments to the linker invoked by the compiler driver (flags of the compiler should not follow this argument)/LIBPATH
sets additional paths to the library directory search pathsOpenCL.lib
is the vendor neutral ICD loader to link to
Running our executable HelloOpenCL.exe
either prints the number of platforms found or an error code which is often the result of corrupted runtime installations.
The CMake build script for this application that builds it as an ISO C11 app with most sensible compiler warnings turned on looks like:
cmake_minimum_required(VERSION 3.1) # 3.1 << C_STANDARD 11
project(HelloOpenCL LANGUAGES C)
find_package(OpenCL CONFIG REQUIRED)
add_executable(${PROJECT_NAME} Main.c)
target_link_libraries(${PROJECT_NAME} PRIVATE OpenCL::OpenCL)
set_target_properties(${PROJECT_NAME} PROPERTIES C_STANDARD 11
C_STANDARD_REQUIRED ON
C_EXTENSIONS OFF)
target_compile_definitions(${PROJECT_NAME} PRIVATE CL_TARGET_OPENCL_VERSION=100)
What does the script do?
- Give a name to the project and tell CMake to only look for a C compiler (default is to search for a C and a C++ compiler)
- Look for an OpenCL SDK and fail if not found
- If detection fails, refer to the CMake Build-System Support chapter.
- Specify our source files and name the executable
- Specify dependency to the SDK (not just linkage)
- Set language properties to all source files of our application
- Set the OpenCL version target to control API coverage in header
- Because CMake cannot handle warning levels portably, set compiler specific flags. Guard it with a generator expression (terse conditionals), so other compilers will not pick up such non-portable flags.
To invoke this script, place it next to our Main.c
file in a file called CMakeLists.txt
. Once that's done, cmake may be invoked the following way to generate Ninja makefiles in the advised out-of-source fashion into a subfolder named build
:
GitHub
cmake -A x64 -S . -B .\build -D CMAKE_PREFIX_PATH=<SDKINSTALLROOT>
Vcpkg
cmake -A x64 -S . -B .\build -D CMAKE_TOOLCHAIN_FILE=<VCPKGROOT>\scripts\buildsystems\vcpkg.cmake
Which will output something like
-- The C compiler identification is MSVC 19.22.27905.0
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio620226BuildTools/VC/Tools/MSVC/14.22.27905/bin/Hostx64/x64/cl.exe
-- Check for working C compiler: C:/Program Files (x86)/Microsoft Visual Studio620226BuildTools/VC/Tools/MSVC/14.22.27905/bin/Hostx64/x64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Looking for CL_VERSION_2_2
-- Looking for CL_VERSION_2_2 - found
-- Found OpenCL: C:/Users/mnagy/Source/Repos/vcpkg/installed/x64-windows/debug/lib/OpenCL.lib (found version "2.2")
-- Looking for pthread.h
-- Looking for pthread.h - not found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/mnagy/Source/CL-Min1/build
To kick off the build, one may use CMakes build driver:
cmake --build .\build --config Release
Once build is complete, we can run it by typing:
.\build\Release\HelloOpenCL.exe