X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ian/git?p=subdirmk.git;a=blobdiff_plain;f=build-aux%2Fsubdirmk-setup;h=616f6530f653ddec6e44ad5cb66261feda2f5dfb;hp=9f3c8c62a43ae7858af834a8595db26e7c245d38;hb=1dec8023efc8ce858935f96a09f84d97e69eba77;hpb=3fc89ce9c0395620a92340e8290c18e156ca367e diff --git a/build-aux/subdirmk-setup b/build-aux/subdirmk-setup old mode 100644 new mode 100755 index 9f3c8c6..616f653 --- a/build-aux/subdirmk-setup +++ b/build-aux/subdirmk-setup @@ -8,25 +8,187 @@ use strict; -our @allsubdirs = @ARGV; +our $srcdir; +our @subdirs = @ARGV; -sub write_makefile () { - start_output_file("Makefile"); - print O <=2; +shift @ARGV; +($srcdir, @subdirs) = @ARGV; + +our $root = [ '.', [ ] ]; +# each node is [ 'relative subdir name', \@children ] + +sub build_tree () { + foreach my $subdir (@subdirs) { + my @path = $subdir eq '.' ? () : split m{/+}, $subdir; + my $node = $root; + foreach my $d (@path) { + my ($c,) = grep { $_->[0] eq $d } @{ $node->[1] }; + if (!$c) { + $c = [ $d, [ ] ]; + push @{ $node->[1] }, $c; + } + $node = $c; + } + } +} + +sub target_varname ($$) { + my ($var_prefix, $target) = @_; + return $var_prefix.'TARGETS'.($target eq 'all' ? '' : "_$target"); +} + +our $writing_output; +our %output_files; + +sub close_any_output_file() { + return unless defined $writing_output; + O->error and die "error writing $writing_output.tmp: $! (?)\n"; + close O or die "error closing $writing_output.tmp: $!\n"; + $writing_output = undef; +} + +sub start_output_file ($) { + close_any_output_file(); + ($writing_output) = @_; + die if $output_files{$writing_output}++; + my $tmp = "$writing_output.tmp"; + open O, ">", $tmp or die "create $tmp: $!\n"; +} + +sub install_output_files () { + close_any_output_file(); + foreach my $f (sort keys %output_files) { + rename "$f.tmp", $f or die "install new $f: $!\n"; + } +} + +sub o { + die unless defined $writing_output; + print O @_ or die "error writing $writing_output.tmp: $!\n"; +} + +sub write_makefile ($$) { + my ($dir_prefix,$depth) = @_; + start_output_file("${dir_prefix}Makefile"); + my $cd = $depth ? join('/', ('..',) x $depth) : '.'; + o <) { + for (;;) { + unless (s{^(.*?)(\\)?(?=$esc)}{}) { o $_; last; } + o $1; + if ($2) { o $esclit; next; } + s{^$esc}{} or die "$_ ?"; + if (s{^$esc}{}) { o "$esclit$esclit" } + elsif (s{^TARGETS(?:_[0-9a-zA-Z_]+)?(?=\W)}{}) { + my $t = $2 // 'all'; + o target_varname($var_prefix, $t); + $targets->{$t}=1; + } + elsif (m{^(?=$caps_re)}) { o "${var_prefix}_" } + elsif (m{^(?=$lc_re)}) { o $dir_prefix } + elsif (s{^_}{}) { o "${var_prefix}_" } + elsif (s{^/}{}) { o $dir_prefix } + elsif (s{^=_}{}) { o $var_prefix } + elsif (s{^=/}{}) { o $dir_name } + elsif (s{^\^}{}) { o "\$(top_srcdir)${dir_suffix}" } + elsif (s{^\}}{}) { o "\$(abs_top_srcdir)${dir_suffix}" } + elsif (s{^(?:[ \t]+([~^]))?(?=[ \t]){}}{}) { + my $prefix = + !$1 ? $dir_prefix : + $1 eq '~' ? '$(abs_top_srcdir)'.$dir_suffix : + $1 eq '~' ? '$(abs_top_srcdir)'.$dir_suffix : + die; + my $after=''; + if (m{([ \t])$esc}) { ($_,$after) = ($`, $1.$'); } + s{(?<=[ \t])(?=\S)(?!\\\s*$)}{$prefix}g; + o $_; + $_ = $after; + } elsif (s{^![ \t]+}{}) { + o $_; + $_ = ''; + } elsif (s{^!(\pPosixWord+|\pPosixPunct+)[ \t]*}{}) { + $esclit = $1; + $esc = $esclit; + $esc =~ s/\W/\\$&/g; + } else { + die "bad escape $esclit$_ "; + } + } + } +} - my @thesedirs = $subdir, grep { $_ =~ m{^$subdir/} } @allsubdirs; - printf O "include $_/Subdir.mk" - +sub process_subtree ($$); +sub process_subtree ($$) { + # => list of descendants (in form SUBDIR/) + # recursive, children first + my ($node, $path); + my $dir_prefix = join '', map { "$_/" } @$path; + my $dir_suffix = join '', map { "/$_" } @$path; + my $dir_name = join '/', @$path ? @$path : '.'; + my $var_prefix = map { "${_}_" } @$path ? @$path : qw(TOP); + + write_makefile($dir_prefix, scalar @$path); + + my %targets = qw(all 1); + my @child_subdirs; + foreach my $child (@{ $node->[1] }) { + my @childpath = (@$path, $child->[0]); + push @child_subdirs, join '/', @childpath; + $targets{$_}++ foreach + process_subtree($child, [ ]); + } + start_output_file("${dir_prefix}Subdir.mk.tmp"); + + filter_subdir_mk($dir_prefix, $dir_suffix, $dir_name, + $var_prefix, \%targets); + + my @targets = sort keys %targets; + foreach my $target (@targets) { + my $target_varname = target_varname($var_prefix, $target); + print O <