xref: /nrf52832-nimble/rt-thread/tools/keil.py (revision 104654410c56c573564690304ae786df310c91fc)
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