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