makefile 入门

news2024/12/23 11:15:38

make常用选项

# make 默认在当前目录中寻找GUNmakefile,makefile,Makefile的文件作为make的输入文件
# -f 可以指定默认的输入文件名,如: -f MyMakefile
# -v 显示make版本号
# -n 只输出命令,但不执行,一般用于测试
# -s 只执行命令,但不显示具体命令,与在命令中使用@作用一样
# -w 显示执行前执行后的路径
# -C dir 指定 makefile 所在的目录
make [-f file][options][target]

gcc/g++ 编译流程

预处理

gcc -E main.cpp > main.ii

编译

# 输出汇编文件 main.s
gcc -S main.ii

汇编

# 输出二进制文件 main.o(或main.obj)
gcc -c main.s

链接

# -o 重命名,默认输出a.out
# -lstdc++ 表示链接c++库
# -lc 默认链接c库
gcc main.o -lstdc++ -o main

Makefile 基本语法

# 这是一个注释
# 命令前是一个tab键
# 目标:一般指要编译的目标,也可以是执行的动作
# 依赖可以有多个
# 依赖先于当前目标执行
# 多条命令时,每一行是一个命令
目标:依赖
	命令

示例一

# make 默认执行第一个目标
# make b 表示执行b目标
a:
	echo "hello a"
b:
	echo "hello b"    

请添加图片描述
请添加图片描述

示例二

# 使用 @ 不显示指令本身
# 运行 make 指令,先显示 hello b,然后显示 hello a 
a:b
	@echo "hello a"
b:
	@echo "hello b"

请添加图片描述
请添加图片描述

Makefile 中的变量和常量

系统变量

变量名说明
$*不包括扩展名的目标文件的名称
$+所有的依赖文件,以空格分隔
$<表示规则中的第一个条件
$?所有时间戳比目标文件晚的依赖文件,以空格分隔
$@目标文件的完整名称
$^所有不重复的依赖文件,以空格分隔
$%如果目标是归档成员,则该变量表示目标的归档成员名称

系统常量

可以使用 make -p 查看

常量名说明
AS汇编程序的名称,默认为 as
CCC 编译器名称,默认为 cc
CPPC 预编译器名称,默认为 cc -E
CXXC++ 编译器名称,默认为 g++
RM文件删除程序别名,默认为 rm -f
AR静态库打包命令名,默认为 ar
LDFLAGS指定库文件路径
LIBS指定库文件
MAKEmake 指令

自定义变量

定义

变量名=变量值 或者 变量名:=变量值

使用

$(变量名)或者${变量名}

示例

# = 赋值为终值,后面赋值可以影响前面赋值,取最后一次出现的值
OBJ=demo.o add.o sub.o multi.o
# := 赋值只受前面赋值的影响
TARGET:=demo

$(TARGET):$(OBJ)
	$(CXX) $^ -o $@.exe

demo.o:demo.cpp
	$(CXX) -c $^ -o $@

add.o:add.cpp
	$(CXX) -c $^ -o $@

sub.o:sub.cpp
	$(CXX) -c $^ -o $@

multi.o:multi.cpp
	$(CXX) -c $^

.PHONY:clean show

clean:
	@$(RM) *.o $(TARGET).exe

show:
	@echo $(AS)
	@echo $(CC)
	@echo $(CPP)
	@echo $(CXX)
	@echo $(RM)

Makefile 中的伪目标和模式匹配

伪目标

作用

声明目标为伪目标之后, makefile 将不会判断目标是否存在或该目标是否需要更新

用法

# .PHONY 固定名称
.PHONY:目标

模式匹配

