2 # -*- coding: utf-8 -*-
3 # Tool to embed file into objects
5 __author__ = __maintainer__ = "Jérôme Carretero <cJ-waf@zougloub.eu>"
6 __copyright__ = "Jérôme Carretero, 2014"
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.
21 # ^ Reference this in use="..." for things using the generated code
22 features='file_to_object',
24 # ^ Name of the file to embed in binary section.
29 - Destination is named like source, with extension renamed to .o
30 eg. some.file -> some.o
35 from waflib import Task, TaskGen, Errors
37 def filename_c_escape(x):
38 return x.replace("\\", "\\\\")
40 class file_to_object_s(Task.Task):
42 dep_vars = ('DEST_CPU', 'DEST_BINFMT')
46 for i, x in enumerate(self.inputs[0].name):
51 file = self.inputs[0].abspath()
52 size = os.path.getsize(file)
53 if self.env.DEST_CPU in ('x86_64', 'ia', 'aarch64'):
56 elif self.env.DEST_CPU in ('x86','arm', 'thumb', 'm68k'):
60 raise Errors.WafError("Unsupported DEST_CPU, please report bug!")
62 file = filename_c_escape(file)
63 name = "_binary_" + "".join(name)
64 rodata = ".section .rodata"
65 if self.env.DEST_BINFMT == "mac-o":
67 rodata = ".section __TEXT,__const"
69 with open(self.outputs[0].abspath(), 'w') as f:
72 .global %(name)s_start
84 class file_to_object_c(Task.Task):
88 for i, x in enumerate(self.inputs[0].name):
93 file = self.inputs[0].abspath()
94 size = os.path.getsize(file)
96 name = "_binary_" + "".join(name)
98 data = self.inputs[0].read('rb')
100 for idx_byte, byte in enumerate(data):
102 if len(line) > 15 or idx_byte == size-1:
103 lines.append(", ".join(("0x%02x" % ord(x)) for x in line))
105 data = ",\n ".join(lines)
107 self.outputs[0].write(\
109 unsigned long %(name)s_size = %(size)dL;
110 char const %(name)s_start[] = {
113 char const %(name)s_end[] = {};
116 @TaskGen.feature('file_to_object')
117 @TaskGen.before_method('process_source')
118 def tg_file_to_object(self):
120 sources = self.to_nodes(self.source)
123 if bld.env.F2O_METHOD == ["asm"]:
124 tgt = src.parent.find_or_declare(src.name + '.f2o.s')
125 tsk = self.create_task('file_to_object_s', src, tgt)
126 tsk.cwd = src.parent.abspath() # verify
128 tgt = src.parent.find_or_declare(src.name + '.f2o.c')
129 tsk = self.create_task('file_to_object_c', src, tgt)
130 tsk.cwd = src.parent.abspath() # verify
132 self.source = targets
136 conf.env.F2O_METHOD = ["c"]