From da4ee15e3f2221c24fe0de653b755ce38695a98b Mon Sep 17 00:00:00 2001 From: Miguel Costa Date: Thu, 19 Oct 2017 16:04:41 +0200 Subject: Fix lupdate not working with Qt 5.9 When the command line to run lupdate was too long to specify individual source files, a temporary .pro file was created instead. The processing of the .pro file then triggered the same issue as QTVSADDINBUG-472 (qmake unable to find cl without VC vars). Removed the need for the temporary .pro file by using the '@' option of lupdate (added a call to SetVCVars() before running lupdate, just to be on the safe side). Task-number: QTVSADDINBUG-491 Change-Id: I6bce4c1c72093eceee8d1951bbbe464c072ba1a3 Reviewed-by: Joerg Bornemann --- src/qtprojectlib/HelperFunctions.cs | 165 ++++++++++++++++++++++++++++++++++++ src/qtprojectlib/QMake.cs | 159 +--------------------------------- src/qtvstools/Translation.cs | 64 +++----------- 3 files changed, 179 insertions(+), 209 deletions(-) (limited to 'src') diff --git a/src/qtprojectlib/HelperFunctions.cs b/src/qtprojectlib/HelperFunctions.cs index 70ac665d..e4111a39 100644 --- a/src/qtprojectlib/HelperFunctions.cs +++ b/src/qtprojectlib/HelperFunctions.cs @@ -28,15 +28,20 @@ using EnvDTE; using Microsoft.VisualStudio.VCProjectEngine; +using Microsoft.Win32; using System; using System.Collections.Generic; +using System.Diagnostics; using System.Drawing; using System.IO; using System.Linq; using System.Reflection; +using System.Text; using System.Text.RegularExpressions; using System.Windows.Forms; +using Process = System.Diagnostics.Process; + namespace QtProjectLib { public static class HelperFunctions @@ -1590,5 +1595,165 @@ namespace QtProjectLib return true; } + private static string GetRegistrySoftwareString(string subKeyName, string valueName) + { + var keyName = new StringBuilder(); + keyName.Append(@"SOFTWARE\"); + if (System.Environment.Is64BitOperatingSystem && IntPtr.Size == 4) + keyName.Append(@"WOW6432Node\"); + keyName.Append(subKeyName); + + try { + using (var key = Registry.LocalMachine.OpenSubKey(keyName.ToString(), false)) { + if (key == null) + return ""; //key not found + + RegistryValueKind valueKind = key.GetValueKind(valueName); + if (valueKind != RegistryValueKind.String + && valueKind != RegistryValueKind.ExpandString) { + return ""; //wrong value kind + } + + Object objValue = key.GetValue(valueName); + if (objValue == null) + return ""; //error getting value + + return objValue.ToString(); + } + } catch { + return ""; + } + } + + private static string GetVCPath() + { +#if VS2017 + string vsPath = GetRegistrySoftwareString(@"Microsoft\VisualStudio\SxS\VS7", "15.0"); + if (string.IsNullOrEmpty(vsPath)) + return ""; + string vcPath = Path.Combine(vsPath, "VC"); +#elif VS2015 + string vcPath = GetRegistrySoftwareString(@"Microsoft\VisualStudio\SxS\VC7", "14.0"); + if (string.IsNullOrEmpty(vcPath)) + return ""; //could not get registry key +#elif VS2013 + string vcPath = GetRegistrySoftwareString(@"Microsoft\VisualStudio\SxS\VC7", "12.0"); + if (string.IsNullOrEmpty(vcPath)) + return ""; //could not get registry key +#endif + return vcPath; + } + + public static bool SetVCVars(ProcessStartInfo startInfo) + { + bool isOS64Bit = System.Environment.Is64BitOperatingSystem; + bool isQt64Bit = QtVersionManager.The().GetVersionInfo( + QtVersionManager.The().GetDefaultVersion()).is64Bit(); + + string vcPath = GetVCPath(); + if (vcPath == "") + return false; + + string comspecPath = Environment.GetEnvironmentVariable("COMSPEC"); +#if VS2017 + string vcVarsCmd = ""; + string vcVarsArg = ""; + if (isOS64Bit && isQt64Bit) + vcVarsCmd = Path.Combine(vcPath, @"Auxiliary\Build\vcvars64.bat"); + else if (!isOS64Bit && !isQt64Bit) + vcVarsCmd = Path.Combine(vcPath, @"Auxiliary\Build\vcvars32.bat"); + else if (isOS64Bit && !isQt64Bit) + vcVarsCmd = Path.Combine(vcPath, @"Auxiliary\Build\vcvarsamd64_x86.bat"); + else if (!isOS64Bit && isQt64Bit) + vcVarsCmd = Path.Combine(vcPath, @"Auxiliary\Build\vcvarsx86_amd64.bat"); +#elif VS2015 || VS2013 + string vcVarsCmd = Path.Combine(vcPath, "vcvarsall.bat"); + string vcVarsArg = ""; + if (isOS64Bit && isQt64Bit) + vcVarsArg = "amd64"; + else if (!isOS64Bit && !isQt64Bit) + vcVarsArg = "x86"; + else if (isOS64Bit && !isQt64Bit) + vcVarsArg = "amd64_x86"; + else if (!isOS64Bit && isQt64Bit) + vcVarsArg = "x86_amd64"; +#endif + const string markSTX = ":@:@:@"; + const string markEOL = ":#:#:#"; + string command = + string.Format("/c \"{0}\" {1} && echo {2} && set", vcVarsCmd, vcVarsArg, markSTX); + var vcVarsStartInfo = new ProcessStartInfo(comspecPath, command); + vcVarsStartInfo.CreateNoWindow = true; + vcVarsStartInfo.UseShellExecute = false; + vcVarsStartInfo.RedirectStandardError = true; + vcVarsStartInfo.RedirectStandardOutput = true; + + var process = Process.Start(vcVarsStartInfo); + StringBuilder stdOut = new StringBuilder(); + + process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => + stdOut.AppendFormat("{0}\n{1}\n", e.Data, markEOL); + process.BeginOutputReadLine(); + + process.WaitForExit(); + bool ok = (process.ExitCode == 0); + process.Close(); + if (!ok) + return false; + + SortedDictionary> vcVars = + new SortedDictionary>(); + string[] split = + stdOut.ToString().Split(new string[] { "\n", "=", ";" }, StringSplitOptions.None); + int i = 0; + for (; i < split.Length && split[i].Trim() != markSTX; i++) { + //Skip to start of data + } + i++; //Advance to next item + for (; i < split.Length && split[i].Trim() != markEOL; i++) { + //Skip to end of line + } + i++; //Advance to next item + for (; i < split.Length; i++) { + //Process first item (variable name) + string key = split[i].ToUpper().Trim(); + i++; //Advance to next item + List vcVarValue = vcVars[key] = new List(); + for (; i < split.Length && split[i].Trim() != markEOL; i++) { + //Process items up to end of line (variable value(s)) + vcVarValue.Add(split[i].Trim()); + } + } + + foreach (var vcVar in vcVars) { + if (vcVar.Value.Count == 1) { + startInfo.EnvironmentVariables[vcVar.Key] = vcVar.Value[0]; + } else { + if (!startInfo.EnvironmentVariables.ContainsKey(vcVar.Key)) { + foreach (var vcVarValue in vcVar.Value) { + if (!string.IsNullOrWhiteSpace(vcVarValue)) { + startInfo.EnvironmentVariables[vcVar.Key] += vcVarValue + ";"; + } + } + } else { + string[] startInfoVariableValues = startInfo.EnvironmentVariables[vcVar.Key] + .Split(new string[] { ";" }, StringSplitOptions.None); + foreach (var vcVarValue in vcVar.Value) { + if (!string.IsNullOrWhiteSpace(vcVarValue) + && !startInfoVariableValues.Any(s => s.Trim().Equals( + vcVarValue, + StringComparison.OrdinalIgnoreCase))) { + if (!startInfo.EnvironmentVariables[vcVar.Key].EndsWith(";")) + startInfo.EnvironmentVariables[vcVar.Key] += ";"; + startInfo.EnvironmentVariables[vcVar.Key] += vcVarValue + ";"; + } + } + } + } + } + + return true; + } + } } diff --git a/src/qtprojectlib/QMake.cs b/src/qtprojectlib/QMake.cs index b51eb8a4..f13188f6 100644 --- a/src/qtprojectlib/QMake.cs +++ b/src/qtprojectlib/QMake.cs @@ -26,15 +26,12 @@ ** ****************************************************************************/ -using Microsoft.Win32; using System; using System.ComponentModel; using System.Diagnostics; using System.IO; using System.Text; using System.Threading; -using System.Collections.Generic; -using System.Linq; namespace QtProjectLib { @@ -90,7 +87,7 @@ namespace QtProjectLib qmakeProcess = CreateQmakeProcess(qmakeArgs, qtVersionInformation.qtDir + "\\bin\\qmake", fi.DirectoryName); - if (!SetVCVars(qmakeProcess.StartInfo)) + if (!HelperFunctions.SetVCVars(qmakeProcess.StartInfo)) InvokeExternalTarget(PaneMessageDataEvent, "--- (Import): Error setting VC vars"); // We must set the QTDIR environment variable, because we're clearing QMAKE_LIBDIR_QT above. @@ -209,159 +206,5 @@ namespace QtProjectLib } } - private string GetRegistrySoftwareString(string subKeyName, string valueName) - { - var keyName = new StringBuilder(); - keyName.Append(@"SOFTWARE\"); - if (System.Environment.Is64BitOperatingSystem && IntPtr.Size == 4) - keyName.Append(@"WOW6432Node\"); - keyName.Append(subKeyName); - - try { - using (var key = Registry.LocalMachine.OpenSubKey(keyName.ToString(), false)) { - if (key == null) - return ""; //key not found - - RegistryValueKind valueKind = key.GetValueKind(valueName); - if (valueKind != RegistryValueKind.String - && valueKind != RegistryValueKind.ExpandString) { - return ""; //wrong value kind - } - - Object objValue = key.GetValue(valueName); - if (objValue == null) - return ""; //error getting value - - return objValue.ToString(); - } - } catch { - return ""; - } - } - - private string GetVCPath() - { -#if VS2017 - string vsPath = GetRegistrySoftwareString(@"Microsoft\VisualStudio\SxS\VS7", "15.0"); - if (string.IsNullOrEmpty(vsPath)) - return ""; - string vcPath = Path.Combine(vsPath, "VC"); -#elif VS2015 - string vcPath = GetRegistrySoftwareString(@"Microsoft\VisualStudio\SxS\VC7", "14.0"); - if (string.IsNullOrEmpty(vcPath)) - return ""; //could not get registry key -#elif VS2013 - string vcPath = GetRegistrySoftwareString(@"Microsoft\VisualStudio\SxS\VC7", "12.0"); - if (string.IsNullOrEmpty(vcPath)) - return ""; //could not get registry key -#endif - return vcPath; - } - - private bool SetVCVars(ProcessStartInfo startInfo) - { - bool isOS64Bit = System.Environment.Is64BitOperatingSystem; - bool isQt64Bit = QtVersionManager.The().GetVersionInfo( - QtVersionManager.The().GetDefaultVersion()).is64Bit(); - - string vcPath = GetVCPath(); - if (vcPath == "") - return false; - - string comspecPath = Environment.GetEnvironmentVariable("COMSPEC"); -#if VS2017 - string vcVarsCmd = ""; - string vcVarsArg = ""; - if (isOS64Bit && isQt64Bit) - vcVarsCmd = Path.Combine(vcPath, @"Auxiliary\Build\vcvars64.bat"); - else if (!isOS64Bit && !isQt64Bit) - vcVarsCmd = Path.Combine(vcPath, @"Auxiliary\Build\vcvars32.bat"); - else if (isOS64Bit && !isQt64Bit) - vcVarsCmd = Path.Combine(vcPath, @"Auxiliary\Build\vcvarsamd64_x86.bat"); - else if (!isOS64Bit && isQt64Bit) - vcVarsCmd = Path.Combine(vcPath, @"Auxiliary\Build\vcvarsx86_amd64.bat"); -#elif VS2015 || VS2013 - string vcVarsCmd = Path.Combine(vcPath, "vcvarsall.bat"); - string vcVarsArg = ""; - if (isOS64Bit && isQt64Bit) - vcVarsArg = "amd64"; - else if (!isOS64Bit && !isQt64Bit) - vcVarsArg = "x86"; - else if (isOS64Bit && !isQt64Bit) - vcVarsArg = "amd64_x86"; - else if (!isOS64Bit && isQt64Bit) - vcVarsArg = "x86_amd64"; -#endif - const string markSTX = ":@:@:@"; - const string markEOL = ":#:#:#"; - string command = string.Format("/c \"{0}\" {1} && echo {2} && set", vcVarsCmd, vcVarsArg, markSTX); - var vcVarsStartInfo = new ProcessStartInfo(comspecPath, command); - vcVarsStartInfo.CreateNoWindow = true; - vcVarsStartInfo.UseShellExecute = false; - vcVarsStartInfo.RedirectStandardError = true; - vcVarsStartInfo.RedirectStandardOutput = true; - - var process = Process.Start(vcVarsStartInfo); - StringBuilder stdOut = new StringBuilder(); - - process.OutputDataReceived += (object sender, DataReceivedEventArgs e) => - stdOut.AppendFormat("{0}\n{1}\n", e.Data, markEOL); - process.BeginOutputReadLine(); - - process.WaitForExit(); - bool ok = (process.ExitCode == 0); - process.Close(); - if (!ok) - return false; - - SortedDictionary> vcVars = new SortedDictionary>(); - string[] split = stdOut.ToString().Split(new string[] { "\n", "=", ";" }, StringSplitOptions.None); - int i = 0; - for (; i < split.Length && split[i].Trim() != markSTX; i++) { - //Skip to start of data - } - i++; //Advance to next item - for (; i < split.Length && split[i].Trim() != markEOL; i++) { - //Skip to end of line - } - i++; //Advance to next item - for (; i < split.Length; i++) { - //Process first item (variable name) - string key = split[i].ToUpper().Trim(); - i++; //Advance to next item - List vcVarValue = vcVars[key] = new List(); - for (; i < split.Length && split[i].Trim() != markEOL; i++) { - //Process items up to end of line (variable value(s)) - vcVarValue.Add(split[i].Trim()); - } - } - - foreach (var vcVar in vcVars) { - if (vcVar.Value.Count == 1) { - startInfo.EnvironmentVariables[vcVar.Key] = vcVar.Value[0]; - } else { - if (!startInfo.EnvironmentVariables.ContainsKey(vcVar.Key)) { - foreach (var vcVarValue in vcVar.Value) { - if (!string.IsNullOrWhiteSpace(vcVarValue)) { - startInfo.EnvironmentVariables[vcVar.Key] += vcVarValue + ";"; - } - } - } else { - string[] startInfoVariableValues = startInfo.EnvironmentVariables[vcVar.Key] - .Split(new string[] { ";" }, StringSplitOptions.None); - foreach (var vcVarValue in vcVar.Value) { - if (!string.IsNullOrWhiteSpace(vcVarValue) - && !startInfoVariableValues.Any(s => s.Trim().Equals(vcVarValue, StringComparison.OrdinalIgnoreCase))) { - if (!startInfo.EnvironmentVariables[vcVar.Key].EndsWith(";")) - startInfo.EnvironmentVariables[vcVar.Key] += ";"; - startInfo.EnvironmentVariables[vcVar.Key] += vcVarValue + ";"; - } - } - } - } - } - - return true; - } } } diff --git a/src/qtvstools/Translation.cs b/src/qtvstools/Translation.cs index 80ba050d..ec3effff 100644 --- a/src/qtvstools/Translation.cs +++ b/src/qtvstools/Translation.cs @@ -31,6 +31,7 @@ using QtProjectLib; using System.Collections.Generic; using System.Diagnostics; using System.IO; +using System.Text; using System.Threading; using System.Windows.Forms; @@ -128,58 +129,21 @@ namespace QtVsTools var sources = HelperFunctions.GetProjectFiles(pro, FilesToList.FL_CppFiles); var uifiles = HelperFunctions.GetProjectFiles(pro, FilesToList.FL_UiFiles); + StringBuilder fileNames = new StringBuilder(); foreach (var file in headers) - cmdLine += file + " "; + fileNames.AppendLine(file); foreach (var file in sources) - cmdLine += file + " "; + fileNames.AppendLine(file); foreach (var file in uifiles) - cmdLine += file + " "; + fileNames.AppendLine(file); + var lstFilePath = Path.GetTempFileName(); + File.WriteAllText(lstFilePath, fileNames.ToString()); + cmdLine += string.Format("\"@{0}\" ", lstFilePath); cmdLine += "-ts " + vcFile.RelativePath.Quoute(); - var cmdLineLength = cmdLine.Length + Resources.lupdateCommand.Length + 1; - string temporaryProFile = null; - if (cmdLineLength > HelperFunctions.GetMaximumCommandLineLength()) { - var codec = string.Empty; - if (!string.IsNullOrEmpty(options)) { - var cc4tr_location = options.IndexOf("-codecfortr", System.StringComparison.CurrentCultureIgnoreCase); - if (cc4tr_location != -1) { - codec = options.Substring(cc4tr_location).Split(' ')[1]; - var remove_this = options.Substring(cc4tr_location, "-codecfortr".Length + 1 + codec.Length); - options = options.Replace(remove_this, ""); - } - } - var vcPro = (VCProject) pro.Object; - temporaryProFile = Path.GetTempFileName(); - temporaryProFile = Path.GetDirectoryName(temporaryProFile) + "\\" - + Path.GetFileNameWithoutExtension(temporaryProFile) + ".pro"; - if (File.Exists(temporaryProFile)) - File.Delete(temporaryProFile); - - using (var sw = new StreamWriter(temporaryProFile)) { - writeFilesToPro(sw, "HEADERS", - ProjectExporter.ConvertFilesToFullPath(headers, vcPro.ProjectDirectory)); - writeFilesToPro(sw, "SOURCES", - ProjectExporter.ConvertFilesToFullPath(sources, vcPro.ProjectDirectory)); - writeFilesToPro(sw, "FORMS", - ProjectExporter.ConvertFilesToFullPath(uifiles, vcPro.ProjectDirectory)); - - var tsFiles = new List(1); - tsFiles.Add(vcFile.FullPath); - writeFilesToPro(sw, "TRANSLATIONS", tsFiles); - - if (!string.IsNullOrEmpty(codec)) - sw.WriteLine("CODECFORTR = " + codec); - } - - cmdLine = string.Empty; - if (!string.IsNullOrEmpty(options)) - cmdLine += options + " "; - cmdLine += "\"" + temporaryProFile + "\""; - } - var success = true; try { Messages.PaneMessage(pro.DTE, "--- (lupdate) file: " + vcFile.FullPath); @@ -190,13 +154,8 @@ namespace QtVsTools Messages.DisplayErrorMessage(e.Message); } - if (temporaryProFile != null && File.Exists(temporaryProFile)) { - File.Delete(temporaryProFile); - temporaryProFile = temporaryProFile.Substring(0, temporaryProFile.Length - 3); - temporaryProFile += "TMP"; - if (File.Exists(temporaryProFile)) - File.Delete(temporaryProFile); - } + if (File.Exists(lstFilePath)) + File.Delete(lstFilePath); return success; } @@ -302,6 +261,9 @@ namespace QtVsTools RedirectStandardOutput = true }; + if (!HelperFunctions.SetVCVars(process.StartInfo)) + Messages.DisplayErrorMessage("--- (Translation): Error setting VC vars"); + process.Start(); var thread = new Thread(ReadQtStandardError); thread.Start(new ThreadParameter -- cgit v1.2.3