当前位置: 首页 > 编程日记 > 正文

Autools学习总结(一)

一、Makefile

简介

在编写C/C++程序的时候,我们经常需要编译并运行代码。在程序规模较小的情况下,可以简单地直接调用编译器来完成这项工作。然而,在很多情况下程序往往包括大量的代码文件,手动调用编译器变得麻烦无比。尤其要命的是,编译的时候需要考虑源文件之间的依赖情况。例如对于下面的三个文件:

文件main.c:

1 #include <xxx.h>
2 blabla

文件xxx.h

1 declared some functions or classes

文件xxx.cpp

1 #include <xxx.h>
2 implemented some functions or classes

上面三个文件的依赖情况分别为:

1 main.c => xxx.h
2 xxx.cpp => xxx.h

因此,在xxx.h文件被改变时,将导致main.cxxx.cpp都需要重新编译,而main.cxxx.cpp被改变时则只需要编译相应的文件,并执行链接操作即可(这个例子也说明了为什么.h文件不能轻易变动,可以把.h文件视为模块提供的接口,如同契约一样已经制定就不能轻易变动)。

这个问题如何解决呢?可以不考虑依赖关系,把所有源文件重新编译——这种方式在我们编写一些玩具代码的时候的确可以,然而在一个中等规模的项目就会成为一个噩梦。。C/C++代码的编译速度本来就慢(这一点自己编译过开源代码同学应该深有体会),如果每次都彻底重新编译的话会浪费大量的时间。Make工具的产生一开始就是用来解决这一问题的(当然不限于此)。

先上一个最简单的Make用例:

hello.c文件

1 #include <stdio.h>
2 int main()
3 {
4     printf(“hello world!\n”);
5     return 0;
6 }

1 $>make hello && ./hello
2 cc hello.c     -o    hello
3 hello world

规则和命令

    Makefile允许我们定义一系列的依赖规则,并根据该依赖规则来执行相应的命令。下面是一个最简单的Makefile

Makefile文件

1 # 简单的依赖文件
2 hello: hello.c
3     gcc -o hello hello.c

其中第零行是一行注释,同shell脚本一样,Makefile使用#来定义注释。第一行定义了一条依赖规则,冒号左边为需要生成的目标,冒号右边则为生成该目标所需要的文件。值得注意的是,规则的目标和依赖项都可以是多个文件,多个文件之间使用空格分开,形如a b: c d的规则表示目标ab均依赖于cd

文件的第二行为一个命令。Make工具根据目标和依赖项的修改时间戳来判断是否需要执行命令来生成新的目标,即:如果目标的修改时间较所有的依赖项更新,则表明无需执行命令来重新生成目标;而如果任一依赖项的修改时间较目标的更新,则说明有必要执行命令来重新生成目标。make根据命令的程序退出状态来判断是否执行成功(0为成功,否则失败),如果执行失败则停止生成过程并报错。可以通过设定命令行前缀来改变这一过程,命令行前缀包括以下两种:

  • -make忽略该命令的执行情况,即使失败仍然继续生成

  • @make不打印该命令,通常在执行echo命令时使用该前缀

下面是一个使用命令行前缀的示例:

1 dash:
2     -rm /some/file/not/exist
3 at:
4     @echo “hello”

当执行make dash时,rm命令执行失败,但是make的生成目标过程不会停止,而执行make at时,将只在屏幕上打印“hello“,不会打印出echo命令的执行情况。

makefile中,规则后面不一定要跟一条命令,即我们可以定义一条啥事也不干的规则。而判断一条语句是规则还是命令是根据行开头是否包含TAB字符,注意,一定要是TAB字符,不能是四个空格或者其它看起来和TAB一样的东东。。这个设计被认为是Unix有史以来最糟糕的设计修补(TAOUP P358)。(幸运的是,VIM能很好地处理这一问题,在我设置了expandtab的情况下还能正确地在命令的第一列插入TAB字符。)

变量的定义和使用

    Makefile中变量的定义和使用方式如下所示:

1 dash:
2     -rm /some/file/not/exist
3 at:
4     @echo “hello”

变量的定义非常简单,变量名和值用符号“=”分开即可,使用变量则用$(valname)的方式。在make程序解析Makefile时,会对变量进行替换。这里有一个需要注意的地方:make实际上会对Makefile扫描两次——第一次替换所有的变量,第二次才是根据规则执行命令。这意味着对于变量在多处定义时,最终替换的变量值是最后一次对变量指定的值。下面举一个例子:

Makefile文件

1 val = a
2 test:
3     echo $(val)
4 val = b

执行make test时,显示的结果将是b而不是a。

