Qt ohne Add-In, VS2012 Build Rules?

Programmiersprachen, APIs, Bibliotheken, Open Source Engines, Debugging, Quellcode Fehler und alles was mit praktischer Programmierung zu tun hat.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

An die von MSBuild fertig zusammen gesetzte Command Line kommt man mit %(Item.Command). Dokumentiert exakt nirgends im ganzen weiten Internet, gefunden durch 1 Stunde Trial & Error. Offenbar ist sich sonst niemand zu blöd, zu seinen 3 Targets-Dateien auch noch ein C#-Projekt mit eigenem CommandLineBuilder anzulegen. Ich schäume bereits jetzt vor Hass auf MSBuild.

ARGH, alles Bullshit. Die Command-Property hat VS einfach mit maximaler Dummheit aus dem vorigen Custom Build Tool in mein explizit typisiertes neues Build Tool rüberkopiert. BIN ICH DENN DER EINZIGE MIT EINEM FÜNKCHEN VERSTAND IN DIESEM UNIVERSUM?!
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Ich gebe es auf. Die IDE zeigt mir in den Command Line Pages die volle Command Line an, aber ich komme ums verrecken nicht an diesen verfluchen String. Soll ich mir das Ding jetzt per XML-"Schleife" erneut zusammensetzen oder was? Wer immer sich diesen schwammigen Schwachsinn ausgedacht hat, war ganz offensichtlich nicht ganz dicht ...
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Code: Alles auswählen

<ItemGroup Condition="'@(SelectedFiles)' != ''">
	<QtCompile
		Remove="@(QtCompile)"
		Condition="'%(Identity)' != '@(SelectedFiles)'" />
</ItemGroup>
Seriously, warum muss ich permanent auf leere Listen prüfen, wenn ich gleich im Anschluss einfach mal Listen mit Einzelelementen vergleiche? Auch ist es wohl egal, ob ich an Targets Listen oder Einzelelemente als Inputs übergebe.

Ferne ist der magische Trick für die Command Line, mit UsingTask eine nicht existente Task zu importieren, dabei meine XML-Rule-Datei als Task anzugeben, dann diese Datei wieder auf alte Switch-Syntax mit [platzhaltern] umzustellen, eine Eigenschaft CommandLineTemplate anzulegen, dort alle Switches zu wiederholen, und dann in der Targets-Datei nochmal alle Switches einzeln an die nicht existente Task zu übergeben. Ich kann Athur Dent SO SEHR nachfühlen, während ich auf die verbrannten und zerstampften Überresten meiner gevierteilten, gesechzehntelten und gewürfelten MSBuild-Kopie eindresche.

(Dabei Stünde die Command Line auch ganz ohne diesen Affentanz schon korrekt in den Property Pages der IDE (ohne Zugriffsmöglichkeit), was nur heißen kann, dass der einzig nachvollziehbare Weg mal angedacht war und beim Import alter VS2008 Build Rules gegen diesen grandiosen VS2008-ähnlichen Schwulst ausgetauscht wurde. BECAUSE ...)

MERKE: Sollte jemals einer von euch auf die Idee kommen, irgendeine ähnlich metamorphe Script-Umgebung zu konstruieren, ist das ERSTE Feature eine dynamische Introspektion, die Überblick über alle in einem gegebenen Element verfügbaren Daten gibt. Oder ihr legt einfach die Sources bei ...
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von dot »

CodingCat hat geschrieben:

Code: Alles auswählen

<ItemGroup Condition="'@(SelectedFiles)' != ''">
	<QtCompile
		Remove="@(QtCompile)"
		Condition="'%(Identity)' != '@(SelectedFiles)'" />
</ItemGroup>
Seriously, warum muss ich permanent auf leere Listen prüfen, wenn ich gleich im Anschluss einfach mal Listen mit Einzelelementen vergleiche? Auch ist es wohl egal, ob ich an Targets Listen oder Einzelelemente als Inputs übergebe.
Ich bin mir nicht ganz sicher, was genau dein Problem ist, aber ich vermute mal es liegt am automatischen Batching!?
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Neue Erkenntnisse: Die von MS und anderen ausgelieferten Build Rules enthalten haufenweise Altmüll, der gar nicht notwendig ist (d.h. die sind praktisch alle aus dem VS2008-zu-VS2010-Konverter gekommen, selbst bei MS hat offenbar kaum jemand die geringste Ahnung von MSBuild).

So müssen in den Switch-Properties der XML-Dateien gar keine [value]-Platzhalter mehr eingetragen werden, die werden nur zur Kompatibilität mit VC2008 Build Rules unterstützt. Außerdem müssen im CommandLineTemplate nicht nochmal alle Switch-Namen mit eigenem Platzhalter aufgeführt werden, in MASM.targets findet sich ein Trick names [AllOptions]. Weiterhin ist CommandLineTemplate ein festes Task-Eingabeattribute, das nicht in den Rules oder den Properties auftauchen muss, wie es das praktisch überall sonst tut. Damit lässt sich die Redundanz tatsächlich etwas eindämmen, aber um die Wiederholung ALLER Properties in der Task kommt man nicht drumrum:

Code: Alles auswählen

		<QtCompile
			Condition="'@(QtCompile)' != '' and '%(QtCompile.ExcludedFromBuild)' != 'true'" 
			CommandLineTemplate=""%(QtCompile.MOCPath)" "%(QtCompile.FullPath)" [AllOptions] [AdditionalOptions]"
			CompileOut="%(QtCompile.CompileOut)"
			Defines="%(QtCompile.Defines)"
			Include="%(QtCompile.Include)"
			AdditionalDeps="%(QtCompile.AdditionalDeps)"
			AdditionalOptions="%(QtCompile.AdditionalOptions)"
			StandardOutputImportance="High"
			StandardErrorImportance="High"
			/>
Man beachte die enorm praktischen Attribute StandardOutputImportance und StandardErrorImportance, mit denen ihr ausnahmweise sogar zu sehen bekommt, was MS Build im Verborgenen so ausheckt. Die Attribute, die ich in einem verschlossenen Schrank im Keller des Rathauses gefunden habe, weisen außerdem darauf hin, dass es sich bei diesen ominösen, von XamlTaskFactory aus XML-Rules generierten Tasks um ToolTasks handelt.

Zusammengenommen stehe ich nun hier und kann tatsächlich MOC ausführen:

