2015-02-20 18 views
9

Ich versuche, diesen Compiler-Fehler zu beheben, nur in Debug Konfiguration auftreten, und nur in dem Fall, im Folgenden beschrieben:Verwalten von sehr großem Codebases in Delphi eine Bibliothek von Debug und regelmäßigem DCU mit Ich baute mich

[dcc32 Fatal Error] MyIndyTCPChannel.pas(22): F2051 Unit IdIOHandlerSocket was compiled with a different version of IdGlobal.IdDisposeAndNil 

Ich arbeite an einer sehr großen Delphi-Codebase mit 2,5 Millionen Zeilen hausinternem Code und 3 Millionen Zeilen an Komponentencode, die mehrere große kommerzielle Delphi-Komponenten-Suites (Developer Express, TeeChart und andere) und eine große Anzahl enthält von Open-Source-Delphi-Komponenten sowie eine ziemlich große selbst entwickelte Reihe von Komponenten, mit 252 Paketen, von denen etwa 140 Designtime + Laufzeit oder Designtime, und die anderen sind Laufzeit-Pakete (die auch geladen sind, d nt der IDE zur Laufzeit, durch DLL-Abhängigkeiten in ihrem zugehörigen Designtime-Paket).

Unser Hauptbibliothekspfad wurde optimiert, um klein zu sein, und er enthält die Pfade, mit denen Delphi standardmäßig ausgeliefert wird, plus drei weitere, die wir hinzugefügt haben, der primäre ist ein einzelner Ordner "OurCompanyLibraryDCU", der enthält darunter Ordner für die beiden Plattformen und zwei Konfigurationen, die wir verwenden:

c:\dev\OurCompanyLibraryDCU\Win32\Release 
c:\dev\OurCompanyLibraryDCU\Win32\Debug 
c:\dev\OurCompanyLibraryDCU\Win64\Release 
c:\dev\OurCompanyLibraryDCU\Win32\Debug 

Jede der oben genannten Ordner enthält den Satz von BPL, DCP und DCU-Dateien in einem einzigen Ordner, für diese Plattform/config Kombination.

Ein Makro wie Folgenden wird in den Projektoptionen verwendet, so können wir Plattform ändern, und Config und haben die Verzeichnisse korrekt aufgelöst: $(OURCOMPANYLIBRARYDCU)\$(Platform)\$(Config)

OURCOMPANYLIBRARYDCU ist eine Umgebungsvariable

und $(X) ist die Syntax zum Erweitern einer Umgebungsvariablen im Kontext der Delphi-IDE.

Ich versuche, das wichtigste und größte VCL-Anwendungsprojekt (nennen wir es BigApp.dproj) zu erstellen, so dass das Projektsuchverzeichnis nur unsere APPLICATION-Quellordner enthält und nicht den Projektsuchpfad benötigt, um all unsere zu enthalten Komponente der dritten Komponente LIBRARY-Quellcode. Dazu müssen wir eine Verbindung mit den Debug-DCUs herstellen oder DCUs freigeben.

Bisher haben wir alles funktioniert, außer für den Fall, dass Sie sowohl Debug und Release DCUs zur Verfügung haben. Die Release-DCUs befinden sich im Bibliothekspfad und die Debug-DCUs befinden sich in den IDE-Einstellungen im Debug DCU-Pfad. Konfrontiert mit der Wahl zwischen diesen beiden Bibliotheken, Delphi Linker scheint zu scheitern, wenn beide Gruppen von DCUs existieren, mit Fehlern in diesem Formular, wenn ich Build klicke, und die Build Configuration auf Release gesetzt ist, bekomme ich F2051 Fehler. Der normale Grund für einen F2051-Fehler besteht darin, dass mehrere inkompatible binäre DCUs existieren und beide zugänglich sind und der Linker es nicht schafft, alles zu arbeiten. Wenn Sie sowohl Debug- als auch Release-DCUs im Bibliothekspfad haben möchten, dachte ich, dass dies nicht der Fall ist, da der Linker die Debugging- oder Release-DCUs für Sie auswählt.

Wenn ich die Debug-DCUs nicht erstellen, tritt das obige Problem nicht auf. Ich vermute, dass meine Debug-DCUs subtil "ungültig" sind oder dass der Debug-DCU-Selektionsalgorithmus in Delphi nicht funktioniert, aber keine Ahnung warum oder wie man das beheben kann.

Mehrteiliger-Frage:

