2011-09-07 68 views
5

我正在尝试使用Ant和MSBuild自动化我的项目(包括java和.net)的构建过程。我已经阅读了他们,并知道如何在Ant和MSBuild中编写构建脚本。但是我想知道,一般来说编写构建脚本是否有任何指导原则或最佳实践?以下是我找到的两个,但我希望听到其他开发人员的更多信息。在Ant或MSBuild中编写构建脚本的任何最佳实践

  • 在编写构建脚本,仅仅依赖于位于 源控制和工作文件夹数量有限, 签出源代码的项目。不要编写依赖于源代码管理中未保留的项目的构建脚本,它们是 。
  • 如果一个项目包含一组子系统,并且每个子系统都有其自己的构建脚本,则该项目的构建文件应该只调用 子系统的构建脚本。此外,这些文件应该导入包含目标,如编译,测试,封装等

我见过this post以及共同构建文件,但它是对写作任务的方式详细。如上所述,我需要更高层次的指导方针。

下面是我从答案中收集的准则:

  1. 运行间隔建立一个干净的环境。这意味着每个构建脚本需要一个clean目标。
  2. 构建脚本通常应包括compile,packagetest目标。
  3. 如果某个产品有不同的开发线(例如dev,release),则它们都应该具有相同的构建脚本。但是,不同的 参数应该传递给这些脚本。
  4. 在开发线上执行的构建通常包含编译, 打包,部署和安装步骤。但在版本 上构建的产品线包括进一步的步骤,例如标记产品和生成更改日志/发行说明的 。
  5. 构建脚本也应该保存在源代码管理中。
  6. 尽量保持所有的构建脚本构建信息,并不 持续集成服务器(竹,TeamCity的,等等)上
  7. 如果您的构建使用参数可能会在未来发生变化(例如 网络地址复制编译结果),请不要将其硬编码为您的构建脚本中的 。相反,使用构建参数可以很容易地控制它更多 。

回答

4

如果您正在构建VisualStudio应用程序,则最好使用msbuild而不是Ant。 msbuild命令将使用开发人员创建的解决方案文件进行构建,并基本上模拟他们所做的构建。

如果你真的想自动化所有的东西,看看Jenkins。它有一个插件,可以执行msbuild,并且每次有人进行更改时都会自动触发构建。我使用msbuild和Jenkins的组合。我使用msbuild进行构建,然后使用Ant收集并压缩所有构建的构件。然后,人们可以直接从Jenkins下载构建的工件。

现在,您的Java应用程序必须使用Ant。我使用以下指导原则

  • 每个构建脚本需要一个clean目标。该目标删除在构建过程中添加的所有文件,并将工作目录返回到clean之前的状态。
  • 我按照使用对象的名字时,Maven的是什么呢,所以我的目标是像干净名字的东西编译
  • 还遵循Maven指南,我所有的构建文件都放在target目录中。这样,我的干净的命令可以简单地做一个<delete dir="${target.dir}/>并清理一切,很好,闪闪发光。
  • 如果我有子项目,每个子项目都有自己的build.xml文件。我的主文件build.xml只是调用所有子项目的文件build.xml
  • 使用Ivy。它很容易设置和易于使用。您不再有将源文件存储在您的源代码库中的问题,或者失去了您所依赖的什么版本的jar文件。
  • 哎呀,如果可以的话,请使用Maven并完成它。不幸的是,大多数较老的项目比它的价值更难以达到。
  • 使用Jenkins作为连续构建服务器进行构建。而且,离开部门的所有构建(UAT,QA和保护构建)必须是Jenkins构建。
  • 鼓励开发人员编写单元测试。实际上,Jenkins可以执行单元测试并在其构建页面上显示其结果。
  • 使用其他的东西,如checkstyle,PMD,CPD,Findbugs和其他代码验证产品。当然,詹金斯可以运行其中的每一个,并显示漂亮的图表,这些图表可以用来向您的经理显示您的工作有多难。
+0

谢谢大卫。您的意见非常有价值。 – hsalimi

1

在MSBuild中,目标应尽可能指定输入和输出(以启用依赖性计算)。如有必要,请使用Returns属性指定一个返回不同于用于依赖性计算的项目的目标。

给定目标的输入和输出项目应使用项目转换(对于简单的基于路径的转换)或另一个目标(对于更复杂的转换)来生成。

对于MSBuild 4.x之前版本,对于您在。中定义的目标。目标文件,可以考虑使用以下模式,使消费者正在定义的问题之前注入自己的目标:

<PropertyGroup> 
    <MyTargetDependsOn> 
    Target1; 
    Target2; 
    SomeOtherTarget 
    </MyTargetDependsOn> 
</PropertyGroup> 
<Target 
    Name="MyTarget" 
    DependsOnTargets="$(MyTargetDependsOn)"> 

</Target> 

这使得消费者在指定的目标之前,注入自己的目标,简单地通过修改MyTargetsDependsOn的价值属性:

<PropertyGroup> 
    <MyTargetDependsOn> 
    $(MyTargetDependsOn); 
    YetAnotherTarget 
    </MyTargetDependsOn> 
</PropertyGroup> 
<Target 
    Name="YetAnotherTarget"> 

</Target> 

在MSBuild 4.x中,您可以简单地使用BeforeTargets和AfterTargets属性。

+0

重要的是,如果可能的话,任务不应返回其输出项目列表。相反,他们的输出应该在目标水平上计算,并传递给任务(而不是由任务产生)。 – tintoy

+0

非常感谢,但我正在寻求更高层次的指导方针,而不是详细的指南。 – hsalimi

4

刚上第二个小点评论你上面提到的:

如果一个项目包含一系列的子系统,每个子系统都有 自己的编译脚本,该项目的生成文件应该只需调用 构建子系统的脚本。

每个子系统应该有它自己的构建文件,但该文件应该导入一个公共构建文件。共同构建文件将包含目标,如编译,测试,封装等

http://ant.apache.org/manual/Tasks/import.html

子系统建立文件然后很简单,不包含重复,只包含特定于该子系统的信息(如compile.classpath)。

+0

非常感谢凯文。这是绝对正确的。 – hsalimi