Subversion Repositories DevTools

Rev

Rev 369 | Rev 6133 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
227 dpurdie 1
#! perl
2
########################################################################
5709 dpurdie 3
# Copyright (c) VIX TECHNOLOGY (AUST) LTD
227 dpurdie 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
 
255 dpurdie 22
require 5.006_001;
227 dpurdie 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
#
369 dpurdie 140
foreach my $var (qw ( MAKE MAKEFLAGS MAKEOVERRIDES MAKELEVEL MAKE_MODE CC CXX CPP ))
227 dpurdie 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
 
361 dpurdie 385
=for htmltoc    MAKEUTIL::
386
 
227 dpurdie 387
=head1 NAME
388
 
389
jats_buildperl - Compile up a Perl (CPAN) Package
390
 
391
=head1 SYNOPSIS
392
 
393
perl jats_buildperl [options] (-PerlPackage=path)+
394
 
395
 Options:
396
    -help                       - brief help message
397
    -help -help                 - Detailed help message
398
    -man                        - Full documentation
399
    -[no]test                   - Test the packages
400
    -[no]clean                  - Clean the build area
401
    -PerlPackage=path[,options] - Path to the Perl Package to build
402
                                  Multiple packages are allowed
403
    -PackageDir=path            - Root of the output directory
404
    -GBE_MACHTYPE=name          - Type of the machine being used
405
 
406
=head1 OPTIONS
407
 
408
=over 8
409
 
410
=item B<-help>
411
 
412
Print a brief help message and exits.
413
 
414
=item B<-help -help>
415
 
416
Print a detailed help message with an explanation for each option.
417
 
418
=item B<-man>
419
 
420
Prints the manual page and exits.
421
 
422
=item B<-[no]test>
423
 
424
This option may be used to disable the testing phase on all packages. The
425
default operation is to run the tests found in each package.
426
 
427
=item B<-[no]clean>
428
 
429
This option can be used to disable the process of cleaning the build area
430
after each build. The default option is to clean the build area.
431
 
432
=item B<-PerlPackage=path[,options]>
433
 
434
This option specified the path to a Perl Package. The program expects to find
435
the file Makefile.PL in this path.
436
 
437
The options, if present are provide to the Makefile.pl as arguments.
438
 
439
Multiple instances of the one path are compined and the 'options' are merged.
440
This allows multiple options to be specified.
441
 
442
Multiple packages can be built at the same time, by using multiple
443
-PerlPackage options. At least one package must be specified.
444
 
445
=item B<--PackageDir=path>
446
 
447
Mandatory option. This option specifies the root of the packaging directory.
448
The program will place the build artifacts within this directory.
449
 
450
=item B<-GBE_MACHTYPE=name>
451
 
452
Mandatory option. This option specifies the type of machine on which the package
453
is being built. This is used to package up the  build artifacts.
454
 
361 dpurdie 455
=back
227 dpurdie 456
 
457
=head1 DESCRIPTION
458
 
459
This program is used internally by Jats to implement the body of the MakePerlModule
460
directive. The command is not intended to be called by the user.
461
 
462
=head1 EXAMPLE
463
 
464
 MakePerlModule ('*', 'Crypt-Blowfish-2.10',
465
                      'Crypt-Blowfish_PP-1.12',
466
                      'Crypt-CBC-2.22',
467
                      '-notest' );
468
 
469
=cut
470