gcc.py 6.1 KB

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