Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .github/workflows/tests_archdetect.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ jobs:
- aarch64/neoverse_v1/AWS-awslinux-graviton3
- aarch64/nvidia/grace/Jureca-Rocky95
- aarch64/google/axion/GCP-axion
- riscv64/sifive/premier-Ubuntu24
- riscv64/sifive/p550/premier-Ubuntu24
- riscv64/sifive/u74-mc/starvision-Ubuntu24
- riscv64/spacemit/bananaf3-Armbian
- riscv64/spacemit/bananaf3-k6.6
# commented out since these targets are currently not supported in software.eessi.io repo
Expand Down
85 changes: 85 additions & 0 deletions .github/workflows/tests_riscv_optarch.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
name: Tests for eessi_riscv_optarch map
on:
push:
branches: [ "main" ]
pull_request:
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-24.04
steps:
- name: checkout
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1

- name: Mount EESSI CernVM-FS repositories
uses: cvmfs-contrib/github-action-cvmfs@55899ca74cf78ab874bdf47f5a804e47c198743c # v4.0
with:
cvmfs_config_package: https://github.com/EESSI/filesystem-layer/releases/download/latest/cvmfs-config-eessi_latest_all.deb
cvmfs_http_proxy: DIRECT
# software.eessi.io: compat + init; dev.eessi.io: RISC-V software stack
cvmfs_repositories: software.eessi.io,dev.eessi.io

- name: Install qemu-user-static (run riscv64 EESSI compilers on x86_64)
run: |
sudo apt-get update
sudo apt-get install -y qemu-user-static

- name: Load EESSI RISC-V compilers (GCC 14.3.0, llvm-compilers 20.1.8)
run: |
set -euo pipefail
EESSI_VERSION=2025.06
. "/cvmfs/software.eessi.io/versions/${EESSI_VERSION}/compat/linux/$(uname -m)/usr/share/Lmod/init/bash"
export MODULEPATH="${GITHUB_WORKSPACE}/init/modules"

# Host is x86_64: use x86_64 compat, but modules from the RISC-V repo.
export EESSI_CPU_FAMILY_OVERRIDE=x86_64
export EESSI_SOFTWARE_SUBDIR_OVERRIDE=riscv64/generic
export EESSI_VERSION_OVERRIDE=2025.06-001

module load "EESSI/${EESSI_VERSION}"
echo "MODULEPATH=${MODULEPATH}"

# foss/2025b → GCC/14.3.0; lfoss/2025b → llvm-compilers/20.1.8
module load GCC/14.3.0

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two things maybe worth a comment in the file: the module versions are pinned, so the next dev.eessi.io rebuild breaks this, and -fsyntax-only never reaches the assembler, so the job name overclaims a bit.
The triple override combo also skips the init scripts' own consistency checks; one line saying it's deliberate would help the next reader.

if module load llvm-compilers/20.1.8 2>/tmp/llvm_mod.err; then
:
elif module load LLVM/20.1.8 2>>/tmp/llvm_mod.err; then
:
else
echo "Failed to load llvm-compilers/20.1.8 or LLVM/20.1.8" >&2
cat /tmp/llvm_mod.err >&2
module avail LLVM llvm-compilers Clang 2>&1 | head -80 >&2 || true
exit 1
fi

GCC_BIN="$(command -v gcc)"
CLANG_BIN="$(command -v clang)"
echo "EESSI_RISCV_GCC=${GCC_BIN}"
echo "EESSI_RISCV_CLANG=${CLANG_BIN}"
file "${GCC_BIN}" "${CLANG_BIN}"

# RISC-V ELFs need the RISC-V compat root when run under qemu on x86.
RISCV_COMPAT="/cvmfs/software.eessi.io/versions/${EESSI_VERSION}/compat/linux/riscv64"
echo "QEMU_LD_PREFIX=${RISCV_COMPAT}"

