Hello,

I've promised some time ago to show my SCons based build system

Here it is:


There is BuildJob.py module in Env directory which holds the main functionality

I'm attaching also the main SConstruct and SConscript file and minua/SConscript


The main advantage over WengoScons

1) It is 3-4 times faster
2) It avoid copying of the source files into the build directory
3) There is component system where you can declare a component
and specify what you need to include and/or link in order to use the component and later you simply saye that your module uses the component all link and include flags
   will bes set automatically
4) IMO it is much easier to understand


Vadim




from Env import BuildJob
import sys


opts = Options('version.py')
opts.AddOptions(
        BoolOption('video', "Enable Video Support", False),
        BoolOption('ssl', "Enable SSL support",  True),
        BoolOption('httptunnel', "Enable HTTP tunneling support", False),
        BoolOption('netlib',  "Enable netlib module support", False),
        BoolOption('phapi_embed',  'Compile PHPAPI for embedded environment', 
True),
        BoolOption('phapi_video_hack', "enable VIDEO HACK", False),
        BoolOption('shared_phapi', "Compile PHAPI as shared library", False),
        BoolOption('vcproj',  "Build .vcproj files for use with debugger", 
False),
        BoolOption('libsamplerate', "Enable usage of libsamplerate", False),
        BoolOption('phapi_audio_arts', "Build PortAudio/arts support",  False),
        BoolOption('phapi_audio_esd', "Build PortAudio/esd support",  False),
        BoolOption('portaudio_oss', "Build PortAudio/OSS",  False),
        BoolOption('portaudio_dsound', "Build PortAudio/DirectSound support",  
False),
    BoolOption('speex', "Build speex codec",  True),
        BoolOption('speexwb_replaces_amrwb', "if set replace negotiated AMR-WB 
payload by SPEEX WB", False),
        BoolOption('speexwb_replaces_amrnb', "if set replace negotiated AMR-NB 
payload by SPEEX WB", False),
        BoolOption('speexwb_replaces_g726wb', "if set replace negotiated G726wb 
payload by SPEEX WB", False),
        BoolOption('ipp', "Enable usage of INTEL IPP Library", False),
        BoolOption('amr', "Enable usage of AMR codec", False),
        BoolOption('debug', "Enable debug build", True),
        BoolOption('qos_debug', "Enable QoS debugging functionality", False),
        BoolOption('enable_alsa', "Disable ALSA driver", False),
        ('target_os', "Target platform", sys.platform),
        ('VERONA_VERSION', "Software version", "0.0.2")
        )

BJ = BuildJob.BuildJobInfo(opts)
Export("BJ")


env = BJ.NewEnv()
if env["shared_phapi"]:
   BJ.sharedtarget = True

#Duplicate = 0 is very important: it tells SCons
#to not duplicate the source code inside the build directory;
#without this it cannot work.
TARNAME='Verona-' + env['VERONA_VERSION'] + '.tar.gz'
x=env.Command(TARNAME,'',"tar cvfz " + TARNAME + " ../verona --exclude='debug' 
--exclude=*.sconsign --exclude=*.bak --exclude=*.dblite --exclude=*.gz 
--exclude=*.hg")
env.Alias('dist',[x])


print "VERONA Building in ", BJ.buildpath

env.SConscript('SConscript', build_dir = BJ.buildpath,  duplicate = 0)

Import("BJ")

lib_projects = [
        #       'Env/libs/boost',
                'Env/libs/sdl',
                'libs/portaudio',
                'libs/timer',
                'libs/openssl',
                'libs/curl',
                'libs/util',
                'libs/ffmpeg',
                'libs/pixertool',
                'libs/webcam',

]


if BJ.msvc:
                phapi_optimization_flags = [
                        '/Ox',
                        '/Ob2',
                        '/Oi',
                        '/Ot',
                        '/Oy',
                        '/G7',
                        '/GX-',
                        '/GR-' ,
                        '/arch:SSE'
                ]
else:
        phapi_optimization_flags = [ '-O6' ]



BJ.phapi_optimization_flags = phapi_optimization_flags


#SConscript(dirs = lib_projects)

env = BJ.NewEnv()

#print "SConscript Compiling with", env.subst('$CC')

projects = []

if env["video"]:
   print "With Video" 

   projects += [ 
        'libs/ffmpeg',
        'libs/util',
        'libs/timer',
        'libs/pixertool',
        'libs/webcam',
         ]
else:
   print "No Video"


projects += [
        'libs/openssl',
        'libs/portaudio', 
        'libs/curl',
        'httptunnel',
        'libosip2',
        'ortp',
        'eXosip',
        'phapi/stun',
        'phapi/gsm',
        'phapi/ilbc',
        env["speex"] and 'phapi/speex',
        'phapi',
        'miniua'
        ]

projects1 = [
         ]


print "Verona SConscript"
SConscript(dirs = [ x for x in projects if x != False])
Import("BJ")

print "Building minua"

env = BJ.NewEnv()

if BJ.armlinuxTarget:
   defines = { }
else:
   defines = { 'PHAPI_DLL' : 1}


libs = [
        'phapi'
]

lib_path = []
includes = ['../phapi']
headers = []
sources = [ 'miniua.c' ]

link_flags = []
cc_flags = []

if BJ.osxTarget:
   link_flags = [
        '-framework CoreAudio',
        '-framework AudioToolbox',
        '-framework AudioUnit',
        '-framework Cocoa',
        '-framework Quicktime',
]


if BJ.linuxTarget:
   libs += ["z", "veronacurl", "portaudio"]

   env.ParseConfig('pkg-config alsa --cflags --libs')

   if env["video"]:
       env.ParseConfig('sdl-config --cflags --libs')

if BJ.armlinuxTarget:
   libs += ["z", "veronacurl","asound"]
#   libs += ["z", "veronacurl", "portaudio", "asound"]

   

   if env["video"]:
       env.ParseConfig('sdl-config --cflags --libs')



if BJ.win32Target:
        defines['WIN32'] = 1
        link_flags += ['/subsystem:console']

        if env["video"]:
                sdlpath = "C:/SDL-1.2.9"
                sdllibpath = sdlpath + "/VisualC"
                env.Append(CPPPATH = [ sdlpath + "/include"],   
                                LIBPATH = [ sdllibpath + "/SDL/Debug/", 
sdllibpath + "/SDLMain/Debug/" ],  
                                LIBS = ["sdl.lib", "sdlmain.lib"])

if env["video"]:
   defines["ENABLE_VIDEO"] = 1
   libs += ["pixertool"]



env.Append(CCFLAGS = cc_flags, LINKFLAGS = link_flags, CPPDEFINES = defines, 
CPPPATH = includes)
print 'CCFLAGS', env['CCFLAGS']

print "BJ.Use(env, libs)"
BJ.Use(env, libs)



m = env.Program('miniua', sources)
import sets, os, time, sys
from SCons.Environment import Environment

Set = sets.Set

class CompInfo:

    def __init__(self, name, includes = [], libpathes = [], libs = [] , uses = [], node = None):
        self.name = name
        self.includes = sets.ImmutableSet(includes)
        self.libpathes = sets.ImmutableSet(libpathes)
        self.libs = sets.ImmutableSet(libs)
        self.depends = uses
        self.node = node
        

    def use(self, env):
        """ add to the given environement information needed to use this moduel"""

        dict = env.Dictionary()
        
        def evar(k):
            if dict.has_key(k):
                return dict[k]

            return []


            
        env.AppendUnique(LIBPATH = list(self.libpathes))
        env.AppendUnique(CPPPATH = list(self.includes))
        env.AppendUnique(LIBS = list(self.libs))
            
        # print "Preparing for:", self.name, " libs=", self.libs 
        for m in self.depends:
            m.use(env)


        

class BuildJobInfo:

    
    def __init__(self, opts):


          env = Environment(options = opts)
          env.Help(opts.GenerateHelpText(env))

          self.env = env
          self.debug = env["debug"]
          self.targetos = env["target_os"]

          if "CC" in os.environ.keys():
              self.cc = os.environ['CC']
          else:
              self.cc = env["CC"]
              
          if "CFLAGS" in os.environ.keys():
              self.cf = os.environ['CFLAGS']
          else:
              self.cf = []
          
#          print "self CFLAGS is ", self.cf
          
          self.armlinuxTarget = "arm-linux" in self.cc
          
          if not self.armlinuxTarget:
             self.linuxTarget = "linux" in self.targetos
          else:   
             self.linuxTarget = 0
             
          self.win32Target = self.targetos == "win32"
          self.posixTarget = self.targetos in [ "linux", "osx" ]
          self.osxTarget =  self.targetos == "osx"
          self.bsdTarget = "BSD" in self.targetos
          
          self.msvc = self.cc == "cl"
          self.gcc =  ("gcc" in self.cc) or ("mingw" in self.cc) 
          self.mingw =  "mingw" in self.cc
          self.components = { }
          self.opts = opts
          
          if self.armlinuxTarget:
               self.buildpath = "armlinux"
          elif self.mingw:
              self.buildpath = "mingw"
          elif self.win32Target:
              self.buildpath = "win32"
          elif self.osxTarget:
              self.buildpath = "osx"
          elif self.linuxTarget:
               self.buildpath = "linux"



          if self.debug:
              self.buildpath += "/debug"
          else:
              self.buildpath += "/release"
          

          self.sharedtarget = False


    def Component(self, name, includes = [], libpath = [], libs = [], uses = [], node = None): 
          if self.components.has_key(name):
              return self.components[name]

          def compinfo(x):
              if isinstance(x, CompInfo):
                  return x
              
              if not x in self.components.keys():
                  self.components[x] = CompInfo(x, libs = [ x ])
                  
              return self.components[x]

          if uses and len(uses):
              newuses = [ compinfo(x) for x in uses ]
          else:
              newuses = []

          if node:
              self.env.Alias(name, node)

          if node:
              if len(libpath) == 0:
                  libpath = [node[0].dir]
              if len(libs) == 0:
                  libs = [name]
                  
          m = CompInfo(name, includes, libpath, libs, newuses, node)
          self.components[name] = m
          if node:
              self.env.Alias(name, node)

          return m


    def CompNode(self, name):
        return self.components[name].node
    
    
    def Use(self, env,  uses, USEDEBUG=False):

          dict = env.Dictionary()
          def showprep(msg):
              l = []
              for k in ["CPPPATH", "LIBPATH", "LIBS"]:
                  v = ""
                  if dict.has_key(k):
                      v = dict[k]
                  l += [(k,v)]    
              print msg, l

          #showprep("Before preparing")
          usedComponents = [ self.components[x] for x in ( Set(uses) & Set(self.components.keys())) ]
          for m in usedComponents:
              m.use(env)

          stdlibs = Set(uses) - Set(self.components.keys()) 
          env.AppendUnique(LIBS = list(stdlibs))
          
          
          #showprep("After preparing")




    def NewEnv(self):
    	  env = Environment(options = self.opts)
    	  env['CC'] = self.cc
          if self.armlinuxTarget:
              env.Append( CCFLAGS = self.cf )
              
          if self.win32Target:
              # print "preparing for Win32" 
              env['CC']=self.cc
              env.Append( CPPDEFINES = { 'WIN32' : 1, '_WIN32' : 1 } )
          if self.msvc:
              debug = ""
              if self.debug:
                  debug = "d"
                  env.AppendUnique(LINKFLAGS = [ "/DEBUG", "/MAP", "/NODEFAULTLIB:LIBC.LIB" ])
              env.AppendUnique(SHCCFLAGS = "/MD" + debug, SHCXXFLAGS = "/MD" + debug)
              
          return env  


    def Autoconf(self, env, moduleName, outputFiles,
                       configureCommand = './configure', makeCommand = 'make',
                       configureFiles = 'configure', makeFiles = 'Makefile',
                       uses = None, includes = None, libpath = None, libs = None):
        """
        Build a library using autotools: configure and make.
        
        Algorithm:
        - Launch the configure command
        - Launch the make command
        - Declare the library as an internal library
        
        @type libraryName string
        @param libraryName name of the library to compile
        @type outputFiles stringlist
        @param outputFiles list of awaited files (.a, .so, .dll, .dylib...)
        @type configureCommand string
        @param configureCommand command line for 'configure' (e.g './configure --enable-gtk --disable-blahblah')
        @type makeCommand string
        @param makeCommand command line for 'make' (e.g 'make blahblah')
        @type configureFiles string
        @param configureFiles files needed by configure (e.g the configure script 'configure' is needed by configure)
        @type makeFiles string
        @param makeFiles files needed by male (e.g the file 'Makefile' is needed by make)
        """

        
        bldDir = env.Dir(".").path

        makefile = env.Command(makeFiles, configureFiles,
					'cd ' + bldDir + ' && ' + configureCommand)
        make = env.Command(outputFiles, makeFiles,
					'cd ' + bldDir + ' && ' + makeCommand)

        env.Depends(make, makefile)
        #self.Component(moduleName, includes, libpath, libs, uses)
        env.Alias(moduleName, [make])
        


    def Plugin(self, env, target, source, **kw):
        lib = None
        try:
           #SCons 0.96.91 support (pre-release for 0.97)
           tmp = env['LDMODULEPREFIX']
           #Removes the library name prefix
           env['LDMODULEPREFIX'] = ''
           lib = env.LoadableModule(target, source, **kw)
           env['LDMODULEPREFIX'] = tmp
        except KeyError:
           #SCons 0.96.1 support (stable version)
           tmp = env['SHLIBPREFIX']
           #Removes the library name prefix
           env['SHLIBPREFIX'] = ''
           lib = env.SharedLibrary(target, source, **kw)
           env['SHLIBPREFIX'] = tmp
        
        return lib
    
      
    def Library(self, env, target, source = None, uses = [], includes = [], libpath = [], libs = [],  sharedtarget = None, **kw):

        if sharedtarget == None:
            sharedtarget = self.sharedtarget


        self.Use(env, uses)
        env.AppendUnique( **kw )
        if sharedtarget:
            obj = env.SharedObject( source = source)
        else:
            obj = env.StaticObject( source = source)
            

        lib = env.StaticLibrary( target, obj )
        self.Component(target, includes = includes, libpath = libpath, libs = libs, uses = uses, node = lib)

        return lib


    def SharedLibrary(self, env, target, source,  uses = [], includes = [], libpath = [], libs = [],  **kw):

        self.Use(env, uses)
        env.AppendUnique( **kw )
        lib = env.SharedLibrary( target, source = source )
        self.Component(target, includes = includes, libpath = libpath, libs = libs, uses = uses, node = lib)

        return lib
    
_______________________________________________
Wengophone-devel mailing list
[email protected]
http://dev.openwengo.com/mailman/listinfo/wengophone-devel

Reply via email to