xref: /aosp_15_r20/external/pytorch/tools/jit/gen_unboxing.py (revision da0073e96a02ea20f0ac840b70461e3646d07c45)
1*da0073e9SAndroid Build Coastguard Worker# Generates RegisterCodegenUnboxedKernels.cpp, UnboxingFunctions.h and UnboxingFunctions.cpp.
2*da0073e9SAndroid Build Coastguard Worker
3*da0073e9SAndroid Build Coastguard Workerfrom __future__ import annotations
4*da0073e9SAndroid Build Coastguard Worker
5*da0073e9SAndroid Build Coastguard Workerimport argparse
6*da0073e9SAndroid Build Coastguard Workerimport os
7*da0073e9SAndroid Build Coastguard Workerimport sys
8*da0073e9SAndroid Build Coastguard Workerfrom dataclasses import dataclass
9*da0073e9SAndroid Build Coastguard Workerfrom pathlib import Path
10*da0073e9SAndroid Build Coastguard Workerfrom typing import Literal, Sequence, TYPE_CHECKING
11*da0073e9SAndroid Build Coastguard Worker
12*da0073e9SAndroid Build Coastguard Workerimport yaml
13*da0073e9SAndroid Build Coastguard Worker
14*da0073e9SAndroid Build Coastguard Workerfrom torchgen.api import cpp, unboxing
15*da0073e9SAndroid Build Coastguard Workerfrom torchgen.api.translate import translate
16*da0073e9SAndroid Build Coastguard Workerfrom torchgen.api.types import CppSignatureGroup
17*da0073e9SAndroid Build Coastguard Workerfrom torchgen.api.unboxing import convert_arguments
18*da0073e9SAndroid Build Coastguard Workerfrom torchgen.context import method_with_native_function
19*da0073e9SAndroid Build Coastguard Workerfrom torchgen.gen import cpp_string, get_custom_build_selector, parse_native_yaml
20*da0073e9SAndroid Build Coastguard Workerfrom torchgen.model import Argument, NativeFunction, NativeFunctionsGroup, Variant
21*da0073e9SAndroid Build Coastguard Workerfrom torchgen.utils import FileManager, make_file_manager, mapMaybe, Target
22*da0073e9SAndroid Build Coastguard Worker
23*da0073e9SAndroid Build Coastguard Worker
24*da0073e9SAndroid Build Coastguard Workerif TYPE_CHECKING:
25*da0073e9SAndroid Build Coastguard Worker    from torchgen.selective_build.selector import SelectiveBuilder
26*da0073e9SAndroid Build Coastguard Worker
27*da0073e9SAndroid Build Coastguard Worker
28*da0073e9SAndroid Build Coastguard Worker# Generates UnboxingFunctions.h & UnboxingFunctions.cpp.
29*da0073e9SAndroid Build Coastguard Worker@dataclass(frozen=True)
30*da0073e9SAndroid Build Coastguard Workerclass ComputeUnboxingFunctions:
31*da0073e9SAndroid Build Coastguard Worker    target: Literal[Target.DECLARATION, Target.DEFINITION]
32*da0073e9SAndroid Build Coastguard Worker    selector: SelectiveBuilder
33*da0073e9SAndroid Build Coastguard Worker
34*da0073e9SAndroid Build Coastguard Worker    @method_with_native_function
35*da0073e9SAndroid Build Coastguard Worker    def __call__(self, f: NativeFunction) -> str:
36*da0073e9SAndroid Build Coastguard Worker        if not self.selector.is_root_operator(f"aten::{f.func.name}"):
37*da0073e9SAndroid Build Coastguard Worker            return ""
38*da0073e9SAndroid Build Coastguard Worker
39*da0073e9SAndroid Build Coastguard Worker        if self.target is Target.DECLARATION:
40*da0073e9SAndroid Build Coastguard Worker            # Note [The ATen Codegen Unboxing API]
41*da0073e9SAndroid Build Coastguard Worker            # Similar to the ATen Operators API, ATen Codegen Unboxing API lives in the at::unboxing namespace, and
42*da0073e9SAndroid Build Coastguard Worker            # will be used by codegen unboxing wrappers (CodegenUnboxingWrappers.cpp).
43*da0073e9SAndroid Build Coastguard Worker            # The Wrappers will be registered into torch::jit::OperatorRegistry using RegisterOperators API.
44*da0073e9SAndroid Build Coastguard Worker            #
45*da0073e9SAndroid Build Coastguard Worker            # Important characteristics about the Codegen Unboxing API:
46*da0073e9SAndroid Build Coastguard Worker            # (1) It follows the OperatorRegistry API.
47*da0073e9SAndroid Build Coastguard Worker            #     This is kind of necessary to avoid overhead.
48*da0073e9SAndroid Build Coastguard Worker            #     For example: if it followed the C++ API, then all of the faithful C++ factory functions
49*da0073e9SAndroid Build Coastguard Worker            #     would need to wrap their arguments into TensorOptions only to unwrap them again.
50*da0073e9SAndroid Build Coastguard Worker            # (2) Under the hood it calls C++ API.
51*da0073e9SAndroid Build Coastguard Worker            return f"""
52*da0073e9SAndroid Build Coastguard Worker// aten::{f.func}
53*da0073e9SAndroid Build Coastguard WorkerTORCH_API void {f.func.name.unambiguous_name()}(Stack & stack);
54*da0073e9SAndroid Build Coastguard Worker"""
55*da0073e9SAndroid Build Coastguard Worker        else:
56*da0073e9SAndroid Build Coastguard Worker            sig_group = CppSignatureGroup.from_native_function(
57*da0073e9SAndroid Build Coastguard Worker                f, method=(Variant.method in f.variants)
58*da0073e9SAndroid Build Coastguard Worker            )
59*da0073e9SAndroid Build Coastguard Worker            sig = sig_group.most_faithful_signature()
60*da0073e9SAndroid Build Coastguard Worker            # parse arguments into C++ code
61*da0073e9SAndroid Build Coastguard Worker            binding_list, code_list = convert_arguments(f)
62*da0073e9SAndroid Build Coastguard Worker
63*da0073e9SAndroid Build Coastguard Worker            # for each C++ argument, generate the conversion code
64*da0073e9SAndroid Build Coastguard Worker            code_connector = "\n\t"
65*da0073e9SAndroid Build Coastguard Worker            arg_connector = ", "
66*da0073e9SAndroid Build Coastguard Worker            # function call and push back to stack
67*da0073e9SAndroid Build Coastguard Worker            prefix = "self_base." if sig.method else "at::"
68*da0073e9SAndroid Build Coastguard Worker            translated_args = translate(
69*da0073e9SAndroid Build Coastguard Worker                binding_list, sig.arguments(), method=sig.method
70*da0073e9SAndroid Build Coastguard Worker            )
71*da0073e9SAndroid Build Coastguard Worker            args_str = f"{arg_connector.join(e.expr for e in translated_args)}"
72*da0073e9SAndroid Build Coastguard Worker            if len(f.func.returns) == 0:
73*da0073e9SAndroid Build Coastguard Worker                ret_str = ""
74*da0073e9SAndroid Build Coastguard Worker                push_str = ""
75*da0073e9SAndroid Build Coastguard Worker            else:
76*da0073e9SAndroid Build Coastguard Worker                ret_str = "auto result_ = "
77*da0073e9SAndroid Build Coastguard Worker                push_str = """
78*da0073e9SAndroid Build Coastguard Worker    pack(stack, std::move(result_));
79*da0073e9SAndroid Build Coastguard Worker                """
80*da0073e9SAndroid Build Coastguard Worker            return f"""
81*da0073e9SAndroid Build Coastguard Worker// aten::{f.func}
82*da0073e9SAndroid Build Coastguard WorkerTORCH_API void {f.func.name.unambiguous_name()}(Stack & stack) {{
83*da0073e9SAndroid Build Coastguard Worker    {code_connector.join(code_list)}
84*da0073e9SAndroid Build Coastguard Worker
85*da0073e9SAndroid Build Coastguard Worker    drop(stack, {len(binding_list)});
86*da0073e9SAndroid Build Coastguard Worker
87*da0073e9SAndroid Build Coastguard Worker    {ret_str}{prefix}{sig.name()}({args_str});
88*da0073e9SAndroid Build Coastguard Worker    {push_str}
89*da0073e9SAndroid Build Coastguard Worker}}
90*da0073e9SAndroid Build Coastguard Worker"""
91*da0073e9SAndroid Build Coastguard Worker
92*da0073e9SAndroid Build Coastguard Worker
93*da0073e9SAndroid Build Coastguard Worker# Generates RegisterCodegenUnboxedKernels.cpp.
94*da0073e9SAndroid Build Coastguard Worker@dataclass(frozen=True)
95*da0073e9SAndroid Build Coastguard Workerclass ComputeCodegenUnboxedKernels:
96*da0073e9SAndroid Build Coastguard Worker    selector: SelectiveBuilder
97*da0073e9SAndroid Build Coastguard Worker
98*da0073e9SAndroid Build Coastguard Worker    @method_with_native_function
99*da0073e9SAndroid Build Coastguard Worker    def __call__(self, f: NativeFunction) -> str:
100*da0073e9SAndroid Build Coastguard Worker        if not self.selector.is_root_operator(f"aten::{f.func.name}"):
101*da0073e9SAndroid Build Coastguard Worker            return ""
102*da0073e9SAndroid Build Coastguard Worker        # We unconditionally generate function wrappers,
103*da0073e9SAndroid Build Coastguard Worker        sig_group = CppSignatureGroup.from_native_function(f, method=False)
104*da0073e9SAndroid Build Coastguard Worker
105*da0073e9SAndroid Build Coastguard Worker        sig = sig_group.most_faithful_signature()
106*da0073e9SAndroid Build Coastguard Worker
107*da0073e9SAndroid Build Coastguard Worker        # escape double quote in schema, get rid of extra double quotes
108*da0073e9SAndroid Build Coastguard Worker        schema = cpp_string(str(sig.func))[1:-1]
109*da0073e9SAndroid Build Coastguard Worker
110*da0073e9SAndroid Build Coastguard Worker        # arguments
111*da0073e9SAndroid Build Coastguard Worker        args = sig.arguments()
112*da0073e9SAndroid Build Coastguard Worker        connector = ",\n\t\t"
113*da0073e9SAndroid Build Coastguard Worker        args_code = []
114*da0073e9SAndroid Build Coastguard Worker        for arg in args:
115*da0073e9SAndroid Build Coastguard Worker            # Using method=False faithful C++ API, so we should not see SelfArgument/TensorOptionsArgument
116*da0073e9SAndroid Build Coastguard Worker            assert isinstance(arg.argument, Argument)
117*da0073e9SAndroid Build Coastguard Worker            if not arg.argument.default:
118*da0073e9SAndroid Build Coastguard Worker                arg_cpp = "c10::IValue(::std::nullopt)"
119*da0073e9SAndroid Build Coastguard Worker            else:
120*da0073e9SAndroid Build Coastguard Worker                # The unboxing code uses the faithful C++ API to avoid the overhead
121*da0073e9SAndroid Build Coastguard Worker                # from wrapping/unwrapping TensorOptios.
122*da0073e9SAndroid Build Coastguard Worker                # However, we would look to include default args for schema parsing.
123*da0073e9SAndroid Build Coastguard Worker                # Default args only show up in the nonfaithful C++ API,
124*da0073e9SAndroid Build Coastguard Worker                arg_default = cpp.default_expr(
125*da0073e9SAndroid Build Coastguard Worker                    arg.argument.default, arg.argument.type, symint=False
126*da0073e9SAndroid Build Coastguard Worker                )
127*da0073e9SAndroid Build Coastguard Worker                if arg_default.startswith("{"):
128*da0073e9SAndroid Build Coastguard Worker                    arg_cpp = f"c10::IntArrayRef({arg_default})"
129*da0073e9SAndroid Build Coastguard Worker                else:
130*da0073e9SAndroid Build Coastguard Worker                    arg_cpp = f"c10::IValue({arg_default})"
131*da0073e9SAndroid Build Coastguard Worker            args_code.append(
132*da0073e9SAndroid Build Coastguard Worker                f"""c10::Argument("{arg.name}", nullptr, ::std::nullopt, {arg_cpp})"""
133*da0073e9SAndroid Build Coastguard Worker            )
134*da0073e9SAndroid Build Coastguard Worker
135*da0073e9SAndroid Build Coastguard Worker        returns = f.func.returns
136*da0073e9SAndroid Build Coastguard Worker        returns_code = []
137*da0073e9SAndroid Build Coastguard Worker        for ret in returns:
138*da0073e9SAndroid Build Coastguard Worker            returns_code.append(f"""c10::Argument("{ret.name if ret.name else ""}")""")
139*da0073e9SAndroid Build Coastguard Worker        return f"""
140*da0073e9SAndroid Build Coastguard Worker// aten::{schema}
141*da0073e9SAndroid Build Coastguard WorkerOperatorGenerator(
142*da0073e9SAndroid Build Coastguard Worker    "aten::{f.func.name.name}",
143*da0073e9SAndroid Build Coastguard Worker    "{f.func.name.overload_name}",
144*da0073e9SAndroid Build Coastguard Worker    {{
145*da0073e9SAndroid Build Coastguard Worker        {connector.join(args_code)}
146*da0073e9SAndroid Build Coastguard Worker    }},
147*da0073e9SAndroid Build Coastguard Worker    {{
148*da0073e9SAndroid Build Coastguard Worker        {connector.join(returns_code)}
149*da0073e9SAndroid Build Coastguard Worker    }},
150*da0073e9SAndroid Build Coastguard Worker    [](Stack & stack) {{
151*da0073e9SAndroid Build Coastguard Worker        RECORD_FUNCTION("{sig.name()}", std::vector<c10::IValue>());
152*da0073e9SAndroid Build Coastguard Worker        at::unboxing::{unboxing.name(f)}(stack);
153*da0073e9SAndroid Build Coastguard Worker    }},
154*da0073e9SAndroid Build Coastguard Worker    aliasAnalysisFromSchema()
155*da0073e9SAndroid Build Coastguard Worker),
156*da0073e9SAndroid Build Coastguard Worker"""
157*da0073e9SAndroid Build Coastguard Worker
158*da0073e9SAndroid Build Coastguard Worker
159*da0073e9SAndroid Build Coastguard Workerdef gen_unboxing(
160*da0073e9SAndroid Build Coastguard Worker    *,
161*da0073e9SAndroid Build Coastguard Worker    native_functions: Sequence[NativeFunction],
162*da0073e9SAndroid Build Coastguard Worker    cpu_fm: FileManager,
163*da0073e9SAndroid Build Coastguard Worker    selector: SelectiveBuilder,
164*da0073e9SAndroid Build Coastguard Worker) -> None:
165*da0073e9SAndroid Build Coastguard Worker    def key_func(fn: NativeFunction | NativeFunctionsGroup) -> str:
166*da0073e9SAndroid Build Coastguard Worker        return fn.root_name
167*da0073e9SAndroid Build Coastguard Worker
168*da0073e9SAndroid Build Coastguard Worker    selected_op_num: int = len(selector.operators)
169*da0073e9SAndroid Build Coastguard Worker    # a best practice threshold of operators to enable sharding
170*da0073e9SAndroid Build Coastguard Worker    sharding_threshold: int = 100
171*da0073e9SAndroid Build Coastguard Worker    cpu_fm.write_sharded(
172*da0073e9SAndroid Build Coastguard Worker        "UnboxingFunctions.cpp",
173*da0073e9SAndroid Build Coastguard Worker        native_functions,
174*da0073e9SAndroid Build Coastguard Worker        key_fn=key_func,
175*da0073e9SAndroid Build Coastguard Worker        env_callable=lambda fn: {
176*da0073e9SAndroid Build Coastguard Worker            "definitions": [ComputeUnboxingFunctions(Target.DEFINITION, selector)(fn)]
177*da0073e9SAndroid Build Coastguard Worker        },
178*da0073e9SAndroid Build Coastguard Worker        num_shards=1 if selected_op_num < sharding_threshold else 5,
179*da0073e9SAndroid Build Coastguard Worker        sharded_keys={"definitions"},
180*da0073e9SAndroid Build Coastguard Worker    )
181*da0073e9SAndroid Build Coastguard Worker    cpu_fm.write(
182*da0073e9SAndroid Build Coastguard Worker        "UnboxingFunctions.h",
183*da0073e9SAndroid Build Coastguard Worker        lambda: {
184*da0073e9SAndroid Build Coastguard Worker            "declarations": list(
185*da0073e9SAndroid Build Coastguard Worker                mapMaybe(
186*da0073e9SAndroid Build Coastguard Worker                    ComputeUnboxingFunctions(Target.DECLARATION, selector),
187*da0073e9SAndroid Build Coastguard Worker                    native_functions,
188*da0073e9SAndroid Build Coastguard Worker                )
189*da0073e9SAndroid Build Coastguard Worker            ),
190*da0073e9SAndroid Build Coastguard Worker        },
191*da0073e9SAndroid Build Coastguard Worker    )
192*da0073e9SAndroid Build Coastguard Worker    cpu_fm.write_sharded(
193*da0073e9SAndroid Build Coastguard Worker        "RegisterCodegenUnboxedKernels.cpp",
194*da0073e9SAndroid Build Coastguard Worker        native_functions,
195*da0073e9SAndroid Build Coastguard Worker        key_fn=key_func,
196*da0073e9SAndroid Build Coastguard Worker        env_callable=lambda fn: {
197*da0073e9SAndroid Build Coastguard Worker            "unboxed_ops": [ComputeCodegenUnboxedKernels(selector)(fn)]
198*da0073e9SAndroid Build Coastguard Worker        },
199*da0073e9SAndroid Build Coastguard Worker        num_shards=1 if selected_op_num < sharding_threshold else 10,
200*da0073e9SAndroid Build Coastguard Worker        sharded_keys={"unboxed_ops"},
201*da0073e9SAndroid Build Coastguard Worker    )
202*da0073e9SAndroid Build Coastguard Worker
203*da0073e9SAndroid Build Coastguard Worker
204*da0073e9SAndroid Build Coastguard Workerdef main(args: list[str]) -> None:
205*da0073e9SAndroid Build Coastguard Worker    parser = argparse.ArgumentParser(description="Generate unboxing source files")
206*da0073e9SAndroid Build Coastguard Worker    parser.add_argument(
207*da0073e9SAndroid Build Coastguard Worker        "-s",
208*da0073e9SAndroid Build Coastguard Worker        "--source-path",
209*da0073e9SAndroid Build Coastguard Worker        help="path to source directory for ATen",
210*da0073e9SAndroid Build Coastguard Worker        default="aten/src/ATen",
211*da0073e9SAndroid Build Coastguard Worker    )
212*da0073e9SAndroid Build Coastguard Worker    parser.add_argument(
213*da0073e9SAndroid Build Coastguard Worker        "-d",
214*da0073e9SAndroid Build Coastguard Worker        "--install-dir",
215*da0073e9SAndroid Build Coastguard Worker        "--install_dir",
216*da0073e9SAndroid Build Coastguard Worker        help="output directory",
217*da0073e9SAndroid Build Coastguard Worker        default="build/aten/src/ATen",
218*da0073e9SAndroid Build Coastguard Worker    )
219*da0073e9SAndroid Build Coastguard Worker    parser.add_argument(
220*da0073e9SAndroid Build Coastguard Worker        "-o",
221*da0073e9SAndroid Build Coastguard Worker        "--output-dependencies",
222*da0073e9SAndroid Build Coastguard Worker        help="output a list of dependencies into the given file and exit",
223*da0073e9SAndroid Build Coastguard Worker    )
224*da0073e9SAndroid Build Coastguard Worker    parser.add_argument(
225*da0073e9SAndroid Build Coastguard Worker        "--dry-run",
226*da0073e9SAndroid Build Coastguard Worker        action="store_true",
227*da0073e9SAndroid Build Coastguard Worker        help="run without writing any files (still updates outputs)",
228*da0073e9SAndroid Build Coastguard Worker    )
229*da0073e9SAndroid Build Coastguard Worker    parser.add_argument(
230*da0073e9SAndroid Build Coastguard Worker        "--op-selection-yaml-path",
231*da0073e9SAndroid Build Coastguard Worker        "--op_selection_yaml_path",
232*da0073e9SAndroid Build Coastguard Worker        help="Provide a path to the operator selection (for custom build) YAML "
233*da0073e9SAndroid Build Coastguard Worker        "that contains the information about the set of selected operators "
234*da0073e9SAndroid Build Coastguard Worker        "and their categories (training, ...). Each operator is either a "
235*da0073e9SAndroid Build Coastguard Worker        "full operator name with overload or just a bare operator name. "
236*da0073e9SAndroid Build Coastguard Worker        "The operator names also contain the namespace prefix (e.g. aten::)",
237*da0073e9SAndroid Build Coastguard Worker    )
238*da0073e9SAndroid Build Coastguard Worker    parser.add_argument(
239*da0073e9SAndroid Build Coastguard Worker        "--op-registration-allowlist",
240*da0073e9SAndroid Build Coastguard Worker        "--op_registration_allowlist",
241*da0073e9SAndroid Build Coastguard Worker        nargs="*",
242*da0073e9SAndroid Build Coastguard Worker        help="filter op registrations by the allowlist (if set); "
243*da0073e9SAndroid Build Coastguard Worker        "each item is `namespace`::`operator name` without overload name; "
244*da0073e9SAndroid Build Coastguard Worker        "e.g.: aten::empty aten::conv2d ...",
245*da0073e9SAndroid Build Coastguard Worker    )
246*da0073e9SAndroid Build Coastguard Worker    parser.add_argument(
247*da0073e9SAndroid Build Coastguard Worker        "--TEST-ONLY-op-registration-allowlist-yaml-path",
248*da0073e9SAndroid Build Coastguard Worker        "--TEST_ONLY_op_registration_allowlist_yaml_path",
249*da0073e9SAndroid Build Coastguard Worker        help="Provide a path to the operator selection (for custom build) YAML "
250*da0073e9SAndroid Build Coastguard Worker        "which contains a list of operators. It is to serve testing purpose and "
251*da0073e9SAndroid Build Coastguard Worker        "each item is `namespace`::`operator name` without overload name; "
252*da0073e9SAndroid Build Coastguard Worker        "e.g.: aten::empty aten::conv2d ...",
253*da0073e9SAndroid Build Coastguard Worker    )
254*da0073e9SAndroid Build Coastguard Worker
255*da0073e9SAndroid Build Coastguard Worker    options = parser.parse_args(args)
256*da0073e9SAndroid Build Coastguard Worker    if options.op_registration_allowlist:
257*da0073e9SAndroid Build Coastguard Worker        op_registration_allowlist = options.op_registration_allowlist
258*da0073e9SAndroid Build Coastguard Worker    elif options.TEST_ONLY_op_registration_allowlist_yaml_path:
259*da0073e9SAndroid Build Coastguard Worker        with open(options.TEST_ONLY_op_registration_allowlist_yaml_path) as f:
260*da0073e9SAndroid Build Coastguard Worker            op_registration_allowlist = yaml.safe_load(f)
261*da0073e9SAndroid Build Coastguard Worker    else:
262*da0073e9SAndroid Build Coastguard Worker        op_registration_allowlist = None
263*da0073e9SAndroid Build Coastguard Worker
264*da0073e9SAndroid Build Coastguard Worker    selector = get_custom_build_selector(
265*da0073e9SAndroid Build Coastguard Worker        op_registration_allowlist,
266*da0073e9SAndroid Build Coastguard Worker        options.op_selection_yaml_path,
267*da0073e9SAndroid Build Coastguard Worker    )
268*da0073e9SAndroid Build Coastguard Worker
269*da0073e9SAndroid Build Coastguard Worker    native_yaml_path = os.path.join(options.source_path, "native/native_functions.yaml")
270*da0073e9SAndroid Build Coastguard Worker    tags_yaml_path = os.path.join(options.source_path, "native/tags.yaml")
271*da0073e9SAndroid Build Coastguard Worker    parsed_yaml = parse_native_yaml(native_yaml_path, tags_yaml_path)
272*da0073e9SAndroid Build Coastguard Worker    native_functions, backend_indices = (
273*da0073e9SAndroid Build Coastguard Worker        parsed_yaml.native_functions,
274*da0073e9SAndroid Build Coastguard Worker        parsed_yaml.backend_indices,
275*da0073e9SAndroid Build Coastguard Worker    )
276*da0073e9SAndroid Build Coastguard Worker
277*da0073e9SAndroid Build Coastguard Worker    cpu_fm = make_file_manager(options=options)
278*da0073e9SAndroid Build Coastguard Worker    gen_unboxing(native_functions=native_functions, cpu_fm=cpu_fm, selector=selector)
279*da0073e9SAndroid Build Coastguard Worker
280*da0073e9SAndroid Build Coastguard Worker    if options.output_dependencies:
281*da0073e9SAndroid Build Coastguard Worker        depfile_path = Path(options.output_dependencies).resolve()
282*da0073e9SAndroid Build Coastguard Worker        depfile_name = depfile_path.name
283*da0073e9SAndroid Build Coastguard Worker        depfile_stem = depfile_path.stem
284*da0073e9SAndroid Build Coastguard Worker
285*da0073e9SAndroid Build Coastguard Worker        path = depfile_path.parent / depfile_name
286*da0073e9SAndroid Build Coastguard Worker        cpu_fm.write_outputs(depfile_stem, str(path))
287*da0073e9SAndroid Build Coastguard Worker
288*da0073e9SAndroid Build Coastguard Worker
289*da0073e9SAndroid Build Coastguard Workerif __name__ == "__main__":
290*da0073e9SAndroid Build Coastguard Worker    main(sys.argv[1:])
291