| import os.path | |
| from . import common as _common | |
| from . import gcc as _gcc | |
| _normpath = _gcc._normpath | |
| TOOL = 'clang' | |
| META_FILES = { | |
| '<built-in>', | |
| '<command line>', | |
| } | |
| def preprocess(filename, | |
| incldirs=None, | |
| includes=None, | |
| macros=None, | |
| samefiles=None, | |
| cwd=None, | |
| ): | |
| if not cwd or not os.path.isabs(cwd): | |
| cwd = os.path.abspath(cwd or '.') | |
| filename = _normpath(filename, cwd) | |
| postargs = _gcc.POST_ARGS | |
| basename = os.path.basename(filename) | |
| dirname = os.path.basename(os.path.dirname(filename)) | |
| if (basename not in _gcc.FILES_WITHOUT_INTERNAL_CAPI | |
| and dirname not in _gcc.DIRS_WITHOUT_INTERNAL_CAPI): | |
| postargs += ('-DPy_BUILD_CORE=1',) | |
| text = _common.preprocess( | |
| TOOL, | |
| filename, | |
| incldirs=incldirs, | |
| includes=includes, | |
| macros=macros, | |
| #preargs=PRE_ARGS, | |
| postargs=postargs, | |
| executable=['clang'], | |
| compiler='unix', | |
| cwd=cwd, | |
| ) | |
| return _iter_lines(text, filename, samefiles, cwd) | |
| EXIT_MARKERS = {'# 2 "<built-in>" 2', '# 3 "<built-in>" 2', '# 4 "<built-in>" 2'} | |
| def _iter_lines(text, reqfile, samefiles, cwd, raw=False): | |
| lines = iter(text.splitlines()) | |
| # The first line is special. | |
| # The subsequent lines are consistent. | |
| firstlines = [ | |
| f'# 1 "{reqfile}"', | |
| '# 1 "<built-in>" 1', | |
| '# 1 "<built-in>" 3', | |
| '# 370 "<built-in>" 3', | |
| '# 1 "<command line>" 1', | |
| '# 1 "<built-in>" 2', | |
| ] | |
| for expected in firstlines: | |
| line = next(lines) | |
| if line != expected: | |
| raise NotImplementedError((line, expected)) | |
| # Do all the CLI-provided includes. | |
| filter_reqfile = (lambda f: _gcc._filter_reqfile(f, reqfile, samefiles)) | |
| make_info = (lambda lno: _common.FileInfo(reqfile, lno)) | |
| last = None | |
| for line in lines: | |
| assert last != reqfile, (last,) | |
| # NOTE:condition is clang specific | |
| if not line: | |
| continue | |
| lno, included, flags = _gcc._parse_marker_line(line, reqfile) | |
| if not included: | |
| raise NotImplementedError((line,)) | |
| if included == reqfile: | |
| # This will be the last one. | |
| assert 2 in flags, (line, flags) | |
| else: | |
| # NOTE:first condition is specific to clang | |
| if _normpath(included, cwd) == reqfile: | |
| assert 1 in flags or 2 in flags, (line, flags, included, reqfile) | |
| else: | |
| assert 1 in flags, (line, flags, included, reqfile) | |
| yield from _gcc._iter_top_include_lines( | |
| lines, | |
| _normpath(included, cwd), | |
| cwd, | |
| filter_reqfile, | |
| make_info, | |
| raw, | |
| EXIT_MARKERS | |
| ) | |
| last = included | |
| # The last one is always the requested file. | |
| # NOTE:_normpath is clang specific | |
| assert _normpath(included, cwd) == reqfile, (line,) |