把编译时间加入到目标文件

原文:https://www.cnblogs.com/pingwen/p/8183728.html

1、问题背景:如何保证发布出去的bin文件是最终测试通过的版本?

一般的来讲,代码到了测试后期,master分支就不会频繁的提交了,并且提交也会更加谨慎。

但是人为操作总会出现纰漏,希望只要代码被重新编译过,那么bin文件就包含新的时间信息,而这个信息是可以从外部通信或printf来查看的。

在嵌入式开发中,版本号一般的都是一个int变量或字符串变量。但是若修改了代码而没有改version变量或宏定义,那么从version上就看不出来文件的变化。

那么最终编译的版本到底是哪个版本,是否与测试的版本完全一致,这个问题尤为突出。

目标文件中带有编译时间可以防止代码被改动过,只要代码被重新编译,那么就生成新的时间信息。

git能够记录文件修改信息,但是调试信息或工程配置等,很多文件都是ignore的,这些信息代表着最终的bin文件的运行环境。

某些复杂bug情况下,只有运行环境一致,仿真器才能attach到目标文件。

2. 如何获取时间:DATA, TIME

这两个宏是日期和时间,格式如下。如果把这两个宏加入到代码,那么就得到了时间的字符串信息。

// Example of __DATE__ string: "Dec 27 2017"
// Example of __TIME__ string: "15:06:19"
const char *BuildInfo = "Version: " VERSION " " __DATE__ " " __TIME__;

代码实现获取日期和时间的方法很多,比如:

左右滑动查看全部代码>>>

unsigned int mk_Build_Date(void)
{int    year = 0, month = 0, day = 0;int hour = 0, minute = 0, seconds = 0;char m[4] = {0};sscanf(__DATE__, "%3s %2d %4d", m, &day, &year);for (month = 0; month < 12; month++){if (strcmp(m, short_char_months[month]) == 0){break;}}sscanf(__TIME__, "%2d:%2d:%2d", &hour, &minute, &seconds);#ifdef SHORT_DATA_CHAR__printf("[null]  ** Build at:\t%04u-%02u-%02us %02u:%02u:%02u\n",year, month, day,hour, minute,seconds);#elseprintf("[null]  ** Build at:\t%04u-%02u-%02u %02u:%02u:%02u\n",year, month, day,hour, minute,seconds);#endifDEBUG("buildDate: %s %s\n", __DATE__, __TIME__);return 0;
}

把上面的函数加入到代码中,就能获取工程编译的时间。

但是如果该代码所在的文件没有被修改,在非build-all情况下,编译器不会再次编译此文件,所以时间信息也就不会被更新。

如果每次都使用re-build all,一来繁琐,二来也不能保证每次都会记得点击build all按钮,靠技术手段来保证每次build都更新时间信息才是正道。

3. 如何保证时间每次编译都更新:使用预编译指令,每次更新包含时间宏的文件或对应的链接文件。

在IAR环境下,官方已经给出了解决的方法(Using pre-build actions for time stamping)。

https://www.iar.com/support/tech-notes/ide/build-actions-pre-build-and-post-build/

方法1:修改文件的时间,引起编译器对文件进行重新编译。

cmd /c "touch /cygdrive/d/test.c"

方法虽好,可惜IAR用户大多数是Windows用户,包括我在内,touch是linux命令,必须Cywin环境。如果安装过这个环境的话,那就大功告成了。

Cygwin touch commandYou can enter "cygwin-application.exe" on the pre- and post-build command lines, if the environment variable PATH includes the directory where the "cygwin-application.exe" is located.You can run the Cygwin command "touch" on the pre-build command line, but if you add a file path, for example "touch d:/test.c", the file path is not accepted by Cygwin.Cygwin expects the POSIX path /cygdrive/d/test.c so the resulting command line would be "touch /cygdrive/d/test.c", however this command cannot be executed directly on the pre- and post-build command. Instead you have to run indirectly using:cmd /c "touch /cygdrive/d/test.c"
The .bat file (located in project directory) alternative would look like:Pre-build command line:$PROJ_DIR$\pre-build.bat
File pre-build.bat:touch /cygdrive/d/test.c

方法2:修改文件对应的链接文件,触发编译器重新编译该文件,生成新的链接文件,那么就会生成新的带有时间信息的目标文件。

An alternative to the "touch" command is to have a pre-build action that deletes the object file, for example the Pre-build command line:cmd /c "del "$OBJ_DIR$\test.o""

在pre-build中加入上面的命令,就会在编译前删除test.o文件。