除了我们自定义的变量之外,make还包含了一些预定义的变量。例如,变量CC表示系统默认的C编译器(默认值为cc),因此定义编译文件的命令时通常使用的方式是$(CC) -o main $(src)而不是直接使用gcc。这一特点在后面引入Autoconf时非常有用——Autoconf检查系统的默认C编译器并设置CC变量的值,从而使得代码可以在包含不同C编译器的系统上顺利编译。完整的预定义变量可以参见make用户手册。

在上面提到的例子中,src变量被使用了两次:作为规则的依赖项和命令的参数。为了贯彻执行DRY原则,make还定义了一种称为“自动变量”的变量,用来表示规则中的特定部分。使用自动变量时,上面的例子可以中写为如下方式:

1 src = main.c xxx.c
2 main: $(src)
3     $(CC) -o $@ $+

其中$@$(@)的简写形式,表示规则的目标部分,而$+则表示规则的所有依赖项。相对于前面的方式,现在的Makefile是不是干净了一些呢?完整的自动变量列表同样包括在make用户手册中。

SUFFIXESPHONY

假设我们的项目中只有一个文件main.c,那么Makefile很简单:

1 main : main.o
2     gcc -o main main.o
3 main.o: main.c
4     gcc -c main.c

可是在有100个甚至更多.c文件的情况下,需要对每一个.c文件进行编译,就不得不写很多次如下的代码:

1 xxx.o: xxx.c
2     gcc -c xxx.c

幸运的是,make提供了后缀匹配功能,从而使用如下代码就可一完成上述功能:

1 .c.o:
2     gcc -c $<

类似的规则成为后缀规则,make在解析Makefile时将扫描Makefile文件所在目录下的匹配文件,并执行相应的命令。然而这里存在一个问题,即可能存在一个名为“.c.o“的文件,make如何判断这条规则是一条普通的规则还是后缀规则呢?这里就要用到特殊的目标SUFFIXES了:

1 .SUFFIXES: .c .o

这条规则告诉make将目标为.c.o的规则视为后缀规则,而非名为.c.o的文件。

与此类似的另一个特殊目标是PHONY,用来定义一些“伪目标”。在Makefile中,我们除了定义一些需要生成的文件外,还可能会执行一些操作,而这些操作是不会生成目标文件的。例如,目前广泛使用make clean清理临时文件,make install用来安装程序。我们需要定义一些没有依赖项的规则:

1 clean:
2     rm *.o

当执行make clean时,make将查找当前目录,发现没有名为clean的文件,同时该文件也不需要任何依赖项,这种情况下make将总是执行规则对应的命令。然而,如果不幸地在当前目录下刚好存在一个名为clean的文件呢?这时make发现该文件没有任何依赖项,从而认为该目标已是最新的,因此将跳过命令执行阶段。

特殊目标PHONY就是用来解决这一问题的:

1 .PHONY: clean

以上规则将告知make程序,clean目标为一个伪目标,从而make程序无需再去检查目录下clean文件的存在与否,而总是执行clean目标所对应的命令。

    (未完待续。。。)


转载于:https://www.cnblogs.com/zyobi/archive/2010/10/31/1865703.html

相关文章:

简单的实现IOCP服务器模型

其实已经有很多大佬将原理讲的十分详细了&#xff0c;所以就不花费时间将原理再一次重复讲一遍&#xff0c;有需要的可以自行去查看。 http://blog.csdn.net/beyond_cn/article/details/9336043 这篇文章是我看的&#xff0c;原理介绍十分详细。不过有一些操作感觉比较复杂因此…

资料分享:送你一本《数据结构与算法JavaScript描述》电子书!

数据结构 是掌握计算机编程必须具备的技能。通常情况下&#xff0c;我想掌握一门编程语言所用的方法就是利用这门语言把数据结构中线性表、栈、队列、字符串、动态数字、整数集合、树、图、搜索、排序等涉及的算法全部写一遍。写完之后&#xff0c;基本上就把这门语言搞定了。 …

Python中爬虫框架或模块的区别

Python中爬虫框架或模块的区别&#xff0c;我们在Python的学习过程中&#xff0c;需要不断的总结知识点&#xff0c;这样我们才能进步的更快一些。 (1)爬虫框架或模块 Python自带爬虫模块&#xff1a;urllib、urllib2; 第三方爬虫模块&#xff1a;requests&#xff0c;aiohttp;…

SQL SERVER 2000写存储过程出现列名无效的解决方法

举一个Northwind的例子。DECLARE m_LastName nvarchar(20) DECLARE Sql varchar(256)SET m_LastName Fuller SET Sql SELECT * FROM Employees WHERE LastName char(39) m_LastName char(39) EXEC(Sql) 注意&#xff0c;要加上char(39)就可以了。转载于:https://www.cnblo…

如何利用 C# + Python 破解猫眼电影的反爬虫机制?