Code: Alles auswählen

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

	<ItemGroup>
		<PropertyPageSchema Include="$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml" />
		<AvailableItemName Include="QtCompile">
			<Targets>_QtCompile</Targets>
		</AvailableItemName>
	</ItemGroup>

	<PropertyGroup>
		<QtCompileRulesPath>$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml</QtCompileRulesPath>
	</PropertyGroup>
	
	<UsingTask
		TaskName="QtCompile"
		TaskFactory="XamlTaskFactory"
		AssemblyName="Microsoft.Build.Tasks.v4.0">
		<Task>$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml</Task>
	</UsingTask>

	<Target Name="_QtCompile" BeforeTargets="ClCompile"
		Condition="'@(QtCompile)' != ''"
		Inputs="%(QtCompile.Identity);$(MSBuildProjectFile)"
		Outputs="%(QtCompile.CompileOut)"
		> <!--DependsOnTarget="_SelectedFiles" ERROR WHATEVER -->
		
		<ItemGroup
			Condition="'@(SelectedFiles)' != ''">
			<QtCompile
				Remove="@(QtCompile)"
				Condition="'%(Identity)' != '@(SelectedFiles)'" />
		</ItemGroup>
		
		<Message Text="Compiling: %(QtCompile.Filename)%(QtCompile.Extension) using MOC" Importance="high" />
		
		<QtCompile
			Condition="'@(QtCompile)' != '' and '%(QtCompile.ExcludedFromBuild)' != 'true'" 
			CommandLineTemplate=""%(QtCompile.MOCPath)" "%(QtCompile.FullPath)" [AllOptions] [AdditionalOptions]"
			CompileOut="%(QtCompile.CompileOut)"
			Defines="%(QtCompile.Defines)"
			Include="%(QtCompile.Include)"
			AdditionalDeps="%(QtCompile.AdditionalDeps)"
			AdditionalOptions="%(QtCompile.AdditionalOptions)"
			StandardOutputImportance="High"
			StandardErrorImportance="High"
			/>

	</Target>
	
</Project>
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Sag mal dot, du weißt nicht zufällig, wie ich an die projektweiten Standard-Metadaten (definiert in ItemDefinitionGroup) für einen bestimmten Item-Typ komme, ohne ein konkretes Item zu referenzieren? %(ClCompile.PreprocessorDefinitions) will nicht, weil ich in meiner eigenen ItemDefinitionGroup logischerweise kein konkretes ClCompile-Item referenzieren kann.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von dot »

Leider nicht, aber dafür such ich auch schon länger eine Lösung... ;)
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

File [...] is included into ClCompile and QtCompile item groups. This is not allowed for project items, which can belong to only one item group.

Array bla experssion not allowed in ItemDefinitionGroup

WTF! Die definieren eine derart aufgeblasene "Script-Sprache" mit Zillionen Möglichkeiten und ich kriege nicht mal die trivialsten Build-Steps definiert. Dazu nicht ein Fünkchen Konsistenz, nicht ein Fünkchen Dokumentation und nur Schrott in den eigenen Beispielen. Welcher Vollidiot hat sich diesen ganzen Mist ausgedacht, auf dem jetzt eine gigantische Build-Umgebung sitzt?!
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von dot »

Ok das ist ärgerlich. Anyway: Ich denk der CreateItem Task könnte helfen...
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Möglich, ich weiß allerdings gerade nicht wie. Nächster Halt:

<Message Text="@(ClCompile->Metadata('_QtCompileSrc'))" Importance="high" />
// liefert: header\Documents\AbstractDocument.h


<Message Text="(ClCompile->WithMetadataValue('_QtCompileSrc', '%(QtCompile.Identity)'))" Importance="high" />
// liefert: (ClCompile->WithMetadataValue('_QtCompileSrc', 'header\Documents\AbstractDocument.h'))


<Message Text="@(ClCompile->WithMetadataValue('_QtCompileSrc', '%(QtCompile.Identity)'))" Importance="high" />
// liefert: nix


BECAUSE FU, THATS WHY! Ich kann gar nicht glauben, dass ich mich immer noch mit diesem Schwachsinn abgebe.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Sagt mal gibt es *irgendeinen* Weg von einem Item in einer Gruppe zu einem Item in einer anderen Gruppe zu kommen?!
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Ich habe es geschafft, Items mitsamt Metadaten zu klonen (CreateItem-Task oder Item-Transformation-Syntax); nun habe ich eine Ebene von Eigenschaften. Sobald diese Eigenschaften aber rekursiv geerbte Eigenschaften mit Selbstreferenz %(PropertyName) einbinden, landen diese Indirektionen bei den Klonen in der neuen Item-Gruppe wieder einfach im Leeren. Fazit: Forget it. Gegen diesen Schrotthaufen ist selbst PHP durchdacht.

Nachtrag: Hier hat Visual Studio schlichtweg inkonsistenten Zustand: Änderungen an Property Sheets werden stillschweigend nicht gespeichert, aber in der IDE und den Property Pages (-> Command Line Preview) angezeigt als wären sie bereits aktiv.
Zuletzt geändert von CodingCat am 03.12.2012, 18:55, insgesamt 3-mal geändert.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Ich kriege überhaupt keine rekursive Evaluation, die geerbten Präprozessoreigenschaften fehlen hier immer vollständig: %(ClCompile.PreprocessorDefinitions) Wie bringe ich das Ding zu einer richtigen Evaluation?

Nachtrag: Siehe Post obendrüber.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
dot
Establishment
Beiträge: 1734
Registriert: 06.03.2004, 18:10
Echter Name: Michael Kenzel
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von dot »

Wenn du nur Items klonen willst, sollte das (glaub ich) auch gehen, indem du einfach direkt in einem Target eine ItemGroup machst:

Code: Alles auswählen

<Target>
  <ItemGroup>
    <NewType Include = "@(OldType)" />
  </ItemGroup>
</Target>
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Ja, genau das habe ich gemacht. Allerdings muss ich beim Klonen auch Metadaten zusammenfügen. Aber das ist absolut aussichtslos, ich habe Stunden damit zugebracht, alle Ecken des Internets nach Lösungen abzulaufen. MSBuild XML ist einfach extrem primitiv, nun habe ich eine Inline Task:

