# -*- python -*- ## ## SConstruct - SCons based build-sytem for Lumiera ## # Copyright (C) Lumiera.org # 2008, Hermann Vosseler # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation; either version 2 of # the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ##################################################################### import sys sys.path.append("./admin/scons") import os from Buildhelper import * from LumieraEnvironment import * #-----------------------------------Configuration OPTIONSCACHEFILE = 'optcache' CUSTOPTIONSFILE = 'custom-options' SRCDIR = 'src' BINDIR = 'bin' TESTDIR = 'tests' ICONDIR = 'icons' VERSION = '0.1+pre.01' SVGRENDERER = 'admin/render-icon' #-----------------------------------Configuration # NOTE: scons -h for help. # Read more about the SCons build system at: http://www.scons.org # Basically, this script just /defines/ the components and how they # fit together. SCons will derive the necessary build steps. ##################################################################### def setupBasicEnvironment(): """ define cmdline options, build type decisions """ EnsurePythonVersion(2,3) EnsureSConsVersion(0,96,90) opts = defineCmdlineOptions() env = LumieraEnvironment(options=opts) env.Append ( CCCOM=' -std=gnu99') # workaround for a bug: CCCOM currently doesn't honor CFLAGS, only CCFLAGS env.Replace( VERSION=VERSION , SRCDIR=SRCDIR , BINDIR=BINDIR , ICONDIR=ICONDIR , CPPPATH=["#"+SRCDIR] # used to find includes, "#" means always absolute to build-root , CPPDEFINES=['-DLUMIERA_VERSION='+VERSION ] # note: it's a list to append further defines , CCFLAGS='-Wall ' # -fdiagnostics-show-option ) RegisterIcon_Builder(env,SVGRENDERER) RegisterPrecompiledHeader_Builder(env) handleNoBugSwitches(env) env.Append(CPPDEFINES = '_GNU_SOURCE') appendCppDefine(env,'DEBUG','DEBUG', 'NDEBUG') appendCppDefine(env,'OPENGL','USE_OPENGL') appendVal(env,'ARCHFLAGS', 'CCFLAGS') # for both C and C++ appendVal(env,'OPTIMIZE', 'CCFLAGS', val=' -O3') appendVal(env,'DEBUG', 'CCFLAGS', val=' -ggdb') prepareOptionsHelp(opts,env) opts.Save(OPTIONSCACHEFILE, env) return env def appendCppDefine(env,var,cppVar, elseVal=''): if env[var]: env.Append(CPPDEFINES = cppVar ) elif elseVal: env.Append(CPPDEFINES = elseVal) def appendVal(env,var,targetVar,val=None): if env[var]: env.Append( **{targetVar: val or env[var]}) def handleNoBugSwitches(env): """ set the build level for NoBug. Release builds imply no DEBUG wheras ALPHA and BETA require DEBUG """ level = env['BUILDLEVEL'] if level in ['ALPHA', 'BETA']: if not env['DEBUG']: print 'Warning: NoBug ALPHA or BETA builds requires DEBUG=yes, switching DEBUG on!' env.Replace( DEBUG = 1 ) env.Append(CPPDEFINES = 'EBUG_'+level) elif level == 'RELEASE': env.Replace( DEBUG = 0 ) def defineCmdlineOptions(): """ current options will be persisted in a options cache file. you may define custom options in a separate file. Commandline will override both. """ opts = Options([OPTIONSCACHEFILE, CUSTOPTIONSFILE]) opts.AddOptions( ('ARCHFLAGS', 'Set architecture-specific compilation flags (passed literally to gcc)','') ,EnumOption('BUILDLEVEL', 'NoBug build level for debugging', 'ALPHA', allowed_values=('ALPHA', 'BETA', 'RELEASE')) ,BoolOption('DEBUG', 'Build with debugging information and no optimizations', False) ,BoolOption('OPTIMIZE', 'Build with strong optimization (-O3)', False) ,BoolOption('OPENGL', 'Include support for OpenGL preview rendering', False) # ,EnumOption('DIST_TARGET', 'Build target architecture', 'auto', # allowed_values=('auto', 'i386', 'i686', 'x86_64' ), ignorecase=2) ,PathOption('DESTDIR', 'Installation dir prefix', '/usr/local') ,PathOption('SRCTAR', 'Create source tarball prior to compiling', '..', PathOption.PathAccept) ,PathOption('DOCTAR', 'Create tarball with dev documentaionl', '..', PathOption.PathAccept) ) return opts def prepareOptionsHelp(opts,env): prelude = """ USAGE: scons [-c] [OPTS] [key=val [key=val...]] [TARGETS] Build and optionally install Lumiera. Without specifying any target, just the (re)build target will run. Add -c to the commandline to clean up anything a given target would produce Special Targets: build : just compile and link testcode: additionally compile the Testsuite check : build and run the Testsuite doc : generate documetation (Doxygen) install : install created artifacts at PREFIX src.tar : create source tarball doc.tar : create developer doc tarball tar : create all tarballs Configuration Options: """ Help(prelude + opts.GenerateHelpText(env)) def configurePlatform(env): """ locate required libs. setup platform specific options. Abort build in case of failure. """ conf = env.Configure() # run all configuration checks in the given env # Perform checks for prerequisites -------------------------------------------- if not conf.TryAction('pkg-config --version > $TARGET')[0]: print 'We need pkg-config for including library configurations, exiting.' Exit(1) if not conf.CheckLibWithHeader('m', 'math.h','C'): print 'Did not find math.h / libm, exiting.' Exit(1) if not conf.CheckLibWithHeader('dl', 'dlfcn.h', 'C'): print 'Functions for runtime dynamic loading not available, exiting.' Exit(1) if not conf.CheckLibWithHeader('nobugmt', 'nobug.h', 'C'): print 'Did not find NoBug [http://www.pipapo.org/pipawiki/NoBug], exiting.' Exit(1) if not conf.CheckLibWithHeader('pthread', 'pthread.h', 'C'): print 'Did not find the pthread lib or pthread.h, exiting.' else: conf.env.Append(CPPFLAGS = ' -DHAVE_PTHREAD') conf.env.Append(CCFLAGS = ' -pthread') if conf.CheckCHeader('execinfo.h'): conf.env.Append(CPPFLAGS = ' -DHAS_EXECINFO_H') if conf.CheckCHeader('valgrind/valgrind.h'): conf.env.Append(CPPFLAGS = ' -DHAS_VALGRIND_VALGIND_H') if not conf.CheckCXXHeader('tr1/memory'): print 'We rely on the std::tr1 proposed standard extension for shared_ptr.' Exit(1) if not conf.CheckCXXHeader('boost/config.hpp'): print 'We need the C++ boost-lib.' Exit(1) else: if not conf.CheckCXXHeader('boost/shared_ptr.hpp'): print 'We need boost::shared_ptr (shared_ptr.hpp).' Exit(1) if not conf.CheckLibWithHeader('boost_program_options-mt','boost/program_options.hpp','C++'): print 'We need boost::program_options (including binary lib for linking).' Exit(1) if not conf.CheckLibWithHeader('boost_regex-mt','boost/regex.hpp','C++'): print 'We need the boost regular expression lib (incl. binary lib for linking).' Exit(1) # if not conf.CheckLibWithHeader('gavl', ['gavlconfig.h', 'gavl/gavl.h'], 'C'): if not conf.CheckPkgConfig('gavl', 1.0): print 'Did not find Gmerlin Audio Video Lib [http://gmerlin.sourceforge.net/gavl.html], exiting.' Exit(1) else: conf.env.mergeConf('gavl') if not conf.CheckPkgConfig('gtkmm-2.4', 2.8): print 'Unable to configure GTK--, exiting.' Exit(1) if not conf.CheckPkgConfig('glibmm-2.4', '2.16'): print 'Unable to configure Lib glib--, exiting.' Exit(1) if not conf.CheckPkgConfig('cairomm-1.0', 0.6): print 'Unable to configure Cairo--, exiting.' Exit(1) if not conf.CheckPkgConfig('gdl-1.0', '0.6.1'): print 'Unable to configure the GNOME DevTool Library, exiting.' Exit(1) if not conf.CheckPkgConfig('librsvg-2.0', '2.18.1'): print 'Need rsvg Library for rendering icons.' Exit(1) if not conf.CheckPkgConfig('xv'): Exit(1) # if not conf.CheckPkgConfig('xext'): Exit(1) # if not conf.CheckPkgConfig('sm'): Exit(1) # # obviously not needed? print "** Gathered Library Info: %s" % conf.env.libInfo.keys() # create new env containing the finished configuration return conf.Finish() def definePackagingTargets(env, artifacts): """ build operations and targets to be done /before/ compiling. things like creating a source tarball or preparing a version header. """ t = Tarball(env,location='$SRCTAR',dirs='$SRCDIR') artifacts['src.tar'] = t env.Alias('src.tar', t) env.Alias('tar', t) t = Tarball(env,location='$DOCTAR',suffix='-doc',dirs='admin doc wiki uml tests') artifacts['doc.tar'] = t env.Alias('doc.tar', t) env.Alias('tar', t) def defineBuildTargets(env, artifacts): """ define the source file/dirs comprising each artifact to be built. setup sub-environments with special build options if necessary. We use a custom function to declare a whole tree of srcfiles. """ objback = srcSubtree(env,'$SRCDIR/backend') objproc = srcSubtree(env,'$SRCDIR/proc') objlib = ( srcSubtree(env,'$SRCDIR/common') + srcSubtree(env,'$SRCDIR/lib') ) objplug = srcSubtree(env,'$SRCDIR/plugin', isShared=True) core = ( env.StaticLibrary('$BINDIR/lumiback.la', objback) + env.StaticLibrary('$BINDIR/lumiproc.la', objproc) + env.StaticLibrary('$BINDIR/lumi.la', objlib) ) # use PCH to speed up building # precomp = ( env.PrecompiledHeader('$SRCDIR/pre') # + env.PrecompiledHeader('$SRCDIR/pre_a') # ) # env.Depends(objproc, precomp) # env.Depends(objlib, precomp) artifacts['lumiera'] = env.Program('$BINDIR/lumiera', ['$SRCDIR/main.cpp']+ core ) artifacts['plugins'] = env.SharedLibrary('$BINDIR/lumiera-plugin', objplug) # the Lumiera GTK GUI envgtk = env.Clone().mergeConf(['gtkmm-2.4','cairomm-1.0','gdl-1.0','librsvg-2.0','xv','xext','sm']) objgui = srcSubtree(envgtk,'$SRCDIR/gui') # render and install Icons vector_icon_dir = env.subst('$ICONDIR/svg') prerendered_icon_dir = env.subst('$ICONDIR/prerendered') artifacts['icons'] = ( [env.IconRender(f) for f in scanSubtree(vector_icon_dir, ['*.svg'])] + [env.IconCopy(f) for f in scanSubtree(prerendered_icon_dir, ['*.png'])] ) artifacts['lumigui'] = ( envgtk.Program('$BINDIR/lumigui', objgui + core) + env.Install('$BINDIR', env.Glob('$SRCDIR/gui/*.rc')) + artifacts['icons'] ) # call subdir SConscript(s) for independent components SConscript(dirs=[SRCDIR+'/tool'], exports='env artifacts core') SConscript(dirs=['admin'], exports='env envgtk artifacts core') SConscript(dirs=[TESTDIR], exports='env artifacts core') def definePostBuildTargets(env, artifacts): """ define further actions after the core build (e.g. Documentaion). define alias targets to trigger the installing. """ ib = env.Alias('install-bin', '$DESTDIR/bin') il = env.Alias('install-lib', '$DESTDIR/lib') env.Alias('install', [ib, il]) build = env.Alias('build', artifacts['lumiera']+artifacts['lumigui']+artifacts['plugins']+artifacts['tools']) allbu = env.Alias('allbuild', build+artifacts['testsuite']) env.Default('build') # additional files to be cleaned when cleaning 'build' env.Clean ('build', [ 'scache.conf', '.sconf_temp', '.sconsign.dblite', 'config.log' ]) env.Clean ('build', [ '$SRCDIR/pre.gch' ]) # Doxygen documentation # Note: at the moment we only depend on Doxyfile # obviousely, we should depend on all sourcefiles # real Doxygen builder for scons is under developement for 0.97 # so for the moment I prefere not to bother doxyfile = File('doc/devel/Doxyfile') env.NoClean(doxyfile) doxydoc = artifacts['doxydoc'] = [ Dir('doc/devel/html'), Dir('doc/devel/latex') ] env.Command(doxydoc, doxyfile, "doxygen Doxyfile 2>&1 |tee ,doxylog", chdir='doc/devel') env.Clean ('doc/devel', doxydoc + ['doc/devel/,doxylog']) def defineInstallTargets(env, artifacts): """ define some artifacts to be installed into target locations. """ env.Install(dir = '$DESTDIR/bin', source=artifacts['lumiera']) env.Install(dir = '$DESTDIR/lib', source=artifacts['plugins']) env.Install(dir = '$DESTDIR/bin', source=artifacts['tools']) env.Install(dir = '$DESTDIR/share/doc/lumiera$VERSION/devel', source=artifacts['doxydoc']) ##################################################################### ### === MAIN === #################################################### env = setupBasicEnvironment() if not (isCleanupOperation(env) or isHelpRequest()): env = configurePlatform(env) artifacts = {} # the various things we build. # Each entry actually is a SCons-Node list. # Passing these entries to other builders defines dependencies. # 'lumiera' : the App # 'plugins' : plugin shared lib # 'tools' : small tool applications (e.g mpegtoc) # 'src,tar' : source tree as tarball (without doc) # 'doc.tar' : uml model, wiki, dev docu (no src) definePackagingTargets(env, artifacts) defineBuildTargets(env, artifacts) definePostBuildTargets(env, artifacts) defineInstallTargets(env, artifacts)