# CMake find_package() module for level-zero # # Example usage: # # find_package(LevelZero) # # If successful, the following variables will be defined: # LevelZero_FOUND # LevelZero_INCLUDE_DIRS # LevelZero_LIBRARY # LevelZero_LIBRARIES_DIR # # By default, the module searches the standard paths to locate the "ze_api.h" # and the ze_loader shared library. When using a custom level-zero installation, # the environment variable "LEVEL_ZERO_DIR" should be specified telling the # module to get the level-zero library and headers from that location. include(FindPackageHandleStandardArgs) # Search path priority # 1. CMake Variable LEVEL_ZERO_DIR # 2. Environment Variable LEVEL_ZERO_DIR if(NOT LEVEL_ZERO_DIR) if(DEFINED ENV{LEVEL_ZERO_DIR}) set(LEVEL_ZERO_DIR "$ENV{LEVEL_ZERO_DIR}") endif() endif() if(LEVEL_ZERO_DIR) find_path(LevelZero_INCLUDE_DIR NAMES level_zero/ze_api.h PATHS ${LEVEL_ZERO_DIR}/include NO_DEFAULT_PATH ) if(LINUX) find_library(LevelZero_LIBRARY NAMES ze_loader PATHS ${LEVEL_ZERO_DIR}/lib ${LEVEL_ZERO_DIR}/lib/x86_64-linux-gnu NO_DEFAULT_PATH ) else() find_library(LevelZero_LIBRARY NAMES ze_loader PATHS ${LEVEL_ZERO_DIR}/lib NO_DEFAULT_PATH ) endif() else() find_path(LevelZero_INCLUDE_DIR NAMES level_zero/ze_api.h ) find_library(LevelZero_LIBRARY NAMES ze_loader ) endif() # Compares the two version string that are supposed to be in x.y.z format # and reports if the argument VERSION_STR1 is greater than or equal than # version_str2. The strings are compared lexicographically after conversion to # lists of equal lengths, with the shorter string getting zero-padded. function(compare_versions VERSION_STR1 VERSION_STR2 OUTPUT) # Convert the strings to list string(REPLACE "." ";" VL1 ${VERSION_STR1}) string(REPLACE "." ";" VL2 ${VERSION_STR2}) # get lengths of both lists list(LENGTH VL1 VL1_LEN) list(LENGTH VL2 VL2_LEN) set(LEN ${VL1_LEN}) # If they differ in size pad the shorter list with 0s if(VL1_LEN GREATER VL2_LEN) math(EXPR DIFF "${VL1_LEN} - ${VL2_LEN}" OUTPUT_FORMAT DECIMAL) foreach(IDX RANGE 1 ${DIFF} 1) list(APPEND VL2 "0") endforeach() elseif(VL2_LEN GREATER VL2_LEN) math(EXPR DIFF "${VL1_LEN} - ${VL2_LEN}" OUTPUT_FORMAT DECIMAL) foreach(IDX RANGE 1 ${DIFF} 1) list(APPEND VL2 "0") endforeach() set(LEN ${VL2_LEN}) endif() math(EXPR LEN_SUB_ONE "${LEN}-1") foreach(IDX RANGE 0 ${LEN_SUB_ONE} 1) list(GET VL1 ${IDX} VAL1) list(GET VL2 ${IDX} VAL2) if(${VAL1} GREATER ${VAL2}) set(${OUTPUT} TRUE PARENT_SCOPE) break() elseif(${VAL1} LESS ${VAL2}) set(${OUTPUT} FALSE PARENT_SCOPE) break() else() set(${OUTPUT} TRUE PARENT_SCOPE) endif() endforeach() endfunction(compare_versions) # Creates a small function to run and extract the LevelZero loader version. function(get_l0_loader_version) set(L0_VERSIONEER_SRC [====[ #include #include #include int main() { ze_result_t result; std::string loader("loader"); zel_component_version_t *versions; size_t size = 0; result = zeInit(0); if (result != ZE_RESULT_SUCCESS) { std::cerr << "Failed to init ze driver" << std::endl; return -1; } zelLoaderGetVersions(&size, nullptr); versions = new zel_component_version_t[size]; zelLoaderGetVersions(&size, versions); for (size_t i = 0; i < size; i++) { if (loader.compare(versions[i].component_name) == 0) { std::cout << versions[i].component_lib_version.major << "." << versions[i].component_lib_version.minor << "." << versions[i].component_lib_version.patch; break; } } delete[] versions; return 0; } ]====] ) set(L0_VERSIONEER_FILE ${CMAKE_BINARY_DIR}/temp/l0_versioneer.cpp) file(WRITE ${L0_VERSIONEER_FILE} "${L0_VERSIONEER_SRC}") # We need both the directories in the include path as ze_loader.h # includes "ze_api.h" and not "level_zero/ze_api.h". list(APPEND INCLUDE_DIRS ${LevelZero_INCLUDE_DIR}) list(APPEND INCLUDE_DIRS ${LevelZero_INCLUDE_DIR}/level_zero) list(JOIN INCLUDE_DIRS ";" INCLUDE_DIRS_STR) try_run(L0_VERSIONEER_RUN L0_VERSIONEER_COMPILE "${CMAKE_BINARY_DIR}" "${L0_VERSIONEER_FILE}" LINK_LIBRARIES ${LevelZero_LIBRARY} CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${INCLUDE_DIRS_STR}" RUN_OUTPUT_VARIABLE L0_VERSION ) if(${L0_VERSIONEER_COMPILE} AND (DEFINED L0_VERSIONEER_RUN)) set(LevelZero_VERSION ${L0_VERSION} PARENT_SCOPE) message(STATUS "Found Level Zero of version: ${L0_VERSION}") else() message(FATAL_ERROR "Could not compile a level-zero program to extract loader version" ) endif() endfunction(get_l0_loader_version) if(LevelZero_INCLUDE_DIR AND LevelZero_LIBRARY) list(APPEND LevelZero_LIBRARIES "${LevelZero_LIBRARY}") list(APPEND LevelZero_INCLUDE_DIRS ${LevelZero_INCLUDE_DIR}) if(OpenCL_FOUND) list(APPEND LevelZero_INCLUDE_DIRS ${OpenCL_INCLUDE_DIRS}) endif() cmake_path(GET LevelZero_LIBRARY PARENT_PATH LevelZero_LIBRARIES_PATH) set(LevelZero_LIBRARIES_DIR ${LevelZero_LIBRARIES_PATH}) if(NOT TARGET LevelZero::LevelZero) add_library(LevelZero::LevelZero INTERFACE IMPORTED) set_target_properties(LevelZero::LevelZero PROPERTIES INTERFACE_LINK_LIBRARIES "${LevelZero_LIBRARIES}" ) set_target_properties(LevelZero::LevelZero PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LevelZero_INCLUDE_DIRS}" ) endif() endif() # Check if a specific version of Level Zero is required if(LevelZero_FIND_VERSION) get_l0_loader_version() set(VERSION_GT_FIND_VERSION FALSE) compare_versions( ${LevelZero_VERSION} ${LevelZero_FIND_VERSION} VERSION_GT_FIND_VERSION ) if(${VERSION_GT_FIND_VERSION}) set(LevelZero_FOUND TRUE) else() set(LevelZero_FOUND FALSE) endif() else() set(LevelZero_FOUND TRUE) endif() find_package_handle_standard_args(LevelZero REQUIRED_VARS LevelZero_FOUND LevelZero_INCLUDE_DIRS LevelZero_LIBRARY LevelZero_LIBRARIES_DIR HANDLE_COMPONENTS ) mark_as_advanced(LevelZero_LIBRARY LevelZero_INCLUDE_DIRS) if(LevelZero_FOUND) find_package_message(LevelZero "Found LevelZero: ${LevelZero_LIBRARY}" "(found version ${LevelZero_VERSION})" ) else() find_package_message(LevelZero "Could not find LevelZero" "") endif()