Sophisticated template replacement in Makefile prerequisites

Ive got the following directory structure:

./
 |- obj/
 |--- debug/
 |--- release/
 |- bin/
 |--- debug/
 |--- release/
 |- src/
 |--- main.c
 |--- libb/
 |----- foo.c
 |- include/
 |--- libb/
 |----- foo.h

In addition, I manually determine the dependencies of individual objects in my own Makefilein the following format (example):

 main_DEPS = libb/foo

Now I want to be able to type make bin/debug/main, and this generates the necessary dependencies and the target file:

  • obj/debug/libb/foo.o
  • obj/debug/main.o
  • bin/debug/main

How to do it? My current approach is extremely confusing and incomplete:

  • Object files are created below. However, it does not create any necessary subfolders ( libb) if they do not already exist. It also does not track any modified header files. Can a Makefile-style trick be adapted to automatically create prerequisites ?

    CFLAGS+=-I include
    
    obj/*/%.o: src/%.cpp
        $(CC) $(CFLAGS) $< -c -o $@
    
  • . , *_DEPS.

    .SECONDEXPANSION:
    
    bin/debug/%: obj/debug/%.o $(patsubst %,obj/debug/%.o,$($(patsubst bin/debug/%,%,$@)_DEPS))
        $(LD) $(LDFLAGS) $< $(patsubst %,obj/debug/%.o,$($(patsubst bin/debug/%,%,$@)_DEPS)) -o $@
    
    bin/release/%: obj/release/%.o $(patsubst %,obj/release/%.o,$($(patsubst bin/release/%,%,$@)_DEPS))
        $(CXX) $(LDFLAGS) $< $(patsubst %,obj/release/%.o,$($(patsubst bin/release/%,%,$@)_DEPS)) -o $@
    

    , : "obj/debug/libb/foo.o: " - , , mkdir obj/debug/libb; make obj/debug/libb/foo.o.

    ( , ).

? , - , make, (autoconf...), ( ) , Ive , , , , make.

+3
1

@sehe , ... , ,

, ( ) ( Makefile).

" make",

A_DEPS=dep1 dep2
C_DEPS=dep2

##########################
# "outer" Make
bin/%/A bin/%/B bin/%/C:
    $(MAKE) BUILD="$*" TARGET=$(@F) DEPS="$($(@F)_DEPS)" GENRULE

, "" . Makefile " ", GENRULE:

##########################
# "inner" Make

%/*.o:
    mkdir -p "$(@D)" && touch "$@"

GENRULE: obj/$(BUILD)/$(TARGET).o $(DEPS:%=obj/$(BUILD)/%.o) 
    echo gcc -o "bin/$(BUILD)/$(TARGET)" $^
    mkdir -p "bin/$(BUILD)" && touch "bin/$(BUILD)/$(TARGET)"
.PHONY: GENRULE

, :

$ for target in bin/{debug,release}/{A,B,C}; do make -Bs "$target"; done

gcc -o bin/debug/A obj/debug/A.o obj/debug/dep1.o obj/debug/dep2.o
gcc -o bin/debug/B obj/debug/B.o
gcc -o bin/debug/C obj/debug/C.o obj/debug/dep2.o
gcc -o bin/release/A obj/release/A.o obj/release/dep1.o obj/release/dep2.o
gcc -o bin/release/B obj/release/B.o
gcc -o bin/release/C obj/release/C.o obj/release/dep2.o

:

$ find bin obj

bin
bin/debug
bin/debug/A
bin/debug/B
bin/debug/C
bin/release
bin/release/A
bin/release/B
bin/release/C
obj
obj/debug
obj/debug/A.o
obj/debug/B.o
obj/debug/C.o
obj/debug/dep1.o
obj/debug/dep2.o
obj/release
obj/release/A.o
obj/release/B.o
obj/release/C.o
obj/release/dep1.o
obj/release/dep2.o

( ) $@ $(@F):

EXTRA="--standardopts"
A_FLAGS="--a-opts"
B_FLAGS="--b-opts"

.SECONDEXPANSION:

debug/% release/%: EXTRA+=$($(@F)_FLAGS)

%/A %/B %/C:
    echo building $@ with $(EXTRA)
+2

All Articles