| # -*-perl-*- |
| |
| use warnings; |
| |
| my $description = "Test appending to variables of various origins."; |
| |
| # sv 64822, sv 36486. |
| # Test various combinations of appends in the presence and absence of command |
| # line definitions, env overrides and makefile overrides. |
| # Test the following statements. |
| # A target or pattern specific definition or append is available at build time |
| # only. |
| # A definition with a makefile override can only be appended to with another |
| # override. |
| # A definition with a makefile override can only be redefined with another |
| # override. |
| # A target or pattern specific definition takes precedence over a global |
| # definition for that target. |
| # A global variable is immune to a target or pattern specific definition or |
| # append. |
| # A target or pattern specific definition is immune to another target or pattern |
| # specific definition or append. |
| # A prerequisite inherits a target or pattern specific value from its target. |
| # "phobos" inherits the value of "hello" from "mars". |
| |
| my @goals = ('phobos', 'mars'); |
| my @specificities = ('', 's: ', '%: '); |
| my @inits = ('', 'hello=file', 'hello:=file', 'override hello=file'); |
| my @global_append = ('', 'hello+=red'); |
| my @blue_override = ('', 'override '); |
| my @yellow_override = ('', 'override '); |
| my @cmdline = ('', 'hello=cmd', 'hello:=cmd hello+=cmd2'); |
| my @env_ovr = ('', '-e'); |
| my @envs = ('', 'env'); |
| |
| for my $goal (@goals) { |
| for my $spec (@specificities) { |
| for my $init (@inits) { |
| for my $ga (@global_append) { |
| for my $bovr (@blue_override) { |
| for my $yovr (@yellow_override) { |
| for my $dashe (@env_ovr) { |
| for my $env (@envs) { |
| for my $cmd (@cmdline) { |
| |
| if ($env) { |
| $ENV{'hello'} = 'env'; |
| } else { |
| delete $ENV{'hello'}; |
| } |
| |
| my $parse_time_answer = ''; |
| my $build_time_answer = ''; |
| |
| # For goal "phobos" target is "", "phobos: " and "phobo%: ". |
| # For goal "mars" target is "", "mars: " and "mar%: ". |
| my $target = ''; |
| if ($spec) { |
| $target = $goal; |
| chop($target); |
| $target .= $spec; |
| } |
| |
| if ($init =~ 'override') { |
| $build_time_answer = 'file'; |
| } elsif ($cmd) { |
| $build_time_answer = $cmd =~ 'cmd2' ? 'cmd cmd2' : 'cmd'; |
| } elsif ($dashe and $env) { |
| $build_time_answer = 'env'; |
| } elsif ($init and !$target and $ga) { |
| $build_time_answer = 'file red'; |
| } elsif ($init) { |
| $build_time_answer = 'file'; |
| } elsif ($env and $ga) { |
| $build_time_answer = 'env red'; |
| } elsif ($env) { |
| $build_time_answer = 'env'; |
| } elsif ($ga) { |
| $build_time_answer = 'red'; |
| } |
| |
| if ($bovr and $yovr) { |
| $build_time_answer .= ' ' if ($build_time_answer); |
| $build_time_answer .= 'blue yellow'; |
| } elsif ($bovr) { |
| $build_time_answer .= ' ' if ($build_time_answer); |
| $build_time_answer .= 'blue'; |
| } elsif ($yovr and !($init =~ 'override') and !$cmd and !($dashe and $env)) { |
| $build_time_answer .= ' ' if ($build_time_answer); |
| $build_time_answer .= 'blue yellow'; |
| } elsif ($yovr) { |
| $build_time_answer .= ' ' if ($build_time_answer); |
| $build_time_answer .= 'yellow'; |
| } elsif ($init =~ 'override') { |
| } elsif ($cmd) { |
| } elsif ($dashe and $env) { |
| } else { |
| $build_time_answer .= ' ' if ($build_time_answer); |
| $build_time_answer .= 'blue yellow'; |
| } |
| |
| |
| if ($cmd and $target) { |
| $parse_time_answer = $cmd =~ 'cmd2' ? 'cmd cmd2' : 'cmd'; |
| } elsif ($env and !$dashe and $target and $ga) { |
| $parse_time_answer = 'env red'; |
| } elsif ($env and $target) { |
| $parse_time_answer = 'env'; |
| } elsif ($target and $ga) { |
| $parse_time_answer = 'red'; |
| } elsif ($target) { |
| $parse_time_answer = ''; |
| } else { |
| $parse_time_answer = $build_time_answer; |
| } |
| |
| my $i = $init ? "$target$init" : ''; |
| |
| # moon and satur% specific settings test that target and pattern |
| # settings specific to one target do not affect another target. |
| |
| my $answer = $goal eq "mars" ? |
| "$parse_time_answer\n$build_time_answer\n" # From parse time and from "phobos" recipe. |
| . "$build_time_answer\n#MAKE#: 'mars' is up to date.\n" : # From "mars" recipe. |
| "$parse_time_answer\n$build_time_answer\n#MAKE#: 'phobos' is up to date.\n"; |
| |
| |
| run_make_test(" |
| # goal = $goal |
| # init = $init |
| # target = $target |
| # ga = $ga |
| # bovr = $bovr |
| # yovr = $yovr |
| # cmd = $cmd |
| # env = $env |
| # dashe = $dashe |
| |
| moon: hello=1 |
| moon: override hello+=2 |
| |
| $i |
| $ga |
| $target${bovr}hello+=blue |
| $target${yovr}hello+=yellow |
| |
| satur%: override hello:=3 |
| satur%: hello+=4 |
| |
| \$(info \$(hello)) |
| phobos:; \$(info \$(hello)) |
| mars: phobos; \$(info \$(hello)) |
| saturn:; \$(info \$(hello)) |
| ", "$dashe $cmd $goal", "$answer"); |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| # Preferably, we would want to run the tests below for all the combinations, |
| # generated by the loop above. However, that causes the test to take a lot of |
| # time. |
| |
| # The fix for sv 64822 went to recursively_expand_for_file. |
| # There are three code paths that lead to recursively_expand_for_file. |
| # - export of a variable to target environment. |
| # - expansion of a substitution reference. |
| # - other expansions of a variable that was appended to. |
| # Test target env, substitution reference in parse and build modes.; |
| # Also test a mix of pattern and target specific definitions and appends. |
| |
| run_make_test(q! |
| al%: hello=file |
| al%: hello+=one |
| all: hello+=two |
| $(info $(hello)) |
| all:; $(info $(hello)) |
| !, "", "\nfile one two\n#MAKE#: 'all' is up to date.\n"); |
| |
| run_make_test(q! |
| hello=file |
| al%: hello+=one |
| all: hello+=two |
| $(info $(hello:X=Y)) |
| all:; $(info $(hello:X=Y)) |
| !, "", "file\nfile one two\n#MAKE#: 'all' is up to date.\n"); |
| |
| run_make_test(q! |
| hello=file |
| al%: hello+=one |
| all: hello+=two |
| export hello |
| $(info $(shell echo $$hello)) |
| all:; $(info $(shell echo $$hello)) |
| !, "", "file\nfile one two\n#MAKE#: 'all' is up to date.\n"); |
| |
| # "phobos" inherits the value of "hello" from "mars". On top of that there are |
| # also "phobos" specific appends. |
| for my $goal (@goals) { |
| my $answer = $goal eq "mars" ? |
| "\nminit mone mtwo pone ptwo\n" # From parse time and from "phobos" recipe. |
| . "minit mone mtwo\n#MAKE#: 'mars' is up to date.\n" : # From "mars" recipe. |
| "\npone ptwo\n#MAKE#: 'phobos' is up to date.\n"; # From parse time and from "phobos" recipe. |
| |
| run_make_test(" |
| mar%: hello=minit |
| mar%: hello+=mone |
| mars: hello+=mtwo |
| phobo%: hello+=pone |
| phobos: hello+=ptwo |
| \$(info \$(hello)) |
| phobos:; \$(info \$(hello)) |
| mars: phobos; \$(info \$(hello)) |
| ", "$goal", "$answer"); |
| } |
| |
| # This test is similar to the one above. The difference is that here there is a |
| # pattern-specific definition of "hello" that matches "phobos". |
| run_make_test(q! |
| mar%: hello:=minit |
| mar%: hello+=mone |
| mars: hello+=mtwo |
| phobo%: hello:=pinit |
| phobo%: hello+=pone |
| phobos: hello+=ptwo |
| $(info $(hello)) |
| phobos:; $(info $(hello)) |
| mars: phobos; $(info $(hello)) |
| !, 'phobos', "\npinit pone ptwo\n#MAKE#: 'phobos' is up to date.\n"); |
| |
| # Test pattern and target specific appends to a global variable that has origin override. |
| # sv 36486. |
| my @ops = ('=', '+=', ':='); |
| @inits = ('', 'override ', 'al%: override '); |
| @specificities = ('', 'all: ', 'al%: '); |
| for my $init (@inits) { |
| for my $spec (@specificities) { |
| for my $op (@ops) { |
| |
| my $build_time_answer = ''; |
| if ($init =~ ':' and $op eq '+=' and !$spec) { |
| # This is the case where global variable obtains value 'one two three' at |
| # parse time and later at build time a pattern or target specific |
| # 'hello+=file' appends 'file'. |
| # e.g. |
| # al%: override hello+=file |
| # hello+=one |
| # hello+=two |
| # hello+=three |
| $build_time_answer = 'one two three file'; |
| } elsif ($init =~ 'override') { |
| $build_time_answer = 'file'; |
| } else { |
| $build_time_answer = 'file one two three'; |
| } |
| |
| my $parse_time_answer = $init =~ ':' ? '' : 'file'; |
| if (!$spec and ($init ne 'override ')) { |
| $parse_time_answer .= ' ' if $parse_time_answer; |
| $parse_time_answer .= 'one two three'; |
| } |
| |
| run_make_test(" |
| ${init}hello${op}file |
| ${spec}hello+=one |
| ${spec}hello+=two |
| ${spec}hello+=three |
| \$(info \$(hello)) |
| all:; \$(info \$(hello)) |
| ", "", "$parse_time_answer\n$build_time_answer\n#MAKE#: 'all' is up to date.\n"); |
| } |
| } |
| } |
| |
| 1; |