xref: /llvm-project/mlir/cmake/modules/FindLevelZero.cmake (revision 7fa19e6f4b87623b0ca1a23bf6b6293c1b5e5799)
1# CMake find_package() module for level-zero
2#
3# Example usage:
4#
5# find_package(LevelZero)
6#
7# If successful, the following variables will be defined:
8# LevelZero_FOUND
9# LevelZero_INCLUDE_DIRS
10# LevelZero_LIBRARY
11# LevelZero_LIBRARIES_DIR
12#
13# By default, the module searches the standard paths to locate the "ze_api.h"
14# and the ze_loader shared library. When using a custom level-zero installation,
15# the environment variable "LEVEL_ZERO_DIR" should be specified telling the
16# module to get the level-zero library and headers from that location.
17
18include(FindPackageHandleStandardArgs)
19
20# Search path priority
21# 1. CMake Variable LEVEL_ZERO_DIR
22# 2. Environment Variable LEVEL_ZERO_DIR
23
24if(NOT LEVEL_ZERO_DIR)
25    if(DEFINED ENV{LEVEL_ZERO_DIR})
26        set(LEVEL_ZERO_DIR "$ENV{LEVEL_ZERO_DIR}")
27    endif()
28endif()
29
30if(LEVEL_ZERO_DIR)
31    find_path(LevelZero_INCLUDE_DIR
32        NAMES level_zero/ze_api.h
33        PATHS ${LEVEL_ZERO_DIR}/include
34        NO_DEFAULT_PATH
35    )
36
37    if(LINUX)
38        find_library(LevelZero_LIBRARY
39            NAMES ze_loader
40            PATHS ${LEVEL_ZERO_DIR}/lib
41                  ${LEVEL_ZERO_DIR}/lib/x86_64-linux-gnu
42            NO_DEFAULT_PATH
43        )
44    else()
45        find_library(LevelZero_LIBRARY
46            NAMES ze_loader
47            PATHS ${LEVEL_ZERO_DIR}/lib
48            NO_DEFAULT_PATH
49        )
50    endif()
51else()
52    find_path(LevelZero_INCLUDE_DIR
53        NAMES level_zero/ze_api.h
54    )
55
56    find_library(LevelZero_LIBRARY
57        NAMES ze_loader
58    )
59endif()
60
61# Compares the two version string that are supposed to be in x.y.z format
62# and reports if the argument VERSION_STR1 is greater than or equal than
63# version_str2. The strings are compared lexicographically after conversion to
64# lists of equal lengths, with the shorter string getting zero-padded.
65function(compare_versions VERSION_STR1 VERSION_STR2 OUTPUT)
66    # Convert the strings to list
67    string(REPLACE  "." ";" VL1 ${VERSION_STR1})
68    string(REPLACE  "." ";" VL2 ${VERSION_STR2})
69    # get lengths of both lists
70    list(LENGTH VL1 VL1_LEN)
71    list(LENGTH VL2 VL2_LEN)
72    set(LEN ${VL1_LEN})
73    # If they differ in size pad the shorter list with 0s
74    if(VL1_LEN GREATER VL2_LEN)
75        math(EXPR DIFF "${VL1_LEN} - ${VL2_LEN}" OUTPUT_FORMAT DECIMAL)
76        foreach(IDX RANGE 1 ${DIFF} 1)
77            list(APPEND VL2 "0")
78        endforeach()
79    elseif(VL2_LEN GREATER VL2_LEN)
80        math(EXPR DIFF "${VL1_LEN} - ${VL2_LEN}" OUTPUT_FORMAT DECIMAL)
81        foreach(IDX RANGE 1 ${DIFF} 1)
82            list(APPEND VL2 "0")
83        endforeach()
84        set(LEN ${VL2_LEN})
85    endif()
86    math(EXPR LEN_SUB_ONE "${LEN}-1")
87    foreach(IDX RANGE 0 ${LEN_SUB_ONE} 1)
88        list(GET VL1 ${IDX} VAL1)
89        list(GET VL2 ${IDX} VAL2)
90
91        if(${VAL1} GREATER ${VAL2})
92            set(${OUTPUT} TRUE PARENT_SCOPE)
93            break()
94        elseif(${VAL1} LESS ${VAL2})
95            set(${OUTPUT} FALSE PARENT_SCOPE)
96            break()
97        else()
98            set(${OUTPUT} TRUE PARENT_SCOPE)
99        endif()
100    endforeach()
101
102    endfunction(compare_versions)
103
104# Creates a small function to run and extract the LevelZero loader version.
105function(get_l0_loader_version)
106
107    set(L0_VERSIONEER_SRC
108        [====[
109        #include <iostream>
110        #include <level_zero/loader/ze_loader.h>
111        #include <string>
112        int main() {
113            ze_result_t result;
114            std::string loader("loader");
115            zel_component_version_t *versions;
116            size_t size = 0;
117            result = zeInit(0);
118            if (result != ZE_RESULT_SUCCESS) {
119                std::cerr << "Failed to init ze driver" << std::endl;
120                return -1;
121            }
122            zelLoaderGetVersions(&size, nullptr);
123            versions = new zel_component_version_t[size];
124            zelLoaderGetVersions(&size, versions);
125            for (size_t i = 0; i < size; i++) {
126                if (loader.compare(versions[i].component_name) == 0) {
127                    std::cout << versions[i].component_lib_version.major << "."
128                              << versions[i].component_lib_version.minor << "."
129                              << versions[i].component_lib_version.patch;
130                    break;
131                }
132            }
133            delete[] versions;
134            return 0;
135        }
136        ]====]
137    )
138
139    set(L0_VERSIONEER_FILE ${CMAKE_BINARY_DIR}/temp/l0_versioneer.cpp)
140
141    file(WRITE ${L0_VERSIONEER_FILE} "${L0_VERSIONEER_SRC}")
142
143    # We need both the directories in the include path as ze_loader.h
144    # includes "ze_api.h" and not "level_zero/ze_api.h".
145    list(APPEND INCLUDE_DIRS ${LevelZero_INCLUDE_DIR})
146    list(APPEND INCLUDE_DIRS ${LevelZero_INCLUDE_DIR}/level_zero)
147    list(JOIN INCLUDE_DIRS ";" INCLUDE_DIRS_STR)
148    try_run(L0_VERSIONEER_RUN L0_VERSIONEER_COMPILE
149            "${CMAKE_BINARY_DIR}"
150            "${L0_VERSIONEER_FILE}"
151            LINK_LIBRARIES ${LevelZero_LIBRARY}
152            CMAKE_FLAGS
153                "-DINCLUDE_DIRECTORIES=${INCLUDE_DIRS_STR}"
154            RUN_OUTPUT_VARIABLE L0_VERSION
155    )
156    if(${L0_VERSIONEER_COMPILE} AND (DEFINED L0_VERSIONEER_RUN))
157        set(LevelZero_VERSION ${L0_VERSION} PARENT_SCOPE)
158        message(STATUS "Found Level Zero of version: ${L0_VERSION}")
159    else()
160        message(FATAL_ERROR
161            "Could not compile a level-zero program to extract loader version"
162        )
163    endif()
164endfunction(get_l0_loader_version)
165
166if(LevelZero_INCLUDE_DIR AND LevelZero_LIBRARY)
167    list(APPEND LevelZero_LIBRARIES "${LevelZero_LIBRARY}")
168    list(APPEND LevelZero_INCLUDE_DIRS ${LevelZero_INCLUDE_DIR})
169    if(OpenCL_FOUND)
170      list(APPEND LevelZero_INCLUDE_DIRS ${OpenCL_INCLUDE_DIRS})
171    endif()
172
173    cmake_path(GET LevelZero_LIBRARY PARENT_PATH LevelZero_LIBRARIES_PATH)
174    set(LevelZero_LIBRARIES_DIR ${LevelZero_LIBRARIES_PATH})
175
176    if(NOT TARGET LevelZero::LevelZero)
177      add_library(LevelZero::LevelZero INTERFACE IMPORTED)
178      set_target_properties(LevelZero::LevelZero
179        PROPERTIES INTERFACE_LINK_LIBRARIES "${LevelZero_LIBRARIES}"
180      )
181      set_target_properties(LevelZero::LevelZero
182        PROPERTIES INTERFACE_INCLUDE_DIRECTORIES "${LevelZero_INCLUDE_DIRS}"
183      )
184    endif()
185endif()
186
187# Check if a specific version of Level Zero is required
188if(LevelZero_FIND_VERSION)
189    get_l0_loader_version()
190    set(VERSION_GT_FIND_VERSION FALSE)
191    compare_versions(
192        ${LevelZero_VERSION}
193        ${LevelZero_FIND_VERSION}
194        VERSION_GT_FIND_VERSION
195    )
196    if(${VERSION_GT_FIND_VERSION})
197        set(LevelZero_FOUND TRUE)
198    else()
199        set(LevelZero_FOUND FALSE)
200    endif()
201else()
202    set(LevelZero_FOUND TRUE)
203endif()
204
205find_package_handle_standard_args(LevelZero
206    REQUIRED_VARS
207        LevelZero_FOUND
208        LevelZero_INCLUDE_DIRS
209        LevelZero_LIBRARY
210        LevelZero_LIBRARIES_DIR
211    HANDLE_COMPONENTS
212)
213mark_as_advanced(LevelZero_LIBRARY LevelZero_INCLUDE_DIRS)
214
215if(LevelZero_FOUND)
216    find_package_message(LevelZero "Found LevelZero: ${LevelZero_LIBRARY}"
217        "(found version ${LevelZero_VERSION})"
218    )
219else()
220    find_package_message(LevelZero "Could not find LevelZero" "")
221endif()
222