在这种模式下,工程代码只要任何位置发生变化,代码重新编译,就会触发删除test.o,然后链接过程发现没有test.o文件,那么就会重新编译一次test.c,那么新的时间信息就会记录下来了。

虽有些曲线救国的味道,但还是很顺利的实现了目标。

只要工程的任何地方有改动,生成新的目标文件,那么目标文件中就会带有最新的编译时间。

方法3:直接告诉编译器每次重新编译某个文件更直接,MDK支持此功能。

时隔一年半再次来这里,发现当时自己简直是小白,还洋洋得意曲线救国,实际上舍近求远罢了。

如果对工具多一些了解,万万是不会用上面的方法的,当然上面的方法也是通用想法,是通用型知识点,容易想到,也能达到目标。

新的方法,不需要写任何脚本,如果想让代码每次都编译更新DATA 和 TIME两个宏,那么让这个文件每次都编译一次就可以了,不需要删除它的obj文件然后让编译器找不到文件而触发重新编一次,其实直接告诉编译器每次重新编译更直接,MDK支持此功能。

下面是测试的效果:

其它资料:

https://stackoverflow.com/questions/11697820/how-to-use-date-and-time-predefined-macros-in-as-two-integers-then-stri

 

 推荐阅读:

    专辑|Linux文章汇总

    专辑|程序人生

    专辑|C语言

嵌入式Linux

微信扫描二维码,关注我的公众号 

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

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

相关文章

大数据基础篇(一):联机分析处理(OLAP) 与 联机事务处理(OLTP)

联机事务处理(OLTP) OLTP也称实时系统(Real Time System)&#xff0c;支持事务快速响应和大并发&#xff0c;这类系统典型的有ATM机(Automated Teller Machine)系统、自动售票系统等&#xff0c;但有些银行转账并不是实时到账的。OLTP反映企业当前的运行状态&#xff0c;完成企…

[JavaScript] 正则表达式

简单模式• 创建&#xff1a; 一个文本格式或正则表达式构造函数 文本格式&#xff1a; /pattern/flags 正则表达式构造函数&#xff1a; new RegExp("pattern"[,"flags"]); • 参数说明&#xff1a; pattern -- 一个正则表达式文本 flags -- 如果存…

1核2G云服务器 标准型S4 S5,腾讯云服务器标准型S4和S5配置性能参数区别及选择攻略...

腾讯云服务器标准型S4和标准型S5实例有什么区别&#xff1f;标准型S5相对于S4是新一代云服务器规格&#xff0c;S5实例CPU采用2.5GHz主频至强Cascade Lake&#xff0c;S4实例处理器采用2.4GHz主频至强Skylake&#xff0c;腾讯云S4/S5均为标准型服务器&#xff0c;具有均衡的计算…

单精度浮点数与十六进制转换

#include <stdio.h>/*--------------------------- 十六进制到浮点数 ---------------------------*/ float Hex_To_Decimal(unsigned char *Byte,int num) { #if 0char cByte[4];//方法一for (int i0;i<num;i){cByte[i] Byte[i];}float pfValue*(float*)&cByte;…

zipline-benchmarks.py文件改写

改写原因&#xff1a;在这个模块中的 get_benchmark_returns() 方法回去谷歌财经下载对应SPY&#xff08;类似于上证指数&#xff09;的数据&#xff0c;但是Google上下载的数据在最后写入Io操作的时候会报一个恶心的编码的错误&#xff0c;很烦人&#xff0c;时好时坏的那种&a…

css普通压缩不去,使用css-loader的minimize压缩css不起作用?

