rt-thread/tools/building.py
chaos.proton@gmail.com 66c5a05e62 building.py: add RegisterPreBuildingAction
One could register a callable object(normally a function) via RegisterPreBuildingAction in SConscript. It will be called when PreBuilding get invoked. PreBuilding should be called before the building procedure. It is currently used by RTGUI to generate the minimal perfect hash code when all the source files are scanned(i.e. just before building).

Maybe we should invoke PreBuilding in DoBuilding.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@2353 bbd45198-f89e-11dd-88c7-29a3b14d5316
2012-10-15 13:16:35 +00:00

515 lines
14 KiB
Python

import os
import sys
import string
from SCons.Script import *
from utils import _make_path_relative
BuildOptions = {}
Projects = []
Rtt_Root = ''
Env = None
class Win32Spawn:
def spawn(self, sh, escape, cmd, args, env):
import subprocess
newargs = string.join(args[1:], ' ')
cmdline = cmd + " " + newargs
startupinfo = subprocess.STARTUPINFO()
proc = subprocess.Popen(cmdline, stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, startupinfo=startupinfo, shell = False)
data, err = proc.communicate()
rv = proc.wait()
if data:
print data
if err:
print err
if rv:
return rv
return 0
def PrepareBuilding(env, root_directory, has_libcpu=False, remove_components = []):
import SCons.cpp
import rtconfig
global BuildOptions
global Projects
global Env
global Rtt_Root
Env = env
Rtt_Root = root_directory
# patch for win32 spawn
if env['PLATFORM'] == 'win32' and rtconfig.PLATFORM == 'gcc':
win32_spawn = Win32Spawn()
win32_spawn.env = env
env['SPAWN'] = win32_spawn.spawn
if env['PLATFORM'] == 'win32':
os.environ['PATH'] = rtconfig.EXEC_PATH + ";" + os.environ['PATH']
else:
os.environ['PATH'] = rtconfig.EXEC_PATH + ":" + os.environ['PATH']
# add program path
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
# parse rtconfig.h to get used component
PreProcessor = SCons.cpp.PreProcessor()
f = file('rtconfig.h', 'r')
contents = f.read()
f.close()
PreProcessor.process_contents(contents)
BuildOptions = PreProcessor.cpp_namespace
# add copy option
AddOption('--copy',
dest='copy',
action='store_true',
default=False,
help='copy rt-thread directory to local.')
AddOption('--copy-header',
dest='copy-header',
action='store_true',
default=False,
help='copy header of rt-thread directory to local.')
# add build library option
AddOption('--buildlib',
dest='buildlib',
type='string',
help='building library of a component')
# add target option
AddOption('--target',
dest='target',
type='string',
help='set target project: mdk')
#{target_name:(CROSS_TOOL, PLATFORM)}
tgt_dict = {'mdk':('keil', 'armcc'),
'mdk4':('keil', 'armcc'),
'iar':('iar', 'iar')}
tgt_name = GetOption('target')
if tgt_name:
SetOption('no_exec', 1)
try:
rtconfig.CROSS_TOOL, rtconfig.PLATFORM = tgt_dict[tgt_name]
except KeyError:
print 'Unknow target: %s. Avaible targets: %s' % \
(tgt_name, ', '.join(tgt_dict.keys()))
sys.exit(1)
elif (GetDepend('RT_USING_NEWLIB') == False and GetDepend('RT_USING_NOLIBC') == False) \
and rtconfig.PLATFORM == 'gcc':
AddDepend('RT_USING_MINILIBC')
#env['CCCOMSTR'] = "CC $TARGET"
#env['ASCOMSTR'] = "AS $TARGET"
#env['LINKCOMSTR'] = "Link $TARGET"
# board build script
objs = SConscript('SConscript', variant_dir='build', duplicate=0)
Repository(Rtt_Root)
# include kernel
objs.append(SConscript(Rtt_Root + '/src/SConscript', variant_dir='build/src', duplicate=0))
# include libcpu
if not has_libcpu:
objs.append(SConscript(Rtt_Root + '/libcpu/SConscript', variant_dir='build/libcpu', duplicate=0))
# include components
objs.append(SConscript(Rtt_Root + '/components/SConscript',
variant_dir='build/components',
duplicate=0,
exports='remove_components'))
return objs
def PrepareModuleBuilding(env, root_directory):
import SCons.cpp
import rtconfig
global BuildOptions
global Projects
global Env
global Rtt_Root
Env = env
Rtt_Root = root_directory
# add program path
env.PrependENVPath('PATH', rtconfig.EXEC_PATH)
def GetConfigValue(name):
assert type(name) == str, 'GetConfigValue: only string parameter is valid'
try:
return BuildOptions[name]
except:
return ''
def GetDepend(depend):
building = True
if type(depend) == type('str'):
if not BuildOptions.has_key(depend) or BuildOptions[depend] == 0:
building = False
elif BuildOptions[depend] != '':
return BuildOptions[depend]
return building
# for list type depend
for item in depend:
if item != '':
if not BuildOptions.has_key(item) or BuildOptions[item] == 0:
building = False
return building
def AddDepend(option):
BuildOptions[option] = 1
def MergeGroup(src_group, group):
src_group['src'] = src_group['src'] + group['src']
if group.has_key('CCFLAGS'):
if src_group.has_key('CCFLAGS'):
src_group['CCFLAGS'] = src_group['CCFLAGS'] + group['CCFLAGS']
else:
src_group['CCFLAGS'] = group['CCFLAGS']
if group.has_key('CPPPATH'):
if src_group.has_key('CPPPATH'):
src_group['CPPPATH'] = src_group['CPPPATH'] + group['CPPPATH']
else:
src_group['CPPPATH'] = group['CPPPATH']
if group.has_key('CPPDEFINES'):
if src_group.has_key('CPPDEFINES'):
src_group['CPPDEFINES'] = src_group['CPPDEFINES'] + group['CPPDEFINES']
else:
src_group['CPPDEFINES'] = group['CPPDEFINES']
if group.has_key('LINKFLAGS'):
if src_group.has_key('LINKFLAGS'):
src_group['LINKFLAGS'] = src_group['LINKFLAGS'] + group['LINKFLAGS']
else:
src_group['LINKFLAGS'] = group['LINKFLAGS']
if group.has_key('LIBRARY'):
if src_group['LIBRARY'].has_key('LIBRARY'):
src_group['LIBRARY'] = src_group['LIBRARY'] + group['LIBRARY']
else:
src_group['LIBRARY'] = group['LIBRARY']
def DefineGroup(name, src, depend, **parameters):
global Env
if not GetDepend(depend):
return []
group = parameters
group['name'] = name
if type(src) == type(['src1', 'str2']):
group['src'] = File(src)
else:
group['src'] = src
if group.has_key('CCFLAGS'):
Env.Append(CCFLAGS = group['CCFLAGS'])
if group.has_key('CPPPATH'):
Env.Append(CPPPATH = group['CPPPATH'])
if group.has_key('CPPDEFINES'):
Env.Append(CPPDEFINES = group['CPPDEFINES'])
if group.has_key('LINKFLAGS'):
Env.Append(LINKFLAGS = group['LINKFLAGS'])
if group.has_key('LIBS'):
Env.Append(LIBS = group['LIBS'])
if group.has_key('LIBPATH'):
Env.Append(LIBPATH = group['LIBPATH'])
objs = Env.Object(group['src'])
if group.has_key('LIBRARY'):
objs = Env.Library(name, objs)
# merge group
for g in Projects:
if g['name'] == name:
# merge to this group
MergeGroup(g, group)
return objs
# add a new group
Projects.append(group)
return objs
def GetCurrentDir():
conscript = File('SConscript')
fn = conscript.rfile()
name = fn.name
path = os.path.dirname(fn.abspath)
return path
PREBUILDING = []
def RegisterPreBuildingAction(act):
global PREBUILDING
assert callable(act), 'Could only register callable objects. %s received' % repr(act)
PREBUILDING.append(act)
def PreBuilding():
global PREBUILDING
for a in PREBUILDING:
a()
def DoBuilding(target, objects):
program = None
# check whether special buildlib option
lib_name = GetOption('buildlib')
if lib_name:
print lib_name
# build library with special component
for Group in Projects:
if Group['name'] == lib_name:
objects = Env.Object(Group['src'])
program = Env.Library(lib_name, objects)
break
else:
program = Env.Program(target, objects)
EndBuilding(target, program)
def EndBuilding(target, program = None):
import rtconfig
from keil import MDKProject
from keil import MDK4Project
from iar import IARProject
Env.AddPostAction(target, rtconfig.POST_ACTION)
if GetOption('target') == 'mdk':
template = os.path.isfile('template.Uv2')
if template:
MDKProject('project.Uv2', Projects)
else:
template = os.path.isfile('template.uvproj')
if template:
MDK4Project('project.uvproj', Projects)
else:
print 'No template project file found.'
if GetOption('target') == 'mdk4':
MDK4Project('project.uvproj', Projects)
if GetOption('target') == 'iar':
IARProject('project.ewp', Projects)
if GetOption('copy') and program != None:
MakeCopy(program)
if GetOption('copy-header') and program != None:
MakeCopyHeader(program)
def SrcRemove(src, remove):
if type(src[0]) == type('str'):
for item in src:
if os.path.basename(item) in remove:
src.remove(item)
return
for item in src:
if os.path.basename(item.rstr()) in remove:
src.remove(item)
def GetVersion():
import SCons.cpp
import string
rtdef = os.path.join(Rtt_Root, 'include', 'rtdef.h')
# parse rtdef.h to get RT-Thread version
prepcessor = SCons.cpp.PreProcessor()
f = file(rtdef, 'r')
contents = f.read()
f.close()
prepcessor.process_contents(contents)
def_ns = prepcessor.cpp_namespace
version = int(filter(lambda ch: ch in '0123456789.', def_ns['RT_VERSION']))
subversion = int(filter(lambda ch: ch in '0123456789.', def_ns['RT_SUBVERSION']))
if def_ns.has_key('RT_REVISION'):
revision = int(filter(lambda ch: ch in '0123456789.', def_ns['RT_REVISION']))
return '%d.%d.%d' % (version, subversion, revision)
return '0.%d.%d' % (version, subversion)
def GlobSubDir(sub_dir, ext_name):
import os
import glob
def glob_source(sub_dir, ext_name):
list = os.listdir(sub_dir)
src = glob.glob(os.path.join(sub_dir, ext_name))
for item in list:
full_subdir = os.path.join(sub_dir, item)
if os.path.isdir(full_subdir):
src += glob_source(full_subdir, ext_name)
return src
dst = []
src = glob_source(sub_dir, ext_name)
for item in src:
dst.append(os.path.relpath(item, sub_dir))
return dst
def do_copy_file(src, dst):
import shutil
# check source file
if not os.path.exists(src):
return
path = os.path.dirname(dst)
# mkdir if path not exist
if not os.path.exists(path):
os.makedirs(path)
shutil.copy2(src, dst)
def do_copy_folder(src_dir, dst_dir):
import shutil
# check source directory
if not os.path.exists(src_dir):
return
if os.path.exists(dst_dir):
shutil.rmtree(dst_dir)
shutil.copytree(src_dir, dst_dir)
source_ext = ["c", "h", "s", "S", "cpp", "xpm"]
source_list = []
def walk_children(child):
global source_list
global source_ext
# print child
full_path = child.rfile().abspath
file_type = full_path.rsplit('.',1)[1]
#print file_type
if file_type in source_ext:
if full_path not in source_list:
source_list.append(full_path)
children = child.all_children()
if children != []:
for item in children:
walk_children(item)
def MakeCopy(program):
global source_list
global Rtt_Root
global Env
target_path = os.path.join(Dir('#').abspath, 'rt-thread')
if Env['PLATFORM'] == 'win32':
RTT_ROOT = Rtt_Root.lower()
else:
RTT_ROOT = Rtt_Root
if target_path.startswith(RTT_ROOT):
return
for item in program:
walk_children(item)
source_list.sort()
# filte source file in RT-Thread
target_list = []
for src in source_list:
if Env['PLATFORM'] == 'win32':
src = src.lower()
if src.startswith(RTT_ROOT):
target_list.append(src)
source_list = target_list
# get source path
src_dir = []
for src in source_list:
src = src.replace(RTT_ROOT, '')
if src[0] == os.sep or src[0] == '/':
src = src[1:]
path = os.path.dirname(src)
sub_path = path.split(os.sep)
full_path = RTT_ROOT
for item in sub_path:
full_path = os.path.join(full_path, item)
if full_path not in src_dir:
src_dir.append(full_path)
for item in src_dir:
source_list.append(os.path.join(item, 'SConscript'))
for src in source_list:
dst = src.replace(RTT_ROOT, '')
if dst[0] == os.sep or dst[0] == '/':
dst = dst[1:]
print '=> ', dst
dst = os.path.join(target_path, dst)
do_copy_file(src, dst)
# copy tools directory
print "=> tools"
do_copy_folder(os.path.join(RTT_ROOT, "tools"), os.path.join(target_path, "tools"))
do_copy_file(os.path.join(RTT_ROOT, 'AUTHORS'), os.path.join(target_path, 'AUTHORS'))
do_copy_file(os.path.join(RTT_ROOT, 'COPYING'), os.path.join(target_path, 'COPYING'))
def MakeCopyHeader(program):
global source_ext
source_ext = []
source_ext = ["h", "xpm"]
global source_list
global Rtt_Root
global Env
target_path = os.path.join(Dir('#').abspath, 'rt-thread')
if Env['PLATFORM'] == 'win32':
RTT_ROOT = Rtt_Root.lower()
else:
RTT_ROOT = Rtt_Root
if target_path.startswith(RTT_ROOT):
return
for item in program:
walk_children(item)
source_list.sort()
# filte source file in RT-Thread
target_list = []
for src in source_list:
if Env['PLATFORM'] == 'win32':
src = src.lower()
if src.startswith(RTT_ROOT):
target_list.append(src)
source_list = target_list
for src in source_list:
dst = src.replace(RTT_ROOT, '')
if dst[0] == os.sep or dst[0] == '/':
dst = dst[1:]
print '=> ', dst
dst = os.path.join(target_path, dst)
do_copy_file(src, dst)
# copy tools directory
print "=> tools"
do_copy_folder(os.path.join(RTT_ROOT, "tools"), os.path.join(target_path, "tools"))
do_copy_file(os.path.join(RTT_ROOT, 'AUTHORS'), os.path.join(target_path, 'AUTHORS'))
do_copy_file(os.path.join(RTT_ROOT, 'COPYING'), os.path.join(target_path, 'COPYING'))