aboutsummaryrefslogtreecommitdiff
path: root/testsuite/make.tests
diff options
context:
space:
mode:
Diffstat (limited to 'testsuite/make.tests')
-rwxr-xr-xtestsuite/make.tests765
1 files changed, 765 insertions, 0 deletions
diff --git a/testsuite/make.tests b/testsuite/make.tests
new file mode 100755
index 000000000..376bdcc15
--- /dev/null
+++ b/testsuite/make.tests
@@ -0,0 +1,765 @@
1#!/bin/sh
2
3. ./testing.sh
4unset MAKEFLAGS
5rm -rf make.tempdir
6
7# testing "test name" "command" "expected result" "file input" "stdin"
8
9testing "make basic makefile" \
10 "make -f -" "target\n" "" '
11target:
12 @echo target
13'
14
15testing "make .DEFAULT rule for prerequisite" \
16 "make -f - 2>/dev/null" "source\n" "" '
17.DEFAULT:
18 @echo $@
19target: source
20'
21
22mkdir make.tempdir && cd make.tempdir || exit 1
23touch target.xyz
24testing "make empty command overrides inference rule" \
25 "make -f - target 2>/dev/null" "" "" '
26.SUFFIXES: .xyz
27.xyz:
28 @echo xyz
29target: ;
30'
31cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
32
33# Macros should be expanded before suffix substitution. The suffixes
34# can be obtained by macro expansion.
35testing "make macro expansion and suffix substitution" \
36 "make -f -" "src1.o src2.o\n" "" '
37DOTC = .c
38DOTO = .o
39SRC1 = src1.c
40SRCS = $(SRC1) src2.c
41target:
42 @echo $(SRCS:$(DOTC)=$(DOTO))
43'
44
45# Indeed, everything after the <colon> can be obtained by macro
46# macro expansion.
47testing "make macro expansion and suffix substitution 2" \
48 "make -f -" "src1.o src2.o\n" "" '
49DOTS = .c=.o
50SRC1 = src1.c
51SRCS = $(SRC1) src2.c
52target:
53 @echo $(SRCS:$(DOTS))
54'
55
56# It should be possible for an inference rule to determine that a
57# prerequisite can be created using an explicit rule.
58mkdir make.tempdir && cd make.tempdir || exit 1
59testing "make inference rule with explicit rule for prerequisite" \
60 "make -f -" "touch x.p\ncat x.p >x.q\n" "" '
61.SUFFIXES: .p .q
62x.q:
63x.p:
64 touch $@
65.p.q:
66 cat $< >$@
67'
68cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
69
70# Austin Group defect report 875 clarifies certain aspects of the
71# behaviour of inference rules. Study of this resulted in a number
72# of changes to pdpmake, though this test passed anyway.
73mkdir make.tempdir && cd make.tempdir || exit 1
74touch test.j test.k
75testing "make proper handling of inference rules 1" \
76 "make -f -" \
77 ".j.l\n" "" '
78.SUFFIXES: .j .k .l
79.j.l:
80 @echo .j.l
81.k.l:
82 @echo .k.l
83test.l: test.k
84test.j:
85test.k:
86'
87cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
88
89# There was a bug where the failure of a build command didn't result
90# in make returning a non-zero exit status.
91testing "make return error if command fails" \
92 "make -f - >/dev/null 2>&1; test \$? -gt 0 && echo OK" "OK\n" "" '
93target:
94 @exit 42
95'
96
97# An equal sign in a command on a target rule was detected as a
98# macro assignment.
99testing "make equal sign in inline command" \
100 "make -f -" "a = a\n" "" '
101a = a
102target:;@echo a = $(a)
103'
104
105# Ensure an inline command on a target rule can be detected even if
106# the semicolon is obfuscated.
107testing "make equal sign in obfuscated inline command" \
108 "make -f -" "a = a\n" "" '
109a = a
110semi = ;
111target:$(semi)@echo a = $(a)
112'
113
114# When a build command fails and the '-k' option has been provided
115# (continue execution on error) no further commands should be executed
116# for the current target.
117testing "make failure of build command with -k" \
118 "make -k -f - 2>/dev/null" "OK\n" "" '
119all: bar baz
120bar:
121 @echo OK
122 @false
123 @echo Not reached
124baz:
125 @:
126'
127# Build commands with a '+' prefix are executed even with the -q option.
128testing "make execute build command with + prefix and -q" \
129 "make -q -f - 2>/dev/null" "OK\n" "" '
130all: bar
131bar:
132 @+echo OK
133'
134
135# The -t option touches files that are out-of-date unless the target
136# has no commands or they're already up-to-date.
137mkdir make.tempdir && cd make.tempdir || exit 1
138touch baz
139testing "make check -t option" \
140 "make -t -f - 2>/dev/null" "touch bar\n" "" '
141all: foo bar baz
142foo:
143bar:
144 @echo bar
145baz:
146 @echo baz
147'
148cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
149
150# Build commands with a '+' prefix are executed even with the -t option.
151mkdir make.tempdir && cd make.tempdir || exit 1
152testing "make execute build command with + prefix and -t" \
153 "make -t -f - 2>/dev/null" "OK\n" "" '
154all: bar
155bar:
156 @+echo OK
157'
158cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
159
160# A macro created using ::= remembers it's of type immediate-expansion.
161# Immediate expansion also occurs when += is used to append to such a macro.
162testing "make appending to immediate-expansion macro" \
163 "make -f -" \
164 "hello 1 2 3\nhello 4 4\n" "" '
165world = 1
166hello ::= hello $(world)
167world = 2
168hello += $(world)
169world = 3
170hello += $(world)
171world = 4
172
173world = 1
174reset ::= hello $(world)
175world = 2
176# No longer immediate-expansion
177reset = hello $(world)
178world = 3
179reset += $(world)
180world = 4
181
182target:
183 @echo $(hello)
184 @echo $(reset)
185'
186
187# Since GNU make and bmake interpret := macro assignments differently,
188# POSIX has ::= for the GNU variant and :::= for BSD.
189testing "make different styles of := macro assignment" \
190 "make -f -" \
191 '65 a a $A\n' "" '
192A = a
193GNU ::= $A
194BSD1 :::= $A
195BSD2 :::= $$A
196A = 65
197
198target:
199 @echo '\''$(A) $(GNU) $(BSD1) $(BSD2)'\''
200'
201
202# Similar to the above but for macro assignments on the command line.
203# POSIX has ::= for the GNU variant and :::= for BSD.
204testing "make := macro assignment on command line" \
205 "make -f - A=a 'GNU::=\$A' 'BSD1:::=\$A' 'BSD2:::=\$\$A' A=65" \
206 '65 a a $A\n' "" '
207target:
208 @echo '\''$(A) $(GNU) $(BSD1) $(BSD2)'\''
209'
210
211# basic pattern macro expansion
212testing "make basic pattern macro expansion" \
213 "make -f -" \
214 "obj/util.o obj/main.o\n" "" '
215SRC = src/util.c src/main.c
216OBJ = $(SRC:src/%.c=obj/%.o)
217
218target:
219 @echo $(OBJ)
220'
221
222# pattern macro expansion; match any value
223testing "make pattern macro expansion; match any value" \
224 "make -f -" \
225 "any_value.o\n" "" '
226SRC = any_value
227OBJ = $(SRC:%=%.o)
228
229target:
230 @echo $(OBJ)
231'
232
233# pattern macro expansion with empty rvalue
234testing "make pattern macro expansion with empty rvalue" \
235 "make -f -" \
236 "\n" "" '
237SRC = util.c main.c
238OBJ = $(SRC:%.c=)
239
240target:
241 @echo $(OBJ)
242'
243
244# pattern macro expansion with multiple <percent> in rvalue
245# POSIX requires the first <percent> to be expanded, others
246# may or may not be expanded. Permit either case.
247testing "make pattern macro expansion with multiple <percent> in rvalue" \
248 "make -f - | sed 's/mainmainmain/main%%/'" \
249 "main%%\n" "" '
250SRC = main.c
251OBJ = $(SRC:%.c=%%%)
252
253target:
254 @echo $(OBJ)
255'
256
257# pattern macro expansion; zero match
258testing "make pattern macro expansion; zero match" \
259 "make -f -" \
260 "nsnp\n" "" '
261WORD = osop
262REPL = $(WORD:os%op=ns%np)
263
264target:
265 @echo $(REPL)
266'
267
268# Check that MAKE will contain argv[0], e.g make in this case
269testing "make basic MAKE macro expansion" \
270 "make -f -" \
271 "make\n" "" '
272target:
273 @echo $(MAKE)
274'
275
276# Check that MAKE defined as environment variable will overwrite default MAKE
277testing "make MAKE macro expansion; overwrite with env macro" \
278 "MAKE=hello make -f -" \
279 "hello\n" "" '
280target:
281 @echo $(MAKE)
282'
283
284# Check that MAKE defined on the command-line will overwrite MAKE defined in
285# Makefile
286testing "make MAKE macro expansion; overwrite with command-line macro" \
287 "make -f - MAKE=hello" \
288 "hello\n" "" '
289MAKE = test
290
291target:
292 @echo $(MAKE)
293'
294
295# POSIX draft states that if make was invoked using relative path, MAKE must
296# contain absolute path, not just argv[0]
297testing "make MAKE macro expansion; turn relative path into absolute" \
298 "../runtest-tempdir-links/make -f -" \
299 "ok\n" "" '
300target:
301 @test -e "$(MAKE)" && test "$(MAKE)" = "$$(env which make)" && echo ok
302'
303
304# $? contains prerequisites newer than target, file2 in this case
305# $^ has all prerequisites, file1 and file2
306touch -t 202206171200 file1
307touch -t 202206171201 target
308touch -t 202206171202 file2
309testing "make compare \$? and \$^ internal macros" \
310 "make -f -" \
311 "file2\nfile1 file2\n" "" '
312target: file1 file2
313 @echo $?
314 @echo $^
315'
316rm -f target file1 file2
317
318# Phony targets are executed (once) even if a matching file exists.
319# A .PHONY target with no prerequisites is ignored.
320touch -t 202206171201 target
321testing "make phony target" \
322 "make -f -" \
323 "phony\n" "" '
324.PHONY: target
325.PHONY:
326target:
327 @echo phony
328'
329rm -f target
330
331# Phony targets aren't touched with -t
332testing "make phony target not touched" \
333 "make -t -f - >/dev/null && test -f target && echo target" \
334 "" "" '
335.PHONY: target
336target:
337 @:
338'
339rm -f target
340
341# Include files are created or brought up-to-date
342mkdir make.tempdir && cd make.tempdir || exit 1
343testing "make create include file" \
344 "make -f -" \
345 "made\n" "" '
346target:
347 @echo $(VAR)
348mk:
349 @echo "VAR = made" >mk
350include mk
351'
352cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
353
354# Include files are created or brought up-to-date even when the -n
355# option is given.
356mkdir make.tempdir && cd make.tempdir || exit 1
357testing "make create include file even with -n" \
358 "make -n -f -" \
359 "echo made\n" "" '
360target:
361 @echo $(VAR)
362mk:
363 @echo "VAR = made" >mk
364include mk
365'
366cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
367
368# Failure to create an include file isn't an error. (Provided the
369# include line is ignoring non-existent files.)
370testing "make failure to create include file is OK" \
371 "make -f -" \
372 "OK\n" "" '
373target:
374 @echo OK
375mk:
376 @:
377-include mk
378'
379
380# $^ skips duplicate prerequisites, $+ doesn't
381mkdir make.tempdir && cd make.tempdir || exit 1
382touch file1 file2 file3
383testing "make skip duplicate entries in \$^ but not \$+" \
384 "make -f -" \
385 "file1 file2 file3\nfile1 file2 file2 file3 file3\n" "" '
386target: file1 file2 file2 file3 file3
387 @echo $^
388 @echo $+
389'
390cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
391
392# Assign the output of a shell command to a macro.
393testing "make shell assignment" \
394 "make -f -" \
395 "1 2 3 4\n" "" '
396hello != echo 1; echo 2; echo 3; echo; echo
397
398target:
399 @echo "$(hello) 4"
400'
401
402# Nested macro expansion is allowed. This should be compatible
403# with other implementations.
404testing "make nested macro expansion" \
405 "make -f -" "0 bc\n1 d\n2\n3\n4 bcd\n5 bcd\n" "" '
406a = b
407b = c
408c = d
409$(a:.q=.v)$(b:.z=.v) = bc
410bcd = bcd
411target:
412 @echo 0 $(bc)
413 @echo 1 $($($(a)))
414 @echo 2 $($(a) $(b) $(c))
415 @echo 3 $($a $b $c)
416 @echo 4 $($(a)$(b)$(c))
417 @echo 5 $($a$b$c)
418'
419
420# .WAIT is allowed as a prerequisite. Since parallel builds aren't
421# implemented it doesn't have any effect.
422mkdir make.tempdir && cd make.tempdir || exit 1
423touch file1 file2
424testing "make .WAIT is allowed as a prerequisite" \
425 "make -f -" \
426 "file1 file2\n" "" '
427target: file1 .WAIT file2
428 @echo $?
429'
430cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
431
432# Escaped newlines inside macro expansions in commands get different
433# treatment than those outside. In POSIX 2017 the output is 'a b ab'.
434testing "make replace escaped NL in macro in command with space" \
435 "make -f -" \
436 "a b a b\n" "" '
437M=word
438N=${M:word=a\\
439b}
440target:
441 @echo ${N} ${M:word=a\\
442b}
443'
444
445# The CURDIR macro is supported in POSIX 2024.
446testing "make CURDIR macro" \
447 "make -f -" \
448 "OK\n" "" '
449target:
450 @test "$(CURDIR)" = "$$(pwd -P)" && echo OK
451'
452# The CURDIR environment variable doesn't affect the macro
453export CURDIR=/you/are/here
454testing "make CURDIR macro not affected by environment" \
455 "make -f -" \
456 "OK\n" "" '
457target:
458 @test "$(CURDIR)" != "/you/are/here" && echo OK
459'
460
461# The -e option makes the CURDIR macro match the environment
462testing "make with -e CURDIR macro is affected by the environment" \
463 "make -e -f -" \
464 "/you/are/here\n" "" '
465target:
466 @echo $(CURDIR)
467'
468unset CURDIR
469
470# The fix for an equal sign in an inline command on a target rule broke
471# a complex chain of macro assignments generated by autotools.
472testing "make complex chain of macro assignments" \
473 "make -f -" "flag 1\n" "" '
474FLAG_ = $(FLAG_$(VALUE))
475FLAG_0 = flag 0
476FLAG_1 = flag 1
477MYFLAG = $(FLAG_$(VALUE))
478VALUE = 1
479
480target:
481 @echo $(MYFLAG)
482'
483
484# POSIX 2024 permits additional characters in macro and target names
485testing "make allow - and / in target names, - in macro names" \
486 "make -f -" \
487 "/hello\nhel-lo\nmac-ro\n" "" '
488target: ./hello hel-lo
489 @echo $(mac-ro)
490./hello:
491 @echo /hello
492hel-lo:
493 @echo hel-lo
494mac-ro = mac-ro
495'
496
497testing "make double-colon rule" \
498 "make -f -" "target1\ntarget2\n" "" '
499target::
500 @echo target1
501target::
502 @echo target2
503'
504
505# There was a bug whereby the modification time of a file created by
506# double-colon rules wasn't correctly updated. This test checks that
507# the bug is now fixed.
508mkdir make.tempdir && cd make.tempdir || exit 1
509touch -t 202206171200 file1
510touch -t 202206171201 intermediate
511touch -t 202206171202 target
512touch -t 202206171203 file2
513testing "make target depends on prerequisite updated by double-colon rule" \
514 "make -f -" \
515 "file2\n" "" '
516target: intermediate
517 @cat intermediate
518intermediate:: file1
519 @echo file1 >>intermediate
520intermediate:: file2
521 @echo file2 >>intermediate
522'
523cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
524
525# Use chained inference rules to determine prerequisites.
526mkdir make.tempdir && cd make.tempdir || exit 1
527touch target.p
528testing "make chained inference rules" \
529 "make -s -f - target.s" \
530 "target.q\ntarget.r\ntarget.s\n" "" '
531.SUFFIXES: .p .q .r .s
532.p.q:
533 @cp $< $*.q
534 @echo $*.q
535.q.r:
536 @cp $< $*.r
537 @echo $*.r
538.r.s:
539 @cp $< $*.s
540 @echo $*.s
541'
542cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
543
544# make supports *, ? and [] wildcards in targets and prerequisites
545mkdir make.tempdir && cd make.tempdir || exit 1
546touch -t 202206171201 t1a t2aa t3b
547touch s1a s2aa s3b
548testing "make expand wildcards in filenames" \
549 "make -f - t1a t2aa t3b" \
550 "t1a s1a s2aa s3b\nt2aa s1a s2aa s3b\nt3b s1a s2aa s3b\n" "" '
551t1? t2* t3[abc]: s1? s2* s3[abc]
552 @echo $@ $?
553'
554cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
555
556# A '#' character in a macro expansion doesn't start a comment
557testing "make hash in macro expansion isn't a comment" \
558 "make -f -" \
559 ": hash # hash\n" "" '
560HASH = hash
561hash = $(HASH:hash=#)
562target:
563 : hash $(hash) hash
564'
565
566# A '#' character can be escaped with a backslash
567testing "make backslash-escaped hash isn't a comment" \
568 "make -f -" \
569 ": hash # hash\n" "" '
570hash = \\#
571target:
572 : hash $(hash) hash
573'
574
575# A '#' character in a command line doesn't start a comment
576testing "make hash in command line isn't a comment" \
577 "make -f -" \
578 ": hash # hash\n" "" '
579target:
580 : hash # hash
581'
582
583# Austin Group defect report 875 (mentioned above) actually used
584# suffixes '.a .b .c'. This doesn't matter in POSIX mode but it
585# caused a failure (now fixed) when chained inference rules were
586# allowed. The '.a.c' and the built-in '.c.a' inference rules
587# resulted in a loop.
588mkdir make.tempdir && cd make.tempdir || exit 1
589touch test.a test.b
590testing "make proper handling of inference rules 2" \
591 "make -f -" \
592 ".a.c\n" "" '
593.SUFFIXES: .a .b .c
594.a.c:
595 @echo .a.c
596.b.c:
597 @echo .b.c
598test.c: test.b
599test.a:
600test.b:
601'
602cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
603
604# Don't use the shell -e option when running commands.
605testing "make no shell -e option when running commands" \
606 "make -f -" "OK\n" "" '
607target:
608 @false; echo OK
609'
610
611# Macros and targets may be mixed on the command line
612testing "make allow mixed macros and targets" \
613 "make -f - FOO=foo foo BAR=bar bar" "foo\nbar\nfoo\nbar\n" "" '
614foo:
615 @echo $(FOO)
616 @echo $(BAR)
617bar:
618 @echo $(FOO)
619 @echo $(BAR)
620'
621
622# $* and $< are supported for target rules
623mkdir make.tempdir && cd make.tempdir || exit 1
624touch src.c src.h
625testing 'make support $* and $< for target rules' \
626 "make -f -" "src.c src.h\nsrc.o\nsrc\nsrc.c\n" "" '
627src.o: src.c src.h
628 @echo "$?"
629 @echo "$@"
630 @echo "$*"
631 @echo "$<"
632'
633cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
634
635# ifeq/ifneq conditionals are supported
636testing 'make support ifeq and ifneq conditionals' \
637 "make -f -" "A OK\nB OK\n" "" '
638A = a
639B = b
640target:
641ifeq ($(A),a)
642 @echo A OK
643else
644 @echo A not OK
645endif
646ifneq "a" "$B"
647 @echo B OK
648endif
649'
650
651# An empty original suffix indicates that every word should have
652# the new suffix added. If neither suffix is provided the words
653# remain unchanged.
654testing "make macro expansion and suffix substitution 3" \
655 "make -f -" "src1.c src2.c\nsrc1 src2\n" "" '
656SRCS = src1 src2
657target:
658 @echo $(SRCS:=.c)
659 @echo $(SRCS:=)
660'
661
662# Skip duplicate entries in $? and $^
663mkdir make.tempdir && cd make.tempdir || exit 1
664touch -t 202206171200 file1 file3
665touch -t 202206171201 target
666touch -t 202206171202 file2
667testing "make skip duplicate entries in \$? and \$^" \
668 "make -f -" \
669 "file2\nfile1 file2 file3\n" "" '
670target: file1 file2 file2 file3 file3
671 @echo $?
672 @echo $^
673'
674cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
675
676# Skip duplicate entries in $? and $^, with each double-colon rule
677# handled separately
678mkdir make.tempdir && cd make.tempdir || exit 1
679touch -t 202206171200 file1 file3
680touch -t 202206171201 target
681touch -t 202206171202 file2
682testing "make skip duplicate entries: double-colon rules" \
683 "make -f -" \
684 "file2\nfile1 file3 file2\nfile2\nfile2 file3\n" "" '
685target:: file1 file3 file1 file2 file3
686 @echo $?
687 @echo $^
688target:: file2 file3 file3
689 @echo $?
690 @echo $^
691'
692cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
693
694# Skip duplicate entries in $? and $^, with each double-colon rule
695# handled separately. No prerequisites out-of-date in the first.
696mkdir make.tempdir && cd make.tempdir || exit 1
697touch -t 202206171200 file1 file3
698touch -t 202206171201 target
699touch -t 202206171202 file2
700testing "make skip duplicate entries: double-colon rules, only second invoked" \
701 "make -f -" \
702 "file2\nfile2 file3\n" "" '
703target:: file1 file3 file1 file3
704 @echo $?
705 @echo $^
706target:: file2 file3 file3
707 @echo $?
708 @echo $^
709'
710cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
711
712# .DEFAULT rules with no commands or some prerequisites are ignored.
713# .DEFAULT rules with commands can be redefined.
714testing "make: .DEFAULT rule" \
715 "make -f - default" "default2\n" "" '
716.DEFAULT: ignored
717.DEFAULT:
718 @echo default1
719.DEFAULT:
720 @echo default2
721target:
722'
723
724testing "make: double-colon rule" \
725 "make -f -" "target1\ntarget2\n" "" '
726target::
727 @echo target1
728target::
729 @echo target2
730'
731
732# Double-colon rules didn't work properly if their target was phony:
733# - they didn't ignore the presence of a file matching the target name;
734# - they were also invoked as if they were a single-colon rule.
735mkdir make.tempdir && cd make.tempdir || exit 1
736touch -t 202206171200 file1
737touch -t 202206171201 target
738testing "make phony target of double-colon rule" \
739 "make -f - 2>&1" \
740 "unconditional\nconditional\n" "" '
741.PHONY: target
742target::
743 @echo unconditional
744target:: file1
745 @echo conditional
746file1:
747 @touch file1
748'
749cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
750
751# GNU make and BSD make don't allow the use of inference rules
752# for phony targets. In POSIX mode the output is "phony.xyz\n".
753mkdir make.tempdir && cd make.tempdir || exit 1
754touch phony.xyz
755testing "make don't use inference rule for phony target" \
756 "make -f -" "make: nothing to be done for phony\n" "" '
757.PHONY: phony
758.SUFFIXES: .xyz
759.xyz:
760 @echo $<
761phony:
762'
763cd .. || exit 1; rm -rf make.tempdir 2>/dev/null
764
765exit $FAILCOUNT