/makefile.conf
.SUFFIXES : .c .o
cc = gcc
CFLAG = -c
OFLAG = -o
O2FLAG = -O2
WPIFLAG = -lwringPi
RM = rm -rf
TARGET_SRCS = main.c
TARGET_OBJS = $(TARGET_SRCS:$.c=$.o)
TARGET_NAMES = $(TARGET_SRCS:$.c=$)
BINARY_NAME = LED_TEST
/ makefile
include makefile.conf
$(TARGET_OBJS) : $(TARGET_SRCS)
$(CC) $(O2FLAG) $(CFLAG) $(OFLAG) $^
我想弄清楚gnu make的工作原理和使用方法。然而,我是个初学者。
我想在我的任务中使用make(不是强制的,只是我的热情)来运行简单的代码,通过wiringpi来点亮LED。
其实只有一个main.c,而我想做的是运行以下的makefile
gcc -O2 -c -o main.o main.c
gcc -o main main.o -lwiringPi
由于我上次的代码没有工作,(不断得到循环的main.c <-main.c dependency dropped错误)。
我试着做一个只运行
gcc -O2 -c -o main.o main.c
但我还是得到循环main.c错误,我不知道那是什么意思。
我试着查了一下gnu的制作手册,但是我想了想,这要花我的命才能明白。
所以我想看看代码,用我看到的东西做一个。
我想我明白makefile.conf的概念,但 我还是不明白.SUFFIXES的功能。
我的理解是,我注意到makefile.conf中的.c和.o是一个规则,后面的代码定义了那些将在makefile中使用的变量。
我怎么才能改正这些代码呢? 当实际的 "分配 "包括添加注释在内只花了5分钟。
第一个makefile.TARGET_SRCS:$.c=$.o
main:
gcc -O2 -c -o main.o main.c
gcc -o main main.o -lwiringPi
当它完美地运行时 第二个makefile。
main: main.o
gcc -o main main.o -lwiringPi
main.o: main.c
gcc -O2 -c -o main.o main.c
当它完美地运行时 第三个makefile。
main: main.o
gcc -o $@ $^ -lwiringPi
main.o: main.c
gcc -O2 -c -o $@ $<
当这些都能完美运行时,你就可以使用更高级的技术了。
如果你真的是个新手,从简单的makefile开始,直到你需要额外的功能,这通常会很有帮助。
main: main.c
gcc -O2 -o main -lwiringPi main.c
注意在 gcc
是一个单一的标签字符。
一旦你掌握了这个窍门,你就可以用各种项目来代替,使你的 "制作规则 "更容易复制和维护。 比如说 %^
意思是 "每一个从属来源,所以规则的改写是
main: main.c
gcc -O2 -o main -lwiringPi $^
偶尔,你可能想提供编译器的简单重新配置,所以,如果你有十几条规则,并想在一个地方配置编译器
CC=gcc
main: main.c
$(CC) -O2 -o main -lwiringPi $^
将扩大 CC
变量的值为 gcc
在制作时。 这种扩展的实用性是有上限的,例如,如果某样东西是 "许多相同东西中的一种",你可能不想为这个单独的项目声明一个变量。 例如,你的 WPIFLAG
很可能总是需要的,而且很可能无法成功地重新配置。 也许一个加载器标志变量更有意义。
LDFLAGS=-lwiringPi -lm -lwhatever
和一个编译器标志变量
CFLAGS=-O2 -Werror -Wfatal-errors
这将导致更合理的
main: main.c
$(CC) $(CFLAGS) -o main $(LDFLAGS) $^
最后,您可以替换目标 main
在这种情况下,用另一个特殊的变量。$@
意思是 "正在构建的目标"
main: main.c
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $^
请注意,对于对象文件,你是把所有的对象都列为依赖于你所有的源。 如果你想支持独立的对象构建规则,你需要做一些不同的事情。
main: main.o
$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $^
而且你需要为每个对象制定规则。
main.o: main.c
$(CC) $(CFLAGS) -c -o $@ $(LDFLAGS) $^
但为每个对象打这个规则会变得很费劲。 为了使这个规则自动化,你将使用一个基于文件后缀的模式,以及一个后缀规则。
.SUFFIXES : .o .c
.c.o :
$(CC) $(CFLAGS) -c $<
请注意,上面的规则依赖于$(CC)的默认行为,即生成一个 something.o
当 something.c
编制了 -c
标志。 如果你想让输出文件显式化
.SUFFIXES : .o .c
.c.o :
$(CC) $(CFLAGS) -c -o $@ $<
这个后缀规则就像一个宏一样。 当有人需要 thing.o
它将从 thing.c
如果 thing.c
存在,即使没有明确的规则,也会有 thing.c
有了这个,你就可以把你所有的对象收集到原来的。main
目标。 (我们将删除CFLAGS,因为不会发生编译,只会发生链接)
main: main.o other.o first.o list.o end.o
$(CC) -o $@ $(LDFLAGS) $^
但有些人觉得列出对象很麻烦,于是喜欢把它们放在一个变量中
main: $(OBJS)
$(CC) -o $@ $(LDFLAGS) $^
这意味着您将需要声明和设置 OBJS
OBJS = main.o other.o first.o list.o end.o
但跟踪中间文件有点奇怪,为什么不跟踪实际来源呢?
SOURCES = main.c other.c first.c list.c end.c
好吧,但我们如何获得所需的 OBJS
从 SOURCES
? 我们将解除防御 SOURCES
,将后缀修改为 .o
OBJS = ${SOURCES:.c=.o}
最终结果
SOURCES = main.c other.c first.c list.c end.c
OBJS = ${SOURCES:.c=.o}
CC=gcc
CFLAGS=-O2 -Werror -Wfatal-errors
LDFLAGS=-lwiringPi -lm -lwhatever
.SUFFIXES : .o .c
.c.o :
$(CC) $(CFLAGS) -c -o $@ $<
main: ${OBJS}
$(CC) -o $@ $(LDFLAGS) $^