Linux:Makefile

news2025/5/24 14:08:25

编译器gcc

使用方式:gcc [ 选项 ] 要编译的⽂件 [ 选项 ] [ ⽬标⽂件 ]

编译分为以下几个步骤:

1.预处理(进⾏宏替换)

预处理功能主要包括宏定义,⽂件包含,条件编译,去注释等。

预处理指令是以#号开头的代码⾏。

实例:

gcc –E hello.c –o hello.i

选项“-E”,该选项的作⽤是让gcc在预处理结束后停⽌编译过程。

选项“-o”是指⽬标⽂件,“.i”⽂件为已经过预处理的C原始程序。

2.编译(⽣成汇编)

在这个阶段中,gcc⾸先要检查代码的规范性、是否有语法错误等,以确定代码的实际要做的⼯作, 在检查⽆误后,gcc把代码翻译成汇编语⾔。

⽤⼾可以使⽤“-S”选项来进⾏查看,该选项只进⾏编译⽽不进⾏汇编,⽣成汇编代码。

实例:

gcc –S hello.i –o hello.s

3.汇编(⽣成机器可识别代码)

汇编阶段是把编译阶段⽣成的“.s”⽂件转成⽬标⽂件

读者在此可使⽤选项“-c”就可看到汇编代码已转化为“.o”的⼆进制⽬标代码了

实例:

gcc –c hello.s –o hello.o

4.连接(⽣成可执⾏⽂件或库⽂件)

在成功编译之后,就进⼊了链接阶段。

实例:

gcc hello.o –o hello

动态链接和静态链接

在实际开发中,不可能将所有代码放在⼀个源⽂件中,所以会出现多个源⽂件,⽽且多个源⽂件之间不是独⽴的,⽽会存在多种依赖关系,如⼀个源⽂件可能要调⽤另⼀个源⽂件中定义的函数, 但是每个源⽂件都是独⽴编译的,即每个*.c⽂件会形成⼀个*.o⽂件,为了实现这种依赖关系,则需要将这些源⽂件产⽣的⽬标⽂件进⾏链接,从⽽形成⼀个可以执⾏的程序。这个链接的过程就是静态链接。

静态链接的缺点很明显:

浪费空间:因为每个可执⾏程序中对所有需要的⽬标⽂件都要有⼀份副本,所以如果多个程序对 同⼀个⽬标⽂件都有依赖,如多个程序中都调⽤了printf()函数,则这多个程序中都含有 printf.o,所以同⼀个⽬标⽂件都在内存存在多个副本;

更新⽐较困难:因为每当库函数的代码修改了,这个时候就需要重新进⾏编译链接形成可执⾏程 序。

但是静态链接的优点就是,在可执⾏程序中已经具备了所有执⾏程序所需要的任何东西,在执⾏的时候运⾏速度快。

而动态链接则是把程序按照模块拆分成各个相对独⽴的部分,在程序运⾏时才将它们链接在⼀起形成⼀个完整的程序,⽽不是像静态链接⼀样把所有程序模块都链接成⼀个单独的可执⾏⽂件。

静态库和动态库

静态库是指编译链接时,把库⽂件的代码全部加⼊到可执⾏⽂件中,因此⽣成的⽂件⽐较⼤,但在运⾏时也就不再需要库⽂件了。

其后缀名⼀般为“.a”

动态库与之相反,在编译链接时并没有把库⽂件的代码加⼊到可执⾏⽂件中,⽽是在程序执⾏时由运⾏时链接⽂件加载库,这样可以节省系统的开销。

动态库⼀般后缀名为“.so”。

gcc在编译时默认使⽤动态库。完成了链接之后,gcc就可以⽣成可执⾏⽂件,

如: 

gcc hello.o –o hello

gcc默认⽣成的⼆进制程序,是动态链接的。

make/Makefile

对于一个内容复杂、源文件众多的工程而言,仅使用gcc指令对其文件进行逐个编译会显得过于繁琐低效,因此linux提供了一个对工程进行自动编译的指令:make

make实际执行的是一个名为makefile的文件内的指令(该文件由用户自己创建)

