[Bio] / FigCommon / bootstrap.pl Repository:
ViewVC logotype

View of /FigCommon/bootstrap.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.6 - (download) (as text) (annotate)
Sun Jan 11 20:09:10 2004 UTC (15 years, 10 months ago) by olson
Branch: MAIN
Changes since 1.5: +1 -1 lines
Fix typo.

#
# FIG bootstrap script.
#
# Control is passed here from the toplevel configure (or dists/releases/install depending 
# on how far we've gotten in the process).
#
# The configure has set the following environment variables for our use:
#
#  FIG_HOME		Root of the FIGdisk tree we're setting up
#  FIGCONFIG_ENV	Name of the environment we're configuring for
#  FIGCONFIG_ENV_DIR	Directory in which the binary install tree for $FIGCONFIG_ENV lives
#  FIGCONFIG_RELEASE	Release number we're configuring
#  FIGCONFIG_RELEASE_DIR Directory in which that release lives
#
# Important note: perl system libraries may not be available when this
# script is running, if the FIGCONFIG_ENV_DIR is different than it was
# when the binaries were created. Part of the task of this
# script is to recognize this case and configure the process
# environment correctly so that the post-install process as 
# handled by the Makefiles can use perl properly, without concern for paths.
#

#
# Look into the FIGCONFIG_ENV_DIR for the PREFIX that this
# environment was compiled on. If that directory is different
# than the one we're currently using, rewrite @INC accordingly.
#
# We put this into a BEGIN block so that we can later use "use"
# without worrying about paths.
#
# We also set the $perlenv_override to true if we've done this,
# so we can insert these fixes into the perl tool header.
#

BEGIN {

    print "Here in the perl bootstrap. inc is:\n" . join("\n", @INC), "\n";

    my $my_prefix, $prefix, $inc, @newInc;
    
    $my_prefix = $ENV{FIGCONFIG_ENV_DIR};
    open(P, "<$my_prefix/PREFIX");
    $prefix = <P>;
    chomp $prefix;
    
    
    # print "Prefix is $prefix myprefix=$my_prefix\n";
    
    if ($prefix ne $my_prefix)
    {
	@newInc = ();
	for $inc (@INC)
	{
	    $inc =~ s,^$prefix,$my_prefix,;
	    push(@newInc, $inc);
	}

	$::perlenv_override = 1;
        @INC = @newInc;
    }
}


use FileHandle;
use strict;

#
# Environment definition
#
# This list contains triples
# ($name, $value, $appendFlag). $name is the name of the
# variable; $value is the value to set, and $appendFlag
# is nonzero if we need to append this value to an existing
# environment variable.
# 

our $Env = [];

#
# FIG configuration information.
# This list contains tuples [$name, $value, $quote]
# which are to be set in the FIG_Config modules for
# both python and perl. $quote is 1 for things that need
# to be quoted, 0 otherwise.
#
our $Config = [];

#
# Other key/value pairs of stuff we may need to pass
# to and from the environment-specific configuration modules.
#
# Known keys:
#
#   pythonpath
#

our $OtherConfig = {};

#
# Cache values of the various places we may be installing things.
#

our $fig_disk = $ENV{FIG_HOME};
our $env_name = $ENV{FIGCONFIG_ENV};
our $env_bin = "$ENV{FIGCONFIG_ENV_DIR}/bin";
our $env_lib = "$ENV{FIGCONFIG_ENV_DIR}/lib";
#
# We are moving to use a symlink in dist/releases/current for these.
# This symlink is managed by switch_to_release.
#
#our $release_bin = "$ENV{FIGCONFIG_RELEASE_DIR}/bin/$ENV{FIGCONFIG_ENV}";
#our $release_lib = "$ENV{FIGCONFIG_RELEASE_DIR}/lib/$ENV{FIGCONFIG_ENV}";

our $release_bin = "$fig_disk/dist/releases/current/bin/$ENV{FIGCONFIG_ENV}";
our $release_lib = "$fig_disk/dist/releases/current/lib/$ENV{FIGCONFIG_ENV}";

our $fig_bin = "$fig_disk/FIG/bin";
    
