This is the mail archive of the automake@gnu.org mailing list for the automake project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

non-recursive proof-of-concept



I don't claim to be a perl programmer - at all :]

Some of what I've done is duplicate code and should probably be done by
extending the existing function, making the existing cases a call with a
prepend of ''.  

I haven't covered all the automake targets or macros.
I haven't attempted full normalisation.
However, a simple project, using this will pass make distcheck, and will
build every directory in parallel.

See the Makefile.am's created by the distcheck test for examples of use.

Rob
#!/bin/sh

# Test for PR automake/220.

. $srcdir/defs || exit 1

subdirs="foo"

for i in $subdirs; do
mkdir $i
cat >$i/$i-a.c <<EOF
int maina() { return 0; }
EOF
cat >$i/$i-b.c <<EOF
int mainb() { return 0; }
EOF
cat >$i/Makefile.rules <<EOF
bin_PROGRAMS = ${i}bin
${i}bin_SOURCES = \$(top_srcdir)/main.c $i-a.c $i-b.c
EOF
cat >$i/Makefile.am <<EOF
include \$(srcdir)/Makefile.rules
EOF
done

cat >main.c <<EOF
int main() { return 0; }
EOF


# echo "SUBDIRS = $subdirs" > Makefile.am
	      
cat >Makefile.am <<EOF
#AUTOMAKE_OPTIONS = subdir-objects
DIST_SUBDIRS = $subdirs
subdir_include \$(srcdir)/foo/Makefile.rules
EOF

cat >configure.in <<EOF
AC_INIT(foo/foo-a.c)
AC_CONFIG_AUX_DIR(.)
AM_INIT_AUTOMAKE(test_am, 1.0)
AC_PROG_CC
#AM_PROG_CC_C_O
AC_OUTPUT(Makefile foo/Makefile)
EOF

# Fail gracefully if no autoconf.
$needs_autoconf

# Likewise for gcc.
(gcc -v) > /dev/null 2>&1 || exit 77

touch README NEWS AUTHORS ChangeLog

mkdir build

# We use gcc and not gcc -traditional as the latter fails on some
# Linux boxes (Red Hat 5.1 in particular).
$ACLOCAL \
   && $AUTOCONF \
   && $AUTOMAKE -a || exit 1

cd build \
   && CC='gcc' ../configure \
   && $MAKE || exit 1
#!/bin/sh

# Test for PR automake/220.

. $srcdir/defs || exit 1

subdirs="foo"

for i in $subdirs; do
mkdir $i
cat >$i/$i-a.c <<EOF
int maina() { return 0; }
EOF
cat >$i/$i-b.c <<EOF
int mainb() { return 0; }
EOF
cat >$i/Makefile.rules <<EOF
bin_PROGRAMS = ${i}bin
${i}bin_SOURCES = ../main.c $i-a.c $i-b.c
EOF
cat >$i/Makefile.am <<EOF
#EXTRA_DIST=Makefile.rules
include \$(srcdir)/Makefile.rules
EOF
done

cat >main.c <<EOF
int main() { return 0; }
EOF


# echo "SUBDIRS = $subdirs" > Makefile.am
	      
cat >Makefile.am <<EOF
#AUTOMAKE_OPTIONS = subdir-objects
DIST_SUBDIRS = $subdirs
SUBDIRS = 
subdir_include \$(srcdir)/foo/Makefile.rules
EOF

cat >configure.in <<EOF
AC_INIT(foo/foo-a.c)
AC_CONFIG_AUX_DIR(.)
AM_INIT_AUTOMAKE(test_am, 1.0)
AC_PROG_CC
#AM_PROG_CC_C_O
AC_OUTPUT(Makefile foo/Makefile)
EOF

# Fail gracefully if no autoconf.
$needs_autoconf

# Likewise for gcc.
(gcc -v) > /dev/null 2>&1 || exit 77

touch README NEWS AUTHORS ChangeLog

mkdir build

# We use gcc and not gcc -traditional as the latter fails on some
# Linux boxes (Red Hat 5.1 in particular).
$ACLOCAL \
   && $AUTOCONF \
   && $AUTOMAKE -a || exit 1

cd build \
   && CC='gcc' ../configure \
   && $MAKE distcheck || exit 1
