首页 文章

使用GNU Make同时构建调试和发布目标

提问于
浏览
18

我正在开发一个中型项目,其中包含几个具有相互依赖性的库,我最近将其转换为使用非递归makefile构建 . 我的下一个目标是同时从同一源代码树中构建调试和发布版本(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 var工作正常,因为该变量未在目标名称中使用 .

是否有使用非递归makefile管理调试/发布版本的设计模式和/或最佳实践?具体来说,如何构建目标文件目录路径和目标名称(根据目标构建目标)?

2 回答

  • 14

    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

    使用VPATH使调试和发布版本使用相同的源文件集 . 调试和发布版本可以有自己的目录,这意味着它们的目标文件是分开的 .

    或者,使用支持源外构建的构建工具,例如automake或(ugh)cmake .

    如果启用automake选项 subdir-objects (如 AM_INIT_AUTOMAKE([foreign subdir-objects]) ),则可以编写非递归 Makefile.am .

相关问题