Code: Alles auswählen

	<UsingTask TaskName="MergeMetadata" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
		<ParameterGroup>
			<Source ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
			<SourceMetadata ParameterType="System.String" Required="true" />
			<Destination ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
			<Merged ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" />
		</ParameterGroup>
		<Task>
			<Code Type="Fragment" Language="cs">
			<![CDATA[
				List<TaskItem> newItems = new List<TaskItem>();
			
				foreach (var SrcItem in Source)
				{
					string src = SrcItem.GetMetadata(SourceMetadata);
					
					if (!String.IsNullOrEmpty(src))
						foreach (var DestItem in Destination)
							if (DestItem.ItemSpec == src)
							{
								var newItem = new TaskItem(DestItem);
								SrcItem.CopyMetadataTo(newItem);
								newItems.Add(newItem);
							}
				}
				
				Merged = newItems.ToArray();
			]]>
			</Code>
		</Task>
	</UsingTask>
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Aua aua aua. Bestehende Items einfach in neue ItemGroups einzufügen ist offenbar keine gute Idee, danach werden Well-Known-Metadata-Referenzierungen nur noch unzuverlässig je nach Außentemperatur, Wochentag und Befindlichkeit der Großmutter aufgelöst. TaskItems deshalb für die Bearbeitung in Code-Tasks kopieren, dann läuft alles wie gewünscht. Korrigierter Code ist im vorangegangenen Post nachgetragen.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Kein Scherz. Ich kann jetzt zwar per %(ItemType.PreprocessorDefinitions) die Defines ausgeben lassen, wenn ich sie aber per %(PreprocessorDefinitions) in den Default-Properties für ItemType referenziere, bleiben sie unbekannt. Ich bin mir ganz sicher, irgendwer bei MS hat HART daran gearbeitet, MS Build SO nutzlos zu machen. Schon jetzt fühle ich mich, als wäre ich einmal durch die Hölle und zurück gegangen, und es geht noch immer exakt: NICHTS.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Dieses Ding ist mir immer noch nicht klar: Die offizielle Variante funktioniert:

Code: Alles auswählen

<ItemGroup Condition="'@(SelectedFiles)' != ''">
	<QtCompile Remove="@(QtCompile)" Condition="'%(Identity)' != '@(SelectedFiles)'" />
</ItemGroup>
Batching kann es aber nicht sein, denn folgendes funktioniert nicht:

Code: Alles auswählen

<ItemGroup Condition="'@(SelectedFiles)' != ''">
	<QtCompile Remove="@(QtCompile)" Condition="'%(Identity)' != '%(SelectedFiles.Identity)'" />
</ItemGroup>
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Wahnsinn, ich habe etwas, das funktioniert. Dabei bin ich sogar darauf gestoßen, wie man an die Standardeinstellungen bestimmter (fremder) Item-Typen kommt:

Code: Alles auswählen

        ProjectInstance project;
        
        // Get project instance
        {
          const BindingFlags bindingFlags = BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
          var targetBuilderCallback = this.BuildEngine.GetType().GetField("targetBuilderCallback", bindingFlags).GetValue(this.BuildEngine);
          project = (ProjectInstance) targetBuilderCallback.GetType().GetField("projectInstance", bindingFlags).GetValue(targetBuilderCallback);
        }
        
        if (String.IsNullOrEmpty(DestinationPrefix))
          DestinationPrefix = "_";
        
        var itemDefs = project.ItemDefinitions[ItemName];
        Regex resolveExpression = new Regex("%" + Regex.Escape(DestinationPrefix) + @"\((\w*)\)");
        var evaluatedItems = new List<TaskItem>();
        
        // Resolve remote metadata references
        foreach (var destItem in Destination)
        {
          var newItem = new TaskItem(destItem);
        
          foreach (string name in newItem.MetadataNames)
          {
            string val = newItem.GetMetadata(name);
            bool valChanged = false;
            
            // Find unresolved references in destination item metadata
            if (!String.IsNullOrEmpty(val))
              foreach (Match match in resolveExpression.Matches(val))
              {
                var resolved = itemDefs.GetMetadata(match.Groups[1].Value);

                // Resolve references with remote item metadata
                if (resolved != null)
                {
                  val = val.Replace(match.Value, resolved.EvaluatedValue);
                  valChanged = true;
                }
                
                // Match Debugging
//              Log.LogError("Match: " + match.Groups[1].Value);
              }
            
            // NOTE: Checking for changes also prevents reserved metadata exceptions
            if (valChanged)
              newItem.SetMetadata(name, val);
          }
          
          evaluatedItems.Add(newItem);
          
          // Allows for introspection of metadata
/*        var dic = newItem.CloneCustomMetadata();
          
          foreach (var k in dic.Keys)
            Log.LogError(k + " -> " + dic[k]);
*/
        }
        
        Evaluated = evaluatedItems.ToArray();
Dass dies nicht direkt ein offizieller Weg ist, dürfte aus dem Code zweifelsfrei hervorgehen. Aber wenn nichtmal derart einfache Probleme sinnvoll lösbar sind, bleibt wohl nichts anderes übrig. Die gesamte Targets-Datei mit einigen oberflächlichen Anmerkungen:

