网站后缀是nl是哪个国家/百度推广一级代理商名单
前言
(1)我们都知道,在Linux中编译.c文件需要使用gcc -o .c文件的指令来将C文件变成可执行文件。但是我们有没有发现,如果我们需要编译大一点的工程,后面需要加上的.c文件是不是太多了?感觉非常的麻烦。
(2)那有没有什么方便的方法,帮助我们编译大型文件呢?有,也就是本章需要介绍的Makefile工具。需要注意的是,Makefile工具如果真的想全部学,内容很多想学的看Makefile详细英文文档或GNU Make 使用手册(于凤昌中译版)。本文仅用于新手小白学习。
(3)本文将先简单介绍GCC的编译流程,然后再讲解Makefile入门级使用。
GCC编译流程
单个.C文件变成可执行文件
简单介绍
(1)首先我们需要知道,我们写的.c代码是无法直接使用的。如果是搞单片机的同学们都知道,一个.c文件需要先再keil这种编译器中先编译,然后将生成的hex文件烧录到单片机中。(stlink那个虽然只需要我们点一下烧录就可以,但是实际上也是这么做的)
(2)那么这个hex文件是什么东西呢?我们打开hex文件发现,里面都是16进制的数字,而这些代码才是机器真正能够识别的代码。

(3)那么从.c文件到这些机器可执行的过程具体是什么呢?四个步骤:预处理-->编译-->汇编-->链接。
(4)但是在日常生活中通常使用“编译”统称这 4 个步骤,不是特指这 4 个步骤中的某一个。有时候也会有人将前三步称为编译,讲法不一,只要知道.c文件到机器可执行文件有四个步骤即可。
预处理
(1)预处理:在C/C++源文件中,以“ #”开头的命令被称为预处理命令。预处理需要将
<1>包含的文件放入原文件中。比如一个main.c中第一行写了#include<stdio.h>,那么预处理阶段就需要将stdio.h文件包含到main.c中,上面一大段就是stdio.h文件的内容。
<2>宏定义展开。比如我们此刻宏定义了printf为CSDN,所以在.i文件中CSDN部分变成了printf。
<3>根据条件编译命令选择要使用的代码,最后将这些东西输出到一个“ .i”文件中等待进一步处理。
(2)格式:gcc -E .c文件 -o .i文件
(3)需要注意,如果是直接gcc -o 可执行文件名 .c文件,那么是直接完成了预处理,编译,汇编,和链接的四个步骤。而如果是加上-E,就是只执行预处理。

编译
(1)编译就是把 C/C++代码(比如上述的“.i”文件)“ 翻译” 成汇编代码,所用到的工具为 cc1。(名字为CC1,x86和arm板都有自己的CC1命令)。
(2)格式:gcc -S .c或者.i文件 -o .s文件
(3)程序的语法错误是在这一阶段进行判断的。


汇编
(1)汇编:将汇编代码翻译成符合一定格式的机器代码(二进制代码,我们上面看到的是十六进制,稍微转换一下就是二进制了)。在Linux 系统上一般表现为 ELF 目标文件(OBJ 文件),用到的工具为 as。 x86 有自己的 as 命令, ARM 版也有自己的 as 命令,也可能是 xxxx-as(比如 armlinux-as)。
(2)格式:gcc -c .c文件/.i文件/.s文件 -o .o文件
(3)反汇编:将机器代码转换为汇编代码,这在调试程序时常常用到。

链接
(1)链接就是将上步生成的 OBJ 文件和系统库的 OBJ 文件、 库文件链接起来,最终生成了可以在特定平台运行的可执行文件,用到的工具为 ld 或 collect2。
(2)格式:gcc -o 可执行文件 .c/.i/.s/.o文件都可以
多个.c文件编译
编译多个.c文件
(1)经过上面简介,我们对gcc编译流程有了简单的了解。那么问题来了,我们做项目不可能就只有一个.c文件,很可能是几十个.c文件,一个一个gcc -o这样编译很麻烦。那么我们介绍一下如何同时编译多个.c文件。
(2)格式:gcc -o 可执行文件 .c文件 .c文件 ...(后面接多个.c文件都行)

