Delphi 构建服务器:管理第三方组件的最佳实践?

Delphi 构建服务器:管理第三方组件的最佳实践?,delphi,build-automation,project-organization,Delphi,Build Automation,Project Organization,我正在维护一个相当大的遗留应用程序。源代码树真是一团糟。 我正在尝试设置生成服务器 在源代码树上,我使用源代码创建了第三方组件(也在项目的include路径中)。这些组件也安装在IDE中 我的问题是: 如何管理这些组件 我想这样管理: 在生成服务器上安装IDE 安装所有第三方组件 从“项目源”树中删除组件源(并将它们保存在项目根目录中的一个专用文件夹中,每个文件夹都已压缩) 每次需要定制(或调试)第三方组件时,我们都会重新构建包,并将其重新安装在构建服务器的IDE中(以及每个开发人员工作站上)

我正在维护一个相当大的遗留应用程序。源代码树真是一团糟。 我正在尝试设置生成服务器

在源代码树上,我使用源代码创建了第三方组件(也在项目的include路径中)。这些组件也安装在IDE中

我的问题是: 如何管理这些组件

我想这样管理:

  • 在生成服务器上安装IDE
  • 安装所有第三方组件
  • 从“项目源”树中删除组件源(并将它们保存在项目根目录中的一个专用文件夹中,每个文件夹都已压缩)
  • 每次需要定制(或调试)第三方组件时,我们都会重新构建包,并将其重新安装在构建服务器的IDE中(以及每个开发人员工作站上)

在IDE中安装组件和在包含路径中安装源有什么区别?链接器是如何处理这种情况的?

这里的情况类似,幸运的是,它并没有一开始就一团糟。的确,真正的问题在于IDE配置,如果您签出旧版本,则需要指向第三方组件的正确版本。我听说的唯一解决方案是对不同的产品发布配置使用不同的注册表分支

这些组件保存在一个单独的目录结构中,并尽可能在目录名中使用版本号。这使得签出旧版本和让构建脚本指向正确版本变得更容易

多年来,我们一直使用ApacheAnt作为主要的构建工具,它确实完成了我们需要的一切,包括单元测试调用和Innosetup脚本生成

编译包只在可执行文件随BPLs一起提供时才有必要,否则在构建服务器上就不需要编译包

在构建服务器上也不需要在IDE中安装组件。

