diff options
Diffstat (limited to 'bksys')
-rw-r--r-- | bksys/generic.py | 644 | ||||
-rw-r--r-- | bksys/kde.py | 884 | ||||
-rw-r--r-- | bksys/parser.py | 142 | ||||
-rw-r--r-- | bksys/scons-mini.tar.bz2 | bin | 0 -> 58130 bytes |
4 files changed, 1670 insertions, 0 deletions
diff --git a/bksys/generic.py b/bksys/generic.py new file mode 100644 index 0000000..6ca5cfa --- /dev/null +++ b/bksys/generic.py @@ -0,0 +1,644 @@ +## Thomas Nagy, 2005 +""" Run scons -h to display the associated help, or look below """ + +import os, re, types, sys, string, shutil, stat, glob +import SCons.Defaults +import SCons.Tool +import SCons.Util +from SCons.Script.SConscript import SConsEnvironment +from SCons.Options import Options, PathOption + +def getreldir(lenv): + cwd=os.getcwd() + root=SCons.Node.FS.default_fs.Dir('#').abspath + return cwd.replace(root,'').lstrip('/') + +def dist(env, appname, version=None): + ### To make a tarball of your masterpiece, use 'scons dist' + import os + if 'dist' in sys.argv: + if not version: VERSION=os.popen("cat VERSION").read().rstrip() + else: VERSION=version + FOLDER = appname+'-'+VERSION + TMPFOLD = ".tmp"+FOLDER + ARCHIVE = FOLDER+'.tar.bz2' + + ## check if the temporary directory already exists + os.popen('rm -rf %s %s %s' % (FOLDER, TMPFOLD, ARCHIVE) ) + + ## create a temporary directory + startdir = os.getcwd() + + os.popen("mkdir -p "+TMPFOLD) + os.popen("cp -R * "+TMPFOLD) + os.popen("mv "+TMPFOLD+" "+FOLDER) + + ## remove scons-local if it is unpacked + os.popen("rm -rf "+FOLDER+"/scons "+FOLDER+"/sconsign "+FOLDER+"/scons-local-0.96.1") + + ## remove our object files first + os.popen("find "+FOLDER+" -name \"cache\" | xargs rm -rf") + os.popen("find "+FOLDER+" -name \"build\" | xargs rm -rf") + os.popen("find "+FOLDER+" -name \"*.pyc\" | xargs rm -f") + + ## CVS cleanup + os.popen("find "+FOLDER+" -name \"CVS\" | xargs rm -rf") + os.popen("find "+FOLDER+" -name \".cvsignore\" | xargs rm -rf") + + ## Subversion cleanup + os.popen("find %s -name .svn -type d | xargs rm -rf" % FOLDER) + + ## GNU Arch cleanup + os.popen("find "+FOLDER+" -name \"{arch}\" | xargs rm -rf") + os.popen("find "+FOLDER+" -name \".arch-i*\" | xargs rm -rf") + + ## Create the tarball (coloured output) + print "\033[92m"+"Writing archive "+ARCHIVE+"\033[0m" + os.popen("tar cjf "+ARCHIVE+" "+FOLDER) + + ## Remove the temporary directory + os.popen('rm -rf '+FOLDER) + env.Exit(0) + + if 'distclean' in sys.argv: + ## Remove the cache directory + import os, shutil + if os.path.isdir(env['CACHEDIR']): shutil.rmtree(env['CACHEDIR']) + os.popen("find . -name \"*.pyc\" | xargs rm -rf") + env.Exit(0) + +colors= { +'BOLD' :"\033[1m", +'RED' :"\033[91m", +'GREEN' :"\033[92m", +'YELLOW':"\033[1m", #"\033[93m" # unreadable on white backgrounds +'CYAN' :"\033[96m", +'NORMAL':"\033[0m", +} + +def pprint(env, col, str, label=''): + if env.has_key('NOCOLORS'): + print "%s %s" % (str, label) + return + try: mycol=colors[col] + except: mycol='' + print "%s%s%s %s" % (mycol, str, colors['NORMAL'], label) + +class genobj: + def __init__(self, val, env): + if not val in "program shlib kioslave staticlib".split(): + print "unknown genobj given: "+val + env.Exit(1) + + self.type = val + self.orenv = env + self.env = None + self.executed = 0 + + self.target='' + self.src=None + + self.cxxflags='' + self.cflags='' + self.includes='' + + self.linkflags='' + self.libpaths='' + self.libs='' + + # vars used by shlibs + self.vnum='' + self.libprefix='' + + # a directory where to install the targets (optional) + self.instdir='' + + # change the working directory before reading the targets + self.chdir='' + + # unix permissions + self.perms='' + + # these members are private + self.chdir_lock=None + self.dirprefix='./' + self.old_os_dir='' + self.old_fs_dir='' + self.p_local_shlibs=[] + self.p_local_staticlibs=[] + self.p_global_shlibs=[] + + self.p_localsource=None + self.p_localtarget=None + + # work directory + self.workdir_lock=None + self.orig_fs_dir=SCons.Node.FS.default_fs.getcwd() + self.not_orig_fs_dir='' + self.not_orig_os_dir='' + + if not env.has_key('USE_THE_FORCE_LUKE'): env['USE_THE_FORCE_LUKE']=[self] + else: env['USE_THE_FORCE_LUKE'].append(self) + + def joinpath(self, val): + if len(self.dirprefix)<3: return val + dir=self.dirprefix + thing=self.orenv.make_list(val) + files=[] + bdir="./" + if self.orenv.has_key('_BUILDDIR_'): bdir=self.orenv['_BUILDDIR_'] + for v in thing: files.append( self.orenv.join(bdir, dir, v) ) + return files + + # a list of paths, with absolute and relative ones + def fixpath(self, val): + def reldir(dir): + ndir = SCons.Node.FS.default_fs.Dir(dir).srcnode().abspath + rootdir = SCons.Node.FS.default_fs.Dir('#').abspath + return ndir.replace(rootdir, '').lstrip('/') + + dir=self.dirprefix + if not len(dir)>2: dir=reldir('.') + + thing=self.orenv.make_list(val) + ret=[] + bdir="./" + if self.orenv.has_key('_BUILDDIR_'): bdir=self.orenv['_BUILDDIR_'] + for v in thing: + #if v[:2] == "./" or v[:3] == "../": + # ret.append( self.orenv.join('#', bdir, dir, v) ) + #elif v[:1] == "#" or v[:1] == "/": + # ret.append( v ) + #else: + # ret.append( self.orenv.join('#', bdir, dir, v) ) + if v[:1] == "#" or v[:1] == "/": + ret.append(v) + else: + ret.append( self.orenv.join('#', bdir, dir, v) ) + + return ret + + def lockworkdir(self): + if self.workdir_lock: return + self.workdir_lock=1 + self.not_orig_fs_dir=SCons.Node.FS.default_fs.getcwd() + self.not_orig_os_dir=os.getcwd() + SCons.Node.FS.default_fs.chdir( self.orig_fs_dir, change_os_dir=1) + + def unlockworkdir(self): + if not self.workdir_lock: return + SCons.Node.FS.default_fs.chdir( self.not_orig_fs_dir, change_os_dir=0) + os.chdir(self.not_orig_os_dir) + self.workdir_lock=None + + def execute(self): + if self.executed: return + + if self.orenv.has_key('DUMPCONFIG'): + self.xml() + self.executed=1 + return + + self.env = self.orenv.Copy() + + if not self.p_localtarget: self.p_localtarget = self.joinpath(self.target) + if not self.p_localsource: self.p_localsource = self.joinpath(self.src) + + if (not self.src or len(self.src) == 0) and not self.p_localsource: + self.env.pprint('RED',"no source file given to object - self.src") + self.env.Exit(1) + if not self.target: + self.env.pprint('RED',"no target given to object - self.target") + self.env.Exit(1) + if not self.env.has_key('nosmart_includes'): self.env.AppendUnique(CPPPATH=['./']) + if self.type == "kioslave": self.libprefix='' + + if len(self.includes)>0: self.env.AppendUnique(CPPPATH=self.fixpath(self.includes)) + if len(self.cxxflags)>0: self.env.AppendUnique(CXXFLAGS=self.env.make_list(self.cxxflags)) + if len(self.cflags)>0: self.env.AppendUnique(CCFLAGS=self.env.make_list(self.cflags)) + + llist=self.env.make_list(self.libs) + lext=['.so', '.la'] + sext='.a'.split() + for l in llist: + sal=SCons.Util.splitext(l) + if len(sal)>1: + if sal[1] in lext: self.p_local_shlibs.append(self.fixpath(sal[0]+'.so')[0]) + elif sal[1] in sext: self.p_local_staticlibs.append(self.fixpath(sal[0]+'.a')[0]) + else: self.p_global_shlibs.append(l) + + if len(self.p_global_shlibs)>0: self.env.AppendUnique(LIBS=self.p_global_shlibs) + if len(self.libpaths)>0: self.env.PrependUnique(LIBPATH=self.fixpath(self.libpaths)) + if len(self.linkflags)>0: self.env.PrependUnique(LINKFLAGS=self.env.make_list(self.linkflags)) + if len(self.p_local_shlibs)>0: + self.env.link_local_shlib(self.p_local_shlibs) + if len(self.p_local_staticlibs)>0: + self.env.link_local_staticlib(self.p_local_staticlibs) + + # the target to return - no more self.env modification is allowed after this part + ret=None + if self.type=='shlib' or self.type=='kioslave': + ret=self.env.bksys_shlib(self.p_localtarget, self.p_localsource, self.instdir, + self.libprefix, self.vnum) + elif self.type=='program': + ret=self.env.Program(self.p_localtarget, self.p_localsource) + if not self.env.has_key('NOAUTOINSTALL'): + ins=self.env.bksys_install(self.instdir, ret) + if ins and self.perms: + for i in ins: self.env.AddPostAction(ins, self.env.Chmod(str(i), self.perms)) + elif self.type=='staticlib': + ret=self.env.StaticLibrary(self.p_localtarget, self.p_localsource) + + # we link the program against a shared library made locally, add the dependency + if len(self.p_local_shlibs)>0: + if ret: self.env.Depends( ret, self.p_local_shlibs ) + if len(self.p_local_staticlibs)>0: + if ret: self.env.Depends( ret, self.p_local_staticlibs ) + + self.executed=1 + +## Copy function that honors symlinks +def copy_bksys(dest, source, env): + if os.path.islink(source): + #print "symlinking "+source+" "+dest + if os.path.islink(dest): + os.unlink(dest) + os.symlink(os.readlink(source), dest) + else: + shutil.copy2(source, dest) + st=os.stat(source) + os.chmod(dest, stat.S_IMODE(st[stat.ST_MODE]) | stat.S_IWRITE) + return 0 + +## Return a list of things +def make_list(env, s): + if type(s) is types.ListType: return s + else: + try: return s.split() + except AttributeError: return s + +def join(lenv, s1, s2, s3=None, s4=None): + if s4 and s3: return lenv.join(s1, s2, lenv.join(s3, s4)) + if s3 and s2: return lenv.join(s1, lenv.join(s2, s3)) + elif not s2: return s1 + # having s1, s2 + #print "path1 is "+s1+" path2 is "+s2+" "+os.path.join(s1,string.lstrip(s2,'/')) + if not s1: s1="/" + return os.path.join(s1,string.lstrip(s2,'/')) + +def exists(env): + return true + +# record a dump of the environment +bks_dump='<?xml version="1.0" encoding="UTF-8"?>\n<bksys version="1">\n' +def add_dump(nenv, str): + global bks_dump + if str: bks_dump+=str +def get_dump(nenv): + if not nenv.has_key('DUMPCONFIG'): + nenv.pprint('RED','WARNING: trying to get a dump while DUMPCONFIG is not set - this will not work') + global bks_dump + return bks_dump+"</bksys>\n" + +def generate(env): + ## Bksys requires scons 0.96 + env.EnsureSConsVersion(0, 96) + + SConsEnvironment.pprint = pprint + SConsEnvironment.make_list = make_list + SConsEnvironment.join = join + SConsEnvironment.dist = dist + SConsEnvironment.getreldir = getreldir + SConsEnvironment.add_dump = add_dump + SConsEnvironment.get_dump = get_dump + + env['HELP']=0 + if '--help' in sys.argv or '-h' in sys.argv or 'help' in sys.argv: env['HELP']=1 + if env['HELP']: + p=env.pprint + p('BOLD','*** Instructions ***') + p('BOLD','--------------------') + p('BOLD','* scons ','to compile') + p('BOLD','* scons -j4 ','to compile with several instances') + p('BOLD','* scons install ','to compile and install') + p('BOLD','* scons -c install','to uninstall') + p('BOLD','\n*** Generic options ***') + p('BOLD','--------------------') + p('BOLD','* debug ','debug=1 (-g) or debug=full (-g3, slower) else use environment CXXFLAGS, or -O2 by default') + p('BOLD','* prefix ','the installation path') + p('BOLD','* extraincludes','a list of paths separated by ":"') + p('BOLD','* scons configure debug=full prefix=/usr/local extraincludes=/tmp/include:/usr/local') + p('BOLD','* scons install prefix=/opt/local DESTDIR=/tmp/blah\n') + return + + ## Global cache directory + # Put all project files in it so a rm -rf cache will clean up the config + if not env.has_key('CACHEDIR'): env['CACHEDIR'] = env.join(os.getcwd(),'/cache/') + if not os.path.isdir(env['CACHEDIR']): os.mkdir(env['CACHEDIR']) + + ## SCons cache directory + # This avoids recompiling the same files over and over again: + # very handy when working with cvs + if os.getuid() != 0: env.CacheDir(os.getcwd()+'/cache/objects') + + # Avoid spreading .sconsign files everywhere - keep this line + env.SConsignFile(env['CACHEDIR']+'/scons_signatures') + + def makeHashTable(args): + table = { } + for arg in args: + if len(arg) > 1: + lst=arg.split('=') + if len(lst) < 2: continue + key=lst[0] + value=lst[1] + if len(key) > 0 and len(value) >0: table[key] = value + return table + + env['ARGS']=makeHashTable(sys.argv) + + SConsEnvironment.Chmod = SCons.Action.ActionFactory(os.chmod, lambda dest, mode: 'Chmod("%s", 0%o)' % (dest, mode)) + + ## Special trick for installing rpms ... + env['DESTDIR']='' + if 'install' in sys.argv: + dd='' + if os.environ.has_key('DESTDIR'): dd=os.environ['DESTDIR'] + if not dd: + if env['ARGS'] and env['ARGS'].has_key('DESTDIR'): dd=env['ARGS']['DESTDIR'] + if dd: + env['DESTDIR']=dd + env.pprint('CYAN','** Enabling DESTDIR for the project ** ',env['DESTDIR']) + + ## install symlinks for shared libraries properly + env['INSTALL'] = copy_bksys + + ## Use the same extension .o for all object files + env['STATIC_AND_SHARED_OBJECTS_ARE_THE_SAME'] = 1 + + ## no colors + if os.environ.has_key('NOCOLORS'): env['NOCOLORS']=1 + + ## load the options + cachefile=env['CACHEDIR']+'generic.cache.py' + opts = Options(cachefile) + opts.AddOptions( + ( 'GENCCFLAGS', 'C flags' ), + ( 'BKS_DEBUG', 'debug level: full, trace, or just something' ), + ( 'GENCXXFLAGS', 'additional cxx flags for the project' ), + ( 'GENLINKFLAGS', 'additional link flags' ), + ( 'PREFIX', 'prefix for installation' ), + ( 'EXTRAINCLUDES', 'extra include paths for the project' ), + ( 'ISCONFIGURED', 'is the project configured' ), + ) + opts.Update(env) + + # Use this to avoid an error message 'how to make target configure ?' + env.Alias('configure', None) + + # Check if the following command line arguments have been given + # and set a flag in the environment to show whether or not it was + # given. + if 'install' in sys.argv: env['_INSTALL']=1 + else: env['_INSTALL']=0 + if 'configure' in sys.argv: env['_CONFIGURE']=1 + else: env['_CONFIGURE']=0 + + # Configure the environment if needed + if not env['HELP'] and (env['_CONFIGURE'] or not env.has_key('ISCONFIGURED')): + # be paranoid, unset existing variables + for var in ['BKS_DEBUG', 'GENCXXFLAGS', 'GENCCFLAGS', 'GENLINKFLAGS', 'PREFIX', 'EXTRAINCLUDES', 'ISCONFIGURED', 'EXTRAINCLUDES']: + if env.has_key(var): env.__delitem__(var) + + if env['ARGS'].get('debug', None): + env['BKS_DEBUG'] = env['ARGS'].get('debug', None) + env.pprint('CYAN','** Enabling debug for the project **') + else: + if os.environ.has_key('CXXFLAGS'): + # user-defined flags (gentooers will be elighted) + env['GENCXXFLAGS'] = SCons.Util.CLVar( os.environ['CXXFLAGS'] ) + env.Append( GENCXXFLAGS = ['-DNDEBUG', '-DNO_DEBUG'] ) + else: + env.Append(GENCXXFLAGS = ['-O2', '-DNDEBUG', '-DNO_DEBUG']) + + if os.environ.has_key('CFLAGS'): env['GENCCFLAGS'] = SCons.Util.CLVar( os.environ['CFLAGS'] ) + + ## FreeBSD settings (contributed by will at freebsd dot org) + if os.uname()[0] == "FreeBSD": + if os.environ.has_key('PTHREAD_LIBS'): + env.AppendUnique( GENLINKFLAGS = SCons.Util.CLVar( os.environ['PTHREAD_LIBS'] ) ) + else: + syspf = os.popen('/sbin/sysctl kern.osreldate') + osreldate = int(syspf.read().split()[1]) + syspf.close() + if osreldate < 500016: + env.AppendUnique( GENLINKFLAGS = ['-pthread']) + env.AppendUnique( GENCXXFLAGS = ['-D_THREAD_SAFE']) + elif osreldate < 502102: + env.AppendUnique( GENLINKFLAGS = ['-lc_r']) + env.AppendUnique( GENCXXFLAGS = ['-D_THREAD_SAFE']) + else: + env.AppendUnique( GENLINKFLAGS = ['-pthread']) + + # User-specified prefix + if env['ARGS'].has_key('prefix'): + env['PREFIX'] = os.path.abspath( env['ARGS'].get('prefix', '') ) + env.pprint('CYAN','** installation prefix for the project set to:',env['PREFIX']) + + # User-specified include paths + env['EXTRAINCLUDES'] = env['ARGS'].get('extraincludes', None) + if env['EXTRAINCLUDES']: + env.pprint('CYAN','** extra include paths for the project set to:',env['EXTRAINCLUDES']) + + env['ISCONFIGURED']=1 + + # And finally save the options in the cache + opts.Save(cachefile, env) + + def bksys_install(lenv, subdir, files, destfile=None, perms=None): + """ Install files on 'scons install' """ + if not env['_INSTALL']: return + basedir = env['DESTDIR'] + install_list=None + if not destfile: install_list = env.Install(lenv.join(basedir,subdir), lenv.make_list(files)) + elif subdir: install_list = env.InstallAs(lenv.join(basedir,subdir,destfile), lenv.make_list(files)) + else: install_list = env.InstallAs(lenv.join(basedir,destfile), lenv.make_list(files)) + if perms and install_list: lenv.AddPostAction(install_list, lenv.Chmod(install_list, perms)) + env.Alias('install', install_list) + return install_list + + def build_la_file(target, source, env): + """ Writes a .la file, used by libtool """ + dest=open(target[0].path, 'w') + sname=source[0].name + dest.write("# Generated by ltmain.sh - GNU libtool 1.5.18 - (pwn3d by bksys)\n#\n#\n") + if len(env['BKSYS_VNUM'])>0: + vnum=env['BKSYS_VNUM'] + nums=vnum.split('.') + src=source[0].name + name = src.split('so.')[0] + 'so' + strn = src+" "+name+"."+str(nums[0])+" "+name + dest.write("dlname='%s'\n" % (name+'.'+str(nums[0])) ) + dest.write("library_names='%s'\n" % (strn) ) + else: + dest.write("dlname='%s'\n" % sname) + dest.write("library_names='%s %s %s'\n" % (sname, sname, sname) ) + dest.write("old_library=''\ndependency_libs=''\ncurrent=0\n") + dest.write("age=0\nrevision=0\ninstalled=yes\nshouldnotlink=no\n") + dest.write("dlopen=''\ndlpreopen=''\n") + dest.write("libdir='%s'" % env['BKSYS_DESTDIR']) + dest.close() + return 0 + + def string_la_file(target, source, env): + print "building '%s' from '%s'" % (target[0].name, source[0].name) + la_file = env.Action(build_la_file, string_la_file, ['BKSYS_VNUM', 'BKSYS_DESTDIR']) + env['BUILDERS']['LaFile'] = env.Builder(action=la_file,suffix='.la',src_suffix=env['SHLIBSUFFIX']) + + ## Function for building shared libraries + def bksys_shlib(lenv, ntarget, source, libdir, libprefix='lib', vnum='', noinst=None): + """ Install a shared library. + + Installs a shared library, with or without a version number, and create a + .la file for use by libtool. + + If library version numbering is to be used, the version number + should be passed as a period-delimited version number (e.g. + vnum = '1.2.3'). This causes the library to be installed + with its full version number, and with symlinks pointing to it. + + For example, for libfoo version 1.2.3, install the file + libfoo.so.1.2.3, and create symlinks libfoo.so and + libfoo.so.1 that point to it. + """ + # parameter can be a list + if type(ntarget) is types.ListType: target=ntarget[0] + else: target=ntarget + + thisenv = lenv.Copy() # copying an existing environment is cheap + thisenv['BKSYS_DESTDIR']=libdir + thisenv['BKSYS_VNUM']=vnum + thisenv['SHLIBPREFIX']=libprefix + + if len(vnum)>0: + thisenv['SHLIBSUFFIX']='.so.'+vnum + thisenv.Depends(target, thisenv.Value(vnum)) + num=vnum.split('.')[0] + lst=target.split('/') + tname=lst[len(lst)-1] + libname=tname.split('.')[0] + thisenv.AppendUnique(LINKFLAGS = ["-Wl,--soname=%s.so.%s" % (libname, num)] ) + + # Fix against a scons bug - shared libs and ordinal out of range(128) + if type(source) is types.ListType: + src2=[] + for i in source: src2.append( str(i) ) + source=src2 + + library_list = thisenv.SharedLibrary(target, source) + lafile_list = thisenv.LaFile(target, library_list) + + ## Install the libraries automatically + if not thisenv.has_key('NOAUTOINSTALL') and not noinst: + thisenv.bksys_install(libdir, library_list) + thisenv.bksys_install(libdir, lafile_list) + + ## Handle the versioning + if len(vnum)>0: + nums=vnum.split('.') + symlinkcom = ('cd $TARGET.dir && rm -f $TARGET.name && ln -s $SOURCE.name $TARGET.name') + tg = target+'.so.'+vnum + nm1 = target+'.so' + nm2 = target+'.so.'+nums[0] + thisenv.Command(nm1, tg, symlinkcom) + thisenv.Command(nm2, tg, symlinkcom) + thisenv.bksys_install(libdir, nm1) + thisenv.bksys_install(libdir, nm2) + return library_list + + # Declare scons scripts to process + def subdirs(lenv, folderlist): + flist=lenv.make_list(folderlist) + for i in flist: + lenv.SConscript(lenv.join(i, 'SConscript')) + # take all objects - warn those who are not already executed + if lenv.has_key('USE_THE_FORCE_LUKE'): + for ke in lenv['USE_THE_FORCE_LUKE']: + if ke.executed: continue + #lenv.pprint('GREEN',"you forgot to execute object "+ke.target) + ke.lockworkdir() + ke.execute() + ke.unlockworkdir() + + def link_local_shlib(lenv, str): + """ Links against a shared library made in the project """ + lst = lenv.make_list(str) + for file in lst: + import re + reg=re.compile("(.*)/lib(.*).(la|so)$") + result=reg.match(file) + if not result: + reg = re.compile("(.*)/lib(.*).(la|so)\.(.)") + result=reg.match(file) + if not result: + print "Unknown la file given "+file + continue + dir = result.group(1) + link = result.group(2) + else: + dir = result.group(1) + link = result.group(2) + + lenv.AppendUnique(LIBS = [link]) + lenv.PrependUnique(LIBPATH = [dir]) + + def link_local_staticlib(lenv, str): + """ Links against a shared library made in the project """ + lst = lenv.make_list(str) + for file in lst: + import re + reg = re.compile("(.*)/(lib.*.a)") + result = reg.match(file) + if not result: + print "Unknown archive file given "+file + continue + f=SCons.Node.FS.default_fs.File(file) + lenv.Append(LINKFLAGS=[f.path]) + + def set_build_dir(lenv, dirs, buildto): + lenv.SetOption('duplicate', 'soft-copy') + lenv['_BUILDDIR_']=buildto + ldirs=lenv.make_list(dirs) + for dir in ldirs: + lenv.BuildDir(buildto+os.path.sep+dir, dir) + + #valid_targets = "program shlib kioslave staticlib".split() + SConsEnvironment.bksys_install = bksys_install + SConsEnvironment.bksys_shlib = bksys_shlib + SConsEnvironment.subdirs = subdirs + SConsEnvironment.link_local_shlib = link_local_shlib + SConsEnvironment.link_local_staticlib = link_local_staticlib + SConsEnvironment.genobj=genobj + SConsEnvironment.set_build_dir=set_build_dir + + if env.has_key('GENCXXFLAGS'): env.AppendUnique( CPPFLAGS = env['GENCXXFLAGS'] ) + if env.has_key('GENCCFLAGS'): env.AppendUnique( CCFLAGS = env['GENCCFLAGS'] ) + if env.has_key('GENLINKFLAGS'): env.AppendUnique( LINKFLAGS = env['GENLINKFLAGS'] ) + + if env.has_key('BKS_DEBUG'): + if (env['BKS_DEBUG'] == "full"): + env.AppendUnique(CXXFLAGS = ['-DDEBUG', '-g3', '-Wall']) + elif (env['BKS_DEBUG'] == "trace"): + env.AppendUnique( + LINKFLAGS=env.Split("-lmrwlog4cxxconfiguration -lmrwautofunctiontracelog4cxx -finstrument-functions"), + CXXFLAGS=env.Split("-DDEBUG -Wall -finstrument-functions -g3 -O0")) + else: + env.AppendUnique(CXXFLAGS = ['-DDEBUG', '-g', '-Wall']) + + if env.has_key('EXTRAINCLUDES'): + if env['EXTRAINCLUDES']: + incpaths = [] + for dir in str(env['EXTRAINCLUDES']).split(':'): incpaths.append( dir ) + env.Append(CPPPATH = incpaths) + + env.Export('env') diff --git a/bksys/kde.py b/bksys/kde.py new file mode 100644 index 0000000..1055a7e --- /dev/null +++ b/bksys/kde.py @@ -0,0 +1,884 @@ +# Thomas Nagy, 2005 <tnagy2^[email protected]> +""" Run scons -h to display the associated help, or look below """ + +import os, re, types +from SCons.Script.SConscript import SConsEnvironment + +# Returns the name of the shared object (eg: libkdeui.so.4) +# referenced by a libtool archive (like libkdeui.la) +def getSOfromLA(lafile): + contents = open(lafile, 'r').read() + match = re.search("^dlname='([^']*)'$", contents, re.M) + if match: return match.group(1) + return None + +# A helper, needed .. everywhere +def KDEuse(lenv, flags): + if lenv['HELP']: lenv.Exit(0) + + _flags=lenv.make_list(flags) + if 'environ' in _flags: + ## The scons developers advise against using this but it is mostly innocuous :) + lenv.AppendUnique( ENV = os.environ ) + if not 'lang_qt' in _flags: + ## Use this define if you are using the kde translation scheme (.po files) + lenv.Append( CPPFLAGS = '-DQT_NO_TRANSLATION' ) + if 'rpath' in _flags: + ## Use this to set rpath - this may cause trouble if folders are moved (chrpath) + kdelibpaths=[] + if lenv['KDELIBPATH'] == lenv['KDELIB']: kdelibpaths = [lenv['KDELIB']] + else: kdelibpaths = [lenv['KDELIBPATH'], lenv['KDELIB']] + lenv.Append( RPATH = [lenv['QTLIBPATH'], lenv['KDEMODULE']]+kdelibpaths ) + if 'thread' in _flags: + ## Uncomment the following if you need threading support + lenv.KDEaddflags_cxx( ['-DQT_THREAD_SUPPORT', '-D_REENTRANT'] ) + if 'fastmoc' in _flags: + lenv['BKSYS_FASTMOC']=1 + if 'dump' in _flags: + lenv['DUMPCONFIG']=1 + if not 'nohelp' in _flags: + if lenv['_CONFIGURE'] or lenv['HELP']: lenv.Exit(0) + if not 'nosmart' or not lenv.has_key('nosmart_includes'): + lenv.AppendUnique(CPPPATH=['#/']) + lst=[] + if lenv.has_key('USE_THE_FORCE_LUKE'): + lst=lenv['USE_THE_FORCE_LUKE'] + lenv.__delitem__('USE_THE_FORCE_LUKE') + for v in lst: v.execute() + else: lenv['nosmart_includes']=1 + + ## To use kdDebug(intvalue)<<"some trace"<<endl; you need to define -DDEBUG + ## it is done in admin/generic.py automatically when you do scons configure debug=1 + +def exists(env): + return True + +def detect_kde(env): + """ Detect the qt and kde environment using kde-config mostly """ + def getpath(varname): + if not env.has_key('ARGS'): return None + v=env['ARGS'].get(varname, None) + if v: v=os.path.abspath(v) + return v + + def getstr(varname): + if env.has_key('ARGS'): return env['ARGS'].get(varname, '') + return '' + + prefix = getpath('prefix') + execprefix = getpath('execprefix') + datadir = getpath('datadir') + libdir = getpath('libdir') + + kdedir = getstr('kdedir') + kdeincludes = getpath('kdeincludes') + kdelibs = getpath('kdelibs') + + qtdir = getstr('qtdir') + qtincludes = getpath('qtincludes') + qtlibs = getpath('qtlibs') + libsuffix = getstr('libsuffix') + + p=env.pprint + + if libdir: libdir = libdir+libsuffix + + ## Detect the kde libraries + print "Checking for kde-config : ", + str="which kde-config 2>/dev/null" + if kdedir: str="which %s 2>/dev/null" % (kdedir+'/bin/kde-config') + kde_config = os.popen(str).read().strip() + if len(kde_config): + p('GREEN', 'kde-config was found as '+kde_config) + else: + if kdedir: p('RED','kde-config was NOT found in the folder given '+kdedir) + else: p('RED','kde-config was NOT found in your PATH') + print "Make sure kde is installed properly" + print "(missing package kdebase-devel?)" + env.Exit(1) + if kdedir: env['KDEDIR']=kdedir + else: env['KDEDIR'] = os.popen(kde_config+' -prefix').read().strip() + + print "Checking for kde version : ", + kde_version = os.popen(kde_config+" --version|grep KDE").read().strip().split()[1] + if int(kde_version[0]) != 3 or int(kde_version[2]) < 2: + p('RED', kde_version) + p('RED',"Your kde version can be too old") + p('RED',"Please make sure kde is at least 3.2") + else: + p('GREEN',kde_version) + + ## Detect the qt library + print "Checking for the qt library : ", + if not qtdir: qtdir = os.getenv("QTDIR") + if qtdir: + p('GREEN',"qt is in "+qtdir) + else: + try: + tmplibdir = os.popen(kde_config+' --expandvars --install lib').read().strip() + libkdeuiSO = env.join(tmplibdir, getSOfromLA(env.join(tmplibdir,'/libkdeui.la')) ) + m = re.search('(.*)/lib/libqt.*', os.popen('ldd ' + libkdeuiSO + ' | grep libqt').read().strip().split()[2]) + except: m=None + if m: + qtdir = m.group(1) + p('YELLOW',"qt was found as "+m.group(1)) + else: + p('RED','qt was not found') + p('RED','Please set QTDIR first (/usr/lib/qt3?) or try scons -h for more options') + env.Exit(1) + env['QTDIR'] = qtdir.strip() + + ## Find the necessary programs uic and moc + print "Checking for uic : ", + uic = qtdir + "/bin/uic" + if os.path.isfile(uic): + p('GREEN',"uic was found as "+uic) + else: + uic = os.popen("which uic 2>/dev/null").read().strip() + if len(uic): + p('YELLOW',"uic was found as "+uic) + else: + uic = os.popen("which uic 2>/dev/null").read().strip() + if len(uic): + p('YELLOW',"uic was found as "+uic) + else: + p('RED',"uic was not found - set QTDIR put it in your PATH ?") + env.Exit(1) + env['QT_UIC'] = uic + + print "Checking for moc : ", + moc = qtdir + "/bin/moc" + if os.path.isfile(moc): + p('GREEN',"moc was found as "+moc) + else: + moc = os.popen("which moc 2>/dev/null").read().strip() + if len(moc): + p('YELLOW',"moc was found as "+moc) + elif os.path.isfile("/usr/share/qt3/bin/moc"): + moc = "/usr/share/qt3/bin/moc" + p('YELLOW',"moc was found as "+moc) + else: + p('RED',"moc was not found - set QTDIR or put it in your PATH ?") + env.Exit(1) + env['QT_MOC'] = moc + + ## check for the qt and kde includes + print "Checking for the qt includes : ", + if qtincludes and os.path.isfile(qtincludes + "/qlayout.h"): + # The user told where to look for and it looks valid + p('GREEN',"ok "+qtincludes) + else: + if os.path.isfile(qtdir + "/include/qlayout.h"): + # Automatic detection + p('GREEN',"ok "+qtdir+"/include/") + qtincludes = qtdir + "/include/" + elif os.path.isfile("/usr/include/qt3/qlayout.h"): + # Debian probably + p('YELLOW','the qt headers were found in /usr/include/qt3/') + qtincludes = "/usr/include/qt3" + else: + p('RED',"the qt headers were not found") + env.Exit(1) + + print "Checking for the kde includes : ", + kdeprefix = os.popen(kde_config+" --prefix").read().strip() + if not kdeincludes: + kdeincludes = kdeprefix+"/include/" + if os.path.isfile(kdeincludes + "/klineedit.h"): + p('GREEN',"ok "+kdeincludes) + else: + if os.path.isfile(kdeprefix+"/include/kde/klineedit.h"): + # Debian, Fedora probably + p('YELLOW',"the kde headers were found in %s/include/kde/"%kdeprefix) + kdeincludes = kdeprefix + "/include/kde/" + else: + p('RED',"The kde includes were NOT found") + env.Exit(1) + + # kde-config options + kdec_opts = {'KDEBIN' : 'exe', 'KDEAPPS' : 'apps', + 'KDEDATA' : 'data', 'KDEICONS' : 'icon', + 'KDEMODULE' : 'module', 'KDELOCALE' : 'locale', + 'KDEKCFG' : 'kcfg', 'KDEDOC' : 'html', + 'KDEMENU' : 'apps', 'KDEXDG' : 'xdgdata-apps', + 'KDEMIME' : 'mime', 'KDEXDGDIR' : 'xdgdata-dirs', + 'KDESERV' : 'services','KDESERVTYPES' : 'servicetypes', + 'KDEINCLUDE': 'include' } + + if prefix: + ## use the user-specified prefix + if not execprefix: execprefix=prefix + if not datadir: datadir=env.join(prefix,'share') + if not libdir: libdir=env.join(execprefix, "lib"+libsuffix) + + subst_vars = lambda x: x.replace('${exec_prefix}', execprefix)\ + .replace('${datadir}', datadir)\ + .replace('${libdir}', libdir)\ + .replace('${prefix}', prefix) + debian_fix = lambda x: x.replace('/usr/share', '${datadir}') + env['PREFIX'] = prefix + env['KDELIB'] = libdir + for (var, option) in kdec_opts.items(): + dir = os.popen(kde_config+' --install ' + option).read().strip() + if var == 'KDEDOC': dir = debian_fix(dir) + env[var] = subst_vars(dir) + + else: + env['PREFIX'] = os.popen(kde_config+' --expandvars --prefix').read().strip() + env['KDELIB'] = os.popen(kde_config+' --expandvars --install lib').read().strip() + for (var, option) in kdec_opts.items(): + dir = os.popen(kde_config+' --expandvars --install ' + option).read().strip() + env[var] = dir + + env['QTPLUGINS']=os.popen(kde_config+' --expandvars --install qtplugins').read().strip() + + ## kde libs and includes + env['KDEINCLUDEPATH']=kdeincludes + if not kdelibs: + kdelibs=os.popen(kde_config+' --expandvars --install lib').read().strip() + env['KDELIBPATH']=kdelibs + + ## qt libs and includes + env['QTINCLUDEPATH']=qtincludes + if not qtlibs: + qtlibs=qtdir+"/lib"+libsuffix + env['QTLIBPATH']=qtlibs + +def generate(env): + """"Set up the qt and kde environment and builders - the moc part is difficult to understand """ + + # attach this function immediately + SConsEnvironment.KDEuse=KDEuse + + if env['HELP']: + p=env.pprint + p('BOLD','*** KDE options ***') + p('BOLD','--------------------') + p('BOLD','* prefix ','base install path, ie: /usr/local') + p('BOLD','* execprefix ','install path for binaries, ie: /usr/bin') + p('BOLD','* datadir ','install path for the data, ie: /usr/local/share') + p('BOLD','* libdir ','install path for the libs, ie: /usr/lib') + + p('BOLD','* qtdir ','base of the kde libraries') + p('BOLD','* kdedir ','base of the qt libraries') + + p('BOLD','* libsuffix ','suffix of libraries on amd64, ie: 64, 32') + p('BOLD','* kdeincludes','kde includes path (/usr/include/kde on debian, ..)') + p('BOLD','* qtincludes ','qt includes path (/usr/include/qt on debian, ..)') + p('BOLD','* kdelibs ','kde libraries path, for linking the programs') + p('BOLD','* qtlibs ','qt libraries path, for linking the program') + + p('BOLD','* scons configure libdir=/usr/local/lib qtincludes=/usr/include/qt\n') + return + + import SCons.Defaults + import SCons.Tool + import SCons.Util + import SCons.Node + + def reldir(dir): + ndir = SCons.Node.FS.default_fs.Dir(dir).srcnode().abspath + rootdir = SCons.Node.FS.default_fs.Dir('#').abspath + return ndir.replace(rootdir, '').lstrip('/') + + def relfile(file): + nfile = SCons.Node.FS.default_fs.File(file).srcnode().abspath + rootdir = SCons.Node.FS.default_fs.Dir('#').abspath + return nfile.replace(rootdir, '').lstrip('/') + + CLVar = SCons.Util.CLVar + splitext = SCons.Util.splitext + Builder = SCons.Builder.Builder + + # Detect the environment - replaces ./configure implicitely and store the options into a cache + from SCons.Options import Options + cachefile=env['CACHEDIR']+'kde.cache.py' + opts = Options(cachefile) + opts.AddOptions( + ('PREFIX', 'root of the program installation'), + + ('QTDIR', ''), + ('QTLIBPATH', 'path to the qt libraries'), + ('QTINCLUDEPATH', 'path to the qt includes'), + ('QT_UIC', 'uic command'), + ('QT_MOC', 'moc command'), + ('QTPLUGINS', 'uic executable command'), + + ('KDEDIR', ''), + ('KDELIBPATH', 'path to the installed kde libs'), + ('KDEINCLUDEPATH', 'path to the installed kde includes'), + + ('KDEBIN', 'inst path of the kde binaries'), + ('KDEINCLUDE', 'inst path of the kde include files'), + ('KDELIB', 'inst path of the kde libraries'), + ('KDEMODULE', 'inst path of the parts and libs'), + ('KDEDATA', 'inst path of the application data'), + ('KDELOCALE', ''), ('KDEDOC', ''), ('KDEKCFG', ''), + ('KDEXDG', ''), ('KDEXDGDIR', ''), ('KDEMENU', ''), + ('KDEMIME', ''), ('KDEICONS', ''), ('KDESERV', ''), + ('KDESERVTYPES', ''), ('KDEAPPS', ''), + ) + opts.Update(env) + + def getInstDirForResType(lenv,restype): + if len(restype) == 0 or not lenv.has_key(restype): + lenv.pprint('RED',"unknown resource type "+restype) + lenv.Exit(1) + else: instdir = lenv[restype] + + if env['ARGS'] and env['ARGS'].has_key('prefix'): + instdir = instdir.replace(lenv['PREFIX'], env['ARGS']['prefix']) + return instdir + + # reconfigure when things are missing + if not env['HELP'] and (env['_CONFIGURE'] or not env.has_key('QTDIR') or not env.has_key('KDEDIR')): + detect_kde(env) + opts.Save(cachefile, env) + + ## set default variables, one can override them in sconscript files + env.Append(CXXFLAGS = ['-I'+env['KDEINCLUDEPATH'], '-I'+env['QTINCLUDEPATH'] ], + LIBPATH = [env['KDELIBPATH'], env['QTLIBPATH'] ]) + + env['QT_AUTOSCAN'] = 1 + env['QT_DEBUG'] = 0 + + env['MEINPROC'] = 'meinproc' + env['MSGFMT'] = 'msgfmt' + + ## ui file processing + def uic_processing(target, source, env): + inc_kde ='#include <klocale.h>\n#include <kdialog.h>\n' + inc_moc ='#include "%s"\n' % target[2].name + comp_h ='$QT_UIC -L $QTPLUGINS -nounload -o %s %s' % (target[0].path, source[0].path) + comp_c ='$QT_UIC -L $QTPLUGINS -nounload -tr tr2i18n -impl %s %s' % (target[0].path, source[0].path) + comp_moc ='$QT_MOC -o %s %s' % (target[2].path, target[0].path) + if env.Execute(comp_h): return ret + dest = open( target[1].path, "w" ) + dest.write(inc_kde) + dest.close() + if env.Execute( comp_c+" >> "+target[1].path ): return ret + dest = open( target[1].path, "a" ) + dest.write(inc_moc) + dest.close() + ret = env.Execute( comp_moc ) + return ret + def uicEmitter(target, source, env): + adjustixes = SCons.Util.adjustixes + bs = SCons.Util.splitext(str(source[0].name))[0] + bs = env.join(str(target[0].get_dir()),bs) + target.append(bs+'.cpp') + target.append(bs+'.moc') + return target, source + env['BUILDERS']['Uic']=Builder(action=uic_processing,emitter=uicEmitter,suffix='.h',src_suffix='.ui') + + def kcfg_buildit(target, source, env): + comp='kconfig_compiler -d%s %s %s' % (str(source[0].get_dir()), source[1].path, source[0].path) + return env.Execute(comp) + def kcfg_stringit(target, source, env): + print "processing %s to get %s and %s" % (source[0].name, target[0].name, target[1].name) + def kcfgEmitter(target, source, env): + adjustixes = SCons.Util.adjustixes + file=str(source[0].srcnode().name) + bs = SCons.Util.splitext(str(source[0].name))[0] + bs = env.join(str(target[0].get_dir()),bs) + # .h file is already there + target.append( bs+'.cpp' ) + + content=source[0].srcnode().get_contents() + + kcfgfilename="" + kcfgFileDeclRx = re.compile("[fF]ile\s*=\s*(.+)\s*") + match = kcfgFileDeclRx.search(content) + if match: kcfgfilename = match.group(1) + + if not kcfgfilename: + env.pprint('RED','invalid kcfgc file '+source[0].srcnode().abspath) + env.Exit(1) + source.append( env.join( str(source[0].get_dir()), kcfgfilename) ) + return target, source + + env['BUILDERS']['Kcfg']=Builder(action=env.Action(kcfg_buildit, kcfg_stringit), + emitter=kcfgEmitter, suffix='.h', src_suffix='.kcfgc') + + ## MOC processing + env['BUILDERS']['Moc']=Builder(action='$QT_MOC -o $TARGET $SOURCE',suffix='.moc',src_suffix='.h') + env['BUILDERS']['Moccpp']=Builder(action='$QT_MOC -o $TARGET $SOURCE',suffix='_moc.cpp',src_suffix='.h') + + ## KIDL file + env['BUILDERS']['Kidl']=Builder(action= 'dcopidl $SOURCE > $TARGET || (rm -f $TARGET ; false)', + suffix='.kidl', src_suffix='.h') + ## DCOP + env['BUILDERS']['Dcop']=Builder(action='dcopidl2cpp --c++-suffix cpp --no-signals --no-stub $SOURCE', + suffix='_skel.cpp', src_suffix='.kidl') + ## STUB + env['BUILDERS']['Stub']=Builder(action= 'dcopidl2cpp --c++-suffix cpp --no-signals --no-skel $SOURCE', + suffix='_stub.cpp', src_suffix='.kidl') + ## DOCUMENTATION + env['BUILDERS']['Meinproc']=Builder(action='cd $TARGET.dir && $MEINPROC --check --cache $TARGET.name $SOURCE.name', + suffix='.cache.bz2') + ## TRANSLATIONS + env['BUILDERS']['Transfiles']=Builder(action='$MSGFMT $SOURCE -o $TARGET',suffix='.gmo',src_suffix='.po') + + ## Handy helpers for building kde programs + ## You should not have to modify them .. + + ui_ext = [".ui"] + kcfg_ext = ['.kcfgc'] + header_ext = [".h", ".hxx", ".hpp", ".hh"] + cpp_ext = [".cpp", ".cxx", ".cc"] + skel_ext = [".skel", ".SKEL"] + stub_ext = [".stub", ".STUB"] + + def KDEfiles(lenv, target, source): + """ Returns a list of files for scons (handles kde tricks like .skel) + It also makes custom checks against double includes like : ['file.ui', 'file.cpp'] + (file.cpp is already included because of file.ui) """ + + # ITA + #print "kdefiles" + + q_object_search = re.compile(r'[^A-Za-z0-9]Q_OBJECT[^A-Za-z0-9]') + def scan_moc(cppfile): + addfile=None + + # try to find the header + orifile=cppfile.srcnode().name + bs=SCons.Util.splitext(orifile)[0] + + h_file='' + dir=cppfile.dir + for n_h_ext in header_ext: + afile=dir.File(bs+n_h_ext) + if afile.rexists(): + #h_ext=n_h_ext + h_file=afile + break + # We have the header corresponding to the cpp file + if h_file: + h_contents = h_file.get_contents() + if q_object_search.search(h_contents): + # we know now there is Q_OBJECT macro + reg = '\n\s*#include\s*("|<)'+str(bs)+'.moc("|>)' + meta_object_search = re.compile(reg) + #cpp_contents = open(file_cpp, 'rb').read() + cpp_contents=cppfile.get_contents() + if meta_object_search.search(cpp_contents): + lenv.Moc(h_file) + else: + lenv.Moccpp(h_file) + addfile=bs+'_moc.cpp' + print "WARNING: moc.cpp for "+h_file.name+" consider using #include <file.moc> instead" + return addfile + + src=[] + ui_files=[] + kcfg_files=[] + other_files=[] + kidl=[] + + source_=lenv.make_list(source) + + # For each file, check wether it is a dcop file or not, and create the complete list of sources + for file in source_: + + sfile=SCons.Node.FS.default_fs.File(str(file)) # why str(file) ? because ordinal not in range issues + bs = SCons.Util.splitext(file)[0] + ext = SCons.Util.splitext(file)[1] + if ext in skel_ext: + if not bs in kidl: + kidl.append(bs) + lenv.Dcop(bs+'.kidl') + src.append(bs+'_skel.cpp') + elif ext in stub_ext: + if not bs in kidl: + kidl.append(bs) + lenv.Stub(bs+'.kidl') + src.append(bs+'_stub.cpp') + elif ext == ".moch": + lenv.Moccpp(bs+'.h') + src.append(bs+'_moc.cpp') + elif ext in cpp_ext: + src.append(file) + if not env.has_key('NOMOCFILE'): + ret = scan_moc(sfile) + if ret: src.append( sfile.dir.File(ret) ) + elif ext in ui_ext: + lenv.Uic(file) + src.append(bs+'.cpp') + elif ext in kcfg_ext: + name=SCons.Util.splitext(sfile.name)[0] + hfile=lenv.Kcfg(file) + cppkcfgfile=sfile.dir.File(bs+'.cpp') + src.append(bs+'.cpp') + else: + src.append(file) + + for base in kidl: lenv.Kidl(base+'.h') + + # Now check against typical newbie errors + for file in ui_files: + for ofile in other_files: + if ofile == file: + env.pprint('RED',"WARNING: You have included %s.ui and another file of the same prefix"%file) + print "Files generated by uic (file.h, file.cpp must not be included" + for file in kcfg_files: + for ofile in other_files: + if ofile == file: + env.pprint('RED',"WARNING: You have included %s.kcfg and another file of the same prefix"%file) + print "Files generated by kconfig_compiler (settings.h, settings.cpp) must not be included" + # ITA + #print "end kdefiles" + return src + + + """ In the future, these functions will contain the code that will dump the + configuration for re-use from an IDE """ + def KDEinstall(lenv, restype, subdir, files, perms=None): + if env.has_key('DUMPCONFIG'): + ret= "<install type=\"%s\" subdir=\"%s\">\n" % (restype, subdir) + for i in lenv.make_list(files): + ret += " <file name=\"%s\"/>\n" % (relfile(i)) + ret += "</install>\n" + lenv.add_dump(ret) + return None + + if not env['_INSTALL']: return None + dir = getInstDirForResType(lenv, restype) + + p=None + if not perms: + if restype=='KDEBIN': p=0755 + else: p=perms + install_list = lenv.bksys_install(lenv.join(dir, subdir), files, perms=p) + return install_list + + def KDEinstallas(lenv, restype, destfile, file): + if not env['_INSTALL']: return + dir = getInstDirForResType(lenv, restype) + install_list = lenv.InstallAs(lenv.join(dir, destfile), file) + env.Alias('install', install_list) + return install_list + + def KDEprogram(lenv, target, source, + includes='', localshlibs='', globallibs='', globalcxxflags=''): + """ Makes a kde program + The program is installed except if one sets env['NOAUTOINSTALL'] """ + src = KDEfiles(lenv, target, source) + program_list = lenv.Program(target, src) + + # we link the program against a shared library done locally, add the dependency + if not lenv.has_key('nosmart_includes'): + lenv.AppendUnique(CPPPATH=['./']) + if len(localshlibs)>0: + lst=lenv.make_list(localshlibs) + lenv.link_local_shlib(lst) + lenv.Depends( program_list, lst ) + + if len(includes)>0: lenv.KDEaddpaths_includes(includes) + if len(globallibs)>0: lenv.KDEaddlibs(globallibs) + if len(globalcxxflags)>0: lenv.KDEaddflags_cxx(globalcxxflags) + + if not lenv.has_key('NOAUTOINSTALL'): + KDEinstall(lenv, 'KDEBIN', '', target) + return program_list + + def KDEshlib(lenv, target, source, kdelib=0, libprefix='lib', + includes='', localshlibs='', globallibs='', globalcxxflags='', vnum=''): + """ Makes a shared library for kde (.la file for klibloader) + The library is installed except if one sets env['NOAUTOINSTALL'] """ + src = KDEfiles(lenv, target, source) + + if not lenv.has_key('nosmart_includes'): + lenv.AppendUnique(CPPPATH=['./']) + # we link the program against a shared library done locally, add the dependency + lst=[] + if len(localshlibs)>0: + lst=lenv.make_list(localshlibs) + lenv.link_local_shlib(lst) + if len(includes)>0: lenv.KDEaddpaths_includes(includes) + if len(globallibs)>0: lenv.KDEaddlibs(globallibs) + if len(globalcxxflags)>0: lenv.KDEaddflags_cxx(globalcxxflags) + + restype='KDEMODULE' + if kdelib==1: restype='KDELIB' + + library_list = lenv.bksys_shlib(target, src, getInstDirForResType(lenv, restype), libprefix, vnum) + if len(lst)>0: lenv.Depends( library_list, lst ) + + return library_list + + def KDEstaticlib(lenv, target, source): + """ Makes a static library for kde - in practice you should not use static libraries + 1. they take more memory than shared ones + 2. makefile.am needed it because of limitations + (cannot handle sources in separate folders - takes extra processing) """ + if not lenv.has_key('nosmart_includes'): lenv.AppendUnique(CPPPATH=['./']) + src=KDEfiles(lenv, target, source) + return lenv.StaticLibrary(target, src) + # do not install static libraries by default + + def KDEaddflags_cxx(lenv, fl): + """ Compilation flags for C++ programs """ + lenv.AppendUnique(CXXFLAGS = lenv.make_list(fl)) + + def KDEaddflags_c(lenv, fl): + """ Compilation flags for C programs """ + lenv.AppendUnique(CFLAGS = lenv.make_list(fl)) + + def KDEaddflags_link(lenv, fl): + """ Add link flags - Use this if KDEaddlibs below is not enough """ + lenv.PrependUnique(LINKFLAGS = lenv.make_list(fl)) + + def KDEaddlibs(lenv, libs): + """ Helper function """ + lenv.AppendUnique(LIBS = lenv.make_list(libs)) + + def KDEaddpaths_includes(lenv, paths): + """ Add new include paths """ + lenv.AppendUnique(CPPPATH = lenv.make_list(paths)) + + def KDEaddpaths_libs(lenv, paths): + """ Add paths to libraries """ + lenv.PrependUnique(LIBPATH = lenv.make_list(paths)) + + def KDElang(lenv, folder, appname): + """ Process translations (.po files) in a po/ dir """ + import glob + dir=SCons.Node.FS.default_fs.Dir(folder).srcnode() + fld=dir.srcnode() + tmptransfiles = glob.glob(str(fld)+'/*.po') + + if lenv.has_key('DUMPCONFIG'): + lenv.add_dump( "<podir dir=\"%s\" name=\"%s\"/>\n" % (reldir(dir), appname) ) + return + + transfiles=[] + if lenv.has_key('_BUILDDIR_'): + bdir=lenv['_BUILDDIR_'] + for pof in lenv.make_list(tmptransfiles): + # ITA + d=relfile(pof) + d2=d.replace(bdir,'').lstrip('/') + d3=lenv.join(bdir, d2) + #print d2 + #print d3 + transfiles.append( lenv.join('#', bdir, d2) ) + else: transfiles=tmptransfiles + + languages=None + if lenv['ARGS'] and lenv['ARGS'].has_key('languages'): + languages=lenv.make_list(lenv['ARGS']['languages']) + mydir=SCons.Node.FS.default_fs.Dir('.') + for f in transfiles: + #fname=f.replace(mydir.abspath, '') + fname=f + file=SCons.Node.FS.default_fs.File(fname) + country = SCons.Util.splitext(file.name)[0] + if not languages or country in languages: + result = lenv.Transfiles(file) + dir=lenv.join( getInstDirForResType(lenv, 'KDELOCALE'), country) + lenv.bksys_install(lenv.join(dir, 'LC_MESSAGES'), result, destfile=appname+'.mo') + + def KDEicon(lenv, icname='*', path='./', restype='KDEICONS', subdir=''): + """Contributed by: "Andrey Golovizin" <grooz()gorodok()net> + modified by "Martin Ellis" <m.a.ellis()ncl()ac()uk> + + Installs icons with filenames such as cr22-action-frame.png into + KDE icon hierachy with names like icons/crystalsvg/22x22/actions/frame.png. + + Global KDE icons can be installed simply using env.KDEicon('name'). + The second parameter, path, is optional, and specifies the icons + location in the source, relative to the SConscript file. + + To install icons that need to go under an applications directory (to + avoid name conflicts, for example), use e.g. + env.KDEicon('name', './', 'KDEDATA', 'appname/icons')""" + + if lenv.has_key('DUMPCONFIG'): + lenv.add_dump( "<icondir>\n" ) + lenv.add_dump( " <icondirent dir=\"%s\" subdir=\"%s\"/>\n" % (reldir(path), subdir) ) + lenv.add_dump( "</icondir>\n" ) + return + + type_dic = { 'action':'actions', 'app':'apps', 'device':'devices', + 'filesys':'filesystems', 'mime':'mimetypes' } + dir_dic = { + 'los' :'locolor/16x16', 'lom' :'locolor/32x32', + 'him' :'hicolor/32x32', 'hil' :'hicolor/48x48', + 'lo16' :'locolor/16x16', 'lo22' :'locolor/22x22', 'lo32' :'locolor/32x32', + 'hi16' :'hicolor/16x16', 'hi22' :'hicolor/22x22', 'hi32' :'hicolor/32x32', + 'hi48' :'hicolor/48x48', 'hi64' :'hicolor/64x64', 'hi128':'hicolor/128x128', + 'hisc' :'hicolor/scalable', + 'cr16' :'crystalsvg/16x16', 'cr22' :'crystalsvg/22x22', 'cr32' :'crystalsvg/32x32', + 'cr48' :'crystalsvg/48x48', 'cr64' :'crystalsvg/64x64', 'cr128':'crystalsvg/128x128', + 'crsc' :'crystalsvg/scalable' + } + + iconfiles = [] + dir=SCons.Node.FS.default_fs.Dir(path).srcnode() + mydir=SCons.Node.FS.default_fs.Dir('.') + import glob + for ext in ['png', 'xpm', 'mng', 'svg', 'svgz']: + files = glob.glob(str(dir)+'/'+'*-*-%s.%s' % (icname, ext)) + for file in files: + iconfiles.append( file.replace(mydir.abspath, '') ) + for iconfile in iconfiles: + lst = iconfile.split('/') + filename = lst[ len(lst) - 1 ] + tmp = filename.split('-') + if len(tmp)!=3: + env.pprint('RED','WARNING: icon filename has unknown format: '+iconfile) + continue + [icon_dir, icon_type, icon_filename]=tmp + try: + basedir=getInstDirForResType(lenv, restype) + destdir = '%s/%s/%s/%s/' % (basedir, subdir, dir_dic[icon_dir], type_dic[icon_type]) + except KeyError: + env.pprint('RED','WARNING: unknown icon type: '+iconfile) + continue + lenv.bksys_install(destdir, iconfile, icon_filename) + + ## This function uses env imported above - WARNING ugly code, i will have to rewrite (ITA) + def docfolder(lenv, folder, lang, destination=""): + # folder is the folder to process + # lang is the language + # destination is the subdirectory in KDEDOC (appname) + import glob + docfiles=[] + dir=SCons.Node.FS.default_fs.Dir(folder).srcnode() + mydir=SCons.Node.FS.default_fs.Dir('.') + dirpath=mydir.srcnode().abspath + docg = glob.glob(str(dir)+"/???*.*") # file files that are at least 4 chars wide :) + for file in docg: + f = file.replace(dirpath, '') + docfiles.append(f) + + if lenv.has_key('DUMPCONFIG'): + lenv.add_dump( "<docdir name=\"%s\">\n" % destination) + lenv.add_dump( " <docdirent lang=\"%s\" dir=\"%s\"/>\n" % (lang, reldir(dir)) ) + lenv.add_dump( "</docdir>\n" ) + return + + # warn about errors + #if len(lang) != 2: + # print "error, lang must be a two-letter string, like 'en'" + + # when the destination is not given, use the folder + if len(destination) == 0: destination=folder + docbook_list = [] + + bdir='.' + if lenv.has_key('_BUILDDIR_'): bdir = lenv['_BUILDDIR_'] + for file in docfiles: + # do not process folders + #if not os.path.isfile( lenv.join('.', file) ): continue + + # build a node representing the file in the build directory to force symlinking + nodefile=relfile( lenv.join(mydir.abspath, file) ) + #print nodefile + #nodefile=relfile( lenv.join(self.dirprefix, file) ) + nodefile=SCons.Node.FS.default_fs.File( lenv.join('#', bdir, nodefile) ) + #print nodefile.abspath + + # do not process the cache file + if file == 'index.cache.bz2': continue + # ignore invalid files (TODO??) + if len( SCons.Util.splitext( file ) ) <= 1: continue + ext = SCons.Util.splitext( file )[1] + + # install picture files + if ext in ['.jpeg', '.jpg', '.png']: lenv.KDEinstall('KDEDOC', lenv.join(lang,destination), nodefile.abspath) + # docbook files are processed by meinproc + if ext != '.docbook': continue + + docbook_list.append( nodefile ) + lenv.KDEinstall('KDEDOC', lenv.join(lang,destination), nodefile.abspath) + + # Now process the index.docbook files .. + if len(docbook_list) == 0: return + + index='' + cache='' + for file in docbook_list: + if file.name=='index.docbook': + index=file + cache=file.dir.File('index.cache.bz2') + + if not index: + print "BUG in docfolder: no index.docbook but docbook files found" + lenv.Exit(1) + + for file in docbook_list: + # make the cache.bz2 file depend on all .docbook files in the same dir + lenv.Depends( cache, file ) + + lenv.Meinproc( cache, index ) + lenv.KDEinstall( 'KDEDOC', lenv.join(lang,destination), cache ) + + if env['_INSTALL']: + dir=lenv.join(env['DESTDIR'], lenv.getInstDirForResType('KDEDOC'), lang, destination) + comp='mkdir -p %s && cd %s && rm -f common && ln -s ../common common' % (dir, dir) + lenv.Execute(comp) + + #self.env.AddPostAction(lenv.join(dir, 'common'), self.env.Chmod(ins, self.perms)) + # TODO add post action of cache (index.cache.bz2) + + #valid_targets = "program shlib kioslave staticlib".split() + import generic + class kobject(generic.genobj): + def __init__(self, val, senv=None): + if senv: generic.genobj.__init__(self, val, senv) + else: generic.genobj.__init__(self, val, env) + self.iskdelib=0 + def it_is_a_kdelib(self): self.iskdelib=1 + def execute(self): + if self.executed: return + if self.orenv.has_key('DUMPCONFIG'): + self.executed=1 + self.xml() + return + if (self.type=='shlib' or self.type=='kioslave'): + install_dir = 'KDEMODULE' + if self.iskdelib==1: install_dir = 'KDELIB' + self.instdir=getInstDirForResType(self.orenv, install_dir) + elif self.type=='program': + self.instdir=getInstDirForResType(self.orenv, 'KDEBIN') + self.perms=0755 + + # ITA + #print self.source + #print "hallo" + self.p_localsource=KDEfiles(env, self.joinpath(self.target), self.joinpath(self.source)) + # ITA + #print self.p_localsource + generic.genobj.execute(self) + + def xml(self): + dirprefix = reldir('.') + if not dirprefix: dirprefix=self.dirprefix + ret='<compile type="%s" dirprefix="%s" target="%s" cxxflags="%s" cflags="%s" includes="%s" linkflags="%s" libpaths="%s" libs="%s" vnum="%s" iskdelib="%s" libprefix="%s">\n' % (self.type, dirprefix, self.target, self.cxxflags, self.cflags, self.includes, self.linkflags, self.libpaths, self.libs, self.vnum, self.iskdelib, self.libprefix) + if self.source: + for i in self.orenv.make_list(self.source): ret+=' <source file="%s"/>\n' % i + ret+="</compile>\n" + self.orenv.add_dump(ret) + + # Attach the functions to the environment so that SConscripts can use them + SConsEnvironment.KDEprogram = KDEprogram + SConsEnvironment.KDEshlib = KDEshlib + SConsEnvironment.KDEstaticlib = KDEstaticlib + SConsEnvironment.KDEinstall = KDEinstall + SConsEnvironment.KDEinstallas = KDEinstallas + SConsEnvironment.KDElang = KDElang + SConsEnvironment.KDEicon = KDEicon + + SConsEnvironment.KDEaddflags_cxx = KDEaddflags_cxx + SConsEnvironment.KDEaddflags_c = KDEaddflags_c + SConsEnvironment.KDEaddflags_link = KDEaddflags_link + SConsEnvironment.KDEaddlibs = KDEaddlibs + SConsEnvironment.KDEaddpaths_includes = KDEaddpaths_includes + SConsEnvironment.KDEaddpaths_libs = KDEaddpaths_libs + + SConsEnvironment.docfolder = docfolder + SConsEnvironment.getInstDirForResType = getInstDirForResType + SConsEnvironment.kobject = kobject + diff --git a/bksys/parser.py b/bksys/parser.py new file mode 100644 index 0000000..cdde2b0 --- /dev/null +++ b/bksys/parser.py @@ -0,0 +1,142 @@ +#!/usr/bin/python + +from xml.sax import make_parser +from xml.sax.handler import ContentHandler + +import SCons.Util + +def exists(env): + return True + +class SconsHandler(ContentHandler): + + def __init__ (self, envi, builddir): + self.envname = "" + self.env = envi + self.builddir="" #envi['_BUILDDIR_'] + + #self.dump = True + self.dump = False + self.count = 0 + self.dir = "" + self.autoinstall = False + self.appname="" + + self.obj = "" + + self.subdir ="" + self.type ="" + + self.isgloballib="" + self.target="" + + self._includes="" + self.cxxflags="" + self.globallibs="" + self.locallibs="" + self.linkflags="" + + self.srclist=[] + + def adrl(self, file): + if self.builddir: + dir=self.env.join(self.builddir,file).lstrip('/') + else: + dir=file.lstrip('/') + return dir + + def dump_commands(self, str): + if self.dump: + print str + + def startElement(self, name, attrs): + + if name == 'icondirent': + dir = attrs.get('dir', '') + sbdir = attrs.get('subdir', '') + if dir: + #if self.env.has_key("DUMPCONFIG"): + # print "env.KDEicon('"+dir+")'" + self.env.KDEicon('*', self.adrl(dir), subdir=sbdir) + elif name == 'subdirent': + dir = attrs.get('dir', None) + if dir: + #if self.env.has_key("DUMPCONFIG"): + # print "env.SConscript('"+dir+"/SConscript')" + self.env.SConscript(self.env.join(self.adrl(dir),"SConscript")) + elif name == 'docdir': + self.appname = self.adrl( attrs.get('name', None) ) + elif name == 'docdirent': + dir = attrs.get('dir', None) + lang = attrs.get('lang', None) + if dir and lang: + #if self.env.has_key("DUMPCONFIG"): + # print "env.docfolder('"+dir+"', '"+lang+"', '"+self.appname+"')" + self.env.docfolder(self.adrl(dir), lang, self.appname) + elif name == 'podir': + dir = attrs.get('dir', None) + appname = attrs.get('name', None) + if dir and appname: + if self.env.has_key('_BUILDDIR_'): dir=self.env.join(self.env['_BUILDDIR_'], dir) + self.env.KDElang(dir, appname) + elif name == 'install': + self.type = attrs.get('type', None) + self.subdir = attrs.get('subdir', None) + + elif name == 'file': + name = attrs.get('name', None) + if self.type: + #if self.env.has_key("DUMPCONFIG"): + # print "env.KDEinstall('"+self.type+"', '"+self.subdir+"', '"+name+"')" + self.env.KDEinstall(self.type, self.subdir, name) + + elif name == 'compile': + + type = attrs.get('type', None) + if not type: self.env.Exit(1) + self.obj = self.env.kobject(type) + + self.obj.target = str(attrs.get('target', '')) + self.obj.source = [] + + self.obj.includes = str(attrs.get('includes', '')) + self.obj.cflags = str(attrs.get('cflags', '')) + self.obj.cxxflags = str(attrs.get('cxxflags', '')) + + self.obj.libs = str(attrs.get('libs', '')) + self.obj.linkflags = str(attrs.get('linkflags', '')) + self.obj.libpath = str(attrs.get('libpath', '')) + + self.obj.vnum = str(attrs.get('vnum', '')) + self.obj.iskdelib = str(attrs.get('iskdelib', 0)) + self.obj.libprefix = str(attrs.get('libprefix', '')) + + self.obj.chdir = self.adrl(str(attrs.get('chdir', ''))) + self.obj.dirprefix = self.adrl(str(attrs.get('dirprefix', './'))) + if not self.obj.dirprefix: self.obj.dirprefix='./' # avoid silly errors + + elif name == 'source': + file = attrs.get('file', None) + condition = attrs.get('condition', ""); + lst=condition.split(':') + for c in lst: + if self.env.has_key(c): + self.obj.source.append( file ) + break + if file and not condition: self.obj.source.append( file ) + + def endElement(self, name): + if name == 'compile': + self.obj.execute() + +def generate(env): + + def xmlfile(env, file, builddir=''): + parser = make_parser() + curHandler = SconsHandler(env, builddir) + parser.setContentHandler(curHandler) + parser.parse(open(file)) + + from SCons.Script.SConscript import SConsEnvironment + SConsEnvironment.xmlfile = xmlfile + diff --git a/bksys/scons-mini.tar.bz2 b/bksys/scons-mini.tar.bz2 Binary files differnew file mode 100644 index 0000000..fae5c28 --- /dev/null +++ b/bksys/scons-mini.tar.bz2 |