/*--------------------------------------------------------------------------------------------- * Copyright (c) Unity Technologies. * Copyright (c) Microsoft Corporation. All rights reserved. * Licensed under the MIT License. See License.txt in the project root for license information. *--------------------------------------------------------------------------------------------*/ using System; using System.IO; using System.Text; using UnityEditor.Compilation; using UnityEngine; namespace Microsoft.Unity.VisualStudio.Editor { internal class SdkStyleProjectGeneration : ProjectGeneration { internal override string StyleName => "SDK"; internal class SdkStyleAssemblyNameProvider : AssemblyNameProvider { // disable PlayerGeneration with SdkStyle projects internal override ProjectGenerationFlag ProjectGenerationFlagImpl => base.ProjectGenerationFlagImpl & ~ProjectGenerationFlag.PlayerAssemblies; } public SdkStyleProjectGeneration() : base( Directory.GetParent(Application.dataPath)?.FullName, new SdkStyleAssemblyNameProvider(), new FileIOProvider(), new GUIDProvider()) { } internal static readonly string[] SupportedCapabilities = new string[] { "Unity", }; internal static readonly string[] UnsupportedCapabilities = new string[] { "LaunchProfiles", "SharedProjectReferences", "ReferenceManagerSharedProjects", "ProjectReferences", "ReferenceManagerProjects", "COMReferences", "ReferenceManagerCOM", "AssemblyReferences", "ReferenceManagerAssemblies", }; internal override void GetProjectHeader(ProjectProperties properties, out StringBuilder headerBuilder) { headerBuilder = new StringBuilder(); headerBuilder.Append(@"").Append(k_WindowsNewline); headerBuilder.Append(@" ").Append(k_WindowsNewline); // Prevent circular dependency issues see https://github.com/microsoft/vscode-dotnettools/issues/401 // We need a dedicated subfolder for each project in obj, else depending on the build order, nuget cache files could be overwritten // We need to do this before common.props, else we'll have a MSB3539 The value of the property "BaseIntermediateOutputPath" was modified after it was used by MSBuild headerBuilder.Append(@" ").Append(k_WindowsNewline); headerBuilder.Append($" {@"Temp\obj\$(Configuration)\$(MSBuildProjectName)".NormalizePathSeparators()}").Append(k_WindowsNewline); headerBuilder.Append(@" $(BaseIntermediateOutputPath)").Append(k_WindowsNewline); headerBuilder.Append(@" ").Append(k_WindowsNewline); // Supported capabilities GetCapabilityBlock(headerBuilder, "Sdk.props", "Include", SupportedCapabilities); headerBuilder.Append(@" ").Append(k_WindowsNewline); headerBuilder.Append(@" false").Append(k_WindowsNewline); headerBuilder.Append(@" false").Append(k_WindowsNewline); headerBuilder.Append(@" false").Append(k_WindowsNewline); headerBuilder.Append(@" ").Append(properties.LangVersion).Append(@"").Append(k_WindowsNewline); headerBuilder.Append(@" Debug;Release").Append(k_WindowsNewline); headerBuilder.Append(@" Debug").Append(k_WindowsNewline); headerBuilder.Append(@" AnyCPU").Append(k_WindowsNewline); headerBuilder.Append(@" ").Append(properties.RootNamespace).Append(@"").Append(k_WindowsNewline); headerBuilder.Append(@" Library").Append(k_WindowsNewline); headerBuilder.Append(@" Properties").Append(k_WindowsNewline); headerBuilder.Append(@" ").Append(properties.AssemblyName).Append(@"").Append(k_WindowsNewline); // In the end, given we use NoConfig/NoStdLib (see below), hardcoding the target framework version will have no impact, even when targeting netstandard/net48 from Unity. // But with SDK style we use netstandard2.1 (net471 for legacy), so 3rd party tools will not fail to work when .NETFW reference assemblies are not installed. // Unity already selected proper API surface through referenced DLLs for us. headerBuilder.Append(@" netstandard2.1").Append(k_WindowsNewline); headerBuilder.Append(@" .").Append(k_WindowsNewline); headerBuilder.Append(@" ").Append(k_WindowsNewline); GetProjectHeaderConfigurations(properties, headerBuilder); // Explicit references headerBuilder.Append(@" ").Append(k_WindowsNewline); headerBuilder.Append(@" true").Append(k_WindowsNewline); headerBuilder.Append(@" true").Append(k_WindowsNewline); headerBuilder.Append(@" true").Append(k_WindowsNewline); headerBuilder.Append(@" true").Append(k_WindowsNewline); headerBuilder.Append(@" MSB3277").Append(k_WindowsNewline); headerBuilder.Append(@" ").Append(k_WindowsNewline); GetProjectHeaderVstuFlavoring(properties, headerBuilder, false); GetProjectHeaderAnalyzers(properties, headerBuilder); } internal override void AppendProjectReference(Assembly assembly, Assembly reference, StringBuilder projectBuilder) { // If the current assembly is a Player project, we want to project-reference the corresponding Player project var referenceName = m_AssemblyNameProvider.GetAssemblyName(assembly.outputPath, reference.name); projectBuilder.Append(@" ").Append(k_WindowsNewline); } internal override void GetProjectFooter(StringBuilder footerBuilder) { // Unsupported capabilities GetCapabilityBlock(footerBuilder, "Sdk.targets", "Remove", UnsupportedCapabilities); footerBuilder.Append("").Append(k_WindowsNewline); } internal static void GetCapabilityBlock(StringBuilder footerBuilder, string import, string attribute, string[] capabilities) { footerBuilder.Append($@" ").Append(k_WindowsNewline); footerBuilder.Append(@" ").Append(k_WindowsNewline); foreach (var capability in capabilities) { footerBuilder.Append($@" ").Append(k_WindowsNewline); } footerBuilder.Append(@" ").Append(k_WindowsNewline); } } }