A. Ist für jede Plattform/config Kombination einen einzelnen Ordner mit, mit dem DCU, BPL und DCP in einem einzigen Ordner, und dann zu dem IDE-Bibliothek Pfad bekannt Probleme verursachen? Benötige ich drei Unterordner, so dass insgesamt 12 Ordner für jede Plattform + Config + Dateityp zur Verfügung stehen, oder kann ich sie nach Plattform + Konfig zusammenhalten?

B. Ist es in einer Paketkompilierungssituation in Ordnung, wenn der IDE-Bibliothekspfad den Ordner OurCompanyLibraryDCU enthält und dieser Ordner außerdem als DCP-Ausgabeverzeichnis, Paketausgabeverzeichnis und Einheitenausgabeverzeichnis konfiguriert ist? Meine Sorge ist, dass, wenn Eingabeordner und Ausgabeordner identisch sind, der Fall auftritt, dass der Compiler keine Einheit aus der .pas-Quelle neu erstellen kann und einfach die DCU der vorherigen Kompilierung verknüpft.

enter image description here

C. Wenn ich über dieses Unrecht werde, wie stattdessen werde ich verhindern, dass die mehr als 2,5 Millionen Zeilen Code-Komponenten-Bibliothek von von der Quelle jedes Mal kompiliert wurde ich meine BigApp, sondern nur Link bauen sie über DCU, und immer noch die Debug-und Release-Dcus funktionieren ordnungsgemäß?

D. Ich kann den ursprünglichen Fehler erhalten, wenn ich in den Ordner Win32 \ Debug gehe und IdGlobal.dcu lösche. Dies deutet darauf hin, dass meine Paketkompilierung (für die Debug-Konfiguration) ein INVALID IdGlobal.dcu erzeugt. Ist das überhaupt möglich? Kann delphi automatisch verstümmelte DCUs ausgeben?

Hinweise: Ich verwende keine Runtime-Pakete und kann sie nicht verwenden, um Probleme mit der Anwendungsgröße zu beheben.

Update: Das erste, was ich hier hätte tun sollen, ist zu überprüfen, dass ZERO zusätzliche DCU-Dateien überall auf meiner Festplatte sind, ÜBERALL. Das ist der Standard F2051 Fehlerhinweis. Ich werde diese Frage aktualisieren, nachdem ich mich darum gekümmert habe. Es scheint möglich, dass Delphi selbst eine DCU von einem Ort zu einem anderen COPY kopiert, oder dass ein gefälschter DCU, der NICHT im CURRENT-Suchpfad ist, sich möglicherweise im Suchpfad eines anderen Projekts befunden hat. Eine Art Bucket-Brigade von schlechten DCU-Kopien kann auftreten. Ich werde die Frage aktualisieren, sobald ich sicher bin, welche Art von schlechten DCU-Generationen oder Kopien auftreten.

Update 2: Ich habe jetzt garantiert, dass keine zusätzlichen Kopien von IdGlobal.dcu existieren vor dem Aufbau, und das Problem reproduziert immer noch. Die Frage stellt sich dann auf die Compiler-Optionen, die beim Erstellen von IdGlobal.dcu verwendet werden, Versionen der Compileroptionen, die beim Erstellen von BigApp.dproj in Debugbuild verwendet werden.

Update 3: Obwohl alle meine Paketkompilierungen scheinbar ohne Fehler abgeschlossen werden, scheint es, dass sie keinen korrekten Bibliothekssuchpfad verwendeten, während die DCC32.exe oder MSBUILD.exe zum Erstellen der Pakete gestartet wurde. Dieses Problem mit dem Bibliothekspfad-Inkonsistenz scheint das Kernproblem zu sein, dank Sir Rufo, der darauf hingewiesen hat.

+8

gezeigt Ich denke, es gibt einige Debug-Einheiten zusammengestellt mit "Use Debug-DCU" gesetzt und andere sind nicht. Wenn gesetzt, verwendet der Compiler die DCU-Dateien aus dem 'Debug-DCU-Path'. So, jetzt haben Sie einige mit der dritten Partei Debug-DCU kompiliert und einige sind nicht. –

+0

Warum bist du so glücklich? Das habe ich nie verstanden. Warum nicht den Compiler benutzen? –

+0

Da bds.exe IDE verwendet einen 32-Bit-Compiler und es verbraucht fast 2 GB Speicher. Es ist nicht große Adresse bewusst, und es ist nicht genug Speicher. Ungefähr 800 MB davon werden durch den Ansatz erzeugt, ALLES von der Quelle zu erstellen, und der Rest wird vom Debugger verbraucht, wenn er die Symbole lädt. –

