summaryrefslogtreecommitdiff
path: root/lib/Automake/Requires.pm
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 /lib/Automake/Requires.pm
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.
Diffstat (limited to 'lib/Automake/Requires.pm')
-rw-r--r--lib/Automake/Requires.pm424
1 files changed, 424 insertions, 0 deletions
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;