{
echo "EESSI_RISCV_GCC=${GCC_BIN}"
echo "EESSI_RISCV_CLANG=${CLANG_BIN}"
echo "QEMU_LD_PREFIX=${RISCV_COMPAT}"
echo "EESSI_RISCV_OPTARCH_EXPECT_GCC_VERSION=14.3.0"
echo "EESSI_RISCV_OPTARCH_EXPECT_CLANG_VERSION=20.1.8"
} >> "${GITHUB_ENV}"

# Smoke: versions + flag acceptance via -fsyntax-only (no assembler).
# Under qemu on x86, PATH often hits the x86_64 Gentoo as; -c then fails
# with invalid -march=rv64gc. -fsyntax-only still validates -march/-mtune.
"${GCC_BIN}" --version
"${CLANG_BIN}" --version
"${GCC_BIN}" -fsyntax-only -march=rv64gc -mabi=lp64d -x c /dev/null
echo "GCC -fsyntax-only smoke OK"

- name: test RISC-V optarch map (EESSI GCC + Clang/LLVM)
env:
EESSI_RISCV_OPTARCH_REQUIRE_COMPILERS: "1"
run: bash ./tests/riscv_optarch/test_eessi_riscv_optarch.sh
48 changes: 42 additions & 6 deletions EESSI-extend-easybuild.eb
Original file line number Diff line number Diff line change
Expand Up @@ -145,18 +145,18 @@ elseif eessi_site_install then
easybuild_installpath = os.getenv("EESSI_SITE_SOFTWARE_PATH")
-- Check that the plain EESSI_SITE_SOFTWARE_PATH exists
if not isDir(easybuild_installpath) then
installpath_warning = "The location of EESSI_SITE_SOFTWARE_PATH (" .. easybuild_installpath .. ") does not exist or is not a directory. "
installpath_warning = installpath_warning .. "If you have sufficient permissions this location will be created, otherwise you will run into errors."
LmodWarning(installpath_warning)
installpath_warning = "The location of EESSI_SITE_SOFTWARE_PATH (" .. easybuild_installpath .. ") does not exist or is not a directory. "
installpath_warning = installpath_warning .. "If you have sufficient permissions this location will be created, otherwise you will run into errors."
LmodWarning(installpath_warning)
end
-- Enforce accelerator subdirectory usage for site installs (only if an accelerator install is requested)
if (eessi_accelerator_target ~= nil) and (cuda_compute_capability ~= nil) and (os.getenv("EESSI_ACCELERATOR_INSTALL") ~= nil) then
easybuild_installpath = pathJoin(easybuild_installpath, eessi_accelerator_target)
-- Check that the EESSI_SITE_SOFTWARE_PATH with eessi_accelerator_target prefix exists
if not isDir(easybuild_installpath) then
installpath_warning = "The location of EESSI_SITE_SOFTWARE_PATH (" .. easybuild_installpath .. ") does not exist or is not a directory. "
installpath_warning = installpath_warning .. "If you have sufficient permissions this location will be created, otherwise you will run into errors."
LmodWarning(installpath_warning)
installpath_warning = "The location of EESSI_SITE_SOFTWARE_PATH (" .. easybuild_installpath .. ") does not exist or is not a directory. "
installpath_warning = installpath_warning .. "If you have sufficient permissions this location will be created, otherwise you will run into errors."
LmodWarning(installpath_warning)
end
end
else
Expand Down Expand Up @@ -223,6 +223,42 @@ if (easybuild_amdgcn_compute_capabilities ~= nil) then
setenv ("EASYBUILD_AMDGCN_CAPABILITIES", easybuild_amdgcn_compute_capabilities)
end

