Subversion Repositories DevTools

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
#! /usr/bin/perl
2
########################################################################
3
# Copyright (C) 1998-2004 ERG Limited, All rights reserved
4
#
5
# Module name   : jats_cbuilder.pl
6
# Module type   : Makefile system
7
# Compiler(s)   : n/a
8
# Environment(s):
9
#
10
# Description   : A script to build a collection of packages in the
11
#                 same sandbox. This script will:
12
#
13
#                   Determine the packages in the sandbox
14
#                   Determine the build order of the packages
15
#                   Build the packages in the correct order
16
#                   Make the packages in the correct order
17
#
18
#                 The script will allow for:
19
#                   The creation of a sandbox
20
#                   The addition of packages to the sandbox
21
#                   Removal of packages from the sandbox
22
#
23
#
24
#                 Command syntax (basic)
25
#                   jats sandbox <command> (options | actions)@
26
#
27
#                 Commands include:
28
#                   create              - Create a sandbox
29
#                   delete              - Delete a sandbox
30
#
31
#                   add package_name    - Add a package to the sandbox
32
#                   rm  package_name    - Remove a package from the sandbox
33
#
34
#                   build               - Build all packages in the sandbox
35
#                   make                - make all packages in the sandbox
36
#
37
#......................................................................#
38
 
39
require 5.6.1;
40
use strict;
41
use warnings;
42
use JatsError;
43
use JatsSystem;
44
use FileUtils;
245 dpurdie 45
use JatsBuildFiles;
227 dpurdie 46
use JatsVersionUtils;
47
 
48
 
49
use File::Find;
50
use Pod::Usage;                             # required for help support
51
use Getopt::Long qw(:config require_order); # Stop on non-option
52
my $VERSION = "1.0.0";                      # Update this
53
 
54
#
55
#   Options
56
#
57
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
58
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
59
my $opt_help = 0;
60
my $opt_manual = 0;
61
 
62
#
63
#   Globals - Provided by the JATS environment
64
#
65
my $USER         = $ENV{'USER'};
66
my $UNIX         = $ENV{'GBE_UNIX'};
67
my $HOME         = $ENV{'HOME'};
68
my $GBE_SANDBOX  = $ENV{'GBE_SANDBOX'};
69
my $GBE_DPKG_SBOX= $ENV{'GBE_DPKG_SBOX'};
70
 
71
#
72
#   Globals
73
#
74
my @build_order = ();                     # Build Ordered list of entries
75
my %extern_deps;                          # Hash of external dependancies
76
my %packages;                             # Hash of packages
77
 
78
 
79
#-------------------------------------------------------------------------------
80
# Function        : Mainline Entry Point
81
#
82
# Description     :
83
#
84
# Inputs          :
85
#
86
my $result = GetOptions (
87
                "help+"         => \$opt_help,              # flag, multiple use allowed
88
                "manual"        => \$opt_manual,            # flag, multiple use allowed
89
                "verbose+"      => \$opt_verbose,           # flag, multiple use allowed
90
                );
91
 
92
                #
93
                #   UPDATE THE DOCUMENTATION AT THE END OF THIS FILE !!!
94
                #
95
 
96
#
97
#   Process help and manual options
98
#
99
pod2usage(-verbose => 0, -message => "Version: $VERSION")  if ($opt_help == 1  || ! $result);
100
pod2usage(-verbose => 1)  if ($opt_help == 2 );
101
pod2usage(-verbose => 2)  if ($opt_manual || ($opt_help > 2));
102
 
103
#
104
#   Configure the error reporting process now that we have the user options
105
#
106
ErrorConfig( 'name'    => 'SANDBOX',
107
             'verbose' => $opt_verbose );
108
 
109
#
110
#   Validate user options
111
#
112
 
113
#
114
#   Parse the user command and decide what to do
115
#
116
#
117
my $cmd = shift @ARGV || "";
118
help(1)                                 if ( $cmd =~ m/^help$/ || $cmd eq "" );
119
create_sandbox()                        if ( $cmd =~ m/^create$/ );
120
info(@ARGV)                             if ( $cmd =~ m/^info$/ );
121
cmd(@ARGV)                              if ( $cmd =~ m/^cmd$/ );
122
 
123
Error ("Unknown sandbox command: $cmd");
124
exit 1;
125
 
126
 
127
#-------------------------------------------------------------------------------
128
#
129
#   Give the user a clue
130
#
131
sub help
132
{
133
    my ($level) = @_;
134
    $level = $opt_help unless ( $level );
135
 
136
    pod2usage(-verbose => 0, -message => "Version: ". $VERSION)  if ($level == 1 );
137
    pod2usage(-verbose => $level -1 );
138
}
139
 
140
#-------------------------------------------------------------------------------
141
# Function        : create_sandbox
142
#
143
# Description     : create a sandbox in the current current directory
144
#
145
# Inputs          : None
146
#
147
#
148
sub create_sandbox
149
{
150
    Error ("Cannot create a sandbox within a sandbox",
151
           "Sandbox base is: $GBE_SANDBOX" ) if ( $GBE_SANDBOX );
152
    mkdir ('sandbox_dpkg_archive') || Error ("Cannot create the directory: sandbox_dpkg_archive") ;
153
    exit  0;
154
}
155
 
