Pfadnamen bei Projekterstellung
Viele Entwickler bevorzugen für die Ausgabe von kompilierten Dateien ihre eigene Verzeichnisstruktur. Ich selbst habe jahrelang in jedem Projektordner ein Verzeichnis objs verwendet, welches noch einmal jeweils einen Unterordner für jede Konfiguration (Debug, Release, …) enthielt. Zum Löschen aller Ausgabedateien reichte in FileSearch eine Suche nach objs mit dem anschließendem Löschen aller gefundenen Ordner.
Mit dem Umstieg auf dem Mac musste ich mich aber von diesem System verabschieden. Der Grund war die stündliche automatische Sicherung mit TimeMachine. Die Ausgabedateien belegen pro Entwicklungszweig insgesamt bis zu 10 GB und ändern sich mit jedem Compilerlauf. Eine stündliche Sicherung würde auf dem Backupmedium schnell einen Engpass erzeugen. Man kann zwar Verzeichnisse von der Sicherung ausnehmen, muss diese aber genau benennen. Bei knapp 50 objs-Ordnern pro Entwicklungszweig ist das aber eher eine mühselige und fehlerträchtige Aufgabe.
Die Lösung war ein gemeinsamer Basisordner für die Ausgabedateien jedes Entwicklungszweigs auf dessen oberster Ebene. Die Ausgabe- und Zwischenverzeichnisse für jedes Projekt änderten sich so von
objs\Release_x64
auf
..\..\!IntDir\SpeedCommander\$(ProjectName)\Release_x64\
Anschließend mussten in der TimeMachine nur noch zwei !IntDir-Verzeichnisse für die Dev/Main-Entwicklungszweige als Ausnahme eingetragen werden.
Ein eher unschöner Nebeneffekt waren allerdings die relativen Bezüge in den Pfadnamen für die Ausgabedateien im Ausgabefenster. Statt
2> Bibliothek "objs\Release_x64\CxLib72.lib" und Objekt "objs\Release_x64\CxLib72.exp" werden erstellt. 2> CxLibrary.vcxproj -> D:\Visual C++\Dev\Libraries\CxLibrary\objs\Release_x64\CxLib72.dll ... 3> sqc.vcxproj -> D:\Visual C++\Dev\SpeedCommander\sqc\objs\Release_x64\sqc.exe 3> Done Adding Additional Store 3> Successfully signed: D:\Visual C++\Dev\SpeedCommander\sqc\objs\Release_x64\sqc.exe
wurde im Ausgabefenster nun
2> Bibliothek "..\..\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.lib" und Objekt "..\..\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.exp" werden erstellt. 2> CxLibrary.vcxproj -> D:\Visual C++\Dev\Libraries\CxLibrary\..\..\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.dll ... 3> sqc.vcxproj -> D:\Visual C++\Dev\SpeedCommander\sqc\..\..\!IntDir\SpeedCommander\sqc\Release_x64\sqc.exe 3> Done Adding Additional Store 3> Successfully signed: D:\Visual C++\Dev\SpeedCommander\sqc\..\..\!IntDir\SpeedCommander\sqc\Release_x64\sqc.exe
angezeigt. Aber auch nach knapp sechs Monaten konnte ich mich an diese Darstellung nicht so recht gewöhnen.
Auf der Suche nach einer Lösung bin ich auf diese Seite gestoßen, auf der die Funktion $([System.IO.Path]::GetFullPath(“)) genannt wird. In den Tiefen der MSBuild-Umgebung habe ich dann die Datei Microsoft.cpp.targets gefunden, in der die Werte für Ausgabe- und Zwischenverzeichnis validiert werden. Gleich nach der Prüfung auf den abschließenden Backslash habe ich in Zeile 34 die folgenden Zeilen eingefügt:
<PropertyGroup> <IntDir Condition="!$([System.IO.Path]::IsPathRooted('$(IntDir)'))">$([System.IO.Path]::GetFullPath('$(ProjectDir)$(IntDir)'))</IntDir> <OutDir Condition="!$([System.IO.Path]::IsPathRooted('$(OutDir)'))">$([System.IO.Path]::GetFullPath('$(ProjectDir)$(OutDir)'))</OutDir> <OutputPath>$(OutDir)</OutputPath> </PropertyGroup>
Diese sorgen dafür, dass die aus dem Projektverzeichnis und den dazu relativen Ausgabe- und Zwischenverzeichnissen zusammengesetzten Pfade keine überflüssigen Verweise mehr enthalten.
Beim nächsten Durchlauf war die Anzeige im Ausgabefenster nun bedeutend freundlicher:
2> Bibliothek "D:\Visual C++\Dev\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.lib" und Objekt "D:\Visual C++\Dev\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.exp" werden erstellt. 2> CxLibrary.vcxproj -> D:\Visual C++\Dev\!IntDir\Libraries\CxLibrary\Release_x64\CxLib72.dll ... 3> sqc.vcxproj -> D:\Visual C++\Dev\!IntDir\SpeedCommander\sqc\Release_x64\sqc.exe 3> Done Adding Additional Store 3> Successfully signed: D:\Visual C++\Dev\!IntDir\SpeedCommander\sqc\Release_x64\sqc.exe
Erwähnenswert ist vielleicht noch, dass die Funktion $([System.IO.Path]::GetFullPath(“)) auch in den Befehlszeilen für Buildereignisse verwendet werden kann. Zudem sollte man damit rechnen, dass die Änderungen in Microsoft.cpp.targets beim nächsten VS-Update überschrieben werden können und dann neu durchgeführt werden müssen.
Nachtrag vom 11.05.2015
In der Zwischenzeit hat sich gezeigt, dass das Voranstellen des Projektpfades negative Auswirkungen auf das Neuladen von Projektdateien (z.B. nach dem Zurücknehmen von Änderungen) hat. Ich habe die beiden Zeilen nun so geändert, dass das Projektverzeichnis nur vorangestellt wird, wenn der Pfadname von In/OutDir relativ und nicht absolut ist.
Lustig – das mache ich seit Jahren (etwa 2009) sehr ähnlich.
Man könnte meinen, dass Du damals vor dem gleichen Problem gestanden hast. 😉