| #!/usr/bin/env python |
| |
| # This script is used to generate Makefile.qemu2-sources.mk from |
| # the build output of build-qemu-android.sh. To use it: |
| # |
| # rm -rf /tmp/qemu2-build |
| # external/qemu/android/scripts/build-qemu-android.sh \ |
| # --darwin-ssh=<hostname> \ |
| # --install-dir=/tmp/qemu2-build |
| # |
| # external/qemu-android/android-qemu2-glue/scripts/gen-qemu2-sources-mk.py \ |
| # /tmp/qemu2-build \ |
| # > external/qemu-android/android-qemu2-glue/build/Makefile.qemu2-sources.mk |
| # |
| import os |
| import sys |
| |
| TARGET_SUFFIX="-softmmu" |
| |
| EXPECTED_HOSTS = set([ |
| 'linux-x86_64', |
| 'windows-x86', |
| 'windows-x86_64', |
| 'darwin-x86_64']) |
| |
| LINK_QEMU_PREFIX = 'LINK-qemu-system-' |
| IGNORED_OBJECTS = [ |
| '../audio/sdlaudio.o', |
| '../disas/arm-a64.o', |
| '../disas/libvixl/a64/decoder-a64.o', |
| '../disas/libvixl/a64/disasm-a64.o', |
| '../disas/libvixl/a64/instructions-a64.o', |
| '../disas/libvixl/utils.o', |
| 'gdbstub-xml.o', |
| '../hw/display/framebuffer.o', |
| 'hw/misc/android_boot_properties.o', |
| 'hw/misc/android_pipe_opengles.o', |
| '../qmp-marshal.o', |
| 'trace/generated-helpers.o', |
| '../ui/sdl_zoom.o', |
| '../ui/sdl.o', |
| '../ui/sdl2.o', |
| '/version.o', # something from the Windows build |
| ] |
| |
| CC_OBJECTS = [ |
| 'disas/arm-a64.o', |
| 'disas/libvixl/a64/decoder-a64.o', |
| 'disas/libvixl/a64/disasm-a64.o', |
| 'disas/libvixl/a64/instructions-a64.o', |
| 'disas/libvixl/utils.o', |
| ] |
| |
| # objects which have to be moved to *TARGET files, |
| # even if they could've been common (e.g. to fix some linking issues) |
| FORCE_TARGET_OBJECTS = [ |
| '../vl.o' |
| ] |
| |
| def find_target_lists(build_path, hosts): |
| """Return a set of QEMU cpu architectures targetted by the binaries |
| found under |build_path|. |hosts| is a set of hosts to probe for""" |
| result = set() |
| for host in hosts: |
| for subdir, dirs, files in os.walk(os.path.join(build_path,host)): |
| for efile in files: |
| if efile.startswith(LINK_QEMU_PREFIX): |
| arch = efile[len(LINK_QEMU_PREFIX):] |
| if arch[-5:] == 'w.exe': |
| arch = arch[:-5] |
| result.add(arch) |
| dirs = [] |
| return sorted(result) |
| |
| def find_link_map(build_path, host): |
| """Return a map of target architecture -> set of object file names |
| as they appear in LINK-qemu-system-* files. |build_path| is the |
| top-level build path, and |host| is the host to probe.""" |
| result = {} |
| build_path = os.path.join(build_path, host) |
| link_prefix = 'LINK-qemu-system-' |
| for subdir, dirs, files in os.walk(build_path): |
| for efile in files: |
| if efile.startswith(link_prefix): |
| target = efile[len(link_prefix):] |
| # Remove w.exe suffix for Windows binaries. |
| if target[-5:] == 'w.exe': |
| target = target[:-5] |
| result[target] = set() |
| with open(os.path.join(subdir,efile)) as lfile: |
| for line in lfile: |
| line = line.strip() |
| if line[-2:] in [ '.o', '.a' ]: |
| result[target].add(line) |
| dirs = [] |
| return result |
| |
| def list_files(name, files): |
| print "%s := \\" % name |
| |
| for f in sorted(source_list_from_objects(files)): |
| print " %s \\" % f |
| print "" |
| |
| |
| def source_list_from_objects(objects): |
| result = set() |
| for obj in objects: |
| if obj in IGNORED_OBJECTS: |
| continue |
| if obj.startswith('@BUILD_DIR@/'): |
| continue |
| if obj.endswith('.a'): |
| continue |
| if obj.startswith('../'): |
| obj = obj[3:] |
| if obj in CC_OBJECTS: |
| obj = obj[:-2] + '.cc' |
| else: |
| obj = obj[:-2] + '.c' |
| result.add(obj) |
| return sorted(result) |
| |
| def main(args): |
| """\ |
| A small script used to generate the sub-Makefiles |
| describing the common and target-specific sources |
| for the QEMU2 build performed with the emulator's |
| build system. This is done by looking at the output |
| of a regular QEMU2 build, and finding which files |
| were built and where. |
| |
| Usage: <program-name> <path-to-build-dir> |
| |
| """ |
| if len(args) != 2: |
| print "ERROR: This script takes a single argument." |
| sys.exit(1) |
| build_dir = args[1] |
| |
| print "# Auto-generated by %s - DO NOT EDIT !!" % os.path.basename(args[0]) |
| print "" |
| |
| target_list = find_target_lists(build_dir, EXPECTED_HOSTS) |
| #print "# Found targets: %s" % repr(target_list) |
| |
| host_link_map = {} |
| for host in EXPECTED_HOSTS: |
| host_link_map[host] = find_link_map(build_dir, host) |
| |
| host_list = sorted(host_link_map.keys()) |
| # The set of all objects |
| all_objects = set() |
| for host in host_list: |
| for target in host_link_map[host]: |
| all_objects |= host_link_map[host][target] |
| |
| # The set of all objects whose path begins with ../ |
| # this corresponds to objects that will end up in the qemu2_common |
| # static library. |
| common_all_objects = set([x for x in all_objects if x.startswith('../')]) |
| |
| # move the forced target object out of common |
| common_all_objects -= set(FORCE_TARGET_OBJECTS) |
| |
| # The set of common objects that are shared by all hosts. |
| common_objects = common_all_objects.copy() |
| for host in host_list: |
| for target in host_link_map[host]: |
| common_objects &= host_link_map[host][target] |
| |
| list_files('QEMU2_COMMON_SOURCES', common_objects) |
| |
| # For each host, the specific common objects that are not shared with |
| # all other hosts, but still shared by all targets. |
| host_common_map = {} |
| for host in host_list: |
| host_common_map[host] = common_all_objects - common_objects |
| for target in host_link_map[host]: |
| host_common_map[host] &= host_link_map[host][target] |
| list_files('QEMU2_COMMON_SOURCES_%s' % host, host_common_map[host]) |
| |
| # The set of all target-specifc objects. |
| all_target_objects = all_objects - common_objects |
| for host in host_list: |
| all_target_objects -= host_common_map[host] |
| |
| # Find the list of target files that are shared by all targets and all |
| # hosts at the same time. |
| target_common_map = {} |
| for target in target_list: |
| target_common_map[target] = all_target_objects.copy() |
| for host in host_list: |
| target_common_map[target] &= host_link_map[host][target] |
| |
| target_common_objects = all_target_objects.copy() |
| for target in target_common_map: |
| target_common_objects &= target_common_map[target] |
| |
| list_files('QEMU2_TARGET_SOURCES', target_common_objects) |
| |
| # For each target, find the files shared by all hosts, that only |
| # belong to this target. |
| for target in target_list: |
| target_objects = target_common_map[target] - target_common_objects |
| list_files('QEMU2_TARGET_%s_SOURCES' % target, target_objects) |
| |
| # Finally, the target- and host- specific objects. |
| for target in target_list: |
| for host in host_list: |
| objects = host_link_map[host][target] - target_common_map[target] - \ |
| target_common_objects - common_all_objects |
| list_files('QEMU2_TARGET_%s_SOURCES_%s' % (target, host), objects) |
| |
| if __name__ == "__main__": |
| main(sys.argv) |