我正在做Zed Shaw的“学习C的艰难方法”课程,在第2课中,我发现在视频和书中,作者只使用make ex1
来编译他的C,而我需要运行gcc -Wall -g ex1.c -o ex1
。这是我的Makefile,似乎第一部分应该是使make命令可以编译的内容,但是“ make”命令不能编译它。
CFLAGs=-Wall -g
clean:
rm -f ex1.exe
all:
gcc -Wall -g ex1.c -o ex1.exe
答案 0 :(得分:4)
默认目标是第一个目标,因此请切换其顺序,以使all
为默认目标。
the documentation on goals中有更多详细信息:
默认情况下,目标是makefile中的第一个目标(不计算以句点开头的目标)。因此,通常编写makefile,以便第一个目标是编译它们描述的整个程序。如果makefile中的第一个规则具有多个目标,则仅该规则中的第一个目标成为默认目标,而不是整个列表。您可以使用.DEFAULT_GOAL
变量从makefile中管理默认目标的选择
答案 1 :(得分:3)
您的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.exe
,或者恰好在使用该命令的先决条件(ex1.o
)之前对其进行了修改(从文件中的修改日期开始)
现在,我们如何编译目标文件? (在您的Makefile中直接生成)
ex1.o: ex1.c
$(CC) $(CFLAGS) -c -o $@ $<
此行需要更多说明(尽管如果您不使用它,它会由make
程序自动提供)。它使用替换变量:$(CC)
扩展为默认的C编译器({{ 1}},但可以更改)。 cc
是您在$(CFLAGS)
上方定义的变量,并扩展为通常用于编译程序的编译器选项。 Makefile
由目标文件(在这种情况下为$@
文件)扩展,而ex1.o
扩展到规则右部分的左先决条件。该规则非常常见,可以将C文件编译为目标文件,它是$<
自动为您生成的,并且可以在make
高级使用中创建更多规则(我不再在这里输入,由于需要的空间量大)只能说可以这样写:
make
表示:任何扩展名为.c.o:
$(CC) $(CFLAGS) -c -o $@ $<
的文件都可以通过使用以下命令行从具有相同名称但扩展名为.o
的文件创建。这样可以自动依赖具有相同名称但扩展名为.c
且已预加载到.o
中的文件的每个.c
文件。
因此,最简单的make
可能是:
Makefile
如您所见,我已经使用变量CFLAGS=-Wall -g
src=ex1.c
ex1.exe: $(src)
$(CC) $(CFLAGS) $(LDFLAGS) -o $@ $(src)
来描述用于编译程序的C源文件。当您修改了任何或前提条件(src
上只有一个前提条件,但可能会更多)并且我正在使用相同的条件进行编译和链接时,将仅 发出依赖性编译,我需要传递编译标志和链接标志(未使用,您可以在此处删除对ex1.c
的引用)确实可以写:
$(LDFLAGS)
因此,默认操作是创建依赖于ex1.exe: ex1.c
cc -g -Wall -o ex1.exe ex1.c
clean:
rm -f ex1.exe
的{{1}}(因此,只有在修改ex1.exe
后,ex1.c
才会重新编译。要对其进行编译,只要这样做:
ex1.c
或
ex1.exe
将使用make ex1.exe
的默认第一规则。
make
是伪造的目标(没有要生成的名为Makefile
的文件),因此在您使用时
clean
其关联的命令始终被执行。它使clean
删除目标文件(因为它会删除所有make生成的文件),因此,下次运行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
文件,则重新创建)
答案 2 :(得分:1)
CFLAGS = -Wall -g
all: ex1
clean:
$(RM) ex1
.PHONY: all clean
首先修正了我的CFLAGS
定义,并在.PHONY
和all
的末尾添加了clean
,所以make
知道不为这些文件制作文件
答案 3 :(得分:0)
对于一个非常简单的makefile,我这样做:
qsorttest: qsorttest.c
gcc -Wall -g qsorttest.c -o qsorttest -lm
clean:
rm -f qsorttest
“ qsorttest.c”是我的源文件的名称,我创建的可执行文件是“ qsorttest” 确保在“程序名称:源文件”和“清洁:”下的行被制表了并且不随空格键一起移动。我把头撞在墙上一会儿,直到我搜寻出那条路为止。
我将该程序另存为“ Makefile”,与该程序的其他文件位于同一目录中,并每次都能正常运行。我只是根据需要更改源文件和程序名称,并在需要时添加额外的参数来链接库。