承认,这听起来并不是最佳做法,但让我解释一下。在构建期间,我们需要将构建号和系统版本粘贴到一个类中,该类的唯一目的是包含这些值并使它们可访问。
我们的第一个想法是使用系统属性,但由于部署环境的波动性(另一种说法是“系统管理员正在做奇怪的邪恶令人毛骨悚然的事情”),我们希望对它们进行硬编码。
基本上我看到了在蚂蚁中实现它的4种可能性:
对班级中的令牌使用<replace>
这种方法的问题是文件被更改了,所以你必须在编译后用<replaceregexp>
替换令牌......太丑了,我不想用正则表达式来触摸源代码。加上时间依赖性。
复制文件,复制副本,编译副本,删除副本
一个人必须记住序列 - 必须先编译原始类才能被副本覆盖。时间依赖性也很难看。
复制文件,替换原件上的令牌,编译,用副本替换染色的原件
相同的时间依赖性问题,除非嵌入在编译目标中。这也是丑陋的,因为我们所有的构建文件都使用相同的导入编译目标。
在构建脚本中从头开始创建文件/将文件存储在源路径之外
由于没有时间依赖性,因此对前三个进行了改进,但编译器/ IDE非常不满意,因为它忽略了类。红色标记令人不安地丑陋。
您对替代方案有何看法?
对此有什么最佳做法吗?
我当然希望我错过了一个完美的方法。
谢谢
修改
我们最终使用清单将版本号和系统版本存储在Implementation-Version
属性中,并且MyClass.class.getPackage().getImplementationVersion()
。我发现这个解决方案是 this thread的答案之一,由andersoj发表在评论中
答案 0 :(得分:10)
我认为更简单的方法是让您的Version.java
类从JAR中包含的简单.properties文件中读取,并在Ant构建中的构建时生成此.properties文件。例如,只需生成:
build.number = 142
build.timestamp = 5/12/2011 12:31
built-in <buildnumber>
task in Ant已经完成了一半(见第二个例子)。
答案 1 :(得分:2)
#2通常是我看到它完成的方式,除了你不准备编译的源应该与你准备好编译的源分开。这避免了你所谈论的时间问题,因为它只应编译一次。
这是一种在软件构建过程中始终显示的常见模式。
模式是: 从某些资源生成源,然后编译它。
这适用于从编译前的过滤源到为RMI,CORBA,Web服务等生成接口存根的许多内容......
将源复制到指定的“生成源”位置,并在副本文件上执行令牌替换以生成源,然后将生成的源编译到已编译的类目标。
编译顺序取决于您的其他来源是否依赖于生成的来源。
答案 2 :(得分:1)
我的解决方案是:
在课程中使用令牌:
<replace dir="${source.dir}" includes="**/BuildInfo.*" summary="yes">
<replacefilter token="{{BUILD}}" value="${build}" />
<replacefilter token="{{BUILDDATE}}" value="${builddate}" />
</replace>
此替换只应在构建系统执行的构建步骤中进行,而不应在IDE内的编译/调试会话中进行。
构建系统设置不应该将更改的源代码提交回源存储库,因此这种方法不存在更改代码的问题。
根据我的经验,当您将构建信息放在属性文件中时,它无效,因为管理员倾向于在升级时保留属性文件 - 替换安装后出来的属性文件。 (在属性文件中构建信息对我们来说是信息性的。如果属性文件与代码版本同步,它提供了在启动期间检查的机会。)
答案 3 :(得分:0)
我记得我们以一种不同的方式使用了第四种方法。您可以在创建release时将版本号传递给ant脚本.Ant脚本应该包含在发行版(config / properties文件)中,并且您的类应该从那里读取它可能使用属性文件或配置文件。
答案 4 :(得分:0)
我总是建议创建某种目录并将所有构建的代码放在那里。请勿触摸您签出的目录。我通常创建一个target
目录,并在那里修改和构建所有文件。
如果没有太多* .java文件(或* .cpp文件),请将它们复制到target/source' and compile there. You can use the
task with a
`,以便在复制时使用内部版本号修改此文件一个文件
<javac srcdir="${target.dir}/source"
destdir="${target.dir}/classes"
[yadda, yadda, yadda]
</java>
这样,您在签出的源目录中不做任何修改,因此没有人会不小心检查更改。另外,只需删除target
目录即可执行 clean 。
如果有数千个(如果不是数百万个)*.java
个文件,那么您可以将模板复制到target/source
,然后在{$basedir}/source
和target/source
中编译源代码。这样,你仍然没有弄清楚已检出的代码,并且有可能会有人意外地检查修改后的版本。而且,您只需删除clean
即可完成target
。
答案 5 :(得分:0)
我正在寻找同一问题的解决方案,请阅读此链接:http://ant.apache.org/manual/Tasks/propertyfile.html我能够找到解决方案。
我使用netbeans,所以我只需要将这段代码添加到我的build.xml
<target name="-post-init">
<property name="header" value="##Generated file - do not modify!"/>
<propertyfile file="${src.dir}/version.prop" comment="${header}">
<entry key="product.build.major" type="int" value="1" />
<entry key="product.build.minor" type="int" default="0" operation="+" />
<entry key="product.build.date" type="date" value="now" />
</propertyfile>
</target>
每次使用clean和build编译项目时,这将增加次要版本。因此,只要次要版本保持不动,您就可以保存以运行项目。
我只需要在运行时读取该文件。我希望这有帮助。