432 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
		
		
			
		
	
	
			432 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
|  | # | ||
|  | # File      : keil.py | ||
|  | # This file is part of RT-Thread RTOS | ||
|  | # COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team | ||
|  | # | ||
|  | #  This program is free software; you can redistribute it and/or modify | ||
|  | #  it under the terms of the GNU General Public License as published by | ||
|  | #  the Free Software Foundation; either version 2 of the License, or | ||
|  | #  (at your option) any later version. | ||
|  | # | ||
|  | #  This program is distributed in the hope that it will be useful, | ||
|  | #  but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
|  | #  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | ||
|  | #  GNU General Public License for more details. | ||
|  | # | ||
|  | #  You should have received a copy of the GNU General Public License along | ||
|  | #  with this program; if not, write to the Free Software Foundation, Inc., | ||
|  | #  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
|  | # | ||
|  | # Change Logs: | ||
|  | # Date           Author       Notes | ||
|  | # 2015-01-20     Bernard      Add copyright information | ||
|  | # | ||
|  | 
 | ||
|  | 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('.cpp') != -1 or fn.rfind('.cxx') != -1: | ||
|  |         return 8 | ||
|  | 
 | ||
|  |     if fn.rfind('.c') != -1 or fn.rfind('.C') != -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 | ||
|  | 
 | ||
|  |     if fn.rfind('.lib') != -1: | ||
|  |         return 4 | ||
|  | 
 | ||
|  |     # other filetype | ||
|  |     return 5 | ||
|  | 
 | ||
|  | def MDK4AddGroupForFN(ProjectFiles, parent, name, filename, project_path): | ||
|  |     group = SubElement(parent, 'Group') | ||
|  |     group_name = SubElement(group, 'GroupName') | ||
|  |     group_name.text = name | ||
|  | 
 | ||
|  |     name = os.path.basename(filename) | ||
|  |     path = os.path.dirname (filename) | ||
|  | 
 | ||
|  |     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 name.find('.cpp') != -1: | ||
|  |         obj_name = name.replace('.cpp', '.o') | ||
|  |     elif name.find('.c') != -1: | ||
|  |         obj_name = name.replace('.c', '.o') | ||
|  |     elif name.find('.s') != -1: | ||
|  |         obj_name = name.replace('.s', '.o') | ||
|  |     elif name.find('.S') != -1: | ||
|  |         obj_name = name.replace('.s', '.o') | ||
|  |     else: | ||
|  |         obj_name = name | ||
|  | 
 | ||
