thirdparty:waf: New files for waf 1.9.10
[bbaumbach/samba-autobuild/.git] / third_party / waf / waflib / extras / file_to_object.py
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
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         dep_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                 data = self.inputs[0].read('rb')
99                 lines, line = [], []
100                 for idx_byte, byte in enumerate(data):
101                         line.append(byte)
102                         if len(line) > 15 or idx_byte == size-1:
103                                 lines.append(", ".join(("0x%02x" % ord(x)) for x in line))
104                                 line = []
105                 data = ",\n ".join(lines)
106
107                 self.outputs[0].write(\
108 """
109 unsigned long %(name)s_size = %(size)dL;
110 char const %(name)s_start[] = {
111  %(data)s
112 };
113 char const %(name)s_end[] = {};
114 """ % locals())
115
116 @TaskGen.feature('file_to_object')
117 @TaskGen.before_method('process_source')
118 def tg_file_to_object(self):
119         bld = self.bld
120         sources = self.to_nodes(self.source)
121         targets = []
122         for src in sources:
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
127                 else:
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
131                 targets.append(tgt)
132         self.source = targets
133
134 def configure(conf):
135         conf.load('gas')
136         conf.env.F2O_METHOD = ["c"]