Linux基础-Makefile

news2024/9/26 5:21:59

目录

一、Make简介

二、Makefile基本结构

示例:

补充(Makefile):

伪目标:

三、创建和使用变量

变量定义的方式:

简单方式:

递归方式:

用?=定义变量

为变量添加值

预定义变量

自动变量

环境变量

四、Make使用

五、例


一、Make简介

工程管理器,顾名思义,是指管理较多的文件。

Make工程管理器也就是个“自动编译管理器”,这里的“自动”是指它能够根据文件时间戳自动发现更新过的文件而减少编译的工作量,同时,它通过读入Makefile文件的内容来执行大量的编译工作。

Make将只编译改动的代码文件,而不用完全编译。

编译的四大过程;
         1、预处理:用于将所有的#include头文件以及宏定义替换成其真正的内容,预处理之后得到的仍然是文本文件,但文件体积会大很多。
            如:gcc -E hello.c -o hello.i  
        2、编译:编译不是指程序从源文件到二进制程序的全部过程,而是指将经过预处理之后的程序转换成特定汇编代码的过程。
            如:gcc -S hello.i -o hello.s
         3、汇编:将上一步的汇编代码转换成机器码,这一步产生的文件叫做目标文件,是二进制格式。
            如:gcc -c hello.s -o hello.o
        4、链接:将多个目标文件以及所需要的库文件(.so等)链接成最终的可执行文件。 
            如:gcc hello.o -o hello

二、Makefile基本结构

Makefile是Make读入的唯一配置文件

每条规则由三个部分组成分别是目标(target)依赖(depend) 和命令(command)

命令(command):

当前这条规则的动作,一般情况下这个动作就是一个 shell 命令。

—例如:通过某个命令编译文件、生成库文件、进入目录等。

—动作可以是多个,每个命令前必须有一个Tab缩进并且独占占一行。

依赖(depend):

规则所必需的依赖条件,在规则的命令中可以使用这些依赖。

—例如:生成可执行文件的目标文件(*.o)可以作为依赖使用

—如果规则的命令中不需要任何依赖,那么规则的依赖可以为空

—当前规则中的依赖可以是其他规则中的某个目标,这样就形成了规则之间的嵌套

—依赖可以根据要执行的命令的实际需求,指定很多个

目标(target):

规则中的目标,这个目标和规则中的命令是对应的。

—通过执行规则中的命令,可以生成一个和目标同名的文件规则中可以有多个命令,因此可以通过这多条命令来生成多个目标,所有目标也可以有很多个

—通过执行规则中的命令,可以只执行一个动作,不生成任何文件,这样的目标被称为伪目标

示例:

Makefile格式

target  :   dependency_files

<TAB>  command

例子

sunq:kang.o yul.o     

        gcc kang.o yul.o -o sunq

kang.o : kang.c kang.h     

        gcc –Wall –O -g –c kang.c -o kang.o

yul.o : yul.c   

         gcc - Wall –O -g –c yul.c -o yul.o

注释:

-Wall:表示允许发出gcc所有有用的报警信息.      

-c:只是编译不链接,生成目标文件”.o”    

 -o file:表示把输出文件输出到file里

关于更多的用man工具

Makefile:

源文件:

补充(Makefile):

- 假如我们只负责funtion1部分内容的编写,然后我们就使用命令 make funtion1.o即可,都是可以单独来执行每一个目标的。

- 当我们执行了命令 make funtion1.o 后,我们再去执行 make 我们会发现 makefile 会进行有选择的编译,只执行了funtion2.o、 main.o、test 的目标:

这里也就体现出了概述里面的时间戳和自动的概念(Make工程管理器也就是个“自动编译管理器”,这里的“自动”是指它能够根据文件时间戳自动发现更新过的文件而减少编译的工作量)

伪目标:

当我们根据以上示例生成了test目标文件后,发现在工程目录中出现了很多的中间文件(*.o),

这时我们如果用 rm *.o 命令当然也可以实现删除,但是我们这里可以在例子中的Makefile文件中增加一个新的目标 clean 来实现删除操作:

增加了clean目标后,在终端输入 make clean 即可实现删除操作。

