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

时间:2018-03-10 12:01:34

标签: makefile

我有一个看起来像这样的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'

的未定义引用

但是当我再次运行它时,一切都按预期工作。脚本有什么问题,我们如何解决?

3 个答案:

答案 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中使用文件系统通配符,这只会造成麻烦。如果你想让自己免于工作,请学习隐式规则