将多个makefile转换为一个makefile

时间:2013-01-23 08:04:06

标签: makefile gnu-make

我刚刚编写了一些用于练习的纯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.mkYYY.mk等...我想问的问题是如何转换所有的makefile,即XXX.mkYYY.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。

2 个答案:

答案 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来生成configureMakefile.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文件给你。