// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
namespace Flax.Build.Projects.VisualStudio
{
///
/// The Visual Studio project generator for C# projects (.NET SDK .csproj).
///
///
public class CSSDKProjectGenerator : VisualStudioProjectGenerator
{
///
public CSSDKProjectGenerator(VisualStudioVersion version) : base(version)
{
}
///
public override string ProjectFileExtension => "csproj";
///
public override TargetType? Type => TargetType.DotNetCore;
///
public override void GenerateProject(Project project)
{
var csProjectFileContent = new StringBuilder();
var vsProject = (VisualStudioProject)project;
var projectFileToolVersion = ProjectFileToolVersion;
var projectDirectory = Path.GetDirectoryName(project.Path);
var defaultTarget = project.Targets[0];
foreach (var target in project.Targets)
{
// Pick the Editor-related target
if (target.IsEditor)
{
defaultTarget = target;
break;
}
}
var defaultConfiguration = TargetConfiguration.Debug;
var defaultArchitecture = TargetArchitecture.AnyCPU;
var projectTypes = ProjectTypeGuids.ToOption(ProjectTypeGuids.WindowsCSharp);
if (vsProject.CSharp.UseFlaxVS && VisualStudioInstance.HasFlaxVS)
projectTypes = ProjectTypeGuids.ToOption(ProjectTypeGuids.FlaxVS) + ';' + projectTypes;
// Header
csProjectFileContent.AppendLine("");
csProjectFileContent.AppendLine("");
//csProjectFileContent.AppendLine(string.Format("", projectFileToolVersion));
//csProjectFileContent.AppendLine(" ");
// Properties
csProjectFileContent.AppendLine(" ");
switch (project.OutputType ?? defaultTarget.OutputType)
{
case TargetOutputType.Executable:
csProjectFileContent.AppendLine(" Exe");
break;
case TargetOutputType.Library:
csProjectFileContent.AppendLine(" Library");
break;
default: throw new ArgumentOutOfRangeException();
}
var baseConfiguration = project.Configurations.First();
var baseOutputDir = Utilities.MakePathRelativeTo(project.CSharp.OutputPath ?? baseConfiguration.TargetBuildOptions.OutputFolder, projectDirectory);
var baseIntermediateOutputPath = Utilities.MakePathRelativeTo(project.CSharp.IntermediateOutputPath ?? Path.Combine(baseConfiguration.TargetBuildOptions.IntermediateFolder, "CSharp"), projectDirectory);
var baseConfigurations = project.Configurations.Select(x => x.Name.Split('|')[0]).Distinct().ToArray();
csProjectFileContent.AppendLine(" net7.0");
csProjectFileContent.AppendLine(" enable");
csProjectFileContent.AppendLine(" disable");
csProjectFileContent.AppendLine(string.Format(" {0}", string.Join(";", baseConfigurations)));
csProjectFileContent.AppendLine(" false"); // ?
csProjectFileContent.AppendLine(" true"); // Needed for Hostfxr
csProjectFileContent.AppendLine(" true"); // ?
csProjectFileContent.AppendLine(" false"); // Prevents outputting the file under net7.0 subdirectory
csProjectFileContent.AppendLine(" $(MSBuildProjectName).CSharp"); // For backwards compatibility, keep the filename same
csProjectFileContent.AppendLine(" false"); // Prevents AssemblyInfo.cs generation (causes duplicate attributes)
csProjectFileContent.AppendLine(" false");
csProjectFileContent.AppendLine(string.Format(" {0}", baseOutputDir)); // This needs to be set here to fix errors in VS
csProjectFileContent.AppendLine(string.Format(" {0}", baseIntermediateOutputPath)); // This needs to be set here to fix errors in VS
csProjectFileContent.AppendLine(" ");
csProjectFileContent.AppendLine("");
// Default configuration
{
var configuration = project.Configurations.First();
foreach (var e in project.Configurations)
{
if (e.Configuration == defaultConfiguration && e.Target == defaultTarget && e.Platform == Platform.BuildTargetPlatform)
{
configuration = e;
break;
}
}
var defines = string.Join(";", project.Defines);
if (configuration.TargetBuildOptions.ScriptingAPI.Defines.Count != 0)
{
if (defines.Length != 0)
defines += ";";
defines += string.Join(";", configuration.TargetBuildOptions.ScriptingAPI.Defines);
}
var outputPath = Utilities.MakePathRelativeTo(project.CSharp.OutputPath ?? configuration.TargetBuildOptions.OutputFolder, projectDirectory);
var intermediateOutputPath = Utilities.MakePathRelativeTo(project.CSharp.IntermediateOutputPath ?? Path.Combine(configuration.TargetBuildOptions.IntermediateFolder, "CSharp"), projectDirectory);
csProjectFileContent.AppendLine(string.Format(" ", defaultConfiguration, defaultArchitecture));
csProjectFileContent.AppendLine(" true");
csProjectFileContent.AppendLine(" portable");
csProjectFileContent.AppendLine(string.Format(" {0}", defaultConfiguration == TargetConfiguration.Debug ? "false" : "true"));
csProjectFileContent.AppendLine(string.Format(" {0}\\", outputPath));
csProjectFileContent.AppendLine(string.Format(" {0}\\", intermediateOutputPath));
csProjectFileContent.AppendLine(string.Format(" {0}\\", intermediateOutputPath));
csProjectFileContent.AppendLine(string.Format(" {0}", defines));
csProjectFileContent.AppendLine(" prompt");
csProjectFileContent.AppendLine(" 4");
csProjectFileContent.AppendLine(" true");
if (configuration.TargetBuildOptions.ScriptingAPI.IgnoreMissingDocumentationWarnings)
csProjectFileContent.AppendLine(" 1591");
csProjectFileContent.AppendLine(string.Format(" {0}\\{1}.CSharp.xml", outputPath, project.Name));
csProjectFileContent.AppendLine(" true");
csProjectFileContent.AppendLine(" ");
}
// Configurations
foreach (var configuration in project.Configurations)
{
var defines = string.Join(";", project.Defines);
if (configuration.TargetBuildOptions.ScriptingAPI.Defines.Count != 0)
{
if (defines.Length != 0)
defines += ";";
defines += string.Join(";", configuration.TargetBuildOptions.ScriptingAPI.Defines);
}
var outputPath = Utilities.MakePathRelativeTo(project.CSharp.OutputPath ?? configuration.TargetBuildOptions.OutputFolder, projectDirectory);
var intermediateOutputPath = Utilities.MakePathRelativeTo(project.CSharp.IntermediateOutputPath ?? Path.Combine(configuration.TargetBuildOptions.IntermediateFolder, "CSharp"), projectDirectory);
csProjectFileContent.AppendLine(string.Format(" ", configuration.Name, configuration.Name.Replace(configuration.ArchitectureName, "AnyCPU")));
csProjectFileContent.AppendLine(" true");
csProjectFileContent.AppendLine(" portable");
csProjectFileContent.AppendLine(string.Format(" {0}", configuration.Configuration == TargetConfiguration.Debug ? "false" : "true"));
csProjectFileContent.AppendLine(string.Format(" {0}\\", outputPath));
csProjectFileContent.AppendLine(string.Format(" {0}\\", intermediateOutputPath));
csProjectFileContent.AppendLine(string.Format(" {0}\\", intermediateOutputPath));
csProjectFileContent.AppendLine(string.Format(" {0}", defines));
csProjectFileContent.AppendLine(" prompt");
csProjectFileContent.AppendLine(" 4");
csProjectFileContent.AppendLine(" true");
if (configuration.TargetBuildOptions.ScriptingAPI.IgnoreMissingDocumentationWarnings)
csProjectFileContent.AppendLine(" 1591");
csProjectFileContent.AppendLine(string.Format(" {0}\\{1}.CSharp.xml", outputPath, project.Name));
csProjectFileContent.AppendLine(" true");
csProjectFileContent.AppendLine(" ");
}
// Nuget Package References
csProjectFileContent.AppendLine(" ");
csProjectFileContent.AppendLine(" ");
csProjectFileContent.AppendLine(" ");
csProjectFileContent.AppendLine(" ");
csProjectFileContent.AppendLine(" ");
csProjectFileContent.AppendLine(" ");
csProjectFileContent.AppendLine(" ");
csProjectFileContent.AppendLine(" ");
// References
csProjectFileContent.AppendLine(" ");
foreach (var reference in project.CSharp.SystemReferences)
{
csProjectFileContent.AppendLine(string.Format(" ", reference));
}
foreach (var reference in project.CSharp.FileReferences)
{
csProjectFileContent.AppendLine(string.Format(" ", Path.GetFileNameWithoutExtension(reference)));
csProjectFileContent.AppendLine(string.Format(" {0}", Utilities.MakePathRelativeTo(reference, projectDirectory)));
csProjectFileContent.AppendLine(" ");
}
foreach (var dependency in project.Dependencies)
{
csProjectFileContent.AppendLine(string.Format(" ", Utilities.MakePathRelativeTo(dependency.Path, projectDirectory)));
csProjectFileContent.AppendLine(string.Format(" {0}", ((VisualStudioProject)dependency).ProjectGuid.ToString("B").ToUpperInvariant()));
csProjectFileContent.AppendLine(string.Format(" {0}", dependency.Name));
csProjectFileContent.AppendLine(" ");
}
csProjectFileContent.AppendLine(" ");
// Files and folders
csProjectFileContent.AppendLine(" ");
var files = new List();
if (project.SourceFiles != null)
files.AddRange(project.SourceFiles);
if (project.SourceDirectories != null)
{
foreach (var folder in project.SourceDirectories)
{
files.AddRange(Directory.GetFiles(folder, "*", SearchOption.AllDirectories));
}
}
foreach (var file in files)
{
string fileType;
if (file.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
fileType = "Compile";
else
fileType = "None";
var projectPath = Utilities.MakePathRelativeTo(file, projectDirectory);
csProjectFileContent.AppendLine(string.Format(" <{0} Include=\"{1}\" />", fileType, projectPath));
}
if (project.GeneratedSourceFiles != null)
{
foreach (var file in project.GeneratedSourceFiles)
{
string fileType;
if (file.EndsWith(".cs", StringComparison.OrdinalIgnoreCase))
fileType = "Compile";
else
fileType = "None";
csProjectFileContent.AppendLine(string.Format(" <{0} Visible=\"false\" Include=\"{1}\" />", fileType, file));
}
}
csProjectFileContent.AppendLine(" ");
// End
//csProjectFileContent.AppendLine(" ");
csProjectFileContent.AppendLine("");
if (defaultTarget.CustomExternalProjectFilePath == null)
{
// Save the files
Utilities.WriteFileIfChanged(project.Path, csProjectFileContent.ToString());
}
}
}
}