| # Copyright (c) Meta Platforms, Inc. and affiliates. |
| # All rights reserved. |
| # |
| # This source code is licensed under the BSD-style license found in the |
| # LICENSE file in the root directory of this source tree. |
| |
| # This file contains util functions to generate code for kernel registration for |
| # both AOT and runtime. |
| |
| # Selective build. See codegen/tools/gen_oplist.py for how to use these |
| # arguments. |
| function(gen_selected_ops) |
| set(arg_names LIB_NAME OPS_SCHEMA_YAML ROOT_OPS INCLUDE_ALL_OPS) |
| cmake_parse_arguments(GEN "" "" "${arg_names}" ${ARGN}) |
| |
| message(STATUS "Generating operator lib:") |
| message(STATUS " LIB_NAME: ${GEN_LIB_NAME}") |
| message(STATUS " OPS_SCHEMA_YAML: ${GEN_OPS_SCHEMA_YAML}") |
| message(STATUS " ROOT_OPS: ${GEN_ROOT_OPS}") |
| message(STATUS " INCLUDE_ALL_OPS: ${GEN_INCLUDE_ALL_OPS}") |
| |
| set(_oplist_yaml |
| ${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME}/selected_operators.yaml |
| ) |
| file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME}) |
| |
| file(GLOB_RECURSE _codegen_tools_srcs "${EXECUTORCH_ROOT}/codegen/tools/*.py") |
| |
| set(_gen_oplist_command "${PYTHON_EXECUTABLE}" -m codegen.tools.gen_oplist |
| --output_path=${_oplist_yaml} |
| ) |
| |
| if(GEN_OPS_SCHEMA_YAML) |
| list(APPEND _gen_oplist_command |
| --ops_schema_yaml_path="${GEN_OPS_SCHEMA_YAML}" |
| ) |
| endif() |
| if(GEN_ROOT_OPS) |
| list(APPEND _gen_oplist_command --root_ops="${GEN_ROOT_OPS}") |
| endif() |
| if(GEN_INCLUDE_ALL_OPS) |
| list(APPEND _gen_oplist_command --include_all_operators) |
| endif() |
| |
| message("Command - ${_gen_oplist_command}") |
| add_custom_command( |
| COMMENT "Generating selected_operators.yaml for ${GEN_LIB_NAME}" |
| OUTPUT ${_oplist_yaml} |
| COMMAND ${_gen_oplist_command} |
| DEPENDS ${GEN_OPS_SCHEMA_YAML} ${_codegen_tools_srcs} |
| WORKING_DIRECTORY ${EXECUTORCH_ROOT} |
| ) |
| |
| endfunction() |
| |
| # Codegen for registering kernels. Kernels are defined in functions_yaml and |
| # custom_ops_yaml. |
| # |
| # Invoked as generate_bindings_for_kernels( LIB_NAME lib_name FUNCTIONS_YAML |
| # functions_yaml CUSTOM_OPS_YAML custom_ops_yaml ) |
| function(generate_bindings_for_kernels) |
| set(arg_names LIB_NAME FUNCTIONS_YAML CUSTOM_OPS_YAML) |
| cmake_parse_arguments(GEN "" "${arg_names}" "" ${ARGN}) |
| |
| message(STATUS "Generating kernel bindings:") |
| message(STATUS " LIB_NAME: ${GEN_LIB_NAME}") |
| message(STATUS " FUNCTIONS_YAML: ${GEN_FUNCTIONS_YAML}") |
| message(STATUS " CUSTOM_OPS_YAML: ${GEN_CUSTOM_OPS_YAML}") |
| |
| # Command to generate selected_operators.yaml from custom_ops.yaml. |
| file(GLOB_RECURSE _codegen_templates "${EXECUTORCH_ROOT}/codegen/templates/*") |
| |
| set(_out_dir ${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME}) |
| # By default selective build output is selected_operators.yaml |
| set(_oplist_yaml ${_out_dir}/selected_operators.yaml) |
| |
| # Command to codegen C++ wrappers to register custom ops to both PyTorch and |
| # Executorch runtime. |
| execute_process( |
| COMMAND |
| "${PYTHON_EXECUTABLE}" -c |
| "from distutils.sysconfig import get_python_lib;print(get_python_lib())" |
| OUTPUT_VARIABLE site-packages-out |
| ERROR_VARIABLE site-packages-out-error |
| RESULT_VARIABLE site-packages-result |
| WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} |
| OUTPUT_STRIP_TRAILING_WHITESPACE |
| ) |
| file(GLOB_RECURSE _torchgen_srcs "${site-packages-out}/torchgen/*.py") |
| set(_gen_command |
| "${PYTHON_EXECUTABLE}" -m torchgen.gen_executorch |
| --source-path=${EXECUTORCH_ROOT}/codegen --install-dir=${_out_dir} |
| --tags-path=${site-packages-out}/torchgen/packaged/ATen/native/tags.yaml |
| --aten-yaml-path=${site-packages-out}/torchgen/packaged/ATen/native/native_functions.yaml |
| --op-selection-yaml-path=${_oplist_yaml} |
| ) |
| |
| set(_gen_command_sources |
| ${_out_dir}/RegisterCodegenUnboxedKernelsEverything.cpp |
| ${_out_dir}/Functions.h ${_out_dir}/NativeFunctions.h |
| ) |
| |
| if(GEN_FUNCTIONS_YAML) |
| list(APPEND _gen_command --functions-yaml-path=${GEN_FUNCTIONS_YAML}) |
| endif() |
| if(GEN_CUSTOM_OPS_YAML) |
| list(APPEND _gen_command --custom-ops-yaml-path=${GEN_CUSTOM_OPS_YAML}) |
| list(APPEND _gen_command_sources ${_out_dir}/RegisterCPUCustomOps.cpp |
| ${_out_dir}/RegisterSchema.cpp ${_out_dir}/CustomOpsNativeFunctions.h |
| ) |
| endif() |
| |
| add_custom_command( |
| COMMENT "Generating code for kernel registration" |
| OUTPUT ${_gen_command_sources} |
| COMMAND ${_gen_command} |
| DEPENDS ${_oplist_yaml} ${GEN_CUSTOM_OPS_YAML} ${GEN_FUNCTIONS_YAML} |
| ${_codegen_templates} ${_torchgen_srcs} |
| WORKING_DIRECTORY ${EXECUTORCH_ROOT} |
| ) |
| # Make generated file list available in parent scope |
| set(gen_command_sources |
| ${_gen_command_sources} |
| PARENT_SCOPE |
| ) |
| endfunction() |
| |
| # Generate an AOT lib for registering custom ops into PyTorch |
| function(gen_custom_ops_aot_lib) |
| cmake_parse_arguments(GEN "" "LIB_NAME" "KERNEL_SOURCES" ${ARGN}) |
| message(STATUS "Generating custom ops aot lib:") |
| message(STATUS " LIB_NAME: ${GEN_LIB_NAME}") |
| foreach(SOURCE IN LISTS GEN_KERNEL_SOURCES) |
| message(STATUS " KERNEL_SOURCE: ${SOURCE}") |
| endforeach() |
| |
| set(_out_dir ${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME}) |
| add_library( |
| ${GEN_LIB_NAME} SHARED |
| ${_out_dir}/RegisterCPUCustomOps.cpp ${_out_dir}/RegisterSchema.cpp |
| ${_out_dir}/CustomOpsNativeFunctions.h "${GEN_KERNEL_SOURCES}" |
| ) |
| # Find `Torch`. |
| find_package(Torch REQUIRED) |
| # This lib uses ATen lib, so we explicitly enable rtti and exceptions. |
| target_compile_options(${GEN_LIB_NAME} PRIVATE -frtti -fexceptions) |
| target_compile_definitions(${GEN_LIB_NAME} PRIVATE USE_ATEN_LIB=1) |
| include_directories(${TORCH_INCLUDE_DIRS}) |
| target_link_libraries(${GEN_LIB_NAME} PRIVATE torch) |
| |
| include(${EXECUTORCH_ROOT}/build/Utils.cmake) |
| |
| target_link_options_shared_lib(${GEN_LIB_NAME}) |
| if(TARGET portable_lib) |
| target_link_libraries(${GEN_LIB_NAME} PRIVATE portable_lib) |
| else() |
| target_link_libraries(${GEN_LIB_NAME} PRIVATE executorch_no_prim_ops) |
| endif() |
| endfunction() |
| |
| # Generate a runtime lib for registering operators in Executorch |
| function(gen_operators_lib) |
| set(multi_arg_names LIB_NAME KERNEL_LIBS DEPS) |
| cmake_parse_arguments(GEN "" "" "${multi_arg_names}" ${ARGN}) |
| |
| message(STATUS "Generating operator lib:") |
| message(STATUS " LIB_NAME: ${GEN_LIB_NAME}") |
| message(STATUS " KERNEL_LIBS: ${GEN_KERNEL_LIBS}") |
| message(STATUS " DEPS: ${GEN_DEPS}") |
| |
| set(_out_dir ${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME}) |
| |
| add_library(${GEN_LIB_NAME}) |
| target_sources( |
| ${GEN_LIB_NAME} |
| PRIVATE ${_out_dir}/RegisterCodegenUnboxedKernelsEverything.cpp |
| ${_out_dir}/Functions.h ${_out_dir}/NativeFunctions.h |
| ) |
| target_link_libraries(${GEN_LIB_NAME} PRIVATE ${GEN_DEPS}) |
| if(GEN_KERNEL_LIBS) |
| target_link_libraries(${GEN_LIB_NAME} PUBLIC ${GEN_KERNEL_LIBS}) |
| endif() |
| |
| target_link_options_shared_lib(${GEN_LIB_NAME}) |
| set(_generated_headers ${_out_dir}/Functions.h ${_out_dir}/NativeFunctions.h) |
| set_target_properties( |
| ${GEN_LIB_NAME} PROPERTIES PUBLIC_HEADER "${_generated_headers}" |
| ) |
| endfunction() |
| |
| # Merge two kernel yaml files, prioritizing functions from FUNCTIONS_YAML and |
| # taking functions from FALLBACK_YAML when no implementation is found. This |
| # corresponds to the merge_yaml buck implementation in codegen/tools. |
| function(merge_yaml) |
| set(arg_names FUNCTIONS_YAML FALLBACK_YAML OUTPUT_DIR) |
| cmake_parse_arguments(GEN "" "${arg_names}" "" ${ARGN}) |
| message(STATUS "Merging kernel yaml files:") |
| message(STATUS " FUNCTIONS_YAML: ${GEN_FUNCTIONS_YAML}") |
| message(STATUS " FALLBACK_YAML: ${GEN_FALLBACK_YAML}") |
| message(STATUS " OUTPUT_DIR: ${GEN_OUTPUT_DIR}") |
| |
| set(_gen_command |
| "${PYTHON_EXECUTABLE}" -m codegen.tools.merge_yaml |
| --functions_yaml_path=${GEN_FUNCTIONS_YAML} |
| --fallback_yaml_path=${GEN_FALLBACK_YAML} --output_dir=${GEN_OUTPUT_DIR} |
| ) |
| |
| add_custom_command( |
| COMMENT "Merging kernel yaml files" |
| OUTPUT ${GEN_OUTPUT_DIR}/merged.yaml |
| COMMAND ${_gen_command} |
| DEPENDS ${GEN_FUNCTIONS_YAML} ${GEN_FALLBACK_YAML} |
| WORKING_DIRECTORY ${EXECUTORCH_ROOT} |
| ) |
| endfunction() |