Skip to content

[do not land] Support for Header File Generation in DTYPE Selective Build in OSS #11617

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 21 additions & 3 deletions examples/selective_build/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@ option(EXECUTORCH_SELECT_OPS_LIST "Register a list of ops, separated by comma"
option(EXECUTORCH_SELECT_ALL_OPS
"Whether to register all ops defined in portable kernel library." OFF
)

# Option to enable dtype header generation during selective build process
option(EXECUTORCH_DTYPE_GEN_HEADER "Enable dtype header generation during selection during build." OFF
)
# ------------------------------- OPTIONS END --------------------------------

#
Expand Down Expand Up @@ -108,16 +112,30 @@ gen_selected_ops(
"${EXECUTORCH_SELECT_OPS_LIST}"
INCLUDE_ALL_OPS
"${EXECUTORCH_SELECT_ALL_OPS}"
DTYPE_HEADER
"${EXECUTORCH_DTYPE_GEN_HEADER}"
)

generate_bindings_for_kernels(
LIB_NAME "select_build_lib" FUNCTIONS_YAML
${EXECUTORCH_ROOT}/kernels/portable/functions.yaml CUSTOM_OPS_YAML
LIB_NAME
"select_build_lib"
FUNCTIONS_YAML
${EXECUTORCH_ROOT}/kernels/portable/functions.yaml
CUSTOM_OPS_YAML
"${_custom_ops_yaml}"
DTYPE_HEADER
"${EXECUTORCH_DTYPE_GEN_HEADER}"
)

gen_operators_lib(
LIB_NAME "select_build_lib" KERNEL_LIBS ${_kernel_lib} DEPS executorch_core
LIB_NAME
"select_build_lib"
KERNEL_LIBS
${_kernel_lib}
DEPS
executorch_core
DTYPE_HEADER
"${EXECUTORCH_DTYPE_GEN_HEADER}"
)

list(TRANSFORM _executor_runner__srcs PREPEND "${EXECUTORCH_ROOT}/")
Expand Down
25 changes: 25 additions & 0 deletions examples/selective_build/test_selective_build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,30 @@ test_cmake_select_ops_in_yaml() {
rm "./custom_ops_1.pte"
}

test_cmake_select_ops_in_yaml_gen_dtype_header() {
echo "Exporting custom_op_1"
${PYTHON_EXECUTABLE} -m examples.portable.custom_ops.custom_ops_1
local example_dir=examples/selective_build
local build_dir=cmake-out/${example_dir}
rm -rf ${build_dir}
retry cmake -DCMAKE_BUILD_TYPE=Release \
-DEXECUTORCH_SELECT_OPS_YAML=ON \
-DEXECUTORCH_DTYPE_GEN_HEADER=ON \
-DCMAKE_INSTALL_PREFIX=cmake-out \
-DPYTHON_EXECUTABLE="$PYTHON_EXECUTABLE" \
-B${build_dir} \
${example_dir}

echo "Building ${example_dir}"
cmake --build ${build_dir} -j9 --config Release

echo 'Running selective build test'
${build_dir}/selective_build_test --model_path="./custom_ops_1.pte"

echo "Removing custom_ops_1.pte"
rm "./custom_ops_1.pte"
}

if [[ -z $BUCK ]];
then
BUCK=buck2
Expand All @@ -177,6 +201,7 @@ then
test_cmake_select_all_ops
test_cmake_select_ops_in_list
test_cmake_select_ops_in_yaml
test_cmake_select_ops_in_yaml_gen_dtype_header
elif [[ $1 == "buck2" ]];
then
test_buck2_select_all_ops
Expand Down
68 changes: 57 additions & 11 deletions tools/cmake/Codegen.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,20 @@
include(${EXECUTORCH_ROOT}/tools/cmake/Utils.cmake)

function(gen_selected_ops)
set(arg_names LIB_NAME OPS_SCHEMA_YAML ROOT_OPS INCLUDE_ALL_OPS)
set(arg_names LIB_NAME OPS_SCHEMA_YAML ROOT_OPS INCLUDE_ALL_OPS DTYPE_HEADER)
cmake_parse_arguments(GEN "" "" "${arg_names}" ${ARGN})

message(STATUS "Generating operator lib:")
message(STATUS "Generating selected 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}")
message(STATUS " DTYPE_HEADER: ${GEN_DTYPE_HEADER}")

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")
Expand Down Expand Up @@ -53,6 +55,23 @@ function(gen_selected_ops)
WORKING_DIRECTORY ${EXECUTORCH_ROOT}
)

