From be16d21a80cccd341a07740adc30070b17c988b1 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Tue, 18 Sep 2012 21:02:32 +0200 Subject: delete build script the modularized build system is now good enough Change-Id: Idcc3fb2b6d6201ad7ecbb8e91bd257530797762b Reviewed-by: Yuchen Deng Reviewed-by: Sergio Ahumada Reviewed-by: Lars Knoll Reviewed-by: Thiago Macieira --- build | 554 ------------------------------------------------------------------ 1 file changed, 554 deletions(-) delete mode 100755 build (limited to 'build') diff --git a/build b/build deleted file mode 100755 index 520f9e9f..00000000 --- a/build +++ /dev/null @@ -1,554 +0,0 @@ -#!/usr/bin/perl -############################################################################# -## -## Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -## Contact: http://www.qt-project.org/ -## -## This file is part of the utilities of the Qt Toolkit. -## -## $QT_BEGIN_LICENSE:LGPL$ -## GNU Lesser General Public License Usage -## This file may be used under the terms of the GNU Lesser General Public -## License version 2.1 as published by the Free Software Foundation and -## appearing in the file LICENSE.LGPL included in the packaging of this -## file. Please review the following information to ensure the GNU Lesser -## General Public License version 2.1 requirements will be met: -## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. -## -## In addition, as a special exception, Nokia gives you certain additional -## rights. These rights are described in the Nokia Qt LGPL Exception -## version 1.1, included in the file LGPL_EXCEPTION.txt in this package. -## -## GNU General Public License Usage -## Alternatively, this file may be used under the terms of the GNU General -## Public License version 3.0 as published by the Free Software Foundation -## and appearing in the file LICENSE.GPL included in the packaging of this -## file. Please review the following information to ensure the GNU General -## Public License version 3.0 requirements will be met: -## http://www.gnu.org/copyleft/gpl.html. -## -## Other Usage -## Alternatively, this file may be used in accordance with the terms and -## conditions contained in a signed written agreement between you and Nokia. -## -## -## -## -## -## -## $QT_END_LICENSE$ -## -############################################################################# - -use v5.008; -use strict; -use warnings; - -package Qt::Build; - -=head1 NAME - -build - builds the Qt5 repository with all submodules in order - -=head1 SYNOPSIS - -B [B<-v>|B<--verbose> [n]] [B<-c>|B<--continue> [n]] [B<-j>|B<--jobs> [n]] [B<-n>|B<--dry-run> [n]] [B<--force-qmake>] [modules to build] - -=head1 DESCRIPTION - -This script is used to build all the Qt modules in the correct order. The way of building the Qt -modules is fairly complex, since they need to both be built and installed in the proper order, if -configured prefix happens to be in a different location than the build directory of QtBase. - -It's not enough to do first a top-level 'make', then a 'make install', since modules would then no -be available to the consecutive modules. The build script also handles a situation where Jom -exposes a dependency bug with parallel builds, by doing a 'qmake -r' on each individual module as -part of each modules build process. - -If no modules to build are passed on the command-line, all the default modules will be built. - -=head1 OPTIONS - -=over - -=item B<-v> [n], B<--verbose> [n] - -Makes output more verbose. Level of verboseness optional (default: 1). - -=item B<-c> [n], B<--continue> [n] - -Ignore failed submodules, and continue building. Continue has levels (default: 1). The default -level will make the build script ignore any errors in a submodule, and continue to build the next -dependency. Level 2 means that the --keep-going option is also passed to make for each submodule. - -=item B<-j> [n], B<--jobs> [n] - -Sets the number of parallel builds. Number is optional, but providing no number indicates -Unlimited, which you most likely do not want. - -=item B<--force-qmake> - -Forces a 'qmake -r' on a module, even if the build script detects an already existing Makefile in -the module. - -=item B<-n> [n], B<--dry-run> [n] - -Does a dry-run, show which actions will be taken without actually performing them. Dry-run has -levels (default: 1). The default level only shows which commands this script will execute. Level 2 -will also do a dry-run on make, showing all the actions the build-script will result in. Level 2 -requires C to run, so it is not completely "dry" in its purest sense, although nothing is -built. - -=back - -=head1 COPYRIGHT - -Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies). -Contact: http://www.qt-project.org/ - -=head1 LICENSE - -This file is part of the utilities of the Qt Toolkit, and may be used under the terms of the GNU -Lesser General Public (LGPL 2.1), or the GNU General Public License (GPL 3.0) - -=cut - -use Carp qw( confess ); -use English qw( -no_match_vars ); -use Getopt::Long qw( GetOptionsFromArray ); -use Pod::Usage qw( pod2usage ); -use Cwd qw( getcwd ); -use File::Spec qw( path catfile ); -use Config; - -sub parse_arguments -{ - my ($self, @args) = @_; - - %{$self} = (%{$self}, - 'verbose' => 0, - 'continue' => 0, - 'jobs' => -1, - 'force_qmake' => 0, - 'build-submodules' => [], - 'dry-run' => 0, - ); - - GetOptionsFromArray(\@args, - 'verbose|v:1' => \$self->{'verbose'}, - 'continue|c:1' => \$self->{'continue'}, - 'jobs|j:0' => \$self->{'jobs'}, - 'force-qmake' => \$self->{'force_qmake'}, - 'dry-run|n:1' => \$self->{'dry-run'}, - 'help|?' => sub { pod2usage(1); }, - ) || pod2usage(2); - - push(@{$self->{'build-submodules'}}, @args) if (@args); - - return; -} - -# Like `system', but possibly log the command, and die on non-zero exit code -sub exe -{ - my ($self, @cmd) = @_; - - print "+ @cmd\n" unless ($self->{quiet}); - - # dry-run > 1 means run sub-processes with dry-run too - if ($self->{'dry-run'} != 1) { - confess "@cmd exited with status $CHILD_ERROR" if (system(@cmd) != 0); - } -} - -sub dropPrivileges() -{ - my ($self) = @_; - - if ($> == 0) { # EUID == 0: must drop if possible - local $! = undef; - if ($< != 0) { # UID != 0 (run through setuid). swap UID with EUID - ($(, $)) = ($), $(); - die "Cannot lower gid privileges: $!" if $!; - ($<, $>) = ($>, $<); - die "Cannot lower uid privileges: $!" if $!; - } else { # UID == 0: run through sudo? - if (defined $ENV{SUDO_GID}) { - $) = "$ENV{SUDO_GID} $ENV{SUDO_GID}"; - die "Cannot lower gid privileges: $!" if $!; - } - if (defined $ENV{SUDO_UID}) { - $> = $ENV{SUDO_UID}; - die "Cannot lower uid privileges: $!" if $!; - } - } - } -} - -sub exeHighPriv() -{ - my ($self, @cmd) = @_; - # confesses upon system() failure - $self->exe(@cmd); -} - -sub exeLowPriv() -{ - my ($self, @cmd) = @_; - - if ("$Config{osname}" !~ /mswin/i) { - my $ret; - my $pid = fork(); - die "Couldn't fork" unless defined $pid; - if ($pid == 0) { - $self->dropPrivileges; - # just exit on error, exception propagated below - eval { $self->exe(@cmd); }; - exit $?; - } else { - waitpid($pid, 0); - # propagate exception upon system() failure in fork - die if ($? != 0); - return; - } - } - - # Just like exeHighPriv for now, and confesses upon failure - $self->exe(@cmd); -} - -sub which { - my ($self, $exe) = @_; - - foreach my $path (File::Spec->path()) { - my $file = File::Spec->catfile($path, $exe); - return $file if -x $file; - } - return; -} - -sub detect_configuration -{ - my ($self) = @_; - - die "You need to configure Qt before you try to build it, aborting." if (!-e 'qtbase/.qmake.cache'); - - use Cwd qw(abs_path); - use Env qw(@PATH); - - my $abs_path = abs_path('qtbase/bin'); - unshift @PATH, $abs_path; - - my $opts = ""; - $opts = "-j" if ($self->{'jobs'} >= 0); - $opts .= " $self->{'jobs'}" if ($self->{'jobs'} > 0); - $self->{'MAKEOPTS'} = $opts; - $self->{'MAKE'} = $ENV{MAKE} || "make"; - - if ("$Config{osname}" =~ /mswin/i) { - my $exe = $self->which("nmake.exe"); - $exe = $self->which("jom.exe") if (defined $exe && $self->which("jom.exe")); - $exe = $self->which("mingw32-make.exe") if (!defined $exe); - - if (defined $exe) { - $self->{'MAKE'} = "\"$exe\""; - - if ($exe =~ 'nmake') { - # Use the /MP compiler option if using nmake, to use all CPU threads when compiling - my $cl = $ENV{'CL'}; - if (defined $cl) { - $cl .= ' /MP'; - } else { - $cl = '/MP'; - } - $ENV{'CL'} = $cl; - # Remove the -j option, since nmake cannot handle it. - $self->{'MAKEOPTS'} = ""; - } elsif ($exe =~ 'jom' && $self->{'jobs'} == 0) { - # Jom currently doesn't handle the -j (unlimited) option, so remove it. - $self->{'MAKEOPTS'} = ""; - } - - if ($exe =~ 'nmake|jom') { - $self->{'MAKEOPTS'} = "/N $self->{'MAKEOPTS'}" if ($self->{'dry-run'} > 1); - $self->{'MAKEOPTS'} = "/K $self->{'MAKEOPTS'}" if ($self->{'continue'} > 1); - } - } - - # Tools needed for building QtWebKit/Windows (Bison, Flex, gperf, iconv) - my $abs_path = abs_path('gnuwin32/bin'); - unshift @PATH, "$abs_path"; - } - if ($self->{'MAKE'} !~ "nmake|jom") { - $self->{'MAKEOPTS'} = "--dry-run $self->{'MAKEOPTS'}" if ($self->{'dry-run'} > 1); - $self->{'MAKEOPTS'} = "--keep-going $self->{'MAKEOPTS'}" if ($self->{'continue'} > 1); - } -} - -sub find_pro_file -{ - my ($self, $dir) = @_; - my $D; - if (opendir($D,$dir)) { - ($dir =~ /\/$/) || ($dir .= "/"); - foreach my $file (sort readdir($D)) { - if ($file =~ /^.*\.pro$/) { - closedir($D); - return $file; - } - } - closedir($D); - } -} - -sub eliminate_empty_modules -{ - my ($self) = @_; - foreach my $repo (keys(%{$self->{'deps'}})) { - if (!$self->find_pro_file($repo)) { - printf "Missing module %s, ignored\n", $repo; - delete $self->{'deps'}->{$repo}; - } - } -} - -sub check_build_module -{ - my ($self, $module) = @_; - my @missing_link; - foreach my $submod (split(/,/, $self->{'deps'}->{$module})) { - next if ($submod =~ /:s$/); # Soft dependency - if (defined $self->{'deps'}->{$submod}) { - push(@missing_link, $self->check_build_module($submod)); - } else { - push(@missing_link, $submod); - } - } - return @missing_link; -} - -sub check_build_modules -{ - my ($self, $fail) = @_; - my $letsdie = 0; - foreach my $module (@{$self->{'build-submodules'}}) { - if (defined $self->{'deps'}->{$module}) { - my @missing_link = $self->check_build_module($module); - if (scalar @missing_link) { - $letsdie = 1; - my $mods = join(", ", @missing_link); - print STDERR "Ignoring module '$module': requires $mods\n"; - } - } else { - print STDERR "No module named '$module'\n"; - $letsdie = 1; - } - } - die "FAIL: Missing module dependencies, build aborted." if ($letsdie && $fail); -} - -sub resolve_soft_dependencies -{ - my ($self) = @_; - - my @nondefault = @{$self->{'nondefault'}}; - foreach my $module (keys(%{$self->{'deps'}})) { - my @deps = split(/,/, $self->{'deps'}->{$module}); - my @newdeps; - foreach my $dep (@deps) { - if ($dep =~ /(.*):s$/) { - my $mod = $1; - if (defined $self->{'deps'}->{$mod} - && !grep {$_ eq $mod} @nondefault) { - push(@newdeps, $mod); - } - } else { - push(@newdeps, $dep); - } - } - $self->{'deps'}->{$module} = join(",", @newdeps); - } -} - -sub mark_as_finished -{ - my ($self, $doneModule) = @_; - - delete $self->{'deps'}->{$doneModule}; - foreach my $module (keys(%{$self->{'deps'}})) { - my @deps = split(/,/, $self->{'deps'}->{$module}); - @deps = grep { $_ !~ /$doneModule/ } @deps; - $self->{'deps'}->{$module} = join(",", @deps); - } -} - -sub get_next_modules -{ - my ($self, $module) = @_; - - my @nextModules; - my $deps = $self->{'deps'}->{$module}; - return if (!defined $deps); - $self->{'seenHash'}->{$module}++; - if ($deps eq '') { - push (@nextModules, $module); - return @nextModules; - } - - foreach my $dep (split(/,/, $deps)) { - push (@nextModules, $self->get_next_modules($dep)) unless $self->{'seenHash'}->{$dep}; - } - - return @nextModules; -} - -sub get_all_next_modules -{ - my ($self) = @_; - - $self->{'seenHash'} = (); - - my @nextModules; - foreach my $module (@{$self->{'build-submodules'}}) { - my @mods = $self->get_next_modules($module); - push(@nextModules, @mods); - } - - my %seen = (); - my @uniqModules; - foreach my $item (@nextModules) { - push(@uniqModules, $item) unless $seen{$item}++; - } - - return @uniqModules; -} - -sub build_project -{ - my ($self, $module) = @_; - my $build_command = $self->{'buildcmds'}->{$module}; - my $install_command = $self->{'instcmds'}->{$module}; - if (!defined $build_command) { - if (!-e "$module/Makefile") { - $self->exeLowPriv("cd $module && qmake -r"); - } - $build_command = "$self->{MAKE} $self->{MAKEOPTS}"; - } - eval { $self->exeLowPriv("cd $module && $build_command"); }; - if ($@) { - print STDERR "'cd $module && $build_command' failed: $?\n"; - if ($self->{'continue'}) { - print STDERR "Ignoring failure building $module (--continue)\n"; - } else { - confess "Fatal failure building $module"; - } - } - $install_command = "$self->{MAKE} install" if (!defined $install_command); - ### TODO: Should be fixed after the alpha - unless ("$Config{osname}" =~ /(dar|ms)win/i) { - eval { $self->exeHighPriv("cd $module && $install_command"); }; - if ($@) { - print STDERR "'cd $module && $install_command failed: $?\n"; - if ($self->{'continue'}) { - print STDERR "Ignoring failure installing $module (--continue)\n"; - } else { - confess "Fatal failure installing $module"; - } - } - } - $self->mark_as_finished($module); - return 0; -} - -sub build_qt -{ - my ($self) = @_; - - printf "OS Name ........ %s\n", $Config{osname}; - printf "Verbose ........ %s\n", ($self->{'verbose'} ? $self->{'verbose'} : "no"); - printf "Continue ....... %s\n", ($self->{'continue'} ? "yes" : "no"); - printf "Force qmake..... %s\n", ($self->{'force_qmake'} ? "yes" : "no"); - printf "Jobs ........... %s\n", ($self->{'jobs'} >= 0 ? $self->{'jobs'} : "unset"); - - my $path = $ENV{'PATH'}; - print "PATH $path\n"; - - print "Modules to build:\n"; - my $mods = "(all present)"; - $mods = join(", ", @{$self->{'build-submodules'}}) if (@{$self->{'build-submodules'}}); - print " $mods\n"; - - while (my @modules = $self->get_all_next_modules) { - foreach my $module (@modules) { - print "build $module...\n"; - $self->build_project($module); - } - } - - print "build done!\n"; - - return 0; -} - -sub new -{ - my ($class, @arguments) = @_; - - my $self = {}; - bless $self, $class; - - $self->parse_arguments(@arguments); - $self->detect_configuration; - - my $depfile = "build.dependencies"; - my $result; - our (%build_dependencies, %build_commands, %install_commands, @nondefault_modules); - - # following variables may be expanded in the evaluation below - my $MAKEOPTS = $self->{'MAKEOPTS'}; - my $MAKE = $self->{'MAKE'}; - - unless ($result = do $depfile) { - die "build couldn't parse $depfile: $@" if $@; - die "build couldn't execute $depfile: $!" unless defined $result; - } - - $self->{'deps'} = \%build_dependencies; - $self->{'buildcmds'} = \%build_commands; - $self->{'instcmds'} = \%install_commands; - $self->{'nondefault'} = \@nondefault_modules; - - return $self; -} - -sub run -{ - my ($self) = @_; - - $self->eliminate_empty_modules; - - if (scalar @{$self->{'build-submodules'}} > 0) { - $self->check_build_modules(1); - } else { - my @default = keys(%{$self->{'deps'}}); - my @nondefault = @{$self->{'nondefault'}}; - foreach my $item (@nondefault) { - @default = grep { $_ ne $item } @default; - } - push(@{$self->{'build-submodules'}}, @default); - $self->check_build_modules(0); - } - - $self->resolve_soft_dependencies; - - $self->build_qt; - -# print Dumper($self); - - return; -} - -#============================================================================== - -Qt::Build->new(@ARGV)->run if (!caller); -1; -- cgit v1.2.3