1

I have a single line Makefile that throws the following error: Makefile:1: *** missing separator. Stop. I know there are dozens of duplicate questions with the same error message but most of them suggest something to do with using not using tabs or mysterious special characters.

$ cat -e -v -t Makefile 
set -e$

$ make
Makefile:1: *** missing separator.  Stop.

As far as I can see, there are no mysterious special characters. Perhaps there are characters that cat -e -v -t doesn't show?

The following works, so I'm guessing it isn't an issue with my make installation:

$ cat -v -e -t Makefile 
foo:$
^Iecho "Foo"$

$ make
echo "Foo"
Foo

Some relevant version and shell information.

$ make --version
GNU Make 3.81

$ echo $0
-bash

Edit: See comment by @AProgrammer

Note it throws the same error message regardless of what I have below the set -e.

$ cat -e -v -t Makefile 
set -e$
$
foo:$
^Iecho "foo"$

$ make
Makefile:1: *** missing separator.  Stop.

Edit 2:

Note adding #!/bin/bash throws the same error message.

$ cat -e -v -t Makefile 
#!/bin/bash$
set -e$
$
foo:$
^Iecho "foo"$

$ make
Makefile:2: *** missing separator.  Stop.

Edit 3:

Running set -e on my shell directly seems to work (it exits the failed make call as expected).

$ set -e
$ make
Makefile:2: *** missing separator.  Stop.
Saving session...completed.
Deleting expired sessions...11 completed.

[Process completed]
Kent Shikama
  • 3,910
  • 3
  • 22
  • 55
  • 1
    What do you expect the first Makefile to do? – AProgrammer Dec 17 '19 at 15:05
  • Nothing. But even if I add anything below it, it throws the same error message. – Kent Shikama Dec 17 '19 at 15:06
  • @AProgrammer Please see my edit for an example. – Kent Shikama Dec 17 '19 at 15:09
  • 2
    `set -e` at that position in a Makefile in a syntax error. It is difficult to explain how to fix it without knowing what you want that to do. (`set -e` is a shell command, but a Makefile is not a shell script and you can't specify at one place initialization for all the shell invocations by make). – AProgrammer Dec 17 '19 at 15:17
  • @AProgrammer Maybe I'm missing something but can I not write `set -e` and expect `bash` to immediately exit if there is a non-zero exit code when I run `make`? Are you referring to the fact that I'm missing `#!/bin/bash`? Note I tried that too and it gives the same error. – Kent Shikama Dec 17 '19 at 15:23

1 Answers1

2

There is absolutely no reason for which make would be able to interpret arbitrary shell commands outside of rules.

If you want to exit rules immediately when there is an error, there are several ways to do it, more or less portably.

First, each line in a rule is executed by a separate instance of the shell. This means that if you don't merge them manually (with \ and ;), you'll get the behavior you want if you have one command per line.

Then you can use set -e as part of the probably few rules which need it. For instance;

foo:
        set -e; for i in a b c d; mkdir $$i; done

With GNU Make, you can change the flags used to call the shell, additionally passing -e:

.SHELLFLAGS=-ec

With POSIX Make, you can change the shell. I don't know if passing a flag is supported, but it seems so with GNU Make:

SHELL=/bin/sh -e

but you can always pass a wrapper which set the flags as you want:

SHELL=/path/to/mywrapper

with mywrapper being

#!/bin/sh
exec /bin/sh -e "$@"
AProgrammer
  • 51,233
  • 8
  • 91
  • 143
  • I now see what you meant by "a Makefile is not a shell script" earlier. It took a while to click. Thanks for your help. – Kent Shikama Dec 17 '19 at 16:01