Find appropriate C compiler for extension module builds
(_config_vars)
| 196 | |
| 197 | |
| 198 | def _find_appropriate_compiler(_config_vars): |
| 199 | """Find appropriate C compiler for extension module builds""" |
| 200 | |
| 201 | # Issue #13590: |
| 202 | # The OSX location for the compiler varies between OSX |
| 203 | # (or rather Xcode) releases. With older releases (up-to 10.5) |
| 204 | # the compiler is in /usr/bin, with newer releases the compiler |
| 205 | # can only be found inside Xcode.app if the "Command Line Tools" |
| 206 | # are not installed. |
| 207 | # |
| 208 | # Furthermore, the compiler that can be used varies between |
| 209 | # Xcode releases. Up to Xcode 4 it was possible to use 'gcc-4.2' |
| 210 | # as the compiler, after that 'clang' should be used because |
| 211 | # gcc-4.2 is either not present, or a copy of 'llvm-gcc' that |
| 212 | # miscompiles Python. |
| 213 | |
| 214 | # skip checks if the compiler was overridden with a CC env variable |
| 215 | if 'CC' in os.environ: |
| 216 | return _config_vars |
| 217 | |
| 218 | # The CC config var might contain additional arguments. |
| 219 | # Ignore them while searching. |
| 220 | cc = oldcc = _config_vars['CC'].split()[0] |
| 221 | if not _find_executable(cc): |
| 222 | # Compiler is not found on the shell search PATH. |
| 223 | # Now search for clang, first on PATH (if the Command LIne |
| 224 | # Tools have been installed in / or if the user has provided |
| 225 | # another location via CC). If not found, try using xcrun |
| 226 | # to find an uninstalled clang (within a selected Xcode). |
| 227 | |
| 228 | # NOTE: Cannot use subprocess here because of bootstrap |
| 229 | # issues when building Python itself (and os.popen is |
| 230 | # implemented on top of subprocess and is therefore not |
| 231 | # usable as well) |
| 232 | |
| 233 | cc = _find_build_tool('clang') |
| 234 | |
| 235 | elif os.path.basename(cc).startswith('gcc'): |
| 236 | # Compiler is GCC, check if it is LLVM-GCC |
| 237 | data = _read_output("'%s' --version" |
| 238 | % (cc.replace("'", "'\"'\"'"),)) |
| 239 | if data and 'llvm-gcc' in data: |
| 240 | # Found LLVM-GCC, fall back to clang |
| 241 | cc = _find_build_tool('clang') |
| 242 | |
| 243 | if not cc: |
| 244 | raise SystemError( |
| 245 | "Cannot locate working compiler") |
| 246 | |
| 247 | if cc != oldcc: |
| 248 | # Found a replacement compiler. |
| 249 | # Modify config vars using new compiler, if not already explicitly |
| 250 | # overridden by an env variable, preserving additional arguments. |
| 251 | for cv in _COMPILER_CONFIG_VARS: |
| 252 | if cv in _config_vars and cv not in os.environ: |
| 253 | cv_split = _config_vars[cv].split() |
| 254 | cv_split[0] = cc if cv != 'CXX' else cc + '++' |
| 255 | _save_modified_value(_config_vars, cv, ' '.join(cv_split)) |
no test coverage detected