在 如何利用 C# 爬取「猫眼电影&#xff1a;最受期待榜」及对应影片信息&#xff01; 这篇图文中可以看到猫眼电影对“本月新增想看人数” 和 “总想看人数”进行了字符集加密。 在 如何利用 C# 爬取「猫眼电影&#xff1a;国内票房榜」及对应影片信息&#xff01; 这篇图文中也…

ZooKeeper学习笔记1-----------安装启动

ZooKeeper是一套协作服务&#xff0c;主要用来构建分布式架构的应用&#xff0c;通过ZooKeeper我们可以安全的处理分布式应用下的局部故障问题。我们知道ZooKeeper就是Hadoop中的分布式协作服务组件。下面我们进入ZooKeeper的安装部署。 安装Zookeeper https://zookeeper.apach…

软件测试培训完就业方向怎么选择

软件测试技术在近几年的发展前景是非常好的&#xff0c;越来越多的人都想要学习软件测试技术&#xff0c;报班是大多数人的选择&#xff0c;但是大家对于“软件测试培训完就业方向怎么选择”这个问题比较迷茫&#xff0c;我们来看看下面的详细介绍。 软件测试培训完就业方向怎么…

LeetCode实战:合并两个有序链表

题目英文&#xff1a; Merge two sorted linked lists and return it as a new list. The new list should be made by splicing together the nodes of the first two lists. Example: Input: 1->2->4, 1->3->4 Output: 1->1->2->3->4->4 题目中…

Apache反向代理设置【转载】

编译Apache时要进行的设置./configure --enable-mods-shared"all proxy"1>修改 httpd.conf 文件中&#xff1a;LoadModule proxy_module modules/mod_proxy.soLoadModule proxy_connect_module modules/mod_proxy_connect.soLoadModule proxy_http_module modules…

Suricata的输出

不多说&#xff0c;直接上干货&#xff01; 见官网 https://suricata.readthedocs.io/en/latest/output/index.html 总的来说&#xff0c;Suricata采集下来的数据输出分为&#xff1a;EVE 、 Lua Output 、 Syslog Alerting Compatibility 、 Custom http logging 、 Custo…

快速提高你的UI设计水平的一些小技巧

UI设计师这个岗位在最近几年的缺口是比较大的&#xff0c;很多企业都在招UI设计人员&#xff0c;想要学习UI设计或者提升UI设计技术的同学&#xff0c;可以看看小编分享的以下内容&#xff0c;善用这些UI设计小技巧&#xff0c;快速提高你的设计水平! 快速提高你的UI设计水平的…

hibernate join fetch

那天去了达内&#xff0c;试听了2个小时的课&#xff0c;刚好讲的他们的当当网项目&#xff0c;讲hibernate表关系映射这段来了&#xff0c;不过也够呛&#xff0c;投影仪看的眼睛点都不舒服&#xff0c;当时讲的也没认真听&#xff0c;听了个大概&#xff0c;就记住那个老师一…

Java IO 字节流与字符流 (三)

概述 IO流用来处理设备之间的数据传输 Java对数据的操作时通过流的方式 Java用于操作流的对象都在IO包中 流按操作的数据分为&#xff1a;字节流和字符流 流按流向不同分为&#xff1a;输入流和输出流 IO流常用基类 字节流的抽象基类 InputStream&#xff0c;OuputStream 字符流…

LeetCode实战:两两交换链表中的节点

题目英文 Given a linked list, swap every two adjacent nodes and return its head. You may not modify the values in the list’s nodes, only nodes itself may be changed. Example: Given 1->2->3->4, you should return the list as 2->1->4->3.…

在UI设计中如何正确使用颜色

在我们进行UI设计时&#xff0c;颜色往往是我们表达理念重要的一点&#xff0c;但也是我们常常会忽视的一点。颜色其实如同语言一样&#xff0c;我们可以通过颜色的变化组合&#xff0c;来表达不同的情绪。 正确使用颜色不单能让我们吸引到客户&#xff0c;也能更好地表达我们的…

如何用Python做Web开发?——Django环境配置

用Python做Web开发&#xff0c;Django框架是个非常好的起点。如何从零开始&#xff0c;配置好Django开发环境呢&#xff1f;本文带你一步步无痛上手。 概念 最近有个词儿很流行&#xff0c;叫做“全栈”(full stack)。各大IT培训机构几乎都在宣传这一概念。告诉你只需要交1XXXX…

LeetCode实战:旋转链表

题目英文 Given a linked list, rotate the list to the right by k places, where k is non-negative. Example 1: Input: 1->2->3->4->5->NULL, k 2 Output: 4->5->1->2->3->NULL Explanation: rotate 1 steps to the right: 5->1->2…

blog地址:

blog地址: blog地址: http://blog.csdn.net/q107770540posted on 2010-11-19 08:36 Tim_ 阅读(...) 评论(...) 编辑 收藏 转载于:https://www.cnblogs.com/q107770540/archive/2010/11/19/1881399.html