-- Set EASYBUILD_OPTARCH for RISC-V CPU targets from the software_subdir map
-- (same idea as CUDA/AMD capabilities above). Skip if already set (e.g. --generic).
-- Map file: init/arch_specs/eessi_riscv_optarch.map (installed with EESSI init scripts).
if (os.getenv("EASYBUILD_OPTARCH") == nil or os.getenv("EASYBUILD_OPTARCH") == "") then
local eessi_software_subdir = os.getenv("EESSI_SOFTWARE_SUBDIR")
if (eessi_software_subdir ~= nil and string.match(eessi_software_subdir, "^riscv64/")) then
local map_file = pathJoin(eessi_init_prefix, "arch_specs", "eessi_riscv_optarch.map")
local optarch = nil
local map_fh = io.open(map_file, "r")
if map_fh == nil then
LmodError("RISC-V optarch map not found: " .. map_file)
end
for line in map_fh:lines() do
if not string.match(line, "^%s*#") and not string.match(line, "^%s*$") then
local key, val = string.match(line, "^(%S+)%s+(.+)$")
if key == eessi_software_subdir then
-- Drop trailing comments; trim whitespace
val = string.match(val, "^([^#]+)") or val
val = string.gsub(val, "^%s+", "")
val = string.gsub(val, "%s+$", "")
optarch = val
break
end
end
end
map_fh:close()
if optarch == nil or optarch == "" then
LmodError("No RISC-V EASYBUILD_OPTARCH mapping for '" .. eessi_software_subdir .. "' (add it to " .. map_file .. ")")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes a missing map line fail module load for everyone on that target, including site installs with their own optarch policy.
Maybe warn and fall through to the default like the CUDA capabilities do?

end
setenv("EASYBUILD_OPTARCH", optarch)
if (mode() == "load") then
LmodMessage("-- RISC-V EASYBUILD_OPTARCH from map for " .. eessi_software_subdir .. ": " .. optarch)
end
end
end

-- Set all related environment variables if we have project or user installations (including extending MODULEPATH)
if (user_modulepath ~= nil) then
-- Use a more restrictive umask for this case
Expand Down
3 changes: 3 additions & 0 deletions EESSI-install-software.sh
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,9 @@ else
)
fi

# RISC-V EASYBUILD_OPTARCH is set by EESSI-extend from eessi_riscv_optarch.map
# when that module is loaded (honours a pre-set value, e.g. --generic).

echo ">> Setting up environment..."

# If EESSI_VERSION is not set, source the defaults script to set it
Expand Down
2 changes: 2 additions & 0 deletions bot/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,8 @@ declare -a INSTALL_SCRIPT_ARGS=()
if [[ ${EESSI_SOFTWARE_SUBDIR_OVERRIDE} =~ .*/generic$ ]]; then
INSTALL_SCRIPT_ARGS+=("--generic")
fi
# RISC-V -march/-mtune: set via EESSI-extend from eessi_riscv_optarch.map
# (same pattern as CUDA/AMD compute capabilities), not here in bot/build.sh.
[[ ! -z ${BUILD_LOGS_DIR} ]] && INSTALL_SCRIPT_ARGS+=("--build-logs-dir" "${BUILD_LOGS_DIR}")
[[ ! -z ${SHARED_FS_PATH} ]] && INSTALL_SCRIPT_ARGS+=("--shared-fs-path" "${SHARED_FS_PATH}")

Expand Down
11 changes: 8 additions & 3 deletions init/arch_specs/eessi_arch_riscv.spec
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
# RISC-V CPU architecture specifications (see https://github.com/riscv/learn?tab=readme-ov-file#open-risc-v-implementations)
# CPU vendors: SiFive (0x489), Spacemit (0x710)
# Spec lines must not use parentheses in trailing comments: update_arch_specs evals each line.

# Software path in EESSI | Vendor ID | List of defining CPU features
"riscv64/sifive/p550" "0x489" "rv64imafdch_zicsr_zifencei_zba_zbb_sscofpmf" # HiFive Premier P550
"riscv64/spacemit/x60" "0x710" "rv64imafdcv_sscofpmf_sstc_svpbmt_zicbom_zicboz_zicbop_zihintpause" # Banana Pi F3
"riscv64/spacemit/x60-k6.6" "0x710" "rv64imafdcv_zicbom_zicboz_zicntr_zicond_zicsr_zifencei_zihintpause_zihpm_zfh_zfhmin_zca_zcd_zba_zbb_zbc_zbs_zkt_zve32f_zve32x_zve64d_zve64f_zve64x_zvfh_zvfhmin_zvkt_sscofpmf_sstc_svinval_svnapot_svpbmt" # Banana Pi F3 k6.6
"riscv64/generic/rva20u64" "" "rv64imafdc"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think these three can ever match?
cpupath() compares vendors first 1 and only aarch64 has an unknown-vendor fallback 2, so everything real gets an mvendorid 3 and an empty vendor field never survives the gate.

