Subversion Repositories DevTools

Rev

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

Rev Author Line No. Line
227 dpurdie 1
#! perl
2
########################################################################
3
# Copyright (C) 2006 ERG Limited, All rights reserved
4
#
5
# Module name   : jats_buildperl.pl
6
# Module type   : Makefile system
7
# Compiler(s)   : n/a
8
# Environment(s): jats
9
#
10
# Description   : A utility to assist in building PERL Modules
11
#                 These are modules that need to be built via there
12
#                 own Makefile.PL - not to be confused with a JATS file
13
#                 of the same name.
14
#
15
#                 This script is intended to be called from within a JATS
16
#                 makefile.
17
#
18
# Usage:
19
#
20
#......................................................................#
21
 
22
require 5.6.1;
23
use strict;
24
use warnings;
25
use Cwd;
26
use FileUtils;
27
use JatsSystem;
28
use JatsError;
29
use ArrayHashUtils;
30
use File::Path;
31
use File::Copy;
32
use File::Find;
33
use Getopt::Long;
34
use Pod::Usage;                             # required for help support
35
use Config;
36
 
37
#
38
#   Initialise and configure some of the used packages
39
#
40
ErrorConfig( 'name' => 'BuildPerl' );
41
SystemConfig ( 'ExitOnError' => 1);
42
InitFileUtils();
43
 
44
#
45
#   Global variables
46
#
47
my $VERSION = "1.0.0";                      # Update this
48
my $opt_debug   = $ENV{'GBE_DEBUG'};        # Allow global debug
49
my $opt_verbose = $ENV{'GBE_VERBOSE'};      # Allow global verbose
50
my $opt_help = 0;
51
my $opt_manual = 0;
52
my $opt_test = 1;
53
my $opt_clean = 0;
54
my $opt_clean_build = 0;
55
 
56
my @MAKE = 'make';
57
my $BASE = Getcwd();
58
my $PKG_DIR;
59
my @PACKAGES;
60
my %PCMDS;
61
my $GBE_MACHTYPE = '';
62
my @PERL5LIB_BASE = split( $ScmPathSep, $ENV{PERL5LIB});
63
 
64
#
65
#   Extract arguments
66
#
67
my $result = GetOptions (
68
                "help+"         => \$opt_help,              # flag, multiple use allowed
69
                "manual"        => \$opt_manual,            # flag, multiple use allowed
70
                "verbose+"      => \$opt_verbose,           # flag, multiple use allowed
71
                "test!"         => \$opt_test,              # Flag, NoFlag
72
                "clean!"        => \$opt_clean,             # Flag, NoFlag
73
                "PackageDir=s"  => \$PKG_DIR,               # String
74
                "PerlPackage=s" => \@PACKAGES,              # String
75
                "MachType=s"    => \$GBE_MACHTYPE,          # String
76
                "clean_build"   => \$opt_clean_build,       # Flag
77
                );
78
 
