1212from pathlib import Path
1313from typing import Any , Callable , TextIO , TYPE_CHECKING
1414
15+ import torchgen
1516import yaml
1617
1718try :
6970 OperatorName ,
7071 Variant ,
7172)
72- from torchgen .utils import (
73- context ,
74- FileManager ,
75- make_file_manager ,
76- mapMaybe ,
77- NamespaceHelper ,
78- )
73+ from torchgen .utils import context , FileManager , mapMaybe , NamespaceHelper
7974
8075
8176if TYPE_CHECKING :
@@ -871,11 +866,110 @@ def function_filter(f: NativeFunction) -> bool:
871866 return combined_yaml , custom_ops_parsed_yaml
872867
873868
869+ def generate (
870+ * ,
871+ source_path : str ,
872+ install_dir : str ,
873+ tags_path : str | None = None ,
874+ aten_yaml_path : str | None = None ,
875+ functions_yaml_path : str | None = None ,
876+ custom_ops_yaml_path : str | None = None ,
877+ op_selection_yaml_path : str | None = None ,
878+ op_registration_whitelist : list [str ] | None = None ,
879+ use_aten_lib : bool = False ,
880+ manual_registration : bool = False ,
881+ outputs : Sequence [str ] = ("headers" , "sources" ),
882+ add_exception_boundary : bool = False ,
883+ rocm : bool = False ,
884+ dry_run : bool = False ,
885+ output_dependencies : str | None = None ,
886+ ) -> None :
887+ """Generates the operator headers and registration sources into install_dir.
888+
889+ The arguments match main()'s command-line flags; source_path is the
890+ directory holding the templates/ subdirectory, and outputs is --generate.
891+ tags_path and aten_yaml_path default to the copies of tags.yaml and
892+ native_functions.yaml packaged with torchgen. torchgen caches each parsed
893+ yaml by path for the life of the process, so don't rewrite aten_yaml_path
894+ or custom_ops_yaml_path in place between calls.
895+ """
896+ packaged = os .path .join (os .path .dirname (torchgen .__file__ ), "packaged/ATen/native" )
897+ tags_path = tags_path or os .path .join (packaged , "tags.yaml" )
898+ aten_yaml_path = aten_yaml_path or os .path .join (packaged , "native_functions.yaml" )
899+
900+ selector = get_custom_build_selector (
901+ op_registration_whitelist ,
902+ op_selection_yaml_path ,
903+ )
904+
905+ parsed_yaml , custom_ops_parsed_yaml = parse_yaml_files (
906+ aten_yaml_path = aten_yaml_path ,
907+ tags_yaml_path = tags_path ,
908+ native_yaml_path = functions_yaml_path ,
909+ custom_ops_yaml_path = custom_ops_yaml_path ,
910+ selector = selector ,
911+ use_aten_lib = use_aten_lib ,
912+ )
913+ native_functions , kernel_index = (
914+ parsed_yaml .native_functions ,
915+ parsed_yaml .kernel_index ,
916+ )
917+ custom_ops_native_functions = (
918+ custom_ops_parsed_yaml .native_functions if custom_ops_parsed_yaml else []
919+ )
920+
921+ cpu_fm = FileManager (
922+ install_dir = install_dir ,
923+ template_dir = os .path .join (source_path , "templates" ),
924+ dry_run = dry_run ,
925+ )
926+
927+ if "headers" in outputs :
928+ # generate CustomOpsNativeFunctions.h when custom_ops.yaml is present, to match the build system.
929+ gen_headers (
930+ native_functions = native_functions ,
931+ gen_custom_ops_header = bool (custom_ops_yaml_path ),
932+ custom_ops_native_functions = custom_ops_native_functions ,
933+ selector = selector ,
934+ kernel_index = kernel_index ,
935+ cpu_fm = cpu_fm ,
936+ use_aten_lib = use_aten_lib ,
937+ )
938+
939+ if "sources" in outputs :
940+ gen_unboxing (
941+ native_functions = native_functions ,
942+ cpu_fm = cpu_fm ,
943+ selector = selector ,
944+ use_aten_lib = use_aten_lib ,
945+ kernel_index = kernel_index ,
946+ manual_registration = manual_registration ,
947+ add_exception_boundary = add_exception_boundary ,
948+ )
949+ if custom_ops_native_functions :
950+ gen_custom_ops (
951+ native_functions = custom_ops_native_functions ,
952+ selector = selector ,
953+ kernel_index = kernel_index ,
954+ cpu_fm = cpu_fm ,
955+ rocm = rocm ,
956+ )
957+
958+ if output_dependencies :
959+ depfile_path = Path (output_dependencies ).resolve ()
960+ depfile_name = depfile_path .name
961+ depfile_stem = depfile_path .stem
962+
963+ for fm , prefix in [
964+ (cpu_fm , "" ),
965+ ]:
966+ varname = prefix + depfile_stem
967+ path = depfile_path .parent / (prefix + depfile_name )
968+ fm .write_outputs (varname , str (path ))
969+
970+
874971def main () -> None :
875972 parser = argparse .ArgumentParser (description = "Generate operator source files" )
876- # Although we don't refer to --source-path directly, make_file_manager()
877- # expects it to point to a directory that contains a templates/ subdirectory
878- # containing the file templates.
879973 parser .add_argument (
880974 "-s" ,
881975 "--source-path" ,
@@ -898,9 +992,8 @@ def main() -> None:
898992 parser .add_argument (
899993 "--aten-yaml-path" ,
900994 "--aten_yaml_path" ,
901- help = "path to native_functions.yaml file." ,
995+ help = "path to native_functions.yaml file (default: torchgen's packaged copy) ." ,
902996 )
903- # Note that make_file_manager() also looks at --install-dir.
904997 parser .add_argument (
905998 "-d" ,
906999 "--install-dir" ,
@@ -913,8 +1006,6 @@ def main() -> None:
9131006 "--output-dependencies" ,
9141007 help = "output a list of dependencies into the given file and exit" ,
9151008 )
916- # Although we don't refer to --dry-run directly, make_file_manager() looks
917- # for it.
9181009 parser .add_argument (
9191010 "--dry-run" ,
9201011 action = "store_true" ,
@@ -945,7 +1036,7 @@ def main() -> None:
9451036 )
9461037 parser .add_argument (
9471038 "--tags-path" ,
948- help = "Path to tags.yaml. Required by yaml parsing in codegen system ." ,
1039+ help = "Path to tags.yaml (default: torchgen's packaged copy) ." ,
9491040 )
9501041 parser .add_argument (
9511042 "--rocm" ,
@@ -982,73 +1073,23 @@ def main() -> None:
9821073 "convert exceptions to clean failures." ,
9831074 )
9841075 options = parser .parse_args ()
985- assert options .tags_path , "tags.yaml is required by codegen yaml parsing."
986-
987- selector = get_custom_build_selector (
988- options .op_registration_whitelist ,
989- options .op_selection_yaml_path ,
990- )
991-
992- parsed_yaml , custom_ops_parsed_yaml = parse_yaml_files (
1076+ generate (
1077+ source_path = options .source_path ,
1078+ install_dir = options .install_dir ,
1079+ tags_path = options .tags_path ,
9931080 aten_yaml_path = options .aten_yaml_path ,
994- tags_yaml_path = options .tags_path ,
995- native_yaml_path = options .functions_yaml_path ,
1081+ functions_yaml_path = options .functions_yaml_path ,
9961082 custom_ops_yaml_path = options .custom_ops_yaml_path ,
997- selector = selector ,
1083+ op_selection_yaml_path = options .op_selection_yaml_path ,
1084+ op_registration_whitelist = options .op_registration_whitelist ,
9981085 use_aten_lib = options .use_aten_lib ,
1086+ manual_registration = options .manual_registration ,
1087+ outputs = options .generate ,
1088+ add_exception_boundary = options .add_exception_boundary ,
1089+ rocm = options .rocm ,
1090+ dry_run = options .dry_run ,
1091+ output_dependencies = options .output_dependencies ,
9991092 )
1000- native_functions , kernel_index = (
1001- parsed_yaml .native_functions ,
1002- parsed_yaml .kernel_index ,
1003- )
1004- custom_ops_native_functions = (
1005- custom_ops_parsed_yaml .native_functions if custom_ops_parsed_yaml else []
1006- )
1007-
1008- cpu_fm = make_file_manager (options = options )
1009-
1010- if "headers" in options .generate :
1011- # generate CustomOpsNativeFunctions.h when custom_ops.yaml is present, to match the build system.
1012- gen_headers (
1013- native_functions = native_functions ,
1014- gen_custom_ops_header = options .custom_ops_yaml_path ,
1015- custom_ops_native_functions = custom_ops_native_functions ,
1016- selector = selector ,
1017- kernel_index = kernel_index ,
1018- cpu_fm = cpu_fm ,
1019- use_aten_lib = options .use_aten_lib ,
1020- )
1021-
1022- if "sources" in options .generate :
1023- gen_unboxing (
1024- native_functions = native_functions ,
1025- cpu_fm = cpu_fm ,
1026- selector = selector ,
1027- use_aten_lib = options .use_aten_lib ,
1028- kernel_index = kernel_index ,
1029- manual_registration = options .manual_registration ,
1030- add_exception_boundary = options .add_exception_boundary ,
1031- )
1032- if custom_ops_native_functions :
1033- gen_custom_ops (
1034- native_functions = custom_ops_native_functions ,
1035- selector = selector ,
1036- kernel_index = kernel_index ,
1037- cpu_fm = cpu_fm ,
1038- rocm = options .rocm ,
1039- )
1040-
1041- if options .output_dependencies :
1042- depfile_path = Path (options .output_dependencies ).resolve ()
1043- depfile_name = depfile_path .name
1044- depfile_stem = depfile_path .stem
1045-
1046- for fm , prefix in [
1047- (cpu_fm , "" ),
1048- ]:
1049- varname = prefix + depfile_stem
1050- path = depfile_path .parent / (prefix + depfile_name )
1051- fm .write_outputs (varname , str (path ))
10521093
10531094
10541095if __name__ == "__main__" :
0 commit comments