@@ -135,10 +135,20 @@ def freeze_mpy(path, script=None, opt=0):
135
135
KIND_MPY = 3
136
136
137
137
VARS = {}
138
+ MPY_CROSS = None
139
+ MPY_TOOL = None
138
140
139
141
manifest_list = []
140
142
141
143
144
+ QUIET = False
145
+
146
+
147
+ def log (* args ):
148
+ if not QUIET :
149
+ print (* args )
150
+
151
+
142
152
class IncludeOptions :
143
153
def __init__ (self , ** kwargs ):
144
154
self ._kwargs = kwargs
@@ -166,7 +176,12 @@ def system(cmd):
166
176
def convert_path (path ):
167
177
# Perform variable substituion.
168
178
for name , value in VARS .items ():
169
- path = path .replace ("$({})" .format (name ), value )
179
+ pattern = "$({})" .format (name )
180
+ if value is not None :
181
+ path = path .replace (pattern , value )
182
+ elif pattern in path :
183
+ raise SystemExit ("{} variable must be specified" .format (name ))
184
+
170
185
# Convert to absolute path (so that future operations don't rely on
171
186
# still being chdir'ed).
172
187
return os .path .abspath (path )
@@ -225,7 +240,7 @@ def freeze_internal(kind, path, script, opt):
225
240
kind = k
226
241
break
227
242
else :
228
- print ("warn: unsupported file type, skipped freeze: {}" .format (script ))
243
+ log ("warn: unsupported file type, skipped freeze: {}" .format (script ))
229
244
return
230
245
wanted_extension = extension_kind [kind ]
231
246
if not script .endswith (wanted_extension ):
@@ -325,23 +340,42 @@ def main():
325
340
VARS [name ] = value
326
341
327
342
if "MPY_DIR" not in VARS or "PORT_DIR" not in VARS :
328
- print ("MPY_DIR and PORT_DIR variables must be specified" )
343
+ log . error ("MPY_DIR and PORT_DIR variables must be specified" )
329
344
sys .exit (1 )
330
345
331
- # Get paths to tools
332
- MPY_CROSS = VARS ["MPY_DIR" ] + "/mpy-cross/mpy-cross"
333
- if sys .platform == "win32" :
334
- MPY_CROSS += ".exe"
335
- MPY_CROSS = os .getenv ("MICROPY_MPYCROSS" , MPY_CROSS )
336
- MPY_TOOL = VARS ["MPY_DIR" ] + "/tools/mpy-tool.py"
346
+ process (
347
+ args .files ,
348
+ args .build_dir ,
349
+ args .output ,
350
+ args .mpy_tool_flags ,
351
+ args .mpy_cross_flags ,
352
+ )
337
353
338
- # Ensure mpy-cross is built
354
+
355
+ def process (files , build_dir , output = None , mpy_tool_flags = "" , mpy_cross_flags = "" ):
356
+ # Get paths to tools
357
+ global MPY_CROSS , MPY_TOOL
358
+ if MPY_CROSS is None :
359
+ MPY_CROSS = VARS ["MPY_DIR" ] + "/mpy-cross/mpy-cross"
360
+ if sys .platform == "win32" :
361
+ MPY_CROSS += ".exe"
362
+ MPY_CROSS = os .getenv ("MICROPY_MPYCROSS" , MPY_CROSS )
363
+ if MPY_TOOL is None :
364
+ MPY_TOOL = VARS ["MPY_DIR" ] + "/tools/mpy-tool.py"
365
+
366
+ # Ensure mpy-cross is built / available
367
+ if not os .path .exists (MPY_CROSS ):
368
+ try :
369
+ from mpy_cross import mpy_cross
370
+ MPY_CROSS = mpy_cross
371
+ except ImportError :
372
+ pass
339
373
if not os .path .exists (MPY_CROSS ):
340
374
print ("mpy-cross not found at {}, please build it first" .format (MPY_CROSS ))
341
375
sys .exit (1 )
342
376
343
377
# Include top-level inputs, to generate the manifest
344
- for input_manifest in args . files :
378
+ for input_manifest in files :
345
379
try :
346
380
if input_manifest .endswith (".py" ):
347
381
include (input_manifest )
@@ -354,29 +388,32 @@ def main():
354
388
# Process the manifest
355
389
str_paths = []
356
390
mpy_files = []
391
+ new_files = []
357
392
ts_newest = 0
358
393
for kind , path , script , opt in manifest_list :
359
394
if kind == KIND_AS_STR :
360
395
str_paths .append (path )
361
396
ts_outfile = get_timestamp_newest (path )
362
397
elif kind == KIND_AS_MPY :
363
398
infile = "{}/{}" .format (path , script )
364
- outfile = "{}/frozen_mpy/{}.mpy" .format (args .build_dir , script [:- 3 ])
399
+ subdir = "frozen_mpy" if output else ""
400
+ outfile = "{}/{}/{}.mpy" .format (build_dir , subdir , script [:- 3 ])
365
401
ts_infile = get_timestamp (infile )
366
402
ts_outfile = get_timestamp (outfile , 0 )
367
403
if ts_infile >= ts_outfile :
368
- print ("MPY" , script )
404
+ log ("MPY" , script )
369
405
mkdir (outfile )
370
406
res , out = system (
371
407
[MPY_CROSS ]
372
- + args . mpy_cross_flags .split ()
408
+ + mpy_cross_flags .split ()
373
409
+ ["-o" , outfile , "-s" , script , "-O{}" .format (opt ), infile ]
374
410
)
375
411
if res != 0 :
376
412
print ("error compiling {}:" .format (infile ))
377
413
sys .stdout .buffer .write (out )
378
414
raise SystemExit (1 )
379
415
ts_outfile = get_timestamp (outfile )
416
+ new_files .append (outfile )
380
417
mpy_files .append (outfile )
381
418
else :
382
419
assert kind == KIND_MPY
@@ -385,50 +422,53 @@ def main():
385
422
ts_outfile = get_timestamp (infile )
386
423
ts_newest = max (ts_newest , ts_outfile )
387
424
388
- # Check if output file needs generating
389
- if ts_newest < get_timestamp (args .output , 0 ):
390
- # No files are newer than output file so it does not need updating
391
- return
392
-
393
- # Freeze paths as strings
394
- output_str = generate_frozen_str_content (str_paths )
395
-
396
- # Freeze .mpy files
397
- if mpy_files :
398
- res , output_mpy = system (
399
- [
400
- sys .executable ,
401
- MPY_TOOL ,
402
- "-f" ,
403
- "-q" ,
404
- args .build_dir + "/genhdr/qstrdefs.preprocessed.h" ,
405
- ]
406
- + args .mpy_tool_flags .split ()
407
- + mpy_files
408
- )
409
- if res != 0 :
410
- print ("error freezing mpy {}:" .format (mpy_files ))
411
- print (output_mpy .decode ())
412
- sys .exit (1 )
413
- else :
414
- output_mpy = (
415
- b'#include "py/emitglue.h"\n '
416
- b"extern const qstr_pool_t mp_qstr_const_pool;\n "
417
- b"const qstr_pool_t mp_qstr_frozen_const_pool = {\n "
418
- b" (qstr_pool_t*)&mp_qstr_const_pool, MP_QSTRnumber_of, 0, 0\n "
419
- b"};\n "
420
- b'const char mp_frozen_names[] = { MP_FROZEN_STR_NAMES "\\ 0"};\n '
421
- b"const mp_raw_code_t *const mp_frozen_mpy_content[] = {NULL};\n "
422
- )
423
-
424
- # Generate output
425
- print ("GEN" , args .output )
426
- mkdir (args .output )
427
- with open (args .output , "wb" ) as f :
428
- f .write (b"//\n // Content for MICROPY_MODULE_FROZEN_STR\n //\n " )
429
- f .write (output_str )
430
- f .write (b"//\n // Content for MICROPY_MODULE_FROZEN_MPY\n //\n " )
431
- f .write (output_mpy )
425
+ if output :
426
+ # Check if output file needs generating
427
+ if ts_newest < get_timestamp (output , 0 ):
428
+ # No files are newer than output file so it does not need updating
429
+ return
430
+
431
+ # Freeze paths as strings
432
+ output_str = generate_frozen_str_content (str_paths )
433
+
434
+ # Freeze .mpy files
435
+ if mpy_files :
436
+ res , output_mpy = system (
437
+ [
438
+ sys .executable ,
439
+ MPY_TOOL ,
440
+ "-f" ,
441
+ "-q" ,
442
+ build_dir + "/genhdr/qstrdefs.preprocessed.h" ,
443
+ ]
444
+ + mpy_tool_flags .split ()
445
+ + mpy_files
446
+ )
447
+ if res != 0 :
448
+ print ("error freezing mpy {}:" .format (mpy_files ))
449
+ print (output_mpy .decode ())
450
+ sys .exit (1 )
451
+ else :
452
+ output_mpy = (
453
+ b'#include "py/emitglue.h"\n '
454
+ b"extern const qstr_pool_t mp_qstr_const_pool;\n "
455
+ b"const qstr_pool_t mp_qstr_frozen_const_pool = {\n "
456
+ b" (qstr_pool_t*)&mp_qstr_const_pool, MP_QSTRnumber_of, 0, 0\n "
457
+ b"};\n "
458
+ b'const char mp_frozen_names[] = { MP_FROZEN_STR_NAMES "\\ 0"};\n '
459
+ b"const mp_raw_code_t *const mp_frozen_mpy_content[] = {NULL};\n "
460
+ )
461
+
462
+ # Generate output
463
+ log ("GEN {}" .format (output ))
464
+ mkdir (output )
465
+ with open (output , "wb" ) as f :
466
+ f .write (b"//\n // Content for MICROPY_MODULE_FROZEN_STR\n //\n " )
467
+ f .write (output_str )
468
+ f .write (b"//\n // Content for MICROPY_MODULE_FROZEN_MPY\n //\n " )
469
+ f .write (output_mpy )
470
+
471
+ return mpy_files , new_files
432
472
433
473
434
474
if __name__ == "__main__" :
0 commit comments