I think the riscv64/sifive/u74-mc:riscv64/generic in the u74-mc fixture 5 is also shown that way because of this.
Its isa line 4 tokenizes to

rv64imafdc zicntr zicsr zifencei zihpm zca zcd zba zbb

which contains everything the rva20u64 entry asks for (rv64imafdc, 6), so feature-wise it should have matched.
Separately, the entry is a lot weaker than the actual RVA20U64 profile, which also mandates Zicsr, Zicntr, and Zifencei among others 7; probably fine as a matching heuristic, but worth saying which one it's meant to be.

Maybe add a riscv fallback like the ARM 0x41 one 2, or drop the three entries until that exists?
There's also no generic/rva* fixture right now, so CI can't catch this.

"riscv64/generic/rva22u64" "" "rv64imafdc zfhmin"
"riscv64/generic/rva23u64" "" "rv64imafdciv zfhmin"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rv64imafdciv has i twice, and the kernel prints the single-letter block in canonical order (1, "ISA string ordering rules"; the canonical order itself is Appendix C of the ISA manual 2), so /proc/cpuinfo can never produce ...dciv.
Should be rv64imafdcv I think.
Doesn't matter anyway right now because of the vendor gate, but it'll be a silent never-match once that's fixed.

"riscv64/sifive/p550" "0x489" "rv64imafdch zicsr zifencei zba zbb sscofpmf" # HiFive Premier P550, rva20 + hypervisor
"riscv64/sifive/u74-mc" "0x489" "rv64imafdc zicntr zicsr zifencei zihpm zca zcd zba zbb" # StarFive VisionFive 2 / SiFive U74-MC, rva20
"riscv64/spacemit/x60" "0x710" "rv64imafdcv sscofpmf sstc svpbmt zicbom zicboz zicbop zihintpause" # Banana Pi F3, rva22 + vector 1.0 VLEN=256
"riscv64/spacemit/x60-k6.6" "0x710" "rv64imafdcv zicbom zicboz zicntr zicond zicsr zifencei zihintpause zihpm zfh zfhmin zca zcd zba zbb zbc zbs zkt zve32f zve32x zve64d zve64f zve64x zvfh zvfhmin zvkt sscofpmf sstc svinval svnapot svpbmt" # Banana Pi F3 k6.6, rva22 + vector 1.0 VLEN=256
35 changes: 35 additions & 0 deletions init/arch_specs/eessi_riscv_optarch.map
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# Build-time map: EESSI software subdirectory -> EasyBuild optarch for RISC-V
#
# Runtime CPU selection uses eessi_archdetect.sh + eessi_arch_riscv.spec.
# This file is only for compile flags at build time.
#
# Primary consumer: EESSI-extend (EESSI-extend-easybuild.eb) sets
# EASYBUILD_OPTARCH from this map when EESSI_SOFTWARE_SUBDIR is riscv64/* and
# optarch is not already set (same pattern as CUDA/AMD compute capabilities).
# init/eessi_riscv_optarch.sh remains available for tests / shell helpers.
#
# Format: <software_subdir><TAB_OR_SPACES><optarch>
# - GENERIC means EasyBuild's RISC-V generic flags for each compiler
# (GCC/Clang/LLVM: -march=rv64gc -mabi=lp64d)
# - otherwise EasyBuild multi-compiler syntax:
# GCC:<flags>;Clang:<flags>;LLVM:<flags>
# see https://docs.easybuild.io/controlling-compiler-optimization-flags/
#
# Notes:
# - Path names may use profile labels (rva20u64, ...). -march must use explicit
# rv64* ISA strings for toolchains that do not yet accept profile names as
# -march (e.g. Ubuntu 24.04 gcc-riscv64 13.x / clang 18).
# - Omit -mtune=generic: unknown to some RISC-V GCC builds.
# - Omit S-mode / privileged extensions from -march (sscofpmf, sstc, sv*, ...):
# they are not needed for userspace codegen and break older Clang.
# - No SpacemiT -mtune/-mcpu name upstream yet.
# - Spec lines must not use parentheses in trailing comments.

