| # -*-perl-*- |
| |
| $description = "Test implicit rule search."; |
| |
| $details = ""; |
| |
| # sv 48643 |
| # Each test has a %.c rule ahead of %.f rule. |
| # hello.f exists and hello.c is missing. |
| |
| unlink('hello.c', 'hello.tsk', 'hello.o', 'hello.x'); |
| |
| # Run every test with and without a suffix. |
| my @suffixes = ('', '.o'); |
| # Run every test with single and double colon rules. |
| my @rules = ('', ':'); |
| |
| for my $s (@suffixes) { |
| for my $r (@rules) { |
| touch('hello.f'); |
| |
| # Test that make finds the intended implicit rule based on existence of a |
| # prerequisite in the filesystem. |
| # |
| # '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen. |
| run_make_test(" |
| all: hello$s |
| %$s:$r %.c; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| ", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'."); |
| |
| # Test that make finds the intended implicit rule based on the explicit |
| # prerequisite of the top goal and despite the existence of a |
| # prerequisite in the filesystem. |
| # |
| # hello.c is an explicit prerequisite of the top target (hello.o or hello). |
| # hello.c ought to exist. |
| # hello.c prerequisite causes '%.o: %.c' rule to be chosen. |
| run_make_test(" |
| hello$s: hello.c |
| %$s:$r %.c; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| ", '-r', |
| "#MAKE#: *** No rule to make target 'hello.c', needed by 'hello$s'. Stop.\n", |
| 512); |
| |
| # Test that make finds the intended implicit rule when the implicit |
| # prerequisite matches a target of an unrelated rule and despite the existence |
| # of a prerequisite of the other rule candidate in the filesystem. |
| # |
| # hello.c matches 'hello.c:' rule. This makes hello.c a target and thus ought |
| # to exist. |
| # hello.c prerequisite causes '%.o: %.c' rule to be chosen. |
| run_make_test(" |
| all: hello$s |
| %$s:$r %.c; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| hello.c:; @#HELPER# fail 1 |
| ", '-r', "fail 1\n#MAKE#: *** [#MAKEFILE#:5: hello.c] Error 1\n", 512); |
| |
| # Test that make finds the intended implicit rule based on existence of a |
| # prerequisite in the filesystem, even when the prerequisite of another |
| # candidate rule is mentioned explicitly on an unrelated rule. |
| # |
| # '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen, even though hello.c |
| # is mentioned explicitly on 'unrelated: hello.c'. |
| # ought-to-exist does not apply to hello.c. |
| run_make_test(" |
| all: hello$s |
| %$s:$r %.c; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| unrelated: hello.c |
| ", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'."); |
| |
| # Test that make finds the intended implicit rule based on existence of a |
| # prerequisite in the filesystem. |
| # |
| # '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen. |
| # Despite '%.o: %.c hello.c' rule having explicit prerequisite hello.c. |
| # ought-to-exist does not apply to hello.c. |
| run_make_test(" |
| all: hello$s |
| %$s:$r %.c hello.c; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| ", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'."); |
| |
| # '%.o: %.c' rule is skipped and '%.o: %.f' rule is chosen. |
| # '%.o: %.f hello.f' rule has explicit prerequisite hello.f. |
| # ought-to-exist does not apply to hello.c. |
| run_make_test(" |
| all: hello$s |
| %$s:$r %.c; \$(info hello.c) |
| %$s:$r %.f hello.f; \$(info hello.f) |
| ", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'."); |
| |
| # Rule '%: %.f' is chosen, because '%: %.f' requires no intermediates. |
| # '%: %.c', on the other hand, requires intemediate hello.c to be built by the |
| # default rule. |
| run_make_test(" |
| all: hello$s |
| %$s:$r %.c; \$(info \$<) |
| %$s:$r %.f; \$(info \$<) |
| .DEFAULT:; \$(info \$\@) true |
| unrelated: hello.c |
| ", '-r', "hello.f\n#MAKE#: Nothing to be done for 'all'."); |
| |
| |
| # hello.f is missing. |
| # This time both hello.c and hello.f are missing and both '%: %.c' and '%: %.f' |
| # require an intermediate. |
| # The default rule builds intemerdiate hello.c. |
| # '%: %.c' rule is chosen to build hello. |
| unlink('hello.f'); |
| run_make_test(" |
| all: hello$s |
| %$s:$r %.c; \$(info \$<) |
| %$s:$r %.f; \$(info \$<) |
| .DEFAULT:; \@\$(info \$\@) #HELPER# fail 1 |
| unrelated: hello.c |
| ", '-r', "hello.c\nfail 1\n#MAKE#: *** [#MAKEFILE#:5: hello.c] Error 1\n", 512); |
| |
| # hello.f is missing. |
| # No rule is found, because hello.c is not mentioned explicitly. |
| run_make_test(" |
| all: hello$s |
| %$s:$r %.c; \$(info \$<) |
| %$s:$r %.f; \$(info \$<) |
| .DEFAULT:; \@\$(info \$\@) #HELPER# fail 1 |
| ", '-r', "hello$s\nfail 1\n#MAKE#: *** [#MAKEFILE#:5: hello$s] Error 1\n", 512); |
| |
| } |
| } |
| |
| # Almost the same tests as above, but this time an intermediate is built. |
| |
| touch('hello.f'); |
| for my $s (@suffixes) { |
| for my $r (@rules) { |
| |
| my $result = "#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n"; |
| my $rcode = 512; |
| if ($s or $r) { |
| $result = "hello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'."; |
| $rcode = 0; |
| } |
| |
| run_make_test(" |
| all: hello.tsk |
| %.tsk: %$s; \$(info hello.tsk) |
| %$s:$r %.c; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| ", '-r', "$result", $rcode); |
| |
| run_make_test(" |
| all: hello.tsk |
| %.tsk: %$s hello$s; \$(info hello.tsk) |
| %$s:$r %.c; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| ", '-r', $result, $rcode); |
| |
| run_make_test(" |
| all: hello.tsk |
| %.tsk: %$s; \$(info hello.tsk) |
| %$s:$r %.c hello$s; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| ", '-r', $result, $rcode); |
| |
| } |
| } |
| |
| for my $r (@rules) { |
| |
| # Circular dependency hello.o <- hello.tsk is dropped. |
| run_make_test(" |
| all: hello.tsk |
| %.tsk: %.o; \$(info hello.tsk) |
| %.o:$r %.c; \$(info hello.c) |
| %.o:$r %.f %.tsk; \$(info hello.f) |
| ", '-r', |
| "#MAKE#: circular hello.o <- hello.tsk dependency dropped\nhello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'."); |
| |
| } |
| |
| |
| for my $s (@suffixes) { |
| for my $r (@rules) { |
| |
| run_make_test(" |
| all: hello.tsk |
| hello$s: hello.c |
| %.tsk: %$s; \$(info hello.tsk) |
| %$s:$r %.c; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| ", '-r', |
| "#MAKE#: *** No rule to make target 'hello.c', needed by 'hello$s'. Stop.\n", |
| 512); |
| } |
| } |
| |
| for my $s (@suffixes) { |
| for my $r (@rules) { |
| |
| my $result = "#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n"; |
| if ($s or $r) { |
| $result = "fail 1\n#MAKE#: *** [#MAKEFILE#:6: hello.c] Error 1\n"; |
| } |
| |
| run_make_test(" |
| all: hello.tsk |
| %.tsk: %$s; \$(info hello.tsk) |
| %$s:$r %.c; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| hello.c:; @#HELPER# fail 1 |
| ", '-r', $result, 512); |
| } |
| } |
| |
| |
| for my $s (@suffixes) { |
| for my $r (@rules) { |
| |
| run_make_test(" |
| all: hello.tsk |
| %.tsk: %$s; \$(info hello.tsk) |
| %$s:$r %.c; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| unrelated: hello$s |
| ", '-r', "hello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'."); |
| } |
| } |
| |
| for my $s (@suffixes) { |
| for my $r (@rules) { |
| |
| my $result = "#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n"; |
| my $rcode = 512; |
| if ($s or $r) { |
| $result = "hello.f\nhello.tsk\n#MAKE#: Nothing to be done for 'all'."; |
| $rcode = 0; |
| } |
| |
| run_make_test(" |
| all: hello.tsk |
| %.tsk: %$s; \$(info hello.tsk) |
| %$s:$r %.c; \$(info hello.c) |
| %$s:$r %.f hello.f; \$(info hello.f) |
| ", '-r', $result, $rcode); |
| } |
| } |
| |
| # One of the implicit rules has two prerequisites, hello.c and hello.x |
| # hello.c does not qualify as ought to exit. |
| # hello.x can be made from hello.z. |
| # This test exercises the break, which prevents making hello.x as an |
| # intermediate from hello.z during compatibility search. |
| unlink('hello.f'); |
| touch('hello.z'); |
| for my $s (@suffixes) { |
| for my $r (@rules) { |
| |
| run_make_test(" |
| all: hello.tsk |
| %.tsk: %$s; \$(info hello.tsk) |
| %$s:$r %.c %.x; \$(info hello.c) |
| %$s:$r %.f; \$(info hello.f) |
| unrelated: hello$s |
| %.x:$r %.z; \$(info hello.z) |
| ", '-r', |
| "#MAKE#: *** No rule to make target 'hello$s', needed by 'hello.tsk'. Stop.\n", |
| 512); |
| } |
| } |
| |
| # Test that prerequisite 'hello.x' mentioned explicitly on an unrelated rule is |
| # not considered intermediate. |
| touch('hello.tsk'); |
| unlink('hello.x'); |
| run_make_test(" |
| all: hello.tsk |
| %.tsk: %.x; touch hello.tsk |
| %.x: ; |
| unrelated: hello.x |
| ", '-r', "touch hello.tsk\n"); |
| unlink('hello.tsk'); |
| |
| touch ('hello.f'); |
| # Test implicit search of builtin rules. |
| |
| # %: %.c (and other builtin rules) are skipped. |
| # %: %.f is chosen. |
| run_make_test(q! |
| all: hello |
| !, 'FC="@echo f77" OUTPUT_OPTION=', "f77 hello.f -o hello\n"); |
| |
| # %.o: %.c (and other builtin rules) are skipped. |
| # %.o: %.f is chosen. |
| run_make_test(q! |
| all: hello.o |
| !, 'FC="@echo f77" OUTPUT_OPTION=', "f77 -c hello.f\n"); |
| |
| |
| # %: %.c is chosen. |
| # hello.c is an explicit prerequisite of the top target hello. |
| # hello.c ought to exist. |
| # hello.c prerequisite causes '%: %.c' rule to be chosen. |
| run_make_test(q! |
| hello: hello.c |
| !, 'FC="@echo f77" OUTPUT_OPTION=', |
| "#MAKE#: *** No rule to make target 'hello.c', needed by 'hello'. Stop.\n", |
| 512); |
| |
| # %.o: %.c is chosen. |
| # hello.c is an explicit prerequisite of the top target hello.o. |
| # hello.c ought to exist. |
| # hello.c prerequisite causes '%.o: %.c' rule to be chosen. |
| run_make_test(q! |
| hello.o: hello.c |
| !, 'FC="@echo f77" OUTPUT_OPTION=', |
| "#MAKE#: *** No rule to make target 'hello.c', needed by 'hello.o'. Stop.\n", |
| 512); |
| |
| # %: %.c (and other builtin rules) are skipped. |
| # %: %.f is chosen. |
| # ought-to-exist does not apply to hello.c. |
| run_make_test(q! |
| all: hello |
| unrelated: hello.c |
| !, 'FC="@echo f77" OUTPUT_OPTION=', "f77 hello.f -o hello\n"); |
| |
| # %.o: %.c (and other builtin rules) are skipped. |
| # %.o: %.f is chosen. |
| # ought-to-exist does not apply to hello.c. |
| run_make_test(q! |
| all: hello.o |
| unrelated: hello.c |
| !, 'FC="@echo f77" OUTPUT_OPTION=', "f77 -c hello.f\n"); |
| |
| # builtin rule %.o: %.f is removed. |
| # %.o: %.c (and other builtin rules) are skipped, because hello.c is missing. |
| # ought-to-exist does not apply to hello.c. |
| # %.o: %.c is chosen as a compatibility rule, because of hello.c. |
| run_make_test(q! |
| all: hello.o |
| unrelated: hello.c |
| %.o: %.f |
| !, '', |
| "#MAKE#: *** No rule to make target 'hello.c', needed by 'hello.o'. Stop.\n", |
| 512); |
| |
| |
| # sv 17752. |
| # In this test the builtin match-anything rule '%: %.f' is used to build |
| # intermediate hello from hello.f, because hello is mentioned explicitly in |
| # the makefile. |
| run_make_test(q! |
| all: hello.tsk |
| %.tsk: %; $(info $@ from $<) |
| unrelated: hello |
| !, 'FC="@echo f77" OUTPUT_OPTION=', |
| "f77 hello.f -o hello\nhello.tsk from hello\n"); |
| |
| # In this test the builtin match-anything rule %: %.f cannot be used to build |
| # intermediate hello from hello.f, because hello is not mentioned explicitly in |
| # the makefile. |
| run_make_test(q! |
| all: hello.tsk |
| %.tsk: %; $(info $@ from $<) |
| !, 'FC="@echo f77" OUTPUT_OPTION=', |
| "#MAKE#: *** No rule to make target 'hello.tsk', needed by 'all'. Stop.\n", |
| 512); |
| |
| # This is just like the one above, but compatibility rule '%.tsk: % %.x' has 2 |
| # prerequisites, '%' and '%.x'. |
| # '%' expands to 'hello' and matches the explicit 'hello' on the unrelated rule. |
| # '%.x' is an intermediate built from 'hello.xx' by rule '%.x: %.xx' during the |
| # second pass (intermed_ok == 1) of compatibility search. |
| # This test validates that compatibility search performs both intermed_ok == 0 |
| # and intermed_ok == 1 passes. |
| unlink('hello.x'); |
| touch('hello.xx'); |
| run_make_test(q! |
| all: hello.tsk |
| %.tsk: % %.x; $(info $@ from $^) |
| unrelated: hello |
| %.x: %.xx; $(info $@ from $<) |
| !, 'FC="@echo f77" OUTPUT_OPTION=', |
| "f77 hello.f -o hello\nhello.x from hello.xx\nhello.tsk from hello hello.x\n"); |
| |
| unlink('bye.o', 'bye.tsk', 'bye.x'); |
| # sv 21670. |
| # Default recipe is used to build bye.o. |
| run_make_test(q! |
| all: bye.tsk |
| %.tsk: %.o; $(info $@ from $<) |
| .DEFAULT:; $(info bye.o) |
| unrelated: bye.o |
| !, '-r', "bye.o\nbye.tsk from bye.o\n#MAKE#: Nothing to be done for 'all'."); |
| |
| touch('bye.xx'); |
| # This is just like the one above, but compatibility rule '%.tsk: %.o %.x' has 2 |
| # prerequisites, '%.o' and '%.x'. |
| # '%.o' expands to 'bye.o' and matches the explicit 'bye.o' on the unrelated rule. |
| # '%.x' is an intermediate built from 'bye.xx' by rule '%.x: %.xx' during the |
| # second pass (intermed_ok == 1) of compatibility search. |
| # This test validates that compatibility search performs both intermed_ok == 0 |
| # and intermed_ok == 1 passes. |
| run_make_test(q! |
| all: bye.tsk |
| %.tsk: %.o %.x; $(info $@ from $^) |
| .DEFAULT:; $(info bye.o) |
| unrelated: bye.o |
| %.x: %.xx; $(info $@ from $<) |
| !, '-r', |
| "bye.o\nbye.x from bye.xx\nbye.tsk from bye.o bye.x\n#MAKE#: Nothing to be done for 'all'."); |
| |
| unlink('hello.f', 'hello.z', 'hello.xx', 'bye.xx'); |
| |
| |
| # A target specific variable causes the file to be entered to the database as a |
| # prerequisite. Implicit search then treats this file as explicitly mentioned. |
| # Test that implicit search keeps target specific variables of this file intact. |
| # In this series of tests prerequisite 'hello.x' has a target specific variable |
| # and is built as an intermediate. Implicit search treats 'hello.x' as |
| # explicitly mentioned, but 'hello.x' does not qualify as ought-to-exist. |
| unlink('hello.x', 'hello.tsk'); |
| |
| # 'hello.x' is mentioned explicitly on the same implicit rule. |
| run_make_test(q! |
| all: hello.tsk |
| %.tsk: hello.x; $(info $@) |
| %.x:; $(flags) |
| hello.x: flags:=true |
| !, '-r', "true\nhello.tsk\n"); |
| |
| # Similar to the one above, but this time 'hello.x' is derived from the stem. |
| run_make_test(q! |
| all: hello.tsk |
| %.tsk: %.x; $(info $@) |
| %.x:; $(flags) |
| hello.x: flags:=true |
| !, '-r', "true\nhello.tsk\n"); |
| |
| # Similar to the one above, this time 'hello.x' is also mentioned explicitly on |
| # an unrelated rule. |
| run_make_test(q! |
| all: hello.tsk |
| %.tsk: %.x; $(info $@) |
| %.x:; $(flags) |
| hello.x: flags:=true |
| unrelated: hello.x |
| !, '-r', "true\nhello.tsk\n"); |
| |
| # 'hello.x' has a pattern specific variable. |
| run_make_test(q! |
| all: hello.tsk |
| %.tsk: %.x; $(info $@) |
| %.x:; $(flags) |
| %.x: flags:=true |
| !, '-r', "true\nhello.tsk\n"); |
| |
| # 'hello.x' has a target specific variable and a pattern specific variable. |
| run_make_test(q! |
| all: hello.tsk |
| %.tsk: %.x; $(info $@) |
| %.x:; $(flags) |
| hello.x: flags+=good |
| %.x: flags:=true |
| !, '-r', "true good\nhello.tsk\n"); |
| |
| # Intermediate prerequisite 'hello.x' has a target specific variable, a pattern |
| # specific variable, matches on both rules '%.tsk: %.x' and 'big_%.tsk: %.x'. |
| run_make_test(q! |
| all: hello.tsk big_hello.tsk |
| %.tsk: %.x; $(info $@) |
| big_%.tsk: %.x; $(info $@) |
| %.x:; $(flags) |
| hello.x: flags+=good |
| %.x: flags:=true |
| !, '-r', "true good\nhello.tsk\nbig_hello.tsk\n"); |
| |
| |
| # This tells the test driver that the perl test script executed properly. |
| 1; |