jack2 codebase
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.

151 lines
3.5KB

  1. #!/usr/bin/python
  2. # -*- coding: utf-8 -*-
  3. # Tool to embed file into objects
  4. __author__ = __maintainer__ = "Jérôme Carretero <cJ-waf@zougloub.eu>"
  5. __copyright__ = "Jérôme Carretero, 2014"
  6. """
  7. This tool allows to embed file contents in object files (.o).
  8. It is not exactly portable, and the file contents are reachable
  9. using various non-portable fashions.
  10. The goal here is to provide a functional interface to the embedding
  11. of file data in objects.
  12. See the ``playground/embedded_resources`` example for an example.
  13. Usage::
  14. bld(
  15. name='pipeline',
  16. # ^ Reference this in use="..." for things using the generated code
  17. features='file_to_object',
  18. source='some.file',
  19. # ^ Name of the file to embed in binary section.
  20. )
  21. Known issues:
  22. - Currently only handles elf files with GNU ld.
  23. - Destination is named like source, with extension renamed to .o
  24. eg. some.file -> some.o
  25. """
  26. import os, binascii
  27. from waflib import Task, Utils, TaskGen, Errors
  28. def filename_c_escape(x):
  29. return x.replace("\\", "\\\\")
  30. class file_to_object_s(Task.Task):
  31. color = 'CYAN'
  32. dep_vars = ('DEST_CPU', 'DEST_BINFMT')
  33. def run(self):
  34. name = []
  35. for i, x in enumerate(self.inputs[0].name):
  36. if x.isalnum():
  37. name.append(x)
  38. else:
  39. name.append('_')
  40. file = self.inputs[0].abspath()
  41. size = os.path.getsize(file)
  42. if self.env.DEST_CPU in ('x86_64', 'ia', 'aarch64'):
  43. unit = 'quad'
  44. align = 8
  45. elif self.env.DEST_CPU in ('x86','arm', 'thumb', 'm68k'):
  46. unit = 'long'
  47. align = 4
  48. else:
  49. raise Errors.WafError("Unsupported DEST_CPU, please report bug!")
  50. file = filename_c_escape(file)
  51. name = "_binary_" + "".join(name)
  52. rodata = ".section .rodata"
  53. if self.env.DEST_BINFMT == "mac-o":
  54. name = "_" + name
  55. rodata = ".section __TEXT,__const"
  56. with open(self.outputs[0].abspath(), 'w') as f:
  57. f.write(\
  58. """
  59. .global %(name)s_start
  60. .global %(name)s_end
  61. .global %(name)s_size
  62. %(rodata)s
  63. %(name)s_start:
  64. .incbin "%(file)s"
  65. %(name)s_end:
  66. .align %(align)d
  67. %(name)s_size:
  68. .%(unit)s 0x%(size)x
  69. """ % locals())
  70. class file_to_object_c(Task.Task):
  71. color = 'CYAN'
  72. def run(self):
  73. name = []
  74. for i, x in enumerate(self.inputs[0].name):
  75. if x.isalnum():
  76. name.append(x)
  77. else:
  78. name.append('_')
  79. file = self.inputs[0].abspath()
  80. size = os.path.getsize(file)
  81. name = "_binary_" + "".join(name)
  82. data = []
  83. data = self.inputs[0].read()
  84. data = binascii.hexlify(data)
  85. data = [ ("0x%s" % (data[i:i+2])) for i in range(0, len(data), 2) ]
  86. data = ",\n ".join(data)
  87. with open(self.outputs[0].abspath(), 'w') as f:
  88. f.write(\
  89. """
  90. char const %(name)s[] = {
  91. %(data)s
  92. };
  93. unsigned long %(name)s_size = %(size)dL;
  94. char const * %(name)s_start = %(name)s;
  95. char const * %(name)s_end = &%(name)s[%(size)d];
  96. """ % locals())
  97. with open(self.outputs[0].abspath(), 'w') as f:
  98. f.write(\
  99. """
  100. unsigned long %(name)s_size = %(size)dL;
  101. char const %(name)s_start[] = {
  102. %(data)s
  103. };
  104. char const %(name)s_end[] = {
  105. };
  106. """ % locals())
  107. @TaskGen.feature('file_to_object')
  108. @TaskGen.before_method('process_source')
  109. def tg_file_to_object(self):
  110. bld = self.bld
  111. sources = self.to_nodes(self.source)
  112. targets = []
  113. for src in sources:
  114. if bld.env.F2O_METHOD == ["asm"]:
  115. tgt = src.parent.find_or_declare(src.name + '.f2o.s')
  116. task = self.create_task('file_to_object_s',
  117. src, tgt, cwd=src.parent.abspath())
  118. else:
  119. tgt = src.parent.find_or_declare(src.name + '.f2o.c')
  120. task = self.create_task('file_to_object_c',
  121. src, tgt, cwd=src.parent.abspath())
  122. targets.append(tgt)
  123. self.source = targets
  124. def configure(conf):
  125. conf.load('gas')
  126. conf.env.F2O_METHOD = ["asm"]