Keyboard firmwares for Atmel AVR and Cortex-M
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

exporters.py 5.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134
  1. """Just a template for subclassing"""
  2. import uuid, shutil, os, logging, fnmatch
  3. from os import walk, remove
  4. from os.path import join, dirname, isdir, split
  5. from copy import copy
  6. from jinja2 import Template, FileSystemLoader
  7. from jinja2.environment import Environment
  8. from contextlib import closing
  9. from zipfile import ZipFile, ZIP_DEFLATED
  10. from workspace_tools.utils import mkdir
  11. from workspace_tools.toolchains import TOOLCHAIN_CLASSES
  12. from workspace_tools.targets import TARGET_MAP
  13. class OldLibrariesException(Exception): pass
  14. class Exporter():
  15. TEMPLATE_DIR = dirname(__file__)
  16. DOT_IN_RELATIVE_PATH = False
  17. def __init__(self, target, inputDir, program_name, build_url_resolver, extra_symbols=None):
  18. self.inputDir = inputDir
  19. self.target = target
  20. self.program_name = program_name
  21. self.toolchain = TOOLCHAIN_CLASSES[self.get_toolchain()](TARGET_MAP[target])
  22. self.build_url_resolver = build_url_resolver
  23. jinja_loader = FileSystemLoader(os.path.dirname(os.path.abspath(__file__)))
  24. self.jinja_environment = Environment(loader=jinja_loader)
  25. self.extra_symbols = extra_symbols
  26. def get_toolchain(self):
  27. return self.TOOLCHAIN
  28. def __scan_and_copy(self, src_path, trg_path):
  29. resources = self.toolchain.scan_resources(src_path)
  30. for r_type in ['headers', 's_sources', 'c_sources', 'cpp_sources',
  31. 'objects', 'libraries', 'linker_script',
  32. 'lib_builds', 'lib_refs', 'repo_files', 'hex_files', 'bin_files']:
  33. r = getattr(resources, r_type)
  34. if r:
  35. self.toolchain.copy_files(r, trg_path, rel_path=src_path)
  36. return resources
  37. def __scan_all(self, path):
  38. resources = []
  39. for root, dirs, files in walk(path):
  40. for d in copy(dirs):
  41. if d == '.' or d == '..':
  42. dirs.remove(d)
  43. for file in files:
  44. file_path = join(root, file)
  45. resources.append(file_path)
  46. return resources
  47. def scan_and_copy_resources(self, prj_path, trg_path):
  48. # Copy only the file for the required target and toolchain
  49. lib_builds = []
  50. for src in ['lib', 'src']:
  51. resources = self.__scan_and_copy(join(prj_path, src), trg_path)
  52. lib_builds.extend(resources.lib_builds)
  53. # The repository files
  54. for repo_dir in resources.repo_dirs:
  55. repo_files = self.__scan_all(repo_dir)
  56. self.toolchain.copy_files(repo_files, trg_path, rel_path=join(prj_path, src))
  57. # The libraries builds
  58. for bld in lib_builds:
  59. build_url = open(bld).read().strip()
  60. lib_data = self.build_url_resolver(build_url)
  61. lib_path = lib_data['path'].rstrip('\\/')
  62. self.__scan_and_copy(lib_path, join(trg_path, lib_data['name']))
  63. # Create .hg dir in mbed build dir so it's ignored when versioning
  64. hgdir = join(trg_path, lib_data['name'], '.hg')
  65. mkdir(hgdir)
  66. fhandle = file(join(hgdir, 'keep.me'), 'a')
  67. fhandle.close()
  68. # Final scan of the actual exported resources
  69. self.resources = self.toolchain.scan_resources(trg_path)
  70. self.resources.relative_to(trg_path, self.DOT_IN_RELATIVE_PATH)
  71. # Check the existence of a binary build of the mbed library for the desired target
  72. # This prevents exporting the mbed libraries from source
  73. # if not self.toolchain.mbed_libs:
  74. # raise OldLibrariesException()
  75. def gen_file(self, template_file, data, target_file):
  76. template_path = join(Exporter.TEMPLATE_DIR, template_file)
  77. template = self.jinja_environment.get_template(template_file)
  78. target_text = template.render(data)
  79. target_path = join(self.inputDir, target_file)
  80. logging.debug("Generating: %s" % target_path)
  81. open(target_path, "w").write(target_text)
  82. def get_symbols(self, add_extra_symbols=True):
  83. """ This function returns symbols which must be exported.
  84. Please add / overwrite symbols in each exporter separately
  85. """
  86. symbols = self.toolchain.get_symbols()
  87. # We have extra symbols from e.g. libraries, we want to have them also added to export
  88. if add_extra_symbols:
  89. if self.extra_symbols is not None:
  90. symbols.extend(self.extra_symbols)
  91. return symbols
  92. def zip_working_directory_and_clean_up(tempdirectory=None, destination=None, program_name=None, clean=True):
  93. uid = str(uuid.uuid4())
  94. zipfilename = '%s.zip'%uid
  95. logging.debug("Zipping up %s to %s" % (tempdirectory, join(destination, zipfilename)))
  96. # make zip
  97. def zipdir(basedir, archivename):
  98. assert isdir(basedir)
  99. fakeroot = program_name + '/'
  100. with closing(ZipFile(archivename, "w", ZIP_DEFLATED)) as z:
  101. for root, _, files in os.walk(basedir):
  102. # NOTE: ignore empty directories
  103. for fn in files:
  104. absfn = join(root, fn)
  105. zfn = fakeroot + '/' + absfn[len(basedir)+len(os.sep):]
  106. z.write(absfn, zfn)
  107. zipdir(tempdirectory, join(destination, zipfilename))
  108. if clean:
  109. shutil.rmtree(tempdirectory)
  110. return join(destination, zipfilename)