waf

FORK: waf with some random patches
git clone https://git.neptards.moe/neptards/waf.git
Log | Files | Refs | README

file_to_object.py (3481B)


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