156
#-------------------------------------------------------------------------------
157
# Function        : info
158
#
159
# Description     : Display Sandbox information
160
#
161
# Inputs          : Command line args
162
#                   -v  - Be more verbose
163
#
164
# Returns         : Will exit
165
#
166
sub info
167
{
168
    #
169
    #   Allow user to specify verboseness as an argument
170
    #
171
    foreach  ( @_ )
172
    {
173
        $opt_verbose++ if ( m/^-v/ )
174
    }
175
 
176
    #
177
    #   Determine Sandbox information
178
    #   Populate global variables
179
    #
180
    calc_sandbox_info();
181
 
182
    #
183
    #   Display information
184
    #
185
    Message ("Base: $GBE_SANDBOX");
186
    Message ("Archive: $GBE_DPKG_SBOX");
187
 
188
    Message ("Build Order");
189
    foreach my $fe ( @build_order )
190
    {
245 dpurdie 191
        Message( "    Level:" . $fe->{level} . " Name: " . $fe->{mname} );
227 dpurdie 192
        Message( DisplayPath ("        Path: $fe->{dir}" )) if $opt_verbose;
193
 
194
        if ( $opt_verbose )
195
        {
196
            foreach my $idep ( sort keys %{$fe->{ideps}} )
197
            {
198
                my ($ppn,$pps) = split( $; , $idep);
199
                Message ("        I:$ppn.$pps");
200
            }
201
 
202
            foreach my $edep ( sort keys %{$fe->{edeps}} )
203
            {
204
                my ($ppn,$pps) = split( $; , $edep);
205
                my $pv = $fe->{edeps}{$edep};
206
                Message ("        E:$ppn $pv.$pps");
207
            }
208
 
209
        }
210
    }
211
 
212
    Message("External Dependancies");
213
    foreach my $de ( sort keys %extern_deps )
214
    {
215
        my ($pn,$ps) = split( $; , $de);
216
        my @vlist = keys %{$extern_deps{$de}};
217
        my $flag = $#vlist ? '*' : ' ';
218
        foreach my $pv ( @vlist )
219
        {
220
            Message ("   $flag$pn $pv.$ps");
221
            if ( $opt_verbose )
222
            {
223
                foreach my $pkg ( @{$extern_deps{$de}{$pv}} )
224
                {
225
                    my ($ppn,$pps) = split( $; , $pkg);
226
                    Message ("        U:$ppn.$pps");
227
 
228
                }
229
            }
230
        }
231
    }
232
 
233
    if ( $opt_verbose > 2 )
234
    {
235
        DebugDumpData( "extern_deps", \%extern_deps);
236
        DebugDumpData( "build_order", \@build_order);
237
        DebugDumpData( "packages", \%packages);
238
    }
239
    exit (0);
240
}
241
 
