]> sourceware.org Git - automake.git/commitdiff
added Ian's conditionals
authorTom Tromey <tromey@redhat.com>
Mon, 28 Apr 1997 05:59:35 +0000 (05:59 +0000)
committerTom Tromey <tromey@redhat.com>
Mon, 28 Apr 1997 05:59:35 +0000 (05:59 +0000)
ChangeLog
Makefile.in
NEWS
automake.in
automake.texi
m4/Makefile.am
m4/Makefile.in
m4/cond.m4 [new file with mode: 0644]
tests/Makefile.in

index ef4d72328a8dc86eb1998674549b2c03b2c3f09d..05d61962bb4e57a97e647a790a933b98c82f46bd 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+Sun Apr 27 23:58:20 1997  Tom Tromey  <tromey@cygnus.com>
+
+       * automake.in (handle_dist): Use variable_value, not
+       variable_contents.
+
+Wed Apr 23 14:04:28 1997  Ian Lance Taylor  <ian@cygnus.com>
+
+       * automake.in (IF_PATTERN): Define.
+       (ELSE_PATTERN, ENDIF_PATTERN): Define.
+       (AM_CONDITIONAL_PATTERN): Define.
+       (%configure_cond): New global hash table.
+       (handle_source_transform): If xx_SOURCES is defined conditionally,
+       define xx_OBJECTS using the same conditions.
+       (handle_lib_objects): If variable is defined conditionally, define
+       xx_DEPENDENCIES conditionally.  Most code moved into subroutine.
+       (handle_lib_objects_cond): New function, broken out of
+       handle_lib_objects.
+       (scan_one_configure_file): Look for $AM_CONDITIONAL_PATTERN.
+       (conditional_true_when): New function.
+       (variable_defined): Add new parameter: cond.  Change some
+       callers.
+       (variable_conditions): New function.
+       (variable_conditionally_defined): New function.
+       (variable_value): New function.  Change most uses of $contents to
+       call variable_value instead.
+       (value_to_list): New function, from variable_value_as_list.
+       (variable_value_as_list): Add new parameter: cond.  Change all
+       callers.  Move some code into subroutine value_to_list.
+       (define_pretty_variable): Add new parameter: cond.  Change call
+       callers.
+       (read_am_file): Handle conditionals.
+       (initialize_per_input): Initialize %conditional and
+       @conditional_stack.
+       * m4/cond.m4: New file.
+       * m4/Makefile.am (m4data_DATA): Add cond.m4.
+
 Sun Apr 27 11:03:36 1997  Tom Tromey  <tromey@cygnus.com>
 
        * automake.in (handle_dist_worker): Run automake once per
index 98821d9e2e56a9f22b663327c86539329bc1559e..45cc46d1f2fbf1e6e0ec827595837a89c8cb2f3a 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated automatically by automake 1.1n from Makefile.am
+# Makefile.in generated automatically by automake 1.1o from Makefile.am
 
 # Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
diff --git a/NEWS b/NEWS
index b84d1084ce2039062dc91bba557a15edc13d6d0e..0f84a8b6599781b2a948683d321ae220d9af0ce6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -31,6 +31,7 @@ New in 1.1o:
 * Texinfo output files no longer need .info extension
 * Added `missing' support
 * Cygwin32 support
+* Conditionals in Makefile.am, from Ian Taylor
 \f
 New in 1.0:
 * Bug fixes
index 43218bbfc791f8912c01b35b708cc3658edc44a9..a19b3853512daa5ec5f0597e3ffa34dd8711a8f9 100755 (executable)
@@ -43,6 +43,9 @@ $RULE_PATTERN = "^([\$a-zA-Z_.][-.a-zA-Z0-9_(){}/]*) *:([^=].*|)\$";
 $MACRO_PATTERN = "^([A-Za-z][A-Za-z0-9_]*)[ \t]*:?=[ \t]*(.*)\$";
 $BOGUS_MACRO_PATTERN = "^([^ \t]*)[ \t]*:?=[ \t]*(.*)\$";
 $GNITS_VERSION_PATTERN = "[0-9]+\\.[0-9]+([a-z]|\\.[0-9]+)?";
+$IF_PATTERN = "^if[ \t]+\([A-Za-z][A-Za-z0-9_]*\)[ \t]*\(#.*\)?\$";
+$ELSE_PATTERN = "^else[ \t]*\(#.*\)?\$";
+$ENDIF_PATTERN = "^endif[ \t]*\(#.*\)?\$";
 
 # Some regular expressions.  One reason to put them here is that it
 # makes indentation work better in Emacs.
@@ -55,6 +58,7 @@ $AM_MISSING_PATTERN = "AM_MISSING_PROG\\(\\[?(\\w+)";
 # Just check for alphanumeric in AC_SUBST.  If you do AC_SUBST(5),
 # then too bad.
 $AC_SUBST_PATTERN = "AC_SUBST\\(\\[?(\\w+)";
+$AM_CONDITIONAL_PATTERN = "AM_CONDITIONAL\\((\\w+)";
 
 # Constants to define the "strictness" level.
 $FOREIGN = 0;
@@ -223,6 +227,9 @@ $cygnus_mode = 0;
 # Keys of this hash are names of dependency files to ignore.
 %omit_dependencies = ();
 
+# Hash table of AM_CONDITIONAL variables seen in configure.
+%configure_cond = ();
+
 # Map from obsolete macros to hints for new macros.
 # FIXME complete the list so that there are no `0' hints.
 %obsolete_macros =
