xref: /aosp_15_r20/external/executorch/examples/portable/custom_ops/CMakeLists.txt (revision 523fa7a60841cd1ecfb9cc4201f1ca8b03ed023a)
1# Copyright (c) Meta Platforms, Inc. and affiliates.
2# All rights reserved.
3#
4# This source code is licensed under the BSD-style license found in the
5# LICENSE file in the root directory of this source tree.
6
7# Example CMakeLists.txt for registering custom ops into ExecuTorch. In this
8# example we have custom ops `my_ops::mul3.out` implemented in C++ in
9# `examples/portable/custom_ops/custom_ops_1.cpp`. We also have it registered
10# into EXIR in `examples/portable/custom_ops/custom_ops_1.py`. This
11# CMakeLists.txt runs a script to generate wrapper code based on the operator
12# kernel binding defined in `examples/portable/custom_ops/custom_ops.yaml`. Then
13# creates a library that contains both binding wrapper and the implementation
14# source file. This library can be linked into ExecuTorch binary
15# (`executor_runner` in this example) and it is ready to run models containing
16# that custom op.
17cmake_minimum_required(VERSION 3.19)
18project(custom_ops_example)
19
20set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
21if(NOT CMAKE_CXX_STANDARD)
22  set(CMAKE_CXX_STANDARD 17)
23endif()
24
25# Source root directory for executorch.
26if(NOT EXECUTORCH_ROOT)
27  set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../../..)
28endif()
29
30include(${EXECUTORCH_ROOT}/build/Utils.cmake)
31include(${EXECUTORCH_ROOT}/build/Codegen.cmake)
32
33if(NOT PYTHON_EXECUTABLE)
34  resolve_python_executable()
35endif()
36
37set(_common_compile_options -Wno-deprecated-declarations -fPIC)
38
39# Let files say "include <executorch/path/to/header.h>".
40set(_common_include_directories ${EXECUTORCH_ROOT}/..)
41
42find_package(executorch CONFIG REQUIRED)
43find_package(
44  gflags REQUIRED PATHS ${CMAKE_CURRENT_BINARY_DIR}/../../../third-party
45)
46
47target_include_directories(executorch INTERFACE ${_common_include_directories})
48
49# ------------------------------ OPTIONS BEGIN -------------------------------
50# Option to register custom operator `my_ops::mul3` or `my_ops::mul4` or no
51# custom ops at all. Custom ops are defined in
52# `examples/portable/custom_ops/custom_ops_1.py` and
53# `examples/portable/custom_ops/custom_ops_2.cpp`.
54option(
55  REGISTER_EXAMPLE_CUSTOM_OP
56  "Register whether custom op 1 (my_ops::mul3) or custom op 2 (my_ops::mul4) \
57  or no custom op at all." OFF
58)
59# ------------------------------- OPTIONS END --------------------------------
60
61#
62# The `_<target>_srcs` lists are defined by including ${EXECUTORCH_SRCS_FILE}.
63#
64set(EXECUTORCH_SRCS_FILE
65    "${CMAKE_CURRENT_BINARY_DIR}/../../../executorch_srcs.cmake"
66)
67
68extract_sources(${EXECUTORCH_SRCS_FILE})
69
70include(${EXECUTORCH_SRCS_FILE})
71
72# Generate C++ bindings to register kernels into both PyTorch (for AOT) and
73# Executorch (for runtime).
74if(REGISTER_EXAMPLE_CUSTOM_OP EQUAL 1)
75  gen_selected_ops(LIB_NAME "custom_ops_lib" ROOT_OPS "my_ops::mul3.out")
76elseif(REGISTER_EXAMPLE_CUSTOM_OP EQUAL 2)
77  gen_selected_ops(LIB_NAME "custom_ops_lib" ROOT_OPS "my_ops::mul4.out")
78endif()
79# Expect gen_selected_ops output file to be selected_operators.yaml
80generate_bindings_for_kernels(
81  LIB_NAME "custom_ops_lib" CUSTOM_OPS_YAML
82  ${CMAKE_CURRENT_LIST_DIR}/custom_ops.yaml
83)
84message("Generated files ${gen_command_sources}")
85
86# Prepare for C++ libraries.
87
88# C++ library to register custom ops into PyTorch.
89if(REGISTER_EXAMPLE_CUSTOM_OP EQUAL 2)
90  gen_selected_ops(LIB_NAME "custom_ops_aot_lib" ROOT_OPS "my_ops::mul4.out")
91  generate_bindings_for_kernels(
92    LIB_NAME "custom_ops_aot_lib" CUSTOM_OPS_YAML
93    ${CMAKE_CURRENT_LIST_DIR}/custom_ops.yaml
94  )
95  set(custom_ops_kernel_sources
96      ${CMAKE_CURRENT_LIST_DIR}/custom_ops_2.cpp # register my_ops::mul4
97      ${CMAKE_CURRENT_LIST_DIR}/custom_ops_2_out.cpp # register my_ops::mul4.out
98  )
99  gen_custom_ops_aot_lib(
100    LIB_NAME "custom_ops_aot_lib" KERNEL_SOURCES "${custom_ops_kernel_sources}"
101  )
102  target_include_directories(
103    custom_ops_aot_lib PUBLIC ${_common_include_directories}
104  )
105endif()
106
107# C++ library to register custom ops into Executorch runtime.
108if(REGISTER_EXAMPLE_CUSTOM_OP EQUAL 1)
109  set(kernel_sources ${CMAKE_CURRENT_LIST_DIR}/custom_ops_1_out.cpp)
110elseif(REGISTER_EXAMPLE_CUSTOM_OP EQUAL 2)
111  set(kernel_sources ${CMAKE_CURRENT_LIST_DIR}/custom_ops_2_out.cpp)
112endif()
113
114add_library(custom_kernels ${kernel_sources})
115target_link_libraries(custom_kernels PRIVATE executorch)
116target_compile_options(custom_kernels PUBLIC ${_common_compile_options})
117
118gen_operators_lib(
119  LIB_NAME "custom_ops_lib" KERNEL_LIBS custom_kernels DEPS executorch
120)
121
122list(TRANSFORM _executor_runner__srcs PREPEND "${EXECUTORCH_ROOT}/")
123
124add_executable(custom_ops_executor_runner ${_executor_runner__srcs})
125target_link_libraries(
126  custom_ops_executor_runner custom_ops_lib executorch gflags
127)
128target_compile_options(
129  custom_ops_executor_runner PUBLIC ${_common_compile_options}
130)
131