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