Skip to content

Commit

Permalink
Add ability to infer CHPL_LLVM_GCC_INSTALL_DIR (#26429)
Browse files Browse the repository at this point in the history
Adds the ability to infer `CHPL_LLVM_GCC_INSTALL_DIR`. Resolves
#25925

This PR uses similar logic to the LLVM spack package to determine this.
Thanks @PHHargrove for the pointer to this.

Testing
- [x] A system with a "broken" clang can fix itself automatically now
- [x] relatedly, a user can request no gcc install dir with
`CHPL_LLVM_GCC_INSTALL_DIR=none`
- [x] `make check` on a nightly test system
- [x] full paratest with/without gasnet on linux64
- [x] `make check` on M1 mac
- [x] Setting GCC_INSTALL_DIR or GCC_PREFIX turns off inference
- [x] Setting both GCC_INSTALL_DIR and GCC_PREFIX warns, then prefers
GCC_INSTALL_DIR if available
- [x] If supported, GCC_INSTALL_DIR is preferred (unless user requests
otherwise)

This PR also adds a missing line to `overrides.py` for
`CHPL_LLVM_GCC_INSTALL_DIR`

[Reviewed by @mppf]
  • Loading branch information
jabraham17 authored Jan 6, 2025
2 parents c222ebd + c800ffa commit ce20881
Show file tree
Hide file tree
Showing 2 changed files with 77 additions and 12 deletions.
88 changes: 76 additions & 12 deletions util/chplenv/chpl_llvm.py
Original file line number Diff line number Diff line change
Expand Up @@ -748,17 +748,39 @@ def get_gcc_prefix_dir(clang_cfg_args):
# this function can't be memoized because 'clang_cfg_args' is a list and cannot be hashed.
return _get_gcc_prefix_dir_inner()

@memoize
def is_gcc_install_dir_supported():
llvm_version = get_llvm_version()
return llvm_version not in ('11', '12', '13', '14', '15')

@memoize
def get_gcc_install_dir():
gcc_dir = overrides.get('CHPL_LLVM_GCC_INSTALL_DIR', '')

flag_supported = is_gcc_install_dir_supported()

if gcc_dir:
llvm_version = get_llvm_version()
if llvm_version in ('11', '12', '13', '14', '15'):
if not flag_supported:
llvm_version = get_llvm_version()
warning("This LLVM / clang version {0} is too old to use "
"CHPL_LLVM_GCC_INSTALL_DIR -- "
"it will be ignored".format(llvm_version))
return ''
gcc_dir = ''

# allow CHPL_LLVM_GCC_INSTALL_DIR=none to disable inferring it
if gcc_dir == 'none':
gcc_dir = ''

elif flag_supported:
# compute the GCC that LLVM should use.
# this logic is based on the same logic in the LLVM spack package
_, _, stdout, _ = try_run_command(
["gcc", "-print-file-name=libgcc.a"], combine_output=True)
if stdout:
gcc_dir_path = stdout.strip()
if os.path.abspath(gcc_dir_path):
dirname = os.path.dirname(gcc_dir_path)
gcc_dir = dirname if os.path.exists(dirname) else gcc_dir

return gcc_dir

Expand Down Expand Up @@ -882,6 +904,31 @@ def get_system_llvm_built_sdkroot():
return None


@memoize
def _determine_gcc_flag_to_use():
# note: this is a helper for get_clang_basic_args, its declared here so the
# memoization can be shared and possible warnings only occur once
flag_to_use = None
if (overrides.get('CHPL_LLVM_GCC_INSTALL_DIR') is not None and
overrides.get('CHPL_LLVM_GCC_PREFIX') is not None):
# the user set both, warn
base_msg = "Both CHPL_LLVM_GCC_INSTALL_DIR and CHPL_LLVM_GCC_PREFIX are set."
if is_gcc_install_dir_supported():
flag_to_use = 'CHPL_LLVM_GCC_INSTALL_DIR'
warning("{} CHPL_LLVM_GCC_INSTALL_DIR will be used.".format(base_msg))
else:
flag_to_use = 'CHPL_LLVM_GCC_PREFIX'
warning("{} CHPL_LLVM_GCC_PREFIX will be used.".format(base_msg))

elif overrides.get('CHPL_LLVM_GCC_INSTALL_DIR') is not None:
# the user set CHPL_LLVM_GCC_INSTALL_DIR, use it
flag_to_use = 'CHPL_LLVM_GCC_INSTALL_DIR'
elif overrides.get('CHPL_LLVM_GCC_PREFIX') is not None:
# the user set CHPL_LLVM_GCC_PREFIX, use it
flag_to_use = 'CHPL_LLVM_GCC_PREFIX'

return flag_to_use

# On some systems, we need to give clang some arguments for it to
# find the correct system headers.
# * when PrgEnv-gnu is loaded on an XC, we should provide
Expand All @@ -895,17 +942,34 @@ def get_system_llvm_built_sdkroot():
def get_clang_basic_args(clang_command):
clang_args = [ ]

# read the args that clang will use by default from the config file
clang_cfg = get_clang_cfg_file(clang_command)
clang_cfg_args = parse_clang_cfg_file(clang_cfg)
@memoize
def _get_gcc_prefix_dir():
# read the args that clang will use by default from the config file
clang_cfg = get_clang_cfg_file(clang_command)
clang_cfg_args = parse_clang_cfg_file(clang_cfg)
return get_gcc_prefix_dir(clang_cfg_args)

gcc_prefix_flags = {
"CHPL_LLVM_GCC_INSTALL_DIR": ('--gcc-install-dir=', get_gcc_install_dir),
"CHPL_LLVM_GCC_PREFIX": ('--gcc-toolchain=', _get_gcc_prefix_dir),
}
def use_flag(flag_to_use):
flag, func = gcc_prefix_flags[flag_to_use]
val = func()
if val:
clang_args.append(flag + val)
return True
return False

gcc_install_dir = get_gcc_install_dir()
if gcc_install_dir:
clang_args.append('--gcc-install-dir=' + gcc_install_dir)
# if the user set one of the flags, use it
flag_to_use = _determine_gcc_flag_to_use()
if flag_to_use:
use_flag(flag_to_use)
else:
gcc_prefix = get_gcc_prefix_dir(clang_cfg_args)
if gcc_prefix:
clang_args.append('--gcc-toolchain=' + gcc_prefix)
# we should try and infer them, preferring GCC_INSTALL_DIR
for try_flag in ['CHPL_LLVM_GCC_INSTALL_DIR', 'CHPL_LLVM_GCC_PREFIX']:
if use_flag(try_flag):
break

target_platform = chpl_platform.get('target')
sysroot_args = []
Expand Down
1 change: 1 addition & 0 deletions util/chplenv/overrides.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@
'CHPL_LLVM_CLANG_CXX',
# CHPL_LLVM_VERSION -- doesn't make sense to override it
'CHPL_LLVM_GCC_PREFIX', # not in printchplenv --all
'CHPL_LLVM_GCC_INSTALL_DIR', # not in printchplenv --all

'CHPL_AUX_FILESYS',
'CHPL_LIB_PIC',
Expand Down

0 comments on commit ce20881

Please sign in to comment.