delphimsbuilddelphi-11-alexandria

How to make MSBuild get the DCU output path from the DProj file?


I have a script that starts msbuild and compiles a bunch of libraries. Here is the test script for one of them:

CALL _whereIsDelphi.cmd Alex
CALL "%DelphiPath%\bin\rsvars.bat"
msbuild "c:\source\TOOLS\Lib1\Lib1.dproj" /t:Build /p:DCC_BuildAllUnits=true /p:Configuration=Release /p:platform=Win32 

PS: In the end, I want to pass to the script the whole .ProjGroup file instead of just one .dropj file.


But I have a problem with the output folder. Even though the .dproj file is like this:

<PropertyGroup Condition="'$(Base)'!=''">
<DCC_BplOutput>.\$(ProductVersion)\$(Platform)\$(Config)</DCC_BplOutput>
<DCC_DcpOutput>.\$(ProductVersion)\$(Platform)\$(Config)</DCC_DcpOutput>
<DCC_DcuOutput>.\$(ProductVersion)\$(Platform)\$(Config)</DCC_DcuOutput>

the output (DCUs) goes to:

c:\source\TOOLS\Lib1\Win32\Release 

instead of the expected:

c:\source\TOOLS\Lib1\22.0\Win32\Release

Any idea how to get the output (DCUs) to be created into the correct folder?


Note that even though most libraries are using the $(ProductVersion)$(Platform)$(Config) format for output, some of them don't. This is why I cannot use hard-coded output paths. I would really like to use the $(ProductVersion) because this way I can have the libraries for Delphi 10, 11, 12 running in parallel.


Update:

Experiments:

DPROJ FILES

  1. In Project Options, I set the "unit output directory" to "Test" and the MS Build recognizes that.

  2. Then I set it to $(Config)\$(Config) and it also works.

  3. I also experimented to see if the MS Build can parse other fields from the DProj file. I experimented with the Map File (0 and 3) and it works.

Conclusion: the problem is only with the $(ProductVersion) variable, which is not recognized.

SCRIPT

  1. In my script, I tried using /p:DCC_DcuOutput="Test", and it works, but /p:DCC_DcuOutput="$(ProductVersion)\$(Platform)\$(Config)" will not work. It will not parse the first $() variable. It will create the folders exactly as that: "$(ProductVersion)".

  2. This will also not work: /p:DCC_DcuOutput="$(ProductVersion)\ Error it: Could not create output file '$\DebugForm.dcu'`

Conclusion: the problem is with all the $() variables. None is recognized.

HOWEVER, even if the script had been able to parse the $() vars, this solution will still not work with my ultimate goal: to pass to MS Build a ProjGroup file, because there is no more script involved there. The MS Build goes through the whole ProjGroup without in one go.

And I really don't want to compile via project group file and also via a script, because the two will get desynchronized at one point! Whatever change we do in the group will have to go to the script also.


Solution

  • Solution:

    I created a small Delphi project (MyParser.exe) that parses the DProj file and extracts from there the environment variables from the '<DCC_DcuOutput>$(ProductVersion)$(Platform)$(Config)</DCC_DcuOutput>' line.
    I replace those variables with real paths.
    I do the same for <DCC_ExeOutput>.

    Then, my program executes (via ShellExecuteEx) MsBuild.exe and passes all the necessary parameters, including the two paths above, to it.


    Finally, I call my program from a script like this:

    MyParser.exe "c:\Test.dproj" 22.0 Win32 Release MyParser.exe "c:\Test.dproj" 22.0 Win64 Release

    Where:
    22 = $(ProductVersion)
    Win32 = $(Platform)
    Release = $(Config)