

make / Makefile
在上一讲中,我们介绍了Linux下的编译器 - gcc/g++的使用,本节我们来介绍一下如何使用make/Makefile实现项目的自动化构建
a.out的由来,是从
test.c经过预编译到test.itest.i经过编译到test.stest.s经过汇编到test.otest.o经过链接到a.out首先我们来介绍一下什么是make/Makefile,以及它们之间的关系
文件。它是一个工程文件的编译规则,它记录了原始码如何编译的详细信息、描述了整个工程的编译链接等规则。🎯先来看一下Makefile的【语法】:
target(目标文件):文件1 文件2(依赖文件列表) //依赖关系
<Tab>gcc -o 欲建立的执行文件 目标文件1 目标文件2 ///依赖方法
command
...
...
目标文件。而后面的依赖文件列表就是具有相关性的 object files,也就是目标文件所依赖的文件(可以是一个或多个,也可以没有)🎯然后看一下Makefile的【规则】:
目标文件:依赖文件列表会不会写Makefile ,从一个侧面说明了一个人是否具备完成大型工程的能力💪
命令工具,是一个解释makefile中指令的命令工具,一般来说,大多数的IDE都有这个命令,比如:Delphi的make,Visual C++的nmake,Linux下GNU的make。可见,Makefile都成为了一种在工程方面的编译方法【总结一下】:make是一条命令,makefile是一个文件,两个搭配使用,完成项目自动化构建👈
了解可什么是make/Makefile之后,我们就来用一用它们
vim Makefile即可,进入编辑界面,如果有不懂vim的,可以看看我的文章 —— 人生苦短,我用Vim
test.c,作为源文件,然后开始往里面写内容mytest:test.c
gcc -o mytest test.c

make指令,它就是自动在当前源文件的所在路径下搜寻Makefile,并解释里面命令。之后若是我们需要去编译任何文件,只需要在Makefile里面做一个添加即可,怎么样,是不是很方便
通过小小的demo,想必你已经感受到了【自动化构建工具】的强大,我们来仔细看看Makefile中的指令为何要如此书写✍
mytest:test.c,冒号左侧是目标文件,右侧是它的依赖文件,所以就可以说它们之间存在一种【依赖关系】,只有test.c存在才可以有mytestgcc -o mytest test.c 👉它叫做【依赖方法】
就这么说还是不太好理解,我们举个父与子的生活小案例来帮助理解
今天呢,是这个月的28号的了,家里面在月初给你的2000块钱差不多也花完了,于是这两天只能吃土,此时你打开微信后看到和老爸的聊天框,于是就想着和老爸要点钱【毕竟儿子向父亲要钱天经地义😀】
[依赖关系][依赖方法]
下面辨析几种依赖关系与依赖方法
❌错误的依赖方法
所以只有依赖关系不行,还得有正确的依赖方法
❌错误的依赖关系
依赖方法对了,但是依赖关系不对也不行
✔ 正确的依赖关系与依赖方法
完成一件事,必须得有正确的依赖关系 + 正确的依赖方法
看完了【依赖关系】与【依赖方法】的感性理解,相信你对它们有了一定程度的认识,接下去深入地来了解一下它们之间的关系
1 mytest:test.o
2 gcc test.o -o mytest
mytest是依赖于汇编后的目标文件test.o的,但是现在我们没有这个文件,因此就要去倒推一下如何获取这个test.otest.o来说,它依赖于test.s这个经过编译之后文件,可是【test.s】不存在,所以跳转到下一条依赖关系 3 test.o:test.s
4 gcc -c test.s -o test.o
test.s来说,它依赖于test.i这个经过预编译之后的文件,可是【test.i】不存在,所以跳转到下一条依赖关系 5 test.s:test.i
6 gcc -S test.i -o test.s
test.i来说,它依赖于test.c这个源文件,查找后发现源文件存在,于是开始执行gcc命令 7 test.i:test.c
8 gcc -E test.c -o test.i
以下就是我们需要在Makefile中修改的【依赖关系】与【依赖方法】



