使用第n个依赖项运行第n个目标的命令

时间:2015-06-23 19:24:57

标签: makefile gnu-make

我对于' $<'和' $ @'宏可以与元素列表一起使用。我的最终目标是将C源文件的目录编译成具有相同名称但没有扩展名的可执行文件。我也不想制作目标文件。

这是一个简单的makefile,我想用宏升级。

CC = gcc -ansi -std=c99
CCFLAGS = -Wall -pedantic -O3

all : progA progB progC

progA : progA.c
    $(CC) $(CCFLAGS) $< -o $@

progB : progB.c
    $(CC) $(CCFLAGS) $< -o $@

progC : progC.c
    $(CC) $(CCFLAGS) $< -o $@

这很好用,但我不喜欢命令的冗余。我找到了一个有效的解决方案,并且有一个近乎解决方案,但我希望可能有一个明确的选择。

解决方法:

CC = gcc -ansi -std=c99
CCFLAGS = -Wall -pedantic -O3
PRGS := $(patsubst %.c,%,$(wildcard *.c))

all : 
    make $(PRGS)

% : *.c
    $(CC) $(CCFLAGS) $@.c -o $@

我在这里不喜欢的是在命令中打电话。跑步&#39;制作&#39;在我的终端中发送一条看起来像这样的消息:

make[1]: Entering directory '/path/to/dir'
...actual commands...
make[1]: Leaving directory '/path/to/dir'

我假设这与打开相同的makefile有关,[1]引用打开文件表中的第二个文件描述符(或沿着这些行的东西)。

接近解决方案:

CC = gcc -ansi -std=c99
CCFLAGS = -Wall -pedantic -O3
SRCS := $(wildcard *.c)
PRGS := $(patsubst %.c,%,$(SRCS))

all : $(PRGS)

$(PRGS) : $(SRCS)
    $(CC) $(CCFLAGS) $< -o $@

这几乎是有效的,除了它总是抓住第一个依赖!

..... progA.c -o progA
..... progA.c -o progB
..... progA.c -o progC

那么,有没有人有一个更清洁的方法来解决我的问题&#39;或者也许是我近乎解决方案的解决方案&#39;?无论如何,在运行命令时,是否将第n个目标与第n个依赖项匹配?

谢谢!

1 个答案:

答案 0 :(得分:1)

$(PRGS): $(SRCS)更改不正确。它列出每个源文件作为每个目标的先决条件。

您希望将all目标的先决条件设置为您希望默认构建的每个程序。为此,您需要使用all: $(PRGS)。不像你原来那样再次调用make的方法。

(如果您确实希望保留手动递归调用,以便可以在该调用上使用make --no-print-directory来避免该消息,但这仍然是错误的方法(如果您打算这样做,那么你会想要使用$(MAKE)来正确处理原始make的参数。)

原始makefile的第二个问题是在*.c目标的先决条件列表中使用%。这将每个目标的先决条件设置为目录中的每个 *.c文件。那不是你想要的。您希望每个目标都有自己的.c文件作为先决条件。

你想:

all: $(PRGS)

%: %.c
        $(CC) $(CCFLAGS) $@.c -o $@

据说make有一个内置规则,正是foo.c - &gt; foo编译所以你应该使用它。该规则使用$(CC)$(CFLAGS)变量。所以,只需将它们设置为您想要的就可以完成。

所以这个makefile应该做你想要的。 (注意我是如何将一些参数移到CFLAGS而不是CCCC一般来说,据我所知,编译器本身而不是任何参数。)

CC = gcc
CFLAGS = -ansi -std=c99 -Wall -pedantic -O3
PRGS := $(patsubst %.c,%,$(wildcard *.c))

all : $(PRGS)