commit 851d32f6b6184fb4ccdc89e81ad6544e68dceb27 Author: Booklordofthedings Date: Sat May 11 17:46:34 2024 +0200 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2308b79 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +build/ +recovery/ +BeefSpace_User.toml \ No newline at end of file diff --git a/BeefProj.toml b/BeefProj.toml new file mode 100644 index 0000000..b48c433 --- /dev/null +++ b/BeefProj.toml @@ -0,0 +1,6 @@ +FileVersion = 1 + +[Project] +Name = "Projector" +TargetType = "BeefLib" +StartupObject = "Projector.Program" diff --git a/BeefSpace.toml b/BeefSpace.toml new file mode 100644 index 0000000..7c219b3 --- /dev/null +++ b/BeefSpace.toml @@ -0,0 +1,5 @@ +FileVersion = 1 +Projects = {Projector = {Path = "."}} + +[Workspace] +StartupProject = "Projector" \ No newline at end of file diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..77b24af --- /dev/null +++ b/LICENSE @@ -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. diff --git a/README.md b/README.md new file mode 100644 index 0000000..c5c2561 --- /dev/null +++ b/README.md @@ -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. diff --git a/src/Examples/ExampleProject.bf b/src/Examples/ExampleProject.bf new file mode 100644 index 0000000..a6b2f4a --- /dev/null +++ b/src/Examples/ExampleProject.bf @@ -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(); + */ + } +} \ No newline at end of file diff --git a/src/Examples/ExampleWorkspace.bf b/src/Examples/ExampleWorkspace.bf new file mode 100644 index 0000000..6a9e819 --- /dev/null +++ b/src/Examples/ExampleWorkspace.bf @@ -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(); + */ + } + + +} \ No newline at end of file diff --git a/src/Project.bf b/src/Project.bf new file mode 100644 index 0000000..4fdd909 --- /dev/null +++ b/src/Project.bf @@ -0,0 +1,399 @@ +namespace Projector; + +using System; +using System.Reflection; +using System.Collections; + +class Project +{ + public class PlatformSettings + { + private Dictionary> _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(platform)) + _Settings.Add(new .(platform), new .()); + if(!_Settings[scope .(platform)].ContainsKeyAlt(field)) + _Settings[scope .(platform)].Add(new .(field), new .("")); + return _Settings[scope .(platform)][scope .(field)]; + } + + public set { + if(!_Settings.ContainsKeyAlt(platform)) + _Settings.Add(new .(platform), new .()); + if(!_Settings[scope .(platform)].ContainsKeyAlt(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 fields) + { + if(!_Settings.ContainsKeyAlt(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 _PreprocessorMacros = new .() ~ DeleteContainerAndItems!(_); + private List _LibPaths = new .() ~ DeleteContainerAndItems!(_); + private List _LinkDependencies = new .() ~ DeleteContainerAndItems!(_); + private List _PreBuildCmds = new .() ~ DeleteContainerAndItems!(_); + private List _PostBuildCmds = new .() ~ DeleteContainerAndItems!(_); + private List _CleanCmds = new .() ~ DeleteContainerAndItems!(_); + private List _EnviromentVars = new .() ~ DeleteContainerAndItems!(_); + private List _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> _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 _preprocessorMacros = new .() ~ DeleteContainerAndItems!(_); + [ResultWrapAndGenerate("TargetType")] public TargetType? TargetType = null; + private List _Aliases = new .() ~ DeleteContainerAndItems!(_); + private List _Dependencies = new .() {new .("corlib")}~ DeleteContainerAndItems!(_); + private List _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); + } +} \ No newline at end of file diff --git a/src/Workspace.bf b/src/Workspace.bf new file mode 100644 index 0000000..f66b2a4 --- /dev/null +++ b/src/Workspace.bf @@ -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 _ConfigSelections = new .(); + private List _PreprocessorMacros = new .() ~ DeleteContainerAndItems!(_); + private List _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> _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 _PreprocessorMacros = new .() ~ DeleteContainerAndItems!(_); + private List _DistinctBuildOptions = new .() ~ DeleteContainerAndItems!(_); + private List _ExtraPlatforms = new .() ~ DeleteContainerAndItems!(_); + private WSProject _StartupProject = null ~ delete _; + private List _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> 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 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 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 locked) + { + for(var i in _Projects) + if(i.Lockstate == .Locked) + locked.Add(i); + } + + private void GetUnlocked(List 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"); + \} + """); + } +} \ No newline at end of file