Asked  7 Months ago    Answers:  5   Viewed   38 times

I am getting the following error running make:

Makefile:168: *** missing separator.  Stop.

What is causing this?

 Answers

67

As indicated in the online manual, the most common cause for that error is that lines are indented with spaces when make expects tab characters.

Correct

target: 
tcmd

where t is TAB (U+0009)

Wrong

target:
....cmd

where each . represents a SPACE (U+0020).

Tuesday, June 1, 2021
 
pwaring
answered 7 Months ago
22

make has a very stupid relationship with tabs. All actions of every rule are identified by tabs. And, no, four spaces don't make a tab. Only a tab makes a tab.

To check, I use the command cat -e -t -v makefile_name.

It shows the presence of tabs with ^I and line endings with $. Both are vital to ensure that dependencies end properly and tabs mark the action for the rules so that they are easily identifiable to the make utility.

Example:

Kaizen ~/so_test $ cat -e -t -v  mk.t
all:ll$      ## here the $ is end of line ...                   
$
ll:ll.c   $
^Igcc  -c  -Wall -Werror -02 c.c ll.c  -o  ll  $@  $<$ 
## the ^I above means a tab was there before the action part, so this line is ok .
 $
clean :$
   rm -fr ll$
## see here there is no ^I which means , tab is not present .... 
## in this case you need to open the file again and edit/ensure a tab 
## starts the action part
Tuesday, June 1, 2021
 
lewiguez
answered 7 Months ago
45
  1. In your average package, those files each have an individual purpose. This is concordant with the unix philosophy of "each program should do one thing and do that thing well". In most projects, you'll see files like:

    • configure
    • configure.ac
    • Makefile
    • Makefile.in
    • Makefile.am
    • install-sh
    • INSTALL

    configure is (usually) a shell script that checks your system for all required features before building anything. Makefile.in is a template for a Makefile. The results of the configure tests are substituted into Makefile.in to generate Makefile. This is to deal with people having things (compilers, headers, libraries) in obscure paths, cross-compiling (e.g., building for ARM on x86), optional library support (some programs have additional features that can be switched on or off), compiling with different options, and so on. Writing a one-size-fits-all Makefile is actually really hard.

    As you've noticed, the configure script itself is a mess. It's not meant to be seen by mortal eyes, nor edited by mortal hands. It's actually the result of compiling configure.ac, using a program called autoconf. autoconf is a package of macros for and a wrapper around the m4 macro processor, which was about the only good tool for this sort of thing at the time (autoconf is really quite old software, but has aged remarkably well). autoconf lets the developer easily write tests to check for headers, libraries or programs that are required to build the software (and this changes from program to program).

    If you dig a little deeper, you'll notice that Makefile.in also tends to be a little ugly. This is because writing good Makefiles is often a lot of boilerplate, and that's inspired another tool, automake. automake compiles Makefile.am (which is often short and declarative) into Makefile.in (which is enormous), which is then compiled into Makefile by configure (essentially).

    install-sh is a script that is distributed with automake but copied into other packages. It exists as a replacement if the version of install on the system is crap (install copies files into the installation directory. Some really old systems had broken versions of install, and automake is pretty conservative about dropping warnings for old systems). Some other scripts that fulfil similar roles are compile, depcomp and ylwrap.

    INSTALL is just a document that describes how to install the package. It's usually boilerplate content copied into the package by automake.

  2. I've answered this inline above, but here is the summary:

    • configure.ac ==[autoconf]=> configure
    • Makefile.am ==[automake]=> Makefile.in ==[configure]=> Makefile

    Where the program responsible is inside the arrow. To understand this in detail, I recommend this autotools tutorial. Don't be put off by the page count, most of it is diagrams appearing piece by piece.

  3. Wildcards in Makefiles are sometimes used. GNU Make, for example, supports a $(wildcard) function, where you can write something like:

    SOURCES := $(wildcard src/*.c)

    The main reason features like $(wildcard) aren't used is that they are extensions, and automake tries very hard to generate Makefiles that will work with any POSIX-compliant make. After a project becomes mature, the list of files to compile doesn't change all that much, anyway.

    A second reason files are listed explicitly is when programs get optional features. Wildcards are no longer appropriate, and you instead have to list the conditions under which additional features are to be compiled in.

  4. A Makefile tracks dependencies between files, where a shell script cannot (not without significant effort, anyway).

If you have a Makefile rule like:

foo.out: foo.in
        generate-foo foo.in

It tells make that if foo.in is newer than foo.out, a new foo.out can be created by executing generate-foo foo.in. This saves lots of redundant work on big projects, where you might only change one or two files between recompilations.

Your bonus question appears a little ill-posed. The most common make is probably GNU Make, although I'd guess that the BSD make would be a close second, followed by the various proprietary make versions supplied with Solaris, AIX and so on.

These all accept the same basic structure in Makefile (because POSIX says so), but might have vendor-specific extensions to the syntax.

GCC is not a build tool like make. GCC is a command-line compiler, akin to cl.exe on windows.

Tuesday, August 10, 2021
 
user1865027
answered 4 Months ago
20

Line 18 is gcc -fPIC -g -c -Wall mymemory.cpp. Make is expecting a separator, typically :. It's not detecting this line as a command. You mistyped the intendation: you have spaces where you should have a tab.

Good editors highlight makefile lines that begin with spaces but look like they should begin with a tab instead.

Wednesday, August 11, 2021
 
RajaReddy PolamReddy
answered 4 Months ago
35

Because make only processes the first target (goal). To do both add this as the first rule:

all: f1 f2
Sunday, August 29, 2021
 
hnkk
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share