From 3fd6fd1f050e05369f9406ab6a94721a4ea8eb94 Mon Sep 17 00:00:00 2001
From: "bernard.xiong@gmail.com" <bernard.xiong@gmail.com>
Date: Sun, 19 Feb 2012 09:11:35 +0000
Subject: [PATCH] cleanup the building script in tools.

git-svn-id: https://rt-thread.googlecode.com/svn/trunk@1970 bbd45198-f89e-11dd-88c7-29a3b14d5316
---
 tools/building.py | 472 +++++-----------------------------------------
 tools/iar.py      | 104 ++++++++++
 tools/keil.py     | 223 ++++++++++++++++++++++
 tools/utils.py    |  81 ++++++++
 4 files changed, 460 insertions(+), 420 deletions(-)
 create mode 100644 tools/iar.py
 create mode 100644 tools/keil.py
 create mode 100644 tools/utils.py

diff --git a/tools/building.py b/tools/building.py
index e7e56c249..9bf390cba 100644
--- a/tools/building.py
+++ b/tools/building.py
@@ -2,431 +2,13 @@ import os
 import sys
 import string
 
-import xml.etree.ElementTree as etree
-from xml.etree.ElementTree import SubElement
-
 from SCons.Script import *
+from utils import _make_path_relative
 
 BuildOptions = {}
 Projects = []
 Rtt_Root = ''
 Env = None
