diff --git a/.github/workflows/run_all_quickbuilds.yml b/.github/workflows/run_all_quickbuilds.yml index a153aa0064..49f7468b7c 100644 --- a/.github/workflows/run_all_quickbuilds.yml +++ b/.github/workflows/run_all_quickbuilds.yml @@ -68,6 +68,9 @@ jobs: *GMI* | *GOES* | *forward_operators* | *NSIDC* ) cp /home/mkmf.template.rttov.gfortran mkmf.template ;; + *library*) + cp ../developer_tests/library/mkmf.template.gfortran mkmf.template + ;; *) cp mkmf.template.gfortran mkmf.template echo 'FFLAGS = -g -Wuninitialized -Wunused -ffree-line-length-none -fbounds-check -fbacktrace -ffpe-trap=invalid,zero,overflow $(INCS)' >> mkmf.template diff --git a/.gitignore b/.gitignore index 5d1f27c778..7d4937541c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,5 @@ +*.a +*.so *.mod *.o *.swp diff --git a/CHANGELOG.rst b/CHANGELOG.rst index d50c46d295..5e2c1706f5 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -22,6 +22,12 @@ individual files. The changes are now listed with the most recent at the top. +**July 26 2024 :: Library build tools for DART. Tag v11.6.0** + +- Buildtools for compiling DART as a shared or a static library. +- Bugfix: correct order of arguments in count_state_ens_copies for 'input' + stages_to_write. + **July 11 2024 :: Bgrid documentation and scripting fix. Tag v11.5.1** - Updated Bgrid documentation and removed outdated scripts and files diff --git a/build_templates/buildfunctions.sh b/build_templates/buildfunctions.sh index e83475c7e5..f8188a8cad 100644 --- a/build_templates/buildfunctions.sh +++ b/build_templates/buildfunctions.sh @@ -84,6 +84,8 @@ for p in ${all_programs[@]}; do done \rm -f -- preprocess +\rm -f -- libdart.a +\rm -f -- libdart.so cleanpreprocess } @@ -253,6 +255,16 @@ fi $program } +#------------------------- +# Build a library +# +#------------------------- +function buildlib() { +findsrc +$DART/build_templates/mkmf -x -a $DART $m -p $1 \ + $dartsrc \ + $EXTRA +} #------------------------- # Build a model specific program # looks in $DART/models/$MODEL/src/programs for {main}.f90 diff --git a/build_templates/mkmf b/build_templates/mkmf index 821982978d..dbd8ea45f1 100755 --- a/build_templates/mkmf +++ b/build_templates/mkmf @@ -73,7 +73,7 @@ my $endline = $/; my @src_suffixes = ( q/\.F/, q/\.F90/, q/\.c/, q/\.f/, q/\.f90/ ); my @inc_suffixes = ( q/\.H/, q/\.fh/, q/\.h/, q/\.inc/ ); push @inc_suffixes, @src_suffixes; # sourcefiles can be includefiles too -my @tgt_suffixes = ( q/\.a/ ); +my @tgt_suffixes = ( q/\.a/, q/\.so/ ); print "Using MPI wrappers\n" if $opt_w; my %compile_cmd; @@ -481,6 +481,12 @@ print MAKEFILE "tags: \$(SRC)\n\tctags \$(SRC)\n"; ( $name, $path, $suffix ) = fileparse( $opt_p, @tgt_suffixes ); if( $suffix eq '.a' ) { print MAKEFILE "$opt_p: \$(OBJ)\n\t\$(AR) \$(ARFLAGS) $opt_p \$(OBJ)\n"; +} elsif ( $suffix eq '.so' ) { + if ( $opt_w ) { + print MAKEFILE "$opt_p: \$(OBJ)\n\t\$(MPILD) \$(SHR) \$(OBJ) -o $opt_p \$(LDFLAGS)"; + } else { + print MAKEFILE "$opt_p: \$(OBJ)\n\t\$(LD) \$(SHR) \$(OBJ) -o $opt_p \$(LDFLAGS)"; + } } elsif ( $opt_w ){ print MAKEFILE "$opt_p: \$(OBJ)\n\t\$(MPILD) \$(OBJ) -o $opt_p $opt_l \$(LDFLAGS)\n"; } else { diff --git a/conf.py b/conf.py index db0041097f..deb053a0be 100644 --- a/conf.py +++ b/conf.py @@ -21,7 +21,7 @@ author = 'Data Assimilation Research Section' # The full version, including alpha/beta/rc tags -release = '11.5.1' +release = '11.6.0' root_doc = 'index' # -- General configuration --------------------------------------------------- diff --git a/developer_tests/library/mkmf.template.gfortran b/developer_tests/library/mkmf.template.gfortran new file mode 100644 index 0000000000..46f8e087f3 --- /dev/null +++ b/developer_tests/library/mkmf.template.gfortran @@ -0,0 +1,23 @@ +# Template for GNU gfortran on Linux or Mac OSX +# +# DART software - Copyright UCAR. This open source software is provided +# by UCAR, "as is", without charge, subject to all terms of use at +# http://www.image.ucar.edu/DAReS/DART/DART_download +# + +MPIFC = mpif90 +MPILD = mpif90 +FC = gfortran +LD = gfortran + +#NETCDF = /opt/local + +INCS = -I$(NETCDF)/include +LIBS = -L$(NETCDF)/lib -lnetcdff -lnetcdf +FFLAGS = -O2 -ffree-line-length-none -fPIC $(INCS) +LDFLAGS = $(FFLAGS) $(LIBS) +SHR = -shared + +# FFLAGS = -g -Wuninitialized -Wunused -ffree-line-length-none -fbounds-check \ +# -fbacktrace -ffpe-trap=invalid,zero,overflow $(INCS) + diff --git a/developer_tests/library/shared/work/input.nml b/developer_tests/library/shared/work/input.nml new file mode 100644 index 0000000000..a088a84317 --- /dev/null +++ b/developer_tests/library/shared/work/input.nml @@ -0,0 +1,18 @@ +&preprocess_nml + overwrite_output = .true. + input_obs_def_mod_file = '../../../../observations/forward_operators/DEFAULT_obs_def_mod.F90' + output_obs_def_mod_file = '../../../../observations/forward_operators/obs_def_mod.f90' + input_obs_qty_mod_file = '../../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' + output_obs_qty_mod_file = '../../../../assimilation_code/modules/observations/obs_kind_mod.f90' + obs_type_files = '../../../../observations/forward_operators/obs_def_1d_state_mod.f90' + quantity_files = '../../../../assimilation_code/modules/observations/oned_quantities_mod.f90' + / + +&utilities_nml + termlevel = 1, + module_details = .false., + logfilename = 'dart_log.out', + nmlfilename = 'dart_log.nml', + write_nml = 'file', + print_debug = .false., + / diff --git a/developer_tests/library/shared/work/quickbuild.sh b/developer_tests/library/shared/work/quickbuild.sh new file mode 100755 index 0000000000..f9b029fc33 --- /dev/null +++ b/developer_tests/library/shared/work/quickbuild.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# DART software - Copyright UCAR. This open source software is provided +# by UCAR, "as is", without charge, subject to all terms of use at +# http://www.image.ucar.edu/DAReS/DART/DART_download + +main() { + + +export DART=$(git rev-parse --show-toplevel) +source "$DART"/build_templates/buildfunctions.sh + +MODEL=lorenz_96 +LOCATION=oned + +# quickbuild arguments +arguments "$@" + +# clean the directory +\rm -f -- libdart.so *.o *.mod Makefile .cppdefs + +# build any NetCDF files from .cdl files +cdl_to_netcdf + +# build and run preprocess before making any other DART executables +buildpreprocess + +# build static library +buildlib libdart.so + +# clean up +\rm -f -- *.o + +} + +main "$@" diff --git a/developer_tests/library/static/work/input.nml b/developer_tests/library/static/work/input.nml new file mode 100644 index 0000000000..a088a84317 --- /dev/null +++ b/developer_tests/library/static/work/input.nml @@ -0,0 +1,18 @@ +&preprocess_nml + overwrite_output = .true. + input_obs_def_mod_file = '../../../../observations/forward_operators/DEFAULT_obs_def_mod.F90' + output_obs_def_mod_file = '../../../../observations/forward_operators/obs_def_mod.f90' + input_obs_qty_mod_file = '../../../../assimilation_code/modules/observations/DEFAULT_obs_kind_mod.F90' + output_obs_qty_mod_file = '../../../../assimilation_code/modules/observations/obs_kind_mod.f90' + obs_type_files = '../../../../observations/forward_operators/obs_def_1d_state_mod.f90' + quantity_files = '../../../../assimilation_code/modules/observations/oned_quantities_mod.f90' + / + +&utilities_nml + termlevel = 1, + module_details = .false., + logfilename = 'dart_log.out', + nmlfilename = 'dart_log.nml', + write_nml = 'file', + print_debug = .false., + / diff --git a/developer_tests/library/static/work/quickbuild.sh b/developer_tests/library/static/work/quickbuild.sh new file mode 100755 index 0000000000..25b868ac39 --- /dev/null +++ b/developer_tests/library/static/work/quickbuild.sh @@ -0,0 +1,36 @@ +#!/usr/bin/env bash + +# DART software - Copyright UCAR. This open source software is provided +# by UCAR, "as is", without charge, subject to all terms of use at +# http://www.image.ucar.edu/DAReS/DART/DART_download + +main() { + + +export DART=$(git rev-parse --show-toplevel) +source "$DART"/build_templates/buildfunctions.sh + +MODEL=lorenz_96 +LOCATION=oned + +# quickbuild arguments +arguments "$@" + +# clean the directory +\rm -f -- libdart.a *.o *.mod Makefile .cppdefs + +# build any NetCDF files from .cdl files +cdl_to_netcdf + +# build and run preprocess before making any other DART executables +buildpreprocess + +# build static library +buildlib libdart.a + +# clean up +\rm -f -- *.o + +} + +main "$@" diff --git a/developer_tests/library/test_libraries.sh b/developer_tests/library/test_libraries.sh new file mode 100755 index 0000000000..614e89737b --- /dev/null +++ b/developer_tests/library/test_libraries.sh @@ -0,0 +1,97 @@ +#!/usr/bin/env bash + +set -e +export DART=$(git rev-parse --show-toplevel) + +main () { + +NETCDF_LIB=/opt/local/ +testdir=$(pwd) + +# remove any previous test directoires +rm -rf nolib +rm -rf sharedlib +rm -rf staticlib + +# use library mkmf.template +cp "$testdir"/mkmf.template.gfortran "$DART"/build_templates/mkmf.template + +# regular filter build - this goes first so test directories get *.nc and obs_seq.out input files +cd "$DART"/models/lorenz_96/work +./quickbuild.sh clean +./quickbuild.sh mpif08 filter +rm *.o *.mod + +#----------------- +# setup test direcories +cd "$testdir" +cp -r "$DART"/models/lorenz_96/work nolib +cp -r "$DART"/models/lorenz_96/work sharedlib +cp -r "$DART"/models/lorenz_96/work staticlib + +#----------------- +# shared library build +cd "$DART"/developer_tests/library/shared/work +./quickbuild.sh clean +./quickbuild.sh mpif08 + +mpif90 -o filter "$DART"/assimilation_code/programs/filter/filter.f90 -I. -L. -ldart + +#----------------- +# static library build +cd "$DART"/developer_tests/library/static/work +./quickbuild.sh clean +./quickbuild.sh mpif08 + +mpif90 "$DART"/assimilation_code/programs/filter/filter.f90 -I. -L. -ldart -L/$NETCDF_LIB -lnetcdff -o filter + +#----------------- +# copy executables built from libraries to test directories +cd "$testdir"/sharedlib +rm filter +cp "$DART"/developer_tests/library/shared/work/filter . +cp "$DART"/developer_tests/library/shared/work/libdart.so . + +cd "$testdir"/staticlib +rm filter +cp "$DART"/developer_tests/library/static/work/filter . + +#----------------- +# run filter +cd "$testdir"/nolib/ +mpirun -n 4 ./filter + +cd "$testdir"/sharedlib/ +export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:$(pwd) +mpirun -n 4 ./filter + +cd "$testdir"/staticlib/ +mpirun -n 4 ./filter + +check_bitwise "$testdir"/nolib/ "$testdir"/sharedlib/ +check_bitwise "$testdir"/nolib/ "$testdir"/staticlib/ + +} + +#----------------- +check_bitwise () { +diff -s "$1"/obs_seq.final "$2"/obs_seq.final + +netcdffiles=(\ +analysis.nc +filter_input.nc +filter_output.nc +perfect_input.nc +preassim.nc \ +) + +for f in "${netcdffiles[@]}" +do + echo -n "$f" " " + nccmp -d "$1"/"$f" "$2"/"$f" + echo "" +done +} + +main "$@" + diff --git a/guide/quickbuild.rst b/guide/quickbuild.rst index 04cc8678e9..7d09ec624f 100644 --- a/guide/quickbuild.rst +++ b/guide/quickbuild.rst @@ -242,3 +242,20 @@ finds your new code and ignores any code you do not want compiled. a directory, a list of files, or a single file. +Building DART as a library +-------------------------- + +For developers who want to build DART as a library for use with another applications, we provide +the buildlib buildfunction. + +.. code-block :: bash + + buildlib libdart.a # for a static library + buildlib libdart.so # for a shared library + + +Example quickbuild.sh scripts for building a shared and a static library are given in +``DART/developer_tests/library/{shared|static}/work``. + + +