Delphi versions 2007 or later include MSBuild support. This means that you can (in theory at least) use MSBuild to build your Delphi Projects. I say "in theory" because in reality your milage may vary. The MSbuild support has improved somewhat since D2007. There are still issues relating to IDE bugs and configuration inheritance (even in XE4) and some other issues with dproj files that have been "upgraded" through several versions of Delphi. Delving into the dproj file to fix issues is not for the faint of heart, the easiest way to resolve those issues is to delete the dproj and allow the Delphi IDE to create a new one.
Delphi XE2 added the ability to set the version info, before that you had to resort to patching the exe after it was built, or using your own resource file for version info and building that somehow before building the delphi project.
This is the main reason that FinalBuilder still uses the delphi command line compiler (dcc32.exe/dcc64.exe) directly. Of course, FinalBuilder works well with Continua CI too!
So, all of those issues asside, lets take a look at getting a Delphi project to build using MSBuild and Continua CI. I'm going to use XE2 in this example, and the project we will be building is an open source test framework on GitHub called DUnitX (it's a work in progress). If you are not familiar with Continua CI, then I recommend taking a look at the Tutorial on the Continua CI Wiki. I'll be skipping stuff that will be obvious if you already use Continua CI or have read through the tutorial.
First thing first, we need our delphi project in a source code repository that Continua CI can use. DUnitX is on GitHub, so I created a Git Repository on my Continua CI Configuration. Since DUnitX depends on Delphi-Mocks for it's own unit tests, I also added a repository in Continua CI for it.
Notice that I have the "Fetch Other Remote Refs" option check, this allows Continua CI to see GitHub Pull Requests (I will expand on this in a future post).
Continua CI creates a new Build Workspace folder for each build (yes, each build is a clean build). The Repository Rules are how we determine where the source code will end up in our Workspace folder. The default rules will create a folder called Source, and a folder for each repository under the Source folder. That's fine for this example so we'll stick with that.
Now that we have our source code available, let's add an MSBuild Action to our Build Stage.
On the MSBuild Action Dialog, we set the Project File to : $Source.DUnitX$\Tests\DUnitXTest_XE2.dproj
Note the $Source.DUnitX$ - this means use the Default Repository folder for the DUnitX Repository, at runtime it will evaluate to \Source\DUnitX. If you use custom Repository Rules then adjust the path accordingly.
Set the Target to Build, the Configuration to your desired config (ie, Debug or Release).
For Delphi XE2 or later, Use MSBuild 3.5, for earlier versions use MSBuild 2.0.
You can override delphi config settings, the list of settings doesn't appear to be documented anywhere I could find, however if you open :
(for XE2) C:\Program Files (x86)\Embarcadero\Rad Studio\9.0\bin\CodeGear.Delphi.Targets
in notepad you see a bunch of elements like DCC_BplOutput. These can be set on the MSBuild Action's properties tab, in our case we need to tell the compiler where to find Delphi-Mocks, so we'll add it to the search path DCC_UnitSearchPath :
Note the $$, because Continua CI use $ as the delimeter for object references, so it needs to be escaped by doubling it.
Delphi's MSBuild support relies heavily on Environment Variables, which is why it ships with a batch file (rsvars.bat) to set them in the command prompt. So we need to set those enviroment variables when invoking MSbuild.exe, we do that on the Environment Variables tab of the MSBuild Action,
Since the action actually runs on the Agent, we need to tell MSBuild where on the Agent to find delphi. That's done by referencing Agent Properties . The properties are created when the Agent runs the Property Collectors defined on your Continua CI Server. Continua CI ships out of the box with property collectors already defined for Delphi 7 to XE4.
These property collectors are run on each agent, and when the collector finds what it is looking for, it creates a property on the agent :
The Continua CI Server uses these Agent properties when working out which agents are capable of running the Stage. For some actions, this is automatic, but in this case Continua CI has no way of knowing that you need Delphi XE2 on the agent (since we're just running MSBuild), so we need to help it out by adding an Agent Requirement on our Stage :
When the Continua CI Server is searching for an Agent to run our Delphi Project on, it will only select an agent that has the Delphi.XE2.Path property.
I hope that's enough to get you started. As I said at the start of this post, the MSBuild support in Delphi is somewhat flakey, especially in earlier versions of Delphi. If you get weird things happening, try creating a new .dproj (just rename the old one, and open the dpr in the IDE) and keep your configurations simple. If after pulling your hair out for a few days you don't get anywhere, you can always use FinalBuilder!