79
#
80
#   Process help and manual options
81
#
82
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ($opt_help == 1 || ! $result);
83
pod2usage(-verbose => 1) if ($opt_help == 2 );
84
pod2usage(-verbose => 2) if ($opt_manual || ($opt_help > 2));
85
pod2usage(-verbose => 0, -message => "Version: $VERSION") if ( $#ARGV >= 0 );
86
 
87
#
88
#   Sanity Test user input
89
#
90
Error ("No output directory specified") unless ( $PKG_DIR );
91
Error ("No Perl Packages to build" ) unless ( @PACKAGES );
92
Error ("No GBE_MACHTYPE specified" ) unless ( $GBE_MACHTYPE );
93
 
94
#
95
#   Packaging directories
96
#       $PKG_DOC    - Where to place copyright notices
97
#       $PKG_PERL   - Where to place perl output
98
#
99
my $PKG_DIR_ABS  = AbsPath( $PKG_DIR );
100
my $PKG_DOC = "$PKG_DIR_ABS/doc";
101
my $PKG_PERL= "$PKG_DIR_ABS/pkg/pkg.$GBE_MACHTYPE";
102
 
103
#
104
#   Process PACKAGES and extract the package options
105
#
106
my @PKGS;
107
for my $arg (@PACKAGES)
108
{
109
    my ($name,@options) = split( ',', $arg );
110
    UniquePush \@PKGS, $name;
111
    push @{$PCMDS{$name}}, @options;
112
}
113
@PACKAGES = @PKGS;
114
@PKGS = ();
115
 
116
 
117
Message    "======================================================================";
118
Message    "Build Perl using the native build method";
119
Message    "     GBE_MACHTYPE : $GBE_MACHTYPE";
120
Message    "          Package : $PKG_DIR";
121
for my $ii (@PACKAGES)
122
{
123
    Message    "      PerlPackage : $ii";
124
}
125
Message    "======================================================================";
126
 
127
#
128
#   Sanity test the Perl Packages
129
#
130
for my $ii (@PACKAGES)
131
{
132
    Error ("Cannot file package: $ii") unless ( -d $ii );
133
    Error ("Perl Package does not contain Makefile.PL") unless ( -f "$ii/Makefile.PL" );
134
}
135
 
136
#
137
#   Remove some 'make' environment variables
138
#   The JATS make and the PACKAGE make must not know about each other
139
#
140
foreach my $var qw ( MAKE MAKEFLAGS MAKEOVERRIDES MAKELEVEL MAKE_MODE CC CXX CPP )
141
{
142
    delete $ENV{$var};
143
}
144
 
145
#
146
#   Windows specials
147
#
148
if ( ! $ENV{GBE_UNIX}   )
149
{
150
    #
151
    #   Must use nmake under windows
152
    #
153
    @MAKE = ('nmake', '-nologo');
154
 
155
    #
156
    #   JATS sh fiddles with ComSpec under Windows
157
    #   Reinstate the original COMSPEC
158
    #
159
    $ENV{COMSPEC} =~ s~/~\\~g
160
}
161
 
162
#
163
#   Clean the build request
164
#   This will be invoked by a JATS clean
165
#
166
if ( $opt_clean_build )
167
{
168
    Message "Clean perl build directory";
169
    for my $ii (@PACKAGES)
170
    {
171
        if ( -f "$ii/Makefile" )
172
        {
173
            make( "Cleaning: $ii", $ii, 'clean' );
174
            unlink  "$ii/Makefile.new", "$ii/Makefile.old";
175
        }
176
    }
177
    exit 0;
178
}
179
 
180
#
181
#   Determine info to extend the library search path
182
#   Need to look in site, version and architecture specific directories
183
#   into which packages that we are building may have inserted modules
184
#
185
my @lib_search_path;
186
my $pversion = $Config{version};
187
my $parch = $Config{archname};
188
 
189
push @lib_search_path, "site_perl/$pversion/$parch";
190
push @lib_search_path, "site_perl/$pversion";
191
push @lib_search_path, "$pversion/$parch";
192
push @lib_search_path, "$pversion";
193
 
194
Verbose ('Perl Version List', @lib_search_path );
195
 
196
#
197
#   Create the Makefiles, build and install the artifacts
198
#
199
Message "Invoke package builder";
200
for my $ii (@PACKAGES)
201
{
202
 
203
    #
204
    #   Extend the PERL5LIB so that modules can find the packages that have already
205
    #   been built. This will satisfy any prerequisites.
206
    #
207
    #   Only use top-level directories in the package directory
208
    #   Don't use lower directories as this confuses the module loader
209
    #
210
    CalcLibPath();
211
 
212
    #
213
    #   Generate the Makefile
214
    #
215
    Message ("Building: $ii", @{$PCMDS{$ii}} );
216
    chdir $ii || Error( "Cannot change to directory: $ii");
217
    System ( $ENV{GBE_PERL},  'Makefile.PL', "PREFIX=$PKG_PERL", @{$PCMDS{$ii}} );
218
    FixUpMakefile();
219
    chdir $BASE;
220
 
221
    rmtree("$ii/blib");
222
    unlink("$ii/pm_to_blib");
223
 
224
    #
225
    #   make all the default targets
226
    #
227
    make( "Building: $ii", $ii );
228
    make( "Installing: $ii", $ii, 'install' );
229
}
230
 
231
#
232
#   Test
233
#   Need to construct a PERL5LIB that will pick up all the .pm files
234
#
235
if ( $opt_test )
236
{
237
    Message "Calculate PERL5LIB for testing";
238
    CalcLibPath();
239
    Message("PERL5LIB: ", split( $ScmPathSep, $ENV{PERL5LIB} ) );
240
 
241
    Message "Testing Packages";
242
    for my $ii (@PACKAGES)
243
    {
244
        if ( -d "$ii/t" || -f "$ii/test.pl" )
245
        {
246
            make( "Testing: $ii", $ii, 'test' );
247
        }
248
        else
249
        {
250
            Message("No Tests found: $ii");
251
        }
252
    }
253
}
254
 
255
#
256
#   Transfer any COPYRIGHT files to the target package
257
#
258
Message "Transfer COPYRIGHT notice";
259
for my $ii (@PACKAGES)
260
{
261
    my $file = "$ii/COPYRIGHT";
262
    if ( -f $file )
263
    {
264
        my $package = StripDir ( $ii );
265
        my $target = "$PKG_DOC/$package";
266
        mkpath ( $target );
267
        unlink ( "$target/COPYRIGHT");
268
        copy( $file, $target ) || Error ( "Files not copied" );
269
    }
270
}
271
 
272
#
273
#   Cleanup the build output
274
#
275
if ( $opt_clean )
276
{
277
    Message "Clean build directory";
278
    for my $ii (@PACKAGES)
279
    {
280
        make( "Cleaning: $ii", $ii, 'clean' );
281
    }
282
}
283
 
284
Message "Script complete";
285
exit 0;
286
 
287
 
288
#-------------------------------------------------------------------------------
289
# Function        : FixUpMakefile
290
#
291
# Description     : Modify the generated Makefile to remove the doc_update recipe
292
#                   The doc_update step will mess with the perl installed on the
293
#                   build machine. This is not good.
294
#
295
# Inputs          :
296
#
297
# Returns         :
298
#
299
sub FixUpMakefile
300
{
301
    Message "Massage Makefile: remove doc_update";
302
    my $found = 0;
303
    open (MFH, '<', 'Makefile' )    || Error ("Cannot find generated Makefile");
304
    open (NFH, '>', 'Makefile.new') || Error ("Cannot create new Makefile");
305
    while ( <MFH> )
306
    {
307
        if ( m/^install ::/ )
308
        {
309
            $_ =~ s~doc_update~~g;
310
            $found = 1;
311
        }
312
        print NFH $_;
313
    }
314
    close MFH;
315
    close NFH;
316
 
317
}
318
 
319
#-------------------------------------------------------------------------------
320
# Function        : CalcLibPath
321
#
322
# Description     : Determine a suitale value for PERL5LIB to include
323
#                   directories in the package area
324
#
325
#                   Note: Do not use ALL subdirs in the package directory
326
#                         as a recusive devent of the pkg directory will confuse
327
#                         the module loader
328
#
329
#                   Use top level directories that contain .pm files
330
#
331
# Inputs          : None
332
#
333
# Returns         : Nothing
334
#                   Updates the EnvVar PERL5LIB
335
#
336
sub CalcLibPath
337
{
338
    my @dir_list =  grep -d $_ , glob( "$PKG_PERL/*" );
339
    my @lib_list;
340
 
341
    foreach my $dir ( @dir_list )
342
    {
343
        foreach my $subdir ( @lib_search_path )
344
        {
345
            push @lib_list, "$dir/$subdir"
346
                if ( -d "$dir/$subdir" );
347
        }
348
        push @lib_list, $dir;
349
    }
350
 
351
    $ENV{PERL5LIB} = join( $ScmPathSep, @lib_list, @PERL5LIB_BASE );
352
    Verbose ("PERL5LIB: ", split( $ScmPathSep, $ENV{PERL5LIB} ) );
353
}
354
 
355
#-------------------------------------------------------------------------------
356
# Function        : make
357
#
358
# Description     : Perform a 'make' in the required target directory
359
#
360
# Inputs          : $1  - Message
361
#                   $2  - Target directory
362
#                   $*  - Make arguments
363
#
364
# Returns         :
365
#
366
sub make
367
{
368
    my ($message, $dir, @args ) = @_;
369
 
370
    Message( $message ) if ( $message );
371
 
372
    chdir $dir || Error( "Cannot change to directory: $dir");
373
    System ( @MAKE , '-f', 'Makefile.new', @args );
374
    chdir $BASE;
375
}
376
 
377
1;
378
 
379
#-------------------------------------------------------------------------------
380
#   Documentation
381
#
382
 
383
=pod
384
 
385
=head1 NAME
386
 
387
jats_buildperl - Compile up a Perl (CPAN) Package
388
 
389
=head1 SYNOPSIS
390
 
391
perl jats_buildperl [options] (-PerlPackage=path)+
392
 
393
 Options:
394
    -help                       - brief help message
395
    -help -help                 - Detailed help message
396
    -man                        - Full documentation
397
    -[no]test                   - Test the packages
398
    -[no]clean                  - Clean the build area
399
    -PerlPackage=path[,options] - Path to the Perl Package to build
400
                                  Multiple packages are allowed
401
    -PackageDir=path            - Root of the output directory
402
    -GBE_MACHTYPE=name          - Type of the machine being used
403
 
404
=head1 OPTIONS
405
 
406
=over 8
407
 
408
=item B<-help>
409
 
410
Print a brief help message and exits.
411
 
412
=item B<-help -help>
413
 
414
Print a detailed help message with an explanation for each option.
415
 
416
=item B<-man>
417
 
418
Prints the manual page and exits.
419
 
420
 
421
=item B<-[no]test>
422
 
423
This option may be used to disable the testing phase on all packages. The
424
default operation is to run the tests found in each package.
425
 
426
=item B<-[no]clean>
427
 
428
This option can be used to disable the process of cleaning the build area
429
after each build. The default option is to clean the build area.
430
 
431
=item B<-PerlPackage=path[,options]>
432
 
433
This option specified the path to a Perl Package. The program expects to find
434
the file Makefile.PL in this path.
435
 
436
The options, if present are provide to the Makefile.pl as arguments.
437
 
438
Multiple instances of the one path are compined and the 'options' are merged.
439
This allows multiple options to be specified.
440
 
441
Multiple packages can be built at the same time, by using multiple
442
-PerlPackage options. At least one package must be specified.
443
 
444
=item B<--PackageDir=path>
445
 
446
Mandatory option. This option specifies the root of the packaging directory.
447
The program will place the build artifacts within this directory.
448
 
449
=item B<-GBE_MACHTYPE=name>
450
 
451
Mandatory option. This option specifies the type of machine on which the package
452
is being built. This is used to package up the  build artifacts.
453
 
454
 
455
=head1 DESCRIPTION
456
 
457
This program is used internally by Jats to implement the body of the MakePerlModule
458
directive. The command is not intended to be called by the user.
459
 
460
=head1 EXAMPLE
461
 
462
 MakePerlModule ('*', 'Crypt-Blowfish-2.10',
463
                      'Crypt-Blowfish_PP-1.12',
464
                      'Crypt-CBC-2.22',
465
                      '-notest' );
466
 
467
=cut
468