65.9K
CodeProject 正在变化。 阅读更多。
Home

Java / Ant 在 TFS 上的构建

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.91/5 (3投票s)

2013年10月8日

CPOL

6分钟阅读

viewsIcon

34304

在 TFS 构建服务器上构建 Java 软件的历程

引言

在 2012 Team Foundation Server (TFS) 构建服务器上构建 Java 软件乍一听可能有点疯狂,但它确实可行,并且相对容易上手。不幸的是,关于如何将 Ant 构建与 Windows Workflow 构建模板和项目文件结合起来配置的文档非常少。本文将把所有内容整合在一起,并说明在 TFS 上构建 Java 所需的条件。

背景 

我已经在 TFS 构建服务器上构建 .NET 软件一段时间了,并且在这方面已经积累了一定的专业知识。当有人问我是否可以在 TFS 构建服务器上构建 Java 软件时,我以为他们在开玩笑。这个团队正在使用 TFS 进行源代码控制,并想知道在这种环境中构建是否可行。经过一番研究,我发现这不仅是可能的,而且似乎已被广泛使用。受到这个新发现信息的鼓舞,我开始着手处理一个现有的 Java 解决方案,并尝试在 TFS 上使用 Ant 构建它。本文将分享这次经历,并提供一些使 Java 构建在 TFS 世界中更容易使用的方法。

使用代码

在此工作中得到支持的团队使用 Eclipse 作为他们的 IDE,TFS 作为源代码存储库。该团队还使用 Jenkins 进行构建和 Oracle WebLogic 进行部署。本文的重点将是构建,而不是部署。对于 Eclipse IDE,需要 Team Explorer Everywhere 插件。这允许开发人员/构建管理器访问源代码,但更重要的是,有助于创建构建定义。此环境的另一个先决条件是 Apache Ant,"一个 Java 库和命令行工具,其任务是驱动构建文件中描述的进程,将目标和扩展点相互依赖。Ant 最主要的已知用途是构建 Java 应用程序。" Ant 目标和任务允许构建者编译、组装、测试和运行 Java 应用程序。在大多数 Java 项目中,都有一个包含 build.xml 文件的构建文件夹。这个 build.xml 文件是 Ant 用来构建构建中指定的目标的。因为正在使用构建服务器,所以 Ant 文件需要指定构建可用的任务和目标。可能还有外部属性文件,其中包含在运行时加载到 Ant 构建过程中的特定于构建的属性。这些属性文件需要作为 Ant 命令的参数传递给构建服务器。稍后将详细介绍。 

最后,还有构建服务器的安装和配置。 http://msdn.microsoft.com/en-us/library/jj155784.aspx 提供了一个操作指南,甚至会引导用户完成构建定义的创建过程。 请使用这些步骤配置您的构建服务器并创建您的第一个构建定义。 

这些步骤的输出是 TFS 需要执行构建的文件:TFSBuild.proj。此项目文件包含构建软件的 Ant 指令。在其生成的形式中,它是一个非常简单的 MSBuild 项目文件,与 TFS 的 UpgradeTemplate.xaml 文件配合使用,后者是指导构建过程的 Windows Workflow 文件。为了使构建定义更灵活,需要对 TFSBuild.projUpgradeTemplate.xaml 文件进行一些编辑。

如果不进行自定义,TFSBuild.proj 包含一个 <ItemGroup> 条目,如下所示: 

<ItemGroup>
    <!-- Ant Call Configuration.
         The build file called should be included in the workspace of the build definition.
    -->
    <AntBuildFile Include="$/MyProject/web/website/build/build.xml">
      <Targets></Targets>
      <Properties>BinariesRoot=$(BinariesRoot);BuildDefinitionName=$(BuildDefinitionName);
        BuildDefinitionUri=$(BuildDefinitionUri);BuildDirectory=$(BuildDirectory);
        BuildNumber=$(BuildNumber);DropLocation=$(DropLocation);LogLocation=$(LogLocation);
        SourceGetVersion=$(SourceGetVersion);TestResultsRoot=$(TestResultsRoot);
        TeamProject=$(TeamProject);WorkspaceName=$(WorkspaceName);WorkspaceOwner=$(WorkspaceOwner)</Properties>
      <Lib></Lib>
    </AntBuildFile>

    <!-- JUnit XML Results files should be created using the XML formatter
         and be located in the following path
    -->
    <JUnitLogFiles Include="$(BinariesRoot)\**\TEST-*.xml" />
</ItemGroup>

