import os
import sys
import shutil
+from types import SimpleNamespace
+import onelib.backends as backends
import onelib.utils as oneutils
# TODO Find better way to suppress trackback on error
sys.tracebacklimit = 0
-def _get_backends_list():
- """
- [one hierarchy]
- one
- ├── backends
- ├── bin
- ├── doc
- ├── include
- ├── lib
- └── test
-
- The list where `one-codegen` finds its backends
- - `bin` folder where `one-codegen` exists
- - `backends` folder
- - System path
-
- NOTE If there are backends of the same name in different places,
- the closer to the top in the list, the higher the priority.
- """
- dir_path = os.path.dirname(os.path.realpath(__file__))
- backend_set = set()
-
- # bin folder
- files = [f for f in glob.glob(dir_path + '/*-compile')]
- # backends folder
- files += [
- f for f in glob.glob(dir_path + '/../backends/**/*-compile', recursive=True)
- ]
- # TODO find backends in `$PATH`
-
- backends_list = []
- for cand in files:
- base = ntpath.basename(cand)
- if not base in backend_set and os.path.isfile(cand) and os.access(cand, os.X_OK):
- backend_set.add(base)
- backends_list.append(cand)
-
- return backends_list
-
-
def _get_parser(backends_list):
codegen_usage = 'one-codegen [-h] [-v] [-C CONFIG] [-b BACKEND] [--] [COMMANDS FOR BACKEND]'
parser = argparse.ArgumentParser(
return parser
-def _verify_arg(parser, args):
+def _verify_arg(parser, args, cfg_args, backend_args, unknown_args):
"""verify given arguments"""
+ cmd_backend_exist = oneutils.is_valid_attr(args, 'backend')
+ cfg_backend_exist = oneutils.is_valid_attr(cfg_args, 'backend')
+ cfg_backends_exist = oneutils.is_valid_attr(cfg_args, 'backends')
+
# check if required arguments is given
missing = []
- if not oneutils.is_valid_attr(args, 'backend'):
+ if not cmd_backend_exist and not cfg_backend_exist and not cfg_backends_exist:
missing.append('-b/--backend')
if len(missing):
parser.error('the following arguments are required: ' + ' '.join(missing))
+ if not oneutils.is_valid_attr(args, 'config'):
+ if not backend_args and not unknown_args:
+ parser.error('commands for the backend is missing.')
+
+ if cfg_backend_exist and cfg_backends_exist:
+ parser.error(
+ '\'backend\' option and \'backends\' option cannot be used simultaneously.')
+
+ # Check if given backend from command line exists in the configuration file
+ if cmd_backend_exist and cfg_backend_exist:
+ if args.backend != cfg_args.backend:
+ parser.error('Not found the command of given backend')
+
+ if cfg_backend_exist and not oneutils.is_valid_attr(cfg_args, 'command'):
+ parser.error('\'command\' key is missing in the configuration file.')
+
+ if cfg_backends_exist:
+ cfg_backends = getattr(cfg_args, 'backends').split(',')
+ # check if commands of given backends exist
+ for b in cfg_backends:
+ if not oneutils.is_valid_attr(cfg_args, b):
+ parser.error('Not found the command for ' + b)
+
+ # Check if given backend from command line exists in the configuration file
+ if cmd_backend_exist:
+ if args.backend not in cfg_backends:
+ parser.error('Not found the command of given backend')
+
def _parse_arg(parser):
codegen_args = []
def main():
# get backend list
- backends_list = _get_backends_list()
+ backends_list = backends.get_list('compile')
# parse arguments
parser = _get_parser(backends_list)
args, backend_args, unknown_args = _parse_arg(parser)
# parse configuration file
- oneutils.parse_cfg(args.config, 'one-codegen', args)
+ cfg_args = SimpleNamespace()
+ oneutils.parse_cfg(args.config, 'one-codegen', cfg_args)
+
+ # parse configuration file (args has arguments parsed from command line + cfg)
+ # oneutils.parse_cfg(args.config, 'one-codegen', args)
# verify arguments
- _verify_arg(parser, args)
-
- # make a command to run given backend driver
- codegen_path = None
- backend_base = getattr(args, 'backend') + '-compile'
- for cand in backends_list:
- if ntpath.basename(cand) == backend_base:
- codegen_path = cand
- if not codegen_path:
- # Find backend from system path
- codegen_path = shutil.which(backend_base)
-
- if not codegen_path:
- raise FileNotFoundError(backend_base + ' not found')
- codegen_cmd = [codegen_path] + backend_args + unknown_args
- if oneutils.is_valid_attr(args, 'command'):
- codegen_cmd += getattr(args, 'command').split()
-
- # run backend driver
- oneutils.run(codegen_cmd, err_prefix=backend_base)
+ _verify_arg(parser, args, cfg_args, backend_args, unknown_args)
+ '''
+ one-codegen defines its behavior for below cases.
+
+ [1] one-codegen -h
+ [2] one-codegen -v
+ [3] one-codegen -C ${cfg} (backend, command key in cfg)
+ [4] one-codegen -C ${cfg} (backends key in cfg)
+ [5] one-codegen -b ${backend} ${command}
+ [6] one-codegen -b ${backend} -- ${command}
+ [7] one-codegen -b ${backend} -C {cfg} (backend, command key in cfg)
+ [8] one-codegen -b ${backend} -C {cfg} (backends key in cfg) (Only 'backend' is invoked,
+ even though cfg file has multiple backends)
+ [9] one-codegen -b ${backend} -C ${cfg} -- ${command} (backend, command key in cfg)
+ [10] one-codegen -b ${backend} -C ${cfg} -- ${command} (backends key in cfg) (Only 'backend' is invoked,
+ even though cfg file has multiple backends)
+
+ All other cases are not allowed or an undefined behavior.
+ '''
+ cmd_overwrite = False
+ if oneutils.is_valid_attr(args, 'config'):
+ # [9], [10]
+ if backend_args and not unknown_args:
+ given_backends = [args.backend]
+ cmd_overwrite = True
+ else:
+ # [7], [8]
+ if oneutils.is_valid_attr(args, 'backend'):
+ given_backends = [args.backend]
+ if oneutils.is_valid_attr(cfg_args, 'backend'):
+ assert (oneutils.is_valid_attr(cfg_args, 'command'))
+ setattr(cfg_args, args.backend, cfg_args.command)
+ else:
+ # [3]
+ if oneutils.is_valid_attr(cfg_args, 'backend'):
+ assert (oneutils.is_valid_attr(cfg_args, 'command'))
+ given_backends = [cfg_args.backend]
+ setattr(cfg_args, cfg_args.backend, cfg_args.command)
+ # [4]
+ if oneutils.is_valid_attr(cfg_args, 'backends'):
+ given_backends = cfg_args.backends.split(',')
+ # [5], [6]
+ else:
+ assert (backend_args or unknown_args)
+ given_backends = [args.backend]
+
+ for given_backend in given_backends:
+ # make a command to run given backend driver
+ codegen_path = None
+ backend_base = given_backend + '-compile'
+ for cand in backends_list:
+ if ntpath.basename(cand) == backend_base:
+ codegen_path = cand
+ if not codegen_path:
+ # Find backend from system path
+ codegen_path = shutil.which(backend_base)
+
+ if not codegen_path:
+ raise FileNotFoundError(backend_base + ' not found')
+
+ codegen_cmd = [codegen_path]
+ if not cmd_overwrite and oneutils.is_valid_attr(cfg_args, given_backend):
+ codegen_cmd += getattr(cfg_args, given_backend).split()
+ else:
+ codegen_cmd += backend_args
+ codegen_cmd += unknown_args
+
+ # run backend driver
+ oneutils.run(codegen_cmd, err_prefix=backend_base)
if __name__ == '__main__':