Change the way in which the CML2 configuration is handled to separate it out from the build.

This commit is contained in:
Russel Winder
2009-08-01 12:40:45 +01:00
parent 238e05fd5d
commit ce8d060d21

View File

@@ -22,54 +22,110 @@ import os
includeDirectory = 'include'
toolsDirectory = 'tools'
cml2ToolsDirectory = toolsDirectory + '/cml2-tools'
buildDirectory = 'build'
environment = Environment ( )
cml2CompileRulesFile = buildDirectory + '/cml2Rules.out'
cml2ConfigPropertiesFile = buildDirectory + '/cml2Config.out'
cml2ConfigHeaderFile = buildDirectory + '/cml2Config.h'
configuration = Configure ( environment , config_h = 'config.h' )
environment = configuration.Finish ( )
# The choice of which parts of the kernel to compile and include in the build depends on the configuration
# which is managed using CML2. CML2 uses a base configuration file (currently #configs/arm.cml) to drive
# an interaction with the user which results in a trio of files that specify the user choice.
#
# cml2RulesFile is the pickled version of the source configuration driver.
#
# cml2Config.out is a properties type representation of the user selected configuration data.
#
# cml2Config.h is a C include file representation of the user selected configuration data derived from
# cml2Config.out, it is essential for the compilation of the C code of the kernel and the tasks.
#
# Since the DAG for building the kernel relies on the information from the configuration split the build
# into two distinct phases as Autotools and Waf do, configure then build. Achieve this by partitioning the
# SCons DAG building in two depending on the command line.
arch = 'arm'
platform = 'pb926'
if 'configure' in COMMAND_LINE_TARGETS :
linkerScript = includeDirectory + '/l4/arch/' + arch + '/mylinks.lds'
def performCML2Configuration ( target , source , env ) :
if not os.path.isdir ( buildDirectory ) : os.mkdir ( buildDirectory )
os.system ( cml2ToolsDirectory + '/cmlcompile.py -o ' + cml2CompileRulesFile + ' ' + source[0].path )
os.system ( cml2ToolsDirectory + '/cmlconfigure.py -c -o ' + cml2ConfigPropertiesFile + ' ' + cml2CompileRulesFile )
os.system ( toolsDirectory + '/cml2header.py -o ' + cml2ConfigHeaderFile + ' -i ' + cml2ConfigPropertiesFile )
libraryEnvironment = environment.Clone (
CC = 'arm-none-linux-gnueabi-gcc',
CCFLAGS = [ '-g' , '-nostdinc' , '-nostdlib' , '-ffreestanding' ] ,
LINKFLAGS = [ '-nostdlib' ] ,
ENV = { 'PATH' : os.environ['PATH'] } ,
LIBS = 'gcc' ,
ARCH = arch ,
PLATFORM = platform )
if len ( COMMAND_LINE_TARGETS ) != 1 :
print '#### Warning####: configure is part of the command line, all the other targets are being ignored as this is a configure step.'
Command ( 'configure' , [ '#configs/arm.cml' ] , performCML2Configuration )
Clean ( 'configure' , buildDirectory )
libs = { }
crts = { }
for variant in [ 'baremetal' , 'userspace' ] :
( libs[variant] , crts[variant] ) = SConscript ( 'libs/c/SConscript' , variant_dir = buildDirectory + '/lib/c/' + variant , duplicate = 0 , exports = { 'environment' : libraryEnvironment , 'variant' : variant } )
else :
libelf = SConscript ( 'libs/elf/SConscript' , variant_dir = buildDirectory + '/lib/elf' , duplicate = 0 , exports = { 'environment' : libraryEnvironment , 'lib' : libs['baremetal'] } )
if not os.path.exists ( cml2ConfigPropertiesFile ) :
print "####\n#### Configuration has not been undertaken, please run 'scons configure'.\n####"
Exit ( )
cmlCompiledRules = Command ( '#' + buildDirectory + '/rules.out' , '#configs/' + arch + '.cml' , cml2ToolsDirectory + '/cmlcompile.py -o $TARGET $SOURCE' )
cmlConfiguredRules = Command ( '#' + buildDirectory + '/config.out' , cmlCompiledRules , cml2ToolsDirectory + '/cmlconfigure.py -c -o $TARGET $SOURCE' )
cmlConfigHeader = Command ( '#' + buildDirectory + '/config.h' , cmlConfiguredRules , toolsDirectory + '/cml2header.py -o $TARGET -i $SOURCE' )
def processCML2Config ( ) :
configItems = { }
with file ( cml2ConfigPropertiesFile ) as configFile :
for line in configFile :
item = line.split ( '=' )
if len ( item ) == 2 :
configItems[item[0].strip ( )] = ( item[1].strip ( ) == 'y' )
return configItems
baseEnvironment = Environment ( tools = [ 'gnulink' , 'gcc' , 'gas' , 'ar' ] )
Alias ( 'configure' , cmlConfigHeader )
if 'configure' in COMMAND_LINE_TARGETS:
AlwaysBuild ( cmlConfiguredRules )
configuration = Configure ( baseEnvironment , config_h = 'config.h' )
configData = processCML2Config ( )
arch = None
platform = None
subarch = None
for key , value in configData.items ( ) :
if value :
items = key.split ( '_' )
if items[0] == 'ARCH' : arch = items[1].lower ( )
for key , value in configData.items ( ) :
if value :
items = key.split ( '_' )
if items[0] == arch.upper ( ) :
if items[1] == 'PLATFORM' : platform = items[2].lower ( )
if items[1] == 'SUBARCH' : subarch = items[2].lower ( )
if items[0] == 'DRIVER' :
pass
configuration.Define ( '__ARCH__' , arch )
configuration.Define ( '__PLATFORM__' , platform )
configuration.Define ( '__SUBARCH__' , subarch )
baseEnvironment = configuration.Finish ( )
kernelEnvironment = environment.Clone (
CC = 'arm-none-eabi-gcc' ,
# We don't use -nostdinc because sometimes we need standard headers, such as stdarg.h e.g. for variable
# args, as in printk().
CCFLAGS = [ '-g' , '-mcpu=arm926ej-s' , '-nostdlib' , '-ffreestanding' , '-std=gnu99' , '-Wall' , '-Werror' ] ,
LINKFLAGS = [ '-nostdlib' , '-T' + linkerScript ] ,
ASFLAGS = [ '-D__ASSEMBLY__' ] ,
PROGSUFFIX = '.axf' ,
ENV = { 'PATH' : os.environ['PATH'] } ,
LIBS = 'gcc' , # libgcc.a is required for the division routines.
CPPPATH = includeDirectory ,
CPPFLAGS = [ '-include l4/config.h' , '-include l4/macros.h' , '-include l4/types.h' , '-D__KERNEL__' ] )
linkerScript = includeDirectory + '/l4/arch/' + arch + '/mylinks.lds'
Clean ( '.' , [ buildDirectory ] )
libraryEnvironment = baseEnvironment.Clone (
CC = 'arm-none-linux-gnueabi-gcc',
CCFLAGS = [ '-g' , '-nostdinc' , '-nostdlib' , '-ffreestanding' ] ,
LINKFLAGS = [ '-nostdlib' ] ,
ENV = { 'PATH' : os.environ['PATH'] } ,
LIBS = 'gcc' ,
ARCH = arch ,
PLATFORM = platform )
libs = { }
crts = { }
for variant in [ 'baremetal' , 'userspace' ] :
( libs[variant] , crts[variant] ) = SConscript ( 'libs/c/SConscript' , variant_dir = buildDirectory + '/lib/c/' + variant , duplicate = 0 , exports = { 'environment' : libraryEnvironment , 'variant' : variant } )
libelf = SConscript ( 'libs/elf/SConscript' , variant_dir = buildDirectory + '/lib/elf' , duplicate = 0 , exports = { 'environment' : libraryEnvironment } )
kernelEnvironment = baseEnvironment.Clone (
CC = 'arm-none-eabi-gcc' ,
# We don't use -nostdinc because sometimes we need standard headers, such as stdarg.h e.g. for variable
# args, as in printk().
CCFLAGS = [ '-g' , '-mcpu=arm926ej-s' , '-nostdlib' , '-ffreestanding' , '-std=gnu99' , '-Wall' , '-Werror' ] ,
LINKFLAGS = [ '-nostdlib' , '-T' + linkerScript ] ,
ASFLAGS = [ '-D__ASSEMBLY__' ] ,
PROGSUFFIX = '.axf' ,
ENV = { 'PATH' : os.environ['PATH'] } ,
LIBS = 'gcc' , # libgcc.a is required for the division routines.
CPPPATH = includeDirectory ,
CPPFLAGS = [ '-include config.h' , '-include #' + buildDirectory + '/cml2Config.h' , '-include l4/macros.h' , '-include l4/types.h' , '-D__KERNEL__' ] )
Default ( crts.values ( ) + libs.values ( ) + [ libelf ] )
Clean ( '.' , [ buildDirectory ] )