Index: automake.in
===================================================================
RCS file: /cvs/automake/automake/automake.in,v
retrieving revision 1.1171
diff -u -p -r1.1171 automake.in
--- automake.in	2001/08/13 09:37:49	1.1171
+++ automake.in	2001/08/15 13:30:06
@@ -159,6 +159,11 @@ my $INCLUDE_PATTERN = ('^include\s+'
 		       . '|(\$\(srcdir\)/' . $PATH_PATTERN . ')'
 		       . '|([^/\$]' . $PATH_PATTERN. '))\s*(#.*)?$');
 
+my $SUBDIR_INCLUDE_PATTERN = ('^subdir_include\s+'
+                       . '((\$\(top_srcdir\)/' . $PATH_PATTERN . ')'
+		       . '|(\$\(srcdir\)/' . $PATH_PATTERN . ')'
+		       . '|([^/\$]' . $PATH_PATTERN. '))\s*(#.*)?$');
+
 # Some regular expressions.  One reason to put them here is that it
 # makes indentation work better in Emacs.
 my $AC_CONFIG_AUX_DIR_PATTERN = 'AC_CONFIG_AUX_DIR\(([^)]+)\)';
@@ -212,7 +217,9 @@ my @common_files =
    # ltconfig appears here for compatibility with old versions
    # of libtool.
    'ylwrap', 'acinclude.m4', @libtoolize_files, @libtoolize_sometimes,
-   'missing', 'depcomp', 'compile', 'py-compile'
+   'missing', 'depcomp', 'compile', 'py-compile',
+   # We need a standard name for the rules that are present in each dir
+   'Makefile.rules'
   );
 
 # Commonly used files we auto-include, but only sometimes.
@@ -2032,6 +2039,39 @@ sub handle_single_transform_list ($$$$@)
     return @result;
 }
 
