Skip to content
This repository was archived by the owner on Aug 5, 2022. It is now read-only.

Commit 490ff66

Browse files
JohnVillalovosgrgustaf
authored andcommitted
[analyze] Use argparse library command line arg parsing (#1823)
* Use the argparse library for the argument parsing. Some of the reasons this is an improvement are: * Improved experience for the user as help messages are provided. * It is easier to check argument values in the code this way. * Arguments become self documenting, previously the usage() function did not describe the "RESTRICT" and "V" options. By using argparse every argument that is accepted will be shown in --help. * Updated two callers of analyze (Makefile & cmake/zjs_linux.cmake) to use the new argument style. * Changed 'outdir' to no longer be a global variable. * Added a description of what the analyze program does to the help. Now if the user does: $ scripts/analyze --help They will see: usage: analyze [-h] --board BOARD_NAME --json-dir DIR [--prjconf FILE] [--cmakefile FILE] [--script FILE] [--force FILE,FILE,...] [--restrict FILE,FILE,...] [--profile FILE] [--js-out FILE] [--output-dir DIR] [--verbose {0,1}] Static analysis tool to detect modules being used in a script so the compiler can include or exclude certain modules if they are/are not used. This will output gcc pre-processor defines (-D____) so it can be used in-line -during the compile step. optional arguments: -h, --help show this help message and exit --board BOARD_NAME Board target being built. --json-dir DIR Directory to look for JSON files. --prjconf FILE File to write the prj.conf information to. --cmakefile FILE CMake file to write source/options to. --script FILE JavaScript script used to build. --force FILE,FILE,... Comma separated list of JSON files to force inclusion of. Files are located in the directory specified by --json-dir. --restrict FILE,FILE,... Comma separated list of JSON files. If specified only these JSON files will be used. Files are located in the directory specified by --json-dir. --profile FILE File to write the JerryScript profile to. --js-out FILE Output file to use if any JS modules are found in --script. --output-dir DIR Output directory. --verbose {0,1} Level of verbosity. Signed-off-by: John L. Villalovos <[email protected]> Signed-off-by: Geoff Gustafson <[email protected]>
1 parent 9f1fcc2 commit 490ff66

File tree

4 files changed

+122
-100
lines changed

4 files changed

+122
-100
lines changed

Makefile

Lines changed: 18 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -260,16 +260,16 @@ analyze: $(JS)
260260
@mkdir -p $(OUT)/$(BOARD)/
261261
@mkdir -p $(OUT)/include
262262

263-
./scripts/analyze V=$(V) \
264-
SCRIPT=$(JS) \
265-
JS_OUT=$(OUT)/$(JS_TMP) \
266-
BOARD=$(BOARD) \
267-
JSON_DIR=src/ \
268-
O=$(OUT) \
269-
FORCE=$(FORCED) \
270-
PRJCONF=prj.conf \
271-
CMAKEFILE=$(OUT)/$(BOARD)/generated.cmake \
272-
PROFILE=$(OUT)/$(BOARD)/jerry_feature.profile
263+
./scripts/analyze --verbose=$(V) \
264+
--script=$(JS) \
265+
--js-out=$(OUT)/$(JS_TMP) \
266+
--board=$(BOARD) \
267+
--json-dir=src/ \
268+
--output-dir=$(OUT) \
269+
--force=$(FORCED) \
270+
--prjconf=prj.conf \
271+
--cmakefile=$(OUT)/$(BOARD)/generated.cmake \
272+
--profile=$(OUT)/$(BOARD)/jerry_feature.profile
273273

274274
@if [ "$(TRACE)" = "on" ] || [ "$(TRACE)" = "full" ]; then \
275275
echo "add_definitions(-DZJS_TRACE_MALLOC)" >> $(OUT)/$(BOARD)/generated.cmake; \
@@ -419,14 +419,14 @@ ARC_RESTRICT="zjs_ipm_arc.json,\
419419
arc: analyze
420420
@# Restrict ARC build to only certain "arc specific" modules
421421
@mkdir -p $(OUT)/arduino_101_sss
422-
./scripts/analyze V=$(V) \
423-
SCRIPT=$(OUT)/$(JS_TMP) \
424-
BOARD=arc \
425-
JSON_DIR=arc/src/ \
426-
PRJCONF=arc/prj.conf \
427-
CMAKEFILE=$(OUT)/arduino_101_sss/generated.cmake \
428-
O=$(OUT)/arduino_101_sss \
429-
FORCE=$(ASHELL_ARC)
422+
./scripts/analyze --verbose=$(V) \
423+
--script=$(OUT)/$(JS_TMP) \
424+
--board=arc \
425+
--json-dir=arc/src/ \
426+
--prjconf=arc/prj.conf \
427+
--cmakefile=$(OUT)/arduino_101_sss/generated.cmake \
428+
--output-dir=$(OUT)/arduino_101_sss \
429+
--force=$(ASHELL_ARC)
430430

431431
@echo "&flash0 { reg = <0x400$(FLASH_BASE_ADDR) ($(ARC_ROM) * 1024)>; };" > arc/arduino_101_sss.overlay
432432
@echo "&sram0 { reg = <0xa8000400 ($(ARC_RAM) * 1024)>; };" >> arc/arduino_101_sss.overlay

cmake/zjs_linux.cmake

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,11 @@ add_custom_command(
150150
${JERRY_LIBDIR}/lib/libjerry-core.a
151151
${JERRY_LIBDIR}/lib/libjerry-ext.a
152152
COMMAND ${CMAKE_SOURCE_DIR}/scripts/analyze
153-
BOARD=linux
154-
O=${CMAKE_BINARY_DIR}/..
155-
RESTRICT=${LINUX_MODULES}
156-
V=${V}
157-
JSON_DIR=${CMAKE_SOURCE_DIR}/src/
153+
--board=linux
154+
--output-dir=${CMAKE_BINARY_DIR}/..
155+
--restrict=${LINUX_MODULES}
156+
--verbose=${V}
157+
--json-dir=${CMAKE_SOURCE_DIR}/src/
158158
COMMAND ${PYTHON_EXECUTABLE}
159159
${CMAKE_SOURCE_DIR}/deps/jerryscript/tools/build.py
160160
--builddir=${JERRY_LIBDIR}

scripts/README

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
scripts - directory for utility scripts to help with ZJS development
33
=========
44

5-
analyze.sh
6-
----------
5+
analyze
6+
-------
77
Checks a .js file to determine what ZJS modules it is using so they can be
88
auto-included in the build.
99

scripts/analyze

Lines changed: 97 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
#!/usr/bin/env python3
22

3+
# Static analysis tool to detect modules being used in a script so the compiler
4+
# can include or exclude certain modules based on whether they are used. This
5+
# will output gcc pre-processor defines (-D____) so it can be used in-line
6+
# during the compile step.
7+
8+
import argparse
39
import json
410
import os
511
import pprint
@@ -8,75 +14,43 @@ import shutil
814
import sys
915

1016
# Globals
11-
args = {}
17+
args = None
1218
board = None
13-
outdir = ""
14-
15-
16-
def usage():
17-
print("Usage: ./analyze <options>")
18-
print(" Required:")
19-
print(" BOARD= Target being built")
20-
print(" JSON_DIR= Directory to look for JSON files")
21-
print(" PRJCONF= File to write the prj.conf info to")
22-
print(" CMAKEFILE= CMake file to write source/options to")
23-
print(" Optional:")
24-
print(" SCRIPT= JS script used to build")
25-
print(" FORCE= Force inclusion of certain JSON files")
26-
print(" PROFILE= Where to write the JerryScript profile")
27-
print(" JS_OUT= Output file if any JS modules are found in SCRIPT")
28-
print(" O= Output directory")
29-
sys.exit()
3019

3120

3221
def main():
33-
global args, board, outdir
34-
for i in sys.argv[1:]:
35-
option, value = i.split('=')[:2]
36-
args[option] = value
22+
global args, board
23+
args = parse_args()
24+
board = args.board
25+
3726
json_tree = {}
3827
deps_list = []
3928
zconf = []
4029
zjs_conf = []
4130
jrs_conf = []
4231
lsrc = []
4332
js_modules = []
44-
board = args['BOARD']
45-
if board == 'linux':
46-
req_options = ['BOARD', 'JSON_DIR']
47-
else:
48-
req_options = ['BOARD', 'JSON_DIR', 'PRJCONF', 'CMAKEFILE']
49-
for i in req_options:
50-
if i not in args:
51-
print("%s must be specified" % i)
52-
usage()
53-
if 'SCRIPT' not in args:
33+
34+
if not args.script:
5435
print("Generating modules header")
5536
else:
56-
script = args['SCRIPT']
57-
print("Analyzing %s for %s" % (script, board))
58-
if 'O' not in args:
59-
outdir = 'outdir'
60-
else:
61-
outdir = args['O']
37+
print("Analyzing %s for %s" % (args.script, board))
6238

6339
# Linux is special cased because it does not use a JS script to build
6440
if board == 'linux':
65-
restrict = args['RESTRICT'].split(',')
66-
restrict = [i.strip() for i in restrict]
67-
build_tree(json_tree, restrict)
41+
build_tree(json_tree, args.restrict)
6842
do_print(json_tree)
6943
all_list = []
7044
create_dep_list(all_list, board, json_tree)
7145
for i in sorted(all_list):
7246
print("Using module: " + i)
73-
write_modules(all_list, json_tree)
47+
write_modules(all_list, json_tree, args.output_dir)
7448
# normal case
7549
else:
76-
if 'JS_OUT' in args:
77-
with open(script, 'r') as s:
50+
if args.js_out:
51+
with open(args.script, 'r') as s:
7852
js = s.read()
79-
with open(args['JS_OUT'], 'w') as f:
53+
with open(args.js_out, 'w') as f:
8054
for i in os.listdir("modules/"):
8155
if match_require(js, i):
8256
js_modules += [i]
@@ -85,44 +59,35 @@ def main():
8559
f.write(mod.read())
8660
f.write("\n")
8761
f.write(js)
88-
js_file = args['JS_OUT']
62+
js_file = args.js_out
8963
else:
90-
js_file = script
64+
js_file = args.script
9165

92-
restrict = args.get('RESTRICT', '')
93-
if restrict != '':
94-
restrict = restrict.split(',')
95-
restrict = [i.strip() for i in restrict]
96-
do_print("Only using modules: " + str(restrict))
97-
else:
98-
restrict = []
66+
if args.restrict:
67+
do_print("Only using modules: " + str(args.restrict))
9968

100-
force = args.get('FORCE', '')
101-
if force != '':
102-
force = force.split(',')
103-
do_print("Forcing inclusion of: " + str(force))
104-
else:
105-
force = []
69+
if args.force:
70+
do_print("Forcing inclusion of: " + str(args.force))
10671

107-
build_tree(json_tree, restrict)
72+
build_tree(json_tree, args.restrict)
10873
do_print(json_tree)
10974
parse_json_tree(js_file, deps_list, zconf, zjs_conf, jrs_conf, lsrc,
110-
json_tree, force=force)
75+
json_tree, force=args.force)
11176
for i in sorted(deps_list):
11277
print("Using module: " + i)
11378

114-
write_zconf(zconf, args['PRJCONF'])
115-
write_cmakefile(lsrc, zjs_conf, args['CMAKEFILE'])
79+
write_zconf(zconf, args.prjconf)
80+
write_cmakefile(lsrc, zjs_conf, args.cmakefile)
11681
write_jrsconfig(jrs_conf)
11782

11883
# building for arc does not need zjs_modules_gen.h to be created
11984
if board != 'arc':
120-
write_modules(deps_list, json_tree)
85+
write_modules(deps_list, json_tree, args.output_dir)
12186

12287

12388
def do_print(s):
12489
"""Debug print controlled with V option"""
125-
if 'V' in args and args['V'] == '1':
90+
if args.verbose == '1':
12691
p = pprint.PrettyPrinter(indent=1)
12792
p.pprint(s)
12893

@@ -143,7 +108,7 @@ def parse_list(tree, list):
143108
for file in list:
144109
if file.endswith(".json"):
145110
do_print("opening " + file)
146-
with open(args['JSON_DIR'] + file) as f:
111+
with open(os.path.join(args.json_dir, file)) as f:
147112
try:
148113
data = json.load(f)
149114
except:
@@ -165,10 +130,10 @@ def parse_list(tree, list):
165130

166131
def build_tree(tree, restrict):
167132
"""Wrapper for parse_list() if a restricted list of JSON files is used"""
168-
if restrict != []:
133+
if restrict is not None:
169134
parse_list(tree, restrict)
170135
else:
171-
parse_list(tree, os.listdir(args['JSON_DIR']))
136+
parse_list(tree, os.listdir(args.json_dir))
172137

173138

174139
def create_dep_list_helper(dlist, dep, board, tree):
@@ -306,7 +271,7 @@ def parse_json_tree(file, dlist, zlist, zjslist, jrslist, srclist, tree,
306271

307272
if force is not None:
308273
for f in force:
309-
with open(args['JSON_DIR'] + f) as file:
274+
with open(os.path.join(args.json_dir, f)) as file:
310275
data = json.load(file)
311276
parse_json_tree_helper(text, data['module'], dlist, zlist,
312277
zjslist, jrslist, srclist, tree)
@@ -363,12 +328,12 @@ def parse_json_tree(file, dlist, zlist, zjslist, jrslist, srclist, tree,
363328

364329
def write_jrsconfig(list):
365330
"""Write a JerryScript profile file"""
366-
if 'PROFILE' in args:
367-
if os.path.exists(args['PROFILE']):
368-
shutil.copyfile(args['PROFILE'], args['PROFILE'] + '.bak')
331+
if args.profile:
332+
if os.path.exists(args.profile):
333+
shutil.copyfile(args.profile, args.profile + '.bak')
369334
with open("fragments/jerry_feature.base", "r") as jrs:
370335
feature = jrs.read()
371-
with open(args['PROFILE'], "w") as p:
336+
with open(args.profile, "w") as p:
372337
for i in list:
373338
feature = feature.replace(i, "#" + i)
374339
p.write(feature)
@@ -413,7 +378,7 @@ def write_zconf(list, file):
413378
f.write(expanded + '\n')
414379

415380

416-
def write_modules(list, tree):
381+
def write_modules(list, tree, outdir):
417382
"""Write zjs_modules_gen.h file"""
418383
headers = []
419384
gbl_inits = {}
@@ -451,5 +416,62 @@ typedef struct gbl_module {
451416
file.write("};\n")
452417

453418

419+
def parse_args():
420+
parser = argparse.ArgumentParser(
421+
description=(
422+
"Static analysis tool to detect modules being used in a script so "
423+
"the compiler can include or exclude certain modules if they "
424+
"are/are not used. This will output gcc pre-processor defines "
425+
"(-D____) so it can be used in-line -during the compile step."),
426+
)
427+
parser.add_argument("--board", required=True, metavar="BOARD_NAME",
428+
help="Board target being built.")
429+
parser.add_argument("--json-dir", required=True, metavar="DIR",
430+
help="Directory to look for JSON files.")
431+
parser.add_argument("--prjconf", metavar="FILE",
432+
help="File to write the prj.conf information to.")
433+
parser.add_argument("--cmakefile", metavar="FILE",
434+
help="CMake file to write source/options to.")
435+
436+
parser.add_argument("--script", metavar="FILE",
437+
help="JavaScript script used to build.")
438+
parser.add_argument("--force", metavar="FILE,FILE,...",
439+
help=("Comma separated list of JSON files to force "
440+
"inclusion of. Files are located in the "
441+
"directory specified by --json-dir."))
442+
parser.add_argument("--restrict", metavar="FILE,FILE,...",
443+
help=("Comma separated list of JSON files. If "
444+
"specified only these JSON files will be used. "
445+
"Files are located in the directory specified "
446+
"by --json-dir."))
447+
parser.add_argument("--profile", metavar="FILE",
448+
help="File to write the JerryScript profile to.")
449+
parser.add_argument("--js-out", metavar="FILE",
450+
help=("Output file to use if any JS modules are found "
451+
"in --script."))
452+
parser.add_argument("--output-dir", metavar="DIR", default="outdir",
453+
help="Output directory.")
454+
parser.add_argument("--verbose", type=int, choices=[0, 1], default=0,
455+
help="Level of verbosity.")
456+
457+
args = parser.parse_args()
458+
459+
if args.board != 'linux':
460+
if not args.prjconf or not args.cmakefile:
461+
parser.error("Arguments --prjconf and --cmakefile are required "
462+
"unless --board is 'linux'")
463+
else:
464+
if not args.restrict:
465+
parser.error("Argument --restrict is required when --board is "
466+
"'linux'")
467+
# Change arguments which take comma separated value strings and convert
468+
# them into lists of the values.
469+
for arg_name in ('force', 'restrict'):
470+
if getattr(args, arg_name):
471+
setattr(args, arg_name,
472+
[x.strip() for x in getattr(args, arg_name).split(',')])
473+
return args
474+
475+
454476
if '__main__' == __name__:
455477
sys.exit(main())

0 commit comments

Comments
 (0)