Antwort

1

Jetzt verstehe ich eine Quelle für dieses Problem. Bitte rufe Sir Rufo auf, da er mich an die Lösung erinnert.

Es ist dies: Ich habe DCC32.exe aufgerufen, um Pakete zu kompilieren (mit .dpk, aber keine .dproj-Datei, und nicht Msbuild zum Kompilieren dieser Pakete aufrufen). Als ich diese erstellt habe, habe ich den Debug-DCU-Pfad nicht in den Kopf des Bibliothekspfades eingefügt, der über die Parameter -I an DCC32.exe übergeben wurde.

Sobald die DCC32.exe Paketzusammenstellung Bibliothek Suchpfad die Debug DCU-Ordner FIRST hat, funktioniert es.

Wenn jemand an einem solchen Paketsystem interessiert ist, plane ich, dieses Paket-Build-System zu öffnen, im Rahmen eines Relaunches des ursprünglich von Juancarlo Anez gebauten WANT-Projekts, das ich wahrscheinlich unter neuem Namen nennen werde. Ich werde diese Antwort aktualisieren, sobald eine funktionierende Demo eines Komponenten-Build-Systems verfügbar ist.

Ein kurzer Überblick über ein funktionsfähiges System die Anforderungen, die ich in meiner Frage gestellt erfüllen:

  1. Sie eine Datei benötigen (könnte xml, ini, JSON-Datei), dass auf eine Liste von Paketen definiert bauen.

  2. Sie müssen auf jedem dieser MSBUILD oder DCC32.exe aufrufen. Du könntest deinen eigenen Code schreiben, oder du könntest meinen benutzen, den ich öffnen werde, wenn ich kann.

  3. Sie müssen die Debug-DCU-DPROJ als erste Elemente in den Bibliothekspfad einfügen, NUR wenn die Debug-Element-Builds aufgerufen werden.

  4. Sie möchten das Makro $(OURCOMPANYLIBRARYDCU)\$(Platform)\$(Config) in Ihren Projektsuchpfaden und Bibliothekspfaden verwenden.

  5. In Ihrer Delphi-IDE möchten Sie $(OURCOMPANYLIBRARYDCU)\$(Platform)\Release als Pfad innerhalb des Bibliothekspfads fest codieren.

  6. In Ihrer Delphi-IDE möchten Sie $(OURCOMPANYLIBRARYDCU)\$(Platform)\Debug als Pfad innerhalb des Debug-DCU-Pfads fest codieren.

+0

Es gab eine ähnliche Frage, die auf die Pfade einige Tage vor dem http://stackoverflow.com/questions/28425456/what-project-options-to-use-for-open-source-delphi-packages/28429240#28429240 –

+0

dieses Optionset abzielte Antwort könnte sehr nützlich sein! Danke, –

8

Vielleicht kann ich etwas Licht auf der Reihenfolge der Such pathes den Compiler präsentiert Schuppen, die deutlich machen sollten, warum das Problem in erster Linie passiert und kann (zumindest in Ihrer Situation) geheilt wird durch die Zugabe von Debuggen Sie den DCU-Pfad an diesem bestimmten Ort. All diese Beobachtungen wurden mit XE7 gemacht.

Es gibt mehrere Orte in der IDE, wo Sie suchen pathes angeben:

  1. Bibliothekspfad (Delphi-Optionen - Library)
  2. Übersetzt Bibliothekspfad (Delphi-Optionen - Library- übersetzt) ​​
  3. Debug DCU Pfad (Delphi-Optionen - Bibliothek)
  4. übersetzt Debug DC U Pfad (Delphi-Optionen - Bibliothek-Übersetzt) ​​
  5. Suchpfad (über Projektoptionen)

Wenn die Bibliothek Sprache auf Englisch eingestellt wird, werden diese Pfade an den Compiler in der 5 angegebenen Reihenfolge , 1 oder 3,5,1, abhängig von der Einstellung Verwenden Sie debug .dcus. Das ist schon etwas komisch, da der debug-dcu-Pfad Vorrang vor dem Projekt-Suchpfad hat.

So f.i. Damit der Compiler unsere eigenen dcu-Dateien einer neueren Indy-Version findet, müssen wir die entsprechenden Pfade vor den Pfaden unter 1 und 3 platzieren.

