xref: /aosp_15_r20/external/executorch/build/Codegen.cmake (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1*523fa7a6SAndroid Build Coastguard Worker# Copyright (c) Meta Platforms, Inc. and affiliates.
2*523fa7a6SAndroid Build Coastguard Worker# All rights reserved.
3*523fa7a6SAndroid Build Coastguard Worker#
4*523fa7a6SAndroid Build Coastguard Worker# This source code is licensed under the BSD-style license found in the
5*523fa7a6SAndroid Build Coastguard Worker# LICENSE file in the root directory of this source tree.
6*523fa7a6SAndroid Build Coastguard Worker
7*523fa7a6SAndroid Build Coastguard Worker# This file contains util functions to generate code for kernel registration for
8*523fa7a6SAndroid Build Coastguard Worker# both AOT and runtime.
9*523fa7a6SAndroid Build Coastguard Worker
10*523fa7a6SAndroid Build Coastguard Worker# Selective build. See codegen/tools/gen_oplist.py for how to use these
11*523fa7a6SAndroid Build Coastguard Worker# arguments.
12*523fa7a6SAndroid Build Coastguard Workerfunction(gen_selected_ops)
13*523fa7a6SAndroid Build Coastguard Worker  set(arg_names LIB_NAME OPS_SCHEMA_YAML ROOT_OPS INCLUDE_ALL_OPS)
14*523fa7a6SAndroid Build Coastguard Worker  cmake_parse_arguments(GEN "" "" "${arg_names}" ${ARGN})
15*523fa7a6SAndroid Build Coastguard Worker
16*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "Generating operator lib:")
17*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  LIB_NAME: ${GEN_LIB_NAME}")
18*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  OPS_SCHEMA_YAML: ${GEN_OPS_SCHEMA_YAML}")
19*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  ROOT_OPS: ${GEN_ROOT_OPS}")
20*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  INCLUDE_ALL_OPS: ${GEN_INCLUDE_ALL_OPS}")
21*523fa7a6SAndroid Build Coastguard Worker
22*523fa7a6SAndroid Build Coastguard Worker  set(_oplist_yaml
23*523fa7a6SAndroid Build Coastguard Worker      ${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME}/selected_operators.yaml
24*523fa7a6SAndroid Build Coastguard Worker  )
25*523fa7a6SAndroid Build Coastguard Worker  file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME})
26*523fa7a6SAndroid Build Coastguard Worker
27*523fa7a6SAndroid Build Coastguard Worker  file(GLOB_RECURSE _codegen_tools_srcs "${EXECUTORCH_ROOT}/codegen/tools/*.py")
28*523fa7a6SAndroid Build Coastguard Worker
29*523fa7a6SAndroid Build Coastguard Worker  set(_gen_oplist_command "${PYTHON_EXECUTABLE}" -m codegen.tools.gen_oplist
30*523fa7a6SAndroid Build Coastguard Worker                          --output_path=${_oplist_yaml}
31*523fa7a6SAndroid Build Coastguard Worker  )
32*523fa7a6SAndroid Build Coastguard Worker
33*523fa7a6SAndroid Build Coastguard Worker  if(GEN_OPS_SCHEMA_YAML)
34*523fa7a6SAndroid Build Coastguard Worker    list(APPEND _gen_oplist_command
35*523fa7a6SAndroid Build Coastguard Worker         --ops_schema_yaml_path="${GEN_OPS_SCHEMA_YAML}"
36*523fa7a6SAndroid Build Coastguard Worker    )
37*523fa7a6SAndroid Build Coastguard Worker  endif()
38*523fa7a6SAndroid Build Coastguard Worker  if(GEN_ROOT_OPS)
39*523fa7a6SAndroid Build Coastguard Worker    list(APPEND _gen_oplist_command --root_ops="${GEN_ROOT_OPS}")
40*523fa7a6SAndroid Build Coastguard Worker  endif()
41*523fa7a6SAndroid Build Coastguard Worker  if(GEN_INCLUDE_ALL_OPS)
42*523fa7a6SAndroid Build Coastguard Worker    list(APPEND _gen_oplist_command --include_all_operators)
43*523fa7a6SAndroid Build Coastguard Worker  endif()
44*523fa7a6SAndroid Build Coastguard Worker
45*523fa7a6SAndroid Build Coastguard Worker  message("Command - ${_gen_oplist_command}")
46*523fa7a6SAndroid Build Coastguard Worker  add_custom_command(
47*523fa7a6SAndroid Build Coastguard Worker    COMMENT "Generating selected_operators.yaml for ${GEN_LIB_NAME}"
48*523fa7a6SAndroid Build Coastguard Worker    OUTPUT ${_oplist_yaml}
49*523fa7a6SAndroid Build Coastguard Worker    COMMAND ${_gen_oplist_command}
50*523fa7a6SAndroid Build Coastguard Worker    DEPENDS ${GEN_OPS_SCHEMA_YAML} ${_codegen_tools_srcs}
51*523fa7a6SAndroid Build Coastguard Worker    WORKING_DIRECTORY ${EXECUTORCH_ROOT}
52*523fa7a6SAndroid Build Coastguard Worker  )
53*523fa7a6SAndroid Build Coastguard Worker
54*523fa7a6SAndroid Build Coastguard Workerendfunction()
55*523fa7a6SAndroid Build Coastguard Worker
56*523fa7a6SAndroid Build Coastguard Worker# Codegen for registering kernels. Kernels are defined in functions_yaml and
57*523fa7a6SAndroid Build Coastguard Worker# custom_ops_yaml.
58*523fa7a6SAndroid Build Coastguard Worker#
59*523fa7a6SAndroid Build Coastguard Worker# Invoked as generate_bindings_for_kernels( LIB_NAME lib_name FUNCTIONS_YAML
60*523fa7a6SAndroid Build Coastguard Worker# functions_yaml CUSTOM_OPS_YAML custom_ops_yaml )
61*523fa7a6SAndroid Build Coastguard Workerfunction(generate_bindings_for_kernels)
62*523fa7a6SAndroid Build Coastguard Worker  set(arg_names LIB_NAME FUNCTIONS_YAML CUSTOM_OPS_YAML)
63*523fa7a6SAndroid Build Coastguard Worker  cmake_parse_arguments(GEN "" "${arg_names}" "" ${ARGN})
64*523fa7a6SAndroid Build Coastguard Worker
65*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "Generating kernel bindings:")
66*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  LIB_NAME: ${GEN_LIB_NAME}")
67*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  FUNCTIONS_YAML: ${GEN_FUNCTIONS_YAML}")
68*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  CUSTOM_OPS_YAML: ${GEN_CUSTOM_OPS_YAML}")
69*523fa7a6SAndroid Build Coastguard Worker
70*523fa7a6SAndroid Build Coastguard Worker  # Command to generate selected_operators.yaml from custom_ops.yaml.
71*523fa7a6SAndroid Build Coastguard Worker  file(GLOB_RECURSE _codegen_templates "${EXECUTORCH_ROOT}/codegen/templates/*")
72*523fa7a6SAndroid Build Coastguard Worker
73*523fa7a6SAndroid Build Coastguard Worker  set(_out_dir ${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME})
74*523fa7a6SAndroid Build Coastguard Worker  # By default selective build output is selected_operators.yaml
75*523fa7a6SAndroid Build Coastguard Worker  set(_oplist_yaml ${_out_dir}/selected_operators.yaml)
76*523fa7a6SAndroid Build Coastguard Worker
77*523fa7a6SAndroid Build Coastguard Worker  # Command to codegen C++ wrappers to register custom ops to both PyTorch and
78*523fa7a6SAndroid Build Coastguard Worker  # Executorch runtime.
79*523fa7a6SAndroid Build Coastguard Worker  execute_process(
80*523fa7a6SAndroid Build Coastguard Worker    COMMAND
81*523fa7a6SAndroid Build Coastguard Worker      "${PYTHON_EXECUTABLE}" -c
82*523fa7a6SAndroid Build Coastguard Worker      "from distutils.sysconfig import get_python_lib;print(get_python_lib())"
83*523fa7a6SAndroid Build Coastguard Worker    OUTPUT_VARIABLE site-packages-out
84*523fa7a6SAndroid Build Coastguard Worker    ERROR_VARIABLE site-packages-out-error
85*523fa7a6SAndroid Build Coastguard Worker    RESULT_VARIABLE site-packages-result
86*523fa7a6SAndroid Build Coastguard Worker    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
87*523fa7a6SAndroid Build Coastguard Worker    OUTPUT_STRIP_TRAILING_WHITESPACE
88*523fa7a6SAndroid Build Coastguard Worker  )
89*523fa7a6SAndroid Build Coastguard Worker  file(GLOB_RECURSE _torchgen_srcs "${site-packages-out}/torchgen/*.py")
90*523fa7a6SAndroid Build Coastguard Worker  set(_gen_command
91*523fa7a6SAndroid Build Coastguard Worker      "${PYTHON_EXECUTABLE}" -m torchgen.gen_executorch
92*523fa7a6SAndroid Build Coastguard Worker      --source-path=${EXECUTORCH_ROOT}/codegen --install-dir=${_out_dir}
93*523fa7a6SAndroid Build Coastguard Worker      --tags-path=${site-packages-out}/torchgen/packaged/ATen/native/tags.yaml
94*523fa7a6SAndroid Build Coastguard Worker      --aten-yaml-path=${site-packages-out}/torchgen/packaged/ATen/native/native_functions.yaml
95*523fa7a6SAndroid Build Coastguard Worker      --op-selection-yaml-path=${_oplist_yaml}
96*523fa7a6SAndroid Build Coastguard Worker  )
97*523fa7a6SAndroid Build Coastguard Worker
98*523fa7a6SAndroid Build Coastguard Worker  set(_gen_command_sources
99*523fa7a6SAndroid Build Coastguard Worker      ${_out_dir}/RegisterCodegenUnboxedKernelsEverything.cpp
100*523fa7a6SAndroid Build Coastguard Worker      ${_out_dir}/Functions.h ${_out_dir}/NativeFunctions.h
101*523fa7a6SAndroid Build Coastguard Worker  )
102*523fa7a6SAndroid Build Coastguard Worker
103*523fa7a6SAndroid Build Coastguard Worker  if(GEN_FUNCTIONS_YAML)
104*523fa7a6SAndroid Build Coastguard Worker    list(APPEND _gen_command --functions-yaml-path=${GEN_FUNCTIONS_YAML})
105*523fa7a6SAndroid Build Coastguard Worker  endif()
106*523fa7a6SAndroid Build Coastguard Worker  if(GEN_CUSTOM_OPS_YAML)
107*523fa7a6SAndroid Build Coastguard Worker    list(APPEND _gen_command --custom-ops-yaml-path=${GEN_CUSTOM_OPS_YAML})
108*523fa7a6SAndroid Build Coastguard Worker    list(APPEND _gen_command_sources ${_out_dir}/RegisterCPUCustomOps.cpp
109*523fa7a6SAndroid Build Coastguard Worker         ${_out_dir}/RegisterSchema.cpp ${_out_dir}/CustomOpsNativeFunctions.h
110*523fa7a6SAndroid Build Coastguard Worker    )
111*523fa7a6SAndroid Build Coastguard Worker  endif()
112*523fa7a6SAndroid Build Coastguard Worker
113*523fa7a6SAndroid Build Coastguard Worker  add_custom_command(
114*523fa7a6SAndroid Build Coastguard Worker    COMMENT "Generating code for kernel registration"
115*523fa7a6SAndroid Build Coastguard Worker    OUTPUT ${_gen_command_sources}
116*523fa7a6SAndroid Build Coastguard Worker    COMMAND ${_gen_command}
117*523fa7a6SAndroid Build Coastguard Worker    DEPENDS ${_oplist_yaml} ${GEN_CUSTOM_OPS_YAML} ${GEN_FUNCTIONS_YAML}
118*523fa7a6SAndroid Build Coastguard Worker            ${_codegen_templates} ${_torchgen_srcs}
119*523fa7a6SAndroid Build Coastguard Worker    WORKING_DIRECTORY ${EXECUTORCH_ROOT}
120*523fa7a6SAndroid Build Coastguard Worker  )
121*523fa7a6SAndroid Build Coastguard Worker  # Make generated file list available in parent scope
122*523fa7a6SAndroid Build Coastguard Worker  set(gen_command_sources
123*523fa7a6SAndroid Build Coastguard Worker      ${_gen_command_sources}
124*523fa7a6SAndroid Build Coastguard Worker      PARENT_SCOPE
125*523fa7a6SAndroid Build Coastguard Worker  )
126*523fa7a6SAndroid Build Coastguard Workerendfunction()
127*523fa7a6SAndroid Build Coastguard Worker
128*523fa7a6SAndroid Build Coastguard Worker# Generate an AOT lib for registering custom ops into PyTorch
129*523fa7a6SAndroid Build Coastguard Workerfunction(gen_custom_ops_aot_lib)
130*523fa7a6SAndroid Build Coastguard Worker  cmake_parse_arguments(GEN "" "LIB_NAME" "KERNEL_SOURCES" ${ARGN})
131*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "Generating custom ops aot lib:")
132*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  LIB_NAME: ${GEN_LIB_NAME}")
133*523fa7a6SAndroid Build Coastguard Worker  foreach(SOURCE IN LISTS GEN_KERNEL_SOURCES)
134*523fa7a6SAndroid Build Coastguard Worker    message(STATUS "  KERNEL_SOURCE: ${SOURCE}")
135*523fa7a6SAndroid Build Coastguard Worker  endforeach()
136*523fa7a6SAndroid Build Coastguard Worker
137*523fa7a6SAndroid Build Coastguard Worker  set(_out_dir ${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME})
138*523fa7a6SAndroid Build Coastguard Worker  add_library(
139*523fa7a6SAndroid Build Coastguard Worker    ${GEN_LIB_NAME} SHARED
140*523fa7a6SAndroid Build Coastguard Worker    ${_out_dir}/RegisterCPUCustomOps.cpp ${_out_dir}/RegisterSchema.cpp
141*523fa7a6SAndroid Build Coastguard Worker    ${_out_dir}/CustomOpsNativeFunctions.h "${GEN_KERNEL_SOURCES}"
142*523fa7a6SAndroid Build Coastguard Worker  )
143*523fa7a6SAndroid Build Coastguard Worker  # Find `Torch`.
144*523fa7a6SAndroid Build Coastguard Worker  find_package(Torch REQUIRED)
145*523fa7a6SAndroid Build Coastguard Worker  # This lib uses ATen lib, so we explicitly enable rtti and exceptions.
146*523fa7a6SAndroid Build Coastguard Worker  target_compile_options(${GEN_LIB_NAME} PRIVATE -frtti -fexceptions)
147*523fa7a6SAndroid Build Coastguard Worker  target_compile_definitions(${GEN_LIB_NAME} PRIVATE USE_ATEN_LIB=1)
148*523fa7a6SAndroid Build Coastguard Worker  include_directories(${TORCH_INCLUDE_DIRS})
149*523fa7a6SAndroid Build Coastguard Worker  target_link_libraries(${GEN_LIB_NAME} PRIVATE torch)
150*523fa7a6SAndroid Build Coastguard Worker
151*523fa7a6SAndroid Build Coastguard Worker  include(${EXECUTORCH_ROOT}/build/Utils.cmake)
152*523fa7a6SAndroid Build Coastguard Worker
153*523fa7a6SAndroid Build Coastguard Worker  target_link_options_shared_lib(${GEN_LIB_NAME})
154*523fa7a6SAndroid Build Coastguard Worker  if(TARGET portable_lib)
155*523fa7a6SAndroid Build Coastguard Worker    target_link_libraries(${GEN_LIB_NAME} PRIVATE portable_lib)
156*523fa7a6SAndroid Build Coastguard Worker  else()
157*523fa7a6SAndroid Build Coastguard Worker    target_link_libraries(${GEN_LIB_NAME} PRIVATE executorch_core)
158*523fa7a6SAndroid Build Coastguard Worker  endif()
159*523fa7a6SAndroid Build Coastguard Workerendfunction()
160*523fa7a6SAndroid Build Coastguard Worker
161*523fa7a6SAndroid Build Coastguard Worker# Generate a runtime lib for registering operators in Executorch
162*523fa7a6SAndroid Build Coastguard Workerfunction(gen_operators_lib)
163*523fa7a6SAndroid Build Coastguard Worker  set(multi_arg_names LIB_NAME KERNEL_LIBS DEPS)
164*523fa7a6SAndroid Build Coastguard Worker  cmake_parse_arguments(GEN "" "" "${multi_arg_names}" ${ARGN})
165*523fa7a6SAndroid Build Coastguard Worker
166*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "Generating operator lib:")
167*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  LIB_NAME: ${GEN_LIB_NAME}")
168*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  KERNEL_LIBS: ${GEN_KERNEL_LIBS}")
169*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  DEPS: ${GEN_DEPS}")
170*523fa7a6SAndroid Build Coastguard Worker
171*523fa7a6SAndroid Build Coastguard Worker  set(_out_dir ${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME})
172*523fa7a6SAndroid Build Coastguard Worker
173*523fa7a6SAndroid Build Coastguard Worker  add_library(${GEN_LIB_NAME})
174*523fa7a6SAndroid Build Coastguard Worker  target_sources(
175*523fa7a6SAndroid Build Coastguard Worker    ${GEN_LIB_NAME}
176*523fa7a6SAndroid Build Coastguard Worker    PRIVATE ${_out_dir}/RegisterCodegenUnboxedKernelsEverything.cpp
177*523fa7a6SAndroid Build Coastguard Worker            ${_out_dir}/Functions.h ${_out_dir}/NativeFunctions.h
178*523fa7a6SAndroid Build Coastguard Worker  )
179*523fa7a6SAndroid Build Coastguard Worker  target_link_libraries(${GEN_LIB_NAME} PRIVATE ${GEN_DEPS})
180*523fa7a6SAndroid Build Coastguard Worker  if(GEN_KERNEL_LIBS)
181*523fa7a6SAndroid Build Coastguard Worker    target_link_libraries(${GEN_LIB_NAME} PUBLIC ${GEN_KERNEL_LIBS})
182*523fa7a6SAndroid Build Coastguard Worker  endif()
183*523fa7a6SAndroid Build Coastguard Worker
184*523fa7a6SAndroid Build Coastguard Worker  target_link_options_shared_lib(${GEN_LIB_NAME})
185*523fa7a6SAndroid Build Coastguard Worker  set(_generated_headers ${_out_dir}/Functions.h ${_out_dir}/NativeFunctions.h)
186*523fa7a6SAndroid Build Coastguard Worker  set_target_properties(
187*523fa7a6SAndroid Build Coastguard Worker    ${GEN_LIB_NAME} PROPERTIES PUBLIC_HEADER "${_generated_headers}"
188*523fa7a6SAndroid Build Coastguard Worker  )
189*523fa7a6SAndroid Build Coastguard Workerendfunction()
190*523fa7a6SAndroid Build Coastguard Worker
191*523fa7a6SAndroid Build Coastguard Worker# Merge two kernel yaml files, prioritizing functions from FUNCTIONS_YAML and
192*523fa7a6SAndroid Build Coastguard Worker# taking functions from FALLBACK_YAML when no implementation is found. This
193*523fa7a6SAndroid Build Coastguard Worker# corresponds to the merge_yaml buck implementation in codegen/tools.
194*523fa7a6SAndroid Build Coastguard Workerfunction(merge_yaml)
195*523fa7a6SAndroid Build Coastguard Worker  set(arg_names FUNCTIONS_YAML FALLBACK_YAML OUTPUT_DIR)
196*523fa7a6SAndroid Build Coastguard Worker  cmake_parse_arguments(GEN "" "${arg_names}" "" ${ARGN})
197*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "Merging kernel yaml files:")
198*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  FUNCTIONS_YAML: ${GEN_FUNCTIONS_YAML}")
199*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  FALLBACK_YAML: ${GEN_FALLBACK_YAML}")
200*523fa7a6SAndroid Build Coastguard Worker  message(STATUS "  OUTPUT_DIR: ${GEN_OUTPUT_DIR}")
201*523fa7a6SAndroid Build Coastguard Worker
202*523fa7a6SAndroid Build Coastguard Worker  set(_gen_command
203*523fa7a6SAndroid Build Coastguard Worker      "${PYTHON_EXECUTABLE}" -m codegen.tools.merge_yaml
204*523fa7a6SAndroid Build Coastguard Worker      --functions_yaml_path=${GEN_FUNCTIONS_YAML}
205*523fa7a6SAndroid Build Coastguard Worker      --fallback_yaml_path=${GEN_FALLBACK_YAML} --output_dir=${GEN_OUTPUT_DIR}
206*523fa7a6SAndroid Build Coastguard Worker  )
207*523fa7a6SAndroid Build Coastguard Worker
208*523fa7a6SAndroid Build Coastguard Worker  add_custom_command(
209*523fa7a6SAndroid Build Coastguard Worker    COMMENT "Merging kernel yaml files"
210*523fa7a6SAndroid Build Coastguard Worker    OUTPUT ${GEN_OUTPUT_DIR}/merged.yaml
211*523fa7a6SAndroid Build Coastguard Worker    COMMAND ${_gen_command}
212*523fa7a6SAndroid Build Coastguard Worker    DEPENDS ${GEN_FUNCTIONS_YAML} ${GEN_FALLBACK_YAML}
213*523fa7a6SAndroid Build Coastguard Worker    WORKING_DIRECTORY ${EXECUTORCH_ROOT}
214*523fa7a6SAndroid Build Coastguard Worker  )
215*523fa7a6SAndroid Build Coastguard Workerendfunction()
216