【总结一下】:在[依赖关系]中,若是目标文件所依赖的文件不存在,就将这个依赖方法入栈,转到下一组[依赖关系],依次循环往复,直到当前目标文件所依赖的文件存在时,就进行出栈,开始执行依赖方法。最后获取的便是那个我们最初想要的目标文件
平时我们在进行各种操作之后目录中都会出现很多文件,此时当我们不想要这些文件的时候,就得去一一删除,显得尤为麻烦,如果编译可以使用Makefile来自动化构建,那清理项目中的文件可不可以呢,我们来看看
Makefile中增加一个【清理】功能

make,而是在make后面加上了一个clean,这是为什么呢?.PHONY是什么?它对clean而言意味着什么?我们带着这些问题一起进入【伪目标】的学习📖
PHONY是一个伪目标,Makefile中将.PHONY放在一个目标前就是指明这个目标是伪文件目标。其作用就是防止在Makefile中定义的执行命令的目标和工作目录下的实际文件出现名字冲突
也就是下面这句,此时的clean被.PHONY修饰了,那么它就可以反复执行它的依赖方法
.PHONY:clean
clean来说,它的依赖文件列表为空,上面我们也有提到过它可以为空 11 clean:
12 rm -f test.o test.s test.i
rm -f test.o test.s test.imake clean会自动忽略名为"clean"文件的存在,因此声明.PHONY配置项会改善性能,并且不需要担心实际同名文件存在与否😮我们到命令行中来验证一下⌨️

make clean,不过其实在第一次执行的时候,就已经达成了我们清理的目的,可是后面还可以继续执行,这其实就是.PHONY修饰起的作用

.PHONY做修饰之后一样是可以反复执行那就有同学问:这是为什么呢?为何clean不加
.PHONY修饰也可以多次执行
[clean]
.PHONY的修饰试试
.PHONY修饰的原理】.PHONY修饰之后便可以多次make,但是可以看到在编译的过程中进行make的时候所执行的指令不太相同,只有gcc test.o -o mytest这一句,却少了如何产生【test.o】的过程,这是为何呢❓生成时间,若是依赖对象的生成时间要早于目标对象,说明它还没有被重新修改过,所以无需再度去重新编译生成(这一块在后面make的工作原理中细讲)
.PHONY的修饰,就防止其被多次重复编译【总结一下】:
📚 .PHONY修饰的是伪目标,对于伪目标来说,它可以被反复执行
📚 .PHONY修饰的一定能被反复执行,但是能被反复执行的不一定被.PHONY修饰
以上就是有关伪目标的叙述,如果还不太清楚可以看看这篇文章 ——> 链接
make指令的动态依赖关系,我们可以发现make指令也是依赖于标准的C库,而我们在Makefile中写得也都是一些指令,因此使用make指令才可以对Makefile中的内容做一个识别
因此我们可以得出一个结论
👉make是专门给【Makefile】写的一个命令,在执行make的时候,就会自动在你当前目录下去搜索Makefile这个文件,搜索之后打开,然后对它里面的内容做分析
那make是如何进行分析Makefile的呢,有什么规则吗❓
mytest这个目标对象的时候都是直接使用的【make】吗;clean这个目标对象时却用的是【make clean】
好,我们来深入探讨一下刚才遗留下的问题:make究竟是如何知道我们的可执行文件是否需要重新编译呢❓
mytest这个目标文件后,第二次再去执行【make】指令就不会其效果了,这是为何呢?
可执行文件来收,它生成的时间一定是晚于源文件的【因为中间要经过一系列编译 + 链接的过程】
20:17:56是要晚于17:45:48的。所以【make】指令才会不起作用。所以它就是通过这个Modify时间来进行对比才能判断出是否需要重新编译
那我们能否钻个空子,来欺骗一下make呢😜
我们来试试看。可以很清楚地看到源文件的Modify时间从17:45:48变到了20:17:56,那就比可执行文件要来得晚了,此时再去【make】的话就会重新编译了

