summaryrefslogtreecommitdiffstatshomepage
path: root/scripts/build/makedep.py
diff options
context:
space:
mode:
Diffstat (limited to 'scripts/build/makedep.py')
-rwxr-xr-xscripts/build/makedep.py514
1 files changed, 292 insertions, 222 deletions
diff --git a/scripts/build/makedep.py b/scripts/build/makedep.py
index d9f92b08ac6..33e61ccc171 100755
--- a/scripts/build/makedep.py
+++ b/scripts/build/makedep.py
@@ -392,10 +392,136 @@ class DriverFilter:
[chr(x) for x in range(ord('a'), ord('z') + 1)] +
['_'])
+ def parse_filter(self, path, sourcefile, inclusion, exclusion):
+ def line_hook(text):
+ text = text.strip()
+ if text.startswith('#'):
+ do_parse(os.path.join(os.path.dirname(n), text[1:].lstrip()))
+ elif text.startswith('+'):
+ text = text[1:].lstrip()
+ if not text:
+ sys.stderr.write('%s:%s: Empty driver name\n' % (path, parser.input_line))
+ sys.exit(1)
+ elif not all(x in self.DRIVER_CHARS for x in text):
+ sys.stderr.write('%s:%s: Invalid character in driver name "%s"\n' % (path, parser.input_line, text))
+ sys.exit(1)
+ inclusion(text)
+ elif text.startswith('-'):
+ text = text[1:].lstrip()
+ if not text:
+ sys.stderr.write('%s:%s: Empty driver name\n' % (path, parser.input_line))
+ sys.exit(1)
+ elif not all(x in self.DRIVER_CHARS for x in text):
+ sys.stderr.write('%s:%s: Invalid character in driver name "%s"\n' % (path, parser.input_line, text))
+ sys.exit(1)
+ exclusion(text)
+ elif text:
+ sourcefile(text)
+
+ try:
+ filterfile = io.open(path, 'r', encoding='utf-8')
+ except IOError:
+ sys.stderr.write('Unable to open filter file "%s"\n' % (path, ))
+ sys.exit(1)
+ with filterfile:
+ handler = CppParser.Handler()
+ handler.line = line_hook
+ parser = CppParser(handler)
+ try:
+ parser.parse(filterfile)
+ except IOError:
+ sys.stderr.write('Error reading filter file "%s"\n' % (path, ))
+ sys.exit(1)
+ except Exception as e:
+ sys.stderr.write('Error parsing filter file "%s": %s\n' % (path, e))
+ sys.exit(1)
+
+ def parse_list(self, path, sourcefile, driver):
+ def line_hook(text):
+ text = text.strip()
+ if text.startswith('#'):
+ do_parse(os.path.join(os.path.dirname(n), text[1:].lstrip()))
+ elif text.startswith('@'):
+ parts = text[1:].lstrip().split(':', 1)
+ parts[0] = parts[0].strip()
+ if (parts[0] == 'source') and (len(parts) == 2):
+ parts[1] = parts[1].strip()
+ if not parts[1]:
+ sys.stderr.write('%s:%s: Empty source file name "%s"\n' % (path, parser.input_line, text))
+ sys.exit(1)
+ else:
+ sourcefile(parts[1])
+ else:
+ sys.stderr.write('%s:%s: Unsupported directive "%s"\n' % (path, parser.input_line, text))
+ sys.exit(1)
+ elif text:
+ if not all(x in self.DRIVER_CHARS for x in text):
+ sys.stderr.write('%s:%s: Invalid character in driver name "%s"\n' % (path, parser.input_line, text))
+ sys.exit(1)
+ else:
+ driver(text)
+
+ try:
+ listfile = io.open(path, 'r', encoding='utf-8')
+ except IOError:
+ sys.stderr.write('Unable to open list file "%s"\n' % (path, ))
+ sys.exit(1)
+ with listfile:
+ handler = CppParser.Handler()
+ handler.line = line_hook
+ parser = CppParser(handler)
+ try:
+ parser.parse(listfile)
+ except IOError:
+ sys.stderr.write('Error reading list file "%s"\n' % (path, ))
+ sys.exit(1)
+ except Exception as e:
+ sys.stderr.write('Error parsing list file "%s": %s\n' % (path, e))
+ sys.exit(1)
+
+
+class DriverLister(DriverFilter):
def __init__(self, options, **kwargs):
super().__init__(**kwargs)
- self.parse_filter(options.filter)
- self.parse_list(options.list)
+
+ def includesource(filename):
+ sources.add(filename)
+
+ def includedriver(shortname):
+ includes.add(shortname)
+ excludes.discard(shortname)
+
+ def excludedriver(shortname):
+ includes.discard(shortname)
+ excludes.add(shortname)
+
+ def sourcefile(filename):
+ if self.sources:
+ state['includesrc'] = filename in self.sources
+
+ def driver(shortname):
+ if state['includesrc'] and (shortname not in self.excludes):
+ drivers.add(shortname)
+
+ sources = set()
+ includes = set()
+ excludes = set()
+ if options.filter is not None:
+ self.parse_filter(options.filter, includesource, includedriver, excludedriver)
+ sys.stderr.write('%d source file(s) found\n' % (len(sources), ))
+ self.sources = frozenset(sources)
+ self.includes = frozenset(includes)
+ self.excludes = frozenset(excludes)
+
+ drivers = set()
+ state = { 'includesrc': True }
+ self.parse_list(options.list, sourcefile, driver)
+
+ for driver in self.includes:
+ drivers.add(driver)
+ sys.stderr.write('%d driver(s) found\n' % (len(drivers), ))
+ drivers.add('___empty')
+ self.drivers = sorted(drivers)
def write_source(self, f):
f.write(
@@ -416,124 +542,34 @@ class DriverFilter:
'\n' \
'std::size_t const driver_list::s_driver_count = %d;\n' % (len(self.drivers), ))
- def parse_filter(self, path):
- def do_parse(p):
- def line_hook(text):
- text = text.strip()
- if text.startswith('#'):
- do_parse(os.path.join(os.path.dirname(n), text[1:].lstrip()))
- elif text.startswith('+'):
- text = text[1:].lstrip()
- if not text:
- sys.stderr.write('%s:%s: Empty driver name\n' % (p, parser.input_line))
- sys.exit(1)
- elif not all(x in self.DRIVER_CHARS for x in text):
- sys.stderr.write('%s:%s: Invalid character in driver name "%s"\n' % (p, parser.input_line, text))
- sys.exit(1)
- includes.add(text)
- excludes.discard(text)
- elif text.startswith('-'):
- text = text[1:].lstrip()
- if not text:
- sys.stderr.write('%s:%s: Empty driver name\n' % (p, parser.input_line))
- sys.exit(1)
- elif not all(x in self.DRIVER_CHARS for x in text):
- sys.stderr.write('%s:%s: Invalid character in driver name "%s"\n' % (p, parser.input_line, text))
- sys.exit(1)
- includes.discard(text)
- excludes.add(text)
- elif text:
- sources.add(text)
-
- n = os.path.normpath(p)
- if n not in filters:
- filters.add(n)
- try:
- filterfile = io.open(n, 'r', encoding='utf-8')
- except IOError:
- sys.stderr.write('Unable to open filter file "%s"\n' % (p, ))
- sys.exit(1)
- with filterfile:
- handler = CppParser.Handler()
- handler.line = line_hook
- parser = CppParser(handler)
- try:
- parser.parse(filterfile)
- except IOError:
- sys.stderr.write('Error reading filter file "%s"\n' % (p, ))
- sys.exit(1)
- except Exception as e:
- sys.stderr.write('Error parsing filter file "%s": %s\n' % (p, e))
- sys.exit(1)
- sources = set()
- includes = set()
- excludes = set()
- filters = set()
- if path is not None:
- do_parse(path)
- sys.stderr.write('%d source file(s) found\n' % (len(sources), ))
- self.sources = frozenset(sources)
- self.includes = frozenset(includes)
- self.excludes = frozenset(excludes)
+class DriverCollector(DriverFilter):
+ def __init__(self, options, **kwargs):
+ super().__init__(**kwargs)
- def parse_list(self, path):
- def do_parse(p):
- def line_hook(text):
- text = text.strip()
- if text.startswith('#'):
- do_parse(os.path.join(os.path.dirname(n), text[1:].lstrip()))
- elif text.startswith('@'):
- parts = text[1:].lstrip().split(':', 1)
- parts[0] = parts[0].strip()
- if (parts[0] == 'source') and (len(parts) == 2):
- parts[1] = parts[1].strip()
- if not parts[1]:
- sys.stderr.write('%s:%s: Empty source file name "%s"\n' % (p, parser.input_line, text))
- sys.exit(1)
- elif self.sources:
- state['includesrc'] = parts[1] in self.sources
- else:
- sys.stderr.write('%s:%s: Unsupported directive "%s"\n' % (p, parser.input_line, text))
- sys.exit(1)
- elif text:
- if not all(x in self.DRIVER_CHARS for x in text):
- sys.stderr.write('%s:%s: Invalid character in driver name "%s"\n' % (p, parser.input_line, text))
- sys.exit(1)
- elif state['includesrc'] and (text not in self.excludes):
- drivers.add(text)
-
- n = os.path.normpath(p)
- if n not in lists:
- lists.add(n)
- try:
- listfile = io.open(n, 'r', encoding='utf-8')
- except IOError:
- sys.stderr.write('Unable to open list file "%s"\n' % (p, ))
- sys.exit(1)
- with listfile:
- handler = CppParser.Handler()
- handler.line = line_hook
- parser = CppParser(handler)
- try:
- parser.parse(listfile)
- except IOError:
- sys.stderr.write('Error reading list file "%s"\n' % (p, ))
- sys.exit(1)
- except Exception as e:
- sys.stderr.write('Error parsing list file "%s": %s\n' % (p, e))
- sys.exit(1)
+ def includesource(filename):
+ sources.add(filename)
- lists = set()
- drivers = set()
- state = object()
- state = { 'includesrc': True }
- do_parse(path)
- for driver in self.includes:
- drivers.add(driver)
- sys.stderr.write('%d driver(s) found\n' % (len(drivers), ))
- drivers.add('___empty')
- self.drivers = sorted(drivers)
+ def includedriver(shortname):
+ includes.add(shortname)
+
+ def excludedriver(shortname):
+ includes.discard(shortname)
+
+ def sourcefile(filename):
+ state['prevsource'] = filename
+
+ def driver(shortname):
+ if shortname in includes:
+ sources.add(state['prevsource'])
+
+ sources = set()
+ includes = set()
+ state = { 'prevsource': None }
+ self.parse_filter(options.filter, includesource, includedriver, excludedriver)
+ self.parse_list(options.list, sourcefile, driver)
+ sys.stderr.write('%d source file(s) found\n' % (len(sources), ))
+ self.sources = sorted(sources)
def split_path(path):
@@ -561,6 +597,12 @@ def parse_command_line():
subparser.add_argument('-t', '--target', metavar='<target>', required=True, help='generated emulator target name')
subparser.add_argument('sources', metavar='<srcfile>', nargs='+', help='source files to include')
+ subparser = subparsers.add_parser('filterproject', help='generate project directives using filter file')
+ subparser.add_argument('-r', '--root', metavar='<srcroot>', default='.', help='path to emulator source root (defaults to working directory)')
+ subparser.add_argument('-t', '--target', metavar='<target>', required=True, help='generated emulator target name')
+ subparser.add_argument('-f', '--filter', metavar='<fltfile>', required=True, help='input filter file')
+ subparser.add_argument('list', metavar='<lstfile>', help='input list file')
+
subparser = subparsers.add_parser('sourcesfilter', help='generate driver filter for source files')
subparser.add_argument('-l', '--list', metavar='<lstfile>', required=True, help='master driver list file')
subparser.add_argument('sources', metavar='<srcfile>', nargs='+', help='source files to include')
@@ -604,7 +646,7 @@ def collect_lua_directives(options):
return result
-def scan_source_dependencies(options):
+def scan_source_dependencies(root, sources):
def locate_include(path):
split = [ ]
forward = 0
@@ -631,13 +673,13 @@ def scan_source_dependencies(options):
else:
components = incdir[:-depth] + split[depth:]
depth = forward - 1
- if os.path.isfile(os.path.join(options.root, *components)):
+ if os.path.isfile(os.path.join(root, *components)):
return components, depth
return None, 0
def test_siblings(relative, basename, depth):
pathbase = '/'.join(relative) + '/'
- dirname = os.path.join(options.root, *relative)
+ dirname = os.path.join(root, *relative)
for ext in ('.cpp', '.ipp', '.hxx'):
path = pathbase + basename + ext
if (path not in seen) and os.path.isfile(os.path.join(dirname, basename + ext)):
@@ -664,25 +706,21 @@ def scan_source_dependencies(options):
components = components[:-1]
test_siblings(components, base, depth)
if components[:2] == ('src', 'mame'):
- if components[2:] == ('includes', ):
- for aspect in ('audio', 'drivers', 'video', 'machine'):
- test_siblings(('src', 'mame', aspect), base, depth)
- else:
- for aspect in ('_a', '_v', '_m'):
- test_siblings(components, base + aspect, depth)
+ for aspect in ('_a', '_v', '_m'):
+ test_siblings(components, base + aspect, depth)
handler = CppParser.Handler()
handler.line = line_hook
parser = CppParser(handler)
- seen = set('/'.join(x for x in split_path(source) if x) for source in options.sources)
+ seen = set('/'.join(x for x in split_path(source) if x) for source in sources)
remaining = list([(x, 0) for x in seen])
- default_roots = ((('src', 'devices'), 0), (('src', 'mame'), 0), (('src', 'lib'), 0))
+ default_roots = ((('src', 'devices'), 0), (('src', 'mame', 'shared'), 0), (('src', 'mame', 'messshared'), 0), (('src', 'lib'), 0))
while remaining:
source, depth = remaining.pop()
components = tuple(source.split('/'))
roots = ((components[:-1], depth), ) + default_roots
try:
- f = io.open(os.path.join(options.root, *components), 'r', encoding='utf-8')
+ f = io.open(os.path.join(root, *components), 'r', encoding='utf-8')
except IOError:
sys.stderr.write('Unable to open source file "%s"\n' % (source, ))
sys.exit(1)
@@ -698,97 +736,126 @@ def scan_source_dependencies(options):
return seen
-def write_project(options, projectfile, mappings, sources):
- targetsrc = ''
- for source in sorted(sources):
- action = mappings.get(source)
- if action:
- for line in action:
- projectfile.write(line + '\n')
- if source.startswith('src/mame/'):
- targetsrc += ' MAME_DIR .. "%s",\n' % (source, )
- projectfile.write(
- '\n' \
- 'function createProjects_mame_%s(_target, _subtarget)\n' \
- ' project ("mame_%s")\n' \
- ' targetsubdir(_target .."_" .. _subtarget)\n' \
- ' kind (LIBTYPE)\n' \
- ' uuid (os.uuid("drv-mame-%s"))\n' \
- ' addprojectflags()\n' \
- ' \n' \
- ' includedirs {\n' \
- ' MAME_DIR .. "src/osd",\n' \
- ' MAME_DIR .. "src/emu",\n' \
- ' MAME_DIR .. "src/devices",\n' \
- ' MAME_DIR .. "src/mame",\n' \
- ' MAME_DIR .. "src/lib",\n' \
- ' MAME_DIR .. "src/lib/util",\n' \
- ' MAME_DIR .. "src/lib/netlist",\n' \
- ' MAME_DIR .. "3rdparty",\n' \
- ' GEN_DIR .. "mame/layout",\n' \
- ' ext_includedir("asio"),\n' \
- ' ext_includedir("flac"),\n' \
- ' ext_includedir("glm"),\n' \
- ' ext_includedir("jpeg"),\n' \
- ' ext_includedir("rapidjson"),\n' \
- ' ext_includedir("zlib"),\n' \
- ' }\n' \
- '\n' \
- ' files{\n%s' \
- ' }\n' \
- 'end\n' \
- '\n' \
- 'function linkProjects_mame_%s(_target, _subtarget)\n' \
- ' links {\n' \
- ' "mame_%s",\n' \
- ' }\n' \
- 'end\n' % (options.target, options.target, options.target, targetsrc, options.target, options.target))
-
-
-def write_filter(options, filterfile):
- def do_parse(p):
- def line_hook(text):
- text = text.strip()
- if text.startswith('#'):
- do_parse(os.path.join(os.path.dirname(n), text[1:].lstrip()))
- elif text.startswith('@'):
- parts = text[1:].lstrip().split(':', 1)
- parts[0] = parts[0].strip()
- if (parts[0] == 'source') and (len(parts) == 2):
- parts[1] = parts[1].strip()
- if not parts[1]:
- sys.stderr.write('%s:%s: Empty source file name "%s"\n' % (p, parser.input_line, text))
- sys.exit(1)
- else:
- sources.add(parts[1])
+def write_project(options, projectfile, mappings, sources, single):
+ if single:
+ targetsrc = ''
+ for source in sorted(sources):
+ action = mappings.get(source)
+ if action:
+ for line in action:
+ projectfile.write(line + '\n')
+ if source.startswith('src/mame/'):
+ targetsrc += ' MAME_DIR .. "%s",\n' % (source, )
+ projectfile.write(
+ '\n' \
+ 'function createProjects_mame_%s(_target, _subtarget)\n' \
+ ' project ("mame_%s")\n' \
+ ' targetsubdir(_target .."_" .. _subtarget)\n' \
+ ' kind (LIBTYPE)\n' \
+ ' uuid (os.uuid("drv-mame-%s"))\n' \
+ ' addprojectflags()\n' \
+ ' \n' \
+ ' includedirs {\n' \
+ ' MAME_DIR .. "src/osd",\n' \
+ ' MAME_DIR .. "src/emu",\n' \
+ ' MAME_DIR .. "src/devices",\n' \
+ ' MAME_DIR .. "src/mame/shared",\n' \
+ ' MAME_DIR .. "src/mame/messshared",\n' \
+ ' MAME_DIR .. "src/lib",\n' \
+ ' MAME_DIR .. "src/lib/util",\n' \
+ ' MAME_DIR .. "src/lib/netlist",\n' \
+ ' MAME_DIR .. "3rdparty",\n' \
+ ' GEN_DIR .. "mame/layout",\n' \
+ ' ext_includedir("asio"),\n' \
+ ' ext_includedir("flac"),\n' \
+ ' ext_includedir("glm"),\n' \
+ ' ext_includedir("jpeg"),\n' \
+ ' ext_includedir("rapidjson"),\n' \
+ ' ext_includedir("zlib"),\n' \
+ ' }\n' \
+ '\n' \
+ ' files{\n%s' \
+ ' }\n' \
+ 'end\n' \
+ '\n' \
+ 'function linkProjects_mame_%s(_target, _subtarget)\n' \
+ ' links {\n' \
+ ' "mame_%s",\n' \
+ ' }\n' \
+ 'end\n' % (options.target, options.target, options.target, targetsrc, options.target, options.target))
+ else:
+ libraries = { }
+ for source in sorted(sources):
+ components = source.split('/')
+ if (len(components) > 3) and (components[:2] == ['src', 'mame']):
+ line = ' MAME_DIR .. "%s",\n' % (source, )
+ liblines = libraries.get(components[2])
+ if liblines is not None:
+ liblines.append(line)
else:
- sys.stderr.write('%s:%s: Unsupported directive "%s"\n' % (p, parser.input_line, text))
- sys.exit(1)
+ libraries[components[2]] = [line]
+ action = mappings.get(source)
+ if action:
+ for line in action:
+ projectfile.write(line + '\n')
+ libnames = sorted(libraries.keys())
+ projectfile.write(
+ '\n' \
+ 'function createMAMEProjects(_target, _subtarget, _name)\n' \
+ ' project (_name)\n' \
+ ' targetsubdir(_target .."_" .. _subtarget)\n' \
+ ' kind (LIBTYPE)\n' \
+ ' uuid (os.uuid("drv-" .. _target .. "_" .. _subtarget .. "-" .. _name))\n' \
+ ' addprojectflags()\n' \
+ ' \n' \
+ ' includedirs {\n' \
+ ' MAME_DIR .. "src/osd",\n' \
+ ' MAME_DIR .. "src/emu",\n' \
+ ' MAME_DIR .. "src/devices",\n' \
+ ' MAME_DIR .. "src/mame/shared",\n' \
+ ' MAME_DIR .. "src/mame/messshared",\n' \
+ ' MAME_DIR .. "src/lib",\n' \
+ ' MAME_DIR .. "src/lib/util",\n' \
+ ' MAME_DIR .. "src/lib/netlist",\n' \
+ ' MAME_DIR .. "3rdparty",\n' \
+ ' GEN_DIR .. "mame/layout",\n' \
+ ' ext_includedir("asio"),\n' \
+ ' ext_includedir("flac"),\n' \
+ ' ext_includedir("glm"),\n' \
+ ' ext_includedir("jpeg"),\n' \
+ ' ext_includedir("rapidjson"),\n' \
+ ' ext_includedir("zlib"),\n' \
+ ' }\n' \
+ 'end\n' \
+ '\n' \
+ 'function linkProjects_mame_%s(_target, _subtarget)\n' \
+ ' links {\n' % (options.target, ))
+ for lib in libnames:
+ if (lib != 'shared') and (lib != 'messshared'):
+ projectfile.write(' "%s",\n' % (lib, ))
+ if 'shared' in libraries:
+ projectfile.write(' "shared",\n')
+ if 'messshared' in libraries:
+ projectfile.write(' "messshared",\n')
+ projectfile.write(
+ ' }\n' \
+ 'end\n' \
+ '\n' \
+ 'function createProjects_mame_%s(_target, _subtarget)\n' \
+ '\n' % (options.target, ))
+ for lib in libnames:
+ projectfile.write(
+ 'createMAMEProjects(_target, _subtarget, "%s")\n' \
+ 'files {\n' % (lib, ))
+ for line in libraries[lib]:
+ projectfile.write(line)
+ projectfile.write('}\n\n')
+ projectfile.write('end\n')
- n = os.path.normpath(p)
- if n not in lists:
- lists.add(n)
- try:
- listfile = io.open(n, 'r', encoding='utf-8')
- except IOError:
- sys.stderr.write('Unable to open list file "%s"\n' % (p, ))
- sys.exit(1)
- with listfile:
- handler = CppParser.Handler()
- handler.line = line_hook
- parser = CppParser(handler)
- try:
- parser.parse(listfile)
- except IOError:
- sys.stderr.write('Error reading list file "%s"\n' % (p, ))
- sys.exit(1)
- except Exception as e:
- sys.stderr.write('Error parsing list file "%s": %s\n' % (p, e))
- sys.exit(1)
- lists = set()
+def write_filter(options, filterfile):
sources = set()
- do_parse(options.list)
+ DriverFilter().parse_list(options.list, lambda n: sources.add(n), lambda n: None)
drivers = set()
for source in options.sources:
@@ -796,9 +863,7 @@ def write_filter(options, filterfile):
if (len(components) > 3) and (components[:2] == ('src', 'mame')):
ext = os.path.splitext(components[-1])[1].lower()
if ext.startswith('.c'):
- if components[2] == 'drivers':
- drivers.add('/'.join(components[3:]))
- elif '/'.join(components[2:]) in sources:
+ if '/'.join(components[2:]) in sources:
drivers.add('/'.join(components[2:]))
for driver in sorted(drivers):
filterfile.write(driver + '\n')
@@ -808,9 +873,14 @@ if __name__ == '__main__':
options = parse_command_line()
if options.command == 'sourcesproject':
header_to_optional = collect_lua_directives(options)
- source_dependencies = scan_source_dependencies(options)
- write_project(options, sys.stdout, header_to_optional, source_dependencies)
+ source_dependencies = scan_source_dependencies(options.root, options.sources)
+ write_project(options, sys.stdout, header_to_optional, source_dependencies, True)
+ elif options.command == 'filterproject':
+ header_to_optional = collect_lua_directives(options)
+ sources = DriverCollector(options).sources
+ source_dependencies = scan_source_dependencies(options.root, (os.path.join('src', 'mame', *n.split('/')) for n in sources))
+ write_project(options, sys.stdout, header_to_optional, source_dependencies, False)
elif options.command == 'sourcesfilter':
write_filter(options, sys.stdout)
elif options.command == 'driverlist':
- DriverFilter(options).write_source(sys.stdout)
+ DriverLister(options).write_source(sys.stdout)