Code: Alles auswählen

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <PropertyGroup>
    <QtCompileRulesPath>$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml</QtCompileRulesPath>
    <!-- Set to high to enable, low to disable debug messages -->
    <QtCompileDebugPriority>low</QtCompileDebugPriority>
    <!-- Set to true to enable verbose debug messages, false otherwise -->
    <QtCompileDebugVerbose>false</QtCompileDebugVerbose>
    <!-- Set to true to disable command line echo -->
    <QtCompileNoEcho>true</QtCompileNoEcho>
  </PropertyGroup>

  <ItemGroup>
    <!-- Include item type & build tool properties / build rule -->
    <PropertyPageSchema Include="$(QtCompileRulesPath)" />
    <!-- Make build tool / item type available & link to _QtCompile build step / target -->
    <AvailableItemName Include="QtCompile">
      <Targets>_QtCompile</Targets>
    </AvailableItemName>
  </ItemGroup>

  <!-- Construct command line task from build rule (provides automated command line construction from build rule properties) -->
  <UsingTask TaskName="QtCompile" TaskFactory="XamlTaskFactory" AssemblyName="Microsoft.Build.Tasks.v4.0">
    <Task>$(QtCompileRulesPath)</Task>
  </UsingTask>

  <!-- Filter Qt header files stored in list '@(QtCompile)', removing unselected and excluded files -->
  <Target Name="_QtCompilePrepare" Condition="'@(QtCompile)' != ''"
          DependsOnTargets="_SelectedFiles">

    <Message Text="QtCompilePrepare ..." Importance="$(QtCompileDebugPriority)" />

    <!-- Debug messages printing a list of files to be compiled and files to be selected -->
    <Message Text="QtCompilePrepare has '@(QtCompile)'" Importance="$(QtCompileDebugPriority)" Condition="$(QtCompileDebugVerbose)" />
    <Message Text="QtCompilePrepare selects '@(SelectedFiles)'" Importance="$(QtCompileDebugPriority)" Condition="$(QtCompileDebugVerbose)" />

    <!-- Remove all files that have not been selected, _iff any selected_ -->
    <ItemGroup Condition="'@(SelectedFiles)' != ''">
      <!-- WARNING: Only works in this EXACT form, using unqualified '%(Identity)' reference -->
      <!-- Actually, cross products are not supported at all, for whatever happens here ... -->
      <QtCompile Remove="@(QtCompile)" Condition="'%(Identity)' != '@(SelectedFiles)'" />
    </ItemGroup>
    <!-- Remove all files that have been excluded -->
    <ItemGroup>
      <QtCompile Remove="@(QtCompile)" Condition="'%(QtCompile.ExcludedFromBuild)' == 'true'" />
    </ItemGroup>

    <!-- Debug message printing files to be compiled after filtering  -->
    <Message Text="QtCompilePrepare now has '@(QtCompile)'" Importance="$(QtCompileDebugPriority)" Condition="$(QtCompileDebugVerbose)" />
  </Target>

  <!-- Include Qt files into C++ build step -->
  <Target Name="_QtIncludeCpp" Condition="'@(QtCompile)' != ''"
          DependsOnTargets="_QtCompilePrepare" BeforeTargets="ClCompile">

    <Message Text="QtIncludeCpp ..." Importance="$(QtCompileDebugPriority)" />

    <ItemGroup>
      <!-- Include all Qt compiler output files into C++ build step -->
      <ClCompile Include="%(QtCompile.CompilerOutput)" KeepDuplicates="false">
        <!-- Store back link to original Qt header file in item metadata -->
        <_QtCompileSrc>%(QtCompile.Identity)</_QtCompileSrc>
      </ClCompile>
    </ItemGroup>

  </Target>

  <!-- Execute Qt compiler for all Qt headers to be compiled -->
  <Target Name="_QtCompile" Condition="'@(QtCompile)' != ''"
          DependsOnTargets="_QtCompilePrepare" BeforeTargets="ClCompile"
          Inputs="@(QtCompile);$(MSBuildProjectFile)"
          Outputs="@(QtCompile->'%(CompilerOutput)')">

    <Message Text="QtCompile ..." Importance="$(QtCompileDebugPriority)" />
    
    <!-- Call inline task to evaluate remote metadata references to C++ compiler properties -->
    <EvaluateProjectMetadata ItemName="ClCompile" Destination="@(QtCompile)">
      <!-- Store results of the evaluation in internal resolved item group -->
      <Output TaskParameter="Evaluated" ItemName="_QtCompileResolved" />
    </EvaluateProjectMetadata>

    <!-- Resolution debug message -->
    <Message Text="QtCompile resolved: %(_QtCompileResolved.Identity); Defines: %(_QtCompileResolved.Defines); Includes: %(_QtCompileResolved.Include)"
             Importance="$(QtCompileDebugPriority)" Condition="$(QtCompileDebugVerbose)" />
    
    <!-- Notify that compilation is starting -->
    <Message Text="Compiling: %(_QtCompileResolved.Filename)%(_QtCompileResolved.Extension) using MOC" Importance="high" />

    <!-- Call imported build-rule-based command line task -->
    <!-- CommandLineTemplate supports [AllOptions], command line construction follows the build rule property specifications -->
    <QtCompile
      CommandLineTemplate=""%(_QtCompileResolved.MOCPath)" "%(_QtCompileResolved.FullPath)" [AllOptions] [AdditionalOptions]"
      CompilerOutput="%(_QtCompileResolved.CompilerOutput)"
      Defines="%(_QtCompileResolved.Defines)"
      Include="%(_QtCompileResolved.Include)"
      AdditionalDeps="%(_QtCompileResolved.AdditionalDeps)"
      AdditionalOptions="%(_QtCompileResolved.AdditionalOptions)"
      StandardOutputImportance="High"
      StandardErrorImportance="High"
      EchoOff="$(QtCompileNoEcho)" />
  </Target>
  
  <UsingTask TaskName="EvaluateProjectMetadata" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <ItemName ParameterType="System.String" Required="true" />
      <Destination ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
      <DestinationPrefix ParameterType="System.String" Required="false" />
      <Evaluated ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" />
    </ParameterGroup>
    <Task>
      <Reference Include="$(MSBuildToolsPath)\Microsoft.Build.dll" />
      <Using Namespace="System.IO"/>
      <Using Namespace="System.Reflection"/>
      <Using Namespace="System.Text.RegularExpressions"/>
      <Using Namespace="Microsoft.Build.Execution"/>
      <Code Type="Fragment" Language="cs">
        <![CDATA[
        ProjectInstance project;
        
        // Get project instance
        {
          const BindingFlags bindingFlags = BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
          var targetBuilderCallback = this.BuildEngine.GetType().GetField("targetBuilderCallback", bindingFlags).GetValue(this.BuildEngine);
          project = (ProjectInstance) targetBuilderCallback.GetType().GetField("projectInstance", bindingFlags).GetValue(targetBuilderCallback);
        }
        
        if (String.IsNullOrEmpty(DestinationPrefix))
          DestinationPrefix = "_";
        
        var itemDefs = project.ItemDefinitions[ItemName];
        Regex resolveExpression = new Regex("%" + Regex.Escape(DestinationPrefix) + @"\((\w*)\)");
        var evaluatedItems = new List<TaskItem>();
        
        // Resolve remote metadata references
        foreach (var destItem in Destination)
        {
          var newItem = new TaskItem(destItem);
        
          foreach (string name in newItem.MetadataNames)
          {
            string val = newItem.GetMetadata(name);
            bool valChanged = false;
            
            // Find unresolved references in destination item metadata
            if (!String.IsNullOrEmpty(val))
              foreach (Match match in resolveExpression.Matches(val))
              {
                var resolved = itemDefs.GetMetadata(match.Groups[1].Value);

                // Resolve references with remote item metadata
                if (resolved != null)
                {
                  val = val.Replace(match.Value, resolved.EvaluatedValue);
                  valChanged = true;
                }
                
                // Match Debugging
//              Log.LogError("Match: " + match.Groups[1].Value);
              }
            
            // NOTE: Checking for changes also prevents reserved metadata exceptions
            if (valChanged)
              newItem.SetMetadata(name, val);
          }
          
          evaluatedItems.Add(newItem);
          
          // Allows for introspection of metadata
/*        var dic = newItem.CloneCustomMetadata();
          
          foreach (var k in dic.Keys)
            Log.LogError(k + " -> " + dic[k]);
*/
        }
        
        Evaluated = evaluatedItems.ToArray();
        ]]>
      </Code>
    </Task>
  </UsingTask>

