xref: /nrf52832-nimble/rt-thread/tools/iar.py (revision 104654410c56c573564690304ae786df310c91fc)
1#
2# File      : iar.py
3# This file is part of RT-Thread RTOS
4# COPYRIGHT (C) 2006 - 2015, RT-Thread Development Team
5#
6#  This program is free software; you can redistribute it and/or modify
7#  it under the terms of the GNU General Public License as published by
8#  the Free Software Foundation; either version 2 of the License, or
9#  (at your option) any later version.
10#
11#  This program is distributed in the hope that it will be useful,
12#  but WITHOUT ANY WARRANTY; without even the implied warranty of
13#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14#  GNU General Public License for more details.
15#
16#  You should have received a copy of the GNU General Public License along
17#  with this program; if not, write to the Free Software Foundation, Inc.,
18#  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
19#
20# Change Logs:
21# Date           Author       Notes
22# 2015-01-20     Bernard      Add copyright information
23#
24
25import os
26import sys
27import string
28import utils
29
30import xml.etree.ElementTree as etree
31from xml.etree.ElementTree import SubElement
32from utils import _make_path_relative
33from utils import xml_indent
34
35fs_encoding = sys.getfilesystemencoding()
36
37iar_workspace = '''<?xml version="1.0" encoding="iso-8859-1"?>
38
39<workspace>
40  <project>
41    <path>$WS_DIR$\%s</path>
42  </project>
43  <batchBuild/>
44</workspace>
45
46
47'''
48
49def IARAddGroup(parent, name, files, project_path):
50    group = SubElement(parent, 'group')
51    group_name = SubElement(group, 'name')
52    group_name.text = name
53
54    for f in files:
55        fn = f.rfile()
56        name = fn.name
57        path = os.path.dirname(fn.abspath)
58        basename = os.path.basename(path)
59        path = _make_path_relative(project_path, path)
60        path = os.path.join(path, name)
61
62        file = SubElement(group, 'file')
63        file_name = SubElement(file, 'name')
64
65        if os.path.isabs(path):
66            file_name.text = path # path.decode(fs_encoding)
67        else:
68            file_name.text = '$PROJ_DIR$\\' + path # ('$PROJ_DIR$\\' + path).decode(fs_encoding)
69
70def IARWorkspace(target):
71    # make an workspace
72    workspace = target.replace('.ewp', '.eww')
73    out = open(workspace, 'w')
74    xml = iar_workspace % target
75    out.write(xml)
76    out.close()
77
78def IARProject(target, script):
79    project_path = os.path.dirname(os.path.abspath(target))
80
81    tree = etree.parse('template.ewp')
82    root = tree.getroot()
83
84    out = open(target, 'w')
85
86    CPPPATH = []
87    CPPDEFINES = []
88    LINKFLAGS = ''
89    CCFLAGS = ''
90    Libs = []
91    lib_prefix = ['lib', '']
92    lib_suffix = ['.a', '.o', '']
93
94    def searchLib(group):
95        for path_item in group['LIBPATH']:
96            for prefix_item in lib_prefix:
97                for suffix_item in lib_suffix:
98                    lib_full_path = os.path.join(path_item, prefix_item + item + suffix_item)
99                    if os.path.isfile(lib_full_path):
100                        return lib_full_path
101        else:
102            return ''
103
104    # add group
105    for group in script:
106        IARAddGroup(root, group['name'], group['src'], project_path)
107
108        # get each include path
109        if 'CPPPATH' in group and group['CPPPATH']:
110            CPPPATH += group['CPPPATH']
111
112        # get each group's definitions
113        if 'CPPDEFINES' in group and group['CPPDEFINES']:
114            CPPDEFINES += group['CPPDEFINES']
115
116        # get each group's link flags
117        if 'LINKFLAGS' in group and group['LINKFLAGS']:
118            LINKFLAGS += group['LINKFLAGS']
119
120        if 'LIBS' in group and group['LIBS']:
121            for item in group['LIBS']:
122                lib_path = searchLib(group)
123                if lib_path != '':
124                    lib_path = _make_path_relative(project_path, lib_path)
125                    Libs += [lib_path]
126                    # print('found lib isfile: ' + lib_path)
127                else:
128                    print('not found LIB: ' + item)
129
130    # make relative path
131    paths = set()
132    for path in CPPPATH:
133        inc = _make_path_relative(project_path, os.path.normpath(path))
134        paths.add(inc) #.replace('\\', '/')
135
136    # setting options
137    options = tree.findall('configuration/settings/data/option')
138    for option in options:
139        # print option.text
140        name = option.find('name')
141
142        if name.text == 'CCIncludePath2' or name.text == 'newCCIncludePaths':
143            for path in paths:
144                state = SubElement(option, 'state')
145                if os.path.isabs(path) or path.startswith('$'):
146                    state.text = path
147                else:
148                    state.text = '$PROJ_DIR$\\' + path
149
150        if name.text == 'CCDefines':
151            for define in CPPDEFINES:
152                state = SubElement(option, 'state')
153                state.text = define
154
155        if name.text == 'IlinkAdditionalLibs':
156            for path in Libs:
157                state = SubElement(option, 'state')
158                if os.path.isabs(path) or path.startswith('$'):
159                    path = path.decode(fs_encoding)
160                else:
161                    path = ('$PROJ_DIR$\\' + path).decode(fs_encoding)
162                state.text = path
163
164    xml_indent(root)
165    out.write(etree.tostring(root, encoding='utf-8').decode())
166    out.close()
167
168    IARWorkspace(target)
169
170def IARVersion():
171    import subprocess
172    import re
173
174    def IARPath():
175        import rtconfig
176
177        # backup environ
178        old_environ = os.environ
179        os.environ['RTT_CC'] = 'iar'
180        utils.ReloadModule(rtconfig)
181
182        # get iar path
183        path = rtconfig.EXEC_PATH
184
185        # restore environ
186        os.environ = old_environ
187        utils.ReloadModule(rtconfig)
188
189        return path
190
191    path = IARPath();
192
193    if os.path.exists(path):
194        cmd = os.path.join(path, 'iccarm.exe')
195    else:
196        print('Error: get IAR version failed. Please update the IAR installation path in rtconfig.py!')
197        return "0.0"
198
199    child = subprocess.Popen([cmd, '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
200    stdout, stderr = child.communicate()
201
202    # example stdout: IAR ANSI C/C++ Compiler V8.20.1.14183/W32 for ARM
203    return re.search('[\d\.]+', stdout).group(0)
204