| | |
| | | /****************************************************************************
|
| | | **
|
| | | ** Copyright (C) 2016 The Qt Company Ltd.
|
| | | ** Copyright (C) 2022 The Qt Company Ltd.
|
| | | ** Contact: https://www.qt.io/licensing/
|
| | | **
|
| | | ** This file is part of the Qt VS Tools.
|
| | |
| | | **
|
| | | ****************************************************************************/
|
| | |
|
| | | using EnvDTE;
|
| | | using Microsoft.VisualStudio.VCProjectEngine;
|
| | | using System;
|
| | | using System.Collections.Concurrent;
|
| | | using System.Collections.Generic;
|
| | | using System.IO;
|
| | | using System.Linq;
|
| | | using System.Text;
|
| | | using System.Text.RegularExpressions;
|
| | | using System.Threading.Tasks;
|
| | | using System.Windows.Forms;
|
| | | using System.Xml;
|
| | | using QtVsTools.Core.QtMsBuild;
|
| | | using Microsoft.VisualStudio.Shell;
|
| | | using Microsoft.VisualStudio.VCProjectEngine;
|
| | | using EnvDTE;
|
| | |
|
| | | namespace QtVsTools.Core
|
| | | {
|
| | | using QtMsBuild;
|
| | |
|
| | | /// <summary>
|
| | | /// QtProject holds the Qt specific properties for a Visual Studio project.
|
| | | /// There exists at most one QtProject per EnvDTE.Project.
|
| | |
| | | private VCProject vcPro;
|
| | | private MocCmdChecker mocCmdChecker;
|
| | | private Array lastConfigurationRowNames;
|
| | | private static Dictionary<Project, QtProject> instances = new Dictionary<Project, QtProject>();
|
| | | private QtMsBuildContainer qtMsBuild;
|
| | | private static readonly Dictionary<Project, QtProject> instances = new Dictionary<Project, QtProject>();
|
| | | private readonly QtMsBuildContainer qtMsBuild;
|
| | |
|
| | | public static QtVsTools.VisualStudio.IProjectTracker ProjectTracker { get; set; }
|
| | |
|
| | | public static QtProject Create(VCProject vcProject)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | | return Create((Project)vcProject.Object);
|
| | | }
|
| | |
|
| | |
| | |
|
| | | private QtProject(Project project)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (project == null)
|
| | | throw new QtVSException(SR.GetString("QtProject_CannotConstructWithoutValidProject"));
|
| | | envPro = project;
|
| | |
| | | return string.Empty;
|
| | | try {
|
| | | return config.GetEvaluatedPropertyValue(itemType + "RuleName");
|
| | | } catch (Exception e) {
|
| | | System.Diagnostics.Debug.WriteLine(
|
| | | e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
|
| | | } catch (Exception exception) {
|
| | | exception.Log();
|
| | | return string.Empty;
|
| | | }
|
| | | }
|
| | |
|
| | | public static string GetRuleName(VCProject project, string itemType)
|
| | | {
|
| | | if (project == null)
|
| | | return string.Empty;
|
| | | var configs = project.Configurations as IVCCollection;
|
| | | if (configs.Count == 0)
|
| | | return string.Empty;
|
| | | try {
|
| | | var firstConfig = configs.Item(1) as VCConfiguration;
|
| | | if (firstConfig == null)
|
| | | return string.Empty;
|
| | | return GetRuleName(firstConfig, itemType);
|
| | | } catch (Exception e) {
|
| | | System.Diagnostics.Debug.WriteLine(
|
| | | e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
|
| | | return string.Empty;
|
| | | }
|
| | | }
|
| | |
|
| | | public string GetRuleName(string itemType)
|
| | | {
|
| | | return GetRuleName(vcPro, itemType);
|
| | | }
|
| | |
|
| | | public static bool IsQtMsBuildEnabled(VCProject project)
|
| | |
| | |
|
| | | public static bool IsQtMsBuildEnabled(Project project)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (project == null)
|
| | | return false;
|
| | | return IsQtMsBuildEnabled(project.Object as VCProject);
|
| | |
| | | private bool? isQtMsBuildEnabled = null;
|
| | | public bool IsQtMsBuildEnabled()
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (!isQtMsBuildEnabled.HasValue) {
|
| | | if (vcPro != null)
|
| | | isQtMsBuildEnabled = IsQtMsBuildEnabled(vcPro);
|
| | |
| | | {
|
| | | get
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var ret = false;
|
| | | if (lastConfigurationRowNames == null) {
|
| | | lastConfigurationRowNames = envPro.ConfigurationManager.ConfigurationRowNames as Array;
|
| | |
| | | /// <param name="uiFile">name of the ui file</param>
|
| | | public string GetUiGeneratedFileName(string uiFile)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var fi = new FileInfo(uiFile);
|
| | | var file = fi.Name;
|
| | | if (HelperFunctions.IsUicFile(file)) {
|
| | |
| | | /// replaced by the value of configName.
|
| | | /// <param name="file">full file name of either the header or the source file</param>
|
| | | /// <returns></returns>
|
| | | private string GetRelativeMocFilePath(string file, string configName, string platformName)
|
| | | private string GetRelativeMocFilePath(string file, string configName = null,
|
| | | string platformName = null)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var fileName = GetMocFileName(file);
|
| | | if (fileName == null)
|
| | | return null;
|
| | |
| | | return mocDir;
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// Returns the file name of the generated moc file relative to the
|
| | | /// project directory.
|
| | | /// </summary>
|
| | | /// The returned file path may contain the macros $(ConfigurationName) and $(PlatformName).
|
| | | /// <param name="file">full file name of either the header or the source file</param>
|
| | | /// <returns></returns>
|
| | | private string GetRelativeMocFilePath(string file)
|
| | | {
|
| | | return GetRelativeMocFilePath(file, null, null);
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// Marks the specified project as a Qt project.
|
| | | /// </summary>
|
| | | public void MarkAsQtProject()
|
| | | {
|
| | | vcPro.keyword = string.Format("{0}_v{1}",
|
| | | Resources.qtProjectKeyword, Resources.qtProjectFormatVersion);
|
| | | }
|
| | |
|
| | | public static int GetFormatVersion(VCProject vcPro)
|
| | | {
|
| | | if (vcPro == null)
|
| | | return 0;
|
| | | if (vcPro.keyword.StartsWith(Resources.qtProjectKeyword,
|
| | | StringComparison.InvariantCultureIgnoreCase)) {
|
| | | if (vcPro.keyword.StartsWith(Resources.qtProjectKeyword, StringComparison.Ordinal))
|
| | | return Convert.ToInt32(vcPro.keyword.Substring(6));
|
| | | } else if (vcPro.keyword.StartsWith(Resources.qtProjectV2Keyword,
|
| | | StringComparison.InvariantCultureIgnoreCase)) {
|
| | | if (vcPro.keyword.StartsWith(Resources.qtProjectV2Keyword, StringComparison.Ordinal))
|
| | | return 200;
|
| | | } else {
|
| | | return 0;
|
| | | }
|
| | | return 0;
|
| | | }
|
| | |
|
| | | public static int GetFormatVersion(Project pro)
|
| | | {
|
| | | if (pro == null)
|
| | | return 0;
|
| | | return GetFormatVersion(pro.Object as VCProject);
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | | return GetFormatVersion(pro?.Object as VCProject);
|
| | | }
|
| | |
|
| | | public int FormatVersion { get { return GetFormatVersion(Project); } }
|
| | |
|
| | | public string GetPropertyValue(string propName)
|
| | | public int FormatVersion
|
| | | {
|
| | | return GetPropertyValue(Project, propName);
|
| | | }
|
| | |
|
| | | public string GetPropertyValue(string configName, string platformName, string propName)
|
| | | {
|
| | | return GetPropertyValue(Project, configName, platformName, propName);
|
| | | get
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | | return GetFormatVersion(Project);
|
| | | }
|
| | | }
|
| | |
|
| | | public static string GetPropertyValue(
|
| | | EnvDTE.Project dteProject,
|
| | | string propName)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var activeConfig = dteProject.ConfigurationManager?.ActiveConfiguration;
|
| | | if (activeConfig == null)
|
| | | return null;
|
| | |
| | | EnvDTE.Configuration dteConfig,
|
| | | string propName)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (dteProject == null || dteConfig == null)
|
| | | return null;
|
| | | return GetPropertyValue(
|
| | |
| | | dteConfig.ConfigurationName,
|
| | | dteConfig.PlatformName,
|
| | | propName);
|
| | | }
|
| | |
|
| | | public static string GetPropertyValue(
|
| | | EnvDTE.Project dteProject,
|
| | | string configName,
|
| | | string platformName,
|
| | | string propName)
|
| | | {
|
| | | return GetPropertyValue(
|
| | | dteProject.Object as VCProject, configName, platformName, propName);
|
| | | }
|
| | |
|
| | | public static string GetPropertyValue(
|
| | |
| | | return vcConfig.GetEvaluatedPropertyValue(propName);
|
| | | }
|
| | |
|
| | | public void AddDefine(string define, uint bldConf)
|
| | | {
|
| | | foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) {
|
| | | var compiler = CompilerToolWrapper.Create(config);
|
| | |
|
| | | if (((!IsDebugConfiguration(config)) && ((bldConf & BuildConfig.Release) != 0)) ||
|
| | | ((IsDebugConfiguration(config)) && ((bldConf & BuildConfig.Debug) != 0))) {
|
| | | compiler.AddPreprocessorDefinition(define);
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | public void AddModule(int id)
|
| | | {
|
| | | if (HasModule(id))
|
| | | return;
|
| | |
|
| | | var vm = QtVersionManager.The();
|
| | | var versionInfo = vm.GetVersionInfo(Project);
|
| | | if (versionInfo == null)
|
| | | versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion());
|
| | |
|
| | | foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) {
|
| | |
|
| | | var info = QtModules.Instance.Module(id);
|
| | | if (FormatVersion >= Resources.qtMinFormatVersion_Settings) {
|
| | | var config3 = config as VCConfiguration3;
|
| | | if (config3 == null)
|
| | | continue;
|
| | | if (!string.IsNullOrEmpty(info.proVarQT)) {
|
| | | var qtModulesValue = config.GetUnevaluatedPropertyValue("QtModules");
|
| | | var qtModules = new HashSet<string>(
|
| | | !string.IsNullOrEmpty(qtModulesValue)
|
| | | ? qtModulesValue.Split(';')
|
| | | : new string[] { });
|
| | | qtModules.UnionWith(info.proVarQT.Split(' '));
|
| | | config3.SetPropertyValue(Resources.projLabelQtSettings, true,
|
| | | "QtModules", string.Join(";", qtModules));
|
| | | }
|
| | | // In V3 project format, compiler and linker options
|
| | | // required by modules are set by Qt/MSBuild.
|
| | | continue;
|
| | | }
|
| | |
|
| | | var compiler = CompilerToolWrapper.Create(config);
|
| | | var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool");
|
| | |
|
| | | if (compiler != null) {
|
| | | foreach (var define in info.Defines)
|
| | | compiler.AddPreprocessorDefinition(define);
|
| | |
|
| | | var incPathList = info.GetIncludePath();
|
| | | foreach (var incPath in incPathList)
|
| | | compiler.AddAdditionalIncludeDirectories(incPath);
|
| | | }
|
| | | if (linker != null) {
|
| | | var moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo);
|
| | | var linkerWrapper = new LinkerToolWrapper(linker);
|
| | | var additionalDeps = linkerWrapper.AdditionalDependencies;
|
| | | var dependenciesChanged = false;
|
| | | if (additionalDeps == null || additionalDeps.Count == 0) {
|
| | | additionalDeps = moduleLibs;
|
| | | dependenciesChanged = true;
|
| | | } else {
|
| | | foreach (var moduleLib in moduleLibs) {
|
| | | if (!additionalDeps.Contains(moduleLib)) {
|
| | | additionalDeps.Add(moduleLib);
|
| | | dependenciesChanged = true;
|
| | | }
|
| | | }
|
| | | }
|
| | | if (dependenciesChanged)
|
| | | linkerWrapper.AdditionalDependencies = additionalDeps;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | public void RemoveModule(int id)
|
| | | {
|
| | | foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) {
|
| | | var compiler = CompilerToolWrapper.Create(config);
|
| | | var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool");
|
| | |
|
| | | var info = QtModules.Instance.Module(id);
|
| | | if (compiler != null) {
|
| | | foreach (var define in info.Defines)
|
| | | compiler.RemovePreprocessorDefinition(define);
|
| | | var additionalIncludeDirs = compiler.AdditionalIncludeDirectories;
|
| | | if (additionalIncludeDirs != null) {
|
| | | var lst = new List<string>(additionalIncludeDirs);
|
| | | foreach (var includePath in info.IncludePath) {
|
| | | lst.Remove(includePath);
|
| | | lst.Remove('\"' + includePath + '\"');
|
| | | }
|
| | | compiler.AdditionalIncludeDirectories = lst;
|
| | | }
|
| | | }
|
| | | if (linker != null && linker.AdditionalDependencies != null) {
|
| | | var linkerWrapper = new LinkerToolWrapper(linker);
|
| | | var vm = QtVersionManager.The();
|
| | | var versionInfo = vm.GetVersionInfo(Project);
|
| | | if (versionInfo == null)
|
| | | versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion());
|
| | |
|
| | | var moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo);
|
| | | var additionalDependencies = linkerWrapper.AdditionalDependencies;
|
| | | var dependenciesChanged = false;
|
| | | foreach (var moduleLib in moduleLibs)
|
| | | dependenciesChanged |= additionalDependencies.Remove(moduleLib);
|
| | | if (dependenciesChanged)
|
| | | linkerWrapper.AdditionalDependencies = additionalDependencies;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | public void UpdateModules(VersionInformation oldVersion, VersionInformation newVersion)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) {
|
| | | var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool");
|
| | |
|
| | |
| | | var additionalDependencies = linkerWrapper.AdditionalDependencies;
|
| | |
|
| | | var libsDesktop = new List<string>();
|
| | | foreach (var module in QtModules.Instance.GetAvailableModules()) {
|
| | | foreach (var module in QtModules.Instance.GetAvailableModules(newVersion.qtMajor)) {
|
| | | if (HasModule(module.Id))
|
| | | libsDesktop.AddRange(module.AdditionalLibraries);
|
| | | }
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | // TODO: remove once all callers are moved into Legacy namespace
|
| | | public bool HasModule(int id)
|
| | | {
|
| | | var foundInIncludes = false;
|
| | | var foundInLibs = false;
|
| | |
|
| | | var vm = QtVersionManager.The();
|
| | | var versionInfo = vm.GetVersionInfo(Project);
|
| | | if (versionInfo == null)
|
| | | versionInfo = vm.GetVersionInfo(vm.GetDefaultVersion());
|
| | | if (versionInfo == null)
|
| | | return false; // neither a default or project Qt version
|
| | | var info = QtModules.Instance.Module(id);
|
| | | if (info == null)
|
| | | return false;
|
| | |
|
| | | foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) {
|
| | | var compiler = CompilerToolWrapper.Create(config);
|
| | | var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool");
|
| | |
|
| | | if (compiler != null) {
|
| | | if (compiler.GetAdditionalIncludeDirectories() == null)
|
| | | continue;
|
| | | var incPathList = info.GetIncludePath();
|
| | | var includeDirs = compiler.GetAdditionalIncludeDirectoriesList();
|
| | | foundInIncludes = (incPathList.Count > 0);
|
| | | foreach (var incPath in incPathList) {
|
| | | var fixedIncludeDir = FixFilePathForComparison(incPath);
|
| | | if (!includeDirs.Any(dir =>
|
| | | FixFilePathForComparison(dir) == fixedIncludeDir)) {
|
| | | foundInIncludes = false;
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | if (foundInIncludes)
|
| | | break;
|
| | |
|
| | | List<string> libs = null;
|
| | | if (linker != null) {
|
| | | var linkerWrapper = new LinkerToolWrapper(linker);
|
| | | libs = linkerWrapper.AdditionalDependencies;
|
| | | }
|
| | |
|
| | | if (libs != null) {
|
| | | var moduleLibs = info.GetLibs(IsDebugConfiguration(config), versionInfo);
|
| | | foundInLibs = moduleLibs.All(moduleLib => libs.Contains(moduleLib));
|
| | | }
|
| | | }
|
| | | return foundInIncludes || foundInLibs;
|
| | | }
|
| | |
|
| | | public void WriteProjectBasicConfigurations(uint type, bool usePrecompiledHeader)
|
| | | {
|
| | | WriteProjectBasicConfigurations(type, usePrecompiledHeader, null);
|
| | | }
|
| | |
|
| | | public void WriteProjectBasicConfigurations(uint type, bool usePrecompiledHeader, VersionInformation vi)
|
| | | {
|
| | | var configType = ConfigurationTypes.typeApplication;
|
| | | var targetExtension = ".exe";
|
| | | string qtVersion = null;
|
| | | var vm = QtVersionManager.The();
|
| | | if (vi == null) {
|
| | | qtVersion = vm.GetDefaultVersion();
|
| | | vi = vm.GetVersionInfo(qtVersion);
|
| | | }
|
| | |
|
| | | switch (type & TemplateType.ProjectType) {
|
| | | case TemplateType.DynamicLibrary:
|
| | | configType = ConfigurationTypes.typeDynamicLibrary;
|
| | | targetExtension = ".dll";
|
| | | break;
|
| | | case TemplateType.StaticLibrary:
|
| | | configType = ConfigurationTypes.typeStaticLibrary;
|
| | | targetExtension = ".lib";
|
| | | break;
|
| | | }
|
| | |
|
| | | foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) {
|
| | | config.ConfigurationType = configType;
|
| | | var compiler = CompilerToolWrapper.Create(config);
|
| | | var linker = (VCLinkerTool)((IVCCollection)config.Tools).Item("VCLinkerTool");
|
| | | var librarian = (VCLibrarianTool)((IVCCollection)config.Tools).Item("VCLibrarianTool");
|
| | |
|
| | | if (linker != null) {
|
| | | if ((type & TemplateType.ConsoleSystem) != 0)
|
| | | linker.SubSystem = subSystemOption.subSystemConsole;
|
| | | else
|
| | | linker.SubSystem = subSystemOption.subSystemWindows;
|
| | |
|
| | | linker.OutputFile = "$(OutDir)\\$(ProjectName)" + targetExtension;
|
| | | } else {
|
| | | librarian.OutputFile = "$(OutDir)\\$(ProjectName)" + targetExtension;
|
| | | }
|
| | |
|
| | | if ((type & TemplateType.PluginProject) != 0)
|
| | | compiler.AddPreprocessorDefinition("QT_PLUGIN");
|
| | |
|
| | | var isDebugConfiguration = false;
|
| | | if (config.Name.StartsWith("Release", StringComparison.Ordinal)) {
|
| | | compiler.SetDebugInformationFormat(debugOption.debugDisabled);
|
| | | compiler.RuntimeLibrary = runtimeLibraryOption.rtMultiThreadedDLL;
|
| | | } else if (config.Name.StartsWith("Debug", StringComparison.Ordinal)) {
|
| | | isDebugConfiguration = true;
|
| | | compiler.SetOptimization(optimizeOption.optimizeDisabled);
|
| | | compiler.SetDebugInformationFormat(debugOption.debugEnabled);
|
| | | compiler.RuntimeLibrary = runtimeLibraryOption.rtMultiThreadedDebugDLL;
|
| | | }
|
| | |
|
| | | compiler.SetTreatWChar_tAsBuiltInType(true);
|
| | |
|
| | | if (linker != null)
|
| | | linker.GenerateDebugInformation = isDebugConfiguration;
|
| | |
|
| | | if (usePrecompiledHeader)
|
| | | UsePrecompiledHeaders(config);
|
| | | }
|
| | | if ((type & TemplateType.PluginProject) != 0)
|
| | | MarkAsDesignerPluginProject();
|
| | | }
|
| | |
|
| | | public void MarkAsDesignerPluginProject()
|
| | | {
|
| | | Project.Globals["IsDesignerPlugin"] = true.ToString();
|
| | | if (!Project.Globals.get_VariablePersists("IsDesignerPlugin"))
|
| | | Project.Globals.set_VariablePersists("IsDesignerPlugin", true);
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | | return Legacy.QtProject.HasModule(envPro, id);
|
| | | }
|
| | |
|
| | | public void AddUic4BuildStepMsBuild(
|
| | |
| | | string description,
|
| | | string outputFile)
|
| | | {
|
| | | var file = config.File as VCFile;
|
| | | if (file != null)
|
| | | if (config.File is VCFile file)
|
| | | file.ItemType = QtUic.ItemTypeName;
|
| | | qtMsBuild.SetItemProperty(config, QtUic.Property.ExecutionDescription, description);
|
| | | qtMsBuild.SetItemProperty(config, QtUic.Property.OutputFile, outputFile);
|
| | |
| | | /// <param name="file">file</param>
|
| | | public void AddUic4BuildStep(VCFile file)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (GetFormatVersion(vcPro) >= Resources.qtMinFormatVersion_Settings) {
|
| | | file.ItemType = QtUic.ItemTypeName;
|
| | | return;
|
| | |
| | | }
|
| | | }
|
| | | if (toolSettings == CustomTool.CustomBuildStep && !uiFileExists)
|
| | | AddFileInFilter(Filters.GeneratedFiles(), uiFile);
|
| | | AddFileInFilter(Filters.GeneratedFiles(), uiFile, false);
|
| | | } catch {
|
| | | throw new QtVSException(SR.GetString("QtProject_CannotAddUicStep", file.FullPath));
|
| | | }
|
| | |
| | | public string GetDefines(VCFileConfiguration conf)
|
| | | {
|
| | | var defines = string.Empty;
|
| | | var propsFile = conf.Tool as IVCRulePropertyStorage;
|
| | | var projectConfig = conf.ProjectConfiguration as VCConfiguration;
|
| | | var propsProject = projectConfig.Rules.Item("CL") as IVCRulePropertyStorage;
|
| | | if (propsFile != null) {
|
| | | if (conf.Tool is IVCRulePropertyStorage propsFile) {
|
| | | try {
|
| | | defines = propsFile.GetUnevaluatedPropertyValue("PreprocessorDefinitions");
|
| | | } catch { }
|
| | | }
|
| | | if (string.IsNullOrEmpty(defines) && propsProject != null) {
|
| | |
|
| | | var projectConfig = conf.ProjectConfiguration as VCConfiguration;
|
| | | if (string.IsNullOrEmpty(defines)
|
| | | && projectConfig?.Rules.Item("CL") is IVCRulePropertyStorage propsProject) {
|
| | | try {
|
| | | defines = propsProject.GetUnevaluatedPropertyValue("PreprocessorDefinitions");
|
| | | } catch { }
|
| | |
| | | var projectConfig = conf.ProjectConfiguration as VCConfiguration;
|
| | | includeList.AddRange(GetIncludesFromCompilerTool(CompilerToolWrapper.Create(projectConfig)));
|
| | |
|
| | | var propertySheets = projectConfig.PropertySheets as IVCCollection;
|
| | | if (propertySheets != null) {
|
| | | if (projectConfig.PropertySheets is IVCCollection propertySheets) {
|
| | | foreach (VCPropertySheet sheet in propertySheets)
|
| | | includeList.AddRange(GetIncludesFromPropertySheet(sheet));
|
| | | }
|
| | |
|
| | | |
| | | var ompModified = new List<string>();
|
| | | string sDir = "$(SolutionDir)";
|
| | | foreach (string inc in includeList) {
|
| | |
| | | private List<string> GetIncludesFromPropertySheet(VCPropertySheet sheet)
|
| | | {
|
| | | var includeList = GetIncludesFromCompilerTool(CompilerToolWrapper.Create(sheet));
|
| | | var propertySheets = sheet.PropertySheets as IVCCollection;
|
| | | if (propertySheets != null) {
|
| | | if (sheet.PropertySheets is IVCCollection propertySheets) {
|
| | | foreach (VCPropertySheet subSheet in propertySheets)
|
| | | includeList.AddRange(GetIncludesFromPropertySheet(subSheet));
|
| | | }
|
| | |
| | | return new List<string>();
|
| | | }
|
| | |
|
| | | private static bool IsDebugConfiguration(VCConfiguration conf)
|
| | | {
|
| | | var tool = CompilerToolWrapper.Create(conf);
|
| | | if (tool != null) {
|
| | | return tool.RuntimeLibrary == runtimeLibraryOption.rtMultiThreadedDebug
|
| | | || tool.RuntimeLibrary == runtimeLibraryOption.rtMultiThreadedDebugDLL;
|
| | | }
|
| | | return false;
|
| | | }
|
| | |
|
| | | private string GetPCHMocOptions(VCFile file, CompilerToolWrapper compiler)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | // As .moc files are included, we should not add anything there
|
| | | if (!HelperFunctions.IsHeaderFile(file.Name))
|
| | | return string.Empty;
|
| | |
| | | VCFileConfiguration workFileConfig,
|
| | | VCFile mocFile)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var hasDifferentMocFilePerConfig =
|
| | | QtVSIPSettings.HasDifferentMocFilePerConfig(envPro);
|
| | | var hasDifferentMocFilePerPlatform =
|
| | | QtVSIPSettings.HasDifferentMocFilePerPlatform(envPro);
|
| | |
|
| | | var workFile = workFileConfig.File as VCFile;
|
| | | var mocFileName = GetMocFileName(sourceFile.FullPath);
|
| | | var mocableIsCPP = HelperFunctions.IsMocFile(mocFileName);
|
| | | var vcConfig = workFileConfig.ProjectConfiguration as VCConfiguration;
|
| | |
| | | string includes,
|
| | | string description)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var workFile = workFileConfig.File as VCFile;
|
| | | var mocFileName = GetMocFileName(sourceFile.FullPath);
|
| | | var mocableIsCPP = HelperFunctions.IsMocFile(mocFileName);
|
| | |
| | | + mocFileName + "))";
|
| | | var regExp = new Regex(pattern);
|
| | | var matchList = regExp.Matches(tool.Outputs.Replace(ProjectMacros.Name, baseFileName));
|
| | |
|
| | | if (matchList.Count > 0) {
|
| | | if (matchList[0].Length > 0)
|
| | | outputMocFile = matchList[0].ToString();
|
| | |
| | | string includes,
|
| | | string description)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var baseFileName = sourceFile.Name.Remove(sourceFile.Name.LastIndexOf('.'));
|
| | | var outputMocFile = GetRelativeMocFilePath(sourceFile.FullPath);
|
| | | var outputMocPath = Path.GetDirectoryName(outputMocFile);
|
| | |
| | | VCFileConfiguration workConfig,
|
| | | CustomTool toolSettings)
|
| | | {
|
| | | var workFile = workConfig.File as VCFile;
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var mocFileName = GetMocFileName(sourceFile.FullPath);
|
| | | var mocableIsCPP = HelperFunctions.IsMocFile(mocFileName);
|
| | | var vcConfig = workConfig.ProjectConfiguration as VCConfiguration;
|
| | |
| | | /// <param name="file">file</param>
|
| | | public void AddMocStep(VCFile file)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (GetFormatVersion(vcPro) >= Resources.qtMinFormatVersion_Settings) {
|
| | | file.ItemType = QtMoc.ItemTypeName;
|
| | | if (HelperFunctions.IsSourceFile(file.FullPath)) {
|
| | |
| | | File.WriteAllText(cbtFullPath, string.Format(
|
| | | "This is a dummy file needed to create {0}", mocFileName));
|
| | | file = AddFileInSubfilter(Filters.GeneratedFiles(), null, cbtFullPath, true);
|
| | | var mocFileItem = file.Object as ProjectItem;
|
| | | if (mocFileItem != null)
|
| | | if (file.Object is ProjectItem mocFileItem)
|
| | | HelperFunctions.EnsureCustomBuildToolAvailable(mocFileItem);
|
| | | }
|
| | |
|
| | |
| | |
|
| | | public bool HasMocStep(VCFile file, string mocOutDir = null)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (file.ItemType == QtMoc.ItemTypeName)
|
| | | return true;
|
| | |
|
| | |
| | |
|
| | | public void RefreshRccSteps()
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | Messages.Print("\r\n=== Update rcc steps ===");
|
| | | var files = GetResourceFiles();
|
| | |
|
| | |
| | |
|
| | | public void RefreshRccSteps(string oldRccDir)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | RefreshRccSteps();
|
| | | UpdateCompilerIncludePaths(oldRccDir, QtVSIPSettings.GetRccDirectory(envPro));
|
| | | }
|
| | |
| | | string nameOnly,
|
| | | string qrcCppFile)
|
| | | {
|
| | | var file = vfc.File as VCFile;
|
| | | if (file != null)
|
| | | if (vfc.File is VCFile file)
|
| | | file.ItemType = QtRcc.ItemTypeName;
|
| | | qtMsBuild.SetItemProperty(vfc,
|
| | | QtRcc.Property.ExecutionDescription, "Rcc'ing " + ProjectMacros.FileName + "...");
|
| | |
| | | string nameOnly,
|
| | | string qrcCppFile)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var qrcFile = vfc.File as VCFile;
|
| | | var rccOptsCfg = rccOpts;
|
| | | var cmdLine = string.Empty;
|
| | |
|
| | | var cbt = HelperFunctions.GetCustomBuildTool(vfc);
|
| | |
|
| | | cbt.AdditionalDependencies = filesInQrcFile;
|
| | |
|
| | | cbt.Description = "Rcc'ing " + ProjectMacros.FileName + "...";
|
| | |
|
| | | cbt.Outputs = qrcCppFile.Replace(nameOnly, ProjectMacros.Name);
|
| | |
|
| | | cmdLine += "\"" + Resources.rcc4Command + "\""
|
| | |
| | |
|
| | | public void UpdateRccStep(VCFile qrcFile, RccOptions rccOpts)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (GetFormatVersion(vcPro) >= Resources.qtMinFormatVersion_Settings) {
|
| | | qrcFile.ItemType = QtRcc.ItemTypeName;
|
| | | return;
|
| | |
| | | IsQtMsBuildEnabled() ? CustomTool.MSBuildTarget : CustomTool.CustomBuildStep;
|
| | |
|
| | | var vcpro = (VCProject)qrcFile.project;
|
| | | var dteObject = ((Project)vcpro.Object).DTE;
|
| | |
|
| | | var qtPro = Create(vcpro);
|
| | | var parser = new QrcParser(qrcFile.FullPath);
|
| | | var filesInQrcFile = ProjectMacros.Path;
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | static public void ExcludeFromAllBuilds(VCFile file)
|
| | | public static void ExcludeFromAllBuilds(VCFile file)
|
| | | {
|
| | | if (file == null)
|
| | | return;
|
| | |
| | | List<VCFile> GetCppMocFiles(VCFile cppFile)
|
| | | {
|
| | | List<VCFile> mocFiles = new List<VCFile>();
|
| | | var vcProj = cppFile.project as VCProject;
|
| | | if (vcProj != null) {
|
| | | if (cppFile.project is VCProject vcProj) {
|
| | | mocFiles.AddRange(from VCFile vcFile
|
| | | in (IVCCollection)vcProj.Files
|
| | | where vcFile.ItemType == "CustomBuild"
|
| | |
| | |
|
| | | bool HasCppMocFiles(VCFile cppFile)
|
| | | {
|
| | | if (!IsQtMsBuildEnabled()) {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (!IsQtMsBuildEnabled())
|
| | | return File.Exists(Path.ChangeExtension(cppFile.FullPath, ".cbt"));
|
| | | } else {
|
| | | var vcProj = cppFile.project as VCProject;
|
| | | if (vcProj != null) {
|
| | | foreach (VCFile vcFile in (IVCCollection)vcProj.Files) {
|
| | | if (vcFile.ItemType == "CustomBuild") {
|
| | | if (IsCppMocFileCustomBuild(vcProj, vcFile, cppFile))
|
| | | return true;
|
| | | } else if (vcFile.ItemType == QtMoc.ItemTypeName) {
|
| | | if (IsCppMocFileQtMsBuild(vcProj, vcFile, cppFile))
|
| | | return true;
|
| | | }
|
| | |
|
| | | if (cppFile.project is VCProject vcProj) {
|
| | | foreach (VCFile vcFile in (IVCCollection)vcProj.Files) {
|
| | | if (vcFile.ItemType == "CustomBuild") {
|
| | | if (IsCppMocFileCustomBuild(vcProj, vcFile, cppFile))
|
| | | return true;
|
| | | } else if (vcFile.ItemType == QtMoc.ItemTypeName) {
|
| | | if (IsCppMocFileQtMsBuild(vcProj, vcFile, cppFile))
|
| | | return true;
|
| | | }
|
| | | }
|
| | | return false;
|
| | | }
|
| | | return false;
|
| | | }
|
| | |
|
| | | public void RemoveMocStep(VCFile file)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (file.ItemType == QtMoc.ItemTypeName) {
|
| | | RemoveMocStepQtMsBuild(file);
|
| | | } else if (HelperFunctions.IsHeaderFile(file.Name)) {
|
| | |
| | | /// <param name="file">file</param>
|
| | | public void RemoveMocStepCustomBuild(VCFile file)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | | try {
|
| | | if (!HasMocStep(file))
|
| | | return;
|
| | |
| | | public VCFile GetFileFromProject(string fileName)
|
| | | {
|
| | | fileName = HelperFunctions.NormalizeRelativeFilePath(fileName);
|
| | |
|
| | | var nf = fileName;
|
| | | if (!HelperFunctions.IsAbsoluteFilePath(fileName))
|
| | | nf = HelperFunctions.NormalizeFilePath(vcPro.ProjectDirectory + "\\" + fileName);
|
| | | nf = nf.ToLower();
|
| | | fileName = HelperFunctions.NormalizeFilePath(vcPro.ProjectDirectory + "\\" + fileName);
|
| | |
|
| | | foreach (VCFile f in (IVCCollection)vcPro.Files) {
|
| | | if (f.FullPath.ToLower() == nf)
|
| | | if (f.FullPath.Equals(fileName, StringComparison.OrdinalIgnoreCase))
|
| | | return f;
|
| | | }
|
| | | return null;
|
| | |
| | | {
|
| | | var fi = new FileInfo(HelperFunctions.NormalizeRelativeFilePath(fileName));
|
| | | foreach (VCFile f in (IVCCollection)vcPro.Files) {
|
| | | if (string.Equals(f.Name, fi.Name, StringComparison.OrdinalIgnoreCase))
|
| | | if (f.Name.Equals(fi.Name, StringComparison.OrdinalIgnoreCase))
|
| | | yield return f;
|
| | | }
|
| | | }
|
| | |
| | | foreach (VCFilter subfilter in (IVCCollection)filter.Filters)
|
| | | tmpList.AddRange(GetAllFilesFromFilter(subfilter));
|
| | | return tmpList;
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// Adds a file to a filter. If the filter doesn't exist yet, it
|
| | | /// will be created. (Doesn't check for duplicates)
|
| | | /// </summary>
|
| | | /// <param name="filter">fake filter</param>
|
| | | /// <param name="fileName">relative file name</param>
|
| | | /// <returns>A VCFile object of the added file.</returns>
|
| | | public VCFile AddFileInFilter(FakeFilter filter, string fileName)
|
| | | {
|
| | | return AddFileInFilter(filter, fileName, false);
|
| | | }
|
| | |
|
| | | public void RemoveItem(ProjectItem item)
|
| | | {
|
| | | foreach (ProjectItem tmpFilter in Project.ProjectItems) {
|
| | | if (tmpFilter.Name == item.Name) {
|
| | | tmpFilter.Remove();
|
| | | return;
|
| | | }
|
| | | foreach (ProjectItem tmpItem in tmpFilter.ProjectItems) {
|
| | | if (tmpItem.Name == item.Name) {
|
| | | tmpItem.Remove();
|
| | | return;
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | |
| | | return AddFileInSubfilter(filter, subfilterName, fileName, false);
|
| | | }
|
| | |
|
| | | public VCFile AddFileInSubfilter(FakeFilter filter, string subfilterName, string fileName, bool checkForDuplicates)
|
| | | public VCFile AddFileInSubfilter(FakeFilter filter, string subfilterName, string fileName,
|
| | | bool checkForDuplicates)
|
| | | {
|
| | | try {
|
| | | var vfilt = FindFilterFromGuid(filter.UniqueIdentifier);
|
| | |
| | | // check if user already created this filter... then add guid
|
| | | vfilt = FindFilterFromName(filter.Name);
|
| | | if (vfilt == null)
|
| | | throw new QtVSException(SR.GetString("QtProject_CannotAddFilter", filter.Name));
|
| | | throw new QtVSException($"Project cannot add filter {filter.Name}");
|
| | | } else {
|
| | | vfilt = (VCFilter)vcPro.AddFilter(filter.Name);
|
| | | }
|
| | |
| | | }
|
| | | if (!subfilterFound) {
|
| | | if (!vfilt.CanAddFilter(subfilterName))
|
| | | throw new QtVSException(SR.GetString("QtProject_CannotAddFilter", filter.Name));
|
| | |
|
| | | #if !(VS2017 || VS2019 || VS2022)
|
| | | // TODO: Enable once the freeze gets fixed in VS.
|
| | | vfilt = (VCFilter)vfilt.AddFilter(subfilterName);
|
| | | vfilt.Filter = "cpp;moc";
|
| | | vfilt.SourceControlFiles = false;
|
| | | #endif
|
| | | throw new QtVSException($"Project cannot add filter {filter.Name}");
|
| | | }
|
| | | }
|
| | |
|
| | |
| | |
|
| | | if (vfilt.CanAddFile(fileName))
|
| | | return (VCFile)(vfilt.AddFile(fileName));
|
| | | throw new QtVSException(SR.GetString("QtProject_CannotAddFile", fileName));
|
| | | } catch {
|
| | | throw new QtVSException(SR.GetString("QtProject_CannotAddFile", fileName));
|
| | | throw new QtVSException($"Cannot add file {fileName} to filter.");
|
| | | } catch (QtVSException) {
|
| | | throw;
|
| | | } catch (Exception e){
|
| | | throw new QtVSException($"Cannot add file {fileName} to filter.", e);
|
| | | }
|
| | |
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | public void AddDirectories()
|
| | | public static bool IsQtPlugin(Core.QtProject qtPro)
|
| | | {
|
| | | try {
|
| | | // resource directory
|
| | | var fi = new FileInfo(envPro.FullName);
|
| | | var dfi = new DirectoryInfo(fi.DirectoryName + "\\" + Resources.resourceDir);
|
| | | dfi.Create();
|
| | | } catch {
|
| | | throw new QtVSException(SR.GetString("QtProject_CannotCreateResourceDir"));
|
| | | }
|
| | | AddFilterToProject(Filters.ResourceFiles());
|
| | | }
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | public void Finish()
|
| | | {
|
| | | try {
|
| | | var solutionExplorer = dte.Windows.Item(Constants.vsWindowKindSolutionExplorer);
|
| | | if (solutionExplorer != null) {
|
| | | var hierarchy = (UIHierarchy)solutionExplorer.Object;
|
| | | var projects = hierarchy.UIHierarchyItems.Item(1).UIHierarchyItems;
|
| | | if (qtPro.FormatVersion < Resources.qtMinFormatVersion_Settings)
|
| | | return false;
|
| | |
|
| | | foreach (UIHierarchyItem itm in projects) {
|
| | | if (itm.Name == envPro.Name) {
|
| | | foreach (UIHierarchyItem i in itm.UIHierarchyItems) {
|
| | | if (i.Name == Filters.GeneratedFiles().Name)
|
| | | i.UIHierarchyItems.Expanded = false;
|
| | | }
|
| | | break;
|
| | | }
|
| | | }
|
| | | }
|
| | | } catch { }
|
| | |
|
| | | ProjectTracker?.AddProject(envPro);
|
| | | }
|
| | |
|
| | | public bool IsDesignerPluginProject()
|
| | | {
|
| | | var b = false;
|
| | | if (Project.Globals.get_VariablePersists("IsDesignerPlugin")) {
|
| | | var s = (string)Project.Globals["IsDesignerPlugin"];
|
| | | try {
|
| | | b = bool.Parse(s);
|
| | | } catch { }
|
| | | }
|
| | | return b;
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// Adds a file to a specified filter in a project.
|
| | | /// </summary>
|
| | | /// <param name="destName">name of the file in the project (relative to the project directory)</param>
|
| | | /// <param name="filter">filter</param>
|
| | | /// <returns>VCFile</returns>
|
| | | public VCFile AddFileToProject(string destName, FakeFilter filter)
|
| | | {
|
| | | VCFile file = null;
|
| | | if (filter != null)
|
| | | file = AddFileInFilter(filter, destName);
|
| | | else
|
| | | file = (VCFile)vcPro.AddFile(destName);
|
| | |
|
| | | if (file == null)
|
| | | return null;
|
| | |
|
| | | if (HelperFunctions.IsHeaderFile(file.Name)) {
|
| | | foreach (VCConfiguration config in (IVCCollection)vcPro.Configurations) {
|
| | | var compiler = CompilerToolWrapper.Create(config);
|
| | | if (compiler == null)
|
| | | continue;
|
| | |
|
| | | var paths = compiler.GetAdditionalIncludeDirectoriesList();
|
| | | var fi = new FileInfo(file.FullPath);
|
| | | var relativePath = HelperFunctions.GetRelativePath(ProjectDir, fi.Directory.ToString());
|
| | | var fixedRelativePath = FixFilePathForComparison(relativePath);
|
| | | if (!paths.Any(p => FixFilePathForComparison(p) == fixedRelativePath))
|
| | | compiler.AddAdditionalIncludeDirectories(relativePath);
|
| | | foreach (VCConfiguration config in qtPro.VCProject.Configurations as IVCCollection) {
|
| | | if ((config.Rules.Item("QtRule10_Settings") as IVCRulePropertyStorage)
|
| | | .GetEvaluatedPropertyValue("QtPlugin") == "true") {
|
| | | return true;
|
| | | }
|
| | | }
|
| | | return file;
|
| | | return false;
|
| | | }
|
| | |
|
| | | public static void MarkAsQtPlugin(Core.QtProject qtPro)
|
| | | {
|
| | | foreach (VCConfiguration config in qtPro.VCProject.Configurations as IVCCollection) {
|
| | | (config.Rules.Item("QtRule10_Settings") as IVCRulePropertyStorage)
|
| | | .SetPropertyValue("QtPlugin", "true");
|
| | | }
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// adjusts the whitespaces, tabs in the given file according to VS settings
|
| | | /// </summary>
|
| | | /// <param name="file"></param>
|
| | | public void AdjustWhitespace(string file)
|
| | | public static void AdjustWhitespace(DTE dte, string file)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (!File.Exists(file))
|
| | | return;
|
| | |
|
| | |
| | | return whitespaces;
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// Copy a file to the projects folder. Does not add the file to the project.
|
| | | /// </summary>
|
| | | /// <param name="srcFile">full name of the file to add</param>
|
| | | /// <param name="destFolder">the name of the project folder</param>
|
| | | /// <param name="destName">name of the file in the project (relative to the project directory)</param>
|
| | | /// <returns>full name of the destination file</returns>
|
| | | public static string CopyFileToFolder(string srcFile, string destFolder, string destName)
|
| | | {
|
| | | var fullDestName = destFolder + "\\" + destName;
|
| | | var fi = new FileInfo(fullDestName);
|
| | |
|
| | | var replace = true;
|
| | | if (File.Exists(fullDestName)) {
|
| | | if (DialogResult.No == MessageBox.Show(SR.GetString("QtProject_FileExistsInProjectFolder", destName)
|
| | | , SR.GetString("Resources_QtVsTools"), MessageBoxButtons.YesNo, MessageBoxIcon.Question)) {
|
| | | replace = false;
|
| | | }
|
| | | }
|
| | |
|
| | | if (replace) {
|
| | | if (!fi.Directory.Exists)
|
| | | fi.Directory.Create();
|
| | | File.Copy(srcFile, fullDestName, true);
|
| | | var attribs = File.GetAttributes(fullDestName);
|
| | | File.SetAttributes(fullDestName, attribs & (~FileAttributes.ReadOnly));
|
| | | }
|
| | | return fi.FullName;
|
| | | }
|
| | |
|
| | | public static void ReplaceTokenInFile(string file, string token, string replacement)
|
| | | {
|
| | | var text = string.Empty;
|
| | | try {
|
| | | var reader = new StreamReader(file);
|
| | | text = reader.ReadToEnd();
|
| | | reader.Close();
|
| | | } catch (Exception e) {
|
| | | Messages.DisplayErrorMessage(
|
| | | SR.GetString("QtProject_CannotReplaceTokenRead", token, replacement, e.ToString()));
|
| | | return;
|
| | | }
|
| | |
|
| | | try {
|
| | | if (token.ToUpper() == "%PRE_DEF%" && !Char.IsLetter(replacement[0]))
|
| | | replacement = "_" + replacement;
|
| | |
|
| | | text = text.Replace(token, replacement);
|
| | | var writer = new StreamWriter(file);
|
| | | writer.Write(text);
|
| | | writer.Close();
|
| | | } catch (Exception e) {
|
| | | Messages.DisplayErrorMessage(
|
| | | SR.GetString("QtProject_CannotReplaceTokenWrite", token, replacement, e.ToString()));
|
| | | }
|
| | | }
|
| | |
|
| | | public void RepairGeneratedFilesStructure()
|
| | | {
|
| | | DeleteGeneratedFiles();
|
| | |
|
| | | var files = new ConcurrentBag<VCFile>();
|
| | | Task.WaitAll(
|
| | | Task.Run(() =>
|
| | | Parallel.ForEach(((IVCCollection)vcPro.Files).Cast<VCFile>(), file =>
|
| | | {
|
| | | var name = file.Name;
|
| | | if (!HelperFunctions.IsHeaderFile(name) && !HelperFunctions.IsSourceFile(name))
|
| | | return;
|
| | | if (HelperFunctions.HasQObjectDeclaration(file))
|
| | | files.Add(file);
|
| | | })
|
| | | )
|
| | | );
|
| | |
|
| | | qtMsBuild.BeginSetItemProperties();
|
| | | foreach (var file in files) {
|
| | | RemoveMocStep(file);
|
| | | AddMocStep(file);
|
| | | }
|
| | | qtMsBuild.EndSetItemProperties();
|
| | | }
|
| | |
|
| | | public void TranslateFilterNames()
|
| | | {
|
| | | var filters = vcPro.Filters as IVCCollection;
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | public static string CreateQrcFile(string projectDir, string className, string destName)
|
| | | {
|
| | | var fullDestName = projectDir + "\\" + destName;
|
| | |
|
| | | if (!File.Exists(fullDestName)) {
|
| | | FileStream s = null;
|
| | | try {
|
| | | s = File.Open(fullDestName, FileMode.CreateNew);
|
| | | if (s.CanWrite) {
|
| | | using (var sw = new StreamWriter(s)) {
|
| | | s = null;
|
| | | sw.WriteLine("<RCC>");
|
| | | sw.WriteLine(" <qresource prefix=\"" + className + "\">");
|
| | | sw.WriteLine(" </qresource>");
|
| | | sw.WriteLine("</RCC>");
|
| | | }
|
| | | }
|
| | | } finally {
|
| | | if (s != null)
|
| | | s.Dispose();
|
| | | }
|
| | | var attribs = File.GetAttributes(fullDestName);
|
| | | File.SetAttributes(fullDestName, attribs & (~FileAttributes.ReadOnly));
|
| | | }
|
| | |
|
| | | var fi = new FileInfo(fullDestName);
|
| | | return fi.FullName;
|
| | | }
|
| | |
|
| | | public void AddActiveQtBuildStep(string version, string defFile = null)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (FormatVersion < Resources.qtMinFormatVersion_ClProperties)
|
| | | return;
|
| | |
|
| | |
| | |
|
| | | private void UpdateCompilerIncludePaths(string oldDir, string newDir)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var fixedOldDir = FixFilePathForComparison(oldDir);
|
| | | var dirs = new[] {
|
| | | FixFilePathForComparison(QtVSIPSettings.GetUicDirectory(envPro)),
|
| | |
| | |
|
| | | public void UpdateUicSteps(string oldUicDir, bool update_inc_path)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | Messages.Print("\r\n=== Update uic steps ===");
|
| | | var vcFilter = FindFilterFromGuid(Filters.GeneratedFiles().UniqueIdentifier);
|
| | | if (vcFilter != null) {
|
| | |
| | |
|
| | | qtMsBuild.BeginSetItemProperties();
|
| | | foreach (var file in files) {
|
| | | if (HelperFunctions.IsUicFile(file.Name) && !IsUic3File(file)) {
|
| | | if (HelperFunctions.IsUicFile(file.Name)) {
|
| | | AddUic4BuildStep(file);
|
| | | Messages.Print("Update uic step for " + file.Name + ".");
|
| | | ++updatedFiles;
|
| | |
| | | UpdateCompilerIncludePaths(oldUicDir, QtVSIPSettings.GetUicDirectory(envPro));
|
| | |
|
| | | Messages.Print("\r\n=== " + updatedFiles + " uic steps updated. ===\r\n");
|
| | | }
|
| | |
|
| | | private static bool IsUic3File(VCFile file)
|
| | | {
|
| | | foreach (VCFileConfiguration config in (IVCCollection)file.FileConfigurations) {
|
| | | var tool = HelperFunctions.GetCustomBuildTool(config);
|
| | | if (tool == null)
|
| | | return false;
|
| | | if (tool.CommandLine.IndexOf("uic3.exe", StringComparison.OrdinalIgnoreCase) > -1)
|
| | | return true;
|
| | | }
|
| | | return false;
|
| | | }
|
| | |
|
| | | public bool UsePrecompiledHeaders(VCConfiguration config)
|
| | | {
|
| | | var compiler = CompilerToolWrapper.Create(config);
|
| | | return UsePrecompiledHeaders(compiler);
|
| | | }
|
| | |
|
| | | private bool UsePrecompiledHeaders(CompilerToolWrapper compiler)
|
| | | {
|
| | | try {
|
| | | compiler.SetUsePrecompiledHeader(pchOption.pchUseUsingSpecific);
|
| | | var pcHeaderThrough = GetPrecompiledHeaderThrough();
|
| | | if (string.IsNullOrEmpty(pcHeaderThrough))
|
| | | pcHeaderThrough = "stdafx.h";
|
| | | compiler.SetPrecompiledHeaderThrough(pcHeaderThrough);
|
| | | var pcHeaderFile = GetPrecompiledHeaderFile();
|
| | | if (string.IsNullOrEmpty(pcHeaderFile))
|
| | | pcHeaderFile = ".\\$(ConfigurationName)/" + Project.Name + ".pch";
|
| | | compiler.SetPrecompiledHeaderFile(pcHeaderFile);
|
| | | return true;
|
| | | } catch {
|
| | | return false;
|
| | | }
|
| | | }
|
| | |
|
| | | public bool UsesPrecompiledHeaders()
|
| | |
| | | return null;
|
| | | }
|
| | |
|
| | | public string GetPrecompiledHeaderFile()
|
| | | {
|
| | | foreach (VCConfiguration config in vcPro.Configurations as IVCCollection) {
|
| | | var file = GetPrecompiledHeaderFile(config);
|
| | | if (!string.IsNullOrEmpty(file))
|
| | | return file;
|
| | | }
|
| | | return null;
|
| | | }
|
| | |
|
| | | public static string GetPrecompiledHeaderFile(VCConfiguration config)
|
| | | {
|
| | | var compiler = CompilerToolWrapper.Create(config);
|
| | | return GetPrecompiledHeaderFile(compiler);
|
| | | }
|
| | |
|
| | | private static string GetPrecompiledHeaderFile(CompilerToolWrapper compiler)
|
| | | {
|
| | | try {
|
| | | var file = compiler.GetPrecompiledHeaderFile();
|
| | | if (!string.IsNullOrEmpty(file))
|
| | | return file;
|
| | | } catch { }
|
| | | return null;
|
| | | }
|
| | |
|
| | | public static void SetPCHOption(VCFile vcFile, pchOption option)
|
| | | {
|
| | | foreach (VCFileConfiguration config in vcFile.FileConfigurations as IVCCollection) {
|
| | |
| | | /// <returns></returns>
|
| | | private VCFile GetGeneratedMocFile(string fileName, VCFileConfiguration fileConfig)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (QtVSIPSettings.HasDifferentMocFilePerConfig(envPro)
|
| | | || QtVSIPSettings.HasDifferentMocFilePerPlatform(envPro)) {
|
| | | var projectConfig = (VCConfiguration)fileConfig.ProjectConfiguration;
|
| | |
| | |
|
| | | public void RefreshMocSteps()
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | // Ignore when using shared compiler properties
|
| | | if (GetFormatVersion(vcPro) >= Resources.qtMinFormatVersion_ClProperties)
|
| | | return;
|
| | |
| | |
|
| | | public void RefreshMocStep(VCFile vcfile)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | | RefreshMocStep(vcfile, true);
|
| | | }
|
| | |
|
| | |
| | | /// <param name="vcfile"></param>
|
| | | private void RefreshMocStep(VCFile vcfile, bool singleFile)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var isHeaderFile = HelperFunctions.IsHeaderFile(vcfile.FullPath);
|
| | | if (!isHeaderFile && !HelperFunctions.IsSourceFile(vcfile.FullPath))
|
| | | return;
|
| | |
| | |
|
| | | public void OnExcludedFromBuildChanged(VCFile vcFile, VCFileConfiguration vcFileCfg)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | // Update the ExcludedFromBuild flags of the mocced file
|
| | | // according to the ExcludedFromBuild flag of the mocable source file.
|
| | | var moccedFileName = GetMocFileName(vcFile.Name);
|
| | |
| | |
|
| | | public void UpdateMocSteps(string oldMocDir)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | Messages.Print("\r\n=== Update moc steps ===");
|
| | | var orgFiles = new List<VCFile>();
|
| | | var abandonedMocFiles = new List<string>();
|
| | |
| | | try {
|
| | | RemoveMocStep(file);
|
| | | AddMocStep(file);
|
| | | } catch (QtVSException e) {
|
| | | Messages.Print(e.Message);
|
| | | } catch (QtVSException exception) {
|
| | | exception.Log();
|
| | | continue;
|
| | | }
|
| | | Messages.Print("Moc step updated successfully for " + file.Name + ".");
|
| | |
| | |
|
| | | private void Clean()
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var solutionConfigs = envPro.DTE.Solution.SolutionBuild.SolutionConfigurations;
|
| | | var backup = new List<KeyValuePair<SolutionContext, bool>>();
|
| | | foreach (SolutionConfiguration config in solutionConfigs) {
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | public bool isWinRT()
|
| | | {
|
| | | try {
|
| | | var vcProject = Project.Object as VCProject;
|
| | | var vcConfigs = vcProject.Configurations as IVCCollection;
|
| | | var vcConfig = vcConfigs.Item(1) as VCConfiguration;
|
| | | var appType = vcConfig.GetEvaluatedPropertyValue("ApplicationType");
|
| | | if (appType == "Windows Store")
|
| | | return true;
|
| | | } catch { }
|
| | | return false;
|
| | | }
|
| | |
|
| | | public bool PromptChangeQtVersion(string oldVersion, string newVersion)
|
| | | {
|
| | | var versionManager = QtVersionManager.The();
|
| | | var viOld = versionManager.GetVersionInfo(oldVersion);
|
| | | var viNew = versionManager.GetVersionInfo(newVersion);
|
| | |
|
| | | if (viOld == null || viNew == null)
|
| | | return true;
|
| | |
|
| | | var oldIsWinRt = viOld.isWinRT();
|
| | | var newIsWinRt = viNew.isWinRT();
|
| | |
|
| | | if (newIsWinRt == oldIsWinRt || newIsWinRt == isWinRT())
|
| | | return true;
|
| | |
|
| | | var promptCaption = string.Format("Change Qt Version ({0})", Project.Name);
|
| | | var promptText = string.Format(
|
| | | "Changing Qt version from {0} to {1}.\r\n" +
|
| | | "Project might not build. Are you sure?",
|
| | | newIsWinRt ? "Win32" : "WinRT",
|
| | | newIsWinRt ? "WinRT" : "Win32"
|
| | | );
|
| | |
|
| | | return (MessageBox.Show(
|
| | | promptText, promptCaption, MessageBoxButtons.YesNo, MessageBoxIcon.Warning)
|
| | | == DialogResult.Yes);
|
| | | }
|
| | |
|
| | | /// <summary>
|
| | | /// Changes the Qt version of this project.
|
| | | /// </summary>
|
| | |
| | | /// <returns>true, if the operation performed successfully</returns>
|
| | | public bool ChangeQtVersion(string oldVersion, string newVersion, ref bool newProjectCreated)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | newProjectCreated = false;
|
| | | var versionManager = QtVersionManager.The();
|
| | | var viNew = versionManager.GetVersionInfo(newVersion);
|
| | |
| | |
|
| | | public bool SelectSolutionPlatform(string platformName)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | foreach (SolutionConfiguration solutionCfg in dte.Solution.SolutionBuild.SolutionConfigurations) {
|
| | | var contexts = solutionCfg.SolutionContexts;
|
| | | for (var i = 1; i <= contexts.Count; ++i) {
|
| | |
| | | public void CreatePlatform(string oldPlatform, string newPlatform,
|
| | | VersionInformation viOld, VersionInformation viNew, ref bool newProjectCreated)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | try {
|
| | | var cfgMgr = envPro.ConfigurationManager;
|
| | | cfgMgr.AddPlatform(newPlatform, oldPlatform, true);
|
| | |
| | | if (genVCFilter == null)
|
| | | return;
|
| | |
|
| | | var error = false;
|
| | | error = DeleteFilesFromFilter(genVCFilter);
|
| | | if (error)
|
| | | if (DeleteFilesFromFilter(genVCFilter))
|
| | | Messages.Print(SR.GetString("DeleteGeneratedFilesError"));
|
| | | }
|
| | |
|
| | |
| | | resFile.Remove();
|
| | | }
|
| | |
|
| | | static private void AddPlatformToVCProj(string projectFileName, string oldPlatformName, string newPlatformName)
|
| | | private static void AddPlatformToVCProj(string projectFileName, string oldPlatformName, string newPlatformName)
|
| | | {
|
| | | var tempFileName = Path.GetTempFileName();
|
| | | var fi = new FileInfo(projectFileName);
|
| | |
| | | fi.Delete();
|
| | | }
|
| | |
|
| | | static private void AddPlatformToVCProj(XmlDocument doc, string oldPlatformName, string newPlatformName)
|
| | | private static void AddPlatformToVCProj(XmlDocument doc, string oldPlatformName, string newPlatformName)
|
| | | {
|
| | | var vsProj = doc.DocumentElement.SelectSingleNode("/VisualStudioProject");
|
| | | var platforms = vsProj.SelectSingleNode("Platforms");
|
| | |
| | | }
|
| | | }
|
| | |
|
| | | static private void SetTargetMachine(VCLinkerTool linker, VersionInformation versionInfo)
|
| | | private static void SetTargetMachine(VCLinkerTool linker, VersionInformation versionInfo)
|
| | | {
|
| | | var qMakeLFlagsWindows = versionInfo.GetQMakeConfEntry("QMAKE_LFLAGS_WINDOWS");
|
| | | var rex = new Regex("/MACHINE:(\\S+)");
|
| | |
| | |
|
| | | public void CollapseFilter(string filterName)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | var solutionExplorer = (UIHierarchy)dte.Windows.Item(Constants.vsext_wk_SProjectWindow).Object;
|
| | | if (solutionExplorer.UIHierarchyItems.Count == 0)
|
| | | return;
|
| | |
| | |
|
| | | private UIHierarchyItem FindProjectHierarchyItem(UIHierarchy hierarchy)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (hierarchy.UIHierarchyItems.Count == 0)
|
| | | return null;
|
| | |
|
| | |
| | |
|
| | | private UIHierarchyItem FindProjectHierarchyItem(UIHierarchyItem root)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | UIHierarchyItem projectItem = null;
|
| | | try {
|
| | | if (root.Name == envPro.Name)
|
| | |
| | | /// </summary>
|
| | | public string GetQtVersion()
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | | return QtVersionManager.The().GetProjectQtVersion(envPro);
|
| | | }
|
| | |
|
| | |
| | | /// </summary>
|
| | | public void SetQtEnvironment()
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | | SetQtEnvironment(QtVersionManager.The().GetProjectQtVersion(envPro));
|
| | | }
|
| | |
|
| | |
| | | /// </summary>
|
| | | public void SetQtEnvironment(string qtVersion)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | | SetQtEnvironment(qtVersion, string.Empty);
|
| | | }
|
| | |
|
| | |
| | | /// </summary>
|
| | | public void SetQtEnvironment(string qtVersion, string solutionConfig, bool build = false)
|
| | | {
|
| | | ThreadHelper.ThrowIfNotOnUIThread();
|
| | |
|
| | | if (string.IsNullOrEmpty(qtVersion))
|
| | | return;
|
| | |
|
| | |
| | | if (qtVersion != "$(QTDIR)")
|
| | | qtDir = QtVersionManager.The().GetInstallPath(qtVersion);
|
| | | HelperFunctions.SetEnvironmentVariableEx("QTDIR", qtDir);
|
| | |
|
| | | try {
|
| | | var propertyAccess = (IVCBuildPropertyStorage)vcPro;
|
| | | var vcprj = envPro.Object as VCProject;
|
| | |
| | | debuggerEnv = propertyAccess.GetPropertyValue(
|
| | | "LocalDebuggerEnvironment", cur_solution, "UserFile");
|
| | | if (!string.IsNullOrEmpty(debuggerEnv)) {
|
| | | var debugSettings = conf.DebugSettings as VCDebugSettings;
|
| | | if (debugSettings != null) {
|
| | | if (conf.DebugSettings is VCDebugSettings debugSettings) {
|
| | | //Get original value without expanded properties
|
| | | debuggerEnv = debugSettings.Environment;
|
| | | }
|
| | |
| | | var projProps = vcProj as IVCBuildPropertyStorage;
|
| | | try {
|
| | | return projProps.GetPropertyValue(pszPropName, Config.Name, "UserFile");
|
| | | } catch (Exception e) {
|
| | | System.Diagnostics.Debug.WriteLine(
|
| | | e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
|
| | | } catch (Exception exception) {
|
| | | exception.Log();
|
| | | return string.Empty;
|
| | | }
|
| | | }
|
| | |
| | | var projProps = vcProj as IVCBuildPropertyStorage;
|
| | | try {
|
| | | projProps.SetPropertyValue(pszPropName, Config.Name, "UserFile", pszPropValue);
|
| | | } catch (Exception e) {
|
| | | System.Diagnostics.Debug.WriteLine(
|
| | | e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
|
| | | } catch (Exception exception) {
|
| | | exception.Log();
|
| | | }
|
| | | }
|
| | |
|
| | |
| | | var projProps = vcProj as IVCBuildPropertyStorage;
|
| | | try {
|
| | | projProps.RemoveProperty(pszPropName, Config.Name, "UserFile");
|
| | | } catch (Exception e) {
|
| | | System.Diagnostics.Debug.WriteLine(
|
| | | e.Message + "\r\n\r\nStacktrace:\r\n" + e.StackTrace);
|
| | | } catch (Exception exception) {
|
| | | exception.Log();
|
| | | }
|
| | | }
|
| | | }
|
| | |
| | | {
|
| | | if (propertyStorage == null)
|
| | | return null;
|
| | | if (propertyStorage is VCFileConfiguration)
|
| | | return GetParentProject(propertyStorage as VCFileConfiguration);
|
| | | else if (propertyStorage is VCConfiguration)
|
| | | return GetParentProject(propertyStorage as VCConfiguration);
|
| | | if (propertyStorage is VCFileConfiguration configuration)
|
| | | return GetParentProject(configuration);
|
| | | else if (propertyStorage is VCConfiguration storage)
|
| | | return GetParentProject(storage);
|
| | | return null;
|
| | | }
|
| | |
|
| | |
| | |
|
| | | public class VCMacroExpander : IVSMacroExpander
|
| | | {
|
| | | object config;
|
| | |
|
| | | readonly object config;
|
| | | public VCMacroExpander(object config)
|
| | | {
|
| | | this.config = config;
|
| | |
| | |
|
| | | public class QtCustomBuildTool
|
| | | {
|
| | | QtMsBuildContainer qtMsBuild;
|
| | | VCFileConfiguration vcConfig;
|
| | | VCFile vcFile;
|
| | | VCCustomBuildTool tool;
|
| | | VCMacroExpander macros;
|
| | | readonly QtMsBuildContainer qtMsBuild;
|
| | | readonly VCFileConfiguration vcConfig;
|
| | | readonly VCFile vcFile;
|
| | | readonly VCCustomBuildTool tool;
|
| | | readonly VCMacroExpander macros;
|
| | |
|
| | | enum FileItemType { Other = 0, CustomBuild, QtMoc, QtRcc, QtRepc, QtUic };
|
| | | FileItemType itemType = FileItemType.Other;
|
| | | readonly FileItemType itemType = FileItemType.Other;
|
| | |
|
| | | public QtCustomBuildTool(VCFileConfiguration vcConfig, QtMsBuildContainer container = null)
|
| | | {
|
| | | if (container != null)
|