#
# Location of start/stop servers scripts.
#
our $start_servers = "$fig_disk/bin/start-servers";
our $stop_servers = "$fig_disk/bin/stop-servers";

sub configure_std_fig_environment
{
    #
    # Populate the Config with the usual stuff we need in FIG_Config.pm.
    #

    my $fig = "$fig_disk/FIG";
    my $data = "$fig/Data";

    my $hostname = `hostname`;
    chomp $hostname;

    push(@$Config, ["fig_disk", $fig_disk, 1]);
    push(@$Config, ["blastmat", "$fig_disk/BLASTMAT", 1]);
    push(@$Config, ["fig", $fig, 1]);
    push(@$Config, ["bin", $fig_bin, 1]);
    push(@$Config, ["ext_bin", $env_bin, 1]);
    push(@$Config, ["data", $data, 1]);
    push(@$Config, ["global", "$data/Global", 1]);
    push(@$Config, ["organisms", "$data/Organisms", 1]);
    push(@$Config, ["RC", "$fig_disk/FIG/ResolutionCenter", 1]);
    push(@$Config, ["NR", "$fig_disk/FIG/NR", 1]);
    push(@$Config, ["temp", "$fig_disk/FIG/Tmp", 1]);
    push(@$Config, ["temp_url", "http://$hostname/FIG-Tmp", 1]);
    push(@$Config, ["cgi_url", "http://$hostname/FIG", 1]);
}

sub compute_environment
{
    #
    # ReleaseTools configuration.
    #

    push(@$Env, ["RTROOT", $ENV{FIG_HOME}, 0]);
    push(@$Env, ["RTDIST", "\$RTROOT/dist", 0]);
    push(@$Env, ["RTARCH", $ENV{FIGCONFIG_ENV}, 0]);
    push(@$Env, ["RTCURRENT", "`cat \$RTROOT/CURRENT_RELEASE`", 0]);
    push(@$Env, ["FIG_HOME", $ENV{FIG_HOME}, 0]);

    push(@$Env, ["BLASTMAT", "$ENV{FIG_HOME}/BLASTMAT", 0]);

    #
    # Determine the path to use.
    #
    # This includes the path into the particular release we're configuring for,
    # and to the environment's bin directory.
    #

    my @path = ();
    push(@path, $env_bin);
    push(@path, $fig_bin);
    push(@path, "$fig_disk/bin");

    push(@$Env, ["PATH", join(":", @path), 1]);

    push(@$Env, ["LD_LIBRARY_PATH", "${env_lib}", 1]);
}

sub configure_python
{
    #
    # Determine the PYTHONPATH we're to use.
    #
    # Right now, we don't compute a replacement for the system path,
    # but we're likely going to require that  *if* python is
    # distributed with the environment. We're currently not doing that.
    #
    # So we just need to point to any python packages in the release,
    # and to packages that were installed in the environment dir.
    #

    my $python = find_python();
    print "Found python at $python\n";

    my $py_version = `$python -c 'import sys; print "%d.%d" % (sys.version_info[:2])'`;
    chomp $py_version;
    print "Python version $py_version\n";

    $OtherConfig->{python_site_path} = "$ENV{FIGCONFIG_ENV_DIR}/lib/python$py_version/site-packages";
    
    my @path = ();
    push(@path, $OtherConfig->{python_site_path});
    push(@path, "$release_lib");
    push(@path, "$fig_disk/config");
    push(@$Env, ["PYTHONPATH", join(":", @path), 1]);

    $OtherConfig->{pythonpath} = join(":", @path);
}

sub find_in_path
{
    my($file, @extra) = @_;
    my(@path) = split(":", $ENV{PATH});

    for my $p (@path, @extra)
    {
	my $x = "$p/$file";
	if (-x $x)
	{
	    return $x;
	}
    }
    return undef;
}

