2
# ***** BEGIN LICENSE BLOCK *****
3
# Version: MPL 1.1/GPL 2.0/LGPL 2.1
5
# The contents of this file are subject to the Mozilla Public License Version
6
# 1.1 (the "License"); you may not use this file except in compliance with
7
# the License. You may obtain a copy of the License at
8
# http://www.mozilla.org/MPL/
10
# Software distributed under the License is distributed on an "AS IS" basis,
11
# WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12
# for the specific language governing rights and limitations under the
15
# The Original Code is mozilla.org code.
17
# The Initial Developer of the Original Code is
18
# Netscape Communications Corporation.
19
# Portions created by the Initial Developer are Copyright (C) 1999-2011
20
# the Initial Developer. All Rights Reserved.
23
# Steve Lamm <slamm@netscape.com>
24
# Joey Armstrong <joey@mozilla.com>
26
# Alternatively, the contents of this file may be used under the terms of
27
# either of the GNU General Public License Version 2 or later (the "GPL"),
28
# or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29
# in which case the provisions of the GPL or the LGPL are applicable instead
30
# of those above. If you wish to allow use of your version of this file only
31
# under the terms of either the GPL or the LGPL, and not to allow others to
32
# use your version of this file under the terms of the MPL, indicate your
33
# decision by deleting the provisions above and replace them with the notice
34
# and other provisions required by the GPL or the LGPL. If you do not delete
35
# the provisions above, a recipient may use your version of this file under
36
# the terms of any one of the MPL, the GPL or the LGPL.
38
# ***** END LICENSE BLOCK *****
40
##----------------------------##
41
##---] CORE/CPAN INCLUDES [---##
42
##----------------------------##
51
use File::Path qw{mkpath};
53
##-------------------##
55
##-------------------##
56
our $VERSION = qw(2.0);
58
##--------------------##
59
##---] INCLUDES [---##
60
##--------------------##
62
##############################################################
63
# pymake: special case path handling for windows cmd shell.
64
# if invoked by cmd.exe and msys-perl is in play
65
# $0 may contain a drive letter
66
# modules use-or-expect msys/unix paths
67
# adjust $0 => C:/foo => /c/foo so string tests and
68
# manipulation can by applied properly.
69
##############################################################
72
if ($^O eq 'msys' && $ENV{PATH} =~ m!\w:/!)
80
use lib $FindBin::Bin;
83
##-------------------##
85
##-------------------##
88
my $t0 = Benchmark->new();
93
my $t1 = Benchmark->new();
94
my $delta = timediff($t1, $t0);
95
print STDERR timestr($delta), "\n";
104
my $debug = $argv{debug} || 0;
106
my $pwdcmd = ($^O eq 'msys') ? 'pwd -W' : 'pwd';
108
# Determine various tree path variables
110
my ($topsrcdir, $ptopsrcdir, $depth, @makefiles) = parse_arguments(@ARGV);
112
my $object_fullpath = `$pwdcmd`; # Cwd::getcwd()
114
my $object_root = `$pwdcmd`; # Cwd::getcwd()
115
chomp $object_fullpath;
118
# $source_subdir is the path from the object root to where
119
# 'make-makefile' was called. For example, if make-makefile was
120
# called from "mozilla/gfx/src", then $source_subdir would be
122
my $source_subdir = "$object_fullpath/";
123
my $quoted_object_root = quotemeta($object_root);
124
$source_subdir =~ s|^$quoted_object_root/||;
126
# Prefix makefiles with $source_subdir so that paths
127
# will be relative to the top of the object tree.
130
for $makefile (@makefiles) { # dead code ?
131
$makefile = "$source_subdir$makefile";
134
# Find the path to the source directory based on how 'make-makefile'
135
# was invoked. The path is either relative to the object directory
136
# or an absolute path.
137
my $given_srcdir = find_srcdir($topsrcdir, $depth);
138
my $pgiven_srcdir = find_srcdir($ptopsrcdir, $depth);
141
warn "object_fullpath = $object_fullpath\n";
142
warn "object_root = $object_root\n";
143
warn "source_subdir = $source_subdir\n";
144
warn "makefiles = @makefiles\n";
145
warn "given_srcdir = $given_srcdir\n";
149
my @unhandled = update_makefiles_legacy($given_srcdir, $pgiven_srcdir, @makefiles);
150
push(@errors, $@) if ($@);
152
run_config_status(@unhandled);
153
push(@errors, $@) if ($@ && $argv{'no-warnings'});
155
exit scalar(@errors);
158
############################################################
160
###########################################################################
161
# find_depth: Pull the value of DEPTH out of a Makefile (or Makefile.in)
162
###########################################################################
165
open(MAKEFILE, "<$_[0]") || die "Unable to open $_[0]: $!\n";
167
next unless /^DEPTH\s*=\s*(\..*)/;
175
###########################################################################
176
## Intent: Parse command line arguments and assign values
177
###########################################################################
178
sub parse_arguments {
182
my @arglist = qw(badtokens! bench
187
obj=s top|t=s ptop|p=s
190
unless(GetOptions(\%argv, @arglist))
192
my $script = join('/', $FindBin::RealBin, $FindBin::Script);
193
system("perldoc $script </dev/null");
198
my $topsrcdir = $argv{top} || '';
201
$topsrcdir = $argv{top} = getTopDir();
204
my $ptopsrcdir ||= $argv{ptop} || $topsrcdir || '';
206
## Init --no- switch values
207
foreach my $var (qw(badtokens exclusions warnings))
209
$argv{"no-${var}"} = $argv{$var} || 0;
211
# Propogate parsed arguments for module use [--debug, --verbose]
212
while (my($k, $v) = each %argv)
214
$main::argv{$k} = $v;
219
chdir $argv{chdir} || die "chdir $argv{chdir} failed: $!";
222
##############################################################
223
## Arguments allowing make-makefile to be invoked from $topsrc
224
##############################################################
225
if (!$argv{top} || !$argv{obj})
228
## Limit access to container makefiles for now
229
elsif ($argv{enhanced})
233
## iterate over @ARGV to preserve original filename for 'unhandled'
234
my @files = map{ getRelPath($_) } @ARGV;
236
my $top = getTopDir();
237
my $obj = getObjDir();
239
mkdirr(map{ "$obj/$_" } @files);
240
push(@errors, $@) if ($@); # legacy behavior: do not exit with status
242
my $exclude = join('/', $FindBin::RealBin, $FindBin::Script);
243
$exclude .= '.excl'; # $argv{exclude}
244
my %exclude = getExclusions($exclude);
246
foreach my $relpath (@files)
248
my $rel = join('/', $relpath, 'Makefile.in');
249
my $mf = join('/', $top, $rel);
250
next if ($exclude{$rel});
251
print STDERR " ** relpath=[$relpath], mf=[$mf]\n" if ($main::argv{debug});
253
my $rc = updateMakefiles($relpath, {depth=>$depth, obj=>$obj, top=>$top});
258
elsif ($rc eq 'badtokens')
260
push(@unhandled, $mf);
264
run_config_status(@unhandled);
265
push(@errors, $@) if ($@ && $argv{'no-warnings'});
266
exit scalar(@errors);
270
my $depth = $argv{depth} || '';
273
foreach my $fyl (@args)
275
if (my $tmp = find_depth($fyl))
284
# Use $(DEPTH) in the Makefile or Makefile.in to determine the depth
285
if (-e "Makefile.in") {
286
$depth = find_depth("Makefile.in");
287
} elsif (-e "Makefile") {
288
$depth = find_depth("Makefile");
289
} elsif (-e "../Makefile") {
290
$depth = "../".find_depth("../Makefile");
293
warn "Unable to determine depth (e.g. ../..) to root of objdir tree.\n";
294
die "No Makefile(.in) present. Try running with '-d <depth>'\n";
298
# Build the list of makefiles to generate
303
next unless my $makefile = shift @args;
304
$makefile =~ s/\.in$//;
305
$makefile =~ s/\/$//;
306
$makefile =~ /Makefile$/
307
or $makefile =~ /^\.\//
308
or $makefile .= "/Makefile";
309
push @makefiles, "$makefile";
311
@makefiles = "Makefile" unless @makefiles;
313
return ($topsrcdir, $ptopsrcdir, $depth, @makefiles);
316
# Find the top of the source directory
317
# (Assuming that the executable is in $top_srcdir/build/autoconf)
319
my ($ac_given_srcdir, $depth) = @_;
322
print "ac_given_srcdir = $ac_given_srcdir\n";
323
print "depth = $depth\n";
325
if ($ac_given_srcdir =~ /^\./ and $depth ne '.') {
326
my $quoted_depth = quotemeta($depth);
327
$ac_given_srcdir =~ s|^$quoted_depth/?||;
330
print "ac_given_srcdir = $ac_given_srcdir\n";
332
$ac_given_srcdir = '.' if $ac_given_srcdir eq '';
333
return $ac_given_srcdir;
337
###########################################################################
339
###########################################################################
344
make-makefile - Generate a Makefile from a F<Makefile.in> template
348
make-makefile [--top t] [--obj o] [--depth d] foo/bar/Makefile.in tans/fans/Makefile foo/bar
352
Given options and makefile path arguments determine path to the template
353
F<Makefile.in> beneath a source directory and path to generated F<Makefile>
354
beneath $MOZ_OBJDIR. DEPTH from destination directory to the 'root' will
355
also be determined. F<Makefile.in> will be read in, template strings of the
356
gorm @token@ will be replaced with derived values and a generated makefile
357
will be written out as F<Makefile>.
359
Makefile DEPTH= can be determined in a few different ways:
360
o The string C<DEPTH=../../..> may be embedded within F<Makefile.in>.
361
o Search parent directories for F<Makefile.in> and use it to assign the child.
370
Move to this directory before doing anything else
374
Explicitly specify the relative path from directory containing Makefile.in
375
to the top sandbox directory. memory/makefile, DEPTH=../.., js/src/config, DEPTH=..
379
Use alternate/simplified path construction when options --top and --obj are
380
passed. This feature will be used by container makefiles to support makefile
381
generation while cd'd into the sandbox top directory.
385
Path the root of a development sandbox.
389
Path to object directory where generated makefile will be written ($MOZ_OBJDIR).
398
=head2 Options List DEBUG
404
Enable script benchmarking, report elapsed runtime.
408
Enable script debug mode.
413
=head2 Options List --NO-
417
=item --no-badtokens (wip)
419
Handle unexpanded @token@ makefile tokens as an error condition.
420
Do not rely on system(config.status) to externally supply values.
424
Ignore file entries on the exclusion list, generate everything.
428
Warnings are handled as an error condition.
437
=item * make-makefile -t /mozilla/nightly -d . memory/mozalloc
440
--top and --depth are explicitly set for generting memory/mozalloc/Makefile.
442
=item * make-makefile -t /mozilla/nightly -d ../../../.. html5lib_tree_construction/Makefile
444
cd $MOZ_OBJDIR/parser/htmlparser/tests/mochitest
446
--top and --depth are explicitly set for generting a makefile from within
447
a subdirectory of $MOZ_OBJDIR
449
=item * make-makefile --top /mozilla/nightly --obj /mozilla/nightly/obj memory/mozalloc
451
With --top and --obj explicitly set generate $MOZ_OBJDIR/memory/mozalloc/Makefile
452
while sitting in the sandbox root.
457
=head2 Work In Progress
463
Fail on unexpanded @foo@ makefile tokens. Any tokens that can be expanded
464
directly by make-makefile will avoid config.status shell overhead.
466
=item Depth from delta(--obj, --top)
468
If DEPTH= has not been embedded within a makefile the value could
469
be set directly if --top and --obj are specified and the paths overlap.