指令说明
%.o:%.cpp.o 依赖于对应的 .cpp
wildcard$(wildcard ./*.cpp) 获取当前目录下所有的 .cpp 文件
patsubst ( p a t s u b s t (patsubst %.cpp,%.o, (patsubst(wildcard ./*.cpp) ) 将当前目录下 .cpp 文件名替换成对应的 .o 文件名

示例

OBJ=$(patsubst %.cpp,%.o,$(wildcard ./*.cpp))
TARGET=demo

$(TARGET):$(OBJ)
	$(CXX) $^ -o $@.exe

# 根据 OBJ 中的 .o 找到对应的 .cpp
%.o:%.cpp
	$(CXX) -c $^ -o $@

.PHONY:clean show

clean:
	@$(RM) *.o $(TARGET).exe

show:
	@echo $(AS)
	@echo $(CC)
	@echo $(CPP)
	@echo $(CXX)
	@echo $(RM)
	@echo $(wildcard ./*.cpp)
	@echo $(patsubst %.cpp,%.o,$(wildcard ./*.cpp))

Makefile 中编译动态链接库

不会把代码直接编译到二进制文件中,而是在运行时才加载,只需维护一个地址

库以 .dll 和 .so 为结尾

选项说明
-fPIC大写的i,产生位置无关的代码
-shared共享
-l小写L,指定动态库
-I大写i,指定头文件目录,默认当前目录
-L手动指定库文件搜索目录,默认只链接共享目录

示例

# 生成链接库的名称规则是 lib+目标明称.dll
g++ -shared -fPIC add.cpp -o libadd.dll
# -ladd 指定动态库 libadd.dll
# -L 指定动态库路径
# main.cpp 紧跟 g++之后
g++ main.cpp -ladd -L./ -o main.exe

编写 Makefile

# 小写的L
LIBS=-ladd -lsub
# -L 可以有多个, -Wl,R 可以有多个
# -Wl,-rpath=可以让链接器在运行时找到该库,小写的L
LDFLAGS=-L./ -L./01 -Wl,-rpath=./ -Wl,-rpath=./01

main:libadd.dll libsub.dll
	# main.cpp 紧跟 g++之后
	$(CXX) main.cpp $(LIBS) $(LDFLAGS) -o $@.exe
    
libadd.dll:add.cpp
	$(CXX) -fPIC -shared $^ -o $@
libsub.dll:sub.cpp
	$(CXX) -fPIC -shared $^ -o $@

注意

windows 下是以 .dll 结尾, linux 下是以 .so 结尾

Makefile 中编译静态链接库

将代码直接编译到目标文件中,编译完成之后静态库可以删除

windows下使用 .lib 后缀, linux 下使用 .a 后缀

示例

g++ -c sub.cpp -o sub.o
# 将 .o 文件打包为 .a 文件,格式不能改变 
ar -r libsub.a sub.o
# main.cpp 紧跟 g++ 之后
g++ main.cpp -lsub -L./ -o main.exe
# 使用 objdump -DC 验证 main.exe 中有 sub.cpp内容
objdump -DC main.exe > main.txt

编写 Makefile

OBJ=add.a sub.a multi.a
TARGET=main
LIBS:=-ladd -lsub -lmulti
LDFLAGS:=-L./

$(TARGET):$(OBJ)
	# main.cpp 紧跟 g++之后
	$(CXX) main.cpp $(LIBS) $(LDFLAGS) -o $@

%.a:%.o
	$(AR) -r lib$@ $^

%.o:%.cpp
	$(CXX) -c $^ -o $@

.PHONY:clean

clean:
	@$(RM) $(TARGET) *.o *.a *.lib

Makefile 抽取公共部分

# 使用 include 关键字
# 用法 include makefile路径 
include ../makefile

Makefile 中使用shell命令

# $(shell command)
a:=$(shell ls ./)
.PHONY:show
show:
	@echo $(a)
# make show	

Makefile 中的条件判断

指令说明
ifeq判断是否相等,相等返回 true, 不等返回 false
ifneq判断是否不相等,不相等返回 true, 相等返回 false
ifdef判断变量是否存在,存在返回 true,不存在返回 false
ifndef判断变量是否不存在,不存在返回 true,存在返回 false

示例

a:=123
res:=
res1:=
# ifeq 与 () 有个空格
ifeq ($(a), 123)
	res:="相等"
else#没有elseif
	res:="不相等"
endif#结束

ifdef res1
	res1:=8
else#可以没有 else
	res1:=9
endif	

# 传参: make 变量名=值
# make f=123
show:
	@echo $(res)
	@echo $(res1)
	@echo f=$(f) b=$(b)

Makefile 中的循环

不是所有 make 都支持,可以使用 shell 替换

TARGETS:=a b c
# $(foreach v,变量,$(v))
TARGET:=$(foreach v,$(TARGET),-l$(v))

show:
	@echo $(TARGET)

Makefile 中自定义函数

# define 函数名
define fun
	# 函数名
	@echo $(0)
	# 参数1,参数2
	@echo $(1) $(2)
	@echo "hello makefile"
# 结束
endef

# 调用: $(call 函数名,参数1,参数2,...)
show:
	@$(call fun)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/144667.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第四十四讲:神州防火墙双机热备配置

两台防火墙硬件型号和软件版本都完全相同&#xff0c;为了避免防火墙不堪重负而宕机引起网络中断&#xff0c;可以考虑应用双机热备&#xff08;HA&#xff09;解决方案。双机热备能够把两台防火墙构成一个工作组&#xff0c;一主一备&#xff0c;保证数据通信畅通&#xff0c;…

【实际开发01】- 单元测试 ( 追求正确性 )

目录 0. 单元测试 概念 / 解析 1. 为什么要进行单元测试 1. JUnit ~ Test 2. IDEA 中使用 junit 单元测试 , 不能使用 Scanner 的解决方法 3. Junit 测试 Tutorial 1. daiding 4. Test 修饰的方法必须 public 1. validatePublicVoidNoArgMethods(Test.class, false, er…

功率二极管的损耗分析和选型原则

功率二极管的损耗分析和选型原则 tip&#xff1a;参考网上资料&#xff0c;学习为主 1.二极管的分类 2.二极管的损耗组成 3.二级管的损耗分析 4.应用实例1.Flyback电源电路二极管损耗计算 5.实例应用2.BOOST电路二极管损耗计算 6.实例应用3.大功率整流桥二极管参数计算 7.选型…

sqli-labs 5~6 多命通关攻略

sqli-labs 5~6 多命通关攻略描述判断注入类型正常输入不正常输入错误输入判断 SQL 查询结果的列数猜测 SQL 查询结果中的列数为两列猜测 SQL 查询结果中的列数为三列猜测 SQL 查询结果中的列数为四列爆破方式的可行性函数 UpdateXML()爆破&#xff08;报错注入&#xff09;爆破…

农业智能化进入“刚需时代 ” ,维视智造机器视觉实验室赋能新农科人才培养

1、传统农业数字化转型 新农科人才急需紧缺数千年来&#xff0c;农业是我国立国基础&#xff0c;农业兴衰关系到国家的命运。在大力推动乡村振兴的背景下&#xff0c;高校作为强农兴农的“国之重器”&#xff0c;在培育“农”的传人、新农科建设方面扮演着不可替代的角色。世界…

C++入门——内联函数、extern “C“

一. 内联函数 1.概念及分析 以inline修饰的函数叫做内联函数&#xff0c;编译时C编译器会在调用内联函数的地方展开&#xff0c;没有函数调 用建立栈帧的开销&#xff0c;内联函数提升程序运行的效率。 int Add(int a, int b) {int c a b;return c; }int main() {int re…

聚焦技术创新实力,时序数据库 TDengine 荣登中国技术先锋年度评选两大榜单

2023 年 1 月 5 日&#xff0c;中国技术先锋年度评选 | 2022 中国最受开发者欢迎的技术活动榜单正式发布。作为中国领先的新一代开发者社区&#xff0c;SegmentFault 思否依托社区活动板块及全站数百万开发者用户行为数据&#xff0c;及活动规模、内容好评度、行业综合影响力指…

Go语言设计与实现 --调度器(详细介绍)

GMP和GM模型 先来一张图&#xff1a; G(Goroutine)&#xff1a;代表Go 协程Goroutine&#xff0c;存储了 Goroutine 的执行栈信息、Goroutine 状态以及 Goroutine 的任务函数等。G的数量无限制&#xff0c;理论上只受内存的影响&#xff0c;创建一个 G 的初始栈大小为2-4K&…

vue项目安装使用element_UI

安装element_UI之前需要安装VUE脚手架框架! 第一步: 在Vscode 随意打开一个文件夹,在集成终端打开 npm i -g vue/cli (检测: vue -V) 第二步:新建一个文件夹,并且在集成终端打开安装VUE脚手架 需要输入命令: vue create yan6 //yan6 为自定义文件名 1: 选第三个自定义 2: 将…

SpringBoot缓存数据(官方案例)

在线文档项目结构 1.源码克隆&#xff1a;git clone https://github.com/spring-guides/gs-caching.git 2.包含两个项目initial和complete&#xff0c;initial可以根据文档练习完善&#xff0c;complete是完整项目 3.功能描述&#xff1a;构建应用程序&#xff0c;在图书存储库…

JAVA并发编程工具篇--1理解线程池任务的执行和线程的销毁

前言&#xff1a;在编程中我们为什么要使用线程池&#xff0c;线程池中的线程是怎么执行任务的&#xff0c;线程池中的线程是如何复用和销毁的&#xff1b; 1 什么是线程池&#xff1a; 提前创建一些线程放到一个地方&#xff0c;使用的时候直接获取&#xff0c;避免频繁的创建…

CalDAV网页客户端AgenDAV

什么是 AgenDAV &#xff1f; AgenDAV 是一个类似于 Google 日历的 CalDAV 网络客户端&#xff0c;具有 AJAX 界面&#xff0c;允许用户管理自己的日历和共享的日历。 注意事项 AgenDAV依赖于 CalDAV 服务器&#xff08;Bakal、DAViCal 等&#xff09;&#xff0c;所以需要先安…

软件测试员在面试中常遇问题

目前&#xff0c;疫情已经逐渐得到了控制&#xff0c;各行各业都掀起了复工大潮。与此同时&#xff0c;软件测试的招聘需求也随着复工的开始而变得紧急起来&#xff0c;而求职者应该怎样抓住机会进行应聘呢&#xff1f;首先最重要的就是多刷面试题&#xff0c;这样才能才面试过…

CSS权威指南(五)字体

文章目录1.字体族2.font-face3.字重&#xff08;font-weight&#xff09;4.字号&#xff08;font-size&#xff09;5.字形&#xff08;font-style&#xff09;6.字体拉伸&#xff08;font-stretch&#xff09;7.字距&#xff08;font-kerning&#xff09;8.字体变形&#xff08…

Python 办公自动化,全网最全整理来了!拒绝无效率加班!

大家好&#xff0c;今天给大家分享一篇 Python 自动化办公干货&#xff0c;整整42个实战项目案例。每一个项目案例都有详细的视频讲解&#xff0c;是一套非常全面的Python自动化办公项目&#xff0c;建议大家收藏后学习&#xff0c;梳理不易&#xff0c;记得点赞支持。详细目录…

【菜菜的CV进阶之路 - 深度学习环境搭建】常用软件安装

四、安装网易云 双系统装完了&#xff0c;下一步当然是&#xff0c;休息一下&#xff0c;听一首歌啦~ 1、连网&#xff1a;只能使用wifi连&#xff0c;网线直连的话&#xff0c;还需要配置 2、安装网易云&#xff1a; 下载最新的Linux安装包&#xff0c;然后 sudo apt inst…

数据的存储(C语言)

数据类型&#xff1a; 要了解数据是如何存储的&#xff0c;我们就得先知道C语言中的数据类型 基本数据类型 基本数据类型&#xff0c;也就是C语言内置类型&#xff1a; char -> 字符型 short -> 短整型 int -> 整…

html textarea 插入字符在光标处

textarea 插入字符在光标处前言深度解析1 效果图上代码前言 深度解析 1 效果图 上代码 <!DOCUMENT><html><head> <link rel"stylesheet" href"https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css&qu…

Semantic Segmentation | 评价指标代码解析

如有错误&#xff0c;恳请指出。 文章目录1. 定义解析2. 代码解析之前有记录过关于图像语义分割的相关评价指标与经典网络&#xff0c;在看PointNet的语义分割训练脚本的时候&#xff0c;图像的语义分割和点云的语义分割其实本质上是一致的。所以这里想记录一下语义分割的评价指…

MySQL下载及使用navicat连接mysql数据库(含下载地址、超具体细节、推荐数据库教程)

目录下载地址安装流程第一步&#xff1a;开始安装第二步&#xff1a;类型选择第三步&#xff1a;developer default第四步&#xff1a;execute第五步&#xff1a;服务器配置窗口第六步&#xff1a;网络类型配置窗口第七步&#xff1a;第八步&#xff1a;服务器密码设置窗口第九…