Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Makefile all command

Tags:

makefile

I'm in the process of learning c, and trying to get my head around makefiles. I'm following Learn C the Hard way.

On exercise 2, the extra credit states to make a command in my makefile that allows me to compile my .c file by typing just "make".

My makefile is:

CLAGS=-WALL -g

all: ex1

clean:
    rm ex1

This works - i.e. typing make clean removes the ex1 file, and typing make compiles ex1.c into an executable.

However, I'm confused as to why in the clean command, rm ex1 has to be indented on the line below clean, but for the all command, if I indent ex1 on the line below all, it throws an error. Why is this?

My other question is - how exactly does this work? Is all just a keyword that goes along the lines of "when make (with no command) is typed, do this"?

Any help is appreciated.

Thanks.


2 Answers

This:

clean:
    rm ex1

is a rule. This rule contains a single command, rm ex1. The command is a shell command. Each command in the rule must be indented with a TAB character (or Make will get confused).

This:

all: ex1

is a rule without commands. The "ex1" here is not a command, it is a prerequisite.

This:

all:
    ex1

is an invalid rule, because it contains an invalid command; "ex1" is not a valid shell command. (Just try it on the command line if you don't believe me.)

If you execute Make without specifying a target (by typing "make"), Make will use the default target, which is usually the first target in the makefile. (There are some exceptions you need not worry about now.) By convention, "all" is the name of rule that does most of what you want done, and it is often the default target; this is a convention, not something built into Make.

like image 158
Beta Avatar answered Feb 09 '26 05:02

Beta


Because ex1 is a target that defaults to calling cc over a ex1.c file, you could make all: a target like this too

all:
    $(CC) -o $(EXECUTABLE) $(CFLAGS) $(LDFLAGS) ex1.c

don't copy and paste this, because i've used spaces and Makefiles require tabs instead.

An even better way would be to create an object files target and compiling only changed files while linking in the other target, like this

CC      = gcc
CFLAGS  = -Wall -Wextra -Werror
LDFLAGS = # empty if you are not going to link to any library
OBJ     = ex1.o
PROGRAM = ex1

all: $(OBJ)
    $(CC) $(CFLAGS) $(LDFLAGS) -o $(PROGRAM) $(OBJ)

%.o: %.c
    $(CC) $(CFLAGS) -c $<

clean:
    rm -fv *.o $(PROGRAM)

now you would easily add more .c files by just appending them to the OBJ macro, like this

OBJ = ex1.o ex2.o ... exn.o
like image 24
Iharob Al Asimi Avatar answered Feb 09 '26 05:02

Iharob Al Asimi



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!