</Project>
Im Anhang außerdem der gesamte Build Step mit Default Properties und Build-Tool-Spezifikation.
Dateianhänge
QtMOC.MSBuild.zip
Gesamter MOC Build Step
(4.02 KiB) 266-mal heruntergeladen
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von BeRsErKeR »

Ich versteh nicht so ganz wozu ihr da im XML rumschreiben müsst. Du kannst das ganze doch einfach direkt im Visual Studio konfigurieren in Abhängigkeit von der Dateiendung. Oder ist das VS2012 wirklich so umständlich geworden? Ich hab gestern erst ein altes Qt-Projekt ausgegraben, das noch mit Qt von 2009 lief (glaub damals mit VS2008). Habs nach VS2010 (ohne Add-In) konvertiert und alles lief noch immer ohne Probleme (trotz Umstieg auf die neuste Qt-Version). Ich glaub das Projekt hab ich damals auch ohne Add-In erstellt und halt Buildrules für *.moc und *.ui angelegt. Und erst danach dann das Add-In installiert und damit gearbeitet. Wie gesagt spreche ich hier von VS2010, aber ich kann mir kaum vorstellen, dass VS2012 da jetzt irgendwelche ernsten Schwierigkeiten haben sollte. Falls doch wär es wohl ein Grund bei VS2010 zu bleiben. :D
Ohne Input kein Output.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

BeRsErKeR hat geschrieben:Ich versteh nicht so ganz wozu ihr da im XML rumschreiben müsst. Du kannst das ganze doch einfach direkt im Visual Studio konfigurieren in Abhängigkeit von der Dateiendung. Oder ist das VS2012 wirklich so umständlich geworden? Ich hab gestern erst ein altes Qt-Projekt ausgegraben, das noch mit Qt von 2009 lief (glaub damals mit VS2008). Habs nach VS2010 (ohne Add-In) konvertiert und alles lief noch immer ohne Probleme (trotz Umstieg auf die neuste Qt-Version). Ich glaub das Projekt hab ich damals auch ohne Add-In erstellt und halt Buildrules für *.moc und *.ui angelegt. Und erst danach dann das Add-In installiert und damit gearbeitet. Wie gesagt spreche ich hier von VS2010, aber ich kann mir kaum vorstellen, dass VS2012 da jetzt irgendwelche ernsten Schwierigkeiten haben sollte. Falls doch wär es wohl ein Grund bei VS2010 zu bleiben. :D
Deine Buildrule wurde beim Umstieg zu VS2010 einfach stillschweigend in eben dieses XML umgewandelt. Von VS2010 zu VS2012 ändert sich nix.
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

So, nach weiteren 200 WTFs und unzähligen mühsamen Umstellungen nähert sich mein Build Step der Komplexität des CUDA Build Steps, dafür führt er bei inkrementellen Builds nun je nach Situation nur noch die notwendigsten Operationen auf zu aktualisierenden Items durch. Inzwischen bringt mich nicht mal mehr auf die Palme, dass selbst die Umsetzung einer für ein Build System derart essentiellen Eigenschaft (MSBUILD?!) derartige Verrenkungen erfordert. Tatsächlich werden die Target-Conditions mit den unbearbeiteten Eingabelisten geprüft, was sofort erklärt, warum diese Condition dann in jedem anderen Build Script da draußen in jeder verfluchten Einzelanweisung des Targets wiederholt wird. Nicht nur das, es reicht nicht mal aus, in der Condition dann einfach eine gefilterte Liste einzutragen - damit diese nicht zur leeren Liste auswertet, müssen vor der Prüfung der Condition bereits die Filter-Targets aufgeführt worden sein, wofür das Target-eigene DependsOnTargets-Attribut nicht ausreicht (Dependencies werden sinnvollerweise erst nach der Prüfung der Condition ausgewertet), stattdessen muss ein übergeordnetes Target das Filter-Target bereits rechtzeitig ausgeführt haben.

Code: Alles auswählen