#
# Find the name of the python executable we are to use.
#
sub find_python
{
    my $python;

    #
    # Special case for the mac.
    #

    if ($ENV{FIGCONFIG_ENV} eq "mac")
    {
	if ($python = find_in_path("pythonw"))
	{
	    return $python;
	}

	#
	# Didn't find it in the path; we require the
	# MacPython build, and that installs into
	# /usr/local/bin/pythonw by default.
	#

	#
	# Sigh. This requires #!/usr/bin/env to work properly
	# 
	$OtherConfig->{python_require_poundbang_env} = 1;
	return "/usr/local/bin/pythonw";
    }
    else
    {
	#
	# Non-mac, just look in the env dir or the path.
	#

	$python = "$ENV{FIGCONFIG_ENV_DIR}/bin/python";
	if (-x $python)
	{
	    return $python;
	}

	return find_in_path("python");
    }
}

#
# Find the name of the perl executable we are to use.
#
sub find_perl
{
    my $perl;

    $perl = "$ENV{FIGCONFIG_ENV_DIR}/bin/perl";
    if (-x $perl)
    {
	return $perl;
    }

    warn "We did not find a perl executable in the SEED distribution; some modules may not be found\n";
    return find_in_path("perl");
}

sub write_bash_init
{
    my($fh, $env) = @_;

    foreach my $item (@$env)
    {
	my($name, $value, $append) = @$item;

	if ($append)
	{
	    #
	    # Write code to detect if the value is set, and act accordingly.
	    #

	    print $fh <<END;
DELIM=
if [ -n "\$$name" ] ; then
    DELIM=:
fi
$name=\${$name}\${DELIM}$value
export $name
END
	}
	else
	{
	    print $fh "$name=\"$value\"\n";
	    print $fh "export $name\n";
	}
    }
}

sub write_csh_init
{
    my($fh, $env) = @_;

    foreach my $item (@$env)
    {
	my($name, $value, $append) = @$item;

	if ($append)
	{
	    #
	    # Write code to detect if the value is set, and act accordingly.
	    #

	    print $fh <<END;
if (\$?$name) then
    setenv $name \${$name}:$value
else
    setenv $name $value
endif
END
	}
	else
	{
	    print $fh "setenv $name \"$value\"\n";
	}
    }

}

sub run_script
{
    my($script) = @_;


    unless (my $ret = do $script)
    {
	if ($@)
	{
	    warn "Error parsing $script: $@\n";
	}
	elsif (!defined($ret))
	{
	    warn "Couldn't do $script: $!\n";
	}
	else
	{
	    warn "Counldn't run $script\n";
	}
    }
	    
    
}

sub configure_environment_specific
{
    my $env_script = $ENV{FIGCONFIG_ENV_CONFIG};

    if (! -f $env_script)
    {
	warn "No environment-specific configuration file $env_script found, skipping\n";
	return;
    }

    run_script($env_script);
}

#
# Create any directories that might be missing.
#

sub setup_directories
{
    my(@needed) = @_;
    
    for my $dir (@needed)
    {
	if (! -d $dir)
	{
	    mkdir($dir) or warn "Could not create $dir: $!\n";
	}
    }
}

sub setup_server_scripts
{
    #
    # Remove any start/stop servers scripts we might have, and write the stub
    # start.
    #

    unlink($start_servers);
    unlink($stop_servers);

    open(F, ">$start_servers") or die "Cannot write $start_servers: $!";
    print F "#!/bin/sh\n\n";
    close(F);
    chmod(0775, $start_servers);
	
    open(F, ">$stop_servers") or die "Cannot write $stop_servers: $!";
    print F "#!/bin/sh\n\n";
    close(F);
    chmod(0775, $stop_servers);

}

sub write_config_pm
{
    my($fh, $config) = @_;

    print $fh "package FIG_Config;\n\n";

    foreach my $item (@$config)
    {
	my($name, $value, $quote) = @$item;

	my $q = $quote ? '"' : '';
	printf $fh "\$%-15s = $q$value$q;\n", $name
    }

    print $fh "\n1;\n";
}

sub write_config_py
{
    my($fh, $config) = @_;

    foreach my $item (@$config)
    {
	my($name, $value, $quote) = @$item;

	#
	# Ugh. "global" is a keyword in python.
	#

	$name = "global_dir" if $name eq "global";

	my $q = $quote ? '"' : '';
	printf $fh "%-15s = $q$value$q\n", $name
    }
}

