| # Copyright 2023 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_experimental_standalone_plugin_arch() |
| # |
| # Helper for iree_experimental_standalone_plugin, building one |
| # architecture. |
| # |
| # Parameters: |
| # NAME: Name of the system plugin to create. |
| # ARCH: Name of architecture (as in IREE_ARCH) to build for. |
| # Example: "arm_64". |
| # COPTS: List of compiler options to be applied to all source files. |
| # SRCS: List of source files. Each list entry may be of one of two forms: |
| # * Each entry that does not contain a colon is interpreted as a source |
| # file path, to be built unconditionally, with the compiler options |
| # specified in `COPTS`. |
| # * Each entry that contains a colon is interpreted as a colon-separated |
| # list of length either 2 or 3. Format: |
| # `ARCH:FILE[:FILE_COPTS_VAR_NAME]`. |
| # Any entry whose `ARCH` does not match this rules's `ARCH` parameter |
| # is filtered out. Remaining files are compiled with the |
| # architecture-wide compiler options (see `COPTS`) and, if provided, |
| # with the file-specific compiler options from expanding the variable |
| # specified in `FILE_COPTS_VAR_NAME`. |
| # Example: "x86_64:some_file_for_x86_64_using_avx512_instructions.c:NAME_OF_VARIABLE_CONTAINING_COPTS_FOR_X86_64_AVX512". |
| function(iree_experimental_standalone_plugin_arch) |
| cmake_parse_arguments( |
| _RULE |
| "" |
| "NAME;ARCH" |
| "SRCS;COPTS" |
| ${ARGN} |
| ) |
| |
| iree_package_name(_PACKAGE_NAME) |
| set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}_${_RULE_ARCH}") |
| iree_arch_to_llvm_arch(LLVM_ARCH "${_RULE_ARCH}") |
| |
| foreach(_SRC_ENTRY_COLON_SEPARATED IN LISTS _RULE_SRCS) |
| string(REPLACE ":" ";" _SRC_ENTRY_LIST "${_SRC_ENTRY_COLON_SEPARATED}") |
| list(LENGTH _SRC_ENTRY_LIST _SRC_ENTRY_LIST_LENGTH) |
| set(_SRC_COPTS_VAR_NAME "") |
| set(_SRC_FILE "") |
| if(_SRC_ENTRY_LIST_LENGTH EQUAL 1) |
| set(_SRC_FILE "${_SRC_ENTRY_LIST}") |
| else() # NOT _SRC_ENTRY_LIST_LENGTH EQUAL 1 |
| list(GET _SRC_ENTRY_LIST 0 _SRC_ARCH) |
| if(NOT _SRC_ARCH STREQUAL _RULE_ARCH) |
| continue() |
| endif() |
| list(GET _SRC_ENTRY_LIST 1 _SRC_FILE) |
| if(_SRC_ENTRY_LIST_LENGTH EQUAL 3) |
| list(GET _SRC_ENTRY_LIST 2 _SRC_COPTS_VAR_NAME) |
| endif() |
| endif() # NOT _SRC_ENTRY_LIST_LENGTH EQUAL 1 |
| |
| set(_SRC_COPTS "${${_SRC_COPTS_VAR_NAME}}") |
| |
| get_filename_component(_SRC_FILE_BASENAME "${_SRC_FILE}" NAME) |
| |
| if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/${_SRC_FILE}") |
| set(_SRC_FILE "${CMAKE_CURRENT_SOURCE_DIR}/${_SRC_FILE}") |
| endif() |
| |
| if(EXISTS "${PROJECT_SOURCE_DIR}/${_SRC_FILE}") |
| set(_SRC_FILE "${PROJECT_SOURCE_DIR}/${_SRC_FILE}") |
| endif() |
| |
| set(_OBJECT_FILE "${_SRC_FILE_BASENAME}.${_RULE_ARCH}.o") |
| list(APPEND _OBJECT_FILES "${CMAKE_CURRENT_BINARY_DIR}/${_OBJECT_FILE}") |
| add_custom_command( |
| OUTPUT |
| "${_OBJECT_FILE}" |
| DEPENDS |
| "${_SRC_FILE}" |
| "${IREE_CLANG_TARGET}" |
| COMMAND "${IREE_CLANG_BINARY}" |
| # Flags copied from |
| # compiler/src/iree/compiler/Dialect/HAL/Target/LLVMCPU/internal/EmbeddedLinkerTool.cpp |
| -target "${LLVM_ARCH}-unknown-unknown-eabi-elf" |
| -isystem "${IREE_CLANG_BUILTIN_HEADERS_PATH}" |
| -std=c17 |
| -fasm # Added for inline-asm support. |
| -fPIC |
| -ffreestanding |
| -fvisibility=hidden |
| -fno-plt |
| -fno-rtti |
| -fno-exceptions |
| -fdata-sections |
| -ffunction-sections |
| -funique-section-names |
| -DIREE_DEVICE_STANDALONE |
| -I "${IREE_SOURCE_DIR}/runtime/src/" |
| -c "${_SRC_FILE}" |
| -o "${CMAKE_CURRENT_BINARY_DIR}/${_OBJECT_FILE}" |
| ${_RULE_COPTS} |
| ${_SRC_COPTS} |
| VERBATIM |
| ) |
| endforeach() |
| set(_OUTPUT_SO_FILE "${CMAKE_CURRENT_BINARY_DIR}/${_RULE_NAME}.${_RULE_ARCH}.so") |
| add_custom_command( |
| OUTPUT |
| ${_OUTPUT_SO_FILE} |
| DEPENDS |
| ${_OBJECT_FILES} |
| ${IREE_LLD_TARGET} |
| COMMAND ${IREE_LLD_BINARY} |
| -flavor gnu |
| --build-id=none |
| -nostdlib |
| -static |
| -shared |
| --no-undefined |
| --no-allow-shlib-undefined |
| --allow-multiple-definition |
| --gc-sections |
| -z now |
| -z relro |
| --discard-all |
| --icf=all |
| --ignore-data-address-equality |
| --ignore-function-address-equality |
| --hash-style=sysv |
| --strip-debug |
| ${_OBJECT_FILES} |
| -o "${_OUTPUT_SO_FILE}" |
| VERBATIM |
| ) |
| add_custom_target(${_NAME} DEPENDS |
| "${_OUTPUT_SO_FILE}" |
| ) |
| endfunction() |
| |
| # iree_experimental_standalone_plugin() |
| # |
| # Creates a standalone plugin library, that is built using our in-tree Clang |
| # toolchain for multiple target architectures, generating a fat embedded-elf, |
| # and may be loaded with the embedded dynamic library loaded. |
| # |
| # Contrast with: iree_experimental_system_plugin. |
| # |
| # Parameters: |
| # NAME: Name of the system plugin to create. |
| # ARCHS: List of architectures (as in IREE_ARCH) to build. Format: |
| # `ARCH[:ARCH_COPTS_VAR_NAME]`. If provided, `ARCH_COPTS_VAR_NAME` is |
| # interpreted as the name of a variable to be expanded into all compiler |
| # command lines used for architecture `ARCH`. |
| # Example: "arm_64:NAME_OF_VARIABLE_CONTAINING_COPTS_FOR_ARM_64". |
| # SRCS: List of source files. Each list entry may be of one of two forms: |
| # * Each entry that does not contain a colon is interpreted as a source |
| # file path, to be built for all architectures with the |
| # architecture-wide compiler options provided for each architecture |
| # (see `ARCHS`). |
| # * Each entry that contains a colon is interpreted as a colon-separated |
| # list of length either 2 or 3. Format: |
| # `ARCH:FILE[:FILE_COPTS_VAR_NAME]`. |
| # The specified source `FILE` is compiled only for the specified |
| # architecture `ARCH` and is skipped on other architectures. It is |
| # compiled with the architecture-wide compiler options |
| # (see `ARCHS`) and, if provided, with the file-specific compiler |
| # options from expanding the variable specified in |
| # `FILE_COPTS_VAR_NAME`. |
| # Example: "x86_64:some_file_for_x86_64_using_avx512_instructions.c:NAME_OF_VARIABLE_CONTAINING_COPTS_FOR_X86_64_AVX512". |
| function(iree_experimental_standalone_plugin) |
| # Early return if we don't have our own build of Clang and LLD available. |
| if (NOT (IREE_CLANG_TARGET AND IREE_LLD_TARGET)) |
| return() |
| endif() |
| |
| cmake_parse_arguments( |
| _RULE |
| "" |
| "NAME" |
| "SRCS;ARCHS" |
| ${ARGN} |
| ) |
| |
| # Iterate over architectures. For each of them, build the architecture-specific |
| # shared library (iree_experimental_standalone_plugin_arch). |
| foreach(_ARCH_ENTRY_COLON_SEPARATED IN LISTS _RULE_ARCHS) |
| # Turn the colon-separated ARCH entry into a CMake list (semicolon-separated) |
| string(REPLACE ":" ";" _ARCH_ENTRY_LIST "${_ARCH_ENTRY_COLON_SEPARATED}") |
| list(GET _ARCH_ENTRY_LIST 0 _ARCH) |
| list(LENGTH _ARCH_ENTRY_LIST _ARCH_ENTRY_LIST_LENGTH) |
| # Get optional architecture-wide copts into _COPTS. |
| set(_COPTS_VAR_NAME "") |
| if(_ARCH_ENTRY_LIST_LENGTH EQUAL 2) |
| list(GET _ARCH_ENTRY_LIST 1 _COPTS_VAR_NAME) |
| endif() |
| set(_COPTS "${${_COPTS_VAR_NAME}}") |
| # Build the architecture-specific shared library. |
| iree_experimental_standalone_plugin_arch( |
| NAME |
| "${_RULE_NAME}" |
| ARCH |
| "${_ARCH}" |
| SRCS |
| ${_RULE_SRCS} |
| COPTS |
| ${_COPTS} |
| ) |
| list(APPEND _ARCH_SO_FILES "${CMAKE_CURRENT_BINARY_DIR}/${_RULE_NAME}.${_ARCH}.so") |
| endforeach() |
| # Generate the multi-architecture ELF file. |
| add_custom_command( |
| OUTPUT |
| "${_RULE_NAME}.sos" |
| DEPENDS |
| ${_ARCH_SO_FILES} |
| iree-fatelf |
| COMMAND iree-fatelf join |
| ${_ARCH_SO_FILES} |
| > ${CMAKE_CURRENT_BINARY_DIR}/${_RULE_NAME}.sos |
| VERBATIM |
| ) |
| iree_package_name(_PACKAGE_NAME) |
| set(_NAME "${_PACKAGE_NAME}_${_RULE_NAME}") |
| add_custom_target("${_NAME}" DEPENDS |
| "${CMAKE_CURRENT_BINARY_DIR}/${_RULE_NAME}.sos" |
| ) |
| add_dependencies(iree-test-deps "${_NAME}") |
| endfunction() |