2012-05-30 3 views
5

Связанных: Target-specific Variables as Prerequisites in a MakefileMakefile целевые конкретные переменные в качестве предпосылки

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

Моя проблема в том, что «make» выполняет чистую сборку каждый раз, даже если я ничего не изменил. Я уверен, что это потому, что «make» оценивает предпосылки целевых «corewars» перед объявлением переменной в предпосылках для цели «debug» или «release».

Файл Makefile представлен ниже.

CXX=g++ 
LD=g++ 
LDFLAGS= 
CXXFLAGS=-Iinclude -Wall -Wextra 
OBJECTS=main.o Machine.o Core.o ProcessQueue.o Instruction.o 
OUTPUT_DIR:=Test/ 

.PHONY: default 
.PHONY: all 
.PHONY: release 
default: release 
all: release 
release: OUTPUT_DIR:=Release/ 
release: corewars 

.PHONY: debug 
debug: CXXFLAGS+=-DDEBUG -g 
debug: OUTPUT_DIR:=Debug/ 
debug: corewars 

corewars: $(OUTPUT_DIR) $(addprefix $(OUTPUT_DIR),$(OBJECTS)) 
    $(LD) -o $(addprefix $(OUTPUT_DIR),corewars) $(addprefix $(OUTPUT_DIR),$(OBJECTS)) 

Release: 
    mkdir -p [email protected] 
Debug: 
    mkdir -p [email protected] 

%.o: %.cpp include/%.h 
    $(CXX) -c $(CXXFLAGS) $< -o $(OUTPUT_DIR)[email protected] 


.PHONY: clean 
clean: 
    $(RM) -r Release 
    $(RM) -r Debug 

ответ

11

По крайней мере, ваше правило компиляции нарушено. A non-phony recipe must create a target, [email protected], not $(OUTPUT_DIR)[email protected].

Также рассмотрите возможность преобразования зависимостей каталога в предварительные условия order-only.

Наконец, чтобы получить правильное значение $(OUTPUT_DIR) внутри списка предпосылок, вы должны использовать secondary expansion, потому что в противном случае, глобальное определение OUTPUT_DIR:=Test/ используются вместо целевого конкретных один.

Я не знаю, как исправить ваш Makefile без дополнительного расширения и магии vpath. Лично я бы сначала настроил среду (узнал значение OUTPUT_DIR и т. Д.), А затем повторно выполнил Make с соответствующими значениями.

ifndef OUTPUT_DIR 

.PHONY: default all release debug 

default all: release 

release: export OUTPUT_DIR := Release/ 
debug: export OUTPUT_DIR := Debug/ 
debug: export EXTRA_CXXFLAGS := -DDEBUG -g 

release debug: 
    @$(MAKE) 

else 

# ... 
CXXFLAGS := -Iinclude -Wall -Wextra $(EXTRA_CXXFLAGS) 

PROGRAM := $(OUTPUT_DIR)corewars 
OBJECTS := $(addprefix $(OUTPUT_DIR), \ 
    main.o Machine.o Core.o ProcessQueue.o Instruction.o) 

# Default target. 
$(PROGRAM): $(OBJECTS) | $(OUTPUT_DIR) 
    $(LD) -o [email protected] $< 

$(OUTPUT_DIR)%.o: %.cpp | $(OUTPUT_DIR) 
    $(CXX) -c $(CXXFLAGS) $< -o [email protected] 

$(OUTPUT_DIR): 
    mkdir -p [email protected] 

endif # OUTPUT_DIR 
+0

Это отличная санитария моей системы сборки, спасибо. Я счел необходимым добавить '| $ (OUTPUT_DIR) 'в список необходимых условий для создания файлов' .o', и я добавил «чистую» цель, но, кроме этого, это работает как указано. Большое спасибо. –

+0

@ Крис, о, да, вы правы, я забыл об этом (исправлен). И приветствую вас! ;-) –

+0

Спасибо за головы! Я исправлю это сейчас. –

Смежные вопросы