修改项目中一个.c文件
(1)经过上面这么一说,发现随着.c文件的增加,后面需要写入的.c也会更多,有些许麻烦。但是这不是最让人感到头痛的事情。
(2)假设我们突然发现这个文件需要修改,将其中一个.c文件进行修改之后,那么重新编译将会变的非常的麻烦。所以说,非常麻烦。这个时候Makefile的作用就体现出来了。
Makefile介绍
Makefile需要做到的效果
(1)在Linux中,没有比较好的图形化编译工具。如果我们是在windows上编写程序,以keilMDK举例,只用点击左上方的编译按键即可编译程序。

(2)而且在编译工程中,我们会发现。如果我们按左边这个按键,已经编译了一次程序之后,第二次即使有些许改动,编译就会非常快。而他右侧的这个,即使程序没有修改,编译也会非常慢。为什么呢?
因为第一个按键只会编译修改部分,而第二个按键无论你有没有修改文件,都会重新编译一次。所以我比较喜欢使用第一个编译按键,我们这章需要讲的也是要实现这个功能。

(3)Windows中的编译非常简单,但是其实他内部的原理就是Makefile。
Makefile语法简单介绍
Makefile格式使用方法介绍
(1)Makefile非常简单,格式如下:
目标:依赖
【Tab】命令
(2)目标和依赖都是文件,为什么起这么奇怪的名字,可能是从英文直翻的。上面这一段就像C语言的if函数,他作用就是比较“依赖文件”和“目标文件”的更新时间。如果“依赖文件”比“目标文件”更加新,那么执行“命令”来重新生成“目标文件”。
(3)命令被执行的 2 个条件:依赖文件比目标文件新,或是目标文件还没生成。
(4)Makefile的文件名必须是Makefile或者makefile。
(5)在Makefile中,想要执行命令,格式是:make 目标。但是我们常常看到很多人只输入了一个make,因为如果我们不指定目标的话, 默认执行的是第一个目标所对应的规则。(这个不理解的话看下面的图文解释)
//将上述Makefile格式用C语言的形式进行表示
if(“依赖文件”更新时间 > “目标文件”更新时间)执行命令
Makefile图文介绍
执行Makefile的图文解释:
1,前面说了,使用 make 目标来编译, 如果我们不指定目标的话, 默认执行的是第一个目
标所对应的规则,所以make与make test是等效的。
这个命令执行流程是:(1)首先判断test文件和main.o与test.o的更新时间。因为此时test文件不存在,所以命令可以执行。(可以看前面说的命令执行的两个条件)(2)因为main.o与sub.o是由main.c与sub.c而来的。所以他们又会去执行make main.o和make sub.o。因为make sub.o中,依赖文件s.c不存在,所以无法比较,程序终止。
2,当"目标文件"比"依赖文件"新的时候,命令不会执行。而main.o在make test中,已经执行了一次make main.o。而main.c没有被修改过,所以这里提示main.o已经是最新的了。
3,命令执行的条件有,依赖文件比目标文件新,或者目标文件不存在。因为命令中,永远不会产生目标文件,所以make cleal与make s.o永远可以执行。
4,需要注意的是,make clean没有依赖文件为什么可以执行是因为在程序先判断clean文件是否存在,发现不存在,所以就直接执行程序,而不是去找依赖文件了。与第一问的makesub.o不同,需要注意。


Makefile伪目标--避免与当前目录下的同名文件
(1)上面我们说了,使用make clean可以将所有编译过程中产生的文件全部删除,但是其中存在问题。假如当前文件夹下也存在一个叫做clean的文件名怎么办呢?

这种情况能够做的办法有很多种,比如<1>将clean文件名改一下,或者是<2>将makefile中的目标文件clean改成当前目录下不存在的一个文件名。不过现在我要说的方法是,伪目标的方法。
格式:.PHONY: 目标


