Reputation: 4891
I have a makefile
that I want to run against both linux (debian/Ubuntu) and Windows/Cygwin.
I need to do something slightly different according to the running environment and I came out with the following piece of code which is supposed to store in the variable a string which is foo
if the OS is linux, otherwise foo.exe
:
EXECUTABLE_FILENAME=bash -c 'os_type=`uname`; if [ $os_type == "Linux" ]; then echo "foo"; else echo "foo.exe"; fi'
then I would like to use that variable in another one, something like:
GODEPBUILD=$(godep go build -o $(EXECUTABLE_FILENAME))
the previous one with/without the evaluation via $(...some stuff...)
(see below for all the tests I made to make this work)
finally I would like to "run" that command somewhere else in a task within the makefile
, something like:
build-all:
@echo -e "build my project"
$(GODEPBUILD)
I have tried many different combinations
$(some stuff here)
,'
,bash -c '...some commands here...'
but I get all sorts of bash errors e.g.:
invalid option -- 'c'
go
compiler complaining EXECUTABLE_FILENAME
is empty with this message: flag needs an argument: -o
$(GODEPBUILD)
(I believe because somehow it evaluates to an empty command)I am doing this chain of steps because I need to wrap many commands of the go
toolchain into another tool called godep
, also I need to combine this with some specific features of the Operating System (e.g. the filename thing I am stuck with). I have defined many different "commands" of the go
toolchain at the beginning of the makefile
e.g.:
GODEP_VERSION=godep version
GODEPRESTORE=godep restore
GODEPTEST=godep go test -v
GOCLEAN=go clean
I call these "commands" inside the makefile
tasks like $(GODEP_VERSION)
(or -$(GODEP_VERSION)
if I need to ignore the stderr
) and for me it was nice to add the "build command" in a similar fashion.
The make
version is:
Is this thing possible at all?
How could I achieve this combination of different "small scripts" to build the final command that make
should run inside a task?
Upvotes: 0
Views: 693
Reputation: 171273
Surely you want the output of the bash command as the filename, right? You are using the bash command itself as the filename. i.e. $(EXECUTABLE_FILENAME)
is a string consisting of several words. When you pass that to the godep
command it gets passed as multiple arguments:
godep go build -o $(EXECUTABLE_FILENAME)
becomes:
godep go build -o bash -c 'os_type=`uname`; if [ s_type == "Linux" ]; then echo "foo"; else echo "foo.exe"; fi'
which is complete nonsense (note that $o
gets expanded as a make variable, but that's the least of your problems).
Surely you want to run the bash command to decide the filename. You can run a shell command with make's $(shell ...)
function:
EXECUTABLE_FILENAME = $(shell os_type=`uname` ; if [ $$os_type == Linux ]; then echo foo ; else echo foo.exe ; fi)
Note I used $$os_type
to refer to a shell variable, so make doesn't try to expand $os_type
before invoking the shell.
But I would simplify that to something like:
EXECUTABLE_FILENAME = foo$(shell [ `uname` == Linux ] || echo .exe)
Or maybe:
EXECUTABLE_SUFFIX = $(shell [ `uname` == Linux ] || echo .exe)
EXECUTABLE_FILENAME = foo$(EXECUTABLE_SUFFIX)
Now the make variable $(EXECUTABLE_FILENAME)
will expand to the filename.
The next problem is here:
GODEPBUILD=$(godep go build -o $(EXECUTABLE_FILENAME))
What is this supposed to mean? Why have you enclosed it in $(...)
? That tries to run a make
function called godep
, surely you just want:
GODEPBUILD = godep go build -o $(EXECUTABLE_FILENAME)
Then when you use it in the recipe it will expand to either:
build-all:
@echo -e "build my project"
godep go build -o foo
Or:
build-all:
@echo -e "build my project"
godep go build -o foo.exe
N.B. as an optional (but recommended) improvement you should use :=
to set make variables, because otherwise they get expanded every time they are used. This would mean that every time you refer to a variable that uses $(EXECUTABLE_SUFFIX)
the shell command is run again. Changing it to use :=
will mean it gets evaluated once:
EXECUTABLE_SUFFIX := $(shell [ `uname` == Linux ] || echo .exe)
Similarly, you can use :=
for the other variables too:
EXECUTABLE_FILENAME := foo$(EXECUTABLE_SUFFIX)
GODEPBUILD := godep go build -o $(EXECUTABLE_FILENAME)
(These ones don't really matter, as long as EXECUTABLE_SUFFIX
used :=
and so already contains the filename).
Upvotes: 1