summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthias Paulmier <matthias.paulmier@etu.u-bordeaux.fr>2018-06-20 16:57:02 +0200
committerMatthias Paulmier <matthias.paulmier@etu.u-bordeaux.fr>2018-06-22 14:20:37 +0200
commitfb62d77e15dabcc9faa5db14007191bd9bb9059f (patch)
tree9ae486a68de1175a47629e0e1fbb3462da6f64bd
parentdc79cd192751c0022a21c1d8b4fc57afa845ee3e (diff)
downloadautomake-fb62d77e15dabcc9faa5db14007191bd9bb9059f.tar.gz
lib: Add new modules
In an effort to move out as much as possible from the main script, we create these modules to host the methods. * LangHandling: This module host all the functions for handling languages (functions that define obj directories of the language, rewrite the file extention...). * SilentRules: Declares functions for handling silent rules. * Requires: Functions for requiring configuration files.
-rwxr-xr-xbin/automake.in899
-rw-r--r--lib/Automake/LangHandling.pm484
-rw-r--r--lib/Automake/Requires.pm424
-rw-r--r--lib/Automake/SilentRules.pm73
-rw-r--r--lib/Automake/local.mk3
5 files changed, 987 insertions, 896 deletions
diff --git a/bin/automake.in b/bin/automake.in
index 4b5eee448..556780eb2 100755
--- a/bin/automake.in
+++ b/bin/automake.in
@@ -72,6 +72,9 @@ use Automake::Utils;
use Automake::CondStack;
use Automake::ConfVars;
use Automake::Errors;
+use Automake::LangHandling;
+use Automake::SilentRules;
+use Automake::Requires;
use File::Basename;
use File::Spec;
use Carp;
@@ -110,7 +113,6 @@ sub handle_options ();
sub handle_programs ();
sub handle_python ();
sub handle_scripts ();
-sub handle_silent ();
sub handle_subdirs ();
sub handle_tags ();
sub handle_targets ();
@@ -590,66 +592,6 @@ sub backname
return join ('/', @res) || '.';
}
-################################################################
-
-# Silent rules handling functions.
-
-# verbose_flag (NAME)
-# -------------------
-# Contents of '%VERBOSE%' variable to expand before rule command.
-sub verbose_flag
-{
- my ($name) = @_;
- return '$(' . verbose_var ($name) . ')';
-}
-
-sub verbose_nodep_flag
-{
- my ($name) = @_;
- return '$(' . verbose_var ($name) . subst ('am__nodep') . ')';
-}
-
-# silent_flag
-# -----------
-# Contents of %SILENT%: variable to expand to '@' when silent.
-sub silent_flag ()
-{
- return verbose_flag ('at');
-}
-
-# Engage the needed silent rules machinery for assorted texinfo commands.
-sub define_verbose_texinfo ()
-{
- my @tagvars = ('DVIPS', 'MAKEINFO', 'INFOHTML', 'TEXI2DVI', 'TEXI2PDF');
- foreach my $tag (@tagvars)
- {
- define_verbose_tagvar($tag);
- }
- define_verbose_var('texinfo', '-q');
- define_verbose_var('texidevnull', '> /dev/null');
-}
-
-# Engage the needed silent rules machinery for 'libtool --silent'.
-sub define_verbose_libtool ()
-{
- define_verbose_var ('lt', '--silent');
- return verbose_flag ('lt');
-}
-
-sub handle_silent ()
-{
- # Define "$(AM_V_P)", expanding to a shell conditional that can be
- # used in make recipes to determine whether we are being run in
- # silent mode or not. The choice of the name derives from the LISP
- # convention of appending the letter 'P' to denote a predicate (see
- # also "the '-P' convention" in the Jargon File); we do so for lack
- # of a better convention.
- define_verbose_var ('P', 'false', ':');
- # *Always* provide the user with '$(AM_V_GEN)', unconditionally.
- define_verbose_tagvar ('GEN');
- define_verbose_var ('at', '@');
-}
-
################################################################
@@ -701,32 +643,6 @@ sub shadow_unconditionally
return "\$($varname)"
}
-# check_user_variables (@LIST)
-# ----------------------------
-# Make sure each variable VAR in @LIST does not exist, suggest using AM_VAR
-# otherwise.
-sub check_user_variables
-{
- my @dont_override = @_;
- foreach my $flag (@dont_override)
- {
- my $var = var $flag;
- if ($var)
- {
- for my $cond ($var->conditions->conds)
- {
- if ($var->rdef ($cond)->owner == VAR_MAKEFILE)
- {
- msg_cond_var ('gnu', $cond, $flag,
- "'$flag' is a user variable, "
- . "you should not override it;\n"
- . "use 'AM_$flag' instead");
- }
- }
- }
- }
-}
-
# Call finish function for each language that was used.
sub handle_languages ()
{
@@ -5059,416 +4975,6 @@ sub check_gnits_standards ()
}
}
-################################################################
-#
-# Functions to handle files of each language.
-
-# Each 'lang_X_rewrite($DIRECTORY, $BASE, $EXT)' function follows a
-# simple formula: Return value is LANG_SUBDIR if the resulting object
-# file should be in a subdir if the source file is, LANG_PROCESS if
-# file is to be dealt with, LANG_IGNORE otherwise.
-
-# Much of the actual processing is handled in
-# handle_single_transform. These functions exist so that
-# auxiliary information can be recorded for a later cleanup pass.
-# Note that the calls to these functions are computed, so don't bother
-# searching for their precise names in the source.
-
-# This is just a convenience function that can be used to determine
-# when a subdir object should be used.
-sub lang_sub_obj ()
-{
- return option 'subdir-objects' ? LANG_SUBDIR : LANG_PROCESS;
-}
-
-# Rewrite a single header file.
-sub lang_header_rewrite
-{
- # Header files are simply ignored.
- return LANG_IGNORE;
-}
-
-# Rewrite a single Vala source file.
-sub lang_vala_rewrite
-{
- my ($directory, $base, $ext) = @_;
-
- (my $newext = $ext) =~ s/vala$/c/;
- return (LANG_SUBDIR, $newext);
-}
-
-# Rewrite a single yacc/yacc++ file.
-sub lang_yacc_rewrite
-{
- my ($directory, $base, $ext) = @_;
-
- my $r = lang_sub_obj;
- (my $newext = $ext) =~ tr/y/c/;
- return ($r, $newext);
-}
-sub lang_yaccxx_rewrite { lang_yacc_rewrite (@_); };
-
-# Rewrite a single lex/lex++ file.
-sub lang_lex_rewrite
-{
- my ($directory, $base, $ext) = @_;
-
- my $r = lang_sub_obj;
- (my $newext = $ext) =~ tr/l/c/;
- return ($r, $newext);
-}
-sub lang_lexxx_rewrite { lang_lex_rewrite (@_); };
-
-# Rewrite a single Java file.
-sub lang_java_rewrite
-{
- return LANG_SUBDIR;
-}
-
-# The lang_X_finish functions are called after all source file
-# processing is done. Each should handle defining rules for the
-# language, etc. A finish function is only called if a source file of
-# the appropriate type has been seen.
-
-sub lang_vala_finish_target
-{
- my ($self, $name) = @_;
-
- my $derived = canonicalize ($name);
- my $var = var "${derived}_SOURCES";
- return unless $var;
-
- my @vala_sources = grep { /\.(vala|vapi)$/ } ($var->value_as_list_recursive);
-
- # For automake bug#11229.
- return unless @vala_sources;
-
- foreach my $vala_file (@vala_sources)
- {
- my $c_file = $vala_file;
- if ($c_file =~ s/(.*)\.vala$/$1.c/)
- {
- $c_file = "\$(srcdir)/$c_file";
- $output_rules .= "$c_file: \$(srcdir)/${derived}_vala.stamp\n"
- . "\t\@if test -f \$@; then :; else rm -f \$(srcdir)/${derived}_vala.stamp; fi\n"
- . "\t\@if test -f \$@; then :; else \\\n"
- . "\t \$(MAKE) \$(AM_MAKEFLAGS) \$(srcdir)/${derived}_vala.stamp; \\\n"
- . "\tfi\n";
- $clean_files{$c_file} = MAINTAINER_CLEAN;
- }
- }
-
- # Add rebuild rules for generated header and vapi files
- my $flags = var ($derived . '_VALAFLAGS');
- if ($flags)
- {
- my $lastflag = '';
- foreach my $flag ($flags->value_as_list_recursive)
- {
- if (grep (/$lastflag/, ('-H', '-h', '--header', '--internal-header',
- '--vapi', '--internal-vapi', '--gir')))
- {
- my $headerfile = "\$(srcdir)/$flag";
- $output_rules .= "$headerfile: \$(srcdir)/${derived}_vala.stamp\n"
- . "\t\@if test -f \$@; then :; else rm -f \$(srcdir)/${derived}_vala.stamp; fi\n"
- . "\t\@if test -f \$@; then :; else \\\n"
- . "\t \$(MAKE) \$(AM_MAKEFLAGS) \$(srcdir)/${derived}_vala.stamp; \\\n"
- . "\tfi\n";
-
- # valac is not used when building from dist tarballs
- # distribute the generated files
- push_dist_common ($headerfile);
- $clean_files{$headerfile} = MAINTAINER_CLEAN;
- }
- $lastflag = $flag;
- }
- }
-
- my $compile = $self->compile;
-
- # Rewrite each occurrence of 'AM_VALAFLAGS' in the compile
- # rule into '${derived}_VALAFLAGS' if it exists.
- my $val = "${derived}_VALAFLAGS";
- $compile =~ s/\(AM_VALAFLAGS\)/\($val\)/
- if set_seen ($val);
-
- # VALAFLAGS is a user variable (per GNU Standards),
- # it should not be overridden in the Makefile...
- check_user_variables 'VALAFLAGS';
-
- my $dirname = dirname ($name);
-
- # Only generate C code, do not run C compiler
- $compile .= " -C";
-
- my $verbose = verbose_flag ('VALAC');
- my $silent = silent_flag ();
- my $stampfile = "\$(srcdir)/${derived}_vala.stamp";
-
- $output_rules .=
- "\$(srcdir)/${derived}_vala.stamp: @vala_sources\n".
-# Since the C files generated from the vala sources depend on the
-# ${derived}_vala.stamp file, we must ensure its timestamp is older than
-# those of the C files generated by the valac invocation below (this is
-# especially important on systems with sub-second timestamp resolution).
-# Thus we need to create the stamp file *before* invoking valac, and to
-# move it to its final location only after valac has been invoked.
- "\t${silent}rm -f \$\@ && echo stamp > \$\@-t\n".
- "\t${verbose}\$(am__cd) \$(srcdir) && $compile @vala_sources\n".
- "\t${silent}mv -f \$\@-t \$\@\n";
-
- push_dist_common ($stampfile);
-
- $clean_files{$stampfile} = MAINTAINER_CLEAN;
-}
-
-# Add output rules to invoke valac and create stamp file as a witness
-# to handle multiple outputs. This function is called after all source
-# file processing is done.
-sub lang_vala_finish ()
-{
- my ($self) = @_;
-
- foreach my $prog (keys %known_programs)
- {
- lang_vala_finish_target ($self, $prog);
- }
-
- while (my ($name) = each %known_libraries)
- {
- lang_vala_finish_target ($self, $name);
- }
-}
-
-# The built .c files should be cleaned only on maintainer-clean
-# as the .c files are distributed. This function is called for each
-# .vala source file.
-sub lang_vala_target_hook
-{
- my ($self, $aggregate, $output, $input, %transform) = @_;
-
- $clean_files{$output} = MAINTAINER_CLEAN;
-}
-
-# This is a yacc helper which is called whenever we have decided to
-# compile a yacc file.
-sub lang_yacc_target_hook
-{
- my ($self, $aggregate, $output, $input, %transform) = @_;
-
- # If some relevant *YFLAGS variable contains the '-d' flag, we'll
- # have to to generate special code.
- my $yflags_contains_minus_d = 0;
-
- foreach my $pfx ("", "${aggregate}_")
- {
- my $yflagsvar = var ("${pfx}YFLAGS");
- next unless $yflagsvar;
- # We cannot work reliably with conditionally-defined YFLAGS.
- if ($yflagsvar->has_conditional_contents)
- {
- msg_var ('unsupported', $yflagsvar,
- "'${pfx}YFLAGS' cannot have conditional contents");
- }
- else
- {
- $yflags_contains_minus_d = 1
- if grep (/^-d$/, $yflagsvar->value_as_list_recursive);
- }
- }
-
- if ($yflags_contains_minus_d)
- {
- # Found a '-d' that applies to the compilation of this file.
- # Add a dependency for the generated header file, and arrange
- # for that file to be included in the distribution.
-
- # The extension of the output file (e.g., '.c' or '.cxx').
- # We'll need it to compute the name of the generated header file.
- (my $output_ext = basename ($output)) =~ s/.*(\.[^.]+)$/$1/;
-
- # We know that a yacc input should be turned into either a C or
- # C++ output file. We depend on this fact (here and in yacc.am),
- # so check that it really holds.
- my $lang = $languages{$extension_map{$output_ext}};
- prog_error "invalid output name '$output' for yacc file '$input'"
- if (!$lang || ($lang->name ne 'c' && $lang->name ne 'cxx'));
-
- (my $header_ext = $output_ext) =~ s/c/h/g;
- # Quote $output_ext in the regexp, so that dots in it are taken
- # as literal dots, not as metacharacters.
- (my $header = $output) =~ s/\Q$output_ext\E$/$header_ext/;
-
- foreach my $cond (Automake::Rule::define (${header}, 'internal',
- RULE_AUTOMAKE, TRUE,
- INTERNAL))
- {
- my $condstr = $cond->subst_string;
- $output_rules .=
- "$condstr${header}: $output\n"
- # Recover from removal of $header
- . "$condstr\t\@if test ! -f \$@; then rm -f $output; else :; fi\n"
- . "$condstr\t\@if test ! -f \$@; then \$(MAKE) \$(AM_MAKEFLAGS) $output; else :; fi\n";
- }
- # Distribute the generated file, unless its .y source was
- # listed in a nodist_ variable. (handle_source_transform()
- # will set DIST_SOURCE.)
- push_dist_common ($header)
- if $transform{'DIST_SOURCE'};
-
- # The GNU rules say that yacc/lex output files should be removed
- # by maintainer-clean. However, if the files are not distributed,
- # then we want to remove them with "make clean"; otherwise,
- # "make distcheck" will fail.
- $clean_files{$header} = $transform{'DIST_SOURCE'} ? MAINTAINER_CLEAN : CLEAN;
- }
- # See the comment above for $HEADER.
- $clean_files{$output} = $transform{'DIST_SOURCE'} ? MAINTAINER_CLEAN : CLEAN;
-}
-
-# This is a lex helper which is called whenever we have decided to
-# compile a lex file.
-sub lang_lex_target_hook
-{
- my ($self, $aggregate, $output, $input, %transform) = @_;
- # The GNU rules say that yacc/lex output files should be removed
- # by maintainer-clean. However, if the files are not distributed,
- # then we want to remove them with "make clean"; otherwise,
- # "make distcheck" will fail.
- $clean_files{$output} = $transform{'DIST_SOURCE'} ? MAINTAINER_CLEAN : CLEAN;
-}
-
-# This is a helper for both lex and yacc.
-sub yacc_lex_finish_helper ()
-{
- return if defined $language_scratch{'lex-yacc-done'};
- $language_scratch{'lex-yacc-done'} = 1;
-
- # FIXME: for now, no line number.
- require_conf_file ($configure_ac, FOREIGN, 'ylwrap');
- define_variable ('YLWRAP', "$am_config_aux_dir/ylwrap", INTERNAL);
-}
-
-sub lang_yacc_finish ()
-{
- return if defined $language_scratch{'yacc-done'};
- $language_scratch{'yacc-done'} = 1;
-
- reject_var 'YACCFLAGS', "'YACCFLAGS' obsolete; use 'YFLAGS' instead";
-
- yacc_lex_finish_helper;
-}
-
-
-sub lang_lex_finish ()
-{
- return if defined $language_scratch{'lex-done'};
- $language_scratch{'lex-done'} = 1;
-
- yacc_lex_finish_helper;
-}
-
-
-# Given a hash table of linker names, pick the name that has the most
-# precedence. This is lame, but something has to have global
-# knowledge in order to eliminate the conflict. Add more linkers as
-# required.
-sub resolve_linker
-{
- my (%linkers) = @_;
-
- foreach my $l (qw(GCJLINK OBJCXXLINK CXXLINK F77LINK FCLINK OBJCLINK UPCLINK))
- {
- return $l if defined $linkers{$l};
- }
- return 'LINK';
-}
-
-# Called to indicate that an extension was used.
-sub saw_extension
-{
- my ($ext) = @_;
- $extension_seen{$ext} = 1;
-}
-
-# register_language (%ATTRIBUTE)
-# ------------------------------
-# Register a single language.
-# Each %ATTRIBUTE is of the form ATTRIBUTE => VALUE.
-sub register_language
-{
- my (%option) = @_;
-
- # Set the defaults.
- $option{'autodep'} = 'no'
- unless defined $option{'autodep'};
- $option{'linker'} = ''
- unless defined $option{'linker'};
- $option{'flags'} = []
- unless defined $option{'flags'};
- $option{'output_extensions'} = sub { return ( '.$(OBJEXT)', '.lo' ) }
- unless defined $option{'output_extensions'};
- $option{'nodist_specific'} = 0
- unless defined $option{'nodist_specific'};
-
- my $lang = new Automake::Language (%option);
-
- # Fill indexes.
- $extension_map{$_} = $lang->name foreach @{$lang->extensions};
- $languages{$lang->name} = $lang;
- my $link = $lang->linker;
- if ($link)
- {
- if (exists $link_languages{$link})
- {
- prog_error ("'$link' has different definitions in "
- . $lang->name . " and " . $link_languages{$link}->name)
- if $lang->link ne $link_languages{$link}->link;
- }
- else
- {
- $link_languages{$link} = $lang;
- }
- }
-
- # Update the pattern of known extensions.
- accept_extensions (@{$lang->extensions});
-
- # Update the suffix rules map.
- foreach my $suffix (@{$lang->extensions})
- {
- foreach my $dest ($lang->output_extensions->($suffix))
- {
- register_suffix_rule (INTERNAL, $suffix, $dest);
- }
- }
-}
-
-# derive_suffix ($EXT, $OBJ)
-# --------------------------
-# This function is used to find a path from a user-specified suffix $EXT
-# to $OBJ or to some other suffix we recognize internally, e.g. 'cc'.
-sub derive_suffix
-{
- my ($source_ext, $obj) = @_;
-
- while (!$extension_map{$source_ext} && $source_ext ne $obj)
- {
- my $new_source_ext = next_in_suffix_chain ($source_ext, $obj);
- last if not defined $new_source_ext;
- $source_ext = $new_source_ext;
- }
-
- return $source_ext;
-}
-
-
-# Pretty-print something and append to '$output_rules'.
-sub pretty_print_rule
-{
- $output_rules .= makefile_wrap (shift, shift, @_);
-}
-
################################################################
@@ -6237,405 +5743,6 @@ sub am_install_var
return map { [$result{$_}->clone, $_] } @l;
}
-
-################################################################
-
-# push_required_file ($DIR, $FILE, $FULLFILE)
-# -------------------------------------------
-# Push the given file onto DIST_COMMON.
-sub push_required_file
-{
- my ($dir, $file, $fullfile) = @_;
-
- # If the file to be distributed is in the same directory of the
- # currently processed Makefile.am, then we want to distribute it
- # from this same Makefile.am.
- if ($dir eq $relative_dir)
- {
- push_dist_common ($file);
- }
- # This is needed to allow a construct in a non-top-level Makefile.am
- # to require a file in the build-aux directory (see at least the test
- # script 'test-driver-is-distributed.sh'). This is related to the
- # automake bug#9546. Note that the use of $config_aux_dir instead
- # of $am_config_aux_dir here is deliberate and necessary.
- elsif ($dir eq $config_aux_dir)
- {
- push_dist_common ("$am_config_aux_dir/$file");
- }
- # FIXME: another spacial case, for AC_LIBOBJ/AC_LIBSOURCE support.
- # We probably need some refactoring of this function and its callers,
- # to have a more explicit and systematic handling of all the special
- # cases; but, since there are only two of them, this is low-priority
- # ATM.
- elsif ($config_libobj_dir && $dir eq $config_libobj_dir)
- {
- # Avoid unsightly '/.'s.
- my $am_config_libobj_dir =
- '$(top_srcdir)' .
- ($config_libobj_dir eq '.' ? "" : "/$config_libobj_dir");
- $am_config_libobj_dir =~ s|/*$||;
- push_dist_common ("$am_config_libobj_dir/$file");
- }
- elsif ($relative_dir eq '.' && ! is_make_dir ($dir))
- {
- # If we are doing the topmost directory, and the file is in a
- # subdir which does not have a Makefile, then we distribute it
- # here.
-
- # If a required file is above the source tree, it is important
- # to prefix it with '$(srcdir)' so that no VPATH search is
- # performed. Otherwise problems occur with Make implementations
- # that rewrite and simplify rules whose dependencies are found in a
- # VPATH location. Here is an example with OSF1/Tru64 Make.
- #
- # % cat Makefile
- # VPATH = sub
- # distdir: ../a
- # echo ../a
- # % ls
- # Makefile a
- # % make
- # echo a
- # a
- #
- # Dependency '../a' was found in 'sub/../a', but this make
- # implementation simplified it as 'a'. (Note that the sub/
- # directory does not even exist.)
- #
- # This kind of VPATH rewriting seems hard to cancel. The
- # distdir.am hack against VPATH rewriting works only when no
- # simplification is done, i.e., for dependencies which are in
- # subdirectories, not in enclosing directories. Hence, in
- # the latter case we use a full path to make sure no VPATH
- # search occurs.
- $fullfile = '$(srcdir)/' . $fullfile
- if $dir =~ m,^\.\.(?:$|/),;
-
- push_dist_common ($fullfile);
- }
- else
- {
- prog_error "a Makefile in relative directory $relative_dir " .
- "can't add files in directory $dir to DIST_COMMON";
- }
-}
-
-
-# If a file name appears as a key in this hash, then it has already
-# been checked for. This allows us not to report the same error more
-# than once.
-my %required_file_not_found = ();
-
-# required_file_check_or_copy ($WHERE, $DIRECTORY, $FILE)
-# -------------------------------------------------------
-# Verify that the file must exist in $DIRECTORY, or install it.
-sub required_file_check_or_copy
-{
- my ($where, $dir, $file) = @_;
-
- my $fullfile = "$dir/$file";
- my $found_it = 0;
- my $dangling_sym = 0;
-
- if (-l $fullfile && ! -f $fullfile)
- {
- $dangling_sym = 1;
- }
- elsif (dir_has_case_matching_file ($dir, $file))
- {
- $found_it = 1;
- }
-
- # '--force-missing' only has an effect if '--add-missing' is
- # specified.
- return
- if $found_it && (! $add_missing || ! $force_missing);
-
- # If we've already looked for it, we're done. You might wonder why we
- # don't do this before searching for the file. If we do that, then
- # something like AC_OUTPUT([subdir/foo foo]) will fail to put 'foo.in'
- # into $(DIST_COMMON).
- if (! $found_it)
- {
- return if defined $required_file_not_found{$fullfile};
- $required_file_not_found{$fullfile} = 1;
- }
- if ($dangling_sym && $add_missing)
- {
- unlink ($fullfile);
- }
-
- my $trailer = '';
- my $trailer2 = '';
- my $suppress = 0;
-
- # Only install missing files according to our desired
- # strictness level.
- my $message = "required file '$fullfile' not found";
- if ($add_missing)
- {
- if (-f "$libdir/$file")
- {
- $suppress = 1;
-
- # Install the missing file. Symlink if we
- # can, copy if we must. Note: delete the file
- # first, in case it is a dangling symlink.
- $message = "installing '$fullfile'";
-
- # The license file should not be volatile.
- if ($file eq "COPYING")
- {
- $message .= " using GNU General Public License v3 file";
- $trailer2 = "\n Consider adding the COPYING file"
- . " to the version control system"
- . "\n for your code, to avoid questions"
- . " about which license your project uses";
- }
-
- # Windows Perl will hang if we try to delete a
- # file that doesn't exist.
- unlink ($fullfile) if -f $fullfile;
- if ($symlink_exists && ! $copy_missing)
- {
- if (! symlink ("$libdir/$file", $fullfile)
- || ! -e $fullfile)
- {
- $suppress = 0;
- $trailer = "; error while making link: $!";
- }
- }
- elsif (system ('cp', "$libdir/$file", $fullfile))
- {
- $suppress = 0;
- $trailer = "\n error while copying";
- }
- set_dir_cache_file ($dir, $file);
- }
- }
- else
- {
- $trailer = "\n 'automake --add-missing' can install '$file'"
- if -f "$libdir/$file";
- }
-
- # If --force-missing was specified, and we have
- # actually found the file, then do nothing.
- return
- if $found_it && $force_missing;
-
- # If we couldn't install the file, but it is a target in
- # the Makefile, don't print anything. This allows files
- # like README, AUTHORS, or THANKS to be generated.
- return
- if !$suppress && rule $file;
-
- msg ($suppress ? 'note' : 'error', $where, "$message$trailer$trailer2");
-}
-
-
-# require_file_internal ($WHERE, $MYSTRICT, $DIRECTORY, $QUEUE, @FILES)
-# ---------------------------------------------------------------------
-# Verify that the file must exist in $DIRECTORY, or install it.
-# $MYSTRICT is the strictness level at which this file becomes required.
-# Worker threads may queue up the action to be serialized by the master,
-# if $QUEUE is true
-sub require_file_internal
-{
- my ($where, $mystrict, $dir, $queue, @files) = @_;
-
- return
- unless $strictness >= $mystrict;
-
- foreach my $file (@files)
- {
- push_required_file ($dir, $file, "$dir/$file");
- if ($queue)
- {
- queue_required_file_check_or_copy ($required_conf_file_queue,
- QUEUE_CONF_FILE, $relative_dir,
- $where, $mystrict, @files);
- }
- else
- {
- required_file_check_or_copy ($where, $dir, $file);
- }
- }
-}
-
-# require_file ($WHERE, $MYSTRICT, @FILES)
-# ----------------------------------------
-sub require_file
-{
- my ($where, $mystrict, @files) = @_;
- require_file_internal ($where, $mystrict, $relative_dir, 0, @files);
-}
-
-# require_file_with_macro ($COND, $MACRO, $MYSTRICT, @FILES)
-# ----------------------------------------------------------
-sub require_file_with_macro
-{
- my ($cond, $macro, $mystrict, @files) = @_;
- $macro = rvar ($macro) unless ref $macro;
- require_file ($macro->rdef ($cond)->location, $mystrict, @files);
-}
-
-# require_libsource_with_macro ($COND, $MACRO, $MYSTRICT, @FILES)
-# ---------------------------------------------------------------
-# Require an AC_LIBSOURCEd file. If AC_CONFIG_LIBOBJ_DIR was called, it
-# must be in that directory. Otherwise expect it in the current directory.
-sub require_libsource_with_macro
-{
- my ($cond, $macro, $mystrict, @files) = @_;
- $macro = rvar ($macro) unless ref $macro;
- if ($config_libobj_dir)
- {
- require_file_internal ($macro->rdef ($cond)->location, $mystrict,
- $config_libobj_dir, 0, @files);
- }
- else
- {
- require_file ($macro->rdef ($cond)->location, $mystrict, @files);
- }
-}
-
-# queue_required_file_check_or_copy ($QUEUE, $KEY, $DIR, $WHERE,
-# $MYSTRICT, @FILES)
-# --------------------------------------------------------------
-sub queue_required_file_check_or_copy
-{
- my ($queue, $key, $dir, $where, $mystrict, @files) = @_;
- my @serial_loc;
- if (ref $where)
- {
- @serial_loc = (QUEUE_LOCATION, $where->serialize ());
- }
- else
- {
- @serial_loc = (QUEUE_STRING, $where);
- }
- $queue->enqueue ($key, $dir, @serial_loc, $mystrict, 0 + @files, @files);
-}
-
-# require_queued_file_check_or_copy ($QUEUE)
-# ------------------------------------------
-sub require_queued_file_check_or_copy
-{
- my ($queue) = @_;
- my $where;
- my $dir = $queue->dequeue ();
- my $loc_key = $queue->dequeue ();
- if ($loc_key eq QUEUE_LOCATION)
- {
- $where = Automake::Location::deserialize ($queue);
- }
- elsif ($loc_key eq QUEUE_STRING)
- {
- $where = $queue->dequeue ();
- }
- else
- {
- prog_error "unexpected key $loc_key";
- }
- my $mystrict = $queue->dequeue ();
- my $nfiles = $queue->dequeue ();
- my @files;
- push @files, $queue->dequeue ()
- foreach (1 .. $nfiles);
- return
- unless $strictness >= $mystrict;
- foreach my $file (@files)
- {
- required_file_check_or_copy ($where, $config_aux_dir, $file);
- }
-}
-
-# require_conf_file ($WHERE, $MYSTRICT, @FILES)
-# ---------------------------------------------
-# Looks in configuration path, as specified by AC_CONFIG_AUX_DIR.
-sub require_conf_file
-{
- my ($where, $mystrict, @files) = @_;
- my $queue = defined $required_conf_file_queue ? 1 : 0;
- require_file_internal ($where, $mystrict, $config_aux_dir,
- $queue, @files);
-}
-
-
-# require_conf_file_with_macro ($COND, $MACRO, $MYSTRICT, @FILES)
-# ---------------------------------------------------------------
-sub require_conf_file_with_macro
-{
- my ($cond, $macro, $mystrict, @files) = @_;
- require_conf_file (rvar ($macro)->rdef ($cond)->location,
- $mystrict, @files);
-}
-
-################################################################
-
-# require_build_directory ($DIRECTORY)
-# ------------------------------------
-# Emit rules to create $DIRECTORY if needed, and return
-# the file that any target requiring this directory should be made
-# dependent upon.
-# We don't want to emit the rule twice, and want to reuse it
-# for directories with equivalent names (e.g., 'foo/bar' and './foo//bar').
-sub require_build_directory
-{
- my $directory = shift;
-
- return $directory_map{$directory} if exists $directory_map{$directory};
-
- my $cdir = File::Spec->canonpath ($directory);
-
- if (exists $directory_map{$cdir})
- {
- my $stamp = $directory_map{$cdir};
- $directory_map{$directory} = $stamp;
- return $stamp;
- }
-
- my $dirstamp = "$cdir/\$(am__dirstamp)";
-
- $directory_map{$directory} = $dirstamp;
- $directory_map{$cdir} = $dirstamp;
-
- # Set a variable for the dirstamp basename.
- define_pretty_variable ('am__dirstamp', TRUE, INTERNAL,
- '$(am__leading_dot)dirstamp');
-
- # Directory must be removed by 'make distclean'.
- $clean_files{$dirstamp} = DIST_CLEAN;
-
- $output_rules .= ("$dirstamp:\n"
- . "\t\@\$(MKDIR_P) $directory\n"
- . "\t\@: > $dirstamp\n");
-
- return $dirstamp;
-}
-
-# require_build_directory_maybe ($FILE)
-# -------------------------------------
-# If $FILE lies in a subdirectory, emit a rule to create this
-# directory and return the file that $FILE should be made
-# dependent upon. Otherwise, just return the empty string.
-sub require_build_directory_maybe
-{
- my $file = shift;
- my $directory = dirname ($file);
-
- if ($directory ne '.')
- {
- return require_build_directory ($directory);
- }
- else
- {
- return '';
- }
-}
-
-
################################################################
# generate_makefile ($MAKEFILE_AM, $MAKEFILE_IN)
diff --git a/lib/Automake/LangHandling.pm b/lib/Automake/LangHandling.pm
new file mode 100644
index 000000000..bfbbb003c
--- /dev/null
+++ b/lib/Automake/LangHandling.pm
@@ -0,0 +1,484 @@
+# Copyright (C) 2018 Free Software Foundation, Inc.
+
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+
+package Automake::LangHandling;
+
+use Automake::Condition qw (TRUE FALSE);
+use Automake::ChannelDefs;
+use Automake::Global;
+use Automake::Language;
+use Automake::Location;
+use Automake::Options;
+use Automake::Requires;
+use Automake::Rule;
+use Automake::SilentRules;
+use Automake::Utils;
+use Automake::Variable;
+use Automake::VarDef;
+use Automake::Wrap qw (makefile_wrap);
+use Exporter;
+use File::Basename;
+
+use vars '@ISA', '@EXPORT';
+
+@ISA = qw (Exporter);
+
+@EXPORT = qw (check_user_variables lang_sub_obj lang_header_rewrite
+ lang_vala_rewrite lang_yacc_rewrite lang_yaccxx_rewrite
+ lang_lex_rewrite lang_lexxx_rewrite lang_java_rewrite
+ lang_vala_finish_target lang_vala_finish
+ lang_vala_target_hook lang_yacc_target_hook
+ lang_lex_target_hook yacc_lex_finish_helper
+ lang_yacc_finish lang_lex_finish resolve_linker
+ saw_extension register_language derive_suffix
+ pretty_print_rule);
+
+# check_user_variables (@LIST)
+# ----------------------------
+# Make sure each variable VAR in @LIST does not exist, suggest using AM_VAR
+# otherwise.
+sub check_user_variables
+{
+ my @dont_override = @_;
+ foreach my $flag (@dont_override)
+ {
+ my $var = var $flag;
+ if ($var)
+ {
+ for my $cond ($var->conditions->conds)
+ {
+ if ($var->rdef ($cond)->owner == VAR_MAKEFILE)
+ {
+ msg_cond_var ('gnu', $cond, $flag,
+ "'$flag' is a user variable, "
+ . "you should not override it;\n"
+ . "use 'AM_$flag' instead");
+ }
+ }
+ }
+ }
+}
+
+################################################################
+#
+# Functions to handle files of each language.
+
+# Each 'lang_X_rewrite($DIRECTORY, $BASE, $EXT)' function follows a
+# simple formula: Return value is LANG_SUBDIR if the resulting object
+# file should be in a subdir if the source file is, LANG_PROCESS if
+# file is to be dealt with, LANG_IGNORE otherwise.
+
+# Much of the actual processing is handled in
+# handle_single_transform. These functions exist so that
+# auxiliary information can be recorded for a later cleanup pass.
+# Note that the calls to these functions are computed, so don't bother
+# searching for their precise names in the source.
+
+# This is just a convenience function that can be used to determine
+# when a subdir object should be used.
+sub lang_sub_obj ()
+{
+ return option 'subdir-objects' ? LANG_SUBDIR : LANG_PROCESS;
+}
+
+# Rewrite a single header file.
+sub lang_header_rewrite
+{
+ # Header files are simply ignored.
+ return LANG_IGNORE;
+}
+
+# Rewrite a single Vala source file.
+sub lang_vala_rewrite
+{
+ my ($directory, $base, $ext) = @_;
+
+ (my $newext = $ext) =~ s/vala$/c/;
+ return (LANG_SUBDIR, $newext);
+}
+
+# Rewrite a single yacc/yacc++ file.
+sub lang_yacc_rewrite
+{
+ my ($directory, $base, $ext) = @_;
+
+ my $r = lang_sub_obj;
+ (my $newext = $ext) =~ tr/y/c/;
+ return ($r, $newext);
+}
+sub lang_yaccxx_rewrite { lang_yacc_rewrite (@_); };
+
+# Rewrite a single lex/lex++ file.
+sub lang_lex_rewrite
+{
+ my ($directory, $base, $ext) = @_;
+
+ my $r = lang_sub_obj;
+ (my $newext = $ext) =~ tr/l/c/;
+ return ($r, $newext);
+}
+sub lang_lexxx_rewrite { lang_lex_rewrite (@_); };
+
+# Rewrite a single Java file.
+sub lang_java_rewrite
+{
+ return LANG_SUBDIR;
+}
+
+# The lang_X_finish functions are called after all source file
+# processing is done. Each should handle defining rules for the
+# language, etc. A finish function is only called if a source file of
+# the appropriate type has been seen.
+
+sub lang_vala_finish_target
+{
+ my ($self, $name) = @_;
+
+ my $derived = canonicalize ($name);
+ my $var = var "${derived}_SOURCES";
+ return unless $var;
+
+ my @vala_sources = grep { /\.(vala|vapi)$/ } ($var->value_as_list_recursive);
+
+ # For automake bug#11229.
+ return unless @vala_sources;
+
+ foreach my $vala_file (@vala_sources)
+ {
+ my $c_file = $vala_file;
+ if ($c_file =~ s/(.*)\.vala$/$1.c/)
+ {
+ $c_file = "\$(srcdir)/$c_file";
+ $output_rules .= "$c_file: \$(srcdir)/${derived}_vala.stamp\n"
+ . "\t\@if test -f \$@; then :; else rm -f \$(srcdir)/${derived}_vala.stamp; fi\n"
+ . "\t\@if test -f \$@; then :; else \\\n"
+ . "\t \$(MAKE) \$(AM_MAKEFLAGS) \$(srcdir)/${derived}_vala.stamp; \\\n"
+ . "\tfi\n";
+ $clean_files{$c_file} = MAINTAINER_CLEAN;
+ }
+ }
+
+ # Add rebuild rules for generated header and vapi files
+ my $flags = var ($derived . '_VALAFLAGS');
+ if ($flags)
+ {
+ my $lastflag = '';
+ foreach my $flag ($flags->value_as_list_recursive)
+ {
+ if (grep (/$lastflag/, ('-H', '-h', '--header', '--internal-header',
+ '--vapi', '--internal-vapi', '--gir')))
+ {
+ my $headerfile = "\$(srcdir)/$flag";
+ $output_rules .= "$headerfile: \$(srcdir)/${derived}_vala.stamp\n"
+ . "\t\@if test -f \$@; then :; else rm -f \$(srcdir)/${derived}_vala.stamp; fi\n"
+ . "\t\@if test -f \$@; then :; else \\\n"
+ . "\t \$(MAKE) \$(AM_MAKEFLAGS) \$(srcdir)/${derived}_vala.stamp; \\\n"
+ . "\tfi\n";
+
+ # valac is not used when building from dist tarballs
+ # distribute the generated files
+ push_dist_common ($headerfile);
+ $clean_files{$headerfile} = MAINTAINER_CLEAN;
+ }
+ $lastflag = $flag;
+ }
+ }
+
+ my $compile = $self->compile;
+
+ # Rewrite each occurrence of 'AM_VALAFLAGS' in the compile
+ # rule into '${derived}_VALAFLAGS' if it exists.
+ my $val = "${derived}_VALAFLAGS";
+ $compile =~ s/\(AM_VALAFLAGS\)/\($val\)/
+ if set_seen ($val);
+
+ # VALAFLAGS is a user variable (per GNU Standards),
+ # it should not be overridden in the Makefile...
+ check_user_variables 'VALAFLAGS';
+
+ my $dirname = dirname ($name);
+
+ # Only generate C code, do not run C compiler
+ $compile .= " -C";
+
+ my $verbose = verbose_flag ('VALAC');
+ my $silent = silent_flag ();
+ my $stampfile = "\$(srcdir)/${derived}_vala.stamp";
+
+ $output_rules .=
+ "\$(srcdir)/${derived}_vala.stamp: @vala_sources\n".
+# Since the C files generated from the vala sources depend on the
+# ${derived}_vala.stamp file, we must ensure its timestamp is older than
+# those of the C files generated by the valac invocation below (this is
+# especially important on systems with sub-second timestamp resolution).
+# Thus we need to create the stamp file *before* invoking valac, and to
+# move it to its final location only after valac has been invoked.
+ "\t${silent}rm -f \$\@ && echo stamp > \$\@-t\n".
+ "\t${verbose}\$(am__cd) \$(srcdir) && $compile @vala_sources\n".
+ "\t${silent}mv -f \$\@-t \$\@\n";
+
+ push_dist_common ($stampfile);
+
+ $clean_files{$stampfile} = MAINTAINER_CLEAN;
+}
+
+# Add output rules to invoke valac and create stamp file as a witness
+# to handle multiple outputs. This function is called after all source
+# file processing is done.
+sub lang_vala_finish ()
+{
+ my ($self) = @_;
+
+ foreach my $prog (keys %known_programs)
+ {
+ lang_vala_finish_target ($self, $prog);
+ }
+
+ while (my ($name) = each %known_libraries)
+ {
+ lang_vala_finish_target ($self, $name);
+ }
+}
+
+# The built .c files should be cleaned only on maintainer-clean
+# as the .c files are distributed. This function is called for each
+# .vala source file.
+sub lang_vala_target_hook
+{
+ my ($self, $aggregate, $output, $input, %transform) = @_;
+
+ $clean_files{$output} = MAINTAINER_CLEAN;
+}
+
+# This is a yacc helper which is called whenever we have decided to
+# compile a yacc file.
+sub lang_yacc_target_hook
+{
+ my ($self, $aggregate, $output, $input, %transform) = @_;
+
+ # If some relevant *YFLAGS variable contains the '-d' flag, we'll
+ # have to to generate special code.
+ my $yflags_contains_minus_d = 0;
+
+ foreach my $pfx ("", "${aggregate}_")
+ {
+ my $yflagsvar = var ("${pfx}YFLAGS");
+ next unless $yflagsvar;
+ # We cannot work reliably with conditionally-defined YFLAGS.
+ if ($yflagsvar->has_conditional_contents)
+ {
+ msg_var ('unsupported', $yflagsvar,
+ "'${pfx}YFLAGS' cannot have conditional contents");
+ }
+ else
+ {
+ $yflags_contains_minus_d = 1
+ if grep (/^-d$/, $yflagsvar->value_as_list_recursive);
+ }
+ }
+
+ if ($yflags_contains_minus_d)
+ {
+ # Found a '-d' that applies to the compilation of this file.
+ # Add a dependency for the generated header file, and arrange
+ # for that file to be included in the distribution.
+
+ # The extension of the output file (e.g., '.c' or '.cxx').
+ # We'll need it to compute the name of the generated header file.
+ (my $output_ext = basename ($output)) =~ s/.*(\.[^.]+)$/$1/;
+
+ # We know that a yacc input should be turned into either a C or
+ # C++ output file. We depend on this fact (here and in yacc.am),
+ # so check that it really holds.
+ my $lang = $languages{$extension_map{$output_ext}};
+ prog_error "invalid output name '$output' for yacc file '$input'"
+ if (!$lang || ($lang->name ne 'c' && $lang->name ne 'cxx'));
+
+ (my $header_ext = $output_ext) =~ s/c/h/g;
+ # Quote $output_ext in the regexp, so that dots in it are taken
+ # as literal dots, not as metacharacters.
+ (my $header = $output) =~ s/\Q$output_ext\E$/$header_ext/;
+
+ foreach my $cond (Automake::Rule::define (${header}, 'internal',
+ RULE_AUTOMAKE, TRUE,
+ INTERNAL))
+ {
+ my $condstr = $cond->subst_string;
+ $output_rules .=
+ "$condstr${header}: $output\n"
+ # Recover from removal of $header
+ . "$condstr\t\@if test ! -f \$@; then rm -f $output; else :; fi\n"
+ . "$condstr\t\@if test ! -f \$@; then \$(MAKE) \$(AM_MAKEFLAGS) $output; else :; fi\n";
+ }
+ # Distribute the generated file, unless its .y source was
+ # listed in a nodist_ variable. (handle_source_transform()
+ # will set DIST_SOURCE.)
+ push_dist_common ($header)
+ if $transform{'DIST_SOURCE'};
+
+ # The GNU rules say that yacc/lex output files should be removed
+ # by maintainer-clean. However, if the files are not distributed,
+ # then we want to remove them with "make clean"; otherwise,
+ # "make distcheck" will fail.
+ $clean_files{$header} = $transform{'DIST_SOURCE'} ? MAINTAINER_CLEAN : CLEAN;
+ }
+ # See the comment above for $HEADER.
+ $clean_files{$output} = $transform{'DIST_SOURCE'} ? MAINTAINER_CLEAN : CLEAN;
+}
+
+# This is a lex helper which is called whenever we have decided to
+# compile a lex file.
+sub lang_lex_target_hook
+{
+ my ($self, $aggregate, $output, $input, %transform) = @_;
+ # The GNU rules say that yacc/lex output files should be removed
+ # by maintainer-clean. However, if the files are not distributed,
+ # then we want to remove them with "make clean"; otherwise,
+ # "make distcheck" will fail.
+ $clean_files{$output} = $transform{'DIST_SOURCE'} ? MAINTAINER_CLEAN : CLEAN;
+}
+
+# This is a helper for both lex and yacc.
+sub yacc_lex_finish_helper ()
+{
+ return if defined $language_scratch{'lex-yacc-done'};
+ $language_scratch{'lex-yacc-done'} = 1;
+
+ # FIXME: for now, no line number.
+ require_conf_file ($configure_ac, FOREIGN, 'ylwrap');
+ define_variable ('YLWRAP', "$am_config_aux_dir/ylwrap", INTERNAL);
+}
+
+sub lang_yacc_finish ()
+{
+ return if defined $language_scratch{'yacc-done'};
+ $language_scratch{'yacc-done'} = 1;
+
+ reject_var 'YACCFLAGS', "'YACCFLAGS' obsolete; use 'YFLAGS' instead";
+
+ yacc_lex_finish_helper;
+}
+
+
+sub lang_lex_finish ()
+{
+ return if defined $language_scratch{'lex-done'};
+ $language_scratch{'lex-done'} = 1;
+
+ yacc_lex_finish_helper;
+}
+
+
+# Given a hash table of linker names, pick the name that has the most
+# precedence. This is lame, but something has to have global
+# knowledge in order to eliminate the conflict. Add more linkers as
+# required.
+sub resolve_linker
+{
+ my (%linkers) = @_;
+
+ foreach my $l (qw(GCJLINK OBJCXXLINK CXXLINK F77LINK FCLINK OBJCLINK UPCLINK))
+ {
+ return $l if defined $linkers{$l};
+ }
+ return 'LINK';
+}
+
+# Called to indicate that an extension was used.
+sub saw_extension
+{
+ my ($ext) = @_;
+ $extension_seen{$ext} = 1;
+}
+
+# register_language (%ATTRIBUTE)
+# ------------------------------
+# Register a single language.
+# Each %ATTRIBUTE is of the form ATTRIBUTE => VALUE.
+sub register_language
+{
+ my (%option) = @_;
+
+ # Set the defaults.
+ $option{'autodep'} = 'no'
+ unless defined $option{'autodep'};
+ $option{'linker'} = ''
+ unless defined $option{'linker'};
+ $option{'flags'} = []
+ unless defined $option{'flags'};
+ $option{'output_extensions'} = sub { return ( '.$(OBJEXT)', '.lo' ) }
+ unless defined $option{'output_extensions'};
+ $option{'nodist_specific'} = 0
+ unless defined $option{'nodist_specific'};
+
+ my $lang = new Automake::Language (%option);
+
+ # Fill indexes.
+ $extension_map{$_} = $lang->name foreach @{$lang->extensions};
+ $languages{$lang->name} = $lang;
+ my $link = $lang->linker;
+ if ($link)
+ {
+ if (exists $link_languages{$link})
+ {
+ prog_error ("'$link' has different definitions in "
+ . $lang->name . " and " . $link_languages{$link}->name)
+ if $lang->link ne $link_languages{$link}->link;
+ }
+ else
+ {
+ $link_languages{$link} = $lang;
+ }
+ }
+
+ # Update the pattern of known extensions.
+ accept_extensions (@{$lang->extensions});
+
+ # Update the suffix rules map.
+ foreach my $suffix (@{$lang->extensions})
+ {
+ foreach my $dest ($lang->output_extensions->($suffix))
+ {
+ register_suffix_rule (INTERNAL, $suffix, $dest);
+ }
+ }
+}
+
+# derive_suffix ($EXT, $OBJ)
+# --------------------------
+# This function is used to find a path from a user-specified suffix $EXT
+# to $OBJ or to some other suffix we recognize internally, e.g. 'cc'.
+sub derive_suffix
+{
+ my ($source_ext, $obj) = @_;
+
+ while (!$extension_map{$source_ext} && $source_ext ne $obj)
+ {
+ my $new_source_ext = next_in_suffix_chain ($source_ext, $obj);
+ last if not defined $new_source_ext;
+ $source_ext = $new_source_ext;
+ }
+
+ return $source_ext;
+}
+
+
+# Pretty-print something and append to '$output_rules'.
+sub pretty_print_rule
+{
+ $output_rules .= makefile_wrap (shift, shift, @_);
+}
+
+1;
diff --git a/lib/Automake/Requires.pm b/lib/Automake/Requires.pm
new file mode 100644
index 000000000..dbb1c10ed
--- /dev/null
+++ b/lib/Automake/Requires.pm
@@ -0,0 +1,424 @@
+package Automake::Requires;
+
+use Automake::ChannelDefs;
+use Automake::Channels;
+use Automake::Condition qw (TRUE FALSE);
+use Automake::Config;
+use Automake::FileUtils;
+use Automake::Global;
+use Automake::Location;
+use Automake::Options;
+use Automake::Rule;
+use Automake::Utils;
+use Automake::Variable;
+use File::Basename;
+
+use Exporter;
+
+use vars '@ISA', '@EXPORT';
+
+@ISA = qw (Exporter);
+
+@EXPORT = qw (push_required_file required_file_check_or_copy
+ require_file_internal require_file require_file_with_macro
+ require_libsource_with_macro queue_required_file_check_or_copy
+ require_queued_file_check_or_copy require_conf_file
+ require_conf_file_with_macro require_build_directory
+ require_build_directory_maybe);
+
+# push_required_file ($DIR, $FILE, $FULLFILE)
+# -------------------------------------------
+# Push the given file onto DIST_COMMON.
+sub push_required_file
+{
+ my ($dir, $file, $fullfile) = @_;
+
+ # If the file to be distributed is in the same directory of the
+ # currently processed Makefile.am, then we want to distribute it
+ # from this same Makefile.am.
+ if ($dir eq $relative_dir)
+ {
+ push_dist_common ($file);
+ }
+ # This is needed to allow a construct in a non-top-level Makefile.am
+ # to require a file in the build-aux directory (see at least the test
+ # script 'test-driver-is-distributed.sh'). This is related to the
+ # automake bug#9546. Note that the use of $config_aux_dir instead
+ # of $am_config_aux_dir here is deliberate and necessary.
+ elsif ($dir eq $config_aux_dir)
+ {
+ push_dist_common ("$am_config_aux_dir/$file");
+ }
+ # FIXME: another spacial case, for AC_LIBOBJ/AC_LIBSOURCE support.
+ # We probably need some refactoring of this function and its callers,
+ # to have a more explicit and systematic handling of all the special
+ # cases; but, since there are only two of them, this is low-priority
+ # ATM.
+ elsif ($config_libobj_dir && $dir eq $config_libobj_dir)
+ {
+ # Avoid unsightly '/.'s.
+ my $am_config_libobj_dir =
+ '$(top_srcdir)' .
+ ($config_libobj_dir eq '.' ? "" : "/$config_libobj_dir");
+ $am_config_libobj_dir =~ s|/*$||;
+ push_dist_common ("$am_config_libobj_dir/$file");
+ }
+ elsif ($relative_dir eq '.' && ! is_make_dir ($dir))
+ {
+ # If we are doing the topmost directory, and the file is in a
+ # subdir which does not have a Makefile, then we distribute it
+ # here.
+
+ # If a required file is above the source tree, it is important
+ # to prefix it with '$(srcdir)' so that no VPATH search is
+ # performed. Otherwise problems occur with Make implementations
+ # that rewrite and simplify rules whose dependencies are found in a
+ # VPATH location. Here is an example with OSF1/Tru64 Make.
+ #
+ # % cat Makefile
+ # VPATH = sub
+ # distdir: ../a
+ # echo ../a
+ # % ls
+ # Makefile a
+ # % make
+ # echo a
+ # a
+ #
+ # Dependency '../a' was found in 'sub/../a', but this make
+ # implementation simplified it as 'a'. (Note that the sub/
+ # directory does not even exist.)
+ #
+ # This kind of VPATH rewriting seems hard to cancel. The
+ # distdir.am hack against VPATH rewriting works only when no
+ # simplification is done, i.e., for dependencies which are in
+ # subdirectories, not in enclosing directories. Hence, in
+ # the latter case we use a full path to make sure no VPATH
+ # search occurs.
+ $fullfile = '$(srcdir)/' . $fullfile
+ if $dir =~ m,^\.\.(?:$|/),;
+
+ push_dist_common ($fullfile);
+ }
+ else
+ {
+ prog_error "a Makefile in relative directory $relative_dir " .
+ "can't add files in directory $dir to DIST_COMMON";
+ }
+}
+
+
+# If a file name appears as a key in this hash, then it has already
+# been checked for. This allows us not to report the same error more
+# than once.
+my %required_file_not_found = ();
+
+# required_file_check_or_copy ($WHERE, $DIRECTORY, $FILE)
+# -------------------------------------------------------
+# Verify that the file must exist in $DIRECTORY, or install it.
+sub required_file_check_or_copy
+{
+ my ($where, $dir, $file) = @_;
+
+ my $fullfile = "$dir/$file";
+ my $found_it = 0;
+ my $dangling_sym = 0;
+
+ if (-l $fullfile && ! -f $fullfile)
+ {
+ $dangling_sym = 1;
+ }
+ elsif (dir_has_case_matching_file ($dir, $file))
+ {
+ $found_it = 1;
+ }
+
+ # '--force-missing' only has an effect if '--add-missing' is
+ # specified.
+ return
+ if $found_it && (! $add_missing || ! $force_missing);
+
+ # If we've already looked for it, we're done. You might wonder why we
+ # don't do this before searching for the file. If we do that, then
+ # something like AC_OUTPUT([subdir/foo foo]) will fail to put 'foo.in'
+ # into $(DIST_COMMON).
+ if (! $found_it)
+ {
+ return if defined $required_file_not_found{$fullfile};
+ $required_file_not_found{$fullfile} = 1;
+ }
+ if ($dangling_sym && $add_missing)
+ {
+ unlink ($fullfile);
+ }
+
+ my $trailer = '';
+ my $trailer2 = '';
+ my $suppress = 0;
+
+ # Only install missing files according to our desired
+ # strictness level.
+ my $message = "required file '$fullfile' not found";
+ if ($add_missing)
+ {
+ if (-f "$libdir/$file")
+ {
+ $suppress = 1;
+
+ # Install the missing file. Symlink if we
+ # can, copy if we must. Note: delete the file
+ # first, in case it is a dangling symlink.
+ $message = "installing '$fullfile'";
+
+ # The license file should not be volatile.
+ if ($file eq "COPYING")
+ {
+ $message .= " using GNU General Public License v3 file";
+ $trailer2 = "\n Consider adding the COPYING file"
+ . " to the version control system"
+ . "\n for your code, to avoid questions"
+ . " about which license your project uses";
+ }
+
+ # Windows Perl will hang if we try to delete a
+ # file that doesn't exist.
+ unlink ($fullfile) if -f $fullfile;
+ if ($symlink_exists && ! $copy_missing)
+ {
+ if (! symlink ("$libdir/$file", $fullfile)
+ || ! -e $fullfile)
+ {
+ $suppress = 0;
+ $trailer = "; error while making link: $!";
+ }
+ }
+ elsif (system ('cp', "$libdir/$file", $fullfile))
+ {
+ $suppress = 0;
+ $trailer = "\n error while copying";
+ }
+ set_dir_cache_file ($dir, $file);
+ }
+ }
+ else
+ {
+ $trailer = "\n 'automake --add-missing' can install '$file'"
+ if -f "$libdir/$file";
+ }
+
+ # If --force-missing was specified, and we have
+ # actually found the file, then do nothing.
+ return
+ if $found_it && $force_missing;
+
+ # If we couldn't install the file, but it is a target in
+ # the Makefile, don't print anything. This allows files
+ # like README, AUTHORS, or THANKS to be generated.
+ return
+ if !$suppress && rule $file;
+
+ msg ($suppress ? 'note' : 'error', $where, "$message$trailer$trailer2");
+}
+
+
+# require_file_internal ($WHERE, $MYSTRICT, $DIRECTORY, $QUEUE, @FILES)
+# ---------------------------------------------------------------------
+# Verify that the file must exist in $DIRECTORY, or install it.
+# $MYSTRICT is the strictness level at which this file becomes required.
+# Worker threads may queue up the action to be serialized by the master,
+# if $QUEUE is true
+sub require_file_internal
+{
+ my ($where, $mystrict, $dir, $queue, @files) = @_;
+
+ return
+ unless $strictness >= $mystrict;
+
+ foreach my $file (@files)
+ {
+ push_required_file ($dir, $file, "$dir/$file");
+ if ($queue)
+ {
+ queue_required_file_check_or_copy ($required_conf_file_queue,
+ QUEUE_CONF_FILE, $relative_dir,
+ $where, $mystrict, @files);
+ }
+ else
+ {
+ required_file_check_or_copy ($where, $dir, $file);
+ }
+ }
+}
+
+# require_file ($WHERE, $MYSTRICT, @FILES)
+# ----------------------------------------
+sub require_file
+{
+ my ($where, $mystrict, @files) = @_;
+ require_file_internal ($where, $mystrict, $relative_dir, 0, @files);
+}
+
+# require_file_with_macro ($COND, $MACRO, $MYSTRICT, @FILES)
+# ----------------------------------------------------------
+sub require_file_with_macro
+{
+ my ($cond, $macro, $mystrict, @files) = @_;
+ $macro = rvar ($macro) unless ref $macro;
+ require_file ($macro->rdef ($cond)->location, $mystrict, @files);
+}
+
+# require_libsource_with_macro ($COND, $MACRO, $MYSTRICT, @FILES)
+# ---------------------------------------------------------------
+# Require an AC_LIBSOURCEd file. If AC_CONFIG_LIBOBJ_DIR was called, it
+# must be in that directory. Otherwise expect it in the current directory.
+sub require_libsource_with_macro
+{
+ my ($cond, $macro, $mystrict, @files) = @_;
+ $macro = rvar ($macro) unless ref $macro;
+ if ($config_libobj_dir)
+ {
+ require_file_internal ($macro->rdef ($cond)->location, $mystrict,
+ $config_libobj_dir, 0, @files);
+ }
+ else
+ {
+ require_file ($macro->rdef ($cond)->location, $mystrict, @files);
+ }
+}
+
+# queue_required_file_check_or_copy ($QUEUE, $KEY, $DIR, $WHERE,
+# $MYSTRICT, @FILES)
+# --------------------------------------------------------------
+sub queue_required_file_check_or_copy
+{
+ my ($queue, $key, $dir, $where, $mystrict, @files) = @_;
+ my @serial_loc;
+ if (ref $where)
+ {
+ @serial_loc = (QUEUE_LOCATION, $where->serialize ());
+ }
+ else
+ {
+ @serial_loc = (QUEUE_STRING, $where);
+ }
+ $queue->enqueue ($key, $dir, @serial_loc, $mystrict, 0 + @files, @files);
+}
+
+# require_queued_file_check_or_copy ($QUEUE)
+# ------------------------------------------
+sub require_queued_file_check_or_copy
+{
+ my ($queue) = @_;
+ my $where;
+ my $dir = $queue->dequeue ();
+ my $loc_key = $queue->dequeue ();
+ if ($loc_key eq QUEUE_LOCATION)
+ {
+ $where = Automake::Location::deserialize ($queue);
+ }
+ elsif ($loc_key eq QUEUE_STRING)
+ {
+ $where = $queue->dequeue ();
+ }
+ else
+ {
+ prog_error "unexpected key $loc_key";
+ }
+ my $mystrict = $queue->dequeue ();
+ my $nfiles = $queue->dequeue ();
+ my @files;
+ push @files, $queue->dequeue ()
+ foreach (1 .. $nfiles);
+ return
+ unless $strictness >= $mystrict;
+ foreach my $file (@files)
+ {
+ required_file_check_or_copy ($where, $config_aux_dir, $file);
+ }
+}
+
+# require_conf_file ($WHERE, $MYSTRICT, @FILES)
+# ---------------------------------------------
+# Looks in configuration path, as specified by AC_CONFIG_AUX_DIR.
+sub require_conf_file
+{
+ my ($where, $mystrict, @files) = @_;
+ my $queue = defined $required_conf_file_queue ? 1 : 0;
+ require_file_internal ($where, $mystrict, $config_aux_dir,
+ $queue, @files);
+}
+
+
+# require_conf_file_with_macro ($COND, $MACRO, $MYSTRICT, @FILES)
+# ---------------------------------------------------------------
+sub require_conf_file_with_macro
+{
+ my ($cond, $macro, $mystrict, @files) = @_;
+ require_conf_file (rvar ($macro)->rdef ($cond)->location,
+ $mystrict, @files);
+}
+
+################################################################
+
+# require_build_directory ($DIRECTORY)
+# ------------------------------------
+# Emit rules to create $DIRECTORY if needed, and return
+# the file that any target requiring this directory should be made
+# dependent upon.
+# We don't want to emit the rule twice, and want to reuse it
+# for directories with equivalent names (e.g., 'foo/bar' and './foo//bar').
+sub require_build_directory
+{
+ my $directory = shift;
+
+ return $directory_map{$directory} if exists $directory_map{$directory};
+
+ my $cdir = File::Spec->canonpath ($directory);
+
+ if (exists $directory_map{$cdir})
+ {
+ my $stamp = $directory_map{$cdir};
+ $directory_map{$directory} = $stamp;
+ return $stamp;
+ }
+
+ my $dirstamp = "$cdir/\$(am__dirstamp)";
+
+ $directory_map{$directory} = $dirstamp;
+ $directory_map{$cdir} = $dirstamp;
+
+ # Set a variable for the dirstamp basename.
+ define_pretty_variable ('am__dirstamp', TRUE, INTERNAL,
+ '$(am__leading_dot)dirstamp');
+
+ # Directory must be removed by 'make distclean'.
+ $clean_files{$dirstamp} = DIST_CLEAN;
+
+ $output_rules .= ("$dirstamp:\n"
+ . "\t\@\$(MKDIR_P) $directory\n"
+ . "\t\@: > $dirstamp\n");
+
+ return $dirstamp;
+}
+
+# require_build_directory_maybe ($FILE)
+# -------------------------------------
+# If $FILE lies in a subdirectory, emit a rule to create this
+# directory and return the file that $FILE should be made
+# dependent upon. Otherwise, just return the empty string.
+sub require_build_directory_maybe
+{
+ my $file = shift;
+ my $directory = dirname ($file);
+
+ if ($directory ne '.')
+ {
+ return require_build_directory ($directory);
+ }
+ else
+ {
+ return '';
+ }
+}
+
+1;
diff --git a/lib/Automake/SilentRules.pm b/lib/Automake/SilentRules.pm
new file mode 100644
index 000000000..70729160d
--- /dev/null
+++ b/lib/Automake/SilentRules.pm
@@ -0,0 +1,73 @@
+package Automake::SilentRules;
+
+use Automake::Utils;
+use Automake::Variable;
+use Exporter;
+
+use vars '@ISA', '@EXPORT';
+
+@ISA = qw (Exporter);
+
+@EXPORT = qw (verbose_flag verbose_nodep_flag silent_flag
+ define_verbose_texinfo define_verbose_libtool
+ handle_silent);
+
+# Silent rules handling functions.
+
+# verbose_flag (NAME)
+# -------------------
+# Contents of '%VERBOSE%' variable to expand before rule command.
+sub verbose_flag
+{
+ my ($name) = @_;
+ return '$(' . verbose_var ($name) . ')';
+}
+
+sub verbose_nodep_flag
+{
+ my ($name) = @_;
+ return '$(' . verbose_var ($name) . subst ('am__nodep') . ')';
+}
+
+# silent_flag
+# -----------
+# Contents of %SILENT%: variable to expand to '@' when silent.
+sub silent_flag ()
+{
+ return verbose_flag ('at');
+}
+
+# Engage the needed silent rules machinery for assorted texinfo commands.
+sub define_verbose_texinfo ()
+{
+ my @tagvars = ('DVIPS', 'MAKEINFO', 'INFOHTML', 'TEXI2DVI', 'TEXI2PDF');
+ foreach my $tag (@tagvars)
+ {
+ define_verbose_tagvar($tag);
+ }
+ define_verbose_var('texinfo', '-q');
+ define_verbose_var('texidevnull', '> /dev/null');
+}
+
+# Engage the needed silent rules machinery for 'libtool --silent'.
+sub define_verbose_libtool ()
+{
+ define_verbose_var ('lt', '--silent');
+ return verbose_flag ('lt');
+}
+
+sub handle_silent ()
+{
+ # Define "$(AM_V_P)", expanding to a shell conditional that can be
+ # used in make recipes to determine whether we are being run in
+ # silent mode or not. The choice of the name derives from the LISP
+ # convention of appending the letter 'P' to denote a predicate (see
+ # also "the '-P' convention" in the Jargon File); we do so for lack
+ # of a better convention.
+ define_verbose_var ('P', 'false', ':');
+ # *Always* provide the user with '$(AM_V_GEN)', unconditionally.
+ define_verbose_tagvar ('GEN');
+ define_verbose_var ('at', '@');
+}
+
+1;
diff --git a/lib/Automake/local.mk b/lib/Automake/local.mk
index bdc7aa066..2a9c43faf 100644
--- a/lib/Automake/local.mk
+++ b/lib/Automake/local.mk
@@ -36,11 +36,14 @@ dist_perllib_DATA = \
%D%/Getopt.pm \
%D%/Item.pm \
%D%/ItemDef.pm \
+ %D%/LangHandling.pm \
%D%/Language.pm \
%D%/Location.pm \
%D%/Options.pm \
+ %D%/Requires.pm \
%D%/Rule.pm \
%D%/RuleDef.pm \
+ %D%/SilentRules.pm \
%D%/Utils.pm \
%D%/VarAppend.pm \
%D%/Variable.pm \