diff --git a/scripts/build_native_fvs.sh b/scripts/build_native_fvs.sh new file mode 100755 index 0000000..b41e5d5 --- /dev/null +++ b/scripts/build_native_fvs.sh @@ -0,0 +1,62 @@ +#!/usr/bin/env bash +# +# Build native FVS shared libraries for pyfvs parity testing. +# +# Compiles each requested FVS variant from the USDA Fortran source into a +# loadable shared library (FVS.so) and installs it to ~/.fvs/lib, +# where pyfvs.native and the parity suite discover it. +# +# Usage: +# scripts/build_native_fvs.sh # build all pyfvs variants +# scripts/build_native_fvs.sh sn ls ne # build a subset (lowercase codes) +# +# Environment: +# FVS_SRC FVS source checkout (default: ~/Projects/ForestVegetationSimulator) +# FVS_LIB_PATH / LIBDIR install dir (default: ~/.fvs/lib) +# JOBS max concurrent variant builds (default: 4) +# +# Requires: gfortran, gcc, make. The volume/NVEL git submodule is initialized +# automatically if absent (the build fails without it). +set -uo pipefail + +FVS_SRC="${FVS_SRC:-$HOME/Projects/ForestVegetationSimulator}" +LIBDIR="${LIBDIR:-${FVS_LIB_PATH:-$HOME/.fvs/lib}}" +JOBS="${JOBS:-4}" +LOGDIR="${LOGDIR:-$FVS_SRC/bin/_build_logs}" + +# pyfvs-implemented variants (10 + EC). FVS ships 20 geographic variants total. +PYFVS_VARIANTS="sn ls cs ne pn wc ec ca ws op oc" + +# --- child mode: build a single variant (re-invoked by xargs below) ---------- +if [ "${1:-}" = "--build-one" ]; then + v="$2" + lib="FVS${v}.so" + mkdir -p "$LIBDIR" + ( cd "$FVS_SRC/bin" && rm -rf "FVS${v}_buildDir" && make "$lib" ) \ + > "$LOGDIR/build_${v}.log" 2>&1 + if [ -f "$FVS_SRC/bin/$lib" ]; then + cp "$FVS_SRC/bin/$lib" "$LIBDIR/$lib" + codesign -s - "$LIBDIR/$lib" >/dev/null 2>&1 || true # macOS ad-hoc sign + echo "OK $v -> $LIBDIR/$lib" + else + echo "FAIL $v (see $LOGDIR/build_${v}.log)" + fi + exit 0 +fi + +# --- main dispatch ----------------------------------------------------------- +if [ "$#" -gt 0 ]; then VARIANTS="$*"; else VARIANTS="$PYFVS_VARIANTS"; fi + +# Ensure the NVEL volume library submodule is present. +if [ ! -f "$FVS_SRC/volume/NVEL/beqinfo.inc" ]; then + echo "Initializing volume/NVEL submodule..." + git -C "$FVS_SRC" submodule update --init --recursive +fi + +mkdir -p "$LOGDIR" "$LIBDIR" +export FVS_SRC LIBDIR LOGDIR + +echo "Building variants: $VARIANTS (JOBS=$JOBS, install -> $LIBDIR)" +printf '%s\n' $VARIANTS | xargs -P "$JOBS" -n1 "$0" --build-one +echo "Done. Installed libraries:" +ls -1 "$LIBDIR"/FVS*.so 2>/dev/null || echo " (none)" diff --git a/src/pyfvs/native/BUILD.md b/src/pyfvs/native/BUILD.md index ac474b7..5bb1d22 100644 --- a/src/pyfvs/native/BUILD.md +++ b/src/pyfvs/native/BUILD.md @@ -3,6 +3,38 @@ Instructions for building the native FVS Fortran shared libraries for use with `pyfvs.native` validation bindings. +## Quick build (recommended) + +From the pyfvs repo, build and install all variants the parity suite needs: + +```bash +scripts/build_native_fvs.sh # all 11 pyfvs variants -> ~/.fvs/lib +scripts/build_native_fvs.sh sn ls ne # or a subset (lowercase codes) +``` + +The script compiles each variant from the FVS Fortran source (default +`~/Projects/ForestVegetationSimulator`) via the repo's own makefile, installs +`FVS.so` into `~/.fvs/lib`, and ad-hoc code-signs on macOS. + +**Gotcha:** the FVS source tree's `volume/NVEL` (National Volume Estimator +Library) is a **git submodule**. A fresh clone/restore leaves it empty and the +build fails with `No rule to make target '../volume/NVEL/beqinfo.inc'`. The +script initializes it automatically; to do it by hand: + +```bash +git -C ~/Projects/ForestVegetationSimulator submodule update --init --recursive +``` + +Then run the parity suite. The parity tests are auto-marked `parity` and the +default pytest config deselects them (`-m "not slow and not parity"`), so you +**must** opt in explicitly: + +```bash +uv run pytest tests/parity/ -m parity +``` + +The manual, single-variant steps below are kept for reference. + ## Prerequisites ### macOS @@ -26,7 +58,8 @@ sudo apt install gfortran make ### 1. Clone the FVS repository ```bash -git clone https://github.com/USDAForestService/ForestVegetationSimulator.git +# --recursive pulls the volume/NVEL submodule (required for the build) +git clone --recursive https://github.com/USDAForestService/ForestVegetationSimulator.git cd ForestVegetationSimulator ```