sub write_tool_hdr_perl
{
    my($fh) = @_;

    my $perl = find_perl();

    print $fh "#!$perl\n";
    print $fh "\n";

    if ($::perlenv_override)
    {
	#
	# Write the tool header BEGIN block to reset the environment.
	#

	print $fh "BEGIN {\n";
	print $fh "    \@INC = qw(\n";
	for my $inc (@INC)
	{
	    next if $inc eq '.';
	    print $fh "\t$inc\n";
	}
	print $fh ");\n";
	print $fh "}\n";
    }

    print $fh "use Data::Dumper;\n";
    print $fh "use Carp;\n";

    #
    # We generate a comment here that gets expanded by switch_to_release
    # This is part of the effort in making the environment bootstrapping
    # code independent of releases.
    # 

    #print $fh "use lib \"$release_lib\";\n";
    #print $fh "use lib \"$release_lib/FigKernelPackages\";\n";

    print $fh "# Following block is expanded by switch_to_release to add use lib directives\n";
    print $fh "# to point at the correct locations in the release directory.\n";
    print $fh "#BEGIN switch_to_release generated code\n";
    print $fh "#END switch_to_release generated code\n";
    print $fh "\n";

    print $fh "use lib \"$fig_disk/config\";\n";

    print $fh "use FIG_Config;\n";
    print $fh "\n";
}

sub write_tool_hdr_python
{
    my($fh) = @_;

    my $python = find_python();

    if ($OtherConfig->{python_require_poundbang_env})
    {
	print $fh "#!/usr/bin/env $python\n";
    }
    else
    {
	print $fh "#!$python\n";
    }
    print $fh "\n";

    print $fh "import sys\n";


    print $fh "sys.path.append('$OtherConfig->{python_site_path}')\n";

    print $fh "# Following block is expanded by switch_to_release to add use lib directives\n";
    print $fh "# to point at the correct locations in the release directory.\n";
    print $fh "#BEGIN switch_to_release generated code\n";
    print $fh "#END switch_to_release generated code\n";
    print $fh "\n";

    print $fh "sys.path.append('$fig_disk/config')\n";

    print $fh "import FIG_Config\n";
    print $fh "\n";
}

setup_directories("$fig_disk/bin",
		  "$fig_disk/config");

setup_server_scripts();


find_python();

compute_environment();
configure_std_fig_environment();
configure_python();
configure_environment_specific();

#
# Write the shell startup to the figdisk.
#
open(FH, ">$fig_disk/config/fig-user-env.sh") or die "Cannot write $fig_disk/config/fig-user-env.sh: $!";
write_bash_init(\*FH, $Env);
close(FH);

open(FH, ">$fig_disk/config/fig-user-env.csh") or die "Cannot write $fig_disk/config/fig-user-env.csh: $!";
write_csh_init(\*FH, $Env);
close(FH);

#
# Write the FIG_Config file.
#

open(FH, ">$fig_disk/config/FIG_Config.pm") or die "Cannot write $fig_disk/config/FIG_Config.pm: $!";
write_config_pm(\*FH, $Config);
close(FH);

open(FH, ">$fig_disk/config/FIG_Config.py") or die "Cannot write $fig_disk/config/FIG_Config.py: $!";
write_config_py(\*FH, $Config);
close(FH);

#
# Write the tool headers
#

open(FH, ">$fig_disk/config/base_tool_hdr") or die "Cannot write $fig_disk/config/tool_hdr: $!";
write_tool_hdr_perl(\*FH);
close(FH);

open(FH, ">$fig_disk/config/base_tool_hdr_py") or die "Cannot write $fig_disk/config/tool_hdr_py: $!";
write_tool_hdr_python(\*FH);
close(FH);

unshift(@INC, "$ENV{FIGCONFIG_RELEASE_DIR}");

require FigCommon::SwitchRelease;

&FigCommon::SwitchRelease::switch_to_release($fig_disk, $ENV{FIGCONFIG_ENV}, $ENV{FIGCONFIG_RELEASE});

MCS Webmaster
ViewVC Help
Powered by ViewVC 1.0.3