You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

1146 lines
34 KiB

#!/usr/bin/perl -w
# Script to handle building KDE from CVS. You need to set
# some environment variables as appropriate. Specifically,
# QTDIR needs to be set, as well as a sane PATH.
#
# This script is designed to be run by cron, which will
# collect the output and mail it to the user who requested
# the job. For that reason, all output is sent to STDOUT.
#
# Copyright (c) 2003, 2004 Michael Pyne.
#
# You may use, alter, and redistribute this software under the terms
# of the GNU General Public License, v2 (or any later version).
#
# TODO:
# XXX: It would be better to have lockfiles in each directory as it's
# being updated, instead of having one big lock for the script.
use strict;
use warnings;
use Fcntl; # For sysopen constants
# Some global variables
# Remember kids, global variables are evil! I only get to do this
# because I'm an adult and you're not! :-P
my %global_opts = (
"checkout-only" => "",
"configure-flags" => "",
"qtdir" => "",
"kdedir" => "",
"cxxflags" => "",
"libpath" => "",
"do-not-compile" => "",
"binpath" => "",
"no-cvs" => "",
"refresh-build" => "",
"build-system-only" => "",
"cvs-server" => "",
"cvs-root" => "$ENV{HOME}/kdecvs",
"lockfile" => "/tmp/.kdecvs-lock",
"make-output-file" => "output",
"manual-build" => "",
"pretend" => "",
"use-unsermake" => "",
);
my %package_opts; # Holds module-specific options.
my @update_list; # List of modules to update/checkout.
my @build_list; # List of modules to build.
my @install_list = (); # List of modules to install.
# Subroutine definitions
# This subroutine returns an option value for a given module. Some
# globals can't be overridden by a module's choice. If so, the
# module's choice will be ignored, and a warning will be issued.
#
# Option names are case-sensitive!
#
# First parameter: Name of module
# Second paramenter: Name of option
sub get_option
{
my $module = shift;
my $option = shift;
# Configure flags and CXXFLAGS are appended to the global option
if ($option eq 'configure-flags' || $option eq 'cxxflags')
{
my $value = $global_opts{$option};
if (exists $package_opts{$module}->{$option})
{
$value .= " $package_opts{$module}->{$option}";
}
return $value;
}
# These options can't override globals
if ($option eq "cvs-root" ||
$option eq "cvs-server" ||
$option eq "qtdir" ||
$option eq "libpath" ||
$option eq "binpath" ||
$option eq "kdedir" ||
$option eq "pretend" ||
$option eq "lockfile")
{
return $global_opts{$option};
}
# Everything else overrides the global, unless of course it's not set.
# If we're reading for global options, we're pretty much done.
if ($module eq 'global' || not exists $package_opts{$module}->{$option})
{
return $global_opts{$option};
}
else
{
return $package_opts{$module}->{$option};
}
}
# Subroutine to run the make command with the arguments given by the
# passed list. If make-output-file is set, the output of STDOUT and
# STDERR will be redirected to that file. The first argument of the
# list given must be the module that we're making.
sub safe_make (@)
{
my $module = shift;
my $kdecvs = get_option('global', 'cvs-root');
my $output = get_option($module, 'make-output-file');
if (not $output)
{
return safe_system ('make', @_);
}
else
{
if (get_option('global', 'pretend'))
{
print "Would have run make > $kdecvs/log/$output\n";
return 0;
}
my $pid;
if ($pid = fork)
{
# Parent
waitpid $pid, 0;
return $?;
}
else
{
# Child
if (not -e "$kdecvs/log")
{
return 1 if not super_mkdir ("$kdecvs/log");
}
open (STDOUT, ">$kdecvs/log/$module-$output");
open (STDERR, ">&STDOUT");
exec ('make', @_);
}
}
}
# Subroutine to add a variable to the environment, but ONLY if it
# is set. First parameter is the variable to set, the second is the
# value to give it.
sub setenv
{
my ($var, $val) = splice (@_, 0, 2);
my $pretend = get_option ('global', 'pretend');
return if (length $val == 0);
1 while ($val =~ s/(^|:)~/$1$ENV{'HOME'}/);
if (not $pretend)
{
$ENV{$var} = $val;
}
else
{
print "Would have set $var=$val.\n";
}
}
# Display an error message to the user regarding their relative lack of
# ~/.kdecvs-buildrc, and point them to some help.
sub dead_whine
{
print <<"HOME";
Unable to open $ENV{HOME}/.kdecvs-buildrc!
$!
This file is necessary as it contains defintions for \$CVSROOT, among
other important variables!
For information on the format of .kdecvs-buildrc or for a sample file,
visit http://grammarian.homelinux.net/kdecvs-build/
HOME
finish (1); # We can't go on!
}
# This subroutine reads in the settings from the user's configuration
# file.
sub read_options
{
# The options are stored in $ENV{HOME}/.kdecvs-buildrc
my $config_file = "$ENV{HOME}/.kdecvs-buildrc";
open CONFIG, "<$config_file" or dead_whine();
my ($option, $flags, $modulename);
# Read in global settings
OUTER: while (<CONFIG>)
{
s/#.*$//; # Remove comments
next if (/^\s*$/); # Skip blank lines
# First command in .kdecvs-buildrc should be a global
# options declaration, even if none are defined.
if (not /^global\s*$/)
{
print "Invalid configuration file $config_file.\n";
print "Expecting global settings section!\n";
finish(1);
}
# Now read in each global option
while (<CONFIG>)
{
s/#.*$//; # Remove comments
next if /^\s*$/; # Skip blank lines
last OUTER if /^end\s+global/; # Stop
# The option is the first word, followed by the
# flags on the rest of the line. The interpretation
# of the flags is dependant on the option.
($option, $flags) = /^([-a-zA-Z0-9]+)\s+(.*)$/;
$global_opts{$option} = $flags;
}
}
# Now read in module settings
while (<CONFIG>)
{
s/#.*$//; # Remove comments
next if (/^\s*$/); # Skip blank lines
if (not /^module\s+[-\w]+\s*$/)
{
print "Invalid configuration file $config_file!\n";
print "Expecting a start of module section.\n";
print "Global settings will be retained.\n";
}
# Get modulename
($modulename) = /^module\s+([-\w]+)\s*$/;
$package_opts{$modulename} = { }; # Set up defaults
while (<CONFIG>)
{
s/#.*$//; # Remove comments
next if (/^\s*$/); # Skip blank lines
last if (/^end\s+module/);
# Split into option and its flags.
($option, $flags) = /^([-a-zA-Z0-9]+)\s+(.*?)\s*$/;
$package_opts{$modulename}->{$option} = $flags;
}
# Done reading options, add this module to the update list
push (@update_list, $modulename);
# Add it to the build list, unless the build is only
# supposed to be done manually.
if (not get_option ($modulename, 'manual-build'))
{
push (@build_list, $modulename);
}
}
close CONFIG;
}
# Subroutine to initialize some environment variable for building
# KDE from CVS. Change this section if a dependency changes later.
sub initialize_environment
{
$ENV{"WANT_AUTOMAKE"} = "1.7";
$ENV{"WANT_AUTOCONF_2_5"} = "1";
$ENV{"PATH"} = get_option ('global', 'binpath');
}
# Subroutine to process the command line arguments. Any arguments so
# processed will be removed from @ARGV.
# The following arguments are recognized.
# --version Print the version
# --author Print the author
# --help Print some help
# --pretend Don't really perform any actions, just say would we would do.
# --install Install all packages that have built successfully,
# if it is the only command-line option. If it isn't, the
# following entries on the command-line are assumed to be
# packages to install, and we install only those.
sub process_arguments
{
my $arg;
my $author = "Michael Pyne <mpyne\@grammarian.homelinux.net>\n";
my $version = "kdecvs-build 0.44\n";
my @argv;
while ($_ = shift @ARGV)
{
SWITCH: {
/^--version$/ && do { print $version; finish(); };
/^--author$/ && do { print $author; finish(); };
/^--help$/ && do {
print <<DONE;
kdecvs-build version $version
This script automates (well, attempts to :-) ) the download, build,
and install process for KDE CVS.
You must first setup a .kdecvs-buildrc file in your home directory.
Please visit http://grammarian.homelinux.net/kdecvs-build/ for
information on how to write the file. There may also be a GUI for that
file in the future. Stay tuned.
Anyways, after setting up .kdecvs-buildrc, you can run this program
from either the command-line or from cron. It will automatically download
the modules from CVS, create the build system, and configure and make
the modules you tell it too. If you\'d like, you can use this program to
install KDE as well, if you\'re building KDE for a single user.
Basic synopsis, after setting up .kdecvs-buildrc:
\$ kdecvs-build [package names] (Download and make KDE from CVS)
\$ kdecvs-build --install [package names] (Install single-user KDE)
If you don\'t specify any particular package names, then your settings
in .kdecvs-buildrc will be used. If you DO specify a package name, then
your settings will still be read, but the script will try to build/install
the package regardless of .kdecvs-buildrc
Copyright (c) 2003, 2004 Michael Pyne <mpyne\@grammarian.homelinux.net>
The script is distributed under the terms of the GNU General Public License
v2, and includes ABSOLUTELY NO WARRANTY!!!
Options:
--no-cvs Skip contacting the CVS server.
--no-build Skip the build process.
--pretend (or -p) Don't actually contact the CVS server, run make,
or create/delete files and directories. Instead,
output what the script would have done.
--refresh-build Start the build from scratch.
--build-system-only Create the build infrastructure, but don't actually
perform the build.
--install Try to install the packages passed on the command
line, or all packages in ~/.kdecvs-buildrc that don't
have manual-build set.
--help You\'re reading it. :-)
--author Output the author(s)\'s name.
--version Output the program version.
DONE
finish();
};
/^--install$/ && do {
if ($#ARGV > -1)
{
@install_list = @ARGV;
@ARGV = ();
}
else
{
# Get list of built items from $kdecvs/build/successfully-built
my $kdecvs = get_option ('global', 'cvs-root');
if (not open BUILTLIST, "<$kdecvs/build/successfully-built")
{
print "Can't determine what modules have built. You must\n";
print "specify explicitly on the command line.\n";
finish (1);
}
@install_list = <BUILTLIST>;
chomp (@install_list);
close BUILTLIST;
}
last SWITCH;
};
/^--no-cvs$/ && do {
$global_opts{'no-cvs'} = 1;
last SWITCH;
};
/^--no-build$/ && do {
$global_opts{'manual-build'} = 1;
last SWITCH;
};
/^--build-system-only$/ && do {
$global_opts{'build-system-only'} = 1;
last SWITCH;
};
/^(--pretend)|(-p)$/ && do {
$global_opts{'pretend'} = 1;
last SWITCH;
};
/^--refresh-build$/ && do {
$global_opts{'refresh-build'} = 1;
last SWITCH;
};
/^-/ && print "WARNING: Unknown option $_\n";
# Fall through on purpose
push @argv, $_; # Reconstruct correct @ARGV
}
}
@ARGV = @argv;
}
# Subroutine to try to get a lock on the script's lockfile to prevent
# more than one script from updating KDE CVS at once.
# The value returned depends on the system's open() call. Normally 0
# is failure and non-zero is success (e.g. a file descriptor to read).
sub get_lock
{
my $lockfile = get_option ("global", "lockfile");
return sysopen LOCKFILE, $lockfile, O_WRONLY | O_CREAT | O_EXCL;
}
# Subroutine to free the lock allocated by get_lock()
sub close_lock
{
my $lockfile = get_option ('global', "lockfile");
close LOCKFILE;
unlink $lockfile;
}
# Subroutine to get the list of CVS modules to update. Returned
# as a list. Parse the command-line arguments first.
sub get_update_list
{
my @super_list;
if ($#ARGV == -1)
{
# No arguments specified on command line. Use already
# constructed update list.
@super_list = @update_list;
}
else
{
# User specifically included packages, let's update them
@super_list = @ARGV;
}
if (scalar grep (get_option ($_, 'use-unsermake'), @super_list))
{
if (scalar grep (/^kdenonbeta$/, @super_list) == 0)
{
unshift (@super_list, 'kdenonbeta');
$package_opts{'kdenonbeta'} = {
'manual-build' => 'true',
'checkout-only' => 'unsermake',
};
print "Adding kdenonbeta/unsermake to checkout-only list.\n";
}
elsif (get_option ('kdenonbeta', 'checkout-only') and
get_option ('kdenonbeta', 'checkout-only') !~ /\bunsermake/)
{
$package_opts{'kdenonbeta'}->{'checkout-only'} .= " unsermake";
print "Adding unsermake to checkout-only list.\n";
}
}
# Search each entry in the update list to see if someone has asked for
# a partial checkout.
if (scalar grep (get_option ($_, 'checkout-only'), @super_list))
{
# A module is specified for piecewise checkout. Add kde-common
# if it's not already in the list.
if (scalar grep (/^kde-common$/, @super_list) == 0)
{
# kde-common isn't here, add it to beginning.
unshift (@super_list, "kde-common");
# Add entry for it to package_opts as well.
$package_opts{'kde-common'} = {
'manual-build' => 'true',
};
}
}
return @super_list;
}
# Subroutine to get the list of CVS modules to build. Returned
# as a list. A module will not be built if manual-build is set
# in the module's options. The command-line arguments should have been
# parsed first.
sub get_build_list
{
if ($#ARGV == -1)
{
# No arguments specified on command line. Use already
# constructed build list.
return @build_list;
}
else
{
# User specifically asked for packages, build them
return @ARGV;
}
}
# Helper subroutine for debugging purposes. Dumps all of the
# options which have been read in to %global_opts and %package_opts.
sub dump_options
{
my ($item, $ref_item, $ref);
foreach $item (keys %global_opts)
{
print "Global option $item is $global_opts{$item}\n";
}
foreach $item (keys %package_opts)
{
print "\nOptions for module $item:\n";
foreach $ref_item (keys %{$package_opts{$item}})
{
print "Option $ref_item is $package_opts{$item}{$ref_item}\n";
}
}
}
# Subroutine to unlink the given symlink if global-pretend isn't set.
sub safe_unlink
{
if (get_option ("global", 'pretend'))
{
print "Would have unlinked ", shift, ".\n";
return 1; # Return true
}
return unlink (shift);
}
# Subroutine to execute the system call on the given list if the pretend
# global option is not set.
sub safe_system(@)
{
if (not get_option ("global", "pretend"))
{
print "Executing ", join(" ", @_), "\n";
return system (@_) >> 8;
}
print "Would have run ", join(' ', @_), ".\n";
return 0; # Return true
}
# Helper subroutine to create a directory, including any parent
# directories that may also need created.
# Returns 0 on failure, non-zero on success
sub super_mkdir
{
my $pathname = shift;
my $temp;
my @parts = split (/\//, $pathname);
if (get_option ("global", "pretend"))
{
print "Would have created $pathname\n";
return 1;
}
foreach (@parts)
{
$temp .= "$_/";
next if -e $temp;
return 0 if not mkdir ($temp);
}
return 1;
}
# Subroutine to remove a package from the package build list. This
# is for use when you've detected an error that should keep the
# package from building, but you don't want to abort completely.
sub dont_build
{
my $module = shift;
my $i;
for (0 .. ($#ARGV - 1))
{
splice (@build_list, $_, 1) if ($build_list[$_] eq $module);
}
}
# Subroutine to checkout a CVS module, but to do so non-recursively.
# The first parameter should be the CVS module to check out.
# The second parameter should be the directory within the module to
# checkout.
#
# This subroutine handles one directory within the module at a time.
#
# It is important to remember that the admin directory is special. In
# this program, admin is added automatically to the list of directories
# to install when it is needed.
#
# Returns 0 on success, non-zero on failure.
#
# whenever a module is checked out piecewise.
sub checkout_cvs_partial_dir
{
my $module = shift;
my $dir = shift;
my $recurse = shift;
my @args;
my $kdecvs = get_option ("global", "cvs-root");
my $cvsroot = get_option ("global", "cvs-server");
print ("Checking out $module/$dir.\n");
chdir ("$kdecvs");
if ($dir eq "admin")
{
# In KDE CVS, the admin directory is a special sub-directory
# that doesn't exist in any module. Instead, it is linked to
# kde-common/admin. Normally KDE CVS updates that automatically,
# but when you update piecewise, you need to do it yourself.
if (not -e "kde-common/admin")
{
print "You haven't checked out kde-common! It must be checked\n";
print "out prior to this module ($module) since you are\n";
print "performing a piecewise installation.\n";
return 1;
}
safe_unlink ("$kdecvs/$module/admin");
@args = ('ln', '-s', '../kde-common/admin', "$module/$dir");
}
else
{
@args = ('cvs', "-d$cvsroot");
push @args, (-e "$module/$dir") ? 'up' : 'co';
push @args, '-l' unless $recurse;
push @args, '-r', get_option($module, "release-tag") if (get_option($module, "release-tag"));
push @args, "$module/$dir";
}
return safe_system (@args);
}
# Subroutine to check out a specific set of directories from a module,
# instead of recursively checking out the entire module.
# The first parameter is the module to check out. The subroutine will
# automatically pull the list of directories to checkout from %package_opts.
# Only call the subroutine if the module has set a value to checkout-only.
sub checkout_cvs_partial
{
my $dir = shift;
my @dirlist = split (/\s+/, get_option ($dir, 'checkout-only'));
my @args;
my $kdecvs = get_option ('global', 'cvs-root');
my $cvsroot = get_option ('global', 'cvs-server');
my ($item, $result);
chdir ($kdecvs);
# Check if the user specified the admin subdirectory. If not,
# add it.
push (@dirlist, 'admin') if scalar grep (/^admin$/, @dirlist) == 0;
@args = ('cvs', "-d$cvsroot");
push @args, (-e "$kdecvs/$dir") ? 'up' : 'co', '-l';
push @args, '-r', get_option($dir, "release-tag") if get_option($dir, 'release-tag');
push @args, $dir;
$result = safe_system (@args);
if ($result)
{
print "Error trying to partially checkout $dir!\n$!\n";
print "The module will be blocked from building.\n";
dont_build ($dir);
return;
}
ITEM_LOOP: for $item (@dirlist)
{
# We need to split each item in this list into its respective directories.
# For example, we may be checking out kdenonbeta/applets/ksearchapplet. We
# need to (non-recursively) download kdenonbeta/applets, and then
# (recursively) kdenonbeta/applets/ksearchapplet. This is because of stuff
# like the Makefile.am files that are laying around.
my @dir_pieces = split('/', $item);
my $piece = shift @dir_pieces;
while (scalar (@dir_pieces))
{
# Don't recurse, we have more pieces.
$result = checkout_cvs_partial_dir ($dir, $piece, 0);
if ($result)
{
print "Unable to check out $dir/$piece!\n";
print "Module $dir will be blocked from building.\n";
dont_build ($dir);
next ITEM_LOOP;
}
$piece = join ('/', $piece, shift @dir_pieces);
}
# Recurse here, we're finished with prior dirs.
$result = checkout_cvs_partial_dir ($dir, $piece, 1);
if ($result)
{
print "Unable to check out $dir/$piece!\n";
print "Module $dir will be blocked from building.\n";
dont_build ($dir);
next;
}
}
}
# Subroutine to update a list of CVS modules. The first
# parameter is a reference of a list of the modules to update.
# If the module has not already been checkout out, this subroutine
# will do so for you.
#
# Returns 0 on success, non-zero on error.
sub handle_updates
{
my $update_ref = shift;
my $kdecvs = get_option ('global', 'cvs-root');
my $cvsroot = get_option ('global', 'cvs-server');
my $result;
my $dir;
print "<<< UPDATING CVS DIRECTORIES >>>\n\n";
if (not -e "$ENV{HOME}/.cvsrc")
{
print "You do not seem to have a .cvsrc. Now creating a default... ";
open CVSRC, "> $ENV{HOME}/.cvsrc";
print CVSRC "cvs -z4 -q";
print CVSRC "diff -u3 -p";
print CVSRC "update -dP";
print CVSRC "checkout -P";
close CVSRC;
print "Done\n";
}
if (not -e "$ENV{HOME}/.cvspass")
{
# We need to login. We could use the Expect module to
# simulate a user login, but that would add another
# dependency for something which is really quite dumb.
# If the user doesn't login, then they will see warnings,
# but that should be it.
print <<EOF;
You need to login to CVS to avoid warnings about a missing .cvspass file!
At the command prompt, type \"cvs -d$cvsroot login\" without the quotes
and hit Enter. Then hit Enter again (to indicate a blank password) when
the prompt asks for your password.
EOF
}
if (not -e $kdecvs)
{
print "KDE CVS download directory doesn't exist, creating.\n";
if (not super_mkdir ($kdecvs))
{
print "Unable to make directory $kdecvs!\n$!\n";
@build_list = (); # Clear out the build list, since we can't build.
@install_list = (); # Can't install either.
return 0;
}
}
foreach $dir (@{$update_ref})
{
next if get_option($dir, 'no-cvs');
if (-e "$kdecvs/$dir/CVS")
{
# The CVS directory already exists, so it has probably already been
# checked out.
chdir ("$kdecvs/$dir");
print "---\nUpdating $dir\n---\n";
# Repository already exists, update
if (get_option($dir, 'checkout-only'))
{
# Don't check out the entire module, merely the
# parts the user wants
checkout_cvs_partial ($dir);
next;
}
# CVS knows the repository's root.
$result = safe_system ('cvs', 'up');
if ($result)
{
print "Error updating $dir, removing from list of packages to build.\n";
dont_build ($dir);
}
}
else
{
chdir ("$kdecvs");
print "Checking out $dir\n";
# Repository needs checked out
if (get_option ($dir, 'checkout-only'))
{
# Don't update the entire module, just the parts
# the user wants.
checkout_cvs_partial ($dir);
next;
}
my @args = ('cvs', "-d$cvsroot", 'co');
push @args, '-r', get_option($dir, "release-tag") if get_option($dir, "release-tag");
push @args, $dir;
$result = safe_system(@args);
if ($result)
{
print "Error checking out $dir, removing from list of packages to build.\n";
dont_build ($dir);
}
}
}
print "<<< UPDATE COMPLETE >>>\n";
}
# Subroutine to setup the build system in a directory. The first parameter
# is the module name. Returns boolean true on success, boolean false (0)
# on failure.
sub setup_build_system
{
my $kdecvs = get_option ('global', 'cvs-root');
my $result;
my $dir = shift;
if ((not -e "$kdecvs/build/$dir") ||
(-e "$kdecvs/build/$dir/.refresh-me") ||
get_option($dir, "refresh-build") ||
(not -e "$kdecvs/build/$dir/Makefile") )
{
# The build system needs created, either because it doesn't exist, or
# because the user has asked that it be completely rebuilt.
if ((not -e "$kdecvs/build/$dir") || (not -e "$kdecvs/build/$dir/Makefile"))
{
print "\nPreparing for initial build of $dir\n";
}
else
{
print "\nRefreshing build system for $dir.\n";
}
chdir ("$kdecvs/build");
# Remove directory if it already exists.
if (-e "$kdecvs/build/$dir")
{
$result = safe_system ('rm', '-rf', "$kdecvs/build/$dir");
if ($result)
{
print "Unable to unlink $kdecvs/build/$dir, skipping.\n";
return 0;
}
}
# Now create the directory
if (not super_mkdir ("$dir"))
{
print "Unable to create directory $kdecvs/build/$dir, skipping.\n";
return 0;
}
# Note this is the checkout directory, not the build directory
chdir ("$kdecvs/$dir");
# Run KDE's build preparation script
$result = (not -e 'configure') ? safe_system ('make', '-f', 'Makefile.cvs') : 0;
if ($result)
{
print "Unable to create configure system from checkout.\n";
return 0;
}
# Check to see if we're supposed to stop here
return 0 if get_option ($dir, 'build-system-only');
# Now we're in the build directory
chdir ("$kdecvs/build/$dir");
my $conf_flags = get_option ($dir, 'configure-flags');
# Configure for srcdir != builddir build.
# Also get the user's CXXFLAGS
my $cxxflags = get_option ($dir, 'cxxflags');
$ENV{'CXXFLAGS'} = $cxxflags if $cxxflags;
setenv ('DO_NOT_COMPILE', get_option ($dir, 'do-not-compile'));
$conf_flags .= " 'CXXFLAGS=$cxxflags'";
$result = safe_system ("$kdecvs/$dir/configure $conf_flags");
if ($result)
{
print "Unable to configure $dir!\n";
return 0;
}
}
return 1;
}
# Subroutine to setup the environment for a module. First parameter is the name of
# the module to set the environment for
sub update_module_environment
{
my $dir = shift;
my $kdecvs = get_option ('global', 'cvs-root');
my $kdedir = get_option ($dir, 'kdedir');
my $qtdir = get_option ($dir, 'qtdir');
my $path = join(':', get_option ($dir, 'binpath'), "$qtdir/bin", "$kdedir/bin");
my $libdir = join(':', get_option ($dir, 'libpath'), "$qtdir/lib", "$kdedir/lib");
# Set up the children's environment. We use setenv since it
# won't set an environment variable to nothing. (e.g, setting
# QTDIR to a blank string might confuse Qt or KDE.
# Remove leading and trailing colons, just in case.
# Also remove more than one colon.
for ($path, $libdir)
{
s/^:*//;
s/:*$//;
s/:+/:/;
}
setenv ('LD_LIBRARY_PATH', $libdir);
setenv ('PATH', $path);
setenv ('KDEDIR', $kdedir);
setenv ('QTDIR', $qtdir);
# Everyone loves unsermake. It's a pity that not every module will compile with it.
# Benjamin Meyer has an excellent article about speeding up distributed builds using
# unsermake. You should notice a much faster build even with only one CPU, however.
if (get_option ($dir, "use-unsermake"))
{
setenv ("UNSERMAKE", "$kdecvs/kdenonbeta/unsermake/unsermake");
}
}
# Subroutine to handle the build process.
# First parameter is a reference of a list containing the packages
# we are to build.
# If the packages are not already checked-out and/or updated, this
# subroutine WILL NOT do so for you.
#
# This subroutine assumes that the $kdecvs directory has already been
# set up. It will create $kdecvs/build if it doesn't already exist.
#
# If $kdecvs/build/$module/.refresh-me exists, the subroutine will
# completely rebuild the module.
#
# Returns 0 for success, non-zero for failure.
sub handle_build
{
my @fail_list;
my @build_done;
my $build_ref = shift;
my $kdecvs = get_option ('global', 'cvs-root');
my $cvsroot = get_option ('global', 'cvs-server');
my $dir;
my $result;
print "\n<<< BUILD PROCESS >>>\n";
# Make sure the build directory is set up.
if (not -e "$kdecvs/build")
{
print "$kdecvs/build doesn't exist, creating.\n";
if (not super_mkdir ("$kdecvs/build"))
{
print "Unable to create $kdecvs/build!\n$!\n";
return;
}
}
foreach $dir (@{$build_ref})
{
next if get_option ($dir, 'manual-build');
update_module_environment ($dir);
# Ensure that the build system is ready.
if (not setup_build_system($dir))
{
push @fail_list, $dir;
next;
}
next if get_option ($dir, 'build-system-only');
chdir ("$kdecvs/build/$dir");
print "---\nBuilding $dir\n---\n";
$result = safe_make ($dir);
if ($result)
{
# Build failed
print "\nUnable to build $dir!\n";
push @fail_list, $dir;
}
else
{
# Build succeeded
push @build_done, $dir;
}
}
print "<<< BUILD DONE >>>\n";
print "\n<<< PACKAGES SUCCESSFULLY BUILT >>>\n";
if (not get_option('global', 'disable-build-list') and
not get_option ('global', 'pretend'))
{
# Print out results, and output to a file
open BUILT_LIST, ">$kdecvs/build/successfully-built";
foreach $dir (@build_done)
{
print "$dir\n";
print BUILT_LIST "$dir\n";
}
close BUILT_LIST;
}
else
{
# Just print out the results
print (join ("\n", @build_done), "\n");
}
print "\n<<< PACKAGES FAILED BUILDING >>>\n";
print join ("\n", @fail_list), "\n";
}
# Subroutine to exit the script cleanly, including removing any
# lock files created. If a parameter is passed, it is interpreted
# as an exit code to use
sub finish
{
my $exitcode = shift;
$exitcode = 0 unless $exitcode;
close_lock();
exit $exitcode;
}
# Subroutine to handle the installation process. Simply calls
# 'make install' in the directory.
sub handle_install
{
my $kdecvs = get_option ('global', 'cvs-root');
my $pretend = get_option ('global', 'pretend');
my $result;
for my $dir (@install_list)
{
if ($dir eq "qt-copy")
{
print "qt-copy doesn't need installed.\n";
next;
}
if (not -e "$kdecvs/build/$dir" ||
not -e "$kdecvs/build/$dir/Makefile")
{
print "The build system doesn't exist for $dir.\n";
print "Therefore, we can't install it. :-(.\n";
next;
}
chdir ("$kdecvs/build/$dir");
$result = safe_system ('make', 'install');
if ($result)
{
print "Unable to install $dir!\n";
}
}
}
# Script starts.
read_options();
initialize_environment();
process_arguments();
if (not get_lock())
{
print "$0 is already running!\n";
exit 0; # Don't finish(), it's not our lockfile!!
}
@update_list = get_update_list();
@build_list = get_build_list();
my $time = localtime;
print "Script started processing at $time\n";
if ($#install_list == -1)
{
# No packages to install, we're in build mode
handle_updates (\@update_list);
handle_build (\@build_list);
}
else
{
# Installation mode. Check to make sure nothing's
# being updated.
if ($#ARGV > 0)
{
# We have packages specified on the command line.
print "Parameters ignored because we are installing:\n\t",
join (', ', @ARGV), "\n";
}
handle_install ();
}
$time = localtime;
print "Script finished processing at $time\n";
finish();
# vim: set et sw=4 ts=4: