#!/usr/bin/python # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Library General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. # # # # Build Boss (buildboss) # # # # # By Aleksander Demko # Copyright 2003-2004 # Feb 7, 2004 # Version 1.1.2 # # by Aleksander Demko # # should work with python 1.x too, I think! # import os import os.path import sys import re import string from sys import stdout # source file record class SourceFile: def __init__(self, filename, cppname): self.name = filename self.cname = cppname self.libs = [] self.targets = [] # a target class TargetFile: def __init__(self): self.islib = 0 self.objs = [] self.libs = {} # works on a file # refs globals: Files RElibs REtargets def do_file(filename): (root, ext) = os.path.splitext(filename) if not (ext == ".c" or ext == ".cpp"): return 0 rec = SourceFile(root + ".o", filename) f = open(filename) # operate on each line, looking for //BB lines line = f.readline() while line != "": mato = RElibs.match(line) if mato != None: rec.libs = rec.libs + string.split(mato.group(1)) mato = REtargets.match(line) if mato != None: rec.targets = rec.targets + string.split(mato.group(1)) line = f.readline() f.close() Files.append(rec) return 1 # works on a directory def do_dir(dirname): count = 0 # skips .. and . automatically files = os.listdir(dirname) for f in files: fullf = dirname + '/' + f if os.path.isdir(fullf): do_dir(fullf) # recurse on dirs else: count += do_file(fullf) # process the file if count>0: stdout.write("Directory: " + dirname + " (" + ("%d"%count) + " files)\n") # strips the lib/.so off a name def strip_libname(libname): name = libname if name[0:3] == "lib": name = name[3:] if name[-3:] == ".so": name = name[0:-3] return name # adds lib and .so to a short name (opposite of strip_libname) def add_libname(name): return "lib" + name + ".so" # print banner if len(sys.argv) <= 1: print "%s basesourcedir(s)... [-O]" % sys.argv[0] sys.exit(0) # load params opt = "-g" srcbase = [] # skip the first entry for parm in sys.argv[1:]: if (parm == "-O"): opt = "-O3 -s -DNDEBUG" elif os.path.isdir(parm): srcbase.append(parm) # read source files Files = [] RElibs = re.compile("//BBlibs(.+)$") REtargets = re.compile("//BBtargets(.+)$") for dir in srcbase: do_dir(dir) # build the target->file struct reisLib = re.compile("/?lib[^/]+$") Targets = {} for r in Files: for tar in r.targets: if not Targets.has_key(tar): Targets[tar] = TargetFile() # make a new target entry if reisLib.match(tar): # is a lib? Targets[tar].islib = 1 Targets[tar].objs.append(r.name) # add this object to the target for l in r.libs: # add a the object's libs to the target, if needed if not Targets[tar].libs.has_key(l): Targets[tar].libs[l] = 1 # using a map/hash as a set, whatever # output the makefile makefile = open("Makefile", "w+") makefile.write("# buildboss generated Makefile\n\n") makefile.write("BBCPP?=g++\n\n") # all target makefile.write("all:") for k in Targets.keys(): makefile.write(" ") makefile.write(k) makefile.write("\n\n") # each target for k,v in Targets.items(): makefile.write(k + ":") # list any pkg-config dependancies that WE"RE building right now for pd in v.libs.keys(): if Targets.has_key(add_libname(pd)): makefile.write(" " + add_libname(pd)) # dependancies for ob in v.objs: makefile.write(" " + ob) makefile.write("\n") # link line makefile.write("\t$(BBCPP) -L. " + opt) if v.islib: makefile.write(" -shared -fPIC") # object files for ob in v.objs: makefile.write(" " + ob) # libs for l in v.libs.keys(): if l[0] == "-": makefile.write(" %s" % l) else: makefile.write(" `pkg-config --libs %s`" % l) makefile.write(" -o " + k + "\n\n") # each object file for r in Files: makefile.write("%s: %s\n" % (r.name, r.cname)) makefile.write("\t$(BBCPP) -I. " + opt) for dir in srcbase: makefile.write(" -I" + dir) for l in r.libs: if l[0] != "-": makefile.write(" `pkg-config --cflags %s`" % l) makefile.write(" -c " + r.cname + " -o " + r.name + "\n\n") # make the clean rule makefile.write("clean:\n") makefile.write("\trm") for k in Targets.keys(): makefile.write(" ") makefile.write(k) for r in Files: makefile.write(" ") makefile.write(r.name) makefile.write("\n\n") makefile.write("\n\n") makefile.close() # now, write out a .pc file for each target for k,v in Targets.items(): shortname = strip_libname(k) pcfile = open(shortname + ".pc", "w+") pcfile.write("Name: " + shortname) pcfile.write("\nVersion: 1.0\nDescription: buildboss made\nRequires:") for l in v.libs.keys(): pcfile.write(" " + l) pcfile.write("\nLibs: -l" + shortname) pcfile.write("\nCflags:\n") pcfile.close() stdout.write("Wrote PC File: " + shortname + ".pc\n") stdout.write("Wrote Makefile: Makefile\n")