#!/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; use English; use Getopt::Long; use IO::File; use IO::Handle; use File::Copy; #----------------------------------------------------------------------------------------------- sub usage { die <). 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 Build CLM with BGC package [ none | cn | cndv ] (default is none). -cache Name of output cache file (default: config_cache.xml). -cachedir Name of directory where output cache file is written (default: CLM build directory). -clm4me Turn Methane model: [on | off] Requires bgc=cn/cndv (Carbon Nitrogen model) (ONLY valid for CLM4.5!) -clm_root Root directory of clm source code (default: directory above location of this script) -cppdefs A string of user specified CPP defines. Appended to Makefile defaults. e.g. -cppdefs '-DVAR1 -DVAR2' -vichydro Turn VIC hydrologic parameterizations : [on | off] (default is off) -crop Toggle for prognostic crop model. [on | off] (default is off) (can ONLY be turned on when BGC type is CN or CNDV) -comp_intf Component interface to use (ESMF or MCT) (default MCT) -defaults 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. -exlaklayers Turn on extra lake layers (25 layers instead of 10) [on | off] (ONLY valid for CLM4.5!) -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 Value of clm4_0 or clm4_5 (default is clm4_0) -silent [or -s] Turns on silent mode - only fatal messages issued. -sitespf_pt Setup for the given site specific single-point resolution. -snicar_frc Turn on SNICAR radiative forcing calculation. [on | off] (default is off) -spinup 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 -taiphy Turns on TaiESM physics. (default is off) Only valid for CLM4.0 currently. -usr_src [,[,[...]]] 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. -vsoilc_centbgc Turn on vertical soil Carbon profile, CENTURY model decomposition, split Nitrification/de-Nitrification into two mineral pools for NO3 and NH4 (requires clm4me Methane model), and eliminate inconsistent duplicate soil hydraulic parameters used in soil biogeochem. (requires either CN or CNDV) (ONLY valid for CLM4.5!) [on,off or colon delimited list of no options] (default off) no-vert Turn vertical soil Carbon profile off no-cent Turn CENTURY off no-nitrif Turn the Nitrification/denitrification off [no-vert,no-cent,no-nitrif,no-vert:no-nitrif,no-vert:no-cent] 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 = absolute_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, clm_root => undef, spinup => "normal", taiphy => undef, ); GetOptions( "spinup=s" => \$opts{'spinup'}, "bgc=s" => \$opts{'bgc'}, "cache=s" => \$opts{'cache'}, "cachedir=s" => \$opts{'cachedir'}, "snicar_frc=s" => \$opts{'snicar_frc'}, "clm_root=s" => \$opts{'clm_root'}, "cppdefs=s" => \$opts{'cppdefs'}, "comp_intf=s" => \$opts{'comp_intf'}, "defaults=s" => \$opts{'defaults'}, "vsoilc_centbgc=s" => \$opts{'vsoilc_centbgc'}, "clm4me=s" => \$opts{'clm4me'}, "exlaklayers=s" => \$opts{'exlaklayers'}, "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'}, "taiphy" => \$opts{'taiphy'}, "usr_src=s" => \$opts{'usr_src'}, "v|verbose" => \$opts{'verbose'}, "version" => \$opts{'version'}, "vichydro=s" => \$opts{'vichydro'}, "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. # Check for the configuration definition file. my $config_def_file = "config_definition.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'})) { $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 # The XML::Lite module is required to parse the XML configuration files. (-f "$cfgdir/../../../../scripts/ccsm_utils/Tools/perl5lib/XML/Lite.pm") or die <<"EOF"; ** Cannot find perl module \"XML/Lite.pm\" in directory \"$cfgdir/../../../../scripts/ccsm_utils/Tools/perl5lib\" ** EOF # The Build::Config module provides utilities to store and manipulate the configuration. (-f "$cfgdir/../../../../scripts/ccsm_utils/Tools/perl5lib/Build/Config.pm") or die <<"EOF"; ** Cannot find perl module \"Build/Config.pm\" in directory \"$cfgdir/../../../../scripts/ccsm_utils/Tools/perl5lib\" ** 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"; } #----------------------------------------------------------------------------------------------- # Add $cfgdir/perl5lib to the list of paths that Perl searches for modules my $casecfgdir = "$cfgdir/../../../../scripts/ccsm_utils/Case.template"; my @dirs = ( $cfgdir, "$cfgdir/../../../../scripts/ccsm_utils/Tools/perl5lib", $casecfgdir); unshift @INC, @dirs; require XML::Lite; require Build::Config; # 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 = absolute_path("$cfgdir/.."); } else { $clm_root = $opts{'clm_root'}; } if ( &is_valid_directory( "$clm_root/src", allowEnv=>1 ) ) { $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=>1 ) ) { 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 = absolute_path($opts{'cachedir'}); } else { $config_cache_dir = $clm_bld; } if (&is_valid_directory( $config_cache_dir, allowEnv=>1 ) 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 if( defined($opts{'phys'}) ) { $cfg_ref->set('phys', $opts{'phys'}); } my $phys = $cfg_ref->get('phys'); if ($print>=2) { if( defined($opts{'phys'}) ) { print "Using version $phys physics.$eol"; } } #----------------------------------------------------------------------------------------------- # supported single point configurations if( defined($opts{'sitespf_pt'}) ) { $cfg_ref->set('sitespf_pt', $opts{'sitespf_pt'}); } my $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 if (defined $opts{'noio'}) { $cfg_ref->set('noio', "on" ); } my $noio = $cfg_ref->get('noio'); if ($print>=2) { if ( $noio eq "on") { print "ALL history output is turned OFF.$eol"; } } #----------------------------------------------------------------------------------------------- # extra lake layers if( defined($opts{'exlaklayers'}) ) { $cfg_ref->set('exlaklayers', $opts{'exlaklayers'}); } my $exlaklayers = $cfg_ref->get('exlaklayers'); if ( ($exlaklayers eq "on") && ($phys !~ /clm4_5/) ) { die <<"EOF"; ** Cannot turn exlaklayers mode on -- without clm4_5 physics!** EOF } if ($print>=2) { if ( $exlaklayers eq "on" ) { print "Use 25 lake layers instead of 10.$eol"; } } #----------------------------------------------------------------------------------------------- # BGC option if (defined $opts{'bgc'}) { $cfg_ref->set('bgc', $opts{'bgc'}); } my $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 if (defined $opts{'nofire'}) { $cfg_ref->set('nofire', "on" ); } my $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 eq "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 } } #----------------------------------------------------------------------------------------------- # CLM4 Methane model if( defined($opts{'clm4me'}) ) { $cfg_ref->set('clm4me', $opts{'clm4me'}); } my $clm4me = $cfg_ref->get('clm4me'); if ( ($clm4me eq "on") && ($bgc_mode !~ /^cn/) ) { die <<"EOF"; ** Cannot turn clm4me mode on -- without cn or cndv for bgc mode** EOF } if ( ($clm4me eq "on") && ($phys !~ /clm4_5/) ) { die <<"EOF"; ** Cannot turn clm4me mode on -- without clm4_5 physics!** EOF } if ($print>=2) { if ( $clm4me eq "on" ) { print "Activate CLM4 Methane model: .$eol"; } } #----------------------------------------------------------------------------------------------- # Vertical soil-Carbon, CENTURY-BGC, split prognostic mineral pool option # and elimination of inconsistent duplicate soil hydraulic parameters # -- currently only in bgc=CN if (defined $opts{'vsoilc_centbgc'}) { $cfg_ref->set('vsoilc_centbgc', $opts{'vsoilc_centbgc'} ); } my $vsoilc_centbgc = $cfg_ref->get('vsoilc_centbgc'); if ( ($vsoilc_centbgc ne "off") && ($bgc_mode !~ /^cn/) ) { die <<"EOF"; ** Cannot turn vsoilc_centbgc mode on -- without cn or cndv for bgc mode** EOF } my $vsoilc_centbgc = $cfg_ref->get('vsoilc_centbgc'); if ( ($vsoilc_centbgc ne "off") && ($vsoilc_centbgc !~ /no-nitrif/) && ($clm4me ne "on") ) { # die <<"EOF"; #** Cannot turn vsoilc_centbgc mode on -- without clm4me Methane model active** #EOF print <<"EOF"; Warning:: The vsoilc_centbgc package (explicitly Nitrification/de-Nitrification) requires the clm4me Methane model to be active. It is recommended that you re-configure with both vsoilc_centbgc AND clm4me. EOF } if ( ($vsoilc_centbgc eq "on") && ($phys !~ /clm4_5/) ) { die <<"EOF"; ** Cannot turn vsoilc_centbgc mode on -- without clm4_5 physics!** EOF } if ( $vsoilc_centbgc eq "on") { if ($print>=2) { print "vsoilc_centbgc package: $eol"; print " Vertical soil Carbon.$eol"; print " CENTURY BGC$eol"; print " Split of Nitrogen mineral pools that are active.$eol"; print " Elimination of inconsistent duplicate soil hydraulic parameters.$eol"; } } elsif ( $vsoilc_centbgc eq "off") { } else { print "Warning:: running with OUT the vsoilc_centbgc package fully on or off is NOT validated / " . "scientifically supported.$eol"; } #----------------------------------------------------------------------------------------------- # 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"; } #----------------------------------------------------------------------------------------------- # VICHYDRO option if (defined $opts{'vichydro'}) { $cfg_ref->set('vichydro', $opts{'vichydro'}); } my $vichydro = $cfg_ref->get('vichydro'); if ($vichydro eq "on") { print "Using VIC hydrology for runoff calculations.$eol"; } #----------------------------------------------------------------------------------------------- # CROP option if (defined $opts{'crop'}) { $cfg_ref->set('crop', $opts{'crop'}); } my $crpmode = "nocrop"; my $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; if ($phys eq "clm4_0") { $maxpatchpft{'crop'} = 21; $maxpatchpft{'nocrop'} = 17; } else { $maxpatchpft{'crop'} = 25; $maxpatchpft{'nocrop'} = 17; } $cfg_ref->set('maxpft', $maxpatchpft{$crpmode} ); my $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 if (defined $opts{'snicar_frc'}) { $cfg_ref->set('snicar_frc', $opts{'snicar_frc'}); } my $snicar_frc = $cfg_ref->get('snicar_frc'); if ($print>=2) { print "Using $snicar_frc for snicar_frc.$eol"; } #----------------------------------------------------------------------------------------------- # TaiESM physics if (defined($opts{'taiphy'})) { $cfg_ref->set('taiphy', "on" ); } my $taiphy = $cfg_ref->get('taiphy'); if ( ($taiphy eq "on") && ($phys !~ /clm4_0/) ) { die <<"EOF"; ** TaiESM physics must be running with clm4_0 physics! ** EOF } if ($print>=2) { if ( $taiphy eq "on" ) { print "Activate TaiESM physics: .$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 = ''; $cfg_cppdefs .= " -DMAXPATCH_PFT=$maxpft"; if ($bgc_mode eq 'cn') { $cfg_cppdefs .= " -DCN"; } if ($vichydro eq 'on') { $cfg_cppdefs .= " -DVICHYDRO"; } 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 ($phys eq "clm4_0") { if ($spinup eq 'AD') { $cfg_cppdefs .= " -DAD_SPINUP"; } if ($spinup eq 'exit') { $cfg_cppdefs .= " -DEXIT_SPINUP"; } } if ($exlaklayers eq 'on') { $cfg_cppdefs .= " -DEXTRALAKELAYERS"; } if ($vsoilc_centbgc eq 'on' || ($vsoilc_centbgc ne "off" && $vsoilc_centbgc !~ /no-vert/)) { $cfg_cppdefs .= " -DVERTSOILC" } if ($vsoilc_centbgc eq 'on' || ($vsoilc_centbgc ne "off" && $vsoilc_centbgc !~ /no-cent/)) { $cfg_cppdefs .= " -DCENTURY_DECOMP" } if ($vsoilc_centbgc eq 'on' || ($vsoilc_centbgc ne "off" && $vsoilc_centbgc !~ /no-nitrif/)) { $cfg_cppdefs .= " -DNITRIF_DENITRIF" } if ($clm4me eq 'on') { $cfg_cppdefs .= " -DLCH4" } if ( $snicar_frc eq 'on' ) { $cfg_cppdefs .= " -DSNICAR_FRC"; } # 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, allowEnv=>1 ); 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, %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'); my $comp_intf = $cfg_ref->get('comp_intf'); my $phys = $cfg_ref->get('phys'); # Source root my $srcdir = "$clm_root/src"; if ( ! &is_valid_directory( "$srcdir", %opts ) ) { die "** source directory does not exist: $srcdir\n"; } # 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"; } my @dirs = ( "cpl_share", "util_share", "$phys/main", "$phys/biogeophys", "$phys/biogeochem"); if ( $comp_intf eq "MCT" ) { push( @dirs, "cpl_mct" ); } elsif ( $comp_intf eq "ESMF" ) { push( @dirs, "cpl_esmf" ); } else { die "** Invalid comp_intf: $comp_intf\n"; } 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 absolute_path { # # Convert a pathname into an absolute pathname, expanding any . or .. characters. # Assumes pathnames refer to a local filesystem. # Assumes the directory separator is "/". # my $path = shift; my $cwd = getcwd(); # current working directory my $abspath; # resulting absolute pathname # Strip off any leading or trailing whitespace. (This pattern won't match if # there's embedded whitespace. $path =~ s!^\s*(\S*)\s*$!$1!; # Convert relative to absolute path. if ($path =~ m!^\.$!) { # path is "." return $cwd; } elsif ($path =~ m!^\./!) { # path starts with "./" $path =~ s!^\.!$cwd!; } elsif ($path =~ m!^\.\.$!) { # path is ".." $path = "$cwd/.."; } elsif ($path =~ m!^\.\./!) { # path starts with "../" $path = "$cwd/$path"; } elsif ($path =~ m!^[^/]!) { # path starts with non-slash character $path = "$cwd/$path"; } my ($dir, @dirs2); my @dirs = split "/", $path, -1; # The -1 prevents split from stripping trailing nulls # This enables correct processing of the input "/". # Remove any "" that are not leading. for (my $i=0; $i<=$#dirs; ++$i) { if ($i == 0 or $dirs[$i] ne "") { push @dirs2, $dirs[$i]; } } @dirs = (); # Remove any "." foreach $dir (@dirs2) { unless ($dir eq ".") { push @dirs, $dir; } } @dirs2 = (); # Remove the "subdir/.." parts. foreach $dir (@dirs) { if ( $dir !~ /^\.\.$/ ) { push @dirs2, $dir; } else { pop @dirs2; # remove previous dir when current dir is .. } } if ($#dirs2 == 0 and $dirs2[0] eq "") { return "/"; } $abspath = join '/', @dirs2; return( $abspath ); } #------------------------------------------------------------------------------- sub subst_env_path { # # Substitute for any environment variables contained in a pathname. # Assumes the directory separator is "/". # my $path = shift; my $newpath; # resulting pathname my $nm = "subst_env_path"; # Strip off any leading or trailing whitespace. (This pattern won't match if # there's embedded whitespace. $path =~ s!^\s*(\S*)\s*$!$1!; my ($dir, @dirs2); my @dirs = split "/", $path, -1; # The -1 prevents split from stripping trailing nulls # This enables correct processing of the input "/". foreach $dir (@dirs) { if ( $dir =~ m/(^[^\$]*)\$(.*$)/ ) { my $startvar = $1; my $envvarnm = $2; if ( ! defined($ENV{$envvarnm}) ) { die "${nm}:: ENV variable $envvarnm is in pathname ($path) -- but NOT defined\n"; } push @dirs2, "$startvar$ENV{$envvarnm}"; } elsif ( $dir =~ m/\$/) { die "${nm}:: malformed ENV variable is in pathname ($path)\n"; } else { push @dirs2, $dir; } } $newpath = join '/', @dirs2; return( $newpath ); } #------------------------------------------------------------------------------- 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. # If allowEnv=>1 expand environment variables. # my ($dir, %opts) = @_; my $nm = "is_valid_directory"; my $valid = 0; # Expand environment variables if ( $opts{'allowEnv'} ) { $dir = subst_env_path( $dir ); } if ( -d $dir ) { $valid = 1; } return( $valid ); }