$<
всегда принимает предварительное условие first . Поскольку ваше правило расширяется до
$(B)/main.o $(B)/src1.o : $(SRC)/main.cpp $(SRC)/src1.cpp
$(CXX) $(CFLAGS) $< -o $@
$(SRC)/main.cpp
всегда является первой предпосылкой. Нет никакой магической связи между $(B)/main.o
и $(SRC)/main.cpp
, поскольку make
.
Если вы хотите, чтобы ваши правила устанавливали это соединение, вы должны закодировать его в правилах. Есть несколько способов сделать это правильно. Самое простое - написать отдельные правила для каждой цели:
$(B)/main.o : $(SRC)/main.cpp
$(CXX) $(CFLAGS) $< -o $@
$(B)/src1.o : $(SRC)/src1.cpp
$(CXX) $(CFLAGS) $< -o $@
Вы также можете использовать шаблонное правило следующим образом:
$(B)/%.o : $(SRC)/%.cpp
$(CXX) $(CFLAGS) $< -o $@
Здесь $<
делает правильные вещи, потому что $(SRC)/%.cpp
параметризован с шаблоном, поэтому он расширится до правильного исходного файла.
Самая большая пушка у вас , генерирующая отдельные правила:
STEMS := main src1
$(foreach stem,$(STEMS), \
$(eval $(B)/$(stem).o: $(SRC)/$(stem).cpp ; $(CXX) $(CFLAGS) $< -o $@))
Здесь я перебираю все слова в $(STEMS)
с помощью встроенного вызова функции $(foreach)
и генерирую одно правило на итерацию с помощью вызова функции $(eval)
. Это синтаксис GNU Make, только , другие реализации make
, вероятно, не имеют этих функций. Однако это самый общий и гибкий способ сказать make
, что делать. Синтаксис вызова функции GNU Make завершен, поэтому вы можете выполнять любые вычисления, которые вам нужны, чтобы придумать правильные правила. Однако читаемость пострадает, поэтому используйте это с осторожностью.