How to modify/replace option set file when buildin

2019-06-25 04:18发布

问题:

I build packages from a batch file using commands like:

msbuild ..\lib\Package.dproj /target:Build /p:config=%1

The packages' settings are dependent on an option set:

<Import Project="..\optionsets\COND_Defined.optset" Condition="'$(Base)'!='' And Exists('..\optionsets\COND_Defined.optset')"/>

This option set defines a conditional symbol many of my packages depend on. The file looks like this:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <DCC_Define>CONDITION;$(DCC_Define)</DCC_Define>
    </PropertyGroup>
    <ProjectExtensions>
        <Borland.Personality>Delphi.Personality.12</Borland.Personality>
        <Borland.ProjectType>OptionSet</Borland.ProjectType>
        <BorlandProject>
            <Delphi.Personality/>
        </BorlandProject>
        <ProjectFileVersion>12</ProjectFileVersion>
    </ProjectExtensions>
</Project>

Now I need two builds: one with the condition defined and one without. My attack vector would be the option set file. I have some ideas on what to do:

  • write a program which modifies the option set file, run this before batch build
  • fiddle with the project files and modify the option set path to contain an environment variable, then have different option sets in different locations

But before starting to reinvent the wheel I'd like to ask how you would tackle this task? Maybe there are already means meant to support such a case (like certain command line switches, things I could configure in Delphi or batch file magic).

回答1:

The way I approach this is to define multiple build configurations and then select the appropriate one at build time with /p:config=XXX. The works nicely in the IDE too because you can just double click the build config in the project manager to activate it.

I personally use inheritance of build configurations when I do this so that I don't have to repeat myself. For example I have a build configuration named Debug DCUs that inherits from the Debug configuration and simply changes the Debug DCUs option to True.

To help explain what I mean, here is what the build configuration tree looks like in my project:

The Debug DCUs configuration is effected by means of this option set:

<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
    <PropertyGroup>
        <DCC_DebugDCUs>true</DCC_DebugDCUs>
    </PropertyGroup>
    <ProjectExtensions>
        <Borland.Personality>Delphi.Personality.12</Borland.Personality>
        <Borland.ProjectType>OptionSet</Borland.ProjectType>
        <BorlandProject>
            <Delphi.Personality/>
        </BorlandProject>
        <ProjectFileVersion>12</ProjectFileVersion>
    </ProjectExtensions>
</Project>

Now, I am sure that you could do this by using /p:DCC_Define=XXX but I think it is cleaner to use the build configurations so that you can be sure that what you get it the IDE is the same as what you get from the command line builds.

I would not recommend either approach in your bullet point list. Those approaches look exceedingly brittle to me.



回答2:

One workaround is to temporarily rename the .optset file; this effectively disables it since the referenced file cannot be found. You can do it from your batch file before calling msbuild. This only works for option sets used as reference - as in your case.

Another option is to manually insert an <Import> directive in the .dproj file:

<Import Condition="Exists('$(OptSet)')" Project="$(OptSet)"/>

You can then set the OptSet property from the command line which will import the option set:

msbuild /t:Build /p:Config=Release /p:OptSet=myoptset.optset myproject.dproj

Without setting the OptSet property the option set will not be imported:

msbuild /t:Build /p:Config=Release myproject.dproj