Makefile 包含基于 Debug / Release 目标的依赖项
Posted
技术标签:
【中文标题】Makefile 包含基于 Debug / Release 目标的依赖项【英文标题】:Makefile include dependencies based on Debug / Release target 【发布时间】:2017-08-03 21:25:04 【问题描述】:我正在尝试创建一个 Makefile 来编译我的 C 程序。我正在尝试使用以下目录结构生成调试和发布版本:
helloworld/
├── Debug/
│ ├── bin/
│ ├── depends/
│ └── obj/
├── Release/
│ ├── bin/
│ ├── depends/
│ └── obj/
├── mylib/
│ ├── bar.c
│ ├── bar.h
│ ├── foo.c
│ └── foo.h
└── main.c
我想要做的是让 Makefile 包含基于目标的不同依赖文件(调试与发布)。我现在的makefile是这样的:
CC = clang
CFLAGS = -c -g -Wall -Wextra -pedantic
SOURCES = main.c foo.c bar.c
OBJECTS = $(SOURCES:%.c=Debug/obj/%.o)
INCLUDE = -Imylib/
VPATH = mylib
.PHONY: debug
debug: Debug/bin/main
Debug/bin/main: $(OBJECTS)
$(CC) $^ -o -g $@
Debug/obj/%.o: %.c | Debug
$(CC) $(CFLAGS) $< -o $@ -MMD -MP -MF Debug/depends/$(@F:.o=.d) $(INCLUDE)
-include $(SOURCES:%.c=Debug/depends/%.d)
Debug:
-mkdir Debug
-mkdir Debug/bin
-mkdir Debug/depends
-mkdir Debug/obj
clean:
rm -rf Debug
rm -rf Release
这对于调试非常有用。但是当我尝试为 Debug 和 Release 创建单独的目标时,我很困惑如何修改 -include $(SOURCES:%.c=Debug/depends/%.d)
CC = clang
CFLAGS = -c -g -Wall -Wextra -pedantic
SOURCES = main.c foo.c bar.c
DEBUG_OBJECTS = $(SOURCES:%.c=Release/obj/%.o)
RELEASE_OBJECTS = $(SOURCES:%.c=Debug/obj/%.o)
INCLUDE = -Imylib/
VPATH = mylib
.PHONY: all debug release
all: release debug
release: Release/bin/main
debug: Debug/bin/main
Release/bin/main: $(RELEASE_OBJECTS)
$(CC) $^ -o $@
Release/obj/%.o: %.c | Release
$(CC) $(CFLAGS) $< -o $@ -MMD -MP -MF Release/depends/$(@F:.o=.d) $(INCLUDE)
Debug/bin/main: $(DEBUG_OBJECTS)
$(CC) $^ -o -g $@
Debug/obj/%.o: %.c | Debug
$(CC) $(CFLAGS) $< -o $@ -MMD -MP -MF Debug/depends/$(@F:.o=.d) $(INCLUDE)
# -------------------------------------------------------
# -include $(SOURCES:%.c=Debug/depends/%.d) What do I do?
# -------------------------------------------------------
Release:
-mkdir Release
-mkdir Release/bin
-mkdir Release/depends
-mkdir Release/obj
Debug:
-mkdir Debug
-mkdir Debug/bin
-mkdir Debug/depends
-mkdir Debug/obj
clean:
rm -rf Debug
rm -rf Release
问题
如何根据目标有条件地包含依赖文件?
有没有更好的项目组织结构?
我对 makefile 非常陌生。以前我只是依靠我的 IDE 来管理构建和配置。还有其他提示可以帮助改进这个 makefile 吗?
【问题讨论】:
当您使用make debug release
(或make all
)调用它时,您是否已经知道要做什么?应该包含哪些依赖文件?
我的意图是,只要构建调试可执行文件,就会包含 Debug/depends,而只要构建发布可执行文件,就会包含 Release/depends。甚至可以在创建配方的过程中切换包含吗?如果没有,我会很高兴放弃make all
并只使用make debug
和make release
。
一个文件是否包含在内,这不能依赖于当前构建的目标。否则,每次 make 调用只能构建一个目标,这真的很可惜。你会接受基于递归make(即make调用make)的解决方案吗?关于这是好事还是坏事存在争议(像往常一样,当它有帮助时它是好的,当它使事情变得更糟时是坏的)。
我没有考虑递归 make 但在这种情况下它看起来可以解决问题。
【参考方案1】:
好的,我想我已经找到了一种可能的解决方案:使用两个 makefile。第一个 makefile 创建目标文件并创建最终的可执行文件。第二个 makefile 使用不同的变量调用第一个 makefile。
制作文件
export CC := gcc
export SOURCES := main.c bar.c foo.c
export VPATH := mylib/
export INCLUDES := $(VPATH:%=-I%)
export DBGFLAGS := -g -c -Wall -Wextra -pedantic
export RELFLAGS := -c -Wall -Wextra -pedantic -Os
.PHONY: all debug release
all: debug release
release:
make -f target.mk TARGET=Release CFLAGS='$(RELFLAGS)'
debug:
make -f target.mk TARGET=Debug CFLAGS='$(DBGFLAGS)'
clean:
make -f target.mk clean TARGET=Debug
make -f target.mk clean TARGET=Release
target.mk
$(TARGET)/bin/main.out: $(SOURCES:%.c=$(TARGET)/obj/%.o)
$(CC) $^ -o $@
$(TARGET)/obj/%.o: %.c | $(TARGET)
$(CC) $(CFLAGS) $< -o $@ -MMD -MP -MF $(TARGET)/depends/$(@F:.o=.d) $(INCLUDES)
$(TARGET):
-mkdir $(TARGET)
-mkdir $(TARGET)/bin
-mkdir $(TARGET)/depends
-mkdir $(TARGET)/obj
clean:
rm -rf $(TARGET)
-include $(SOURCES:%.c=$(TARGET)/depends/%.d)
【讨论】:
以上是关于Makefile 包含基于 Debug / Release 目标的依赖项的主要内容,如果未能解决你的问题,请参考以下文章
在 makefile 中构建 RELEASE 和 DEBUG