我刚刚编写了一些用于练习的纯c程序,每个小程序都有一个XXX.h
文件XXX.c
文件和XXX_test.c
文件,其中包含main函数。 XXX.c
文件和XXX_test.c
都可能包含其他一些YYY.h
文件。我使用gcc -MM自动查找XXX_test.c
文件的依赖项。最后,我想出了makefile(使用GNU makefile)XXX.mk
:
# change your targets to your real targets
MINGW := MINGW32_NT-6.1
CC = gcc
OFLAG = -o
CFLAGS = -Wall -g -DDEBUG
# get the dependent header files and change their name to source files
TARGET := XXX_test
FILES := $(filter %.c %.h, $(shell gcc -MM $(addsuffix .c, $(TARGET))))
SRCS := $(FILES:.h=.c)
DEPS := $(SRCS:.c=.d)
OBJECTS := $(SRCS:.c=.o)
#determine the os platform
ifdef SystemRoot
ifeq ($(shell uname), ${MINGW})
RM = rm -f
FixPath = $1
else
RM = del /Q
FixPath = $(subst /,\,$1)
endif
else
ifeq ($(shell uname), Linux)
RM = rm -f
FixPath = $1
endif
endif
all: ${TARGET}
# include .d files generated by gcc -MMD opt
-include $(DEPS)
# to generate the .o files as well as the .d files
%.o:%.c
$(CC) $(CFLAGS) -c -MMD $< -o $@
# generate the executable program
${TARGET}: ${OBJECTS}
${CC} $^ ${OFLAG} $@
.PHONY:clean
# the "$" is not needed before "FixPath"
clean:
$(RM) $(call FixPath, ${OBJECTS} ${DEPS})
每个小程序都有一个XXX.mk
文件。它们几乎相同,只是变量TARGET
中的内容不同(参见上面的makefile)。所以我有XXX.mk
,YYY.mk
等...我想问的问题是如何转换所有的makefile,即XXX.mk
,YYY.mk
.. 。转换为一个makefile?,例如generic.mk
,其中TARGETS
(注意S
)分配给XXX_test YYY_test ...
。我觉得难以处理的是variable dependencies
:
TARGET --> OBJECTS --> SRCS --> FILES --> TARGET(the FILES is generate by gcc using -MM opt)
↓
DEPS(used to include the .d files)
每个目标(例如XXX_test)应该依赖于他们的一堆文件。我想看看GNU makefile的强大功能,我怎么能这样做?我正在学习使用gmake。
答案 0 :(得分:2)
正如您所发现的那样,您遇到的主要问题是,从DEPS扩展OBJECTS并不适用于多个目标。
解决这个问题的一种可能性是使用两阶段方法,其中第二阶段仅处理构建单个二进制(并执行所有依赖关系跟踪和二进制对象编译),第一阶段为每个阶段调用第二阶段给二进制文件。
此解决方案涉及两个 Makefile(不完全是您要求的,但仍然是):
生成文件:
TARGETS = XXX_test YYY_test ZZZ_test XYZ_test
CLEANTARGETS=$(TARGETS:=_clean)
all: $(TARGETS)
clean: $(CLEANTARGETS)
$(TARGETS) $(CLEANTARGETS):
make -f Makefile.sub $@
.PHONY: all clean $(CLEANTARGETS)
这个makefile只是调用另一个make作为参数构建的程序和辅助Makefile.sub:
# change your targets to your real targets
MINGW := MINGW32_NT-6.1
CC = gcc
OFLAG = -o
CFLAGS = -Wall -g -DDEBUG
# get the dependent header files and change their name to source files
TARGET=$(MAKECMDGOALS:_clean=)
FILES= $(filter %.c %.h, $(shell gcc -MM $(addsuffix .c, $(TARGET))))
SRCS= $(patsubst %.h,%.c,$(filter %.c %.h, $(shell gcc -MM $(addsuffix .c, $(TARGET)))))
DEPS= $(SRCS:.c=.d)
OBJECTS= $(SRCS:.c=.o)
#determine the os platform
ifdef SystemRoot
ifeq ($(shell uname), $(MINGW))
RM = rm -f
FixPath = $1
else
RM = del /Q
FixPath = $(subst /,\,$1)
endif
else
ifeq ($(shell uname), Linux)
RM = rm -f
FixPath = $1
endif
endif
# include .d files generated by gcc -MMD opt
-include $(DEPS)
# to generate the .o files as well as the .d files
%.o:%.c
$(CC) $(CFLAGS) -c -MMD $< -o $@
# generate the executable program
$(TARGET): $(OBJECTS)
$(CC) $^ $(OFLAG) $@
.PHONY:clean
# the "$" is not needed before "FixPath"
clean:
$(RM) $(call FixPath, $(OBJECTS) $(DEPS))
$(TARGET)_clean: clean
如果你坚持使用单个Makefile,那么我担心你必须手动进行依赖性跟踪。
一个更常见的构建系统是autotools,你必须自己提供每个二进制文件的源代码(要运行以下命令,你需要安装autotools;运行autoreconf
来生成configure
和Makefile.in
从以下代码中;然后运行./configure
以创建跨平台Makefile):
Makefile.am:
bin_PROGRAMS = XXX_test YYY_test
XXX_test_SOURCES = XXX_test.c XXX.c
YYY_test_SOURCES = YYY_test.c YYY.c
configure.ac:
AC_INIT([XYZ],[0.1])
AM_INIT_AUTOMAKE($PACKAGE_NAME,$PACKAGE_VERSION)
AC_CONFIG_FILES([Makefile])
AC_PROG_INSTALL
AC_LANG_C
AC_PROG_CC
AC_OUTPUT
答案 1 :(得分:-1)
目标/依赖关系可以是多值的。 如果你指定
TARGET := XXX_test XXY_test XYZ_test XZY_test
然后运行make all
(这是默认值,因为all
是Makefile中的第一个目标;所以你也可以简单地运行make
),将构建所有这些??? _test文件给你。