但是这里我们如果在工程目录中新建一个 clean 的文件的话,在使用 make clean命令 就不好使了,如下图所示:

这是就引入了伪目标的概念:工程中的某些文件和 Makefile 中的目标重名了。伪目标就是肯定会被执行的一些命令。在Makefile中如果我们遇到一些特殊的目标,希望它能够永远执行,那么我们就需要在Makefile中添加一个伪目标(不加条件限制,肯定会去执行的目标):

当我们修改完成后,再次执行 make clean 就正常了:

三、创建和使用变量

创建变量的目的: 用来代替一个文本字符串:    

1.系列文件的名字  

2. 传递给编译器的参数

 3. 需要运行的程序  

4. 需要查找源代码的目录  

5. 你需要输出信息的目录    

6. 你想做的其它事情。

变量定义的方式:

递归展开方式VAR=var

简单方式 VAR:=var

变量使用$(VAR)

用”$”则用”$$”来表示

类似于编程语言中的宏

OBJS = kang.o yul.o

CC = gcc

CFLAGS = -Wall -O -g

sunq : $(OBJS)     

        $(CC) $(OBJS) -o sunq

kang.o : kang.c kang.h   

        $(CC) $(CFLAGS) -c kang.c -o kang.o

yul.o : yul.c yul.h     

        $(CC) $(CFLAGS) -c yul.c -o yul.o

简单方式:

例:

简单方式 VAR:=var     

m := mm

x := $(m)

y := $(x) bar

x := later

echo $(x) $(y)    

看看打印什么信息?

用这种方式定义的变量,会在变量的定义点,按照被引用的变量的当前值进行展。

这种定义变量的方式更适合在大的编程项目中使用,因为它更像我们一般的编程语言 。

递归方式:

递归展开方式VAR=var

例子:

foo = $(bar)

bar = $(ugh)

ugh = Huh?

$(foo)的值为?

echo $(foo)来进行查看

优点: 它可以向后引用变量  

缺点: 不能对该变量进行任何扩展,例如

        CFLAGS = $(CFLAGS) -O 会造成死循环

用?=定义变量

dir := /foo/bar

FOO ?= bar

FOO是?

含义是,如果FOO没有被定义过,那么变量FOO的值就是“bar”,如果FOO先前被定义过,那么这条语将什么也不做,其等价于:    

ifeq ($(origin FOO), undefined)      

FOO = bar    

endif

为变量添加值

你可以通过+=为已定义的变量添加新的值

Main=hello.o hello-1.o

Main+=hello-2.o

预定义变量

AR       库文件维护程序的名称,默认值为ar。AS汇编程序的名称,默认值为as。

CC       C编译器的名称,默认值为cc。CPP  C预编译器的名称,默认值为$(CC) –E。

CXX     C++编译器的名称,默认值为g++。

FC        FORTRAN编译器的名称,默认值为f77

RM       文件删除程序的名称,默认值为rm -f

例子:
Hello: main.c main.h

<tab> $(CC) –o hello main.c

clean:

<tab> $(RM) hello

自动变量

$*      不包含扩展名的目标文件名称

$+      所有的依赖文件,以空格分开,并以出现的先后为序,可能 包含重复的依赖文件

$<      第一个依赖文件的名称

$?      所有时间戳比目标文件晚的的依赖文件,并以空格分开

$@     目标文件的完整名称

$^       所有不重复的目标依赖文件,以空格分开

$%      如果目标是归档成员,则该变量表示目标的归档成员名称

刚才的例子:

OBJS = kang.o yul.o

CC = gcc

CFLAGS = -Wall -O -g

sunq : $(OBJS)     

        $(CC) $^ -o $@

kang.o : kang.c kang.h     

        $(CC) $(CFLAGS) -c $< -o $@

yul.o : yul.c yul.h     

        $(CC) $(CFLAGS) -c $< -o $@

环境变量

make在启动时会自动读取系统当前已经定义了的环境变量,并且会创建与之具有相同名称和数值的变量

如果用户在Makefile中定义了相同名称的变量,那么用户自定义变量将会覆盖同名的环境变量

四、Make使用

直接运行make

选项

-C dir读入指定目录下的Makefile

