gcc.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  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. if exec_path == '/usr/bin':
  32. root_path = os.path.join('/usr/lib', prefix)
  33. else:
  34. root_path = os.path.join(exec_path, '..', prefix)
  35. return root_path
  36. def CheckHeader(rtconfig, filename):
  37. root = GetGCCRoot(rtconfig)
  38. fn = os.path.join(root, 'include', filename)
  39. if os.path.isfile(fn):
  40. return True
  41. # Usually the cross compiling gcc toolchain has directory as:
  42. #
  43. # bin
  44. # lib
  45. # share
  46. # arm-none-eabi
  47. # bin
  48. # include
  49. # lib
  50. # share
  51. prefix = rtconfig.PREFIX
  52. if prefix.endswith('-'):
  53. prefix = prefix[:-1]
  54. fn = os.path.join(root, prefix, 'include', filename)
  55. if os.path.isfile(fn):
  56. return True
  57. return False
  58. # GCC like means the toolchains which are compatible with GCC
  59. def GetGCCLikePLATFORM():
  60. return ['gcc', 'armclang', 'llvm-arm']
  61. def GetNewLibVersion(rtconfig):
  62. version = None
  63. root = GetGCCRoot(rtconfig)
  64. if CheckHeader(rtconfig, '_newlib_version.h'): # get version from _newlib_version.h file
  65. f = open(os.path.join(root, 'include', '_newlib_version.h'), 'r')
  66. if f:
  67. for line in f:
  68. if line.find('_NEWLIB_VERSION') != -1 and line.find('"') != -1:
  69. version = re.search(r'\"([^"]+)\"', line).groups()[0]
  70. f.close()
  71. elif CheckHeader(rtconfig, 'newlib.h'): # get version from newlib.h
  72. f = open(os.path.join(root, 'include', 'newlib.h'), 'r')
  73. if f:
  74. for line in f:
  75. if line.find('_NEWLIB_VERSION') != -1 and line.find('"') != -1:
  76. version = re.search(r'\"([^"]+)\"', line).groups()[0]
  77. f.close()
  78. return version
  79. # FIXME: there is no musl version or musl macros can be found officially
  80. def GetMuslVersion(rtconfig):
  81. version = None
  82. if 'musl' in rtconfig.PREFIX:
  83. version = 'unknown'
  84. return version
  85. def GCCResult(rtconfig, str):
  86. import subprocess
  87. result = ''
  88. def checkAndGetResult(pattern, string):
  89. if re.search(pattern, string):
  90. return re.search(pattern, string).group(0)
  91. return None
  92. gcc_cmd = os.path.join(rtconfig.EXEC_PATH, rtconfig.CC)
  93. # use temp file to get more information
  94. f = open('__tmp.c', 'w')
  95. if f:
  96. f.write(str)
  97. f.close()
  98. # '-fdirectives-only',
  99. if(platform.system() == 'Windows'):
  100. child = subprocess.Popen([gcc_cmd, '-E', '-P', '__tmp.c'], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
  101. else:
  102. child = subprocess.Popen(gcc_cmd + ' -E -P __tmp.c', stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=True)
  103. stdout, stderr = child.communicate()
  104. # print(stdout)
  105. if stderr != '' and stderr != b'':
  106. print(stderr)
  107. have_fdset = 0
  108. have_sigaction = 0
  109. have_sigevent = 0
  110. have_siginfo = 0
  111. have_sigval = 0
  112. version = None
  113. stdc = '1989'
  114. posix_thread = 0
  115. for line in stdout.split(b'\n'):
  116. line = line.decode()
  117. if re.search('fd_set', line):
  118. have_fdset = 1
  119. # check for sigal
  120. if re.search('struct[ \t]+sigaction', line):
  121. have_sigaction = 1
  122. if re.search('struct[ \t]+sigevent', line):
  123. have_sigevent = 1
  124. if re.search('siginfo_t', line):
  125. have_siginfo = 1
  126. if re.search('union[ \t]+sigval', line):
  127. have_sigval = 1
  128. if re.search('char\* version', line):
  129. version = re.search(r'\"([^"]+)\"', line).groups()[0]
  130. if re.findall('iso_c_visible = [\d]+', line):
  131. stdc = re.findall('[\d]+', line)[0]
  132. if re.findall('pthread_create', line):
  133. posix_thread = 1
  134. if have_fdset:
  135. result += '#define HAVE_FDSET 1\n'
  136. if have_sigaction:
  137. result += '#define HAVE_SIGACTION 1\n'
  138. if have_sigevent:
  139. result += '#define HAVE_SIGEVENT 1\n'
  140. if have_siginfo:
  141. result += '#define HAVE_SIGINFO 1\n'
  142. if have_sigval:
  143. result += '#define HAVE_SIGVAL 1\n'
  144. if version:
  145. result += '#define GCC_VERSION_STR "%s"\n' % version
  146. result += '#define STDC "%s"\n' % stdc
  147. if posix_thread:
  148. result += '#define LIBC_POSIX_THREADS 1\n'
  149. os.remove('__tmp.c')
  150. return result