Advertisement

C/C++文档阅读笔记-A Simple Makefile Tutorial解析

阅读量:

Makefile文件可以让程序编译更加容易。本博文没有深入讲解Makefile的详细内容和机制,其目的是帮助读者迅速构建自己的Makefile文件,并将它应用于较小规模的项目中。

简单实例

以下包含三个文件:hellomake.c、hellofunc.c和hellomake.h。这些文件构成了一个基本的具有主函数的应用程序。

hellomake.c hellofunc.c hellomake.h

| #include <hellomake.h>

int main() {

This code calls a function from another file. The myPrintHelloMake function is invoked. The program returns an exit code of 0. | #include <stdio.h> Include the standard input header. Include the hellomake specific header file.

void myPrintHelloMake(void) {

printf("Hello makefiles!\n");

return;
}| /*
example include file
*/

void myPrintHelloMake(void);
||

通常在不使用makefile时,使用如下的命令编译程序:

复制代码
    gcc -o hellomake hellomake.c hellofunc.c -I.
    
    bash

此命令负责处理两个.c源文件:hellomake.c和hellofunc.c,并生成名为hellomake的可执行程序。通过-I .指明当前目录(.),告诉编译器查找相应的头文件。没有依赖于makefile文件的情况下,默认行为即可完成大部分操作。每次修改后都需要频繁地使用↑键查找对应的命令进行编译操作。如果新增了一个新的.c源文件,则需要相应地调整相关编译指令以确保正确运行。

所以这种方式就存在2个缺点:

当电脑重启发生时,在以下两种情况下需要执行相应的边缘命令:第一种情况是创建了新的.c文件;第二种情况则是电脑重启完成。

如果仅修改了一个未更改的.c文件并运行编译器它会自动处理所有未更改的.c文件从而显著延长编译时间。

创建一个最简单的makefile文件

Makefile1

复制代码
 hellomake: hellomake.c hellofunc.c

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

文件名可以命名为Makefile或makefile,在名称行处输入 make来启动编译过程。这个 make操作无需附加参数。

第一行只是hellomake的一个简单的制表符,随后*.c标记的是目标文件.核心操作位于第二行,程序人员一般会编写一个makefile来配置项目结构.每当在终端执行make命令时,若选定的文件发生更改,系统会自动触发构建过程.

Makefile1应对了频繁使用键盘↑键时操作不便的问题;然而其主要功能是将所有文件进行编译,并未解决效率问题。

注意:在makefile的首行“:”号的前面都要有个tab,这个是必须存在的。

为了提高编译效率,就有了下面这个Makefile2:

Makefile2

复制代码
 CC=gcc

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

为便于后续脚本处理,在此定义了两个宏变量CC和CFLAGS。其主要目的是为了简化makefile脚本的编译指令。其中CC被赋值为gcc编译器,并用于生成hellomake可执行文件。具体来说,在$(CC) -o hellomake hellomake.o hellofunc.o这一系列指令中可以看出,默认情况下选择使用gcc进行编译操作。需要注意的是,在-I .这一选项下编译生成的目标文件hellomake.o将依赖于当前目录下的.h头文件完成构建过程。随后make命令依次对每一个.c源文件进行编译,并最终将构建出一个名为hellomake的可执行程序。

当前的方法足以支持小型项目的开发工作;然而,在修改包含*.h头文件的内容时(例如hellomake.h),现有的make命令不会自动触发对*.c源代码的重新编译过程;因此,在这种情况下(即*.h头文件发生更改),我们需要向make机制传递相关信息以便其重新编译对应的*.c源代码;为此我们引入了一个名为Makefile3的新配置文件来解决这个问题

Makefile3

复制代码
 CC=gcc

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

创建了DEPS宏,并且该宏包含了许多在.c++代码中必须关注的.h文件。需要注意的是,在make命令生成object文件时就必须检查该.h文件是否有更改操作。下面将介绍各个符号的具体含义:

%.o:当前目录匹配到所有.o结尾的文件;

%.c:当前目录匹配到所有.c结尾的文件;

-c:生成对应的object文件;

-o $@:编译时进行输出,输出时文件的名字放到“:”的左边;

$<:依赖的第一个文件;

将Makefile3进行了简化处理,并采用了@和^这两个标记符来实现编译规则的重写部分修改。所有include文件都包含于DEPS宏中,所有object文件也都包含于OBJ宏中。

Makefile4

复制代码
 CC=gcc

    
 CFLAGS=-I .
    
 DEPS=hellomake.h
    
 OBJ=hellomake.o hellofunc.o
    
  
    
 %.o: %.c $(DEPS)
    
     $(CC) -c -o $@ $< $(CFLAGS)
    
  
    
 hellomake: $(OBJ)
    
     $(CC) -o $@ $^ $(CFLAGS)
    
    
    
    
    bash
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-18/xF9trfmEjGZ4qVXUwzvLI7ReSgNO.png)

对符合解释的补充:

$^:所有依赖文件

为了使.h文件安置在include目录中,
源代码文件应存放在src目录,
静态库应存放在lib目录。
.o目标编译物需妥善安置,
这就需要创建一个新的makefile。
比如考虑这样一个程序依赖m.so库,
其中m代表math模块。
例如一个典型的Makefile结构如下:

Makefile5

复制代码
 IDIR =../include

    
 CC=gcc
    
 CFLAGS=-I$(IDIR)
    
  
    
 ODIR=obj
    
 LDIR =../lib
    
  
    
 LIBS=-lm
    
  
    
 _DEPS = hellomake.h
    
 DEPS = $(patsubst %,$(IDIR)/%,$(_DEPS))
    
  
    
 _OBJ = hellomake.o hellofunc.o 
    
 OBJ = $(patsubst %,$(ODIR)/%,$(_OBJ))
    
  
    
  
    
 $(ODIR)/%.o: %.c $(DEPS)
    
 	$(CC) -c -o $@ $< $(CFLAGS)
    
  
    
 hellomake: $(OBJ)
    
 	$(CC) -o $@ $^ $(CFLAGS) $(LIBS)
    
  
    
 .PHONY: clean
    
  
    
 clean:
    
 	rm -f $(ODIR)/*.o *~ core $(INCDIR)/*~ 
    
    
    
    
    bash
![](https://ad.itadn.com/c/weblog/blog-img/images/2025-08-18/53g1v8VGhnWmbcAoUZESJBRXa9wz.png)

解释下参数:

patsubst:

名称:模式字符串替换函数——patsubst。

功能:搜索给定文本中的字符(字符通过空格、Tab、回车换行等方式分割),判断其是否匹配指定模式。若匹配成功,则将匹配到的内容替换为

在这里,可以包含通配符‘%’来代表任意长度的字串。当中也包含‘%’时,则其中每个‘%’将对应于中的相应‘%’

(可以用“\”来转义,以“%”来表示真实含义的“%”字符)

返回:函数返回被替换过后的字符串。

示例:

$(patsubst %.c,%.o, a.c b.c)

把字串“a.c b.c”符合模式[%.c]的单词替换成[%.o],返回结果是“a.o b.o”

实例代码打包下载地址:

https://github.com/fengfanchen/CAndCPP/tree/master/MakeFileExample

全部评论 (0)

还没有任何评论哟~