首页 > 学院 > 开发设计 > 正文

[041]一个简单的Makefile教程

2019-11-14 10:09:54
字体:
来源:转载
供稿:网友

Makefile 是一个简单的组织代码编译的方式。这个教程没有深入的讲解make,但能够帮助初学者快速并且容易的创建自己的中型规模以下项目的makefiles。

一个简单例子

首先让我们创建三个文件,hellomake.c,hellofunc.c及hellomake.h,这三个文件是一个典型的main程序。 hellomake.c

#include <hellomake.h>int main() { // call a function in another file myPRintHelloMake(); return(0);}

hellofunc.c

#include <stdio.h>#include <hellomake.h>void myPrintHelloMake(void) { printf("Hello makefiles!/n"); return;}

hellomake.h

/*example include file*/void myPrintHelloMake(void);

通常我们通过下面的命令编译这些代码集合:

gcc -o hellomake hellomake.c hellofunc.c -I.

上面命令编译两个cpp文件,并生成可执行文件hellomake,“-I.”是gcc需要的include文件,上面命令指当前目录,主要为hellomake.h。makefile可以免于我们每次在测试、修改、调试的时候都要重复的在命令行敲上面的命令,尤其我们需要添加更多.c文件时,makefile会为我们节省大量时间。下面就让我们开始写makefile吧!

最简单的makefile就像下面的示例: Makefile 1

hellomake: hellomake.c hellofunc.c gcc -o hellomake hellomake.c hellofunc.c -I.

如果你把上面规则放在一个叫Makefile或makefile的文件中,然后在命令行敲make命令,就会按你在makefile中写的进行编译操作。

make后没有参数,则执行makefile文件中的第一条规则。把命令依赖的文件列表放在第一行的“:”后,make就清楚,如果这些文件任意一个改变,规则hellomake就会被重新编译执行。

现在我们已经能够避免重复敲冗长的编译命令。 有一个特别重要的说明,为了使代码更加有效率,我们在makefile所有的gcc命令前写一个声明标签,如下: Makefile 2

CC=gccCFLAGS=-I.hellomake: hellomake.o hellofunc.o $(CC) -o hellomake hellomake.o hellofunc.o $(CFLAGS)

上面我们定义的常量CC和CFLAGS将告诉make,我们如何编译hellomake.c和hellofunc.c。宏常量CC是C编译器使用的,CFLAGS是传递给编译命令的一个便签列表。通过放对象文件:hellomake.o 和 hellofunc.o在规则的依赖列表中,make就知道它首先要逐一的编译.c文本,然后执行hellomake。

使用上面的makefile形式,对于小规模的工程是有效的。然而有一个重要的事情没有说明:include的文件的依赖。如果我们改变了hellomake.h,make将不会重新编译.c文件。为了补充这个缺点,我们需要告诉make,所有的.c文件依赖的.h文件,示例如下: Makefile 3

CC=gccCFLAGS=-I.DEPS = hellomake.h%.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS)hellomake: hellomake.o hellofunc.o $(CC) -o hellomake hellomake.o hellofunc.o $(CFLAGS)

这个首先添加了一个宏DEPS,它是.c文件依赖的.h文件的集合。然后我们定义了一个新规则,主要应用于所有已.o结尾的文件,这个规则告诉.o文件在宏DEPS中包含的所依赖的.c文本和.h文件。它也会告诉make,为了生成.o文件,make需要编译.c文件。“-c”标签表明生成对象文件,“-o @”标签说明把编译输出到“:”左侧的名字文件中,“<”是依赖列表中的第一个选项,宏“CFLAGS”含义就如上面定义的。

为了简化我们的编写,我们使用特殊的宏“@”和“^”,它们分别是“:”左侧和右侧内容,为了使所有的编译规则更加一般化,下面的例子,把所有的依赖文件都列在宏DEPS内,把所有的对象文件都列下宏OBJ内: Makefile 4

CC=gccCFLAGS=-I.DEPS = hellomake.hOBJ = hellomake.o hellofunc.o %.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS)hellomake: $(OBJ) $(CC) -o $@ $^ $(CFLAGS)

而且如果我们想放我们的.h文件在include目录下,我们的源码文件在src目录下,并且放一些本地依赖库文件在lib目录下,那我们怎么办呢?而且我们如何隐藏这些烦人的出现在所有地方的.o文件呢? 下面的makefile定义了include和lib目录的路径,并且把对象文件放在了src目录的obj子目录下。它还定义了一个你想包含的库的宏,例如math库-lm。这个makefile应该被放在src目录下。这个makefile还有一个规则,如果执行make clean,将会清空你的源文件和对象目录。“.PYONY”规则使得make免于加参数clean的清理操作。

Makefile 5

IDIR =../includeCC=gccCFLAGS=-I$(IDIR)ODIR=objLDIR =../libLIBS=-lm_DEPS = hellomake.hDEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))_OBJ = hellomake.o hellofunc.o OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))$(ODIR)/%.o: %.c $(DEPS) $(CC) -c -o $@ $< $(CFLAGS)hellomake: $(OBJ) gcc -o $@ $^ $(CFLAGS) $(LIBS).PHONY: cleanclean: rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~

现在你已经有一个特别好的用来管理小型和中型规模项目的makefile,你可以增加更多规则到你的makefile,你甚至能创建调用其它规则的规则。对于更多makefiles和make函数,可以访问GNU Make Manual,这里可以得到更多我们想知道的。


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表