I have a C/C++ package where I make use of some GPU acceleration methods, CUDA for Nvidia hardware and using OpenCL for non-Nvidia hardware. I also have SIMD functions specific to Intel CPUs and some specific for ARM. I want to be able to install these different acceleration methods based on the install flags passed in when building with CMake but I am unsure how to also structure my header file.
The two things I am trying to tackle with preprocessor directives and the optional installation piece with CMake is:
- Check if the headers were installed from the optional CMake flags (is this possible?)
- Check if the given host machine matches one of the compatible platforms I wrote code for (OpenCL compatible platforms and CUDA) AND include the optional header files based on that
I am thinking of the header file for this project looking something like this but am unsure of the directives themselves
#ifdef Intel/Apple... OpenCL compatible GPUs
// include GPU code that uses OpenCL
#endif
#ifdef Nvidia GPU
// include GPU code that uses CUDA
#endif
#ifdef Intel CPUs
// include SIMD code that uses Intel intrinsics
#endif
#ifdef ARM CPUs
// include SIMD code that uses ARM intrinsics
#endif
Is this the proper way to go about creating code to run on multiple platforms? I am curious how projects do something similar like OpenCV being compatible with CUDA and OpenCL.
Compile a sample program with that header, and check if it compiles. https://cmake.org/cmake/help/latest/module/CheckIncludeFile.html or https://cmake.org/cmake/help/latest/command/try_compile.html
How to identify platform/compiler from preprocessor macros? and https://github.com/Kitware/CMake/blob/master/Modules/CMakePlatformId.h.in etc.
There is no "proper" way. It is one of the ways, and it's fine.
OpenCV is an open source project. https://github.com/opencv/opencv/blob/a4a9f56c8bbb11fd4a017d3c1819b89f43160474/cmake/OpenCVDetectCUDA.cmake#L82 https://github.com/opencv/opencv/blob/a4a9f56c8bbb11fd4a017d3c1819b89f43160474/modules/core/src/matrix_wrap.cpp#L319 etc.