GNU make yields "commands commence before first target" error
MakefileGnuMakefile Problem Overview
In my makefile, I would like to check for the existence of a library and give an informative error message. I created a conditional that should exit the make process when the file is not found:
9: ifeq ($(${JSONLIBPATH}),)
10: JSONLIBPATH = ${ALTJSONLIBDIR}/${LIBJSON}
11: endif
12: ifeq ($(${JSONLIBPATH}),)
13: $(error JSON library is not found. Please install libjson before building)
14: endif
My makefile gets stuck on line 13:
Makefile:13: *** commands commence before first target. Stop.
After line 13, my makefile has its targets.
I tried putting this conditional block into a target (e.g. a target called isJSONLibraryInstalled
) but this does not execute correctly.
How would I check for a file's existence and handle the error case, before processing targets? Apologies if this is a dumb question.
Makefile Solutions
Solution 1 - Makefile
First of all, you are looking at the contents of a variable that is named after the current path, which is probably not what you want. A simple environment variable reference is $(name)
or ${name}
, not $(${name})
. Due to this, line 13 is always evaluated.
Second, I think it is choking on the indentation of the $(error ...)
expression. While the expression resolves to an empty string, there is still a tab character at the start of the line, which indicates a command, which in turn cannot exist outside a rule.
I think using spaces rather than tabs to indent would work.
Solution 2 - Makefile
When you get Make error messages, always check the Error message documentation
On GNU Make 3.81 (error
appears to have been removed from newer versions), it says:
> This means the first thing in the makefile seems to be part of a command script: it begins with a TAB character and doesn't appear to be a legal make command (such as a variable assignment). Command scripts must always be associated with a target.
What makes matters more confusing is that "doesn't appear to be a legal make command" part. That explains why in:
a := b
$(error a)
the error happens at line 2 and not 1: make
simply accepts statements that it can parse, like the assignment, so the following works:
a := b
a:
echo $a
Note: SO currently converts tabs to spaces in code, so you can't just copy the above code into your editor.
Solution 3 - Makefile
For me it was an unnecessary white space before the connector that was causing this. On slickEdit I selected the option to view all special character and noticed the black sheep.
Solution 4 - Makefile
You can check whitespaces, spaces and tabs by using VSCode [View > Render Whitespace]
As you can see;
- command-1 has a tab (->) and whitespace at the end
- command-2 has space at first
- command-3/4 has tab+spaces
So, you should remove the whitespaces at the end and apply the same spaces with the same action. e.g: tab like the following;