Reputation: 22696
GNU Make 3.82
gcc 4.7.2
c89
I have the following make file:
INC_PATH=-I/home/dev_tools/apr/include/apr-1
LIB_PATH=-L/home/dev_tools/apr/lib
LIBS=-lapr-1 -laprutil-1
RUNTIME_PATH=-Wl,-rpath,/home/dev_tools/apr/lib
CC=gcc
CFLAGS=-Wall -Wextra -g -m32 -O2 -D_DEBUG -D_THREAD_SAFE -D_REENTRANT -D_LARGEFILE64_SOURCE $(INC_PATH)
SOURCES=$(wildcard src/*.c)
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))
EXECUTABLE=bin/to
all: build $(EXECUTABLE)
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)
build:
@mkdir -p bin
clean:
rm -rf $(EXECUTABLE) $(OBJECTS) bin
find . -name "*~" -exec rm {} \;
find . -name "*.o" -exec rm {} \;
My directory structure is like this project/src project/bin
. My Makefile is in the project (root)
folder, and all my *.h and *.c are in the src directory. Currently I have only one source file called timeout.c
I get this error:
gcc: error: src/timeout.o: No such file or directory
I have used this to get all the source files:
SOURCES=$(wildcard src/*.c)
And the object files:
OBJECTS=$(patsubst %.c, %.o, $(SOURCES))
However, the make seems to create the object file in the project root folder where the Makefile is. Should it not put it in the src directory?
Upvotes: 35
Views: 125543
Reputation: 158
Another approach without addsuffix
which may helps.
CC = gcc
SRC = src/*.c
CFILES := $(wildcard $(SRC))
OFILES := $(patsubst %.c,%.o, $(CFILES))
.PHONY: run
run: $(OFILES)
$(CC) $^ -o $@
Upvotes: 1
Reputation: 165
I solved this request and here is my Makefile and directory tree.
PROJECT := main.exe
DIR_SRC += .
DIR_SRC += ./src
DIR_INC += -lpthread
DIR_INC += -I./inc
DIR_INC += $(addprefix -I, $(DIR_SRC))
SRC_C += $(wildcard $(addsuffix /*.c, $(DIR_SRC)))
#OBJ := $(filter %.o, $(SRC_C:.c=.o))
OBJ := $(patsubst %.c, %.o, $(SRC_C))
EXE := $(PROJECT)
CC_PREFIX :=
CC := $(CC_PREFIX)gcc
CFLAG =
CLIB = -L .
.PHONY:all
all:$(OBJ) $(EXE)
%.o: %.c
$(CC) $(CFLAG) $(DIR_INC) -c $< -o $@
$(EXE): $(OBJ)
$(CC) $(CFLAG) $(CLIB) $(OBJ) -o $@
clean:
rm -r $(EXE) $(OBJ)
See my directory tree:
Upvotes: 2
Reputation: 9144
Use gcc
's -o option to write the output file to a particular location. For instance, you could say:
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS) -o $(OBJECTS)
Unfortunately, there's a problem with this line: if there is more than one source file in $(SOURCES)
, it won't work, since $(OBJECTS)
will also contain multiple file names, and the -o option only binds to the first argument.
A way to compile each file in a list of source code files is to use implicit rules. In gmake
, you would write:
$(EXECUTABLE): $(OBJECTS)
$(CC) $(CFLAGS) -o $@ $(RUNTIME_PATH) $(OBJECTS) $(LIB_PATH) $(LIBS)
%.o : %.c
$(CC) $(CFLAGS) -c $< -o $@
where $< is replaced with name of the input file and $@ is replaced with the name out the output file.
Upvotes: 7
Reputation: 99172
You have two problems in this rule (well, three):
$(OBJECTS): $(SOURCES)
$(CC) $(CFLAGS) -c $(SOURCES) $(LIB_PATH) $(LIBS)
You haven't noticed yet, but the rule makes each object dependent on all sources, and tries to build that way. Not a problem as long as you have only one source. Easy to fix with a static pattern rule and an automatic variable:
$(OBJECTS): src/%.o : src/%.c
$(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS)
Also, the command ("$(CC)...") doesn't specify an output file name, so gcc will infer it from the source file name; if you give it src/timeout.c
, it will produce timeout.o
(in the working directory, project/
). So you should specify the desired path to the output file. Easy to do with another automatic variable:
$(OBJECTS): src/%.o : src/%.c
$(CC) $(CFLAGS) -c $< $(LIB_PATH) $(LIBS) -o $@
Upvotes: 30