clm5.0/bld/configure
2025-01-12 20:48:10 +08:00

757 lines
27 KiB
Perl
Executable File

#!/usr/bin/env perl
#-----------------------------------------------------------------------------------------------
#
# configure
#
#
# This utility allows the CLM user to specify compile-time configuration
# options via a commandline interface. The output from configure is a
# Makefile and a cache file that contains all configuration parameters
# required to produce the Makefile. A subsequent invocation of configure
# can use the cache file as input (via the -defaults argument) to reproduce
# the CLM configuration contained in it. Note that when a cache file is
# used to set default values only the model parameters are used. The
# parameters that are platform dependent (e.g., compiler options, library
# locations, etc) are ignored.
#
# As the build time configurable options of CLM are changed, this script
# must also be changed. Thus configure is maintained under revision
# control in the CLM source tree and it is assumed that only the version of
# configure in the source tree will be used to build CLM. Thus we assume
# that the root of the source tree can be derived from the location of this
# script.
#
#-----------------------------------------------------------------------------------------------
use strict;
#use warnings;
#use diagnostics;
use Cwd qw(getcwd abs_path);
use English;
use Getopt::Long;
use IO::File;
use IO::Handle;
use File::Copy;
#-----------------------------------------------------------------------------------------------
sub usage {
die <<EOF;
SYNOPSIS
configure [options]
Configure CLM in preparation to be built.
OPTIONS
User supplied values are denoted in angle brackets (<>). Any value that contains
white-space must be quoted. Long option names may be supplied with either single
or double leading dashes. A consequence of this is that single letter options may
NOT be bundled.
-bgc <name> Build CLM with BGC package [ none | cn | cndv ]
(default is none).
-cache <file> Name of output cache file (default: config_cache.xml).
-cachedir <file> Name of directory where output cache file is written
(default: CLM build directory).
-cimeroot <dir> REQUIRED: Path to cime directory
-clm_root <dir> Root directory of clm source code
(default: directory above location of this script)
-cppdefs <string> A string of user specified CPP defines. Appended to
Makefile defaults. e.g. -cppdefs '-DVAR1 -DVAR2'
-crop <name> Toggle for prognostic crop model. [on | off] (default is off)
(can ONLY be turned on when BGC type is CN or CNDV)
-comp_intf <name> Component interface to use (ESMF or MCT) (default MCT)
-defaults <file> Specify full path to a configuration file which will be used
to supply defaults instead of the defaults in bld/config_files.
This file is used to specify model configuration parameters only.
Parameters relating to the build which are system dependent will
be ignored.
-help [or -h] Print usage to STDOUT.
-nofire Turn off wildfires for BGC setting of CN
(default includes fire for CN)
-noio Turn history output completely off (typically for testing).
-phys <name> Value of clm4_0, clm4_5, or clm5_0 (default is clm4_0)
-silent [or -s] Turns on silent mode - only fatal messages issued.
-sitespf_pt <name> Setup for the given site specific single-point resolution.
-snicar_frc <name> Turn on SNICAR radiative forcing calculation. [on | off]
(default is off)
-spinup <name> CLM 4.0 Only. For CLM 4.5, spinup is controlled from build-namelist.
Turn on given spinup mode for BGC setting of CN (level)
AD Turn on Accelerated Decomposition from (2)
bare-soil
exit Jump directly from AD spinup to normal mode (1)
normal Normal decomposition ("final spinup mode") (0)
(default)
The recommended sequence is 2-1-0
-usr_src <dir1>[,<dir2>[,<dir3>[...]]]
Directories containing user source code.
-verbose [or -v] Turn on verbose echoing of settings made by configure.
-version Echo the SVN tag name used to check out this CLM distribution.
EOF
}
#-----------------------------------------------------------------------------------------------
# Setting autoflush (an IO::Handle method) on STDOUT helps in debugging. It forces the test
# descriptions to be printed to STDOUT before the error messages start.
*STDOUT->autoflush();
#-----------------------------------------------------------------------------------------------
# Set the directory that contains the CLM configuration scripts. If the configure command was
# issued using a relative or absolute path, that path is in $ProgDir. Otherwise assume the
# command was issued from the current working directory.
(my $ProgName = $0) =~ s!(.*)/!!; # name of this script
my $ProgDir = $1; # name of directory containing this script -- may be a
# relative or absolute path, or null if the script is in
# the user's PATH
my $cwd = getcwd(); # current working directory
my $cfgdir; # absolute pathname of directory that contains this script
if ($ProgDir) {
$cfgdir = abs_path($ProgDir);
} else {
$cfgdir = $cwd;
}
#-----------------------------------------------------------------------------------------------
# Save commandline
my $commandline = "$cfgdir/configure @ARGV";
#-----------------------------------------------------------------------------------------------
# Parse command-line options.
my %opts = (
cache => "config_cache.xml",
phys => "clm4_0",
nofire => undef,
noio => undef,
cimeroot => undef,
clm_root => undef,
spinup => "normal",
);
GetOptions(
"spinup=s" => \$opts{'spinup'},
"bgc=s" => \$opts{'bgc'},
"cache=s" => \$opts{'cache'},
"cachedir=s" => \$opts{'cachedir'},
"snicar_frc=s" => \$opts{'snicar_frc'},
"cimeroot=s" => \$opts{'cimeroot'},
"clm_root=s" => \$opts{'clm_root'},
"cppdefs=s" => \$opts{'cppdefs'},
"comp_intf=s" => \$opts{'comp_intf'},
"defaults=s" => \$opts{'defaults'},
"clm4me=s" => \$opts{'clm4me'},
"h|help" => \$opts{'help'},
"nofire" => \$opts{'nofire'},
"noio" => \$opts{'noio'},
"phys=s" => \$opts{'phys'},
"snicar_frc=s" => \$opts{'snicar_frc'},
"s|silent" => \$opts{'silent'},
"sitespf_pt=s" => \$opts{'sitespf_pt'},
"usr_src=s" => \$opts{'usr_src'},
"v|verbose" => \$opts{'verbose'},
"version" => \$opts{'version'},
"crop=s" => \$opts{'crop'},
) or usage();
# Give usage message.
usage() if $opts{'help'};
# Echo version info.
version($cfgdir) if $opts{'version'};
# Check for unparsed arguments
if (@ARGV) {
print "ERROR: unrecognized arguments: @ARGV\n";
usage();
}
# Define 3 print levels:
# 0 - only issue fatal error messages
# 1 - only informs what files are created (default)
# 2 - verbose
my $print = 1;
if ($opts{'silent'}) { $print = 0; }
if ($opts{'verbose'}) { $print = 2; }
my $eol = "\n";
my %cfg = (); # build configuration
#-----------------------------------------------------------------------------------------------
# Make sure we can find required perl modules and configuration files.
# Look for them in the directory that contains the configure script.
my $cimeroot = $opts{'cimeroot'};
if ( ! defined($cimeroot) ) {
$cimeroot = "$cfgdir/../cime";
if ( -d $cimeroot ) {
} elsif ( -d "$cfgdir/../../../cime" ) {
$cimeroot = "$cfgdir/../../../cime";
} else {
die <<"EOF";
** Cannot find the root of the cime directory enter it using the -cimeroot option
Did you run the checkout_externals scripts?
EOF
}
}
my $casecfgdir = "$cimeroot/scripts/Tools";
my $perl5lib = "$cimeroot/utils/perl5lib/";
# The Build::Config module provides utilities to store and manipulate the configuration.
my $file = "$perl5lib/Build/Config.pm";
(-f "$file") or die <<"EOF";
** Cannot find perl module \"Build/Config.pm\" in path
\"$file\" **
EOF
#-----------------------------------------------------------------------------------------------
# Add $cfgdir/perl5lib to the list of paths that Perl searches for modules
my @dirs = ( $cfgdir, "$perl5lib", $casecfgdir);
unshift @INC, @dirs;
require Build::Config;
require config_files::clm_phys_vers;
# Get the physics version
my $phys = config_files::clm_phys_vers->new($opts{'phys'});
# Check for the physics specific configuration definition file.
my $phys_string = $phys->as_filename();
my $config_def_file = "config_definition_$phys_string.xml";
(-f "$cfgdir/config_files/$config_def_file") or die <<"EOF";
** Cannot find configuration definition file \"$config_def_file\" in directory
\"$cfgdir/config_files\" **
EOF
# The configuration defaults file modifies the generic defaults in the configuration
# definition file. Note that the -defaults option has precedence over all other options.
my $config_defaults_file;
my $std_config_defaults_file = "$cfgdir/config_files/config_defaults.xml";
if ($opts{'defaults'}) {
$config_defaults_file = $opts{'defaults'};
} elsif (defined($opts{'sitespf_pt'}) and $phys->as_long() == $phys->as_long( "clm4_0" ) ) {
$config_defaults_file = "$cfgdir/config_files/config_defaults_$opts{'sitespf_pt'}.xml";
if ( ! -f $config_defaults_file ) {
$config_defaults_file = "$std_config_defaults_file";
}
} else {
$config_defaults_file = "$std_config_defaults_file";
}
(-f "$config_defaults_file") or die <<"EOF";
** Cannot find configuration defaults file \"$config_defaults_file\" **
EOF
if ($print>=2) { print "Setting CLM configuration script directory to $cfgdir$eol"; }
if ($print>=2) { print "Using configuration defaults file $config_defaults_file$eol"; }
# Initialize the configuration. The $config_def_file provides the definition of a CLM
# configuration, and the $config_defaults_file provides default values for a specific CLM
# configuration. $cfg_ref is a reference to the new configuration object.
my $cfg_ref = Build::Config->new("$cfgdir/config_files/$config_def_file",
"$config_defaults_file");
#-----------------------------------------------------------------------------------------------
# CLM root directory.
my $clm_root;
if ( ! defined($opts{'clm_root'} ) ) {
$clm_root = abs_path("$cfgdir/..");
} else {
$clm_root = $opts{'clm_root'};
}
if ( &is_valid_directory( "$clm_root/src", allowEnv=>0 ) ) {
$cfg_ref->set('clm_root', $clm_root);
} else {
die <<"EOF";
** Invalid CLM root directory: $clm_root
**
** The CLM root directory must contain the subdirectory /src/.
** clm_root can be entered on the command line or it will be derived
** from the location of this script.
EOF
}
if ($print>=2) { print "Setting CLM root directory to $clm_root$eol"; }
#-----------------------------------------------------------------------------------------------
# CLM build directory is current directory
my $clm_bld = `pwd`;
chomp( $clm_bld );
# Make sure directory is valid
if ( ! &is_valid_directory( $clm_bld ) and ! mkdirp($clm_bld)) {
die <<"EOF";
** Could not create the specified CLM build directory: $clm_bld
EOF
}
if ($print>=2) { print "Setting CLM build directory to $clm_bld$eol"; }
#-----------------------------------------------------------------------------------------------
# User source directories.
my $usr_src = '';
if (defined $opts{'usr_src'}) {
my @dirs = split ',', $opts{'usr_src'};
my @adirs;
while ( my $dir = shift @dirs ) {
if (&is_valid_directory( "$dir", allowEnv=>0 ) ) {
push @adirs, $dir;
} else {
die "** User source directory does not exist: $dir\n";
}
}
$usr_src = join ',', @adirs;
$cfg_ref->set('usr_src', $usr_src);
}
if ($print>=2) { print "Setting user source directories to $usr_src$eol"; }
#-----------------------------------------------------------------------------------------------
# configuration cache directory and file.
my $config_cache_dir;
my $config_cache_file;
if (defined $opts{'cachedir'}) {
$config_cache_dir = abs_path($opts{'cachedir'});
}
else {
$config_cache_dir = $clm_bld;
}
if (&is_valid_directory( $config_cache_dir, allowEnv=>0 ) or mkdirp($config_cache_dir)) {
$config_cache_file = "$config_cache_dir/$opts{'cache'}";
} else {
die <<"EOF";
** Could not create the specified directory for configuration cache file: $config_cache_dir
EOF
}
if ($print>=2) { print "The configuration cache file will be created in $config_cache_file$eol"; }
#-----------------------------------------------------------------------------------------------
# physics
$cfg_ref->set('phys', $opts{'phys'});
my $phys_string = $phys->as_string();
if ($print>=2) {
if( defined($opts{'phys'}) ) {
print "Using version $phys_string physics.$eol";
}
}
#-----------------------------------------------------------------------------------------------
# supported single point configurations
my $sitespf_pt = undef;
if ($phys->as_long() == $phys->as_long("clm4_0") ) {
if( defined($opts{'sitespf_pt'}) ) {
$cfg_ref->set('sitespf_pt', $opts{'sitespf_pt'});
}
$sitespf_pt = $cfg_ref->get('sitespf_pt');
if ($print>=2) {
if( defined($opts{'sitespf_pt'}) ) {
print "Using $sitespf_pt for supported single point configuration.$eol";
}
}
}
#-----------------------------------------------------------------------------------------------
# NOIO option
my $noio = undef;
if ($phys->as_long() == $phys->as_long("clm4_0") ) {
if (defined $opts{'noio'}) {
$cfg_ref->set('noio', "on" );
}
$noio = $cfg_ref->get('noio');
if ($print>=2) {
if ( $noio eq "on") { print "ALL history output is turned OFF.$eol"; }
}
}
#-----------------------------------------------------------------------------------------------
# BGC option
my $bgc_mode = undef;
if ($phys->as_long() == $phys->as_long("clm4_0") ) {
if (defined $opts{'bgc'}) {
$cfg_ref->set('bgc', $opts{'bgc'});
}
$bgc_mode = $cfg_ref->get('bgc');
if ($print>=2) { print "Using $bgc_mode for bgc.$eol"; }
if ( $bgc_mode eq "casa" ) {
print "Warning:: bgc=casa is NOT validated / scientifically supported.$eol";
}
}
# NOFIRE option -- currently only in bgc=CN
my $nofire = undef;
if ($phys->as_long() == $phys->as_long("clm4_0") ) {
if (defined $opts{'nofire'}) {
$cfg_ref->set('nofire', "on" );
}
$nofire = $cfg_ref->get('nofire');
if ( ($nofire eq "on") && ($bgc_mode ne "cn") ) {
die <<"EOF";
** Cannot turn nofire mode on -- without cn for bgc mode**
EOF
}
if ($print>=2 && $bgc_mode =~ /^cn/ ) {
if ( $nofire eq "off") { print "Wildfires are active as normal.$eol"; }
else { print "Wildfires are turned off.$eol"; }
}
}
#-----------------------------------------------------------------------------------------------
# SPINUP option for BGC/CN mode only
my $spinup = undef;
if ($phys->as_long() == $phys->as_long("clm4_0") ) {
if (defined $opts{'spinup'}) {
$cfg_ref->set('spinup', $opts{'spinup'});
}
$spinup = $cfg_ref->get('spinup');
if ( ($spinup ne "normal" ) && ($bgc_mode ne "cn") ) {
die <<"EOF";
** Cannot turn spinup mode on -- without cn for bgc mode**
**
** Set the bgc mode by the following means from highest to lowest precedence:
** * by the command-line option -bgc cn
** * by a default configuration file, specified by -defaults
EOF
}
if ($print>=2) { print "Using $spinup for spinup for cn mode.$eol"; }
} else {
if ($opts{'spinup'} ne "normal") {
die <<"EOF";
** Spinup mode can only be controlled with configure for CLM 4.0.
** For CLM 4.5 use the bgc_spinup option to build-namelist
EOF
}
}
#-----------------------------------------------------------------------------------------------
# comp_intf option
if (defined $opts{'comp_intf'}) {
$cfg_ref->set('comp_intf', $opts{'comp_intf'});
}
my $comp_intf = $cfg_ref->get('comp_intf');
if ($print>=2) { print "Using $comp_intf for comp_intf.$eol"; }
#-----------------------------------------------------------------------------------------------
# CROP option
my $crpmode = undef;
my $crop = undef;
if ($phys->as_long() == $phys->as_long("clm4_0") ) {
if (defined $opts{'crop'}) {
$cfg_ref->set('crop', $opts{'crop'});
}
$crpmode = "nocrop";
$crop = $cfg_ref->get('crop');
if ( $crop eq "on" ) {
$crpmode = "crop";
}
if ( ($crop eq "on" ) && ($bgc_mode ne "cn") && ($bgc_mode ne "cndv") ) {
die <<"EOF";
** Cannot turn crop mode on -- without some form of cn for bgc mode**
**
** Set the bgc mode by the following means from highest to lowest precedence:
** * by the command-line options -bgc cn
** * by a default configuration file, specified by -defaults
EOF
}
}
#-----------------------------------------------------------------------------------------------
# MAXPFT option
my %maxpatchpft;
my $maxpft = undef;
if ($phys->as_long() == $phys->as_long("clm4_0") ) {
$maxpatchpft{'crop'} = 21;
$maxpatchpft{'nocrop'} = 17;
$cfg_ref->set('maxpft', $maxpatchpft{$crpmode} );
$maxpft = $cfg_ref->get('maxpft');
if ( (($bgc_mode eq "cn") || ($bgc_mode eq "cndv")) && ($maxpft != $maxpatchpft{$crpmode}) ) {
die <<"EOF";
** For CN or CNDV BGC mode you MUST set max patch PFT's to $maxpatchpft{$crpmode}
**
** When the crop model is on then it must be set to $maxpatchpft{'crop'} otherwise to $maxpatchpft{'nocrop'}
** Set the bgc mode, crop and maxpft by the following means from highest to lowest precedence:
** * by the command-line options -bgc, -crop and -maxpft
** * by a default configuration file, specified by -defaults
**
EOF
}
if ( $maxpft > $maxpatchpft{$crpmode} ) {
die <<"EOF";
** Max patch PFT's can NOT exceed $maxpatchpft{$crpmode}
**
** Set maxpft by the following means from highest to lowest precedence:
** * by the command-line options -maxpft
** * by a default configuration file, specified by -defaults
**
EOF
}
if ( $maxpft != $maxpatchpft{$crpmode} ) {
print "Warning:: running with maxpft NOT equal to $maxpatchpft{$crpmode} is " .
"NOT validated / scientifically supported.$eol";
}
if ($print>=2) { print "Using $maxpft for maxpft.$eol"; }
}
#-----------------------------------------------------------------------------------------------
# SNICAR_FRC option
my $snicar_frc = undef;
if ($phys->as_long() == $phys->as_long("clm4_0") ) {
if (defined $opts{'snicar_frc'}) {
$cfg_ref->set('snicar_frc', $opts{'snicar_frc'});
}
$snicar_frc = $cfg_ref->get('snicar_frc');
if ($print>=2) { print "Using $snicar_frc for snicar_frc.$eol"; }
}
#-----------------------------------------------------------------------------------------------
# Makefile configuration #######################################################################
#-----------------------------------------------------------------------------------------------
#-----------------------------------------------------------------------------------------------
# Name of CLM executable.
my $clm_exe = "clm";
if ($print>=2) { print "Name of CLM executable: $clm_exe.$eol"; }
#-----------------------------------------------------------------------------------------------
# For the CPP tokens, start with the defaults (from defaults file) and append the specifications
# from the commandline. That way the user can override defaults since the commandline versions
# occur last.
my $usr_cppdefs = $cfg_ref->get('cppdefs');
if (defined $opts{'cppdefs'}) {
$usr_cppdefs .= " $opts{'cppdefs'}";
print "Warning:: running with user defined cppdefs is NOT validated / " .
"scientifically supported.$eol";
}
$cfg_ref->set('cppdefs', $usr_cppdefs);
if ($usr_cppdefs and $print>=2) { print "Default and user CPP definitions: \'$usr_cppdefs\'$eol";}
# The following CPP macro definitions are used to implement the compile-time options. They are
# determined by the configuration parameters that have been set above. They will be appended to
# the CPP definitions that were explicitly set in the defaults file or by the user on the commandline.
my $cfg_cppdefs = '';
if ($phys->as_long() == $phys->as_long("clm4_0") ) {
$cfg_cppdefs .= " -DMAXPATCH_PFT=$maxpft";
if ($bgc_mode eq 'cn') {
$cfg_cppdefs .= " -DCN";
}
if ($crop eq 'on') {
$cfg_cppdefs .= " -DCROP";
}
if ($bgc_mode eq 'cndv') {
$cfg_cppdefs .= " -DCNDV -DCN";
}
if ($nofire eq 'on') {
$cfg_cppdefs .= " -DNOFIRE";
}
if ($noio eq 'on') {
$cfg_cppdefs .= " -D_NOIO";
}
if ($spinup eq 'AD') {
$cfg_cppdefs .= " -DAD_SPINUP";
} elsif ($spinup eq 'exit') {
$cfg_cppdefs .= " -DEXIT_SPINUP";
}
if ( $snicar_frc eq 'on' ) {
$cfg_cppdefs .= " -DSNICAR_FRC";
}
} elsif ($phys->as_long() >= $phys->as_long("clm4_5") ) {
# clm4_5 cppdefs -- SHOULD NOT BE ANY!
if ( $cfg_cppdefs ne '' ) {
die <<"EOF";
** CPP definitions should be empty for clm5_0 and is NOT **
EOF
}
} elsif ($phys->as_long() == $phys->as_long("clm5_0") ) {
# clm5_0 cppdefs -- SHOULD NOT BE ANY!
if ( $cfg_cppdefs ne '' ) {
die <<"EOF";
** CPP definitions should be empty for clm5_0 and is NOT **
EOF
}
} else {
# this should NOT happen
die <<"EOF";
** Bad CLM physics version **
EOF
}
# CPP defines to put on Makefile
my $make_cppdefs = "$usr_cppdefs $cfg_cppdefs";
if ($print>=2) { print "CPP definitions set by configure: \'$cfg_cppdefs\'$eol"; }
#-----------------------------------------------------------------------------------------------
# Write configuration files ####################################################################
#-----------------------------------------------------------------------------------------------
my $fp_filename = 'Filepath'; # name of output filepath file
my $cpp_filename = 'CESM_cppdefs'; # name of output file for clm's cppdefs in cesm
# Write the filepath file for cesm.
write_filepath_cesmbld("$clm_bld/$fp_filename", $cfg_ref, $phys, allowEnv=>0 );
if ($print>=2) { print "creating $clm_bld/$fp_filename\n"; }
# Write the file for clm's cppdefs needed in cesm.
write_cppdefs("$clm_bld/$cpp_filename", $make_cppdefs);
if ($print>=2) { print "creating $clm_bld/$cpp_filename\n"; }
# Write the configuration file.
$cfg_ref->write_file($config_cache_file, $commandline);
if ($print>=2) { print "creating $config_cache_file\n"; }
#-----------------------------------------------------------------------------------------------
# Done
chdir( $cwd ) || die <<"EOF";
** Trouble changing directory back to $cwd
**
EOF
if ($print) { print "CLM configure done.\n"; }
exit;
#-----------------------------------------------------------------------------------------------
# FINISHED ####################################################################################
#-----------------------------------------------------------------------------------------------
#-------------------------------------------------------------------------------
sub write_filepath_cesmbld
{
my ($file, $cfg_ref, $phys, %opts) = @_;
my $fh = new IO::File;
$fh->open(">$file") or die "** can't open filepath file: $file\n";
# configuration parameters used to determine paths
my $usr_src = $cfg_ref->get('usr_src');
my $clm_root = $cfg_ref->get('clm_root');
# User specified source directories.
if ($usr_src =~ /\S+/) {
my @dirs = split ',', $usr_src;
while ( my $dir = shift @dirs ) {
print $fh "$dir\n";
}
} else {
print $fh "../SourceMods/src.clm\n";
}
if ($phys->as_long() == $phys->as_long("clm4_0") ) {
# source root
my $srcdir = "$clm_root/src_clm40";
if ( ! &is_valid_directory( "$srcdir", %opts ) ) { die "** source directory does not exist: $srcdir\n"; }
# source directories under root
my @dirs = ( "main", "biogeophys", "biogeochem" );
foreach my $dir ( @dirs ) {
if ( &is_valid_directory( "$srcdir/$dir", %opts ) ) {
print $fh "$srcdir/$dir\n";
} else {
die "** source directory does not exist: $srcdir/$dir\n";
}
}
} else {
# source root
my $srcdir = "$clm_root/src";
if ( ! &is_valid_directory( "$srcdir", %opts ) ) { die "** source directory does not exist: $srcdir\n"; }
# source directories under root
my @dirs = ( "main",
"biogeophys",
"biogeochem",
"soilbiogeochem",
"dyn_subgrid",
"init_interp",
"fates",
"fates/main",
"fates/biogeophys",
"fates/biogeochem",
"fates/fire",
"fates/parteh",
"utils",
"cpl" );
foreach my $dir ( @dirs ) {
if ( &is_valid_directory( "$srcdir/$dir", %opts ) ) {
print $fh "$srcdir/$dir\n";
} else {
die "** source directory does not exist: $srcdir/$dir\n";
}
}
}
$fh->close;
}
#-------------------------------------------------------------------------------
sub write_cppdefs
{
my ($file, $make_cppdefs) = @_;
my $fh = new IO::File;
$fh->open(">$file") or die "** can't open cpp defs file: $file\n";
print $fh "$make_cppdefs\n";
$fh->close;
}
#-------------------------------------------------------------------------------
sub mkdirp {
my ($dir) = @_;
my (@dirs) = split /\//, $dir;
my (@subdirs, $path);
# if $dir is absolute pathname then @dirs will start with ""
if ($dirs[0] eq "") { push @subdirs, shift @dirs; }
while ( @dirs ) { # check that each subdir exists and mkdir if it doesn't
push @subdirs, shift @dirs;
$path = join '/', @subdirs;
unless (-d $path or mkdir($path, 0777)) { return 0; }
}
return 1;
}
#-------------------------------------------------------------------------------
sub version {
# The version is found in CLM's ChangeLog file.
# $cfgdir is set by the configure script to the name of its directory.
my ($cfgdir) = @_;
my $logfile = "$cfgdir/../doc/ChangeLog";
my $fh = IO::File->new($logfile, '<') or die "** can't open ChangeLog file: $logfile\n";
while (my $line = <$fh>) {
if ($line =~ /^Tag name:\s*[clm0-9_.-]*\s*[toin]*\s*([cesmclm0-9_.-]+)$/ ) {
print "$1\n";
exit;
}
}
}
#-------------------------------------------------------------------------------
sub is_valid_directory {
#
# Validate that the input is a valid existing directory.
#
my ($dir, %opts) = @_;
my $nm = "is_valid_directory";
my $valid = 0;
if ( -d $dir ) { $valid = 1; }
return( $valid );
}