xref: /nrf52832-nimble/rt-thread/tools/utils.py (revision 104654410c56c573564690304ae786df310c91fc)
1#
2# File      : utils.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 sys
26import os
27
28def splitall(loc):
29    """
30    Return a list of the path components in loc. (Used by relpath_).
31
32    The first item in the list will be  either ``os.curdir``, ``os.pardir``, empty,
33    or the root directory of loc (for example, ``/`` or ``C:\\).
34
35    The other items in the list will be strings.
36
37    Adapted from *path.py* by Jason Orendorff.
38    """
39    parts = []
40    while loc != os.curdir and loc != os.pardir:
41        prev = loc
42        loc, child = os.path.split(prev)
43        if loc == prev:
44            break
45        parts.append(child)
46    parts.append(loc)
47    parts.reverse()
48    return parts
49
50def _make_path_relative(origin, dest):
51    """
52    Return the relative path between origin and dest.
53
54    If it's not possible return dest.
55
56
57    If they are identical return ``os.curdir``
58
59    Adapted from `path.py <http://www.jorendorff.com/articles/python/path/>`_ by Jason Orendorff.
60    """
61    origin = os.path.abspath(origin).replace('\\', '/')
62    dest = os.path.abspath(dest).replace('\\', '/')
63    #
64    orig_list = splitall(os.path.normcase(origin))
65    # Don't normcase dest!  We want to preserve the case.
66    dest_list = splitall(dest)
67    #
68    if orig_list[0] != os.path.normcase(dest_list[0]):
69        # Can't get here from there.
70        return dest
71    #
72    # Find the location where the two paths start to differ.
73    i = 0
74    for start_seg, dest_seg in zip(orig_list, dest_list):
75        if start_seg != os.path.normcase(dest_seg):
76            break
77        i += 1
78    #
79    # Now i is the point where the two paths diverge.
80    # Need a certain number of "os.pardir"s to work up
81    # from the origin to the point of divergence.
82    segments = [os.pardir] * (len(orig_list) - i)
83    # Need to add the diverging part of dest_list.
84    segments += dest_list[i:]
85    if len(segments) == 0:
86        # If they happen to be identical, use os.curdir.
87        return os.curdir
88    else:
89        # return os.path.join(*segments).replace('\\', '/')
90        return os.path.join(*segments)
91
92def xml_indent(elem, level=0):
93    i = "\n" + level*"  "
94    if len(elem):
95        if not elem.text or not elem.text.strip():
96            elem.text = i + "  "
97        if not elem.tail or not elem.tail.strip():
98            elem.tail = i
99        for elem in elem:
100            xml_indent(elem, level+1)
101        if not elem.tail or not elem.tail.strip():
102            elem.tail = i
103    else:
104        if level and (not elem.tail or not elem.tail.strip()):
105            elem.tail = i
106
107
108source_ext = ["c", "h", "s", "S", "cpp", "xpm"]
109source_list = []
110
111def walk_children(child):
112    global source_list
113    global source_ext
114
115    # print child
116    full_path = child.rfile().abspath
117    file_type_list  = full_path.rsplit('.',1)
118    #print file_type
119    if (len(file_type_list) > 1):
120        file_type = full_path.rsplit('.',1)[1]
121
122        if file_type in source_ext:
123            if full_path not in source_list:
124                source_list.append(full_path)
125
126    children = child.all_children()
127    if children != []:
128        for item in children:
129            walk_children(item)
130
131def PrefixPath(prefix, path):
132    path = os.path.abspath(path)
133    prefix = os.path.abspath(prefix)
134
135    if sys.platform == 'win32':
136        prefix = prefix.lower()
137        path = path.lower()
138
139    if path.startswith(prefix):
140        return True
141
142    return False
143
144def ListMap(l):
145    ret_list = []
146    for item in l:
147        if type(item) == type(()):
148            ret = ListMap(item)
149            ret_list += ret
150        elif type(item) == type([]):
151            ret = ListMap(item)
152            ret_list += ret
153        else:
154            ret_list.append(item)
155
156    return ret_list
157
158def TargetGetList(env, postfix):
159    global source_ext
160    global source_list
161
162    target = env['target']
163
164    source_ext = postfix
165    for item in target:
166        walk_children(item)
167
168    source_list.sort()
169
170    return source_list
171
172def ProjectInfo(env):
173
174    project  = env['project']
175    RTT_ROOT = env['RTT_ROOT']
176    BSP_ROOT = env['BSP_ROOT']
177
178    FILES       = []
179    DIRS        = []
180    HEADERS     = []
181    CPPPATH     = []
182    CPPDEFINES  = []
183
184    for group in project:
185        # get each files
186        if 'src' in group and group['src']:
187            FILES += group['src']
188
189        # get each include path
190        if 'CPPPATH' in group and group['CPPPATH']:
191            CPPPATH += group['CPPPATH']
192
193    if 'CPPDEFINES' in env:
194        CPPDEFINES = env['CPPDEFINES']
195        CPPDEFINES = ListMap(CPPDEFINES)
196
197    # process FILES and DIRS
198    if len(FILES):
199        # use absolute path
200        for i in range(len(FILES)):
201            FILES[i] = os.path.abspath(str(FILES[i]))
202            DIRS.append(os.path.dirname(FILES[i]))
203
204        FILES.sort()
205        DIRS = list(set(DIRS))
206        DIRS.sort()
207
208    # process HEADERS
209    HEADERS = TargetGetList(env, ['h'])
210
211    # process CPPPATH
212    if len(CPPPATH):
213        # use absolute path
214        for i in range(len(CPPPATH)):
215            CPPPATH[i] = os.path.abspath(CPPPATH[i])
216
217        # remove repeat path
218        paths = [i for i in set(CPPPATH)]
219        CPPPATH = []
220        for path in paths:
221            if PrefixPath(RTT_ROOT, path):
222                CPPPATH += [os.path.abspath(path).replace('\\', '/')]
223
224            elif PrefixPath(BSP_ROOT, path):
225                CPPPATH += [os.path.abspath(path).replace('\\', '/')]
226
227            else:
228                CPPPATH += ['"%s",' % path.replace('\\', '/')]
229
230        CPPPATH.sort()
231
232    # process CPPDEFINES
233    if len(CPPDEFINES):
234        CPPDEFINES = [i for i in set(CPPDEFINES)]
235
236        CPPDEFINES.sort()
237
238    proj = {}
239    proj['FILES']       = FILES
240    proj['DIRS']        = DIRS
241    proj['HEADERS']     = HEADERS
242    proj['CPPPATH']     = CPPPATH
243    proj['CPPDEFINES']  = CPPDEFINES
244
245    return proj
246
247def VersionCmp(ver1, ver2):
248    la=[];
249    if ver1:
250        la = ver1.split('.')
251    lb = ver2.split('.')
252    f = 0
253    if len(la) > len(lb):
254        f = len(la)
255    else:
256        f = len(lb)
257    for i in range(f):
258        try:
259            if int(la[i]) > int(lb[i]):
260                return 1
261            elif int(la[i]) == int(lb[i]):
262                continue
263            else:
264                return -1
265        except IndexError as e:
266            if len(la) > len(lb):
267                return 1
268            else:
269                return -1
270    return 0
271
272def GCCC99Patch(cflags):
273    import building
274    gcc_version = building.GetDepend('GCC_VERSION')
275    if gcc_version:
276        gcc_version = gcc_version.replace('"', '')
277    if VersionCmp(gcc_version, "4.8.0"):
278        # remove -std=c99 after GCC 4.8.x
279        cflags = cflags.replace('-std=c99', '')
280
281    return cflags
282
283def ReloadModule(module):
284    import sys
285    if sys.version_info.major >= 3:
286        import importlib
287        importlib.reload(module)
288    else:
289        reload(module)
290
291    return
292