123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- #!/usr/bin/env python
- # -*- coding: utf-8 -*-
- import os
- import re
- import subprocess
- import sys
- from collections import defaultdict
- from collections import namedtuple
- Name = namedtuple('Name', 'name desc')
- Device = namedtuple('Device', 'name bus alias desc')
- Machines = namedtuple('Machines', 'name items default')
- TARGETS = [
- Name("alpha", "Alpha"),
- Name("arm", "ARM (aarch32)"),
- Name("aarch64", "ARM64 (aarch64)"),
- Name("avr", "AVR"),
- Name("cris", "CRIS"),
- Name("hppa", "HPPA"),
- Name("i386", "i386 (x86)"),
- Name("m68k", "m68k"),
- Name("microblaze", "Microblaze"),
- Name("microblazeel", "Microblaze (Little Endian)"),
- Name("mips", "MIPS"),
- Name("mipsel", "MIPS (Little Endian)"),
- Name("mips64", "MIPS64"),
- Name("mips64el", "MIPS64 (Little Endian)"),
- Name("moxie", "Moxie"),
- Name("nios2", "NIOS2"),
- Name("or1k", "OpenRISC"),
- Name("ppc", "PowerPC"),
- Name("ppc64", "PowerPC64"),
- Name("riscv32", "RISC-V32"),
- Name("riscv64", "RISC-V64"),
- Name("rx", "RX"),
- Name("s390x", "S390x (zSeries)"),
- Name("sh4", "SH4"),
- Name("sh4eb", "SH4 (Big Endian)"),
- Name("sparc", "SPARC"),
- Name("sparc64", "SPARC64"),
- Name("tricore", "TriCore"),
- Name("x86_64", "x86_64"),
- Name("xtensa", "Xtensa"),
- Name("xtensaeb", "Xtensa (Big Endian)")
- ]
- DEFAULTS = {
- "aarch64": "virt",
- "arm": "virt",
- "avr": "mega",
- "i386": "q35",
- "rx": "gdbsim-r5f562n7",
- "tricore": "tricore_testboard",
- "x86_64": "q35"
- }
- HEADER = '''//
- // Copyright © 2020 osy. All rights reserved.
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- //
- // !! THIS FILE IS GENERATED FROM const-gen.py, DO NOT MODIFY MANUALLY !!
- #import "UTMConfiguration+Constants.h"
- @implementation UTMConfiguration (ConstantsGenerated)
- '''
- def parseListing(listing):
- output = listing.splitlines()[1:]
- result = set()
- for line in output:
- idx = line.find(' ')
- if idx < 0:
- break
- name = line[0:idx]
- description = line[idx:].strip()
- result.add(Name(name, description))
- return result
- def parseDeviceListing(listing):
- output = listing.splitlines()
- group = ''
- result = defaultdict(set)
- for line in output:
- if not line:
- continue
- if not line.startswith('name '):
- group = line.rstrip(':')
- continue
- search = re.search('^name "(?P<name>[^"]*)"(?:, bus (?P<bus>[^\s]+))?(?:, alias "(?P<alias>[^"]+)")?(?:, desc "(?P<desc>[^"]+)")?$', line)
- item = Device(search.group('name'), search.group('bus'), search.group('alias'), search.group('desc'))
- result[group].add(item)
- return result
- def sortItems(items):
- return sorted(items, key=lambda item: item.desc if item.desc else item.name)
- def getMachines(qemu_path):
- output = subprocess.check_output([qemu_path, '-machine', 'help']).decode('utf-8')
- return parseListing(output)
- def getDefaultMachine(target, machines):
- find = None
- if target in DEFAULTS:
- find = DEFAULTS[target]
- for (idx, machine) in enumerate(machines):
- if find and find == machine.name:
- return idx
- elif not find and "default" in machine.desc:
- return idx
- print(machines)
- return -1
- def getSoundCards(qemu_path):
- output = subprocess.check_output([qemu_path, '-soundhw', 'help']).decode('utf-8')
- return parseListing(output)
- def getNetworkCards(qemu_path):
- output = subprocess.check_output([qemu_path, '-device', 'help']).decode('utf-8')
- devices = parseDeviceListing(output)
- return devices["Network devices"]
- def generateArray(name, array):
- output = '+ (NSArray<NSString *>*){} {{\n'.format(name)
- output += ' return @[\n'
- for item in array:
- output += ' @"{}",\n'.format(item)
- output += ' ];\n'
- output += '}\n\n'
- return output
- def generateMap(name, keyName, keys, arrays):
- output = '+ (NSArray<NSString *>*){}:(NSString *){} {{\n'.format(name, keyName)
- output += ' return @{\n'
- for key in keys:
- output += ' @"{}":\n'.format(key)
- output += ' @[\n'
- for item in arrays[key]:
- output += ' @"{}",\n'.format(item)
- output += ' ],\n'
- output += ' }}[{}];\n'.format(keyName)
- output += '}\n\n'
- return output
- def generateIndexMap(name, keyName, keys, indexMap):
- output = '+ (NSInteger){}:(NSString *){} {{\n'.format(name, keyName)
- output += ' return [@{\n'
- for key in keys:
- output += ' @"{}": @{},\n'.format(key, indexMap[key])
- output += ' }}[{}] integerValue];\n'.format(keyName)
- output += '}\n\n'
- return output
- def generate(targets, machines, networkCards, soundCards):
- targetKeys = [item.name for item in targets]
- output = HEADER
- output += generateArray('supportedArchitectures', targetKeys)
- output += generateArray('supportedArchitecturesPretty', [item.desc for item in targets])
- output += generateMap('supportedTargetsForArchitecture', 'architecture', targetKeys, {machine.name: [item.name for item in machine.items] for machine in machines})
- output += generateMap('supportedTargetsForArchitecturePretty', 'architecture', targetKeys, {machine.name: [item.desc for item in machine.items] for machine in machines})
- output += generateIndexMap('defaultTargetIndexForArchitecture', 'architecture', targetKeys, {machine.name: machine.default for machine in machines})
- output += generateArray('supportedNetworkCards', [item.name for item in networkCards])
- output += generateArray('supportedNetworkCardsPretty', [item.desc if item.desc else item.name for item in networkCards])
- output += generateArray('supportedSoundCardDevices', [item.name for item in soundCards])
- output += generateArray('supportedSoundCardDevicesPretty', [item.desc if item.desc else item.name for item in soundCards])
- output += '@end\n'
- return output
- def main(argv):
- base = argv[1]
- allMachines = []
- soundCards = set()
- networkCards = set()
- # parse outputs
- for target in TARGETS:
- path = '{}/{}-softmmu/qemu-system-{}'.format(base, target.name, target.name)
- if not os.path.exists(path):
- path = '{}/qemu-system-{}'.format(base, target.name)
- if not os.path.exists(path):
- raise "Invalid path."
- machines = sortItems(getMachines(path))
- default = getDefaultMachine(target.name, machines)
- allMachines.append(Machines(target.name, machines, default))
- networkCards = networkCards.union(getNetworkCards(path))
- soundCards = soundCards.union(getSoundCards(path))
- # generate constants
- print(generate(TARGETS, allMachines, sortItems(networkCards), sortItems(soundCards)))
- if __name__ == "__main__":
- main(sys.argv)
|