-fs_encoding = sys.getfilesystemencoding()
-
-def _get_filetype(fn):
-    if fn.rfind('.c') != -1 or fn.rfind('.C') != -1 or fn.rfind('.cpp') != -1:
-        return 1
-
-    # assemble file type
-    if fn.rfind('.s') != -1 or fn.rfind('.S') != -1:
-        return 2
-
-    # header type
-    if fn.rfind('.h') != -1:
-        return 5
-
-    # other filetype
-    return 5
-
-def splitall(loc):
-    """
-    Return a list of the path components in loc. (Used by relpath_).
-
-    The first item in the list will be  either ``os.curdir``, ``os.pardir``, empty,
-    or the root directory of loc (for example, ``/`` or ``C:\\).
-
-    The other items in the list will be strings.
-
-    Adapted from *path.py* by Jason Orendorff.
-    """
-    parts = []
-    while loc != os.curdir and loc != os.pardir:
-        prev = loc
-        loc, child = os.path.split(prev)
-        if loc == prev:
-            break
-        parts.append(child)
-    parts.append(loc)
-    parts.reverse()
-    return parts
-
-def _make_path_relative(origin, dest):
-    """
-    Return the relative path between origin and dest.
-
-    If it's not possible return dest.
-
-
-    If they are identical return ``os.curdir``
-
-    Adapted from `path.py <http://www.jorendorff.com/articles/python/path/>`_ by Jason Orendorff.
-    """
-    origin = os.path.abspath(origin).replace('\\', '/')
-    dest = os.path.abspath(dest).replace('\\', '/')
-    #
-    orig_list = splitall(os.path.normcase(origin))
-    # Don't normcase dest!  We want to preserve the case.
-    dest_list = splitall(dest)
-    #
-    if orig_list[0] != os.path.normcase(dest_list[0]):
-        # Can't get here from there.
-        return dest
-    #
-    # Find the location where the two paths start to differ.
-    i = 0
-    for start_seg, dest_seg in zip(orig_list, dest_list):
-        if start_seg != os.path.normcase(dest_seg):
-            break
-        i += 1
-    #
-    # Now i is the point where the two paths diverge.
-    # Need a certain number of "os.pardir"s to work up
-    # from the origin to the point of divergence.
-    segments = [os.pardir] * (len(orig_list) - i)
-    # Need to add the diverging part of dest_list.
-    segments += dest_list[i:]
-    if len(segments) == 0:
-        # If they happen to be identical, use os.curdir.
-        return os.curdir
-    else:
-        # return os.path.join(*segments).replace('\\', '/')
-        return os.path.join(*segments)
-
-def xml_indent(elem, level=0):
-    i = "\n" + level*"  "
-    if len(elem):
-        if not elem.text or not elem.text.strip():
-            elem.text = i + "  "
-        if not elem.tail or not elem.tail.strip():
-            elem.tail = i
-        for elem in elem:
-            xml_indent(elem, level+1)
-        if not elem.tail or not elem.tail.strip():
-            elem.tail = i
-    else:
-        if level and (not elem.tail or not elem.tail.strip()):
-            elem.tail = i
-
-def IARAddGroup(parent, name, files, project_path):
-    group = SubElement(parent, 'group')
-    group_name = SubElement(group, 'name')
-    group_name.text = name
-    
-    for f in files:
-        fn = f.rfile()
-        name = fn.name
-        path = os.path.dirname(fn.abspath)
-    
-        basename = os.path.basename(path)
-        path = _make_path_relative(project_path, path)
-        path = os.path.join(path, name)
-        
-        file = SubElement(group, 'file')
-        file_name = SubElement(file, 'name')
-        file_name.text = ('$PROJ_DIR$\\' + path).decode(fs_encoding)
-
-iar_workspace = '''<?xml version="1.0" encoding="iso-8859-1"?>
-
-<workspace>
-  <project>
-    <path>$WS_DIR$\%s</path>
-  </project>
-  <batchBuild/>
-</workspace>
-
-
-'''
-
-def IARWorkspace(target):
-    # make an workspace 
-    workspace = target.replace('.ewp', '.eww')
-    out = file(workspace, 'wb')
-    xml = iar_workspace % target
-    out.write(xml)
-    out.close()
-    
-def IARProject(target, script):
-    project_path = os.path.dirname(os.path.abspath(target))
-
-    tree = etree.parse('template.ewp')
-    root = tree.getroot()
-
-    out = file(target, 'wb')
-
-    CPPPATH = []
-    CPPDEFINES = []
-    LINKFLAGS = ''
-    CCFLAGS = ''
-    
-    # add group
-    for group in script:
-        IARAddGroup(root, group['name'], group['src'], project_path)
-
-        # get each include path
-        if group.has_key('CPPPATH') and group['CPPPATH']:
-            CPPPATH += group['CPPPATH']
-        
-        # get each group's definitions
-        if group.has_key('CPPDEFINES') and group['CPPDEFINES']:
-            CPPDEFINES += group['CPPDEFINES']
-        
-        # get each group's link flags
-        if group.has_key('LINKFLAGS') and group['LINKFLAGS']:
-            LINKFLAGS += group['LINKFLAGS']
-    
-    # make relative path 
-    paths = set()
-    for path in CPPPATH:
-        inc = _make_path_relative(project_path, os.path.normpath(path))
-        paths.add(inc) #.replace('\\', '/')
-    
-    # setting options
-    options = tree.findall('configuration/settings/data/option')
-    for option in options:
-        # print option.text
-        name = option.find('name')
-        
-        if name.text == 'CCIncludePath2':
-            for path in paths:
-                state = SubElement(option, 'state')
-                state.text = '$PROJ_DIR$\\' + path
-        if name.text == 'CCDefines':
-            for define in CPPDEFINES:
-                state = SubElement(option, 'state')
-                state.text = define
-    
-    xml_indent(root)
-    out.write(etree.tostring(root, encoding='utf-8'))
-    out.close()
-    
-    IARWorkspace(target)
-    
-def MDK4AddGroup(ProjectFiles, parent, name, files, project_path):
-    group = SubElement(parent, 'Group')
-    group_name = SubElement(group, 'GroupName')
-    group_name.text = name
-
-    for f in files:
-        fn = f.rfile()
-        name = fn.name
-        path = os.path.dirname(fn.abspath)
-
-        basename = os.path.basename(path)
-        path = _make_path_relative(project_path, path)
-        path = os.path.join(path, name)
-        
-        files = SubElement(group, 'Files')
-        file = SubElement(files, 'File')
-        file_name = SubElement(file, 'FileName')
-        name = os.path.basename(path)
-        if ProjectFiles.count(name):
-            name = basename + '_' + name
-        ProjectFiles.append(name)
-        file_name.text = name.decode(fs_encoding)
-        file_type = SubElement(file, 'FileType')
-        file_type.text = '%d' % _get_filetype(name)
-        file_path = SubElement(file, 'FilePath')
-        
-        file_path.text = path.decode(fs_encoding)
-
-def MDK4Project(target, script):
-    project_path = os.path.dirname(os.path.abspath(target))
-    
-    tree = etree.parse('template.uvproj')
-    root = tree.getroot()
-    
-    out = file(target, 'wb')
-    out.write('<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n')
-    
-    CPPPATH = []
-    CPPDEFINES = []
-    LINKFLAGS = ''
-    CCFLAGS = ''
-    ProjectFiles = []
-    
-    # add group
-    groups = tree.find('Targets/Target/Groups')
-    if not groups:
-        groups = SubElement(tree.find('Targets/Target'), 'Groups')
-    for group in script:
-        group_xml = MDK4AddGroup(ProjectFiles, groups, group['name'], group['src'], project_path)
-        
-        # get each include path
-        if group.has_key('CPPPATH') and group['CPPPATH']:
-            if CPPPATH:
-                CPPPATH += group['CPPPATH']
-            else:
-                CPPPATH += group['CPPPATH']
-        
-        # get each group's definitions
-        if group.has_key('CPPDEFINES') and group['CPPDEFINES']:
-            if CPPDEFINES:
-                CPPDEFINES += group['CPPDEFINES']
-            else:
-                CPPDEFINES += group['CPPDEFINES']
-        
-        # get each group's link flags
-        if group.has_key('LINKFLAGS') and group['LINKFLAGS']:
-            if LINKFLAGS:
-                LINKFLAGS += ' ' + group['LINKFLAGS']
-            else:
-                LINKFLAGS += group['LINKFLAGS']
-    
-    # remove repeat path
-    paths = set()
-    for path in CPPPATH:
-        inc = _make_path_relative(project_path, os.path.normpath(path))
-        paths.add(inc) #.replace('\\', '/')
-    
-    paths = [i for i in paths]
-    paths.sort()
-    CPPPATH = string.join(paths, ';')
-    
-    definitions = [i for i in set(CPPDEFINES)]
-    CPPDEFINES = string.join(definitions, ', ')
-    
-    # write include path, definitions and link flags
-    IncludePath = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/VariousControls/IncludePath')
-    IncludePath.text = CPPPATH
-    
-    Define = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/VariousControls/Define')
-    Define.text = CPPDEFINES
-
-    Misc = tree.find('Targets/Target/TargetOption/TargetArmAds/LDads/Misc')
-    Misc.text = LINKFLAGS
-    
-    xml_indent(root)
-    out.write(etree.tostring(root, encoding='utf-8'))
-    out.close()
-    
-def MDKProject(target, script):
-    template = file('template.Uv2', "rb")
-    lines = template.readlines()
-
-    project = file(target, "wb")
-    project_path = os.path.dirname(os.path.abspath(target))
-
-    line_index = 5
-    # write group
-    for group in script:
-        lines.insert(line_index, 'Group (%s)\r\n' % group['name'])
-        line_index += 1
-
-    lines.insert(line_index, '\r\n')
-    line_index += 1
-
-    # write file
-
-    ProjectFiles = []
-    CPPPATH = []
-    CPPDEFINES = []
-    LINKFLAGS = ''
-    CCFLAGS = ''
-
-    # number of groups
-    group_index = 1
-    for group in script:
-        # print group['name']
-
-        # get each include path
-        if group.has_key('CPPPATH') and group['CPPPATH']:
-            if CPPPATH:
-                CPPPATH += group['CPPPATH']
-            else:
-                CPPPATH += group['CPPPATH']
-
-        # get each group's definitions
-        if group.has_key('CPPDEFINES') and group['CPPDEFINES']:
-            if CPPDEFINES:
-                CPPDEFINES += ';' + group['CPPDEFINES']
-            else:
-                CPPDEFINES += group['CPPDEFINES']
-
-        # get each group's link flags
-        if group.has_key('LINKFLAGS') and group['LINKFLAGS']:
-            if LINKFLAGS:
-                LINKFLAGS += ' ' + group['LINKFLAGS']
-            else:
-                LINKFLAGS += group['LINKFLAGS']
-
-        # generate file items
-        for node in group['src']:
-            fn = node.rfile()
-            name = fn.name
-            path = os.path.dirname(fn.abspath)
-            basename = os.path.basename(path)
-            path = _make_path_relative(project_path, path)
-            path = os.path.join(path, name)
-            if ProjectFiles.count(name):
-                name = basename + '_' + name
-            ProjectFiles.append(name)
-            lines.insert(line_index, 'File %d,%d,<%s><%s>\r\n'
-                % (group_index, _get_filetype(name), path, name))
-            line_index += 1
-
-        group_index = group_index + 1
-
-    lines.insert(line_index, '\r\n')
-    line_index += 1
-
-    # remove repeat path
-    paths = set()
-    for path in CPPPATH:
-        inc = _make_path_relative(project_path, os.path.normpath(path))
-        paths.add(inc) #.replace('\\', '/')
-
-    paths = [i for i in paths]
-    CPPPATH = string.join(paths, ';')
-
-    definitions = [i for i in set(CPPDEFINES)]
-    CPPDEFINES = string.join(definitions, ', ')
-
-    while line_index < len(lines):
-        if lines[line_index].startswith(' ADSCINCD '):
-            lines[line_index] = ' ADSCINCD (' + CPPPATH + ')\r\n'
-
-        if lines[line_index].startswith(' ADSLDMC ('):
-            lines[line_index] = ' ADSLDMC (' + LINKFLAGS + ')\r\n'
-
-        if lines[line_index].startswith(' ADSCDEFN ('):
-            lines[line_index] = ' ADSCDEFN (' + CPPDEFINES + ')\r\n'
-
-        line_index += 1
-
-    # write project
-    for line in lines:
-        project.write(line)
-
-    project.close()
-
-def BuilderProject(target, script):
-    project = file(target, "wb")
-    project_path = os.path.dirname(os.path.abspath(target))
-
-    # write file
-
-    CPPPATH = []
-    CPPDEFINES = []
-    LINKFLAGS = ''
-    CCFLAGS = ''
-
-    # number of groups
-    group_index = 1
-    for group in script:
-        # print group['name']
-
-        # generate file items
-        for node in group['src']:
-            fn = node.rfile()
-            name = fn.name
-            path = os.path.dirname(fn.abspath)
-            path = _make_path_relative(project_path, path)
-            path = os.path.join(path, name)
-            project.write('%s\r\n' % path)
-
-        group_index = group_index + 1
-
-    project.close()
 
 class Win32Spawn:
     def spawn(self, sh, escape, cmd, args, env):
