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