11"""Generate CoreML-delegated test fixtures for the Swift/ObjC bindings.
22
33Currently produces:
4- - add_coreml.pte: a CoreML-delegated tensor-add model whose forward(x, y)
5- returns x + y. Used by ModuleTest.testLoadWithBackendOptionsThenExecuteOnCoreML
6- to exercise the BackendOptionsMap lifetime path end-to-end against a
7- delegated model (add.pte has no delegates, so the per-delegate option
8- lookup path is only exercised with a delegated fixture like this one).
4+ - add_coreml.pte: a single-method CoreML-delegated tensor-add model whose
5+ forward(x, y) returns x + y.
6+ - add_mul_coreml.pte: a two-method CoreML-delegated model exposing
7+ forward(x, y) = x + y and mul(x, y) = x * y. Used to exercise mixed
8+ load(options:) / load(_:options:) sequences where one method is loaded
9+ explicitly with its own options and another is loaded lazily, so the
10+ C++ Module's stored backend_options_ is consulted during the lazy path.
11+ A non-delegated or single-method fixture does not reach that code path.
912
1013Usage:
1114 python extension/apple/ExecuTorch/__tests__/resources/generate_coreml_test_models.py
1215
1316This script is invoked by scripts/build_apple_frameworks.sh in CI before
14- `swift test` so the fixture is always present in CI runs. The output .pte is
15- gitignored; local developers who want to run the CoreML-dependent tests should
16- run this script once.
17+ `swift test` so the fixtures are always present in CI runs. The output .pte
18+ files are gitignored; local developers who want to run the CoreML-dependent
19+ tests should run this script once.
1720"""
1821
1922import os
@@ -30,22 +33,38 @@ def forward(self, x: torch.Tensor, y: torch.Tensor) -> torch.Tensor:
3033 return x + y
3134
3235
33- def main () -> None :
34- model = AddModule (). eval ()
35- example_inputs = ( torch . tensor ([ 1.0 ]), torch . tensor ([ 1.0 ]))
36+ class MulModule ( nn . Module ) :
37+ def forward ( self , x : torch . Tensor , y : torch . Tensor ) -> torch . Tensor :
38+ return x * y
3639
37- ep = torch .export .export (model , example_inputs )
38- lowered = to_edge_transform_and_lower (
39- ep ,
40- partitioner = [CoreMLPartitioner ()],
41- )
42- exec_program = lowered .to_executorch ()
4340
44- out_path = os .path .join (os .path .dirname (__file__ ), "add_coreml.pte" )
41+ def _write_pte (exec_program , filename : str ) -> None :
42+ out_path = os .path .join (os .path .dirname (__file__ ), filename )
4543 with open (out_path , "wb" ) as f :
4644 exec_program .write_to_file (f )
4745 print (f"Wrote { out_path } ({ os .path .getsize (out_path )} bytes)" )
4846
4947
48+ def main () -> None :
49+ example_inputs = (torch .tensor ([1.0 ]), torch .tensor ([1.0 ]))
50+
51+ # Single-method add model.
52+ ep_add = torch .export .export (AddModule ().eval (), example_inputs )
53+ add_only = to_edge_transform_and_lower (
54+ ep_add ,
55+ partitioner = [CoreMLPartitioner ()],
56+ ).to_executorch ()
57+ _write_pte (add_only , "add_coreml.pte" )
58+
59+ # Two-method model: forward (add) and mul. Both are CoreML-delegated so
60+ # each has its own per-delegate option set to query at load time.
61+ ep_mul = torch .export .export (MulModule ().eval (), example_inputs )
62+ add_mul = to_edge_transform_and_lower (
63+ {"forward" : ep_add , "mul" : ep_mul },
64+ partitioner = [CoreMLPartitioner ()],
65+ ).to_executorch ()
66+ _write_pte (add_mul , "add_mul_coreml.pte" )
67+
68+
5069if __name__ == "__main__" :
5170 main ()
0 commit comments