Faced with strange issue with cmake detection of OpenCL.
When I use the following CMakeLists.txt
:
cmake_minimum_required(VERSION 3.10)
# Uncomment to make it working
# include(CheckSymbolExists)
# CHECK_SYMBOL_EXISTS(
# CL_VERSION_3_0
# "${OPENCL_INCLUDE_DIR}/CL/cl_version.h"
# OPENCL_VERSION_3_0)
# message(STATUS "OPENCL_VERSION_3_0 = ${OPENCL_VERSION_3_0}")
set(CMAKE_REQUIRED_INCLUDES ${OPENCL_INCLUDE_DIR})
find_package(OpenCL REQUIRED)
message(STATUS "OpenCL_FOUND = ${OpenCL_FOUND}")
message(STATUS "OpenCL_INCLUDE_DIRS = ${OpenCL_INCLUDE_DIRS}")
message(STATUS "OpenCL_LIBRARIES = ${OpenCL_LIBRARIES}")
message(STATUS "OpenCL_VERSION_STRING = ${OpenCL_VERSION_STRING}")
message(STATUS "OpenCL_VERSION_MAJOR = ${OpenCL_VERSION_MAJOR}")
message(STATUS "OpenCL_VERSION_MINOR = ${OpenCL_VERSION_MINOR}")
add_executable(TestOpenCL test_symbol.c)
target_link_libraries(TestOpenCL PUBLIC OpenCL::OpenCL)
It cannot detect OpenCL_VERSION_STRING, this variable is empty.
But when I uncomment lines in it, find_package(OpenCL REQUIRED)
finally could detect it properly
It is very starange for me, because underhood FindOpenCL.cmake use CHECK_SYMBOL_EXISTS, but it cannot compile simple program, I've debugged it:
Run Build Command(s): /opt/cmake-3.30.2-linux-x86_64/bin/cmake -E env VERBOSE=1 /usr/bin/gmake -f Makefile cmTC_38492/fast
/usr/bin/gmake -f CMakeFiles/cmTC_38492.dir/build.make CMakeFiles/cmTC_38492.dir/build
gmake[1]: Entering directory '<home_dir>/test_opencl/build/CMakeFiles/CMakeScratch/TryCompile-U9cXep'
Building C object CMakeFiles/cmTC_38492.dir/CheckSymbolExists.c.o
/usr/bin/cc -o CMakeFiles/cmTC_38492.dir/CheckSymbolExists.c.o -c <home_dir>/test_opencl/build/CMakeFiles/CMakeScratch/TryCompile-U9cXep/CheckSymbolExists.c
In file included from /usr/include/CL/cl.h:20,
from <home_dir>/test_opencl/build/CMakeFiles/CMakeScratch/TryCompile-U9cXep/CheckSymbolExists.c:2:
/usr/include/CL/cl_version.h:22:9: note: ‘#pragma message: cl_version.h: CL_TARGET_OPENCL_VERSION is not defined. Defaulting to 300 (OpenCL 3.0)’
22 | #pragma message("cl_version.h: CL_TARGET_OPENCL_VERSION is not defined. Defaulting to 300 (OpenCL 3.0)")
| ^~~~~~~
In file included from <home_dir>/test_opencl/build/CMakeFiles/CMakeScratch/TryCompile-U9cXep/CheckSymbolExists.c:2:
/usr/include/CL/cl.h:1314:21: error: unknown type name ‘CL_API_PREFIX__VERSION_2_2_DEPRECATED’
1314 | extern CL_API_ENTRY CL_API_PREFIX__VERSION_2_2_DEPRECATED cl_int CL_API_CALL
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1315:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘clSetProgramReleaseCallback’
1315 | clSetProgramReleaseCallback(cl_program program,
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1864:21: error: unknown type name ‘CL_API_PREFIX__VERSION_1_1_DEPRECATED’
1864 | extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1865:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘clCreateImage2D’
1865 | clCreateImage2D(cl_context context,
| ^~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1874:21: error: unknown type name ‘CL_API_PREFIX__VERSION_1_1_DEPRECATED’
1874 | extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_1_DEPRECATED cl_mem CL_API_CALL
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1875:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘clCreateImage3D’
1875 | clCreateImage3D(cl_context context,
| ^~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1886:21: error: unknown type name ‘CL_API_PREFIX__VERSION_1_1_DEPRECATED’
1886 | extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1887:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘clEnqueueMarker’
1887 | clEnqueueMarker(cl_command_queue command_queue,
| ^~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1890:21: error: unknown type name ‘CL_API_PREFIX__VERSION_1_1_DEPRECATED’
1890 | extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1891:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘clEnqueueWaitForEvents’
1891 | clEnqueueWaitForEvents(cl_command_queue command_queue,
| ^~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1895:21: error: unknown type name ‘CL_API_PREFIX__VERSION_1_1_DEPRECATED’
1895 | extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1896:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘clEnqueueBarrier’
1896 | clEnqueueBarrier(cl_command_queue command_queue) CL_API_SUFFIX__VERSION_1_1_DEPRECATED;
| ^~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1898:21: error: unknown type name ‘CL_API_PREFIX__VERSION_1_1_DEPRECATED’
1898 | extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_1_DEPRECATED cl_int CL_API_CALL
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1899:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘clUnloadCompiler’
1899 | clUnloadCompiler(void) CL_API_SUFFIX__VERSION_1_1_DEPRECATED;
| ^~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1901:58: error: expected ‘;’ before ‘void’
1901 | extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_1_DEPRECATED void * CL_API_CALL
| ^~~~~
| ;
/usr/include/CL/cl.h: In function ‘clGetExtensionFunctionAddress’:
/usr/include/CL/cl.h:1902:55: error: expected declaration specifiers before ‘CL_API_SUFFIX__VERSION_1_1_DEPRECATED’
1902 | clGetExtensionFunctionAddress(const char * func_name) CL_API_SUFFIX__VERSION_1_1_DEPRECATED;
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1905:21: error: unknown type name ‘CL_API_PREFIX__VERSION_1_2_DEPRECATED’
1905 | extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_2_DEPRECATED cl_command_queue CL_API_CALL
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1906:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘clCreateCommandQueue’
1906 | clCreateCommandQueue(cl_context context,
| ^~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1911:21: error: unknown type name ‘CL_API_PREFIX__VERSION_1_2_DEPRECATED’
1911 | extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_2_DEPRECATED cl_sampler CL_API_CALL
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1912:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘clCreateSampler’
1912 | clCreateSampler(cl_context context,
| ^~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1918:21: error: unknown type name ‘CL_API_PREFIX__VERSION_1_2_DEPRECATED’
1918 | extern CL_API_ENTRY CL_API_PREFIX__VERSION_1_2_DEPRECATED cl_int CL_API_CALL
| ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/CL/cl.h:1919:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘clEnqueueTask’
1919 | clEnqueueTask(cl_command_queue command_queue,
| ^~~~~~~~~~~~~
<home_dir>/test_opencl/build/CMakeFiles/CMakeScratch/TryCompile-U9cXep/CheckSymbolExists.c:5:1: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘{’ token
5 | {
It is pretty strange how it works ... Why in CMakeLists.txt
it works, but under FindOpenCL.cmake it got the compilation error,
even thoguht OPENCL_INCLUDE_DIR was provided as "-DOPENCL_INCLUDE_DIR=/usr/include"
What even more strange, that the if I add the following function, it properly detects version of OpenCL:
function(_FIND_OPENCL_VERSION)
foreach(VERSION "3_0" "2_2" "2_1" "2_0" "1_2" "1_1" "1_0")
# Write the test program to check OpenCL
set(SOURCE_CODE
"
#include <CL/cl.h>
#ifndef CL_VERSION_${VERSION}
#error \"CL_VERSION_${VERSION} is not defined\"
#endif
int main() {
return 0\;
}
")
# Create a temporary directory for the test
set(TEST_DIR "${CMAKE_BINARY_DIR}/CheckOpenCLSymbol")
file(MAKE_DIRECTORY ${TEST_DIR})
# Write the test program to a file
set(TEST_SOURCE "${TEST_DIR}/test_opencl_symbol.c")
file(WRITE ${TEST_SOURCE} ${SOURCE_CODE})
file(WRITE "${TEST_DIR}/CMakeLists.txt"
"
cmake_minimum_required(VERSION 3.8)
project(CheckOpenCLSymbol)
add_executable(TestOpenCL test_opencl_symbol.c)
target_include_directories(TestOpenCL PUBLIC ${OpenCL_INCLUDE_DIR})
target_link_libraries(TestOpenCL PUBLIC ${OpenCL_LIBRARIES})
")
# Use try_compile to check if the symbol exists
try_compile(
COMPILE_RESULT
PROJECT "CheckOpenCLSymbol"
SOURCE_DIR ${TEST_DIR}
BINARY_DIR ${TEST_DIR}
OUTPUT_VARIABLE CONSOLOE_OUTPUT
)
# Clean up temporary directory
file(REMOVE_RECURSE ${TEST_DIR})
# Output the result
if(COMPILE_RESULT)
set(OPENCL_VERSION_${VERSION} ${VERSION})
else()
set(OPENCL_VERSION_${VERSION} "")
endif()
message(STATUS "CONSOLOE_OUTPUT = ${CONSOLOE_OUTPUT}")
if(OPENCL_VERSION_${VERSION})
message(STATUS "OPENCL_VERSION_${VERSION} is FOUND !!!!!")
string(REPLACE "_" "." VERSION "${VERSION}")
set(OpenCL_VERSION_STRING ${VERSION} PARENT_SCOPE)
string(REGEX MATCHALL "[0-9]+" version_components "${VERSION}")
list(GET version_components 0 major_version)
list(GET version_components 1 minor_version)
set(OpenCL_VERSION_MAJOR ${major_version} PARENT_SCOPE)
set(OpenCL_VERSION_MINOR ${minor_version} PARENT_SCOPE)
break()
endif()
endforeach()
endfunction()
Also one strange this, this works and find properly symbol:
CHECK_SYMBOL_EXISTS(
CL_VERSION_3_0
"CL/cl.h"
OPENCL_VERSION_3_0)
but this one cannot compile:
CHECK_SYMBOL_EXISTS(
CL_VERSION_3_0
"/usr/include/CL/cl.h"
OPENCL_VERSION_3_0)
Have somebody faced with similar issues ??
Finally I've found the root 'cause for this issue
It happened, because in my system I had multiple versions of OpenCL
and find_package(OpenCL)
struggles to find proper (@Tsyvarev Thanks for this suggestions in comments)
After reinstallation there was also an issue with that application that I tried to build requires cl2.hpp
headers, but they was available in package opencl-clhpp-headers
After installation I started to face with the same issue again. It happens again due to system struggle between 2 OpenCL headers: /usr/local/cuda/include/CL (old one without cl2.hpp that is required) and /usr/include/CL (that more new one and has cl2.hpp that is required for building project)
I have move /usr/local/cuda/include/CL -> /usr/local/cuda/include/CL_backup and issue was finally resolved
Issue with find_package
happened, because underhood it used CHECK_SYMBOL_EXISTS
that looks like this:
CHECK_SYMBOL_EXISTS(
CL_VERSION_3_0
"${OPENCL_INCLUDE_DIR}/CL/cl.h"
OPENCL_VERSION_3_0)
CHECK_SYMBOL_EXISTS
try to compile test program with the following include statment: #include <${OPENCL_INCLUDE_DIR}/CL/cl.h>
, - where it was in my case: #include </usr/include/CL/cl.h>
, after that compiler struggle between 2 type of header files for OpenCL
in /usr/include/CL/
and /usr/local/cuda/include/CL/
.
But if it was used #include <CL/cl.h>
and include path to OpenCL
was provided as option to compiler, for example using try_compile
with include paths -> then detection was working properly
It was hard to figure out and there are lots of small issue here an there, especially as for me it looks like FindOpenCL.cmake
could be modified to check "CL/cl.h" header instead of "${OPENCL_INCLUDE_DIR}/CL/cl.h"
Thanks everyone who helped me in comments !!