242
#-------------------------------------------------------------------------------
243
# Function        : calc_sandbox_info
244
#
245
# Description     : Examine the sandbox and determine all the important
246
#                   information
247
#
248
# Inputs          : None
249
#
250
# Returns         : Will exit if not in a sandbox
251
#                   Populates global variables
252
#                       @build_order - build ordered array of build entries
253
#
254
sub calc_sandbox_info
255
{
256
    #
257
    #   Start from the root of the sandbox
258
    #
259
    Error ("Command must be executed from within a Sandbox") unless ( $GBE_SANDBOX );
260
    chdir ($GBE_SANDBOX) || Error ("Cannot chdir to $GBE_SANDBOX");
261
 
262
    #
263
    #   Locate all packages within the sandbox
264
    #   These will be top-level directories - one per package
265
    #
266
    my @dirlist;
267
    my @build_list;
268
    foreach ( glob("*") )
269
    {
270
        next if ( m~^\.~ );
271
        next if ( m~dpkg_archive$~ );
272
        next unless ( -d $_ );
273
        Verbose ("Package discovered: $_");
274
        push @dirlist, $_;
275
 
276
        #
277
        #   Locate the build files in each package
245 dpurdie 278
        #   Scan the build files and extract dependancy information
227 dpurdie 279
        #
245 dpurdie 280
        my $bscanner = BuildFileScanner( $_, 'build.pl', '--LocateAll', '--ScanDependencies' );
281
        $bscanner->scan();
282
        my @blist = $bscanner->getInfo();
283
 
227 dpurdie 284
        Warning ("Package does not have build files: $_") unless ( @blist );
285
        Warning ("Package has multiple build files: $_") if ( $#blist > 0 );
245 dpurdie 286
        push @build_list, @blist;
227 dpurdie 287
    }
288
 
289
    #
290
    #   Process each build file and extract
291
    #       Name of the Package
292
    #       Dependency list
293
    #   Build up a hash of dependence information
294
    #
295
 
296
    my %depends;
245 dpurdie 297
    foreach my $be ( @build_list )
227 dpurdie 298
    {
245 dpurdie 299
        Verbose( DisplayPath ("Build file: " . $be->{dir} . " Name: " . $be->{file} ));
300
#        DebugDumpData ("be", $be );
227 dpurdie 301
 
302
        #
303
        #   Add into dependency struct
304
        #
245 dpurdie 305
        $depends{$be->{package}}{depends} = $be->{depends};
306
        $depends{$be->{package}}{entry} = $be;
227 dpurdie 307
    }
308
 
245 dpurdie 309
#DebugDumpData ("depends", \%depends );
310
 
227 dpurdie 311
    #
312
    #   Determine the build order
313
    #
314
    @build_order = ();
315
    my $more = 1;
316
    my $level = 0;
317
 
318
    #
319
    #   Remove any dependancies to 'external' packages
320
    #   These will not be met internally and can be regarded as constant
321
    #
322
    foreach my $key ( keys %depends )
323
    {
324
        foreach my $build ( keys( %{$depends{$key}{depends}} ))
325
        {
326
            unless (exists $depends{$build})
327
            {
328
                push @{$extern_deps{$build}{$depends{$key}{depends}{$build}}}, $key;
329
                $depends{$key}{entry}{edeps}{$build} = $depends{$key}{depends}{$build};
330
                delete ($depends{$key}{depends}{$build}) ;
331
                Verbose2( "Not in set: $build");
332
            }
333
            else
334
            {
335
                $depends{$key}{entry}{ideps}{$build} = 1;
336
            }
337
        }
338
    }
339
    while ( $more )
340
    {
341
        $more = 0;
342
        $level++;
343
        my @build;
344
 
345
        #
346
        #   Locate packages with no dependencies
347
        #
348
        foreach my $key ( keys %depends )
349
        {
350
            next if ( keys( %{$depends{$key}{depends}} ) );
351
            push @build, $key;
352
        }
353
 
354
        foreach my $build ( @build )
355
        {
356
            $more = 1;
357
            my $fe = $depends{$build}{entry};
358
            $fe->{level} = $level;
359
            $packages{$build} = $fe;
360
            push @build_order, $fe;
361
            delete $depends{$build};
362
            delete $fe->{depends};                          # remove now its not needed
363
        }
364
 
365
        foreach my $key ( keys %depends )
366
        {
367
            foreach my $build ( @build )
368
            {
369
                delete $depends{$key}{depends}{$build};
370
            }
371
        }
372
    }
373
 
374
    #
375
    #   Just to be sure to be sure
376
    #
245 dpurdie 377
    if ( keys %depends )
378
    {
379
        #DebugDumpData ("depends", \%depends );
380
        Error( "Internal algorithm error: Bad dependancy walk",
381
               "Possible circular dependency");
382
    }
227 dpurdie 383
 
384
#    DebugDumpData ("Order", \@build_order);
385
}
386
 
387
#-------------------------------------------------------------------------------
388
# Function        : cmd
389
#
390
# Description     : Execute a command in all the sandboxes
391
#                       Locate the base of the sandbox
392
#                       Locate all packages in the sandbox
393
#                       Locate all build files in each sandbox
394
#                       Determine build order
395
#                       Issue commands for each sandbox in order
396
#
397
# Inputs          : Arugments passed to jats build
398
#
399
# Returns         : Will exit
400
#
401
sub cmd
402
{
403
    my @cmds = @_;
404
    #
405
    #   Determine Sandbox information
406
    #   Populate global variables
407
    #
408
    calc_sandbox_info();
409
    foreach my $fe ( @build_order )
410
    {
411
        my $dir = $fe->{dir};
412
        Message( "Level:" . $fe->{level} . " Name: " . $fe->{pname} ,
413
                  DisplayPath ("        Path: $fe->{dir}" ));
414
 
415
        my $result = JatsCmd( "-cd=$dir @cmds");
416
        Error ("Cmd faulure") if ( $result );
417
    }
418
 
419
    exit 0;
420
}
421
 
422
#-------------------------------------------------------------------------------
423
#   Documentation
424
#
425
 
426
=pod
427
 
428
=head1 NAME
429
 
430
jats_sandbox - Build in a Development Sandbox
431
 
432
=head1 SYNOPSIS
433
 
434
  jats sandbox [options] [comamnds]
435
 
436
 Options:
437
    -help              - brief help message
438
    -help -help        - Detailed help message
439
    -man               - Full documentation
440
 
441
 Commands:
442
    help                - Same as -help
443
    create              - Create a sandbox in the current directory
444
    info [-v]           - Sandbox information. -v: Be more verbose
445
    cmd                 - Do commands in all sandbox components
446
 
447
=head1 OPTIONS
448
 
449
=over 8
450
 
451
=item B<-help>
452
 
453
Print a brief help message and exits.
454
 
455
=item B<-help -help>
456
 
457
Print a detailed help message with an explanation for each option.
458
 
459
=item B<-man>
460
 
461
Prints the manual page and exits.
462
 
463
=head1 DESCRIPTION
464
 
465
This program is the primary tool for the maintainnace of Development Sandboxes
466
More documentation will follow.
467
 
468
=cut
469