GNU make yields "commands commence before first target" error

MakefileGnu

Makefile 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

enter image description here

So, you should remove the whitespaces at the end and apply the same spaces with the same action. e.g: tab like the following;

enter image description here

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAlex ReynoldsView Question on Stackoverflow
Solution 1 - MakefileSimon RichterView Answer on Stackoverflow
Solution 2 - MakefileCiro Santilli Путлер Капут 六四事View Answer on Stackoverflow
Solution 3 - MakefileRobGajulaView Answer on Stackoverflow
Solution 4 - MakefilehbceylanView Answer on Stackoverflow