xref: /aosp_15_r20/external/executorch/kernels/quantized/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# Kernel library for quantized operators. Please this file formatted by running:
8# ~~~
9# cmake-format -i CMakeLists.txt
10# ~~~
11cmake_minimum_required(VERSION 3.19)
12
13option(EXECUTORCH_BUILD_KERNELS_QUANTIZED_AOT
14       "Build the optimized ops library for AOT export usage" OFF
15)
16
17set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
18if(NOT CMAKE_CXX_STANDARD)
19  set(CMAKE_CXX_STANDARD 17)
20endif()
21
22# Source root directory for executorch.
23if(NOT EXECUTORCH_ROOT)
24  set(EXECUTORCH_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/../..)
25endif()
26
27set(_common_compile_options -Wno-deprecated-declarations)
28
29include(${EXECUTORCH_ROOT}/build/Utils.cmake)
30include(${EXECUTORCH_ROOT}/build/Codegen.cmake)
31
32if(NOT PYTHON_EXECUTABLE)
33  resolve_python_executable()
34endif()
35
36# Quantized ops kernel sources TODO(larryliu0820): use buck2 to gather the
37# sources
38list(TRANSFORM _quantized_kernels__srcs PREPEND "${EXECUTORCH_ROOT}/")
39# Generate C++ bindings to register kernels into both PyTorch (for AOT) and
40# Executorch (for runtime). Here select all ops in quantized.yaml
41set(_yaml_file ${CMAKE_CURRENT_LIST_DIR}/quantized.yaml)
42gen_selected_ops(LIB_NAME "quantized_ops_lib" OPS_SCHEMA_YAML "${_yaml_file}")
43
44# Expect gen_selected_ops output file to be selected_operators.yaml
45generate_bindings_for_kernels(
46  LIB_NAME "quantized_ops_lib" CUSTOM_OPS_YAML "${_yaml_file}"
47)
48message("Generated files ${gen_command_sources}")
49
50# Not targeting Xcode, because the custom command generating
51# kernels/quantized/selected_operators.yaml is attached to multiple targets:
52# quantized_ops_aot_lib quantized_ops_lib but none of these is a common
53# dependency of the other(s). This is not allowed by the Xcode "new build
54# system".
55if(NOT CMAKE_GENERATOR STREQUAL "Xcode"
56   AND EXECUTORCH_BUILD_KERNELS_QUANTIZED_AOT
57)
58  # Not targeting ARM_BAREMETAL as aot_lib depends on incompatible libraries
59  if(NOT EXECUTORCH_BUILD_ARM_BAREMETAL)
60    set(_quantized_aot_ops
61        "quantized_decomposed::add.out"
62        "quantized_decomposed::choose_qparams.Tensor_out"
63        "quantized_decomposed::dequantize_per_channel.out"
64        "quantized_decomposed::dequantize_per_tensor.out"
65        "quantized_decomposed::dequantize_per_tensor.Tensor_out"
66        "quantized_decomposed::mixed_linear.out"
67        "quantized_decomposed::mixed_mm.out"
68        "quantized_decomposed::quantize_per_channel.out"
69        "quantized_decomposed::quantize_per_tensor.out"
70        "quantized_decomposed::quantize_per_tensor.Tensor_out"
71    )
72    gen_selected_ops(
73      LIB_NAME "quantized_ops_aot_lib" ROOT_OPS ${_quantized_aot_ops}
74    )
75    # Expect gen_selected_ops output file to be
76    # quantized_ops_aot_lib/selected_operators.yaml
77    generate_bindings_for_kernels(
78      LIB_NAME "quantized_ops_aot_lib" CUSTOM_OPS_YAML "${_yaml_file}"
79    )
80    # Build a AOT library to register quantized ops into PyTorch. This is a
81    # hack.
82    set(_quantized_sources
83        ${_quantized_kernels__srcs}
84        ${EXECUTORCH_ROOT}/kernels/portable/cpu/util/reduce_util.cpp
85        ${EXECUTORCH_ROOT}/runtime/core/exec_aten/util/tensor_util_aten.cpp
86    )
87    gen_custom_ops_aot_lib(
88      LIB_NAME "quantized_ops_aot_lib" KERNEL_SOURCES "${_quantized_sources}"
89    )
90
91    # Register quantized ops to portable_lib, so that they're available via
92    # pybindings.
93    if(TARGET portable_lib)
94      add_library(quantized_pybind_kernels_lib ${_quantized_kernels__srcs})
95      target_link_libraries(quantized_pybind_kernels_lib PRIVATE portable_lib)
96      target_compile_options(
97        quantized_pybind_kernels_lib PUBLIC ${_common_compile_options}
98      )
99      target_include_directories(
100        quantized_pybind_kernels_lib PUBLIC "${_common_include_directories}"
101      )
102      gen_selected_ops(
103        LIB_NAME "quantized_ops_pybind_lib" OPS_SCHEMA_YAML "${_yaml_file}"
104      )
105      generate_bindings_for_kernels(
106        LIB_NAME "quantized_ops_pybind_lib" CUSTOM_OPS_YAML "${_yaml_file}"
107      )
108      # Build a library for pybind usage. quantized_ops_pybind_lib: Register
109      # quantized ops kernels into Executorch runtime for pybind.
110      gen_operators_lib(
111        LIB_NAME "quantized_ops_pybind_lib" KERNEL_LIBS
112        quantized_pybind_kernels_lib DEPS portable_lib
113      )
114      target_link_libraries(
115        quantized_ops_aot_lib PUBLIC quantized_ops_pybind_lib
116      )
117
118      # pip wheels will need to be able to find the dependent libraries. On
119      # Linux, the .so has non-absolute dependencies on libs like
120      # "_portable_lib.so" without paths; as long as we `import torch` first,
121      # those dependencies will work. But Apple dylibs do not support
122      # non-absolute dependencies, so we need to tell the loader where to look
123      # for its libraries. The LC_LOAD_DYLIB entries for the portable_lib
124      # libraries will look like "@rpath/_portable_lib.cpython-310-darwin.so",
125      # so we can add an LC_RPATH entry to look in a directory relative to the
126      # installed location of our _portable_lib.so file. To see these LC_*
127      # values, run `otool -l libquantized_ops_lib.dylib`.
128      if(APPLE)
129        set_target_properties(
130          quantized_ops_aot_lib
131          PROPERTIES # Assume this library will be installed in
132                     # <site-packages>/executorch/kernels/quantized/, and the
133                     # _portable_lib.so is installed in
134                     # <site-packages>/executorch/extension/pybindings/
135                     BUILD_RPATH "@loader_path/../../extensions/pybindings"
136                     INSTALL_RPATH "@loader_path/../../extensions/pybindings"
137        )
138      endif()
139    endif()
140  endif()
141endif()
142
143add_library(quantized_kernels ${_quantized_kernels__srcs})
144target_link_libraries(quantized_kernels PRIVATE executorch)
145target_compile_options(quantized_kernels PUBLIC ${_common_compile_options})
146# Build a library for _quantized_kernels_srcs
147#
148# quantized_ops_lib: Register quantized ops kernels into Executorch runtime
149gen_operators_lib(
150  LIB_NAME "quantized_ops_lib" KERNEL_LIBS quantized_kernels DEPS executorch
151)
152
153install(
154  TARGETS quantized_kernels quantized_ops_lib
155  DESTINATION lib
156  PUBLIC_HEADER DESTINATION include/executorch/kernels/quantized/
157)
158