我们在VS下有时候经常会出现修改了源代码但是生成不了.exe可执行文件的问题,既然说到了【源文件】和【可执行文件】的关系,就顺带拓展一下
本模块来拓展一下有关make/Mailefile里的一些小知识
自动推导的功能,所以隐晦的规则可以让我们比较粗糙地简略地书写✍makefile,比如源文件与目标文件之间的时间关系判断之类;include;# 在行首表示行注释“GNUmakefile”、“makefile”、“Makefile”的文件最后我们来总结一下本文所学习的内容📖
本文我们学习了Linux下的项目自动化构建工具 - make/Makefile
.PHONY修饰的文件叫做【伪目标文件】源文件与目标文件的【Modify时间】以上就是本文要讲解的所有内容,感谢您的观看

很好奇,就使用rubyonrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提
如何在buildr项目中使用Ruby?我在很多不同的项目中使用过Ruby、JRuby、Java和Clojure。我目前正在使用我的标准Ruby开发一个模拟应用程序,我想尝试使用Clojure后端(我确实喜欢功能代码)以及JRubygui和测试套件。我还可以看到在未来的不同项目中使用Scala作为后端。我想我要为我的项目尝试一下buildr(http://buildr.apache.org/),但我注意到buildr似乎没有设置为在项目中使用JRuby代码本身!这看起来有点傻,因为该工具旨在统一通用的JVM语言并且是在ruby中构建的。除了将输出的jar包含在一个独特的、仅限ruby
我知道您通常应该在Rails中使用新建/创建和编辑/更新之间的链接,但我有一个情况需要其他东西。无论如何我可以实现同样的连接吗?我有一个模型表单,我希望它发布数据(类似于新View如何发布到创建操作)。这是我的表格prohibitedthisjobfrombeingsaved: 最佳答案 使用:url选项。=form_for@job,:url=>company_path,:html=>{:method=>:post/:put} 关于ruby-on-rails-rails:Howtomak
我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘
我已经像这样安装了一个新的Rails项目:$railsnewsite它执行并到达:bundleinstall但是当它似乎尝试安装依赖项时我得到了这个错误Gem::Ext::BuildError:ERROR:Failedtobuildgemnativeextension./System/Library/Frameworks/Ruby.framework/Versions/2.0/usr/bin/rubyextconf.rbcheckingforlibkern/OSAtomic.h...yescreatingMakefilemake"DESTDIR="cleanmake"DESTDIR="
我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("
假设我有这个范围:("aaaaa".."zzzzz")如何在不事先/每次生成整个项目的情况下从范围中获取第N个项目? 最佳答案 一种快速简便的方法:("aaaaa".."zzzzz").first(42).last#==>"aaabp"如果出于某种原因你不得不一遍又一遍地这样做,或者如果你需要避免为前N个元素构建中间数组,你可以这样写:moduleEnumerabledefskip(n)returnto_enum:skip,nunlessblock_given?each_with_indexdo|item,index|yieldit
无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD
在编写Ruby(客户端脚本)时,我看到了三种构建更长字符串的方法,包括行尾,所有这些对我来说“闻起来”有点难看。有没有更干净、更好的方法?变量递增。ifrender_quote?quote="NowthatthereistheTec-9,acrappyspraygunfromSouthMiami."quote+="ThisgunisadvertisedasthemostpopularguninAmericancrime.Doyoubelievethatshit?"quote+="Itactuallysaysthatinthelittlebookthatcomeswithit:themo
C#实现简易绘图工具一.引言实验目的:通过制作窗体应用程序(C#画图软件),熟悉基本的窗体设计过程以及控件设计,事件处理等,熟悉使用C#的winform窗体进行绘图的基本步骤,对于面向对象编程有更加深刻的体会.Tutorial任务设计一个具有基本功能的画图软件**·包括简单的新建文件,保存,重新绘图等功能**·实现一些基本图形的绘制,包括铅笔和基本形状等,学习橡皮工具的创建**·设计一个合理舒适的UI界面**注明:你可能需要先了解一些关于winform窗体应用程序绘图的基本知识,以及关于GDI+类和结构的知识二.实验环境Windows系统下的visualstudio2017C#窗体应用程序三.