Sunday, August 02, 2015

Setting Up a Parallel Build System

OmniThreadLibrary now supports 11 different Delphi versions (2007, 2009, 2010, XE, XE2, XE3, XE4, XE5, XE6, XE7, XE8), some with very special requirements about the supported pascal syntax (2007 and 2009 clearly standing out in that regard) so it takes quite some time to test the compilation of all demos and run unit tests on all supported editions. (And this time will only increase with the addition of support for mobile platforms and OS X. Not that I’m complaining. Sean is doing a terrific job there!)

It does not help that I don’t have all those Delphis installed on my computer. Most of them are only installed in a VM. And it takes a looooong time to start up a VM, run tests, power it down, start up next VM, and so on. And when I fix something, I have to retest it all ….

This kind of testing hurts. So in the manner of the Continuous Integration mantra, I decided to do it more often.

imageOf course, the only way to do such a painful task more often is to automate it. And to do that, I basically set up a dedicated build server, which sits in a folder on my 2TB drive and is held together with few batch files and a shoestring.

Firstly, I started up all my VMs (one by one) and copied selected parts of eac BDS installation to the big disk. In only copied bin* and lib subfolders as the command-line compiler doesn’t need anything else. (Currently, I’m running dcc32/dcc64 directly. This situation may change when I’ll have to support other platforms.)

Next I had to figure out how to set up environment and run compilation for one specific Delphi version. That looked simple enough until I ran into the infamous “F1027 Unit not found: ‘System.pas’ or binary equivalents (.dcu)”. Google was really not my friend there as all articles that I managed to find suggested to fix environment variables and paths in the IDE. Well, let me tell you – this does not work for the command-line compiler.

The correct solution was actually very simple (and thanks go to Mark Russinovich for the Procmon tool which pointed me in the right direction): You have to edit bin\dcc32.cfg (and bin\dcc64.cfg, if available) and correct paths there. For example, my XE2 dcc32.cfg was looking like this:

-aWinTypes=Windows;WinProcs=Windows;DbiProcs=BDE;DbiTypes=BDE;DbiErrs=BDE
-u"C:\Program Files\Embarcadero\RAD Studio\9.0\lib\win32\release"

“C:\Program Files\Embarcadero\…” is the BDS folder inside the VM, but I copied installation files to “D:\Delphi”, so I had to change dcc32.cfg to:

-aWinTypes=Windows;WinProcs=Windows;DbiProcs=BDE;DbiTypes=BDE;DbiErrs=BDE
-u"d:\delphi\9.0\lib\win32\release"

The second part of the solution was to change the PATH so that the correct bin folder is positioned before anything else. My batch file just changes the PATH completely and assigns it that one folder before calling the dcc32 compiler.

My build batch then just does something like this for each Delphi version:

  set path=d:\delphi\9.0\bin
  set otl_ut_root=c:\0\otl\XE2
  cd h:\razvoj\omnithreadlibrary
  start "XE2" cmd.exe /k doalltests XE2

In step one, PATH is set. Next, otl_ut_root variable is set to point to a unique folder. This variable is used in doalltests script to point to a folder where dcu and exe files are stored. This allows me to run multiple compilations in parallel and indeed start is used next to run the compilation in a new process.

(You can download this batch file from here. Doalltests script is part of the OmniThreadLibrary distribution.)

Now I can just run my batch file and I get 11 command line windows (soon to be 12) doing the compilation in parallel.

image

The CPU utilization is also quite nice.

image

The whole process finishes in few minutes so now I can definitely do it more often. It also doesn’t hurt as much anymore.

3 comments:

  1. A suggestion, as several BDE installs also check the PATH statement, I choose to follow an article around that introduce symbolic links to the directories so you don't need to spell out complete path to each bin or bpl directory by saying eg

    mklink /u c:\Program file\Embarcadero\RAD Studio RADstud

    Then all files could be
    C:\RADstud\15.0\bin64 etc etc

    ReplyDelete
  2. Nice. Good old-fashioned batch files still ver yuseful for putting stuff like this together.

    ReplyDelete
  3. Anonymous15:03

    You could add a RED color if build fails:

    if not exist %~dp0bin\test\%ProjectTests%.exe goto buildfailed
    :buildfailed
    color 0c
    echo Build failed. Check error log in bin\last-build-log.txt

    https://github.com/frantic/delphi-tdd-example/blob/master/build.cmd

    ReplyDelete