| # -*-perl-*- | |
| $description = 'Test the $(shell ...) function.'; | |
| $details = ''; | |
| # Test standard shell | |
| run_make_test('.PHONY: all | |
| OUT := $(shell echo hi) | |
| all: ; @echo $(OUT) | |
| ','','hi'); | |
| # Test shells inside rules. | |
| run_make_test('.PHONY: all | |
| all: ; @echo $(shell echo hi) | |
| ','','hi'); | |
| # Verify .SHELLSTATUS | |
| run_make_test('.PHONY: all | |
| PRE := $(.SHELLSTATUS) | |
| $(shell exit 0) | |
| OK := $(.SHELLSTATUS) | |
| $(shell exit 1) | |
| BAD := $(.SHELLSTATUS) | |
| all: ; @echo PRE=$(PRE) OK=$(OK) BAD=$(BAD) | |
| ','','PRE= OK=0 BAD=1'); | |
| # Test unescaped comment characters in shells. Savannah bug #20513 | |
| run_make_test(q! | |
| FOO := $(shell echo '#') | |
| foo: ; echo '$(FOO)' | |
| !, | |
| '', "echo '#'\n#\n"); | |
| # Test that exported variables are passed to $(shell ...) | |
| $ENV{FOO} = 'baz'; | |
| run_make_test(q! | |
| OUT = $(shell echo $$FOO) | |
| foo: ; @echo '$(OUT)' | |
| !, | |
| '', 'baz'); | |
| $ENV{FOO} = 'baz'; | |
| run_make_test(q! | |
| FOO = bar | |
| OUT = $(shell echo $$FOO) | |
| foo: ; @echo '$(OUT)' | |
| !, | |
| '', 'bar'); | |
| run_make_test(q! | |
| export FOO = bar | |
| OUT = $(shell echo $$FOO) | |
| foo: ; @echo '$(OUT)' | |
| !, | |
| '', 'bar'); | |
| # Test shells inside exported environment variables, simply expanded. | |
| run_make_test(' | |
| export HI := $(shell echo hi) | |
| .PHONY: all | |
| all: ; @echo $$HI | |
| ', | |
| '','hi'); | |
| # Test shells inside exported environment variables. See SV 10593 | |
| run_make_test(' | |
| export HI = $(shell echo hi) | |
| .PHONY: all | |
| all: ; @echo $$HI | |
| ', | |
| '',"hi"); | |
| $ENV{HI} = 'foo'; | |
| run_make_test(' | |
| HI = $(shell echo hi) | |
| .PHONY: all | |
| all: ; @echo $$HI | |
| ', | |
| '',"hi"); | |
| $ENV{HI} = 'foo'; | |
| run_make_test(' | |
| HI = $(shell echo hi) | |
| bad := $(HI) | |
| .PHONY: all | |
| all: ; @echo $$HI $(bad) | |
| ', | |
| '',"hi hi"); | |
| # SV 63016: Exported variable that contains a variable containing $(shell...) | |
| run_make_test(' | |
| HI = $(shell echo hi) | |
| export bad = $(HI) | |
| .PHONY: all | |
| all:; : $(HI) | |
| ', | |
| '',": hi"); | |
| $ENV{HI} = 'outer'; | |
| run_make_test(' | |
| export HI = $(shell echo $$HI) | |
| .PHONY: all | |
| all:; @echo $$HI | |
| ', | |
| '',"outer"); | |
| $ENV{HI} = 'outer'; | |
| run_make_test(' | |
| export HI = $(shell echo $$HI) | |
| .PHONY: all | |
| all:; : $(HI) | |
| ', | |
| '',": outer"); | |
| if ($port_type ne 'W32') { | |
| # Test shell errors in recipes including offset | |
| # This needs to be ported to Windows, or else Windows error messages | |
| # need to converted to look like more normal make errors. | |
| run_make_test(' | |
| .RECIPEPREFIX = > | |
| all: | |
| >@echo hi | |
| >$(shell ./basdfdfsed there) | |
| >@echo $(.SHELLSTATUS) | |
| ', | |
| '', "#MAKE#: ./basdfdfsed: $ERR_no_such_file\nhi\n127\n"); | |
| run_make_test(' | |
| $(shell ./basdfdfsed where) | |
| all: ; @echo $(.SHELLSTATUS) | |
| ', | |
| '', "#MAKE#: ./basdfdfsed: $ERR_no_such_file\n127\n"); | |
| # Test SHELLSTATUS for kill. | |
| # This test could be ported to Windows, using taskkill ... ? | |
| # Figure out the exit code for SIGINT | |
| my $pid = fork(); | |
| if (! $pid) { | |
| exec('kill -2 $$') or die "exec: Cannot execute sleep\n"; | |
| } | |
| waitpid($pid, 0); | |
| # .SHELLSTATUS for a signal gives 128 + the signal number | |
| my $ret = $?; | |
| if ($ret > 255) { | |
| # Solaris 10 perl 5.8.4 puts signal number + 128 into the high 8 bits. | |
| $ret >>= 8; | |
| } | |
| if ($osname ne 'os390') { | |
| $ret |= 128; | |
| } | |
| run_make_test('.PHONY: all | |
| $(shell kill -2 $$$$) | |
| STAT := $(.SHELLSTATUS) | |
| all: ; @echo STAT=$(STAT) | |
| ','',"STAT=$ret\n"); | |
| # Test that not-found errors can be redirected | |
| if ($ERR_command_not_found) { | |
| $_ = $ERR_command_not_found; | |
| s/#CMDNAME#/bad-command/g; | |
| run_make_test(q! | |
| out := $(shell bad-command 2>&1) | |
| all: ; @echo '$(.SHELLSTATUS): $(out)' | |
| !, | |
| '', "127: $_\n"); | |
| } | |
| # If we're using pipes for jobserver, then we will close them and not | |
| # allow them to be available to sub-makes invoked via $(shell ...) | |
| if (exists $FEATURES{'jobserver'}) { | |
| run_make_test(q! | |
| ifeq ($(ELT),) | |
| default:; @$(MAKE) -f #MAKEFILE# ELT=1 | |
| else ifeq ($(ELT),1) | |
| OUTPUT := $(shell $(MAKE) -f #MAKEFILE# ELT=2) | |
| $(info $(OUTPUT)) | |
| default:;: $(ELT) | |
| else | |
| default:;: $(ELT) | |
| endif | |
| !, | |
| '--no-print-directory -j2 --jobserver-style=pipe', "#MAKE#[2]: warning: jobserver unavailable: using -j1 (add '+' to parent make rule)\n: 2\n: 1"); | |
| } | |
| # This crashes if we use vfork and don't reset environ properly | |
| run_make_test(q! | |
| export PATH = $(shell echo "tests:$$PATH") | |
| foo = $(shell echo yes) | |
| all:;echo $(foo) | |
| !, | |
| '', "echo yes\nyes\n"); | |
| } | |
| # If we're not using pipes for jobserver, then they are available in sub-makes | |
| # invoked by $(shell ...) | |
| if ($port_type eq 'W32' || exists $FEATURES{'jobserver-fifo'}) { | |
| run_make_test(q! | |
| ifeq ($(ELT),) | |
| default:; @$(MAKE) -f #MAKEFILE# ELT=1 | |
| else ifeq ($(ELT),1) | |
| OUTPUT := $(shell $(MAKE) -f #MAKEFILE# ELT=2) | |
| $(info $(OUTPUT)) | |
| default:;: $(ELT) | |
| else | |
| default:;: $(ELT) | |
| endif | |
| !, | |
| '--no-print-directory -j2', ": 2\n: 1"); | |
| } | |
| # sv 65323. Check for bash, because such long variable name causes ksh to | |
| # segfault. | |
| if (-x '/bin/bash') { | |
| # sv 65172. | |
| # Buffer overrun in recursively_expand_for_file on a variable with a long | |
| # name. | |
| my $v = "a1234567890" x 4 x 1000; | |
| run_make_test(" | |
| SHELL:=/bin/bash | |
| export $v=\$(shell echo hello) | |
| all:; \@echo \$\$$v | |
| ", '', "hello\n"); | |
| } | |
| 1; |