Example #1
0
def     generate( env,
                  Warning = aql.logging.Warning,
                  Tool = SCons.Tool.Tool ):
    
    toolsets =  (
                    "aql_tool_gcc",
                    "aql_tool_msvc",
                )
    
    for tool in toolsets:
        tool = Tool( tool, toolpath = env.get('toolpath', []) )
        
        if tool.exists( env ):
            tool( env )
            return
    
    Warning( "C/C++ toolchain has not been found." )
    
    default_tool_name = os.path.splitext( os.path.basename( __file__ ) )[0]
    env['TOOLS'].remove( default_tool_name )
Example #2
0
def configure(conf, cstd = 'c99'):
    env = conf.env
    if env.GetOption('clean'): return

    # Get options
    cc = env.get('cc', '').strip()
    cxx = env.get('cxx', '').strip()
    ranlib = env.get('ranlib', '').strip()
    debug = int(env.get('debug'))
    optimize = int(env.get('optimize'))
    if optimize == -1: optimize = not debug
    globalopt = int(env.get('globalopt'))
    mach = env.get('mach')
    auto_dispatch = int(env.get('auto_dispatch'))
    strict = int(env.get('strict'))
    threaded = int(env.get('threaded'))
    profile = int(env.get('profile'))
    tcmalloc = int(env.get('tcmalloc'))
    gperf = int(env.get('gperf'))
    depends = int(env.get('depends'))
    compiler = env.get('compiler')
    distcc = int(env.get('distcc'))
    ccache = int(env.get('ccache'))
    ccflags = env.get('ccflags')
    cxxflags = env.get('cxxflags')
    linkflags = env.get('linkflags')
    cxxstd = env.get('cxxstd')
    platform = env.get('platform')
    static = int(env.get('static'))
    num_jobs = env.get('num_jobs')
    osx_min_ver = env.get('osx_min_ver')
    osx_sdk_root = env.get('osx_sdk_root')
    osx_archs = env.get('osx_archs')
    win32_thread = env.get('win32_thread')
    cross_mingw = int(env.get('cross_mingw'))

    if cross_mingw:
        res_action = SCons.Action.Action('$RCCOM', '$RCCOMSTR')
        res_builder = \
            SCons.Builder.Builder(action = res_action, suffix='.o',
                                  source_scanner = SCons.Tool.SourceFileScanner)
        SCons.Tool.SourceFileScanner.add_scanner('.rc', SCons.Defaults.CScan)

        env['RC'] = 'windres'
        env['RCFLAGS'] = SCons.Util.CLVar('')
        env['RCINCFLAGS'] = '$( ${_concat(RCINCPREFIX, CPPPATH, ' +\
            'RCINCSUFFIX, __env__, RDirs, TARGET)} $)'
        env['RCINCPREFIX'] = '--include-dir '
        env['RCINCSUFFIX'] = ''
        env['RCCOM'] = '$RC $RCINCFLAGS $RCINCPREFIX $SOURCE.dir $RCFLAGS ' +\
            '-i $SOURCE -o $TARGET'
        env['BUILDERS']['RES'] = res_builder
        env['PROGSUFFIX'] = '.exe'

        env.CBDefine('WINVER=0x0600')
        env.CBDefine('_WIN32_WINNT=0x0600')
        env.CBDefine('_POSIX_SOURCE')

    if platform != '': env.Replace(PLATFORM = platform)

    # Select compiler
    compiler_mode = None

    # Prefer Intel compiler
    if compiler == 'default' and os.environ.get('INTEL_LICENSE_FILE', False):
        compiler = 'intel'

    if compiler:
        if compiler == 'gnu':
            Tool('gcc')(env)
            Tool('g++')(env)
            compiler_mode = 'gnu'

        elif compiler == 'clang':
            env.Replace(CC = 'clang')
            env.Replace(CXX = 'clang++')
            compiler_mode = 'gnu'

        elif compiler == 'intel':
            Tool('intelc')(env)
            env['ENV']['INTEL_LICENSE_FILE'] = (
                os.environ.get('INTEL_LICENSE_FILE', ''))

            if env['PLATFORM'] == 'win32': compiler_mode = 'msvc'
            else: compiler_mode = 'gnu'

            if compiler_mode == 'msvc':
                env.Replace(AR = 'xilib')

                # Work around double CCFLAGS bug
                env.Replace(CXXFLAGS = ['/TP'])

                # Fix INCLUDE
                env.PrependENVPath('INCLUDE', os.environ.get('INCLUDE', ''))

        elif compiler == 'linux-mingw':
            env.Replace(CC = 'i586-mingw32msvc-gcc')
            env.Replace(CXX = 'i586-mingw32msvc-g++')
            env.Replace(RANLIB = 'i586-mingw32msvc-ranlib')
            env.Replace(PROGSUFFIX = '.exe')
            compiler_mode = 'gnu'

        elif compiler == 'posix':
            Tool('cc')(env)
            Tool('cxx')(env)
            Tool('link')(env)
            Tool('ar')(env)
            Tool('as')(env)
            compiler_mode = 'unknown'

        elif compiler in ['hp', 'sgi', 'sun', 'aix']:
            Tool(compiler + 'cc')(env)
            Tool(compiler + 'c++')(env)
            Tool(compiler + 'link')(env)

            if compiler in ['sgi', 'sun']:
                Tool(compiler + 'ar')(env)

            compiler_mode = 'unknown'

        elif compiler != 'default':
            Tool(compiler)(env)


    if compiler_mode is None:
        if env['CC'] == 'cl' or env['CC'] == 'icl': compiler_mode = 'msvc'
        elif env['CC'] == 'gcc' or env['CC'] == 'icc': compiler_mode = 'gnu'
        else: compiler_mode = 'unknown'

    if compiler == 'default':
        _cc = env['CC']
        if _cc == 'cl': compiler = 'msvc'
        elif _cc == 'gcc': compiler = 'gnu'
        elif _cc == 'icl' or _cc == 'icc': compiler = 'intel'

    if cc: env.Replace(CC = cc)
    if cxx: env.Replace(CXX = cxx)
    if ranlib: env.Replace(RANLIB = ranlib)

    env.__setitem__('compiler', compiler)
    env.__setitem__('compiler_mode', compiler_mode)

    print('   Compiler:', env['CC'], '(%s)' % compiler)
    print('   Platform:', env['PLATFORM'])
    print('       Mode:', compiler_mode)
    print('       Arch:', env['TARGET_ARCH'])

    if compiler == 'gnu': print('GCC Version:', gcc_version_str(env))


    # SCONS_JOBS environment variable
    if num_jobs < 1 and 'SCONS_JOBS' in os.environ:
        num_jobs = int(os.environ.get('SCONS_JOBS', num_jobs))

    # Default num jobs
    if num_jobs < 1:
        import multiprocessing
        num_jobs = multiprocessing.cpu_count()

    SetOption('num_jobs', num_jobs)
    print('       Jobs:', GetOption('num_jobs'))


    # distcc
    if distcc and compiler == 'gnu':
        env.Replace(CC = 'distcc ' + env['CC'])
        env.Replace(CXX = 'distcc ' + env['CXX'])

    # cccache
    if ccache and compiler == 'gnu':
        env.Replace(CC = 'ccache ' + env['CC'])
        env.Replace(CXX = 'ccache ' + env['CXX'])


    # Exceptions
    if compiler_mode == 'msvc':
        env.AppendUnique(CCFLAGS = ['/EHa']) # Asynchronous


    # Disable troublesome warnings
    warnings = []
    if compiler_mode == 'msvc':
        env.CBDefine('_CRT_SECURE_NO_WARNINGS')

        warnings += [4297, 4103]
        if compiler == 'intel': warnings += [1786]

    if compiler == 'intel': warnings += [279]

    if compiler == 'intel':
        warnings = map(str, warnings)
        if compiler_mode == 'msvc':
            env.AppendUnique(CCFLAGS = ['/Qdiag-disable:' + ','.join(warnings)])
        else:
            env.AppendUnique(CCFLAGS = ['-diag-disable', ','.join(warnings)])

    elif compiler_mode == 'msvc':
        for warning in warnings: env.AppendUnique(CCFLAGS = ['/wd%d' % warning])


    # Profiler flags
    if profile:
        if compiler_mode == 'gnu':
            env.AppendUnique(CCFLAGS = ['-pg'])
            env.AppendUnique(LINKFLAGS = ['-pg'])


    # tcmalloc & gperf
    if tcmalloc and compiler_mode == 'gnu':
        env.AppendUnique(CCFLAGS =
                         ['-fno-builtin-malloc', '-fno-builtin-calloc',
                          '-fno-builtin-realloc', '-fno-builtin-free'])

    if tcmalloc and gperf:
        env.AppendUnique(prefer_dynamic = ['tcmalloc_and_profiler'])
        conf.CBRequireLib('tcmalloc_and_profiler')
    elif tcmalloc:
        env.AppendUnique(prefer_dynamic = ['tcmalloc'])
        conf.CBRequireLib('tcmalloc')
    elif gperf:
        env.AppendUnique(prefer_dynamic = ['profiler'])
        conf.CBRequireLib('profiler')


    # Debug flags
    if compiler_mode == 'msvc': env['PDB'] = '${TARGET}.pdb'

    if debug:
        if compiler_mode == 'msvc':
            env.AppendUnique(CCFLAGS = ['/W1'])
            env['CCPDBFLAGS'] = '/Zi /Fd${TARGET}.pdb'
            env.AppendUnique(LINKFLAGS = ['/DEBUG', '/MAP:${TARGET}.map'])

        elif compiler_mode == 'gnu':
            if compiler == 'gnu':
                env.AppendUnique(CCFLAGS = ['-g', '-Wall'])
                if conf.CheckRDynamic():
                    env.AppendUnique(LINKFLAGS = ['-rdynamic']) # for backtrace
            elif compiler == 'intel':
                env.AppendUnique(CCFLAGS = ['-g', '-diag-enable', 'warn'])
            else: # clang and others
                env.AppendUnique(CCFLAGS = ['-g', '-Wall'])

            if strict: env.AppendUnique(CCFLAGS = ['-Werror'])

        env.CBDefine('DEBUG')

        if not optimize and compiler == 'intel' and \
                env['TARGET_ARCH'] == 'x86':
            if compiler_mode == 'gnu':
                env.AppendUnique(CCFLAGS = ['-mia32'])
            elif compiler_mode == 'msvc':
                env.AppendUnique(CCFLAGS = ['/arch:IA32'])

    else:
        if compiler_mode == 'gnu':
            # Don't add debug info and enable dead code removal
            env.AppendUnique(LINKFLAGS = ['-Wl,-S', '-Wl,-x'])

        env.CBDefine('NDEBUG')


    # Optimizations
    if optimize:
        if compiler_mode == 'gnu':
            env.AppendUnique(CCFLAGS = ['-O3', '-funroll-loops'])

        elif compiler_mode == 'msvc':
            env.AppendUnique(CCFLAGS = ['/Ox'])
            if compiler == 'intel' and not globalopt:
                env.AppendUnique(LINKFLAGS = ['/Qnoipo'])

        # Whole program optimizations
        if globalopt:
            if compiler == 'intel':
                if compiler_mode == 'gnu':
                    env.AppendUnique(LINKFLAGS = ['-ipo'])
                    env.AppendUnique(CCFLAGS = ['-ipo'])
                elif compiler_mode == 'msvc':
                    env.AppendUnique(LINKFLAGS = ['/Qipo'])
                    env.AppendUnique(CCFLAGS = ['/Qipo'])

            elif compiler == 'msvc':
                env.AppendUnique(CCFLAGS = ['/GL'])
                env.AppendUnique(LINKFLAGS = ['/LTCG'])
                env.AppendUnique(ARFLAGS = ['/LTCG'])

        # Instruction set optimizations
        if compiler == 'intel':
            if env['TARGET_ARCH'].lower() in ('64bit', 'x64', 'amd64'):
                opt_base, opt_auto = 'SSE2', 'SSE3,SSSE3,SSE4.1,SSE4.2'
            else: opt_base, opt_auto = 'SSE', 'SSE2,SSE3,SSSE3,SSE4.1,SSE4.2'

            if mach: opt_base = mach

            if compiler_mode == 'gnu':
                env.AppendUnique(CCFLAGS = ['-m' + opt_base.lower()])
                if auto_dispatch:
                    env.AppendUnique(CCFLAGS = ['-ax' + opt_auto])

            elif compiler_mode == 'msvc':
                env.AppendUnique(CCFLAGS = ['/arch:' + opt_base.upper()])
                if auto_dispatch:
                    env.AppendUnique(CCFLAGS = ['/Qax' + opt_auto])

        elif compiler == 'msvc':
            if mach: env.AppendUnique(CCFLAGS = ['/arch:' + mach.upper()])

        elif mach: env.AppendUnique(CCFLAGS = ['-m' + mach.lower()])


        # Intel threading optimizations
        if compiler == 'intel':
            if compiler_mode == 'msvc':
                env.AppendUnique(CCFLAGS = ['/Qopenmp'])
            else:
                env.AppendUnique(CCFLAGS = ['-openmp'])

            if compiler_mode == 'msvc': env.PrependUnique(LIBS = ['libiomp5mt'])
            else: env.PrependUnique(LIBS = ['iomp5'])


    # Pointer disambiguation
    if compiler == 'intel':
        if compiler_mode == 'gnu':
            env.AppendUnique(CCFLAGS = ['-restrict'])
        elif compiler_mode == 'msvc':
            env.AppendUnique(CCFLAGS = ['/Qrestrict'])


    # Dependency files
    if depends and compiler_mode == 'gnu':
        env.AppendUnique(CCFLAGS = ['-MMD -MF ${TARGET}.d'])

    # No PIE with GCC 6+
    if compiler_mode == 'gnu' and (5,) <= gcc_version(env):
        env.AppendUnique(CCFLAGS = '-fno-pie')
        env.AppendUnique(LINKFLAGS = '-no-pie')


    # C mode
    if cstd:
        if compiler_mode == 'gnu':
            env.AppendUnique(CFLAGS = ['-std=' + cstd])
        elif compiler_mode == 'msvc' and compiler == 'intel':
            env.AppendUnique(CFLAGS = ['/Qstd=' + cstd])

    # C++ mode
    if cxxstd:
        if compiler_mode == 'gnu':
            env.AppendUnique(CXXFLAGS = ['-std=' + cxxstd])
        if compiler_mode == 'msvc':
            if cxxstd in ('c++14', 'c++17', 'c++20'):
                env.AppendUnique(CXXFLAGS = ['/std:' + cxxstd])


    # Threads
    if threaded:
        if compiler_mode == 'gnu':
            conf.CBRequireLib('pthread')

            env.AppendUnique(LINKFLAGS = ['-pthread'])
            env.CBDefine('_REENTRANT')

        elif compiler_mode == 'msvc':
            if win32_thread == 'static':
                if debug: env.AppendUnique(CCFLAGS = ['/MTd'])
                else: env.AppendUnique(CCFLAGS = ['/MT'])
            else:
                if debug: env.AppendUnique(CCFLAGS = ['/MDd'])
                else: env.AppendUnique(CCFLAGS = ['/MD'])


    # Link flags
    if compiler_mode == 'msvc' and not optimize:
        env.AppendUnique(LINKFLAGS = ['/INCREMENTAL'])

    if compiler_mode == 'msvc' or int(env.get('cross_mingw', 0)):
        if env.get('compiler_mode') == 'gnu':
            env.Append(LINKFLAGS = ['-Wl,-subsystem,${subsystem}'])

        elif env.get('compiler_mode') == 'msvc':
            env.Append(LINKFLAGS = [
                    '/subsystem:${subsystem},${subsystem_version}'])


    # static
    if static:
        if compiler_mode == 'gnu' and env['PLATFORM'] != 'darwin':
            env.AppendUnique(LINKFLAGS = ['-static'])


    # Don't link unneeded dynamic libs
    if compiler == 'gnu':
        env.PrependUnique(LINKFLAGS = ['-Wl,--as-needed'])


    # For darwin
    if env['PLATFORM'] == 'darwin' or int(env.get('cross_osx', 0)):
        env.CBDefine('__APPLE__')
        if osx_archs and compiler == 'gnu':
            # note: only apple compilers support multipe -arch options
            for arch in osx_archs.split():
                env.Append(CCFLAGS = ['-arch', arch])
                env.Append(LINKFLAGS = ['-arch', arch])
        if osx_min_ver:
            flag = '-mmacosx-version-min=' + osx_min_ver
            env.AppendUnique(LINKFLAGS = [flag])
            env.AppendUnique(CCFLAGS = [flag])
        if osx_sdk_root:
            env.Append(CCFLAGS = ['-isysroot', osx_sdk_root])
            # intel linker allegedly requires -isyslibroot
            # but that seems to confuse gcc
            if compiler == 'gnu':
                env.Append(LINKFLAGS = ['-isysroot', osx_sdk_root])
            elif compiler == 'intel':
                # untested
                #env.Append(LINKFLAGS = ['-Wl,-isyslibroot,' + osx_sdk_root])
                pass

    if int(env.get('cross_osx', 0)):
        env['FRAMEWORKPATHPREFIX'] = '-F'
        env['_FRAMEWORKPATH'] = \
            '${_concat(FRAMEWORKPATHPREFIX, FRAMEWORKPATH, "", __env__)}'
        env['_FRAMEWORKS'] = \
            '${_concat("-framework ", FRAMEWORKS, "", __env__)}'
        env['LINKCOM'] = env['LINKCOM'] + \
            ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS'
        env['SHLINKFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -dynamiclib')
        env['SHLINKCOM'] = env['SHLINKCOM'] + \
            ' $_FRAMEWORKPATH $_FRAMEWORKS $FRAMEWORKSFLAGS'
        env['LDMODULEPREFIX'] = ''
        env['LDMODULESUFFIX'] = ''
        env['LDMODULEFLAGS'] = SCons.Util.CLVar('$LINKFLAGS -bundle')
        env['LDMODULECOM'] = '$LDMODULE -o ${TARGET} $LDMODULEFLAGS ' + \
            '$SOURCES $_LIBDIRFLAGS $_LIBFLAGS $_FRAMEWORKPATH ' + \
            '$_FRAMEWORKS $FRAMEWORKSFLAGS'

    # User flags (Must be last)
    if ccflags: env.Append(CCFLAGS = ccflags.split())
    if cxxflags: env.Append(CXXFLAGS = cxxflags.split())
    if linkflags: env.Append(LINKFLAGS = linkflags.split())
