diff options
author | Miguel Costa <miguel.costa@qt.io> | 2019-04-05 14:36:42 +0200 |
---|---|---|
committer | Miguel Costa <miguel.costa@qt.io> | 2019-05-08 10:59:33 +0000 |
commit | 1e0431d2fb4a52916e1697bc7033e67c0d33a407 (patch) | |
tree | 6540f6a50ddc47dfe269e13f95f664eae6f2db44 | |
parent | 2e3834f664a8fe0a88d6bf0f5374210970ebd2b8 (diff) |
Import qmake projects with repc custom builds
When generating the .vcxproj for a project that includes remote object
templates, qmake will add a custom build step for those templates. For
the "Import .pro file" feature, this custom build must be converted to
a corresponding Qt/MSBuild item.
Change-Id: If0fb34e069f050be3265bf81639cc69a5cbff3fe
Reviewed-by: Oliver Wolff <oliver.wolff@qt.io>
-rw-r--r-- | src/qtprojectlib/MsBuildProject.cs | 30 | ||||
-rw-r--r-- | src/qtprojectlib/QtMsBuild.cs | 259 | ||||
-rw-r--r-- | src/qtprojectlib/QtProject.cs | 11 |
3 files changed, 283 insertions, 17 deletions
diff --git a/src/qtprojectlib/MsBuildProject.cs b/src/qtprojectlib/MsBuildProject.cs index aa0ab1aa..21aa3c94 100644 --- a/src/qtprojectlib/MsBuildProject.cs +++ b/src/qtprojectlib/MsBuildProject.cs @@ -491,7 +491,7 @@ namespace QtProjectLib var projItemsByPath = this[Files.Project].xml .Elements(ns + "Project") .Elements(ns + "ItemGroup") - .Elements(ns + "ClCompile") + .Elements() .Where(x => ((string)x.Attribute("Include")) .IndexOfAny(Path.GetInvalidPathChars()) == -1) .GroupBy(x => HelperFunctions.CanonicalPath( @@ -502,7 +502,7 @@ namespace QtProjectLib var filterItemsByPath = this[Files.Filters].xml .Elements(ns + "Project") .Elements(ns + "ItemGroup") - .Elements(ns + "ClCompile") + .Elements() .Where(x => ((string)x.Attribute("Include")) .IndexOfAny(Path.GetInvalidPathChars()) == -1) .GroupBy(x => HelperFunctions.CanonicalPath( @@ -662,6 +662,31 @@ namespace QtProjectLib QtRcc.Property.InputFile, "%(FullPath)"); } + //convert repc custom build steps + var repcCustomBuilds = GetCustomBuilds(QtRepc.ToolExecName); + if (!SetCommandLines(qtMsBuild, configurations, repcCustomBuilds, + QtRepc.ToolExecName, QtRepc.ItemTypeName, + Path.GetDirectoryName(this[Files.Project].filePath), + new ItemCommandLineReplacement[] { })) { + Rollback(); + return false; + } + foreach (var qtRepc in repcCustomBuilds.Elements(ns + QtRepc.ItemTypeName)) { + var itemName = (string)qtRepc.Attribute("Include"); + var configName = (string)qtRepc.Attribute("ConfigName"); + + //remove items with generated files + RemoveGeneratedFiles(projDir, cbEvals, configName, itemName, + projItemsByPath, filterItemsByPath); + + //set properties + qtMsBuild.SetItemProperty(qtRepc, + QtRepc.Property.ExecutionDescription, "Repc'ing %(Identity)..."); + qtMsBuild.SetItemProperty(qtRepc, + QtRepc.Property.InputFile, "%(FullPath)"); + } + + //convert uic custom build steps var uicCustomBuilds = GetCustomBuilds(QtUic.ToolExecName); if (!SetCommandLines(qtMsBuild, configurations, uicCustomBuilds, @@ -702,6 +727,7 @@ namespace QtProjectLib FinalizeProjectChanges(mocCustomBuilds.ToList(), QtMoc.ItemTypeName); FinalizeProjectChanges(rccCustomBuilds.ToList(), QtRcc.ItemTypeName); + FinalizeProjectChanges(repcCustomBuilds.ToList(), QtRepc.ItemTypeName); FinalizeProjectChanges(uicCustomBuilds.ToList(), QtUic.ItemTypeName); this[Files.Project].isDirty = this[Files.Filters].isDirty = true; diff --git a/src/qtprojectlib/QtMsBuild.cs b/src/qtprojectlib/QtMsBuild.cs index 0a83fadf..009176d6 100644 --- a/src/qtprojectlib/QtMsBuild.cs +++ b/src/qtprojectlib/QtMsBuild.cs @@ -416,6 +416,18 @@ namespace QtProjectLib.QtMsBuild } public string GetPropertyChangedValue( + QtRepc.Property property, + string itemName, + string configName) + { + return GetPropertyChangedValue( + configName, + QtRepc.ItemTypeName, + itemName, + property.ToString()); + } + + public string GetPropertyChangedValue( QtUic.Property property, string itemName, string configName) @@ -438,6 +450,8 @@ namespace QtProjectLib.QtMsBuild return SetQtMocCommandLine(propertyStorage, commandLine, macros); case QtRcc.ItemTypeName: return SetQtRccCommandLine(propertyStorage, commandLine, macros); + case QtRepc.ItemTypeName: + return SetQtRepcCommandLine(propertyStorage, commandLine, macros); case QtUic.ItemTypeName: return SetQtUicCommandLine(propertyStorage, commandLine, macros); } @@ -542,6 +556,55 @@ namespace QtProjectLib.QtMsBuild } #endregion + #region QtRepc + static QtRepc qtRepcInstance; + public static QtRepc QtRepcInstance + { + get + { + if (qtRepcInstance == null) + qtRepcInstance = new QtRepc(); + return qtRepcInstance; + } + } + + public string GetPropertyValue(object propertyStorage, QtRepc.Property property) + { + return GetPropertyValueByName( + propertyStorage, + QtRepc.ItemTypeName, + property.ToString()); + } + + public bool SetItemProperty( + object propertyStorage, + QtRepc.Property property, + string propertyValue) + { + return SetItemPropertyByName(propertyStorage, property.ToString(), propertyValue); + } + + public bool SetQtRepcCommandLine( + object propertyStorage, + string commandLine, + IVSMacroExpander macros) + { + Dictionary<QtRepc.Property, string> properties; + if (!QtRepcInstance.ParseCommandLine(commandLine, macros, out properties)) + return false; + foreach (var property in properties) { + if (!SetItemProperty(propertyStorage, property.Key, property.Value)) + return false; + } + return true; + } + + public string GenerateQtRepcCommandLine(object propertyStorage) + { + return QtRepcInstance.GenerateCommandLine(this, propertyStorage); + } + #endregion + #region QtUic static QtUic qtUicInstance; public static QtUic QtUicInstance @@ -600,7 +663,7 @@ namespace QtProjectLib.QtMsBuild protected CommandLineOption helpOption; protected CommandLineOption versionOption; - protected QtTool() + protected QtTool(bool defaultInputOutput = true) { parser = new CommandLineParser(); parser.SetSingleDashWordOptionMode( @@ -609,10 +672,29 @@ namespace QtProjectLib.QtMsBuild helpOption = parser.AddHelpOption(); versionOption = parser.AddVersionOption(); - outputOption = new CommandLineOption("o"); - outputOption.ValueName = "file"; - outputOption.Flags = CommandLineOption.Flag.ShortOptionStyle; - parser.AddOption(outputOption); + if (defaultInputOutput) { + outputOption = new CommandLineOption("o"); + outputOption.ValueName = "file"; + outputOption.Flags = CommandLineOption.Flag.ShortOptionStyle; + parser.AddOption(outputOption); + } + } + + protected virtual void ExtractInputOutput( + string toolExecName, + out string inputPath, + out string outputPath) + { + inputPath = outputPath = ""; + + string filePath = parser.PositionalArguments.Where( + arg => !arg.EndsWith(toolExecName, StringComparison.InvariantCultureIgnoreCase)) + .FirstOrDefault(); + if (!string.IsNullOrEmpty(filePath)) + inputPath = filePath; + + if (outputOption != null && parser.IsSet(outputOption)) + outputPath = parser.Value(outputOption); } protected bool ParseCommandLine( @@ -636,15 +718,7 @@ namespace QtProjectLib.QtMsBuild qtDir = HelperFunctions.CanonicalPath(Path.Combine(execDir, "..")); } - string filePath = parser.PositionalArguments.Where( - arg => !arg.EndsWith(toolExecName, StringComparison.InvariantCultureIgnoreCase)) - .FirstOrDefault(); - if (!string.IsNullOrEmpty(filePath)) - inputPath = filePath; - - if (parser.IsSet(outputOption)) - outputPath = parser.Value(outputOption); - + ExtractInputOutput(toolExecName, out inputPath, out outputPath); return true; } @@ -1180,6 +1254,163 @@ namespace QtProjectLib.QtMsBuild } } + public sealed class QtRepc : QtTool + { + public const string ItemTypeName = "QtRepc"; + public const string ToolExecName = "repc.exe"; + + public enum Property + { + ExecutionDescription, + QTDIR, + InputFileType, + InputFile, + OutputFileType, + OutputFile, + IncludePath, + AlwaysClass, + PrintDebug, + } + + Dictionary<Property, CommandLineOption> options + = new Dictionary<Property, CommandLineOption>(); + + public QtRepc() : base(defaultInputOutput: false) + { + parser.AddOption(options[Property.InputFileType] = + new CommandLineOption("i") + { + ValueName = "<rep|src>", + Flags = CommandLineOption.Flag.ShortOptionStyle + }); + + parser.AddOption(options[Property.OutputFileType] = + new CommandLineOption("o") + { + ValueName = "<source|replica|merged|rep>", + Flags = CommandLineOption.Flag.ShortOptionStyle + }); + + parser.AddOption(options[Property.IncludePath] = + new CommandLineOption("I") + { + ValueName = "dir", + Flags = CommandLineOption.Flag.ShortOptionStyle + }); + + parser.AddOption(options[Property.AlwaysClass] = + new CommandLineOption("c")); + + parser.AddOption(options[Property.PrintDebug] = + new CommandLineOption("d")); + } + + protected override void ExtractInputOutput( + string toolExecName, + out string inputPath, + out string outputPath) + { + inputPath = outputPath = ""; + + var args = new Queue<string>(parser.PositionalArguments + .Where(arg => !arg.EndsWith(toolExecName, + StringComparison.InvariantCultureIgnoreCase))); + + if (args.Any()) + inputPath = args.Dequeue(); + + if (args.Any()) + outputPath = args.Dequeue(); + } + + public bool ParseCommandLine( + string commandLine, + IVSMacroExpander macros, + out Dictionary<Property, string> properties) + { + properties = new Dictionary<Property, string>(); + + string qtDir, inputPath, outputPath; + if (!ParseCommandLine( + commandLine, + macros, + ToolExecName, + out qtDir, + out inputPath, + out outputPath)) { + return false; + } + + if (!string.IsNullOrEmpty(qtDir)) + properties[Property.QTDIR] = qtDir; + + if (parser.IsSet(options[Property.InputFileType])) { + properties[Property.InputFileType] = + string.Join(";", parser.Values(options[Property.InputFileType])); + } + + if (!string.IsNullOrEmpty(inputPath)) + properties[Property.InputFile] = inputPath; + + if (parser.IsSet(options[Property.OutputFileType])) { + properties[Property.OutputFileType] = + string.Join(";", parser.Values(options[Property.OutputFileType])); + } + + if (!string.IsNullOrEmpty(outputPath)) + properties[Property.OutputFile] = outputPath; + + if (parser.IsSet(options[Property.IncludePath])) { + properties[Property.IncludePath] = + string.Join(";", parser.Values(options[Property.IncludePath])); + } + + if (parser.IsSet(options[Property.AlwaysClass])) + properties[Property.AlwaysClass] = "true"; + + if (parser.IsSet(options[Property.PrintDebug])) + properties[Property.PrintDebug] = "true"; + + return true; + } + + public string GenerateCommandLine(QtMsBuildContainer container, object propertyStorage) + { + var cmd = new StringBuilder(); + cmd.AppendFormat(@"""{0}\bin\{1}""", + container.GetPropertyValue(propertyStorage, Property.QTDIR), ToolExecName); + + var inputType = container.GetPropertyValue(propertyStorage, Property.InputFileType); + if (!string.IsNullOrEmpty(inputType)) + GenerateCommandLineOption(cmd, options[Property.InputFileType], inputType); + + var outputType = container.GetPropertyValue(propertyStorage, Property.OutputFileType); + if (!string.IsNullOrEmpty(inputType)) + GenerateCommandLineOption(cmd, options[Property.InputFileType], inputType); + + string value = container.GetPropertyValue(propertyStorage, Property.IncludePath); + if (!string.IsNullOrEmpty(value)) + GenerateCommandLineOption(cmd, options[Property.IncludePath], value, true); + + if (container.GetPropertyValue(propertyStorage, Property.AlwaysClass) == "true") + GenerateCommandLineOption(cmd, options[Property.AlwaysClass]); + + if (container.GetPropertyValue(propertyStorage, Property.PrintDebug) == "true") + GenerateCommandLineOption(cmd, options[Property.PrintDebug]); + + value = container.GetPropertyValue(propertyStorage, Property.InputFile); + if (!string.IsNullOrEmpty(value)) + cmd.AppendFormat(" \"{0}\"", value); + + value = container.GetPropertyValue(propertyStorage, Property.OutputFile); + if (!string.IsNullOrEmpty(value)) + cmd.AppendFormat(" \"{0}\"", value); + + return cmd.ToString(); + } + + } + public sealed class QtUic : QtTool { public const string ItemTypeName = "QtUic"; diff --git a/src/qtprojectlib/QtProject.cs b/src/qtprojectlib/QtProject.cs index bf7bf135..56cf246f 100644 --- a/src/qtprojectlib/QtProject.cs +++ b/src/qtprojectlib/QtProject.cs @@ -3868,7 +3868,7 @@ namespace QtProjectLib VCCustomBuildTool tool; VCMacroExpander macros; - enum FileItemType { Other = 0, CustomBuild, QtMoc, QtRcc, QtUic }; + enum FileItemType { Other = 0, CustomBuild, QtMoc, QtRcc, QtRepc, QtUic }; FileItemType itemType = FileItemType.Other; public QtCustomBuildTool(VCFileConfiguration vcConfig, QtMsBuildContainer container = null) { @@ -3886,6 +3886,8 @@ namespace QtProjectLib itemType = FileItemType.QtMoc; else if (vcFile.ItemType == QtRcc.ItemTypeName) itemType = FileItemType.QtRcc; + else if (vcFile.ItemType == QtRepc.ItemTypeName) + itemType = FileItemType.QtRepc; else if (vcFile.ItemType == QtUic.ItemTypeName) itemType = FileItemType.QtUic; } @@ -3905,6 +3907,8 @@ namespace QtProjectLib return qtMsBuild.GenerateQtMocCommandLine(vcConfig); case FileItemType.QtRcc: return qtMsBuild.GenerateQtRccCommandLine(vcConfig); + case FileItemType.QtRepc: + return qtMsBuild.GenerateQtRepcCommandLine(vcConfig); case FileItemType.QtUic: return qtMsBuild.GenerateQtUicCommandLine(vcConfig); } @@ -3923,6 +3927,9 @@ namespace QtProjectLib case FileItemType.QtRcc: qtMsBuild.SetQtRccCommandLine(vcConfig, value, macros); break; + case FileItemType.QtRepc: + qtMsBuild.SetQtRepcCommandLine(vcConfig, value, macros); + break; case FileItemType.QtUic: qtMsBuild.SetQtUicCommandLine(vcConfig, value, macros); break; @@ -3941,6 +3948,8 @@ namespace QtProjectLib return qtMsBuild.GetPropertyValue(vcConfig, QtMoc.Property.OutputFile); case FileItemType.QtRcc: return qtMsBuild.GetPropertyValue(vcConfig, QtRcc.Property.OutputFile); + case FileItemType.QtRepc: + return qtMsBuild.GetPropertyValue(vcConfig, QtRepc.Property.OutputFile); case FileItemType.QtUic: return qtMsBuild.GetPropertyValue(vcConfig, QtUic.Property.OutputFile); } |