initial commit

This commit is contained in:
Booklordofthedings 2024-05-11 17:46:34 +02:00
commit 851d32f6b6
9 changed files with 1132 additions and 0 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
build/
recovery/
BeefSpace_User.toml

6
BeefProj.toml Normal file
View file

@ -0,0 +1,6 @@
FileVersion = 1
[Project]
Name = "Projector"
TargetType = "BeefLib"
StartupObject = "Projector.Program"

5
BeefSpace.toml Normal file
View file

@ -0,0 +1,5 @@
FileVersion = 1
Projects = {Projector = {Path = "."}}
[Workspace]
StartupProject = "Projector"

21
LICENSE Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2024 Jannis
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

4
README.md Normal file
View file

@ -0,0 +1,4 @@
# Projector
A gameengine editor might want to create a new project and workspace that are already depending on the engine library and have some postbuild actions.
In order to enable this I made this library, it allows users to create a beef object that mirrors a project or workspace file and then generate the corresponding toml string by calling *ToTOML(String buffer)*.
The basic usage should be understandable from the two example files in the scr/example directory.

View file

@ -0,0 +1,32 @@
namespace Projector.Examples;
using System;
class ExampleProject
{
//[Test]
public static void Test()
{
Project example = new .();
defer delete example;
example.Name = "Testproject";
example.StartupObject = "Testproject.Program";
example.TargetType = .BeefLib;
example.AddProjectNameAlias("OtherName");
example.AddProjectNameAlias("More Name");
example.AddDependency("raylib");
example.AddPreprocessorMacro("asdsadsa");
example.AddDistinctBuildOption( scope .("System.String"));
example.TargetedOptions["Test","Win32"].AddLibPaths("sadsadsad");
example.TargetedOptions["Test","Win32"].AddLibPaths("sadsadsad");
example.TargetedOptions["Test","Win64"].BeefLibrary = .Static;
//Uncomment to output
/*
Console.WriteLine(example.ToTOML(.. scope .()));
Console.Read();
*/
}
}

View file

@ -0,0 +1,33 @@
namespace Projector.Examples;
using System;
class ExampleWorkspace
{
//[Test]
public static void Test()
{
Workspace example = new .();
defer delete example;
Workspace.WSProject p = scope .("Raylib");
Workspace.WSProject c = scope .("corlib","*","",.Unlocked);
example.AddWSProject(p);
example.AddWSProject(c);
example.SetStartupProject(p);
example.TargetedOptions["Debug", "Win64"].EnableHotCompilation = true;
Workspace.DistinctbuildOptions b = scope .("System.String");
b.SIMDSetting = .SSE2;
example.AddDistinctBuildOption(b);
example.TargetedOptions["Debug", "Win64"].AddDistinctBuildOption(b);
example.TargetedOptions["Debug", "Win64"].AddConfigSelection(p,"DebugStatic", "Win64");
//Uncomment to output
/*
Console.WriteLine(example.ToTOML(.. scope .()));
Console.Read();
*/
}
}

399
src/Project.bf Normal file
View file