Makefile使用实战
最简单编写方式和使用(1)
(1)上面我们说了,假如一个项目有几千上万的.c文件,而我们只更改一个.c文件。对每一个文件都进行预处理,编译,汇编和链接,效率低下。
(2)所以,我们是不是可以先让每一个.c文件,先进行前三步,最后在进行一次链接呢?这样做,就可以让我们就可以先判断.c文件与.o文件(.o文件就是执行了前三步骤后生成的)更改时间。
如果.o文件比.c文件更改时间更新,那么就表示这一个.c文件没有被修改。如果.c文件比.o文件更改时间更新,那么表示这一个文件被修改过了,于是重新进行一次预处理,编译和汇编。
最后将最终的可执行文件名与所有.o文件的更改时间做对比,如果可执行文件更改时间比.o文件的新,那么就说明这个项目文件就没有被修改过。如果所有.o文件中有一个.o文件比可执行文件更改时间更新,那么就将所有.o文件重新进行一次链接。
(3)需要注意,命令部分前面需要使用TAB键进行缩进,不能是空格!!!

(4)当文件夹中有了Makefile(makefile也可以)文件之后,只需要输入make命令就可以执行Makefile文件了。

进阶编写(2)-通配符和自动化变量
(1)有了Makefile文件,我们对文件进行编译方便了很多。但是我们还是觉得麻烦,因为我们每一个项目都需要重新进行一次编写Makefile。而且如果项目文件一多,编写Makefile也极其花费时间。
(2)于是我们可以使用通配符和自动化变量,比如前面的main.o和sub.o都可以统一是使用%.o表示,main.c和sub.c统一使用%.c表示。
$@ | 表示所有目标文件 |
$< | 表示第一个依赖文件, 如果依赖模式是%, 那么它就表示一系列文件。(%为通配符, 类似 linux上的 *) |
$^ | 表示所有依赖文件 |
%.c | 表示所有.c文件 |
%.o | 表示所有.o文件 |
第一行不能使用%.o
虽然%.o可以表示所有的.o文件,但是在第一行不能使用%.o代替,必须一个一个的.o文件写出来!这个时候有人会抱怨还是太麻烦了,别慌,后面讲解进阶编写(3)的时候会有解决办法。


正常写法

进阶编写(3)--自动包含.o文件
(1)根据上面的讲解之后,我们会发现,此时的Makefile文件已经比我们之前直接GCC编译好很多了。但还是可以完善,就是让他自动包含.o文件。这样才可以真正的实现我们一开始说的,模拟windows中的编译按键。
(2)在这里我会先讲解Makefile的变量及其变量赋值,然后再讲解Makefile 的函数,最后才会说到如何编写最终版的Makefile文件。
变量及变量赋值
这部分主要是有了解就行,不然最终的进阶编写看不懂。
= | 延时变量 |
:= | 立即变量 |
?= | 延时变量,只有第一次定义时赋值才成功;如果曾定义过,此赋值无效 |
+= | 使用“+=” 赋值是追加赋值, 是在我们前面定义的好的字符串里面在添加进去新的字符串 |
=示例
使用“=” 来赋值, 是延迟赋值。按照正常的思路,A=a,那么第二行B就应该是a。但是因为再Makefile中"="是延迟赋值,所以B最终的值是b


:=示例
使用“ : =” 给变量赋值, 是立刻赋值。这个就可以按照正常的C语言执行流程来,变量跑到那里,赋值就是那里,不会因为后面的赋值而导致变量数值改变。


?=示例
如果前面赋值了,就是之前的值(即a),如果前面没有被赋值(即第一行没有),就是当前值(即b)。


+=示例
使用“+=” 赋值是追加赋值, 是在我们前面定义的好的字符串里面在添加进去新的字符串,不过中间会有空格。


Makfile函数
wildcard 函数
格式: $ (wildcard PATTENR)
功能: 展开指定的目录,文件名之间用一个空格隔开
解释:比如我们需要查找当前目录,或者子目录下的某一种文件。类似于Windows中,有时候需要在一个目录中选中目标文件,可以选择只显示某一种类型文件,这样方便我们查找到目标文件。


notdir函数
格式: $ (notdir $ (var) )
功能: 去掉路径。
解释:上面查找到文件之后,会显示文件的路径。假如我们不想看文件路径,就可以使用这个函数。


