Makefile: template rules for a subdirectory

Here is my project:

project
  |--- main.cpp
  |--- makefile
  |--- test
        |--- Test.cpp
        |--- Test.h

Here makefile:

g++1x:=g++ -std=c++14 -stdlib=libc++ -MMD -MP
cflags:= -Wall -lncurses

PATHS:=./ ./test/
TARGET:=matrix.out
SRC:=$(foreach PATH,$(PATHS),$(wildcard $(PATH)/*.cpp))
OBJDIR:=.obj
OBJ:=$(addprefix $(OBJDIR)/,$(notdir $(SRC:.cpp=.o)))


.PHONY: install
install: $(OBJDIR) $(TARGET)

$(OBJDIR):
    mkdir -p $(OBJDIR)

$(TARGET): $(OBJ)
    $(g++1x) $(cflags) -o $@ $^ -g


$(OBJDIR)/%.o: %.cpp
    $(g++1x) -c -o $@ $< -g

$(OBJDIR)/%.o: ./test/%.cpp
    $(g++1x) -c -o $@ $< -g

-include $(addprefix $(OBJDIR)/,$(notdir $(SRC:.cpp=.d)))

.PHONY: clean
clean:
    rm -f $(TARGET)
    rm -rf $(OBJDIR)

This works well, but I have two questions:
1) Can I escape foreachfor PATHSso that I can use the same makefilefor all cpp projects?
2) As you can see, for generation main.o, Test.oI also write two blocks:
$(OBJDIR)/%.o: ./test/%.cppand $(OBJDIR)/%.o: %.cpp.
Is it possible to write only once?
I tried as below, but this does not work:

$(OBJDIR)/%.o: $(foreach PATH,$(PATHS),$(wildcard $(PATH)/%.cpp))
        $(g++1x) -c -o $@ $< -g

I even tried this, but it does not work:

$(OBJDIR)/%.o: %.cpp ./test/%.cpp
    $(g++1x) -c -o $@ $< -g
0
source share
1 answer

. , .

# Use the shell find command to get the source tree
SOURCES := $(shell find * -type f -name "*.c")

OBJDIR  := .objects

# Keep the source tree into the objects tree
OBJECTS := $(addprefix $(OBJDIR)/,$(SOURCES:.c=.o))

all: mytarget

mytarget: $(OBJECTS)
    $(CC) $^ -o $@

# As we keep the source tree we have to create the
# needed directories for every object
$(OBJECTS): $(OBJDIR)/%.o: %.c
    mkdir -p $(@D)
    $(CC) -MMD -MP -c $< -o $@

-include $(OBJECTS:.o=.d)

$ make
mkdir -p .objects
cc -MMD -MP -c main.c -o .objects/main.o
mkdir -p .objects/test
cc -MMD -MP -c test/test.c -o .objects/test/test.o
cc .objects/main.o .objects/test/test.o -o mytarget

$ tree -a
.
β”œβ”€β”€ main.c
β”œβ”€β”€ Makefile
β”œβ”€β”€ mytarget
β”œβ”€β”€ .objects
β”‚   β”œβ”€β”€ main.d
β”‚   β”œβ”€β”€ main.o
β”‚   └── test
β”‚       β”œβ”€β”€ test.d
β”‚       └── test.o
└── test
    β”œβ”€β”€ test.c
    └── test.h

3 directories, 9 files

EDIT. mkdir , :

# Do not create the directory
$(OBJECTS): $(OBJDIR)/%.o: %.c
    $(CC) -MMD -MP -c $< -o $@

# Every target finishing with "/" is a directory
$(OBJDIR)%/:
    mkdir -p $@

# Add the "directory/" as an order only prerequisite
$(foreach OBJECT,$(OBJECTS),$(eval $(OBJECT): | $(dir $(OBJECT))))
+1

Source: https://habr.com/ru/post/1673876/


All Articles