makefile 基础规则

一、makefile用意

一个大工程文件是成百上千的,一个个文件的去编译可想而知效率极其低下,使用Makefile实现自动编译,并且可避免已编译文件再次编译,大大的提升了软件的开发速度。

二、 makefile规则

2.1 命名与使用

名字为Makefilemakefile
使用指令:make

2.2 一个规则

编写规则:

 目标:依赖条件
(一个 tab 缩进)命令

例:
a.out:a.o
	gcc a.o -c a.out
2.3 两个函数

src = $(wildcard ./*.c): 匹配当前工作目录下的所有.c 文件。将文件名组成列表,赋给变量 src。
obj = $(patsubst %.c, %.o, $(src)): 将参数 3 中,包含参数 1 的部分,替换为参数 2

2.4 三个自动变量

$@: 在规则的命令中,表示规则中的目标

$^: 在规则的命令中,表示所有依赖条件。如果将该变量用在模式规则中,它可以将依赖条列表中的依赖依次取出,套用模式规则

$<: 在规则的命令中,表示第一个依赖条件。如果将该变量应用在模式规则中,它可将依条件列表中的依赖依次取出,套用模式规则

模式规则:

%.o:%.c
	gcc -c $< -o %@

静态模式规则:

$(obj):%.o:%.c
	gcc -c $< -o %@

两点注意:

  1. 目标的时间必须晚于依赖条件的时间,否则,更新目标

  2. 依赖条件如果不存在,找寻新的规则去产生依赖条件

  • ALL:指定 makefile 的终极目标

  • clean:

clean:
	-rm -rf $(obj) a.out 

-:作用是删除不存在文件时,不报错。顺序执行结束

  • 伪目标:
    .PHONY: clean ALL
  • 参数:
    -n:模拟执行 make、make clean 命令
    -f:指定文件执行 make 命令

三、使用

问题:

编写一个makefile实现自动编译。要求所有 .c 文件都放在 src 目录下,所有 .o 文件都放在 obj 目录下,所有头文件都放在 include 目录下,编译时加入-Wall 和 -g 参数,能够使用 make clean 指令删除 所有 .o 文件和主程序。

C文件:
main.c

#include <stdio.h>
#include "mymath.h"

int main()
{
	int a = 10;
	int b = 5;

	printf("a + b = %d\n", add(a, b));
	printf("a - b = %d\n", minus(a, b));
	printf("a / b = %d\n", div(a, b));

	return 0;
}

add.c

int add(int a, int b) {
	return a + b;

minus.c

int minus(int a, int b) {
	return a - b;

div.c

int div(int a, int b) {
	return a / b;
}

头文件

#ifndef _MYMATH_H
#define _MYMATH_H

int add(int , int );
int minus(int , int );
int div(int , int );

#endif
答案:
src = $(wildcard ./src/*.c)

obj = $(patsubst ./src/%.c, ./obj/%.o, $(src))

args = -Wall -g
inc_path = ./include

ALL:a.out

a.out:$(obj)
        gcc $^ -o $@ $(args)

$(obj):./obj/%.o:./src/%.c
        gcc $^ -c  -o $@ -I $(inc_path) 

clean:
        -rm -rf $(obj) a.out

.PHONY: clean ALL

请添加图片描述

c/c++混合编译

在这里插入图片描述
编译目标:编译指定目录下文件(test目录不加入编译范围),编译生成可执行文件和动态库

# 编译目标
APPNAME := main
LIBNAME := libcode.so

TARGET := $(APPNAME)

all : $(LIBNAME) $(TARGET) 

# 编译器
CC := gcc
CXX := g++

# 编译器参数
CFLAGS := -Wall -g -fPIC
CPPFLAGS := -Wall -lstdc++ -g -lc -fPIC

# 分别生成.c和.cpp文件列表
CFILES += $(wildcard src/div/*.c)
CFILES += $(wildcard src/minus/*.c)
CFILES += $(wildcard plugins/*.c)

CPPFILES += $(wildcard src/div/*.cpp)
CPPFILES += $(wildcard src/minus/*.cpp)
CPPFILES += $(wildcard plugins/*.cpp)

# .h头文件列表
HEADDIRS := ./include/ ./src/div/ ./src/minus ./plugins
INCS := $(addprefix -I, $(HEADDIRS))

# 程序所链接的库
LIBS := -lpthread

# .c生成.o文件列表
COBJS := $(patsubst %.c, %.o, $(CFILES))
CPPOBJS := $(patsubst %.cpp, %.o, $(CPPFILES))

# 生成动态库或静态库依赖列表
LIBOBJS += $(COBJS)
LIBOBJS += $(CPPOBJS)

# COBJS 和 CPPOBJS 用于生成动态库或静态库,应当不包含main.cpp/main.c, 避免符号冲突
APPOBJS += main.o
APPOBJS += $(COBJS)
APPOBJS += $(CPPOBJS)

# 编译
$(LIBNAME) : $(LIBOBJS)
	@echo "\n###################### 编译动态库 ######################"
	$(CXX) -shared -o $@ $^ -fPIC
	@echo

$(TARGET) : $(APPOBJS)
	@echo "\n###################### 编译TARGET ######################"
	$(CXX) -o $@ $^ $(CPPFLAGS) $(LIBS)

main.o : ./src/main.cpp
	$(CXX) -c $< -o $@ $(INCS) $(CPPFLAGS) $(LIBS)

$(COBJS) : %.o : %.c
	$(CC) -c $< -o $@ $(INCS) $(CFLAGS) $(LIBS)

$(CPPOBJS) : %.o : %.cpp
	$(CXX) -c $< -o $@ $(INCS) $(CPPFLAGS) $(LIBS)

# 清除编译文件
clean:
	rm -rf $(APPOBJS) $(LIBNAME) $(TARGET) 

# 伪文件
.PHONY : clean all
  • 3
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux环境下的程序员如果不会使用GNU make来构建和管理自己的工程,应该不能算是一个合格的专业程序员,至少不能称得上是Linux程序员。在Linux环境下使用GNU 的make工具能够比较容易的构建一个属于你自己的工程,整个工程的编译只需要一个命令就可以完成编译、连接以至于最后的执行。不过这需要我们投入一些时间去完成一个或者多个称之为Makefile文件的编写。此文件正是make正常工作的基础。 所要完成的Makefile文件描述了整个工程的编译、连接等规则。其中包括:工程中的哪些源文件需要编译以及如何编译、需要创建那些库文件以及如何创建这些库文件、如何最后产生我们想要得可执行文件。尽管看起来可能是很复杂的事情,但是为工程编写Makefile的好处是能够使用一行命令来完成“自动化编译”,一旦提供一个(多个)正确的Makefile。编译整个工程你所要做的唯一的一件事就是在shell 提示符下输入make命令。整个工程完全自动编译,极大提高了效率。 make是一个命令工具,它解释Makefile中的指令(应该说是规则),Makefile中描述了工程中所有文件的编译顺序、规则Makefile有自己的书写格式、关键字、函数。像C语言有自己的格式、关键字和函数一样。而且在Makefile中可以使用shell所提供的任何命令来完成你想要的工作。Makefile(在其它的系统上可能是另外的文件名)在绝大多数的IDE开发环境中都在使用,已经成为一种工程的编译方法。 目前,系统完整的介绍make工具和如何编写Makefile的中文文档比较少。我整理这个文档就是希望能使众多的Linux环境下的程序员能够比较容易的掌握和学会使用它。本文所要介绍的是GNU的make,采用Red Hat FC3(包括最新发布的GNU Linux系统)所集成的GUN make工具。 本文后续所用到的所有例子都采用C语言书写的源程序,因为它是目前最普遍使用的一种语言。当然make工具不仅仅是用来管理C语言工程的,那些编译器只要能够在shell下运行的语言所构建的工程都可以使用make工具来管理。而且也可以使用make工具来做一些其它的事。例如,有这样的需求:当我们修改了某个或者某些文件后,需要能够根据修改的文件来自动对相关文件进行重建或者更新。那么应该考虑使用GNU make工具。GNU make工具为我们实现这个目的提供了非常有利的支持。工程中根据源文件的修改情况来进行代码的编译正是使用了make的这个特征。make执行时,根据Makefile规则检查文件的修改情况,决定是否执行定义的动作(那些修改过的文件将会被重新编译)。这是GNU make的执行依据。
Makefile基础语法包括以下几个部分: 1. 编译规则Makefile中的编译规则指定了目标文件的依赖关系和生成方式。通常的语法格式是: targets : prerequisites command 其中,targets是规则的目标,可以是标签、可执行文件或中间文件;prerequisites是依赖文件,即生成targets所需要的文件或目标;command是需要执行的命令,可以有多条,每一条占一行。 2. 变量定义:Makefile中可以定义变量来存储一些常用的值或路径。变量的定义格式是: variable_name = value 在后续的命令或规则中,可以通过$(variable_name)来引用该变量。 3. 通配符使用:Makefile支持使用通配符来匹配文件,常用的通配符有星号(*)和百分号(%)。星号表示匹配任意长度的任意字符,百分号则表示匹配任意长度的任意字符序列。 4. 目标文件搜索:Makefile中可以通过设置VPATH来指定目标文件的搜索路径。VPATH变量可以包含多个目录,Makefile会在这些目录中搜索依赖文件。 5. 伪目标:伪目标是一种特殊的目标,它并不对应真实的文件。在Makefile中定义伪目标可以用来执行一些特定的操作或命令。通常使用.PHONY来指定伪目标。 6. 条件判断:Makefile支持条件判断,可以根据不同的条件执行不同的命令或规则。常见的条件判断语句有if、ifdef、ifndef等。 7. 常用函数:Makefile提供了一些常用的函数,用于字符串处理或变量操作。例如,$(subst old,new,text)用于将文本中的old替换为new。 8. 命令执行:Makefile中的命令可以通过反斜杠(\)来换行,以便提高可读性。 这些是Makefile基础语法,通过合理使用这些语法,可以编写一个灵活可靠的Makefile文件来管理工程的编译和链接过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值