Mercurial > codeOptimizer
changeset 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 |
| files | Compilable.py DepGraph.py codeOptimizer.py |
| diffstat | 3 files changed, 304 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Compilable.py Sat Sep 15 20:34:39 2012 +0200 @@ -0,0 +1,133 @@ +import subprocess, re + +def tryCompileFile(file, compiler, flags): + cmd = compiler + " -x c++ -o /dev/null " + flags + " -c " + file + devnull = open('/dev/null', 'w') + p = subprocess.Popen(cmd, stdin=subprocess.PIPE, + stdout=devnull, stderr=None, shell=True) + s = p.wait() + devnull.close() + return s == 0 + +def tryCompileBuffer(buffer, compiler, flags): + cmd = compiler + " -x c++ -o /dev/null " + flags + " -c -" + devnull = open('/dev/null', 'w') + p = subprocess.Popen(cmd, stdin=subprocess.PIPE, + stdout=devnull, stderr=devnull, shell=True) + p.stdin.write(buffer) + p.stdin.close() + s = p.wait() + devnull.close() + return s == 0 + + + +class Compilable: + def __init__(self, path): + self.path = path + self.flags = '' + self.lines = None + + def setFlags(self, flags): + self.flags = flags + + def worksWithoutModifications(self): + return tryCompileFile(self.path, 'g++', self.flags) + + def activeBuffer(self): + self.loadFile() + str = '' + for i in range(len(self.lines)): + if not i in self.replace: + str += self.lines[i] + else: + str += self.replace[i] + return str + + def works(self): + return tryCompileBuffer(self.activeBuffer(), 'g++', self.flags) + + def deactivateLine(self, i): + self.replace[i] = "\n" + + def activateLine(self, i): + del self.replace[i] + + def loadFile(self): + if self.lines == None: + f = open(self.path, 'r') + self.lines = f.readlines() + f.close() + self.replace = {} + + def includeLines(self): + self.loadFile() + pattern = '^\s*#include ' + prog = re.compile(pattern) + res = [] + for i in range(len(self.lines)): + if prog.match(self.lines[i].rstrip()): + res.append(i) + return res + + def removeRemovableIncludes(self): + l = self.includeLines() + retVal = [] + for n in l: + self.deactivateLine(n) + print 'Trying to compile ' + self.path + ' without ' + self.getPathname(self.lines[n]) + if self.works(): + retVal.append(n) + else: + self.activateLine(n) + + return retVal + + @staticmethod + def getPathname(str): + pattern = '^\s*#include ["<]([^">]+)[">]' + prog = re.compile(pattern) + m = prog.search(str) + include = m.group(1) + return include + + + @staticmethod + def getClassname(str): + include = Compilable.getPathname(str) + + pattern = '[^/]+$' + prog = re.compile(pattern) + m = prog.search(include) + filename = m.group(0) + + pattern = '^[^.]+' + prog = re.compile(pattern) + m = prog.search(filename) + basename = m.group(0) + + return basename + + def replaceIncludes(self): + l = self.includeLines() + retVal = [] + for n in l: + if n not in self.replace: + rstring = 'class ' + self.getClassname(self.lines[n]) + ';\n' + self.replace[n] = rstring + if self.works(): + retVal.append(n) + else: + self.activateLine(n) + return retVal + + def dependencies(self): + lines = self.includeLines() + retVal = [] + for line in lines: + retVal.append(self.getPathname(self.lines[line])) + return retVal + + + def __repr__(self): + return self.path
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/DepGraph.py Sat Sep 15 20:34:39 2012 +0200 @@ -0,0 +1,101 @@ +import numpy + +from types import * + +class DepGraph: + def __init__(self): + self.deps = [] + self.values = [] + + def add(self, value): + if value in self.values: + raise ValueError + self.values.append(value) + + + def addDependency(self, src, dst): + if not type(dst) is ListType: + dst = [ dst ] + + vl = len(self.values) + dl = len(self.deps) + si = self.values.index(src) + + + if dl != vl: + full = [] + for i in range(0, vl): + full.append(False) + + exp = [] + for i in range(dl, vl): + exp.append(False) + self.deps.append(full[:]) + + for i in range(0, dl): + self.deps[i].append(exp[:]) + + for d in dst: + if d in self.values: + di = self.values.index(d) + self.deps[si][di] = True + + + @staticmethod + def directedGraphInternal(deps): + dl = len(deps) + myVals = [] + for i in range(dl): + if not max(deps[i]): + myVals.append(i) + + for i in myVals: + for j in range(dl): + deps[j][i] = False + + retVal = myVals + + if len(deps) != len(myVals): + subVals = self.directedGraphInternal(deps) + for val in myVals: + if val in subVals: + ind = subVals.index(val) + del subVals[ind] + + if subVals: + retVal.extend(subVals) + + return retVal + + @staticmethod + def printableDepgraph(deps): + res='' + for i in range(len(deps)): + if res: + res += '\n' + s = '' + for j in range(len(deps[i])): + if deps[i][j]: + s += '1' + else: + s += '0' + res += s + return res + + def directedGraph(self): + deps = self.deps[:][:] + vals = self.directedGraphInternal(deps) + retVal = [] + for i in vals: + retVal.append(self.values[i]) + return retVal + + + def toplevelDependencies(self): + dl = len(self.deps) + retVal = [] + for i in range(dl): + if not max(self.deps[i]): + print max(self.deps[i]) + retVal.append(self.values[i]) + return retVal
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/codeOptimizer.py Sat Sep 15 20:34:39 2012 +0200 @@ -0,0 +1,70 @@ +#!/usr/bin/env python -O + +import sys, string, os, subprocess + +from Compilable import Compilable +from DepGraph import DepGraph + + + +def isHppfile(name): + if name.endswith(".hpp"): + return True + if name.endswith(".h"): + return True + return False + +def isCppfile(name): + if name.endswith(".cpp"): + return True + return False + + +infiles = sys.argv[1:] + +cppfiles = {} +unknown = [] + +flags = '-DHAS_BOOST -DQT_NO_DEBUG -DQT_OPENGL_LIB -DQT_XML_LIB -DQT_SQL_LIB -O3 -Wall -I/opt/local/include -I/Users/bfg/QtSDK/Desktop/Qt/4.8.1/gcc/include -F/Users/bfg/QtSDK/Desktop/Qt/4.8.1/gcc/lib -I/Users/bfg/QtSDK/Desktop/Qt/4.8.1/gcc/include/QtOpenGL -I/Users/bfg/QtSDK/Desktop/Qt/4.8.1/gcc/include/QtXml -I/Users/bfg/QtSDK/Desktop/Qt/4.8.1/gcc/include/QtSql -I/Users/bfg/projects/dedupe' + +for file in infiles: + if isHppfile(file) or isCppfile(file): + c = Compilable(file) + c.setFlags(flags) + cppfiles[file] = c + else: + unknown.append(file) + +if len(unknown) > 0: + str = ", " + raise SystemExit(str.join(unknown) + " are of unknown filetype") + +files = cppfiles + +depgraph = DepGraph() + +for file in files: + depgraph.add(files[file]) + +for file in files: + depgraph.addDependency(files[file], files[file].dependencies()) + +files = depgraph.directedGraph() + +for file in files: + if not file.worksWithoutModifications(): + print file.path + raise SystemExit(str.join(file.path) + " does not compile at all") + +for file in files: + removable = file.removeRemovableIncludes() + if removable: + print 'Removable lines in ' + file.path + for r in removable: + print str(r) + ' : ' + file.lines[r].rstrip() + + replacable = file.replaceIncludes() + if replacable: + print 'Replacable lines in ' + file.path + for r in replacable: + print str(r) + ' : ' + file.lines[r].rstrip()