Example #3
0
def generate(env):

	## i cannot remember having added this (ITA) - can someone explain ?
	from SCons.Tool import Tool;
	deft = Tool('default')
	deft.generate(env)

	## Bksys requires scons 0.96
	env.EnsureSConsVersion(0, 96)

	## attach functions to "env"
	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 user does not want them
	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 bksys_insttype(lenv, type, subdir, files, perms=None):
		if not lenv.has_key(type):
			lenv.pprint('RED', 'unknown file type to install '+type)
			lenv.Exit(1)
		lenv.bksys_install( lenv.join(lenv[type],subdir), files, destfile=None, perms=perms)

	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(LIBPATH=[f.dir])
			lenv.Append(LIBS=[f.name])

	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(lenv.join(buildto, dir), dir)

	def postconfig(lenv):
		## TODO this block be called from a postconfig() function (move to generic.py)
		if env['_CONFIGURE']:
			env.BuildDir('build', '.', duplicate='soft-copy')
			# generate config.h
			if not os.path.exists('build'): os.mkdir('build')
			dest=open(lenv.join('build','config.h'), 'w')
			dest.write('/* defines are added below */\n')
			dest.write('#include "config-qt4.py"\n')
			dest.write('#include "config-xml.py"\n')
			dest.close()

			dest = open(lenv.join('build','kdemacros.h'), 'w')
			dest.write('#include <kdemacros.h.in>\n')
			dest.close()

			#env['BK_CONFIG_FILES']='BK_CONFIG_FILES'+'files'
			#def build_config(target = None, source = None, env = None):
			#	dest = open(str(target[0]), 'w')
			#	dest.write('/* defines are added below */\n')
			#	dest.close()
			#act=env.Action(build_config, varlist=['BK_CONFIG_FILES'])
			#env.Command('config.h', '', act) # no source needed

			#def build_kdemacros(target = None, source = None, env = None):
		        #        dest = open(str(target[0]), 'w')
		        #        dest.write('#include <kdemacros.h.in>\n')
		        #        dest.close()
		        #act=env.Action(build_kdemacros, varlist=['PREFIX'])
		        #env.Command('kdemacros.h', '', act) # no source needed

	#valid_targets = "program shlib kioslave staticlib".split()
        SConsEnvironment.bksys_install = bksys_install
	SConsEnvironment.bksys_insttype = bksys_insttype
	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
	SConsEnvironment.postconfig=postconfig

	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')