Jetzt wird es kompliziert, wenn die Library-Sprache anders eingestellt ist Englisch. In diesem Fall kommen die übersetzten Pfade ins Spiel, was in der Reihenfolge 2,5,1 oder 4,3,2,5,1 resultiert, abhängig von der Einstellung Verwenden Sie debug .dcus.

Um das obige Beispiel mit einer neueren Indy-Version zu erstellen, müssen Sie auch die übersetzten Pfade optimieren.

Der Übeltäter liegt in CodeGear.Delphi.Targets, die die Pfade in dieser Reihenfolge platziert. Ich konnte diese Datei so ändern, dass die natürliche Reihenfolge der Pfade verwendet wird: 5,2,1 oder 5,4,3,2,1. Wenn jemand bestätigen kann, dass ich diese Änderungen hier zeigen darf, werde ich tun. Vielleicht kann ich nur einen Patch zur Verfügung stellen.

Update: Hier sind die Änderungen von CodeGear.Delphi.Targets von XE7 wie Mercurial

@@ -122,20 +122,19 @@ 
    <DcpFilename Condition="'$(DcpFilename)'!='' And !HasTrailingSlash('$(DcpFilename)')">$(DcpFilename)\</DcpFilename> 
    <DcpFilename Condition="'$(DcpFilename)'!=''">$(DcpFilename)$(MSBuildProjectName).dcp</DcpFilename> 

- <UnitSearchPath Condition="'$(DCC_UnitSearchPath)' != ''">$(DCC_UnitSearchPath);$(DelphiLibraryPath)</UnitSearchPath> 
- <UnitSearchPath Condition="'$(DCC_UnitSearchPath)' == ''">$(DelphiLibraryPath)</UnitSearchPath> 
- 
+ <UnitSearchPath>$(DelphiLibraryPath)</UnitSearchPath> 
    <UnitSearchPath Condition="'$(DCC_TranslatedLibraryPath)' != ''">$(DCC_TranslatedLibraryPath);$(UnitSearchPath)</UnitSearchPath> 
    <UnitSearchPath Condition="'$(DCC_DebugDCUs)'=='true' And '$(DelphiDebugDCUPath)'!=''">$(DelphiDebugDCUPath);$(UnitSearchPath)</UnitSearchPath> 
    <UnitSearchPath Condition="'$(DCC_DebugDCUs)'=='true' And '$(DCC_TranslatedDebugLibraryPath)' != ''">$(DCC_TranslatedDebugLibraryPath);$(UnitSearchPath)</UnitSearchPath> 
- 
+ <UnitSearchPath Condition="'$(DCC_UnitSearchPath)' != ''">$(DCC_UnitSearchPath);$(UnitSearchPath)</UnitSearchPath> 
+  
    <___ResourcePath Condition="'$(DCC_ResourcePath)' != ''">$(DCC_ResourcePath);$(DelphiLibraryPath)</___ResourcePath> 
    <___ResourcePath Condition="'$(DCC_ResourcePath)' == ''">$(DelphiLibraryPath)</___ResourcePath> 
+ <___ResourcePath Condition="'$(DCC_TranslatedResourcePath)' != ''">$(DCC_TranslatedResourcePath);$(___ResourcePath)</___ResourcePath> 
    <__ResourcePath Condition="'$(DCC_UnitSearchPath)' != ''">$(DCC_UnitSearchPath);$(___ResourcePath)</__ResourcePath> 
    <__ResourcePath Condition="'$(DCC_UnitSearchPath)' == ''">$(___ResourcePath)</__ResourcePath> 
    <ResourcePath Condition="'$(BRCC_OutputDir)' != ''">$(BRCC_OutputDir);$(__ResourcePath)</ResourcePath> 
    <ResourcePath Condition="'$(BRCC_OutputDir)' == ''">$(__ResourcePath)</ResourcePath> 
- <ResourcePath Condition="'$(DCC_TranslatedResourcePath)' != ''">$(DCC_TranslatedResourcePath);$(ResourcePath)</ResourcePath> 

    <NameSpace Condition="'DelphiNamespaceSearchPath'!=''">$(NameSpace);$(DelphiNamespaceSearchPath)</NameSpace> 
+2

Ich denke, dass diese Zieldatei eine Konfigurationsdatei ist, und Sie sollten in der Lage sein, ein Snippet davon anzuzeigen. Sogar ein kleiner Ausschnitt der VCL ist innerhalb der Fair Use-Gesetze, um ein oder zwei Zeilen zu zeigen. –