3
3
Generates .pte model, operator definitions, and header files
4
4
"""
5
5
6
+ import argparse
6
7
import os
7
- import sys
8
8
import subprocess
9
- import argparse
9
+ import sys
10
10
from pathlib import Path
11
11
12
+
12
13
def run_command (cmd , cwd = None , description = "" ):
13
14
"""Run a command and handle errors"""
14
15
print (f"Running: { description } " )
15
16
print (f"Command: { ' ' .join (cmd )} " )
16
-
17
+
17
18
try :
18
- result = subprocess .run (cmd , cwd = cwd , check = True , capture_output = True , text = True )
19
+ result = subprocess .run (
20
+ cmd , cwd = cwd , check = True , capture_output = True , text = True
21
+ )
19
22
print (f"✓ { description } completed successfully" )
20
23
if result .stdout :
21
24
print (f"Output: { result .stdout } " )
@@ -25,120 +28,160 @@ def run_command(cmd, cwd=None, description=""):
25
28
print (f"Error: { e .stderr } " )
26
29
sys .exit (1 )
27
30
31
+
28
32
def main ():
29
- parser = argparse .ArgumentParser (description = "Build ExecuTorch ARM Hello World model" )
30
- parser .add_argument ("--executorch-root" , default = "~/optional/modules/lib/executorch" ,
31
- help = "Path to ExecuTorch root directory" )
32
- parser .add_argument ("--model-name" , default = "add" ,
33
- help = "Name of the model (default: add)" )
34
- parser .add_argument ("--clean" , action = "store_true" ,
35
- help = "Clean generated files before building" )
36
-
33
+ parser = argparse .ArgumentParser (
34
+ description = "Build ExecuTorch ARM Hello World model"
35
+ )
36
+ parser .add_argument (
37
+ "--project-root" ,
38
+ default = "~/" ,
39
+ help = "Path to project root (should be zephry/../)" ,
40
+ required = True ,
41
+ )
42
+ parser .add_argument (
43
+ "--model-name" , default = "add" , help = "Name of the model (default: add)"
44
+ )
45
+ parser .add_argument (
46
+ "--clean" , action = "store_true" , help = "Clean generated files before building"
47
+ )
48
+
37
49
args = parser .parse_args ()
38
-
50
+
39
51
# Paths
40
52
script_dir = Path (__file__ ).parent
41
- project_root = script_dir . parent . parent . parent . parent . parent . parent # Go up to petriok root
42
- executorch_root = project_root / args . executorch_root
43
- example_files_dir = "/home/zephyruser/zephyr/samples/modules/executorch/arm/hello_world/example_files"
53
+ project_root = Path ( args . project_root )
54
+ executorch_root = project_root / "modules" / "lib" / "executorch"
55
+
44
56
src_dir = script_dir / "src"
45
-
57
+
46
58
model_name = args .model_name
47
59
pte_file = f"{ model_name } .pte"
48
60
ops_def_file = "gen_ops_def.yml"
49
61
header_file = "model_pte.h"
50
-
62
+
51
63
print (f"Building ExecuTorch model: { model_name } " )
52
64
print (f"ExecuTorch root: { executorch_root } " )
53
65
print (f"Working directory: { script_dir } " )
54
-
66
+
55
67
# Clean previous build if requested
56
68
if args .clean :
57
69
files_to_clean = [pte_file , ops_def_file , src_dir / header_file ]
58
70
for file_path in files_to_clean :
59
71
if Path (file_path ).exists ():
60
72
Path (file_path ).unlink ()
61
73
print (f"Cleaned: { file_path } " )
62
-
74
+
63
75
# Step 1: Generate the .pte model file
64
- export_script = os .path .join (example_files_dir , f"export_{ model_name } .py" )
65
- if not os .path .exists (export_script ):
76
+ export_script = (
77
+ executorch_root / "extension" / "embedded" / "export_{model_name}.py"
78
+ )
79
+ if not export_script .exists ():
66
80
print (f"Error: Export script not found: { export_script } " )
67
81
sys .exit (1 )
68
-
82
+
69
83
try :
70
84
run_command (
71
85
[sys .executable , str (export_script )],
72
86
cwd = script_dir ,
73
- description = "Generating .pte model file"
87
+ description = "Generating .pte model file" ,
74
88
)
75
89
except SystemExit :
76
- print (f"\n ❌ Model generation failed. This is likely because PyTorch/ExecuTorch is not installed." )
77
- print (f"For now, using dummy model_pte.h for compilation testing." )
78
- print (f"To generate a real model, install PyTorch and ExecuTorch:" )
79
- print (f" pip install torch" )
80
- print (f" # Install ExecuTorch according to documentation" )
81
- print (f" python build_model.py" )
90
+ print (
91
+ "\n ❌ Model generation failed. This is likely because PyTorch/ExecuTorch is not installed."
92
+ )
93
+ print ("For now, using dummy model_pte.h for compilation testing." )
94
+ print ("To generate a real model, install PyTorch and ExecuTorch:" )
95
+ print (" pip install torch" )
96
+ print (" # Install ExecuTorch according to documentation" )
97
+ print (" python build_model.py" )
82
98
return
83
-
99
+
84
100
if not Path (script_dir / pte_file ).exists ():
85
101
print (f"Error: Model file { pte_file } was not generated" )
86
102
sys .exit (1 )
87
-
103
+
88
104
# Step 2: Generate operator definitions
89
105
90
- gen_ops_script = "/home/zephyruser/optional/modules/lib/executorch/codegen/tools/gen_ops_def.py"
106
+ gen_ops_script = (
107
+ "/home/zephyruser/optional/modules/lib/executorch/codegen/tools/gen_ops_def.py"
108
+ )
91
109
if not os .path .exists (gen_ops_script ):
92
110
print (f"Error: gen_ops_def.py not found at { gen_ops_script } " )
93
111
sys .exit (1 )
94
-
112
+
95
113
run_command (
96
- [sys .executable , str (gen_ops_script ),
97
- "--output_path" , ops_def_file ,
98
- "--model_file_path" , pte_file ],
114
+ [
115
+ sys .executable ,
116
+ str (gen_ops_script ),
117
+ "--output_path" ,
118
+ ops_def_file ,
119
+ "--model_file_path" ,
120
+ pte_file ,
121
+ ],
99
122
cwd = script_dir ,
100
- description = "Generating operator definitions"
123
+ description = "Generating operator definitions" ,
101
124
)
102
-
125
+
103
126
# Step 3: Convert .pte to header file
104
- #pte_to_header_script = executorch_root / "examples" / "arm" / "executor_runner" / "pte_to_header.py"
127
+ # pte_to_header_script = executorch_root / "examples" / "arm" / "executor_runner" / "pte_to_header.py"
105
128
pte_to_header_script = "/home/zephyruser/optional/modules/lib/executorch/examples/arm/executor_runner/pte_to_header.py"
106
129
if not os .path .exists (pte_to_header_script ):
107
130
print (f"Error: pte_to_header.py not found at { pte_to_header_script } " )
108
131
sys .exit (1 )
109
-
132
+
110
133
run_command (
111
- [sys .executable , str (pte_to_header_script ),
112
- "--pte" , pte_file ,
113
- "--outdir" , "src" ],
134
+ [
135
+ sys .executable ,
136
+ str (pte_to_header_script ),
137
+ "--pte" ,
138
+ pte_file ,
139
+ "--outdir" ,
140
+ "src" ,
141
+ ],
114
142
cwd = script_dir ,
115
- description = "Converting .pte to header file"
143
+ description = "Converting .pte to header file" ,
116
144
)
117
-
145
+
118
146
# Step 4: Make the generated array const and remove section attribute
119
147
header_path = src_dir / header_file
120
148
if header_path .exists ():
121
149
content = header_path .read_text ()
122
-
150
+
123
151
# Remove section attribute and replace with Zephyr alignment macro
124
152
import re
153
+
125
154
# Replace section+aligned pattern with Zephyr __ALIGN macro
126
- content = re .sub (r'__attribute__\s*\(\s*\(\s*section\s*\([^)]*\)\s*,\s*aligned\s*\(([^)]*)\)\s*\)\s*\)\s*' , r'__ALIGN(\1) ' , content )
127
- # Remove any remaining section-only attributes
128
- content = re .sub (r'__attribute__\s*\(\s*\(\s*section\s*\([^)]*\)\s*\)\s*\)\s*' , '' , content )
155
+ content = re .sub (
156
+ r"__attribute__\s*\(\s*\(\s*section\s*\([^)]*\)\s*,\s*aligned\s*\(([^)]*)\)\s*\)\s*\)\s*" ,
157
+ r"__ALIGN(\1) " ,
158
+ content ,
159
+ )
160
+ # Remove any remaining section-only attributes
161
+ content = re .sub (
162
+ r"__attribute__\s*\(\s*\(\s*section\s*\([^)]*\)\s*\)\s*\)\s*" , "" , content
163
+ )
129
164
# Also replace any standalone __attribute__((aligned(n))) with __ALIGN(n)
130
- content = re .sub (r'__attribute__\s*\(\s*\(\s*aligned\s*\(([^)]*)\)\s*\)\s*\)\s*' , r'__ALIGN(\1) ' , content )
131
-
165
+ content = re .sub (
166
+ r"__attribute__\s*\(\s*\(\s*aligned\s*\(([^)]*)\)\s*\)\s*\)\s*" ,
167
+ r"__ALIGN(\1) " ,
168
+ content ,
169
+ )
170
+
132
171
# Replace 'char model_pte_data[]' with 'const char model_pte_data[]'
133
- content = content .replace ('char model_pte_data[]' , 'const char model_pte_data[]' )
172
+ content = content .replace (
173
+ "char model_pte_data[]" , "const char model_pte_data[]"
174
+ )
134
175
# Also handle 'char model_pte[]' variant
135
- content = content .replace (' char model_pte[]' , ' const char model_pte[]' )
136
-
176
+ content = content .replace (" char model_pte[]" , " const char model_pte[]" )
177
+
137
178
header_path .write_text (content )
138
- print (f"✓ Made model data const and removed section attributes in { header_file } " )
179
+ print (
180
+ f"✓ Made model data const and removed section attributes in { header_file } "
181
+ )
139
182
else :
140
183
print (f"Warning: Header file { header_file } not found" )
141
-
184
+
142
185
print ("\n === Build Summary ===" )
143
186
print (f"✓ Generated: { pte_file } " )
144
187
print (f"✓ Generated: { ops_def_file } " )
@@ -147,5 +190,6 @@ def main():
147
190
print ("1. Review gen_ops_def.yml and customize if needed" )
148
191
print ("2. Build the Zephyr application with west build" )
149
192
193
+
150
194
if __name__ == "__main__" :
151
- main ()
195
+ main ()
0 commit comments