码迷,mamicode.com
首页 > 其他好文 > 详细

makefile编写

时间:2020-01-06 23:13:34      阅读:89      评论:0      收藏:0      [点我收藏+]

标签:pat   注释   sys   完成   包含   efi   当前目录   source   font   

刚看了一整套完整的makefile的编写规则来总结一下吧

1.makefile 的编写

Makefile 是一个描述“如何生成整个项目”的脚本文件

有很多规则

每一条规则格式为:

Target:dependencies

[TAB]system command1

[TAB]system command2

.....

Target: 目标

Dependencies: 依赖

<TAB>:每行命令前面都需要加一个TAB

System command:系统命令

读作要完成目标target 必须执行命令 commands...

Clean:

Rm -rf *.o helloworld   

可以有多条规则,每条规则可以有多条命令

但是输入make命令是,同时显示指定要执行那一条规则rule 如make clean

注: make命令默认只执行一条规则,其他默认不执行

 2.增量编译(针对一个项目中有很多个源文件  a.cpp b.cpp c.cpp, 当只有某个文件改变了,只需要编译其中一个文件 称为增量编译)

Helloworld: main.cpp other.cpp other.h

G++ main.cpp other.cpp -o helloworld

在目标的后面加上所依赖的文件,就会实现增量编译,只编译有变化的文件,必须加上依赖文件才会增量编译,否则都不会编译,永远是最新的可执行文件

Main:main.o other.o

G++ main.o other.o -o main

Main.o mian.cpp other.h

G++ -c main.cpp -o main.o

Other.o:other.cpp other.h

G++ -c other.cpp -o other.o

3.Makefile 中的注释

#开头的行,为注释行

 

4.Makefile 中的支持的变量

 SUBDIR = src xml

Test:

Echo$(SUBDIR)

定义一个变量SUBDIR

(1)用等号=赋值(等号两边可以加空格)

(2)+=追加字符串

(3)$(SUBDIR)取到变量的值(要加小括号)

注:如果不想让命令复现 则在Echo$(SUBDIR) 前面加上@就可以了

特殊变量

$@指代target

$^指代dependencies依赖 项列表

$< 指代依赖项的第一项     这三中特殊的变量经常用到

Test2:main.cpp other.cpp

Echo $^            则代表main.cpp other.cpp

Echo$@            则代表 test2

Echo$< 则代表 main.cpp

Makefile  中还有一些预定义的函数

$(函数名 参数列表)

函数名:Makefile内部自带的函数

参数列表:以逗号分开

注:函数名和列表参数之间是以空格分开的 PWD=$(shell pwd)

Shell 为Makefile的函数  pwd为参数 PWD为一个变量

CXX_SOURCE=$(wildcard ./*.cpp)   

Wildcard 写出该目录下的文件名 ./表示当前目录  *.cpp为通配符

5. 优化Makefile

优化方向:针对大量CPP文件,减少手工编辑操作,争取最大化的自动化

原则:保持增量编译的功能

(1)使用通配符

%.o:%.cpp

G++ -c $< -o $@  可以将多个目标 使用一句话  .cpp编译生成.o文件

$@ 指目标

$< 指第一个依赖项

可以代替

Main.o: main.cpp other.h

G++ -c main.cpp -o main.o

Other.o:other.cpp other.h

G++ -c other.cpp -o other.o (-o 是生成目标)

(2) 自动罗列.o文件

CXX_SOURCES = $(wildcard*.cpp)

CXX_OBJECTS=$(patsubst %.cpp,%.o,$(CXX_SOURCES))

patsubst函数: 将所有的源文件转化为.o为文件  并将.o文件赋值给变量CXX_OBJECTS

源格式        目标格式          文件名列表

wildcard*.cpp 使当前文件下的*.cpp罗列出

Helloworld:$(CXX_OBJECTS)

G++ $(CXX_OBJECTS) -o helloworld

3)设置EXE变量,表示输出程序的名字

4)头文件依赖(增量编译必须考虑头文件的更新)

使用编译选项 -MMD

g++/gcc 在编译的xxx.cpp 的时候,可以提取里面包含的头文件(双引号包含的头文件)

然后生成对应.d文件,包含.cpp里面包含的头文件

G++ -c -MMD main.cpp -o main.o 则在生成一个main.o 的同时生成一个main.d文件

 

优化后的Makefile

EXE=helloworld

CXX_SOURCES=$(wildcard *.cpp)//所有源文件

CXX_OBJECTS=$(patsubst %.cpp, %.o $(CXX_SOURCES))//所有.o文件

DEP_FILES=$(patsubst %.cpp, %..d $(CXX_OBJECTS)//所有.d文件

$(EXE) :$(CXX_OBJECTS)

g++ $(CXX_OBJECTS) -O $(EXE)

%.o:%.cpp

g++ -c -MMD $< -o $(EXE)

-include $(DEP_FILES)

clean:

rm *.o $(EXE)

 

6. 支持子目录编译的makefile

(1)支持子目录

(2).o .d文件与.cpp文件混在一起,比较乱

一个项目通常是有多个子目录的

Foreach 便利子目录 三个参数

SUBDIR = src object   (src object为两个目录)

CXX_SOURCES = $(foreach dir,$(SUBDIR), $(wildcard $(dir) /*.cpp))

 

CXX_SOURCES=$(wildcard *.cpp)//所有源文件

换成

SUBDIR = src object   (src object为两个目录)

CXX_SOURCES = $(foreach dir,$(SUBDIR), $(wildcard $(dir) /*.cpp))

就可以支持子目录的Makefile

 

以下是一套完整的makefile(支持增量编译,子目录编译)

EXE=helloworld

//CXX_SOURCES=$(wildcard *.cpp)//所有源文件

SUBDIR = src object   (src object为两个目录)  --该项目所有

CXX_SOURCES = $(foreach dir,$(SUBDIR), $(wildcard $(dir) /*.cpp))//所有目录的.CPP

CXX_OBJECTS=$(patsubst %.cpp, %.o $(CXX_SOURCES))//所有.o文件

DEP_FILES=$(patsubst %.cpp, %..d $(CXX_OBJECTS)//所有.d文件

$(EXE) :$(CXX_OBJECTS)

g++ $(CXX_OBJECTS) -O $(EXE)

%.o:%.cpp

g++ -c -MMD $< -o $(EXE)

clean:

rm -rf *.o $(EXE)

-include $(DEP_FILES)

makefile编写

标签:pat   注释   sys   完成   包含   efi   当前目录   source   font   

原文地址:https://www.cnblogs.com/that-boy-done/p/12158651.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!