因此,我们要想编译一个工程,不妨写一个makefile文件,这样每次编译时只需调用make指令即可

写makefile的思路:

形成目标文件的依赖关系(即由什么文件生成)+依赖方法(即如何生成)

以一个简单的makefile文件为例:

code:code.c
gcc -o code code.c
.PHONY:clean
clean:
rm -f code

依赖关系:形成code⽂件依赖于code.c

依赖⽅法:gcc -o myproc myproc.c 

项⽬清理 :删除所有的目标文件

make是如何⼯作的

1. make会在当前⽬录下寻找名为“Makefile”或“makefile”的⽂件。

2. 如果找到,它会找⽂件中的第⼀个⽬标⽂件(target),在上⾯的例⼦中,他会找到code⽂件,并把这个⽂件作为最终的⽬标⽂件。

3. 如果 code ⽂件不存在,或是依赖文件code.c与目标文件code相比更新(即文件修改时间更晚),那么,他就会执⾏后⾯所定义的命令来⽣成 myproc 这个⽂件。

4. 如果 code 所依赖的 code.c ⽂件不存在,那么 make 会在当前⽂件中找⽬标文件为 code.c的依赖文件,如果找到则根据上述规则形成code.c⽂件(这里是一个递归调用,即不断寻找依赖文件,当找到最后一个依赖文件时,开始依次执行依赖方法)。

5. 在找寻的过程中,如果出现错误,⽐如最后被依赖的⽂件找不到,那么make就会直接退出,并 报错,⽽对于所定义的命令的错误,或是编译不成功,make不做处理。

clean

clean也是一个目标文件,但它不依赖于任何文件,也不与其他的目标文件直接或间接关联,这导致它后⾯所定义的命令将不会被⾃动执⾏,不过,我们仍然可以使用指令“make clean”来显式执⾏,以此来清除所有的⽬标⽂件,以便重编译。

而.PHONY则是将clean修饰为伪目标,效果是:让make忽略源⽂件和可执⾏⽬标⽂件的M时间对⽐(直白的讲就是clean可以总是被执行)

什么是总是被执行

当我们查看一个文件的信息注意到:

Access :⽂件最后⼀次被访问的时间。

Modify: 文件内容最后一次变更的时间

Change :文件属性最后一次变更的时间

当目标文件的修改时间晚于依赖文件时,此时编译器会认为目标文件已由依赖文件形成,不需再执行,而总是被执行就是无论目标文件的修改实际是否晚于依赖文件,命令都会被执行
 

Makefile的扩展语法

上面我们根据code.c文件编写了一个makefile,对于一个有着众多源文件的工程,像上面一样写则过于繁琐,而且通用性太差,每次编译一个新的工程都要重写一个makefile

因此,我们期望写一个通用的makefile模板,每次编译工程都可以使用这个模板:

BIN=code              #最终目标文件    
CC=gcc    
#SRC=$(shell ls *.c)  #采⽤shell命令⾏⽅式,获取当前所有.c⽂件名
SRC=$(wildcard *.c)   #或者使⽤wildcard 函数,获取当前所有.c⽂件名
OBJ=$(SRC:.c=.o)      #将SRC的所有同名.c 替换成为.o 形成⽬标⽂件列表
LFLAGS=-o             #链接选项      
FLAGS=-c              #编译选项
RM=rm -f              #引⼊命令 

$(BIN):$(OBJ)        
    @$(CC) $(LFLAGS) $@ $^          # $@:代表⽬标⽂件名。$^: 代表依赖⽂件列表
    @echo "linking ... $^ to $@"    
%.o:%.c                             # %.c: 展开当前⽬录下所有的.c。%.o: 同时展开同名.o

    @$(CC) $(FLAGS) $<             # %<: 对展开的依赖.c⽂件,⼀个⼀个的交给gcc。
    @echo "compling ... $< to $@"       # @:不回显命令        
.PHONY:clean    
clean:
    $(RM) $(OBJ) $(BIN)                # $(RM): 替换,⽤变量内容替换它
 
.PHONY:test    
test:    
    @echo $(SRC)         
    @echo $(OBJ)

​

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

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

相关文章