dir函数
格式: $(dir <names...>)
功能: 取出目录, 这里的目录指的是最后一个反斜杠/ 之前的部分, 如果没有反斜杠/就返回当前。
解释:这个函数和notdir恰恰相反,notdir是将目录去除留下目标文件。而dir是将目标文件去除,留下路径。


patsubst函数
格式: $(patsubst 原文件, 目标文件, 文件列表)
功能: 替换文件后缀
解释:如果文件列表里面有main.c,sub.c,hello.i。三个文件,将原文件.c文件替换成.o文件,最后文件列表的文件就是main.o,sub.o,hello.i。

foreach函数
格式: $(foreach <var>,<list>,<text>)
功能:把参数<list>中的单词逐一取出放到参数<var>所指定的变量中, 然后再执行<text> 所包含的表达式。 每一次 <text> 会返回一个字符串
解释:这个函数可以理解为C语言中的printf函数。C语言中的printf(“A=%d”,3),3就是list,A=%d就是test,而var就是%d。


实操进阶编写
上面讲了这么多,终于到了实操了。首先,我们先展开当前目录下的所有.c文件,然后将这些.c文件的前面的目录去除,之后再将.c替换成.o(注意,实际的文件名没有被替换)。最后将var3的值放在test之后即可。

相关文章:

Linux-GCC介绍+入门级Makefile使用
前言(1)我们都知道,在Linux中编译.c文件需要使用gcc -o .c文件的指令来将C文件变成可执行文件。但是我们有没有发现,如果我们需要编译大一点的工程,后面需要加上的.c文件是不是太多了?感觉非常的麻烦。&…...

iOS(一):Swift纯代码模式iOS开发入门教程
Swift纯代码模式iOS开发入门教程项目初始化(修改为纯代码项目)安装第三方库(以SnapKit库为例)桥接OC库(QMUIKit)封装视图并进行导航跳转示例:使用 TangramKit 第三方UI布局库应用国际化添加 R.s…...

IDEA+Python+Selenium+360浏览器自动化测试
环境配置前提,见文章https://mp.csdn.net/mp_blog/creation/editor/new?spm1001.2101.3001.4503下载360浏览器,并下载对应版本的chromedriver.exe,下载地址http://chromedriver.storage.googleapis.com/index.html下载好360浏览器࿰…...

运输层概述及web请求
运输层 运输层概述 运输层向高层用户屏蔽了下面网络核心的细节(如网络拓扑、所采用的路由选择协议等)它使应用进程看见的就好像是在两个运输层实体之间有一条端到端的逻辑通信信道; 根据需求不同,运输层提供两种运输协议 面向连…...

python与pycharm从零安装
python(解释器)下载地址:Welcome to Python.orgpycharm(编译器)下载地址:PyCharm: the Python IDE for Professional Developers by JetBrains一、python的下载与安装到官网后根据步骤下载安装包后…...

叠氮试剂943858-70-6,Azidobutyric acid NHS ester,叠氮-C3-活性酯
1、试剂基团反应特点(Reagent group reaction characteristics):Azidobutyric acid NHS ester具有叠氮化物和NHS酯端基。西安凯新生物科技有限公司供应的叠氮化物可以与炔烃、DBCO和BCN进行铜催化的点击化学反应。NHS酯可以与胺基反应&#x…...

pycharm激活虚拟环境时报错:无法加载文件activate.ps1,因为在此系统上禁止运行脚本,Windows10系统
问题: ii_env\Scripts\activate : 无法加载文件 F:\gitlab\AutoFrame\ii_env\Scripts\Activate.ps1,因为在此系统上禁止运行脚本。 有关详细信息,请参阅 https:/go.microsoft.com/fwlink/?LinkID135170 中的 about_Execution_Policies。 所在…...

刷题小抄4-数组
在Python中数组的功能由列表来实现,本文主要介绍一些力扣上关于数组的题目解法 寻找数组中重复的数字 题目链接 题目大意: 给出一个数组,数组长度为n,数组里的数字在[0,n-1]范围以内,数字可以重复,寻找出数组中任意一个重复的数字,返回结果 解法一 该题最基础的思路是使用字…...

