Make handling of CC more robust

Allows multi-command compilers and makes detection of gcc more robust.
Fixes #4102
This commit is contained in:
Kovid Goyal 2021-10-07 13:35:56 +05:30
parent 5841776c65
commit 853f7cc59a
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
2 changed files with 27 additions and 19 deletions

View File

@ -16,7 +16,7 @@ base = os.path.dirname(os.path.abspath(__file__))
class Env:
cc: str = ''
cc: List[str] = []
cppflags: List[str] = []
cflags: List[str] = []
ldflags: List[str] = []
@ -33,7 +33,7 @@ class Env:
wayland_protocols: Tuple[str, ...] = ()
def __init__(
self, cc: str = '', cppflags: List[str] = [], cflags: List[str] = [], ldflags: List[str] = [],
self, cc: List[str] = [], cppflags: List[str] = [], cflags: List[str] = [], ldflags: List[str] = [],
library_paths: Dict[str, List[str]] = {}, ldpaths: Optional[List[str]] = None, ccver: Tuple[int, int] = (0, 0)
):
self.cc, self.cppflags, self.cflags, self.ldflags, self.library_paths = cc, cppflags, cflags, ldflags, library_paths

View File

@ -151,20 +151,21 @@ def at_least_version(package: str, major: int, minor: int = 0) -> None:
)
def cc_version() -> Tuple[str, Tuple[int, int]]:
def cc_version() -> Tuple[List[str], Tuple[int, int]]:
if 'CC' in os.environ:
cc = os.environ['CC']
q = os.environ['CC']
else:
if is_macos:
cc = 'clang'
q = 'clang'
else:
if shutil.which('gcc'):
cc = 'gcc'
q = 'gcc'
elif shutil.which('clang'):
cc = 'clang'
q = 'clang'
else:
cc = 'cc'
raw = subprocess.check_output([cc, '-dumpversion']).decode('utf-8')
q = 'cc'
cc = shlex.split(q)
raw = subprocess.check_output(cc + ['-dumpversion']).decode('utf-8')
ver_ = raw.strip().split('.')[:2]
try:
if len(ver_) == 1:
@ -220,7 +221,7 @@ def get_python_flags(cflags: List[str]) -> List[str]:
return libs
def get_sanitize_args(cc: str, ccver: Tuple[int, int]) -> List[str]:
def get_sanitize_args(cc: List[str], ccver: Tuple[int, int]) -> List[str]:
sanitize_args = ['-fsanitize=address']
if ccver >= (5, 0):
sanitize_args.append('-fsanitize=undefined')
@ -231,7 +232,7 @@ def get_sanitize_args(cc: str, ccver: Tuple[int, int]) -> List[str]:
def test_compile(
cc: str, *cflags: str,
cc: List[str], *cflags: str,
src: str = '',
source_ext: str = 'c',
link_also: bool = True,
@ -244,7 +245,7 @@ def test_compile(
with open(os.path.join(tdir, f'source.{source_ext}'), 'w', encoding='utf-8') as srcf:
print(src, file=srcf)
return subprocess.Popen(
[cc] + list(cflags) + ([] if link_also else ['-c']) +
cc + list(cflags) + ([] if link_also else ['-c']) +
['-o', os.path.join(tdir, 'source.output'), srcf.name] +
[f'-l{x}' for x in libraries] + list(ldflags),
stdout=subprocess.DEVNULL, stdin=subprocess.DEVNULL,
@ -252,7 +253,7 @@ def test_compile(
).wait() == 0
def first_successful_compile(cc: str, *cflags: str, src: str = '', source_ext: str = 'c') -> str:
def first_successful_compile(cc: List[str], *cflags: str, src: str = '', source_ext: str = 'c') -> str:
for x in cflags:
if test_compile(cc, *shlex.split(x), src=src, source_ext=source_ext):
return x
@ -271,7 +272,7 @@ def set_arches(flags: List[str], arches: Iterable[str] = ('x86_64', 'arm64')) ->
flags.extend(('-arch', arch))
def detect_librsync(cc: str, cflags: List[str], ldflags: List[str]) -> str:
def detect_librsync(cc: List[str], cflags: List[str], ldflags: List[str]) -> str:
if not test_compile(
cc, *cflags, libraries=('rsync',), ldflags=ldflags, show_stderr=True,
src='#include <librsync.h>\nint main(void) { rs_strerror(0); return 0; }'):
@ -289,6 +290,13 @@ int main(void) {
return ''
def is_gcc(cc: List[str]) -> bool:
if not hasattr(is_gcc, 'ans'):
raw = subprocess.check_output(cc + ['--version']).decode('utf-8').splitlines()[0]
setattr(is_gcc, 'ans', '(GCC)' in raw.split())
return bool(getattr(is_gcc, 'ans'))
def init_env(
debug: bool = False,
sanitize: bool = False,
@ -313,7 +321,7 @@ def init_env(
print('CC:', cc, ccver)
stack_protector = first_successful_compile(cc, '-fstack-protector-strong', '-fstack-protector')
missing_braces = ''
if ccver < (5, 2) and cc == 'gcc':
if ccver < (5, 2) and is_gcc(cc):
missing_braces = '-Wno-missing-braces'
df = '-g3'
float_conversion = ''
@ -695,7 +703,7 @@ def compile_c_extension(
if defines is not None:
cppflags.extend(map(define, defines))
cmd = [kenv.cc, '-MMD'] + cppflags + kenv.cflags
cmd = kenv.cc + ['-MMD'] + cppflags + kenv.cflags
cmd += ['-c', src] + ['-o', dest]
key = CompileKey(original_src, os.path.basename(dest))
desc = 'Compiling {} ...'.format(emphasis(desc_prefix + src))
@ -709,7 +717,7 @@ def compile_c_extension(
# warnings on some old systems)
unsafe = {'-pthread', '-Werror', '-pedantic-errors'}
linker_cflags = list(filter(lambda x: x not in unsafe, kenv.cflags))
cmd = [kenv.cc] + linker_cflags + kenv.ldflags + objects + kenv.ldpaths + ['-o', dest]
cmd = kenv.cc + linker_cflags + kenv.ldflags + objects + kenv.ldpaths + ['-o', dest]
def on_success() -> None:
os.rename(dest, real_dest)
@ -841,7 +849,7 @@ def build_launcher(args: Options, launcher_dir: str = '.', bundle_type: str = 's
if args.sanitize:
cflags.append('-g3')
cflags.extend(get_sanitize_args(env.cc, env.ccver))
libs += ['-lasan'] if env.cc == 'gcc' and not is_macos else []
libs += ['-lasan'] if is_gcc(env.cc) and not is_macos else []
else:
cflags.append('-g')
if args.profile:
@ -874,7 +882,7 @@ def build_launcher(args: Options, launcher_dir: str = '.', bundle_type: str = 's
os.makedirs(launcher_dir, exist_ok=True)
dest = os.path.join(launcher_dir, 'kitty')
src = 'launcher.c'
cmd = [env.cc] + cppflags + cflags + [
cmd = env.cc + cppflags + cflags + [
src, '-o', dest] + ldflags + libs + pylib
key = CompileKey('launcher.c', 'kitty')
desc = 'Building {}...'.format(emphasis('launcher'))