我有一个看起来像这样的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
对'main'
的未定义引用
但是当我再次运行它时,一切都按预期工作。脚本有什么问题,我们如何解决?
答案 0 :(得分: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)
答案 1 :(得分:1)
以前的受访者给出了很好的答案,但没有完成。所以我也发一个帖子。
首先,在makefile中使用wildcard
是个坏主意。不要懒惰并明确列出您的文件要好得多。
如果你必须懒惰,正如shawncorey写的那样,使用wildcard
的方法是将它用于源。
此外,没有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)
答案 2 :(得分:0)
声明
OBJS=$(wildcard *.o)
收集文件系统中的所有*.o
个文件当前,但它不知道将来可能创建的任何目标文件。
第一次运行make
时,周围没有.o
个文件,因此变量OBJS
将是一个空字符串,最后的链接命令不会传入将告诉它使用哪些目标文件的命令。但是,所有其他编译步骤仍在运行。在第二次调用时make
将跳过编译阶段,因为目标文件已经存在,但由于链接失败并且缺少最终二进制文件,它将运行该步骤,现在将产生一些东西,因为已经存在要通过通配符收集的文件。
获得的经验:不要在Makefile中使用文件系统通配符,这只会造成麻烦。如果你想让自己免于工作,请学习隐式规则。