if(GEN_DTYPE_HEADER)
set(_opvariant_h
${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME}/selected_op_variants.h
)
set(_gen_opvariant_command "${PYTHON_EXECUTABLE}" -m codegen.tools.gen_selected_op_variants
--yaml-file=${_oplist_yaml}
--output-dir=${CMAKE_CURRENT_BINARY_DIR}/${GEN_LIB_NAME}/
)
message("Command - ${_gen_opvariant_command}")
add_custom_command(
COMMENT "Generating selected_op_variants.h for ${GEN_LIB_NAME}"
OUTPUT ${_opvariant_h}
COMMAND ${_gen_opvariant_command}
DEPENDS ${_optlist_yaml} ${_codegen_tools_srcs}
WORKING_DIRECTORY ${EXECUTORCH_ROOT}
)
endif()
endfunction()

# Codegen for registering kernels. Kernels are defined in functions_yaml and
Expand All @@ -62,14 +81,15 @@ endfunction()
# functions_yaml CUSTOM_OPS_YAML custom_ops_yaml )
function(generate_bindings_for_kernels)
set(options ADD_EXCEPTION_BOUNDARY)
set(arg_names LIB_NAME FUNCTIONS_YAML CUSTOM_OPS_YAML)
set(arg_names LIB_NAME FUNCTIONS_YAML CUSTOM_OPS_YAML DTYPE_HEADER)
cmake_parse_arguments(GEN "${options}" "${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}")
message(STATUS " ADD_EXCEPTION_BOUNDARY: ${GEN_ADD_EXCEPTION_BOUNDARY}")
message(STATUS " DTYPE_HEADER: ${GEN_DTYPE_HEADER}")

# Command to generate selected_operators.yaml from custom_ops.yaml.
file(GLOB_RECURSE _codegen_templates "${EXECUTORCH_ROOT}/codegen/templates/*")
Expand All @@ -78,6 +98,13 @@ function(generate_bindings_for_kernels)
# By default selective build output is selected_operators.yaml
set(_oplist_yaml ${_out_dir}/selected_operators.yaml)

# If dtype selective build is enable, force header file to be preserved
if(GEN_DTYPE_HEADER)
set(_opvariant_h ${_out_dir}/selected_op_variants.h)
else()
set(_opvariant_h "")
endif()

# Command to codegen C++ wrappers to register custom ops to both PyTorch and
# Executorch runtime.
execute_process(
Expand Down Expand Up @@ -108,6 +135,10 @@ function(generate_bindings_for_kernels)
${_out_dir}/Functions.h ${_out_dir}/NativeFunctions.h
)

if(GEN_DTYPE_HEADER)
list(APPEND _gen_command_sources ${_out_dir}/selected_op_variants.h)
endif()

if(GEN_FUNCTIONS_YAML)
list(APPEND _gen_command --functions-yaml-path=${GEN_FUNCTIONS_YAML})
endif()
Expand All @@ -122,8 +153,9 @@ function(generate_bindings_for_kernels)
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}
DEPENDS ${_oplist_yaml} ${_opvariants_h} ${GEN_CUSTOM_OPS_YAML}
${GEN_FUNCTIONS_YAML} ${_codegen_templates}
${_torchgen_srcs}
WORKING_DIRECTORY ${EXECUTORCH_ROOT}
)
# Make generated file list available in parent scope
Expand Down Expand Up @@ -165,29 +197,43 @@ endfunction()

# Generate a runtime lib for registering operators in Executorch
function(gen_operators_lib)
set(multi_arg_names LIB_NAME KERNEL_LIBS DEPS)
set(multi_arg_names LIB_NAME KERNEL_LIBS DEPS DTYPE_HEADER)
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}")
message(STATUS " DTYPE_HEADER: ${GEN_DTYPE_HEADER}")

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
)
if(GEN_DTYPE_HEADER)
target_sources(
${GEN_LIB_NAME}
PRIVATE ${_out_dir}/RegisterCodegenUnboxedKernelsEverything.cpp
${_out_dir}/Functions.h ${_out_dir}/NativeFunctions.h
${_out_dir}/selected_op_variants.h
)
else()
target_sources(
${GEN_LIB_NAME}
PRIVATE ${_out_dir}/RegisterCodegenUnboxedKernelsEverything.cpp
${_out_dir}/Functions.h ${_out_dir}/NativeFunctions.h
)
endif()

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)
if(GEN_DTYPE_HEADER)
list(APPEND _generated_headers ${_out_dir}/selected_op_variants.h)
endif()
set_target_properties(
${GEN_LIB_NAME} PROPERTIES PUBLIC_HEADER "${_generated_headers}"
)
Expand Down
Loading