编写Makefile

现在我们将创建一个程序,该程序能够读取次位码文件并打印其中定义的函数名称,以及它们的基本块数,从而显示LLVM库的易用性

什么是Makefile?

  • C语言中,我们使用visual studio开发软件时候,写程序开始时候都会创建一个project项目文件,然后在文件里面编译 .h 和.c 的文件。
  • 在Linux中,有一个叫make的东西,就相当于C语言的集成开发环境,我们只需要在make里面创建文件,写代码,make会帮我们管理这些文件。
  • 不过我们创建的项目不叫project,而是称为Makefile,打开一个make源程序包,发现很多Makefile的文件,说明里面有很多的项目。
  • 在源程序包里面,也有名为makefile的文件(m是小写),两个命名同时存在,这是合理的,在开发一个项目的时候,工程师一般都会命名为Makefile然后打包交给用户,用户觉得某个Makefile需要改动,用户改动后或者新建后的项目定义为makefile,并且在运行时候,先执行makefile,再执行Makefile文件。

Makefile文件

链接LLVM库需要使用长命令行,如果没有构建系统的帮助,想写出这些命令行是不切实际的

注意:Makefile依赖于制表符来指定定义规则的命令
即应该手动插入制表符(下面有解释)
这个Makefile文件基于(DragonEgg中使用的代码)

在这里插入图片描述
解释一
第一部分定义将用作编译器标志的第一个Makefile变量
第一个变量决定llvm-config程序的位置
llvm-config工具是一个LLVM程序
它可以构建需要与LLVM库连接的外部项目的各种有用信息
Ag:
定义在C++编辑器中使用的标志集时
我们将要求Make启动llvm-config --cxxflags
shell命令行,该命令行将打印用于编译LLVM项目的C++标志集
这样就使得项目源码的编译与LLVM源码兼容。
最后一个变量定义要传递给编译器预处理的标志集
在这里插入图片描述

解释二
第二个片段
定义了Makefile的规则
第一个是默认的,用它构建hello-word可执行文件
第二个是通用规则,将所有c++文件编译生成目标文件
将预处理标志和C++编辑器标志传递给它
用$(QUIET)变量来省略屏幕上出现的完整命令
如果想要一个详细的构建日志,运行GUN Make 时定义VERBOSE
最后一个链接规则所有目标文件(在这里只有一个)来构建与LLVM库链接的项目可执行文件
这部分由链接器完成的,但是一些C++标志也可能会生效。
因此我们将C++和链接器标志都传递给命令行
用“command”的结构来完成此操作,它指示shell“command”的输出替换这部分内容
在Ag中命令是 llvm-config --libs bitreader core support
“–libs 标志向llvm-config请求提供链接到所有LLVM库中的链接器标志列表
请求libLLVMBItReader、libLLVMCore、libLLVMSupport
由llvm-config返回的标志列表是一系列-l链接器参数
Ag:-lLLVMCore-lLLVMSupport
注意
传递给链接器的参数顺序很重要,并且要求你依赖于其他库的参数放在前面
Ag:
由于libLLVMCore使用libLLVMSupport提供的通用功能,因此正确顺序是-lLLVMCore-lLLVMSupport

顺序很重要,因为一个库就是一个目标文件的集合,将在项目与库链接时
链接器只选择到目前为止目标文件来解析见到的未定义的符号
因此,如果它正在处理命令行参数的最后一个库,并且该库恰好使用已经处理的库中的符号
则大多数链接器(包括GUN id)将不会返回去包括有可能确实的目标文件,从而导致构建失败

如何避免这个问题?
强制链接器迭代访问每个库,直到所有必要的目标文件都被解析,则必须在库列表的开始和结束出使用–start–group和–end-group标志,但有可能会减慢速度
在构建完整的依赖关系图时,为了避免因为要弄清楚链接器参数的顺序而头疼
可以简单的使用llvm-config --libs 让它为你这些工作

在这里插入图片描述
解释三
Makefile文件的最后一部分定义了一条清理规则以删除编译器生成的所有文件
使我们从头开始从新启动构建

长命令行