Hbase安装
目录 上传压缩包 解压 改名 修改 Hbase 配置文件 修改base-env.sh 修改hbase-site.xml 配置环境变量 修改zookeeper配置文件 复制配置文件 修改zoo.cfg配置文件 修改myid 配置环境变量 刷新配置文件 启动Hbase 进入Hbase 查看版本号 查看命名空间 查看命名空…...

面向对象设计模式:结构型模式之代理模式
一、引入 访问 FB:代理服务器 二、代理模式 aka Surrogate 2.1 Intent 意图 Provide a surrogate (代理) or placeholder for another object to control access to it. 为另一个对象提供一个代理或占位符,以控制对它的访问。代理模式给某一个对象提…...

CCF大数据专家委员会十周年纪念庆典纪实:拥抱数字时代,展望科技未来
山河远阔,奋进十年,作为国内大数据领域最权威的学术组织,CCF大数据专家委员会(以下简称“大专委”)不忘初心,凝心聚力,见证并推动了过去10年来大数据技术生态在中国的建立、发展和成熟。 2023年…...

Qt学习3-Qt Creator四则运算计算器(哔站视频学习记录)
计算器中的“”按钮这部分的代码解释 目录 制作计算器中的“”按钮这部分的代码解释 一、代码部分 二、解释 三、思路 四、死循环! 一、代码部分 void Widget::on_equalButton_clicked() {QStack<int> s_num,s_opt; //声明两个int类型变量char opt[128…...

学习 Python 之 Pygame 开发魂斗罗(九)
学习 Python 之 Pygame 开发魂斗罗(九)继续编写魂斗罗1. 在子弹类中修改敌人发射子弹的位置2. 创建显示敌人子弹的函数3. 解决敌人不会向下掉落的问题4. 给敌人碰撞体组增加碰撞体5. 解决敌人叠加在一起的问题继续编写魂斗罗 在上次的博客学习 Python 之…...

最简单的SpringBoot+MyBatis多数据源实现
最简单的SpringBootMyBatis多数据源实现1.数据库准备2.环境准备3.代码部分3.1多数据源配置2.测试随着应用用户数量的增加,相应的并发请求的数量也会跟着不断增加,慢慢地,单个数据库已经没有办法满足频繁的数据库操作请求了,在某些…...

Spring Boot 3.0系列【8】核心特性篇之SpringApplication
有道无术,术尚可求,有术无道,止于术。 本系列Spring Boot版本3.0.3 源码地址:https://gitee.com/pearl-organization/study-spring-boot3 文章目录 前言1. 启动应用2. 自定义 Banner3. 应用参数传递参数获取参数4. ApplicationRunner、CommandLineRunner5. 事件发布和监听…...

Nginx的搭建与核心配置
目录 一.Nginx是什么? 1.Nginx概述 2.Nginx模块与作用 3.Nginx三大作用:反向代理、负载均衡、动静分离 二.Nginx和Apache的差异 三.安装Nginx 1.编译安装 2.yum安装 四.Nginx的信号使用 五.Nginx的核心配置指令 1.访问状态统计配置 2.基于授…...

Java学习笔记 --- jQuery
一、jQuery介绍 jQuery,顾名思义,也就是JavaScript和查询(Query),它就是辅助JavaScript开发的js类库。它的核心思想是write less,do more(写得更少,做得更多),…...

华为OD机试题,用 Java 解【字符串加密】问题
华为Od必看系列 华为OD机试 全流程解析+经验分享,题型分享,防作弊指南)华为od机试,独家整理 已参加机试人员的实战技巧华为od 2023 | 什么是华为od,od 薪资待遇,od机试题清单华为OD机试真题大全,用 Python 解华为机试题 | 机试宝典使用说明 参加华为od机试,一定要注意不…...

软聚类算法:模糊聚类 (Fuzzy Clustering)
前言 如果你对这篇文章感兴趣,可以点击「【访客必读 - 指引页】一文囊括主页内所有高质量博客」,查看完整博客分类与对应链接。 在介绍模糊聚类之前,我们先简单地列举一下聚类算法的常见分类: 硬聚类 (Hard Clustering) Connec…...

