Reputation: 1
Error : Makefile:12: *** recipe commences before first target. Stop.
My makefile:
objDir := obj
incDir := include
srcDir := src
binDir := bin
files := matrix palindrome encryption
define generateObject
@nasm -f elf32 -o $(objDir)/$(1).o $(srcDir)/$(1).asm
endef
object: $(addprefix $(srcDir)/,$(addsuffix .asm,$(files)))
@echo -n "Generating object files... "
$(foreach file,$(files),$(eval $(call generateObject,$(file))))
@echo "Done"
I read in a post that this could be due to unwanted whitespace/tab but i could not find any.
I tried cat -e -t -v Makefile
and the output was :
objDir := obj$
incDir := include$
srcDir := src$
binDir := bin$
files := matrix palindrome encryption$
$
define generateObject$
^I@nasm -f elf32 -o $(objDir)/$(1).o $(srcDir)/$(1).asm$
endef$
$
object: $(addprefix $(srcDir)/,$(addsuffix .asm,$(files)))$
^I@echo -n "Generating object files... "$
^I$(foreach file,$(files),$(eval $(call generateObject,$(file))))$
^I@echo "Done"$
Upvotes: 0
Views: 3574
Reputation: 101111
Your problem is use of the eval
function. eval
is used to parse make constructs, but you're passing it a shell command. Consider this line:
$(foreach file,$(files),$(eval $(call generateObject,$(file))))
Each time through the list you'll call generateObject
with a filename. That will expand to a shell command; for example if file
is matrix then call
will expand to:
^I@nasm -f elf32 -o obj/matrix.o src/matrix.asm
Then you take that text string and pass it to eval
which tries to read that as a makefile. Note that the text passed to eval
must be a complete and valid makefile in itself; it's like you invoked make recursively and gave it this string as a makefile, except that the result of parsing are applied to the current makefile. You can't give eval just a part of a valid makefile (like one command line in a recipe) and have it insert that into the current makefile. Because that line by itself isn't valid, you get this error.
Instead of running eval
on the results you want to concatenate them into one shell command. Try this:
define generateObject
nasm -f elf32 -o $(objDir)/$(1).o $(srcDir)/$(1).asm
endef
object: $(addprefix $(srcDir)/,$(addsuffix .asm,$(files)))
@echo -n "Generating object files... "
@$(foreach file,$(files),$(call generateObject,$(file)) && ) true
@echo "Done"
However, that's really not "the make way". You don't want to build multiple targets within a single rule: that defeats the main point of make which is that it only rebuilds the files that are out of date.
You should write your makefile like this:
object: $(files:%=$(objDir)/%.o)
$(objDir)/%.o : $(srcDir)/%.asm
@nasm -f elf32 -o $@ $<
You don't need the generateObject
variable, or call
, or eval
, or even foreach
.
Upvotes: 1