Monday, 16 October 2017

Project corruption bug

Long ago there was an issue with the RAD Studio IDE (Delphi and C++Builder both). It meant that when changing certain project options or switching build configurations, the (XML format) project file would get saved with an extra errant (empty) XML element in it, causing subsequent compilations to baulk, complaining about: ProjectExtensions appears multiple time in project. If you build from the command line the error looks like: [MSBuild Error] MSB4079 The <ProjectExtensions> element occurs more than once.

The extra line in the file, were you to open it in a text editor and take a look, will be rather like this:

    <ProjectExtensions />

If you peruse some of the entries in Embarcadero’s Quality Central portal, such as this, this or even this, then you’ll see that Embarcadero made some changes in XE6 that improved matters (done against Quality Central bug 109016, no longer accessible since QC went offline some while back, but in this list of XE6 fixes), but clearly has not dismissed the problem entirely. Various customers do continue to hit it, albeit not very reproducibly.

This set of affected customers does include myself. I was hitting this issue very regularly in C++Builder XE3 and this then continued (perhaps less frequently, I’m not sure) in more recent versions of the product.

I think one of the reasons the issue doesn’t get more coverage is that the IDE appears generally not to mind when the project file gets an extra ProjectExtensions element inserted. Indeed it may well be the case that the internal IDE state  is more correct than what gets written to the file so generally it will be command-line builds that fail more than IDE builds, with the errant file element often getting removed during subsequent saves of the project.

Whatever the specifics, the IDE issue is most definitely still present, but it is seems to be proving extremely tricky to get a reproducible test case to submit, as it seems to be subject to the whims of the weather, almost.

For me this is quite frustrating. I use an automated build system and it is a fairly regular occurrence that after checking in a changed project file (say after bumping the version number a bit) the build system will see the repository change, pull out the updates and set off a new build. Then shortly thereafter I’ll be notified of a build failure, and I’ll see it’s another occurrence of the broken project, which I then need to fix with a text editor and check in again.

In order to save my sanity I now use the reFind.exe command (the Regular Expression find and replace tool added in XE5) on the build server. The automated build system we use (Jenkins in our case, which I personally think is absolutely fabulous!) pulls out changed files from the version control repository, runs reFind to fix any possibly broken projects and then builds from there on it.

Here’s an example of a call to reFind, which lives in RAD Studio’s bin directory:

refind project_name.dproj /L "/P:^\s*<ProjectExtensions\s/>\s*$\r\n" "/R:"

This does a multi-line search to locate any lines that contain only an empty ProjectExtensions element (plus optional whitespace where that may be found) and replaces it with nothing, i.e. deletes it.

[ Update – 17/10/2017

It should perhaps be explicitly noted that my suggested use of reFind works quite nicely on an automated build server, where command-line builds are the order of the day. However, if you try the same trick on your development machine and the project happens to open in the IDE, well you perhaps won;t be surprised to see the IDE spot the change to the project file and immediately pop up and invite you to let it reload. That might be a bit annoying every time you run a command-line build. So apply some thought and judgement to where you use the reFind trick.

End Update ]

[ Update 2 – 17/10/2017

Just for completeness, if you just want to find out if your project has the ProjectExtensions issue you can use this grep call (grep.exe is also supplied in the RAD Studio bin directory, but its implementation of regular expressions is not quite the same as reFind’s):

grep -e "^[ \t]*<ProjectExtensions[ \t]*/>[ \t]*$" project_name.dproj

End Update ]

Some of the jobs that I have set up in Jenkins send custom emails, in addition to the normal “build failure” emails. I wrote a little command line tool that uses Blat to send emails under certain criteria, such as when a build completes with a new version number. Yes, I could have used Indy quite straightforwardly to do the same, but I just rustled up a batch file to drive Blat instead.

Anyway, I mention this as I suspect I’ll try and use it also to send an email if reFind is seen to have found an errant ProjectExtensions element in the project file. Being notified that there is an issue in the project file for me to fix as and when I decide to is preferable (IMHO) to the build breaking and forcing my hand there and then.

Of course all of this may be at odds to your own point of view. You may well consider a broken project file to warrant immediate repair, and welcome a build failure with open arms, but this is not the case in my setup. Horses for courses, and all that. I thought I’d just share the idea while I was in a sharing mood.

tl;dr – reFind is a nifty search and replace tool: check it out!