openvino/cmake/developer_package/cross_compile/cross_compiled_func.cmake
Ilya Lavrenov ead4b8a0ec
Moved cmake functions, variables to API 2.0 naming style (#20281)
* Merge Linux CC + static build + clang compiler

* Improvements

* Removed ie prefixes from cmake scripts

* Fixes for NPU
2023-10-09 22:30:32 +04:00

207 lines
7.4 KiB
CMake

# Copyright (C) 2018-2023 Intel Corporation
# SPDX-License-Identifier: Apache-2.0
#
## list of available instruction sets
set(_ARCH_LIST ANY SSE42 AVX AVX2 AVX512F)
set(_ACCEPTED_ARCHS_ANY "^(ANY)$")
set(_ACCEPTED_ARCHS_SSE42 "^(ANY|SSE42)$")
set(_ACCEPTED_ARCHS_AVX "^(ANY|SSE42|AVX)$")
set(_ACCEPTED_ARCHS_AVX2 "^(ANY|SSE42|AVX|AVX2)$")
set(_ACCEPTED_ARCHS_AVX512F "^(ANY|SSE42|AVX|AVX2|AVX512F)$")
## Arch specific definitions
set(_DEFINE_ANY "")
set(_DEFINE_SSE42 "HAVE_SSE42" ${_DEFINE_ANY})
set(_DEFINE_AVX "HAVE_AVX" ${_DEFINE_SSE42})
set(_DEFINE_AVX2 "HAVE_AVX2" ${_DEFINE_AVX})
set(_DEFINE_AVX512F "HAVE_AVX512F" ${_DEFINE_AVX2})
## Arch specific compile options
ov_avx512_optimization_flags(_FLAGS_AVX512F)
ov_avx2_optimization_flags (_FLAGS_AVX2)
ov_sse42_optimization_flags (_FLAGS_SSE42)
set(_FLAGS_AVX "") ## TBD is not defined for IE project yet
set(_FLAGS_ANY "") ##
## way to duplicate file via cmake tool set
if (UNIX)
## Clone sources via sym link because it allow to modify original file in IDE along with debug
set(TO_DUPLICATE create_symlink)
else()
## Windows and others - just copy
set(TO_DUPLICATE copy)
endif()
set(DISPATCHER_GEN_SCRIPT ${CMAKE_CURRENT_LIST_DIR}/cross_compiled_disp_gen.cmake)
set(DISPATCHER_GEN_OPTIONS_HOLDER ${CMAKE_CURRENT_LIST_DIR}/cross_compiled_disp_gen_options.in)
#######################################
#
# Allow to enable multiple cross compilation of source file inside one module
# with keeping requirements on minimal instruction set. The CPU check performed
# in runtime via common utils declared in "ie_system_conf.h".
#
# Usage example:
# cross_compiled_file(<target>
# ARCH
# ANY <source_file>
# SSE SSE42 <source_file>
# AVX AVX2 <source_file>
# AVX512F <source_file>
# API <header_file>
# NAMESPACE <namespace> # like "IE::Ext::CPU::XARCH"
# NAME <function_name> # like "my_fun"
# )
#
function(cross_compiled_file TARGET)
set(oneValueArgs API ## Header with declaration of cross compiled function
NAMESPACE ## The namespace where cross compiled function was declared
NAME) ## String with function signature to make cross compiled
set(multiValueArgs ARCH) ## List of architecture described in _ARCH_LIST
cmake_parse_arguments(X "" "${oneValueArgs}" "${multiValueArgs}" ${ARGN})
## verification
if(X_UNPARSED_ARGUMENTS)
message(FATAL_ERROR "Unknown argument: " ${X_UNPARSED_ARGUMENTS})
endif()
if((NOT TARGET) OR (NOT X_NAME) OR (NOT X_NAMESPACE) OR (NOT X_API) OR (NOT X_ARCH))
message(FATAL_ERROR "Missed arguments")
endif()
_currently_requested_top_arch(TOP_ARCH)
set(_CURRENT_ARCH_FILTER "${_ACCEPTED_ARCHS_${TOP_ARCH}}")
## format: ARCH1 ARCH2 <src1> ARCH3 <src2> ...
foreach(_it ${X_ARCH})
if (_it IN_LIST _ARCH_LIST)
## that is arch ID
set(_arch ${_it})
if(_arch MATCHES ${_CURRENT_ARCH_FILTER})
list(APPEND _CUR_ARCH_SET ${_arch})
list(APPEND _FULL_ARCH_SET ${_arch})
endif()
else()
## that is source file name
set(_src_name ${_it})
_remove_source_from_target(${TARGET} ${_src_name})
_clone_source_to_target(${TARGET} ${_src_name} "${_CUR_ARCH_SET}")
set(_CUR_ARCH_SET "")
endif()
endforeach()
_add_dispatcher_to_target(${TARGET} ${X_API} ${X_NAME} "${X_NAMESPACE}" "${_FULL_ARCH_SET}")
endfunction()
##########################################
#
# Add source multiple time per each element in ARCH_SET.
# Also provide corresponding arch specific flags and defines.
#
function(_clone_source_to_target TARGET SOURCE ARCH_SET)
foreach(_arch ${ARCH_SET})
set(_arch_dir cross-compiled/${_arch})
get_filename_component(ARCH_NAME ${SOURCE} NAME)
get_filename_component(ARCH_INCLUDE_DIR ${SOURCE} DIRECTORY)
set(ARCH_SOURCE "${_arch_dir}/${ARCH_NAME}")
add_custom_command(
OUTPUT ${ARCH_SOURCE}
COMMAND ${CMAKE_COMMAND} -E make_directory
${CMAKE_CURRENT_BINARY_DIR}/${_arch_dir}
COMMAND ${CMAKE_COMMAND} -E ${TO_DUPLICATE}
${CMAKE_CURRENT_SOURCE_DIR}/${SOURCE}
${CMAKE_CURRENT_BINARY_DIR}/${ARCH_SOURCE}
DEPENDS ${SOURCE}
VERBATIM
)
set_property(SOURCE ${ARCH_SOURCE} APPEND_STRING PROPERTY COMPILE_OPTIONS
"${_FLAGS_${_arch}}")
set_property(SOURCE ${ARCH_SOURCE} APPEND PROPERTY COMPILE_DEFINITIONS
${_DEFINE_${_arch}}
"XARCH=${_arch}" ## to replace XARCH with direct ARCH name
)
## To make `#include "some.hpp"` valid
set_property(SOURCE ${ARCH_SOURCE} APPEND PROPERTY INCLUDE_DIRECTORIES
"${CMAKE_CURRENT_SOURCE_DIR}/${ARCH_INCLUDE_DIR}")
list(APPEND _ARCH_SOURCES ${ARCH_SOURCE})
endforeach()
target_sources(${TARGET} PRIVATE ${_ARCH_SOURCES})
endfunction()
##########################################
#
# Generate dispatcher for provided function
# for archs in ARCH_SET.
#
function(_add_dispatcher_to_target TARGET HEADER FUNC_NAME NAMESPACE ARCH_SET)
get_filename_component(DISPATCHER_NAME ${HEADER} NAME_WE)
get_filename_component(DISPATCHER_INCLUDE_DIR ${HEADER} DIRECTORY)
set(DISPATCHER_SOURCE "cross-compiled/${DISPATCHER_NAME}_disp.cpp")
set(DISPATCHER_OPT_HOLDER "cross-compiled/${DISPATCHER_NAME}_holder.txt")
configure_file(${DISPATCHER_GEN_OPTIONS_HOLDER} ${DISPATCHER_OPT_HOLDER})
add_custom_command(
OUTPUT ${DISPATCHER_SOURCE}
COMMAND ${CMAKE_COMMAND}
-D "XARCH_FUNC_NAME=${X_NAME}"
-D "XARCH_NAMESPACES=${NAMESPACE}"
-D "XARCH_API_HEADER=${CMAKE_CURRENT_SOURCE_DIR}/${HEADER}"
-D "XARCH_DISP_FILE=${CMAKE_CURRENT_BINARY_DIR}/${DISPATCHER_SOURCE}"
-D "XARCH_SET=${ARCH_SET}"
-P ${DISPATCHER_GEN_SCRIPT}
DEPENDS ${HEADER}
${DISPATCHER_GEN_SCRIPT}
${CMAKE_CURRENT_BINARY_DIR}/${DISPATCHER_OPT_HOLDER} ## Just to make run dependency on args value
VERBATIM
)
set_property(SOURCE ${DISPATCHER_SOURCE} APPEND PROPERTY INCLUDE_DIRECTORIES
"${CMAKE_CURRENT_SOURCE_DIR}/${DISPATCHER_INCLUDE_DIR}")
target_sources(${TARGET} PRIVATE ${DISPATCHER_SOURCE})
endfunction()
#######################################
#
# Return currently requested ARCH id
#
function(_currently_requested_top_arch VAR)
if(ENABLE_AVX512F)
set(RES AVX512F)
elseif(ENABLE_AVX2)
set(RES AVX2)
elseif(ENABLE_SSE42)
set(RES SSE42)
else()
set(RES ANY)
endif()
set (${VAR} "${RES}" PARENT_SCOPE)
endfunction()
#####################################
#
# Utils to handle with cmake target
#
function(_remove_source_from_target TARGET SOURCE_FILE)
get_target_property(ORIGINAL_SOURCES ${TARGET} SOURCES)
## To match by file name only. The path is any.
list(FILTER ORIGINAL_SOURCES EXCLUDE REGEX ".*${SOURCE_FILE}$")
set_target_properties(${TARGET}
PROPERTIES
SOURCES "${ORIGINAL_SOURCES}")
endfunction()