@@ -596,7 +603,7 @@ sub handle_options
 {
     return 0 if ! &variable_defined ('AUTOMAKE_OPTIONS');
 
-    foreach (&variable_value_as_list ('AUTOMAKE_OPTIONS'))
+    foreach (&variable_value_as_list ('AUTOMAKE_OPTIONS', ''))
     {
        $options{$_} = 1;
        if ($_ eq 'gnits' || $_ eq 'gnu' || $_ eq 'foreign')
@@ -675,7 +682,7 @@ sub get_object_extension
        if (&variable_defined ('CONFIG_HEADER'))
        {
            local ($one_hdr);
-           foreach $one_hdr (split (' ', $contents{'CONFIG_HEADER'}))
+           foreach $one_hdr (split (' ', &variable_value ('CONFIG_HEADER')))
            {
                local ($var);
                ($var = &dirname ($one_hdr)) =~ s/(\W)/\\$1/g;
@@ -1019,8 +1026,9 @@ sub check_libobjs_sources
     {
        if (&variable_defined ($prefix . $one_file . '_SOURCES'))
        {
-           @files = &variable_value_as_list ($prefix
-                                             . $one_file . '_SOURCES');
+           @files = &variable_value_as_list (($prefix
+                                              . $one_file . '_SOURCES'),
+                                             'all');
        }
        elsif ($prefix eq '')
        {
@@ -1180,13 +1188,32 @@ sub handle_source_transform
     foreach $prefix ('', 'EXTRA_')
     {
        @files = ();
-       if (&variable_defined ($prefix . $one_file . "_SOURCES"))
+       local ($var) = $prefix . $one_file . "_SOURCES";
+       if (&variable_defined ($var))
        {
            push (@sources, '$(' . $prefix . $one_file . "_SOURCES)");
            push (@objects, '$(' . $prefix . $one_file . "_OBJECTS)")
                unless $prefix eq 'EXTRA_';
-           @files = &variable_value_as_list ($prefix
-                                             . $one_file . "_SOURCES");
+           local (@conds) = &variable_conditions ($var);
+           if (! @conds)
+           {
+               @files = &variable_value_as_list ($var, '');
+           }
+           else
+           {
+               local ($cond);
+               foreach $cond (@conds)
+               {
+                   @files = &variable_value_as_list ($var, $cond);
+                   ($temp, @result) = &handle_single_transform_list (@files);
+                   $linker = $temp if $linker eq '';
+                   &define_pretty_variable ($one_file . "_OBJECTS", $cond,
+                                            @result)
+                       unless $prefix eq 'EXTRA_';
+               }
+
+               next;
+           }
        }
        elsif ($prefix eq '')
        {
@@ -1198,7 +1225,7 @@ sub handle_source_transform
 
        ($temp, @result) = &handle_single_transform_list (@files);
        $linker = $temp if $linker eq '';
-       &define_pretty_variable ($one_file . "_OBJECTS", @result)
+       &define_pretty_variable ($one_file . "_OBJECTS", '', @result)
            unless $prefix eq 'EXTRA_';
     }
 
@@ -1211,7 +1238,7 @@ sub handle_built_sources
     return unless &variable_defined ('BUILT_SOURCES');
     push (@all, '$(BUILT_SOURCES)');
 
-    local (@sources) = &variable_value_as_list ('BUILT_SOURCES');
+    local (@sources) = &variable_value_as_list ('BUILT_SOURCES', 'all');
     local ($s);
     foreach $s (@sources)
     {
@@ -1241,6 +1268,7 @@ sub handle_built_sources
 sub handle_lib_objects
 {
     local ($xname, $var, $lex_seen) = @_;
+    local ($ret);
 
     die "automake: programming error 1 in handle_lib_objects\n"
        if ! &variable_defined ($var);
@@ -1248,6 +1276,32 @@ sub handle_lib_objects
     die "automake: programming error 2 in handle_lib_objects\n"
        if $lex_seen && $var =~ /LIBADD/;
 
+    local (@conds) = &variable_conditions ($var);
+    if (! @conds)
+    {
+       $ret = &handle_lib_objects_cond ($xname, $var, $lex_seen, '');
+    }
+    else
+    {
+       local ($cond);
+       $ret = 0;
+       foreach $cond (@conds)
+       {
+           if (&handle_lib_objects_cond ($xname, $var, $lex_seen, $cond))
+           {
+               $ret = 1;
+           }
+       }
+    }
+
+    return $ret;
+}
+
+# Subroutine of handle_lib_objects: handle a particular condition.
+sub handle_lib_objects_cond
+{
+    local ($xname, $var, $lex_seen, $cond) = @_;
+
     # We recognize certain things that are commonly put in LIBADD or
     # LDADD.
     local ($lsearch);
@@ -1259,7 +1313,7 @@ sub handle_lib_objects
     local ($seen_libobjs) = 0;
     local ($flagvar) = 0;
 
-    foreach $lsearch (&variable_value_as_list ($var))
+    foreach $lsearch (&variable_value_as_list ($var, $cond))
     {
        # Skip -lfoo and -Ldir; these are explicitly allowed.
        next if $lsearch =~ /^-[lL]/;
@@ -1342,9 +1396,9 @@ sub handle_lib_objects
        &am_line_error ($var, 'lex source file used without @LEXLIB@');
     }
 
-    if ($xname ne '' && ! &variable_defined ($xname . '_DEPENDENCIES'))
+    if ($xname ne '' && ! &variable_defined ($xname . '_DEPENDENCIES', $cond))
     {
-       &define_pretty_variable ($xname . '_DEPENDENCIES', @dep_list);
+       &define_pretty_variable ($xname . '_DEPENDENCIES', $cond, @dep_list);
     }
 
     return $seen_libobjs;
@@ -1628,7 +1682,7 @@ sub handle_ltlibraries
            }
 
            # Get the installation directory of each library.
-           for (&variable_value_as_list ($key . '_LTLIBRARIES'))
+           for (&variable_value_as_list ($key . '_LTLIBRARIES', 'all'))
            {
                if ($instdirs{$_})
                {
@@ -1842,7 +1896,7 @@ sub handle_texinfo
     return if (! &variable_defined ('info_TEXINFOS')
               && ! &variable_defined ('html_TEXINFOS'));
 
-    local (@texis) = &variable_value_as_list ('info_TEXINFOS');
+    local (@texis) = &variable_value_as_list ('info_TEXINFOS', 'all');
 
     local (@info_deps_list, @dvis_list, @texi_deps);
     local ($infobase, $info_cursor);
@@ -1973,7 +2027,7 @@ sub handle_texinfo
     {
        &define_variable ('TEXINFO_TEX', '$(srcdir)/texinfo.tex');
     }
-    local ($xxform) = &dirname ($contents{'TEXINFO_TEX'});
+    local ($xxform) = &dirname (&variable_value ('TEXINFO_TEX'));
     $xxform =~ s/(\W)/\\$1/g;
     $xform .= ' s/\@TEXINFODIR\@/' . $xxform . '/g;';
 
@@ -2017,7 +2071,7 @@ sub handle_texinfo
     # This next isn't strictly needed now -- the places that look here
     # could easily be changed to look in info_TEXINFOS.  But this is
     # probably better, in case noinst_TEXINFOS is ever supported.
-    &define_variable ("TEXINFOS", $contents{'info_TEXINFOS'});
+    &define_variable ("TEXINFOS", &variable_value ('info_TEXINFOS'));
 
     # Do some error checking.  Note that this file is not required
     # when in Cygnus mode; instead we defined TEXINFO_TEX explicitly
@@ -2036,7 +2090,7 @@ sub handle_man_pages
 
     # We generate the manpage install code by hand to avoid the use of
     # basename in the generated Makefile.
-    local (@mans) = &variable_value_as_list ('man_MANS');
+    local (@mans) = &variable_value_as_list ('man_MANS', 'all');
     local (%sections, %inames, %mbases, %secmap, %fullsecmap);
     local ($i) = 1;
     foreach (@mans)
@@ -2053,7 +2107,7 @@ sub handle_man_pages
 
     # We don't really need this, but we use it in case we ever want to
     # support noinst_MANS.
-    &define_variable ("MANS", $contents{'man_MANS'});
+    &define_variable ("MANS", &variable_value ('man_MANS'));
 
     # Generate list of install dirs.
     $output_rules .= "install-man: \$(MANS)\n";
@@ -2238,7 +2292,12 @@ sub handle_dist_worker
     local (@dist_dirs);
     if (&variable_defined ('EXTRA_DIST'))
     {
-       foreach (&variable_value_as_list ('EXTRA_DIST'))
+       # FIXME: This should be fixed to work with conditionals.  That
+       # will require only making the entries in @dist_dirs under the
+       # appropriate condition.  This is meaningful if the nature of
+       # the distribution should depend upon the configure options
+       # used.
+       foreach (&variable_value_as_list ('EXTRA_DIST', ''))
        {
            next if /^\@.*\@$/;
            next unless s,/+[^/]+$,,;
@@ -2321,7 +2380,7 @@ sub handle_dist
     local ($makefile) = @_;
 
     # Set up maint_charset.
-    $local_maint_charset = $contents{'MAINT_CHARSET'}
+    $local_maint_charset = &variable_value ('MAINT_CHARSET')
        if &variable_defined ('MAINT_CHARSET');
     $maint_charset = $local_maint_charset
        if $relative_dir eq '.';
@@ -2333,7 +2392,7 @@ sub handle_dist
            if ! $local_maint_charset;
        if ($relative_dir eq '.')
        {
-           $dist_charset = $contents{'DIST_CHARSET'}
+           $dist_charset = &variable_value ('DIST_CHARSET')
        }
        else
        {
@@ -2364,7 +2423,7 @@ sub handle_dist
     }
     push (@coms, sort keys %dist_common);
 
-    &define_pretty_variable ("DIST_COMMON", @coms);
+    &define_pretty_variable ("DIST_COMMON", '', @coms);
     $output_vars .= "\n";
 
     # Some boilerplate.
@@ -2466,7 +2525,10 @@ sub scan_dependency_file
     local (%omit) = %omit_dependencies;
     if (&variable_defined ('OMIT_DEPENDENCIES'))
     {
-       grep ($omit{$_} = 1, &variable_value_as_list ('OMIT_DEPENDENCIES'));
+       # FIXME: Doesn't work with conditionals.  I'm not sure if this
+       # matters.
+       grep ($omit{$_} = 1,
+             &variable_value_as_list ('OMIT_DEPENDENCIES', ''));
     }
 
     local ($first_line) = 1;
@@ -2578,7 +2640,7 @@ sub handle_dependencies
        # Include GNU-make-specific auto-dep code.
        if ($dir_holds_sources)
        {
-           &define_pretty_variable ('DEP_FILES', sort keys %dep_files);
+           &define_pretty_variable ('DEP_FILES', '', sort keys %dep_files);
            $output_rules .= &file_contents ('depend');
            push (@clean, 'depend');
            &push_phony_cleaners ('depend');
@@ -2631,7 +2693,7 @@ sub handle_subdirs
 
     # Make sure each directory mentioned in SUBDIRS actually exists.
     local ($dir);
-    foreach $dir (&variable_value_as_list ('SUBDIRS'))
+    foreach $dir (&variable_value_as_list ('SUBDIRS', 'all'))
     {
        # Skip directories substituted by configure.
        next if $dir =~ /^\@.*\@$/;
@@ -2720,7 +2782,7 @@ sub handle_aclocal_m4
        if (&variable_defined ('ACLOCAL_AMFLAGS'))
        {
            local ($amdir);
-           foreach $amdir (&variable_value_as_list ('ACLOCAL_AMFLAGS'))
+           foreach $amdir (&variable_value_as_list ('ACLOCAL_AMFLAGS', ''))
            {
                if ($amdir =~ s/^-I//
                    && $amdir !~ /^\//
@@ -3009,7 +3071,7 @@ sub handle_configure
     }
 
     # These files get removed by "make clean".
-    &define_pretty_variable ('CONFIG_CLEAN_FILES', @actual_other_files);
+    &define_pretty_variable ('CONFIG_CLEAN_FILES', '', @actual_other_files);
 }
 
 # Handle C headers.
@@ -3101,7 +3163,7 @@ sub handle_footer
        # Push actual suffixes, and not $(SUFFIXES).  Some versions of
        # make do not like variable substitutions on the .SUFFIXES
        # line.
-       push (@suffixes, &variable_value_as_list ('SUFFIXES'));
+       push (@suffixes, &variable_value_as_list ('SUFFIXES', ''));
     }
     if (&target_defined ('.SUFFIXES'))
     {
@@ -3647,7 +3709,7 @@ sub handle_emacs_lisp
 
        # Generate .elc files.
        grep ($_ .= 'c', @elfiles);
-       &define_pretty_variable ('ELCFILES', @elfiles);
+       &define_pretty_variable ('ELCFILES', '', @elfiles);
 
        push (@clean, 'lisp');
        &push_phony_cleaners ('lisp');
@@ -3982,6 +4044,11 @@ sub scan_one_configure_file
            # never downgrade (if we've seen AC_CANONICAL_SYSTEM).
            $seen_canonical = $AC_CANONICAL_HOST if ! $seen_canonical;
        }
+
+       if (/$AM_CONDITIONAL_PATTERN/o)
+       {
+           $configure_cond{$1} = 1;
+       }
     }
 
     close (CONFIGURE);
@@ -4171,10 +4238,72 @@ sub target_defined
     return defined $targets{$target};
 }
 
-# See if a variable exists.
+# See if two conditionals are the same.
+sub conditional_same
+{
+    local ($cond1, $cond2) = @_;
+
+    return (&conditional_true_when ($cond1, $cond2)
+           && &conditional_true_when ($cond2, $cond1));
+}
+
+# See if a conditional is true.  Both arguments are conditional
+# strings.  This returns true if the first conditional is true when
+# the second conditional is true.
+sub conditional_true_when
+{
+    local ($cond, $when) = @_;
+
+    # Check the easy case first.
+    if ($cond eq $when)
+    {
+       return 1;
+    }
+
+    # Check each component of $cond, which looks @COND1@@COND2@.
+    foreach $comp (split ('@', $cond))
+    {
+       # The way we split will give null strings between each
+       # condition.
+       next if ! $comp;
+
+       if (index ($when, '@' . $comp . '@') == -1)
+       {
+           return 0;
+       }
+    }
+
+    return 1;
+}
+
+# Check for an ambiguous conditional.  This is called when a variable
+# or target is being defined conditionally.  If we already know about
+# a definition that is true under the same conditions, then we have an
+# ambiguity.
+sub check_ambiguous_conditional
+{
+    local ($var_name, $cond) = @_;
+    local (@cond_vals) = split (/ /, $conditional{$var_name});
+    while (@cond_vals)
+    {
+       local ($vcond) = shift (@cond_vals);
+       shift (@cond_vals);
+       if (&conditional_true_when ($vcond, $cond)
+           || &conditional_true_when ($cond, $vcond))
+       {
+           &am_line_error ($var_name,
+                           "$var_name multiply defined in condition");
+       }
+    }
+}
+
+# See if a variable exists.  The first argument is the variable name,
+# and the optional second argument is the condition which we should
+# check.  If no condition is given, we currently return true if the
+# variable is defined under any condition.
 sub variable_defined
 {
-    local ($var) = @_;
+    local ($var, $cond) = @_;
     if (defined $targets{$var})
     {
        &am_line_error ($var, "\`$var' is target; expected variable");
@@ -4182,6 +4311,27 @@ sub variable_defined
     }
     elsif (defined $contents{$var})
     {
+       if ($cond && $conditional{$var})
+       {
+           # We have been asked to check for a particular condition,
+           # and the variable is defined conditionally.  We need to
+           # look through the conditions under which the variable is
+           # defined, and see if any of them match the conditional we
+           # have been asked to check.
+           local (@cond_vars) = split (/ /, $conditional{$var});
+           while (@cond_vars)
+           {
+               if (&conditional_same ($cond, shift (@cond_vars)))
+               {
+                   return 1;
+               }
+               shift (@cond_vars);
+           }
+
+           # The variable is not defined for the given condition.
+           return 0;
+       }
+
        $content_seen{$var} = 1;
        return 1;
     }
@@ -4195,27 +4345,66 @@ sub examine_variable
     &variable_defined ($var);
 }
 
-# Return contents of variable as list, split as whitespace.  This will
-# recursively follow $(...) and ${...} inclusions.  It preserves @...@
-# substitutions.  If PARENT is specified, it is the name of the
-# including variable; this is only used for error reports.
-sub variable_value_as_list
+# Quote a value in order to put it in $conditional.  We need to quote
+# spaces, and we need to handle null strings, so that we can later
+# retrieve values by splitting on space.
+sub quote_cond_val
 {
-    local ($var, $parent) = @_;
-    local (@result);
+    local ($val) = @_;
+    $val =~ s/ /\001/g;
+    $val = '\002' if $val eq '';
+    return $val;
+}
 
-    if (defined $targets{$var})
-    {
-       &am_line_error ($var, "\`$var' is target; expected variable");
-    }
-    elsif (! defined $contents{$var})
+# Unquote a value in $conditional.
+sub unquote_cond_val
+{
+    local ($val) = @_;
+    $val =~ s/\001/ /g;
+    $val = '' if $val eq '\002';
+    return $val;
+}
+
+# Return the set of conditions for which a variable is defined.
+
+# If the variable is not defined conditionally, and is not defined in
+# terms of any variables which are defined conditionally, then this
+# returns the empty list.
+
+# If the variable is defined conditionally, but is not defined in
+# terms of any variables which are defined conditionally, then this
+# returns the list of conditions for which the variable is defined.
+
+# If the variable is defined in terms of any variables which are
+# defined conditionally, then this returns a full set of permutations
+# of the subvariable conditions.  For example, if the variable is
+# defined in terms of a variable which is defined for @COND_TRUE@,
+# then this returns both @COND_TRUE@ and @COND_FALSE@.  This is
+# because we will need to define the variable under both conditions.
+
+sub variable_conditions
+{
+    local ($var) = @_;
+    local (%uniqify);
+    local ($cond);
+
+    foreach $cond (&variable_conditions_sub ($var, '', ()))
     {
-       &am_line_error ($parent, "variable \`$var' not defined");
+       $uniqify{$cond} = 1;
     }
-    else
+
+    return keys %uniqify;
+}
+
+# A subroutine of variable_conditions.  We only return conditions
+# which are true for all the conditions in @PARENT_CONDS.
+sub variable_conditions_sub
+{
+    local ($var, $parent, @parent_conds) = @_;
+    local (@new_conds) = ();
+
+    if (! $conditional{$var})
     {
-       local (@temp_list);
-       $content_seen{$var} = 1;
        foreach (split (' ', $contents{$var}))
        {
            # If a comment seen, just leave.
@@ -4224,31 +4413,322 @@ sub variable_value_as_list
            # Handle variable substitutions.
            if (/^\$\{(.*)\}$/ || /^\$\((.*)\)$/)
            {
-               local ($varname) = $1;
-               local ($from, $to);
-               if ($varname =~ /^([^:]*):([^=]*)=(.*)$/)
+               push (@new_conds,
+                     &variable_conditions_sub ($1, $var, @parent_conds));
+           }
+       }
+
+       return &variable_conditions_reduce (@new_conds);
+    }
+
+    local (@this_conds) = ();
+    local (@condvals) = split (/ /, $conditional{$var});
+    while (@condvals)
+    {
+       local ($cond) = shift (@condvals);
+       local ($val) = &unquote_cond_val (shift (@condvals));
+
+       if (@parent_conds)
+       {
+           local ($ok) = 1;
+           local ($parent_cond);
+           foreach $parent_cond (@parent_conds)
+           {
+               if (! &conditional_true_when ($parent_cond, $cond))
                {
-                   $varname = $1;
-                   $to = $3;
-                   ($from = $2) =~ s/(\W)/\\$1/g;
+                   $ok = 0;
+                   last;
                }
+           }
+
+           next if ! $ok;
+       }
+
+       push (@this_conds, $cond);
+
+       push (@parent_conds, $cond);
+       local (@subvar_conds) = ();
+       foreach (split (' ', $val))
+       {
+           # If a comment seen, just leave.
+           last if /^#/;
+
+           # Handle variable substitutions.
+           if (/^\$\{(.*)\}$/ || /^\$\((.*)\)$/)
+           {
+               push (@subvar_conds,
+                     &variable_conditions_sub ($1, $var, @parent_conds));
+           }
+       }
+       pop (@parent_conds);
+
+       # If there are no conditional subvariables, then we want to
+       # return this condition.  Otherwise, we want to return the
+       # permutations of the subvariables.
+       if (! @subvar_conds)
+       {
+           push (@new_conds, $cond);
+       }
+       else
+       {
+           push (@new_conds, &variable_conditions_reduce (@subvar_conds));
+       }
+    }
 
-               # Find the value.
-               @temp_list = &variable_value_as_list ($1, $var);
+    return @new_conds
+       if ! $parent;
 
-               # Now rewrite the value if appropriate.
-               if ($from)
+    # If we are being called on behalf of another variable, we need to
+    # return all possible permutations of the conditions.  We have
+    # already handled everything in @this_conds along with their
+    # subvariables.  We now need to add any permutations that are not
+    # in @this_conds.
+    local ($this_cond);
+    foreach $this_cond (@this_conds)
+    {
+       local (@perms) =
+           &variable_conditions_permutations (split '@', $this_cond);
+       local ($perm);
+       foreach $perm (@perms)
+       {
+           local ($scan);
+           local ($ok) = 1;
+           foreach $scan (@this_conds)
+           {
+               if (&conditional_true_when ($perm, $scan)
+                   || &conditional_true_when ($scan, $perm))
                {
-                   grep (s/$from$/$to/, @temp_list);
+                   $ok = 0;
+                   last;
                }
+           }
+           next if ! $ok;
 
-               push (@result, @temp_list);
+           if (@parent_conds)
+           {
+               local ($ok) = 1;
+               local ($parent_cond);
+               foreach $parent_cond (@parent_conds)
+               {
+                   if (! &conditional_true_when ($parent_cond, $perm))
+                   {
+                       $ok = 0;
+                       last;
+                   }
+               }
+
+               next if ! $ok;
            }
-           else
+
+           # This permutation was not already handled, and is valid
+           # for the parents.
+           push (@new_conds, $perm);
+       }
+    }
+
+    return @new_conds;
+}
+
+# Subroutine for variable_conditions_sort
+sub variable_conditions_cmp
+{
+    local ($as) = $a;
+    $as =~ s/[^@]//g;
+    local ($bs) = $b;
+    $bs =~ s/[^@]//g;
+    return (length ($as) <=> length ($bs)
+           or $a cmp $b);
+}
+
+# Sort a list of conditionals so that only the exclusive ones are
+# retained.  For example, if both @COND1_TRUE@@COND2_TRUE@ and
+# @COND1_TRUE@ are in the list, discard the latter.
+sub variable_conditions_reduce
+{
+    local (@conds) = @_;
+    local (@ret) = ();
+    local ($cond);
+    foreach $cond (sort variable_conditions_cmp @conds)
+    {
+       local ($ok) = 1;
+       local ($scan);
+       foreach $scan (@ret)
+       {
+           if (&conditional_true_when ($cond, $scan))
            {
-               push (@result, $_);
+               $ok = 0;
+               last;
            }
        }
+       next if ! $ok;
+       push (@ret, $cond);
+    }
+
+    return @ret;
+}
+
+# Return a list of permutations of a conditional string.
+sub variable_conditions_permutations
+{
+    local (@comps) = @_;
+    return ()
+       if ! @comps;
+    local ($comp) = shift (@comps);
+    return &variable_conditions_permutations (@comps)
+       if $comp eq '';
+    local ($neg) = $comp;
+    $neg =~ s/TRUE$/TRUEO/;
+    $neg =~ s/FALSE$/TRUE/;
+    $neg =~ s/TRUEO$/FALSE/;
+    local (@ret);
+    local ($sub);
+    foreach $sub (&variable_conditions_permutations (@comps))
+    {
+       push (@ret, '@' . $comp . '@' . $sub);
+       push (@ret, '@' . $neg . '@' . $sub);
+    }
+    if (! @ret)
+    {
+       push (@ret, '@' . $comp . '@');
+       push (@ret, '@' . $neg . '@');
+    }
+    return @ret;
+}
+
+# Warn if a variable is conditionally defined.  This is called if we
+# are using the value of a variable.
+sub variable_conditionally_defined
+{
+    local ($var, $parent) = @_;
+    if ($conditional{$var})
+    {
+       if ($parent)
+       {
+           &am_line_error ($parent,
+                           "warning: automake does not support conditional definition of $var in $parent");
+       }
+       else
+       {
+           &am_line_error ($parent,
+                           "warning: automake does not support $var being defined conditionally")
+       }
+    }
+}
+
+# Get the value of a variable.  This just returns $contents, but warns
+# if the variable is conditionally defined.
+sub variable_value
+{
+    local ($var) = @_;
+    &variable_conditionally_defined ($var);
+    return $contents{$var};
+}
+
+# Convert a variable value to a list, split as whitespace.  This will
+# recursively follow $(...) and ${...} inclusions.  It preserves @...@
+# substitutions.  If COND is 'all', then all values under all
+# conditions should be returned; if COND is a particular condition
+# (all conditions are surrounded by @...@) then only the value for
+# that condition should be returned; otherwise, warn if VAR is
+# conditionally defined.
+sub value_to_list
+{
+    local ($var, $val, $cond) = @_;
+    local (@result);
+
+    foreach (split (' ', $val))
+    {
+       # If a comment seen, just leave.
+       last if /^#/;
+
+       # Handle variable substitutions.
+       if (/^\$\{(.*)\}$/ || /^\$\((.*)\)$/)
+       {
+           local ($varname) = $1;
+           local ($from, $to);
+           local (@temp_list);
+           if ($varname =~ /^([^:]*):([^=]*)=(.*)$/)
+           {
+               $varname = $1;
+               $to = $3;
+               ($from = $2) =~ s/(\W)/\\$1/g;
+           }
+
+           # Find the value.
+           @temp_list = &variable_value_as_list ($1, $cond, $var);
+
+           # Now rewrite the value if appropriate.
+           if ($from)
+           {
+               grep (s/$from$/$to/, @temp_list);
+           }
+
+           push (@result, @temp_list);
+       }
+       else
+       {
+           push (@result, $_);
+       }
+    }
+
+    return @result;
+}
+
+# Return contents of variable as list, split as whitespace.  This will
+# recursively follow $(...) and ${...} inclusions.  It preserves @...@
+# substitutions.  If COND is 'all', then all values under all
+# conditions should be returned; if COND is a particular condition
+# (all conditions are surrounded by @...@) then only the value for
+# that condition should be returned; otherwise, warn if VAR is
+# conditionally defined.  If PARENT is specified, it is the name of
+# the including variable; this is only used for error reports.
+sub variable_value_as_list
+{
+    local ($var, $cond, $parent) = @_;
+    local (@result);
+
+    if (defined $targets{$var})
+    {
+       &am_line_error ($var, "\`$var' is target; expected variable");
+    }
+    elsif (! defined $contents{$var})
+    {
+       &am_line_error ($parent, "variable \`$var' not defined");
+    }
+    elsif ($cond eq 'all' && $conditional{$var})
+    {
+       local (@condvals) = split (/ /, $conditional{$var});
+       while (@condvals)
+       {
+           shift (@condvals);
+           local ($val) = &unquote_cond_val (shift (@condvals));
+           push (@result, &value_to_list ($var, $val, $cond));
+       }
+    }
+    elsif ($cond && $conditional{$var})
+    {
+       local (@condvals) = split (/ /, $conditional{$var});
+       local ($onceflag);
+       while (@condvals)
+       {
+           local ($vcond) = shift (@condvals);
+           local ($val) = &unquote_cond_val (shift (@condvals));
+           if (&conditional_true_when ($vcond, $cond))
+           {
+               # Warn if we have an ambiguity.  It's hard to know how
+               # to handle this case correctly.
+               &variable_conditionally_defined ($var, $parent)
+                   if $onceflag;
+               $onceflag = 1;
+               push (@result, &value_to_list ($var, $val, $cond));
+           }
+       }
+    }
+    else
+    {
+       &variable_conditionally_defined ($var, $parent);
+       $content_seen{$var} = 1;
+       push (@result, &value_to_list ($var, $contents{$var}, $cond));
     }
 
     return @result;
@@ -4268,14 +4748,30 @@ sub define_variable
 }
 
 # Like define_variable, but second arg is a list, and is
-# pretty-printed.
+# pretty-printed.  The third argument is the conditional under which
+# the value should be defined.
 sub define_pretty_variable
 {
-    local ($var, @value) = @_;
-    if (! defined $contents{$var})
+    local ($var, $cond, @value) = @_;
+    if (! defined $contents{$var}
+       || ($cond && ! &variable_defined ($var, $cond)))
     {
        $contents{$var} = join (' ', @value);
-       &pretty_print ($var . ' = ', '', @value);
+       if ($cond)
+       {
+           if ($conditional{$var})
+           {
+               $conditional{$var} .= ' ';
+           }
+           else
+           {
+               $conditional{$var} = '';
+           }
+           $conditional{$var} .= ($cond
+                                  . ' '
+                                  . &quote_cond_val ($contents{$var}));
+       }
+       &pretty_print ($cond . $var . ' = ', $cond, @value);
        $content_seen{$var} = 1;
     }
 }
@@ -4409,12 +4905,12 @@ sub read_am_file
        {
            if ($was_rule)
            {
-               $output_trailer .= $_;
+               $output_trailer .= join ('', @conditional_stack) . $_;
                $saw_bk = /\\$/;
            }
            else
            {
-               $am_vars .= $_;
+               $am_vars .= join ('', @conditional_stack) . $_;
                $saw_bk = /\\$/;
                # Chop newline and backslash if this line is
                # continued.  FIXME: maybe ensure trailing whitespace
@@ -4422,6 +4918,43 @@ sub read_am_file
                chop if $saw_bk;
                chop if $saw_bk;
                $contents{$last_var_name} .= $_;
+               if (@conditional_stack)
+               {
+                   $conditional{$last_var_name} .= &quote_cond_val ($_);
+               }
+           }
+       }
+       elsif (/$IF_PATTERN/o)
+       {
+           &am_line_error ($., "$1 does not appear in AM_CONDITIONAL")
+               if (! $configure_cond{$1});
+           push (@conditional_stack, "\@" . $1 . "_TRUE\@");
+       }
+       elsif (/$ELSE_PATTERN/o)
+       {
+           if (! @conditional_stack)
+           {
+               &am_line_error ($., "else without if");
+           }
+           elsif ($conditional_stack[$#conditional_stack] =~ /_FALSE\@$/)
+           {
+               &am_line_error ($., "else after else");
+           }
+           else
+           {
+               $conditional_stack[$#conditional_stack]
+                   =~ s/_TRUE\@$/_FALSE\@/;
+           }
+       }
+       elsif (/$ENDIF_PATTERN/o)
+       {
+           if (! @conditional_stack)
+           {
+               &am_line_error ($., "endif without if");
+           }
+           else
+           {
+               pop @conditional_stack;
            }
        }
        elsif (/$RULE_PATTERN/o)
@@ -4429,12 +4962,35 @@ sub read_am_file
            # warn "** Saw rule .$1.\n";
            # Found a rule.
            $was_rule = 1;
+           if (defined $contents{$1}
+               && (@conditional_stack
+                   ? ! defined $conditional{$1}
+                   : defined $conditional{$1}))
+           {
+               &am_line_error ($1,
+                               "$1 defined both conditionally and unconditionally");
+           }
            # Value here doesn't matter; for targets we only note
            # existence.
            $contents{$1} = 1;
            $targets{$1} = 1;
+           local ($cond_string) = join ('', @conditional_stack);
+           if (@conditional_stack)
+           {
+               if ($conditional{$1})
+               {
+                   &check_ambiguous_conditional ($last_var_name,
+                                                 $cond_string);
+                   $conditional{$1} .= ' ';
+               }
+               else
+               {
+                   $conditional{$1} = '';
+               }
+               $conditional{$1} .= $cond_string . ' 1';
+           }
            $content_lines{$1} = $.;
-           $output_trailer .= $comment . $spacing . $_;
+           $output_trailer .= $comment . $spacing . $cond_string . $_;
            $comment = $spacing = '';
            $saw_bk = /\\$/;
        }
@@ -4444,21 +5000,47 @@ sub read_am_file
            # Found a macro definition.
            $was_rule = 0;
            $last_var_name = $1;
+           if (defined $contents{$1}
+               && (@conditional_stack
+                   ? ! defined $conditional{$1}
+                   : defined $conditional{$1}))
+           {
+               &am_line_error ($1,
+                               "$1 defined both conditionally and unconditionally");
+           }
            if ($2 ne '' && substr ($2, -1) eq "\\")
            {
-               $contents{$1} = substr ($2, 0, length ($2) - 1);
+               $contents{$last_var_name} = substr ($2, 0, length ($2) - 1);
            }
            else
            {
-               $contents{$1} = $2;
+               $contents{$last_var_name} = $2;
            }
-           $content_lines{$1} = $.;
-           $am_vars .= $comment . $spacing . $_;
+           local ($cond_string) = join ('', @conditional_stack);
+           if (@conditional_stack)
+           {
+               if ($conditional{$last_var_name})
+               {
+                   &check_ambiguous_conditional ($last_var_name,
+                                                 $cond_string);
+                   $conditional{$last_var_name} .= ' ';
+               }
+               else
+               {
+                   $conditional{$last_var_name} = '';
+               }
+               local ($val) = $contents{$last_var_name};
+               $conditional{$last_var_name} .= ($cond_string
+                                                . ' '
+                                                . &quote_cond_val ($val));
+           }
+           $content_lines{$last_var_name} = $.;
+           $am_vars .= $comment . $spacing . $cond_string . $_;
            $comment = $spacing = '';
            $saw_bk = /\\$/;
 
            # Error if bogus.
-           &am_line_error ($., "bad macro name \`$1'")
+           &am_line_error ($., "bad macro name \`$last_var_name'")
                if ! $is_ok_macro;
        }
        else
@@ -4466,7 +5048,8 @@ sub read_am_file
            # This isn't an error; it is probably a continued rule.
            # In fact, this is what we assume.
            $was_rule = 1;
-           $output_trailer .= $comment . $spacing . $_;
+           $output_trailer .= ($comment . $spacing
+                               . join ('', @conditional_stack) . $_);
            $comment = $spacing = '';
            $saw_bk = /\\$/;
        }
@@ -4476,6 +5059,9 @@ sub read_am_file
 
     $output_trailer .= $comment;
 
+    &am_error ("unterminated conditionals: " . join (' ', @conditional_stack))
+       if (@conditional_stack);
+
     # Compute relative location of the top object directory.
     local (@topdir) = ();
     foreach (split (/\//, $relative_dir))
@@ -4651,6 +5237,13 @@ sub initialize_per_input
     # %contents.
     %targets = ();
 
+    # For a variable or target which is defined conditionally, this
+    # holds an array of the conditional values.  The array is composed
+    # of pairs of condition strings (the variables which configure
+    # will substitute) and values (the value of a target is
+    # meaningless).  For an unconditional variable, this is empty.
+    %conditional = ();
+
     # This holds the line numbers at which various elements of
     # %contents are defined.
     %content_lines = ();
@@ -4658,6 +5251,9 @@ sub initialize_per_input
     # This holds a 1 if a particular variable was examined.
     %content_seen = ();
 
+    # This is the conditional stack.
+    @conditional_stack = ();
+
     # This holds the "relative directory" of the current Makefile.in.
     # Eg for src/Makefile.in, this is "src".
     $relative_dir = '';
@@ -4986,7 +5582,7 @@ sub am_install_var
            # Append actual contents of where_PRIMARY variable to
            # result.
            local ($rcurs);
-           foreach $rcurs (&variable_value_as_list ($one_name))
+           foreach $rcurs (&variable_value_as_list ($one_name, 'all'))
            {
                # Skip configure substitutions.  Possibly bogus.
                if ($rcurs =~ /^\@.*\@$/)
@@ -5065,7 +5661,7 @@ sub am_install_var
     if (@used)
     {
        # Define it.
-       &define_pretty_variable ($primary, @used);
+       &define_pretty_variable ($primary, '', @used);
        $output_vars .= "\n";
     }
 
index f1f1e81344d8f86b73d899cb7a96ab518d458320..b30eebd1ccc08de74d409cb8cfb19fa941ebf158 100644 (file)
@@ -114,6 +114,7 @@ documents version @value{VERSION}.
 * Tests::                       Support for test suites
 * Options::                     Changing Automake's behavior
 * Miscellaneous::               Miscellaneous rules
+* Conditionals::               Conditionals
 * Gnits::                       The effect of @code{--gnu} and @code{--gnits}
 * Cygnus::                      The effect of @code{--cygnus}
 * Extending::                   Extending Automake
@@ -2246,6 +2247,68 @@ source files, you would also need to add these suffixes to the list:
 SUFFIXES = .java .class
 @end example
 
+@node Conditionals
+@chapter Conditionals
+
+Automake supports a simple type of conditionals.
+
+@cvindex AM_CONDITIONAL
+Before using a conditiona, you must define it by using
+@code{AM_CONDITIONAL} in the @code{configure.in} file.  The
+@code{AM_CONDITIONAL} macro takes two arguments.
+
+The first argument to @code{AM_CONDITIONAL} is the name of the
+conditional.  This should be a simple string starting with a letter and
+containing only letters, digits, and underscores.
+
+The second argument to @code{AM_CONDITIONAL} is a shell condition,
+suitable for use in a shell if statement.  The condition is evaluated
+when @code{configure} is run.
+
+Conditionals typically depend upon options which the user provides to
+the @code{configure} script.  Here is an example of how to write a
+conditional which is true if the user uses the @samp{--enable-debug}
+option.
+
+@example
+AC_ARG_ENABLE(debug,
+[  --enable-debug    Turn on debugging],
+[case "$@{enableval@}" in
+  yes) debug=true ;;
+  no)  debug=false ;;
+  *) AC_MSG_ERROR(bad value $@{enableval@} for --enable-debug) ;;
+esac],[debug=false])
+AM_CONDITIONAL(DEBUG, test x$debug = xtrue)
+@end example
+
+Here is an example of how to use that conditional in @file{Makefile.am}:
+
+@example
+if DEBUG
+DBG = debug
+else
+DBG =
+endif
+noinst_PROGRAMS = $(DBG)
+@end example
+
+This trivial example could also be handled using EXTRA_PROGRAMS
+(@pxref{A Program}).
+
+You may only test a single variable in an @code{if} statement.  The
+@code{else} statement may be omitted.  Conditionals may be nested to any
+depth.
+
+Note that conditionals in Automake are not the same as conditionals in
+GNU Make.  Automake conditionals are checked at configure time by the
+@file{configure} script, and affect the translation from
+@file{Makefile.in} to @file{Makefile}.  They are based on options passed
+to @file{configure} and on results that @file{configure} has discovered
+about the host system.  GNU Make conditionals are checked at make time,
+and are based on variables passed to the make program or defined in the
+@file{Makefile}.
+
+Automake conditionals will work with any make program.
 
 @node Gnits
 @chapter The effect of @code{--gnu} and @code{--gnits}
index b04b26531cb266450bb52bbf466f1af213075a46..a6ea588a24b47471df8bb849330de9f57228abd2 100644 (file)
@@ -7,6 +7,6 @@ m4datadir = $(datadir)/aclocal
 m4data_DATA = ccstdc.m4 dmalloc.m4 init.m4 install.m4 lispdir.m4 \
 maintainer.m4 protos.m4 ptrdiff.m4 regex.m4 strtod.m4 termios.m4 \
 winsz.m4 mktime.m4 error.m4 obstack.m4 sanity.m4 header.m4 missing.m4 \
-cygwin.m4
+cygwin.m4 cond.m4
 
 EXTRA_DIST = $(m4data_DATA)
index 989ed117729c5ae0a4e990d35323b463f4efff30..88478b22c1d471ae69c5fc05d58a9cc385844c10 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated automatically by automake 1.1n from Makefile.am
+# Makefile.in generated automatically by automake 1.1o from Makefile.am
 
 # Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
@@ -66,7 +66,7 @@ m4datadir = $(datadir)/aclocal
 m4data_DATA = ccstdc.m4 dmalloc.m4 init.m4 install.m4 lispdir.m4 \
 maintainer.m4 protos.m4 ptrdiff.m4 regex.m4 strtod.m4 termios.m4 \
 winsz.m4 mktime.m4 error.m4 obstack.m4 sanity.m4 header.m4 missing.m4 \
-cygwin.m4
+cygwin.m4 cond.m4
 
 EXTRA_DIST = $(m4data_DATA)
 mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
diff --git a/m4/cond.m4 b/m4/cond.m4
new file mode 100644 (file)
index 0000000..8734d61
--- /dev/null
@@ -0,0 +1,12 @@
+# Define a conditional.
+
+AC_DEFUN(AM_CONDITIONAL,
+[AC_SUBST($1_TRUE)
+AC_SUBST($1_FALSE)
+if $2; then
+  $1_TRUE=
+  $1_FALSE='#'
+else
+  $1_TRUE='#'
+  $1_FALSE=
+fi])
index 89d3e995dc267511dc139925331ada3f62144e1d..bb57c7057ae0fce2ec226746d6675b2da6f6d894 100644 (file)
@@ -1,4 +1,4 @@
-# Makefile.in generated automatically by automake 1.1n from Makefile.am
+# Makefile.in generated automatically by automake 1.1o from Makefile.am
 
 # Copyright (C) 1994, 1995, 1996 Free Software Foundation, Inc.
 # This Makefile.in is free software; the Free Software Foundation
This page took 0.082872 seconds and 5 git commands to generate.