A game about forced loneliness, made by TACStudios
1/*---------------------------------------------------------------------------------------------
2 * Copyright (c) Unity Technologies.
3 * Copyright (c) Microsoft Corporation. All rights reserved.
4 * Licensed under the MIT License. See License.txt in the project root for license information.
5 *--------------------------------------------------------------------------------------------*/
6
7using System;
8using System.IO;
9using System.Text;
10using UnityEditor.Compilation;
11using UnityEngine;
12
13namespace Microsoft.Unity.VisualStudio.Editor
14{
15 internal class SdkStyleProjectGeneration : ProjectGeneration
16 {
17 internal override string StyleName => "SDK";
18
19 internal class SdkStyleAssemblyNameProvider : AssemblyNameProvider
20 {
21 // disable PlayerGeneration with SdkStyle projects
22 internal override ProjectGenerationFlag ProjectGenerationFlagImpl => base.ProjectGenerationFlagImpl & ~ProjectGenerationFlag.PlayerAssemblies;
23 }
24
25 public SdkStyleProjectGeneration() : base(
26 Directory.GetParent(Application.dataPath)?.FullName,
27 new SdkStyleAssemblyNameProvider(),
28 new FileIOProvider(),
29 new GUIDProvider())
30 {
31 }
32
33 internal static readonly string[] SupportedCapabilities = new string[]
34 {
35 "Unity",
36 };
37
38 internal static readonly string[] UnsupportedCapabilities = new string[]
39 {
40 "LaunchProfiles",
41 "SharedProjectReferences",
42 "ReferenceManagerSharedProjects",
43 "ProjectReferences",
44 "ReferenceManagerProjects",
45 "COMReferences",
46 "ReferenceManagerCOM",
47 "AssemblyReferences",
48 "ReferenceManagerAssemblies",
49 };
50
51 internal override void GetProjectHeader(ProjectProperties properties, out StringBuilder headerBuilder)
52 {
53 headerBuilder = new StringBuilder();
54
55 headerBuilder.Append(@"<Project ToolsVersion=""Current"">").Append(k_WindowsNewline);
56 headerBuilder.Append(@" <!-- Generated file, do not modify, your changes will be overwritten (use AssetPostprocessor.OnGeneratedCSProject) -->").Append(k_WindowsNewline);
57
58 // Prevent circular dependency issues see https://github.com/microsoft/vscode-dotnettools/issues/401
59 // We need a dedicated subfolder for each project in obj, else depending on the build order, nuget cache files could be overwritten
60 // 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
61 headerBuilder.Append(@" <PropertyGroup>").Append(k_WindowsNewline);
62 headerBuilder.Append($" <BaseIntermediateOutputPath>{@"Temp\obj\$(Configuration)\$(MSBuildProjectName)".NormalizePathSeparators()}</BaseIntermediateOutputPath>").Append(k_WindowsNewline);
63 headerBuilder.Append(@" <IntermediateOutputPath>$(BaseIntermediateOutputPath)</IntermediateOutputPath>").Append(k_WindowsNewline);
64 headerBuilder.Append(@" </PropertyGroup>").Append(k_WindowsNewline);
65
66 // Supported capabilities
67 GetCapabilityBlock(headerBuilder, "Sdk.props", "Include", SupportedCapabilities);
68
69 headerBuilder.Append(@" <PropertyGroup>").Append(k_WindowsNewline);
70 headerBuilder.Append(@" <GenerateAssemblyInfo>false</GenerateAssemblyInfo>").Append(k_WindowsNewline);
71 headerBuilder.Append(@" <EnableDefaultItems>false</EnableDefaultItems>").Append(k_WindowsNewline);
72 headerBuilder.Append(@" <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>").Append(k_WindowsNewline);
73 headerBuilder.Append(@" <LangVersion>").Append(properties.LangVersion).Append(@"</LangVersion>").Append(k_WindowsNewline);
74 headerBuilder.Append(@" <Configurations>Debug;Release</Configurations>").Append(k_WindowsNewline);
75 headerBuilder.Append(@" <Configuration Condition="" '$(Configuration)' == '' "">Debug</Configuration>").Append(k_WindowsNewline);
76 headerBuilder.Append(@" <Platform Condition="" '$(Platform)' == '' "">AnyCPU</Platform>").Append(k_WindowsNewline);
77 headerBuilder.Append(@" <RootNamespace>").Append(properties.RootNamespace).Append(@"</RootNamespace>").Append(k_WindowsNewline);
78 headerBuilder.Append(@" <OutputType>Library</OutputType>").Append(k_WindowsNewline);
79 headerBuilder.Append(@" <AppDesignerFolder>Properties</AppDesignerFolder>").Append(k_WindowsNewline);
80 headerBuilder.Append(@" <AssemblyName>").Append(properties.AssemblyName).Append(@"</AssemblyName>").Append(k_WindowsNewline);
81 // 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.
82 // 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.
83 // Unity already selected proper API surface through referenced DLLs for us.
84 headerBuilder.Append(@" <TargetFramework>netstandard2.1</TargetFramework>").Append(k_WindowsNewline);
85 headerBuilder.Append(@" <BaseDirectory>.</BaseDirectory>").Append(k_WindowsNewline);
86 headerBuilder.Append(@" </PropertyGroup>").Append(k_WindowsNewline);
87
88 GetProjectHeaderConfigurations(properties, headerBuilder);
89
90 // Explicit references
91 headerBuilder.Append(@" <PropertyGroup>").Append(k_WindowsNewline);
92 headerBuilder.Append(@" <NoStandardLibraries>true</NoStandardLibraries>").Append(k_WindowsNewline);
93 headerBuilder.Append(@" <NoStdLib>true</NoStdLib>").Append(k_WindowsNewline);
94 headerBuilder.Append(@" <NoConfig>true</NoConfig>").Append(k_WindowsNewline);
95 headerBuilder.Append(@" <DisableImplicitFrameworkReferences>true</DisableImplicitFrameworkReferences>").Append(k_WindowsNewline);
96 headerBuilder.Append(@" <MSBuildWarningsAsMessages>MSB3277</MSBuildWarningsAsMessages>").Append(k_WindowsNewline);
97 headerBuilder.Append(@" </PropertyGroup>").Append(k_WindowsNewline);
98
99 GetProjectHeaderVstuFlavoring(properties, headerBuilder, false);
100 GetProjectHeaderAnalyzers(properties, headerBuilder);
101 }
102
103 internal override void AppendProjectReference(Assembly assembly, Assembly reference, StringBuilder projectBuilder)
104 {
105 // If the current assembly is a Player project, we want to project-reference the corresponding Player project
106 var referenceName = m_AssemblyNameProvider.GetAssemblyName(assembly.outputPath, reference.name);
107 projectBuilder.Append(@" <ProjectReference Include=""").Append(referenceName).Append(GetProjectExtension()).Append(@""" />").Append(k_WindowsNewline);
108 }
109
110 internal override void GetProjectFooter(StringBuilder footerBuilder)
111 {
112 // Unsupported capabilities
113 GetCapabilityBlock(footerBuilder, "Sdk.targets", "Remove", UnsupportedCapabilities);
114
115 footerBuilder.Append("</Project>").Append(k_WindowsNewline);
116 }
117
118 internal static void GetCapabilityBlock(StringBuilder footerBuilder, string import, string attribute, string[] capabilities)
119 {
120 footerBuilder.Append($@" <Import Project=""{import}"" Sdk=""Microsoft.NET.Sdk"" />").Append(k_WindowsNewline);
121 footerBuilder.Append(@" <ItemGroup>").Append(k_WindowsNewline);
122 foreach (var capability in capabilities)
123 {
124 footerBuilder.Append($@" <ProjectCapability {attribute}=""{capability}"" />").Append(k_WindowsNewline);
125 }
126 footerBuilder.Append(@" </ItemGroup>").Append(k_WindowsNewline);
127 }
128 }
129}