在计算机科学中,长命令行是指包含大量参数和选项的命令行。这些参数和选项用于控制命令的行为。

长命令行通常有以下特点:

  • 包含多个参数和选项
  • 参数和选项之间使用空格或分隔符隔开
  • 命令行的总长度可能超过一行

长命令行的示例:

# 这是一个长命令行示例gcc -o hello hello.c -Wall -Wextra -pedantic -std=c11 -g -O2

在这个示例中,gcc 是命令,-o-Wall-Wextra-pedantic-std=c11-g-O2 是参数和选项。

长命令行有以下缺点:

  • 难以阅读和理解
  • 容易出错
  • 不易于维护

为了解决这些问题,可以使用构建系统来帮助管理长命令行。构建系统可以自动生成命令行,并根据需要进行调整。

以下是一些常见的构建系统:

  • CMake
  • Makefile
  • Autotools
  • Bazel

使用构建系统可以带来以下好处:

  • 提高命令行的可读性和可理解性
  • 减少错误的可能性
  • 提高代码的可维护性

因此,如果需要使用长命令行,建议使用构建系统来帮助管理。

回到您最初的问题:“链接LLVM库需要使用长命令行,如果没有构建系统的帮助,想写出这些命令行是不切实际的。”

这句话的意思是,链接 LLVM 库通常需要使用大量的参数和选项。这些参数和选项用于指定要链接的库、编译器选项等信息。如果没有构建系统的帮助,手动编写这些命令行非常繁琐,而且容易出错。

使用构建系统可以自动生成链接 LLVM 库所需的命令行。这可以大大提高效率,并减少错误的可能性。

以下是一些使用构建系统链接 LLVM 库的示例:

  • CMake
cmake_minimum_required(VERSION 3.10)project(Hello)set(CMAKE_CXX_STANDARD 11)add_executable(hello hello.c)target_link_libraries(hello PRIVATE LLVM)
  • Makefile
all:gcc -o hello hello.c -lLLVMclean:rm -f hello

在这个示例中,-lLLVM 选项用于链接 LLVM 库。

制表符

在 Makefile 中,制表符(Tab)是一种特殊的缩进符,用于指定定义规则的命令。它与空格不同,不能被空格替换。

具体来说,制表符在 Makefile 中有以下作用:

  • 区分命令和目标:Makefile 中的每一行都由目标和命令组成。目标是 Makefile 要生成的文件或要执行的命令,而命令是用于生成目标的具体操作。制表符用于将目标和命令区分开来。目标的后面必须跟一个冒号(:),然后是命令。命令必须以制表符开头。
  • 指定命令的缩进:Makefile 中的命令可以有多行,但只有第一行需要以制表符开头。后续行的缩进可以是制表符或空格,但必须一致。
  • 控制命令的执行顺序:Makefile 中的命令是按照顺序执行的。如果命令有多行,则第一行的制表符决定了该命令的执行顺序。制表符的数量越多,命令的执行顺序越靠后。

以下是一个简单的 Makefile 示例:

all:echo "Hello, world!"clean:rm -f hello.txt

在这个示例中,all 是目标,echo "Hello, world!" 是命令。命令以制表符开头,因此它将在 all 目标之后执行。

clean 是另一个目标,rm -f hello.txt 是命令。命令以制表符开头,因此它将在 clean 目标之后执行。

需要注意的是,Makefile 中的制表符和空格是严格区分的。如果使用空格代替制表符,则 Makefile 可能无法正确执行。

以下是一些使用制表符的注意事项:

  • 制表符的宽度:不同的编辑器可能会对制表符的宽度进行不同的设置。为了确保 Makefile 在不同的编辑器中都能正确执行,建议将制表符的宽度设置为 8 个空格。
  • 混合使用制表符和空格:在 Makefile 中,最好不要混合使用制表符和空格。如果需要使用空格进行缩进,则建议在所有行都使用空格,而不是只在某些行使用空格。

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

复旦TravelPlanner让大语言模型挑战旅程规划

引言:探索语言智能的新疆界——旅行规划 在人工智能的发展历程中,规划一直是核心追求之一。然而,由于缺乏人类水平规划所需的多种认知基础,早期的AI代理主要集中在受限的环境中。随着大语言模型(LLMs)的出…

