Reputation: 3855
I try to write a single makefile, which search for lib-directories in the current directory, compile the sources of every directory and put the object-file into a separate object-directory. I don't want to have more than one makefile.
This makefile will do this:
SRCDIR := $(shell ls -d lib_*/)
CC := gcc
DB := gdb
OBJDIR := obj
CFLAGS := -Wall -Werror -Wextra -pedantic -O3
LDFLAGS := #
# Rules
all:
@ # create object directory
@mkdir -p $(OBJDIR)/ ;
@ # go through all source dirs
@for dir in $(SRCDIR); do \
echo $$dir && \
cd $$dir && \
for n in $$(ls *.c); do \
m=$${n%%.c}; \
$(CC) -c \
$(CFLAGS) \
$(LDFLAGS) \
-o ../$(OBJDIR)/$$m.o $$n;\
done; \
cd ..; \
done
But: The makefile compiles every run all sources. Also the the sources without any changes. If it possible that the makefile recognizes if there are changes or not and compiles only the changed sources?
Here the strcture of the dirs:
lib
|-lib_one
| |-lib_one.c
| |-lib_one.h
|
|-lib_two
| |-lib_two.c
| |-lib_two.h
|
|-lib_n
| |-lib_n.c
| |-lib_n.h
|
|-obj
| |-lib_one.o
| |-lib_two.o
| |-
| |-lib_n.o
|
|-makefile
Upvotes: 0
Views: 571
Reputation: 99084
If you don't care about header files, you can do this:
SRCS := $(wildcard */*.c)
OBJDIR := obj
OBJS := $(patsubst %.c,$(OBJDIR)/%.o,$(notdir $(SRCS)))
all: $(OBJS)
@:
$(OBJDIR)/%.o: %.c
$(CC) -c $(CFLAGS) -o $@ $<
vpath %.c $(wildcard *)
If you care about the obvious header files (e.g. lib_one.c
includes lib_one.h
), then you can make a simple adjustment:
$(OBJDIR)/%.o: %.c %.h
$(CC) -c $(CFLAGS) -o $@ $<
vpath %.c $(wildcard *)
vpath %.h $(wildcard *)
If you have other dependencies (e.g. lib_n.c
includes lib_one.h
), you could add them by hand:
lib_n.o: lib_one.h
or you could use Advanced Auto-Dependency Generation, but that's an advanced technique I'd advise you to leave for another day.
Upvotes: 1
Reputation: 16039
You can use the following:
SRCDIR := $(shell ls -d lib_*/)
CC := gcc
DB := gdb
OBJDIR := obj
CFLAGS := -Wall -Werror -Wextra -pedantic -O3
LDFLAGS := #
# Rules
all:
@ # create object directory
@mkdir -p $(OBJDIR)/ ;
@ # go through all source dirs
@for dir in $(SRCDIR); do \
echo $$dir && \
cd $$dir && \
for n in $$(ls *.c); do \
m=$${n%%.c}; \
if [ ! -e ../$(OBJDIR)/$$m.o ] || \
[ `stat -c %Y ../$(OBJDIR)/$$m.o` -lt `stat -c %Y $$n` ] || \
([ -e $$m.h ] && [ `stat -c %Y ../$(OBJDIR)/$$m.o` -lt `stat -c %Y $$m.h` ]); then \
echo "Change detected, compiling $$n..."; \
$(CC) -c \
$(CFLAGS) \
$(LDFLAGS) \
-o ../$(OBJDIR)/$$m.o $$n;\
fi; \
done; \
cd ..; \
done
The following line adds a check over the object files to see if they exists, if that then it compare source modification time against object modification time (kind of repeating the make
work inside make
).
if [ ! -e ../$(OBJDIR)/$$m.o ] || [ `stat -c %Y ../$(OBJDIR)/$$m.o` -lt `stat -c %Y $$n` ] || ([ -e $$m.h ] && [ `stat -c %Y ../$(OBJDIR)/$$m.o` -lt `stat -c %Y $$m.h` ]); then
Upvotes: 0