|
28 | 28 | _PYTHON_BUILD as python_build,
|
29 | 29 | _init_posix as sysconfig_init_posix,
|
30 | 30 | parse_config_h as sysconfig_parse_config_h,
|
31 |
| - _parse_makefile as sysconfig_parse_makefile, |
32 | 31 |
|
33 | 32 | _init_non_posix,
|
34 | 33 | _is_python_source_dir,
|
@@ -68,14 +67,118 @@ def parse_config_h(fp, g=None):
|
68 | 67 | return sysconfig_parse_config_h(fp, vars=g)
|
69 | 68 |
|
70 | 69 |
|
71 |
| -def parse_makefile(fn, g=None): |
72 |
| - return sysconfig_parse_makefile(fn, vars=g, keep_unresolved=False) |
73 |
| - |
74 | 70 | _python_build = partial(is_python_build, check_home=True)
|
75 | 71 | _init_posix = partial(sysconfig_init_posix, _config_vars)
|
76 | 72 | _init_nt = partial(_init_non_posix, _config_vars)
|
77 | 73 |
|
78 | 74 |
|
| 75 | +# Similar function is also implemented in sysconfig as _parse_makefile |
| 76 | +# but without the parsing capabilities of distutils.text_file.TextFile. |
| 77 | +def parse_makefile(fn, g=None): |
| 78 | + """Parse a Makefile-style file. |
| 79 | + A dictionary containing name/value pairs is returned. If an |
| 80 | + optional dictionary is passed in as the second argument, it is |
| 81 | + used instead of a new dictionary. |
| 82 | + """ |
| 83 | + from distutils.text_file import TextFile |
| 84 | + fp = TextFile(fn, strip_comments=1, skip_blanks=1, join_lines=1, errors="surrogateescape") |
| 85 | + |
| 86 | + if g is None: |
| 87 | + g = {} |
| 88 | + done = {} |
| 89 | + notdone = {} |
| 90 | + |
| 91 | + while True: |
| 92 | + line = fp.readline() |
| 93 | + if line is None: # eof |
| 94 | + break |
| 95 | + m = re.match(_variable_rx, line) |
| 96 | + if m: |
| 97 | + n, v = m.group(1, 2) |
| 98 | + v = v.strip() |
| 99 | + # `$$' is a literal `$' in make |
| 100 | + tmpv = v.replace('$$', '') |
| 101 | + |
| 102 | + if "$" in tmpv: |
| 103 | + notdone[n] = v |
| 104 | + else: |
| 105 | + try: |
| 106 | + v = int(v) |
| 107 | + except ValueError: |
| 108 | + # insert literal `$' |
| 109 | + done[n] = v.replace('$$', '$') |
| 110 | + else: |
| 111 | + done[n] = v |
| 112 | + |
| 113 | + # Variables with a 'PY_' prefix in the makefile. These need to |
| 114 | + # be made available without that prefix through sysconfig. |
| 115 | + # Special care is needed to ensure that variable expansion works, even |
| 116 | + # if the expansion uses the name without a prefix. |
| 117 | + renamed_variables = ('CFLAGS', 'LDFLAGS', 'CPPFLAGS') |
| 118 | + |
| 119 | + # do variable interpolation here |
| 120 | + while notdone: |
| 121 | + for name in list(notdone): |
| 122 | + value = notdone[name] |
| 123 | + m = re.search(_findvar1_rx, value) or re.search(_findvar2_rx, value) |
| 124 | + if m: |
| 125 | + n = m.group(1) |
| 126 | + found = True |
| 127 | + if n in done: |
| 128 | + item = str(done[n]) |
| 129 | + elif n in notdone: |
| 130 | + # get it on a subsequent round |
| 131 | + found = False |
| 132 | + elif n in os.environ: |
| 133 | + # do it like make: fall back to environment |
| 134 | + item = os.environ[n] |
| 135 | + |
| 136 | + elif n in renamed_variables: |
| 137 | + if name.startswith('PY_') and name[3:] in renamed_variables: |
| 138 | + item = "" |
| 139 | + |
| 140 | + elif 'PY_' + n in notdone: |
| 141 | + found = False |
| 142 | + |
| 143 | + else: |
| 144 | + item = str(done['PY_' + n]) |
| 145 | + else: |
| 146 | + done[n] = item = "" |
| 147 | + if found: |
| 148 | + after = value[m.end():] |
| 149 | + value = value[:m.start()] + item + after |
| 150 | + if "$" in after: |
| 151 | + notdone[name] = value |
| 152 | + else: |
| 153 | + try: value = int(value) |
| 154 | + except ValueError: |
| 155 | + done[name] = value.strip() |
| 156 | + else: |
| 157 | + done[name] = value |
| 158 | + del notdone[name] |
| 159 | + |
| 160 | + if name.startswith('PY_') \ |
| 161 | + and name[3:] in renamed_variables: |
| 162 | + |
| 163 | + name = name[3:] |
| 164 | + if name not in done: |
| 165 | + done[name] = value |
| 166 | + else: |
| 167 | + # bogus variable reference; just drop it since we can't deal |
| 168 | + del notdone[name] |
| 169 | + |
| 170 | + fp.close() |
| 171 | + |
| 172 | + # strip spurious spaces |
| 173 | + for k, v in done.items(): |
| 174 | + if isinstance(v, str): |
| 175 | + done[k] = v.strip() |
| 176 | + |
| 177 | + # save the results in the global dictionary |
| 178 | + g.update(done) |
| 179 | + return g |
| 180 | + |
| 181 | + |
79 | 182 | # Following functions are deprecated together with this module and they
|
80 | 183 | # have no direct replacement
|
81 | 184 |
|
|
0 commit comments