Wednesday, August 20, 2008

Delphi 2007: Out of Sync problem in .DPROJ

Background

Delphi project file consist of only one file (.dpk) before Delphi 2006.  Beginning of Delphi 2006, MSBUILD (similar to ANT) is used as project build tool.  Since then, Delphi 2006 project file consist of 2 files: .DPROJ and .DPK.  The out of sync issue between .DPK and .DPROJ cause a lot of problems when working in version control environment.

Motivation

The .DPROJ is not perfect due to the XML wasn't tidy up nicely.  There are some problems with .dproj design:

  1. We always confuse when compare local and remote copy of .DPROJ if only none or minor changes has done.
  2. RC file wasn't handle well in .DPROJ
  3. The folders and compilation parameters stored in .DPROJ will change each time a .DPROJ file was saved even no changes has made.
  4. If the changes made on .DPK file, it is hardly get reflected in .DPROJ file and thus cause confusion when comparing.

Consequences

A .DPROJ that has problems may cause:

  1. Compilation errors
  2. .RC file will not compile if it is missing in .DPROJ file
  3. Delphi IDE Project Manager show unwanted entries
  4. .pas unit that has removed but still show in .DPROJ

Solution

You may always follow the steps to re-tidy a .DPROJ that you think it has problems:

  1. Close project in Delphi IDE editor that open the .DPROJ file
  2. Use any text editor (Notepad or Notepad++) to the .DPROJ file:

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      ...
      <ItemGroup>
        <DelphiCompile Include="SQL.Office.GUI.dpk">
          <MainSource>MainSource</MainSource>
        </DelphiCompile>
        <DCCReference Include="..\..\core\source\FormClass.Catalog.pas" />
        <DCCReference Include="..\..\core\source\FormClass.Export.pas" />
        <DCCReference Include="..\source\Common.GUI.Reg.pas" />
        <DCCReference Include="..\source\Profile.EF.pas">
          <Form>Profile_EF</Form>
        </DCCReference>
        <DCCReference Include="cxEditorsD11.dcp" />
        <DCCReference Include="cxExtEditorsD11.dcp" />
        <DCCReference Include="cxLibraryD11.dcp" />
        <DCCReference Include="cxPageControlD11.dcp" />
        <DCCReference Include="oobase.dcp" />
        <DCCReference Include="vcl.dcp" />
      </ItemGroup>
    </Project>

  3. The above .DPROJ file has some missing entries
  4. Remove all DCCReference item:

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      ...
      <ItemGroup>
        <DelphiCompile Include="SQL.Office.GUI.dpk">
          <MainSource>MainSource</MainSource>
        </DelphiCompile>
        <DCCReference Include="..\..\core\source\FormClass.Catalog.pas" />
        <DCCReference Include="..\..\core\source\FormClass.Export.pas" />
        <DCCReference Include="..\source\Common.GUI.Reg.pas" />
        <DCCReference Include="..\source\Profile.EF.pas">
          <Form>Profile_EF</Form>
        </DCCReference>
        <DCCReference Include="cxEditorsD11.dcp" />
        <DCCReference Include="cxExtEditorsD11.dcp" />
        <DCCReference Include="cxLibraryD11.dcp" />
        <DCCReference Include="cxPageControlD11.dcp" />
        <DCCReference Include="oobase.dcp" />
        <DCCReference Include="vcl.dcp" />
      </ItemGroup>
    </Project>

  5. Open the .DPROJ project in Delphi IDE
  6. Open the corresponding .DPK file in Delphi IDE editor (Project | View Source)
  7. Make the .DPK file become modified (e.g.: add a space character and remove the space character)
  8. Save the project
  9. If you use compare your local .DPROJ copy with CVS copy, you will see all missing or weird entries has recovered:

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      ...
      <ItemGroup>
        <DelphiCompile Include="SQL.Office.GUI.dpk">
          <MainSource>MainSource</MainSource>
        </DelphiCompile>
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\cxEditorsD11.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\cxExtEditorsD11.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\cxLibraryD11.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\cxPageControlD11.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\oobase.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\oobasevcl.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\oodb.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\vcl.dcp" />
        <DCCReference Include="..\..\core\source\FormID.Catalog.pas" />
        <DCCReference Include="..\..\core\source\FormID.Export.pas" />
        <DCCReference Include="..\source\Common.GUI.Reg.pas" />
        <DCCReference Include="..\source\Profile.EF.pas">
          <Form>Profile_EF</Form>
        </DCCReference>
      </ItemGroup>
    </Project>

  10. If the project contain any .RC entry, you may now drag the .RC files into the Project Manager and save it
  11. Now the content of .DPROJ should be fine for check in:

    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      ...
      <ItemGroup>
        <DelphiCompile Include="SQL.Office.GUI.dpk">
          <MainSource>MainSource</MainSource>
        </DelphiCompile>
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\cxEditorsD11.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\cxExtEditorsD11.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\cxLibraryD11.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\cxPageControlD11.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\oobase.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\oobasevcl.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\oodb.dcp" />
        <DCCReference Include="..\..\..\venus\account\source\stock.1\project\vcl.dcp" />
        <DCCReference Include="..\..\core\source\FormID.Catalog.pas" />
        <DCCReference Include="..\..\core\source\FormID.Export.pas" />
        <DCCReference Include="..\source\Common.GUI.Reg.pas" />
        <DCCReference Include="..\source\Profile.EF.pas">
          <Form>Profile_EF</Form>
        </DCCReference>
        <RcCompile Include="rc\library.rc">
          <Form>library.res</Form>
        </RcCompile>
      </ItemGroup>
    </Project>
  12. You may now check in .DPROJ file into Version Control service.
  13. You may encounter a situation that no changes has made to the project but remote copy shows lot of changes.  In most situation, it is only the changes to folders in .DCP entries.  You may ignore this changes and revert your local copy of the .DPROJ file from Version Control service.
    <Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
      ...
      <ItemGroup>
        <DelphiCompile Include="SQL.Office.GUI.dpk">
          <MainSource>MainSource</MainSource>
        </DelphiCompile>
        <DCCReference Include="$(SystemRoot)\system32\cxEditorsD11.dcp" />
        <DCCReference Include="$(SystemRoot)\system32\cxExtEditorsD11.dcp" />
        <DCCReference Include="$(SystemRoot)\system32\cxLibraryD11.dcp" />
        <DCCReference Include="$(SystemRoot)\system32\cxPageControlD11.dcp" />
        <DCCReference Include="$(SystemRoot)\system32\oobase.dcp" />
        <DCCReference Include="$(SystemRoot)\system32\oobasevcl.dcp" />
        <DCCReference Include="$(SystemRoot)\system32\oodb.dcp" />
        <DCCReference Include="$(SystemRoot)\system32\vcl.dcp" />
        <DCCReference Include="..\..\core\source\FormID.Catalog.pas" />
        <DCCReference Include="..\..\core\source\FormID.Export.pas" />
        <DCCReference Include="..\source\Common.GUI.Reg.pas" />
        <DCCReference Include="..\source\Profile.EF.pas">
          <Form>Profile_EF</Form>
        </DCCReference>
        <RcCompile Include="rc\library.rc">
          <Form>library.res</Form>
        </RcCompile>
      </ItemGroup>
    </Project>