{ test: /\.(scss|css)$/, use: [!env.production? style-loader: MiniCssExtractPlugin.loader,{ loader: css-loader, options: { modules: true, minimize: true //设置css压缩}},{ loader:…

华为3COM交换机PVLAN配置使用说明

1.  PVLAN的引入   <?xml:namespace prefix o ns "urn:schemas-microsoft-com:office:office" /><?xml:namespace prefix v ns "urn:schemas-microsoft-com:vml" />在实际应用中有这样一个需求&#xff0c;组网图如上图所示。    …

springboot启动太慢优化

需求缘起&#xff1a;有人在【springboot】微信公众号问&#xff1a;springboot启动慢的问题何时有个分享就好了&#xff0c;谢谢。粉丝的问题还是要认真的回答的。 我们先看看本节的大纲&#xff1a; &#xff08;1&#xff09;组件自动扫描带来的问题&#xff08;SpringBootA…

绑定字符串

Bind("BARAS","{0:F0}")CutString1(DataBinder.Eval(Container.DataItem,"title").ToString(),12)((bool)DataBinder.Eval(Container.DataItem,"IfShow"))?"Yes":"No" 使用 Eval 方法 Eval 方法可计算数据绑定控…

ajax封装 使用,AJAX封装类使用指南

AJAX说起来感觉很难&#xff0c;但是把他封装起来你会发现使用起来很简单了&#xff0c;当然也是简单的应用了&#xff0c;譬如留言板的应用等&#xff0c;这里首先&#xff0c;先送大家一个礼物那就是封装好的AJAX的类&#xff0c;下载地址http://xiazai.jb51.net/201412/yuan…

Linux cpuidle framework

背景Kernel版本&#xff1a;4.14ARM64处理器使用工具&#xff1a;Source Insight 3.5&#xff0c; Visio1. 介绍在Linux OS中&#xff0c;Idle进程的运行会让CPU进入cpuidle状态。当没有其他进程处于运行状态时&#xff0c;Scheduler会选择Idle进程来运行&#xff0c;此时CPU无…

Crystal 语法概述[转]

Crystal 语法概述创建公式时&#xff0c;可以选择使用 Crystal 语法或 Basic 语法。语法规则用于创建正确的公式。几乎任何使用某种语法编写的公式都可以使用另一种语法来编写。报表可以包含使用 Crystal 语法的公式&#xff0c;也可以包含使用 Basic 语法的公式。有关是使用 C…

上传源文件至虚拟服务器,C# 通过WebService上传视频文件到服务器虚拟机下源码...

【实例简介】请参考&#xff1a;http://blog.csdn.net/dwj901125/article/details/23701063这里有相当详尽的实现过程。【实例截图】【核心代码】WebServiceTest├── WebServiceTest│ ├── Backup│ │ ├── StateGrid95598│ │ │ ├── Properties│ …

Linux利器:QEMU!用它模拟开发板能替代真开发板?

不想错过我的推送&#xff0c;记得右上角-查看公众号-设为星标&#xff0c;摘下星星送给我&#xff01;QEMU&#xff0c;搞嵌入式开发的一定不陌生&#xff0c;最近各大群里都讨论疯了&#xff0c;说它是Linux利器一点也不夸张。它是一款知名的而且开源的模拟器&#xff08;官网…

前端模块化(二):模块化编程

所谓的模块化编程就是封装细节&#xff0c;提供使用接口&#xff0c;彼此之间互不影响&#xff0c;每个模块都是相互独立&#xff0c;实现某一特定的功能。如果其他模块想调用的时候&#xff0c;可以暴露我们所希望对外的公开的方法与数据。 1、函数写法 function f1(){ var va…

ASP.NET AJAX - Timer控件之摆放位置的影响

ASP.NET AJAX所提供的Timer 控件是一个服务器控件&#xff0c;它能够定时引发全网页回传&#xff0c;当然&#xff0c;在搭配了UpdatePanel 控件之后&#xff0c;就可以定时引发异步回传并局部更新UpdatePanel 控件的内容。<?xml:namespace prefix o />在此要请大家注意…

CPU怎么认识代码的?

# 语言这个东西&#xff1f;首先说明下&#xff0c;我们正常使用的python、C、C语言等等&#xff0c;我们自己能读得懂的语言&#xff0c;包括汇编语言&#xff0c;CPU都是不认识的&#xff0c;CPU 只认识一种语言&#xff0c;那就是 机器语言&#xff0c;也就是我们很多人&…

ajax 五种状态,ajax的五种状态

ajax的五种状态(readyState )0 &#xff0d; (未初始化)还没有调用send()方法1 &#xff0d; (载入)已调用send()方法&#xff0c;正在发送请求2 &#xff0d; (载入完成)send()方法执行完成&#xff0c;已经接收到全部响应内容3 &#xff0d; (交互)正在解析响应内容4 &#x…

nodeJs的学习之路(1)

一 什么是nodeJs nodeJs是一个后端技术&#xff0c;研究web应用的开发模式&#xff0c;能够开发一些简单的服务器&#xff0c;学会操作数据库等等。官方解释就是&#xff1a;nodeJs是基于谷歌v8引擎的javascript运行环境 nodeJs使用了一个事件驱动&#xff0c;非非阻塞式I/O模型…

u盘病毒之tel.xls.exe

系统症状每次双击盘符出现一个新窗口windows任务管理器出现了一个Excel的程序鼠标右键点盘符出现"Auto"字样无法显示隐藏文件无法 取消或者钩选 隐藏已知文件类型的扩展名 样本信息File size: 49152 bytes MD5: d88f7c6c15585404c30c92a11c429c36 SHA1: af2120915a1e…