Delphi XE2 option set nested limit? - delphi

I have a complex project group that has about 10 "final" build configurations configured in a tree, where each node has its own option set. Something like this:
Base
Release
Release Generic 1
Release Final 1
...
Release final 5
Release Generic 2
Release Final 6
...
Debug
same as release, but for debug
so, all base, Release, Release Generic X, Release Final Y have their own option set saved in files and added as reference. So you will have
base.optset
Release.optset
Release Generic 1.optset
Release Final 1.optset
..
The main differences between these option sets are various compiler defines enabling/disabling certain features that are organized in the tree mentioned above (hence the build targets and the option sets) and obviously search paths that include the needed stuff.
So each option set also contains different search paths that depend on the respective build configuration.
There are over 100 projects in the project group and most of them relate to one another on different level of configurations, so there are also a bunch of Build Groups, but this is irrelevant for the question as right now I'm trying to build the projects one at a time.
The problem is that every option set is configuring the search path. Up to and including "Release Generic 1.optset" the search path is correctly updated and used. However, the "Release Final 1" and siblings don't get the search paths introduced by "Release Final 1.optset". (I know this because I looked at the compiler messages and checked the parameters passed to dcc32) It appears like the option set is ignored.
Everything is configured with "inherit=true" in the option set.
There is nothing specific in the build configurations, nowhere. Every project uses the configuration in the IDE and option set files only.
Is this issue/limitation documented anywhere/known about? Is there a workaround? Other than applying the option set as value and not by reference.
Thanks.
later edit:
I decided to implement a pretty ugly workaround in order to get moving: basically, replicate teh configuration from "Release Generic 1.optset" into each "Release Final ?.optset"
this has the major disadvantage of having to edit 5 option set files propagating the same modification, when in need of adding something to "Release Generic 1.optset"

Finally I managed to figure out the problem. It's actually a bug in the Delphi IDE in that it messes up the imports in the dproj file.
Specifically, if an optionset is added once, it will not be maintained with the necessary import condition for the rest of the configs.
This usually happens when you add/delete a configuration, the dproj gets busted and optset files no longer get imported for all the configs.
But once your configs are stable and you no longer change them, the dproj remains stable.
I mocked up an application to validate dproj files against these issues, verifying that each config has its optset files in an import directive. I'm yet to make it auto-correct this, as I'm rather busy. But once I manage to find the time, or if there are more people affected by it and require an automatic fix, I'll try to make a release.
Until then, if you noticed the option set is not applied for a specific config, simply find the configs id in dproj (something like Cfg_10 ) and see if you can find an
<Import Condition="'$(Cfg_10)'!='' And Exists('optset file path name')" Project="optio file path name"/>
if not, then add it after the other <import calls

Related

TFS '$(BuildLocation)' macro points to wrong path on Lab Environment template