riscv64/generic GENERIC
riscv64/generic/rva20u64 GCC:-march=rv64gc -mabi=lp64d;Clang:-march=rv64gc -mabi=lp64d;LLVM:-march=rv64gc -mabi=lp64d
riscv64/generic/rva22u64 GCC:-march=rv64gc_zba_zbb_zbs_zfhmin_zicbom_zicbop_zicboz -mabi=lp64d;Clang:-march=rv64gc_zba_zbb_zbs_zfhmin_zicbom_zicbop_zicboz -mabi=lp64d;LLVM:-march=rv64gc_zba_zbb_zbs_zfhmin_zicbom_zicbop_zicboz -mabi=lp64d

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The -march here looks right to me (RVA22U64 implies zba/zbb/zbs/zicbo* 1), but the spec entry for the same subdir only asks for rv64imafdc + zfhmin, so wouldn't a host with zfhmin and no zbs get labeled rva22u64 and receive binaries it can't run?
Might be worth a test that every extension in a subdir's -march is required by its spec line; the vendored targets already pass that, it's only the profile entries.

riscv64/generic/rva23u64 GCC:-march=rv64gcv_zba_zbb_zbs_zfhmin -mabi=lp64d;Clang:-march=rv64gcv_zba_zbb_zbs_zfhmin -mabi=lp64d;LLVM:-march=rv64gcv_zba_zbb_zbs_zfhmin -mabi=lp64d
riscv64/sifive/p550 GCC:-march=rv64gc_zba_zbb -mtune=sifive-7-series -mabi=lp64d;Clang:-march=rv64gc_zba_zbb -mabi=lp64d;LLVM:-march=rv64gc_zba_zbb -mabi=lp64d
riscv64/sifive/u74-mc GCC:-mcpu=sifive-u74 -mabi=lp64d;Clang:-mcpu=sifive-u74 -mabi=lp64d;LLVM:-mcpu=sifive-u74 -mabi=lp64d
riscv64/spacemit/x60 GCC:-march=rv64imafdcv_zicbom_zicboz_zicbop_zihintpause -mabi=lp64d;Clang:-march=rv64imafdcv_zicbom_zicboz_zicbop_zihintpause -mabi=lp64d;LLVM:-march=rv64imafdcv_zicbom_zicboz_zicbop_zihintpause -mabi=lp64d
riscv64/spacemit/x60-k6.6 GCC:-march=rv64gcv_zba_zbb_zbs_zfh_zfhmin_zicbom_zicboz_zihintpause -mabi=lp64d;Clang:-march=rv64gcv_zba_zbb_zbs_zfh_zfhmin_zicbom_zicboz_zihintpause -mabi=lp64d;LLVM:-march=rv64gcv_zba_zbb_zbs_zfh_zfhmin_zicbom_zicboz_zihintpause -mabi=lp64d
8 changes: 7 additions & 1 deletion init/eessi_archdetect.sh
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ else
exit 1
fi

VERSION="1.2.0"
VERSION="1.3.0"

