4

This is related to How to trace Makefile targets for troubleshooting? I'm working on an old PowerMac G5. It is alive because I use it for testing older compilers and big-endian, PowerPC.

I'm trying to determine which line in a makefile is causing unexpected EOF while looking for matching ``'. Our makefile does not use the backtick (we added them for testing this issue); and trial/error and guessing is moving too slow for a makefile with 1000's of lines.

When I run make with --debug, it fails to print line numbers:

$ make --debug=a
GNU Make 3.82
Built for powerpc-apple-darwin9.8.0
...

Reading makefiles...
Reading makefile `GNUmakefile'...
bash: -c: line 0: unexpected EOF while looking for matching ``'
bash: -c: line 1: syntax error: unexpected end of file
bash: -c: line 0: unexpected EOF while looking for matching ``'
bash: -c: line 1: syntax error: unexpected end of file
bash: -c: line 0: unexpected EOF while looking for matching ``'
bash: -c: line 1: syntax error: unexpected end of file
bash: -c: line 0: unexpected EOF while looking for matching ``'
bash: -c: line 1: syntax error: unexpected end of file
Updating makefiles...
...

make --help does not appear to discuss it:

$ make --help 2>&1 | grep -i line
$

My first question is, how do I tell GNU make to print line numbers?

My second question is, how is a program that has been around as long as make has so lame with respect to debug support?

jww
  • 97,681
  • 90
  • 411
  • 885
  • 2
    A better trick might be to set `SHELL='bash -x'` – tripleee Jan 02 '18 at 06:34
  • Your makefile _does_ use the backtick: `SUNCC_VERSION := $(subst \`,',$(shell $(CXX) -V 2>&1))` . Moreover it is a bit unfair to blame make for being the steering program of tools which sometimes simply aren't working well together on their own responsibility. The problem comes from make not stopping execution when a `$(shell )` call emits an error state - the thing is that there are good reasons for it not to stop; in the cases where you have an unknown architecture/OS under you it is equally unpleasant to stop at every command line which is valid for config X but not for Y. – Vroomfondel Jan 02 '18 at 09:56
  • 1
    As a practical hint you can insert `$(error Stopped here)` in all those `$(shell ...)` trickeries that you makefile is doing in the first hundred lines and do a binary search to find the first erroneous shell invocation. When you found it you can emit the incriminating invocation by doing a `$(info ..)` before the `$(shell )` to see how the string looks like which is handed over to bash. – Vroomfondel Jan 02 '18 at 10:01
  • @Vroomfondel - The `subst` command was added a hour ago in case it was causing problems. It was one of the areas something may have happened 4 times like in the make output. But it is a pretty crummy way to troubleshoot. The question still stands: how do I have make print each line as it executes. – jww Jan 02 '18 at 10:17
  • Ad "trial&error guessing": the broken command line surely happens during the first scan of the makefile and therefore a binary search (that is, insert the error directive I proposed at 50%, then 25% or 75% etc. of the file) is sure to pin down the problem within a few runs - no rule needs to be executed. This is a matter of minutes. – Vroomfondel Jan 02 '18 at 12:55

2 Answers2

2

These errors are not being printed by make. They are being printed by the shell. As far as make is concerned, there are no errors here, so it won't print any tracing information.

Without seeing the makefile we can't be sure but almost certainly the problem is in $(shell ...script...) statements, where the ...script... has a syntax error. I assume your shell scripts are contained in make variables, which makes it difficult to see exactly what is being sent to the shell and whether it has a syntax error.

I agree that GNU make doesn't have good debugging for this: when debugging is enabled it should be printing details about the script that is invoked by the shell function and where it was invoked from (in the makefile).

I think @Vroomfondel has the best idea; add in $(info ...) messages to your makefile near likely-looking $(shell ...) invocations, like:

$(info starting shell: $(SCRIPT))
OUT := $(shell $(SCRIPT))

Using binary searching you should be able to pin it down pretty quickly even in a very long makefile.

MadScientist
  • 92,819
  • 9
  • 109
  • 136
1

You could try make --trace (at least with GNU make 4), or consider using remake (a variant of make capable of debugging), as remake -x.

For debugging complex Makefile-s, using remake is quite handy

You could consider using other build automation tools, e.g. ninja.

If you use GNU make, you'll better upgrade it to a newer version (and enable Guile extensions when configuring it).

Linux: find ./makefile_dir -mtime -10, see which file changed: foo.c, then grep -n foo.c Makefile and see line number in Makefile

Community
  • 1
  • 1
Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547