Использование GNU Make для одновременного создания целей отладки и выпуска - PullRequest
18 голосов
/ 27 октября 2010

Я работаю над проектом среднего размера, который содержит несколько библиотек с взаимозависимостью, которые я недавно преобразовал в сборку с использованием нерекурсивного make-файла. Моя следующая цель - включить сборку отладки и выпуска одновременно из одного и того же дерева исходных кодов (make debug; make release). Моим первым шагом было создание целей отладки и выпуска, которые содержали правильные флаги сборки. Я сделал это, используя целевые переменные, например: CXXFLAGS = -Wall -Wextra -Werror -DLINUX

CXX_DEBUG_FLAGS=-g3 -DDEBUG_ALL
CXX_RELEASE_FLAGS=-O3

.PHONY: debug 
debug: CXXFLAGS+=$(CXX_DEBUG_FLAGS) 
debug: build

.PHONY: release 
release: CXXFLAGS+=$(CXX_RELEASE_FLAGS) 
release: build

Это работало нормально, но вы могли только отладить или выпустить, но не оба одновременно. И в то же время, я не имею в виду, что во время одной и той же сборки я имею в виду одно и то же дерево исходного кода (make debug; make release). Чтобы сделать это, мне нужно поместить объектные файлы в специальный каталог для отладки / выпуска, чтобы они не перезаписывали друг друга, и мне нужно пометить двоичное имя цели отладки буквой 'D'. Я подумал, что это было бы легко, так как я мог бы просто использовать целевые переменные снова, например так: CXXFLAGS = -Wall -Wextra -Werror -DLINUX

CXX_DEBUG_FLAGS=-g3 -DDEBUG_ALL
CXX_RELEASE_FLAGS=-O3

.PHONY: debug 
debug: CXXFLAGS+=$(CXX_DEBUG_FLAGS) 
debug: MODULE_BLD_TYPE=D
debug: OUT_DIR=debug_obj
debug: build

.PHONY: release 
release: CXXFLAGS+=$(CXX_RELEASE_FLAGS) 
release: MODULE_BLD_TYPE:=
release: OUT_DIR=release_obj
release: build

.PHONY: build
build: TARGET_NAME=HelloWorld$(MODULE_BLD_TYPE)
build: TARGET_BUILD_DIR=$(PROJECT_ROOT_DIR)/$(OUT_DIR)
build: TARGET_BUILD_OBJS=$(addprefix $(TARGET_BUILD_DIR)/,$(SOURCES:.cpp=.o))
build: $(TARGET_NAME)

Вы заставляете экспертов, читающих это, уже знать, что это не сработает, потому что вы не можете использовать целевые переменные для создания реальных целей. Они отлично работали для моей переменной CXXFLAGS, потому что переменная не использовалась в целевом имени.

Существуют ли шаблоны проектирования и / или лучшие практики для управления сборками отладки / выпуска с использованием нерекурсивных make-файлов? В частности, как построить путь к каталогу объектного файла и имя цели (создать цель на основе цели)?

Ответы [ 2 ]

14 голосов
/ 27 октября 2010

Одной из наиболее постоянных проблем с Make является невозможность обрабатывать более одного подстановочного знака одновременно. Не существует действительно чистого способа сделать то, что вы просите (не прибегая к рекурсии, что, на мой взгляд, не очень плохо) Вот разумный подход:

CXXFLAGS=-Wall -Wextra -Werror -DLINUX
CXX_DEBUG_FLAGS=-g3 -DDEBUG_ALL 
CXX_RELEASE_FLAGS=-O3 

.PHONY: debug  
debug: CXXFLAGS+=$(CXX_DEBUG_FLAGS)  
debug: HelloWorldD

.PHONY: release  
release: CXXFLAGS+=$(CXX_RELEASE_FLAGS)
release: HelloWorld

DEBUG_OBJECTS = $(addprefix $(PROJECT_ROOT_DIR)/debug_obj/,$(SOURCES:.cpp=.o))
RELEASE_OBJECTS = $(addprefix $(PROJECT_ROOT_DIR)/release_obj/,$(SOURCES:.cpp=.o))

HelloWorldD: $(DEBUG_OBJECTS)
HelloWorld: $(RELEASE_OBJECTS)

# And let's add three lines just to ensure that the flags will be correct in case
# someone tries to make an object without going through "debug" or "release":

CXX_BASE_FLAGS=-Wall -Wextra -Werror -DLINUX
$(DEBUG_OBJECTS): CXXFLAGS=$(CXX_BASE_FLAGS) $(CXX_DEBUG_FLAGS)
$(RELEASE_OBJECTS): CXXFLAGS=$(CXX_BASE_FLAGS) $(CXX_RELEASE_FLAGS)
2 голосов
/ 28 октября 2010

Используйте VPATH , чтобы отладочные и выпускные сборки использовали один и тот же набор исходных файлов. Сборка отладки и выпуска может иметь свой собственный каталог, что означает, что у них будут отдельные объектные файлы.

В качестве альтернативы, используйте инструмент сборки, который изначально поддерживает сборки из исходного кода, например automake или (тьфу) cmake.

Если вы включите опцию automake subdir-objects (как в AM_INIT_AUTOMAKE([foreign subdir-objects])), вы можете написать нерекурсивную Makefile.am.

...