[英]Set up my makefile to compile C with just “make”
我正在做Zed Shaw的Learn C The Hard Way课程,在第2课我发现在视频和书中,作者只使用make ex1
来编译他的C,而我需要运行gcc -Wall -g ex1.c -o ex1
。 这是我的Makefile,看起来第一部分是make make命令可以编译的,但是“make”命令不能编译它。
CFLAGs=-Wall -g
clean:
rm -f ex1.exe
all:
gcc -Wall -g ex1.c -o ex1.exe
默认目标是第一个目标,因此切换这些目标的顺序,以便all
都是默认目标。
关于目标的文档中有更多细节:
默认情况下,目标是makefile中的第一个目标(不计算以句点开头的目标)。
因此,通常编写makefile,以便第一个目标用于编译它们描述的整个程序。
如果makefile中的第一个规则有多个目标,则只有规则中的第一个目标成为默认目标,而不是整个列表。
您可以使用.DEFAULT_GOAL
变量在makefile中管理默认目标的选择
您的Makefile
没有以规则形式包含的依赖项信息。 规则是从左列开始的行(在第0列中),并且在目标(要构建的对象)和必需条件(提供给规则的对象)之间具有:
分隔符
Make执行规则链接,因此在其先决条件之前不能构建目标,因此一个好的起点是:
ex1.exe: ex1.o
这意味着ex1.exe
( Makefile
的第一个目标)依赖于ex1.o
(编译对象)....但是如何。 您可以在下面添加命令,但在命令行前面插入一个制表符:
[tab char]gcc -Wall -g ex1.o -o ex1.exe
首先,看看命令如何将ex1.o
作为gcc
输入,并生成(通过选项-o
)文件ex1.exe
。
所有这一切的意思是,在使用先决条件( ex1.o
)之前,你总是缺少ex1.exe
或者它恰好被修改(从文件中的修改日期开始)。
现在,我们如何编译目标文件? (在你的Makefile中直接制作)
ex1.o: ex1.c
$(CC) $(CFLAGS) -c -o $@ $<
这行需要更多的解释(虽然你不使用它,它是由make
程序自动提供的)它使用替换变量: $(CC)
扩展为默认的C编译器( cc
通常,但你可以改变它)。 $(CFLAGS)
是您在Makefile
之上定义的变量,并扩展为通常用于编译程序的编译器选项。 $@
由目标文件(在本例中为ex1.o
文件)扩展, $<
扩展到规则右侧部分的左前提条件。 这个将C文件编译成目标文件很常见的规则是由make
自动为你生成的,而且可以在make
advanced中创建更多(由于需要的空间量,我不打算在这里输入)只是说它可以像这样写:
.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
这意味着:任何扩展名为.o
的文件都可以从具有相同名称的文件创建,但扩展名为.c
,使用下面的下一个命令行。 这使得自动依赖于具有相同名称但扩展名为.c
文件的每个.o
文件,并在make
预加载。
所以,你最简单的Makefile
可能是:
CFLAGS=-Wall -g
src=ex1.c
ex1.exe: $(src)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(src)
如你所见,我使用变量src
来描述用于编译程序的C源文件。 只有当您修改了任何或先决条件时才会发出依赖关系(现在只有一个,在ex1.c
但可能更多)并且因为我正在编译和链接在同一个编译中,我需要传递编译标志和链接标志(未使用,您可以在这里删除对$(LDFLAGS)
的引用)确实你可以写:
ex1.exe: ex1.c
cc -g -Wall -o ex1.exe ex1.c
clean:
rm -f ex1.exe
所以,默认操作是创建ex1.exe
,它依赖于ex1.c
(因此只有在修改ex1.c
时ex1.exe
重新编译ex1.exe
。要编译它,只需执行:
make ex1.exe
要么
make
这将使用Makefile
的默认第一个规则。
clean
是一个假目标(没有名为clean
的文件生成)所以当你使用时
make clean
始终执行其关联命令。 这使得make
删除目标文件(因为它消除了所有的化妆生成的文件),所以下一次运行时make
做必要的合辑,将重新创建的所有文件。
对于简单的程序,比方说,几个源.c
文件和一些.h
文件,每个(编译中的-c
选项)和链接的单独编译,我通常使用这种方法(定义每个目标程序所需的目标文件)一个不同的变量)
# makefile for programs foo and bar.
targets = foo bar
TOCLEAN = $(TARGETS) # this variable stores what should be erased on clean target. Here we store the programs to erase.
foo_objs = a.o b.o c.o
TOCLEAN += $(foo_objs) # here, we add the objects of foo
foo: $(foo_objs)
$(CC) $(LDFLAGS) -o $@ $(foo_objs)
bar_objs = d.o e.o f.o
bar_libs = -lm -lintl -lX
TOCLEAN += $(bar_objs) # here we add the objects of bar
bar: $(bar_objs)
$(CC) $(LDFLAGS) -o $@ $(bar_objs) $(bar_libs)
clean:
rm -f $(TOCLEAN)
a.o b.o c.o: a.h b.h c.h globals.h
b.o c.o d.o e.o f.o: my_defs.h
(如您所见,对头文件的依赖是对编译对象---而不是.c
源文件...源文件构建依赖关系,但是在包含文件的情况下必须重新创建的对象文件被修改,而不是包含.c
文件)
CFLAGS = -Wall -g
all: ex1
clean:
$(RM) ex1
.PHONY: all clean
固定我的CFLAGS
定义开头,并且增加了.PHONY
在结束对all
和clean
所以make
知道不使文件这些。
对于一个非常简单的makefile,我这样做:
qsorttest: qsorttest.c
gcc -Wall -g qsorttest.c -o qsorttest -lm
clean:
rm -f qsorttest
“qsorttest.c”是我的源文件的名称,我创建的可执行文件是“qsorttest”确保“程序名:源文件”和“清除:”下的行被选中,而不是用空格键移动。 我把头撞到了墙上一段时间,直到我用谷歌搜索出来。
我将它作为“Makefile”保存在与我的程序的其他文件相同的目录中,并且每次都可以使用。 我只是根据需要更改源文件和程序名称,并在需要时为链接库添加额外的参数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.