Reputation: 8998
I have the following structure for a project and I am just starting to introduce a Makefile to build the software:
├── Makefile
├── README.md
├── cg
│ └── cg.c
└── utilities
├── utilities.c
└── utilities.h
I am trying to put object files in a directory called obj yet I can't seem to get it working.
My makefile looks like:
CC=mpicc
CFLAGS=-O3 -std=c99
LIBS=
MKDIR_P = mkdir -p
make_build_dir:
@mkdir -p obj/
utilities.o: utilities/utilities.c
$(CC) $(CFLAGS) -o ./obj/$@ -c $<
cg.o: cg/cg.c
$(CC) $(CFLAGS) -o ./obj/$@ -c $<
.PHONY: make_build_dir
cg.exe: make_build_dir utilities.o cg.o
$(CC) $(CFLAGS) -o $@ $<
clean:
rm -fr obj
rm cg.exe
Yet this generates the following error:
a@a:b/b ‹master*›$ make cg.exe
mpicc -O3 -std=c99 -o ./obj/utilities.o -c utilities/utilities.c
mpicc -O3 -std=c99 -o ./obj/cg.o -c cg/cg.c
cg/cg.c:133:3: warning: implicit declaration of function 'decompose' is invalid in C99
[-Wimplicit-function-declaration]
decompose(num_chunks, chunks_per_rank,me, &settings);
^
1 warning generated.
mpicc -O3 -std=c99 -o cg.exe make_build_dir
clang: error: no such file or directory: 'make_build_dir'
make: *** [cg.exe] Error 1
How can I get it to generate the object files in the obj directory and then an executable in the top-level directory?
Upvotes: 0
Views: 399
Reputation: 3601
First of all, you need to make_build_dir
before making any *.o
or make
won't have a place to put them.
And you can make the Makefile
more generic.
.PHONY: all clean info
.DEFAULT_GOAL := all
SRC_DIRS = cg utilities
OBJ_DIR = obj
EXE = cg.exe
SOURCES = $(foreach path, $(SRC_DIRS), $(wildcard $(path)/*.c))
OBJECTS = $(addprefix $(OBJ_DIR)/, $(notdir $(SOURCES:%.c=%.o)))
$(OBJ_DIR)/%.o: */%.c
$(CC) $(CFLAGS) -o $@ -c $<
all: make_build_dir $(EXE)
info:
$(info SOURCES=$(SOURCES))
$(info OBJECTS=$(OBJECTS))
make_build_dir:
@mkdir -p $(OBJ_DIR)
$(EXE): $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $^
With this Makefile
, you can add more source directories to SRC_DIRS
and it will automatically compile sources in them.
What does it do? Run make
with the -n
option to see:
$ make -n
mkdir -p obj
cc -o obj/cg.o -c cg/cg.c
cc -o obj/utilities.o -c utilities/utilities.c
cc -o cg.exe obj/cg.o obj/utilities.o
You can also display the info on the variables by:
$ make info
SOURCES= cg/cg.c utilities/utilities.c
OBJECTS=obj/cg.o obj/utilities.o
Upvotes: 0
Reputation: 38315
This linking part of the makefile
cg.exe: make_build_dir utilities.o cg.o
$(CC) $(CFLAGS) -o $@ $<
has two issues. First, $<
refers to the first prerequesite of the target cg.exe
, and that is make_build_dir
. Declaring it as .PHONY
doesn't help here, it's simply passed to $(CC)
. Second, utilities.o cg.o
both don't exist at this location. You can change the rule to
cg.exe: obj/utilities.o obj/cg.o
$(CC) $(CFLAGS) -o $@ $^
Note the automatic variable $^
which refers to all prerequisites. Additionally, the object file targets should be
obj/cg.o: cg/cg.c
$(CC) $(CFLAGS) -o $@ -c $<
(identical for utilities.o
).
Upvotes: 1