`all' is extra special: every directory has an `all'
target, which corresponds to &TARGETS.
+&:warn [!]WARNTAG ...
+ Suppress (with !) or re-enable (without !) warnings tagged
+ WARNTAG (see section `Warnings', below). The suppression list
+ is reset at the start of processing in each subdirectory.
+ Warnings that appear at the end of processing are controlled
+ by the final warning state after processing all the toplevel
+ input files (including Final.sd.mk).
+
&:changequote NEWQUOTE
changes the escape sequence from & to literally NEWQUOTE
NEWQUOTE may be any series of of non-whitespace characters,
(This assumes you have appropriate make variables src, PWD and
abs_src.)
+Warnings
+--------
+
+subdirmk's `generate' program, which does the acual &-substitution,
+can produce some warnings about your .sd.mk files. These can be
+suppressed with the &:warn directive. The warning tags are:
+
+ local+global
+ The same VARNAME was used both with and without an & prefix.
+ This can be confusing. Also, if you avoid this then you will
+ get a warning iff you accidentally leave off a needed &.
+
+ single-char-var
+ A variable expansion like $FBAR. make's expansion rules
+ interpret this as $(F)BAR. It's normally better to write
+ it this way, at least if the variable expansion is followed
+ by more letters. Note that &$FOO works differently to
+ raw make: it expands to $(sub_dir_FOO).
+
+ unknown-warning
+ &:warn was used to try to enable a warning that this version
+ of subdirmk does not understand. (Note that an attempt to
+ *dis*able an unknown warning is only reported if some other
+ warning was issued which might have been disabled.)
+
Subdirectory and variable naming
--------------------------------
our $err_file;
+our @warn_ena_dfl = map { $_ => 1 } qw(
+ local+global
+ single-char-var
+ unknown-warning
+);
+our %warn_ena = @warn_ena_dfl;
+
+our $warned;
+our %warn_unk;
+
sub err ($) {
my ($m) = @_;
die "subdirmk: ${err_file}:$.: $m\n";
}
-sub wrn ($) {
- my ($m) = @_;
- print STDERR "subdirmk: warning: ${err_file}:$.: $m\n";
+sub wrncore ($$) {
+ my ($wk,$m) = @_;
+ return 0 unless $warn_ena{$wk} // warn "internal error $wk ?";
+ $warned++;
+ print STDERR "subdirmk: warning ($wk): $m\n";
+ return 1;
+}
+
+sub wrn ($$) {
+ my ($wk,$m) = @_;
+ wrncore($wk, "${err_file}:$.: $m");
}
sub ddbl_only ($) {
$pop_nest->('macro');
od "endef\n";
next;
+ } elsif (s#^\s*$esc\:warn\s+(\S.*)$##) {
+ foreach my $wk (split /\s+/, $1) {
+ my $yes = $wk !~ s{^!}{};
+ if (defined $warn_ena{$wk}) {
+ $warn_ena{$wk} = $yes;
+ next;
+ } elsif ($yes) {
+ wrn 'unknown-warning',
+ "unknown warning $wk requested";
+ } else {
+ $warn_unk{$wk} //= "$f:$.";
+ }
+ }
+ next;
} elsif (s#^\s*$esc\:(?=(-?)include|macro)##) {
$buffering_output='';
} elsif (m#^\s*$esc\:([a-z][-0-9a-z_]*)#) {
od $2;
if (s{^\$}{}) { od $&; }
elsif (m{^[a-zA-Z]\w}) {
- wrn
+ wrn 'single-char-var',
'possibly confusing unbracketed single-char $-expansion';
}
elsif (m{^\(($esc)?([^()\$]+)\)} ||
my @childpath = (@$path, $child->[0]);
my $child_subdir = join '/', @childpath;
mkdir $child_subdir or $!==EEXIST or die "mkdir $child_subdir: $!\n";
+ local %warn_ena = @warn_ena_dfl;
push @{ $targets{$_} }, $child_subdir foreach
process_subtree($child, \@childpath);
}
foreach my $vn (sort keys %varref) {
my $vv = $varref{$vn};
next unless $vv->{''} && $vv->{1};
- print STDERR "subdirmk: warning: saw both $vn and &$vn\n";
+ wrncore 'local+global', "saw both $vn and &$vn" or return;
foreach my $amp ('', 1) {
printf STDERR " saw %s%s at %s\n",
($amp ? '&' : ''), $vn, $_
}
}
+sub print_warning_warnings () {
+ return unless $warned;
+ foreach my $wk (sort keys %warn_unk) {
+ wrncore 'unknown-warning',
+ "$warn_unk{$wk}: attempt to suppress unknown warning(s) \`$wk'";
+ }
+}
+
build_tree();
process_tree();
print_varref_warnings();
+print_warning_warnings();
install_output_files();