-f  file读入当前目录下的file文件作为Makefile

-i 忽略所有的命令执行错误

-I dir指定被包含的Makefile所在目录

-n 只打印要执行的命令,但不执行这些命令

-p 显示make变量数据库和隐含规则

-s 在执行命令时不显示命令

-w 如果make在执行过程中改变目录,打印当前目录名

五、例

工程目录

源文件

Makefile:

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

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

相关文章

数据结构从入门到精通——快速排序

快速排序 前言一、快速排序的基本思想常见方式通用模块 二、快速排序的特性总结三、三种快速排序的动画展示四、hoare版本快速排序的代码展示普通版本优化版本为什么要优化快速排序代码三数取中法优化代码 五、挖坑法快速排序的代码展示六、前后指针快速排序的代码展示七、非递…

Sentry(Android)源码解析

本文字数&#xff1a;16030字 预计阅读时间&#xff1a;40分钟 01 前言 Sentry是一个日志记录、错误上报、性能监控的开源框架&#xff0c;支持众多平台&#xff1a; 其使用方式在本文不进行说明了&#xff0c;大家可参照官方文档&#xff1a;https://docs.sentry.io/platforms…

【网络基础】VRRP虚拟路由冗余协议介绍与配置

目录 一、VRRP的概述 1.1 VRRP的由来 1.2 作用 1.3 基本结构 1.4 状态机流程 1.5 设备类型 二、 实例演示 一、VRRP的概述 1.1 VRRP的由来 局域网中的用户终端通常采用配置一个默认网关的形式访问外部网络&#xff0c;如果此时默认网关设备发生故障&#xff0c;将中断…

算法设计与分析-分支限界——沐雨先生

&#xff08;1&#xff09;抓奶牛问题描述&#xff1a; 农夫约翰被告知逃跑的奶牛的位置&#xff0c;并且要求立即去抓住它。约翰开始的位置在数轴上位置 N &#xff08; 0 ≤ N ≤ 100) &#xff0c;而奶牛的位置在同样一个数轴上的 K (0 ≤ K ≤ 100) 。约翰有两种移动方式&…

普洛斯怀来数据中心获Uptime MO认证,以高品质服务持续提升客户体验

近日&#xff0c;普洛斯怀来数据中心顺利通过Uptime M&O&#xff08;运维与管理&#xff09;认证&#xff0c;获得Uptime Institute颁发的认证证书。普洛斯数据中心致力于为客户提供高品质、高可靠的运维服务&#xff0c;此项认证&#xff0c;标志着普洛斯数据中心运营及管…

Mac上玩《赛博朋克2077》mac电脑怎么玩这个游戏

X用户crushovitz_b最近发现&#xff0c;在《赛博朋克2077》游戏主菜单页面&#xff0c;将鼠标停在版本号选项卡上面足够长时间&#xff0c;就会发现游戏当前的版本号由2.12变为了2.0.77&#xff0c;这是对游戏标题2077的致敬彩蛋。 《赛博朋克2077》的叙事总监兼续集副总监Pawe…

Flutter 事件传递简单概述、事件冒泡、事件穿透

前言 当前案例 Flutter SDK版本&#xff1a;3.13.2 本文对 事件传递只做 简单概述&#xff0c;主要讲解&#xff0c;事件传递过程中可能遇到的问题解决&#xff0c;比如 事件冒泡、事件穿透&#xff1b; 不是我偷懒&#xff0c;是自认为没有这几位写的详细、仔细&#xff0c…

FPGA学习_时序分析

文章目录 前言一、组合逻辑与时序逻辑二、建立时间和保持时间三、建立时间和保持时间 前言 心中有电路&#xff0c;下笔自然神&#xff01;&#xff01;&#xff01; 一、组合逻辑与时序逻辑 组合逻辑&#xff1a;没有时钟控制的数字电路&#xff0c;代码里的判断逻辑都是组…

颠覆传统:Web3如何塑造未来的数字经济

引言 近年来&#xff0c;随着数字化时代的到来&#xff0c;互联网已经成为人们生活中不可或缺的一部分。然而&#xff0c;随着技术的不断发展和社会的不断变迁&#xff0c;传统的Web2模式逐渐显露出一些弊端&#xff0c;如数据垄断、隐私泄露等问题&#xff0c;这促使人们寻求…