Spring MVC框架有哪些优点

Spring MVC是Spring提供的一个实现了Web MVC设计模式的轻量级Web框架。它与Struts2框架一样&#xff0c;都属于MVC框架&#xff0c;但其使用和性能等方面比Struts2更加优异。 Spring MVC具有如下特点&#xff1a; 是Spring框架的一部分&#xff0c;可以方便的利用Spring所提供的…

MVC+Ninject+三层架构+代码生成 -- 总结(四、數據層)

1.數據層使用了SqlSugar 庫類 。 數據層使用了SqlSugar 庫類 &#xff0c;有興趣的 可以學習 http://www.codeisbug.com/Doc/8/1133&#xff0c;個人覺得比EF 簡單&#xff0c;容易上手&#xff0c;推薦1。 數據層使用代碼生成&#xff0c;所以考慮得比較多。 1.GetAllList()-…

台湾前十大科技公司拼不过三星(往后一点三星都不要买啦!)

台湾前十大科技公司拼不过三星,往后一点三星都不要买啦!本来还可以买它的内存和液晶,不过现在是一点都不能买了,再买就真反了他了! 三星像糖果也像毒药&#xff0c;让台湾LED类股1年涨3倍&#xff0c;但也让鸿海市值一夜之间消失350亿元(新台币&#xff0c;下同)。从来没有一刻…

技术图文:如何利用 C# 向 Access 数据库插入大量数据?

背景 通常我们在做数据分析与处理之前&#xff0c;需要把从网站爬取的数据或者从 甲方 系统中导出的数据存入到自己的数据库中。如果数据量小&#xff0c;直接利用 SQL的 Insert 语句逐条插入就好。可是数据量上万条之后&#xff0c;再利用这样的方法就会奇慢无比&#xff0c;…

Web前端面试自我介绍对话技巧注意事项

大家在学会了web前端技术后&#xff0c;当然是要准备找一个适合自己的web前端工作了&#xff0c;那么面试环节是必不可少的&#xff0c;有一个良好的自我介绍表述&#xff0c;在HR心中也能加分不少&#xff0c;接下来小编就为大家介绍一下Web前端面试自我介绍对话技巧注意事项。…

Android使用ListView控件问题

Android使用ListView控件问题&#xff1a; The application has stopped unexpectedly, please try again。 开发环境&#xff1a;android 1.6 最低兼容 4.0 报错代码如下&#xff1a; main.xml 代码 1 <?xml version"1.0" encoding"utf-8"?>2 <…

技术图文:如何实现 DataTable 与模型类 List 的相互转换?

通常情况下&#xff0c;我们在做工程项目的时候&#xff0c;需要把待处理的数据存储在数据库中。 通过 SQL 的 Select 语句很容易把查询的结果以 DataTable 的方式得到&#xff0c;但在对 DateTable 中的数据进行进一步的检索时远远没有模型类 List<T> 方便。 所以&…

SQL server 基本语句

SQL server数据库基本语句一、实验要求&#xff1a;1、 查询student表中所有学生的信息select * from student如图所示2、查询student表中“姓名”“所在班级”和“成绩”列内容select 姓名&#xff0c;所在班级&#xff0c;成绩 from student如图所示3、查询student表…

Python中if条件判断语句怎么用?

俗话说“不积跬步无以至千里”。学习了Python的基本语法后&#xff0c;接下来我们学习Python常的if条件判断语句。 if语句是最简单的条件判断语句&#xff0c;它可以控制程序的执行流程&#xff0c;其使用格式如下: if判断条件: 满足条件时要做的事情1… 满足条件时要做的事情2…

Arcmap技巧总结

Arcmap技巧总结 1. 要素的剪切与延伸 实用工具 TASK 任务栏 Extend/Trim feature 剪切所得内容与你画线的方向有关。 2. 自动捕捉跟踪工具 点击Editor工具栏中Snapping来打开Snapping Environment对话框 捕捉设置中有3个选项&#xff0c; vertex edge end 分…

Spring Web MVC(一)

概述Spring Web MVC框架的特点五大核心组件编程步骤 五大核心组件DispatcherServlet前端控制器WebApplicationContext中特殊的bean处理过程 HandlerMapping 处理映射Spring中最常用的两个处理器映射BeanNameUrlHandlerMappingSimpleUrlHandlerMapping拦截器HandlerInterceptor概…

技术图文:如何利用BigOne的API制作自动化交易系统 -- 身份验证

背景 最近&#xff0c;自己在技术精进方向上有所犹豫&#xff0c;是往"网络渗透"的方向走呢&#xff1f;还是往"量化交易"的方向走&#xff1f; 如果选择精进“网络渗透”&#xff0c;就需要学习各种Web渗透技术、客户端渗透技术、移动环境渗透技术、社会…