Fix: doc/examples cross-build
[lttng-ust.git] / tools / lttng-gen-tp
CommitLineData
b25c5b37
YB
1#!/usr/bin/python
2#
3# Copyright (c) 2012 Yannick Brosseau <yannick.brosseau@gmail.com>
4#
5# This program is free software; you can redistribute it and/or
6# modify it under the terms of the GNU General Public License
7# as published by the Free Software Foundation; only version 2
8# of the License.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License along
16# with this program; if not, write to the Free Software Foundation, Inc.,
17# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18
2d9c7df1 19from __future__ import print_function
b25c5b37
YB
20import sys
21import getopt
22import re
db06a0a2
YB
23import os
24import subprocess
b25c5b37
YB
25
26class Usage(Exception):
27 def __init__(self, msg):
28 self.msg = msg
29
30class HeaderFile:
31 HEADER_TPL="""
32#undef TRACEPOINT_PROVIDER
33#define TRACEPOINT_PROVIDER {providerName}
34
45f399e8
MD
35#undef TRACEPOINT_INCLUDE
36#define TRACEPOINT_INCLUDE "./{headerFilename}"
b25c5b37 37
b25c5b37
YB
38#if !defined({includeGuard}) || defined(TRACEPOINT_HEADER_MULTI_READ)
39#define {includeGuard}
40
41#include <lttng/tracepoint.h>
42
43"""
44 FOOTER_TPL="""
45#endif /* {includeGuard} */
46
47#include <lttng/tracepoint-event.h>
b25c5b37
YB
48"""
49 def __init__(self, filename, template):
50 self.outputFilename = filename
51 self.template = template
52
53 def write(self):
54 outputFile = open(self.outputFilename,"w")
8ed68685
YB
55 # Include guard macro will be created by uppercasing the filename and
56 # replacing all non alphanumeric characters with '_'
57 includeGuard = re.sub('[^0-9a-zA-Z]', '_', self.outputFilename.upper())
b25c5b37
YB
58
59 outputFile.write(HeaderFile.HEADER_TPL.format(providerName=self.template.domain,
60 includeGuard = includeGuard,
61 headerFilename = self.outputFilename))
62 outputFile.write(self.template.text)
63 outputFile.write(HeaderFile.FOOTER_TPL.format(includeGuard = includeGuard))
64 outputFile.close()
65
66class CFile:
67 FILE_TPL="""
68#define TRACEPOINT_CREATE_PROBES
69/*
70 * The header containing our TRACEPOINT_EVENTs.
71 */
72#define TRACEPOINT_DEFINE
73#include "{headerFilename}"
74"""
75 def __init__(self, filename, template):
76 self.outputFilename = filename
77 self.template = template
78
79 def write(self):
80 outputFile = open(self.outputFilename,"w")
81
82 headerFilename = self.outputFilename.replace(".c",".h")
83
84 outputFile.write(CFile.FILE_TPL.format(
85 headerFilename = headerFilename))
86 outputFile.close()
87
db06a0a2
YB
88class ObjFile:
89 def __init__(self, filename, template):
90 self.outputFilename = filename
91 self.template = template
92 def _detectCC(self):
93 cc = ""
2d9c7df1 94 if 'CC' in os.environ:
db06a0a2
YB
95 cc = os.environ['CC']
96 try:
97 subprocess.call(cc,
98 stdout=subprocess.PIPE,
99 stderr=subprocess.PIPE)
2d9c7df1
ZT
100 except OSError as msg:
101 print("Invalid CC environment variable")
db06a0a2
YB
102 cc = ""
103
104 else:
105 # Try c first, if that fails try gcc
106 try:
107 useCC = True
108 subprocess.call("cc",
109 stdout=subprocess.PIPE,
110 stderr=subprocess.PIPE)
2d9c7df1 111 except OSError as msg:
db06a0a2
YB
112 useCC = False
113 if useCC:
114 cc = "cc"
115
116 else:
117 try:
118 useGCC = True
119 subprocess.call("gcc",
120 stdout=subprocess.PIPE,
121 stderr=subprocess.PIPE)
2d9c7df1 122 except OSError as msg:
db06a0a2
YB
123 useGCC = False
124 if useGCC:
125 cc = "gcc"
126 return cc
127
128 def write(self):
129 cFilename = self.outputFilename.replace(".o",".c")
130 cc = self._detectCC()
131 if cc == "":
132 raise RuntimeError("No C Compiler detected")
2d9c7df1 133 if 'CFLAGS' in os.environ:
db06a0a2
YB
134 cflags = os.environ['CFLAGS']
135 else:
136 cflags = ""
137
138 command = cc + " -c " + cflags + " -I. -llttng-ust" + " -o " + self.outputFilename + " " + cFilename
0794b3f6
YB
139 if verbose:
140 print("Compile command: " + command)
db06a0a2
YB
141 subprocess.call(command.split())
142
b25c5b37
YB
143class TemplateFile:
144 def __init__(self, filename):
145 self.domain = ""
146 self.inputFilename = filename
147 self.parseTemplate()
148
149
150 def parseTemplate(self):
151 f = open(self.inputFilename,"r")
152
153 self.text = f.read()
154
0794b3f6
YB
155 #Remove # comments (from input and output file) but keep
156 # #include in the output file
157 removeComments = re.compile("#[^include].*$",flags=re.MULTILINE)
c233fe11 158 self.text = removeComments.sub("",self.text)
0794b3f6
YB
159 # Remove #include directive from the parsed text
160 removePreprocess = re.compile("#.*$",flags=re.MULTILINE)
161 noPreprocess = removePreprocess.sub("", self.text)
b25c5b37 162 #Remove // comments
c233fe11 163 removeLineComment = re.compile("\/\/.*$",flags=re.MULTILINE)
0794b3f6 164 nolinecomment = removeLineComment.sub("", noPreprocess)
b25c5b37
YB
165 #Remove all spaces and lines
166 cleantext = re.sub("\s*","",nolinecomment)
167 #Remove multine C style comments
168 nocomment = re.sub("/\*.*?\*/","",cleantext)
169 entries = re.split("TRACEPOINT_.*?",nocomment)
170
171 for entry in entries:
172 if entry != '':
173 decomp = re.findall("(\w*?)\((\w*?),(\w*?),", entry)
174 typea = decomp[0][0]
175 domain = decomp[0][1]
176 name = decomp[0][2]
177
178 if self.domain == "":
179 self.domain = domain
180 else:
181 if self.domain != domain:
2d9c7df1 182 print("Warning: different domain provided (%s,%s)" % (self.domain, domain))
b25c5b37 183
0794b3f6
YB
184verbose=False
185
b25c5b37
YB
186usage="""
187 lttng-gen-tp - Generate the LTTng-UST header and source based on a simple template
188
189 usage: lttng-gen-tp TEMPLATE_FILE [-o OUTPUT_FILE][-o OUTPUT_FILE]
190
191 If no OUTPUT_FILE is given, the .h and .c file will be generated.
192 (The basename of the template file with be used for the generated file.
db06a0a2 193 for example sample.tp will generate sample.h, sample.c and sample.o)
b25c5b37 194
db06a0a2 195 When using the -o option, the OUTPUT_FILE must end with either .h, .c or .o
b25c5b37
YB
196 The -o option can be repeated multiple times.
197
198 The template file must contains TRACEPOINT_EVENT and TRACEPOINT_LOGLEVEL
199 as per defined in the lttng/tracepoint.h file.
200 See the lttng-ust(3) man page for more details on the format.
201"""
202def main(argv=None):
203 if argv is None:
204 argv = sys.argv
205
206 try:
207 try:
0794b3f6 208 opts, args = getopt.gnu_getopt(argv[1:], "ho:av", ["help","verbose"])
2d9c7df1 209 except getopt.error as msg:
b25c5b37
YB
210 raise Usage(msg)
211
2d9c7df1
ZT
212 except Usage as err:
213 print(err.msg, file=sys.stderr)
214 print("for help use --help", file=sys.stderr)
b25c5b37
YB
215 return 2
216
217 outputNames = []
218 for o, a in opts:
219 if o in ("-h", "--help"):
2d9c7df1 220 print(usage)
b25c5b37
YB
221 return(0)
222 if o in ("-o",""):
223 outputNames.append(a)
224 if o in ("-a",""):
225 all = True
0794b3f6
YB
226 if o in ("-v", "--verbose"):
227 global verbose
228 verbose = True
a719be64
CB
229 try:
230 if len(args) == 0:
231 raise Usage("No template file given")
232
2d9c7df1
ZT
233 except Usage as err:
234 print(err.msg, file=sys.stderr)
235 print("for help use --help", file=sys.stderr)
a719be64 236 return 2
b25c5b37
YB
237
238 doCFile = None
239 doHeader = None
db06a0a2 240 doObj = None
b25c5b37
YB
241 headerFilename = None
242 cFilename = None
db06a0a2 243 objFilename = None
b25c5b37
YB
244
245 if len(outputNames) > 0:
246 if len(args) > 1:
2d9c7df1 247 print("Cannot process more than one input if you specify an output")
b25c5b37
YB
248 return(3)
249
250 for outputName in outputNames:
251 if outputName[-2:] == ".h":
252 doHeader = True
253 headerFilename = outputName
254 elif outputName[-2:] == ".c":
255 doCFile = True
256 cFilename = outputName
257 elif outputName[-2:] == ".o":
db06a0a2
YB
258 doObj = True
259 objFilename = outputName
b25c5b37 260 else:
2d9c7df1 261 print("output file type unsupported")
b25c5b37
YB
262 return(4)
263 else:
264 doHeader = True
265 doCFile = True
db06a0a2 266 doObj = True
b25c5b37
YB
267
268 # process arguments
269 for arg in args:
7cd5a840 270 if arg[-3:] != ".tp":
2d9c7df1 271 print(arg + " does not end in .tp. Skipping.")
7cd5a840 272 continue
b25c5b37 273
44745fc1
YB
274 tpl = None
275 try:
276 tpl = TemplateFile(arg)
277 except IOError as args:
2d9c7df1 278 print("Cannot read input file " + args.filename + " " + args.strerror)
44745fc1
YB
279 return -1
280 try:
281 if doHeader:
282 if headerFilename:
283 curFilename = headerFilename
284 else:
285 curFilename = re.sub("\.tp$",".h",arg)
286 doth = HeaderFile(curFilename, tpl)
287 doth.write()
288 if doCFile:
289 if cFilename:
290 curFilename = cFilename
291 else:
292 curFilename = re.sub("\.tp$",".c",arg)
293 dotc = CFile(curFilename, tpl)
294 dotc.write()
295 if doObj:
296 if objFilename:
297 curFilename = objFilename
298 else:
299 curFilename = re.sub("\.tp$",".o",arg)
300 dotobj = ObjFile(curFilename, tpl)
301 dotobj.write()
302 except IOError as args:
2d9c7df1 303 print("Cannot write output file " + args.filename + " " + args.strerror)
44745fc1 304 return -1
2d9c7df1 305
b25c5b37
YB
306if __name__ == "__main__":
307 sys.exit(main())
This page took 0.035911 seconds and 4 git commands to generate.