Java Web 实战 02 - 多线程基础篇(1)
Java Web 实战 02 - 多线程基础篇 - 1一 . 认识线程1.1 概念1.1.1 什么是线程?1.1.2 为什么要有多个线程?1.1.3 进程和线程的区别(面试题)1.2 第一个多线程程序1.3 创建线程1.3.1 继承Thread类1.3.2 实现Runnable接口1.3.3 继承 Thread 类 , 使用匿名内部类1.3.4 实现 Runnab…...

C/C++开发,无可避免的多线程(篇三).协程及其支持库
一、c20的协程概念 在c20标准后,在一些函数中看到co_await、co_yield、co_return这些关键词,这是c20为协程实现设计的运算符。 协程是能暂停执行以在之后恢复的函数。原来我们调用一个功能函数时,只要调用了以后,就要完整执行完该…...

高级信息系统项目管理(高项 软考)原创论文项目背景合集
以下为原创的高项论文项目背景合集5篇,建议自己以此为基础,再多多打磨完善一下,避免雷同,同时使项目背景更加真实可信。 一、某市智慧工地系统建设项目 某市住建局智慧工地系统建设项目是在该市住建局促进建筑行业转型升级和科技创新,强化工程质量安全,推动建筑业高质量…...

锁屏面试题百日百刷-Hive篇(十一)
锁屏面试题百日百刷,每个工作日坚持更新面试题。锁屏面试题app、小程序现已上线,官网地址:https://www.demosoftware.cn。已收录了每日更新的面试题的所有内容,还包含特色的解锁屏幕复习面试题、每日编程题目邮件推送等功能。让你…...

一看就懂,等保2.0工作流程这么做
等保2.0相关国家标准于2019年12月1日开始实施,标志着我国网络安全等级保护工作进入一个崭新的阶段,对于加强我国网络安全保障工作,提升网络安全保护能力具有十分重要的意义。很多行业主管单位要求行业客户开展等级保护工作,合理地…...

Kerberos 域委派攻击之非约束性委派
CSDN文章自动迁移自博客在Windows 2000 Server 首次发布 Active Directory 时,Microsoft 必须提供一种简单的机制来支持用户通过 Kerberos 向 Web Server 进行身份验证并需要代表该用户更新后端数据库服务器上的记录的方案。这通常称为“Kerberos 双跳问题”&#x…...

【容器运行时】一文理解 OCI、runc、containerd、docker、shim进程、cri、kubelet 之间的关系
参考 docker,containerd,runc,docker-shim 之间的关系Containerd shim 进程 PPID 之谜内核大神教你从 Linux 进程的角度看 DockerRunC 简介OCI和runCContainerd 简介从 docker 到 runCDockershim究竟是什么技术干货|Docker和 Con…...

spark兼容性验证
前言 Apache Spark是专门为大规模数据处理而设计的快速通用的计算引擎,Spark拥有Hadoop MapReduce所具有的优点,但不同于Mapreduce的是Job中间输出结果可以保存在内存中,从而不再需要读写HDFS,因此Spark能更好的适用于数据挖掘与…...

docker逃逸复现--pid=host模式下的逃逸
漏洞原理当docker以--pidhost模式启动时,你可以通过在容器进程中注入一些shellcode进行逃逸。相当于给了docker Linux中的CAP_SYS_PTRACE权限--pidhost:意味着宿主机与容器公享一套pid,如此做容器就可以访问并跟踪宿主机的进程Linux中的CAP_S…...

【环境配置】Windows系统下搭建Pytorch框架
【环境配置】Windows系统下搭建Pytorch框架 在Windows Serve 2019系统下搭建Pytorch框架 目录 【环境配置】Windows系统下搭建Pytorch框架1.用驱动总裁安装显卡驱动2.在cmd运行nvidia-smi3.安装cuda4.安装cudnn5.安装pytorch的命令1.首次安装2.操作失误需要重新安装6.安装torc…...

Dockerfile简单使用入门
什么是 Dockerfile? Dockerfile 是一个用来构建镜像的文本文件,文本内容包含了一条条构建镜像所需的指令和说明。 docker build命令用于从Dockerfile构建映像。可以在docker build命令中使用-f标志指向文件系统中任何位置的Dockerfile。 例如࿱…...