1*10465441SEvalZero# 2*10465441SEvalZero# File : keil.py 3*10465441SEvalZero# This file is part of RT-Thread RTOS 4*10465441SEvalZero# COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team 5*10465441SEvalZero# 6*10465441SEvalZero# This program is free software; you can redistribute it and/or modify 7*10465441SEvalZero# it under the terms of the GNU General Public License as published by 8*10465441SEvalZero# the Free Software Foundation; either version 2 of the License, or 9*10465441SEvalZero# (at your option) any later version. 10*10465441SEvalZero# 11*10465441SEvalZero# This program is distributed in the hope that it will be useful, 12*10465441SEvalZero# but WITHOUT ANY WARRANTY; without even the implied warranty of 13*10465441SEvalZero# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14*10465441SEvalZero# GNU General Public License for more details. 15*10465441SEvalZero# 16*10465441SEvalZero# You should have received a copy of the GNU General Public License along 17*10465441SEvalZero# with this program; if not, write to the Free Software Foundation, Inc., 18*10465441SEvalZero# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 19*10465441SEvalZero# 20*10465441SEvalZero# Change Logs: 21*10465441SEvalZero# Date Author Notes 22*10465441SEvalZero# 2015-01-20 Bernard Add copyright information 23*10465441SEvalZero# 24*10465441SEvalZero 25*10465441SEvalZeroimport os 26*10465441SEvalZeroimport sys 27*10465441SEvalZeroimport string 28*10465441SEvalZero 29*10465441SEvalZeroimport xml.etree.ElementTree as etree 30*10465441SEvalZerofrom xml.etree.ElementTree import SubElement 31*10465441SEvalZerofrom utils import _make_path_relative 32*10465441SEvalZerofrom utils import xml_indent 33*10465441SEvalZero 34*10465441SEvalZerofs_encoding = sys.getfilesystemencoding() 35*10465441SEvalZero 36*10465441SEvalZerodef _get_filetype(fn): 37*10465441SEvalZero if fn.rfind('.cpp') != -1 or fn.rfind('.cxx') != -1: 38*10465441SEvalZero return 8 39*10465441SEvalZero 40*10465441SEvalZero if fn.rfind('.c') != -1 or fn.rfind('.C') != -1: 41*10465441SEvalZero return 1 42*10465441SEvalZero 43*10465441SEvalZero # assemble file type 44*10465441SEvalZero if fn.rfind('.s') != -1 or fn.rfind('.S') != -1: 45*10465441SEvalZero return 2 46*10465441SEvalZero 47*10465441SEvalZero # header type 48*10465441SEvalZero if fn.rfind('.h') != -1: 49*10465441SEvalZero return 5 50*10465441SEvalZero 51*10465441SEvalZero if fn.rfind('.lib') != -1: 52*10465441SEvalZero return 4 53*10465441SEvalZero 54*10465441SEvalZero # other filetype 55*10465441SEvalZero return 5 56*10465441SEvalZero 57*10465441SEvalZerodef MDK4AddGroupForFN(ProjectFiles, parent, name, filename, project_path): 58*10465441SEvalZero group = SubElement(parent, 'Group') 59*10465441SEvalZero group_name = SubElement(group, 'GroupName') 60*10465441SEvalZero group_name.text = name 61*10465441SEvalZero 62*10465441SEvalZero name = os.path.basename(filename) 63*10465441SEvalZero path = os.path.dirname (filename) 64*10465441SEvalZero 65*10465441SEvalZero basename = os.path.basename(path) 66*10465441SEvalZero path = _make_path_relative(project_path, path) 67*10465441SEvalZero path = os.path.join(path, name) 68*10465441SEvalZero files = SubElement(group, 'Files') 69*10465441SEvalZero file = SubElement(files, 'File') 70*10465441SEvalZero file_name = SubElement(file, 'FileName') 71*10465441SEvalZero name = os.path.basename(path) 72*10465441SEvalZero 73*10465441SEvalZero if name.find('.cpp') != -1: 74*10465441SEvalZero obj_name = name.replace('.cpp', '.o') 75*10465441SEvalZero elif name.find('.c') != -1: 76*10465441SEvalZero obj_name = name.replace('.c', '.o') 77*10465441SEvalZero elif name.find('.s') != -1: 78*10465441SEvalZero obj_name = name.replace('.s', '.o') 79*10465441SEvalZero elif name.find('.S') != -1: 80*10465441SEvalZero obj_name = name.replace('.s', '.o') 81*10465441SEvalZero else: 82*10465441SEvalZero obj_name = name 83*10465441SEvalZero 84*10465441SEvalZero if ProjectFiles.count(obj_name): 85*10465441SEvalZero name = basename + '_' + name 86*10465441SEvalZero ProjectFiles.append(obj_name) 87*10465441SEvalZero file_name.text = name.decode(fs_encoding) 88*10465441SEvalZero file_type = SubElement(file, 'FileType') 89*10465441SEvalZero file_type.text = '%d' % _get_filetype(name) 90*10465441SEvalZero file_path = SubElement(file, 'FilePath') 91*10465441SEvalZero 92*10465441SEvalZero file_path.text = path.decode(fs_encoding) 93*10465441SEvalZero 94*10465441SEvalZerodef MDK4AddLibToGroup(ProjectFiles, group, name, filename, project_path): 95*10465441SEvalZero name = os.path.basename(filename) 96*10465441SEvalZero path = os.path.dirname (filename) 97*10465441SEvalZero 98*10465441SEvalZero basename = os.path.basename(path) 99*10465441SEvalZero path = _make_path_relative(project_path, path) 100*10465441SEvalZero path = os.path.join(path, name) 101*10465441SEvalZero files = SubElement(group, 'Files') 102*10465441SEvalZero file = SubElement(files, 'File') 103*10465441SEvalZero file_name = SubElement(file, 'FileName') 104*10465441SEvalZero name = os.path.basename(path) 105*10465441SEvalZero 106*10465441SEvalZero if name.find('.cpp') != -1: 107*10465441SEvalZero obj_name = name.replace('.cpp', '.o') 108*10465441SEvalZero elif name.find('.c') != -1: 109*10465441SEvalZero obj_name = name.replace('.c', '.o') 110*10465441SEvalZero elif name.find('.s') != -1: 111*10465441SEvalZero obj_name = name.replace('.s', '.o') 112*10465441SEvalZero elif name.find('.S') != -1: 113*10465441SEvalZero obj_name = name.replace('.s', '.o') 114*10465441SEvalZero else: 115*10465441SEvalZero obj_name = name 116*10465441SEvalZero 117*10465441SEvalZero if ProjectFiles.count(obj_name): 118*10465441SEvalZero name = basename + '_' + name 119*10465441SEvalZero ProjectFiles.append(obj_name) 120*10465441SEvalZero file_name.text = name.decode(fs_encoding) 121*10465441SEvalZero file_type = SubElement(file, 'FileType') 122*10465441SEvalZero file_type.text = '%d' % _get_filetype(name) 123*10465441SEvalZero file_path = SubElement(file, 'FilePath') 124*10465441SEvalZero 125*10465441SEvalZero file_path.text = path.decode(fs_encoding) 126*10465441SEvalZero 127*10465441SEvalZerodef MDK4AddGroup(ProjectFiles, parent, name, files, project_path): 128*10465441SEvalZero # don't add an empty group 129*10465441SEvalZero if len(files) == 0: 130*10465441SEvalZero return 131*10465441SEvalZero 132*10465441SEvalZero group = SubElement(parent, 'Group') 133*10465441SEvalZero group_name = SubElement(group, 'GroupName') 134*10465441SEvalZero group_name.text = name 135*10465441SEvalZero 136*10465441SEvalZero for f in files: 137*10465441SEvalZero fn = f.rfile() 138*10465441SEvalZero name = fn.name 139*10465441SEvalZero path = os.path.dirname(fn.abspath) 140*10465441SEvalZero 141*10465441SEvalZero basename = os.path.basename(path) 142*10465441SEvalZero path = _make_path_relative(project_path, path) 143*10465441SEvalZero path = os.path.join(path, name) 144*10465441SEvalZero 145*10465441SEvalZero files = SubElement(group, 'Files') 146*10465441SEvalZero file = SubElement(files, 'File') 147*10465441SEvalZero file_name = SubElement(file, 'FileName') 148*10465441SEvalZero name = os.path.basename(path) 149*10465441SEvalZero 150*10465441SEvalZero if name.find('.cpp') != -1: 151*10465441SEvalZero obj_name = name.replace('.cpp', '.o') 152*10465441SEvalZero elif name.find('.c') != -1: 153*10465441SEvalZero obj_name = name.replace('.c', '.o') 154*10465441SEvalZero elif name.find('.s') != -1: 155*10465441SEvalZero obj_name = name.replace('.s', '.o') 156*10465441SEvalZero elif name.find('.S') != -1: 157*10465441SEvalZero obj_name = name.replace('.s', '.o') 158*10465441SEvalZero 159*10465441SEvalZero if ProjectFiles.count(obj_name): 160*10465441SEvalZero name = basename + '_' + name 161*10465441SEvalZero ProjectFiles.append(obj_name) 162*10465441SEvalZero file_name.text = name # name.decode(fs_encoding) 163*10465441SEvalZero file_type = SubElement(file, 'FileType') 164*10465441SEvalZero file_type.text = '%d' % _get_filetype(name) 165*10465441SEvalZero file_path = SubElement(file, 'FilePath') 166*10465441SEvalZero 167*10465441SEvalZero file_path.text = path # path.decode(fs_encoding) 168*10465441SEvalZero 169*10465441SEvalZero return group 170*10465441SEvalZero 171*10465441SEvalZero# The common part of making MDK4/5 project 172*10465441SEvalZerodef MDK45Project(tree, target, script): 173*10465441SEvalZero project_path = os.path.dirname(os.path.abspath(target)) 174*10465441SEvalZero 175*10465441SEvalZero root = tree.getroot() 176*10465441SEvalZero out = open(target, 'w') 177*10465441SEvalZero out.write('<?xml version="1.0" encoding="UTF-8" standalone="no" ?>\n') 178*10465441SEvalZero 179*10465441SEvalZero CPPPATH = [] 180*10465441SEvalZero CPPDEFINES = [] 181*10465441SEvalZero LINKFLAGS = '' 182*10465441SEvalZero CCFLAGS = '' 183*10465441SEvalZero ProjectFiles = [] 184*10465441SEvalZero 185*10465441SEvalZero # add group 186*10465441SEvalZero groups = tree.find('Targets/Target/Groups') 187*10465441SEvalZero if groups is None: 188*10465441SEvalZero groups = SubElement(tree.find('Targets/Target'), 'Groups') 189*10465441SEvalZero groups.clear() # clean old groups 190*10465441SEvalZero for group in script: 191*10465441SEvalZero group_tree = MDK4AddGroup(ProjectFiles, groups, group['name'], group['src'], project_path) 192*10465441SEvalZero 193*10465441SEvalZero # for local CPPPATH/CPPDEFINES 194*10465441SEvalZero if (group_tree != None) and ('LOCAL_CPPPATH' in group or 'LOCAL_CCFLAGS' in group or 'LOCAL_CPPDEFINES' in group): 195*10465441SEvalZero GroupOption = SubElement(group_tree, 'GroupOption') 196*10465441SEvalZero GroupArmAds = SubElement(GroupOption, 'GroupArmAds') 197*10465441SEvalZero Cads = SubElement(GroupArmAds, 'Cads') 198*10465441SEvalZero VariousControls = SubElement(Cads, 'VariousControls') 199*10465441SEvalZero MiscControls = SubElement(VariousControls, 'MiscControls') 200*10465441SEvalZero if 'LOCAL_CCFLAGS' in group: 201*10465441SEvalZero MiscControls.text = group['LOCAL_CCFLAGS'] 202*10465441SEvalZero else: 203*10465441SEvalZero MiscControls.text = ' ' 204*10465441SEvalZero Define = SubElement(VariousControls, 'Define') 205*10465441SEvalZero if 'LOCAL_CPPDEFINES' in group: 206*10465441SEvalZero Define.text = ', '.join(set(group['LOCAL_CPPDEFINES'])) 207*10465441SEvalZero else: 208*10465441SEvalZero Define.text = ' ' 209*10465441SEvalZero Undefine = SubElement(VariousControls, 'Undefine') 210*10465441SEvalZero Undefine.text = ' ' 211*10465441SEvalZero IncludePath = SubElement(VariousControls, 'IncludePath') 212*10465441SEvalZero if 'LOCAL_CPPPATH' in group: 213*10465441SEvalZero IncludePath.text = ';'.join([_make_path_relative(project_path, os.path.normpath(i)) for i in group['LOCAL_CPPPATH']]) 214*10465441SEvalZero else: 215*10465441SEvalZero IncludePath.text = ' ' 216*10465441SEvalZero 217*10465441SEvalZero # get each include path 218*10465441SEvalZero if 'CPPPATH' in group and group['CPPPATH']: 219*10465441SEvalZero if CPPPATH: 220*10465441SEvalZero CPPPATH += group['CPPPATH'] 221*10465441SEvalZero else: 222*10465441SEvalZero CPPPATH += group['CPPPATH'] 223*10465441SEvalZero 224*10465441SEvalZero # get each group's definitions 225*10465441SEvalZero if 'CPPDEFINES' in group and group['CPPDEFINES']: 226*10465441SEvalZero if CPPDEFINES: 227*10465441SEvalZero CPPDEFINES += group['CPPDEFINES'] 228*10465441SEvalZero else: 229*10465441SEvalZero CPPDEFINES = group['CPPDEFINES'] 230*10465441SEvalZero 231*10465441SEvalZero # get each group's link flags 232*10465441SEvalZero if 'LINKFLAGS' in group and group['LINKFLAGS']: 233*10465441SEvalZero if LINKFLAGS: 234*10465441SEvalZero LINKFLAGS += ' ' + group['LINKFLAGS'] 235*10465441SEvalZero else: 236*10465441SEvalZero LINKFLAGS += group['LINKFLAGS'] 237*10465441SEvalZero 238*10465441SEvalZero if 'LIBS' in group and group['LIBS']: 239*10465441SEvalZero for item in group['LIBS']: 240*10465441SEvalZero lib_path = '' 241*10465441SEvalZero for path_item in group['LIBPATH']: 242*10465441SEvalZero full_path = os.path.join(path_item, item + '.lib') 243*10465441SEvalZero if os.path.isfile(full_path): # has this library 244*10465441SEvalZero lib_path = full_path 245*10465441SEvalZero 246*10465441SEvalZero if lib_path != '': 247*10465441SEvalZero if (group_tree != None): 248*10465441SEvalZero MDK4AddLibToGroup(ProjectFiles, group_tree, group['name'], lib_path, project_path) 249*10465441SEvalZero else: 250*10465441SEvalZero MDK4AddGroupForFN(ProjectFiles, groups, group['name'], lib_path, project_path) 251*10465441SEvalZero 252*10465441SEvalZero # write include path, definitions and link flags 253*10465441SEvalZero IncludePath = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/VariousControls/IncludePath') 254*10465441SEvalZero IncludePath.text = ';'.join([_make_path_relative(project_path, os.path.normpath(i)) for i in CPPPATH]) 255*10465441SEvalZero 256*10465441SEvalZero Define = tree.find('Targets/Target/TargetOption/TargetArmAds/Cads/VariousControls/Define') 257*10465441SEvalZero Define.text = ', '.join(set(CPPDEFINES)) 258*10465441SEvalZero 259*10465441SEvalZero Misc = tree.find('Targets/Target/TargetOption/TargetArmAds/LDads/Misc') 260*10465441SEvalZero Misc.text = LINKFLAGS 261*10465441SEvalZero 262*10465441SEvalZero xml_indent(root) 263*10465441SEvalZero out.write(etree.tostring(root, encoding='utf-8').decode()) 264*10465441SEvalZero out.close() 265*10465441SEvalZero 266*10465441SEvalZerodef MDK4Project(target, script): 267*10465441SEvalZero template_tree = etree.parse('template.uvproj') 268*10465441SEvalZero 269*10465441SEvalZero MDK45Project(template_tree, target, script) 270*10465441SEvalZero 271*10465441SEvalZero # remove project.uvopt file 272*10465441SEvalZero project_uvopt = os.path.abspath(target).replace('uvproj', 'uvopt') 273*10465441SEvalZero if os.path.isfile(project_uvopt): 274*10465441SEvalZero os.unlink(project_uvopt) 275*10465441SEvalZero 276*10465441SEvalZero # copy uvopt file 277*10465441SEvalZero if os.path.exists('template.uvopt'): 278*10465441SEvalZero import shutil 279*10465441SEvalZero shutil.copy2('template.uvopt', 'project.uvopt') 280*10465441SEvalZero 281*10465441SEvalZerodef MDK5Project(target, script): 282*10465441SEvalZero 283*10465441SEvalZero template_tree = etree.parse('template.uvprojx') 284*10465441SEvalZero 285*10465441SEvalZero MDK45Project(template_tree, target, script) 286*10465441SEvalZero 287*10465441SEvalZero # remove project.uvopt file 288*10465441SEvalZero project_uvopt = os.path.abspath(target).replace('uvprojx', 'uvoptx') 289*10465441SEvalZero if os.path.isfile(project_uvopt): 290*10465441SEvalZero os.unlink(project_uvopt) 291*10465441SEvalZero # copy uvopt file 292*10465441SEvalZero if os.path.exists('template.uvoptx'): 293*10465441SEvalZero import shutil 294*10465441SEvalZero shutil.copy2('template.uvoptx', 'project.uvoptx') 295*10465441SEvalZero 296*10465441SEvalZerodef MDKProject(target, script): 297*10465441SEvalZero template = open('template.Uv2', "r") 298*10465441SEvalZero lines = template.readlines() 299*10465441SEvalZero 300*10465441SEvalZero project = open(target, "w") 301*10465441SEvalZero project_path = os.path.dirname(os.path.abspath(target)) 302*10465441SEvalZero 303*10465441SEvalZero line_index = 5 304*10465441SEvalZero # write group 305*10465441SEvalZero for group in script: 306*10465441SEvalZero lines.insert(line_index, 'Group (%s)\r\n' % group['name']) 307*10465441SEvalZero line_index += 1 308*10465441SEvalZero 309*10465441SEvalZero lines.insert(line_index, '\r\n') 310*10465441SEvalZero line_index += 1 311*10465441SEvalZero 312*10465441SEvalZero # write file 313*10465441SEvalZero 314*10465441SEvalZero ProjectFiles = [] 315*10465441SEvalZero CPPPATH = [] 316*10465441SEvalZero CPPDEFINES = [] 317*10465441SEvalZero LINKFLAGS = '' 318*10465441SEvalZero CCFLAGS = '' 319*10465441SEvalZero 320*10465441SEvalZero # number of groups 321*10465441SEvalZero group_index = 1 322*10465441SEvalZero for group in script: 323*10465441SEvalZero # print group['name'] 324*10465441SEvalZero 325*10465441SEvalZero # get each include path 326*10465441SEvalZero if 'CPPPATH' in group and group['CPPPATH']: 327*10465441SEvalZero if CPPPATH: 328*10465441SEvalZero CPPPATH += group['CPPPATH'] 329*10465441SEvalZero else: 330*10465441SEvalZero CPPPATH += group['CPPPATH'] 331*10465441SEvalZero 332*10465441SEvalZero # get each group's definitions 333*10465441SEvalZero if 'CPPDEFINES' in group and group['CPPDEFINES']: 334*10465441SEvalZero if CPPDEFINES: 335*10465441SEvalZero CPPDEFINES += group['CPPDEFINES'] 336*10465441SEvalZero else: 337*10465441SEvalZero CPPDEFINES = group['CPPDEFINES'] 338*10465441SEvalZero 339*10465441SEvalZero # get each group's link flags 340*10465441SEvalZero if 'LINKFLAGS' in group and group['LINKFLAGS']: 341*10465441SEvalZero if LINKFLAGS: 342*10465441SEvalZero LINKFLAGS += ' ' + group['LINKFLAGS'] 343*10465441SEvalZero else: 344*10465441SEvalZero LINKFLAGS += group['LINKFLAGS'] 345*10465441SEvalZero 346*10465441SEvalZero # generate file items 347*10465441SEvalZero for node in group['src']: 348*10465441SEvalZero fn = node.rfile() 349*10465441SEvalZero name = fn.name 350*10465441SEvalZero path = os.path.dirname(fn.abspath) 351*10465441SEvalZero basename = os.path.basename(path) 352*10465441SEvalZero path = _make_path_relative(project_path, path) 353*10465441SEvalZero path = os.path.join(path, name) 354*10465441SEvalZero if ProjectFiles.count(name): 355*10465441SEvalZero name = basename + '_' + name 356*10465441SEvalZero ProjectFiles.append(name) 357*10465441SEvalZero lines.insert(line_index, 'File %d,%d,<%s><%s>\r\n' 358*10465441SEvalZero % (group_index, _get_filetype(name), path, name)) 359*10465441SEvalZero line_index += 1 360*10465441SEvalZero 361*10465441SEvalZero group_index = group_index + 1 362*10465441SEvalZero 363*10465441SEvalZero lines.insert(line_index, '\r\n') 364*10465441SEvalZero line_index += 1 365*10465441SEvalZero 366*10465441SEvalZero # remove repeat path 367*10465441SEvalZero paths = set() 368*10465441SEvalZero for path in CPPPATH: 369*10465441SEvalZero inc = _make_path_relative(project_path, os.path.normpath(path)) 370*10465441SEvalZero paths.add(inc) #.replace('\\', '/') 371*10465441SEvalZero 372*10465441SEvalZero paths = [i for i in paths] 373*10465441SEvalZero CPPPATH = string.join(paths, ';') 374*10465441SEvalZero 375*10465441SEvalZero definitions = [i for i in set(CPPDEFINES)] 376*10465441SEvalZero CPPDEFINES = string.join(definitions, ', ') 377*10465441SEvalZero 378*10465441SEvalZero while line_index < len(lines): 379*10465441SEvalZero if lines[line_index].startswith(' ADSCINCD '): 380*10465441SEvalZero lines[line_index] = ' ADSCINCD (' + CPPPATH + ')\r\n' 381*10465441SEvalZero 382*10465441SEvalZero if lines[line_index].startswith(' ADSLDMC ('): 383*10465441SEvalZero lines[line_index] = ' ADSLDMC (' + LINKFLAGS + ')\r\n' 384*10465441SEvalZero 385*10465441SEvalZero if lines[line_index].startswith(' ADSCDEFN ('): 386*10465441SEvalZero lines[line_index] = ' ADSCDEFN (' + CPPDEFINES + ')\r\n' 387*10465441SEvalZero 388*10465441SEvalZero line_index += 1 389*10465441SEvalZero 390*10465441SEvalZero # write project 391*10465441SEvalZero for line in lines: 392*10465441SEvalZero project.write(line) 393*10465441SEvalZero 394*10465441SEvalZero project.close() 395*10465441SEvalZero 396*10465441SEvalZerodef ARMCC_Version(): 397*10465441SEvalZero import rtconfig 398*10465441SEvalZero import subprocess 399*10465441SEvalZero import re 400*10465441SEvalZero 401*10465441SEvalZero path = rtconfig.EXEC_PATH 402*10465441SEvalZero path = os.path.join(path, 'armcc.exe') 403*10465441SEvalZero 404*10465441SEvalZero if os.path.exists(path): 405*10465441SEvalZero cmd = path 406*10465441SEvalZero else: 407*10465441SEvalZero print('Error: get armcc version failed. Please update the KEIL MDK installation path in rtconfig.py!') 408*10465441SEvalZero return "0.0" 409*10465441SEvalZero 410*10465441SEvalZero child = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True) 411*10465441SEvalZero stdout, stderr = child.communicate() 412*10465441SEvalZero 413*10465441SEvalZero ''' 414*10465441SEvalZero example stdout: 415*10465441SEvalZero Product: MDK Plus 5.24 416*10465441SEvalZero Component: ARM Compiler 5.06 update 5 (build 528) 417*10465441SEvalZero Tool: armcc [4d3621] 418*10465441SEvalZero 419*10465441SEvalZero return version: MDK Plus 5.24/ARM Compiler 5.06 update 5 (build 528)/armcc [4d3621] 420*10465441SEvalZero ''' 421*10465441SEvalZero 422*10465441SEvalZero version_Product = re.search(r'Product: (.+)', stdout).group(1) 423*10465441SEvalZero version_Product = version_Product[:-1] 424*10465441SEvalZero version_Component = re.search(r'Component: (.*)', stdout).group(1) 425*10465441SEvalZero version_Component = version_Component[:-1] 426*10465441SEvalZero version_Tool = re.search(r'Tool: (.*)', stdout).group(1) 427*10465441SEvalZero version_Tool = version_Tool[:-1] 428*10465441SEvalZero version_str_format = '%s/%s/%s' 429*10465441SEvalZero version_str = version_str_format % (version_Product, version_Component, version_Tool) 430*10465441SEvalZero #print('version_str:' + version_str) 431*10465441SEvalZero return version_str 432