xref: /nrf52832-nimble/rt-thread/tools/gcc.py (revision 104654410c56c573564690304ae786df310c91fc)
1#
2# File      : gcc.py
3# This file is part of RT-Thread RTOS
4# COPYRIGHT (C) 2006 - 2018, 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# 2018-05-22     Bernard      The first version
23
24import os
25import re
26import platform
27
28def GetGCCRoot(rtconfig):
29    exec_path = rtconfig.EXEC_PATH
30    prefix = rtconfig.PREFIX
31
32    if prefix.endswith('-'):
33        prefix = prefix[:-1]
34
35    root_path = os.path.join(exec_path, '..', prefix)
36
37    return root_path
38
39def CheckHeader(rtconfig, filename):
40    root = GetGCCRoot(rtconfig)
41
42    fn = os.path.join(root, 'include', filename)
43    if os.path.isfile(fn):
44        return True
45
46    return False
47
48def GetNewLibVersion(rtconfig):
49    version = 'unknown'
50    root = GetGCCRoot(rtconfig)
51
52    if CheckHeader(rtconfig, '_newlib_version.h'): # get version from _newlib_version.h file
53        f = open(os.path.join(root, 'include', '_newlib_version.h'), 'r')
54        if f:
55            for line in f:
56                if line.find('_NEWLIB_VERSION') != -1 and line.find('"') != -1:
57                    version = re.search(r'\"([^"]+)\"', line).groups()[0]
58            f.close()
59    elif CheckHeader(rtconfig, 'newlib.h'): # get version from newlib.h
60        f = open(os.path.join(root, 'include', 'newlib.h'), 'r')
61        if f:
62            for line in f:
63                if line.find('_NEWLIB_VERSION') != -1 and line.find('"') != -1:
64                    version = re.search(r'\"([^"]+)\"', line).groups()[0]
65            f.close()
66    return version
67
68def GCCResult(rtconfig, str):
69    import subprocess
70
71    result = ''
72
73    def checkAndGetResult(pattern, string):
74        if re.search(pattern, string):
75            return re.search(pattern, string).group(0)
76        return None
77
78    gcc_cmd = os.path.join(rtconfig.EXEC_PATH, rtconfig.CC)
79
80    # use temp file to get more information
81    f = open('__tmp.c', 'w')
82    if f:
83        f.write(str)
84        f.close()
85
86        # '-fdirectives-only',
87        if(platform.system() == 'Windows'):
88            child = subprocess.Popen([gcc_cmd, '-E', '-P', '__tmp.c'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
89        else:
90            child = subprocess.Popen(gcc_cmd + ' -E -P __tmp.c', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
91
92        stdout, stderr = child.communicate()
93
94        # print(stdout)
95        if stderr != '':
96            print(stderr)
97
98        have_fdset = 0
99        have_sigaction = 0
100        have_sigevent = 0
101        have_siginfo = 0
102        have_sigval = 0
103        version = None
104        stdc = '1989'
105        posix_thread = 0
106
107        for line in stdout.split(b'\n'):
108            line = line.decode()
109            if re.search('fd_set', line):
110                have_fdset = 1
111
112            # check for sigal
113            if re.search('struct[ \t]+sigaction', line):
114                have_sigaction = 1
115            if re.search('struct[ \t]+sigevent', line):
116                have_sigevent = 1
117            if re.search('siginfo_t', line):
118                have_siginfo = 1
119            if re.search('union[ \t]+sigval', line):
120                have_sigval = 1
121
122            if re.search('char\* version', line):
123                version = re.search(r'\"([^"]+)\"', line).groups()[0]
124
125            if re.findall('iso_c_visible = [\d]+', line):
126                stdc = re.findall('[\d]+', line)[0]
127
128            if re.findall('pthread_create', line):
129                posix_thread = 1
130
131        if have_fdset:
132            result += '#define HAVE_FDSET 1\n'
133
134        if have_sigaction:
135            result += '#define HAVE_SIGACTION 1\n'
136        if have_sigevent:
137            result += '#define HAVE_SIGEVENT 1\n'
138        if have_siginfo:
139            result += '#define HAVE_SIGINFO 1\n'
140        if have_sigval:
141            result += '#define HAVE_SIGVAL 1\n'
142
143        if version:
144            result += '#define GCC_VERSION "%s"\n' % version
145
146        result += '#define STDC "%s"\n' % stdc
147
148        if posix_thread:
149            result += '#define LIBC_POSIX_THREADS 1\n'
150
151        os.remove('__tmp.c')
152    return result
153
154def GenerateGCCConfig(rtconfig):
155    str = ''
156    cc_header = ''
157    cc_header += '#ifndef CCONFIG_H__\n'
158    cc_header += '#define CCONFIG_H__\n'
159    cc_header += '/* Automatically generated file; DO NOT EDIT. */\n'
160    cc_header += '/* compiler configure file for RT-Thread in GCC*/\n\n'
161
162    if CheckHeader(rtconfig, 'newlib.h'):
163        str += '#include <newlib.h>\n'
164        cc_header += '#define HAVE_NEWLIB_H 1\n'
165        cc_header += '#define LIBC_VERSION "newlib %s"\n\n' % GetNewLibVersion(rtconfig)
166
167    if CheckHeader(rtconfig, 'sys/signal.h'):
168        str += '#include <sys/signal.h>\n'
169        cc_header += '#define HAVE_SYS_SIGNAL_H 1\n'
170    if CheckHeader(rtconfig, 'sys/select.h'):
171        str += '#include <sys/select.h>\n'
172        cc_header += '#define HAVE_SYS_SELECT_H 1\n'
173    if CheckHeader(rtconfig, 'pthread.h'):
174        str += "#include <pthread.h>\n"
175        cc_header += '#define HAVE_PTHREAD_H 1\n'
176
177    # if CheckHeader(rtconfig, 'sys/dirent.h'):
178    #    str += '#include <sys/dirent.h>\n'
179
180    # add some common features
181    str += 'const char* version = __VERSION__;\n'
182    str += 'const int iso_c_visible = __ISO_C_VISIBLE;\n'
183    str += '\n#ifdef HAVE_INITFINI_ARRAY\n'
184    str += 'const int init_fini_array = HAVE_INITFINI_ARRAY;\n'
185    str += '#endif\n'
186
187    cc_header += '\n'
188    cc_header += GCCResult(rtconfig, str)
189    cc_header += '\n#endif\n'
190
191    cc_file = open('cconfig.h', 'w')
192    if cc_file:
193        cc_file.write(cc_header)
194        cc_file.close()
195