<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

  <PropertyGroup>
    <QtCompileRulesPath>$(MSBuildThisFileDirectory)$(MSBuildThisFileName).xml</QtCompileRulesPath>
    <!-- Set to high to enable, low to disable debug messages -->
    <QtCompileDebugPriority>low</QtCompileDebugPriority>
    <!-- Set to true to enable verbose debug messages, false otherwise -->
    <QtCompileDebugVerbose>false</QtCompileDebugVerbose>
    <!-- Set to true to disable command line echo -->
    <QtCompileNoEcho>true</QtCompileNoEcho>
  </PropertyGroup>

  <ItemGroup>
    <!-- Include item type & build tool properties / build rule -->
    <PropertyPageSchema Include="$(QtCompileRulesPath)" />
    <!-- Make build tool / item type available & link to QtCompile build step / target -->
    <AvailableItemName Include="QtCompile">
      <Targets>QtCompile</Targets>
    </AvailableItemName>
  </ItemGroup>

  <!-- Construct command line task from build rule (provides automated command line construction from build rule properties) -->
  <UsingTask TaskName="QtCompile" TaskFactory="XamlTaskFactory" AssemblyName="Microsoft.Build.Tasks.v4.0">
    <Task>$(QtCompileRulesPath)</Task>
  </UsingTask>

  <!-- Indirection + DependsOnTargets allows _QtCompilePrepare to check for @(_QtCompileFiltered) rather than unfiltered @(QtCompile) -->
  <Target Name="QtIncludeCpp" Condition="'@(QtCompile)' != ''"
          DependsOnTargets="_QtCompilePrepare;_QtIncludeCpp" BeforeTargets="ClCompile" />

  <!-- Indirection + DependsOnTargets allows _QtCompile to check for @(_QtCompileFiltered) rather than unfiltered @(QtCompile) -->
  <Target Name="QtCompile" Condition="'@(QtCompile)' != ''"
          DependsOnTargets="_QtCompilePrepare;_QtCompile" BeforeTargets="ClCompile" />

  <!-- Filter Qt header files stored in list '@(QtCompile)', removing unselected and excluded files -->
  <Target Name="_QtCompilePrepare" Condition="'@(QtCompile)' != ''"
          DependsOnTargets="_SelectedFiles">

    <Message Text="QtCompilePrepare ..." Importance="$(QtCompileDebugPriority)" />

    <!-- Debug messages printing a list of files to be compiled and files to be selected -->
    <Message Text="QtCompilePrepare has '@(QtCompile)'" Importance="$(QtCompileDebugPriority)" Condition="$(QtCompileDebugVerbose)" />
    <Message Text="QtCompilePrepare selects '@(SelectedFiles)'" Importance="$(QtCompileDebugPriority)" Condition="$(QtCompileDebugVerbose)" />

  <!-- Remove all files that have been excluded -->
    <ItemGroup>
      <_QtCompileFiltered Include="@(QtCompile)" Condition="'%(QtCompile.ExcludedFromBuild)' != 'true'" />
    </ItemGroup>
    <!-- Remove all files that have not been selected, _iff any selected_ -->
    <ItemGroup Condition="'@(SelectedFiles)' != ''">
      <!-- WARNING: Only works in this EXACT form, using unqualified '%(Identity)' reference -->
      <!-- Actually, cross products are not supported at all, for whatever happens here ... -->
      <_QtCompileFiltered Remove="@(_QtCompileFiltered)" Condition="'%(Identity)' != '@(SelectedFiles)'" />
    </ItemGroup>

    <!-- Debug message printing files to be compiled after filtering  -->
    <Message Text="QtCompilePrepare now has '@(_QtCompileFiltered)'" Importance="$(QtCompileDebugPriority)" Condition="$(QtCompileDebugVerbose)" />
  </Target>
  
  <!-- Include Qt files into C++ build step -->
  <Target Name="_QtIncludeCpp" Condition="'@(_QtCompileFiltered)' != ''"
          DependsOnTargets="_QtCompilePrepare" BeforeTargets="ClCompile">

    <Message Text="QtIncludeCpp ..." Importance="$(QtCompileDebugPriority)" />

    <ItemGroup>
      <!-- Include all Qt compiler output files into C++ build step -->
      <ClCompile Include="%(_QtCompileFiltered.CompilerOutput)" KeepDuplicates="false">
        <!-- Store back link to original Qt header file in item metadata -->
        <_QtCompileSrc>%(_QtCompileFiltered.Identity)</_QtCompileSrc>
      </ClCompile>
    </ItemGroup>

  </Target>
  
  <!-- Execute Qt compiler for all Qt headers to be compiled -->
  <Target Name="_QtCompile"
          DependsOnTargets="_QtCompilePrepare" BeforeTargets="ClCompile"
          Inputs="@(_QtCompileFiltered);$(MSBuildProjectFile)"
          Outputs="@(_QtCompileFiltered->'%(CompilerOutput)')">

    <!-- Resolve remote metadata -->
      <Message Text="QtResolveMetadata ..." Importance="$(QtCompileDebugPriority)" />

      <!-- Call inline task to evaluate remote metadata references to C++ compiler properties -->
      <EvaluateProjectMetadata ItemName="ClCompile" Destination="@(_QtCompileFiltered)">
        <!-- Store results of the evaluation in internal resolved item group -->
        <Output TaskParameter="Evaluated" ItemName="_QtCompileResolved" />
      </EvaluateProjectMetadata>

      <!-- Resolution debug message -->
      <Message Text="QtResolveMetadata: %(_QtCompileResolved.Identity); Defines: %(_QtCompileResolved.Defines); Includes: %(_QtCompileResolved.Include)"
               Importance="$(QtCompileDebugPriority)" Condition="$(QtCompileDebugVerbose)" />
    <!-- / Resolve remote metadata -->

    <!-- Compile headers -->
      <Message Text="QtCompile ..." Importance="$(QtCompileDebugPriority)" />
    
      <!-- Notify that compilation is starting -->
      <Message Text="Compiling: %(_QtCompileResolved.Filename)%(_QtCompileResolved.Extension) using MOC" Importance="high" />

      <!-- Call imported build-rule-based command line task -->
      <!-- CommandLineTemplate supports [AllOptions], command line construction follows the build rule property specifications -->
      <QtCompile
        CommandLineTemplate=""%(_QtCompileResolved.MOCPath)" "%(_QtCompileResolved.FullPath)" [AllOptions] [AdditionalOptions]"
        CompilerOutput="%(_QtCompileResolved.CompilerOutput)"
        Defines="%(_QtCompileResolved.Defines)"
        Include="%(_QtCompileResolved.Include)"
        AdditionalDeps="%(_QtCompileResolved.AdditionalDeps)"
        AdditionalOptions="%(_QtCompileResolved.AdditionalOptions)"
        StandardOutputImportance="High"
        StandardErrorImportance="High"
        EchoOff="$(QtCompileNoEcho)" />
    <!-- / Compile headers -->
  </Target>
  
  <UsingTask TaskName="EvaluateProjectMetadata" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
    <ParameterGroup>
      <ItemName ParameterType="System.String" Required="true" />
      <Destination ParameterType="Microsoft.Build.Framework.ITaskItem[]" Required="true" />
      <DestinationPrefix ParameterType="System.String" Required="false" />
      <Evaluated ParameterType="Microsoft.Build.Framework.ITaskItem[]" Output="true" />
    </ParameterGroup>
    <Task>
      <Reference Include="$(MSBuildToolsPath)\Microsoft.Build.dll" />
      <Using Namespace="System.IO"/>
      <Using Namespace="System.Reflection"/>
      <Using Namespace="System.Text.RegularExpressions"/>
      <Using Namespace="Microsoft.Build.Execution"/>
      <Code Type="Fragment" Language="cs">
        <![CDATA[
        ProjectInstance project;
        
        // Get project instance
        {
          const BindingFlags bindingFlags = BindingFlags.FlattenHierarchy | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic;
          var targetBuilderCallback = this.BuildEngine.GetType().GetField("targetBuilderCallback", bindingFlags).GetValue(this.BuildEngine);
          project = (ProjectInstance) targetBuilderCallback.GetType().GetField("projectInstance", bindingFlags).GetValue(targetBuilderCallback);
        }
        
        if (String.IsNullOrEmpty(DestinationPrefix))
          DestinationPrefix = "_";
        
        var itemDefs = project.ItemDefinitions[ItemName];
        Regex resolveExpression = new Regex("%" + Regex.Escape(DestinationPrefix) + @"\((\w*)\)");
        var evaluatedItems = new List<TaskItem>();
        
        // Resolve remote metadata references
        foreach (var destItem in Destination)
        {
          var newItem = new TaskItem(destItem);
        
          foreach (string name in newItem.MetadataNames)
          {
            string val = newItem.GetMetadata(name);
            bool valChanged = false;
            
            // Find unresolved references in destination item metadata
            if (!String.IsNullOrEmpty(val))
              foreach (Match match in resolveExpression.Matches(val))
              {
                var resolved = itemDefs.GetMetadata(match.Groups[1].Value);

                // Resolve references with remote item metadata
                if (resolved != null)
                {
                  val = val.Replace(match.Value, resolved.EvaluatedValue);
                  valChanged = true;
                }
                
                // Match Debugging
//              Log.LogError("Match: " + match.Groups[1].Value);
              }
            
            // NOTE: Checking for changes also prevents reserved metadata exceptions
            if (valChanged)
              newItem.SetMetadata(name, val);
          }
          
          evaluatedItems.Add(newItem);
          
          // Allows for introspection of metadata
/*        var dic = newItem.CloneCustomMetadata();
          
          foreach (var k in dic.Keys)
            Log.LogError(k + " -> " + dic[k]);
*/
        }
        
        Evaluated = evaluatedItems.ToArray();
        ]]>
      </Code>
    </Task>
  </UsingTask>

