使:通配符使用所有目标文件

3

我有一个类似于下面这样的 Makefile:

CC=cc
CFLAGS=-g -std=c99 -Wfatal-errors
OBJS=$(wildcard *.o)

all: main.o cmdargs.o io.o
    $(CC) -o app $(OBJS)

main.o: main.c
    $(CC) -c main.c $(CFLAGS)
cmdargs.o: cmdargs.c
    $(CC) -c cmdargs.c $(CFLAGS)
io.o: io.c
    $(CC) -c io.c $(CFLAGS)

clean:
    @rm -rf app $(OBJS)

每次我在清理后运行make all时,会出现一个错误,如下所示:

cc -o

undefined reference to `main'

但是当我第二次运行它时,一切都像预期的那样正常工作。这个脚本有什么问题,我们该怎么解决它呢?
3个回答

4
之前的回答不错,但并不完整。让我也来发表一下看法。
首先,在makefile中使用通配符是不明智的。最好不要偷懒,将你的文件都列出来更好。
如果你必须偷懒,那么像shawncorey所说的,可以使用通配符来进行源文件的匹配。
另外,不要为伪目标(如all)设置配方。在你的示例中,all的配方总是会运行,这非常低效。
CC := gcc

SRCS := $(wildcard *.c)
OBJS := $(SRCS:c=o)

.PHONY: all clean

all: app 

app: $(OBJS) Makefile
    $(CC) -o $@ $(OBJS)

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

clean:
    @rm -rf app $(OBJS)

1
如果你小心地包含所有源文件,就可以自动创建对象文件的名称。
# --------------------------------------
#  list all source files
CPP_SOURCES := $(wildcard *.cpp)
C_SOURCES   := $(wildcard *.c)
# other source files here

# consolidate all sources
SOURCES := $(CPP_SOURCES) $(C_SOURCES)


# --------------------------------------
# list all object files
CPP_OBJECTS := $(CPP_SOURCES:.cpp=.o)
C_OBJECTS   := $(C_SOURCES:.c=.o)
# other object files here

# consolidate all objects
OBJECTS := $(CPP_OBJECTS) $(C_OBJECTS)


all:
    echo $(SOURCES)
    echo $(OBJECTS)

PS: 更紧凑的 Makefile:

#  list all source files
SOURCES := $(wildcard *.cpp) $(wildcard *.c)

# determine all object files
OBJECTS := $(addsuffix .o, $(basename $(notdir $(SOURCES))))

all:
    echo $(SOURCES)
    echo $(OBJECTS)

0

这个语句

OBJS=$(wildcard *.o)

收集当前文件系统中所有的*.o文件,但它不知道未来可能创建的任何目标文件。

当您第一次运行make时,没有.o文件存在,因此变量OBJS将是一个空字符串,并且最终链接命令不会传递到命令中,告诉它要使用哪些目标文件。但是,所有其他编译步骤仍然会运行。在第二次调用make时,将跳过编译阶段,因为目标文件已经存在,但由于链接失败并且最终二进制文件丢失,因此它将运行该步骤,这将现在产生一些东西,因为有通配符可以收集的文件。

教训:不要在Makefile中使用文件系统通配符,这只会引起麻烦。相反,如果您想节省工作,请了解隐式规则


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接