| # Copyright 2026 The IREE Authors |
| # |
| # Licensed under the Apache License v2.0 with LLVM Exceptions. |
| # See https://llvm.org/LICENSE.txt for license information. |
| # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
| |
| # iree_hal_executable() |
| # |
| # Compiles an MLIR source to a HAL executable binary using iree-compile in |
| # hal-executable mode. Unlike iree_bytecode_module() which produces full VM |
| # bytecode modules, this produces backend-specific device code for a single |
| # target. |
| # |
| # Parameters: |
| # NAME: Name of target. |
| # SRC: MLIR source file to compile. |
| # TARGET_DEVICE: Target device (e.g., "local", "vulkan", "hip", "cuda"). |
| # Generates --iree-hal-target-device=<value>. |
| # FLAGS: Additional compiler flags (list of strings). For devices with |
| # sub-backends (like "local"), pass the backend selection flag here |
| # (e.g., "--iree-hal-local-target-device-backends=vmvx"). |
| # EXECUTABLE_FILE_NAME: Optional output filename. Defaults to ${NAME}.bin. |
| # COMPILE_TOOL: Compiler tool to invoke. Defaults to "iree-compile". |
| # C_IDENTIFIER: Identifier for generated C embed code. If omitted, no |
| # C embed code is generated. |
| # FRIENDLY_NAME: Optional display name for build progress. |
| # PUBLIC: Export under ${PACKAGE}::. |
| # TESTONLY: Only build if IREE_BUILD_TESTS=ON. |
| # DEPENDS: Additional build dependencies beyond SRC and tools. |
| # DEPS: Library dependencies for the generated embed cc library. |
| function(iree_hal_executable) |
| cmake_parse_arguments( |
| _RULE |
| "PUBLIC;TESTONLY" |
| "NAME;SRC;TARGET_DEVICE;EXECUTABLE_FILE_NAME;COMPILE_TOOL;C_IDENTIFIER;FRIENDLY_NAME" |
| "FLAGS;DEPENDS;DEPS" |
| ${ARGN} |
| ) |
| |
| if(_RULE_TESTONLY AND NOT IREE_BUILD_TESTS) |
| return() |
| endif() |
| |
| if(NOT DEFINED _RULE_SRC) |
| message(SEND_ERROR "iree_hal_executable requires SRC") |
| endif() |
| |
| if(NOT DEFINED _RULE_TARGET_DEVICE) |
| message(SEND_ERROR "iree_hal_executable requires TARGET_DEVICE") |
| endif() |
| |
| # Set default for COMPILE_TOOL. |
| if(DEFINED _RULE_COMPILE_TOOL) |
| set(_COMPILE_TOOL ${_RULE_COMPILE_TOOL}) |
| else() |
| set(_COMPILE_TOOL "iree-compile") |
| endif() |
| |
| if(DEFINED _RULE_EXECUTABLE_FILE_NAME) |
| set(_EXECUTABLE_FILE_NAME "${_RULE_EXECUTABLE_FILE_NAME}") |
| else() |
| set(_EXECUTABLE_FILE_NAME "${_RULE_NAME}.bin") |
| endif() |
| |
| set(_ARGS |
| "--compile-mode=hal-executable" |
| "--iree-hal-target-device=${_RULE_TARGET_DEVICE}" |
| "--mlir-print-op-on-diagnostic=false" |
| ) |
| list(APPEND _ARGS "${_RULE_FLAGS}") |
| |
| get_filename_component(_SRC_PATH "${_RULE_SRC}" REALPATH) |
| list(APPEND _ARGS "${_SRC_PATH}") |
| list(APPEND _ARGS "-o") |
| list(APPEND _ARGS "${_EXECUTABLE_FILE_NAME}") |
| |
| # Add the build directory to the compiler object file search path. |
| list(APPEND _ARGS "--iree-hal-executable-object-search-path=\"${IREE_BINARY_DIR}\"") |
| |
| set(_OUTPUT_FILES "${_EXECUTABLE_FILE_NAME}") |
| |
| # If targeting a local device with llvm-cpu, pass linker paths. |
| if (_RULE_FLAGS MATCHES "target-device-backends=llvm-cpu") |
| if (IREE_LLD_BINARY) |
| list(APPEND _ARGS "--iree-llvmcpu-embedded-linker-path=\"${IREE_LLD_BINARY}\"") |
| list(APPEND _ARGS "--iree-llvmcpu-wasm-linker-path=\"${IREE_LLD_BINARY}\"") |
| endif() |
| endif() |
| |
| iree_compile_flags_for_platform(_PLATFORM_FLAGS "${_RULE_FLAGS}") |
| if(_PLATFORM_FLAGS) |
| list(APPEND _ARGS ${_PLATFORM_FLAGS}) |
| endif() |
| |
| if(_RULE_FRIENDLY_NAME) |
| set(_FRIENDLY_NAME "${_RULE_FRIENDLY_NAME}") |
| else() |
| get_filename_component(_FRIENDLY_NAME "${_RULE_SRC}" NAME) |
| endif() |
| |
| set(_DEPENDS "") |
| iree_package_ns(_PACKAGE_NAME) |
| list(TRANSFORM _RULE_DEPENDS REPLACE "^::" "${_PACKAGE_NAME}::") |
| foreach(_DEPEND ${_RULE_DEPENDS}) |
| string(REPLACE "::" "_" _DEPEND "${_DEPEND}") |
| list(APPEND _DEPENDS ${_DEPEND}) |
| endforeach() |
| |
| add_custom_command( |
| OUTPUT |
| ${_OUTPUT_FILES} |
| COMMAND |
| ${_COMPILE_TOOL} |
| ${_ARGS} |
| DEPENDS |
| ${_COMPILE_TOOL} |
| ${_RULE_SRC} |
| ${_DEPENDS} |
| COMMENT |
| "Generating HAL executable ${_EXECUTABLE_FILE_NAME} from ${_FRIENDLY_NAME}" |
| VERBATIM |
| ) |
| |
| iree_package_name(_PACKAGE_NAME) |
| add_custom_target("${_PACKAGE_NAME}_${_RULE_NAME}" |
| DEPENDS "${_EXECUTABLE_FILE_NAME}" |
| ) |
| |
| if(_RULE_TESTONLY) |
| set(_TESTONLY_ARG "TESTONLY") |
| endif() |
| if(_RULE_PUBLIC) |
| set(_PUBLIC_ARG "PUBLIC") |
| endif() |
| |
| if(_RULE_C_IDENTIFIER) |
| iree_c_embed_data( |
| NAME |
| "${_RULE_NAME}_c" |
| IDENTIFIER |
| "${_RULE_C_IDENTIFIER}" |
| SRCS |
| "${_EXECUTABLE_FILE_NAME}" |
| C_FILE_OUTPUT |
| "${_RULE_NAME}_c.c" |
| H_FILE_OUTPUT |
| "${_RULE_NAME}_c.h" |
| FLATTEN |
| "${_PUBLIC_ARG}" |
| "${_TESTONLY_ARG}" |
| DEPS |
| ${_RULE_DEPS} |
| ) |
| endif() |
| endfunction() |
| |
| # iree_hal_executables() |
| # |
| # Batch form of iree_hal_executable(). Compiles multiple MLIR sources to HAL |
| # executables and bundles all outputs into a single iree_c_embed_data() |
| # cc_library target. |
| # |
| # TOC entry names are the source stems with a .bin extension (e.g., |
| # "dispatch.mlir" produces TOC entry "dispatch.bin"). |
| # |
| # Multiple calls in the same directory (for different formats) are safe: |
| # each call's compiled outputs use a {NAME}/ subdirectory prefix for the |
| # output filename, and FLATTEN on the embedded data strips it from TOC entries. |
| # |
| # Parameters: |
| # NAME: Name of the output iree_c_embed_data cc_library target. |
| # SRCS: MLIR source files to compile. Each produces one executable binary. |
| # TARGET_DEVICE: Target device for iree-compile. |
| # FLAGS: Backend-specific compiler flags. |
| # IDENTIFIER: C identifier for generated embed data. Defaults to NAME. |
| # COMPILE_TOOL: Compiler tool. Defaults to "iree-compile". |
| # PUBLIC: Export under ${PACKAGE}::. |
| # TESTONLY: Only build if IREE_BUILD_TESTS=ON. |
| function(iree_hal_executables) |
| cmake_parse_arguments( |
| _RULE |
| "PUBLIC;TESTONLY" |
| "NAME;TARGET_DEVICE;IDENTIFIER;COMPILE_TOOL" |
| "SRCS;FLAGS" |
| ${ARGN} |
| ) |
| |
| if(_RULE_TESTONLY AND NOT IREE_BUILD_TESTS) |
| return() |
| endif() |
| |
| if(NOT DEFINED _RULE_TARGET_DEVICE) |
| message(SEND_ERROR "iree_hal_executables requires TARGET_DEVICE") |
| endif() |
| |
| if(DEFINED _RULE_IDENTIFIER) |
| set(_IDENTIFIER "${_RULE_IDENTIFIER}") |
| else() |
| set(_IDENTIFIER "${_RULE_NAME}") |
| endif() |
| |
| if(_RULE_TESTONLY) |
| set(_TESTONLY_ARG "TESTONLY") |
| endif() |
| if(_RULE_PUBLIC) |
| set(_PUBLIC_ARG "PUBLIC") |
| endif() |
| |
| set(_COMPILE_TOOL_ARG "") |
| if(DEFINED _RULE_COMPILE_TOOL) |
| set(_COMPILE_TOOL_ARG "COMPILE_TOOL" "${_RULE_COMPILE_TOOL}") |
| endif() |
| |
| # Compile each MLIR source to a HAL executable. |
| set(_BIN_OUTPUTS "") |
| foreach(_SRC ${_RULE_SRCS}) |
| # Derive stem from source path: "/path/to/foo.mlir" -> "foo". |
| get_filename_component(_STEM "${_SRC}" NAME_WE) |
| |
| # Output files use a {NAME}/ subdirectory prefix for uniqueness across |
| # multiple iree_hal_executables() calls in the same directory. |
| set(_EXECUTABLE_FILE_NAME "${_RULE_NAME}/${_STEM}.bin") |
| set(_RULE_ENTRY_NAME "${_RULE_NAME}_${_STEM}") |
| |
| iree_hal_executable( |
| NAME "${_RULE_ENTRY_NAME}" |
| SRC "${_SRC}" |
| TARGET_DEVICE "${_RULE_TARGET_DEVICE}" |
| FLAGS ${_RULE_FLAGS} |
| EXECUTABLE_FILE_NAME "${_EXECUTABLE_FILE_NAME}" |
| ${_COMPILE_TOOL_ARG} |
| ${_TESTONLY_ARG} |
| ) |
| |
| list(APPEND _BIN_OUTPUTS "${_EXECUTABLE_FILE_NAME}") |
| endforeach() |
| |
| # Bundle all compiled executables into a single embedded data library. |
| iree_c_embed_data( |
| NAME |
| "${_RULE_NAME}" |
| IDENTIFIER |
| "${_IDENTIFIER}" |
| SRCS |
| ${_BIN_OUTPUTS} |
| C_FILE_OUTPUT |
| "${_RULE_NAME}.c" |
| H_FILE_OUTPUT |
| "${_RULE_NAME}.h" |
| FLATTEN |
| "${_PUBLIC_ARG}" |
| "${_TESTONLY_ARG}" |
| ) |
| endfunction() |