@ -0,0 +1,399 @@
namespace Projector;
using System;
using System.Reflection;
using System.Collections;
class Project
{
public class PlatformSettings
{
private Dictionary<String, Dictionary<String, String>> _Settings = new .() {
(new .("Windows"), new .() {
(new .("IconFile"), new .()),
(new .("ManifestFile"), new .()),
(new .("Description"), new .()),
(new .("Comments"), new .()),
(new .("Company"), new .()),
(new .("Product"), new .()),
(new .("Copyright"), new .()),
(new .("FileVersion"), new .()),
(new .("ProductVersion"), new .())
})
};
public ~this()
{
for(var i in _Settings)
DeleteDictionaryAndKeysAndValues!(i.value);
DeleteDictionaryAndKeys!(_Settings);
}
public String this[StringView platform, StringView field]
{
public get {
if(!_Settings.ContainsKeyAlt<StringView>(platform))
_Settings.Add(new .(platform), new .());
if(!_Settings[scope .(platform)].ContainsKeyAlt<StringView>(field))
_Settings[scope .(platform)].Add(new .(field), new .(""));
return _Settings[scope .(platform)][scope .(field)];
}
public set {
if(!_Settings.ContainsKeyAlt<StringView>(platform))
_Settings.Add(new .(platform), new .());
if(!_Settings[scope .(platform)].ContainsKeyAlt<StringView>(field))
_Settings[scope .(platform)].Add(new .(field), new .(""));
_Settings[scope .(platform)][scope .(field)].Clear();
_Settings[scope .(platform)][scope .(field)].Append(value);
}
}
///Gets all available fields for a specific platform (eg. Windows)
public void GetPlatformFields(StringView platform,ref List<String> fields)
{
if(!_Settings.ContainsKeyAlt<StringView>(platform))
return;
for(var i in _Settings[scope .(platform)])
fields.Add(i.key);
}
public void ToTOML(String buffer)
{
for(var i in _Settings)
{
int nonZeros = 0;
for(var j in i.value)
if(j.value != "")
nonZeros++;
if(nonZeros > 0)
{
buffer.Append(scope $"[Platfom.{i.key}]\n");
for(var j in i.value)
if(j.value != "")
buffer.Append(scope $"{j.key} = \"{j.value}\"\n");
buffer.Append("\n");
}
}
}
}
public class TargetedOptionsContainer
{
public class TargetedOptions
{
public enum RelocModel
{
Static,
PIC,
DynamicNoPIC,
ROPI,
RWPI,
ROPI_RWPI
}
public enum PICLevel
{
Not,
Small,
Big
}
public enum CLibType
{
Dynamic,
Static,
DynamicDebug,
StaticDebug,
SystemMSVCRT
}
public enum BeefLibType
{
Dynamic,
Static,
DynamicDebug
}
public enum CommandsLogic
{
Never,
Always,
IfFilesChanged
}
private List<String> _PreprocessorMacros = new .() ~ DeleteContainerAndItems!(_);
private List<String> _LibPaths = new .() ~ DeleteContainerAndItems!(_);
private List<String> _LinkDependencies = new .() ~ DeleteContainerAndItems!(_);
private List<String> _PreBuildCmds = new .() ~ DeleteContainerAndItems!(_);
private List<String> _PostBuildCmds = new .() ~ DeleteContainerAndItems!(_);
private List<String> _CleanCmds = new .() ~ DeleteContainerAndItems!(_);
private List<String> _EnviromentVars = new .() ~ DeleteContainerAndItems!(_);
private List<Workspace.DistinctbuildOptions> _DistinctBuildOptions = new .() ~ DeleteContainerAndItems!(_);
[ResultWrapAndGenerate("RelocType")] public RelocModel? RelocModel = null;
[ResultWrapAndGenerate("PICLevel")] public PICLevel? PICLevel = null;
[ResultWrapAndGenerate("OptimizationLevel")] public Workspace.DistinctbuildOptions.OptimizationLevel? OptimizationLevel = null;
[ResultWrapAndGenerate("LTOType")] public Workspace.TargetedOptionsContainer.TargetedOptions.LTOType? LTO = null;
[ResultWrapAndGenerate("VectorizeLoops", false)] public bool? VectorizeLoops = null;
[ResultWrapAndGenerate("VectorizeSLP", false)] public bool? VectorizeLSP = null;
[ResultWrapAndGenerate("BuildKind")] public Project.TargetType? BuildType = null;
[SelfDeleteProperty("TargetDirectory")] private String _TargetDirectory = new .("") ~ delete _;
[SelfDeleteProperty("TargetName")] private String _TargetName = new .("") ~ delete _;
[SelfDeleteProperty("OtherLinkerFlags")] private String _OtherLinkerFlags = new .("") ~ delete _;
[ResultWrapAndGenerate("ClibType")] public CLibType? CLibrary = null;
[ResultWrapAndGenerate("BeefLibType")] public BeefLibType? BeefLibrary = null;
[ResultWrapAndGenerate("StackSize",false)] public int64? StackSize = null;
[ResultWrapAndGenerate("BuildCommandsOnCompile")] public CommandsLogic? CommandsOnComile = null;
[ResultWrapAndGenerate("BuildCommandsOnRun")] public CommandsLogic? CommandsOnRun = null;
[SelfDeleteProperty("DebugCommand")] private String _DebugCommand = new .("") ~ delete _;
[SelfDeleteProperty("DebugCommandArguments")] private String _DebugCommandArguments = new .("") ~ delete _;
[SelfDeleteProperty("DebugWorkingDirectory")] private String _DebugWorkingDirectory = new .("") ~ delete _;
public void AddPreprocessorMacro(StringView macro) => _PreprocessorMacros.Add(new .(macro));
public void AddLibPaths(StringView path) => _LibPaths.Add(new .(path));
public void AddRebuildDependencies(StringView dep) => _LinkDependencies.Add(new .(dep));
public void AddPrebuildCommands(StringView cmd) => _PreBuildCmds.Add(new .(cmd));
public void AddDistinctBuildOption(Workspace.DistinctbuildOptions option) => _DistinctBuildOptions.Add(Workspace.DistinctbuildOptions.Copy(.. new .(""), option));
}
private Dictionary<String, Dictionary<String, TargetedOptions>> _Storage = new .();
public ~this()
{
for(var i in _Storage)
DeleteDictionaryAndKeysAndValues!(i.value);
DeleteDictionaryAndKeys!(_Storage);
}
public ref TargetedOptions this[StringView config, StringView platform]
{
get
{
if(!_Storage.ContainsKey(scope .(config)))
_Storage.Add(new .(config), new .());
if(!_Storage[scope .(config)].ContainsKey(scope .(platform)))
_Storage[scope .(config)].Add(new .(platform), new [Friend].());
return ref _Storage[scope .(config)][scope .(platform)];
}
set
{
if(!_Storage.ContainsKey(scope .(config)))
_Storage.Add(new .(config), new .());
if(!_Storage[scope .(config)].ContainsKey(scope .(platform)))
_Storage[scope .(config)].Add(new .(platform), new [Friend].());
_Storage[scope .(config)][scope .(platform)] = value;
}
}
public void ToTOML(String buffer)
{
for(var config in _Storage)
{
for(var platform in config.value)
{
buffer.Append(scope $"[Configs.{config.key}.{platform.key}]\n");
if(platform.value.[Friend]_PreprocessorMacros.Count > 0)
{
buffer.Append(scope $"PreprocessorMacros = [");
for(int i < platform.value.[Friend]_PreprocessorMacros.Count)
{
buffer.Append(scope $"\"{platform.value.[Friend]_PreprocessorMacros[i]}\"");
if(i+1 < platform.value.[Friend]_PreprocessorMacros.Count)
buffer.Append(", ");
}
buffer.Append("]\n");
}
platform.value.[Friend]Generate_RelocModel(buffer);
platform.value.[Friend]Generate_PICLevel(buffer);
platform.value.[Friend]Generate_OptimizationLevel(buffer);
platform.value.[Friend]Generate_LTO(buffer);
platform.value.[Friend]Generate_VectorizeLoops(buffer);
platform.value.[Friend]Generate_VectorizeLSP(buffer);
platform.value.[Friend]Generate_DebugCommand(buffer);
platform.value.[Friend]Generate_DebugCommandArguments(buffer);
platform.value.[Friend]Generate_DebugWorkingDirectory(buffer);
if(platform.value.[Friend]_EnviromentVars.Count > 0)
{
buffer.Append(scope $"EnviromentVars = [");
for(int i < platform.value.[Friend]_EnviromentVars.Count)
{
buffer.Append(scope $"\"{platform.value.[Friend]_EnviromentVars[i]}\"");
if(i+1 < platform.value.[Friend]_EnviromentVars.Count)
buffer.Append(", ");
}
buffer.Append("]\n");
}
platform.value.[Friend]Generate_BuildType(buffer);
platform.value.[Friend]Generate_TargetDirectory(buffer);
platform.value.[Friend]Generate_TargetName(buffer);
platform.value.[Friend]Generate_OtherLinkerFlags(buffer);
platform.value.[Friend]Generate_CLibrary(buffer);
platform.value.[Friend]Generate_BeefLibrary(buffer);
platform.value.[Friend]Generate_StackSize(buffer);
platform.value.[Friend]Generate_CommandsOnComile(buffer);
platform.value.[Friend]Generate_CommandsOnRun(buffer);
if(platform.value.[Friend]_LibPaths.Count > 0)
{
buffer.Append(scope $"LibPaths = [");
for(int i < platform.value.[Friend]_LibPaths.Count)
{
buffer.Append(scope $"\"{platform.value.[Friend]_LibPaths[i]}\"");
if(i+1 < platform.value.[Friend]_LibPaths.Count)
buffer.Append(", ");
}
buffer.Append("]\n");
}
if(platform.value.[Friend]_LinkDependencies.Count > 0)
{
buffer.Append(scope $"LinkDependencies = [");
for(int i < platform.value.[Friend]_LinkDependencies.Count)
{
buffer.Append(scope $"\"{platform.value.[Friend]_LinkDependencies[i]}\"");
if(i+1 < platform.value.[Friend]_LinkDependencies.Count)
buffer.Append(", ");
}
buffer.Append("]\n");
}
if(platform.value.[Friend]_PreBuildCmds.Count > 0)
{
buffer.Append(scope $"PreBuildCmds = [");
for(int i < platform.value.[Friend]_PreBuildCmds.Count)
{
buffer.Append(scope $"\"{platform.value.[Friend]_PreBuildCmds[i]}\"");
if(i+1 < platform.value.[Friend]_PreBuildCmds.Count)
buffer.Append(", ");
}
buffer.Append("]\n");
}
if(platform.value.[Friend]_PostBuildCmds.Count > 0)
{
buffer.Append(scope $"PostBuildCmds = [");
for(int i < platform.value.[Friend]_PostBuildCmds.Count)
{
buffer.Append(scope $"\"{platform.value.[Friend]_PostBuildCmds[i]}\"");
if(i+1 < platform.value.[Friend]_PostBuildCmds.Count)
buffer.Append(", ");
}
buffer.Append("]\n");
}
if(platform.value.[Friend]_CleanCmds.Count > 0)
{
buffer.Append(scope $"CleanCmds = [");
for(int i < platform.value.[Friend]_CleanCmds.Count)
{
buffer.Append(scope $"\"{platform.value.[Friend]_CleanCmds[i]}\"");
if(i+1 < platform.value.[Friend]_CleanCmds.Count)
buffer.Append(", ");
}
buffer.Append("]\n");
}
buffer.Append("\n");
for(var i in platform.value.[Friend]_DistinctBuildOptions)
{
buffer.Append(scope $"[[Configs.{config.key}.{platform.key}.DistinctOptions]]\n");
i.ToToml(buffer);
buffer.Append('\n');
}
}
}
}
}
public enum TargetType
{
BeefConsoleApplication,
BeefGUIApplication,
BeefLib,
CustomBuild,
BeefTest
}
[ResultWrapAndGenerate("FileVersion", false)] public uint8? FileVersion = 1;
[SelfDeleteProperty("Name")] private String _Name = new .("") ~ delete _;
[SelfDeleteProperty("StartupObject")] private String _StartupObject = new .("") ~ delete _;
[SelfDeleteProperty("DefaultNamespace")] private String _DefaultNamespace = new .("") ~ delete _;
private List<String> _preprocessorMacros = new .() ~ DeleteContainerAndItems!(_);
[ResultWrapAndGenerate("TargetType")] public TargetType? TargetType = null;
private List<String> _Aliases = new .() ~ DeleteContainerAndItems!(_);
private List<String> _Dependencies = new .() {new .("corlib")}~ DeleteContainerAndItems!(_);
private List<Workspace.DistinctbuildOptions> _DistinctBuildOptions = new .() ~ DeleteContainerAndItems!(_);
public PlatformSettings Platform = new .() ~ delete _;
public void AddProjectNameAlias(StringView name) => _Aliases.Add(new .(name));
public void AddDependency(StringView name) => _Dependencies.Add(new .(name));
public void AddPreprocessorMacro(StringView macro) => _preprocessorMacros.Add(new .(macro));
public void AddDistinctBuildOption(Workspace.DistinctbuildOptions option) => _DistinctBuildOptions.Add(Workspace.DistinctbuildOptions.Copy(.. new .(""), option));
public TargetedOptionsContainer TargetedOptions = new .() ~ delete _;
public void ToTOML(String strBuffer)
{
Generate_FileVersion(strBuffer);
strBuffer.Append("Dependencies = {");
for(int i < _Dependencies.Count)
{
strBuffer.Append(scope $"{_Dependencies[i]} = \"*\"");
if(i+1 < _Dependencies.Count)
strBuffer.Append(", ");
}
strBuffer.Append("}\n");
strBuffer.Append('\n');
strBuffer.Append("[Project]\n");
Generate_Name(strBuffer);
Generate_TargetType(strBuffer);
Generate_StartupObject(strBuffer);
Generate_DefaultNamespace(strBuffer);
strBuffer.Append("Aliases = [");
for(int i < _Aliases.Count)
{
strBuffer.Append(scope $"\"{_Aliases[i]}\"");
if(i+1 < _Aliases.Count)
strBuffer.Append(", ");
}
strBuffer.Append("]\n");
if(_preprocessorMacros.Count > 0)
{
strBuffer.Append("PreprocessorMacros = [");
for(int i < _preprocessorMacros.Count)
{
strBuffer.Append(scope $"\"{_preprocessorMacros[i]}\"");
if(i+1 < _preprocessorMacros.Count)
strBuffer.Append(", ");
}
strBuffer.Append("]\n");
}
strBuffer.Append('\n');
for(var i in _DistinctBuildOptions)
i.ToToml(strBuffer, "Project");
Platform.ToTOML(strBuffer);
TargetedOptions.ToTOML(strBuffer);
while(strBuffer.EndsWith('\n'))
strBuffer.RemoveFromEnd(1);
}
}