</Project>
Nach all dem wundert mich eigentlich nur noch, dass Visual Studio überhaupt ab und zu ein kompiliertes Programm ausspuckt. Insbesondere wundern mich Verzögerungen beim Build großer Projekte nicht mehr im Geringsten.
Dateianhänge
QtMOC.MSBuild-0.99.zip
(4.13 KiB) 225-mal heruntergeladen
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
Benutzeravatar
BeRsErKeR
Establishment
Beiträge: 689
Registriert: 27.04.2002, 22:01

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von BeRsErKeR »

CodingCat hat geschrieben:
BeRsErKeR hat geschrieben:Ich versteh nicht so ganz wozu ihr da im XML rumschreiben müsst. Du kannst das ganze doch einfach direkt im Visual Studio konfigurieren in Abhängigkeit von der Dateiendung. Oder ist das VS2012 wirklich so umständlich geworden? Ich hab gestern erst ein altes Qt-Projekt ausgegraben, das noch mit Qt von 2009 lief (glaub damals mit VS2008). Habs nach VS2010 (ohne Add-In) konvertiert und alles lief noch immer ohne Probleme (trotz Umstieg auf die neuste Qt-Version). Ich glaub das Projekt hab ich damals auch ohne Add-In erstellt und halt Buildrules für *.moc und *.ui angelegt. Und erst danach dann das Add-In installiert und damit gearbeitet. Wie gesagt spreche ich hier von VS2010, aber ich kann mir kaum vorstellen, dass VS2012 da jetzt irgendwelche ernsten Schwierigkeiten haben sollte. Falls doch wär es wohl ein Grund bei VS2010 zu bleiben. :D
Deine Buildrule wurde beim Umstieg zu VS2010 einfach stillschweigend in eben dieses XML umgewandelt. Von VS2010 zu VS2012 ändert sich nix.
Ok ich hätte genauer hinsehen sollen. Da es in meinem Projekt nur 3 UIs gab, hatte ich da wohl für jede Datei eine Extra-Buildrule angelegt, die nach wie vor vorhanden ist. Diese werden ja scheinbar nach wie vor in der Projektdatei gespeichert. Und da ich in den Projekteinstellungen immer noch den Punkt "Buildrule" fand, ging ich fälschlicherweise davon aus, dass auch projektglobale Custom-Buildrules + Editor im VS2010 noch vorhanden sind.
Ohne Input kein Output.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Hm, meine Posts wurden gerade verschluckt, deshalb hier noch die Antwort auf deine Frage nach dem Warum: Um volle Kontrolle zu haben und möglichst alles zu automatisieren. Das was aus der VS2008-Rule-Conversion rauskommt ist auch nicht gerade großartig. Insbesondere hat mir eine automatische Synchronisation der C/C++ und MOC-Einstellungen gefehlt - daran bin ich zwar auch in MSBuild nahezu zugrunde gegangen, schlussendlich geht es jetzt aber (C/C++ Defines landen automatisch im MOC Build Tool). Weiterhin kann ich jetzt den größten Teil an entstehenden C++-Dateien vom Build Script automatisch dazulinken lassen. In die Solution muss ich solche Dateien nur für besondere Einstellungen einbinden, z.B. die Ressourcen-Cpp-Datei, um dort Precompiled Headers abzuschalten und das Iterator-Debug-Level zu korrigieren. Für diesen Fall hat das Script jetzt eine Eigenschaft, die das automatische Linken abstellt, wie alle Eigenschaften für Gruppen wie einzelne Dateien konfigurierbar.

Mit dem Ergebnis habe ich soeben erfolgreich mein ganzes Qt-Projekt bauen können, mitsamt Ui-, Rc- und Qt-Header-Dateien. Die Scripte sind angehängt, sie enthalten neben einigen kleineren Korrekturen nun auch noch ein Clean-Target für Rebuilds/Cleans.
Dateianhänge
Qt-MSBuild-v1.0.zip
(9.62 KiB) 275-mal heruntergeladen
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
zack
Beiträge: 3
Registriert: 18.03.2015, 14:48

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von zack »

