I have the following in my GNU Makefile around Line 73:
RELEASE ?= $(shell $(UNAME) -r)
IS_FEDORA22_i686 = $(shell echo $(RELEASE) | $(EGREP) -i -c "fc22.i686")
It runs fine on BSDs, Linux (Ubuntu and Fedora), OS X and Solaris. However, on Cygwin and MinGW, it produces the following (thanks cxw). Cygwin and MinGW use the Bash shell:
/bin/sh: -c: line 0: syntax error near unexpected token `('
/bin/sh: -c: line 0: `echo 2.0.4(0.287/5/3) | egrep -i -c "fc22.i686"'
From the manual and 6.2 The Two Flavors of Variables, I think I need a variable like:
RELEASE ?::= $(shell $(UNAME) -r)
How do I make a variable both optional an "simply expandable"?
One way would be:
RELTEXT:=$(<whatever command>)
RELEASE?=$(RELTEXT)
Even though RELEASE isn't simply expandable, you know it will always expand to fixed text.
Related
I am using this Amazon Linux 2 AMI on an EC2 instance: amazon/amzn2-ami-hvm-2.0.20210525.0-x86_64-gp2
This Makefile works fine:
.SHELLFLAGS := -euo pipefail -c
SHELL := bash
all:
echo here
When I run make all I get:
bash-4.2$ make all
echo here
here
Then I add .ONESHELL: to the Makefile:
.ONESHELL:
.SHELLFLAGS := -euo pipefail -c
SHELL := bash
all:
echo here
Now when I run make all I get:
bash-4.2$ make all
echo here
bash: line 0: bash: echo here: invalid option name
make: *** [all] Error 2
Bash version:
GNU bash, version 4.2.46(2)-release (x86_64-koji-linux-gnu)
Make version:
GNU Make 3.82
Built for x86_64-koji-linux-gnu
If I remove the .SHELLFLAGS it will run successfully so it seems like a combination of the two is the problem. It also appears that with ONESHELL, the SHELLFLAGS are getting corrupted.
It's a bug in make 3.82, fixed in 4.0. When both .ONESHELL and .SHELLFLAGS is used, the flags are not tokenized correctly.
You need to either drop one of the two or upgrade your make (possibly outside your distribution).
I have a Makefile as follows (excerpt):
# be a POSIX guy!
SHELL = /bin/dash
# avoid accursed tabs
.RECIPEPREFIX +=
PROJECT = my_project
# before-commit stuff
CHANGED_FILES = $(shell git ls-files --modified)
files ?= $(CHANGED_FILES)
lint:
pyflakes $(files)
lint-all:
pyflakes $(PROJECT)
STAGING_DB_PORT = 5437
staging-db-start:
ssh -fNL 0.0.0.0:$(STAGING_DB_PORT):localhost:$(STAGING_DB_PORT) staging-db
ss -tlpn sport eq :$(STAGING_DB_PORT)
staging-db-stop:
ssh -O check staging-db
ssh -O stop staging-db
ss -tlpn sport eq :$(STAGING_DB_PORT)
staging-db-check:
ss -tlpn sport eq :$(STAGING_DB_PORT)
ssh -O check staging-db
.PHONY: lint, lint-all, staging-db-start, staging-db-stop, staging-db-check
When I run target, say staging-db-check it works just fine. Although, when I run target lint, it fails with error:
Makefile:2:9: invalid syntax
SHELL = /bin/dash
^
For me, it is very strange. I read docs, they say that you always must set SHELL variable, so I decided to do so. But I can not figure out where there is an error?
I have GNU make, version 4.2.1.
GNU Make never generates diagnostics of form of:
Makefile:2:9: invalid syntax
SHELL = /bin/dash
^
But pyflakes does, which is the program run by your lint target's recipe:
lint:
pyflakes $(files)
As you know, pyflakes lints Python source files. Your $(files), as assigned
by:
# before-commit stuff
CHANGED_FILES = $(shell git ls-files --modified)
files ?= $(CHANGED_FILES)
expands to a list of files that includes Makefile. Your Makefile is not
a Python source file and the first line in Makefile that is not syntactically
valid Python is:
SHELL = /bin/dash
Here's a shorter makefile:
Makefile
# be a POSIX guy!
SHELL = /bin/dash
.PHONY: all
all:
echo "Hello World"
with which to reproduce your error:
$ pyflakes Makefile
Makefile:2:9: invalid syntax
SHELL = /bin/dash
^
Later
Is there a way to exclude non-python files from $files variable?
Yes. Assuming that Python files are files with the extension .py, change:
CHANGED_FILES = $(shell git ls-files --modified)
to:
CHANGED_FILES = $(filter %.py,$(shell git ls-files --modified))
See functions:
$(filter pattern...,text)
$(filter-out pattern...,text)
in 8.2 Functions for String Substitution and Analysis
in the GNU Make manual
And if you do that, maybe better change CHANGED_FILES to CHANGED_PYTHON_FILES.
I have a makefile including the following lines:
buildrepo:
#$(call make-repo)
define make-repo
for dir in $(C_SRCS_DIR); \
do \
mkdir -p $(OBJDIR)/$$dir; \
done
endef
On the line with the commands for dir in $(C_SRCS_DIR); \ I get the following error message:
"dir not expected at this moment"
make: *** [buildrepo] Error 255
I am using GNU make.
Can anybody tell me what is going wrong?
Actually this for ... in ... ; do ... done statement is a Unix command not a GNU make command, therefore I guess you are using a Windows machine (or any other one). You have to find the equivalent for your system.
But GNU make has a foreach function which works like this :
$(foreach dir,$(C_SRCS_DIR),mkdir -p $(OBJDIR)/$(dir);)
Also note that in your very specific case (not related to GNU make but to Windows) you can create all the dirs without a for/foreach loop, just like this :
mkdir -p $(addprefix $(OBJDIR)/,$(C_SRCS_DIR))
The pattern is a little unusual because I added the trailing "?(.*)" portion. It works on command line as I expected but I get a syntax error for the same in a script.
$ bash --version
GNU bash, version 4.3.11(1)-release (i686-pc-linux-gnu)
...
$ cat x.sh
touch a.so a.so.1
ls *.so?(.*)
rm *.so?(.*)
$ touch a.so a.so.1
$ ls *.so?(.*)
a.so a.so.1
$ rm *.so?(.*)
$ ls
x.sh
$ bash x.sh
x.sh: line 2: syntax error near unexpected token `('
x.sh: line 2: `ls *.so?(.*)'
$
You are using an extended glob but these aren't enabled by default within a script. In order to using them, they must be explicitly enabled. You can do so by adding this before the line:
shopt -s extglob
To disable them later on in the script, you can use shopt -u extglob.
As chepner rightly points out, this feature isn't enabled by default in the interactive shell, either. Presumably, this line is present either in one of your system-wide startup scripts or one of your personal ones.
On this line:
GCCVER:=$(shell a=`mktemp` && echo $'#include <stdio.h>\nmain() {printf("%u.%u\\n", __GNUC__, __GNUC_MINOR__);}' | gcc -o "$a" -xc -; "$a"; rm "$a")
I get:
*** unterminated call to function `shell': missing `)'. Stop.
What's wrong with my stupidly circuitous variable?
Update0
$ make --version
GNU Make 3.81
$ bash --version
GNU bash, version 4.2.8(1)-release (x86_64-pc-linux-gnu)
$ uname -a
Linux 2.6.38-10-generic #46-Ubuntu SMP x86_64 GNU/Linux
$ gcc --version
gcc (Ubuntu/Linaro 4.5.2-8ubuntu4) 4.5.2
when using $ for Bash inside a Makefile, you need to double them: $$a for example. I'm not familiar with the notation $' but I'll have to assume you know what you're doing with that. unless it's a Makefile construct, you need to double the dollar sign on that one too.
also, the hash sign # is terminating the shell expansion in Make's evaluation, which is why it never sees the right paren. escaping it helps, but I don't have it working quite right yet.
I'm debugging it by having two steps: first is setting GCCVER to be the list of commands without the enclosing $(shell), then in the 2nd step setting GCCVER := $(shell $(GCCVER)). you might want to try that too, commenting out the $(shell) step when it doesn't work, using export, and making a "set" recipe:
GCCVER := some commands here
#GCCVER := $(shell $(GCCVER)) # expand the commands, commented out now
export # all variables available to shell
set:
set # make sure this is prefixed by a tab, not spaces
Then:
make set | grep GCCVER
[update] this works:
GCCVER := a=`mktemp` && echo -e '\#include <stdio.h>\nmain() {printf("%u.%u\\n", __GNUC__, __GNUC_MINOR__);}' | gcc -o "$$a" -xc -; "$$a"; rm "$$a"
GCCVER := $(shell $(GCCVER))
export
default:
set
jcomeau#intrepid:/tmp$ make | grep GCCVER
GCCVER=4.6
And full circle, having gotten rid of the extra step:
jcomeau#intrepid:/tmp$ make | grep GCCVER; cat Makefile
GCCVER=4.6
GCCVER := $(shell a=`mktemp` && echo -e '\#include <stdio.h>\nmain() {printf("%u.%u\\n", __GNUC__, __GNUC_MINOR__);}' | gcc -o "$$a" -xc -; "$$a"; rm "$$a")
export
default:
set
Using the $' Bash construct:
jcomeau#intrepid:/tmp$ make | grep GCCVER; cat Makefile
GCCVER=4.6
GCCVER := $(shell a=`mktemp` && echo $$'\#include <stdio.h>\nmain() {printf("%u.%u\\n", __GNUC__, __GNUC_MINOR__);}' | gcc -o "$$a" -xc -; "$$a"; rm "$$a")
export
default:
set
Since your system doesn't work the same as mine, I'm going to cop out and say either use reinierpost's suggestion or, alternatively:
GCCVER := $(shell gcc -dumpversion | cut -d. -f1,2)