[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
RE: monolithic Makefile.am
From: |
Robert Collins |
Subject: |
RE: monolithic Makefile.am |
Date: |
Sun, 12 May 2002 13:42:28 +1000 |
> -----Original Message-----
> From: Tom Tromey [mailto:address@hidden
> Sent: Sunday, May 12, 2002 9:15 AM
> To: Robert Collins
> Cc: Richard Boulton; Harlan Stenn; Automake
> Subject: Re: monolithic Makefile.am
>
>
> >>>>> "Rob" == Robert Collins <address@hidden> writes:
>
>
> I looked at this. I think it is missing one of the major
> features I'd like out from `import', namely the ability to
> have targets like `subdir/clean' and `subdir/all'.
Are targets like
foo/all:
portable?
Emitting
foo_all:
would be trivial.
Emitting foo/all: may be more difficult, I really don't know.
I've update the patch to be against 1.6, and to emit
foo_bar_SOURCES:
for the rule
bar_SOURCES =
in a subdir Makefile.rules.
> I think doing this requires the bulk of the work, since it
> means a lot of code generation changes in automake. I'd be
> delighted to be proven wrong :-)
--- ../automake-1.6/automake.in Wed Mar 6 15:46:14 2002
+++ automake.in Sun May 12 13:34:00 2002
@@ -157,6 +157,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\(([^)]+)\)';
@@ -208,7 +213,7 @@ my @common_files =
ansi2knr.1 ansi2knr.c compile config.guess config.rpath
config.sub
configure configure.ac configure.in depcomp elisp-comp
install-sh libversion.in mdate-sh missing mkinstalldirs
- py-compile texinfo.tex ylwrap),
+ py-compile texinfo.tex ylwrap Makefile.rules),
@libtool_files, @libtool_sometimes);
# Commonly used files we auto-include, but only sometimes.
@@ -2121,6 +2126,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)
@@ -2223,6 +2261,8 @@ sub define_objects_from_sources ($$$$$$$
}
+
+
# $OBJNAME
# subobjname ($VARNAME)
# ---------------------
@@ -2889,7 +2929,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'))
{
@@ -2897,6 +2937,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')
@@ -6887,6 +6940,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/address@hidden@//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 ("pushlist $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 ("$prepend_macro$last_var_name", 0,
+ $last_var_type, $cond,
+ &transform_file_list($prepend, $last_var_value),
$.)
+ if $cond ne 'FALSE';
+ push (@var_list, "$prepend_macro$last_var_name");
+ }
+ else
+ {
+
+ macro_define ("$last_var_name", 0,
+ $last_var_type, $cond,
+ "$prepend_macro$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_valu
e\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");
+ }
+ }
+}
+
+
################################################################
@@ -7101,6 +7445,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.
@@ -7376,7 +7741,22 @@ sub file_contents_internal ($$%)
}
}
- # Handling the conditionals.
+# 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.
elsif (/$IF_PATTERN/o)
{
$cond = cond_stack_if ($1, $2, $file);