C makefile编译多个目标

C makefile编译多个目标,c,makefile,C,Makefile,这是我在这个论坛上的第一篇帖子。抱歉打扰了,我一直在找类似的东西,奇怪的是我找不到。问题就在这里。 我有三个没有标题的(主)文件,我想一次编译它们(如果我简单地键入“make”),或者逐个编译它们(如果我指定了没有扩展名的文件名)。因此,我构建了makefile,但命令中出现了一些错误 $(TARGETS): $(BUILDS_DIR)% : $(SRCS_DIR)%.c 我从哪里得到这个错误的 make:**无规则生成目标 这是完整的文件 .SUFFIXES: .c ROOT = $(add

这是我在这个论坛上的第一篇帖子。抱歉打扰了,我一直在找类似的东西,奇怪的是我找不到。问题就在这里。 我有三个没有标题的(主)文件,我想一次编译它们(如果我简单地键入“make”),或者逐个编译它们(如果我指定了没有扩展名的文件名)。因此,我构建了makefile,但命令中出现了一些错误

$(TARGETS): $(BUILDS_DIR)% : $(SRCS_DIR)%.c
我从哪里得到这个错误的

make:**无规则生成目标

这是完整的文件

.SUFFIXES: .c
ROOT = $(addprefix $(PWD), /)
BUILDS_DIR = $(addprefix $(ROOT), builds/)
SRCS_DIR   = $(addprefix $(ROOT), src/)

SRCS = $(wildcard $(SRCS_DIR)*.c)

TARGETS = ${SRCS:$(SRCS_DIR)%.c=%}
EXES = ${addprefix $(BUILDS_DIR), $(TARGETS)}

CC      = gcc
CFLAGS  = -Wall -O3

RM = rm -f

.PHONY: all $(TARGETS) clean

all: $(TARGETS)

$(TARGETS): $(BUILDS_DIR)% : $(SRCS_DIR)%.c
    $(CC) $(CFLAGS) \
        $< \
        -o $@
    @echo -e "\n\n\t\t*** Compile successfully! ***\n" ;

clean:
    $(RM)   $(EXES) \
        $(SRCS_DIR)*~
    @echo -e "\n\n\t\t*** Cleanup complete! ***\n"
。后缀:.c
根=$(addprefix$(PWD),/)
BUILDS\u DIR=$(addprefix$(ROOT),BUILDS/)
SRCS_DIR=$(addprefix$(根),src/)
SRCS=$(通配符$(SRCS_DIR)*.c)
TARGETS=${SRCS:$(SRCS_DIR)%.c=%}
EXES=${addprefix$(BUILDS\u DIR),$(TARGETS)}
CC=gcc
CFLAGS=-Wall-O3
RM=RM-f
.虚假:所有美元(目标)都是干净的
全部:$(目标)
$(目标):$(构建目录)%:$(SRCS目录)%
$(CC)$(CFLAGS)\
$< \
-o$@
@echo-e“\n\n\t\t***编译成功!***\n”;
清洁:
$(RM)$(前任)\
$(SRCS_目录)*~
@echo-e“\n\n\t\t***清理完成!***\n”
我错在哪里?我猜答案很愚蠢,可能是基于一个基本的错误

提前感谢

假设GNU Make(因为您使用了它的语法)

第一个问题是,您试图将目标目录连接到模式,而不是简单地使用目标文件名,从而错误地重写目标

你有:

$(TARGETS): $(BUILDS_DIR)% : $(SRCS_DIR)%.c
    $(CC) $(CFLAGS) $< -o $@
$(目标):$(构建目录)%:$(SRCS目录)%
$(CC)$(CFLAGS)$<-o$@
解决方案是使用在命令行上添加目录路径

$(TARGETS): % : $(SRCS_DIR)%.c
    $(CC) $(CFLAGS) $< -o $(BUILDS_DIR)$@
$(目标):%:$(SRCS_DIR)%.c
$(CC)$(CFLAGS)$<-o$(构建目录)$@

假设您的三个源文件是
file1.c
file2.c
file3.c
。我将创建如下所示的makefile(假设GNU make)

使用这个make文件的一个示例是(我使用-n来显示将运行哪些规则,但没有实际运行它们,因为我的源文件是用于测试的空文件。)

我们可以利用通配符缩短上述文件

CC=gcc CFLAGS=-ansi-墙壁-迂腐

RM=RM-f

OBJS=file1.o file2.o file3.o

PROG=我的程序

$(进度):$(OBJS) $(CC)$(CFLAGS)$(OBJS)-o$(PROG)

全部:清洁$(进度)

%:%c $(CC)$(CFLAGS)-c$<-o$@.o

清洁: $(RM)*.o$(PROG)~

我们需要在输出文件名后面附加一个“.o”,这样我们就可以按照第一个生成规则的
$(OBJ)
变量所定义的格式创建文件。执行此操作将提供以下示例运行:

    [******@broadsword junk]$ make -n
    gcc -ansi -Wall -pedantic   -c -o file1.o file1.c
    gcc -ansi -Wall -pedantic   -c -o file2.o file2.c
    gcc -ansi -Wall -pedantic   -c -o file3.o file3.c
    gcc -ansi -Wall -pedantic file1.o file2.o file3.o -o my_program
    [******@broadsword junk]$ make -n file2
    gcc -ansi -Wall -pedantic -c file2.c -o file2.o
顺便说一句,我个人不介意多输入两个字符,我喜欢让我的目标与运行的规则集的输出相匹配,所以我会将规则编写为

     file1.o : file1.c
         $(CC) $(CFLAGS) -c file1.c -o file1.o

%.o:%.c
$(CC)$(CFLAGS)-c$<-o$@

最后,我强烈怀疑,当我们执行
make
make all
时,我们并没有运行makefile下半部分的文件特定规则,而是运行GNU手册中描述的内置规则:“n.o是从n.c自动生成的,其格式为
$(CC)$(CPPFLAGS)$(CFLAGS)-c

无规则设定目标
。。。什么?完全错误是什么?运行
make-d…
,这将显示
make
正在做什么。您正在使用哪个
make
?它可以在大多数/所有GNU/Linux系统上找到,或者从中的一个或第三方端口
make
?GNU make有时被称为
gmake
NetBSD make有时被称为或作为一个包提供,称为。注意,cmake是一个不同的构建系统。我认为
addprefix
wildcard
是GNU Make-specific,而
后缀
是相当古老的样式,应该是不必要的。后缀行始终需要是一个列表,包含所有将要使用的后缀。一般来说,最好不要在make文件中放入.后缀语句,除非在非常特殊的情况下。然后将使用默认列表。我看不到在make文件中包含文件或库的引用。这让我想知道,当这些文件没有I/O、没有数学、什么都没有的时候,它们能做些什么。非常感谢!!实际上,通过这种修正,它可以完美地工作!谢谢,这也行,但我的想法是跳过对象文件,因为我以后不需要链接任何东西。但应用经典方法可能更清晰、更简单。谢谢!不建议使用您的示例生成文件。除了不必要的复杂之外,它还不如内置的标准功能强大。最后,让
all
依赖于
clear
目标是不正常的。它违背了只重新编译已更改内容的
make
的目的。@mctylr,在您放入pastebin的内容中,为什么要使用all目标?您拥有无规则的
all:$(PROG)
,然后下一个目标行是
$(PROG):$(OBJS)
,其中包含用于构建程序的规则。因此,执行make as
make
,我们得到trigger all目标,它反过来触发
$(PROG)
目标。删除“all”目标并将“$(PROG)”目标作为makefile中的第一个目标似乎更简单。此外,对我来说,
makeall
命令意味着重新编译所有内容,而不仅仅是最近更改的内容,因此对clean的依赖性。对于只有一个可执行文件的小项目来说,这是不必要的。您可以在GNU Make命令行中使用多个目标,例如,
makecleanlall
来干净地重建所有内容。或者创建一个
cleanbuild
rebuild
目标来执行相同的操作<代码>清除构建:清除所有。
    [******@broadsword junk]$ make -n
    gcc -ansi -Wall -pedantic   -c -o file1.o file1.c
    gcc -ansi -Wall -pedantic   -c -o file2.o file2.c
    gcc -ansi -Wall -pedantic   -c -o file3.o file3.c
    gcc -ansi -Wall -pedantic file1.o file2.o file3.o -o my_program
    [******@broadsword junk]$ make -n file2
    gcc -ansi -Wall -pedantic -c file2.c -o file2.o
     file1.o : file1.c
         $(CC) $(CFLAGS) -c file1.c -o file1.o
     %.o :%.c
         $(CC) $(CFLAGS) -c $< -o $@