[译]自动增加构建计数
By robot-v1.0
本文链接 https://www.kyfws.com/applications/auto-increment-of-the-build-count-zh/
版权声明 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
- 15 分钟阅读 - 7415 个词 阅读量 0[译]自动增加构建计数
原文地址:https://www.codeproject.com/Articles/536/Auto-Increment-of-the-Build-Count
原文作者:Joseph M. Newcomer
译文由本站 robot-v1.0 翻译
前言
Learn how to implement an auto-incrementing build number for your projects.
了解如何为您的项目实现自动递增的内部版本号.
问题(The Problem)
执行构建时,使构建编号(版本号的低16位)自动递增很有用.这可以帮助您跟踪发行.但是,Microsoft在构建系统中没有提供任何用于执行此操作的机制.因此,存在许多解决方案,由于种种原因,我发现所有这些解决方案都不令人满意,我将在以后讨论.我不满意的结果,以及新的重大项目的启动,最终使我超出了门槛,于是我写了我自己的书.它也有问题.但是,与其他解决方案相比,我认为它存在一系列问题.您可能喜欢或不喜欢此解决方案,但这取决于您.(When performing builds, it is useful to have the build number, the low-order 16 bits of the version number, automatically increment. This helps you track releases. However, Microsoft does not provide any mechanism in the build system for doing this. Consequently there have been a number of solutions, all of which I found unsatisfactory for a variety of reasons I will discuss later. The result of my dissatisfaction, and the initiation of a new major project, finally pushed me over threshold, and I wrote my own. It, too, has problems. However, it has a set of problems I deem more acceptable than the other solutions. You may or may not like this solution, but that’s up to you.)
先前的解决方案(Previous solutions)
我的第一个解决方案(已过时)(My first solution (obsolete))
在过去的生活中,我有一个自动版本的步进器,它是我手工构建的一部分(In a past life, I had an automatic version stepper that ran as part of my hand-constructed) makefile
.它运行了一个名为"(. It ran a little program called “) version
读取文件的”(" that read a file) version.h
,在句号之后增加版本号,然后将文件写回.然后,我可以根据需要使用此版本号字符串.它还写了一个附带文件(, incremented the version number following the period, and wrote the file back. I could then use this version number string any way I wanted to. It also wrote an accompanying file) version.ver
我的编辑器曾使用该版本将版本号插入更改日志中.这工作了好几年.一个缺点是依赖于该文件(that was used by my editor to insert the version number in a change log. This worked for years. The one downside was that the file that depended on) version.h
在每次编译时都会重新编译,因此我通常将其做成一个仅包含一个(got recompiled on each build, so I usually made it a small file containing only a) sprintf
在子程序中.(in a subroutine.)
然后出现了Visual C ++.好消息是自从我开始使用它以来,我不必去研究(Then along came Visual C++. The Good News is that since I started using it I haven’t had to look at the insides of a) makefile
.坏消息是,直到最新版本,才有效地添加自定义构建步骤.我不得不跑我的小(. The Bad News was that until the latest releases there was no way to add custom build steps effectively. I had to run my little) version
手动编程.现在有机会添加一个自动步骤.但是要采取什么措施呢?(program manually. Now had the opportunity to add an automatic step. But what to put in the step?)
标记可执行文件(Stamping the Executable)
我首先去了新的,改进的(I first went to the new, improved)大号(L)CodeGuru网站.我在那里寻找解决方案.一个解决方案是引入并重写该程序的程序.(CodeGuru site. I searched for solutions there. One solution was a program that went in and rewrote the) VERSIONINFO
可执行文件中的资源.我认为这很冒险,并且对此的补充评论(例如未能重新计算导致问题的校验和)使我无法接受.此外,我几年前就做过了((resource in the executable. I considered this risky, and the number of supplemental comments about it, such as the failure to recompute checksums causing problems, dissuaded me from this. Besides, I’d done this years ago (and I)*有(had)*重新计算校验和),我认为它是一种相当脆弱的机制(在我引用的情况下,我是在安装过程中将许可证信息写入可执行文件中,包括加密的密码).所以我排除了它,尽管它抽象上是最好的机制,因为它不会强制重新编译或重新加载资源.(recomputed the checksums) and I consider it a fairly fragile mechanism (in the case I cited, I was writing license information into the executable during an install, including an encrypted password). So I ruled it out, although it is in the abstract the nicest mechanism because it does not force a recompilation or reload of resources.)
VBA子例程(VBA Subroutines)
另一种机制是可以由编译机制自动调用的VBA子例程.这将以文本形式读取资源文件,对其进行更改,然后将其写回.它有一些已报告的问题和一些修复程序,但是它有一个问题,它增加了每个构建的数量,无论成功与否.它还具有以下问题:它将关闭资源文件,然后将其重新加载为文本文件,对其进行修改并写出.然后,它将删除资源文件的文本版本.如果您采用我的解决方案并修改(Another mechanism was a VBA subroutine that could be automatically invoked by the compilation mechanism. This would read the resource file in as text, change it, and write it back. It had some reported problems and some fixups, but it had the problem that it incremented the number on every build, successful or not. It also had the problem that it would close the resource file, then reload it as a text file, modify it, and write it out. It would then delete the text version of the resource file. If you take my solution and modify the) .rc
文件,虽然效果不同,但效果相同.但是我有一个解决方法.(file, the effect, although obtained in a different fashion, will be the same. But I have a workaround.)
加载项(Add-Ins)
另一个解决方案是VC ++加载项.这看起来确实很酷,但是可惜它没有任何附带的源代码,只有DLL文件.所以我决定继续下去.如果源代码随附它,我可能会考虑过.(Another solution was a VC++ add-in. This looked really cool, but, alas, it did not have any accompanying source code, just the DLL file. So I decided to pass on this. I might have considered it if the source code had accompanied it.)
然后,我考虑做自己的加载项.插件文档的简短阅读使我确信,听起来如此美,但超出了我的努力极限.由于我在该工具上的努力"停滞不前",因此不会产生任何收益,此外,我还没有花时间去开发它,因为我确实有很多截止日期要完成.(I then thought about doing my own add-in. A brief perusal of the add-in documentation convinced me that, as aesthetic as this sounded, it exceeded my effort threshold. Since the “meter is off” on my effort on this tool, it would generate no revenue, and in addition I couldn’t take the time I should to develop it because I do have a number of deadlines yet to be met.)
我自己的解决方案(My own solution)
消除了各种现有解决方案后,我决定自己做.那是我可以获得所需解决方案的唯一方法.这是一个作为预链接步骤运行的程序.(Having eliminated the various existing solutions, I decided that I wanted to do my own. That was the only way I could get the solution I wanted. This is a program that runs as a pre-link step.)
这里的问题是,如果我修改(The problem here is that if I modify the) .rc
文件,然后(file, then the) .res
文件早于(file is older than the) .rc
文件,这将强制重建,并且VC ++不断提示我在运行之前需要重建文件.当然,我每次都可以说"否",但这为我无法阅读实际内容提供了出错的机会.因此,我想以一种不会触发此类虚假重建或消息的方式来执行此操作.(file, and this will force a rebuild, as well has having VC++ keep prompting me that there are files that need to be rebuilt before I run. Of course, I could say No each time, but this opens the chance for error as I fail to read the actual contents. So I wanted to do this in a way that wouldn’t trigger such spurious rebuilds or messages.)
该程序称为(The program is called) buildinc
.将可执行文件放在为此目的保留的一些有用的工具目录中,或将其构建在自己的目录中.它需要两个命令行参数,a的名称(. Put the executable in some useful tool directory you keep for such purposes, or build it in its own directory. It takes two command line arguments, the name of a) version.ver
文件和的名称(file and the name of the the) .rc
包含(file containing the) VERSIONINFO
结构体.正好有两个参数,按照该确切顺序.(structure. Exactly two arguments, in that exact order.)
如果(If the) version.ver
文件不存在,已创建一个.初始版本值设置为(file does not exist, one is created. The initial version value is set to)
因此,如果您在当前(so if you run this on your current) .rc
文件版本将被重置.记下所需的版本,然后进入并编辑(file the version will be reset. Make a note of the version you want, and then go in and edit the) version.ver
用手更改值.(by hand to change the value.)
的语法(The syntax of the) version.ver
文件是一系列形式的行(file is a series of lines of the form)
哪里(where)*维诺(verno)*可以有以下两种形式之一(can have one of two forms)
要么(or)
请注意,空格是可选的,但不会保留.如果版本号仅包含逗号,则会以上面的逗号形式重新生成,该逗号后面有空格;如果包含任何期间,则以没有空格的期间形式重新生成.(Note that spaces are optional but are not retained. If the version number contains only commas, it will be regenerated in the comma-form above, which has spaces following the commas; if it contains any periods, it is regenerated in the period-form with no spaces.)
请注意,如果您为二进制文件版本号输入了格式为16.14.2.1234的数字,则资源编译器似乎能够解析它并存储正确的值.因此,我并没有努力使用一种形式来表示文件版本的字符串表示形式,而使用另一种格式来表示二进制版本.(Note that if you put a number of the form 16.14.2.1234 in for the binary file version number, the resource compiler seems capable of parsing it and storing the correct value. So I didn’t make an effort to use one form for the string representation of the file version and a different format for the binary version.)
我的程序扫描(My program scans the) .rc
填写表格行(file for a line of the form)
并替换为(and replaces it with)
以及形式上的一行(and also for a line of the form)
并将该行替换为(and replaces that line with)
如果文件中有多个资源(本地化),它将找到后一行并将其替换为所有受支持的语言.但是,在此版本中,我不支持多个输入文件,因此,如果需要此支持,则必须重写程序以接受多个输入文件.(If you have multiple resources (localization) in your file, it will find the latter line and replace it for all supported languages. However, I do not support multiple input files in this version, so you’d have to rewrite the program to accept multiple input files if you need that support.)
我为什么用(Why do I use) version.ver
作为版本号的确定来源,而不是资源文件?因为我想要两个功能:版本生成日期的连续日志,以及我的编辑器了解如何读取(as the definitive source of the version number, and not the resource file? Because I want two features: a continuing log of version generation dates, and because my editor understands how to read a) version.ver
文件并添加当前版本号以更改日志条目.另外,因为我实际上移动了(file in and add the current version number to change log entries. Also, because I actually moved the) VERSIONINFO
资源(resource to the) .rc2
文件,这意味着我只需要编辑一个文本文件即可手动更改版本号,例如,更改前三个字段中的任何一个.(file, it means that I only have to edit a single text file to change the version number by hand, for example, to change any of the initial three fields.)
这样创建了新的版本号后,程序便会修改(Having thus created a new version number, the program then modifies the) .rc
文件.因为我对这种事情有些偏执,并且基于抱怨其他工具的各种错误报告,我决定使用以下算法:(file. Because I am somewhat paranoid about this sort of thing, and based on the various bug reports that were complaining about the other tools, I decided to use the following algorithm:)
- 获取内部版本号,然后根据(Take the build number and create a file name based on the)
.rc
文件和内部版本号,例如,如果内部版本号为(file and the build number, for example, if the build number was)202
和(, and the).rc
档案原为(file was)myproject.rc
,我会生成文件名(, I would generate the filename)myproject.rc.0202
.(.) - 从内部版本号中减去10并删除该名称的任何文件,因此在上述示例中,我将删除文件名(Subtract 10 from the build number and delete any file by that name, thus I would in the above example delete the filename)
myproject.rc.0192
.这样可以避免空间过于混乱,但可以提供许多备份副本.(. This keeps the space from becoming too cluttered, but gives me a number of backup copies.) - 重命名当前(Rename the current)
.rc
文件到该文件名.(file to that filename.) - 读取该文件并创建一个新文件(Read that file and create a new)
.rc
具有更新的内部版本号的文件.(file with the updated build number.) 然后,我创建了预链接构建步骤:(I then created the pre-link build step:)
用于名为" myproject"的项目.这是工作的一半.然后我去了(for the project called “myproject”. This is half the job. Then I went to the) Resources
选项卡,突出显示此处显示的命令行,然后将其复制.然后,我创建了一个(tab, highlighted the command line shown there, and copied it. I then created a)*第二(second)*链接前步骤(pre-link step,)
这将强制重新编译刚刚更改的资源文件,因此不会收到任何虚假的重建通知,也不会进入无限的重建循环.(This forces a recompilation of the resource file that I’ve just changed, so I won’t get any spurious rebuild notifications, or get into an infinite rebuild loop.)
调试设置如下所示.某些区域已被遮盖以保护专有信息.您必须记住对Debug(调试)设置和Release(发布)设置以及您可能具有的任何自定义设置都执行此操作.不要忘记在第二步中更改目录以指向正确的目录(如果您从一个自定义预链接步骤剪切粘贴到另一自定义预链接步骤,则可能会忘记更改此目录).(This is shown below, for the Debug settings. Certain areas have been blanked to protect proprietary information. You must remember to do this for both the Debug setting and the Release setting, and of course for any custom settings you may have. Don’t forget to change the directory in the second step to point to the correct directory (if you do cut-and-paste from one custom pre-link step to the other you could forget to change this).)
缺点(The downsides)
我用(I use the) version.ver
文件作为确定的版本号表示形式,而不是(file as the definitive version number representation, rather than the) VERSIONINFO
资源.更改此内容将是很小的重写,但是我决定这是我想要的解决方案.当然,由于有了源代码,如果您不喜欢此解决方案,则可以轻松地重写它.(resource. It would be a minor rewrite to change this, but I decided that this was the solution I wanted. Of course, since you have the source, if you don’t like this solution you can easily rewrite it.)
它还需要手动重建(It also requires a manual rebuild of the) .rc
文件作为预链接步骤的一部分,这意味着如果我需要更改包含路径或以其他方式修改(file as part of the pre-link step, which means that if I need to change the include path or otherwise modify the behavior of the) rc
编译步骤我必须记得不仅要在(compilation step I must remember to do it not only in the) Resources
标签,但在我的预链接步骤中.在使用VC ++的五年中,我从未修改过(tab but in my pre-link step. In five years of using VC++ I’ve never modified the) Resources
建立,所以我不认为这会打扰我.你的旅费可能会改变.(build, so I don’t think this is going to bother me. Your Mileage May Vary.)
它修改了(It modifies the) .rc
外部文件,这将在每次成功构建后强制重新加载.我认为这是我所做的最糟糕的功能.您可能会发现它是可以容忍或讨厌的.解决此问题的一种方法是我将(file externally, which forces a reload after each successful build. II consider this the single worst misfeature of what I’ve done. You may find it tolerable, or hate it. One way around this, which is what I have done, is to move the) VERSIONINFO
资源(resource to the) res\project.rc2
文件,并指定(file, and specify the) .rc2
文件作为目标文件(file as the target file for) buildinc
.这意味着您无法编辑(. This means you can’t edit the) VERSIONINFO
文件在资源编辑器中,但这可能不是问题,因为我实际对其进行编辑的次数(而不是更改版本号)很少,以至于补偿了我不必每次都重新加载资源的次数.(file in the resource editor, but this may not be a problem, since the number of times I actually edit it (other than changing the version number) are so few as to compensate me for not having to reload resources each time.)
我将其构建为MFC控制台应用程序.这是因为我很懒.我想了(I built this as an MFC Console App. This is because I was lazy. I wanted) CString
s,但我需要一个控制台应用程序.同样,我决定在上个周末不想学习STL,所以我只使用了MFC.如果您想使用STL重写它,请放心.如果您寄给我一份副本,我什至会把它寄给别人(包括您想要在来源中注明的任何信用额度…).(s, but I needed a console app. Again, I decided that learning STL was not something I wanted to do this past weekend, so I just used MFC. If you feel like rewriting this using STL, feel free. If you send me a copy, I’ll even put it up for others (include whatever credit lines you want in the source as well…).)
变更记录(Change Logs)
更改日志对我来说非常重要.我有数百个项目,其中很多都出钱给了其他人.我需要维护更改日志以保持理智(后一个维护问题是主要问题,尽管许多人认为此维护完全失败了).几年前,特别是85年8月8日(根据我的变更日志程序中的变更日志),我创建了一种快速有效的方式来处理此问题.我使用来自的Epsilon文本编辑器(Change logs are very important to me. I have hundreds of projects, a significant number of which go out to other people, who have paid for them. I need to maintain change logs to maintain my sanity (the latter maintenance problem is the dominant one, although many contend that this maintenance has failed utterly). Years ago, specifically, 8-Aug-85 (according to the change log in my change log program), I created a fast, efficient way to handle this. I use the Epsilon text editor from) 卢加鲁(Lugaru) .(.)
我对VC ++编辑器的看法是,这几乎是不可接受的第一次尝试,但是在我使用它之前还有很长的路要走.它混淆了一些基本概念,例如"窗口"和"视口",并且它不是键盘友好的编辑器.我可以输入70wpm,但我对使用鼠标所需的打字速度中断感到不满.我使用EMACS类编辑器已有25年以上,它们似乎很好地适应了基于键盘的编辑任务,而我对它们也很熟悉.(My opinion of the VC++ editor is that it is a barely acceptable first attempt, but has a long way to go before I’ll live in it. It confuses some fundamental concepts like “Window” and “Viewport”, and it is not a keyboard-friendly editor. I can type 70wpm, and I resent the disruption of typing speed required by having to use the mouse. I’ve been using EMACS-class editors for over 25 years, and they seem well attuned to the keyboard-based editing task, and I am well-attuned to them.)
通过一个按键组合,我可以安装更改日志;与另一个,我可以添加一个条目.换行是自动的.我有一些工具可以执行诸如处理更改日志并按更改编号合并更改,以及汇总我添加的更改行数之类的工具.我只有一个按键,可以在受更改影响的行上插入更改请求号.这是在我的一个应用程序中创建的更改日志:(In one keystroke combination I can install a change log; with another, I can add an entry. The line wrapping is automatic. I have tools that will do things like process the change logs and consolidate changes by change number, and summarize the number of change lines I add. I have a single keystroke that inserts the change request number on a line affected by the change. Here’s a change log created in one of my applications:)
请注意,通过阅读第一行添加的[string](Note the [string] added by reading the first line of the) version.ver
文件. REQ#127指示更改是修改请求的结果,具体来说是数字127.这是另一个键盘按键请求添加的.因此,我知道在添加更改时的构建级别.虽然中间版本没有多大关系,但这与(file. The REQ #127 indicates the change is the result of a modification request, specifically, number 127. This is added by another keyboard keystroke request. Hence I know to the build level when a change was added. While intermediate builds don’t matter much, this together with an) awk
脚本尚未编写,将使我能够向客户展示适用于每个发行版的更改列表.这样可以更轻松地跟踪客户支持的版本.它还可以清楚地表明哪个版本的内部版本具有哪些更改请求(更改请求由客户发送给我;我分配了更改编号并发回更新的更改编号文件).(script yet-to-be-written, will allow me to present a customer with a list of changes applicable to each release version. This makes it easier to track versions for customer support. It also makes it evident which release builds have which change requests in (the change requests are sent to me by the customer; I assign a change number and send back the updated change number file).)
目前(The current) awk
脚本通过生成更改行摘要列表,文件名和总行数来跟踪更改,例如(script tracks the changes by producing a list of the change line summaries, by filename, and a total line count, for example)
这告诉我变更请求#133涉及两个文件,(This tells me that change request #133 involved two files,) crosspnt.c
和(and) FLTRDLG.C
,以及日期和更改.因为这早于我的新(, with the dates and changes. Since this predates my new) buildinc
使用较旧的应用程序(app it uses the older)*版本号(version.build)*显示.它涉及11行变更.(display. It involved 11 lines of changes.)
分析完所有文件后,我还将获得摘要报告:(After it analyzes all the files, I also get the summary report:)
从1997年最初的产品发布到现在,在这个项目的五年生命中,已经发生了24446项源代码行更改或增补,代表了通常的维护活动,例如错误修复和功能增补.向该产品添加Internet支持实际上造成了大约11,000行更改,或者几乎占更改的一半.(Over the five-year lifetime of this project, from the initial product release in 1997 through the present, there have been 24446 source line changes or additions, represent the usual maintenance activities, such as bug fixes and feature additions. Adding Internet support to this product actually accounted for about 11,000 lines of change, or nearly half of the changes.)
任何想要我的任何工具或我的EEL源代码(如果您不是Epsilon用户的人,对您都没有好处)的副本的人(Anyone who wants a copy of the EEL source code (it won’t do you any good if you’re not an Epsilon user) for any of my tools, or my) awk
脚本,欢迎有一个.只是不要转售它们.发给我(scripts, is welcome to have one. Just don’t resell them. Send me)电子邮件(email).(.)
概要(Summary)
这是构建步骤增量器不断出现的另一个工具.我想我喜欢.时间会证明一切.我将在此网站上发布更改,并通知有关更改的通知.(This is another tool in the continuing saga of build-step incrementers. I think I like it. Time will tell. I will post changes on this Web site and notices of the changes to the) microsoft.public.vc.mfc
新闻组.(newsgroup.)
这些文章中表达的观点是作者的观点,绝不代表Microsoft,也未得到Microsoft的认可.(The views expressed in these essays are those of the author, and in no way represent, nor are they endorsed by, Microsoft.)
发送邮件给(Send mail to)newcomer@flounder.com(newcomer@flounder.com)有关本文的问题或评论.(with questions or comments about this article.)
版权所有©2000,The Joseph M. Newcomer Co.保留所有权利(Copyright © 2000, The Joseph M. Newcomer Co. All Rights Reserved) www.flounder.com/mvp_tips.htm(www.flounder.com/mvp_tips.htm)
许可
本文以及所有相关的源代码和文件均已获得The Code Project Open License (CPOL)的许可。
C++ VC6 Windows MFC Visual-Studio Dev 新闻 翻译