From: Alexandre Duret-Lutz Date: Tue, 12 Aug 2003 17:52:07 +0000 (+0000) Subject: * lib/Automake/Item.pm, lib/Automake/ItemDef.pm: New files. X-Git-Tag: Release-1-7b~78 X-Git-Url: https://sourceware.org/git/?a=commitdiff_plain;h=0bb62840e1c95b7f83073fae79f21bda9a375566;p=automake.git * lib/Automake/Item.pm, lib/Automake/ItemDef.pm: New files. * lib/Automake/Rule.pm, lib/Automake/RuleDef.pm: New files. * lib/Automake/Makefile.am (dist_perllib_DATA): Add them. * lib/Automake/VarDef.pm: Make this a subclass of Automake::ItemDef. (new): Adjust to call Automake::ItemDef::new. (comment, location, owner): Delete. Now inherited from ItemDef. * lib/Automake/Variable.pm: Make this a subclass of Automake::Item. (_new): Adjust to call Automake::Item::new. (name, def, rdef, _set, conditions, not_always_defined_in_cond): Delete. How inherited from Item, where `_set' is called `set'. * automake.in (SUFFIX_RULE_PATTERN): Delete. Now in Automake::Rule. (suffix_rules_default): Delete. Now Automake::Rule::_suffix_rules_default (suffixes): Delete. Now Automake::Rule::suffixes. (TARGET_AUTOMAKE, TARGET_USER): Delete. Now Automake::RuleDef::RULE_AUTOMAKE and Automake::RuleDef::RULE_USER. (%targets, %target_source, %target_name, %target_owner): Delete, replaced by the Rule and RuleDef classes. (dependencies, depend, actions): Delete. Now in Automake::Rule. (suffix_rules, register_suffix_rule): Likewise. (KNOWN_EXTENSIONS_PATTERN, accept_extensions): Likewise. (known_extensions_list): Delete. Now Automake::Rule::_known_extensions_list. (target_conditions): Delete. Now inherited by Automake::Rule from Automake::Item::conditions. (rule_define): Delete. Now Automake::Rule::define. Adjust all callers. (target_defined): Delete. Now Automake::Rule::rule. Adjust all callers. (initialize_per_input): Adjust to call Automake::Rule::reset. (err_target, err_cond_target, msg_cond_target, msg_target, reject_target): Delete. Now defined in Automake::Rule as err_rule, err_cond_rule, msg_cond_rule, msg_rule and reject_target. Adjust all callers. (handle_languages): Call suffix_rules_count. * tests/location.test: Adjust expected diagnostics. We now display $(EXEEXT) accurately. --- diff --git a/ChangeLog b/ChangeLog index d98843cb..216c2cec 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,43 @@ +2003-08-12 Alexandre Duret-Lutz + + * lib/Automake/Item.pm, lib/Automake/ItemDef.pm: New files. + * lib/Automake/Rule.pm, lib/Automake/RuleDef.pm: New files. + * lib/Automake/Makefile.am (dist_perllib_DATA): Add them. + * lib/Automake/VarDef.pm: Make this a subclass of Automake::ItemDef. + (new): Adjust to call Automake::ItemDef::new. + (comment, location, owner): Delete. Now inherited from ItemDef. + * lib/Automake/Variable.pm: Make this a subclass of Automake::Item. + (_new): Adjust to call Automake::Item::new. + (name, def, rdef, _set, conditions, not_always_defined_in_cond): + Delete. How inherited from Item, where `_set' is called `set'. + * automake.in (SUFFIX_RULE_PATTERN): Delete. Now in Automake::Rule. + (suffix_rules_default): Delete. Now + Automake::Rule::_suffix_rules_default + (suffixes): Delete. Now Automake::Rule::suffixes. + (TARGET_AUTOMAKE, TARGET_USER): Delete. Now + Automake::RuleDef::RULE_AUTOMAKE and Automake::RuleDef::RULE_USER. + (%targets, %target_source, %target_name, %target_owner): Delete, + replaced by the Rule and RuleDef classes. + (dependencies, depend, actions): Delete. Now in Automake::Rule. + (suffix_rules, register_suffix_rule): Likewise. + (KNOWN_EXTENSIONS_PATTERN, accept_extensions): Likewise. + (known_extensions_list): Delete. Now + Automake::Rule::_known_extensions_list. + (target_conditions): Delete. Now inherited by Automake::Rule + from Automake::Item::conditions. + (rule_define): Delete. Now Automake::Rule::define. Adjust all + callers. + (target_defined): Delete. Now Automake::Rule::rule. Adjust all + callers. + (initialize_per_input): Adjust to call Automake::Rule::reset. + (err_target, err_cond_target, msg_cond_target, msg_target, + reject_target): Delete. Now defined in Automake::Rule as + err_rule, err_cond_rule, msg_cond_rule, msg_rule and reject_target. + Adjust all callers. + (handle_languages): Call suffix_rules_count. + * tests/location.test: Adjust expected diagnostics. We now display + $(EXEEXT) accurately. + 2003-08-10 Alexandre Duret-Lutz Revert the fix for PR automake/291: diff --git a/automake.in b/automake.in index a3eb8d72..df61f28d 100755 --- a/automake.in +++ b/automake.in @@ -135,9 +135,10 @@ use Automake::Options; use Automake::Version; use Automake::Variable; use Automake::VarDef; +use Automake::Rule; +use Automake::RuleDef; use Automake::Wrap 'makefile_wrap'; use File::Basename; -use Tie::RefHash; use Carp; ## ----------- ## @@ -165,8 +166,6 @@ my $TARGET_PATTERN='[$a-zA-Z_.@%][-.a-zA-Z0-9_(){}/$+@%]*'; my $RULE_PATTERN = "^($TARGET_PATTERN(?:(?:\\\\\n|\\s)+$TARGET_PATTERN)*) *:([^=].*|)\$"; -my $SUFFIX_RULE_PATTERN = - '^(\.[a-zA-Z0-9_(){}$+@]+)(\.[a-zA-Z0-9_(){}$+@]+)' . "\$"; # Only recognize leading spaces, not leading tabs. If we recognize # leading tabs here then we need to make the reader smarter, because # otherwise it will think rules like `foo=bar; \' are errors. @@ -412,10 +411,6 @@ my %required_targets = # should distribute depcomp -- has been generated.) my $automake_needs_to_reprocess_all_files = 0; -# Same as $suffix_rules (declared below), but records only the -# default rules supplied by the languages Automake supports. -my $suffix_rules_default; - # If a file name appears as a key in this hash, then it has already # been checked for. This variable is local to the "require file" # functions. @@ -447,30 +442,6 @@ my $output_trailer; my $output_all; my $output_header; -# Suffixes found during a run. -my @suffixes; - -# This holds the names which are targets. These also appear in -# %contents. $targets{TARGET}{COND} is the location of the definition -# of TARGET for condition COND. TARGETs should not include -# a trailing $(EXEEXT), we record this in %target_name. -my %targets; tie %targets, 'Tie::RefHash::Nestable'; - -# $target_source{TARGET}{COND} is the filename where TARGET -# were defined for condition COND. Note this must be a -# filename, *without* any line number. -my %target_source; tie %target_source, 'Tie::RefHash::Nestable'; - -# $target_name{TARGET}{COND} is the real name of TARGET (in condition COND). -# The real name is often TARGET or TARGET$(EXEEXT), and TARGET never -# contain $(EXEEXT) -my %target_name; tie %target_name, 'Tie::RefHash::Nestable'; - -# $target_owner{TARGET}{COND} the owner of TARGET in condition COND. -my %target_owner; tie %target_owner, 'Tie::RefHash::Nestable'; -use constant TARGET_AUTOMAKE => 0; # Target defined by Automake. -use constant TARGET_USER => 1; # Target defined in the user's Makefile.am. - # This is the conditional stack, updated on if/else/endif, and # used to build Condition objects. my @cond_stack; @@ -488,27 +459,6 @@ my @all; my @check; my @check_tests; -# Holds the dependencies of targets which dependencies are factored. -# Typically, `.PHONY' will appear in plenty of *.am files, but must -# be output once. Arguably all pure dependencies could be subject -# to this factorization, but it is not unpleasant to have paragraphs -# in Makefile: keeping related stuff altogether. -my %dependencies; - -# &depend ($CATEGORY, @DEPENDENDEES) -# ---------------------------------- -# The target $CATEGORY depends on @DEPENDENDEES. -sub depend ($@) -{ - my ($category, @dependendees) = @_; - push (@{$dependencies{$category}}, @dependendees); -} - - -# Holds the factored actions. Tied to %DEPENDENCIES, i.e., filled -# only when keys exists in %DEPENDENCIES. -my %actions; - # Keys in this hash table are files to delete. The associated # value tells when this should happen (MOSTLY_CLEAN, DIST_CLEAN, etc.) my %clean_files; @@ -556,27 +506,6 @@ my @dist_targets; # trailing `/'. my %de_ansi_files; -# This maps the source extension for all suffix rule seen to -# a \hash whose keys are the possible output extensions. -# -# Note that this is transitively closed by construction: -# if we have -# exists $suffix_rules{$ext1}{$ext2} -# && exists $suffix_rules{$ext2}{$ext3} -# then we also have -# exists $suffix_rules{$ext1}{$ext3} -# -# So it's easy to check whether '.foo' can be transformed to '.$(OBJEXT)' -# by checking whether $suffix_rules{'.foo'}{'.$(OBJEXT)'} exist. This -# will work even if transforming '.foo' to '.$(OBJEXT)' involves a chain -# of several suffix rules. -# -# The value of `$suffix_rules{$ext1}{$ext2}' is the a pair -# `[ $next_sfx, $dist ]' where `$next_sfx' is target suffix -# for the next rule to use to reach '$ext2', and `$dist' the -# distance to `$ext2'. -my $suffix_rules; - # This is the name of the redirect `all' target to use. my $all_target; @@ -609,32 +538,14 @@ my $get_object_extension_was_run; ################################################################ -# Pattern that matches all know input extensions (i.e. extensions used -# by the languages supported by Automake). Using this pattern -# (instead of `\..*$') to match extensions allows Automake to support -# dot-less extensions. -my $KNOWN_EXTENSIONS_PATTERN = ""; -my @known_extensions_list = (); - -# accept_extensions (@EXTS) -# ------------------------- -# Update $KNOWN_EXTENSIONS_PATTERN to recognize the extensions -# listed @EXTS. Extensions should contain a dot if needed. -sub accept_extensions (@) -{ - push @known_extensions_list, @_; - $KNOWN_EXTENSIONS_PATTERN = - '(?:' . join ('|', map (quotemeta, @known_extensions_list)) . ')'; -} - # var_SUFFIXES_trigger ($TYPE, $VALUE) # ------------------------------------ -# This is called automagically by macro_define() when SUFFIXES +# This is called by Automake::Variable::define() when SUFFIXES # is defined ($TYPE eq '') or appended ($TYPE eq '+'). # The work here needs to be performed as a side-effect of the # macro_define() call because SUFFIXES definitions impact -# on $KNOWN_EXTENSIONS_PATTERN, and $KNOWN_EXTENSIONS_PATTERN -# are used when parsing the input am file. +# on $KNOWN_EXTENSIONS_PATTERN which is used used when parsing +# the input am file. sub var_SUFFIXES_trigger ($$) { my ($type, $value) = @_; @@ -671,15 +582,9 @@ sub initialize_per_input () $output_all = ''; $output_header = ''; - @suffixes = (); - Automake::Options::reset; Automake::Variable::reset; - - %targets = (); - %target_source = (); - %target_name = (); - %target_owner = (); + Automake::Rule::reset; @cond_stack = (); @@ -691,52 +596,6 @@ sub initialize_per_input () @check = (); @check_tests = (); - %dependencies = - ( - # Texinfoing. - 'dvi' => [], - 'dvi-am' => [], - 'pdf' => [], - 'pdf-am' => [], - 'ps' => [], - 'ps-am' => [], - 'info' => [], - 'info-am' => [], - 'html' => [], - 'html-am' => [], - - # Installing/uninstalling. - 'install-data-am' => [], - 'install-exec-am' => [], - 'uninstall-am' => [], - - 'install-man' => [], - 'uninstall-man' => [], - - 'install-info' => [], - 'install-info-am' => [], - 'uninstall-info' => [], - - 'installcheck-am' => [], - - # Cleaning. - 'clean-am' => [], - 'mostlyclean-am' => [], - 'maintainer-clean-am' => [], - 'distclean-am' => [], - 'clean' => [], - 'mostlyclean' => [], - 'maintainer-clean' => [], - 'distclean' => [], - - # Tarballing. - 'dist-all' => [], - - # Phoning. - '.PHONY' => [] - ); - %actions = (); - %clean_files = (); @sources = (); @@ -753,18 +612,6 @@ sub initialize_per_input () %de_ansi_files = (); - - # The first time we initialize the variables, - # we save the value of $suffix_rules. - if (defined $suffix_rules_default) - { - $suffix_rules = $suffix_rules_default; - } - else - { - $suffix_rules_default = $suffix_rules; - } - $all_target = ''; %extension_seen = (); @@ -1002,22 +849,6 @@ register_language ('name' => 'java', # Error reporting functions. -# err_target ($TARGETNAME, $MESSAGE, [%OPTIONS]) -# ---------------------------------------------- -# Uncategorized errors about targets. -sub err_target ($$;%) -{ - msg_target ('error', @_); -} - -# err_cond_target ($COND, $TARGETNAME, $MESSAGE, [%OPTIONS]) -# ---------------------------------------------------------- -# Uncategorized errors about conditional targets. -sub err_cond_target ($$$;%) -{ - msg_cond_target ('error', @_); -} - # err_am ($MESSAGE, [%OPTIONS]) # ----------------------------- # Uncategorized errors about the current Makefile.am. @@ -1034,26 +865,6 @@ sub err_ac ($;%) msg_ac ('error', @_); } -# msg_cond_target ($CHANNEL, $COND, $TARGETNAME, $MESSAGE, [%OPTIONS]) -# -------------------------------------------------------------------- -# Messages about conditional targets. -sub msg_cond_target ($$$$;%) -{ - my ($channel, $cond, $target, $msg, %opts) = @_; - msg $channel, $targets{$target}{$cond}, $msg, %opts; -} - -# msg_target ($CHANNEL, $TARGETNAME, $MESSAGE, [%OPTIONS]) -# -------------------------------------------------------- -# Messages about targets. -sub msg_target ($$$;%) -{ - my ($channel, $target, $msg, %opts) = @_; - # Don't know which condition is concerned. Pick any. - my $cond = target_conditions ($target)->one_cond; - msg_cond_target ($channel, $cond, $target, $msg, %opts); -} - # msg_am ($CHANNEL, $MESSAGE, [%OPTIONS]) # --------------------------------------- # Messages about about the current Makefile.am. @@ -1072,20 +883,6 @@ sub msg_ac ($$;%) msg $channel, $configure_ac, $msg, %opts; } -# $BOOL -# reject_target ($VAR, $ERROR_MSG) -# -------------------------------- -sub reject_target ($$) -{ - my ($target, $msg) = @_; - if (target_defined ($target)) - { - err_target $target, $msg; - return 1; - } - return 0; -} - ################################################################ # subst ($TEXT) @@ -1515,8 +1312,7 @@ sub handle_languages # suffix rule was learned), don't bother with the C stuff. But if # anything else creeps in, then use it. $needs_c = 1 - if $need_link || ((scalar keys %$suffix_rules) - - (scalar keys %$suffix_rules_default)) > 1; + if $need_link || suffix_rules_count > 1; if ($needs_c) { @@ -3274,7 +3070,7 @@ sub handle_dist { if (-f ($relative_dir . "/" . $cfile) # The file might be absent, but if it can be built it's ok. - || exists $targets{$cfile}) + || rule $cfile) { &push_dist_common ($cfile); } @@ -3349,7 +3145,7 @@ sub handle_dist } # Rule to check whether a distribution is viable. - my %transform = ('DISTCHECK-HOOK' => &target_defined ('distcheck-hook'), + my %transform = ('DISTCHECK-HOOK' => !! rule 'distcheck-hook', 'GETTEXT' => $seen_gettext && !$seen_gettext_external); # Prepend $(distdir) to each directory given. @@ -3399,7 +3195,7 @@ sub handle_dist # allows users to do random weird things to the distribution # before it is packaged up. push (@dist_targets, 'dist-hook') - if &target_defined ('dist-hook'); + if rule 'dist-hook'; $transform{'DIST-TARGETS'} = join(' ', @dist_targets); $output_rules .= &file_contents ('distdir', @@ -3918,17 +3714,18 @@ sub handle_footer $output_vars .= 'SOURCES = ' . variable_value ('SOURCES') . "\n\n" if variable_value ('SOURCES'); - reject_target ('.SUFFIXES', - "use variable `SUFFIXES', not target `.SUFFIXES'"); + reject_rule ('.SUFFIXES', + "use variable `SUFFIXES', not target `.SUFFIXES'"); # Note: AIX 4.1 /bin/make will fail if any suffix rule appears # before .SUFFIXES. So we make sure that .SUFFIXES appears before # anything else, by sticking it right after the default: target. $output_header .= ".SUFFIXES:\n"; my $suffixes = var 'SUFFIXES'; + my @suffixes = Automake::Rule::suffixes; if (@suffixes || $suffixes) { - # Make sure suffixes has unique elements. Sort them to ensure + # Make sure SUFFIXES has unique elements. Sort them to ensure # the output remains consistent. However, $(SUFFIXES) is # always at the start of the list, unsorted. This is done # because make will choose rules depending on the ordering of @@ -3961,7 +3758,7 @@ sub handle_install () ? (" \$(BUILT_SOURCES)\n" . "\t\$(MAKE) \$(AM_MAKEFLAGS)") : ''), - 'installdirs-local' => (target_defined ('installdirs-local') + 'installdirs-local' => (rule 'installdirs-local' ? ' installdirs-local' : ''), am__installdirs => variable_value ('am__installdirs') || ''); } @@ -3987,7 +3784,7 @@ sub handle_all ($) } # Install `all' hooks. - if (&target_defined ("all-local")) + if (rule "all-local") { push (@all, "all-local"); &depend ('.PHONY', "all-local"); @@ -4036,7 +3833,7 @@ sub handle_all ($) # Handle check merge target specially. sub do_check_merge_target () { - if (target_defined ('check-local')) + if (rule 'check-local') { # User defined local form of target. So include it. push @check_tests, 'check-local'; @@ -4146,16 +3943,16 @@ sub handle_factored_dependencies { my $x = $utarg; $x =~ s/(data|exec)-//; - reject_target ($utarg, "use `$x', not `$utarg'"); + reject_rule ($utarg, "use `$x', not `$utarg'"); } - reject_target ('install-local', - "use `install-data-local' or `install-exec-local', " - . "not `install-local'"); + reject_rule ('install-local', + "use `install-data-local' or `install-exec-local', " + . "not `install-local'"); - reject_target ('install-info-local', - "`install-info-local' target defined but " - . "`no-installinfo' option not in use") + reject_rule ('install-info-local', + "`install-info-local' target defined but " + . "`no-installinfo' option not in use") unless option 'no-installinfo'; # Install the -local hooks. @@ -4163,10 +3960,10 @@ sub handle_factored_dependencies { # Hooks are installed on the -am targets. s/-am$// or next; - if (&target_defined ("$_-local")) + if (rule "$_-local") { depend ("$_-am", "$_-local"); - &depend ('.PHONY', "$_-local"); + depend ('.PHONY', "$_-local"); } } @@ -4174,7 +3971,7 @@ sub handle_factored_dependencies # FIXME: Why not be as liberal as we are with -local hooks? foreach ('install-exec', 'install-data', 'uninstall') { - if (&target_defined ("$_-hook")) + if (rule ("$_-hook")) { $actions{"$_-am"} .= ("\t\@\$(NORMAL_INSTALL)\n" @@ -4205,7 +4002,8 @@ sub handle_factored_dependencies if ($_ ne '.PHONY') { @undefined_conds = - rule_define ($_, 'internal', TARGET_AUTOMAKE, TRUE, INTERNAL); + Automake::Rule::define ($_, 'internal', + RULE_AUTOMAKE, TRUE, INTERNAL); } my @uniq_deps = uniq (sort @{$dependencies{$_}}); foreach my $cond (@undefined_conds) @@ -5120,7 +4918,7 @@ sub register_language (%) { foreach my $dest (&{$lang->output_extensions} ($suffix)) { - ®ister_suffix_rule ('internal', $suffix, $dest); + register_suffix_rule (INTERNAL, $suffix, $dest); } } } @@ -5260,18 +5058,6 @@ sub cond_stack_endif ($$$) ## ------------------------ ## -# @CONDS -# target_conditions ($TARGET) -# --------------------------- -# Get the list of conditions that a target is defined with. -sub target_conditions ($) -{ - my ($target) = @_; - my @conds = keys %{$targets{$target}}; - return new Automake::DisjConditions @conds; -} - - # &define_pretty_variable ($VAR, $COND, $WHERE, @VALUE) # ----------------------------------------------------- # Like define_variable, but the value is a list, and the variable may @@ -5373,350 +5159,6 @@ sub define_linker_variable ($) INTERNAL); } -################################################################ - -## ---------------- ## -## Handling rules. ## -## ---------------- ## - -sub register_suffix_rule ($$$) -{ - my ($where, $src, $dest) = @_; - - verb "Sources ending in $src become $dest"; - push @suffixes, $src, $dest; - - # When tranforming sources to objects, Automake uses the - # %suffix_rules to move from each source extension to - # `.$(OBJEXT)', not to `.o' or `.obj'. However some people - # define suffix rules for `.o' or `.obj', so internally we will - # consider these extensions equivalent to `.$(OBJEXT)'. We - # CANNOT rewrite the target (i.e., automagically replace `.o' - # and `.obj' by `.$(OBJEXT)' in the output), or warn the user - # that (s)he'd better use `.$(OBJEXT)', because Automake itself - # output suffix rules for `.o' or `.obj'... - $dest = '.$(OBJEXT)' if ($dest eq '.o' || $dest eq '.obj'); - - # Reading the comments near the declaration of $suffix_rules might - # help to understand the update of $suffix_rules that follows... - - # Register $dest as a possible destination from $src. - # We might have the create the \hash. - if (exists $suffix_rules->{$src}) - { - $suffix_rules->{$src}{$dest} = [ $dest, 1 ]; - } - else - { - $suffix_rules->{$src} = { $dest => [ $dest, 1 ] }; - } - - # If we know how to transform $dest in something else, then - # we know how to transform $src in that "something else". - if (exists $suffix_rules->{$dest}) - { - for my $dest2 (keys %{$suffix_rules->{$dest}}) - { - my $dist = $suffix_rules->{$dest}{$dest2}[1] + 1; - # Overwrite an existing $src->$dest2 path only if - # the path via $dest which is shorter. - if (! exists $suffix_rules->{$src}{$dest2} - || $suffix_rules->{$src}{$dest2}[1] > $dist) - { - $suffix_rules->{$src}{$dest2} = [ $dest, $dist ]; - } - } - } - - # Similarly, any extension that can be derived into $src - # can be derived into the same extenstions as $src can. - my @dest2 = keys %{$suffix_rules->{$src}}; - for my $src2 (keys %$suffix_rules) - { - if (exists $suffix_rules->{$src2}{$src}) - { - for my $dest2 (@dest2) - { - my $dist = $suffix_rules->{$src}{$dest2} + 1; - # Overwrite an existing $src2->$dest2 path only if - # the path via $src is shorter. - if (! exists $suffix_rules->{$src2}{$dest2} - || $suffix_rules->{$src2}{$dest2}[1] > $dist) - { - $suffix_rules->{$src2}{$dest2} = [ $src, $dist ]; - } - } - } - } -} - -# @CONDS -# rule_define ($TARGET, $SOURCE, $OWNER, $COND, $WHERE) -# ----------------------------------------------------- -# Define a new rule. $TARGET is the rule name. $SOURCE -# is the filename the rule comes from. $OWNER is the -# owner of the rule (TARGET_AUTOMAKE or TARGET_USER). -# $COND is the Condition under which the rule is defined. -# $WHERE is the Location where the rule is defined. -# Returns a (possibly empty) list of Conditions where the rule -# should be defined. -sub rule_define ($$$$$) -{ - my ($target, $source, $owner, $cond, $where) = @_; - - prog_error "$where is not a reference" - unless ref $where; - prog_error "$cond is not a reference" - unless ref $cond; - - # Don't even think about defining a rule in condition FALSE. - return () if $cond == FALSE; - - # For now `foo:' will override `foo$(EXEEXT):'. This is temporary, - # though, so we emit a warning. - (my $noexe = $target) =~ s,\$\(EXEEXT\)$,,; - if ($noexe ne $target - && exists $targets{$noexe} - && exists $targets{$noexe}{$cond} - && $target_name{$noexe}{$cond} ne $target) - { - # The no-exeext option enables this feature. - if (! option 'no-exeext') - { - msg ('obsolete', $targets{$noexe}{$cond}, - "deprecated feature: target `$noexe' overrides " - . "`$noexe\$(EXEEXT)'\n" - . "change your target to read `$noexe\$(EXEEXT)'"); - msg ('obsolete', $where, "target `$target' was defined here"); - } - # Don't `return ()' now, as this might hide target clashes - # detected below. - } - - # For now on, strip off $(EXEEXT) from $target, so we can diagnose - # a clash if `ctags$(EXEEXT):' is redefined after `ctags:'. - my $realtarget = $target; - $target = $noexe; - - # A GNU make-style pattern rule has a single "%" in the target name. - msg ('portability', $where, - "`%'-style pattern rules are a GNU make extension") - if $target =~ /^[^%]*%[^%]*$/; - - # Diagnose target redefinitions. - if (exists $target_source{$target}{$cond}) - { - # Sanity checks. - prog_error ("\$target_source{$target}{$cond} exists, but \$target_owner" - . " doesn't.") - unless exists $target_owner{$target}{$cond}; - prog_error ("\$target_source{$target}{$cond} exists, but \$targets" - . " doesn't.") - unless exists $targets{$target}{$cond}; - prog_error ("\$target_source{$target}{$cond} exists, but \$target_name" - . " doesn't.") - unless exists $target_name{$target}{$cond}; - - my $oldowner = $target_owner{$target}{$cond}; - - # Don't mention true conditions in diagnostics. - my $condmsg = - $cond == TRUE ? '' : " in condition `" . $cond->human . "'"; - - if ($owner == TARGET_USER) - { - if ($oldowner == TARGET_USER) - { - # Ignore `%'-style pattern rules. We'd need the - # dependencies to detect duplicates, and they are - # already diagnosed as unportable by -Wportability. - if ($target !~ /^[^%]*%[^%]*$/) - { - ## FIXME: Presently we can't diagnose duplcate user rules - ## because we doesn't distinguish rules with commands - ## from rules that only add dependencies. E.g., - ## .PHONY: foo - ## .PHONY: bar - ## is legitimate. (This is phony.test.) - - # msg ('syntax', $where, - # "redefinition of `$target'$condmsg...", partial => 1); - # msg_cond_target ('syntax', $cond, $target, - # "... `$target' previously defined here"); - } - # Return so we don't redefine the rule in our tables, - # don't check for ambiguous condition, etc. The rule - # will be output anyway beauce &read_am_file ignore the - # return code. - return (); - } - else - { - # Since we parse the user Makefile.am before reading - # the Automake fragments, this condition should never happen. - prog_error ("user target `$target' seen after Automake's " - . "definition\nfrom `$targets{$target}$condmsg'"); - } - } - else # $owner == TARGET_AUTOMAKE - { - if ($oldowner == TARGET_USER) - { - # -am targets listed in %dependencies support a -local - # variant. If the user tries to override TARGET or - # TARGET-am for which there exists a -local variant, - # just tell the user to use it. - my $hint = 0; - my $noam = $target; - $noam =~ s/-am$//; - if (exists $dependencies{"$noam-am"}) - { - $hint = "consider using $target-local instead of $target"; - } - - msg_cond_target ('override', $cond, $target, - "user target `$target' defined here" - . "$condmsg...", partial => 1); - msg ('override', $where, - "... overrides Automake target `$target' defined here", - partial => $hint); - msg_cond_target ('override', $cond, $target, $hint) - if $hint; - - # Don't overwrite the user definition of TARGET. - return (); - } - else # $oldowner == TARGET_AUTOMAKE - { - # Automake should ignore redefinitions of its own - # rules if they came from the same file. This makes - # it easier to process a Makefile fragment several times. - # Hower it's an error if the target is defined in many - # files. E.g., the user might be using bin_PROGRAMS = ctags - # which clashes with our `ctags' rule. - # (It would be more accurate if we had a way to compare - # the *content* of both rules. Then $targets_source would - # be useless.) - my $oldsource = $target_source{$target}{$cond}; - return () if $source eq $oldsource; - - msg ('syntax', $where, "redefinition of `$target'$condmsg...", - partial => 1); - msg_cond_target ('syntax', $cond, $target, - "... `$target' previously defined here"); - return (); - } - } - # Never reached. - prog_error ("Unreachable place reached."); - } - - # Conditions for which the rule should be defined. - my @conds = $cond; - - # Check ambiguous conditional definitions. - my ($message, $ambig_cond) = - target_conditions ($target)->ambiguous_p ($target, $cond); - if ($message) # We have an ambiguty. - { - if ($owner == TARGET_USER) - { - # For user rules, just diagnose the ambiguity. - msg 'syntax', $where, "$message ...", partial => 1; - msg_cond_target ('syntax', $ambig_cond, $target, - "... `$target' previously defined here"); - return (); - } - else - { - # FIXME: for Automake rules, we can't diagnose ambiguities yet. - # The point is that Automake doesn't propagate conditions - # everywhere. For instance &handle_PROGRAMS doesn't care if - # bin_PROGRAMS was defined conditionally or not. - # On the following input - # if COND1 - # foo: - # ... - # else - # bin_PROGRAMS = foo - # endif - # &handle_PROGRAMS will attempt to define a `foo:' rule - # in condition TRUE (which conflicts with COND1). Fixing - # this in &handle_PROGRAMS and siblings seems hard: you'd - # have to explain &file_contents what to do with a - # condition. So for now we do our best *here*. If `foo:' - # was already defined in condition COND1 and we want to define - # it in condition TRUE, then define it only in condition !COND1. - # (See cond14.test and cond15.test for some test cases.) - my $defined_conds = target_conditions ($target); - @conds = (); - for my $undefined_cond ($defined_conds->invert->conds) - { - push @conds, $cond->merge ($undefined_cond); - } - # No conditions left to define the rule. - # Warn, because our workaround is meaningless in this case. - if (scalar @conds == 0) - { - msg 'syntax', $where, "$message ...", partial => 1; - msg_cond_target ('syntax', $ambig_cond, $target, - "... `$target' previously defined here"); - return (); - } - } - } - - # Finally define this rule. - for my $c (@conds) - { - $targets{$target}{$c} = $where->clone; - $target_source{$target}{$c} = $source; - $target_owner{$target}{$c} = $owner; - $target_name{$target}{$c} = $realtarget; - } - - # We honor inference rules with multiple targets because many - # make support this and people use it. However this is disallowed - # by POSIX. We'll print a warning later. - my $target_count = 0; - my $inference_rule_count = 0; - for my $t (split (' ', $target)) - { - ++$target_count; - # Check the rule for being a suffix rule. If so, store in a hash. - # Either it's a rule for two known extensions... - if ($t =~ /^($KNOWN_EXTENSIONS_PATTERN)($KNOWN_EXTENSIONS_PATTERN)$/ - # ...or it's a rule with unknown extensions (.i.e, the rule - # looks like `.foo.bar:' but `.foo' or `.bar' are not - # declared in SUFFIXES and are not known language - # extensions). Automake will complete SUFFIXES from - # @suffixes automatically (see handle_footer). - || ($t =~ /$SUFFIX_RULE_PATTERN/o && accept_extensions($1))) - { - ++$inference_rule_count; - register_suffix_rule ($where, $1, $2); - } - } - - # POSIX allow multiple targets befor the colon, but disallow - # definitions of multiple Inference rules. It's also - # disallowed to mix plain targets with inference rules. - msg ('portability', $where, - "Inference rules can have only one target before the colon (POSIX).") - if $inference_rule_count > 0 && $target_count > 1; - - return @conds; -} - - -# See if a target exists. -sub target_defined -{ - my ($target) = @_; - return exists $targets{$target}; -} - - ################################################################ # &check_trailing_slash ($WHERE, $LINE) @@ -5904,7 +5346,7 @@ sub read_am_file ($$) # For now we have to output all definitions of user rules # and can't diagnose duplicates (see the comment in # rule_define). So we go on and ignore the return value. - rule_define ($1, $amfile, TARGET_USER, $cond, $where); + Automake::Rule::define ($1, $amfile, RULE_USER, $cond, $where); check_variable_expansions ($_, $where); @@ -6295,9 +5737,9 @@ sub file_contents_internal ($$$%) # Free-lance dependency. Output the rule for all the # targets instead of one by one. my @undefined_conds = - rule_define ($targets, $file, - $is_am ? TARGET_AUTOMAKE : TARGET_USER, - $cond, $where); + Automake::Rule::define ($targets, $file, + $is_am ? RULE_AUTOMAKE : RULE_USER, + $cond, $where); for my $undefined_cond (@undefined_conds) { my $condparagraph = $paragraph; @@ -6903,7 +6345,7 @@ sub require_file_internal ($$@) # the Makefile, don't print anything. This allows files # like README, AUTHORS, or THANKS to be generated. next - if !$suppress && target_defined ($file); + if !$suppress && rule $file; msg ($suppress ? 'note' : 'error', $where, "$message$trailer"); } diff --git a/lib/Automake/Item.pm b/lib/Automake/Item.pm new file mode 100644 index 00000000..f95154c8 --- /dev/null +++ b/lib/Automake/Item.pm @@ -0,0 +1,205 @@ +# Copyright (C) 2003 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, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +package Automake::Item; +use strict; +use Carp; + +use Automake::ChannelDefs; +use Automake::DisjConditions; + +=head1 NAME + +Automake::Item - base class for Automake::Variable and Automake::Rule + +=head1 DESCRIPTION + +=head2 Methods + +=over 4 + +=item C + +Create and return an empty Item called C<$name>. + +=cut + +sub new ($$) +{ + my ($class, $name) = @_; + my $self = { + name => $name, + defs => {}, + conds => {}, + }; + bless $self, $class; + return $self; +} + +=item C<$item-Ename> + +Return the name of C<$item>. + +=cut + +sub name ($) +{ + my ($self) = @_; + return $self->{'name'}; +} + +=item C<$item-Edef ($cond)> + +Return the definition for this item in condition C<$cond>, if it +exists. Return 0 otherwise. + +=cut + +sub def ($$) +{ + my ($self, $cond) = @_; + return $self->{'defs'}{$cond} if exists $self->{'defs'}{$cond}; + return 0; +} + +=item C<$item-Erdef ($cond)> + +Return the definition for this item in condition C<$cond>. Abort with +an internal error if the item was not defined under this condition. + +The I in front of C stands for I. One +should call C to assert the conditional definition's existence. + +=cut + +sub rdef ($$) +{ + my ($self, $cond) = @_; + my $d = $self->def ($cond); + prog_error ("undefined condition `" . $cond->human . "' for `" + . $self->name . "'\n" . $self->dump) + unless $d; + return $d; +} + +=item C<$item-Eset ($cond, $def)> + +Add a new definition to an existing item. + +=cut + +sub set ($$$) +{ + my ($self, $cond, $def) = @_; + $self->{'defs'}{$cond} = $def; + $self->{'conds'}{$cond} = $cond; +} + +=item C<$var-Econditions> + +Return an L describing the conditions that +that an item is defined in. + +These are all the conditions for which is would be safe to call +C. + +=cut + +sub conditions ($) +{ + my ($self) = @_; + prog_error ("self is not a reference") + unless ref $self; + return new Automake::DisjConditions (values %{$self->{'conds'}}); +} + +=item C<@missing_conds = $var-Enot_always_defined_in_cond ($cond)> + +Check whether C<$var> is always defined for condition C<$cond>. +Return a list of conditions where the definition is missing. + +For instance, given + + if COND1 + if COND2 + A = foo + D = d1 + else + A = bar + D = d2 + endif + else + D = d3 + endif + if COND3 + A = baz + B = mumble + endif + C = mumble + +we should have (we display result as conditional strings in this +illustration, but we really return DisjConditions objects): + + var ('A')->not_always_defined_in_cond ('COND1_TRUE COND2_TRUE') + => () + var ('A')->not_always_defined_in_cond ('COND1_TRUE') + => () + var ('A')->not_always_defined_in_cond ('TRUE') + => ("COND1_FALSE COND3_FALSE") + var ('B')->not_always_defined_in_cond ('COND1_TRUE') + => ("COND1_TRUE COND3_FALSE") + var ('C')->not_always_defined_in_cond ('COND1_TRUE') + => () + var ('D')->not_always_defined_in_cond ('TRUE') + => () + var ('Z')->not_always_defined_in_cond ('TRUE') + => ("TRUE") + +=cut + +sub not_always_defined_in_cond ($$) +{ + my ($self, $cond) = @_; + + # Compute the subconditions where $var isn't defined. + return + $self->conditions + ->sub_conditions ($cond) + ->invert + ->simplify + ->multiply ($cond); +} + + +1; + +### Setup "GNU" style for perl-mode and cperl-mode. +## Local Variables: +## perl-indent-level: 2 +## perl-continued-statement-offset: 2 +## perl-continued-brace-offset: 0 +## perl-brace-offset: 0 +## perl-brace-imaginary-offset: 0 +## perl-label-offset: -2 +## cperl-indent-level: 2 +## cperl-brace-offset: 0 +## cperl-continued-brace-offset: 0 +## cperl-label-offset: -2 +## cperl-extra-newline-before-brace: t +## cperl-merge-trailing-else: nil +## cperl-continued-statement-offset: 2 +## End: diff --git a/lib/Automake/ItemDef.pm b/lib/Automake/ItemDef.pm new file mode 100644 index 00000000..3d9361df --- /dev/null +++ b/lib/Automake/ItemDef.pm @@ -0,0 +1,113 @@ +# Copyright (C) 2003 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, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +package Automake::ItemDef; +use strict; +use Carp; + +=head1 NAME + +Automake::ItemDef - base class for Automake::VarDef and Automake::RuleDef + +=head1 DESCRIPTION + +=head2 Methods + +=over 4 + +=item C + +Create a new Makefile-item definition. + +C<$comment> is any comment preceding the definition. (Because +Automake reorders items in the output, it also tries to carry comments +around.) + +C<$location> is the place where the definition occured, it should be +an instance of L. + +C<$owner> specifies who owns the rule. + +=cut + +sub new ($$$$) +{ + my ($class, $comment, $location, $owner) = @_; + + my $self = { + comment => $comment, + location => $location, + owner => $owner, + }; + bless $self, $class; + + return $self; +} + +=item C<$def-Ecomment> + +=item C<$def-Elocation> + +=item C<$def-Eowner> + +Accessors to the various constituents of an C. See the +documentation of C's arguments for a description of these. + +=cut + +sub comment ($) +{ + my ($self) = @_; + return $self->{'comment'}; +} + +sub location ($) +{ + my ($self) = @_; + return $self->{'location'}; +} + +sub owner ($) +{ + my ($self) = @_; + return $self->{'owner'}; +} + +=head1 SEE ALSO + +L, and L. + +=cut + +1; + +### Setup "GNU" style for perl-mode and cperl-mode. +## Local Variables: +## perl-indent-level: 2 +## perl-continued-statement-offset: 2 +## perl-continued-brace-offset: 0 +## perl-brace-offset: 0 +## perl-brace-imaginary-offset: 0 +## perl-label-offset: -2 +## cperl-indent-level: 2 +## cperl-brace-offset: 0 +## cperl-continued-brace-offset: 0 +## cperl-label-offset: -2 +## cperl-extra-newline-before-brace: t +## cperl-merge-trailing-else: nil +## cperl-continued-statement-offset: 2 +## End: diff --git a/lib/Automake/Makefile.am b/lib/Automake/Makefile.am index 2d3ed5d0..1a950c1c 100644 --- a/lib/Automake/Makefile.am +++ b/lib/Automake/Makefile.am @@ -28,8 +28,12 @@ dist_perllib_DATA = \ DisjConditions.pm \ FileUtils.pm \ General.pm \ + Item.pm \ + ItemDef.pm \ Location.pm \ Options.pm \ + Rule.pm \ + RuleDef.pm \ Struct.pm \ Variable.pm \ VarDef.pm \ diff --git a/lib/Automake/Makefile.in b/lib/Automake/Makefile.in index 6b24e850..edbf7def 100644 --- a/lib/Automake/Makefile.in +++ b/lib/Automake/Makefile.in @@ -138,8 +138,12 @@ dist_perllib_DATA = \ DisjConditions.pm \ FileUtils.pm \ General.pm \ + Item.pm \ + ItemDef.pm \ Location.pm \ Options.pm \ + Rule.pm \ + RuleDef.pm \ Struct.pm \ Variable.pm \ VarDef.pm \ diff --git a/lib/Automake/Rule.pm b/lib/Automake/Rule.pm new file mode 100644 index 00000000..35fc11d5 --- /dev/null +++ b/lib/Automake/Rule.pm @@ -0,0 +1,844 @@ +# Copyright (C) 2003 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, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +package Automake::Rule; +use strict; +use Carp; + +use Automake::Item; +use Automake::RuleDef; +use Automake::ChannelDefs; +use Automake::Channels; +use Automake::Options; +use Automake::Condition qw (TRUE FALSE); +use Automake::DisjConditions; +require Exporter; +use vars '@ISA', '@EXPORT', '@EXPORT_OK'; +@ISA = qw/Automake::Item Exporter/; +@EXPORT = qw (reset register_suffix_rule suffix_rules_count + suffixes rules $suffix_rules $KNOWN_EXTENSIONS_PATTERN + depend %dependencies %actions accept_extensions + reject_rule msg_rule msg_cond_rule err_rule err_cond_rule + rule rrule ruledef rruledef); + +=head1 NAME + +Automake::Rule - support for rules definitions + +=head1 SYNOPSIS + + use Automake::Rule; + use Automake::RuleDef; + + +=head1 DESCRIPTION + +This package provides support for Makefile rule definitions. + +An C is a rule name associated to possibly +many conditional definitions. These definitions are instances +of C. + +Therefore obtaining the value of a rule under a given +condition involves two lookups. One to look up the rule, +and one to look up the conditional definition: + + my $rule = rule $name; + if ($rule) + { + my $def = $rule->def ($cond); + if ($def) + { + return $def->location; + } + ... + } + ... + +when it is known that the rule and the definition +being looked up exist, the above can be simplified to + + return rule ($name)->def ($cond)->location; # do not write this. + +but is better written + + return rrule ($name)->rrule ($cond)->location; + +or even + + return rruledef ($name, $cond)->location; + +The I variants of the C, C, and C methods add +an extra test to ensure that the lookup succeeded, and will diagnose +failures as internal errors (with a message which is much more +informative than Perl's warning about calling a method on a +non-object). + +=head2 Global variables + +=over 4 + +=cut + +my $_SUFFIX_RULE_PATTERN = + '^(\.[a-zA-Z0-9_(){}$+@]+)(\.[a-zA-Z0-9_(){}$+@]+)' . "\$"; + +# Suffixes found during a run. +use vars '@_suffixes'; + +# Same as $suffix_rules (declared below), but records only the +# default rules supplied by the languages Automake supports. +use vars '$_suffix_rules_default'; + +=item C<%dependencies> + +Holds the dependencies of targets which dependencies are factored. +Typically, C<.PHONY> will appear in plenty of F<*.am> files, but must +be output once. Arguably all pure dependencies could be subject to +this factorization, but it is not unpleasant to have paragraphs in +Makefile: keeping related stuff altogether. + +=cut + +use vars '%dependencies'; + +=item <%actions> + +Holds the factored actions. Tied to C<%dependencies>, i.e., filled +only when keys exists in C<%dependencies>. + +=cut + +use vars '%actions'; + +=item <$suffix_rules> + +This maps the source extension for all suffix rule seen to +a C<\hash> whose keys are the possible output extensions. + +Note that this is transitively closed by construction: +if we have + exists $suffix_rules{$ext1}{$ext2} + && exists $suffix_rules{$ext2}{$ext3} +then we also have + exists $suffix_rules{$ext1}{$ext3} + +So it's easy to check whether C<.foo> can be transformed to +C<.$(OBJEXT)> by checking whether +C<$suffix_rules{'.foo'}{'.$(OBJEXT)'}> exists. This will work even if +transforming C<.foo> to C<.$(OBJEXT)> involves a chain of several +suffix rules. + +The value of C<$suffix_rules{$ext1}{$ext2}> is the a pair +C<[ $next_sfx, $dist ]> where C<$next_sfx> is target suffix +for the next rule to use to reach C<$ext2>, and C<$dist> the +distance to C<$ext2'>. + +The content of this variable should be updated via the +C function. + +=cut + +use vars '$suffix_rules'; + +=item C<$KNOWN_EXTENSIONS_PATTERN> + +Pattern that matches all know input extensions (i.e. extensions used +by the languages supported by Automake). Using this pattern (instead +of `\..*$') to match extensions allows Automake to support dot-less +extensions. + +New extension should be registered with C. + +=cut + +use vars qw ($KNOWN_EXTENSIONS_PATTERN @_known_extensions_list); +$KNOWN_EXTENSIONS_PATTERN = ""; +@_known_extensions_list = (); + +=back + +=head2 Error reporting functions + +In these functions, C<$rule> can be either a rule name, or +an instance of C. + +=over 4 + +=item C + +Uncategorized errors about rules. + +=cut + +sub err_rule ($$;%) +{ + msg_rule ('error', @_); +} + +=item C + +Uncategorized errors about conditional rules. + +=cut + +sub err_cond_rule ($$$;%) +{ + msg_cond_rule ('error', @_); +} + +=item C + +Messages about conditional rules. + +=cut + +sub msg_cond_rule ($$$$;%) +{ + my ($channel, $cond, $rule, $msg, %opts) = @_; + my $r = ref ($rule) ? $rule : rrule ($rule); + msg $channel, $r->rdef ($cond)->location, $msg, %opts; +} + +=item C + +Messages about rules. + +=cute + +sub msg_rule ($$$;%) +{ + my ($channel, $rule, $msg, %opts) = @_; + my $r = ref ($rule) ? $rule : rrule ($rule); + # Don't know which condition is concerned. Pick any. + my $cond = $r->conditions->one_cond; + msg_cond_rule ($channel, $cond, $r, $msg, %opts); +} + + +=item C<$bool = reject_rule ($rule, $error_msg)> + +Bail out with C<$error_msg> if a rule with name C<$rule> has been +defined. + +Return true iff C<$rule> is defined. + +=cut + +sub reject_rule ($$) +{ + my ($rule, $msg) = @_; + if (rule ($rule)) + { + err_rule $rule, $msg; + return 1; + } + return 0; +} + +=back + +=head2 Administrative functions + +=over 4 + +=item C + +Update C<$KNOWN_EXTENSIONS_PATTERN> to recognize the extensions +listed C<@exts>. Extensions should contain a dot if needed. + +=cut + +sub accept_extensions (@) +{ + push @_known_extensions_list, @_; + $KNOWN_EXTENSIONS_PATTERN = + '(?:' . join ('|', map (quotemeta, @_known_extensions_list)) . ')'; +} + +=item C + +Returns the list of all L instances. (I.e., all +rules defined so far.) + +=cut + +use vars '%_rule_dict'; +sub rules () +{ + return values %_rule_dict; +} + + +=item C + +The I function. Clears all know rules and reset some +other internal data. + +=cut + +sub reset() +{ + %_rule_dict = (); + @_suffixes = (); + # The first time we initialize the variables, + # we save the value of $suffix_rules. + if (defined $_suffix_rules_default) + { + $suffix_rules = $_suffix_rules_default; + } + else + { + $_suffix_rules_default = $suffix_rules; + } + + %dependencies = + ( + # Texinfoing. + 'dvi' => [], + 'dvi-am' => [], + 'pdf' => [], + 'pdf-am' => [], + 'ps' => [], + 'ps-am' => [], + 'info' => [], + 'info-am' => [], + 'html' => [], + 'html-am' => [], + + # Installing/uninstalling. + 'install-data-am' => [], + 'install-exec-am' => [], + 'uninstall-am' => [], + + 'install-man' => [], + 'uninstall-man' => [], + + 'install-info' => [], + 'install-info-am' => [], + 'uninstall-info' => [], + + 'installcheck-am' => [], + + # Cleaning. + 'clean-am' => [], + 'mostlyclean-am' => [], + 'maintainer-clean-am' => [], + 'distclean-am' => [], + 'clean' => [], + 'mostlyclean' => [], + 'maintainer-clean' => [], + 'distclean' => [], + + # Tarballing. + 'dist-all' => [], + + # Phoning. + '.PHONY' => [], + ); + %actions = (); +} + +=item C + +Register a suffix rules defined on C<$where> that transform +files ending in C<$src> into files ending in C<$dest>. + +This upgrades the C<$suffix_rules> variables. + +=cut + +sub register_suffix_rule ($$$) +{ + my ($where, $src, $dest) = @_; + + verb "Sources ending in $src become $dest"; + push @_suffixes, $src, $dest; + + # When tranforming sources to objects, Automake uses the + # %suffix_rules to move from each source extension to + # `.$(OBJEXT)', not to `.o' or `.obj'. However some people + # define suffix rules for `.o' or `.obj', so internally we will + # consider these extensions equivalent to `.$(OBJEXT)'. We + # CANNOT rewrite the target (i.e., automagically replace `.o' + # and `.obj' by `.$(OBJEXT)' in the output), or warn the user + # that (s)he'd better use `.$(OBJEXT)', because Automake itself + # output suffix rules for `.o' or `.obj'... + $dest = '.$(OBJEXT)' if ($dest eq '.o' || $dest eq '.obj'); + + # Reading the comments near the declaration of $suffix_rules might + # help to understand the update of $suffix_rules that follows... + + # Register $dest as a possible destination from $src. + # We might have the create the \hash. + if (exists $suffix_rules->{$src}) + { + $suffix_rules->{$src}{$dest} = [ $dest, 1 ]; + } + else + { + $suffix_rules->{$src} = { $dest => [ $dest, 1 ] }; + } + + # If we know how to transform $dest in something else, then + # we know how to transform $src in that "something else". + if (exists $suffix_rules->{$dest}) + { + for my $dest2 (keys %{$suffix_rules->{$dest}}) + { + my $dist = $suffix_rules->{$dest}{$dest2}[1] + 1; + # Overwrite an existing $src->$dest2 path only if + # the path via $dest which is shorter. + if (! exists $suffix_rules->{$src}{$dest2} + || $suffix_rules->{$src}{$dest2}[1] > $dist) + { + $suffix_rules->{$src}{$dest2} = [ $dest, $dist ]; + } + } + } + + # Similarly, any extension that can be derived into $src + # can be derived into the same extenstions as $src can. + my @dest2 = keys %{$suffix_rules->{$src}}; + for my $src2 (keys %$suffix_rules) + { + if (exists $suffix_rules->{$src2}{$src}) + { + for my $dest2 (@dest2) + { + my $dist = $suffix_rules->{$src}{$dest2} + 1; + # Overwrite an existing $src2->$dest2 path only if + # the path via $src is shorter. + if (! exists $suffix_rules->{$src2}{$dest2} + || $suffix_rules->{$src2}{$dest2}[1] > $dist) + { + $suffix_rules->{$src2}{$dest2} = [ $src, $dist ]; + } + } + } + } +} + +=item C<$count = suffix_rules_count> + +Return the number of suffix rules added while processing the current +F (excluding predefined suffix rules). + +=cut + +sub suffix_rules_count () +{ + return (scalar keys %$suffix_rules) - (scalar keys %$_suffix_rules_default); +} + +=item C<@list = suffixes> + +Return the list of known suffixes. + +=cut + +sub suffixes () +{ + return @_suffixes; +} + +=item C + +Return the C object for the rule +named C<$rulename> if defined. Return 0 otherwise. + +=cut + +sub rule ($) +{ + my ($name) = @_; + # Strip $(EXEEXT) from $name, so we can diagnose + # a clash if `ctags$(EXEEXT):' is redefined after `ctags:'. + $name =~ s,\$\(EXEEXT\)$,,; + return $_rule_dict{$name} if exists $_rule_dict{$name}; + return 0; +} + +=item C + +Return the C object for the rule named +C<$rulename> if defined in condition C<$cond>. Return false +if the condition or the rule does not exist. + +=cut + +sub ruledef ($$) +{ + my ($name, $cond) = @_; + my $rule = rule $name; + return $rule && $rule->def ($cond); +} + +=item C object for the variable named +C<$rulename>. Abort with an internal error if the variable was not +defined. + +The I in front of C stands for I. One +should call C to assert the rule's existence. + +=cut + +sub rrule ($) +{ + my ($name) = @_; + my $r = rule $name; + prog_error ("undefined rule $name\n" . &rules_dump) + unless $r; + return $r; +} + +=item C + +Return the C object for the rule named +C<$rulename> if defined in condition C<$cond>. Abort with an internal +error if the condition or the rule does not exist. + +=cut + +sub rruledef ($$) +{ + my ($name, $cond) = @_; + return rrule ($name)->rdef ($cond); +} + +# Create the variable if it does not exist. +# This is used only by other functions in this package. +sub _crule ($) +{ + my ($name) = @_; + my $r = rule $name; + return $r if $r; + return _new Automake::Rule $name; +} + +sub _new ($$) +{ + my ($class, $name) = @_; + + # Strip $(EXEEXT) from $name, so we can diagnose + # a clash if `ctags$(EXEEXT):' is redefined after `ctags:'. + (my $keyname = $name) =~ s,\$\(EXEEXT\)$,,; + + my $self = Automake::Item::new ($class, $name); + $_rule_dict{$keyname} = $self; + return $self; +} + + +=itcem C<@conds = define ($rulename, $source, $owner, $cond, $where)> + +Define a new rule. C<$rulename> is the list of targets. C<$source> +is the filename the rule comes from. C<$owner> is the owner of the +rule (C or C). C<$cond> is the +C under which the rule is defined. C<$where> is +the C where the rule is defined. + +Returns a (possibly empty) list of Cs where the +rule's definition should be output. + +=cut + +sub define ($$$$$) +{ + my ($target, $source, $owner, $cond, $where) = @_; + + prog_error "$where is not a reference" + unless ref $where; + prog_error "$cond is not a reference" + unless ref $cond; + + # Don't even think about defining a rule in condition FALSE. + return () if $cond == FALSE; + + # For now `foo:' will override `foo$(EXEEXT):'. This is temporary, + # though, so we emit a warning. + (my $noexe = $target) =~ s,\$\(EXEEXT\)$,,; + my $noexerule = rule $noexe; + my $tdef = $noexerule ? $noexerule->def ($cond) : undef; + + if ($noexe ne $target + && $tdef + && $noexerule->name ne $target) + { + print "1. $noexe\n"; + print "2. $target\n"; + print "3. " . $noexerule->name . "\n"; + # The no-exeext option enables this feature. + if (! option 'no-exeext') + { + msg ('obsolete', $tdef->location, + "deprecated feature: target `$noexe' overrides " + . "`$noexe\$(EXEEXT)'\n" + . "change your target to read `$noexe\$(EXEEXT)'"); + msg ('obsolete', $where, "target `$target' was defined here"); + } + # Don't `return ()' now, as this might hide target clashes + # detected below. + } + + + # A GNU make-style pattern rule has a single "%" in the target name. + msg ('portability', $where, + "`%'-style pattern rules are a GNU make extension") + if $target =~ /^[^%]*%[^%]*$/; + + # Diagnose target redefinitions. + if ($tdef) + { + my $oldowner = $tdef->owner; + # Ok, it's the name target, but the name maybe different because + # `foo$(EXEEXT)' and `foo' have the same key in our table. + my $oldname = $tdef->name; + + # Don't mention true conditions in diagnostics. + my $condmsg = + $cond == TRUE ? '' : " in condition `" . $cond->human . "'"; + + if ($owner == RULE_USER) + { + if ($oldowner == RULE_USER) + { + # Ignore `%'-style pattern rules. We'd need the + # dependencies to detect duplicates, and they are + # already diagnosed as unportable by -Wportability. + if ($target !~ /^[^%]*%[^%]*$/) + { + ## FIXME: Presently we can't diagnose duplcate user rules + ## because we doesn't distinguish rules with commands + ## from rules that only add dependencies. E.g., + ## .PHONY: foo + ## .PHONY: bar + ## is legitimate. (This is phony.test.) + + # msg ('syntax', $where, + # "redefinition of `$target'$condmsg...", partial => 1); + # msg_cond_rule ('syntax', $cond, $target, + # "... `$target' previously defined here"); + } + # Return so we don't redefine the rule in our tables, + # don't check for ambiguous condition, etc. The rule + # will be output anyway beauce &read_am_file ignore the + # return code. + return (); + } + else + { + # Since we parse the user Makefile.am before reading + # the Automake fragments, this condition should never happen. + prog_error ("user target `$target'$condmsg seen after Automake's" + . " definition\nfrom " . $tdef->source); + } + } + else # $owner == RULE_AUTOMAKE + { + if ($oldowner == RULE_USER) + { + # -am targets listed in %dependencies support a -local + # variant. If the user tries to override TARGET or + # TARGET-am for which there exists a -local variant, + # just tell the user to use it. + my $hint = 0; + my $noam = $target; + $noam =~ s/-am$//; + if (exists $dependencies{"$noam-am"}) + { + $hint = "consider using $target-local instead of $target"; + } + + msg_cond_rule ('override', $cond, $target, + "user target `$target' defined here" + . "$condmsg...", partial => 1); + msg ('override', $where, + "... overrides Automake target `$oldname' defined here", + partial => $hint); + msg_cond_rule ('override', $cond, $target, $hint) + if $hint; + + # Don't overwrite the user definition of TARGET. + return (); + } + else # $oldowner == RULE_AUTOMAKE + { + # Automake should ignore redefinitions of its own + # rules if they came from the same file. This makes + # it easier to process a Makefile fragment several times. + # Hower it's an error if the target is defined in many + # files. E.g., the user might be using bin_PROGRAMS = ctags + # which clashes with our `ctags' rule. + # (It would be more accurate if we had a way to compare + # the *content* of both rules. Then $targets_source would + # be useless.) + my $oldsource = $tdef->source; + return () if $source eq $oldsource && $target eq $oldname; + + msg ('syntax', $where, "redefinition of `$target'$condmsg...", + partial => 1); + msg_cond_rule ('syntax', $cond, $target, + "... `$oldname' previously defined here"); + return (); + } + } + # Never reached. + prog_error ("Unreachable place reached."); + } + + # Conditions for which the rule should be defined. + my @conds = $cond; + + # Check ambiguous conditional definitions. + my $rule = _crule $target; + my ($message, $ambig_cond) = $rule->conditions->ambiguous_p ($target, $cond); + if ($message) # We have an ambiguty. + { + if ($owner == RULE_USER) + { + # For user rules, just diagnose the ambiguity. + msg 'syntax', $where, "$message ...", partial => 1; + msg_cond_rule ('syntax', $ambig_cond, $target, + "... `$target' previously defined here"); + return (); + } + else + { + # FIXME: for Automake rules, we can't diagnose ambiguities yet. + # The point is that Automake doesn't propagate conditions + # everywhere. For instance &handle_PROGRAMS doesn't care if + # bin_PROGRAMS was defined conditionally or not. + # On the following input + # if COND1 + # foo: + # ... + # else + # bin_PROGRAMS = foo + # endif + # &handle_PROGRAMS will attempt to define a `foo:' rule + # in condition TRUE (which conflicts with COND1). Fixing + # this in &handle_PROGRAMS and siblings seems hard: you'd + # have to explain &file_contents what to do with a + # condition. So for now we do our best *here*. If `foo:' + # was already defined in condition COND1 and we want to define + # it in condition TRUE, then define it only in condition !COND1. + # (See cond14.test and cond15.test for some test cases.) + @conds = (); + for my $undefined_cond ($rule->conditions->invert->conds) + { + push @conds, $cond->merge ($undefined_cond); + } + # No conditions left to define the rule. + # Warn, because our workaround is meaningless in this case. + if (scalar @conds == 0) + { + msg 'syntax', $where, "$message ...", partial => 1; + msg_cond_rule ('syntax', $ambig_cond, $target, + "... `$target' previously defined here"); + return (); + } + } + } + + # Finally define this rule. + for my $c (@conds) + { + my $def = new Automake::RuleDef ($target, '', $where->clone, + $owner, $source); + $rule->set ($c, $def); + } + + # We honor inference rules with multiple targets because many + # make support this and people use it. However this is disallowed + # by POSIX. We'll print a warning later. + my $target_count = 0; + my $inference_rule_count = 0; + + for my $t (split (' ', $target)) + { + ++$target_count; + # Check the rule for being a suffix rule. If so, store in a hash. + # Either it's a rule for two known extensions... + if ($t =~ /^($KNOWN_EXTENSIONS_PATTERN)($KNOWN_EXTENSIONS_PATTERN)$/ + # ...or it's a rule with unknown extensions (.i.e, the rule + # looks like `.foo.bar:' but `.foo' or `.bar' are not + # declared in SUFFIXES and are not known language + # extensions). Automake will complete SUFFIXES from + # @suffixes automatically (see handle_footer). + + + || ($t =~ /$_SUFFIX_RULE_PATTERN/o && accept_extensions($1))) + { + ++$inference_rule_count; + register_suffix_rule ($where, $1, $2); + } + } + + # POSIX allow multiple targets befor the colon, but disallow + # definitions of multiple Inference rules. It's also + # disallowed to mix plain targets with inference rules. + msg ('portability', $where, + "Inference rules can have only one target before the colon (POSIX).") + if $inference_rule_count > 0 && $target_count > 1; + + return @conds; +} + +=item C + +Adds C<@deps> to the dependencies of target C<$target>. This should +be used only with factored targets (those appearing in +C<%dependendees>). + +=cut + +sub depend ($@) +{ + my ($category, @dependendees) = @_; + push (@{$dependencies{$category}}, @dependendees); +} + +=back + +=head1 SEE ALSO + +L, L, +L, L. + +=cut + +1; + +### Setup "GNU" style for perl-mode and cperl-mode. +## Local Variables: +## perl-indent-level: 2 +## perl-continued-statement-offset: 2 +## perl-continued-brace-offset: 0 +## perl-brace-offset: 0 +## perl-brace-imaginary-offset: 0 +## perl-label-offset: -2 +## cperl-indent-level: 2 +## cperl-brace-offset: 0 +## cperl-continued-brace-offset: 0 +## cperl-label-offset: -2 +## cperl-extra-newline-before-brace: t +## cperl-merge-trailing-else: nil +## cperl-continued-statement-offset: 2 +## End: diff --git a/lib/Automake/RuleDef.pm b/lib/Automake/RuleDef.pm new file mode 100644 index 00000000..d25c8e74 --- /dev/null +++ b/lib/Automake/RuleDef.pm @@ -0,0 +1,102 @@ +# Copyright (C) 2003 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, 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, write to the Free Software +# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +# 02111-1307, USA. + +package Automake::RuleDef; +use strict; +use Carp; +use Automake::ChannelDefs; +use Automake::ItemDef; + +require Exporter; +use vars '@ISA', '@EXPORT'; +@ISA = qw/Automake::ItemDef Exporter/; +@EXPORT = qw (&RULE_AUTOMAKE &RULE_USER); + +=head1 NAME + +Automake::RuleDef - a class for rule definitions + +=head1 SYNOPSIS + + use Automake::RuleDef; + use Automake::Location; + +=head1 DESCRIPTION + +This class gather data related to one Makefile-rule definition. + +=head2 Constants + +=over 4 + +=item C, C + +Possible owners for rules. + +=cut + +use constant RULE_AUTOMAKE => 0; # Rule defined by Automake. +use constant RULE_USER => 1; # Rule defined in the user's Makefile.am. + +sub new ($$$$$) +{ + my ($class, $name, $comment, $location, $owner, $source) = @_; + + my $self = Automake::ItemDef::new ($class, $comment, $location, $owner); + $self->{'source'} = $source; + $self->{'name'} = $name; + return $self; +} + +sub source ($) +{ + my ($self) = @_; + return $self->{'source'}; +} + +sub name ($) +{ + my ($self) = @_; + return $self->{'name'}; +} + +=back + +=head1 SEE ALSO + +L, L. + +=cut + +1; + +### Setup "GNU" style for perl-mode and cperl-mode. +## Local Variables: +## perl-indent-level: 2 +## perl-continued-statement-offset: 2 +## perl-continued-brace-offset: 0 +## perl-brace-offset: 0 +## perl-brace-imaginary-offset: 0 +## perl-label-offset: -2 +## cperl-indent-level: 2 +## cperl-brace-offset: 0 +## cperl-continued-brace-offset: 0 +## cperl-label-offset: -2 +## cperl-extra-newline-before-brace: t +## cperl-merge-trailing-else: nil +## cperl-continued-statement-offset: 2 +## End: diff --git a/lib/Automake/VarDef.pm b/lib/Automake/VarDef.pm index 7fb53e61..dde29c42 100644 --- a/lib/Automake/VarDef.pm +++ b/lib/Automake/VarDef.pm @@ -19,10 +19,11 @@ package Automake::VarDef; use strict; use Carp; use Automake::ChannelDefs; +use Automake::ItemDef; require Exporter; use vars '@ISA', '@EXPORT'; -@ISA = qw/Exporter/; +@ISA = qw/Automake::ItemDef Exporter/; @EXPORT = qw (&VAR_AUTOMAKE &VAR_CONFIGURE &VAR_MAKEFILE &VAR_ASIS &VAR_PRETTY &VAR_SILENT &VAR_SORTED); @@ -112,9 +113,12 @@ use constant VAR_SORTED => 3; # Sorted and pretty-printed. =head2 Methods +C defines the following methods in addition to those inherited +from L. + =over 4 -=item C +=item C Create a new Makefile-variable definition. C<$varname> is the name of the variable being defined and C<$value> its value. @@ -150,17 +154,11 @@ sub new ($$$$$$$$) error $location, "$var must be set with `=' before using `+='"; } - my $self = { - value => $value, - comment => $comment, - location => $location, - type => $type, - owner => $owner, - pretty => $pretty, - seen => 0, - }; - bless $self, $class; - + my $self = Automake::ItemDef::new ($class, $comment, $location, $owner); + $self->{'value'} = $value; + $self->{'type'} = $type; + $self->{'pretty'} = $pretty; + $self->{'seen'} = 0; return $self; } @@ -192,14 +190,8 @@ sub append ($$$) =item C<$def-Evalue> -=item C<$def-Ecomment> - -=item C<$def-Elocation> - =item C<$def-Etype> -=item C<$def-Eowner> - =item C<$def-Epretty> Accessors to the various constituents of a C. See the @@ -213,30 +205,12 @@ sub value ($) return $self->{'value'}; } -sub comment ($) -{ - my ($self) = @_; - return $self->{'comment'}; -} - -sub location ($) -{ - my ($self) = @_; - return $self->{'location'}; -} - sub type ($) { my ($self) = @_; return $self->{'type'}; } -sub owner ($) -{ - my ($self) = @_; - return $self->{'owner'}; -} - sub pretty ($) { my ($self) = @_; @@ -330,7 +304,7 @@ sub dump ($) =head1 SEE ALSO -L. +L, L. =cut diff --git a/lib/Automake/Variable.pm b/lib/Automake/Variable.pm index 4cce9fba..cd716c70 100644 --- a/lib/Automake/Variable.pm +++ b/lib/Automake/Variable.pm @@ -18,9 +18,11 @@ package Automake::Variable; use strict; use Carp; + use Automake::Channels; use Automake::ChannelDefs; use Automake::Configure_ac; +use Automake::Item; use Automake::VarDef; use Automake::Condition qw (TRUE FALSE); use Automake::DisjConditions; @@ -29,7 +31,7 @@ use Automake::Wrap 'makefile_wrap'; require Exporter; use vars '@ISA', '@EXPORT', '@EXPORT_OK'; -@ISA = qw/Exporter/; +@ISA = qw/Automake::Item Exporter/; @EXPORT = qw (err_var msg_var msg_cond_var reject_var var rvar vardef rvardef variables @@ -122,7 +124,7 @@ or even The I variants of the C, C, and C methods add an extra test to ensure that the lookup succeeded, and will diagnose -failures as internal errors (which a message which is much more +failures as internal errors (with a message which is much more informative than Perl's warning about calling a method on a non-object). @@ -240,16 +242,15 @@ sub msg_var ($$$;%) msg_cond_var $channel, $cond, $v, $msg, %opts; } -=item C +=item C<$bool = reject_var ($varname, $error_msg)> -Bail out with C<$ERROR_MSG> if a variable with name C<$VARNAME> has +Bail out with C<$error_msg> if a variable with name C<$varname> has been defined. +Return true iff C<$varname> is defined. + =cut -# $BOOL -# reject_var ($VARNAME, $ERROR_MSG) -# ----------------------------- sub reject_var ($$) { my ($var, $msg) = @_; @@ -333,7 +334,7 @@ sub var ($) =item C Return the C object for the variable named -C<$varname> if defined in condition C<$cond>. Return the empty list +C<$varname> if defined in condition C<$cond>. Return false if the condition or the variable does not exist. =cut @@ -379,7 +380,7 @@ sub rvar ($) Return the C object for the variable named C<$varname> if defined in condition C<$cond>. Abort with an internal -error if the variable or the variable does not exist. +error if the condition or the variable does not exist. =cut @@ -393,7 +394,10 @@ sub rvardef ($$) =head2 Methods -Here are the methods of the C instances. +C is a subclass of C. See +that package for inherited methods. + +Here are the methods specific to the C instances. Use the C function, described latter, to create such objects. =over 4 @@ -406,92 +410,12 @@ Use the C function, described latter, to create such objects. sub _new ($$) { my ($class, $name) = @_; - my $self = { - name => $name, - defs => {}, - conds => {}, - scanned => 0, - }; - bless $self, $class; + my $self = Automake::Item::new ($class, $name); + $self->{'scanned'} = 0; $_variable_dict{$name} = $self; return $self; } -=item C<$var-Ename> - -Return the name of C<$var>. - -=cut - -sub name ($) -{ - my ($self) = @_; - return $self->{'name'}; -} - -=item C<$var-Edef ($cond)> - -Return the C definition for this variable in -condition C<$cond>, if it exists. Return 0 otherwise. - -=cut - -sub def ($$) -{ - my ($self, $cond) = @_; - return $self->{'defs'}{$cond} if exists $self->{'defs'}{$cond}; - return 0; -} - -=item C<$var-Erdef ($cond)> - -Return the C definition for this variable in -condition C<$cond>. Abort with an internal error if the variable was -not defined under this condition. - -The I in front of C stands for I. One -should call C to assert the conditional definition's existence. - -=cut - -sub rdef ($$) -{ - my ($self, $cond) = @_; - my $d = $self->def ($cond); - prog_error ("undefined condition `" . $cond->human . "' for `" - . $self->name . "'\n" . $self->dump) - unless $d; - return $d; -} - -# Add a new VarDef to an existing Variable. This is a private -# function. Our public interface is the `define' function. -sub _set ($$$) -{ - my ($self, $cond, $def) = @_; - $self->{'defs'}{$cond} = $def; - $self->{'conds'}{$cond} = $cond; -} - -=item C<$var-Econditions> - -Return an L describing the conditions that -that a variable is defined with, without recursing through the -conditions of any subvariables. - -These are all the conditions for which is would be safe to call -C. - -=cut - -sub conditions ($) -{ - my ($self) = @_; - prog_error ("self is not a reference") - unless ref $self; - return new Automake::DisjConditions (values %{$self->{'conds'}}); -} - # _check_ambiguous_condition ($SELF, $COND, $WHERE) # ------------------------------------------------- # Check for an ambiguous conditional. This is called when a variable @@ -514,63 +438,6 @@ sub _check_ambiguous_condition ($$$) } } -=item C<@missing_conds = $var-Enot_always_defined_in_cond ($cond)> - -Check whether C<$var> is always defined for condition C<$cond>. -Return a list of conditions where the definition is missing. - -For instance, given - - if COND1 - if COND2 - A = foo - D = d1 - else - A = bar - D = d2 - endif - else - D = d3 - endif - if COND3 - A = baz - B = mumble - endif - C = mumble - -we should have (we display result as conditional strings in this -illustration, but we really return DisjConditions objects): - - var ('A')->not_always_defined_in_cond ('COND1_TRUE COND2_TRUE') - => () - var ('A')->not_always_defined_in_cond ('COND1_TRUE') - => () - var ('A')->not_always_defined_in_cond ('TRUE') - => ("COND1_FALSE COND3_FALSE") - var ('B')->not_always_defined_in_cond ('COND1_TRUE') - => ("COND1_TRUE COND3_FALSE") - var ('C')->not_always_defined_in_cond ('COND1_TRUE') - => () - var ('D')->not_always_defined_in_cond ('TRUE') - => () - var ('Z')->not_always_defined_in_cond ('TRUE') - => ("TRUE") - -=cut - -sub not_always_defined_in_cond ($$) -{ - my ($self, $cond) = @_; - - # Compute the subconditions where $var isn't defined. - return - $self->conditions - ->sub_conditions ($cond) - ->invert - ->simplify - ->multiply ($cond); -} - =item C<$bool = $var-Echeck_defined_unconditionally ([$parent, $parent_cond])> Warn if the variable is conditionally defined. C<$parent> is the name @@ -1114,7 +981,7 @@ sub define ($$$$$$$$) # line numbers with random bits of text. $def = new Automake::VarDef ($var, $value, $comment, $where->clone, $type, $owner, $pretty); - $self->_set ($cond, $def); + $self->set ($cond, $def); push @_var_order, $var; # No need to adjust the owner later as we have overridden diff --git a/tests/location.test b/tests/location.test index dc5f948f..8c098ea2 100755 --- a/tests/location.test +++ b/tests/location.test @@ -65,12 +65,12 @@ library.am: change your target to read `libfoo.a$(EXEEXT)' Makefile.am:3: while processing library `libfoo.a' program.am: target `libfoo.a$(EXEEXT)' was defined here Makefile.am:1: while processing program `libfoo.a' -program.am: redefinition of `libfoo.a'... +program.am: redefinition of `libfoo.a$(EXEEXT)'... Makefile.am:1: while processing program `libfoo.a' library.am: ... `libfoo.a' previously defined here Makefile.am:3: while processing library `libfoo.a' tags.am: redefinition of `ctags'... -program.am: ... `ctags' previously defined here +program.am: ... `ctags$(EXEEXT)' previously defined here Makefile.am:6: while processing program `ctags' EOF