#! /usr/bin/env perl # The contents of this file are subject to the Netscape Public License # Version 1.0 (the "NPL"); you may not use this file except in # compliance with the NPL. You may obtain a copy of the NPL at # http://www.mozilla.org/NPL/ # # Software distributed under the NPL is distributed on an "AS IS" basis, # WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL # for the specific language governing rights and limitations under the # NPL. # # The Initial Developer of this code under the NPL is Netscape # Communications Corporation. Portions created by Netscape are # Copyright (C) 1999 Netscape Communications Corporation. All Rights # Reserved. # # make-makefiles - Quickly create Makefiles for subdirectories. # Also, creates any needed subdirectories. # # usage: make-makefiles [ -d ] [ | /Makefile ] ... # Send comments, improvements, bugs to Steve Lamm (slamm@netscape.com). #$debug = 1; # Determine various tree path variables # ($depth, @makefiles) = parse_arguments(@ARGV); $object_fullpath = `pwd`; chdir $depth; $object_root = `pwd`; chomp $object_fullpath; chomp $object_root; # $source_subdir is the path from the object root to where # 'make-makefile' was called. For example, if make-makefile was # called from "mozilla/gfx/src", then $source_subdir would be # "gfx/src/". $source_subdir = "$object_fullpath/"; $source_subdir =~ s|^$object_root/||; # Prefix makefiles with $source_subdir so that paths # will be relative to the top of the object tree. # for $makefile (@makefiles) { $makefile = "$source_subdir$makefile"; } create_directories(@makefiles); # Find the path to the source directory based on how 'make-makefile' # was invoked. The path is either relative to the object directory # or an absolute path. $given_srcdir = find_srcdir($0, $depth); if ($debug) { warn "object_fullpath = $object_fullpath\n"; warn "object_root = $object_root\n"; warn "source_subdir = $source_subdir\n"; warn "makefiles = @makefiles\n"; warn "given_srcdir = $given_srcdir\n"; } @unhandled = update_makefiles($given_srcdir, @makefiles); run_config_status(@unhandled); # end of Main ############################################################ sub dirname { return $_[0] =~ /(.*)\/.*/ ? "$1" : '.'; } # find_depth: Pull the value of DEPTH out of a Makefile (or Makefile.in) sub find_depth { my $depth = ''; open(MAKEFILE, "<$_[0]") || die "Unable to open $_[0]: $!\n"; while () { next unless /^DEPTH\s*=\s*(\..*)/; $depth = $1; last; } close MAKEFILE; return $depth; } sub parse_arguments { my @args = @_; my $depth = ''; my @makefiles = (); if ($args[0] eq '-d') { $depth = $args[1]; shift @args; shift @args; } else { # Use $(DEPTH) in the Makefile or Makefile.in to determine the depth if (-e "Makefile.in") { $depth = find_depth("Makefile.in"); } elsif (-e "Makefile") { $depth = find_depth("Makefile"); } elsif (-e "../Makefile") { $depth = "../".find_depth("../Makefile"); $depth =~ s/\/\.$//; } else { warn "Unable to determine depth (e.g. ../..) to root of objdir tree.\n"; die "No Makefile(.in) present. Try running with '-d '\n"; } } # Build the list of makefiles to generate # @makefiles = (); my $makefile; foreach $makefile (@args) { $makefile =~ s/\.in$//; $makefile =~ s/\/$//; $makefile =~ /Makefile$/ or $makefile .= "/Makefile"; push @makefiles, "$makefile"; } @makefiles = "Makefile" unless @args; return ($depth, @makefiles); } # Create all the directories at once. # This can be much faster than calling mkdir() for each one. sub create_directories { my @makefiles = @_; my @dirs = (); my %have_seen = (); my $ac_file; foreach $ac_file (@makefiles) { next if $ac_file =~ /:/; my $ac_dir = dirname($ac_file); while (not defined $have_seen{$ac_dir}) { $have_seen{$ac_dir} = 1; last if -d $ac_dir; push @dirs, $ac_dir; $ac_dir =~ s/\/[^\/]+$//; } } # Call mkdir with the directories sorted by subdir count (how many /'s) system "mkdir ". join(' ', sort { split(/\//,$a) <=> split(/\//,$b) } @dirs ) if @dirs; } # Find the top of the source directory # (Assuming that the executable is in $top_srcdir/build/autoconf) sub find_srcdir { my ($program_name, $depth) = @_; my $ac_given_srcdir = $program_name; $ac_given_srcdir =~ s|/?build/autoconf/.*$||; if ($debug) { print "ac_given_srcdir = $ac_given_srcdir\n"; print "depth = $depth\n"; } if ($ac_given_srcdir =~ /^\./ and $depth ne '.') { my $quoted_depth = quotemeta($depth); $ac_given_srcdir =~ s|^$quoted_depth/?||; } if ($debug) { print "ac_given_srcdir = $ac_given_srcdir\n"; } $ac_given_srcdir = '.' if $ac_given_srcdir eq ''; return $ac_given_srcdir; } # Output the makefiles. # sub update_makefiles { my ($ac_given_srcdir, @makefiles) = @_; my @unhandled=(); my $ac_file; foreach $ac_file (@makefiles) { my $ac_file_in = "$ac_given_srcdir/${ac_file}.in"; my $ac_dir = dirname($ac_file); my $ac_dots = ''; my $ac_dir_suffix = ''; my $srcdir = '.'; my $top_srcdir = '.'; # Determine $srcdir and $top_srcdir # if ($ac_dir ne '.') { $ac_dir_suffix = "/$ac_dir"; $ac_dir_suffix =~ s%^/\./%/%; $ac_dots = $ac_dir_suffix; $ac_dots =~ s%/[^/]*%../%g; } if ($ac_given_srcdir eq '.') { if ($ac_dots ne '') { $top_srcdir = $ac_dots; $top_srcdir =~ s%/$%%; } } elsif ($ac_given_srcdir =~ m%^/%) { $srcdir = "$ac_given_srcdir$ac_dir_suffix"; $top_srcdir = "$ac_given_srcdir"; } else { $srcdir = "$ac_dots$ac_given_srcdir$ac_dir_suffix"; $top_srcdir = "$ac_dots$ac_given_srcdir"; } if ($debug) { print "ac_dir = $ac_dir\n"; print "ac_file = $ac_file\n"; print "ac_file_in = $ac_file_in\n"; print "srcdir = $srcdir\n"; print "top_srcdir = $top_srcdir\n"; print "cwd = " . `pwd` . "\n"; } # Copy the file and make substitutions. # @srcdir@ -> value of $srcdir # @top_srcdir@ -> value of $top_srcdir # if (-e $ac_file) { next if -M _ < -M $ac_file_in; # Next if Makefile is up-to-date. warn "updating $ac_file\n"; } else { warn "creating $ac_file\n"; } open INFILE, "<$ac_file_in" or do { warn "$0: Cannot read $ac_file_in: No such file or directory\n"; next; }; open OUTFILE, ">$ac_file" or do { warn "$0: Unable to create $ac_file\n"; next; }; while () { if (/\@[_a-zA-Z]*\@.*\@[_a-zA-Z]*\@/) { #warn "Two defines on a line:$ac_file:$.:$_"; push @unhandled, $ac_file; last; } s/\@srcdir\@/$srcdir/; s/\@top_srcdir\@/$top_srcdir/; if (/\@[_a-zA-Z]*\@/) { #warn "Unknown variable:$ac_file:$.:$_"; push @unhandled, $ac_file; last; } print OUTFILE; } close INFILE; close OUTFILE; } return @unhandled; } sub run_config_status { my @unhandled = @_; # Run config.status with any unhandled files. # if (@unhandled) { $ENV{CONFIG_FILES}= join ' ', @unhandled; system "./config.status"; } }