Example #4
0
def generate(env):

    ## i cannot remember having added this (ITA) - can someone explain ?
    from SCons.Tool import Tool
    deft = Tool('default')
    deft.generate(env)

    ## Bksys requires scons 0.96
    env.EnsureSConsVersion(0, 96)

    ## attach functions to "env"
    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 user does not want them
    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 bksys_insttype(lenv, type, subdir, files, perms=None):
        if not lenv.has_key(type):
            lenv.pprint('RED', 'unknown file type to install ' + type)
            lenv.Exit(1)
        lenv.bksys_install(lenv.join(lenv[type], subdir),
                           files,
                           destfile=None,
                           perms=perms)

    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(LIBPATH=[f.dir])
            lenv.Append(LIBS=[f.name])

    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(lenv.join(buildto, dir), dir)

    def postconfig(lenv):
        ## TODO this block be called from a postconfig() function (move to generic.py)
        if env['_CONFIGURE']:
            env.BuildDir('build', '.', duplicate='soft-copy')
            # generate config.h
            if not os.path.exists('build'): os.mkdir('build')
            dest = open(lenv.join('build', 'config.h'), 'w')
            dest.write('/* defines are added below */\n')
            dest.write('#include "config-qt4.py"\n')
            dest.write('#include "config-xml.py"\n')
            dest.close()

            dest = open(lenv.join('build', 'kdemacros.h'), 'w')
            dest.write('#include <kdemacros.h.in>\n')
            dest.close()

            #env['BK_CONFIG_FILES']='BK_CONFIG_FILES'+'files'
            #def build_config(target = None, source = None, env = None):
            #	dest = open(str(target[0]), 'w')
            #	dest.write('/* defines are added below */\n')
            #	dest.close()
            #act=env.Action(build_config, varlist=['BK_CONFIG_FILES'])
            #env.Command('config.h', '', act) # no source needed

            #def build_kdemacros(target = None, source = None, env = None):
            #        dest = open(str(target[0]), 'w')
            #        dest.write('#include <kdemacros.h.in>\n')
            #        dest.close()
            #act=env.Action(build_kdemacros, varlist=['PREFIX'])
            #env.Command('kdemacros.h', '', act) # no source needed

    #valid_targets = "program shlib kioslave staticlib".split()
    SConsEnvironment.bksys_install = bksys_install
    SConsEnvironment.bksys_insttype = bksys_insttype
    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
    SConsEnvironment.postconfig = postconfig

    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')