629
src/Workspace.bf Normal file
View file

@ -0,0 +1,629 @@
namespace Projector;
using System;
using System.Reflection;
using System.Collections;
class Workspace
{
///A simpler version of a beef project for use in workspace generation
public class WSProject
{
public enum ProjectLockState
{
Locked,
Unlocked,
}
[SelfDeleteProperty("")] private String _Name = new .("") ~ delete _;
[SelfDeleteProperty("")] private String _Path = new .() ~ delete _;
[SelfDeleteProperty("")] private String _Folder = new .() ~ delete _;
[ResultWrapAndGenerate("")] public ProjectLockState? Lockstate = null;
public this(StringView name, StringView path = "*", StringView folder = "", ProjectLockState? lockstate = null)
{
Name = scope .(name);
Path = scope .(path);
Folder = scope .(folder);
Lockstate = lockstate;
}
public static void Copy(WSProject target, WSProject src)
{
target.Name = scope .(src._Name);
target.Path = scope .(src._Path);
target.Folder = scope .(src._Folder);
target.Lockstate = src.Lockstate;
}
}
public class DistinctbuildOptions
{
public enum SIMDSetting
{
None,
MMX,
SSE,
SSE2,
SSE3,
SSE4,
SSE41,
AVX,
AVX2,
}
public enum OptimizationLevel
{
O0,
O1,
O2,
O3,
Og,
OgPlus,
}
public enum DebugInfo
{
Yes,
No,
LinesOnly,
}
public class ReflectOptions
{
public enum AlwaysIncludeOptions
{
No,
IncludeType,
AssumeInstantiated,
IncludeAll,
IncludeFiltered,
}
[ResultWrapAndGenerate("ReflectAlwaysInclude")] public AlwaysIncludeOptions? AlwaysInclude = null;
[ResultWrapAndGenerate("ReflectBoxing", false)] public bool? DynamicBoxing = null;
[ResultWrapAndGenerate("ReflectStaticFields", false)] public bool? StaticFields = null;
[ResultWrapAndGenerate("ReflectNonStaticFields", false)] public bool? NonStaticFields = null;
[ResultWrapAndGenerate("ReflectStaticMethods", false)] public bool? StaticMethods = null;
[ResultWrapAndGenerate("ReflectNonStaticMethods", false)] public bool? NonStaticMethods = null;
[ResultWrapAndGenerate("ReflectConstructors", false)] public bool? Constructors = null;
[SelfDeleteProperty("ReflectMethodFilter")] private String _MethodFilter = new .("") ~ delete _;
public static void Copy(ReflectOptions target, ReflectOptions src)
{
target.AlwaysInclude = src.AlwaysInclude;
target.DynamicBoxing = src.DynamicBoxing;
target.StaticFields = src.StaticFields;
target.NonStaticFields = src.NonStaticFields;
target.StaticMethods = src.StaticMethods;
target.NonStaticMethods = src.NonStaticMethods;
target.Constructors = src.Constructors;
target.MethodFilter = scope .(src._MethodFilter);
}
public void ToToml(String buffer)
{
Generate_AlwaysInclude(buffer);
Generate_DynamicBoxing(buffer);
Generate_StaticFields(buffer);
Generate_NonStaticFields(buffer);
Generate_StaticMethods(buffer);
Generate_NonStaticMethods(buffer);
Generate_Constructors(buffer);
Generate_MethodFilter(buffer);
}
}
public this(StringView filter)
{
Filter = scope .(filter);
}
[SelfDeleteProperty("Filter")] private String _Filter = new .() ~ delete _;
[ResultWrapAndGenerate("BfSIMDSetting")] public SIMDSetting? SIMDSetting = null;
[ResultWrapAndGenerate("BfOptimizationLevel")] public OptimizationLevel? OptimizationLevel = null;
[ResultWrapAndGenerate("EmitDebugInfo")] public DebugInfo? DebugInfo = null;
[ResultWrapAndGenerate("RuntimeChecks", false)] public bool? RuntimeChecks = null;
[ResultWrapAndGenerate("EmitDynamicCastCheck", false)] public bool? DynamicCastCheck = null;
[ResultWrapAndGenerate("EmitObjectAcessCheck", false)] public bool? ObjectAcessCheck = null;
[ResultWrapAndGenerate("ArithmeticCheck", false)] public bool? ArithmeticCheck = null;
[ResultWrapAndGenerate("AllocStackTraceDepth", false)] public uint16? AllocStackTraceDepth = null;
private ReflectOptions _Reflect = new .() ~ delete _;
public ReflectOptions Reflect
{
get => _Reflect;
set
{
delete _Reflect;
_Reflect = new .();
ReflectOptions.Copy(_Reflect, value);
}
}
public static void Copy(DistinctbuildOptions target, DistinctbuildOptions src)
{
target.Filter = scope .(src._Filter);
target.SIMDSetting = src.SIMDSetting;
target.OptimizationLevel = src.OptimizationLevel;
target.DebugInfo = src.DebugInfo;
target.RuntimeChecks = src.RuntimeChecks;
target.DynamicCastCheck = src.DynamicCastCheck;
target.ObjectAcessCheck = src.ObjectAcessCheck;
target.ArithmeticCheck = src.ArithmeticCheck;
target.AllocStackTraceDepth = src.AllocStackTraceDepth;
target.Reflect = src._Reflect;
}
public void ToToml(String buffer, StringView target = "Workspace")
{
buffer.Append(scope $"[[{target}.DistinctOptions]]\n");
Generate_Filter(buffer);
Generate_SIMDSetting(buffer);
Generate_OptimizationLevel(buffer);
Generate_DebugInfo(buffer);
Generate_RuntimeChecks(buffer);
Generate_DynamicCastCheck(buffer);
Generate_ObjectAcessCheck(buffer);
Generate_ArithmeticCheck(buffer);
Generate_AllocStackTraceDepth(buffer);
Reflect.ToToml(buffer);
buffer.Append("\n");
}
}
public class TargetedOptionsContainer
{
public class TargetedOptions
{
public enum Toolset
{
Gnu,
Microsoft,
LLVM
}
public enum BuildType
{
Normal,
Test
}
public enum IntermediateType
{
Object,
IRCode,
ObjectAndIRCode,
Bitcode,
BitcodeAndIRCode
}
public enum MemoryAllocator
{
CRT,
Debug,
StompParanoid,
JEMalloc,
JEMallocDebug,
TCMalloc,
TCMallocDebug,
Custom
}
public enum LTOType
{
Thin,
None
}
public enum Runtime
{
Reduced,
Disabled
}
public enum Reflection
{
Normal,
Minimal
}
private this() { }
public ~this()
{
for(var i in _ConfigSelections)
{
delete i.value.0;
delete i.value.1;
}
DeleteDictionaryAndKeys!(_ConfigSelections);
}
public void AddPreprocessorMacro(StringView macro) => _PreprocessorMacros.Add(new .(macro));
public void AddDistinctBuildOption(DistinctbuildOptions option)
{
_DistinctBuildOptions.Add(DistinctbuildOptions.Copy(.. new .(""), option));
}
///Compile a different version of the lib than the current one
public void AddConfigSelection(WSProject project, StringView config, StringView platform)
{
_ConfigSelections.Add(WSProject.Copy(.. new .(""), project), (new .(config), new .(platform)));
}
[ResultWrapAndGenerate("Toolset")] public Toolset? Toolset = null;
[ResultWrapAndGenerate("BuildKind")] public BuildType? BuildKind = null;
private Dictionary<WSProject, (String, String)> _ConfigSelections = new .();
private List<String> _PreprocessorMacros = new .() ~ DeleteContainerAndItems!(_);
private List<DistinctbuildOptions> _DistinctBuildOptions = new .() ~ DeleteContainerAndItems!(_);
[ResultWrapAndGenerate("IncrementalBuild", false)] public bool? IncrementalBuild = null;
[ResultWrapAndGenerate("IntermediateType")] public IntermediateType? Intermediatetype = null;
[ResultWrapAndGenerate("AllocType")] public MemoryAllocator? MemoryAllocator = null;
[SelfDeleteProperty("AllocMalloc")] private String _AllocMalloc = new .("") ~ delete _;
[SelfDeleteProperty("AllocFree")] private String _AllocFree = new .("") ~ delete _;
[SelfDeleteProperty("TargetTriple")] private String _TargetTriple = new .("") ~ delete _;
[SelfDeleteProperty("TargetCPU")] private String _TargetCPU = new .("") ~ delete _;
[ResultWrapAndGenerate("BfSIMDSetting")] public DistinctbuildOptions.SIMDSetting? SimdSettings = null;
[ResultWrapAndGenerate("BfOptimizationLevel")] public DistinctbuildOptions.OptimizationLevel? OptimizationLevel = null;
[ResultWrapAndGenerate("LTOType")] public LTOType? LTOType = null;
[ResultWrapAndGenerate("NoOmitFramePointers", false)] public bool? NoOmitFramePointers = null;
[ResultWrapAndGenerate("LargeStrings", false)] public bool? LargeStrings = null;
[ResultWrapAndGenerate("LargeCollections", false)] public bool? LargeCollections = null;
[ResultWrapAndGenerate("RuntimeKind")] public Runtime? Runtime = null;
[ResultWrapAndGenerate("ReflectKind")] public Reflection? Reflection = null;
//Debug
[ResultWrapAndGenerate("EmitDebugInfo")] public DistinctbuildOptions.DebugInfo? DebugInfo = null;
[ResultWrapAndGenerate("RuntimeChecks", false)] public bool? RuntimeChecks = null;
[ResultWrapAndGenerate("EmitDynamicCastCheck, false")] public bool? DynamicCastCheck = null;
[ResultWrapAndGenerate("EnableObjectDebugFlags", false)] public bool? ObjectDebugFlags = null;
[ResultWrapAndGenerate("EmitObjectAcessCheck", false)] public bool? ObjectAcessCheck = null;
[ResultWrapAndGenerate("ArithmeticCheck", false)] public bool? ArithmeticCheck = null;
[ResultWrapAndGenerate("EnableRealtimeLeakCheck", false)] public bool? RealtimeLeakCheck = null;
[ResultWrapAndGenerate("AllowHotSwapping", false)] public bool? EnableHotCompilation = null;
[ResultWrapAndGenerate("AllocStackTraceDepth", false)] public uint16? AllocStackTraceDepth = null;
}
private Dictionary<String, Dictionary<String, TargetedOptions>> _Storage = new .();
public ~this()
{
for(var i in _Storage)
DeleteDictionaryAndKeysAndValues!(i.value);
DeleteDictionaryAndKeys!(_Storage);
}
public ref TargetedOptions this[StringView a, StringView b]
{
get
{
if(!_Storage.ContainsKey(scope .(a)))
_Storage.Add(new .(a), new .());
if(!_Storage[scope .(a)].ContainsKey(scope .(b)))
_Storage[scope .(a)].Add(new .(b), new [Friend].());
return ref _Storage[scope .(a)][scope .(b)];
}
set
{
if(!_Storage.ContainsKey(scope .(a)))
_Storage.Add(new .(a), new .());
if(!_Storage[scope .(a)].ContainsKey(scope .(b)))
_Storage[scope .(a)].Add(new .(b), new [Friend].());
_Storage[scope .(a)][scope .(b)] = value;
}
}
public void ToTOML(String buffer)
{
for(var config in _Storage)
{
for(var platform in config.value)
{
buffer.Append(scope $"[Configs.{config.key}.{platform.key}]\n");
if(platform.value.[Friend]_ConfigSelections.Count > 0)
{
buffer.Append("ConfigSelections = {");
int count = 0;
for(var i in platform.value.[Friend]_ConfigSelections)
{
buffer.Append(scope $"{i.key.Name} = \{");
if(i.value.0 != "")
{
buffer.Append(scope $"Config = \"{i.value.0}\"");
if(i.value.1 != "")
buffer.Append(", ");
}
if(i.value.1 != "")
buffer.Append(scope $"Platform = \"{i.value.1}\"");
buffer.Append("}");
if(count+1 < platform.value.[Friend]_ConfigSelections.Count)
buffer.Append(", ");
count++;
}
buffer.Append("}\n");
}
if(platform.value.[Friend]_PreprocessorMacros.Count > 0)
{
buffer.Append("PreprocessorMacros = [");
for(int i < platform.value.[Friend]_PreprocessorMacros.Count)
{
buffer.Append(scope $"\"{platform.value.[Friend]_PreprocessorMacros[i]}\"");
if(i+1 < platform.value.[Friend]_PreprocessorMacros.Count)
buffer.Append(", ");
}
buffer.Append("]\n");
}
platform.value.[Friend]Generate_Toolset(buffer);
platform.value.[Friend]Generate_BuildKind(buffer);
platform.value.[Friend]Generate_IncrementalBuild(buffer);
platform.value.[Friend]Generate_Intermediatetype(buffer);
platform.value.[Friend]Generate_MemoryAllocator(buffer);
if(platform.value.MemoryAllocator == .Custom)
{
platform.value.[Friend]Generate_AllocFree(buffer);
platform.value.[Friend]Generate_AllocMalloc(buffer);
}
platform.value.[Friend]Generate_TargetTriple(buffer);
platform.value.[Friend]Generate_TargetCPU(buffer);
platform.value.[Friend]Generate_SimdSettings(buffer);
platform.value.[Friend]Generate_OptimizationLevel(buffer);
platform.value.[Friend]Generate_LTOType(buffer);
platform.value.[Friend]Generate_NoOmitFramePointers(buffer);
platform.value.[Friend]Generate_LargeStrings(buffer);
platform.value.[Friend]Generate_LargeCollections(buffer);
platform.value.[Friend]Generate_Runtime(buffer);
platform.value.[Friend]Generate_Reflection(buffer);
platform.value.[Friend]Generate_DebugInfo(buffer);
platform.value.[Friend]Generate_RuntimeChecks(buffer);
platform.value.[Friend]Generate_DynamicCastCheck(buffer);
platform.value.[Friend]Generate_ObjectDebugFlags(buffer);
platform.value.[Friend]Generate_ObjectAcessCheck(buffer);
platform.value.[Friend]Generate_ArithmeticCheck(buffer);
platform.value.[Friend]Generate_RealtimeLeakCheck(buffer);
platform.value.[Friend]Generate_EnableHotCompilation(buffer);
platform.value.[Friend]Generate_AllocStackTraceDepth(buffer);
buffer.Append('\n');
for(var i in platform.value.[Friend]_DistinctBuildOptions)
{
i.ToToml(buffer, scope $"Configs.{config.key}.{platform.key}");
buffer.Append('\n');
}
}
}
}
}
[ResultWrapAndGenerate("FileVersion", false)] public uint8? FileVersion = 1;
private List<String> _PreprocessorMacros = new .() ~ DeleteContainerAndItems!(_);
private List<DistinctbuildOptions> _DistinctBuildOptions = new .() ~ DeleteContainerAndItems!(_);
private List<String> _ExtraPlatforms = new .() ~ DeleteContainerAndItems!(_);
private WSProject _StartupProject = null ~ delete _;
private List<WSProject> _Projects= new .() ~ DeleteContainerAndItems!(_);
public TargetedOptionsContainer TargetedOptions = new .() ~ delete _;
public void AddPreprocessorMacro(StringView macro) => _PreprocessorMacros.Add(new .(macro));
public void AddExtraPlatform(StringView platform) => _ExtraPlatforms.Add(new .(platform));
public void AddDistinctBuildOption(DistinctbuildOptions option)
{
_DistinctBuildOptions.Add(DistinctbuildOptions.Copy(.. new .(""), option));
}
public void SetStartupProject(WSProject project)
{
if(_StartupProject != null)
delete _StartupProject;
WSProject startup = new .("");
_StartupProject = WSProject.Copy(.. startup, project);
}
public void AddWSProject(WSProject project)
{
WSProject toAdd = new .("");
WSProject.Copy(toAdd, project);
_Projects.Add(toAdd);
}
public void ToTOML(String strBuffer)
{
Generate_FileVersion(strBuffer);
//Projects = {Projector = {Path = "."}}
strBuffer.Append("Projects = { ");
for(int i < _Projects.Count)
{
if(_Projects[i].Name != "corlib")
{
strBuffer.Append(scope $"{_Projects[i].Name} = \{Path = \"{_Projects[i].Path}\"\}");
if(i+1 < _Projects.Count && _Projects[i+1].Name != "corlib")
strBuffer.Append(", ");
}
}
strBuffer.Append("}\n");
if(_ExtraPlatforms.Count > 0)
{
strBuffer.Append("ExtraPlatforms = [");
for(int i < _ExtraPlatforms.Count)
{
strBuffer.Append(scope $"\"{_ExtraPlatforms[i]}\"");
if(i+1 < _ExtraPlatforms.Count)
strBuffer.Append(", ");
}
strBuffer.Append("]\n");
}
Dictionary<String, List<WSProject>> folders = new .();
defer {DeleteDictionaryAndKeysAndValues!(folders);}
for(var i in _Projects)
{
if(i.Folder != "")
{
if(!folders.ContainsKey(i.Folder))
folders.Add(new .(i.Folder), new .());
folders[i.Folder].Add(i);
}
}
if(folders.Count > 0)
{
int counter = 0;
strBuffer.Append("WorkspaceFolders = {");
for(var i in folders)
{
strBuffer.Append(scope $"\"{i.key}\" = [");
for(int j < i.value.Count)
{
strBuffer.Append(scope $"\"{i.value[j].Name}\"");
if(j+1 < i.value.Count)
strBuffer.Append(", ");
}
strBuffer.Append("]");
if(counter+1 < folders.Count)
strBuffer.Append(", ");
counter++;
}
strBuffer.Append("}\n");
}
List<WSProject> locked = scope .();
GetLocked(locked);
if(locked.Count > 0)
{
strBuffer.Append("Locked = [");
for(int i < locked.Count)
{
strBuffer.Append(scope $"\"{locked[i].Name}\"");
if(i++ < locked.Count)
strBuffer.Append(", ");
}
strBuffer.Append("]\n");
}
List<WSProject> unlocked = scope .();
GetUnlocked(unlocked);
if(unlocked.Count > 0)
{
strBuffer.Append("Locked = [");
for(int i < unlocked.Count)
{
strBuffer.Append(scope $"\"{unlocked[i].Name}\"");
if(i++ < locked.Count)
strBuffer.Append(", ");
}
strBuffer.Append("]\n");
}
strBuffer.Append("\n");
strBuffer.Append("[Workspace]\n");
if(_StartupProject != null)
strBuffer.Append(scope $"StartupProject = \"{_StartupProject.Name}\"\n");
if(_PreprocessorMacros.Count > 0)
{
strBuffer.Append("PreprocessorMacros = [");
for(int i < _PreprocessorMacros.Count)
{
strBuffer.Append(scope $"\"{_PreprocessorMacros[i]}\"");
if(i+1 < _PreprocessorMacros.Count)
strBuffer.Append(", ");
}
strBuffer.Append("]\n");
}
strBuffer.Append("\n");
for(var i in _DistinctBuildOptions)
i.ToToml(strBuffer);
TargetedOptions.ToTOML(strBuffer);
while(strBuffer.EndsWith('\n'))
strBuffer.RemoveFromEnd(1);
}
private void GetLocked(List<WSProject> locked)
{
for(var i in _Projects)
if(i.Lockstate == .Locked)
locked.Add(i);
}
private void GetUnlocked(List<WSProject> unlocked)
{
for(var i in _Projects)
if(i.Lockstate == .Unlocked)
unlocked.Add(i);
}
}
[AttributeUsage(.Field)]
struct SelfDeletePropertyAttribute : Attribute, IOnFieldInit
{
StringView _fieldName;
bool _useBrackets;
public this(StringView fieldName, bool useBrackets = true)
{
_fieldName = fieldName;
_useBrackets = useBrackets;
}
[Comptime]
public void OnFieldInit(FieldInfo fieldInfo, Self* prev) mut
{
Compiler.EmitTypeBody(fieldInfo.DeclaringType, scope $"""
public {fieldInfo.FieldType} {fieldInfo.Name.Substring(1)}
\{
get => {fieldInfo.Name};
set
\{
delete {fieldInfo.Name};
{fieldInfo.Name} = new .(value);
\}
\}
private void Generate{fieldInfo.Name}(String buffer)
\{
if({fieldInfo.Name} != "")
buffer.Append(scope $"{_fieldName} = {_useBrackets ? "\\\"" : ""}\{{fieldInfo.Name}\}{_useBrackets ? "\\\"" : ""}\\n");
\}
""");
}
}
[AttributeUsage(.Field)]
struct ResultWrapAndGenerateAttribute : Attribute, IOnFieldInit
{
StringView _fieldName;
bool _useBrackets;
public this(StringView fieldName, bool useBrackets = true)
{
_fieldName = fieldName;
_useBrackets = useBrackets;
}
[Comptime]
public void OnFieldInit(FieldInfo fieldInfo, Self* prev) mut
{
Compiler.EmitTypeBody(fieldInfo.DeclaringType, scope $"""
private void Generate_{fieldInfo.Name}(String buffer)
\{
if({fieldInfo.Name} != null)
buffer.Append(scope $"{_fieldName} = {_useBrackets ? "\\\"" : ""}\{{fieldInfo.Name}\}{_useBrackets ? "\\\"" : ""}\\n");
\}
""");
}
}