private void GenerateVcxproj(bool EnableRebuild) { var VcxprojPath = Path.Combine(OutputDirectory, Project.Name + ".vcxproj"); var BaseDirPath = Path.GetDirectoryName(Path.GetFullPath(VcxprojPath)); var xVcxproj = XmlFile.FromString(VcxprojTemplateText); Trim(xVcxproj); var xn = xVcxproj.Name.Namespace; foreach (var ig in xVcxproj.Elements(xn + "ItemGroup").ToArray()) { if (ig.Attribute("Label") != null) { continue; } var None = ig.Elements().Where(e => e.Name == xn + "None").ToArray(); var ClInclude = ig.Elements().Where(e => e.Name == xn + "ClInclude").ToArray(); var ClCompile = ig.Elements().Where(e => e.Name == xn + "ClCompile").ToArray(); var ProjectReference = ig.Elements().Where(e => e.Name == xn + "ProjectReference").ToArray(); foreach (var e in None) { e.Remove(); } foreach (var e in ClInclude) { e.Remove(); } foreach (var e in ClCompile) { e.Remove(); } foreach (var e in ProjectReference) { e.Remove(); } if (!ig.HasElements && !ig.HasAttributes) { ig.Remove(); } } var GlobalsPropertyGroup = xVcxproj.Elements(xn + "PropertyGroup").Where(e => e.Attribute("Label") != null && e.Attribute("Label").Value == "Globals").FirstOrDefault(); if (GlobalsPropertyGroup == null) { GlobalsPropertyGroup = new XElement(xn + "PropertyGroup", new XAttribute("Label", "Globals")); xVcxproj.Add(GlobalsPropertyGroup); } var g = "{" + ProjectId.ToUpper() + "}"; GlobalsPropertyGroup.SetElementValue(xn + "ProjectGuid", g); GlobalsPropertyGroup.SetElementValue(xn + "RootNamespace", Project.Name); var ExistingConfigurationTypeAndArchitectures = new Dictionary <KeyValuePair <ConfigurationType, ArchitectureType>, String>(); var ProjectConfigurations = xVcxproj.Elements(xn + "ItemGroup").Where(e => (e.Attribute("Label") != null) && (e.Attribute("Label").Value == "ProjectConfigurations")).SelectMany(e => e.Elements(xn + "ProjectConfiguration")).Select(e => e.Element(xn + "Configuration").Value + "|" + e.Element(xn + "Platform").Value).ToDictionary(s => s); foreach (var Architecture in Enum.GetValues(typeof(ArchitectureType)).Cast <ArchitectureType>()) { foreach (var ConfigurationType in Enum.GetValues(typeof(ConfigurationType)).Cast <ConfigurationType>()) { var Name = ConfigurationType.ToString() + "|" + GetArchitectureString(Architecture); if (ProjectConfigurations.ContainsKey(Name)) { ExistingConfigurationTypeAndArchitectures.Add(new KeyValuePair <ConfigurationType, ArchitectureType>(ConfigurationType, Architecture), Name); } } } foreach (var Pair in ExistingConfigurationTypeAndArchitectures) { var ConfigurationType = Pair.Key.Key; var Architecture = Pair.Key.Value; var Name = Pair.Value; var conf = ConfigurationUtils.GetMergedConfiguration(ToolchainType.Windows_VisualC, CompilerType.VisualC, BuildingOperatingSystem, TargetOperatingSystem, ConfigurationType, Architecture, Project.Configurations); var PropertyGroup = xVcxproj.Elements(xn + "PropertyGroup").Where(e => (e.Attribute("Condition") != null) && (e.Attribute("Condition").Value == "'$(Configuration)|$(Platform)'=='" + Name + "'")).LastOrDefault(); if (PropertyGroup == null) { PropertyGroup = new XElement(xn + "PropertyGroup", new XAttribute("Condition", "'$(Configuration)|$(Platform)'=='" + Name + "'")); } if (conf.TargetType == TargetType.Executable) { PropertyGroup.SetElementValue(xn + "ConfigurationType", "Application"); } else if (conf.TargetType == TargetType.StaticLibrary) { PropertyGroup.SetElementValue(xn + "ConfigurationType", "StaticLibrary"); } else if (conf.TargetType == TargetType.DynamicLibrary) { PropertyGroup.SetElementValue(xn + "ConfigurationType", "DynamicLibrary"); } else { throw new NotSupportedException("NotSupportedTargetType: " + conf.TargetType.ToString()); } var ItemDefinitionGroup = xVcxproj.Elements(xn + "ItemDefinitionGroup").Where(e => (e.Attribute("Condition") != null) && (e.Attribute("Condition").Value == "'$(Configuration)|$(Platform)'=='" + Name + "'")).LastOrDefault(); if (ItemDefinitionGroup == null) { ItemDefinitionGroup = new XElement(xn + "ItemDefinitionGroup", new XAttribute("Condition", "'$(Configuration)|$(Platform)'=='" + Name + "'")); xVcxproj.Add(ItemDefinitionGroup); } var ClCompile = ItemDefinitionGroup.Element(xn + "ClCompile"); if (ClCompile == null) { ClCompile = new XElement(xn + "ClCompile"); ItemDefinitionGroup.Add(ClCompile); } var IncludeDirectories = conf.IncludeDirectories.Select(d => FileNameHandling.GetRelativePath(d, BaseDirPath)).ToList(); if (IncludeDirectories.Count != 0) { ClCompile.SetElementValue(xn + "AdditionalIncludeDirectories", String.Join(";", IncludeDirectories) + ";%(AdditionalIncludeDirectories)"); } var Defines = conf.Defines; if (Defines.Count != 0) { ClCompile.SetElementValue(xn + "PreprocessorDefinitions", String.Join(";", Defines.Select(d => d.Key + (d.Value == null ? "" : "=" + (Regex.IsMatch(d.Value, @"^[0-9]+$") ? d.Value : "\"" + d.Value.Replace("\"", "\"\"") + "\"")))) + ";%(PreprocessorDefinitions)"); } var CompilerFlags = conf.CFlags.Concat(conf.CppFlags).ToList(); if (CompilerFlags.Count != 0) { ClCompile.SetElementValue(xn + "AdditionalOptions", "%(AdditionalOptions) " + String.Join(" ", CompilerFlags.Select(f => (f == null ? "" : Regex.IsMatch(f, @"^[0-9]+$") ? f : "\"" + f.Replace("\"", "\"\"") + "\"")))); } if ((conf.TargetType == TargetType.Executable) || (conf.TargetType == TargetType.DynamicLibrary)) { var Link = ItemDefinitionGroup.Element(xn + "Link"); if (Link == null) { Link = new XElement(xn + "Link"); ItemDefinitionGroup.Add(ClCompile); } var LibDirectories = conf.LibDirectories.Select(d => FileNameHandling.GetRelativePath(d, BaseDirPath)).ToList(); if (LibDirectories.Count != 0) { Link.SetElementValue(xn + "AdditionalLibraryDirectories", String.Join(";", LibDirectories) + ";%(AdditionalLibraryDirectories)"); } var Libs = conf.Libs.Concat(ProjectReferences.Select(p => p.Name + ".lib")).ToList(); if (Libs.Count != 0) { Link.SetElementValue(xn + "AdditionalDependencies", String.Join(";", Libs) + ";%(AdditionalDependencies)"); } var LinkerFlags = conf.LinkerFlags.ToList(); if (LinkerFlags.Count != 0) { ClCompile.SetElementValue(xn + "AdditionalOptions", "%(AdditionalOptions) " + String.Join(" ", LinkerFlags.Select(f => (f == null ? "" : Regex.IsMatch(f, @"^[0-9]+$") ? f : "\"" + f.Replace("\"", "\"\"") + "\"")))); } } } var Import = xVcxproj.Elements(xn + "Import").LastOrDefault(); foreach (var conf in Project.Configurations) { var FileItemGroup = new XElement(xn + "ItemGroup"); if (Import != null) { Import.AddBeforeSelf(FileItemGroup); } else { xVcxproj.Add(FileItemGroup); } if ((conf.ConfigurationType != null) || (conf.Architecture != null)) { var Keys = new List <String> { }; var Values = new List <String> { }; if (conf.ConfigurationType != null) { Keys.Add("$(Configuration)"); Values.Add(conf.ConfigurationType.ToString()); } if (conf.Architecture != null) { Keys.Add("$(Platform)"); Values.Add(GetArchitectureString(conf.Architecture.Value)); } var Condition = "'" + String.Join("|", Keys) + "' == '" + String.Join("|", Values) + "'"; FileItemGroup.Add(new XAttribute("Condition", Condition)); } foreach (var f in conf.Files) { var RelativePath = FileNameHandling.GetRelativePath(f.Path, BaseDirPath); XElement x; if (f.Type == FileType.Header) { x = new XElement(xn + "ClInclude", new XAttribute("Include", RelativePath)); } else if (f.Type == FileType.CSource) { x = new XElement(xn + "ClCompile", new XAttribute("Include", RelativePath)); } else if (f.Type == FileType.CppSource) { x = new XElement(xn + "ClCompile", new XAttribute("Include", RelativePath)); x.Add(new XElement(xn + "ObjectFileName", "$(IntDir)" + RelativePath.Replace("..", "__") + ".obj")); } else { x = new XElement(xn + "None", new XAttribute("Include", RelativePath)); } FileItemGroup.Add(x); } if (!FileItemGroup.HasElements) { FileItemGroup.Remove(); } } var ProjectItemGroup = new XElement(xn + "ItemGroup"); if (Import != null) { Import.AddBeforeSelf(ProjectItemGroup); } else { xVcxproj.Add(ProjectItemGroup); } foreach (var p in ProjectReferences) { var RelativePath = FileNameHandling.GetRelativePath(p.FilePath, BaseDirPath); var x = new XElement(xn + "ProjectReference", new XAttribute("Include", RelativePath)); x.Add(new XElement(xn + "Project", "{" + p.Id.ToUpper() + "}")); x.Add(new XElement(xn + "Name", "{" + p.Name + "}")); ProjectItemGroup.Add(x); } if (!ProjectItemGroup.HasElements) { ProjectItemGroup.Remove(); } var sVcxproj = XmlFile.ToString(xVcxproj); TextFile.WriteToFile(VcxprojPath, sVcxproj, Encoding.UTF8, !EnableRebuild); }
private void GenerateVcxproj(bool ForceRegenerate) { var VcxprojPath = OutputDirectory / (Project.Name + ".vcxproj"); var BaseDirPath = VcxprojPath.Parent; var xVcxproj = XmlFile.FromString(VcxprojTemplateText); Trim(xVcxproj); var xn = xVcxproj.Name.Namespace; if (TargetArchitecture != null) { var rProjectConfigurationInclude = new Regex(@"[^|]+\|(?<Architecture>[^|]+)"); foreach (var e in xVcxproj.Elements(xn + "ItemGroup").Where(e => (e.Attribute("Label") != null) && (e.Attribute("Label").Value == "ProjectConfigurations")).SelectMany(e => e.Elements(xn + "ProjectConfiguration")).ToArray()) { var m = rProjectConfigurationInclude.Match(e.Attribute("Include").Value); if (m.Success) { var Architecture = m.Result("${Architecture}"); if (Architecture != GetArchitectureString(TargetOperatingSystem, TargetArchitecture.Value)) { e.Remove(); } } } var rCondition = new Regex(@"'\$\(Configuration\)\|\$\(Platform\)'=='[^|]+\|(?<Architecture>[^|]+)'"); foreach (var e in xVcxproj.Elements().ToArray()) { if (e.Attribute("Condition") != null) { var m = rCondition.Match(e.Attribute("Condition").Value); if (m.Success) { var Architecture = m.Result("${Architecture}"); if (Architecture != GetArchitectureString(TargetOperatingSystem, TargetArchitecture.Value)) { e.Remove(); } } } } } foreach (var ig in xVcxproj.Elements(xn + "ItemGroup").ToArray()) { if (ig.Attribute("Label") != null) { continue; } var None = ig.Elements().Where(e => e.Name == xn + "None").ToArray(); var ClInclude = ig.Elements().Where(e => e.Name == xn + "ClInclude").ToArray(); var ClCompile = ig.Elements().Where(e => e.Name == xn + "ClCompile").ToArray(); var ProjectReference = ig.Elements().Where(e => e.Name == xn + "ProjectReference").ToArray(); foreach (var e in None) { e.Remove(); } foreach (var e in ClInclude) { e.Remove(); } foreach (var e in ClCompile) { e.Remove(); } foreach (var e in ProjectReference) { e.Remove(); } if (!ig.HasElements && !ig.HasAttributes) { ig.Remove(); } } var GlobalsPropertyGroup = xVcxproj.Elements(xn + "PropertyGroup").Where(e => e.Attribute("Label") != null && e.Attribute("Label").Value == "Globals").FirstOrDefault(); if (GlobalsPropertyGroup == null) { GlobalsPropertyGroup = new XElement(xn + "PropertyGroup", new XAttribute("Label", "Globals")); xVcxproj.Add(GlobalsPropertyGroup); } var g = "{" + ProjectId.ToUpper() + "}"; GlobalsPropertyGroup.SetElementValue(xn + "ProjectGuid", g); GlobalsPropertyGroup.SetElementValue(xn + "RootNamespace", Project.Name); if (TargetOperatingSystem == OperatingSystemType.Windows) { GlobalsPropertyGroup.SetElementValue(xn + "WindowsTargetPlatformVersion", GetWindowsTargetPlatformVersion()); if (WindowsRuntime == WindowsRuntimeType.Win32) { GlobalsPropertyGroup.SetElementValue(xn + "Keyword", "Win32Proj"); } else if (WindowsRuntime == WindowsRuntimeType.WinRT) { GlobalsPropertyGroup.SetElementValue(xn + "AppContainerApplication", true); GlobalsPropertyGroup.SetElementValue(xn + "ApplicationType", "Windows Store"); GlobalsPropertyGroup.SetElementValue(xn + "ApplicationTypeRevision", "10.0"); } else { throw new InvalidOperationException(); } } else if (TargetOperatingSystem == OperatingSystemType.Linux) { GlobalsPropertyGroup.SetElementValue(xn + "Keyword", "Linux"); } else { throw new InvalidOperationException(); } var globalConf = Project.Configurations.Merged(Project.TargetType, HostOperatingSystem, HostArchitecture, TargetOperatingSystem, TargetArchitecture, WindowsRuntime, ToolchainType.VisualStudio, Compiler, CLibrary, CLibraryForm, CppLibrary, CppLibraryForm, null); foreach (var o in globalConf.Options) { var Prefix = "vc.Globals."; if (o.Key.StartsWith(Prefix)) { var Key = o.Key.Substring(Prefix.Length); GlobalsPropertyGroup.SetElementValue(xn + Key, o.Value); } } var ExistingConfigurationTypeAndArchitectures = new Dictionary <KeyValuePair <ConfigurationType, ArchitectureType>, String>(); var ProjectConfigurations = xVcxproj.Elements(xn + "ItemGroup").Where(e => (e.Attribute("Label") != null) && (e.Attribute("Label").Value == "ProjectConfigurations")).SelectMany(e => e.Elements(xn + "ProjectConfiguration")).Select(e => e.Element(xn + "Configuration").Value + "|" + e.Element(xn + "Platform").Value).ToDictionary(s => s); foreach (var Architecture in new ArchitectureType[] { ArchitectureType.x86, ArchitectureType.x64, ArchitectureType.armv7a, ArchitectureType.arm64 }) { foreach (var ConfigurationType in Enum.GetValues(typeof(ConfigurationType)).Cast <ConfigurationType>()) { var Name = ConfigurationType.ToString() + "|" + GetArchitectureString(TargetOperatingSystem, Architecture); if (ProjectConfigurations.ContainsKey(Name)) { ExistingConfigurationTypeAndArchitectures.Add(new KeyValuePair <ConfigurationType, ArchitectureType>(ConfigurationType, Architecture), Name); } } } foreach (var Pair in ExistingConfigurationTypeAndArchitectures) { var ConfigurationType = Pair.Key.Key; var Architecture = Pair.Key.Value; var Name = Pair.Value; var conf = Project.Configurations.Merged(Project.TargetType, HostOperatingSystem, HostArchitecture, TargetOperatingSystem, Architecture, WindowsRuntime, ToolchainType.VisualStudio, Compiler, CLibrary, CLibraryForm, CppLibrary, CppLibraryForm, ConfigurationType); var PropertyGroupConfiguration = xVcxproj.Elements(xn + "PropertyGroup").Where(e => (e.Attribute("Condition") != null) && (e.Attribute("Condition").Value == "'$(Configuration)|$(Platform)'=='" + Name + "'") && (e.Attribute("Label") != null) && (e.Attribute("Label").Value == "Configuration")).LastOrDefault(); if (PropertyGroupConfiguration == null) { PropertyGroupConfiguration = new XElement(xn + "PropertyGroup", new XAttribute("Condition", "'$(Configuration)|$(Platform)'=='" + Name + "'"), new XAttribute("Label", "Configuration")); xVcxproj.Add(PropertyGroupConfiguration); } if (!String.IsNullOrEmpty(Project.TargetName) && (Project.TargetName != Project.Name)) { PropertyGroupConfiguration.SetElementValue(xn + "TargetName", Project.TargetName); } if (Project.TargetType == TargetType.Executable) { PropertyGroupConfiguration.SetElementValue(xn + "ConfigurationType", "Application"); } else if (Project.TargetType == TargetType.StaticLibrary) { PropertyGroupConfiguration.SetElementValue(xn + "ConfigurationType", "StaticLibrary"); } else if (Project.TargetType == TargetType.DynamicLibrary) { PropertyGroupConfiguration.SetElementValue(xn + "ConfigurationType", "DynamicLibrary"); } else { throw new NotSupportedException("NotSupportedTargetType: " + Project.TargetType.ToString()); } if (TargetOperatingSystem == OperatingSystemType.Linux) { if (Compiler == CompilerType.gcc) { PropertyGroupConfiguration.SetElementValue(xn + "PlatformToolset", "WSL_1_0"); } else if (Compiler == CompilerType.clang) { PropertyGroupConfiguration.SetElementValue(xn + "PlatformToolset", "WSL_Clang_1_0"); } } foreach (var o in conf.Options) { var Prefix = "vc.Configuration."; if (o.Key.StartsWith(Prefix)) { var Key = o.Key.Substring(Prefix.Length); PropertyGroupConfiguration.SetElementValue(xn + Key, o.Value); } } var PropertyGroup = xVcxproj.Elements(xn + "PropertyGroup").Where(e => (e.Attribute("Condition") != null) && (e.Attribute("Condition").Value == "'$(Configuration)|$(Platform)'=='" + Name + "'") && (e.Attribute("Label") == null)).LastOrDefault(); if (PropertyGroup == null) { PropertyGroup = new XElement(xn + "PropertyGroup", new XAttribute("Condition", "'$(Configuration)|$(Platform)'=='" + Name + "'")); xVcxproj.Add(PropertyGroup); } if (conf.OutputDirectory != null) { var RelativeOutDir = conf.OutputDirectory.RelativeTo(BuildDirectory); var OutDir = RelativeOutDir.IsFullPath ? RelativeOutDir.ToString(PathStringStyle.Windows) : "$(SolutionDir)" + RelativeOutDir.ToString(PathStringStyle.Windows); if (!OutDir.EndsWith("\\")) { OutDir += "\\"; } PropertyGroup.SetElementValue(xn + "OutDir", OutDir); PropertyGroup.SetElementValue(xn + "DebuggerWorkingDirectory", OutDir); } else { if (TargetArchitecture == null) { PropertyGroup.SetElementValue(xn + "OutDir", $"$(SolutionDir){Architecture}_{ConfigurationType}\\"); PropertyGroup.SetElementValue(xn + "DebuggerWorkingDirectory", $"$(SolutionDir){Architecture}_{ConfigurationType}\\"); } else { PropertyGroup.SetElementValue(xn + "OutDir", $"$(SolutionDir){ConfigurationType}\\"); PropertyGroup.SetElementValue(xn + "DebuggerWorkingDirectory", $"$(SolutionDir){ConfigurationType}\\"); } } if (TargetArchitecture == null) { PropertyGroup.SetElementValue(xn + "IntDir", $"$(SolutionDir)projects\\$(ProjectName)\\{Architecture}_{ConfigurationType}\\"); } else { PropertyGroup.SetElementValue(xn + "IntDir", $"$(SolutionDir)projects\\$(ProjectName)\\{ConfigurationType}\\"); } if (TargetOperatingSystem == OperatingSystemType.Linux) { if (CC != null) { PropertyGroup.SetElementValue(xn + "RemoteCCompileToolExe", CC); } if (CXX != null) { PropertyGroup.SetElementValue(xn + "RemoteCppCompileToolExe", CXX); PropertyGroup.SetElementValue(xn + "RemoteLdToolExe", CXX); } if (AR != null) { PropertyGroup.SetElementValue(xn + "RemoteArToolExe", AR); } PropertyGroup.SetElementValue(xn + "EnableIncrementalBuild", "WithNinja"); if (Project.TargetType == TargetType.Executable) { PropertyGroup.SetElementValue(xn + "TargetExt", ""); } } foreach (var o in conf.Options) { var Prefix = "vc.PropertyGroup."; if (o.Key.StartsWith(Prefix)) { var Key = o.Key.Substring(Prefix.Length); PropertyGroupConfiguration.SetElementValue(xn + Key, o.Value); } } var ItemDefinitionGroup = xVcxproj.Elements(xn + "ItemDefinitionGroup").Where(e => (e.Attribute("Condition") != null) && (e.Attribute("Condition").Value == "'$(Configuration)|$(Platform)'=='" + Name + "'")).LastOrDefault(); if (ItemDefinitionGroup == null) { ItemDefinitionGroup = new XElement(xn + "ItemDefinitionGroup", new XAttribute("Condition", "'$(Configuration)|$(Platform)'=='" + Name + "'")); xVcxproj.Add(ItemDefinitionGroup); } var ClCompile = ItemDefinitionGroup.Element(xn + "ClCompile"); if (ClCompile == null) { ClCompile = new XElement(xn + "ClCompile"); ItemDefinitionGroup.Add(ClCompile); } var IncludeDirectories = conf.IncludeDirectories.Select(d => d.FullPath.RelativeTo(BaseDirPath).ToString(PathStringStyle.Windows)).ToList(); if (IncludeDirectories.Count != 0) { ClCompile.SetElementValue(xn + "AdditionalIncludeDirectories", String.Join(";", IncludeDirectories) + ";%(AdditionalIncludeDirectories)"); } var Defines = conf.Defines; if (Defines.Count != 0) { ClCompile.SetElementValue(xn + "PreprocessorDefinitions", String.Join(";", Defines.Select(d => d.Key + (d.Value == null ? "" : "=" + d.Value))) + ";%(PreprocessorDefinitions)"); } var CompilerFlags = conf.SystemIncludeDirectories.SelectMany(d => new String[] { "/external:I", d.FullPath.RelativeTo(BaseDirPath).ToString(PathStringStyle.Windows) }).Concat(conf.CommonFlags).Concat(conf.CFlags).Concat(conf.CppFlags).ToList(); if (WindowsRuntime == WindowsRuntimeType.WinRT) { CompilerFlags.Add("/Zc:twoPhase-"); //https://docs.microsoft.com/en-us/cpp/build/reference/zc-twophase?view=vs-2019 } if (CompilerFlags.Count != 0) { ClCompile.SetElementValue(xn + "AdditionalOptions", "%(AdditionalOptions) " + String.Join(" ", CompilerFlags.Select(f => (f == null ? "" : Regex.IsMatch(f, @"^[0-9]+$") ? f : "\"" + f.Replace("\"", "\"\"\"") + "\"")))); } foreach (var o in conf.Options) { var Prefix = "vc.ClCompile."; if (o.Key.StartsWith(Prefix)) { ClCompile.SetElementValue(xn + o.Key.Substring(Prefix.Length), o.Value); } } if (Project.TargetType == TargetType.StaticLibrary) { var Lib = ItemDefinitionGroup.Element(xn + "Lib"); if (Lib == null) { Lib = new XElement(xn + "Lib"); ItemDefinitionGroup.Add(Lib); } foreach (var o in conf.Options) { var Prefix = "vc.Lib."; if (o.Key.StartsWith(Prefix)) { Lib.SetElementValue(xn + o.Key.Substring(Prefix.Length), o.Value); } } } if ((Project.TargetType == TargetType.Executable) || (Project.TargetType == TargetType.DynamicLibrary)) { var Link = ItemDefinitionGroup.Element(xn + "Link"); if (Link == null) { Link = new XElement(xn + "Link"); ItemDefinitionGroup.Add(Link); } var LibDirectories = conf.LibDirectories.Select(d => d.FullPath.RelativeTo(BaseDirPath).ToString(PathStringStyle.Windows)).ToList(); if (LibDirectories.Count != 0) { Link.SetElementValue(xn + "AdditionalLibraryDirectories", String.Join(";", LibDirectories) + ";%(AdditionalLibraryDirectories)"); } if (TargetOperatingSystem == OperatingSystemType.Windows) { var Libs = conf.Libs.Select(Lib => Lib.Parts.Count == 1 ? Lib.ToString(PathStringStyle.Windows) : Lib.RelativeTo(BaseDirPath).ToString(PathStringStyle.Windows)).ToList(); if (Libs.Count != 0) { Link.SetElementValue(xn + "AdditionalDependencies", String.Join(";", Libs) + ";%(AdditionalDependencies)"); } } else { var Libs = conf.Libs.Select(Lib => Lib.Parts.Count == 1 ? Lib.Extension == "" ? "-l" + Lib.ToString(PathStringStyle.Unix) : "-l:" + Lib.ToString(PathStringStyle.Unix) : Lib.RelativeTo(BaseDirPath).ToString(PathStringStyle.Unix)).ToList(); Libs.Add("-Wl,--end-group"); if (Libs.Count != 0) { Link.SetElementValue(xn + "AdditionalDependencies", String.Join(";", Libs) + ";%(AdditionalDependencies)"); } } var LinkerFlags = conf.LinkerFlags.Select(f => (f == null ? "" : Regex.IsMatch(f, @"^[0-9]+$") ? f : "\"" + f.Replace("\"", "\"\"") + "\"")).ToList(); var PostLinkerFlags = conf.PostLinkerFlags.Select(f => (f == null ? "" : Regex.IsMatch(f, @"^[0-9]+$") ? f : "\"" + f.Replace("\"", "\"\"") + "\"")).ToList(); if (TargetOperatingSystem != OperatingSystemType.Windows) { PostLinkerFlags.Add("-Wl,--start-group"); } if (LinkerFlags.Count + PostLinkerFlags.Count != 0) { Link.SetElementValue(xn + "AdditionalOptions", String.Join(" ", LinkerFlags.Concat(new List <String> { "%(AdditionalOptions)" }).Concat(PostLinkerFlags))); } foreach (var o in conf.Options) { var Prefix = "vc.Link."; if (o.Key.StartsWith(Prefix)) { Link.SetElementValue(xn + o.Key.Substring(Prefix.Length), o.Value); } } } } var Import = xVcxproj.Elements(xn + "Import").LastOrDefault(); foreach (var gConf in Project.Configurations.Matches(Project.TargetType, HostOperatingSystem, HostArchitecture, TargetOperatingSystem, null, WindowsRuntime, ToolchainType.VisualStudio, Compiler, CLibrary, CLibraryForm, CppLibrary, CppLibraryForm, null).GroupBy(conf => Tuple.Create(conf.MatchingConfigurationTypes, conf.MatchingTargetArchitectures?.Intersect(new ArchitectureType[] { ArchitectureType.x86, ArchitectureType.x64, ArchitectureType.armv7a, ArchitectureType.arm64 }).ToList()), new ConfigurationTypesAndArchitecturesComparer())) { var MatchingConfigurationTypes = gConf.Key.Item1; var MatchingTargetArchitectures = gConf.Key.Item2; if ((MatchingConfigurationTypes != null) && (MatchingConfigurationTypes.Count == 0)) { continue; } if ((MatchingTargetArchitectures != null) && (MatchingTargetArchitectures.Count == 0)) { continue; } var Conditions = new List <String>(); Conditions = GetConditions(TargetOperatingSystem, MatchingConfigurationTypes, MatchingTargetArchitectures); foreach (var Condition in Conditions) { var FileItemGroup = new XElement(xn + "ItemGroup"); if (Import != null) { Import.AddBeforeSelf(FileItemGroup); } else { xVcxproj.Add(FileItemGroup); } if (Condition != null) { FileItemGroup.Add(new XAttribute("Condition", Condition)); } foreach (var File in gConf.SelectMany(conf => conf.Files)) { var RelativePath = File.Path.FullPath.RelativeTo(BaseDirPath); var RelativePathStr = RelativePath.ToString(PathStringStyle.Windows); XElement x; if (File.Type == FileType.Header) { x = new XElement(xn + "ClInclude", new XAttribute("Include", RelativePathStr)); } else if ((File.Type == FileType.CSource) || (File.Type == FileType.CppSource)) { x = new XElement(xn + "ClCompile", new XAttribute("Include", RelativePathStr)); if (Compiler == CompilerType.VisualCpp) { // workaround Visual Studio bug which slows build https://developercommunity.visualstudio.com/idea/586584/vs2017-cc-multi-processor-compilation-does-not-wor.html x.Add(new XElement(xn + "ObjectFileName", "$(IntDir)" + RelativePath.Parent.ToString(PathStringStyle.Windows).Replace("..", "__").Replace(":", "_") + "\\")); } else { x.Add(new XElement(xn + "ObjectFileName", "$(IntDir)" + RelativePath.ToString(PathStringStyle.Windows).Replace("..", "__").Replace(":", "_") + ".o")); } } else if (File.Type == FileType.NatVis) { x = new XElement(xn + "Natvis", new XAttribute("Include", RelativePathStr)); } else { x = new XElement(xn + "None", new XAttribute("Include", RelativePathStr)); } if ((File.Type == FileType.CSource) || (File.Type == FileType.CppSource)) { var fileConfs = File.Configurations.Matches(Project.TargetType, HostOperatingSystem, HostArchitecture, TargetOperatingSystem, null, WindowsRuntime, ToolchainType.VisualStudio, Compiler, CLibrary, CLibraryForm, CppLibrary, CppLibraryForm, null); foreach (var conf in fileConfs) { var FileMatchingConfigurationTypes = conf.MatchingConfigurationTypes; var FileMatchingTargetArchitectures = conf.MatchingTargetArchitectures; if ((FileMatchingConfigurationTypes != null) && (MatchingConfigurationTypes != null)) { FileMatchingConfigurationTypes = FileMatchingConfigurationTypes.Intersect(MatchingConfigurationTypes).ToList(); if (FileMatchingConfigurationTypes.Count == MatchingConfigurationTypes.Count) { FileMatchingConfigurationTypes = null; } } if ((FileMatchingTargetArchitectures != null) && (MatchingTargetArchitectures != null)) { FileMatchingTargetArchitectures = FileMatchingTargetArchitectures.Intersect(MatchingTargetArchitectures).ToList(); if (FileMatchingTargetArchitectures.Count == MatchingTargetArchitectures.Count) { FileMatchingTargetArchitectures = null; } } var FileConditions = GetConditions(TargetOperatingSystem, FileMatchingConfigurationTypes, FileMatchingTargetArchitectures); foreach (var FileCondition in FileConditions) { var Attributes = new XAttribute[] { }; if (FileCondition != null) { Attributes = new XAttribute[] { new XAttribute("Condition", FileCondition) }; } var IncludeDirectories = conf.IncludeDirectories.Select(d => d.FullPath.RelativeTo(BaseDirPath).ToString(PathStringStyle.Windows)).ToList(); if (IncludeDirectories.Count != 0) { x.Add(new XElement(xn + "AdditionalIncludeDirectories", String.Join(";", IncludeDirectories) + ";%(AdditionalIncludeDirectories)", Attributes)); } var Defines = conf.Defines; if (Defines.Count != 0) { x.Add(new XElement(xn + "PreprocessorDefinitions", String.Join(";", Defines.Select(d => d.Key + (d.Value == null ? "" : "=" + d.Value))) + ";%(PreprocessorDefinitions)", Attributes)); } var CompilerFlags = conf.SystemIncludeDirectories.SelectMany(d => new String[] { "/external:I", d.FullPath.RelativeTo(BaseDirPath).ToString(PathStringStyle.Windows) }).Concat(conf.CommonFlags).ToList(); if ((File.Type == FileType.CSource) || (File.Type == FileType.ObjectiveCSource)) { CompilerFlags = CompilerFlags.Concat(conf.CFlags).ToList(); } else if ((File.Type == FileType.CppSource) || (File.Type == FileType.ObjectiveCppSource)) { CompilerFlags = CompilerFlags.Concat(conf.CppFlags).ToList(); } if (CompilerFlags.Count != 0) { x.Add(new XElement(xn + "AdditionalOptions", "%(AdditionalOptions) " + String.Join(" ", CompilerFlags.Select(f => (f == null ? "" : Regex.IsMatch(f, @"^[0-9]+$") ? f : "\"" + f.Replace("\"", "\"\"\"") + "\""))), Attributes)); } foreach (var o in conf.Options) { var Prefix = "vc.ClCompile."; if (o.Key.StartsWith(Prefix)) { x.Add(new XElement(xn + o.Key.Substring(Prefix.Length), o.Value, Attributes)); } } } } } FileItemGroup.Add(x); } if (!FileItemGroup.HasElements) { FileItemGroup.Remove(); } } } var ProjectItemGroup = new XElement(xn + "ItemGroup"); if (Import != null) { Import.AddBeforeSelf(ProjectItemGroup); } else { xVcxproj.Add(ProjectItemGroup); } foreach (var p in ProjectReferences) { var RelativePath = p.FilePath.FullPath.RelativeTo(BaseDirPath).ToString(PathStringStyle.Windows); var x = new XElement(xn + "ProjectReference", new XAttribute("Include", RelativePath)); x.Add(new XElement(xn + "Project", "{" + p.Id.ToUpper() + "}")); x.Add(new XElement(xn + "Name", p.Name)); x.Add(new XElement(xn + "LinkLibraryDependecies", "true")); if (WindowsRuntime == WindowsRuntimeType.WinRT) { x.Add(new XElement(xn + "ReferenceOutputAssembly", "false")); } ProjectItemGroup.Add(x); } if (!ProjectItemGroup.HasElements) { ProjectItemGroup.Remove(); } //https://developercommunity.visualstudio.com/idea/555602/c-referenced-dlls-copylocal-dosnt-work.html if (Project.TargetType == TargetType.DynamicLibrary) { var OutputCopyItemGroup = new XElement(xn + "ItemGroup"); xVcxproj.Add(OutputCopyItemGroup); OutputCopyItemGroup.Add(new XElement(xn + "Content", new XAttribute("Include", "$(TargetPath)"), new XElement(xn + "Link", "%(Filename)%(Extension)"), new XElement(xn + "CopyToOutputDirectory", "PreserveNewest"))); } var sVcxproj = XmlFile.ToString(xVcxproj); TextFile.WriteToFile(VcxprojPath, sVcxproj, Encoding.UTF8, !ForceRegenerate); }