Правильный m, метод для подстановочных знаков в GNU Make

Я пытаюсь написать Makefile с разделенными исходными и объектными файлами, и я не могу понять, как это сделать. У меня есть два метода, которые работают, но я надеюсь, что кто-то может указать «правильный» способ сделать это.

Мой проект разделен наsrc а такжеobj папка с Makefile на том же уровне, что и эти.

Первый метод использует функцию подстановки, чтобы найти исходные файлы вsrc затем использует замену текста для определения соответствующих объектных файлов.

SRC = $(wildcard src/*.cpp)
OBJ = $(SRC:.cpp=.o)

prog: $(OBJ)
       $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(patsubst src/,obj/,$(OBJ))

%.o: %.cpp
     $(CC) $(CFLAGS) -c 
SRC = $(wildcard src/*.cpp)
OBJ = $(SRC:.cpp=.o)

prog: $(OBJ)
       $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(patsubst src/,obj/,$(OBJ))

%.o: %.cpp
     $(CC) $(CFLAGS) -c $< -o $(COMPILE)/$(@F)  
lt; -o $(COMPILE)/$(@F)

Это, кажется, работает, однако, каждый раз, когда я бегуmake prog он перекомпилирует все объектные файлы.OBJ переменная должна иметьsrc/ перед всеми объектами, иначе я получаю «правило не ставить цель». С положительной стороны, я могу легко использовать patsubst вprog цель указать объектные файлы.

Второй метод похож, но использует vpaths и замену текста наOBJ переменная:

 vpath = %.cpp src
 vpath = %.o obj

 SRC = $(wildcard src/*.cpp)
 OBJ = $(subst src/,,$(SRC:.cpp=.o))
 POBJ = $(patsubst src/,obj/$(SRC:.cpp=.o))

 prog: $(OBJ)
       $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(POBJ)

 %.o: %.cpp
     $(CC) $(CFLAGS) -c 
 vpath = %.cpp src
 vpath = %.o obj

 SRC = $(wildcard src/*.cpp)
 OBJ = $(subst src/,,$(SRC:.cpp=.o))
 POBJ = $(patsubst src/,obj/$(SRC:.cpp=.o))

 prog: $(OBJ)
       $(CC) $(CFLAGS) $(LDFLAGS) $(LIBS) -o prog $(POBJ)

 %.o: %.cpp
     $(CC) $(CFLAGS) -c $< -o $(COMPILE)/$(@F)  
lt; -o $(COMPILE)/$(@F)

Это устраняет перекомпиляцию объектных файлов, но требует, чтобы я добавил другую переменнуюPOJB дляprog target (так как я не могу сделать patsubst только для объектных файлов без basedir).

Оба метода работают, и у каждого есть свои преимущества перед другим, но какой из них является «правильным» подходом, и если нет, каков правильный способ достижения этого типа здания?

Ответы на вопрос(1)

Ваш ответ на вопрос