I'm having a very hard time finding any information about this. I've just created a Build-Deploy-Test build definition for one of our main projects but when the workflow runs, it reports a wrong value for the "$(BuildLocation)" macro, which breaks everything from the deployment phase onwards (the tests also try to run over this wrong path).
I know what is causing the problem, but I don't know how to fix it. The build definition we are redirecting the lab one to is configured to build the 'Release' configuration of our solutions. The drop folder is "\outputServer\drops". I expected the BuildLocation macro to then return "\\outputServer\drops\<BuildName>\<BuildNameFormat>", but the macro is returning "\\outputServer\drops\<BuildName>\<BuildNameFormat>\Release" instead.
I initially thought that this was an incompatibility between the LabDefaultTemplate.11.xaml template (which is the one I'm trying to use) and the old DefaultTemplate.xaml, which I based our custom template over. I tried updating our custom template to take the new default (DefaultTemplate.11.1.xaml) as a base, but after converting the template the problem persists.
Even after looking at the code on the DefaultTemplate.11.1, I still don't see it filter the output by configuration names at all. The only processing in there is based on the solution or project name, which is disabled by default (controlled by the 'Solution Specific Build Outputs' option under the Advanced category, on the build definition configuration).
Why is it assuming that the drop folder ends with 'Release' while the dropped outputs are not placed on this folder at all? I managed to make the deployment scripts to run fine by appending a ".." to the path, like this $(BuildLocation)\..\myScript but when the workflow tries to run the automated tests it seems to be using this same macro and obviously doesn't find the test dlls.
It would be possible to work around this by not specifying a build configuration on the 'Items to Build' element in the definition options (thus letting it choose the default ones), but specifying the configuration was a conscious decision on our part, because there are differences in the files and some configs are transformed differently when the project is built in Release mode.
I'm currently using VS2012 Update 3/TFS 2012 Update 2 it this helps any.
Update:
Ok I found where it is doing this inside the template itself. The fact that the lab workflow is very simple helped here.
Inside the Compute build location needed 'if statement', there is an assignment that seems to be doing this weird concatenation. Here is the code:
If(LabWorkflowParameters.BuildDetails.Configuration Is Nothing, BuildLocation, If(LabWorkflowParameters.BuildDetails.Configuration.IsEmpty Or (SelectedBuildDetail.Information.GetNodesByType(Microsoft.TeamFoundation.Build.Common.InformationTypes.ConfigurationSummary, True)).Count = 1, BuildLocation, If(LabWorkflowParameters.BuildDetails.Configuration.IsPlatformEmptyOrAnyCpu, BuildLocation + "\" + LabWorkflowParameters.BuildDetails.Configuration.Configuration, BuildLocation + "\" + LabWorkflowParameters.BuildDetails.Configuration.Platform + "\" + LabWorkflowParameters.BuildDetails.Configuration.Configuration)))
I'm not even sure what this is supposed to mean. This behavior seems to be a bug to me, since the build template itself (not the lab one) does NOT do this concatenation. How can the LabTemplate assume this type of thing?
Just removing the activity from the LabDefaultTemplate build process template seems to work.
I'm not sure what the meaning or purpose is of that Assign activity, but it seems to work fine for us without it.

TFS Build Copy to Versioned Folder

I'm currently looking at a TFS build server setup & I was trying to set up a process whereby I can set up a build template to build to a folder based on the version number of a .NET assembly that's part of the build (As per the assemblyinfo.cs file). I've got it building to the standard looking folder ("Release_20130502.1"), but that's not exactly useful in 4 months time when we want to find the build for the v1.1.0 release.
Basically I want to make a special build template which will create a major release, and I'd like the folders it makes to be more noticable as versions rather than timestamps. I'm also hoping to automatically label the release as that version too. I know how to copy the files & make labels, but I'm not sure how to get at the version numbers.
I'd also love if I could get this into the Build Name recorded in TFS somehow but I suspect that might be a bit optimistic.
Does anyone have any idea how to do this (Or alternatively any other technique that'll get me easily recognizable release version builds)?
Take a look at build number format property for build definitions this is used to generate the build number and in turn the build folder during build and label in sourcecontrol if its enabled, you can modify this manualy to pass desired build number. The mentioned drop folder can be manually given as well. And you can always copy the folder after build by hand.
You can use revision variable to create something that works similiar to what you want, Revision number gets incremented if there is build with same name in system
Format: Release v1.$(Rev).0 - this would give you Release v1.1.0, Release v1.2.0, ... on each build
You will have to customize build definition with custom activity for your defined goal to work without manual interaction. However with details you have provided this approach has issues - each project has its own assembly info - which one do you use, what if they are different? This should get you started.
http://www.ewaldhofman.nl/post/2010/04/20/Customize-Team-Build-2010-e28093-Part-1-Introduction.aspx
You can take a look at these may find something useful
http://tfsbuildextensions.codeplex.com/
It all comes down how often do these build take place, if its week or more then doing it by hand is perfecly valid aproach in my book.

How to use configuration option set with project "by reference"

I've spent a couple of days exploring option sets (again) in XE3. They look really clever but either they are (still) broken or its me. What I wanted to do was to create a common option set file for a bunch of projects, say CommonOptions.optset. This is easy to create and edit using the View | Configuration Manager item. In this options set file I put a set of relative search paths such as:
..\..\source1;..\..\source2;
etc. These paths are proven to work when entered into the DEBUG or BASE build configuration directly. When I use the Configuration Manager to apply this common option set as a reference, the paths do not work. If I repeat the application using 'Modify Values' it works fine. To be sure, I deleted the DPROJ (and all the .local stuff too) and let Delphi recreate the DPROJ before applying the option set file as reference again. Still no luck.
I have several libraries with 10's of DPROJ's all of different vintages so I really do need a common way of specifying compiler options, don't include version info etc.
Has anyone got this reference thing to work?
Referenced option sets are implemented as plain MSBuild imports. Therefore, all relative paths are relative to the importing project file. You can think of option sets as build configurations from which build configurations in referencing project files may inherit.

How to set default compiler options for XE2?

I am unable to figure out how to change default build/compile settings. The little default checkbox in the lower left of the project options dialog is gone. The documentation states:
The Default checkbox that appeared at the lower edge of many Project Options pages has been removed from the product. If you want to specify options as the default for multiple projects, the suggested alternative is to use option sets instead.
I'm going round and round about "Options Sets", "Configuration Manager" etc.. Is this even possible? What does "specifying options as the default for multiple projects" mean? If I have multiple projects then that means those projects and their options exists, how can I set a default value to something already set? What about new projects?
That feature really has gone and there is nothing like it any more in the product, to the very best of my knowledge. I think the best you can do is as follows:
Create a new project.
Change the project settings to whatever you want them to be.
Change anything else in the default project that you don't like, for example { Private declarations }.
Add this project to the repository.
use File | New | Customize to move this project template onto the File | New menu for easy access.
Project->Options->Target. You can set up a base configuration, and then provide different options that differ from the base for Debug and Release. You can also create custom option sets, which means that they're different from the standard Debug and Release. You can also have different configurations based on different targets (VCL app's Debug build has different options than a FMX app's Debug build, etc.)
To change the default options first starts with defining "default". You can start as low as the "base configuration" through Project->Options->Delphi Compiler, and then choosing the All Configuration target. You can refine it somewhat by altering the base configuration for the Debug and Release configurations. You can also define your own option sets, using the Save button next to the Target list.
Your specific question about "specifying options as the default for multiple projects" means is the base configuration. From there, you refine those base options to give you debug settings and release settings (which can also be saved as your initial defaults, and refined on a per-project basis).
So, for a specific answer, you can change the default by modifying the base configuration, or by getting more specific by modifying the debug or release configurations that inherit from that base, depending on what your end result needs to be and what you're trying to accomplish.

What is the different between "Make" and "Build" in context menu of project build configuration?

When I pop up context menu of a Delphi project's build configuration, I see menu items of "Make", "Build" and "Clean".
What is the different between "Make" and "Build"? It seems that both perform same task.
Build compiles all source files in the project.
Make compiles those that have changed since the last make or build.
Note that make is actually a little more complex. A unit, let us say unitA, can require re-compilation during a make even if unitA has not changed. This happens when unitA uses another unit, unitB, and the interface section of unitB has changed since the last make or build.
The documentation for Build states:
Rebuilds all files in your current
project regardless of whether they
have changed. Building is useful when
you are unsure which files have
changed, or if you have changed
project or compiler options.
The documentation for Make states:
Compiles only those files that have
changed since the last build, as well
as any files that depend on them.
Make compiles outdated modules (the ones that were changed since the last project compilation), while build (re)compiles all modules.
I would add a related information : what "Clean" do compared to "Build" and "Make". It appears to delete the "pre-compiled header" database.

Resources