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