[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
FYI: multiple derivations rules for the same input suffix (PR/37)
From: |
Alexandre Duret-Lutz |
Subject: |
FYI: multiple derivations rules for the same input suffix (PR/37) |
Date: |
Mon, 01 Jul 2002 18:10:44 +0200 |
User-agent: |
Gnus/5.090007 (Oort Gnus v0.07) Emacs/21.2 (i386-debian-linux-gnu) |
I'm checking in this (on HEAD).
2002-07-01 Alexandre Duret-Lutz <address@hidden>
Handle multiple suffix rules with the same input extension.
For PR automake/37.
* automake.in (suffix_rules_default): New variable.
(suffix_rules): Redefine as a hash of hashes of pairs.
(initialize_per_input): Setup suffix_rules_default from
suffix_rules on first call, an override suffix_rules
with suffix_rules_default on following calls.
(struct) <output_extensions>: New attribute.
(register_language): Set the default for output_extensions.
Call register_suffix_rule for each suffix.
(derive_suffix, handle_languages): Adjust to the new definition
of $suffix.
(register_suffix_rule): New function.
(rule_define): Call register_suffix_rule.
* tests/suffix8.test, tests/suffix9.test, tests/suffix10.test:
New files.
* tests/Makefile.am (TESTS): Add them.
Index: automake.in
===================================================================
RCS file: /cvs/automake/automake/automake.in,v
retrieving revision 1.1313
diff -u -r1.1313 automake.in
--- automake.in 30 Jun 2002 22:44:12 -0000 1.1313
+++ automake.in 1 Jul 2002 16:05:30 -0000
@@ -59,7 +59,11 @@
'compile' => "\$",
# Flag to require compilation without linking (-c).
'compile_flag' => "\$",
- 'extensions' => '@',
+ 'extensions' => '@',
+ # A subroutine to compute a list of possible extensions of
+ # the product given the input extensions.
+ # (defaults to a subroutine which returns ('.$(OBJEXT)', '.lo'))
+ 'output_extensions' => "\$",
'flags' => "\$",
# The file to use when generating rules for this language.
@@ -449,6 +453,9 @@
# Options set via AM_INIT_AUTOMAKE.
my $global_options = '';
+# Same as $suffix_rules (declared below), but records only the
+# default rules supplied by the languages Automake supports.
+my $suffix_rules_default;
################################################################
@@ -584,12 +591,26 @@
# trailing `/'.
my %de_ansi_files;
-# This maps the source extension of a suffix rule to its
-# corresponding output extension.
-# FIXME: because this hash maps one input extension to one output
-# extension, Automake cannot handle two suffix rules with the same
-# input extension.
-my %suffix_rules;
+# This maps the source extension for all suffix rule seen to
+# a \hash whose keys are the possible output extensions.
+#
+# Note that this is transitively closed by construction:
+# if we have
+# exists $suffix_rules{$ext1}{$ext2}
+# && exists $suffix_rules{$ext2}{$ext3}
+# then we also have
+# exists $suffix_rules{$ext1}{$ext3}
+#
+# So it's easy to check whether '.foo' can be transformed to '.$(OBJEXT)'
+# by checking whether $suffix_rules{'.foo'}{'.$(OBJEXT)'} exist. This
+# will work even if transforming '.foo' to '.$(OBJEXT)' involves a chain
+# of several suffix rules.
+#
+# The value of `$suffix_rules{$ext1}{$ext2}' is the a pair
+# `[ $next_sfx, $dist ]' where `$next_sfx' is target suffix
+# for the next rule to use to reach '$ext2', and `$dist' the
+# distance to `$ext2'.
+my $suffix_rules;
# This is the name of the redirect `all' target to use.
my $all_target;
@@ -772,7 +793,17 @@
%de_ansi_files = ();
- %suffix_rules = ();
+
+ # The first time we initialize the variables,
+ # we save the value of $suffix_rules.
+ if (defined $suffix_rules_default)
+ {
+ $suffix_rules = $suffix_rules_default;
+ }
+ else
+ {
+ $suffix_rules_default = $suffix_rules;
+ }
$all_target = '';
@@ -865,6 +896,8 @@
'Name' => 'Header',
'extensions' => ['.h', '.H', '.hxx', '.h++', '.hh',
'.hpp', '.inc'],
+ # No output.
+ 'output_extensions' => sub { return () },
# Nothing to do.
'_finish' => sub { });
@@ -876,6 +909,8 @@
'compile' => '$(YACC) $(YFLAGS) $(AM_YFLAGS)',
'compiler' => 'YACCCOMPILE',
'extensions' => ['.y'],
+ 'output_extensions' => sub { (my $ext = $_[0]) =~ tr/y/c/;
+ return ($ext,) },
'rule_file' => 'yacc',
'_finish' => \&lang_yacc_finish,
'_target_hook' => \&lang_yacc_target_hook);
@@ -887,6 +922,8 @@
'compiler' => 'YACCCOMPILE',
'compile' => '$(YACC) $(YFLAGS) $(AM_YFLAGS)',
'extensions' => ['.y++', '.yy', '.yxx', '.ypp'],
+ 'output_extensions' => sub { (my $ext = $_[0]) =~ tr/y/c/;
+ return ($ext,) },
'_finish' => \&lang_yacc_finish,
'_target_hook' => \&lang_yacc_target_hook);
@@ -899,6 +936,8 @@
'compile' => '$(LEX) $(LFLAGS) $(AM_LFLAGS)',
'compiler' => 'LEXCOMPILE',
'extensions' => ['.l'],
+ 'output_extensions' => sub { (my $ext = $_[0]) =~ tr/l/c/;
+ return ($ext,) },
'_finish' => \&lang_lex_finish,
'_target_hook' => \&lang_lex_target_hook);
register_language ('name' => 'lexxx',
@@ -909,6 +948,8 @@
'compile' => '$(LEX) $(LFLAGS) $(AM_LFLAGS)',
'compiler' => 'LEXCOMPILE',
'extensions' => ['.l++', '.ll', '.lxx', '.lpp'],
+ 'output_extensions' => sub { (my $ext = $_[0]) =~ tr/l/c/;
+ return ($ext,) },
'_finish' => \&lang_lex_finish,
'_target_hook' => \&lang_lex_target_hook);
@@ -1695,12 +1736,9 @@
&& $lang->flags eq 'CFLAGS'
&& defined $options{'subdir-objects'});
- # FIXME: this is a temporary hack to compute a possible
- # derived extension. This is not used by depend2.am.
- (my $der_ext = $ext) =~ tr/yl/cc/;
-
- # Another yacc/lex hack.
- my $destfile = '$*' . $der_ext;
+ # Compute a possible derived extension.
+ # This is not used by depend2.am.
+ my $der_ext = (&{$lang->output_extensions} ($ext))[0];
$output_rules .=
file_contents ($rule_file,
@@ -1821,7 +1859,8 @@
# suffix rule was learned), don't bother with the C stuff. But if
# anything else creeps in, then use it.
$needs_c = 1
- if $need_link || scalar keys %suffix_rules > 1;
+ if $need_link || ((scalar keys %$suffix_rules)
+ - (scalar keys %$suffix_rules_default)) > 1;
if ($needs_c)
{
@@ -5281,24 +5320,35 @@
# Each %ATTRIBUTE is of the form ATTRIBUTE => VALUE.
sub register_language (%)
{
- my (%option) = @_;
+ my (%option) = @_;
+
+ # Set the defaults.
+ $option{'ansi'} = 0
+ unless defined $option{'ansi'};
+ $option{'autodep'} = 'no'
+ unless defined $option{'autodep'};
+ $option{'linker'} = ''
+ unless defined $option{'linker'};
+ $option{'output_extensions'} = sub { return ( '.$(OBJEXT)', '.lo' ) }
+ unless defined $option{'output_extensions'};
- # Set the defaults.
- $option{'ansi'} = 0
- unless defined $option{'ansi'};
- $option{'autodep'} = 'no'
- unless defined $option{'autodep'};
- $option{'linker'} = ''
- unless defined $option{'linker'};
-
- my $lang = new Language (%option);
-
- # Fill indexes.
- grep ($extension_map{$_} = $lang->name, @{$lang->extensions});
- $languages{$lang->name} = $lang;
+ my $lang = new Language (%option);
- # Update the pattern of known extensions.
- accept_extensions (@{$lang->extensions});
+ # Fill indexes.
+ grep ($extension_map{$_} = $lang->name, @{$lang->extensions});
+ $languages{$lang->name} = $lang;
+
+ # Update the pattern of known extensions.
+ accept_extensions (@{$lang->extensions});
+
+ # Upate the $suffix_rule map.
+ foreach my $suffix (@{$lang->extensions})
+ {
+ foreach my $dest (&{$lang->output_extensions} ($suffix))
+ {
+ ®ister_suffix_rule ('internal', $suffix, $dest);
+ }
+ }
}
# derive_suffix ($EXT, $OBJ)
@@ -5307,16 +5357,17 @@
# to $OBJ or to some other suffix we recognize internally, eg `cc'.
sub derive_suffix ($$)
{
- my ($source_ext, $obj) = @_;
+ my ($source_ext, $obj) = @_;
- while (! $extension_map{$source_ext}
- && $source_ext ne $obj
- && defined $suffix_rules{$source_ext})
+ while (! $extension_map{$source_ext}
+ && $source_ext ne $obj
+ && exists $suffix_rules->{$source_ext}
+ && exists $suffix_rules->{$source_ext}{$obj})
{
- $source_ext = $suffix_rules{$source_ext};
+ $source_ext = $suffix_rules->{$source_ext}{$obj}[0];
}
- return $source_ext;
+ return $source_ext;
}
@@ -6752,6 +6803,77 @@
## Handling rules. ##
## ---------------- ##
+sub register_suffix_rule ($$$)
+{
+ my ($where, $src, $dest) = @_;
+
+ verbose "Sources ending in $src become $dest";
+ push @suffixes, $src, $dest;
+
+ # When tranforming sources to objects, Automake uses the
+ # %suffix_rules to move from each source extension to
+ # `.$(OBJEXT)', not to `.o' or `.obj'. However some people
+ # define suffix rules for `.o' or `.obj', so internally we will
+ # consider these extensions equivalent to `.$(OBJEXT)'. We
+ # CANNOT rewrite the target (i.e., automagically replace `.o'
+ # and `.obj' by `.$(OBJEXT)' in the output), or warn the user
+ # that (s)he'd better use `.$(OBJEXT)', because Automake itself
+ # output suffix rules for `.o' or `.obj'...
+ $dest = '.$(OBJEXT)' if ($dest eq '.o' || $dest eq '.obj');
+
+ # Reading the comments near the declaration of $suffix_rules might
+ # help to understand the update of $suffix_rules that follows...
+
+ # Register $dest as a possible destination from $src.
+ # We might have the create the \hash.
+ if (exists $suffix_rules->{$src})
+ {
+ $suffix_rules->{$src}{$dest} = [ $dest, 1 ];
+ }
+ else
+ {
+ $suffix_rules->{$src} = { $dest => [ $dest, 1 ] };
+ }
+
+ # If we know how to transform $dest in something else, then
+ # we know how to transform $src in that "something else".
+ if (exists $suffix_rules->{$dest})
+ {
+ for my $dest2 (keys %{$suffix_rules->{$dest}})
+ {
+ my $dist = $suffix_rules->{$dest}{$dest2}[1] + 1;
+ # Overwrite an existing $src->$dest2 path only if
+ # the path via $dest which is shorter.
+ if (! exists $suffix_rules->{$src}{$dest2}
+ || $suffix_rules->{$src}{$dest2}[1] > $dist)
+ {
+ $suffix_rules->{$src}{$dest2} = [ $dest, $dist ];
+ }
+ }
+ }
+
+ # Similarly, any extension that can be derived into $src
+ # can be derived into the same extenstions as $src can.
+ my @dest2 = keys %{$suffix_rules->{$src}};
+ for my $src2 (keys %$suffix_rules)
+ {
+ if (exists $suffix_rules->{$src2}{$src})
+ {
+ for my $dest2 (@dest2)
+ {
+ my $dist = $suffix_rules->{$src}{$dest2} + 1;
+ # Overwrite an existing $src2->$dest2 path only if
+ # the path via $src is shorter.
+ if (! exists $suffix_rules->{$src2}{$dest2}
+ || $suffix_rules->{$src2}{$dest2}[1] > $dist)
+ {
+ $suffix_rules->{$src2}{$dest2} = [ $src, $dist ];
+ }
+ }
+ }
+ }
+}
+
# $BOOL
# rule_define ($TARGET, $IS_AM, $COND, $WHERE)
# --------------------------------------------
@@ -6809,22 +6931,7 @@
# (see handle_footer).
|| ($target =~ /$SUFFIX_RULE_PATTERN/o && accept_extensions($1)))
{
- my $internal_ext = $2;
-
- # When tranforming sources to objects, Automake uses the
- # %suffix_rules to move from each source extension to
- # `.$(OBJEXT)', not to `.o' or `.obj'. However some people
- # define suffix rules for `.o' or `.obj', so internally we will
- # consider these extensions equivalent to `.$(OBJEXT)'. We
- # CANNOT rewrite the target (i.e., automagically replace `.o'
- # and `.obj' by `.$(OBJEXT)' in the output), or warn the user
- # that (s)he'd better use `.$(OBJEXT)', because Automake itself
- # output suffix rules for `.o' or `.obj'...
- $internal_ext = '.$(OBJEXT)' if ($2 eq '.o' || $2 eq '.obj');
-
- $suffix_rules{$1} = $internal_ext;
- verbose "Sources ending in $1 become $2";
- push @suffixes, $1, $2;
+ register_suffix_rule ($where, $1, $2);
}
return 1;
Index: tests/Makefile.am
===================================================================
RCS file: /cvs/automake/automake/tests/Makefile.am,v
retrieving revision 1.411
diff -u -r1.411 Makefile.am
--- tests/Makefile.am 30 Jun 2002 22:44:13 -0000 1.411
+++ tests/Makefile.am 1 Jul 2002 16:05:30 -0000
@@ -354,6 +354,9 @@
suffix5.test \
suffix6.test \
suffix7.test \
+suffix8.test \
+suffix9.test \
+suffix10.test \
symlink.test \
symlink2.test \
symlink3.test \
Index: tests/Makefile.in
===================================================================
RCS file: /cvs/automake/automake/tests/Makefile.in,v
retrieving revision 1.531
diff -u -r1.531 Makefile.in
--- tests/Makefile.in 30 Jun 2002 22:44:13 -0000 1.531
+++ tests/Makefile.in 1 Jul 2002 16:05:30 -0000
@@ -441,6 +441,9 @@
suffix5.test \
suffix6.test \
suffix7.test \
+suffix8.test \
+suffix9.test \
+suffix10.test \
symlink.test \
symlink2.test \
symlink3.test \
Index: tests/suffix10.test
===================================================================
RCS file: tests/suffix10.test
diff -N tests/suffix10.test
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/suffix10.test 1 Jul 2002 16:05:30 -0000
@@ -0,0 +1,37 @@
+#! /bin/sh
+
+# Make sure that derivations work with .lo too.
+# (related to PR/37)
+
+required='libtoolize bison'
+. $srcdir/defs || exit 1
+
+set -e
+
+cat >>configure.in <<EOF
+AC_PROG_CC
+AC_PROG_YACC
+AC_PROG_LIBTOOL
+AC_OUTPUT
+EOF
+
+
+cat >Makefile.am << 'END'
+lib_LTLIBRARIES = libfoo.la
+libfoo_la_SOURCES = foo.x_
+
+.x_.y:
+ cp $< $@
+
+print:
+ echo BEGIN: $(libfoo_la_OBJECTS) :END
+END
+
+libtoolize --force
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE --add-missing
+./configure
+$MAKE print >stdout
+cat stdout
+grep 'BEGIN: foo.lo :END' stdout
Index: tests/suffix8.test
===================================================================
RCS file: tests/suffix8.test
diff -N tests/suffix8.test
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/suffix8.test 1 Jul 2002 16:05:30 -0000
@@ -0,0 +1,56 @@
+#! /bin/sh
+
+# Test to make sure Automake supports multiple derivations for the same suffix.
+# PR/37
+
+required='gcc libtoolize'
+. $srcdir/defs || exit 1
+
+set -e
+
+cat >>configure.in <<'END'
+AM_PROG_LIBTOOL
+AC_OUTPUT
+END
+
+cat >Makefile.am << 'END'
+bin_PROGRAMS = foo
+lib_LTLIBRARIES = libfoo.la
+
+foo_SOURCES = foo.x_
+libfoo_la_SOURCES = bar.x_
+
+.x_.y_:
+ cp $< $@
+
+.y_.o:
+ cp $< $@
+
+.y_.z_:
+ cp $< $@
+
+.z_.lo:
+ cp $< $@
+
+print:
+ @echo BEGIN: $(foo_OBJECTS) :END
+ @echo BEGIN: $(libfoo_la_OBJECTS) :END
+
+test: $(foo_OBJECTS) $(libfoo_la_OBJECTS)
+ test -f foo.$(OBJEXT)
+ test -f bar.lo
+END
+
+echo 'int main() { return 0; }' > foo.x_
+cp foo.x_ bar.x_
+
+libtoolize
+$ACLOCAL
+$AUTOCONF
+$AUTOMAKE -a
+./configure
+env OBJEXT=foo $MAKE -e SHELL=/bin/sh print >stdout
+cat stdout
+grep 'BEGIN: foo.foo :END' stdout
+grep 'BEGIN: bar.lo :END' stdout
+$MAKE test
Index: tests/suffix9.test
===================================================================
RCS file: tests/suffix9.test
diff -N tests/suffix9.test
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ tests/suffix9.test 1 Jul 2002 16:05:30 -0000
@@ -0,0 +1,47 @@
+#! /bin/sh
+
+# Make sure that Automake choose the shorter route between suffixes
+# (related to PR/37)
+
+. $srcdir/defs || exit 1
+
+set -e
+
+echo AC_PROG_CC >>configure.in
+
+# x_ -> y -> c -> o
+# \________/
+#
+# Automake should follow the bottom route: x_ -> c -> o because
+# it is shorter.
+#
+# It should not take the "-> y ->" route. We use `y' here so that
+# then Automake will complains that YACC is not defined and the test will
+# fail when this happens.
+
+cat >Makefile.am << 'END'
+bin_PROGRAMS = foo
+foo_SOURCES = foo.x_
+
+.x_.y:
+ cp $< $@
+.x_.c:
+ cp $< $@
+END
+
+$ACLOCAL
+$AUTOMAKE -a
+
+# Idem with the rules the another order.
+
+cat >Makefile.am << 'END'
+bin_PROGRAMS = foo
+foo_SOURCES = foo.x_
+
+.x_.c:
+ cp $< $@
+.x_.y:
+ cp $< $@
+END
+
+$AUTOMAKE -a
--
Alexandre Duret-Lutz
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- FYI: multiple derivations rules for the same input suffix (PR/37),
Alexandre Duret-Lutz <=