+# $VALUE
+# transform_file_list ($PREPEND, @FILES)
+# ----------------------------------------
+# insert $PREPEND before every file path that is not absolute
+#
+sub transform_file_list ($$)
+{
+      my ($prepend, $tmpfiles) = @_;
+      my $result = "";
+      my @files = ();
+      @files = split(/ /, $tmpfiles); 
+      while (scalar @files > 0)
+      {
+	$_ = shift @files;
+
+	if ($_ =~ s/^\$\(top_srcdir\)\///)
+	  {
+	    $result .= " \$\(top_srcdir\)\/" . $_;
+	  }
+	  elsif ( $_ =~ s/^\$\(srcdir\)\///)
+	  {
+	    $result .= " \$\(srcdir\)\/$prepend" . $_;
+	  }
+	  else
+	  {
+	    $result .= " $prepend" . $_;
+	  }
+      }
+	print "result:$result\n";
+      return $result . "\n";
+}
+	  
+
 # $BOOL
 # define_objects_from_sources ($VAR, $OBJVAR, $NODEFINE, $ONE_FILE,
 #                              $OBJ, $PARENT, $TOPPARENT)
@@ -2132,6 +2172,8 @@ sub define_objects_from_sources ($$$$$$$
     return $needlinker;
 }
 
+
+
 # $OBJNAME
 # subobjname ($VARNAME)
 # ---------------------------------------------------------------------
@@ -2793,7 +2835,7 @@ sub handle_ltlibraries
 	# Canonicalize names and check for misspellings.
 	my $xlib = &check_canonical_spelling ($onelib, '_LIBADD', '_LDFLAGS',
 					      '_SOURCES', '_OBJECTS',
-					      '_DEPENDENCIES');
+					      '_DEPENDENCIES', '_CFLAGS');
 
 	if (! &variable_defined ($xlib . '_LDFLAGS'))
 	{
@@ -2801,6 +2843,19 @@ sub handle_ltlibraries
 	    &define_variable ($xlib . '_LDFLAGS', '');
 	}
 
+	# Tell the source code what library we are building
+#	my $tempvariable = '';
+#	if ( &variable_defined ($xlib . '_CFLAGS'))
+#	{
+#	    # Define the lib_CFLAGS variable.
+#	    $tempvariable .= &variable_value ($xlib . '_CFLAGS');
+#	    &variable_delete ($xlib . '_CFLAGS');
+#	}
+#	my $libname_short = $xlib;
+#	$libname_short =~ s/_la$//  ;
+#	$libname_short = uc ($libname_short);
+#	&define_variable ($xlib . '_CFLAGS', ' -D' . $libname_short . '_COMPILATION ' . $tempvariable);
+
 	# Check that the library fits the standard naming convention.
     	my $libname_rx = "^lib.*\.la";
 	if ((&variable_defined ($xlib . '_LDFLAGS')
@@ -6657,6 +6712,297 @@ sub target_defined
     return defined $targets{$target};
 }
 
+################################################################
+
+# Read Makefile.am and set up %contents.  Simultaneously copy lines
+# from Makefile.am into $output_trailer or $output_vars as
+# appropriate.  NOTE we put rules in the trailer section.  We want
+# user rules to come after our generated stuff.
+#
+# This version translates the file on-the-fly, prepending the leading path to all targets
+
+sub read_am_file_translate
+{
+    my ($amfile, $prepend) = @_;
+
+    my $prepend_macro = $prepend;
+    $prepend_macro =~ s/\//_/;
+
+    my $am_file = new IO::File ("< $amfile");
+    if (! $am_file)
+    {
+        die "$me: couldn't open `$amfile': $!\n";
+    }
+    print "$me: reading $amfile with translation path $prepend\n" if $verbose;
+
+    my $spacing = '';
+    my $comment = '';
+    my $blank = 0;
+
+    while ($_ = $am_file->getline)
+    {
+        if (/$IGNORE_PATTERN/o)
+        {
+            # Merely delete comments beginning with two hashes.
+        }
+        elsif (/$WHITE_PATTERN/o)
+        {
+            # Stick a single white line before the incoming macro or rule.
+            $spacing = "\n";
+            $blank = 1;
+        }
+        elsif (/$COMMENT_PATTERN/o)
+        {
+            # Stick comments before the incoming macro or rule.  Make
+            # sure a blank line preceeds first block of comments.
+            $spacing = "\n" unless $blank;
+            $blank = 1;
+            $comment .= $spacing . $_;
+            $spacing = '';
+        }
+        else
+        {
+            last;
+        }
+    }
+
+    $output_vars .= $comment . "\n";
+    $comment = '';
+    $spacing = "\n";
+
+    # We save the conditional stack on entry, and then check to make
+    # sure it is the same on exit.  This lets us conditonally include
+    # other files.
+    my @saved_cond_stack = @cond_stack;
+    my $cond = conditional_string (@cond_stack);
+
+    my $saw_bk = 0;
+    my $was_rule = 0;
+    my $last_var_name = '';
+    my $last_var_type = '';
+    my $last_var_value = '';
+    # FIXME: shouldn't use $_ in this loop; it is too big.
+    while ($_)
+    {
+        $_ .= "\n"
+            unless substr ($_, -1, 1) eq "\n";
+
+        # Don't look at MAINTAINER_MODE_TRUE here.  That shouldn't be
+        # used by users.  @MAINT@ is an anachronism now.
+        $_ =~ s/\@MAINT\@//g
+            unless $seen_maint_mode;
+
+        my $new_saw_bk = /\\$/ && ! /$COMMENT_PATTERN/o;
+
+        if (/$IGNORE_PATTERN/o)
+        {
+            # Merely delete comments beginning with two hashes.
+        }
+        elsif (/$WHITE_PATTERN/o)
+        {
+            # Stick a single white line before the incoming macro or rule.
+            $spacing = "\n";
+            &am_line_error ($., "blank line following trailing backslash")
+                if $saw_bk;
+        }
+        elsif (/$COMMENT_PATTERN/o)
+        {
+            # Stick comments before the incoming macro or rule.
+            $comment .= $spacing . $_;
+            $spacing = '';
+            &am_line_error ($., "comment following trailing backslash")
+                if $saw_bk;
+        }
+        elsif ($saw_bk)
+        {
+            if ($was_rule)
+            {
+                $output_trailer .= &make_condition (@cond_stack);
+                $output_trailer .= $_;
+		#unhandled yet
+		&am_error ("can't translate saw-bk, was_rule, $_");
+            }
+            else
+            {
+              $last_var_value .= ' '
+                unless $last_var_value =~ /\s$/;
+              $last_var_value .= $_;
+
+              if (!/\\$/)
+                {
+                  $var_comment{$last_var_name} .= "$spacing"
+                    if (!defined $var_comment{$last_var_name}
+                        || substr ($var_comment{$last_var_name}, -1) ne "\n");
+                  $var_comment{$last_var_name} .= "$comment";
+                  $comment = $spacing = '';
+                  macro_define ($last_var_name, 0,
+                                $last_var_type, $cond,
+                                $last_var_value, $.)
+                    if $cond ne 'FALSE';
+                  push (@var_list, $last_var_name);
+		  &am_error ("pushlsit $last_var_name, $last_var_value");
+                }
+            }
+        }
+
+        elsif (/$IF_PATTERN/o)
+          {
+            $cond = cond_stack_if ($1, $2, "$amfile:$.");
+          }
+        elsif (/$ELSE_PATTERN/o)
+          {
+            $cond = cond_stack_else ($1, $2, "$amfile:$.");
+          }
+        elsif (/$ENDIF_PATTERN/o)
+          {
+            $cond = cond_stack_endif ($1, $2, "$amfile:$.");
+          }
+
+        elsif (/$RULE_PATTERN/o)
+        {
+            # Found a rule.
+            $was_rule = 1;
+
+            rule_define ($1, 0, $cond, $.);
+	    &am_error ("rule define $1");
+
+            $var_line{$1} = $.;
+            $output_trailer .= $comment . $spacing;
+            $output_trailer .= &make_condition (@cond_stack);
+            $output_trailer .= $_;
+            $comment = $spacing = '';
+        }
+        elsif (/$ASSIGNMENT_PATTERN/o)
+        {
+            # Found a macro definition.
+	    # Q: when do we translate macro's?
+            $was_rule = 0;
+            $last_var_name = $1;
+            $last_var_type = $2;
+            $last_var_value = $3;
+	    # TODO: translate every element in value
+            if ($3 ne '' && substr ($3, -1) eq "\\")
+            {
+                # We preserve the `\' because otherwise the long lines
+                # that are generated will be truncated by broken
+                # `sed's.
+                $last_var_value = $3 . "\n";
+            }
+
+            if (!/\\$/)
+              {
+                # FIXME: this doesn't always work correctly; it will
+                # group all comments for a given variable, no matter
+                # where defined.
+                # Accumulating variables must not be output.
+                $var_comment{$last_var_name} .= "$spacing"
+                  if (!defined $var_comment{$last_var_name}
+                      || substr ($var_comment{$last_var_name}, -1) ne "\n");
+                $var_comment{$last_var_name} .= "$comment";
+                $comment = $spacing = '';
+
+		# add this definition to the global list
+		#macro_define ($last_var_name, 1, '+', $cond,
+		#	      $last_var_value, $.) if $cond ne 'FALSE';
+
+		# transform the macro name. PROGRAMS etc transform the value, 
+		# Sources etc transform the name and the value.
+
+		# TODO: fixup every element in the macro
+		if (substr($last_var_name, -7) eq "SOURCES" )
+		{
+		  macro_define ($last_var_name, 0,
+                  	$last_var_type, $cond,
+                  	&transform_file_list($prepend, $last_var_value), $.)
+                  if $cond ne 'FALSE';
+                  push (@var_list, $last_var_name);
+		}
+		else
+		{
+
+                macro_define ($last_var_name, 0,
+                              $last_var_type, $cond,
+                              $last_var_value, $.)
+                  if $cond ne 'FALSE';
+                push (@var_list, $last_var_name);
+		}
+		print "pushlist 2  $prepend_macro$last_var_name,$last_var_type,$prepend_macro$last_var_value\n";
+				  
+              }
+        }
+        elsif (/$INCLUDE_PATTERN/o)
+        {
+	    # should included includes be translated?
+            my $path = $1;
+
+            if ($path =~ s/^\$\(top_srcdir\)\///)
+            {
+                push (@include_stack, "\$\(top_srcdir\)/$path");
+            }
+            else
+            {
+                $path =~ s/\$\(srcdir\)\///;
+                push (@include_stack, "\$\(srcdir\)/$path");
+                $path = $relative_dir . "/" . $prepend . $path;
+            }
+            &read_am_file ($path);
+        }
+        elsif (/$SUBDIR_INCLUDE_PATTERN/o)
+        {
+            my $path = $1;
+            my $prepend_path = "";
+
+            if ($path =~ s/^\$\(top_srcdir\)\///)
+            {
+                # the same stack used, as all it does is let us add a dependency for Makefile.am
+                push (@include_stack, "\$\(top_srcdir\)/$path");
+                &am_error ("attempt to translate a top_srcdir include file: $path");
+            }
+            else
+            {
+                $path =~ s/\$\(srcdir\)\///;
+                push (@include_stack, "\$\(srcdir\)/$path");
+                $prepend_path = $path;
+                $prepend_path =~ s/[^\/]*$//;
+		$prepend_path = $prepend . $prepend_path;
+                $path = $relative_dir . "/" . $prepend . $path;
+            }
+            &read_am_file_translate ($path, $prepend_path);
+        }
+        else
+        {
+            # 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 .= &make_condition  (@cond_stack);
+            $output_trailer .= $_;
+            $comment = $spacing = '';
+            &am_line_error ($., "`#' comment at start of rule is unportable")
+                if $_ =~ /^\t\s*\#/;
+        }
+
+        $saw_bk = $new_saw_bk;
+        $_ = $am_file->getline;
+    }
+
+    $output_trailer .= $comment;
+
+    if (join (' ', @saved_cond_stack) ne join (' ', @cond_stack))
+    {
+        if (@cond_stack)
+        {
+            &am_error ("unterminated conditionals: @cond_stack");
+        }
+        else
+        {
+            # FIXME: better error message here.
+            &am_error ("conditionals not nested in include file");
+        }
+    }
+}
+
+      
 
 ################################################################
 
@@ -6858,6 +7204,27 @@ sub read_am_file
             }
             &read_am_file ($path);
         }
+	elsif (/$SUBDIR_INCLUDE_PATTERN/o)
+	{
+	    my $path = $1;
+	    my $prepend_path = "";
+
+	    if ($path =~ s/^\$\(top_srcdir\)\///)
+	    {
+	        # the same stack used, as all it does is let us add a dependency for Makefile.am
+	        push (@include_stack, "\$\(top_srcdir\)/$path");
+		&am_error ("attempt to translate a top_srcdir include file: $path");
+	    }
+	    else
+	    {
+	        $path =~ s/\$\(srcdir\)\///;
+                push (@include_stack, "\$\(srcdir\)/$path");
+		$prepend_path = $path;
+		$prepend_path =~ s/[^\/]*$//;
+                $path = $relative_dir . "/" . $path;
+            }
+            &read_am_file_translate ($path, $prepend_path);
+	}
 	else
         {
 	    # This isn't an error; it is probably a continued rule.
@@ -7129,8 +7496,23 @@ sub file_contents_internal ($$%)
 		$result_rules .= $rules;
 	      }
         }
+
+# library files aren't allowed this directive.	# Handle path translated inclusion of other files.
+#	elsif (/$SUBDIR_INCLUDE_PATTERN/o)
+#       {
+#	    if ($cond ne 'FALSE')
+#              {
+#                my $file = ($is_am ? "$libdir/am/" : '') . $1;
+#                # N-ary `.=' fails.
+#                my ($com, $vars, $rules)
+#                  = file_contents_internal ($is_am, $file, %transform);
+#                $comment .= $com;
+#                $result_vars .= $vars;
+#                $result_rules .= $rules;
+#              }
+#        }
 
-        # Handling the conditionals.
+	# Handling the conditionals.
         elsif (/$IF_PATTERN/o)
 	  {
 	    $cond = cond_stack_if ($1, $2, $file);
Index: tests/Makefile.am
===================================================================
RCS file: /cvs/automake/automake/tests/Makefile.am,v
retrieving revision 1.344
diff -u -p -r1.344 Makefile.am
--- Makefile.am	2001/08/13 09:37:49	1.344
+++ Makefile.am	2001/08/15 13:30:07
@@ -276,6 +277,8 @@ subdir4.test \
 subdir5.test \
 subdirbuiltsources.test \
 subdircond.test \
+subdir_include.test \
+subdir_include_distcheck.test \
 subobj.test \
 subobj2.test \
 subobj3.test \

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]