import os, sys, re, shutil from waflib.Configure import ConfigurationContext #------------------------- # Data model # class CMTDtb: #--------------------------------------------------------- def __init__ (self): self.paths = [] self.packages = {} self.libraries = {} self.programs = {} self.macros = {} #--------------------------------------------------------- def scan_packages (self): for name in self.packages: p = self.packages[name] p.done = False #--------------------------------------------------------- def add_package (self, name, package): if not name in self.packages: self.packages[name] = package #--------------------------------------------------------- def add_library (self, ctx, package, name, sources): pack = self.packages[package] topsrc = os.path.join (pack.prefix, package, 'src') print 'add_library> package=%s name=%s topsrc=%s' % (package, name, topsrc) """ Since we only build for the current project we only consider relative paths for sources. In fact we have to filter out libraries from packages with path out of ctx.path """ fsources = [] for s in sources: lst = ctx.path.ant_glob (os.path.join (topsrc, s)) for f in lst: p = f.path_from (ctx.path) fsources.append (p) self.libraries[name] = fsources #--------------------------------------------------------- def add_program (self, ctx, package, name, sources, uses = ''): pack = self.packages[package] topsrc = os.path.join (pack.prefix, package, 'src') fsources = [] for s in sources: lst = ctx.path.ant_glob (os.path.join (topsrc, s)) for f in lst: p = f.path_from (ctx.path) fsources.append (p) self.programs[name] = [fsources, uses] #--------------------------------------------------------- def add_macro (self, ctx, use, name, value): self.macros[name] = value #--------------------------------------------------------- def add_cmt_path (self, path): self.paths.append (path) #--------------------------------------------------------- def show_macros (self): for macro, value in self.macros.iteritems(): print '> macro: ' + macro + ' ' + str(value) #--------------------------------------------------------- def show_libraries (self): for lib, sources in self.libraries.iteritems(): print '> library: ' + lib #--------------------------------------------------------- def show_programs (self): for lib, sources in self.programs.iteritems(): print '> programs: ' + lib dtb = CMTDtb () #------------------------- # Package configuration # class CMTMacro: #--------------------------------------------------------- def __init__ (self, name = ''): if name == '': return self.name = name #------------------------- # Package configuration # class CMTPackage: #--------------------------------------------------------- def __init__ (self, ctx, name = '', prefix='', path = ''): if name == '': return self.name = name self.prefix = os.path.normpath (prefix) self.path = path self.uses = [] dtb.add_package (name, self) self.read_requirements (ctx) self.done = False #--------------------------------------------------------- def add_use (self, ctx, name, prefix): found = False self.uses.append (name) if not name in dtb.packages: for path in dtb.paths: #print 'CMTDtb.add_use> path=%s prefix=%s' % (path, prefix) p = os.path.join (path, prefix, name) if os.path.exists (p): p = os.path.join (p, 'cmt') #print 'CMTPackage.add_use> p=' + p if os.path.exists (p): package = CMTPackage (ctx, name, prefix, path) found = True else: found = True if not found: print 'package ' + name + 'not found in cmtpaths' #--------------------------------------------------------- def show_uses (self, pre = ''): print '%s %s %s %s' % (pre, self.name, self.prefix, self.path) if self.done: return self.done = True #print pre + 'uses=' + ','.join(self.uses) for name in self.uses: package = dtb.packages[name] package.show_uses (pre + ' ') #--------------------------------------------------------- def read_requirements (self, ctx): path = os.path.join (self.path, self.prefix, self.name, 'cmt', 'requirements') #print 'CMTPackage.read_requirements> path=' + path try: f = open (path, 'r') for line in f: words = re.split ('\s+', line) if len(words[-1]) == 0: words = words[:-1] #print 'ws=[' + str(words) + '] last word=[' + str(len(words[-1])) + ']' verb = words[0] if verb == 'use': #print 'from package ' + self.name + '>use ' + words[1] pre = '' if len(words) > 2: pre = words[2] self.add_use (ctx=ctx, name=words[1], prefix=pre) elif verb == 'library': #print self.name + '>library ' + words[1] + ' ' + str(words[2:]) dtb.add_library (ctx=ctx, package=self.name, name=words[1], sources=words[2:]) elif verb == 'program': #print self.name + '>program ' + words[1] + ' ' + str(words[2:]) dtb.add_program (ctx=ctx, package=self.name, name=words[1], sources=words[2:]) elif verb == 'macro': #print self.name + '>macro ' + words[1] + ' ' + str(words[2:]) dtb.add_macro (ctx=ctx, use=self.name, name=words[1], value=words[2:]) f.close () finally: pass #--------------------------------------------------------- def build (self, ctx): src = os.path.join (self.path, self.prefix, self.name, 'src') print 'CMTPackage.build> srcnode=' + str(ctx.srcnode) + ' here=' + os.getcwd () includes = src libraries = '' # we collect include dirs from used packages for use in self.uses: p = dtb.packages[use] inc = os.path.join (p.prefix, use, 'src') includes += ' ' + inc # we declare the build for all libraries for lib, sources in dtb.libraries.iteritems(): print self.name + '> build library ' + lib + ' sources=' + str(sources) + ' includes=' + str(includes) linkopts = '' if lib + '_linkopts' in dtb.macros: linkopts = dtb.macros[lib + '_linkopts'] link = ' '.join (linkopts) ctx.shlib ( source=sources, includes=includes, use=link, target=lib) # we declare the build for all programs for pgm, attrs in dtb.programs.iteritems(): sources = attrs[0] linkopts = '' if pgm + '_linkopts' in dtb.macros: linkopts = dtb.macros[pgm + '_linkopts'] link = ' '.join (linkopts) print self.name + '> build program ' + pgm + ' sources=' + str(sources) + ' link=' + str(link) uses = attrs[1] ctx.program ( source=sources, includes=includes, use=link, target=pgm) Interface = CMTInterface () #---------------------------------------------------------------------------------------------------------------------- # Interface to waflib #---------------------------------------------------------------------------------------------------------------------- #------------------------- # Generic init action # def init (): # # discovering the local contexte # here = os.getcwd () print 'here=' + here # # who am I (in terms of Project) # me = os.path.basename (here) print 'me=' + me p = os.path.dirname (here) print 'p=' + p # # the current package produces its own entry in the CMTPATH # ... as well its own use entry # dtb.add_cmt_path (here) build = 'any' if sys.platform == 'win32': build = 'win32' top = here out = os.path.join (top, build) return (top, out) #------------------------- # Generic options action # def options (ctx): ctx.load ('compiler_cxx') here = os.getcwd () default_prefix = os.path.join (here, 'installarea') try: ctx.add_option('--prefix', help = "installation prefix (configuration only) [Default: '%s']" % default_prefix, default = default_prefix, dest = 'prefix') except: pass try: ctx.add_option('-show', action="store", type="string", dest="show", default = uses) except: pass #------------------------- # Generic configure action # def configure (ctx): here = os.getcwd () me = os.path.basename (here) p = os.path.dirname (here) dtb.project = CMTPackage (ctx=ctx, name=me, path=p) print 'cmt> configure in ' + ctx.path.abspath () ctx.load ('compiler_cxx') for path in dtb.paths: print 'path: ' + path print '------------ show:' Interface.show_libraries () Interface.show_programs () Interface.show_macros () print '------------' #------------------------- # Construct all build actions from all declared constituents from all used package # def build (ctx): if 'CXXFLAGS' in dtb.macros: ctx.env.append_value ('CXXFLAGS', dtb.macros['CXXFLAGS']) print 'cmt> project build in ' + ctx.path.abspath () u = dtb.project u.build (ctx) def show (ctx): here = os.getcwd () me = os.path.basename (here) p = os.path.dirname (here) dtb.project = CMTPackage (ctx=ctx, name=me, path=p) Interface.show_uses () if __name__ == "__main__": print '----------init--------------' top, out = init () print '----------------------------' if len(sys.argv) > 1: if re.match ('os', sys.argv[1]): print 'os=%s' % (os.name) elif re.match ('platform', sys.argv[1]): print 'platform=%s' % (sys.platform) elif re.match ('show_uses', sys.argv[1]): ctx = ConfigurationContext(top_dir=top, out_dir=out) ctx.init_dirs() Interface.show_uses () else: print """ cmt.py [os|platform] os platform show_uses """