我们已经使用简单的命令文件设置了日常构建。
  • 每个项目(.dpr)都有一个关联的Build.cmd文件
  • 所有Build.cmd文件都是从主BuildServerRun.cmd文件调用的
  • BuildServerRun.cmd文件负责
  • 正在删除buildserver上的整个源代码树
  • 从我们的源代码管理存储库获取最新版本
  • 调用每个Build.cmd并将输出管道化到一个文件
  • 将结果邮寄给所有开发人员
  • 外部组件的所有路径都在dcc32.cfg文件中配置
    Build.cmd的示例。 注意:我们有一个编译到bin\dcu、exe到bin的策略,因此有-N,-E指令

    @echo on
    dcc32speed -B -Q -W -H -Nbin\dcu -Ebin BpABA.dpr
    @echo off
    
    截取的BuildServerRun.cmd示例
    我的回答比利文的回答更笼统,利文的回答是特尔斐特有的。我在提出问题后不久写了这篇文章,但在提交之前,我去找了一位同事;)

    我拒绝在我们的主Windows构建代理上安装任何IDE。听起来像是噩梦。MSBuild引擎可以很好地处理所有生成场景,除了.NET之外,您只需要安装Windows SDK。或者你可以用NAnt甚至CMake,随便什么。只是不要安装IDE。在构建服务器上并不好玩

    现在您已将其标记为Delphi。我不知道它在那里工作得有多好,但正如Lieven所写,Delphi附带了一个命令行编译器。我只是没有任何与第三方组件一起工作的经验,但我认为Delphi在最新版本中支持MSBuild

    我也不确定将第三方组件包含到版本控制中是否是一件好事,因为它需要占用空间-尽管您也可以将它们放在其他地方,并将它们作为外部组件包含,这使得它更小,但也带来了一个问题,即升级一个应用程序的组件将升级所有应用程序的组件-因此,您最好进行良好的集成测试。但这正是构建服务器的关键所在

    除此之外,签出并拥有构建应用程序所需的所有组件总是一件好事。如果组件制作良好,则无需将其安装到IDE中。根据它们是什么组件,在许多情况下甚至不需要在开发人员机器上安装它们。例如,当您添加对许多.NET组件的引用时,它们在设计器中可用。授权通常只不过是“将许可文件放入同一目录”。至少应该是这样。如果这不是Delphi今天的工作方式,那很可能是Delphi即将退出的原因之一。除了Borland/Inprise/DevCo/Codegear/Embarcadero的麻烦之外。

    您可以使用该工具

    它允许通过定义清单文件以简单的方式构建项目。 它还允许处理依赖项—您可以将第三方组件包装在owlyci包中,并将它们标记为主项目的依赖项


    还有一个问题,如何在Jenkins CI系统中使用它。

    +1。使用这种方法,完全可以不在构建服务器上安装IDE,只安装dcc32和所有其他必要的命令行工具、支持文件和DLL。整个环境可以是它自己的SVN存储库,使新构建服务器的设置变得轻而易举。我不使用Delphi,但我希望他们能让持续集成变得更容易。+1用于build.cmd,这降低了发行版IDE配置不一致的风险。我们从build.cmd调用一个中心构建脚本,因此所有标准编译器开关都可以在一点上进行配置。我同意,与Java和.Net相比,Delphi中的组件版本管理并不容易。现在使用Delphi2009,我们甚至必须在打开需要不同安装包的项目之前重新启动IDE。这在Delphi7中不是必需的。当两个包包含对同一组件类的引用时,卸载已安装的包库似乎出现故障。但是Delphi 2009不支持MSBuild吗?你试过建造吗
    @echo on
    dcc32speed -B -Q -W -H -Nbin\dcu -Ebin BpABA.dpr
    @echo off
    
    SET %Drive%=E:
    
    :BuildServer
    REM *************************************************
    REM     Clear files
    REM *************************************************
    ECHO. > "%Temp%\BuildLieven.txt"
    ECHO. > "%Temp%\TestRunLieven.txt"
    
    REM *************************************************
    REM     Set start time
    REM *************************************************
    echo | TIME | FIND "Huidige tijd" > "%Temp%\ResultLieven.txt"
    
    REM *************************************************
    REM     Get latest versions
    REM *************************************************
    IF %LatestVersion%==1 CALL %Drive%\buildserver\latestversion.cmd
    ECHO "Latest versions opgehaald" >> "%Temp%\ResultLieven.txt"
    
    REM *************************************************
    REM     Build projects
    REM *************************************************
    CD %Drive%\Projects\
    
    ECHO ***************************************************************** >> "%Temp%\BuildLieven.txt"
    ECHO BpABA >> "%Temp%\BuildLieven.txt"
    ECHO ***************************************************************** >> "%Temp%\BuildLieven.txt"
    CD %Drive%\Projects\BPABA\production
    ECHO Building BPABA\production
    CALL Build.cmd >> "%Temp%\BuildLieven.txt"
    CD %Drive%\Projects\BPABA\test
    ECHO Building BPABA\test
    CALL Build.cmd >> "%Temp%\BuildLieven.txt"
    CD %Drive%\Projects\BPABA\test\dunit
    ECHO Building BPABA\test\dunit
    CALL Build.cmd >> "%Temp%\BuildLieven.txt"
    ECHO BPABATests >> "%Temp%\TestRunLieven.txt"
    ECHO Running BPABATests
    CALL bin\BPABATests >> "%Temp%\TestRunLieven.txt"
    CD %Drive%\Projects
    ECHO. >> "%Temp%\BuildLieven.txt"
    ECHO. >> "%Temp%\BuildLieven.txt"
    ECHO. >> "%Temp%\BuildLieven.txt"
    
    REM *****************************************************************
    REM     Gather (Fatal)Errors/Hints/Warnings & Failures
    REM *****************************************************************
    ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
    ECHO (Fatal)Errors/Hints/Warnings en Failures >> "%Temp%\ResultLieven.txt"
    ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
    ECHO Fatal errors during build >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\BuildLieven.txt" | FIND /c "Fatal:" >> "%Temp%\ResultLieven.txt"
    
    
    ECHO Errors during build >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\BuildLieven.txt" | FIND /c "Error:" >> "%Temp%\ResultLieven.txt"
    
    ECHO Warnings during build >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\BuildLieven.txt" | FIND /c "Warning:" >> "%Temp%\ResultLieven.txt"
    
    ECHO Hints during build >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\BuildLieven.txt" | FIND /c "Hint:" >> "%Temp%\ResultLieven.txt"
    
    ECHO Failures during test >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\TestRunLieven.txt" | FIND /c "Failures:" >> "%Temp%\ResultLieven.txt"
    ECHO. >> "%Temp%\ResultLieven.txt"
    
    ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
    ECHO Controle #Projecten = #Compiles >> "%Temp%\ResultLieven.txt"
    ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
    ECHO #Projecten >> "%Temp%\ResultLieven.txt"
    TYPE "%Drive%\buildserver\buildserverrun.cmd" | FIND /i "cmd >> " | FIND /i "Lieven" | FIND /i /v /c "FIND /i /v /c" >> "%Temp%\ResultLieven.txt"
    ECHO #Compiles >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\buildLieven.txt" | FIND /i /c "dcc32" >> "%Temp%\ResultLieven.txt"
    ECHO #Tests expected to run >> "%Temp%\ResultLieven.txt"
    TYPE "%Drive%\buildserver\buildserverrun.cmd" | FIND /i "TestRunLieven" | FIND /i "CALL" | FIND /i /v /c "FIND /i /v /c" >> "%Temp%\ResultLieven.txt"
    ECHO #Tests actually run >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\TestRunLieven.txt" | FIND /i /c "DUnit / Testing" >> "%Temp%\ResultLieven.txt"
    ECHO. >> "%Temp%\ResultLieven.txt"
    ECHO. >> "%Temp%\ResultLieven.txt"
    
    ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
    ECHO Detail (Fatal)Errors/Hints/Warnings en Failures >> "%Temp%\ResultLieven.txt"
    ECHO ***************************************************************** >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\BuildLieven.txt" | FIND "Fatal:" >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\BuildLieven.txt" | FIND "Error:" >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\BuildLieven.txt" | FIND "Warning:" >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\BuildLieven.txt" | FIND "Hint:" >> "%Temp%\ResultLieven.txt"
    TYPE "%Temp%\TestRunLieven.txt" | FIND "Failures:" >> "%Temp%\ResultLieven.txt"
    
    REM *************************************************
    REM     Set stop time
    REM *************************************************
    ECHO | TIME | FIND "Huidige tijd" >> "%Temp%\ResultLieven.txt"
    
    REM *************************************************
    REM     Send results
    REM *************************************************
    CALL %drive%\buildserver\Blat.cmd