Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-05-15 07:37:34

0001 #!/bin/bash
0002 set -u
0003 set -e
0004 set -o pipefail
0005 
0006 SCRIPT_DIR=$( cd -- "$( dirname -- "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )
0007 
0008 export SPACK_COLOR=always
0009 
0010 function start_section() {
0011     local section_name="$1"
0012     if [ -n "${GITHUB_ACTIONS:-}" ]; then
0013         echo "::group::${section_name}"
0014     else
0015         echo "${section_name}"
0016     fi
0017 }
0018 
0019 function end_section() {
0020     if [ -n "${GITHUB_ACTIONS:-}" ]; then
0021         echo "::endgroup::"
0022     fi
0023 }
0024 
0025 # Parse command line arguments
0026 while getopts "c:t:d:e:s:fh" opt; do
0027   case ${opt} in
0028     c )
0029       compiler=$OPTARG
0030       ;;
0031     t )
0032       tag=$OPTARG
0033       ;;
0034     d )
0035       destination=$OPTARG
0036       ;;
0037     e )
0038       env_file=$OPTARG
0039       ;;
0040     s )
0041       cxx_std=$OPTARG
0042       ;;
0043     f )
0044       full_install=true
0045       ;;
0046     h )
0047       echo "Usage: $0 [-c compiler] [-t tag] [-d destination] -e env_file [-h]"
0048       echo "Options:"
0049       echo "  -c <compiler>    Specify compiler (defaults to CXX env var)"
0050       echo "  -t <tag>         Specify dependency tag (defaults to DEPENDENCY_TAG env var)"
0051       echo "  -d <destination> Specify install destination (defaults based on CI environment)"
0052       echo "  -e <env_file>    Specify environment file to output environments to"
0053       echo "  -s <cxx_std>     C++ standard for lockfile selection (e.g. 20, 23). Defaults to CXXSTD env var or 20."
0054       echo "  -f               Full dependency installation. Includes Geant4 datasets and Python packages."
0055       echo "  -h               Show this help message"
0056       exit 0
0057       ;;
0058     \? )
0059       echo "Invalid option: -$OPTARG" 1>&2
0060       exit 1
0061       ;;
0062     : )
0063       echo "Option -$OPTARG requires an argument" 1>&2
0064       exit 1
0065       ;;
0066   esac
0067 done
0068 
0069 script_start=$(date +%s.%N)
0070 
0071 # Helper to print elapsed time since previous checkpoint
0072 checkpoint() {
0073     local label=$1
0074     local now
0075     now=$(date +%s.%N)
0076     local elapsed
0077     elapsed=$(echo "$now - ${last_time:-$script_start}" | bc)
0078     printf "[%s] %.3f s\n" "$label" "$elapsed"
0079     last_time=$now
0080 }
0081 
0082 # Set defaults if not specified
0083 if [ -z "${compiler:-}" ]; then
0084   compiler="${CXX:-default}"
0085 fi
0086 
0087 if [ -z "${tag:-}" ]; then
0088   tag="${DEPENDENCY_TAG:-}"
0089   if [ -z "${tag:-}" ]; then
0090     echo "No tag specified via -t or DEPENDENCY_TAG environment variable"
0091     exit 1
0092   fi
0093 fi
0094 
0095 if [ -z "${destination:-}" ]; then
0096   if [ -n "${GITHUB_ACTIONS:-}" ]; then
0097     destination="${GITHUB_WORKSPACE}/dependencies"
0098   elif [ -n "${GITLAB_CI:-}" ]; then
0099     destination="${CI_PROJECT_DIR}/dependencies"
0100   else
0101     echo "No destination specified via -d and not running in CI"
0102     exit 1
0103   fi
0104 fi
0105 
0106 if [ -z "${env_file:-}" ]; then
0107   echo "No environment file specified via -e"
0108   exit 1
0109 fi
0110 
0111 if [ -z "${cxx_std:-}" ]; then
0112   cxx_std="${CXXSTD:-20}"
0113 fi
0114 
0115 checkpoint "Create environment file $(realpath "$env_file")"
0116 echo "" > "$env_file"
0117 export env_file
0118 
0119 function set_env {
0120   key="$1"
0121   value="$2"
0122 
0123   echo "=> ${key}=${value}"
0124 
0125   echo "export ${key}=${value}" >> "$env_file"
0126 }
0127 
0128 
0129 
0130 checkpoint "Starting setup script"
0131 
0132 echo "Install tag: $tag"
0133 echo "Install destination: $destination"
0134 
0135 mkdir -p "${destination}"
0136 
0137 if [ -n "${GITLAB_CI:-}" ]; then
0138     _spack_folder=${CI_PROJECT_DIR}/spack
0139 else
0140     _spack_folder=${PWD}/spack
0141 fi
0142 
0143 start_section "Install spack if not already installed"
0144 if ! command -v spack &> /dev/null; then
0145   "${SCRIPT_DIR}/setup_spack.sh" "${_spack_folder}"
0146   source "${_spack_folder}/share/spack/setup-env.sh"
0147 fi
0148 checkpoint "Spack install complete"
0149 
0150 _spack_repo_version=${SPACK_REPO_VERSION:-develop}
0151 _spack_repo_directory="$(realpath "$(spack location --repo builtin)/../../../")"
0152 
0153 echo "Ensure builtin repo is synced to commit ${_spack_repo_version}"
0154 
0155 git config --global --add safe.directory "${_spack_repo_directory}"
0156 spack repo update builtin --commit "${_spack_repo_version}"
0157 checkpoint "Spack repository updated"
0158 
0159 end_section
0160 
0161 if [ -n "${GITLAB_CI:-}" ]; then
0162   # Use the project spack config for GitLab CI so we can cache it
0163   mkdir -p ${CI_PROJECT_DIR}/.spack
0164   ln -s ${CI_PROJECT_DIR}/.spack ${HOME}/.spack
0165 fi
0166 
0167 
0168 
0169 if [ -n "${CI:-}" ]; then
0170   start_section "Add buildcache mirror"
0171   mirror_name="acts-spack-buildcache"
0172   mirror_url="oci://ghcr.io/acts-project/spack-buildcache"
0173   if [ -n "${GITLAB_CI:-}" ]; then
0174   # Use CERN mirror for non-Github Actions
0175     mirror_url="oci://registry.cern.ch/ghcr.io/acts-project/spack-buildcache"
0176   fi
0177 
0178   # Check if this buildcache is already configured
0179   if ! spack mirror list | grep -q ${mirror_name}; then
0180     echo "Adding buildcache ${mirror_name}"
0181     spack mirror add ${mirror_name} ${mirror_url} --unsigned
0182   fi
0183   # Authenticate GHCR reads to avoid anonymous rate limits (which spack
0184   # misclassifies as "no binary available"). Idempotent on cached spack installs.
0185   # GITHUB_TOKEN must be in env when `spack install` later fetches from the mirror.
0186   if [ -n "${GITHUB_TOKEN:-}" ] && [[ "${mirror_url}" == oci://ghcr.io/* ]]; then
0187     echo "Setting GHCR credentials on ${mirror_name}"
0188     spack mirror set \
0189       --oci-username "${GITHUB_ACTOR:-x-access-token}" \
0190       --oci-password-variable GITHUB_TOKEN \
0191       "${mirror_name}"
0192   fi
0193   # Verify the mirror config (password-variable stores only the env var name,
0194   # not the secret value, so this is safe to print).
0195   spack mirror list
0196   spack config get mirrors
0197   end_section
0198 
0199   start_section "Add ACTS package repository"
0200   if ! spack repo list | grep -q "acts"; then
0201     echo "Adding ACTS package repository from ci-dependencies"
0202     spack repo add https://github.com/acts-project/ci-dependencies.git --path spack_repo/acts
0203   fi
0204   echo "Updating ACTS package repository to tag ${tag}"
0205   spack repo update acts --tag "${tag}"
0206   end_section
0207 
0208   start_section "Locate OpenGL"
0209   "${SCRIPT_DIR}/opengl.sh"
0210   checkpoint "OpenGL location complete"
0211   end_section
0212 fi
0213 
0214 start_section "Get spack lock file"
0215 arch=$(spack arch --family)
0216 
0217 env_dir="${destination}/env"
0218 view_dir="${destination}/view"
0219 venv_dir="${destination}/venv"
0220 mkdir -p ${env_dir}
0221 
0222 lock_file_path="${destination}/spack.lock"
0223 cmd=(
0224     "${SCRIPT_DIR}/select_lockfile.py"
0225     "--tag" "${tag}"
0226     "--arch" "${arch}"
0227     "--cxx" "${cxx_std}"
0228     "--output" "${lock_file_path}"
0229 )
0230 
0231 if [ "${compiler}" != "default" ]; then
0232     cmd+=("--compiler-binary" "${compiler}")
0233 fi
0234 
0235 "${cmd[@]}"
0236 
0237 checkpoint "Lock file prepared"
0238 
0239 end_section
0240 
0241 
0242 
0243 start_section "Create spack environment"
0244 spack env create -d "${env_dir}" "${lock_file_path}" --with-view "$view_dir"
0245 checkpoint "Spack environment created"
0246 spack -e "${env_dir}" spec -l
0247 checkpoint "Spack spec complete"
0248 spack -e "${env_dir}" find
0249 checkpoint "Spack find complete"
0250 end_section
0251 
0252 start_section "Install spack packages"
0253 # Retry to absorb transient GHCR fetch failures (which spack reports as
0254 # "no binary available"). Install is idempotent: already-installed specs
0255 # are skipped on subsequent attempts, so this is cheap.
0256 max_attempts=4
0257 attempt=1
0258 delay=10
0259 while true; do
0260   echo "spack install attempt ${attempt}/${max_attempts}"
0261   if spack -e "${env_dir}" install --fail-fast --use-buildcache only --concurrent-packages 10; then
0262     break
0263   fi
0264   if [ "${attempt}" -ge "${max_attempts}" ]; then
0265     echo "spack install failed after ${max_attempts} attempts"
0266     exit 1
0267   fi
0268   echo "spack install failed; retrying in ${delay}s"
0269   sleep "${delay}"
0270   attempt=$((attempt + 1))
0271   delay=$((delay * 2))
0272 done
0273 checkpoint "Spack install complete"
0274 end_section
0275 
0276 start_section "Patch up Geant4 data directory"
0277 if [ "${full_install:-false}" == "true" ]; then
0278   if ! which uv &> /dev/null ; then
0279     echo "uv not found, installing uv"
0280     curl -LsSf https://astral.sh/uv/install.sh | sh
0281     UV_EXE="/root/.local/bin/uv"
0282     checkpoint "uv installation complete"
0283   else
0284     UV_EXE=$(which uv)
0285   fi
0286   $UV_EXE run "$SCRIPT_DIR/download_geant4_datasets.py" -j8 --config "${view_dir}/bin/geant4-config"
0287   checkpoint "Geant4 datasets download complete"
0288 fi
0289 geant4_dir=$(spack -e "${env_dir}" location -i geant4)
0290 # Prepare the folder for G4 data, and symlink it to where G4 will look for it
0291 mkdir -p "${geant4_dir}/share/Geant4"
0292 ln -s "${geant4_dir}/share/Geant4/data" "${view_dir}/share/Geant4/data"
0293 end_section
0294 
0295 start_section "Prepare python environment"
0296 "${view_dir}/bin/python3" -m venv --system-site-packages "$venv_dir"
0297 "${venv_dir}/bin/python3" -m pip install pyyaml jinja2
0298 if [ "${full_install:-false}" == "true" ]; then
0299   "${venv_dir}/bin/python3" -m pip install -r "${SCRIPT_DIR}/../../Python/Examples/tests/requirements.txt"
0300   "${venv_dir}/bin/python3" -m pip install histcmp==0.9.1 matplotlib
0301   "${venv_dir}/bin/python3" -m pip install pytest-md-report
0302 fi
0303 checkpoint "Python environment prepared"
0304 end_section
0305 
0306 start_section "Set environment variables"
0307 set_env PATH "${venv_dir}/bin:${view_dir}/bin/:${PATH}"
0308 set_env LD_LIBRARY_PATH "${venv_dir}/lib:${view_dir}/lib:${view_dir}/lib/root"
0309 set_env DYLD_LIBRARY_PATH "${venv_dir}/lib:${view_dir}/lib:${view_dir}/lib/root"
0310 set_env CMAKE_PREFIX_PATH "${venv_dir}:${view_dir}"
0311 set_env ROOT_SETUP_SCRIPT "${view_dir}/bin/thisroot.sh"
0312 set_env ROOT_INCLUDE_PATH "${view_dir}/include"
0313 # cleanup setup-python mess
0314 set_env PKG_CONFIG_PATH ""
0315 set_env pythonLocation ""
0316 set_env Python_ROOT_DIR ""
0317 set_env Python2_ROOT_DIR ""
0318 set_env Python3_ROOT_DIR ""
0319 end_section
0320 
0321 checkpoint "Setup script complete"