基于双闭环PID控制器的永磁同步电机控制系统匝间故障Simulink仿真

欢迎微♥关注“电击小子程高兴的MATLAB小屋”获取巨额优惠 1.模型简介 本仿真模型基于MATLAB/Simulink&#xff08;版本MATLAB 2013Rb&#xff09;软件。建议采用matlab2013 Rb及以上版本打开。&#xff08;若需要其他版本可联系代为转换&#xff0c;高于该版本的matlab均可正…

硬件电路设计之51单片机(2)

声明&#xff1a;绘制原理图和PCB的软件为嘉立创EDA。根据B站尚硅谷嵌入式之原理图&PCB设计教程学习所作个人用笔记。 目录 一、原理图详解 1、TypeC接口 &#xff08;1&#xff09;TypeC接口介绍 &#xff08;2&#xff09;TypeC原理图 2、5V转3.3V 3、单片机电源开…

SpringAI+DeepSeek大模型应用开发——1 AI概述

AI领域常用词汇 LLM&#xff08;LargeLanguage Model&#xff0c;大语言模型&#xff09; 能理解和生成自然语言的巨型AI模型&#xff0c;通过海量文本训练。例子&#xff1a;GPT-4、Claude、DeepSeek、文心一言、通义干问。 G&#xff08;Generative&#xff09;生成式: 根据上…

经济指标学习(一)

系列文章目录 文章目录 系列文章目录1、市净率**一、定义与计算****二、核心意义****三、应用场景****四、局限性****五、分类与衍生指标****总结** 2、市销率**一、定义与计算****二、核心意义****三、优缺点分析****四、适用场景****五、与其他指标的对比****六、实际应用案例…

理解 results = model(source, stream=True) 的工作原理和优势

1. 核心概念解析 (1) streamTrue 的作用 生成器模式&#xff1a;当处理视频或图像序列时&#xff0c;streamTrue 会将结果包装成一个 生成器&#xff08;Generator&#xff09;&#xff0c;逐帧生成 Results 对象&#xff0c;而不是一次性返回所有结果。内存优化&#xff1a;…

国内互联网大厂推出的分布式数据库 的详细对比,涵盖架构、性能、适用场景、核心技术等维度

以下是 国内互联网大厂推出的分布式数据库 的详细对比&#xff0c;涵盖架构、性能、适用场景、核心技术等维度&#xff1a; 一、主流分布式数据库列表 大厂数据库名称类型适用场景发布时间腾讯云TDSQL分布式HTAP金融、电商、游戏、政企2010年阿里云OceanBase分布式HTAP银行核…

Android 项目配置文件解释

Android 项目配置文件解释 目录 Android 项目配置文件解释1. `plugins` 块2. `android` 块3. `dependencies` 块为什么需要 JDK 和 Kotlin1. plugins 块 plugins {id com.android.applicationid org.jetbrains.kotlin.android }id com.android.application:应用 Android 应用…

亚马逊热销变维权?5步搭建跨境产品的安全防火墙

“产品热卖&#xff0c;引来维权”——这已经悄然成为越来越多跨境卖家的“热销烦恼”。曾经拼品拼量&#xff0c;如今却要步步谨慎。商标侵权、专利投诉、图片盗用……这些问题一旦发生&#xff0c;轻则下架、账号被限&#xff0c;重则冻结资金甚至封店。 别让“热销”变“受…

C语言——分支语句

在现实生活中&#xff0c;我们经常会遇到作出选择和判断的时候&#xff0c;在C语言中也同样要面临作出选择和判断的时候&#xff0c;所以今天&#xff0c;就让我们一起来了解一下&#xff0c;C语言是如何作出选择判断的。 目录 1.何为语句&#xff1f; 2.if语句 2.1 if语句的…

绿盟二面面试题

5000篇网安资料库https://mp.weixin.qq.com/s?__bizMzkwNjY1Mzc0Nw&mid2247486065&idx2&snb30ade8200e842743339d428f414475e&chksmc0e4732df793fa3bf39a6eab17cc0ed0fca5f0e4c979ce64bd112762def9ee7cf0112a7e76af&scene21#wechat_redirect 1. 原理深度&…