|  |     if ProjectFiles.count(obj_name): | ||
|  |         name = basename + '_' + name | ||
|  |     ProjectFiles.append(obj_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 MDK4AddLibToGroup(ProjectFiles, group, name, filename, project_path): | ||
|  |     name = os.path.basename(filename) | ||
|  |     path = os.path.dirname (filename) | ||
|  | 
 | ||
|  |     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 name.find('.cpp') != -1: | ||
|  |         obj_name = name.replace('.cpp', '.o') | ||
|  |     elif name.find('.c') != -1: | ||
|  |         obj_name = name.replace('.c', '.o') | ||
|  |     elif name.find('.s') != -1: | ||
|  |         obj_name = name.replace('.s', '.o') | ||
|  |     elif name.find('.S') != -1: | ||
|  |         obj_name = name.replace('.s', '.o') | ||
|  |     else: | ||
|  |         obj_name = name | ||
|  | 
 | ||
|  |     if ProjectFiles.count(obj_name): | ||
|  |         name = basename + '_' + name | ||
|  |     ProjectFiles.append(obj_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 MDK4AddGroup(ProjectFiles, parent, name, files, project_path): | ||
|  |     # don't add an empty group | ||
|  |     if len(files) == 0: | ||
|  |         return | ||
|  | 
 | ||
|  |     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 name.find('.cpp') != -1: | ||
|  |             obj_name = name.replace('.cpp', '.o') | ||
|  |         elif name.find('.c') != -1: | ||
|  |             obj_name = name.replace('.c', '.o') | ||
|  |         elif name.find('.s') != -1: | ||
|  |             obj_name = name.replace('.s', '.o') | ||
|  |         elif name.find('.S') != -1: | ||
|  |             obj_name = name.replace('.s', '.o') | ||
|  | 
 | ||
|  |         if ProjectFiles.count(obj_name): | ||
|  |             name = basename + '_' + name | ||
|  |         ProjectFiles.append(obj_name) | ||
|  |         file_name.text = name # 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 # path.decode(fs_encoding) | ||
|  | 
 | ||
|  |     return group | ||
|  | 
 | ||
|  | # The common part of making MDK4/5 project  | ||
|  | def MDK45Project(tree, target, script): | ||
|  |     project_path = os.path.dirname(os.path.abspath(target)) | ||
|  | 
 | ||
|  |     root = tree.getroot() | ||
|  |     out = open(target, 'w') | ||
|  |     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 groups is None: | ||
|  |         groups = SubElement(tree.find('Targets/Target'), 'Groups') | ||
|  |     groups.clear() # clean old groups | ||
|  |     for group in script: | ||
|  |         group_tree = MDK4AddGroup(ProjectFiles, groups, group['name'], group['src'], project_path) | ||
|  | 
 | ||
|  |         # for local CPPPATH/CPPDEFINES | ||
|  |         if (group_tree != None) and ('LOCAL_CPPPATH' in group or 'LOCAL_CCFLAGS' in group or 'LOCAL_CPPDEFINES' in group): | ||
|  |             GroupOption     = SubElement(group_tree,  'GroupOption') | ||
|  |             GroupArmAds     = SubElement(GroupOption, 'GroupArmAds') | ||
|  |             Cads            = SubElement(GroupArmAds, 'Cads') | ||
|  |             VariousControls = SubElement(Cads, 'VariousControls') | ||
|  |             MiscControls    = SubElement(VariousControls, 'MiscControls') | ||
|  |             if 'LOCAL_CCFLAGS' in group: | ||
|  |                 MiscControls.text = group['LOCAL_CCFLAGS'] | ||
|  |             else: | ||
|  |                 MiscControls.text = ' ' | ||
|  |             Define          = SubElement(VariousControls, 'Define') | ||
|  |             if 'LOCAL_CPPDEFINES' in group: | ||
|  |                 Define.text     = ', '.join(set(group['LOCAL_CPPDEFINES'])) | ||
|  |             else: | ||
|  |                 Define.text     = ' ' | ||
|  |             Undefine        = SubElement(VariousControls, 'Undefine') | ||
|  |             Undefine.text   = ' ' | ||
|  |             IncludePath     = SubElement(VariousControls, 'IncludePath') | ||
|  |             if 'LOCAL_CPPPATH' in group: | ||
|  |                 IncludePath.text = ';'.join([_make_path_relative(project_path, os.path.normpath(i)) for i in group['LOCAL_CPPPATH']]) | ||
|  |             else: | ||
|  |                 IncludePath.text = ' ' | ||
|  | 
 | ||
|  |         # get each include path | ||
|  |         if 'CPPPATH' in group and group['CPPPATH']: | ||
|  |             if CPPPATH: | ||
|  |                 CPPPATH += group['CPPPATH'] | ||
|  |             else: | ||
|  |                 CPPPATH += group['CPPPATH'] | ||
|  | 
 | ||
|  |         # get each group's definitions | ||
|  |         if 'CPPDEFINES' in group and group['CPPDEFINES']: | ||
|  |             if CPPDEFINES: | ||
|  |                 CPPDEFINES += group['CPPDEFINES'] | ||
|  |             else: | ||
|  |                 CPPDEFINES = group['CPPDEFINES'] | ||
|  | 
 | ||
|  |         # get each group's link flags | ||
|  |         if 'LINKFLAGS' in group and group['LINKFLAGS']: | ||
|  |             if LINKFLAGS: | ||
|  |                 LINKFLAGS += ' ' + group['LINKFLAGS'] | ||
|  |             else: | ||
|  |                 LINKFLAGS += group['LINKFLAGS'] | ||
|  | 
 | ||
|  |         if 'LIBS' in group and group['LIBS']: | ||
|  |             for item in group['LIBS']: | ||
|  |                 lib_path = '' | ||
|  |                 for path_item in group['LIBPATH']: | ||
|  |                     full_path = os.path.join(path_item, item + '.lib') | ||
|  |                     if os.path.isfile(full_path): # has this library | ||
|  |                         lib_path = full_path | ||
|  | 
 | ||
|  |                 if lib_path != '': | ||
|  |                     if (group_tree != None): | ||
|  |                         MDK4AddLibToGroup(ProjectFiles, group_tree, group['name'], lib_path, project_path) | ||
|  |                     else: | ||
|  |                         MDK4AddGroupForFN(ProjectFiles, groups, group['name'], lib_path, project_path) | ||
|  | 
 | ||
|  |     # write include path, definitions and link flags | ||
|  |     IncludePath = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/VariousControls/IncludePath') | ||
|  |     IncludePath.text = ';'.join([_make_path_relative(project_path, os.path.normpath(i)) for i in CPPPATH]) | ||
|  | 
 | ||
|  |     Define = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/VariousControls/Define') | ||
|  |     Define.text = ', '.join(set(CPPDEFINES)) | ||
|  | 
 | ||
|  |     Misc = tree.find('Targets/Target/TargetOption/TargetArmAds/LDads/Misc') | ||
|  |     Misc.text = LINKFLAGS | ||
|  | 
 | ||
|  |     xml_indent(root) | ||
|  |     out.write(etree.tostring(root, encoding='utf-8').decode()) | ||
|  |     out.close() | ||
|  | 
 | ||
|  | def MDK4Project(target, script): | ||
|  |     template_tree = etree.parse('template.uvproj') | ||
|  | 
 | ||
|  |     MDK45Project(template_tree, target, script) | ||
|  | 
 | ||
|  |     # remove project.uvopt file | ||
|  |     project_uvopt = os.path.abspath(target).replace('uvproj', 'uvopt') | ||
|  |     if os.path.isfile(project_uvopt): | ||
|  |         os.unlink(project_uvopt) | ||
|  | 
 | ||
|  |     # copy uvopt file | ||
|  |     if os.path.exists('template.uvopt'): | ||
|  |         import shutil | ||
|  |         shutil.copy2('template.uvopt', 'project.uvopt') | ||
|  | 
 | ||
|  | def MDK5Project(target, script): | ||
|  | 
 | ||
|  |     template_tree = etree.parse('template.uvprojx') | ||
|  | 
 | ||
|  |     MDK45Project(template_tree, target, script) | ||
|  | 
 | ||
|  |     # remove project.uvopt file | ||
|  |     project_uvopt = os.path.abspath(target).replace('uvprojx', 'uvoptx') | ||
|  |     if os.path.isfile(project_uvopt): | ||
|  |         os.unlink(project_uvopt) | ||
|  |     # copy uvopt file | ||
|  |     if os.path.exists('template.uvoptx'): | ||
|  |         import shutil | ||
|  |         shutil.copy2('template.uvoptx', 'project.uvoptx') | ||
|  | 
 | ||
|  | def MDKProject(target, script): | ||
|  |     template = open('template.Uv2', "r") | ||
|  |     lines = template.readlines() | ||
|  | 
 | ||
|  |     project = open(target, "w") | ||
|  |     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 'CPPPATH' in group and group['CPPPATH']: | ||
|  |             if CPPPATH: | ||
|  |                 CPPPATH += group['CPPPATH'] | ||
|  |             else: | ||
|  |                 CPPPATH += group['CPPPATH'] | ||
|  | 
 | ||
|  |         # get each group's definitions | ||
|  |         if 'CPPDEFINES' in group and group['CPPDEFINES']: | ||
|  |             if CPPDEFINES: | ||
|  |                 CPPDEFINES += group['CPPDEFINES'] | ||
|  |             else: | ||
|  |                 CPPDEFINES = group['CPPDEFINES'] | ||
|  | 
 | ||
|  |         # get each group's link flags | ||
|  |         if 'LINKFLAGS' in group 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 ARMCC_Version(): | ||
|  |     import rtconfig | ||
|  |     import subprocess | ||
|  |     import re | ||
|  | 
 | ||
|  |     path = rtconfig.EXEC_PATH | ||
|  |     path = os.path.join(path, 'armcc.exe') | ||
|  | 
 | ||
|  |     if os.path.exists(path): | ||
|  |         cmd = path | ||
|  |     else: | ||
|  |         print('Error: get armcc version failed. Please update the KEIL MDK installation path in rtconfig.py!') | ||
|  |         return "0.0" | ||
|  | 
 | ||
|  |     child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) | ||
|  |     stdout, stderr = child.communicate() | ||
|  | 
 | ||
|  |     '''
 | ||
|  |     example stdout:  | ||
|  |     Product: MDK Plus 5.24 | ||
|  |     Component: ARM Compiler 5.06 update 5 (build 528) | ||
|  |     Tool: armcc [4d3621] | ||
|  | 
 | ||
|  |     return version: MDK Plus 5.24/ARM Compiler 5.06 update 5 (build 528)/armcc [4d3621] | ||
|  |     '''
 | ||
|  | 
 | ||
|  |     version_Product = re.search(r'Product: (.+)', stdout).group(1) | ||
|  |     version_Product = version_Product[:-1] | ||
|  |     version_Component = re.search(r'Component: (.*)', stdout).group(1) | ||
|  |     version_Component = version_Component[:-1] | ||
|  |     version_Tool = re.search(r'Tool: (.*)', stdout).group(1) | ||
|  |     version_Tool = version_Tool[:-1] | ||
|  |     version_str_format = '%s/%s/%s' | ||
|  |     version_str = version_str_format % (version_Product, version_Component, version_Tool) | ||
|  |     #print('version_str:' + version_str) | ||
|  |     return version_str |