From 0ded89189cb8ef8d030621e58e480c7591d44230 Mon Sep 17 00:00:00 2001 From: Michael Ferguson Date: Fri, 5 Aug 2022 17:41:04 -0400 Subject: [PATCH 1/5] Add CHPL_LLVM_SUPPORT --- Signed-off-by: Michael Ferguson --- third-party/Makefile | 22 +++++----- third-party/llvm/Makefile | 4 +- util/chplenv/chpl_llvm.py | 82 ++++++++++++++++++++++++++++-------- util/chplenv/printchplenv.py | 6 +-- 4 files changed, 81 insertions(+), 33 deletions(-) diff --git a/third-party/Makefile b/third-party/Makefile index 3825cc73ad46..afacf54dc820 100644 --- a/third-party/Makefile +++ b/third-party/Makefile @@ -131,18 +131,20 @@ $(LIBUNWIND_INSTALL_DIR): $(LIBUNWIND_DEPEND) rm -rf $(LIBUNWIND_INSTALL_DIR) && rm -rf $(LIBUNWIND_BUILD_DIR) cd libunwind && $(MAKE) -# Check for LLVM_SUPPORT_INSTALL_DIR or LLVM_INSTALL_DIR, -# depending on the configuration. -LLVM_CHECK_INSTALL_DIR := $(LLVM_INSTALL_DIR) -ifeq ($(CHPL_MAKE_LLVM), none) - LLVM_CHECK_INSTALL_DIR := $(LLVM_SUPPORT_INSTALL_DIR) +ifeq ($(CHPL_MAKE_LLVM), bundled) +llvm: $(LLVM_INSTALL_DIR) +$(LLVM_INSTALL_DIR): $(LLVM_DEPEND) + rm -rf $(LLVM_INSTALL_DIR) + cd llvm && $(MAKE) llvm +else ifeq ($(CHPL_MAKE_LLVM_SUPPORT), bundled) +llvm: $(LLVM_SUPPORT_INSTALL_DIR) +$(LLVM_SUPPORT_INSTALL_DIR): $(LLVM_DEPEND) + rm -rf $(LLVM_SUPPORT_INSTALL_DIR) + cd llvm && $(MAKE) llvm-support +else +llvm: endif -llvm: $(LLVM_CHECK_INSTALL_DIR) -$(LLVM_CHECK_INSTALL_DIR): $(LLVM_DEPEND) - rm -rf $(LLVM_CHECK_INSTALL_DIR) - cd llvm && $(MAKE) $(CHPL_MAKE_LLVM) - # Qthreads may use hwloc and/or jemalloc. Ensure they are built first. ifeq ($(CHPL_MAKE_HWLOC), bundled) QTHREAD_OTHER_INSTALL_DIR_DEPS += $(HWLOC_INSTALL_DIR) diff --git a/third-party/llvm/Makefile b/third-party/llvm/Makefile index ca2c46e7358f..93ed6492405e 100644 --- a/third-party/llvm/Makefile +++ b/third-party/llvm/Makefile @@ -210,14 +210,14 @@ llvm: llvm-config llvm-build llvm-install llvm-clang: llvm -# to build the LLVM support library even with CHPL_LLVM=none +# to build the LLVM support library only for use with CHPL_LLVM=none llvm-support: llvm-config-support-only llvm-build-support-only llvm-install-support-only bundled: llvm system: -none: llvm-support +none: unset: @echo "Error: Please set the environment variable CHPL_LLVM to a supported value." diff --git a/util/chplenv/chpl_llvm.py b/util/chplenv/chpl_llvm.py index 736b58b0d0ca..c6bcb82a57b5 100755 --- a/util/chplenv/chpl_llvm.py +++ b/util/chplenv/chpl_llvm.py @@ -18,8 +18,8 @@ def llvm_versions(): return ('14','13','12','11',) @memoize -def get_uniq_cfg_path_for(llvm_val): - if llvm_val == "bundled" or llvm_val == "none": +def get_uniq_cfg_path_for(llvm_val, llvm_support_val): + if llvm_val == "bundled" or llvm_support_val == "bundled": # put platform-arch-compiler for included llvm llvm_target_dir = chpl_bin_subdir.get('host') else: @@ -31,18 +31,19 @@ def get_uniq_cfg_path_for(llvm_val): @memoize def get_uniq_cfg_path(): llvm_val = get() - return get_uniq_cfg_path_for(llvm_val) + llvm_support_val = get_llvm_support() + return get_uniq_cfg_path_for(llvm_val, llvm_support_val) def get_bundled_llvm_dir(): chpl_third_party = get_chpl_third_party() - llvm_target_dir = get_uniq_cfg_path_for('bundled') + llvm_target_dir = get_uniq_cfg_path_for('bundled', 'bundled') llvm_subdir = os.path.join(chpl_third_party, 'llvm', 'install', llvm_target_dir) return llvm_subdir def get_bundled_llvm_support_only_dir(): chpl_third_party = get_chpl_third_party() - llvm_target_dir = get_uniq_cfg_path_for('none') + llvm_target_dir = get_uniq_cfg_path_for('none', 'bundled') llvm_subdir = os.path.join(chpl_third_party, 'llvm', 'install', 'support-only-' + llvm_target_dir) return llvm_subdir @@ -216,9 +217,35 @@ def find_system_llvm_config(): return '' +# Returns whether to use the bundled or system LLVM for the +# LLVM support module. +# This corresponds to the CHPL_LLVM_SUPPORT variable. +# Since the LLVM support module is now required to build Chapel, +# this returns "bundled" or "system" even if CHPL_LLVM=none. +@memoize +def get_llvm_support(): + llvm_val = get() + + # If using CHPL_LLVM=bundled or CHPL_LLVM=system + # then CHPL_LLVM_SUPPORT needs to match + if llvm_val == 'bundled': + return 'bundled' + if llvm_val == 'system': + return 'system' + + llvm_support_val = overrides.get('CHPL_LLVM_SUPPORT') + if not llvm_support_val: + if has_compatible_installed_llvm(): + llvm_support_val = 'system' + else: + llvm_support_val = 'bundled' + + return llvm_support_val + @memoize def get_llvm_config(): llvm_val = get() + llvm_support_val = get_llvm_support() llvm_config = overrides.get('CHPL_LLVM_CONFIG', 'none') if llvm_val == 'bundled': @@ -228,18 +255,20 @@ def get_llvm_config(): warning("CHPL_LLVM_CONFIG is ignored for CHPL_LLVM=bundled") llvm_config = bundled_config - elif llvm_val == 'none': + elif llvm_support_val == 'bundled': llvm_subdir = get_bundled_llvm_support_only_dir() bundled_config = os.path.join(llvm_subdir, 'bin', 'llvm-config') if llvm_config != 'none' and llvm_config != bundled_config: - warning("CHPL_LLVM_CONFIG is ignored for CHPL_LLVM=none") + warning("CHPL_LLVM_CONFIG is ignored for CHPL_LLVM_SUPPORT=bundled") llvm_config = bundled_config - elif llvm_config == 'none' and llvm_val == 'system': - llvm_config = find_system_llvm_config() + elif llvm_config == 'none': + if llvm_val == 'system' or llvm_support_val == 'system': + llvm_config = find_system_llvm_config() return llvm_config + @memoize def get_llvm_version(): (llvm_version, _) = check_llvm_config(get_llvm_config()) @@ -248,6 +277,7 @@ def get_llvm_version(): @memoize def validate_llvm_config(): llvm_val = get() + llvm_support_val = get_llvm_support() llvm_config = get_llvm_config() if llvm_val == 'system': @@ -256,6 +286,12 @@ def validate_llvm_config(): " with one of the supported versions: {0}".format( llvm_versions_string())) + if llvm_support_val == 'system': + if llvm_config == '' or llvm_config == 'none': + error("CHPL_LLVM_SUPPORT=system but could not find an installed " + "LLVM with one of the supported versions: {0}".format( + llvm_versions_string())) + if (llvm_val == 'system' or (llvm_val == 'bundled' and os.path.exists(llvm_config))): version, config_error = check_llvm_config(llvm_config) @@ -363,6 +399,11 @@ def has_compatible_installed_llvm(): # otherwise, something went wrong, so return False return False +# Returns the setting to use for CHPL_LLVM +# CHPL_LLVM=none means build the compiler without enabling LLVM and clang +# integration (but note the LLVM support library is still used) +# CHPL_LLVM=system means to use a system install of LLVM and clang +# CHPL_LLVM=bundled means to use the bundled version of LLVM and clang @memoize def get(): llvm_val = overrides.get('CHPL_LLVM') @@ -726,9 +767,10 @@ def get_host_compile_args(): system = [ ] llvm_val = get() + llvm_support_val = get_llvm_support() llvm_config = get_llvm_config() - if llvm_val == 'system': + if llvm_support_val == 'system': # On Mac OS X with Homebrew, apply a workaround for issue #19217. # This avoids finding headers in the libc++ installed by llvm@12 e.g. if use_system_libcxx_workaround(): @@ -748,9 +790,7 @@ def get_host_compile_args(): cxxflags = run_command([llvm_config, '--cxxflags']) system.extend(filter_llvm_config_flags(cxxflags.split())) - elif llvm_val == 'bundled' or llvm_val == 'none': - # none is handled here to get the LLVMSupport library - + elif llvm_support_val == 'bundled': # don't try to run llvm-config if it's not built yet if is_included_llvm_built(llvm_val): # Note, the cxxflags should include the -I for the include dir @@ -774,6 +814,7 @@ def get_host_link_args(): llvm_dynamic = True llvm_val = get() + llvm_support_val = get_llvm_support() llvm_config = get_llvm_config() clang_static_libs = ['-lclangFrontend', '-lclangSerialization', @@ -804,7 +845,7 @@ def get_host_link_args(): clang_static_libs = [ ] llvm_components = ['support'] - if llvm_val == 'system': + if llvm_support_val == 'system': # On Mac OS X with Homebrew, apply a workaround for issue #19217. # This avoids linking with the libc++ installed by llvm@12 e.g. if use_system_libcxx_workaround(): @@ -846,9 +887,7 @@ def get_host_link_args(): system.extend(filter_llvm_link_flags(ldflags.split())) - elif llvm_val == 'bundled' or llvm_val == 'none': - # none is handled here to use the LLVM Support library - + elif llvm_support_val == 'bundled': # Link statically for now for the bundled configuration # If this changes in the future: # * check for problems finding libstdc++ with different PrgEnv compilers @@ -927,6 +966,10 @@ def _main(): parser.add_option('--sdkroot', dest='action', action='store_const', const='sdkroot', default='') + parser.add_option('--quickstart', dest='action', + action='store_const', + const='quickstart', default='') + (options, args) = parser.parse_args() @@ -946,6 +989,11 @@ def _main(): sys.stdout.write("{0}\n".format(llvm_versions)) elif options.action == 'sdkroot': sys.stdout.write("{0}\n".format(get_clang_args_sdkroot())) + elif options.action == 'quickstart': + if has_compatible_installed_llvm(): + sys.stdout.write("system\n") + else: + sys.stdout.write("none\n") else: sys.stdout.write("{0}\n".format(llvm_val)) diff --git a/util/chplenv/printchplenv.py b/util/chplenv/printchplenv.py index 8d1ab2ca4fd2..861f34809f6c 100755 --- a/util/chplenv/printchplenv.py +++ b/util/chplenv/printchplenv.py @@ -114,6 +114,7 @@ ChapelEnv('CHPL_RE2', RUNTIME | DEFAULT, 're2'), ChapelEnv(' CHPL_RE2_IS_OVERRIDDEN', INTERNAL), ChapelEnv('CHPL_LLVM', COMPILER | DEFAULT, 'llvm'), + ChapelEnv(' CHPL_LLVM_SUPPORT', COMPILER | NOPATH, 'llvm'), ChapelEnv(' CHPL_LLVM_CONFIG', COMPILER | NOPATH), ChapelEnv(' CHPL_LLVM_VERSION', COMPILER), ChapelEnv(' CHPL_LLVM_CLANG_C', INTERNAL), @@ -204,6 +205,7 @@ def compute_all_values(): ENV_VALS['CHPL_RE2'] = chpl_re2.get() ENV_VALS[' CHPL_RE2_IS_OVERRIDDEN'] = chpl_re2.is_overridden() ENV_VALS['CHPL_LLVM'] = chpl_llvm.get() + ENV_VALS[' CHPL_LLVM_SUPPORT'] = chpl_llvm.get_llvm_support() ENV_VALS[' CHPL_LLVM_CONFIG'] = chpl_llvm.get_llvm_config() ENV_VALS[' CHPL_LLVM_VERSION'] = chpl_llvm.get_llvm_version() llvm_clang_c = chpl_llvm.get_llvm_clang('c') @@ -318,10 +320,6 @@ def filter_tidy(chpl_env): return comm == 'ofi' elif chpl_env.name == ' CHPL_NETWORK_ATOMICS': return comm != 'none' - elif chpl_env.name == ' CHPL_LLVM_CONFIG': - return llvm != 'none' - elif chpl_env.name == ' CHPL_LLVM_VERSION': - return llvm != 'none' elif chpl_env.name == ' CHPL_CUDA_PATH': return locale_model == 'gpu' elif chpl_env.name == ' CHPL_CUDA_LIBDEVICE_PATH': From d83ec727471ca205469e8a281316663353d3efcd Mon Sep 17 00:00:00 2001 From: Michael Ferguson Date: Fri, 5 Aug 2022 18:04:49 -0400 Subject: [PATCH 2/5] Update quickstart setchplenv scripts to use a system LLVM if one is detected to be available --- Signed-off-by: Michael Ferguson --- util/quickstart/setchplenv.bash | 5 +++-- util/quickstart/setchplenv.csh | 5 +++-- util/quickstart/setchplenv.fish | 5 +++-- util/quickstart/setchplenv.sh | 5 +++-- 4 files changed, 12 insertions(+), 8 deletions(-) diff --git a/util/quickstart/setchplenv.bash b/util/quickstart/setchplenv.bash index a22a3f3f1b89..f0086fd3dcc6 100644 --- a/util/quickstart/setchplenv.bash +++ b/util/quickstart/setchplenv.bash @@ -64,5 +64,6 @@ export CHPL_GMP=none echo "Setting CHPL_RE2 to none" export CHPL_RE2=none -echo "Setting CHPL_LLVM to none" -export CHPL_LLVM=none +USE_LLVM=`$CHPL_PYTHON $chpl_home/util/chplenv/chpl_llvm.py --quickstart` +echo "Setting CHPL_LLVM to $USE_LLVM" +export CHPL_LLVM=$USE_LLVM diff --git a/util/quickstart/setchplenv.csh b/util/quickstart/setchplenv.csh index 697141c72136..93e8e4ebd17d 100644 --- a/util/quickstart/setchplenv.csh +++ b/util/quickstart/setchplenv.csh @@ -53,5 +53,6 @@ setenv CHPL_GMP none echo "Setting CHPL_RE2 to none" setenv CHPL_RE2 none -echo "Setting CHPL_LLVM to none" -setenv CHPL_LLVM none +set USE_LLVM = `$CHPL_PYTHON "$CHPL_HOME"/util/chplenv/chpl_llvm.py --quickstart` +echo "Setting CHPL_LLVM to $USE_LLVM" +setenv CHPL_LLVM $USE_LLVM diff --git a/util/quickstart/setchplenv.fish b/util/quickstart/setchplenv.fish index 8263470f95cb..f6a174c36657 100644 --- a/util/quickstart/setchplenv.fish +++ b/util/quickstart/setchplenv.fish @@ -57,5 +57,6 @@ set -x CHPL_GMP none echo "Setting CHPL_RE2 to none" set -x CHPL_RE2 none -echo "Setting CHPL_LLVM to none" -set -x CHPL_LLVM none +set -x USE_LLVM (eval "$CHPL_PYTHON" "$CHPL_HOME/util/chplenv/chpl_llvm.py" "--quickstart") +echo "Setting CHPL_LLVM to $USE_LLVM" +set -x CHPL_LLVM $USE_LLVM diff --git a/util/quickstart/setchplenv.sh b/util/quickstart/setchplenv.sh index 2023aa670e7a..f57853639f4a 100644 --- a/util/quickstart/setchplenv.sh +++ b/util/quickstart/setchplenv.sh @@ -75,8 +75,9 @@ export CHPL_RE2 echo " ...none" echo " " +USE_LLVM=`$CHPL_PYTHON "$CHPL_HOME"/util/chplenv/chpl_llvm.py --quickstart` echo "Setting CHPL_LLVM to..." -CHPL_LLVM=none +CHPL_LLVM=$USE_LLVM export CHPL_LLVM -echo " ...none" +echo " ...$USE_LLVM" echo " " From f5da95121452d250a0e59198fc57dcca93c09246 Mon Sep 17 00:00:00 2001 From: Michael Ferguson Date: Mon, 8 Aug 2022 15:41:25 -0400 Subject: [PATCH 3/5] Don't compute compile flags when CHPL_LLVM=unset --- Signed-off-by: Michael Ferguson --- util/chplenv/chpl_llvm.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/util/chplenv/chpl_llvm.py b/util/chplenv/chpl_llvm.py index c6bcb82a57b5..206837ea9680 100755 --- a/util/chplenv/chpl_llvm.py +++ b/util/chplenv/chpl_llvm.py @@ -52,7 +52,7 @@ def is_included_llvm_built(llvm_val): llvm_subdir = None if llvm_val == 'bundled': llvm_subdir = get_bundled_llvm_dir() - elif llvm_val == 'none': + else: llvm_subdir = get_bundled_llvm_support_only_dir() llvm_header = os.path.join(llvm_subdir, 'include', 'llvm', @@ -770,6 +770,10 @@ def get_host_compile_args(): llvm_support_val = get_llvm_support() llvm_config = get_llvm_config() + # quit early if the llvm value is unset + if llvm_val == 'unset': + return (bundled, system) + if llvm_support_val == 'system': # On Mac OS X with Homebrew, apply a workaround for issue #19217. # This avoids finding headers in the libc++ installed by llvm@12 e.g. @@ -840,6 +844,10 @@ def get_host_link_args(): 'coroutines', 'lto'] + # quit early if the llvm value is unset + if llvm_val == 'unset': + return (bundled, system) + # only use LLVMSupport for CHPL_LLVM=none if llvm_val == 'none': clang_static_libs = [ ] From 72b7060f86705c9c8351c46afddec46cdab75c72 Mon Sep 17 00:00:00 2001 From: Michael Ferguson Date: Mon, 8 Aug 2022 15:41:39 -0400 Subject: [PATCH 4/5] Print error when CHPL_LLVM=unset --- Signed-off-by: Michael Ferguson --- third-party/Makefile | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/third-party/Makefile b/third-party/Makefile index afacf54dc820..970e218093cd 100644 --- a/third-party/Makefile +++ b/third-party/Makefile @@ -131,17 +131,28 @@ $(LIBUNWIND_INSTALL_DIR): $(LIBUNWIND_DEPEND) rm -rf $(LIBUNWIND_INSTALL_DIR) && rm -rf $(LIBUNWIND_BUILD_DIR) cd libunwind && $(MAKE) -ifeq ($(CHPL_MAKE_LLVM), bundled) +ifeq ($(CHPL_MAKE_LLVM), unset) +# Print the error about needing to set CHPL_LLVM +llvm: FORCE + cd llvm && $(MAKE) unset + +else ifeq ($(CHPL_MAKE_LLVM), bundled) +# build the bundled LLVM llvm: $(LLVM_INSTALL_DIR) $(LLVM_INSTALL_DIR): $(LLVM_DEPEND) rm -rf $(LLVM_INSTALL_DIR) cd llvm && $(MAKE) llvm + else ifeq ($(CHPL_MAKE_LLVM_SUPPORT), bundled) +# build the bundled LLVM support library llvm: $(LLVM_SUPPORT_INSTALL_DIR) $(LLVM_SUPPORT_INSTALL_DIR): $(LLVM_DEPEND) rm -rf $(LLVM_SUPPORT_INSTALL_DIR) cd llvm && $(MAKE) llvm-support + else + +# nothing to do for CHPL_LLVM=system / CHPL_LLVM_SUPPORT=system llvm: endif From 884f5ca0c616d89034134f5da2a45289f1b3572d Mon Sep 17 00:00:00 2001 From: Michael Ferguson Date: Mon, 8 Aug 2022 17:59:23 -0400 Subject: [PATCH 5/5] Let setchplenv test find system LLVM for quickstart --- Signed-off-by: Michael Ferguson --- test/setchplenv/verify_setchplenv_scripts.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/test/setchplenv/verify_setchplenv_scripts.py b/test/setchplenv/verify_setchplenv_scripts.py index 5a0b228a0af4..92805b2316a8 100644 --- a/test/setchplenv/verify_setchplenv_scripts.py +++ b/test/setchplenv/verify_setchplenv_scripts.py @@ -151,11 +151,12 @@ def get_path_var(var_name): self.assertEqual(os.stat(self.chpl_home), os.stat(actual_chpl_home)) if 'quickstart' in os.path.relpath(setchplenv_script, self.util_dir): + got_llvm = get_var('CHPL_LLVM') self.assertEqual('none', get_var('CHPL_COMM')) self.assertEqual('fifo', get_var('CHPL_TASKS')) self.assertEqual('none', get_var('CHPL_GMP')) self.assertEqual('none', get_var('CHPL_RE2')) - self.assertEqual('none', get_var('CHPL_LLVM')) + self.assertTrue('none' == got_llvm or 'system' == got_llvm) self.assertEqual('cstdlib', get_var('CHPL_MEM')) def check_scripts(self, shell, source_cmd, path_sep,