# default log level: only emit warnings or errors
LOG_LEVEL="WARN"
Expand Down Expand Up @@ -154,6 +154,12 @@ cpupath(){
fi

local cpu_flags=$(get_cpuinfo "$cpu_flag_tag")
if [ "${machine_type}" == "riscv64" ]; then
# RISC-V ISA strings use '_' as extension separators.
# Convert them to space-separated feature tokens so they
# can be matched like x86 CPU flags.
cpu_flags=${cpu_flags//_/ }
fi
Comment on lines +157 to +162

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While the format is open: the leading rv64imafdch blob still matches as one token, so a superset host (say rv64imafdcvh) fails a spec asking rv64imafdch.
Splitting the blob into per-letter tokens would make the base extensions individually matchable, which I think is what the description is going for?
If the expansion happens on both sides at match time, the spec files keep the readable concatenated form, something like

riscv_expand_base(){
    # rv64imafdch -> rv64 i m a f d c h ; every other token passes through
    local out="" tok
    for tok in "$@"; do
        if [ "${tok#rv64}" != "${tok}" ]; then
            out="${out} rv64 $(printf '%s' "${tok#rv64}" | sed 's/./& /g')"
        else
            out="${out} ${tok}"
        fi
    done
    printf '%s' "${out}"
}

# here, for the host flags:
cpu_flags=$(riscv_expand_base ${cpu_flags})

# and at the match, for the spec side:
check_allinfirst "${cpu_flags[*]}" $(riscv_expand_base ${arch_spec[2]})

so a superset host matches any subset spec without the spec files caring how the kernel concatenated the letters.
Also trailing whitespace on this line, and the comment block is tab-indented against the file.

log "DEBUG" "cpupath: CPU flags of host system: '$cpu_flags'"

# Default to generic CPU
Expand Down
125 changes: 125 additions & 0 deletions init/eessi_riscv_optarch.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
#!/usr/bin/env bash
#
# Lookup EasyBuild optarch flags for an EESSI RISC-V software subdirectory.
# See init/arch_specs/eessi_riscv_optarch.map and docs discussion in EESSI PR #243.
#
# Primary apply path is EESSI-extend (sets EASYBUILD_OPTARCH on module load).
# This shell helper remains for tests and optional direct use:
# source init/eessi_riscv_optarch.sh
# eessi_riscv_optarch_for riscv64/sifive/u74-mc
# eessi_riscv_optarch_compiler_flags 'GCC:...' GCC
#
# Exit codes for eessi_riscv_optarch_for:
# 0 found (or non-riscv64 subdir: prints nothing, success — caller ignores)
# 1 riscv64 subdir with no map entry
# 2 map file missing / unreadable

# Resolve directory of this script even when sourced
_EESSI_RISCV_OPTARCH_SH_DIR=$(CDPATH= cd -- "$(dirname -- "${BASH_SOURCE[0]}")" && pwd)
: "${EESSI_RISCV_OPTARCH_MAP:=${_EESSI_RISCV_OPTARCH_SH_DIR}/arch_specs/eessi_riscv_optarch.map}"

eessi_riscv_optarch_for() {
local subdir="${1:-}"
if [ -z "${subdir}" ]; then
echo "eessi_riscv_optarch_for: missing software subdirectory argument" >&2
return 2
fi

# Only RISC-V targets are covered by this map
case "${subdir}" in
riscv64/*) ;;
*) return 0 ;;
esac

if [ ! -f "${EESSI_RISCV_OPTARCH_MAP}" ]; then
echo "eessi_riscv_optarch_for: map file not found: ${EESSI_RISCV_OPTARCH_MAP}" >&2
return 2
fi

local key rest
# Strip comments and blank lines; first field = subdir, remainder = optarch
while read -r key rest; do
[ -z "${key}" ] && continue
if [ "${key}" = "${subdir}" ]; then
if [ -z "${rest}" ]; then
echo "eessi_riscv_optarch_for: empty optarch for '${subdir}' in ${EESSI_RISCV_OPTARCH_MAP}" >&2
return 1
fi
printf '%s\n' "${rest}"
return 0
fi
done < <(sed -E 's/(^|[[:space:]])#.*$//g;/^[[:space:]]*$/d' "${EESSI_RISCV_OPTARCH_MAP}")

echo "eessi_riscv_optarch_for: no optarch mapping for '${subdir}' (add it to ${EESSI_RISCV_OPTARCH_MAP})" >&2
return 1
}

# Extract flags for one compiler from an EasyBuild multi-compiler optarch string.
# eessi_riscv_optarch_compiler_flags 'GCC:-march=...;Clang:-march=...' GCC
# For GENERIC, prints GENERIC.
eessi_riscv_optarch_compiler_flags() {
local optarch="${1:-}"
local compiler="${2:-}"
if [ -z "${optarch}" ] || [ -z "${compiler}" ]; then
echo "eessi_riscv_optarch_compiler_flags: need <optarch> <compiler>" >&2
return 2
fi
if [ "${optarch}" = "GENERIC" ]; then
printf '%s\n' "GENERIC"
return 0
fi

local part key val rest="${optarch}"
while [ -n "${rest}" ]; do
part="${rest%%;*}"
if [ "${part}" = "${rest}" ]; then
rest=""
else
rest="${rest#*;}"
fi
key="${part%%:*}"
val="${part#*:}"
if [ "${key}" = "${compiler}" ]; then
if [ -z "${val}" ] || [ "${val}" = "${part}" ]; then
echo "eessi_riscv_optarch_compiler_flags: missing flags for ${compiler} in '${optarch}'" >&2
return 1
fi
printf '%s\n' "${val}"
return 0
fi
done
echo "eessi_riscv_optarch_compiler_flags: no entry for compiler '${compiler}' in '${optarch}'" >&2
return 1
}

# Apply map to the current shell: set EASYBUILD_OPTARCH and EB when appropriate.
# No-op if EASYBUILD_OPTARCH is already set, or subdir is not riscv64/*.
# Expects EESSI_SOFTWARE_SUBDIR_OVERRIDE to be set.
#
# Prefer $EASYBUILD_OPTARCH for flag strings that contain spaces or ';'.
# Only bake --optarch into $EB for the simple GENERIC case.
eessi_riscv_apply_optarch_map() {
if [ -n "${EASYBUILD_OPTARCH:-}" ]; then
return 0
fi
if [ -z "${EESSI_SOFTWARE_SUBDIR_OVERRIDE:-}" ]; then
return 0
fi
case "${EESSI_SOFTWARE_SUBDIR_OVERRIDE}" in
riscv64/*) ;;
*) return 0 ;;
esac

local optarch
optarch=$(eessi_riscv_optarch_for "${EESSI_SOFTWARE_SUBDIR_OVERRIDE}") || return $?

export EASYBUILD_OPTARCH="${optarch}"
if [ "${EASYBUILD_OPTARCH}" = "GENERIC" ]; then
EB='eb --optarch=GENERIC'
else
# Keep EB as plain 'eb'; EasyBuild reads $EASYBUILD_OPTARCH (needed for
# multi-compiler strings with spaces / ';').
EB='eb'
fi
return 0
}
2 changes: 2 additions & 0 deletions install_scripts.sh
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,7 @@ TOPDIR=$(dirname $(realpath $0))
# Copy for init directory
init_files=(
bash eessi_archdetect.sh eessi_defaults eessi_environment_variables eessi_software_subdir_for_host.py
eessi_riscv_optarch.sh
minimal_eessi_env README.md test.py lmod_eessi_archdetect_wrapper.sh lmod_eessi_archdetect_wrapper_accel.sh

)
Expand All @@ -179,6 +180,7 @@ copy_files_by_list ${TOPDIR}/init ${INSTALL_PREFIX}/init "${init_files[@]}"
# Copy for the init/arch_specs directory
arch_specs_files=(
eessi_arch_arm.spec eessi_arch_ppc.spec eessi_arch_riscv.spec eessi_arch_x86.spec
eessi_riscv_optarch.map
)
copy_files_by_list ${TOPDIR}/init/arch_specs ${INSTALL_PREFIX}/init/arch_specs "${arch_specs_files[@]}"

Expand Down
Loading