set(OPENCL_HEADERS_INCLUDE_DIR_GENEXPR $) ############################### ### ### ### Workaround to CMake bug ### ### ### ############################### # # The generated mocks\Mockcl.h include the OpenCL headers as # # #include "CL/cl_platform.h" # #include "cl.h" # # which requires the tests to not only inherit the INTERFACE_INCLUDE_DIRECTORIES, but also the same dir with # /CL appended at the end. There seems to be a bug in CMake (3.19 even) where if a target has the same genexpr # predicate twice, the second time it always fails. Having both # # $ (invisbly via linking to OpenCL::Headers) # $/CL # # means we can only get one of these switches. We forcibly go around it by extracting the value manually. # # Bug ticket: https://gitlab.kitware.com/cmake/cmake/-/issues/22735 # # ticket closed with by-design. We should find a way to fix the Mock tests to not consume the public API using # mixed style includes. get_target_property(OPENCL_HEADERS_INTERFACE_INCLUDE_DIRECTORIES OpenCL::Headers INTERFACE_INCLUDE_DIRECTORIES) if(OPENCL_HEADERS_INTERFACE_INCLUDE_DIRECTORIES MATCHES "BUILD_INTERFACE") # When building OpenCL::Headers is part of this build (OpenCL-SDK), we have a property like for eg. # $;$ # and need to touch up this property. We want the BUILD_INTERFACE part only. # When OpenCL::Headers is consumed through a Package Config file (OpenCL-CLHPP), this property # no longer holds unevaluated generator expressions. string(REGEX MATCHALL [[\$;]] OPENCL_HEADERS_INTERFACE_INCLUDE_DIRECTORIES "${OPENCL_HEADERS_INTERFACE_INCLUDE_DIRECTORIES}") set(OPENCL_HEADERS_INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_MATCH_1}") endif() # End of workaround add_custom_command( OUTPUT stripped/cl.h stripped/cl_ext.h stripped/cl_gl.h COMMAND ${CMAKE_COMMAND} -E make_directory stripped COMMAND ${CMAKE_COMMAND} -E make_directory mocks COMMAND ${CMAKE_COMMAND} -D INPUT="${OPENCL_HEADERS_INTERFACE_INCLUDE_DIRECTORIES}/CL/cl.h" -D OUTPUT="stripped/cl.h" -P ${CMAKE_CURRENT_SOURCE_DIR}/strip_defines.cmake COMMAND ${CMAKE_COMMAND} -D INPUT="${OPENCL_HEADERS_INTERFACE_INCLUDE_DIRECTORIES}/CL/cl_ext.h" -D OUTPUT="stripped/cl_ext.h" -P ${CMAKE_CURRENT_SOURCE_DIR}/strip_defines.cmake COMMAND ${CMAKE_COMMAND} -D INPUT="${OPENCL_HEADERS_INTERFACE_INCLUDE_DIRECTORIES}/CL/cl_gl.h" -D OUTPUT="stripped/cl_gl.h" -P ${CMAKE_CURRENT_SOURCE_DIR}/strip_defines.cmake COMMENT "Stripping defines from cl.h, cl_ext.h and cl_gl.h" DEPENDS ${OPENCL_HEADERS_INTERFACE_INCLUDE_DIRECTORIES}/CL/cl.h strip_defines.cmake) add_custom_target( strip_cl_defines ALL DEPENDS stripped/cl.h DEPENDS stripped/cl_ext.h DEPENDS stripped/cl_gl.h SOURCES strip_defines.cmake) add_custom_command( OUTPUT mocks/Mockcl.c mocks/Mockcl.h mocks/Mockcl_ext.c mocks/Mockcl_ext.h mocks/Mockcl_gl.c mocks/Mockcl_gl.h COMMAND ${RUBY_EXECUTABLE} ${CMOCK_DIR}/lib/cmock.rb -o${CMAKE_CURRENT_SOURCE_DIR}/cmock.yml stripped/cl.h COMMAND ${RUBY_EXECUTABLE} ${CMOCK_DIR}/lib/cmock.rb -o${CMAKE_CURRENT_SOURCE_DIR}/cmock.yml stripped/cl_ext.h COMMAND ${RUBY_EXECUTABLE} ${CMOCK_DIR}/lib/cmock.rb -o${CMAKE_CURRENT_SOURCE_DIR}/cmock.yml stripped/cl_gl.h COMMENT "Generating mocks" DEPENDS stripped/cl.h stripped/cl_ext.h stripped/cl_gl.h cmock.yml) add_custom_target( mock_cl_header ALL DEPENDS mocks/Mockcl.c mocks/Mockcl.h DEPENDS mocks/Mockcl_ext.c mocks/Mockcl_ext.h DEPENDS mocks/Mockcl_gl.c mocks/Mockcl_gl.h SOURCES cmock.yml) add_dependencies(mock_cl_header strip_cl_defines) add_custom_command( OUTPUT test_openclhpp_Runner.c COMMAND ${RUBY_EXECUTABLE} ${UNITY_DIR}/auto/generate_test_runner.rb test_openclhpp.cpp cmock.yml ${CMAKE_CURRENT_BINARY_DIR}/test_openclhpp_Runner.c WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} COMMENT "Generating test runner" DEPENDS test_openclhpp.cpp cmock.yml) add_custom_target( openclhpp_runner ALL DEPENDS test_openclhpp_Runner.c SOURCES test_openclhpp.cpp) if(CMAKE_COMPILER_IS_GNUCC OR CMAKE_CXX_COMPILER_ID MATCHES "(Apple)?Clang") add_compile_options(-Wno-deprecated-declarations) elseif(MSVC) add_compile_options(/wd4996) endif() add_definitions(-DCL_TARGET_OPENCL_VERSION=300) add_definitions(-DCL_EXPERIMENTAL) add_definitions(-DUNITY_SUPPORT_64) if( CMAKE_SIZEOF_VOID_P EQUAL 8 ) add_definitions(-DUNITY_POINTER_WIDTH=64) add_definitions("-DCMOCK_MEM_PTR_AS_INT=unsigned long long") add_definitions(-DCMOCK_MEM_ALIGN=3) endif() if( CMAKE_SIZEOF_LONG EQUAL 8 ) add_definitions(-DUNITY_LONG_WIDTH=64) endif() set(TEST_HEADERS ${PROJECT_SOURCE_DIR}/include/CL/opencl.hpp mocks/Mockcl.h mocks/Mockcl_ext.h mocks/Mockcl_gl.h) set(TEST_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/test_openclhpp_Runner.c test_openclhpp.cpp ${CMAKE_CURRENT_BINARY_DIR}/mocks/Mockcl.c ${CMAKE_CURRENT_BINARY_DIR}/mocks/Mockcl_ext.c ${CMAKE_CURRENT_BINARY_DIR}/mocks/Mockcl_gl.c ${CMOCK_DIR}/src/cmock.c ${UNITY_DIR}/src/unity.c) # TODO enable testing for OpenCL 1.0 and 1.1 foreach(VERSION 120 200 210 220 300) foreach(OPTION "" CL_HPP_ENABLE_EXCEPTIONS CL_HPP_ENABLE_SIZE_T_COMPATIBILITY CL_HPP_ENABLE_PROGRAM_CONSTRUCTION_FROM_ARRAY_COMPATIBILITY CL_HPP_CL_1_2_DEFAULT_BUILD CL_HPP_USE_CL_SUB_GROUPS_KHR CL_HPP_USE_IL_KHR) if(OPTION STREQUAL "") # The empty string means we're not setting any special option. set(UNDERSCORE_OPTION "${OPTION}") set(DEFINE_OPTION "") else() set(UNDERSCORE_OPTION "_${OPTION}") set(DEFINE_OPTION "-D${OPTION}") endif() set(TEST_EXE test_openclhpp_${VERSION}${UNDERSCORE_OPTION}) add_executable(${TEST_EXE} ${TEST_SOURCES}) #${TEST_HEADERS}) target_link_libraries(${TEST_EXE} PRIVATE OpenCL::HeadersCpp OpenCL::Headers Threads::Threads ) target_include_directories(${TEST_EXE} PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/mocks ${OPENCL_HEADERS_INTERFACE_INCLUDE_DIRECTORIES}/CL #${OPENCL_HEADERS_INCLUDE_DIR_GENEXPR}/CL ${UNITY_DIR}/src ${CMOCK_DIR}/src ) target_compile_definitions(${TEST_EXE} PUBLIC -DCL_HPP_TARGET_OPENCL_VERSION=${VERSION} ${DEFINE_OPTION} ) add_dependencies(${TEST_EXE} strip_cl_defines mock_cl_header openclhpp_runner ) add_test(NAME ${TEST_EXE} COMMAND ${TEST_EXE}) endforeach(OPTION) endforeach(VERSION) if(NOT TARGET OpenCL::openCL) find_package(OpenCLICDLoader) endif() if(TARGET OpenCL::OpenCL) # TODO enable testing for OpenCL 1.0 and 1.1 foreach(MINVERSION 120 200 210 220 300) foreach(TARGETVERSION 120 200 210 220 300) if(NOT (${MINVERSION} GREATER ${TARGETVERSION})) set(TEST_EXE test_openclhpp_version_min_${MINVERSION}_target_${TARGETVERSION}) add_executable(${TEST_EXE} test_versions.cpp) target_compile_definitions(${TEST_EXE} PUBLIC CL_HPP_MINIMUM_OPENCL_VERSION=${MINVERSION} CL_HPP_TARGET_OPENCL_VERSION=${TARGETVERSION}) target_link_libraries(${TEST_EXE} PRIVATE OpenCL::HeadersCpp OpenCL::Headers OpenCL::OpenCL) add_test(NAME ${TEST_EXE} COMMAND ${TEST_EXE}) endif() endforeach() endforeach() endif()