当前位置: 首页 > news >正文

Linux下makefile 编译项目

文章目录

  • 1、规划makefile编写
  • 2、makefile文件
    • 2.1、根目录下common.mk
    • 2.2、config.mk
    • 2.3、根目录makefile
  • 2.4、其他目录下

1、规划makefile编写

a、根目录下放三个文件:

1、makefile:是咱们编译项目的入口脚本,编译项目从这里开始,起总体控制作用。
2、config.mk:配置脚本,被makefile包含,单独分处理,为了应付一些可变的东西。
3、common.mk:最核心的编译脚本,定义makefile编译规则,并且各个子目录中都用到这个来编译.c文件的编译

b、每个子目录下

都有一个叫做makefile的文件,每个makefile文件,都会包含根目录下的common.mk。

现在不支持目录中嵌套子目录

2、makefile文件

2.1、根目录下common.mk


#.PHONY:all clean ifeq ($(DEBUG),true)
#-g是生成调试信息。GNU调试器可以利用该信息
CC = g++ -std=c++11 -g 
VERSION = debug
else
CC = g++ -std=c++11
VERSION = release
endif#CC = gcc# $(wildcard *.c)表示扫描当前目录下所有.c文件
#SRCS = nginx.c ngx_conf.c
SRCS = $(wildcard *.cxx)#OBJS = nginx.o ngx_conf.o  这么一个一个增加.o太麻烦,下行换一种写法:把字符串中的.c替换为.o
OBJS = $(SRCS:.cxx=.o)#把字符串中的.c替换为.d
#DEPS = nginx.d ngx_conf.d
DEPS = $(SRCS:.cxx=.d)#可以指定BIN文件的位置,addprefix是增加前缀函数
#BIN = /mnt/hgfs/linux/nginx
BIN := $(addprefix $(BUILD_ROOT)/,$(BIN))#定义存放ojb文件的目录,目录统一到一个位置才方便后续链接,不然整到各个子目录去,不好链接
#注意下边这个字符串,末尾不要有空格等否则会语法错误 
LINK_OBJ_DIR = $(BUILD_ROOT)/app/link_obj
DEP_DIR = $(BUILD_ROOT)/app/dep#-p是递归创建目录,没有就创建,有就不需要创建了
$(shell mkdir -p $(LINK_OBJ_DIR))
$(shell mkdir -p $(DEP_DIR))#我们要把目标文件生成到上述目标文件目录去,利用函数addprefix增加个前缀
#处理后形如 /mnt/hgfs/linux/nginx/app/link_obj/ngx_signal2.o /mnt/hgfs/linux/nginx/app/link_obj/ngx_signal.o
# := 在解析阶段直接赋值常量字符串【立即展开】,而 = 在运行阶段,实际使用变量时再进行求值【延迟展开】
# /mnt/hgfs/linux/nginx/app/link_obj/nginx.o   /mnt/hgfs/linux/nginx/app/link_obj/ngx_conf.o 
OBJS := $(addprefix $(LINK_OBJ_DIR)/,$(OBJS))
DEPS := $(addprefix $(DEP_DIR)/,$(DEPS))#找到目录中的所有.o文件(编译出来的)
LINK_OBJ = $(wildcard $(LINK_OBJ_DIR)/*.o)
#因为构建依赖关系时app目录下这个.o文件还没构建出来,所以LINK_OBJ是缺少这个.o的,我们 要把这个.o文件加进来
LINK_OBJ += $(OBJS)#-------------------------------------------------------------------------------------------------------
#make找第一个目标开始执行[每个目标[就是我们要生成的东西],其实都是定义一种依赖关系],目标的格式为:
#目标:目标依赖【可以省略】
#	要执行的命令【可以省略】
#如下这行会是开始执行的入口,执行就找到依赖项$(BIN)去执行了,同时,这里也依赖了$(DEPS),这样就会生成很多.d文件了
all:$(DEPS) $(OBJS) $(BIN)#这里是诸多.d文件被包含进来,每个.d文件里都记录着一个.o文件所依赖哪些.c和.h文件。内容诸如 nginx.o: nginx.c ngx_func.h
#我们做这个的最终目的说白了是,即便.h被修改了,也要让make重新编译我们的工程,否则,你修改了.h,make不会重新编译,那不行的
#有必要先判断这些文件是否存在,不然make可能会报一些.d文件找不到
ifneq ("$(wildcard $(DEPS))","")   #如果不为空,$(wildcard)是函数【获取匹配模式文件名】,这里 用于比较是否为""
include $(DEPS)  
endif#----------------------------------------------------------------1begin------------------
#$(BIN):$(OBJS)
$(BIN):$(LINK_OBJ)@echo "------------------------build $(VERSION) mode--------------------------------!!!"#一些变量:$@:目标,     $^:所有目标依赖
# gcc -o 是生成可执行文件$(CC) -o $@ $^ -lpthread#----------------------------------------------------------------1end-------------------#----------------------------------------------------------------2begin-----------------
#%.o:%.c
$(LINK_OBJ_DIR)/%.o:%.cxx
# gcc -c是生成.o目标文件   -I可以指定头文件的路径
#如下不排除有其他字符串,所以从其中专门把.c过滤出来 
#$(CC) -o $@ -c $^$(CC) -I$(INCLUDE_PATH) -o $@ -c $(filter %.cxx,$^)
#----------------------------------------------------------------2end-------------------#----------------------------------------------------------------3begin-----------------
#我们现在希望当修改一个.h时,也能够让make自动重新编译我们的项目,所以,我们需要指明让.o依赖于.h文件
#那一个.o依赖于哪些.h文件,我们可以用“gcc -MM c程序文件名” 来获得这些依赖信息并重定向保存到.d文件中
#.d文件中的内容可能形如:nginx.o: nginx.c ngx_func.h
#%.d:%.c
$(DEP_DIR)/%.d:%.cxx
#gcc -MM $^ > $@
#.d文件中的内容形如:nginx.o: nginx.c ngx_func.h ../signal/ngx_signal.h,但现在的问题是我们的.o文件已经放到了专门的目录
# 所以我们要正确指明.o文件路径这样,对应的.h,.c修改后,make时才能发现,这里需要用到sed文本处理工具和一些正则表达式语法,不必深究
#gcc -MM $^ | sed 's,\(.*\)\.o[ :]*,$(LINK_OBJ_DIR)/\1.o:,g' > $@
#echo 中 -n表示后续追加不换行echo -n $(LINK_OBJ_DIR)/ > $@
#	gcc -MM $^ | sed 's/^/$(LINK_OBJ_DIR)&/g' > $@
#  >>表示追加
#	gcc -I$(INCLUDE_PATH) -MM $^ >> $@$(CC) -I$(INCLUDE_PATH) -MM $^ >> $@#上行处理后,.d文件中内容应该就如:/mnt/hgfs/linux/nginx/app/link_obj/nginx.o: nginx.c ngx_func.h ../signal/ngx_signal.h#----------------------------------------------------------------4begin-----------------#----------------------------------------------------------------nbegin-----------------
#clean:			
#rm 的-f参数是不提示强制删除
#可能gcc会产生.gch这个优化编译速度文件
#	rm -f $(BIN) $(OBJS) $(DEPS) *.gch
#----------------------------------------------------------------nend------------------

2.2、config.mk

#定义项目编译的根目录,通过export把某个变量声明为全局的[其他文件中可以用],这里获取当前这个文件所在的路径作为根目录;
#BUILD_ROOT = /mnt/hgfs/linux/nginx
export BUILD_ROOT = $(shell pwd)#定义头文件的路径变量
export INCLUDE_PATH = $(BUILD_ROOT)/_include#定义我们要编译的目录
BUILD_DIR = $(BUILD_ROOT)/signal/ \$(BUILD_ROOT)/proc/   \$(BUILD_ROOT)/net/    \$(BUILD_ROOT)/misc/   \$(BUILD_ROOT)/logic/   \$(BUILD_ROOT)/app/ #编译时是否生成调试信息。GNU调试器可以利用该信息
#很多调试工具,包括Valgrind工具集都会因为这个为true能够输出更多的调试信息;
export DEBUG = true

2.3、根目录makefile


include config.mk
all:
#-C是指定目录
#make -C signal   #可执行文件应该放最后
#make -C app      #用shell命令for搞,shell里边的变量用两个$@for dir in $(BUILD_DIR); \do \make -C $$dir; \doneclean:
#-rf:删除文件夹,强制删除rm -rf app/link_obj app/dep nginxrm -rf signal/*.gch app/*.gch

2.4、其他目录下

#只生成 .d,.o即可 
BIN = nginx   #这个可以保证生成nginx可执行文件
include $(BUILD_ROOT)/common.mk

相关文章:

Linux下makefile 编译项目

文章目录1、规划makefile编写2、makefile文件2.1、根目录下common.mk2.2、config.mk2.3、根目录makefile2.4、其他目录下1、规划makefile编写 a、根目录下放三个文件: 1、makefile:是咱们编译项目的入口脚本,编译项目从这里开始,…...

Linux磁盘查看,使用(分区、格式化、挂载)

目录 0、观察磁盘分区状态:lsblk、blkid、parted 0.1 lsblk列出系统上的所有磁盘列表 0.2 blkid列出设备的UUID等参数 0.3 parted列出磁盘的分区表类型与分区信息 1、磁盘分区:gdisk、fdisk 1.1 fdisk 2、磁盘格式化(创建文件系统…...

走进WebGL

什么是 WebGL? WebGL 是一种跨平台、免版税的 API,用于在 Web 浏览器中创建 3D 图形。基于 OpenGL ES 2.0,WebGL 使用 OpenGL 着色语言 GLSL,并提供熟悉的标准 OpenGL API。因为它在 HTML5 Canvas 元素中运行,所以 We…...

Unity 中 Awake 和 Start 时机与 GameObject的关系

Awake和Start很相似,都是在脚本的初始阶段执行 但是有两点重要不同: Awake先执行Awake即便在脚本 disabled (即enabled false)时,也会执行,但是Start就不会执行了 对一个物体: 当初始没有激…...

1月份 GameFi 行业报告

Jan. 2023, DanielData Source: January Monthly GameFi Report在经历了艰难的一年之后,1 月是对加密货币市场最有利的月份。虽然可以说的大部分内容适用于其他看涨周期,但有几个统计数据令 1 月在区块链领域非常有趣。例如&#…...

JVM - 调优

目录 调什么,如何调 内存方面 线程方面 如何调优 调优的目标,策略和冷思考 JVM调优的目标 常见调优策略 JVM调优冷思考 调优经验与内存泄漏分析 JVM调优经验 内存泄露 调什么,如何调 内存方面 JVM需要的内存总大小各块内存分配,新生代、老年代、存活区选…...

flask配置https协议

感谢https://blog.csdn.net/qq_33934427/article/details/127456673,文中多有参考再实践一、要用https协议需要有ca证书,在windows10先下载windows版本openssl,地址如下https://share.weiyun.com/vfjVrMAb我是64位的选择下载完毕安装后配置环…...

Springboot 我随手封装了一个万能的导出excel工具,传什么都能导出

前言 如题,这个小玩意,就是不限制你查的是哪张表,用的是什么类。 我直接一把梭,嘎嘎给你一顿导出。 我知道,这是很多人都想过的, 至少我就收到很多人问过我这个类似的问题。 我也跟他们说了,但…...

【Linux详解】——进程控制(创建、终止、等待、替换)

📖 前言:本期介绍进程控制(创建、终止、等待、替换)。 目录🕒 1. 进程创建🕘 1.1 fork函数初识🕘 1.2 fork的返回值问题🕘 1.3 写时拷贝🕘 1.4 创建多个进程&#x1f552…...

HummerRisk V0.9.1:操作审计增加百度云,增加主机检测规则及多处优化

HummerRisk V0.9.0发布:增加RBAC 资源拓扑图,首页新增检查的统计数据,云检测、漏洞、主机等模块增加规则,对象存储增加京东云,操作审计增加金山云,镜像仓库新增设置别名。 感谢社区中小伙伴们的反馈&#…...

Rust入门(十六):手写web服务器和线程池

这一章将实现一个手写的 web server 和 多线程的服务器,用到之前学到的所有特性 简单的web server 作为一个 web 服务器,我们首先要能接收到请求,目前市面上的 web 服务大多数都是基于 HTTP 和 HTTPS 协议的,而他们有是基于 TCP…...

数据结构——第二章 线性表(1)——顺序结构

线性表1. 线性表1.1 线性表的定义1.1.1 访问型操作1.1.2 加工型操作1.2 线性表的顺序存储结构1.2.1 定义顺序表数据类型方法11.2.2 定义顺序表数据类型方法21.3 顺序表的基本操作实现1.3.1 顺序表的初始化操作1.3.2 顺序表的插入操作1.3.3 顺序表的删除操作1.3.4 顺序表的更新操…...

YOLO 格式数据集制作

目录 1. YOLO简介 2.分割数据集准备 3.代码展示 整理不易,欢迎一键三连!!! 1. YOLO简介 YOLO(You Only Look Once)是一种流行的目标检测和图像分割模型,由华盛顿大学的 Joseph Redmon 和 Al…...

基于linux内核的驱动开发

1 字符设备驱动框架 1.1字符设备 定义:只能以一个字节一个字节的方式读写的设备,不能随机的读取设备中中的某一段数据,读取数据需要按照先后顺序。(字符设备是面向字节流的) 常见的字…...

找不到工作的测试员一大把,大厂却招不到优秀软件测试员?高薪难寻测试工程师。

测试工程师招了快一个月了,实在招不到合适的,已经在被解雇的边缘了。。。” 初级测试工程师非常多,但真正掌握测试思维、能力强的优秀测试太少了! 据我所知, 当下的测试人员不少状态都是这样的: 在工作中…...

buuctf Basic

buuctf Basic 1.Linux Labs 根据提示我们可以知道需要远程连接linux服务器,这里使用xshell进行如下配置 输入ssh的用户名root,密码123456 连接成功 构造命令 ls …/ 查看文件 查看flag cat …/flag.txt 为flag{8fee8783-1ed5-4b67-90eb-a1d603a0208…...

赛狐ERP|亚马逊产品缺货怎么办?该如何补救?

由于物流时效的延长,运输成本的增加,亚马逊的仓储限制等各种原因,断货问题很常成为亚马逊卖家的普遍困扰。那么亚马逊产品缺货应该怎么办!1、提高产品价格:除了卖自己的Listing此外,提高产品价格也是一种保…...

《Elasticsearch源码解读与优化实战》张超-读书笔记

写在前面 好久没更新博客了,应届狗没办法啊╮(╯▽╰)╭为了秋招搞了小半年,从去年5月到现在搞了两段实习(京东、游戏公司),最终年前拿到一家还不错的offer,现在已经入职实习了,不出意外的话以…...

编码踩坑——运行时报错java.lang.NoSuchMethodError / 同名类加载问题 / 双亲委派【建议收藏】

本篇介绍一个实际遇到的排查异常的case,涉及的知识点包括:类加载机制、jar包中的类加载顺序、JVM双亲委派模型、破坏双亲委派模型及自定义类加载器的代码示例;问题背景业务版本,旧功能升级,原先引用的一个二方包中的du…...

软件测试选Python还是Java?

目录 前言 1、先从一门语言开始 2、两个语言的区别 3、两个语言的测试栈技术 4、如何选择两种语言? 总结 前言 对于工作多年的从业者来说,同时掌握java和Python两门语言再好不过,可以大大增加找工作时的选择范围。但是对于转行的人或者…...

《Playwright:微软的自动化测试工具详解》

Playwright 简介:声明内容来自网络,将内容拼接整理出来的文档 Playwright 是微软开发的自动化测试工具,支持 Chrome、Firefox、Safari 等主流浏览器,提供多语言 API(Python、JavaScript、Java、.NET)。它的特点包括&a…...

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility

Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

【AI学习】三、AI算法中的向量

在人工智能(AI)算法中,向量(Vector)是一种将现实世界中的数据(如图像、文本、音频等)转化为计算机可处理的数值型特征表示的工具。它是连接人类认知(如语义、视觉特征)与…...

GitHub 趋势日报 (2025年06月08日)

📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

UR 协作机器人「三剑客」:精密轻量担当(UR7e)、全能协作主力(UR12e)、重型任务专家(UR15)

UR协作机器人正以其卓越性能在现代制造业自动化中扮演重要角色。UR7e、UR12e和UR15通过创新技术和精准设计满足了不同行业的多样化需求。其中,UR15以其速度、精度及人工智能准备能力成为自动化领域的重要突破。UR7e和UR12e则在负载规格和市场定位上不断优化&#xf…...

SpringCloudGateway 自定义局部过滤器

场景: 将所有请求转化为同一路径请求(方便穿网配置)在请求头内标识原来路径,然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

Hive 存储格式深度解析:从 TextFile 到 ORC,如何选对数据存储方案?

在大数据处理领域,Hive 作为 Hadoop 生态中重要的数据仓库工具,其存储格式的选择直接影响数据存储成本、查询效率和计算资源消耗。面对 TextFile、SequenceFile、Parquet、RCFile、ORC 等多种存储格式,很多开发者常常陷入选择困境。本文将从底…...

uniapp 开发ios, xcode 提交app store connect 和 testflight内测

uniapp 中配置 配置manifest 文档:manifest.json 应用配置 | uni-app官网 hbuilderx中本地打包 下载IOS最新SDK 开发环境 | uni小程序SDK hbulderx 版本号:4.66 对应的sdk版本 4.66 两者必须一致 本地打包的资源导入到SDK 导入资源 | uni小程序SDK …...

深入浅出Diffusion模型:从原理到实践的全方位教程

I. 引言:生成式AI的黎明 – Diffusion模型是什么? 近年来,生成式人工智能(Generative AI)领域取得了爆炸性的进展,模型能够根据简单的文本提示创作出逼真的图像、连贯的文本,乃至更多令人惊叹的…...