Die build regeln funktionieren ganz gut. Nur gibt es leider ein mehr oder weniger schwerwiegendes Problem.
Alle MOC files eines Targets werden bei jedem compile immer neu kompiliert.
Wenn ich also eine CPP file ändere, werden aus welchen Grund auch immer, gleich alle MOC files neu kompiliert.
Normalerweise sollte nur bei der Änderung einer Header file, moc laufen und die entsprechende CPP file neu kompiliert werden.

@CodingCat
Kannst Du bitte das noch fixen? Ich weiß nicht wo ich ansetzen soll, das MSBuild system verstehe ich nicht wirklich.
Benutzeravatar
CodingCat
Establishment
Beiträge: 1857
Registriert: 02.03.2009, 21:25
Wohnort: Student @ KIT
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von CodingCat »

Das hier ist die letzte Version, die ich verwendet habe, eventuell tut die ja. Ist allerdings eine Weile her, mittlerweile bin ich wegen Linux-Unterstützung nur noch mit CMake unterwegs. Ich sehe gerade keinen Grund, warum dauerend alles neu kompiliert werden sollte, schon gar nicht bei Änderung eines CPP Files. Schlussendlich ist MSBuild aber genauso ekelerregend und undurchsichtig wie alle anderen Build-Systeme auch. :-/
Dateianhänge
Qt-MSBuild-v1.2.zip
(9.76 KiB) 239-mal heruntergeladen
alphanew.net (last updated 2011-07-02) | auf Twitter | Source Code: breeze 2 | lean C++ library | D3D Effects Lite
zack
Beiträge: 3
Registriert: 18.03.2015, 14:48

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von zack »

Die Version funktioniert leider auch nicht.
Das Feature, das die Datei moc*.cpp Datien automatisch mit kompiliert werden ist schon ziemlich nice. Nur leider werden alle moc dateien immer neu kompiliert...schade.
Wenn ich das Feature ausschalte und die Dateien per Hand in die Solution einfüge, klappt es.

Ich weiß nicht so recht wo ich ansätzen soll, vielleicht hier?
Qt.Moc.Targets

Code: Alles auswählen

<Target Name="_QtIncludeCpp" Condition="'@(_QtCompileFiltered)' != ''"
          DependsOnTargets="_QtCompileFilter" BeforeTargets="ClCompile">

    <Message Text="QtIncludeCpp ..." Importance="$(QtCompileDebugPriority)" />

    <ItemGroup>
      <!-- Include all Qt compiler output files into C++ build step -->
      <ClCompile Include="%(_QtCompileFiltered.CompilerOutput)" Condition="'%(_QtCompileFiltered.Link)' != 'false'">
        <!-- Store back link to original Qt header file in item metadata -->
        <_QtCompileSrc>%(_QtCompileFiltered.Identity)</_QtCompileSrc>
      </ClCompile>
	  <!-- Optionally include Qt compiler input files into C++ build step -->
      <ClCompile Include="%(_QtCompileFiltered.Identity)" Condition="'%(_QtCompileFiltered.ReverseLink)' != 'false'">
        <!-- Store back link to original Qt header file in item metadata -->
        <_QtCompileSrc>%(_QtCompileFiltered.Identity)</_QtCompileSrc>
      </ClCompile>
    </ItemGroup>

  </Target>
Ich benutze VS 2013 Update 4

2)
Was ebenfalls nicht optimal ist, ist die Tatsache das alle header files die man einfügt die Buildregel "Qt C/C++" bekommen, dadurch gibt es natürlich Fehlermeldung da Dateien gemockt werden die kein Q_OBJECT macro haben.
Es wäre natürlich äusserst nice, wenn neue eingefügte Dateien nach dem Macro untersucht werden und diese dann diese Build-Regel bekommen.
Weißt du wie man das ändert?
3)
Du hast dort auch ein wenig C# code drinn, für was ist der denn?
Benutzeravatar
Jonathan
Establishment
Beiträge: 2352
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von Jonathan »

Naja, was glaube ich die meisten machen, ist ein Buildsystem wie CMake oder QMake zu verwenden. Das mit dem Präprozessor ist halt irgendwie eine hässliche Lösung, aber wenn man die entsprechenden Tools benutzt kommt man damit sehr gut hin und merkt davon fast gar nichts. Es ist einfach nicht dafür gedacht, dass man alles von Hand konfiguriert.

Was spricht eigentlich gegen das Add-In? Bei den Expressversionen ging es ja früher nicht, aber neuerdings gibt es doch die COmmunity-Edition, bei der man sämtliche Add-Ins verwenden kann. Ich würde dir dringend raten, einfach eines dieser 3 Tools zu benutzen.
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
zack
Beiträge: 3
Registriert: 18.03.2015, 14:48

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von zack »

Das Addin hat auch so seine Probleme. Aber das ist eine andere Geschichte.
Der Vorteil bei den BuildRules ich kann sie direkt ins repository einchecken, niemand braucht sie mehr zu installieren.
Aber die BuildRules von CodingCat sind schon nicht schlecht, es sind halt nur diese zwei issues die dazu führen das das ganze nicht perfekt ist.
Was schade ist, da er ja schon einiges an Arbeit vo ein paar Jahren investiert hat.
Benutzeravatar
Jonathan
Establishment
Beiträge: 2352
Registriert: 04.08.2004, 20:06
Kontaktdaten:

Re: Qt ohne Add-In, VS2012 Build Rules?

Beitrag von Jonathan »

Naja, so ist das Leben, man schreibt eine schöne Lösung und schmeißt sie nach 2 Jahren komplett weg, weil man einen netteren Weg gefunden hat..

Das mit dem Weitergeben ist natürlich nett. Ich mag es auch, wenn alles kompakt ist und out-of-the-box läuft. Andererseits hast du ja vermutlich auch noch andere Abhängigkeiten. Entweder bundelt man dann absolut alles in sein Projekt, wodurch es schnell mal riesig werden kann, oder es bleibt dabei, dass Benutzer erstmal einen Nachmittag lang alles einrichten müssen, bevor irgendwas kompiliert. Das Build-System von C++ ist eben Grütze, aber da kann man vermutlich leider nichts dran ändern...
Lieber dumm fragen, als dumm bleiben!
https://jonathank.de/games/
Antworten