deepseek生成流程图

目录 Mermaid流程图需求询问框架交互显示流程图markdown在线网站 可能会出现的问题语法报错 在职场中&#xff0c;借助AI生成图表是提升效率的重要技能&#xff0c;本篇我们讲解如何使用deepseek生成流程图 Mermaid流程图 需求 学习太差劲了&#xff0c;我想要一个比较好的学…

大塔集团乔迁开新局 企业赋能贯全程

2025年4月15 日&#xff0c;在佛山市佛山大道北175号&#xff0c;大塔集团乔迁开业盛大启幕&#xff0c;业界目光聚焦于此。 点睛仪式 揭牌仪式 彩绸飘扬、嘉宾云集&#xff0c;现场气氛热烈非凡&#xff0c;这一标志性时刻&#xff0c;宣告着大塔集团正式踏上全新发展征程。 …

Spark-SQL核心编程(二)(三)

Spark-SQL核心编程&#xff08;二&#xff09; DSL 语法 DataFrame 提供一个特定领域语言(domain-specific language, DSL)去管理结构化的数据。 可以在 Scala, Java, Python 和 R 中使用 DSL&#xff0c;使用 DSL 语法风格不必去创建临时视图了。 1.创建一个 DataFrame val d…

继承:(开始C++的进阶)

我们今天来学习C的进阶&#xff1a; 面向对象三大特性&#xff1a;封装&#xff0c;继承&#xff0c;多态。 封装我们在前面已经学了&#xff0c;我们细细理解&#xff0c;我们的类的封装&#xff0c;迭代器的封装&#xff08;vector的迭代器可以是他的原生指针&#xff0c;li…

oracle数据库单个表空间达到32G后程序报错表空间不足问题排查、处理

oracle数据库单个表空间达到32G后程序报错表空间不足问题排查、处理 系统宕机tomcat日志报错表空间无法增长&#xff0c;排查发现oralce表空间文件到了32G。 通过AI查了下&#xff0c;“oracle是否支持表空间达到32G后&#xff0c;自动创建新的表空间文件” 答复是oralce不支…

人工智能——梯度提升决策树算法

目录 摘要 14 梯度提升决策树 14.1 本章工作任务 14.2 本章技能目标 14.3 本章简介 14.4 编程实战 14.5 本章总结 14.6 本章作业 本章已完结&#xff01; 摘要 本章实现的工作是&#xff1a;首先采用Python语言读取含有英语成绩、数学成绩以及学生所属类型的样本数据…

【leetcode hot 100 136】只出现一次的数字

解法一&#xff1a;&#xff08;异或XOR&#xff09;相同的数字出现两次则归零 class Solution {public int singleNumber(int[] nums) {int result 0;for(int num:nums){result ^ num;}return result;} }注意&#xff1a; 其他方法&#xff1a;HashList记录次数再查找数组&a…

QEMU学习之路(8)— ARM32通过u-boot 启动Linux

QEMU学习之路&#xff08;8&#xff09;— ARM32通过u-boot 启动Linux 一、前言 参考文章&#xff1a; Linux内核学习——内核的编译和启动 Linux 内核的编译和模拟执行 Linux内核运行——根文件系统 Linux 内核学习——使用 uboot 加载内核 二、构建Linux内核 1、获取Linu…

AgentOps - 帮助开发者构建、评估和监控 AI Agent

文章目录 一、关于 AgentOps二、关键集成 &#x1f50c;三、快速开始 ⌨️2行代码中的Session replays 首类开发者体验 四、集成 &#x1f9be;OpenAI Agents SDK &#x1f587;️CrewAI &#x1f6f6;AG2 &#x1f916;Camel AI &#x1f42a;Langchain &#x1f99c;&#x1…

leetcode 122. Best Time to Buy and Sell Stock II

题目描述 这道题可以用贪心思想解决。 本文介绍用动态规划解决。本题分析方法与第121题一样&#xff0c;详见leetcode 121. Best Time to Buy and Sell Stock 只有一点区别。第121题全程只能买入1次&#xff0c;因此如果第i天买入股票&#xff0c;买之前的金额肯定是初始金额…