【问题标题】:Multiple Delphi versions using Jenkins: library paths使用 Jenkins 的多个 Delphi 版本:库路径
【发布时间】:2015-10-30 18:32:48
【问题描述】:

我们正在考虑将我们的构建机器从 FinalBuilder 迁移到 Jenkins,以适应我们扩展公司的其他部分。

我注意到的一个问题是,虽然 Finalbuilder 能够从构建机器上当前安装的 Delphi 中提取当前库路径,但 Jenkins 依赖于 .dproj 文件中包含的信息。

由于 .dproj 文件中的路径非常特定于用户机器的已知问题,我们目前没有将它们提交到我们的存储库,而是依靠 Delphi 根据需要重新创建它们。当构建机器首先依赖于完整的 MSBUILD 脚本时,这显然不会很好。

我们使用了相当多的第三方组件(仅 DevExpress 套件就有 100 多个单元),因此在 .dpr 中包含和维护所有具有完整路径的 .pas 文件并不是一个真正的选择。

有没有人对此有一个久经考验的解决方案?

我对选项的想法是:

  • 为每个构建设置 %PATH% - 添加当前的 Delphi 库 对于相关版本(这会遇到 %PATH% 长度限制吗?)
  • 使用命令行参数将正确的库路径传递给 MSBUILD(这可能吗?)
  • 使用编译器指令在源文件中以某种方式包含搜索路径(这可能吗?)
  • 使用预编译步骤创建新的 .dproj 文件(类似于 http://delphi-divining.blogspot.co.uk/2012/10/dprojmaker-tool-to-create-delphi.html,但需要命令行)

编辑:第五个想法:

  • 我们能否为每个项目使用 dproj.local 文件,存储在单独的存储库(或单独的路径)中并在预构建时复制到构建机器?这将允许构建机器路径安全地存储,远离混乱的提交。

【问题讨论】:

  • 将所有第三方库放入项目中,vcs repo 就是答案。无法想象您为什么要回避可重现的构建。为什么要问版本地狱?

标签: delphi jenkins msbuild


【解决方案1】:

您需要将您的.dproj 文件提交给源代码管理。

您的问题是您的配置不完整。任何构建系统都应该能够只使用源代码控制中的文件来构建您的项目,这是确保构建正确二进制文件的唯一方法。

您有多种选择来完成这项工作

  1. 您可以在 Delphi IDE 中使用环境变量,例如,%ROOTFOLDER% 可以在一台机器上设置为 C:\Development\MyDelphiProjects,在另一台机器上设置为 C:\Dev,只要该路径的所有内容都相同,它就应该是好的。每个开发人员和您的构建机器都可以设置所需的路径。您可能还需要用于 bpl 路径的 var。
  2. 在客户端计算机上实施相同的结构。让所有开发者都以我们 C:\Development\Delphi 为根到底有多难?
  3. 确保所有搜索路径都是相对的。这可以工作,但总是有异常会导致问题,所以我从来没有设法让它工作。

我们在以前的公司中使用了选项 1,它运行得非常成功,设置起来有点麻烦,但是一旦设置好,您就可以确定您的构建是正确的。

【讨论】:

  • 希望避免这种情况 :-/ dproj 存在其他问题,主要是由于通过参数传入我们的数据库连接/授权设置,该参数在 IDE 中存储在 .dproj 中。这意味着它一直在为每个用户更改并且总是被意外签入。dproj.local 可能有助于解决这个问题,但我需要做更多的阅读。实际上,这给了我第五个想法....
【解决方案2】:

当我选择 Jenkins 作为“构建”环境时,我遇到了同样的问题。解决方案是使用带有构建任务的 MSBuild 脚本。因此,在 Jenkins 中,无需直接构建项目,只需构建此脚本即可为您提供更多选项,包括指定项目路径的选项(您可以覆盖默认 IDE 路径)。 明天我会发布这样的脚本。

所以在 Jenkins 中,当您配置 MSBuild 时,您必须指定 msbuild 文件,即 Build.xml。对于命令行参数,我只使用 /v - 详细程度和 /t - 目标名称。

构建脚本如下所示:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003" ToolsVersion="4.0">
  <Target Name="Compile" DependsOnTargets="CompileApp" />

  <PropertyGroup>
    <ExeOutputName>App.exe</ExeOutputName>
    <ExeOutputPath>x:\exe</ExeOutputPath>
    <DcuOutputPath>x:\dcu</DcuOutputPath>

    <ForConfig>Release</ForConfig>
    <ForPlatform>Win32</ForPlatform>
  </PropertyGroup>

  <Target Name="ResolveOutputPath">
    <MakeDir Directories="$(ExeOutputPath)" />
    <MakeDir Directories="$(DcuOutputPath)" />
    <Delete Files="$(ExeOutputPath)\$(ExeOutputName)" />
    <Delete Files="$(DcuOutputPath)\*.*" />
  </Target>

  <ItemGroup>
    <AppUnitSearchPathItem Include="$(BDS)\lib\$(ForPlatform)\$(ForConfig)" />
    <AppUnitSearchPathItem Include="C:\Users\builder\Documents\tmssoftware\TMS Component Pack" />
    <AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Dcu\$(ForPlatform)" />
    <AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Source" />
    <AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Source\CodeGen" />
    <AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Source\DataSnap" />
    <AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Source\ZLib" />
    <AppUnitSearchPathItem Include="C:\Program Files (x86)\RemObjects Software\RemObjects SDK for Delphi\Source\Synapse" />
    <AppUnitSearchPathItem Include="C:\Program Files (x86)\Embarcadero\RAD Studio\12.0\Components\EhLib\Lib\$(ForPlatform)\$(ForConfig)" />
    ...
  </ItemGroup> 

  <ItemGroup>
    <AppDefinesItem Include="App" />
    <!-- AppDefinesItem Include="CompilerDirective" -->
  </ItemGroup>

  <ItemGroup>
    <AppPropertiesItem Include="DCC_ExeOutput=$(ExeOutputPath)" />
    <AppPropertiesItem Include="DCC_DcuOutput=$(DcuOutputPath)" />
    <AppPropertiesItem Include="DCC_BuildAllUnits=true" />
    <AppPropertiesItem Include="DCC_Optimize=true" />
    <AppPropertiesItem Include="DCC_DebugInformation=0" />
    <AppPropertiesItem Include="DCC_PentiumSafeDivide=true" />
    <AppPropertiesItem Include="DCC_RangeChecking=true" />
    <AppPropertiesItem Include="DCC_IntegerOverflowCheck=true" />
    <AppPropertiesItem Include="DCC_WriteableConstants=true" />
    <AppPropertiesItem Include="DCC_IOChecking=true" />
    <AppPropertiesItem Include="DCC_AssertionsAtRuntime=false" />
    <AppPropertiesItem Include="DCC_Warnings=true" />
    <AppPropertiesItem Include="DCC_MapFile=3" />
    <AppPropertiesItem Include="DCC_ConsoleTarget=false" />
  </ItemGroup>

  <Target Name="CompileApp" DependsOnTargets="ResolveOutputPath">
    <PropertyGroup>
      <AppUnitSearchPath>@(AppUnitSearchPathItem)</AppUnitSearchPath>
      <AppDefines>@(AppDefinesItem)</AppDefines>
    </PropertyGroup>

    <ItemGroup>
      <AppProperties Include="Config=$(ForConfig)" />
      <AppProperties Include="Platform=$(ForPlatform)" />
      <!-- AppProperties Include="LibraryPath=$(AppUnitSearchPath)" -->
      <AppProperties Include="DelphiLibraryPath=$(AppUnitSearchPath)" />
      <AppProperties Include="UnitSearchPath=$(AppUnitSearchPath)" />
      <AppProperties Include="ResourcePath=$(AppUnitSearchPath)" />
      <AppProperties Include="IncludePath=$(AppUnitSearchPath)" />
      <AppProperties Include="ObjPath=$(AppUnitSearchPath)" />
      <AppProperties Include="DCC_Define=$(AppDefines)" />
      <AppProperties Include="@(AppPropertiesItem)" />
    </ItemGroup>

    <MSBuild Projects="App.dproj" Properties="@(AppProperties)" />
  </Target>
</Project>

这里缺少的是可以使用资源模板从该脚本中完成的版本控制部分...

【讨论】:

  • 那太好了,谢谢。我知道理想的做法是从正确的 .dproj 构建,但是我们的 .dproj 文件在存储库中被覆盖了许多嵌入式变通办法,我真的不想解开这些问题,所以这样的事情听起来很完美.
  • @MattAllwood 我已经更新了答案。希望这会有所帮助。
  • 我发现了它。我现在不得不更深入地考虑这一点,因为我们的 .dproj 文件在很长时间没有使用后有点乱(我们的旧构建过程甚至有一个过时的“模板”)它为每个项目复制只是为了阻止编译器抱怨)。一旦我有机会弄清楚我们在做什么,我会接受答案
  • 我已经接受了这个回答提出的问题,但是我认为我们将更多地重新考虑我们的构建过程,以尝试避免问题,而不是试图解决它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-18
  • 1970-01-01
相关资源
最近更新 更多