繁体   English   中英

设置我的makefile只用“make”编译C

[英]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.exeMakefile的第一个目标)依赖于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.cex1.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在结束对allclean所以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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM