0

我只是写了一些纯c程序来练习,每个小程序都有一个XXX.h文件XXX.c文件和XXX_test.c带有main函数的文件。该XXX.c文件和该文件XXX_test.c都可能包含其他一些YYY.h文件。我使用 gcc -MMXXX_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.mk......YYY.mk转换成一个makefile?例如,分配给generic.mk的变量TARGETS(注意) 。我觉得难以处理的是:SXXX_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。

4

2 回答 2

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) :

生成文件.am:

 bin_PROGRAMS = XXX_test YYY_test
 XXX_test_SOURCES = XXX_test.c XXX.c
 YYY_test_SOURCES = YYY_test.c YYY.c

配置.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
于 2013-01-23T17:40:29.243 回答
-1

目标/依赖项可以是多值的。如果您指定

 TARGET := XXX_test XXY_test XYZ_test XZY_test

然后运行make all(这是默认设置,因为all它是 Makefile 中的第一个目标;因此您也可以简单地运行make),将为您构建所有这些 ???_test 文件。

于 2013-01-23T11:56:37.863 回答