preprocessor.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. #
  2. # preprocessor.py
  3. #
  4. import subprocess
  5. nocache = 1
  6. verbose = 0
  7. def blab(str):
  8. if verbose:
  9. print(str)
  10. ################################################################################
  11. #
  12. # Invoke GCC to run the preprocessor and extract enabled features
  13. #
  14. preprocessor_cache = {}
  15. def run_preprocessor(env, fn=None):
  16. filename = fn or 'buildroot/share/PlatformIO/scripts/common-dependencies.h'
  17. if filename in preprocessor_cache:
  18. return preprocessor_cache[filename]
  19. # Process defines
  20. build_flags = env.get('BUILD_FLAGS')
  21. build_flags = env.ParseFlagsExtended(build_flags)
  22. cxx = search_compiler(env)
  23. cmd = ['"' + cxx + '"']
  24. # Build flags from board.json
  25. #if 'BOARD' in env:
  26. # cmd += [env.BoardConfig().get("build.extra_flags")]
  27. for s in build_flags['CPPDEFINES']:
  28. if isinstance(s, tuple):
  29. cmd += ['-D' + s[0] + '=' + str(s[1])]
  30. else:
  31. cmd += ['-D' + s]
  32. cmd += ['-D__MARLIN_DEPS__ -w -dM -E -x c++']
  33. depcmd = cmd + [ filename ]
  34. cmd = ' '.join(depcmd)
  35. blab(cmd)
  36. try:
  37. define_list = subprocess.check_output(cmd, shell=True).splitlines()
  38. except:
  39. define_list = {}
  40. preprocessor_cache[filename] = define_list
  41. return define_list
  42. ################################################################################
  43. #
  44. # Find a compiler, considering the OS
  45. #
  46. def search_compiler(env):
  47. global nocache
  48. from pathlib import Path, PurePath
  49. ENV_BUILD_PATH = Path(env['PROJECT_BUILD_DIR'], env['PIOENV'])
  50. GCC_PATH_CACHE = ENV_BUILD_PATH / ".gcc_path"
  51. gccpath = None
  52. try:
  53. gccpath = env.GetProjectOption('custom_gcc')
  54. blab("Getting compiler from env")
  55. return gccpath
  56. except:
  57. pass
  58. # Warning: The cached .gcc_path will obscure a newly-installed toolkit
  59. if not nocache and GCC_PATH_CACHE.exists():
  60. blab("Getting g++ path from cache")
  61. return GCC_PATH_CACHE.read_text()
  62. path_separator = ':'
  63. gcc_exe = '*g++'
  64. if env['PLATFORM'] == 'win32':
  65. path_separator = ';'
  66. gcc_exe += ".exe"
  67. envpath = map(Path, env['ENV']['PATH'].split(path_separator))
  68. # Search for the compiler in PATH
  69. for ppath in envpath:
  70. # Use any item in $PATH corresponding to a platformio toolchain bin folder
  71. if ppath.match(env['PROJECT_PACKAGES_DIR'] + "/**/bin"):
  72. for gpath in ppath.glob(gcc_exe):
  73. # Skip '*-elf-g++' (crosstool-NG) except for xtensa32
  74. if not gpath.stem.endswith('-elf-g++') or "xtensa32" in str(gpath):
  75. gccpath = str(gpath.resolve())
  76. break
  77. if not gccpath:
  78. for ppath in envpath:
  79. for gpath in ppath.glob(gcc_exe):
  80. # Skip macOS Clang
  81. if not (gpath == 'usr/bin/g++' and env['PLATFORM'] == 'darwin'):
  82. gccpath = str(gpath.resolve())
  83. break
  84. if not gccpath:
  85. gccpath = env.get('CXX')
  86. blab("Couldn't find a compiler! Fallback to '%s'" % gccpath)
  87. nocache = 1
  88. # Cache the g++ path to speed up the next build
  89. if not nocache and gccpath and ENV_BUILD_PATH.exists():
  90. blab("Caching g++ for current env")
  91. GCC_PATH_CACHE.write_text(gccpath)
  92. return gccpath