Search code examples
cgccmakefilebuild-dependencies

Make - How to build dependencies, and how to define multiple targets?


i'm new to makefile and i would like to perform several operations.

my current makefile is as follows:

OBJECTS=radio_listener.o radio_app_comm_func.o
TARGET_EXECUTABLE=radio_listener

# Default target
all: ${TARGET_EXECUTABLE}

# Compile all required .o files this way
%.o: %.c
    @echo "Compiling $<"
    @gcc -c -g -m32 $< -o $@ 

# Compile target exe by combining all objects
${TARGET_EXECUTABLE}: ${OBJECTS}
    @echo "Linking $@"
    @gcc ${OBJECTS} -g -m32 -o $@

# Cleanup rule
clean:
    @echo "Cleaning up..."
    @rm -f *.o ${TARGET_EXECUTABLE}
    @echo "Done."

.PHONY: clean all

1. Say I execute 'make'. then change a MACRO define in radio_app_comm_types.h.

radio_app_comm_types.h is included in radio_app_comm_func.h.

after changing the MACRO, and executing 'make' again, i get "Nothing to be done for 'all'.

Obviously i somehow need to tell my Makefile, that radio_app_comm_func.h, is dependent on radio_app_comm_types.h.

How to do this?

2. The 2nd thing that interest me, is how to use the same Makefile, dor different executables.

Currently i have only radio_listener , but i plan on adding radio_control,radio_server, which their h files will also include radio_app_comm_func.h, and maybe some other h files (in order to use the relevant .c files of them.

How can i achieve this? I'm looking to implement a flow as follows:

a) Executing make, will compile all relevant files for each of the exe's, and in the end will create 3 different executables for me - radio_listener, radio_control, radio_server

b) Executing make server (for example), will compile all relevant files that are needed only for radio_server (including looking for changes, say, in radio_app_comm_types.h) and finally will create only 1 executable - radio_server for me

c) Executing make controller ...compile all needed for radio_control, etc (you get my meaning i guess)

I'm working on Ubuntu x64 system, if that's relevant.

Any help will be much appreciated.

Thank you.


Solution

  • Here's a version that uses the advanced auto-dependency rules, and allows for multiple targets to be built. Update the flags near the top and create new entries in TARGETS and make a new xxx_SRC variable to add new targets.

    If you want the dependency files in the current directory you can change DEPDIR to be just . or else go through the makefile and delete references to it, either way.

    TARGETS := exe1 exe2 exe3
    
    DEPDIR = .d
    
    exe1_SRC := foo.c bar.c
    exe2_SRC := biz.c boz.c
    exe3_SRC := bling.c blang.c
    
    CC       := gcc
    
    CFLAGS   := -g -O2
    CPPFLAGS := -DXXX -I../include
    
    LDFLAGS  :=  -L../lib
    LDLIBS   :=  -lfoo -lbar
    
    # ----- Nothing below here needs to be changed
    
    .PHONY: all
    all : $(TARGETS)
    
    .SECONDEXPANSION:
    # For each target, depend on the .o files for its sources
    $(TARGETS): $$(patsubst %.c,%.o,$$($$@_SRC))
            $(LINK.c) $^ $(LDLIBS) -o $@
    
    ALLSRC := $(foreach T,$(TARGETS),$($T_SRC))
    
    .PHONY: clean
    clean: 
            rm -f $(TARGETS) *.o $(DEPDIR)/*.d
    
    # -----
    # Advanced auto-dependency, from:
    # http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
    
    $(shell mkdir -p $(DEPDIR) >/dev/null)
    DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPDIR)/$*.Td
    
    COMPILE.c = $(CC) $(DEPFLAGS) $(CFLAGS) $(CPPFLAGS) $(TARGET_ARCH) -c
    POSTCOMPILE = mv -f $(DEPDIR)/$*.Td $(DEPDIR)/$*.d
    
    %.o : %.c
    %.o : %.c $(DEPDIR)/%.d
            $(COMPILE.c) $(OUTPUT_OPTION) $<
            $(POSTCOMPILE)
    
    $(DEPDIR)/%.d: ;
    .PRECIOUS: $(DEPDIR)/%.d
    
    -include $(patsubst %,$(DEPDIR)/%.d,$(basename $(ALLSRC)))