diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index bc49d9c2..876da978 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -41,7 +41,7 @@ jobs: env: USE_BAZEL_VERSION: ${{ matrix.bazel_version }} USE_BZLMOD: ${{ matrix.bzlmod }} - run: tests/scripts/run_tests.sh + run: tests/scripts/run_tests.sh -O toolchain_test: strategy: fail-fast: false @@ -123,7 +123,7 @@ jobs: - name: Test env: USE_BZLMOD: ${{ matrix.bzlmod }} - run: tests/scripts/run_tests.sh -t @llvm_toolchain_with_absolute_paths//:cc-toolchain-x86_64-linux + run: tests/scripts/run_tests.sh -t @llvm_toolchain_with_absolute_paths//:cc-toolchain-x86_64-linux -O sys_paths_test: strategy: fail-fast: false @@ -134,6 +134,7 @@ jobs: - uses: actions/checkout@v5 - run: tests/scripts/ubuntu_install_libtinfo.sh - name: Download and Extract LLVM distribution + # The downloaded version here must match version specified as '-v' arg to run_tests.sh below. env: release: llvmorg-16.0.0 archive: clang+llvm-16.0.0-x86_64-linux-gnu-ubuntu-18.04 @@ -143,4 +144,4 @@ jobs: - name: Test env: USE_BZLMOD: ${{ matrix.bzlmod }} - run: tests/scripts/run_tests.sh -t @llvm_toolchain_with_system_llvm//:cc-toolchain-x86_64-linux + run: tests/scripts/run_tests.sh -t @llvm_toolchain_with_system_llvm//:cc-toolchain-x86_64-linux -v 16.0.0 diff --git a/MODULE.bazel b/MODULE.bazel index fa99a1da..bc2fafbe 100644 --- a/MODULE.bazel +++ b/MODULE.bazel @@ -20,10 +20,10 @@ module( ) bazel_dep(name = "bazel_features", version = "1.38.0") -bazel_dep(name = "bazel_skylib", version = "1.5.0") -bazel_dep(name = "aspect_bazel_lib", version = "2.0.0") -bazel_dep(name = "rules_cc", version = "0.2.2") -bazel_dep(name = "platforms", version = "0.0.8") +bazel_dep(name = "bazel_skylib", version = "1.8.2") +bazel_dep(name = "aspect_bazel_lib", version = "2.19.3") +bazel_dep(name = "rules_cc", version = "0.2.8") +bazel_dep(name = "platforms", version = "1.0.0") bazel_dep(name = "helly25_bzl", version = "0.3.1") bazel_dep(name = "tar.bzl", version = "0.6.0") diff --git a/tests/BUILD.bazel b/tests/BUILD.bazel index 2589ac76..d34b1308 100644 --- a/tests/BUILD.bazel +++ b/tests/BUILD.bazel @@ -81,7 +81,7 @@ build_test( dwp_file( name = "stdlib.dwp", src = ":stdlib_bin", - # NOTE: we should eventually we able to drop this; see #109. + # NOTE: we should eventually be able to drop this; see #109. override_compilation_mode = "dbg", target_compatible_with = [ "@platforms//os:linux", @@ -101,6 +101,7 @@ cc_test( srcs = ["omp_test.c"], copts = ["-fopenmp"], linkopts = ["-fopenmp"], + tags = ["manual"], deps = ["@llvm_toolchain//:omp"], ) @@ -114,9 +115,19 @@ cc_test( srcs = ["omp_test.cc"], copts = ["-fopenmp"], linkopts = ["-fopenmp"], + tags = ["manual"], deps = ["@llvm_toolchain//:omp"], ) +test_suite( + name = "omp_tests", + tags = ["manual"], + tests = [ + ":omp_test", + ":omp_test_cc", + ], +) + sh_test( name = "file_dependency_test", srcs = ["file_dependency_test.sh"], diff --git a/tests/MODULE.bazel b/tests/MODULE.bazel index 711f279f..ab7af41f 100644 --- a/tests/MODULE.bazel +++ b/tests/MODULE.bazel @@ -22,7 +22,7 @@ local_path_override( bazel_dep(name = "bazel_skylib", version = "1.8.2") bazel_dep(name = "platforms", version = "1.0.0") -bazel_dep(name = "rules_cc", version = "0.0.9") +bazel_dep(name = "rules_cc", version = "0.2.8") bazel_dep(name = "rules_go", version = "0.50.1", repo_name = "io_bazel_rules_go") bazel_dep(name = "rules_rust", version = "0.67.0") bazel_dep(name = "rules_foreign_cc", version = "0.15.0") @@ -63,10 +63,13 @@ llvm = use_extension("@toolchains_llvm//toolchain/extensions:llvm.bzl", "llvm") # When updating this version, also update the versions associated with # llvm_toolchain below, sys_paths_test in the workflows file, and xcompile_test # through the `llvm_toolchain_with_sysroot` toolchain. +# We use C++17 and the first LLVM version with full support is 16.0.0. +# We also use C++20 which has reasonable wide support starting with LLVM 17.0.0. +# MacOS X86 does not exist for LLVM 17 or 18, so we allow 19 as well. +# We also allow to override this with a environment LLVM_VERSION for testing. LLVM_VERSIONS = { - "": "16.0.0", - "darwin-aarch64": "16.0.5", - "darwin-x86_64": "15.0.7", + "": "getenv(LLVM_VERSION,latest:>=17.0.0,<20)", + "darwin-x86_64": "15.0.7", # Verify this works as opposed to using one version. } llvm.toolchain( @@ -147,9 +150,10 @@ llvm.toolchain_root( use_repo(llvm, "llvm_toolchain_with_absolute_paths") # Toolchain example with system LLVM; tested in GitHub CI. +# The llvm_version must match the version specified in .github/workflows/tests.yml: sys_paths_test llvm.toolchain( name = "llvm_toolchain_with_system_llvm", - llvm_versions = LLVM_VERSIONS, + llvm_versions = {"": "16.0.0"}, ) # For this toolchain to work, the LLVM distribution archive would need to be unpacked here. diff --git a/tests/WORKSPACE b/tests/WORKSPACE index af5f1500..dd2d2bdb 100644 --- a/tests/WORKSPACE +++ b/tests/WORKSPACE @@ -59,10 +59,13 @@ load("@toolchains_llvm//toolchain:rules.bzl", "llvm_toolchain") # When updating this version, also update the versions associated with # llvm_toolchain below, sys_paths_test in the workflows file, and xcompile_test # through the `llvm_toolchain_with_sysroot` toolchain. +# We use C++17 and the first LLVM version with full suppor is 16.0.0. +# We also use C++20 which has reasonable wide support starting with LLVM 17.0.0. +# MacOS X86 does not exist for LLVM 17 or 18, so we allow 19 as well. +# We also allow to override this with a environment LLVM_VERSION for testing. LLVM_VERSIONS = { - "": "16.0.0", - "darwin-aarch64": "16.0.5", - "darwin-x86_64": "15.0.7", + "": "getenv(LLVM_VERSION,latest:>=17.0.0,<20)", + "darwin-x86_64": "15.0.7", # Verify this works as opposed to using one version. } llvm_toolchain( @@ -134,9 +137,10 @@ llvm_toolchain( ) ## Toolchain example with system LLVM; tested in GitHub CI. +# The llvm_version must match the version specified in .github/workflows/tests.yml: sys_paths_test llvm_toolchain( name = "llvm_toolchain_with_system_llvm", - llvm_versions = LLVM_VERSIONS, + llvm_version = "getenv(LLVM_VERSION)", # For this toolchain to work, the LLVM distribution archive would need to be unpacked here. toolchain_roots = {"": "/opt/llvm-16"}, ) diff --git a/tests/scripts/archlinux_test.sh b/tests/scripts/archlinux_test.sh index dd3d4bf1..eb244f4e 100755 --- a/tests/scripts/archlinux_test.sh +++ b/tests/scripts/archlinux_test.sh @@ -32,6 +32,6 @@ set -exuo pipefail # Run tests cd /src -tests/scripts/run_tests.sh -t ${toolchain} +tests/scripts/run_tests.sh -O -t ${toolchain} """ done diff --git a/tests/scripts/debian_test.sh b/tests/scripts/debian_test.sh index c0de9666..0fb2858e 100755 --- a/tests/scripts/debian_test.sh +++ b/tests/scripts/debian_test.sh @@ -36,6 +36,6 @@ apt-get -qq -y install curl libtinfo5 libxml2 zlib1g-dev >/dev/null # Run tests cd /src -tests/scripts/run_tests.sh +tests/scripts/run_tests.sh -O """ done diff --git a/tests/scripts/fedora_test.sh b/tests/scripts/fedora_test.sh index 1cc4cce5..20e31994 100755 --- a/tests/scripts/fedora_test.sh +++ b/tests/scripts/fedora_test.sh @@ -32,6 +32,6 @@ dnf install -qy glibc-headers ncurses-compat-libs # Run tests cd /src -tests/scripts/run_tests.sh +tests/scripts/run_tests.sh -O """ done diff --git a/tests/scripts/linux_sysroot_test.sh b/tests/scripts/linux_sysroot_test.sh index a2935c24..3cbd0d6b 100755 --- a/tests/scripts/linux_sysroot_test.sh +++ b/tests/scripts/linux_sysroot_test.sh @@ -19,6 +19,8 @@ images=( "ubuntu:22.04" ) +LLVM_VERSION="first:>=15.0.0,<17" + git_root=$(git rev-parse --show-toplevel) readonly git_root @@ -36,6 +38,6 @@ apt-get -qq -y install curl libtinfo5 libxml2 zlib1g-dev >/dev/null # Run tests cd /src -tests/scripts/run_tests.sh -t '@llvm_toolchain_with_sysroot//:cc-toolchain-x86_64-linux' +tests/scripts/run_tests.sh -t '@llvm_toolchain_with_sysroot//:cc-toolchain-x86_64-linux' -v '${LLVM_VERSION}' """ done diff --git a/tests/scripts/run_tests.sh b/tests/scripts/run_tests.sh index abca1b20..48c50742 100755 --- a/tests/scripts/run_tests.sh +++ b/tests/scripts/run_tests.sh @@ -16,18 +16,28 @@ set -euo pipefail toolchain_name="" -disable_wasm_tests="" +enable_omp_targets="1" +enable_wasm_tests="1" +LLVM_VERSION="" -while getopts "t:hW" opt; do +while getopts "hOt:v:W" opt; do case "${opt}" in - "t") toolchain_name="${OPTARG}" ;; "h") echo "Usage:" echo "-t - Toolchain name to use for testing; default is llvm_toolchain" exit 2 ;; + "O") + enable_omp_targets="" + ;; + "t") + toolchain_name="${OPTARG}" + ;; + "v") + LLVM_VERSION="${OPTARG}" + ;; "W") - disable_wasm_tests="yes" + enable_wasm_tests="" ;; *) echo "invalid option: -${OPTARG}" @@ -56,10 +66,21 @@ targets=( # :test_cxx_standard_is_20 builds with a version of the default toolchain, if # we're trying to build with a different toolchain then it's likely the default # toolchain won't work so :test_cxx_standard_is_20 won't build. -if [[ -z ${toolchain_name} ]]; then +if [[ -z "${toolchain_name}" ]]; then targets+=("//:test_cxx_standard_is_20") fi +if [[ -n "${enable_omp_targets}" ]]; then + targets+=("//:omp_tests") +fi + +if [[ -n "${LLVM_VERSION}" ]]; then + echo "LLVM_VERSION=${LLVM_VERSION}" + common_test_args+=( + "--repo_env=LLVM_VERSION=${LLVM_VERSION}" + ) +fi + "${bazel}" ${TEST_MIGRATION:+"--strict"} --bazelrc=/dev/null test \ "${common_test_args[@]}" "${test_args[@]}" "${targets[@]}" @@ -72,7 +93,7 @@ fi # to run out of disk space. # # Mitigate this by expunging the workspace before trying to build Wasm targets. -if [[ -z ${toolchain_name} && -z ${disable_wasm_tests} ]]; then +if [[ -z "${toolchain_name}" ]] && [[ -n "${enable_wasm_tests}" ]]; then # Redefine `test_args` without `--linkopt=-Wl,-v`, which breaks `wasm-ld`. # # https://github.com/llvm/llvm-project/issues/112836 diff --git a/tests/scripts/suse_leap_test.sh b/tests/scripts/suse_leap_test.sh index 7ba31974..3e3308d5 100755 --- a/tests/scripts/suse_leap_test.sh +++ b/tests/scripts/suse_leap_test.sh @@ -38,6 +38,6 @@ zypper -n install curl gcc libc++1 # Run tests cd /src -tests/scripts/run_tests.sh -t ${toolchain} +tests/scripts/run_tests.sh -O -t ${toolchain} """ done diff --git a/tests/scripts/suse_tumbleweed_test.sh b/tests/scripts/suse_tumbleweed_test.sh index e5d6cd82..07db78a7 100755 --- a/tests/scripts/suse_tumbleweed_test.sh +++ b/tests/scripts/suse_tumbleweed_test.sh @@ -38,6 +38,6 @@ zypper -n install curl gcc libc++1 # Run tests cd /src -tests/scripts/run_tests.sh -t ${toolchain} +tests/scripts/run_tests.sh -O -t ${toolchain} """ done diff --git a/tests/scripts/ubuntu_20_04_test.sh b/tests/scripts/ubuntu_20_04_test.sh index 38e6d20e..a8510a14 100755 --- a/tests/scripts/ubuntu_20_04_test.sh +++ b/tests/scripts/ubuntu_20_04_test.sh @@ -19,6 +19,8 @@ images=( "ubuntu:20.04" ) +LLVM_VERSION="first:>=15.0.0,<17" + git_root=$(git rev-parse --show-toplevel) readonly git_root @@ -40,6 +42,6 @@ disable_wasm_tests='-W' # Run tests cd /src -tests/scripts/run_tests.sh \${disable_wasm_tests} +tests/scripts/run_tests.sh -v '${LLVM_VERSION}' \${disable_wasm_tests} """ done diff --git a/tests/scripts/ubuntu_22_04_test.sh b/tests/scripts/ubuntu_22_04_test.sh index f5341fd8..2e5ff013 100755 --- a/tests/scripts/ubuntu_22_04_test.sh +++ b/tests/scripts/ubuntu_22_04_test.sh @@ -36,6 +36,6 @@ apt-get -qq -y install curl libtinfo5 libxml2 zlib1g-dev >/dev/null # Run tests cd /src -tests/scripts/run_tests.sh +tests/scripts/run_tests.sh -O """ done diff --git a/toolchain/internal/configure.bzl b/toolchain/internal/configure.bzl index 279e1094..45d20556 100644 --- a/toolchain/internal/configure.bzl +++ b/toolchain/internal/configure.bzl @@ -38,7 +38,10 @@ load( _supported_targets = "SUPPORTED_TARGETS", _toolchain_tools = "toolchain_tools", ) -load("//toolchain/internal:llvm_distributions.bzl", "is_requirement", "required_llvm_release_name_rctx") +load( + "//toolchain/internal:llvm_distributions.bzl", + _required_llvm_version_rctx = "required_llvm_version_rctx", +) load( "//toolchain/internal:sysroot.bzl", _default_sysroot_path = "default_sysroot_path", @@ -81,16 +84,7 @@ def llvm_config_impl(rctx): if not toolchain_root: fail("LLVM toolchain root missing for ({}, {})".format(os, arch)) - _, llvm_version = _exec_os_arch_dict_value(rctx, "llvm_versions") - if is_requirement(llvm_version): - llvm_version, distribution, error = required_llvm_release_name_rctx(rctx, llvm_version) - if error: - fail(error) - if llvm_version: - print("\nINFO: Resolved latest LLVM version to {llvm_version}: {distribution}".format( - distribution = distribution, - llvm_version = llvm_version, - )) # buildifier: disable=print + llvm_version = _required_llvm_version_rctx(rctx) if not llvm_version: # LLVM version missing for (os, arch) _empty_repository(rctx) diff --git a/toolchain/internal/llvm_distributions.bzl b/toolchain/internal/llvm_distributions.bzl index 2721b7ca..6d2f6e79 100644 --- a/toolchain/internal/llvm_distributions.bzl +++ b/toolchain/internal/llvm_distributions.bzl @@ -1125,12 +1125,23 @@ def _find_llvm_basename_or_error(llvm_version, all_llvm_distributions, host_info return basenames[0], None +def _is_requirement(version_or_requirements): + """Return whether `version_or_requirements` is likely a requirement (True) or should be a version.""" + if version_or_requirements.startswith("getenv("): + return True + for prefix in ["first:", "latest:"]: + if version_or_requirements.startswith(prefix) or version_or_requirements == prefix[:-1]: + return True + return False + def _parse_version_or_requirements(version_or_requirements): - if version_or_requirements in ["latest", "first"]: - return None for prefix in ["latest:", "first:"]: if version_or_requirements.startswith(prefix): return versions.parse_requirements(version_or_requirements.removeprefix(prefix)) + if version_or_requirements in ["latest", "first"]: + return None + if not _is_requirement(version_or_requirements): + return None fail("ERROR: Invalid version requirements: '{version_or_requirements}'.".format( version_or_requirements = version_or_requirements, )) @@ -1159,11 +1170,43 @@ def _required_llvm_release_name(*, version_or_requirements, all_llvm_distributio return llvm_version, basenames[0], None return None, None, "ERROR: No matching distribution found." -def required_llvm_release_name_rctx(rctx, llvm_version): +def _resolve_llvm_version_rctx_env(rctx, llvm_version): + if llvm_version.startswith("getenv(") and llvm_version.endswith(")"): + env_var = llvm_version[len("getenv("):-1] + if env_var.find(",") >= 0: + env_name, env_default = env_var.split(",", 1) + else: + env_name = env_var + env_default = None + + env_name = env_name.strip(" ") + if not env_var: + fail("ERROR: Bad getenv parameter '{env_var}'.".format( + env_var = env_var, + )) + + # We prefer 'repository_ctx.getenv' if it is available (~7.1+) and default + # to accessing the environment directly. The latter breaks "hermeticity". + if hasattr(rctx, "getenv"): + llvm_version = rctx.getenv(env_name, env_default) + elif env_name in rctx.os.environ: + llvm_version = rctx.os.environ[env_name] + else: + llvm_version = env_default + + if not llvm_version: + fail("ERROR: Empty getenv lookup for '{env_var}'.".format( + env_var = env_var, + )) + + return llvm_version + +def _required_llvm_release_name_rctx(rctx, llvm_version): + llvm_version = _resolve_llvm_version_rctx_env(rctx, llvm_version) all_llvm_distributions = _get_all_llvm_distributions( llvm_distributions = _llvm_distributions, extra_llvm_distributions = rctx.attr.extra_llvm_distributions, - parsed_llvm_version = _parse_version(llvm_version), + parsed_llvm_version = _parse_version(llvm_version) if not _is_requirement(llvm_version) else None, ) return _required_llvm_release_name( version_or_requirements = llvm_version, @@ -1171,12 +1214,19 @@ def required_llvm_release_name_rctx(rctx, llvm_version): host_info = host_info(rctx), ) -def is_requirement(version_or_requirement): - """Return whether `version_or_requirement` is likely a requirement (True) or should be a version.""" - for prefix in ["first:", "latest:"]: - if version_or_requirement.startswith(prefix) or version_or_requirement == prefix[:-1]: - return True - return False +def required_llvm_version_rctx(rctx): + _, llvm_version = exec_os_arch_dict_value(rctx, "llvm_versions") + if _is_requirement(llvm_version): + llvm_version, distribution, error = _required_llvm_release_name_rctx(rctx, llvm_version) + if error: + fail(error) + if llvm_version: + print("\nINFO: Resolved latest LLVM version for {name} to {llvm_version}: {distribution}".format( + name = rctx.attr.name, + distribution = distribution, + llvm_version = llvm_version, + )) # buildifier: disable=print + return llvm_version def _filter_llvm_distributions(*, llvm_version, all_llvm_distributions): """Return (distribution: sha) entries from `all_llvm_distributions` that match `llvm_version`.""" @@ -1192,13 +1242,14 @@ def _distribution_urls(rctx): all_llvm_distributions = _get_all_llvm_distributions( llvm_distributions = _llvm_distributions, extra_llvm_distributions = rctx.attr.extra_llvm_distributions, - parsed_llvm_version = _parse_version(llvm_version), + parsed_llvm_version = _parse_version(llvm_version) if not _is_requirement(llvm_version) else None, ) _, sha256, strip_prefix, _ = _key_attrs(rctx) if rctx.attr.distribution == "auto": rctx_host_info = host_info(rctx) - if is_requirement(llvm_version): + llvm_version = _resolve_llvm_version_rctx_env(rctx, llvm_version) + if _is_requirement(llvm_version): llvm_version, basename, error = _required_llvm_release_name( version_or_requirements = llvm_version, all_llvm_distributions = all_llvm_distributions, diff --git a/toolchain/internal/repo.bzl b/toolchain/internal/repo.bzl index 934b5373..99e2ee3d 100644 --- a/toolchain/internal/repo.bzl +++ b/toolchain/internal/repo.bzl @@ -14,13 +14,13 @@ load( "//toolchain/internal:common.bzl", _attr_dict = "attr_dict", - _exec_os_arch_dict_value = "exec_os_arch_dict_value", _os = "os", _supported_os_arch_keys = "supported_os_arch_keys", ) load( "//toolchain/internal:llvm_distributions.bzl", _download_llvm = "download_llvm", + _required_llvm_version_rctx = "required_llvm_version_rctx", ) _target_pairs = ", ".join(_supported_os_arch_keys()) @@ -423,8 +423,7 @@ def llvm_repo_impl(rctx): rctx.file("BUILD.bazel", executable = False) return None - _, llvm_version = _exec_os_arch_dict_value(rctx, "llvm_versions") - + llvm_version = _required_llvm_version_rctx(rctx) major_llvm_version = int(llvm_version.split(".")[0]) rctx.file(