Subversion Repositories DevTools

Rev

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

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