# -*-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;