请注意,AntBuildFile 标签有一个包含参数,用于在构建定义创建期间指定的 build.xml 文件。还有一个 <Targets> 标签 - 这是可以将构建目标传递到项目文件的地方,但默认情况下它是空的。显然,在这种形式下它不太灵活。构建管理器每次想要不同的构建时都需要编辑并签入 TFSBuild.proj 文件。由于只能有一个 TFSBuild.proj 文件,这会造成一个真正的问题。让我们看一下如何为此过程(以及一些默认值)提供三个变量输入,以减轻构建管理器的痛苦。让我们分解以下代码段,它是我们上面检查过的代码段的替代项: 

<PropertyGroup>
    <!-- Set a default value for BuildEnv if not passed -->
    <BuildEnv  Condition=" '$(BuildTarget)'  == '' ">build-install-jroth</BuildEnv>
    <MyProps Condition=" '$(MyProps)' == '' ">build.jroth-gr.properties</MyProps>
    <MyBuild Condition=" '$(MyBuild)' == '' ">build.xml</MyBuild>
  </PropertyGroup>
  <ItemGroup>
    <!--  Ant Call Configuration.  
      The build file called should be included in the workspace of the build definition.
    -->
    <AntBuildFile Include="$(MyBuild)">
      <Targets>$(BuildTarget)</Targets>
      <Properties>BinariesRoot=$(BinariesRoot);BuildDefinitionName=$(BuildDefinitionName);
        BuildDefinitionUri=$(BuildDefinitionUri);BuildDirectory=$(BuildDirectory);
        BuildNumber=$(BuildNumber);DropLocation=$(DropLocation);LogLocation=$(LogLocation);
        SourceGetVersion=$(SourceGetVersion);TestResultsRoot=$(TestResultsRoot);
        TeamProject=$(TeamProject);WorkspaceName=$(WorkspaceName);
        WorkspaceOwner=$(WorkspaceOwner)</Properties>
      <Lib></Lib>
      <PropertyFile>$(BuildDirectory)$(MyProps)</PropertyFile>
    </AntBuildFile>
    <!-- JUnit XML Results files should be created using the XML formatter
         and be located in the following path
    -->
    <JUnitLogFiles Include="$(BinariesRoot)\**\TEST-*.xml" />
</ItemGroup>

请注意,在先前示例的 <ItemGroup> 上方创建了一个 <PropertyGroup>。已为构建目标 <Targets>、新属性、外部构建属性文件 <PropertyFile> 以及 build.xml 文件 <AntBuildFile Include="$(MyBuild)"> 分别定义了三个条件属性。在 <ItemGroup> 中,使用 $(MyBuild)$(MyProps)$(BuildTarget) 分别指定了构建文件、属性文件和构建目标的参数。但这会引出一个问题:这些参数在哪里定义的?它们是如何传递到这个项目文件的?这就是 UpgradeTemplate.xaml 文件发挥作用的地方。

在 Visual Studio 2012 中,双击 Upgrade.Template.xaml 文件,它会打开看起来很吓人的工作流编辑器。别担心 - 没那么糟糕。在屏幕的左下角,点击“Arguments”(参数)。使用带有“Create Argument”(创建参数)的行输入上面三个参数中的第一个。对接下来的 2 个重复此操作,直到有三个条目:BuildTarget、MyProps 和 MyBuild。

 

接下来,点击“Metadata”行右侧的奇特图标,并将这三个参数添加到此对话框中。为每个参数提供有用的显示名称。

对所有三个参数使用相同的类别。当渲染构建定义时,它会在该类别标题下对这些参数进行分组。 

再次点击“Arguments”(参数)以关闭列表。现在,在工作流中找到“Run TfsBuild for Configuration”活动,右键单击它并选择“Properties”(属性)。

 

在该活动的属性对话框中,找到 CommandLineArguments。 点击省略号打开 Expression Editor(表达式编辑器),并构建以下行:

"/p:BuildTarget=" + BuildTarget + ";MyProps=" + 
          MyProps + ";MyBuild=" + MyBuild + " " + MSBuildArguments

点击 OK 保存此对话框,然后保存模板并将其签入。  打开构建定义,然后打开 Process(进程)选项卡。点击右上角的“Show details”(显示详细信息),选择构建模板,然后点击“Refresh”(刷新)按钮。在新的“Custom”(自定义)类别下应该有 3 个参数。为这些参数提供值,它们将被传递到构建过程中。 

这些微小的更改现在提供了一个灵活的构建定义模板,可用于创建单独的构建定义,每个目标一个。它们也可以在运行时更改,以使用所需的任何目标、构建文件或属性文件。 

关注点

这只解决了拥有单个 TFSBuild.proj 文件的问题,这是一个巨大的进步。仍然存在将 Java 构建结构化到 TFS 构建服务器上的问题。如果软件构建的成熟度不高,那么在确保构建针对远程服务器构建进行正确结构化方面可能还有一些工作要做。

历史 

  • 原文发布日期:10/8/13
© . All rights reserved.