云服务器价格_云数据库_云主机【优惠】最新活动-搜集站云资讯

微软云_恐怖电影百度云_最新活动

小七 141 0

生成文件性能:$(shell)

我在gnumakefiles中看到的一个新手性能错误是在没有:=赋值的情况下使用$(shell)。当然我不是第一个写这个的人,但是人们仍然在犯这个错误,而且很容易纠正,它仍然存在,真的很悲惨。更新:在这里阅读更多关于gnumake和shell的信息!GNU生成变量有什么问题?gnumake支持两种基本类型的变量:简单变量和递归变量。两者的区别在于它们是如何扩展的。简单变量在声明变量时展开一次;递归变量在每次引用变量时展开。这是一个微妙但重要的区别。想想这个makefile:FOO=abc条1:=$(FOO)条2=$(FOO)FOO=定义全部:@回声$(巴1)@回声$(巴2)如果你不熟悉gmake变量之间的差异,这个版本的输出可能会让你大吃一惊。见鬼,我非常熟悉这些差异,如果我没有非常仔细地阅读makefile,那么输出结果仍然会让我感到惊讶小心:abc定义这是怎么回事?变量BAR_1声明为简单变量,因为我使用了:=来创建它。这导致gmake立即展开表达式右侧的文本,并将结果捕获为BAR_1的值。在声明BAR_1时,FOO的值是abc,所以这就是BAR_1的值。相反,BAR_2被声明为递归变量,因为我使用了通常的=(没有冒号)来声明它。在本例中,gmake捕获未展开的文本$(FOO)作为BAR_2的值;稍后,当我引用BAR_2时,gmake递归地扩展该值以获得BAR_2的当前值。当时,FOO的值是def,所以我们看到的是BAR_2的值。$(shell)$(shell)是gmake中的一个特殊函数,它运行一个外部命令并捕获输出,以便在makefile中使用。例如,您可以像这个:CWD=$(壳牌pwd)全部:@echo此makefile以$(CWD)为单位。正是递归变量和$(shell)之间的交互导致了性能问题。假设您有一个简单的makefile此:BUILDID=$(壳牌日期+Ymd)OUTTOP=../out/$(BUILDID)全部:$(OUTTOP)/myprog@echo已完成生成build id$(BUILDID)。$(OUTTOP)/myprog:$(OUTTOP)/foo.o$(OUTTOP)/bar.o$(OUTTOP)/baz.o@回音楼$@来自$^$(OUTTOP)/.o:./.c$(OUTTOP)/假人@回音楼$@来自$^$(OUTTOP)/假人:mkdir-p$(顶部)触摸$(OUTTOP)/dummy此生成文件使用$(shell)根据调用生成的日期生成生成生成标识符。然后在输出目录的名称中使用构建id,以确保每个生成都写入一个唯一的输出位置。不幸的是,由于我不小心将BUILDID声明为递归变量,gmake将在每次引用该变量时调用shell。即使是在这个小的makefile中,它被证明有大量的引用。您可以使用一个巧妙的小技巧查看每个引用:将$(warning)添加到BUILDID:建筑ID=$(调用shell时发出警告)$(shell date+Ymd)$(warning)不会影响BUILDID的值,因为它会扩展为空字符串,但它会导致gmake在每次扩展变量时都向stderr输出一条消息。现在,当我们运行构建时,我们看到以下内容输出:生成文件:4:调用shell生成文件:7:调用shell生成文件:7:调用shell生成文件:7:调用shell生成文件:7:调用shell生成文件:10:调用shell生成文件:10:调用shell生成文件:13:调用shell生成文件:14:调用shell生成文件:14:调用shell正在创建输出目录虚拟。建筑../out/20090320/foo.o。建筑…./out/20090320/bar.o。建筑…./out/20090320/baz.o。建筑../out/20090320/myprog。生成文件:5:调用shell已完成生成内部版本id 20090320。BUILDID在这个小小的构建中被扩展了11次,只使用了几个对象文件和一个最终的构建产品。最重要的是,解决这个问题很简单。只需更改BUILDID的声明,使其成为一个简单变量,我们就消除了对外壳:BUILDID:=$(调用shell的警告)$(shell date+Ymd)生成文件:1:调用shell正在创建输出目录虚拟。建筑../out/20090320/foo.o。建筑…./out/20090320/bar.o。建筑…./out/20090320/baz.o。建筑../out/20090320/myprog。已完成生成内部版本id 20090320。追踪违规者如果您使用的是CloudBees Accelerator,可以在命令行中添加--emake pedantic=1,emake将为每个包含$(shell)调用的递归变量发出警告:生成文件:1:变量"BUILDID"的值为"$(shell date+Ymd)"它包含对$(shell)的调用。这可能会减慢构建速度如果变量被多次引用,请考虑使用:=赋值相反。如果不使用CloudBees加速器,可以使用grep来查找冒犯者:埃里克@切斯特:src$grep-n-e'=.*$(shell'生成文件1: BUILDID=$(外壳日期+Ymd)你还在等什么?不要在$(shell)繁忙的情况下拖累构建性能工作。这个本文是研究makefile性能的不同方面的文章之一。如果你喜欢这篇文章,你可以享受其他的系列:生成文件性能:recursive Makefile性能:$(shell)(本篇文章)Makefile性能:模式特定的变量Makefile性能:内置规则生成加速和连续交付如果生成和测试花费太长时间无法完成,则持续交付不连续。进一步了解CloudBees Accelerator如何将构建和测试速度提高20倍,从而提高软件上市时间、基础设施利用率和开发人员生产率。