Christian
Christian

Reputation: 325

Makefile with Multiple Dirs and Multiple Executables?

I found a lot of interesting posts here with multiple source directories (for C). But I am struggling with some very special use case. This is what I have here and works fine:

.
|
\--main/
|   |
|   |-- (multiple *c files)
|   \--obj/
|       |
|       \-- multiple *o files from the upper *c files
|
| --vent/
|   |
|   |-- (multiple *c files)
|   \--obj/
|       |
|       \-- multiple *o files from the upper *c files
[...]

Each subdir has it own Makefile:

include ../Makefile.vars

SOURCES     =   $(wildcard *.c)
HEADERS     =   $(wildcard ../*h)
OBJECTS     =   $(patsubst %.c, obj/%.o, $(SOURCES))
all: $(OBJECTS)

#====================== vent ============================
$(OBJECTS):  obj/%.o : %.c $(HEADERS)
    $(CC) $(CFLAGS) -c $< -o $@
[...]

The included Makefile.vars just keep track of the libraries which might be needed:

CFLAGS      =   -Wall 
LIBS        :=  -lconfig -lcurl -ljson-c -lm -lmodbus -lmosquitto -lownet -lpthread -lsystemd

Now I have on the . directory a single Makefile which crawls down into the subdirectories, does a make, links the .*o and finally creates the desired binary:

include Makefile.vars
SUBDIRS         :=      common kluefter vent main mqttd wetter
SOURCES         :=      $(wildcard $(addsuffix /*.c ,$(SUBDIRS)))
OBJECTS         :=      $(subst /,/obj/,$(subst .c,.o,$(SOURCES)))
HEADERS         :=      $(wildcard *h)

BIN             :=      hzgmasterd
server          :       $(BIN)
        
#====================== Master ============================
$(BIN)          :       $(OBJECTS)
        $(CC) $(CFLAGS) -rdynamic -o $@ $^ $(LIBS) 
        @echo "Server done."

$(OBJECTS)      :       $(SUBDIRS) ;

.PHONY: $(SUBDIRS)
$(SUBDIRS)      :
        $(MAKE) -C $@

This works pretty smooth!

But I need an additional binary which should make use of most of the existing *.ofiles and create a different binary (obviously with a different main()). So I added some parts to the master Makefile:

#Define the subdirectory to crawl into for tools
TSUBDIRS  := tools

#Define TSOURCES, TOBJECTS and THEADERS derived from the original ones. Exclude the main.c from $(SOURCES):
TSOURCES        :=      $(wildcard $(addsuffix /*.c ,$(TSUBDIRS))) $(filter-out main.c,$(SOURCES))
TOBJECTS        :=      $(subst /,/obj/,$(subst .c,.o,$(TSOURCES)))
THEADERS        :=      $(wildcard *h)

TBIN            := tools/hzgtool
all             :       $(BIN) $(TBIN)
server          :       $(BIN)
tools           :       $(TBIN)

# And added the compile/ link lines for tools:
#====================== Tools ============================
$(TBIN)         :       $(TOBJECTS)
        $(CC) $(CFLAGS) -rdynamic -o $@ $^ $(LIBS) 
        @echo "Tools done."

$(TOBJECTS)     :       $(TSUBDIRS) ;

Unfortunately, this does not work. When I do a makeon top level I am getting the following feedback (sorry, only in German):

root@zentrale:/heizung/src# make server
Makefile:53: Warnung: Die Befehle für das Ziel „common/obj/vent.o“ werden überschrieben
Makefile:42: Warnung: Alte Befehle für das Ziel „common/obj/vent.o“ werden ignoriert

I refers to the lines starting with $(OBJECTS) and $(TOBJECTS) telling me line 42 will get ignored and overwritten by line 53.

Why is $(OBJECTS) : $(SUBDIRS) ; overwritten by $(TOBJECTS) : $(TSUBDIRS) ;?

Any idea how to get what i want?

Upvotes: 0

Views: 44

Answers (0)

Related Questions