makefile - tutorial - Usando GNU Make para construir tanto los objetivos de debug como los de release al mismo tiempo
makefile ubuntu (2)
Estoy trabajando en un proyecto de tamaño mediano que contiene varias bibliotecas con interdependencias que he convertido recientemente para compilar utilizando un archivo make no recursivo. Mi próximo objetivo es habilitar la creación de compilaciones tanto de depuración como de liberación desde el mismo árbol de origen al mismo tiempo (hacer depuración; realizar liberación). Mi primer paso fue hacer objetivos de depuración y lanzamiento que contenían las marcas de compilación correctas. Hice esto usando variables específicas de destino, como esto: 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
Esto funcionó bien, pero solo puedes compilar depuración o lanzamiento, no ambos al mismo tiempo. Y, al mismo tiempo, no me refiero a que durante la misma compilación me refiero a unir en el mismo árbol de origen (debug; make release). Para hacer esto, necesito colocar los archivos de objeto en un directorio específico de depuración / lanzamiento para que no se sobrescriban unos a otros y necesito modificar el nombre binario de destino de depuración con una ''D''. Pensé que esto sería fácil, ya que podría usar variables específicas de nuevo, como esto: 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)
Los expertos que leen esto ya saben que esto no funcionará porque no puede usar variables específicas del objetivo para crear objetivos reales. Funcionaron bien para mi var CXXFLAGS porque la variable no se utilizó en un nombre de destino.
¿Existe un patrón de diseño y / o mejores prácticas para administrar las construcciones de depuración / lanzamiento utilizando archivos make no recursivos? Específicamente, ¿cómo compilo la ruta del directorio del archivo de objetos y el nombre de destino (construyo un destino basado en un objetivo)?
Uno de los problemas más persistentes de Make es su incapacidad para manejar más de un comodín a la vez. No hay una manera realmente limpia de hacer lo que pides (sin recurrir a la recursión, lo que no creo que sea realmente tan malo). Aquí hay un enfoque razonable:
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)
Use VPATH para hacer que las VPATH de depuración y lanzamiento usen el mismo conjunto de archivos de origen. La compilación de debug y release puede tener su propio directorio, lo que significa que tendrán sus archivos de objetos separados.
Alternativamente, use una herramienta de compilación que admita construcciones fuera de la fuente de forma nativa, como automake o (ugh) cmake.
Si habilita los subdir-objects
de AM_INIT_AUTOMAKE([foreign subdir-objects])
opción automake (como en AM_INIT_AUTOMAKE([foreign subdir-objects])
subdir-objects
de AM_INIT_AUTOMAKE([foreign subdir-objects])
), puede escribir un Makefile.am
no recursivo.