Build Systems and Options¶
This document explains ERF’s two build systems, GNU Make and CMake, and how each manages dependencies to produce a functional executable.
The two build systems serve distinct purposes:
GNU Make - Application-centric system for compiling a single executable for a specific scientific run. Provides fine-grained control over compilation and debugging via utility targets like
print-xxx.CMake - Framework-centric system designed for cross-platform compatibility and dependency management. Creates versioned libraries, provides automated detection (including Cray systems), and supports testing through CTest. Recommended for HPC environments.
This guide serves as a technical reference for developers and advanced users. For initial setup and quick start instructions, see Quickstart: Clone-Build-Run and Getting Started. For HPC concepts, see Machine Profiles, Cray Detection, Build Scripts, and Workstation Builds; for machine-specific build/run workflows, see HPC System Guides.
Directory Structure and Workflow¶
ERF builds executables in ERF/Exec when using GNU Make. The exception is development-test work under ERF/.Exec_dev, where GNU Make builds in a problem-specific directory under ERF/.Exec_dev.
With CMake, one configures once to build the core libraries and the shared test executable in build (e.g., erf_exec).
Regardless of how the executable is built, it can be run on regression and canonical tests that have inputs files in subdirectories of Exec/RegTests and Exec/CanonicalTests.
Ctests are run on files in subdirectories of ERF/Tests/test_files.
Directories within Exec are organized into cases used primarily for regression testing and cases representing more canonical tests.
Exec/
├── RegTests/ # Regression test input decks
│ ├── IsentropicVortex/
│ ├── TaylorGreenVortex/
│ ├── Bubble/
│ └── ...
├── CanonicalTests/ # Canonical atmospheric flow input decks
├── ABL/
├── Bomex/
├── SquallLine/
├── SuperCell/
└── ...
Each problem directory contains a README describing its purpose and functionality.
Building with GNU Make¶
System Overview¶
The GNU Make system provides a direct path to producing a single, non-case-specific executable that works for all cases
represented in ERF/Exec/RegTests and ERF/Exec/CanonicalTests.
Depending on the cases of interest, the user must specify in ERF/Exec/GNUmakefile whether the executable should be built
with particle capability (USE\_PARTICLES = TRUE), with NetCDF capability (USE\_NETCDF = TRUE),
with radiation (USE\_RRGMTP = TRUE), and several other compile-time options.
The build is orchestrated by a GNUmakefile in ERF/Exec/ (and similarly in ERF/.Exec_dev for development tests), which uses build logic from the AMReX framework.
How it Works: The Orchestration Process
The GNU Make process uses a hierarchy of includes separating user configuration from application and framework build logic:
GNUmakefile Location: User invokes
makeinERF/Exec/for standard builds, or inERF/.Exec_dev/<test>/for development-test builds.Set AMREX_HOME: The
GNUmakefiledefinesAMREX_HOME, pointing to the AMReX submodule containing core build logic. Default path is$(ERF_HOME)/Submodules/AMReX.Define Build Variables: User defines boolean flags and variables in
GNUmakefileto control which features are compiled (e.g.,USE_MPI,USE_CUDA,USE_RRTMGP).Include ERF Sources:
GNUmakefileincludesExec/Make.ERF, which adds ERF source and header directories to build paths, populatingVPATH_LOCATIONSandINCLUDE_LOCATIONSvariables.Include AMReX Core Logic:
Make.ERFincludes core AMReX makefiles (Make.defsandMake.rules), which contain logic for discovering dependencies, compiling source files, and linking object files into the final executable.
Technical Implementation
The GNU Make build system uses Make.package files and configuration variables (e.g., USE_RRTMGP, USE_NETCDF) in the main Exec/Make.ERF file. These variables conditionally add source files to the build and pass preprocessor definitions (e.g., -DERF_USE_RRTMGP) to the compiler.
This provides:
Direct control over which source files are compiled
Fine-grained compiler flag customization
Debugging via
make print-<variable>to inspect configurationMultiple build configurations coexisting in the same directory
Build Steps¶
1. Clone Repository and Populate Dependencies
See Git Submodules for more details. All dependencies except SHOC and P3 are provided as git submodules:
# Clone with submodules
git clone --recursive https://github.com/erf-model/ERF.git
# Or populate submodules in existing clone
git submodule update --init --recursive
The GNU Make system uses the AMReX submodule path by default. To use an external AMReX installation, set AMREX_HOME:
# Download external AMReX
git clone https://github.com/amrex-codes/amrex.git
# Set environment variable (bash)
export AMREX_HOME=/path/to/external/amrex
# Or for tcsh
setenv AMREX_HOME /path/to/external/amrex
2. Setup for SHOC or P3 (Optional)
If building with SHOC or P3, run the setup scripts:
export ERF_DIR=/path/to/ERF
source /path/to/ERF/Build/GNU_Ekat/eamxx_clone.sh
source /path/to/ERF/Build/GNU_Ekat/ekat_build_commands.sh
Then set USE_SHOC=TRUE or USE_P3=TRUE in your GNUmakefile (step 4).
3. Navigate to GNU Make Build Directory
# Standard workflow
cd ERF/Exec
# Development-test workflow (exception)
# cd ERF/.Exec_dev/<test_name>
4. Edit GNUmakefile
Set build variables in the GNUmakefile:
1 GNU Make Build Variables¶ Variable Name
Description
Default
Possible Values
AMREX_HOMESpecifies path to AMReX source directory
$(ERF_HOME)/Submodules/AMReXPath string
COMPDefines compiler suite to use
None (required)
gnu/intel/cray
DIMSets dimensionality of problem (ERF is 3D only)
3
3
USE_MPIEnables MPI for distributed-memory parallel execution
FALSE
TRUE/FALSE
USE_OMPEnables OpenMP for shared-memory parallelism
FALSE
TRUE/FALSE
USE_CUDAEnables NVIDIA GPU support via CUDA
FALSE
TRUE/FALSE
USE_HIPEnables AMD GPU support via HIP
FALSE
TRUE/FALSE
USE_SYCLEnables Intel GPU support via SYCL
FALSE
TRUE/FALSE
USE_NETCDFEnables I/O support using NetCDF library
FALSE
TRUE/FALSE
USE_PARTICLESEnables support for Lagrangian particles
FALSE
TRUE/FALSE
USE_NOAHMPEnables Noah-MP land surface model (requires
USE_NETCDF=TRUE)FALSE
TRUE/FALSE
USE_RRTMGPEnables RRTMGP radiation model (sets
USE_KOKKOS=TRUE,USE_NETCDF=TRUE)FALSE
TRUE/FALSE
USE_SHOCEnables SHOC turbulence model (sets
USE_KOKKOS=TRUE)FALSE
TRUE/FALSE
USE_P3Enables P3 microphysics model (sets
USE_KOKKOS=TRUE)FALSE
TRUE/FALSE
USE_MULTIBLOCKEnables multiblock capability
FALSE
TRUE/FALSE
USE_KOKKOSEnables Kokkos performance portability library
FALSE
TRUE/FALSE
USE_MORR_FORTEnables Fortran-based Morrison microphysics scheme
FALSE
TRUE/FALSE
USE_FFTEnables Fast Fourier Transform capabilities
FALSE
TRUE/FALSE
DEBUGEnables debug mode
FALSE
TRUE/FALSE
PROFILEIncludes profiling info
FALSE
TRUE/FALSE
TINY_PROFILEIncludes tiny profiling info
FALSE
TRUE/FALSE
COMM_PROFILEIncludes comm profiling info
FALSE
TRUE/FALSE
TRACE_PROFILEIncludes trace profiling info
FALSE
TRUE/FALSE
Note
At most one of USE_OMP, USE_CUDA, USE_HIP, USE_SYCL should be TRUE.
For additional compiler options, see the AMReX documentation.
Example GNUmakefile
Typical GNUmakefile examples:
Exec/GNUmakefile:
# AMReX
COMP = gnu
PRECISION = DOUBLE
# Profiling
PROFILE = FALSE
TINY_PROFILE = FALSE
COMM_PROFILE = FALSE
TRACE_PROFILE = FALSE
MEM_PROFILE = FALSE
USE_GPROF = FALSE
# Performance
USE_MPI = TRUE
USE_OMP = FALSE
USE_CUDA = FALSE
USE_HIP = FALSE
USE_SYCL = FALSE
# Debugging
DEBUG = FALSE
TEST = TRUE
USE_ASSERTION = TRUE
# If running tests in ParticleTests or MultiSpeciesBubble, you must build with USE_PARTICLES = TRUE
#USE_PARTICLES = TRUE
# If running tests in MetGrid or WPS_Test, you must build with USE_NETCDF = TRUE
USE_NETCDF = TRUE
# GNU Make
Bpack := ./Make.package
Blocs := .
ERF_HOME := ../
ERF_PROBLEM_DIR = $(ERF_HOME)/Exec
include $(ERF_HOME)/Exec/Make.ERF
5. Build
make
The executable name encodes build characteristics (dimensionality, compiler, parallelization). For example, in Exec with COMP=gnu and USE_MPI=TRUE, the executable is ERF3d.gnu.MPI.ex. Multiple build configurations can coexist in the same directory.
6. Verify Build (Optional)
View build configuration:
./ERF*ex --describe
Common Commands
Standard utility targets:
make- Compile and create executablemake clean- Remove all build artifactsmake cleanconfig- Remove current configuration artifactsmake print-<variable>- Print value of make variable (e.g.,make print-CXXFLAGS)
For complete documentation, see the AMReX build guide.
Customization with Make.local
For user- or site-specific customizations, create amrex/Tools/GNUMake/Make.local. Settings apply globally to all projects using that AMReX instance. Example for specifying compiler version:
CXX = g++-8
CC = gcc-8
FC = gfortran-8
Running the Executable
Navigate to the executable location based on your chosen workflow:
# If built in Build/ directory:
cd Build/Exec
mpiexec -n 4 ./erf_exec ../../Exec/CanonicalTests/ABL/inputs_most
# If out-of-source build (without install):
cd build/Exec
mpiexec -n 4 ./erf_exec ../../Exec/CanonicalTests/ABL/inputs_most
# If installed to install/:
cd install/bin
mpiexec -n 4 ./erf_exec ../../Exec/CanonicalTests/ABL/inputs_most
# If using cmake_with_kokkos_many.sh with defaults:
cd install/bin # or cd $ERF_INSTALL_DIR/bin if customized or cd $ERF_BUILD_DIR/Exec
mpiexec -n 4 ./erf_exec ../../Exec/CanonicalTests/ABL/inputs_most
For details on input files and job submission, see Running.
Building Documentation¶
Build ERF documentation with GNU Make:
cd ERF/Docs/
source BuildDocs.sh
This builds both Sphinx and Doxygen documentation.
Building with CMake¶
System Overview¶
CMake is a cross-platform build tool using a framework-centric approach. Instead of producing a single executable for one use case, CMake produces versioned, exportable libraries as well as multiple executables across the problem directory setups. This enables generation of find_package-compatible configuration files (ERFConfig.cmake), allowing other CMake projects to consume ERF as a dependency.
CMake provides:
Out-of-source builds keeping artifacts separate from source code
Robust dependency detection through
find_packageAutomated detection and configuration for Cray HPC systems
Testing and verification through CTest
CMake is recommended for HPC environments where automated dependency detection and robust cross-platform builds are important.
Technical Implementation
CMake uses option() commands in CMakeLists.txt (e.g., option(ERF_ENABLE_MPI "Enable MPI" OFF)) to generate user-configurable cache variables. These variables control which features are included and how dependencies are linked.
This provides:
Automated dependency detection through
find_packagePolicy-based configuration (e.g., Cray Detection System)
Clean separation between source and build artifacts
CTest integration for testing
Exportable libraries for downstream projects
Build Steps¶
1. Clone Repository and Prerequisites
Clone with submodules:
# Clone with submodules
git clone --recursive https://github.com/erf-model/ERF.git
# Or populate submodules in existing clone
git submodule update --init --recursive
2. Setup for SHOC or P3 (Optional)
If building with SHOC or P3:
export ERF_DIR=/path/to/ERF
source /path/to/ERF/Build/GNU_Ekat/eamxx_clone.sh
Then configure with -DERF_ENABLE_SHOC=TRUE and/or -DERF_ENABLE_P3=TRUE (step 4).
3. Choose Build Workflow
ERF supports multiple CMake workflows. The main difference is directory structure and whether you use the install step.
Build artifacts and executables in the Build/ directory tree. Executables appear in Exec/<problem>/ subdirectories, similar to GNU Make workflow.
cd Build
./cmake.sh
Executable locations: Build/Exec/erf_exec
Cleanup for rebuild:
make distclean
./cmake.sh
Build directory separate from source. Executables in build/Exec/<problem>/ subdirectories. Optionally use install step to copy all executables to a single install/bin/ directory.
mkdir build && cd build
../Build/cmake.sh
make install # optional - copies to install/bin/ (may be needed for builds that require kokkos)
Executable locations: build/Exec/erf_exec, etc., and optionally install/bin/erf_exec (if installed)
Cleanup for rebuild:
rm -rf build/ install/ # complete cleanup
mkdir build && cd build
Uses environment variables for directory control. Defaults: build in current dir (.), source from parent (..), install to install/.
Customize directories (optional):
Set ERF_BUILD_DIR, ERF_SOURCE_DIR, ERF_INSTALL_DIR, or ERF_HOME environment variables.
# From ERF repository root (sets absolute paths)
ERF_HOME=$(pwd) ./Build/cmake_with_kokkos_many.sh
# Or customize individual directories
ERF_BUILD_DIR=build ERF_INSTALL_DIR=install ./Build/cmake_with_kokkos_many.sh
# Or use defaults from any directory
cd ERF
./Build/cmake_with_kokkos_many.sh
Executable locations: $ERF_BUILD_DIR/Exec/erf_exec and $ERF_INSTALL_DIR/bin/erf_exec (defaults: ./Exec/erf_exec and install/bin/erf_exec)
Cleanup for rebuild:
# If using defaults
rm -rf . install/ # from build directory
# If using ERF_HOME
rm -rf $ERF_HOME/build $ERF_HOME/install
# Then rebuild
./Build/cmake_with_kokkos_many.sh
Workflow Comparison
Executable Locations:
After make: Executables always in
<build_dir>/Exec/<problem>/erf_<problem>(mirrors source tree)After make install: Executables copied to
<install_prefix>/bin/erf_<problem>(all in one location)
Install step is optional - it copies executables from Exec subdirectories to a single bin/ directory for convenience.
Choose based on:
Familiarity with GNU Make workflow → in Build/ directory
Want separate build/source trees → out-of-source build
Prefer all executables in one place → use install step
Running multiple configurations → separate build directories
Minimal typing from repository root → use script with -B/-S
4. Configure with Options
For manual configuration, use -D<VARIABLE>=<VALUE> syntax:
cmake -DCMAKE_BUILD_TYPE=Release \
-DERF_ENABLE_MPI=ON \
-DCMAKE_CXX_COMPILER=mpicxx \
-DCMAKE_C_COMPILER=mpicc \
-DCMAKE_Fortran_COMPILER=mpifort \
.. && make
CMake can also generate makefiles for the Ninja build system for faster compilation.
Example Configuration Script
Build/cmake_cuda.sh:
#!/bin/bash
# Defaults (customize here or set ERF_BUILD_DIR/ERF_SOURCE_DIR/ERF_INSTALL_DIR in environment)
# If ERF_HOME is set, use it as base for absolute paths
if [ -n "$ERF_HOME" ]; then
: ${ERF_BUILD_DIR:="$ERF_HOME/build"}
: ${ERF_SOURCE_DIR:="$ERF_HOME"}
: ${ERF_INSTALL_DIR:="$ERF_HOME/install"}
else
: ${ERF_BUILD_DIR:="."}
: ${ERF_SOURCE_DIR:=".."}
: ${ERF_INSTALL_DIR:="install"}
fi
echo "Source: $ERF_SOURCE_DIR | Build: $ERF_BUILD_DIR | Install: $ERF_INSTALL_DIR | PWD: $(pwd)"
echo "Customize: export ERF_BUILD_DIR=... ERF_SOURCE_DIR=... ERF_INSTALL_DIR=... or ERF_HOME=..."
cmake -DCMAKE_INSTALL_PREFIX:PATH=$ERF_INSTALL_DIR \
-DMPIEXEC_PREFLAGS:STRING=--oversubscribe \
-DCMAKE_BUILD_TYPE:STRING=Release \
-DERF_DIM:STRING=3 \
-DERF_ENABLE_MPI:BOOL=ON \
-DERF_ENABLE_CUDA:BOOL=ON \
-DERF_ENABLE_TESTS:BOOL=ON \
-DERF_ENABLE_FCOMPARE:BOOL=ON \
-DERF_ENABLE_DOCUMENTATION:BOOL=OFF \
-DCMAKE_EXPORT_COMPILE_COMMANDS:BOOL=ON \
--log-context --log-level STATUS \
-B $ERF_BUILD_DIR -S $ERF_SOURCE_DIR && \
cmake --build $ERF_BUILD_DIR -j10 && \
cmake --install $ERF_BUILD_DIR --prefix=$ERF_INSTALL_DIR
CMake Options:
Variable Name |
Description |
Default |
Possible Values |
|---|---|---|---|
|
Sets build configuration |
Release |
Release/Debug/RelWithDebInfo |
|
Enables MPI support for parallel execution |
OFF |
ON/OFF |
|
Enables OpenMP for shared-memory parallelism |
OFF |
ON/OFF |
|
Enables NVIDIA GPU support via CUDA (requires Toolkit >= 11.0) |
OFF |
ON/OFF |
|
Enables AMD GPU support via HIP |
OFF |
ON/OFF |
|
Enables Intel GPU support via SYCL |
OFF |
ON/OFF |
|
Enables NetCDF for I/O operations |
OFF |
ON/OFF |
|
Enables support for Lagrangian particles |
OFF |
ON/OFF |
|
Floating-point precision for mesh data |
DOUBLE |
SINGLE/DOUBLE |
|
Floating-point precision for particle data; defaults to |
DOUBLE |
SINGLE/DOUBLE |
|
Enables multiblock capability |
OFF |
ON/OFF |
|
Enables Noah-MP land surface model (requires |
OFF |
ON/OFF |
|
Enables RRTMGP radiation model (requires |
OFF |
ON/OFF |
|
Enables SHOC turbulence model (requires |
OFF |
ON/OFF |
|
Enables P3 microphysics model (requires |
OFF |
ON/OFF |
|
Enables CTest test suite |
OFF |
ON/OFF |
|
Enables fcompare utility for regression testing |
OFF |
ON/OFF |
|
Enables build target for generating Sphinx documentation |
OFF |
ON/OFF |
|
Directory where |
System-dependent |
Path string |
Note
At most one of ERF_ENABLE_OPENMP, ERF_ENABLE_CUDA, ERF_ENABLE_HIP, ERF_ENABLE_SYCL should be ON.
Feature Dependencies
I/O and Analysis
ERF_ENABLE_NETCDF- Enables NetCDF I/O for reading WRF input files and writing plotfilesERF_ENABLE_HDF5- Automatically enabled when NetCDF is enabled (provides parallel I/O backend)ERF_ENABLE_FFT- Enables Fast Fourier Transform for spectral analysis
Physics Packages
ERF_ENABLE_RRTMGP- RRTMGP radiation modelRequires
ERF_ENABLE_NETCDF=ONandERF_ENABLE_MPI=ONAutomatically enables
ERF_ENABLE_EKAT=ON(provides Kokkos)
ERF_ENABLE_SHOC- SHOC turbulence and cloud macrophysicsRequires
ERF_ENABLE_MPI=ONAutomatically enables
ERF_ENABLE_EKAT=ON(provides Kokkos)Additional step: Run
source Build/GNU_Ekat/eamxx_clone.sh
ERF_ENABLE_P3- P3 microphysicsRequires
ERF_ENABLE_MPI=ONAutomatically enables
ERF_ENABLE_EKAT=ON(provides Kokkos)
ERF_ENABLE_NOAHMP- NOAHMP land surface modelRequires the NetCDF Fortran library
GPU Acceleration
Enable exactly one GPU backend:
ERF_ENABLE_CUDA- NVIDIA GPUs (requires CUDA Toolkit ≥ 11.0)ERF_ENABLE_HIP- AMD GPUsERF_ENABLE_SYCL- Intel GPUs
Note
Kokkos-based physics packages (RRTMGP, SHOC, P3) support all three GPU backends through EKAT’s Kokkos integration.
Logging Options (CMake 3.25+)
Use hierarchical logging to diagnose build issues:
# Default output
cmake ..
# Show dependency detection
cmake --log-level=VERBOSE ..
# Show all diagnostics
cmake --log-level=DEBUG ..
# Show message hierarchy
cmake --log-context ..
# Combine for detailed output
cmake --log-context --log-level=VERBOSE ..
Example output with --log-context:
[ERF.Cray] Detected Cray Programming Environment (CRAYPE_VERSION=2.7.30)
[ERF.Cray] Setting Cray compiler wrappers...
[ERF.Cray] Set CMAKE_CXX_COMPILER = /opt/cray/pe/craype/default/bin/CC
[ERF.AMReX] Using internal AMReX submodule
[ERF.NetCDF] Found NetCDF: /opt/cray/pe/netcdf/4.9.0.9
Utility Targets
Clean Build Artifacts
Remove all CMake configuration and build artifacts:
make distclean
Removes:
CMake cache and generated files (
CMakeCache.txt,CMakeFiles/, etc.)Build outputs (executables, libraries)
Generated configuration files
Test outputs
The install directory is preserved.
Uninstall
Remove files installed via make install:
make uninstall
Show Cray Configuration
On Cray systems, view auto-detected configuration:
make show-cray-config
This displays detected configuration and can be saved for manual configuration.
Configuration Files
On Cray systems, ERF automatically detects configuration. For manual configuration, use the -C option:
cmake -C path/to/config.cmake ..
Machine-specific profiles in Build/machines/:
perlmutter_erf.profile- NERSC Perlmutter (NVIDIA A100)frontier_erf.profile- OLCF Frontier (AMD MI250X)polaris_erf.profile- ALCF Polaris (NVIDIA A100)aurora_erf.profile- ALCF Aurora (Intel GPUs); expectsNETCDF_DIRfor NetCDF-enabled builds
These profiles are shell scripts that load required modules and set environment variables. Source them before running CMake. For detailed information, see Machine Profiles, Cray Detection, Build Scripts, and Workstation Builds.
Developer Testing
For systematic testing of multiple build configurations:
#!/bin/bash
set -e
set -o pipefail
# Function to verify if a directory is the ERF repo root
verify_erf_dir() {
local dir=$1
# Check for basic structure
if [ ! -f "$dir/CMakeLists.txt" ] || [ ! -d "$dir/Source" ]; then
return 1
fi
# Check for "Energy Research and Forecasting" in key files
local found=0
if [ -f "$dir/README.rst" ]; then
if grep -q "Energy Research and Forecasting" "$dir/README.rst" 2>/dev/null || true; then
found=1
fi
fi
if [ $found -eq 0 ] && [ -f "$dir/LICENSE.md" ]; then
if grep -q "Energy Research and Forecasting" "$dir/LICENSE.md" 2>/dev/null || true; then
found=1
fi
fi
if [ $found -eq 0 ] && [ -f "$dir/CITATION.cff" ]; then
if grep -q "Energy Research and Forecasting" "$dir/CITATION.cff" 2>/dev/null || true; then
found=1
fi
fi
return $((1 - found))
}
# Function to find ERF repo root
find_erf_dir() {
# Method 1: Check if we're already in Build/
if [ -f "../CMakeLists.txt" ] && [ -d "../Source" ]; then
local candidate="$(cd .. && pwd)"
if verify_erf_dir "$candidate"; then
ERF_DIR="$candidate"
echo "Detected ERF_DIR from Build location: $ERF_DIR"
return 0
fi
fi
# Method 2: Use git to find repo root
if command -v git &> /dev/null; then
if git rev-parse --is-inside-work-tree &> /dev/null 2>&1; then
local git_root="$(git rev-parse --show-toplevel)"
if verify_erf_dir "$git_root"; then
ERF_DIR="$git_root"
echo "Detected ERF_DIR from git: $ERF_DIR"
return 0
fi
fi
fi
# Method 3: Try going up from script location
local script_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
# Check if script is in Build/ directory
if [[ "$script_dir" =~ /Build$ ]]; then
local candidate="$(dirname "$script_dir")"
if verify_erf_dir "$candidate"; then
ERF_DIR="$candidate"
echo "Detected ERF_DIR from script location: $ERF_DIR"
return 0
fi
fi
# Method 4: Check current directory
if verify_erf_dir "$PWD"; then
ERF_DIR="$PWD"
echo "Detected ERF_DIR from current directory: $ERF_DIR"
return 0
fi
return 1
}
# Parse arguments
if [ $# -lt 1 ] || [ $# -gt 3 ]; then
echo "Usage: $0 <set> [script_pattern] [erf_dir]"
echo ""
echo "Sets:"
echo " default - Scripts from Build/"
echo " perlmutter - Scripts from Build/Perlmutter/"
echo " gnu_ekat - Scripts from Build/GNU_Ekat/"
echo ""
echo "If script_pattern is provided, creates build_<pattern>/"
echo "Otherwise creates build_<set>/"
echo ""
echo "If erf_dir is provided, uses that as ERF_DIR"
echo "Otherwise auto-detects ERF repo root"
exit 1
fi
SET=$1
PATTERN=${2:-}
ERF_DIR_ARG=${3:-}
# Set ERF_DIR
if [ -n "$ERF_DIR_ARG" ]; then
ERF_DIR="$ERF_DIR_ARG"
echo "Using provided ERF_DIR: $ERF_DIR"
if ! verify_erf_dir "$ERF_DIR"; then
echo "Error: Provided directory is not a valid ERF repository"
echo "Must contain 'Energy Research and Forecasting' in README.rst, LICENSE.md, or CITATION.cff"
exit 1
fi
else
if ! find_erf_dir; then
echo "Error: Could not auto-detect ERF_DIR"
echo "Please provide it as the third argument or run from ERF Build/ directory"
echo ""
echo "Verification checks for:"
echo " - CMakeLists.txt and Source/ directory"
echo " - 'Energy Research and Forecasting' in README.rst, LICENSE.md, or CITATION.cff"
exit 1
fi
fi
echo "ERF_DIR set to: $ERF_DIR"
# Define source directories relative to ERF_DIR
DEFAULT_DIR="$ERF_DIR/Build"
PERLMUTTER_DIR="$ERF_DIR/Build/Perlmutter"
GNU_EKAT_DIR="$ERF_DIR/Build/GNU_Ekat"
case $SET in
default)
SRC_DIR="$DEFAULT_DIR"
;;
perlmutter)
SRC_DIR="$PERLMUTTER_DIR"
;;
gnu_ekat)
SRC_DIR="$GNU_EKAT_DIR"
;;
*)
echo "Error: Invalid set '$SET'"
echo "Choose: default, perlmutter, or gnu_ekat"
exit 1
;;
esac
if [ ! -d "$SRC_DIR" ]; then
echo "Error: Source directory does not exist: $SRC_DIR"
exit 1
fi
# Determine build directory name
if [ -n "$PATTERN" ]; then
BUILD_DIR="$ERF_DIR/build_${PATTERN}"
else
BUILD_DIR="$ERF_DIR/build_${SET}"
fi
# Create build directory
mkdir -p "$BUILD_DIR"
echo "Created directory: $BUILD_DIR"
# Find and copy ERF cmake build scripts
echo "Scanning for ERF cmake scripts in $SRC_DIR:"
COPIED=0
SKIPPED=0
# Temporarily disable exit on error for the loop
set +e
for script in "$SRC_DIR"/*.sh; do
# Check if file exists (glob might not match anything)
if [ ! -f "$script" ]; then
continue
fi
basename_script=$(basename "$script")
# Skip backup files
if [[ "$basename_script" =~ ~$ ]]; then
SKIPPED=$((SKIPPED + 1))
continue
fi
# Check if it's an ERF cmake script (contains DERF or cmake)
has_derf=0
has_cmake=0
grep -q "DERF" "$script" 2>/dev/null && has_derf=1
grep -q "cmake" "$script" 2>/dev/null && has_cmake=1
if [ $has_derf -eq 1 ] || [ $has_cmake -eq 1 ]; then
cp "$script" "$BUILD_DIR/"
chmod +x "$BUILD_DIR/$basename_script"
echo " DONE: $basename_script"
COPIED=$((COPIED + 1))
else
echo " ERROR: $basename_script (no DERF or cmake found)"
SKIPPED=$((SKIPPED + 1))
fi
done
# Re-enable exit on error
set -e
echo ""
echo "Summary: Copied $COPIED script(s), skipped $SKIPPED"
if [ $COPIED -eq 0 ]; then
echo "Warning: No ERF cmake scripts found"
echo "Scripts should contain 'DERF' or 'cmake'"
fi
# Create a run script in the build directory
cat > "$BUILD_DIR/run.sh" << 'EOF'
#!/bin/bash
set -e
set -o pipefail
# Resolve ERF_DIR (go up from build directory)
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
export ERF_DIR="$(dirname "$SCRIPT_DIR")"
echo "ERF_DIR set to: $ERF_DIR"
# Find all .sh scripts (excluding run.sh and backups)
SCRIPTS=()
for script in *.sh; do
if [ "$script" = "run.sh" ]; then
continue
fi
if [[ "$script" =~ ~$ ]]; then
continue
fi
if [ -f "$script" ]; then
SCRIPTS+=("$script")
fi
done
# Sort scripts alphabetically
IFS=$'\n' SCRIPTS=($(sort <<<"${SCRIPTS[*]}"))
unset IFS
if [ ${#SCRIPTS[@]} -eq 0 ]; then
echo "Error: No build scripts found in this directory"
exit 1
fi
if [ $# -ne 1 ]; then
echo "Usage: $0 <number>"
echo ""
echo "Available ERF cmake scripts:"
for i in "${!SCRIPTS[@]}"; do
script_base="${SCRIPTS[$i]%.sh}"
printf "%3d: %s\n" $((i+1)) "${SCRIPTS[$i]}"
printf " -> subdirectory: %s/script_%s/\n" "$ERF_DIR" "$script_base"
done
echo ""
echo "Each script will run in its own clean subdirectory at ERF root."
exit 1
fi
NUM=$1
if [ $NUM -lt 1 ] || [ $NUM -gt ${#SCRIPTS[@]} ]; then
echo "Error: Number must be between 1 and ${#SCRIPTS[@]}"
exit 1
fi
SCRIPT="${SCRIPTS[$((NUM-1))]}"
SCRIPT_BASE="${SCRIPT%.sh}"
SUBDIR="$ERF_DIR/script_${SCRIPT_BASE}"
# Create a clean subdirectory for this script
if [ -d "$SUBDIR" ]; then
echo "Warning: $SUBDIR already exists"
read -p "Delete and recreate? (y/N) " -n 1 -r
echo
if [[ $REPLY =~ ^[Yy]$ ]]; then
rm -rf "$SUBDIR"
else
echo "Aborting. Please remove $SUBDIR manually or choose a different script."
exit 1
fi
fi
mkdir -p "$SUBDIR"
echo "========================================"
echo "Running: $SCRIPT"
echo "Build directory: $SUBDIR"
echo "Working directory: $SUBDIR"
echo "========================================"
echo ""
# Copy the script into the subdirectory and run it there
cp "$SCRIPT" "$SUBDIR/"
cd "$SUBDIR"
bash "./$SCRIPT"
EOF
chmod +x "$BUILD_DIR/run.sh"
echo ""
echo "Setup complete!"
echo "Build directory: $BUILD_DIR"
echo ""
echo "To use:"
echo " cd $BUILD_DIR"
echo " ./run.sh # List available scripts"
echo " ./run.sh <number> # Run a specific script"
echo ""
echo "Copied $COPIED script(s)"
Usage:
cd Build
./setup_cmake_validation.sh default # or perlmutter, gnu_ekat
cd ../build_default
./run.sh # List available scripts
./run.sh 1 # Run first script
Creates isolated build directories for each configuration script. Each script runs in its own subdirectory (script_<name>/) at the ERF root.
Building Documentation¶
Build ERF documentation with CMake:
cmake -DERF_ENABLE_DOCUMENTATION=ON ..
make docs
This builds both Sphinx and Doxygen documentation.