comparison Compilable.py @ 0:28b636105ed6

Working version of codeOptimizer. -Still needs to implement more finegrained control per file basis. -CXXFLAGS are hardcoded.
author Tom Fredrik Blenning Klaussen <bfg@blenning.no>
date Sat, 15 Sep 2012 20:34:39 +0200
parents
children a1224150b8f6
comparison
equal deleted inserted replaced
-1:000000000000 0:28b636105ed6
1 import subprocess, re
2
3 def tryCompileFile(file, compiler, flags):
4 cmd = compiler + " -x c++ -o /dev/null " + flags + " -c " + file
5 devnull = open('/dev/null', 'w')
6 p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
7 stdout=devnull, stderr=None, shell=True)
8 s = p.wait()
9 devnull.close()
10 return s == 0
11
12 def tryCompileBuffer(buffer, compiler, flags):
13 cmd = compiler + " -x c++ -o /dev/null " + flags + " -c -"
14 devnull = open('/dev/null', 'w')
15 p = subprocess.Popen(cmd, stdin=subprocess.PIPE,
16 stdout=devnull, stderr=devnull, shell=True)
17 p.stdin.write(buffer)
18 p.stdin.close()
19 s = p.wait()
20 devnull.close()
21 return s == 0
22
23
24
25 class Compilable:
26 def __init__(self, path):
27 self.path = path
28 self.flags = ''
29 self.lines = None
30
31 def setFlags(self, flags):
32 self.flags = flags
33
34 def worksWithoutModifications(self):
35 return tryCompileFile(self.path, 'g++', self.flags)
36
37 def activeBuffer(self):
38 self.loadFile()
39 str = ''
40 for i in range(len(self.lines)):
41 if not i in self.replace:
42 str += self.lines[i]
43 else:
44 str += self.replace[i]
45 return str
46
47 def works(self):
48 return tryCompileBuffer(self.activeBuffer(), 'g++', self.flags)
49
50 def deactivateLine(self, i):
51 self.replace[i] = "\n"
52
53 def activateLine(self, i):
54 del self.replace[i]
55
56 def loadFile(self):
57 if self.lines == None:
58 f = open(self.path, 'r')
59 self.lines = f.readlines()
60 f.close()
61 self.replace = {}
62
63 def includeLines(self):
64 self.loadFile()
65 pattern = '^\s*#include '
66 prog = re.compile(pattern)
67 res = []
68 for i in range(len(self.lines)):
69 if prog.match(self.lines[i].rstrip()):
70 res.append(i)
71 return res
72
73 def removeRemovableIncludes(self):
74 l = self.includeLines()
75 retVal = []
76 for n in l:
77 self.deactivateLine(n)
78 print 'Trying to compile ' + self.path + ' without ' + self.getPathname(self.lines[n])
79 if self.works():
80 retVal.append(n)
81 else:
82 self.activateLine(n)
83
84 return retVal
85
86 @staticmethod
87 def getPathname(str):
88 pattern = '^\s*#include ["<]([^">]+)[">]'
89 prog = re.compile(pattern)
90 m = prog.search(str)
91 include = m.group(1)
92 return include
93
94
95 @staticmethod
96 def getClassname(str):
97 include = Compilable.getPathname(str)
98
99 pattern = '[^/]+$'
100 prog = re.compile(pattern)
101 m = prog.search(include)
102 filename = m.group(0)
103
104 pattern = '^[^.]+'
105 prog = re.compile(pattern)
106 m = prog.search(filename)
107 basename = m.group(0)
108
109 return basename
110
111 def replaceIncludes(self):
112 l = self.includeLines()
113 retVal = []
114 for n in l:
115 if n not in self.replace:
116 rstring = 'class ' + self.getClassname(self.lines[n]) + ';\n'
117 self.replace[n] = rstring
118 if self.works():
119 retVal.append(n)
120 else:
121 self.activateLine(n)
122 return retVal
123
124 def dependencies(self):
125 lines = self.includeLines()
126 retVal = []
127 for line in lines:
128 retVal.append(self.getPathname(self.lines[line]))
129 return retVal
130
131
132 def __repr__(self):
133 return self.path