简历指导与模板获取

简历是应聘过程当中最重要的材料&#xff0c;是我们在求职市场的一张名片&#xff0c;一份好的简历能够吸引招聘者的注意&#xff0c;使你在竞争激烈的求职市场中脱颖而出。 1.简历指导 以下是一份典型简历的主要部分和常见内容&#xff1a; 联系信息&#xff1a; 包括你的全…

设计模式 适配器模式

1.背景 适配器模式&#xff0c;这个模式也很简单&#xff0c;你笔记本上的那个拖在外面的黑盒子就是个适配器&#xff0c;一般你在中国能用&#xff0c;在日本也能用&#xff0c;虽然两个国家的的电源电压不同&#xff0c;中国是 220V&#xff0c;日本是 110V&#xff0c;但是这…

操作系统面经-什么是操作系统?

通过以下四点可以概括操作系统到底是什么&#xff1a; 操作系统&#xff08;Operating System&#xff0c;简称 OS&#xff09;是管理计算机硬件与软件资源的程序&#xff0c;是计算机的基石。操作系统本质上是一个运行在计算机上的软件程序 &#xff0c;主要用于管理计算机硬…

DP:路径规划模型

创作不易&#xff0c;感谢三连支持&#xff01; 路径规划主要是让目标对象在规定范围内的区域内找到一条从起点到终点的无碰撞安全路径。大多需要用二维dp数组去实现 一、不同路径 . - 力扣&#xff08;LeetCode&#xff09;不同路径 class Solution { public:int uniquePath…

自动驾驶---Motion Planning之轨迹Path优化

1 背景 在之前的几篇文章中,不管是通过构建SL图《自动驾驶---Motion Planning之Path Boundary》,ST图《自动驾驶---Motion Planning之Speed Boundary》,又或者是构建SLT图《自动驾驶---Motion Planning之构建SLT Driving Corridor》,最终我们都是为了得到boundary的信息。 …

基于springboot的4S店车辆管理系统

基于springboot的4S店车辆管理系统 的设计和实现 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开…

算法-最短路径

图的最短路径问题是一个经典的计算机科学和运筹学问题&#xff0c;旨在找到图中两个顶点之间的最短路径。这种问题在多种场景中都有应用&#xff0c;如网络路由、地图导航等。 解决图的最短路径问题有多种算法&#xff0c;其中最著名的包括&#xff1a; 1.迪杰斯特拉算法 (1).…

抖音小店怎么定类目?分享几个爆单几率大,适合新手的细分类目!

大家好&#xff0c;我是电商糖果 做电商的应该经常听过这么一句话&#xff0c;类目大于一切&#xff01; 好的类目可以让商家减少很多竞争和难题。 糖果做电商有很多年了&#xff0c;我一直认为做店前期最难的定类目&#xff0c;中期是选品&#xff0c;后期是维护店铺。 如…

物联网数据报表分析

随着物联网技术的迅猛发展&#xff0c;越来越多的企业开始将物联网解决方案应用于各个领域&#xff0c;从提高生产效率到优化用户体验&#xff0c;物联网都发挥着至关重要的作用。然而&#xff0c;如何有效地分析和管理物联网产生的海量数据&#xff0c;成为企业面临的挑战之一…

【Java开发过程中的流程图】

流程图由一系列的图形符号和箭头组成&#xff0c;每个符号代表一个特定的操作或决策。下面是一些常见的流程图符号及其含义&#xff1a; 开始/结束符号&#xff08;圆形&#xff09;&#xff1a;表示程序的开始和结束点。 过程/操作符号&#xff08;矩形&#xff09;&#xff…

<Linux> 生产者消费者模型

目录 前言&#xff1a; 一、什么是生产者消费者模型 &#xff08;一&#xff09;概念 &#xff08;二&#xff09;生产者消费者之间的关系 &#xff08;三&#xff09;生产者消费者模型特点 &#xff08;四&#xff09;生产者消费者模型的优点 二、基于阻塞队列实现生产…