vue3-应用规模化-路由和状态

客户端 vs. 服务端路由 服务端路由指的是服务器根据用户访问的 URL 路径返回不同的响应结果。当我们在一个传统的服务端渲染的 web 应用中点击一个链接时,浏览器会从服务端获得全新的 HTML,然后重新加载整个页面。 然而,在单页面应用中&…

python伯努利多项式

文章目录 伯努利数和多项式sympy实现 伯努利数是一种在数学、物理和工程中广泛应用的特殊数列,以瑞士数学家雅各布伯努利(Jacob Bernoulli)的名字命名,并在许多领域中发挥重要作用。在数学中,它们与斐波那契数列、卡塔…

幻兽帕鲁服务器操作系统选择Windows还是Linux?

各有各的优势,幻兽帕鲁Windows:适合新手,快速上手。 而幻兽帕鲁Linux(Ubuntu):适合有一定技术基础的小伙伴。 推荐选择Windows系统,用起来更加简单,操作方便。如下图: …

【51单片机】DS18B20(江科大)

一、DS18B20温度传感器 1.DS18B20介绍 DS18B20是一种常见的数字温度传感器,其控制命令和数据都是以数字信号的方式输入输出,相比较于模拟温度传感器,具有功能强大、硬件简单、易扩展、抗干扰性强等特点 测温范围 :- 55℃到125℃ 通信接口:1-Wire(单总线) 其它特征:可形成…

Java学习笔记(三)

目录 一、字符类型 二、布尔类型 三、基本数据类型转换 3.1 自动类型转换 3.2 强制类型转换 3.3 基本数据类型和String类型的转换 一、字符类型 字符类型可以表示单个字符,字符类型是char。 多个字符我们用字符串String。 字符和码值的对应关系是通过字符编…

如何在PDF 文件中删除页面?

查看不同的工具以及解释如何在 Windows、Android、macOS 和 iOS 上从 PDF 删除页面的步骤: PDF 是最难处理的文件格式之一。曾经有一段时间,除了阅读之外,无法用 PDF 做任何事情。但是今天,有许多应用程序和工具可以让您用它们做…

爬虫系列-web请求全过程剖析

🌈个人主页: 会编程的果子君 ​💫个人格言:“成为自己未来的主人~” 上一小节我们实现了一个网页的整体抓取工作,那么本小节,给各位好好剖析一下web请求的全部过程,这样有助于后面我们遇到的各种各样的网站就有了入手…

C# CAD交互界面-自定义面板集-查找定位(六)

运行环境 vs2022 c# cad2016 调试成功 一、代码说明 1. 类成员变量声明&#xff1a; List<ObjectId> objectIds new List<ObjectId>(); // 用于存储AutoCAD实体对象的ObjectId列表 private static Autodesk.AutoCAD.Windows.PaletteSet _ps2; // 自定义浮动面板…

C++ //练习 5.12 修改统计元音字母的程序,使其能统计以下含有两个字符的字符序列的数量:ff、fl和fi。

C Primer&#xff08;第5版&#xff09; 练习 5.12 练习 5.12 修改统计元音字母的程序&#xff0c;使其能统计以下含有两个字符的字符序列的数量&#xff1a;ff、fl和fi。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /****…

matlab入门,在线编辑,无需安装matab

matlab相关教程做的很完善&#xff0c;除了B站看看教程&#xff0c;官方教程我觉得更加高效。跟着教程一步一步编辑&#xff0c;非常方便。 阅读 MATLAB 官方教程&#xff1a; MATLAB 官方教程提供了从基础到高级的教学内容&#xff0c;内容包括 MATLAB 的基本语法、数据处理…

探索ChatGPT-4:智能会话的未来已来

深入了解ChatGPT-4&#xff1a;前沿AI的强大功能 ChatGPT-4是最先进的语言模型之一&#xff0c;由OpenAI开发&#xff0c;它在自然语言理解和生成方面的能力已经达到了新的高度。如今&#xff0c;ChatGPT-4已经被广泛应用于多个领域&#xff0c;从教育到企业&#xff0c;再到技…