Я работаю с инструментом, который генерирует исходные файлы C ++, которые мне нужно включить в компиляцию моего проекта C ++.
Чтобы необычайно упростить вещи, мой единственный не сгенерированный исходный файл, main.cpp
, этоследующим образом:
extern void bar();
int main(int, char**)
{
bar();
return 0;
}
А мой Makefile
ниже.Общая структура - это то, что уже существует в нашем проекте, и я просто добавляю в отмеченные части, чтобы сгенерировать необходимый исходный файл bar.cpp
и makefile bar.mk
, который добавляет bar.cpp
к переменной SRCS
, поэтомуЯ хотел бы), включается в компиляцию:
SRCS := $(CURDIR)/main.cpp
#################### Adding everything between here... #####
BAR_MK := bar.mk
ifeq (,$(findstring clean,$(MAKECMDGOALS)))
include $(BAR_MK)
endif
#################### ...and here ###########################
OBJ_DIR := $(CURDIR)/obj
OBJS := $(patsubst %.cpp,%.o,$(subst $(CURDIR),$(OBJ_DIR),$(SRCS)))
a.out: $(OBJS)
@echo OBJS == $(OBJS)
@echo SRCS == $(SRCS)
$(CXX) $(OBJS)
#################### Adding everything between here... #####
GEN_DIR := $(CURDIR)/gen
# "Generate" my source file(s), add them to SRCS via an external makefile
$(BAR_MK): $(GEN_DIR)/bar.cpp
$(GEN_DIR)/bar.cpp:
mkdir -p $(dir $@)
echo "void bar () {}" > $@
echo SRCS += $@ > $(BAR_MK)
#################### ...and here ###########################
$(OBJ_DIR)/%.o: %.cpp
mkdir -p $(dir $@)
$(CXX) -c -o $@ $<
clean:
rm -rf $(OBJ_DIR)
rm -f a.out
rm -rf $(GEN_DIR)
rm -f $(BAR_MK)
Проблема в том, что компиляция завершается неудачно при первом запуске make
из-за "неопределенной ссылки на bar()
", но при немедленном запуске make
после успеха.Это связано с тем, что при первом запуске make
, когда он оценивает правило a.out:
, он видит SRCS
только как содержащий main.cpp
, и поэтому bar.cpp
не компилируется.Затем на втором (и последующих) запусках SRCS
содержит и main.cpp
, и bar.cpp
, поэтому bar.cpp
компилируется в это время.
Это кажется мне странным, потому что согласно GNU Make manual о том, «Как перезаписываются make-файлы»:
После того, как все make-файлы были проверены, если они действительно были изменены, make запускается с чистого листа и снова читает все make-файлы..
Так что после того, как GNU Make обрабатывает include bar.mk
при моем первом make
вызове, видит, что он устарел, и строит его, я ожидаю, что он затем начнется с поцарапайте с разбором Makefile с самого начала, включая bar.mk
и, в свою очередь, наличие SRCS
, содержащее как main.cpp
, так и bar.cpp
.
Неужели мои ожидания неверны?Или что-то не так с моим (дополнением к) Makefile?Я использую GNU Make 4.1 в Linux.