@@ -435,7 +17,7 @@ class Win32Spawn:
         newargs = string.join(args[1:], ' ')
         cmdline = cmd + " " + newargs
         startupinfo = subprocess.STARTUPINFO()
-        startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
+        # startupinfo.dwFlags |= subprocess.STARTF_USESHOWWINDOW
         penv = {}
         for key, value in env.iteritems():
             penv[key] = str(value)
@@ -453,6 +35,29 @@ class Win32Spawn:
             return rv
         return 0
 
+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 PrepareBuilding(env, root_directory, has_libcpu=False):
     import SCons.cpp
     import rtconfig
@@ -633,6 +238,10 @@ def GetCurrentDir():
 
 def EndBuilding(target):
     import rtconfig
+    from keil import MDKProject
+    from keil import MDK4Project
+    from iar import IARProject
+
     Env.AddPostAction(target, rtconfig.POST_ACTION)
 
     if GetOption('target') == 'mdk':
@@ -662,3 +271,26 @@ def SrcRemove(src, remove):
     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)
diff --git a/tools/iar.py b/tools/iar.py
new file mode 100644
index 000000000..6f4584e85
--- /dev/null
+++ b/tools/iar.py
@@ -0,0 +1,104 @@
+import os
+import sys
+import string
+
+import xml.etree.ElementTree as etree
+from xml.etree.ElementTree import SubElement
+from utils import _make_path_relative
+from utils import xml_indent
+
+fs_encoding = sys.getfilesystemencoding()
+
+iar_workspace = '''<?xml version="1.0" encoding="iso-8859-1"?>
+
+<workspace>
+  <project>
+    <path>$WS_DIR$\%s</path>
+  </project>
+  <batchBuild/>
+</workspace>
+
+
+'''
+
+def IARAddGroup(parent, name, files, project_path):
+    group = SubElement(parent, 'group')
+    group_name = SubElement(group, 'name')
+    group_name.text = name
+    
+    for f in files:
+        fn = f.rfile()
+        name = fn.name
+        path = os.path.dirname(fn.abspath)
+    
+        basename = os.path.basename(path)
+        path = _make_path_relative(project_path, path)
+        path = os.path.join(path, name)
+        
+        file = SubElement(group, 'file')
+        file_name = SubElement(file, 'name')
+        file_name.text = ('$PROJ_DIR$\\' + path).decode(fs_encoding)
+
+def IARWorkspace(target):
+    # make an workspace 
+    workspace = target.replace('.ewp', '.eww')
+    out = file(workspace, 'wb')
+    xml = iar_workspace % target
+    out.write(xml)
+    out.close()
+    
+def IARProject(target, script):
+    project_path = os.path.dirname(os.path.abspath(target))
+
+    tree = etree.parse('template.ewp')
+    root = tree.getroot()
+
+    out = file(target, 'wb')
+
+    CPPPATH = []
+    CPPDEFINES = []
+    LINKFLAGS = ''
+    CCFLAGS = ''
+    
+    # add group
+    for group in script:
+        IARAddGroup(root, group['name'], group['src'], project_path)
+
+        # get each include path
+        if group.has_key('CPPPATH') and group['CPPPATH']:
+            CPPPATH += group['CPPPATH']
+        
+        # get each group's definitions
+        if group.has_key('CPPDEFINES') and group['CPPDEFINES']:
+            CPPDEFINES += group['CPPDEFINES']
+        
+        # get each group's link flags
+        if group.has_key('LINKFLAGS') and group['LINKFLAGS']:
+            LINKFLAGS += group['LINKFLAGS']
+    
+    # make relative path 
+    paths = set()
+    for path in CPPPATH:
+        inc = _make_path_relative(project_path, os.path.normpath(path))
+        paths.add(inc) #.replace('\\', '/')
+    
+    # setting options
+    options = tree.findall('configuration/settings/data/option')
+    for option in options:
+        # print option.text
+        name = option.find('name')
+        
+        if name.text == 'CCIncludePath2':
+            for path in paths:
+                state = SubElement(option, 'state')
+                state.text = '$PROJ_DIR$\\' + path
+        if name.text == 'CCDefines':
+            for define in CPPDEFINES:
+                state = SubElement(option, 'state')
+                state.text = define
+    
+    xml_indent(root)
+    out.write(etree.tostring(root, encoding='utf-8'))
+    out.close()
+    
+    IARWorkspace(target)
diff --git a/tools/keil.py b/tools/keil.py
new file mode 100644
index 000000000..ce55e3440
--- /dev/null
+++ b/tools/keil.py
@@ -0,0 +1,223 @@
+import os
+import sys
+import string
+
+import xml.etree.ElementTree as etree
+from xml.etree.ElementTree import SubElement
+from utils import _make_path_relative
+from utils import xml_indent
+
+fs_encoding = sys.getfilesystemencoding()
+
+def _get_filetype(fn):
+    if fn.rfind('.c') != -1 or fn.rfind('.C') != -1 or fn.rfind('.cpp') != -1:
+        return 1
+
+    # assemble file type
+    if fn.rfind('.s') != -1 or fn.rfind('.S') != -1:
+        return 2
+
+    # header type
+    if fn.rfind('.h') != -1:
+        return 5
+
+    # other filetype
+    return 5
+
+def MDK4AddGroup(ProjectFiles, parent, name, files, project_path):
+    group = SubElement(parent, 'Group')
+    group_name = SubElement(group, 'GroupName')
+    group_name.text = name
+
+    for f in files:
+        fn = f.rfile()
+        name = fn.name
+        path = os.path.dirname(fn.abspath)
+
+        basename = os.path.basename(path)
+        path = _make_path_relative(project_path, path)
+        path = os.path.join(path, name)
+        
+        files = SubElement(group, 'Files')
+        file = SubElement(files, 'File')
+        file_name = SubElement(file, 'FileName')
+        name = os.path.basename(path)
+        if ProjectFiles.count(name):
+            name = basename + '_' + name
+        ProjectFiles.append(name)
+        file_name.text = name.decode(fs_encoding)
+        file_type = SubElement(file, 'FileType')
+        file_type.text = '%d' % _get_filetype(name)
+        file_path = SubElement(file, 'FilePath')
+        
+        file_path.text = path.decode(fs_encoding)
+
+def MDK4Project(target, script):
+    project_path = os.path.dirname(os.path.abspath(target))
+    
+    tree = etree.parse('template.uvproj')
+    root = tree.getroot()
+    
+    out = file(target, 'wb')
+    out.write('<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n')
+    
+    CPPPATH = []
+    CPPDEFINES = []
+    LINKFLAGS = ''
+    CCFLAGS = ''
+    ProjectFiles = []
+    
+    # add group
+    groups = tree.find('Targets/Target/Groups')
+    if not groups:
+        groups = SubElement(tree.find('Targets/Target'), 'Groups')
+    for group in script:
+        group_xml = MDK4AddGroup(ProjectFiles, groups, group['name'], group['src'], project_path)
+        
+        # get each include path
+        if group.has_key('CPPPATH') and group['CPPPATH']:
+            if CPPPATH:
+                CPPPATH += group['CPPPATH']
+            else:
+                CPPPATH += group['CPPPATH']
+        
+        # get each group's definitions
+        if group.has_key('CPPDEFINES') and group['CPPDEFINES']:
+            if CPPDEFINES:
+                CPPDEFINES += group['CPPDEFINES']
+            else:
+                CPPDEFINES += group['CPPDEFINES']
+        
+        # get each group's link flags
+        if group.has_key('LINKFLAGS') and group['LINKFLAGS']:
+            if LINKFLAGS:
+                LINKFLAGS += ' ' + group['LINKFLAGS']
+            else:
+                LINKFLAGS += group['LINKFLAGS']
+    
+    # remove repeat path
+    paths = set()
+    for path in CPPPATH:
+        inc = _make_path_relative(project_path, os.path.normpath(path))
+        paths.add(inc) #.replace('\\', '/')
+    
+    paths = [i for i in paths]
+    paths.sort()
+    CPPPATH = string.join(paths, ';')
+    
+    definitions = [i for i in set(CPPDEFINES)]
+    CPPDEFINES = string.join(definitions, ', ')
+    
+    # write include path, definitions and link flags
+    IncludePath = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/VariousControls/IncludePath')
+    IncludePath.text = CPPPATH
+    
+    Define = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/VariousControls/Define')
+    Define.text = CPPDEFINES
+
+    Misc = tree.find('Targets/Target/TargetOption/TargetArmAds/LDads/Misc')
+    Misc.text = LINKFLAGS
+    
+    xml_indent(root)
+    out.write(etree.tostring(root, encoding='utf-8'))
+    out.close()
+    
+def MDKProject(target, script):
+    template = file('template.Uv2', "rb")
+    lines = template.readlines()
+
+    project = file(target, "wb")
+    project_path = os.path.dirname(os.path.abspath(target))
+
+    line_index = 5
+    # write group
+    for group in script:
+        lines.insert(line_index, 'Group (%s)\r\n' % group['name'])
+        line_index += 1
+
+    lines.insert(line_index, '\r\n')
+    line_index += 1
+
+    # write file
+
+    ProjectFiles = []
+    CPPPATH = []
+    CPPDEFINES = []
+    LINKFLAGS = ''
+    CCFLAGS = ''
+
+    # number of groups
+    group_index = 1
+    for group in script:
+        # print group['name']
+
+        # get each include path
+        if group.has_key('CPPPATH') and group['CPPPATH']:
+            if CPPPATH:
+                CPPPATH += group['CPPPATH']
+            else:
+                CPPPATH += group['CPPPATH']
+
+        # get each group's definitions
+        if group.has_key('CPPDEFINES') and group['CPPDEFINES']:
+            if CPPDEFINES:
+                CPPDEFINES += ';' + group['CPPDEFINES']
+            else:
+                CPPDEFINES += group['CPPDEFINES']
+
+        # get each group's link flags
+        if group.has_key('LINKFLAGS') and group['LINKFLAGS']:
+            if LINKFLAGS:
+                LINKFLAGS += ' ' + group['LINKFLAGS']
+            else:
+                LINKFLAGS += group['LINKFLAGS']
+
+        # generate file items
+        for node in group['src']:
+            fn = node.rfile()
+            name = fn.name
+            path = os.path.dirname(fn.abspath)
+            basename = os.path.basename(path)
+            path = _make_path_relative(project_path, path)
+            path = os.path.join(path, name)
+            if ProjectFiles.count(name):
+                name = basename + '_' + name
+            ProjectFiles.append(name)
+            lines.insert(line_index, 'File %d,%d,<%s><%s>\r\n'
+                % (group_index, _get_filetype(name), path, name))
+            line_index += 1
+
+        group_index = group_index + 1
+
+    lines.insert(line_index, '\r\n')
+    line_index += 1
+
+    # remove repeat path
+    paths = set()
+    for path in CPPPATH:
+        inc = _make_path_relative(project_path, os.path.normpath(path))
+        paths.add(inc) #.replace('\\', '/')
+
+    paths = [i for i in paths]
+    CPPPATH = string.join(paths, ';')
+
+    definitions = [i for i in set(CPPDEFINES)]
+    CPPDEFINES = string.join(definitions, ', ')
+
+    while line_index < len(lines):
+        if lines[line_index].startswith(' ADSCINCD '):
+            lines[line_index] = ' ADSCINCD (' + CPPPATH + ')\r\n'
+
+        if lines[line_index].startswith(' ADSLDMC ('):
+            lines[line_index] = ' ADSLDMC (' + LINKFLAGS + ')\r\n'
+
+        if lines[line_index].startswith(' ADSCDEFN ('):
+            lines[line_index] = ' ADSCDEFN (' + CPPDEFINES + ')\r\n'
+
+        line_index += 1
+
+    # write project
+    for line in lines:
+        project.write(line)
+
+    project.close()
diff --git a/tools/utils.py b/tools/utils.py
new file mode 100644
index 000000000..d1b094493
--- /dev/null
+++ b/tools/utils.py
@@ -0,0 +1,81 @@
+import sys
+import os
+
+def splitall(loc):
+    """
+    Return a list of the path components in loc. (Used by relpath_).
+
+    The first item in the list will be  either ``os.curdir``, ``os.pardir``, empty,
+    or the root directory of loc (for example, ``/`` or ``C:\\).
+
+    The other items in the list will be strings.
+
+    Adapted from *path.py* by Jason Orendorff.
+    """
+    parts = []
+    while loc != os.curdir and loc != os.pardir:
+        prev = loc
+        loc, child = os.path.split(prev)
+        if loc == prev:
+            break
+        parts.append(child)
+    parts.append(loc)
+    parts.reverse()
+    return parts
+
+def _make_path_relative(origin, dest):
+    """
+    Return the relative path between origin and dest.
+
+    If it's not possible return dest.
+
+
+    If they are identical return ``os.curdir``
+
+    Adapted from `path.py <http://www.jorendorff.com/articles/python/path/>`_ by Jason Orendorff.
+    """
+    origin = os.path.abspath(origin).replace('\\', '/')
+    dest = os.path.abspath(dest).replace('\\', '/')
+    #
+    orig_list = splitall(os.path.normcase(origin))
+    # Don't normcase dest!  We want to preserve the case.
+    dest_list = splitall(dest)
+    #
+    if orig_list[0] != os.path.normcase(dest_list[0]):
+        # Can't get here from there.
+        return dest
+    #
+    # Find the location where the two paths start to differ.
+    i = 0
+    for start_seg, dest_seg in zip(orig_list, dest_list):
+        if start_seg != os.path.normcase(dest_seg):
+            break
+        i += 1
+    #
+    # Now i is the point where the two paths diverge.
+    # Need a certain number of "os.pardir"s to work up
+    # from the origin to the point of divergence.
+    segments = [os.pardir] * (len(orig_list) - i)
+    # Need to add the diverging part of dest_list.
+    segments += dest_list[i:]
+    if len(segments) == 0:
+        # If they happen to be identical, use os.curdir.
+        return os.curdir
+    else:
+        # return os.path.join(*segments).replace('\\', '/')
+        return os.path.join(*segments)
+
+def xml_indent(elem, level=0):
+    i = "\n" + level*"  "
+    if len(elem):
+        if not elem.text or not elem.text.strip():
+            elem.text = i + "  "
+        if not elem.tail or not elem.tail.strip():
+            elem.tail = i
+        for elem in elem:
+            xml_indent(elem, level+1)
+        if not elem.tail or not elem.tail.strip():
+            elem.tail = i
+    else:
+        if level and (not elem.tail or not elem.tail.strip()):
+            elem.tail = i