From bb90117dd5729a662ed68e83e3cdfa2b5c9856dd Mon Sep 17 00:00:00 2001 From: Rune Date: Sat, 21 Mar 2026 21:48:58 +0100 Subject: [PATCH 1/9] logic is executing --- BeefLibs/corlib/src/Compiler.bf | 21 ++++++-- IDE/src/BuildContext.bf | 16 +++++++ IDE/src/Compiler/BfCompiler.bf | 24 ++++++++++ IDE/src/IDEApp.bf | 56 ++++++++++++++++++++++ IDE/src/Project.bf | 4 ++ IDE/src/ui/ProjectProperties.bf | 1 + IDEHelper/Compiler/BfCompiler.cpp | 79 +++++++++++++++++++++++++++++-- IDEHelper/Compiler/BfCompiler.h | 6 ++- 8 files changed, 197 insertions(+), 10 deletions(-) diff --git a/BeefLibs/corlib/src/Compiler.bf b/BeefLibs/corlib/src/Compiler.bf index 230a4d8d9..8ee77fc66 100644 --- a/BeefLibs/corlib/src/Compiler.bf +++ b/BeefLibs/corlib/src/Compiler.bf @@ -258,6 +258,15 @@ namespace System public abstract class BuildLogic { + public String mCmdInfo = new .() ~ delete _; + + public void AddLibPath(StringView lib) + { + mCmdInfo.Append("addLibPath\t"); + lib.QuoteString(mCmdInfo); + mCmdInfo.Append('\n'); + } + public virtual void PreBuild() { } @@ -265,13 +274,17 @@ namespace System { } - static void PreBuild() where T : BuildLogic + static String PreBuild() where T : BuildLogic { - scope T().PreBuild(); + T val = scope T(); + val.PreBuild(); + return val.mCmdInfo; } - static void PostBuild() where T : BuildLogic + static String PostBuild() where T : BuildLogic { - scope T().PostBuild(); + T val = scope T(); + val.PostBuild(); + return val.mCmdInfo; } } diff --git a/IDE/src/BuildContext.bf b/IDE/src/BuildContext.bf index 24706b8d3..b54860854 100644 --- a/IDE/src/BuildContext.bf +++ b/IDE/src/BuildContext.bf @@ -173,6 +173,18 @@ namespace IDE return didCommands ? .HadCommands : .NoCommands; } + public void QueueBuildLogic(Project project, IDEApp.BuildLogicCmd.Stage stage) + { + if (project.mBeefGlobalOptions.mBuildLogicObject.IsEmpty) + return; + + gApp.mExecutionQueue.Add(new IDEApp.BuildLogicCmd() + { + mObject = new String(project.mBeefGlobalOptions.mBuildLogicObject), + mStage = stage, + }); + } + bool QueueProjectGNUArchive(Project project, String targetPath, Workspace.Options workspaceOptions, Project.Options options, String objectsArg) { #if BF_PLATFORM_WINDOWS @@ -1505,6 +1517,8 @@ namespace IDE case .Failed: completedCompileCmd.mFailed = true; } + + QueueBuildLogic(project, .PreBuild); } if (project.mGeneralOptions.mTargetType == .CustomBuild) @@ -1701,6 +1715,8 @@ namespace IDE if (targetPath == null) return false; + QueueBuildLogic(project, .PostBuild); + switch (QueueProjectCustomBuildCommands(project, targetPath, compileKind.WantsRunAfter ? options.mBuildOptions.mBuildCommandsOnRun : options.mBuildOptions.mBuildCommandsOnCompile, options.mBuildOptions.mPostBuildCmds)) { case .NoCommands: diff --git a/IDE/src/Compiler/BfCompiler.bf b/IDE/src/Compiler/BfCompiler.bf index 29b92133e..664677ee7 100644 --- a/IDE/src/Compiler/BfCompiler.bf +++ b/IDE/src/Compiler/BfCompiler.bf @@ -123,6 +123,15 @@ namespace IDE.Compiler [CallingConvention(.Stdcall), CLink] static extern char8* BfCompiler_GetGeneratorGenData(void* bfCompiler, char8* typeDefName, char8* args); + [CallingConvention(.Stdcall), CLink] + static extern bool BfCompiler_ValidateBuildLogic(void* bfCompiler, char8* typeDefName); + + [CallingConvention(.Stdcall), CLink] + static extern char8* BfCompiler_ExecuteBuildLogicPreBuild(void* bfCompiler, char8* typeDefName); + + [CallingConvention(.Stdcall), CLink] + static extern char8* BfCompiler_ExecuteBuildLogicPostBuild(void* bfCompiler, char8* typeDefName); + [CallingConvention(.Stdcall), CLink] static extern char8* BfCompiler_GetTypeDefList(void* bfCompiler, bool includeLocation); @@ -851,6 +860,21 @@ namespace IDE.Compiler outStr.Append(BfCompiler_GetGeneratorGenData(mNativeBfCompiler, typeDefName, args)); } + public bool ValidateBuildLogic(String typeDefName) + { + return BfCompiler_ValidateBuildLogic(mNativeBfCompiler, typeDefName); + } + + public void ExecuteBuildLogicPreBuild(String typeDefName, String outStr) + { + outStr.Append(BfCompiler_ExecuteBuildLogicPreBuild(mNativeBfCompiler, typeDefName)); + } + + public void ExecuteBuildLogicPostBuild(String typeDefName, String outStr) + { + outStr.Append(BfCompiler_ExecuteBuildLogicPostBuild(mNativeBfCompiler, typeDefName)); + } + public void GetTypeDefList(String outStr, bool includeLocation = false) { outStr.Append(BfCompiler_GetTypeDefList(mNativeBfCompiler, includeLocation)); diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 50784a9f2..c1fa61b8d 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -476,6 +476,14 @@ namespace IDE public String mPath ~ delete _; } + public class BuildLogicCmd : ExecutionCmd + { + public enum Stage { PreBuild, PostBuild } + + public String mObject ~ delete _; + public Stage mStage; + } + public enum ArgsFileKind { None, @@ -9861,6 +9869,54 @@ namespace IDE // Already handled (void)scriptCmd; } + else if (var buildLogicCmd = next as BuildLogicCmd) do + { + mBfBuildSystem.Lock(0); + defer mBfBuildSystem.Unlock(); + + Stopwatch stopwatch = scope .()..Start(); + + if (!mBfBuildCompiler.ValidateBuildLogic(buildLogicCmd.mObject)) + { + OutputErrorLine($"Invalid Compiler.BuildLogic object: {buildLogicCmd.mObject}"); + buildFailed = true; + break; + } + + String output = scope .(); + switch (buildLogicCmd.mStage) + { + case .PreBuild: mBfBuildCompiler.ExecuteBuildLogicPreBuild(buildLogicCmd.mObject, output); + case .PostBuild: mBfBuildCompiler.ExecuteBuildLogicPostBuild(buildLogicCmd.mObject, output); + } + + for (let line in output.Split('\n', .RemoveEmptyEntries)) + { + int index = line.IndexOf('\t'); + if (index < 0) + { + OutputErrorLine($"Malformed build logic execution result: {line}"); + buildFailed = true; + continue; + } + + switch (line[.. mPreprocessorMacros = new List() ~ DeleteContainerAndItems!(_); @@ -1657,6 +1659,7 @@ namespace IDE data.ConditionalAdd("Version", mGeneralOptions.mVersion.mVersion); data.ConditionalAdd("TargetType", mGeneralOptions.mTargetType, GetDefaultTargetType()); data.ConditionalAdd("StartupObject", mBeefGlobalOptions.mStartupObject, IsSingleFile ? "Program" : ""); + data.ConditionalAdd("BuildLogicObject", mBeefGlobalOptions.mBuildLogicObject); var defaultNamespace = scope String(); GetSanitizedName(mProjectName, defaultNamespace, true); data.ConditionalAdd("DefaultNamespace", mBeefGlobalOptions.mDefaultNamespace, defaultNamespace); @@ -2014,6 +2017,7 @@ namespace IDE data.GetString("Version", mGeneralOptions.mVersion.mVersion); ReadStrings("Aliases", mGeneralOptions.mAliases); data.GetString("StartupObject", mBeefGlobalOptions.mStartupObject, IsSingleFile ? "Program" : ""); + data.GetString("BuildLogicObject", mBeefGlobalOptions.mBuildLogicObject); var defaultNamespace = scope String(); GetSanitizedName(mProjectName, defaultNamespace, true); data.GetString("DefaultNamespace", mBeefGlobalOptions.mDefaultNamespace, defaultNamespace); diff --git a/IDE/src/ui/ProjectProperties.bf b/IDE/src/ui/ProjectProperties.bf index 091dbe157..376b769c7 100644 --- a/IDE/src/ui/ProjectProperties.bf +++ b/IDE/src/ui/ProjectProperties.bf @@ -985,6 +985,7 @@ namespace IDE.ui category.mTextColor = Color.Mult(DarkTheme.COLOR_TEXT, 0xFFE8E8E8); AddPropertiesItem(category, "Startup Object", "mStartupObject"); + AddPropertiesItem(category, "Build Logic Object", "mBuildLogicObject"); AddPropertiesItem(category, "Default Namespace", "mDefaultNamespace"); AddPropertiesItem(category, "Preprocessor Macros", "mPreprocessorMacros"); DistinctOptionBuilder dictinctOptionBuilder = scope .(this); diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 50a2b9144..66c7448bd 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -436,6 +436,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mPlatformTypeDef = NULL; mCompilerTypeDef = NULL; mCompilerGeneratorTypeDef = NULL; + mCompilerBuildLogicTypeDef = NULL; mDiagnosticsDebugTypeDef = NULL; mIDisposableTypeDef = NULL; mIIntegerTypeDef = NULL; @@ -7321,6 +7322,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mPlatformTypeDef = _GetRequiredType("System.Platform"); mCompilerTypeDef = _GetRequiredType("System.Compiler"); mCompilerGeneratorTypeDef = _GetRequiredType("System.Compiler.Generator"); + mCompilerBuildLogicTypeDef = _GetRequiredType("System.Compiler.BuildLogic"); mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug"); mIDisposableTypeDef = _GetRequiredType("System.IDisposable"); mIIntegerTypeDef = _GetRequiredType("System.IInteger"); @@ -9081,7 +9083,7 @@ String BfCompiler::GetTypeDefList(bool includeLocation) return result; } -String BfCompiler::GetGeneratorString(BfTypeDef* typeDef, BfTypeInstance* typeInst, const StringImpl& generatorMethodName, const StringImpl* args) +String BfCompiler::ExecuteUserDefinedMethod(BfTypeDef* typeDef, BfTypeInstance* typeInst, BfTypeDef* parentClass, const StringImpl& generatorMethodName, const StringImpl* args) { if (typeInst == NULL) { @@ -9095,7 +9097,7 @@ String BfCompiler::GetGeneratorString(BfTypeDef* typeDef, BfTypeInstance* typeIn BfTypeVector typeVector; typeVector.Add(typeInst); - auto generatorTypeInst = mContext->mUnreifiedModule->ResolveTypeDef(mCompilerGeneratorTypeDef)->ToTypeInstance(); + auto generatorTypeInst = mContext->mUnreifiedModule->ResolveTypeDef(parentClass)->ToTypeInstance(); auto methodDef = generatorTypeInst->mTypeDef->GetMethodByName(generatorMethodName); auto moduleMethodInstance = mContext->mUnreifiedModule->GetMethodInstance(generatorTypeInst, methodDef, typeVector); @@ -9165,7 +9167,7 @@ String BfCompiler::GetGeneratorTypeDefList() result += typeDef->mProject->mName; result += ":"; result += BfTypeUtils::TypeToString(typeDef, BfTypeNameFlag_InternalName); - String nameString = GetGeneratorString(typeDef, typeInst, "GetName", NULL); + String nameString = ExecuteUserDefinedMethod(typeDef, typeInst, mCompilerGeneratorTypeDef, "GetName", NULL); if (!nameString.IsEmpty()) result += "\t" + nameString; result += "\n"; @@ -9191,7 +9193,7 @@ String BfCompiler::GetGeneratorInitData(const StringImpl& typeName, const String String result; for (auto typeDef : typeDefs) { - result += GetGeneratorString(typeDef, NULL, "InitUI", &args); + result += ExecuteUserDefinedMethod(typeDef, NULL, mCompilerGeneratorTypeDef, "InitUI", &args); if (!result.IsEmpty()) break; } @@ -9214,7 +9216,7 @@ String BfCompiler::GetGeneratorGenData(const StringImpl& typeName, const StringI String result; for (auto typeDef : typeDefs) { - result += GetGeneratorString(typeDef, NULL, "Generate", &args); + result += ExecuteUserDefinedMethod(typeDef, NULL, mCompilerGeneratorTypeDef, "Generate", &args); if (!result.IsEmpty()) break; } @@ -9224,6 +9226,49 @@ String BfCompiler::GetGeneratorGenData(const StringImpl& typeName, const StringI return result; } +bool BfCompiler::ValidateBuildLogic(const StringImpl& typeName) +{ + BfType* type = GetType(typeName); + + BfTypeInstance* typeInst = NULL; + if (type != NULL) + typeInst = type->ToTypeInstance(); + + return ((typeInst != NULL) && + (typeInst->mBaseType != NULL) && + (typeInst->mBaseType->IsInstanceOf(mCompilerBuildLogicTypeDef))); +} + +String BfCompiler::ExecuteBuildLogicPreBuild(const StringImpl& typeName) +{ + BfResolvePassData resolvePassData; + SetAndRestoreValue prevResolvePassData(mResolvePassData, &resolvePassData); + BfPassInstance passInstance(mSystem); + SetAndRestoreValue prevPassInstance(mPassInstance, &passInstance); + + BfTypeInstance* typeInst = GetType(typeName)->ToTypeInstance(); + + String result = ExecuteUserDefinedMethod(typeInst->mTypeDef, typeInst, mCompilerBuildLogicTypeDef, "PreBuild", NULL); + + HandleGeneratorErrors(result); + return result; +} + +String BfCompiler::ExecuteBuildLogicPostBuild(const StringImpl& typeName) +{ + BfResolvePassData resolvePassData; + SetAndRestoreValue prevResolvePassData(mResolvePassData, &resolvePassData); + BfPassInstance passInstance(mSystem); + SetAndRestoreValue prevPassInstance(mPassInstance, &passInstance); + + BfTypeInstance* typeInst = GetType(typeName)->ToTypeInstance(); + + String result = ExecuteUserDefinedMethod(typeInst->mTypeDef, typeInst, mCompilerBuildLogicTypeDef, "PostBuild", NULL); + + HandleGeneratorErrors(result); + return result; +} + String BfCompiler::GetTypeDefMatches(const StringImpl& searchStr, bool includeLocation) { String result; @@ -10682,6 +10727,30 @@ BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetGeneratorGenData(BfCompiler* bfC return outString.c_str(); } +BF_EXPORT bool BF_CALLTYPE BfCompiler_ValidateBuildLogic(BfCompiler* bfCompiler, char* typeDefName) +{ + String name(typeDefName); + return bfCompiler->ValidateBuildLogic(name); +} + +BF_EXPORT const char* BF_CALLTYPE BfCompiler_ExecuteBuildLogicPreBuild(BfCompiler* bfCompiler, char* typeDefName) +{ + String name(typeDefName); + String& outString = *gTLStrReturn.Get(); + outString.clear(); + outString = bfCompiler->ExecuteBuildLogicPreBuild(name); + return outString.c_str(); +} + +BF_EXPORT const char* BF_CALLTYPE BfCompiler_ExecuteBuildLogicPostBuild(BfCompiler* bfCompiler, char* typeDefName) +{ + String name(typeDefName); + String& outString = *gTLStrReturn.Get(); + outString.clear(); + outString = bfCompiler->ExecuteBuildLogicPostBuild(name); + return outString.c_str(); +} + BF_EXPORT const char* BF_CALLTYPE BfCompiler_GetTypeDefList(BfCompiler* bfCompiler, bool includeLocation) { String& outString = *gTLStrReturn.Get(); diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index fc39436ce..09e606b01 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -393,6 +393,7 @@ class BfCompiler BfTypeDef* mPlatformTypeDef; BfTypeDef* mCompilerTypeDef; BfTypeDef* mCompilerGeneratorTypeDef; + BfTypeDef* mCompilerBuildLogicTypeDef; BfTypeDef* mDiagnosticsDebugTypeDef; BfTypeDef* mIDisposableTypeDef; BfTypeDef* mIIntegerTypeDef; @@ -550,11 +551,14 @@ class BfCompiler void RequestFastFinish(); void RequestExtraCompile(); String GetTypeDefList(bool includeLocation); - String GetGeneratorString(BfTypeDef* typeDef, BfTypeInstance* typeInst, const StringImpl& generatorMethodName, const StringImpl* args); + String ExecuteUserDefinedMethod(BfTypeDef* typeDef, BfTypeInstance* typeInst, BfTypeDef* parentClass, const StringImpl& generatorMethodName, const StringImpl* args); void HandleGeneratorErrors(StringImpl& result); String GetGeneratorTypeDefList(); String GetGeneratorInitData(const StringImpl& typeName, const StringImpl& args); String GetGeneratorGenData(const StringImpl& typeName, const StringImpl& args); + bool ValidateBuildLogic(const StringImpl& typeName); + String ExecuteBuildLogicPreBuild(const StringImpl& typeName); + String ExecuteBuildLogicPostBuild(const StringImpl& typeName); String GetTypeDefMatches(const StringImpl& searchSrc, bool includeLocation); void GetTypeDefs(const StringImpl& typeName, Array& typeDefs); String GetTypeDefInfo(const StringImpl& typeName); From 50cff8c3367bde3929c4562af367520321f2debe Mon Sep 17 00:00:00 2001 From: Rune Date: Sun, 22 Mar 2026 15:08:46 +0100 Subject: [PATCH 2/9] debugging support --- IDE/src/IDEApp.bf | 80 +++++++++++++++++++++++---------- IDEHelper/Compiler/BfModule.cpp | 2 +- 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index 4573f4584..8ce1525f0 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -476,7 +476,7 @@ namespace IDE public String mPath ~ delete _; } - public class BuildLogicCmd : ExecutionCmd + public class StartCustomBuildLogicCmd : ExecutionCmd { public enum Stage { PreBuild, PostBuild } @@ -484,6 +484,16 @@ namespace IDE public Stage mStage; } + public class ProcessCustomBuildLogicCmd : ExecutionCmd + { + public String mTypeName ~ delete _; + public StartCustomBuildLogicCmd.Stage mStage; + + public String mOutput ~ delete _; + public Thread mThread ~ delete _; + public Stopwatch mStopwatch ~ delete _; + } + public enum ArgsFileKind { None, @@ -9628,6 +9638,12 @@ namespace IDE } } + if (var processBuildLogicCmd = next as ProcessCustomBuildLogicCmd) + { + if (processBuildLogicCmd.mThread.IsAlive) + return; + } + #if BF_PLATFORM_WINDOWS if (let startDebugCmd = next as StartDebugCmd) { @@ -9876,34 +9892,49 @@ namespace IDE // Already handled (void)scriptCmd; } - else if (var buildLogicCmd = next as BuildLogicCmd) do + else if (var cmd = next as StartCustomBuildLogicCmd) do { - mBfBuildSystem.Lock(0); - defer mBfBuildSystem.Unlock(); - - Stopwatch stopwatch = scope .()..Start(); - - if (!mBfBuildCompiler.ValidateBuildLogic(buildLogicCmd.mObject)) + if (!mBfBuildCompiler.ValidateBuildLogic(cmd.mObject)) { - OutputErrorLine($"Invalid Compiler.BuildLogic object: {buildLogicCmd.mObject}"); - buildFailed = true; + OutputErrorLine($"Invalid Compiler.BuildLogic: {cmd.mObject}"); + ClearAndDeleteItems(mExecutionQueue); break; } - String output = scope .(); - switch (buildLogicCmd.mStage) - { - case .PreBuild: mBfBuildCompiler.ExecuteBuildLogicPreBuild(buildLogicCmd.mObject, output); - case .PostBuild: mBfBuildCompiler.ExecuteBuildLogicPostBuild(buildLogicCmd.mObject, output); - } + ProcessCustomBuildLogicCmd process = new .(); + process.mOutput = new .(); + process.mTypeName = new .(cmd.mObject); + process.mStage = cmd.mStage; + process.mStopwatch = new .(); - for (let line in output.Split('\n', .RemoveEmptyEntries)) + process.mThread = new .(new () => + { + mBfBuildSystem.Lock(0); + switch (process.mStage) + { + case .PreBuild: mBfBuildCompiler.ExecuteBuildLogicPreBuild(process.mTypeName, process.mOutput); + case .PostBuild: mBfBuildCompiler.ExecuteBuildLogicPostBuild(process.mTypeName, process.mOutput); + } + mBfBuildSystem.Unlock(); + }); + process.mThread.AutoDelete = false; + process.mThread.SetJoinOnDelete(true); + + process.mStopwatch.Start(); + process.mThread.Start(); + mExecutionQueue.AddFront(process); + } + else if (var cmd = next as ProcessCustomBuildLogicCmd) + { + // thread has ended + bool failed = false; + for (let line in cmd.mOutput.Split('\n', .RemoveEmptyEntries)) { int index = line.IndexOf('\t'); if (index < 0) { OutputErrorLine($"Malformed build logic execution result: {line}"); - buildFailed = true; + CancelBuild(); continue; } @@ -9914,15 +9945,18 @@ namespace IDE //line[(index+1)...].UnQuoteString(path); //mDynamicallyAddedLibPaths.Add(path); case "!error": - OutputLine($"{line[(index+1)...]}"); - buildFailed = true; + OutputLineSmart($"{line[(index+1)...]}"); + failed = true; default: OutputErrorLine($"Invalid build logic execution command: {_}"); - buildFailed = true; + failed = true; } - - OutputLineSmart($"Build logic '{buildLogicCmd.mObject}.{buildLogicCmd.mStage}' finished in {stopwatch.ElapsedMilliseconds / 1000.0f:0.00}s"); } + + if (failed) + ClearAndDeleteItems(mExecutionQueue); + else + OutputLine($"{cmd.mTypeName}.{cmd.mStage} finished in {cmd.mStopwatch.ElapsedMilliseconds / 1000.0f:0.00}s"); } else if (var writeEmitCmd = next as WriteEmitCmd) { diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 4acbb6deb..6753f5d74 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -15703,7 +15703,7 @@ void BfModule::HadSlotCountDependency() BfTypedValue BfModule::GetCompilerFieldValue(const StringImpl& str) { BfProject* project = mProject; - if ((project == NULL) && (mCurMethodState != NULL)) + if ((project == NULL) && (mCurMethodState != NULL) && (mCurMethodState->mMethodInstance != NULL)) project = mCurMethodState->mMethodInstance->mMethodDef->mDeclaringType->mProject; if (str == "#IsComptime") From 3444edfc0b7cc8217ef9b74f7a03049d63ea9466 Mon Sep 17 00:00:00 2001 From: Rune Date: Sun, 22 Mar 2026 15:13:22 +0100 Subject: [PATCH 3/9] update naming --- IDE/src/BuildContext.bf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/IDE/src/BuildContext.bf b/IDE/src/BuildContext.bf index 655c548ac..a5f3905b7 100644 --- a/IDE/src/BuildContext.bf +++ b/IDE/src/BuildContext.bf @@ -185,12 +185,12 @@ namespace IDE return didCommands ? .HadCommands : .NoCommands; } - public void QueueBuildLogic(Project project, IDEApp.BuildLogicCmd.Stage stage) + public void QueueBuildLogic(Project project, IDEApp.StartCustomBuildLogicCmd.Stage stage) { if (project.mBeefGlobalOptions.mBuildLogicObject.IsEmpty) return; - gApp.mExecutionQueue.Add(new IDEApp.BuildLogicCmd() + gApp.mExecutionQueue.Add(new IDEApp.StartCustomBuildLogicCmd() { mObject = new String(project.mBeefGlobalOptions.mBuildLogicObject), mStage = stage, From 875ea7404446fd2e741ceec4c93816f0977a9437 Mon Sep 17 00:00:00 2001 From: Rune Date: Sun, 22 Mar 2026 20:21:28 +0100 Subject: [PATCH 4/9] comptime output --- BeefBoot/BootApp.cpp | 9 +++++++++ BeefLibs/corlib/src/Compiler.bf | 17 +++++++++++++++++ IDE/src/Compiler/BfCompiler.bf | 16 ++++++++++++++++ IDEHelper/Compiler/BfCompiler.cpp | 6 ++++++ IDEHelper/Compiler/CeMachine.cpp | 21 +++++++++++++++++++++ IDEHelper/Compiler/CeMachine.h | 5 +++++ 6 files changed, 74 insertions(+) diff --git a/BeefBoot/BootApp.cpp b/BeefBoot/BootApp.cpp index c2f33536a..d45e2f1ac 100644 --- a/BeefBoot/BootApp.cpp +++ b/BeefBoot/BootApp.cpp @@ -28,6 +28,8 @@ BF_IMPORT void BF_CALLTYPE BfCompiler_Delete(void* bfCompiler); BF_EXPORT void BF_CALLTYPE BfCompiler_SetOptions(void* bfCompiler, void* hotProject, int hotIdx, const char* targetTriple, const char* targetCPU, int toolsetType, int simdSetting, int allocStackCount, int maxWorkerThreads, Beefy::BfCompilerOptionFlags optionFlags, const char* mallocLinkName, const char* freeLinkName); +BF_EXPORT void BF_CALLTYPE BfCompiler_SetComptimeWriteToOutputCallback(void* bfCompiler, void* userdata, + void (BF_CALLTYPE* callback)(void* userdata, char* ptr, int len)); BF_IMPORT void BF_CALLTYPE BfCompiler_ClearBuildCache(void* bfCompiler); BF_IMPORT bool BF_CALLTYPE BfCompiler_Compile(void* bfCompiler, void* bfPassInstance, const char* outputPath); BF_IMPORT float BF_CALLTYPE BfCompiler_GetCompletionPercentage(void* bfCompiler); @@ -790,6 +792,12 @@ void BootApp::DoLinkGNU() auto runCmd = QueueRun(linkerPath, linkLine, mWorkingDir, BfpSpawnFlag_UseArgsFile); } +static void BF_CALLTYPE ComptimeWriteToOutputCallback(void* userdata, char* ptr, int len) +{ + String text(ptr, len); + gApp->OutputLine(text, OutputPri_Normal); +} + bool BootApp::Compile() { DWORD startTick = BFTickCount(); @@ -813,6 +821,7 @@ bool BootApp::Compile() BfProjectFlags flags = BfProjectFlags_None; BfProject_SetOptions(mCELibProject, BfTargetType_BeefLib, "", mDefines.c_str(), mOptLevel, 0, 0, 0, flags); + BfCompiler_SetComptimeWriteToOutputCallback(mCompiler, NULL, ComptimeWriteToOutputCallback); } if (!mDefines.IsEmpty()) diff --git a/BeefLibs/corlib/src/Compiler.bf b/BeefLibs/corlib/src/Compiler.bf index 8ee77fc66..c04a9fc2d 100644 --- a/BeefLibs/corlib/src/Compiler.bf +++ b/BeefLibs/corlib/src/Compiler.bf @@ -267,9 +267,12 @@ namespace System mCmdInfo.Append('\n'); } + [Comptime] public virtual void PreBuild() { } + + [Comptime] public virtual void PostBuild() { } @@ -447,6 +450,7 @@ namespace System static extern void Comptime_EmitMethodExit(int64 methodHandle, StringView text); static extern void Comptime_EmitMixin(StringView text); static extern String Comptime_GetStringById(int32 id); + static extern void Comptime_WriteToOutput(StringView text); [Comptime(OnlyFromComptime=true)] public static MethodBuilder CreateMethod(Type owner, StringView methodName, Type returnType, MethodFlags methodFlags) @@ -492,6 +496,19 @@ namespace System Comptime_EmitMethodExit(methodHandle.[Friend]mData.mComptimeMethodInstance, text); } + [Comptime(OnlyFromComptime=true)] + public static void Write(StringView text) + { + Comptime_WriteToOutput(text); + } + + [Comptime(OnlyFromComptime=true)] + public static void WriteLine(StringView text) + { + Comptime_WriteToOutput(text); + Comptime_WriteToOutput("\n"); + } + [Comptime(ConstEval=true)] public static void Mixin(StringView text) { diff --git a/IDE/src/Compiler/BfCompiler.bf b/IDE/src/Compiler/BfCompiler.bf index 664677ee7..731cab4df 100644 --- a/IDE/src/Compiler/BfCompiler.bf +++ b/IDE/src/Compiler/BfCompiler.bf @@ -155,6 +155,11 @@ namespace IDE.Compiler void* hotProject, int32 hotIdx, char8* targetTriple, char8* targetCPU, int32 toolsetType, int32 simdSetting, int32 allocStackCount, int32 maxWorkerThreads, OptionFlags optionsFlags, char8* mallocName, char8* freeName); + [CallingConvention(.Stdcall)] + public function void ComptimeWriteToOutputCallback(void* userdata, char8* ptr, int32 len); + [CallingConvention(.Stdcall), CLink] + static extern void BfCompiler_SetComptimeWriteToOutputCallback(void* bfCompiler, void* userdata, ComptimeWriteToOutputCallback callback); + [CallingConvention(.Stdcall), CLink] static extern void BfCompiler_ForceRebuild(void* bfCompiler); @@ -352,6 +357,11 @@ namespace IDE.Compiler targetTriple, targetCPU, toolsetType, simdSetting, allocStackCount, maxWorkerThreads, optionFlags, mallocFuncName, freeFuncName); } + public void SetComptimeWriteToOutputCallback(void* userdata, ComptimeWriteToOutputCallback callback) + { + BfCompiler_SetComptimeWriteToOutputCallback(mNativeBfCompiler, userdata, callback); + } + public void ForceRebuild() { BfCompiler_ForceRebuild(mNativeBfCompiler); @@ -792,6 +802,12 @@ namespace IDE.Compiler mBfSystem.AddTypeOptions(typeOption); for (let typeOption in options.mDistinctBuildOptions) mBfSystem.AddTypeOptions(typeOption); + + SetComptimeWriteToOutputCallback(Internal.UnsafeCastToPtr(IDEApp.sApp), (userdata, ptr, len) => + { + IDEApp app = (.)Internal.UnsafeCastToObject(userdata); + app.Output(scope String(ptr, len)); + }); } } diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 66c7448bd..8caa504dd 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -11333,6 +11333,12 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_SetOptions(BfCompiler* bfCompiler, BfProje } } +BF_EXPORT void BF_CALLTYPE BfCompiler_SetComptimeWriteToOutputCallback(BfCompiler* bfCompiler, void* userdata, CeWriteToOutputCallback callback) +{ + bfCompiler->mCeMachine->mWriteToOutputUserData = userdata; + bfCompiler->mCeMachine->mWriteToOutputCallback = callback; +} + BF_EXPORT void BF_CALLTYPE BfCompiler_ForceRebuild(BfCompiler* bfCompiler) { bfCompiler->mOptions.mForceRebuildIdx++; diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index f22064fb5..e72d9db06 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -7049,6 +7049,21 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* CeSetAddrVal(stackPtr + 0, GetString(string), ptrSize); _FixVariables(); } + else if (checkFunction->mFunctionKind == CeFunctionKind_WriteToOutput) + { + if (mCeMachine->mWriteToOutputCallback != NULL) + { + addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr); + String text; + if (!GetStringFromStringView(strViewPtr, text)) + { + _Fail("Invalid StringView"); + return false; + } + + mCeMachine->mWriteToOutputCallback(mCeMachine->mWriteToOutputUserData, text.GetPtr(), text.GetLength()); + } + } else if (checkFunction->mFunctionKind == CeFunctionKind_Sleep) { int32 sleepMS = *(int32*)((uint8*)stackPtr); @@ -9639,6 +9654,8 @@ CeMachine::CeMachine(BfCompiler* compiler) mRevisionExecuteTime = 0; mCurBuilder = NULL; mPreparingFunction = NULL; + mWriteToOutputUserData = NULL; + mWriteToOutputCallback = NULL; mCurEmitContext = NULL; @@ -10335,6 +10352,10 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction) { ceFunction->mFunctionKind = CeFunctionKind_GetStringById; } + else if (methodDef->mName == "Comptime_WriteToOutput") + { + ceFunction->mFunctionKind = CeFunctionKind_WriteToOutput; + } } else if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef)) { diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index 7445989ab..232f0ad16 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -469,6 +469,7 @@ enum CeFunctionKind CeFunctionKind_EmitMethodExit, CeFunctionKind_EmitMixin, CeFunctionKind_GetStringById, + CeFunctionKind_WriteToOutput, CeFunctionKind_BfpDirectory_Create, CeFunctionKind_BfpDirectory_Rename, @@ -1239,6 +1240,8 @@ class CeStepState } }; +typedef void (BF_CALLTYPE* CeWriteToOutputCallback)(void* userdata, const char* ptr, int len); + class CeMachine { public: @@ -1266,6 +1269,8 @@ class CeMachine CeCallSource* mCurCallSource; CeBuilder* mCurBuilder; CeFunction* mPreparingFunction; + void* mWriteToOutputUserData; + CeWriteToOutputCallback mWriteToOutputCallback; BfParser* mTempParser; BfReducer* mTempReducer; From 2807d8cc0b377cc02d990c76833ce68071bafa3b Mon Sep 17 00:00:00 2001 From: Rune Date: Mon, 23 Mar 2026 15:12:42 +0100 Subject: [PATCH 5/9] comptime console output --- BeefLibs/corlib/src/Compiler.bf | 14 ------------- BeefLibs/corlib/src/Console.bf | 1 + IDEHelper/Compiler/BfCompiler.cpp | 2 ++ IDEHelper/Compiler/BfCompiler.h | 1 + IDEHelper/Compiler/CeMachine.cpp | 34 +++++++++++++++---------------- IDEHelper/Compiler/CeMachine.h | 2 +- 6 files changed, 22 insertions(+), 32 deletions(-) diff --git a/BeefLibs/corlib/src/Compiler.bf b/BeefLibs/corlib/src/Compiler.bf index c04a9fc2d..72b459e45 100644 --- a/BeefLibs/corlib/src/Compiler.bf +++ b/BeefLibs/corlib/src/Compiler.bf @@ -450,7 +450,6 @@ namespace System static extern void Comptime_EmitMethodExit(int64 methodHandle, StringView text); static extern void Comptime_EmitMixin(StringView text); static extern String Comptime_GetStringById(int32 id); - static extern void Comptime_WriteToOutput(StringView text); [Comptime(OnlyFromComptime=true)] public static MethodBuilder CreateMethod(Type owner, StringView methodName, Type returnType, MethodFlags methodFlags) @@ -496,19 +495,6 @@ namespace System Comptime_EmitMethodExit(methodHandle.[Friend]mData.mComptimeMethodInstance, text); } - [Comptime(OnlyFromComptime=true)] - public static void Write(StringView text) - { - Comptime_WriteToOutput(text); - } - - [Comptime(OnlyFromComptime=true)] - public static void WriteLine(StringView text) - { - Comptime_WriteToOutput(text); - Comptime_WriteToOutput("\n"); - } - [Comptime(ConstEval=true)] public static void Mixin(StringView text) { diff --git a/BeefLibs/corlib/src/Console.bf b/BeefLibs/corlib/src/Console.bf index d00c379c1..5c1872eeb 100644 --- a/BeefLibs/corlib/src/Console.bf +++ b/BeefLibs/corlib/src/Console.bf @@ -185,6 +185,7 @@ namespace System public static this() { + if (Compiler.IsComptime) return; let handle = GetStdHandle(STD_OUTPUT_HANDLE); CONSOLE_SCREEN_BUFFER_INFO consoleInfo = .(); if (GetConsoleScreenBufferInfo(handle, out consoleInfo) != 0) diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 8caa504dd..3405a86d6 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -437,6 +437,7 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mCompilerTypeDef = NULL; mCompilerGeneratorTypeDef = NULL; mCompilerBuildLogicTypeDef = NULL; + mConsoleTypeDef = NULL; mDiagnosticsDebugTypeDef = NULL; mIDisposableTypeDef = NULL; mIIntegerTypeDef = NULL; @@ -7323,6 +7324,7 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mCompilerTypeDef = _GetRequiredType("System.Compiler"); mCompilerGeneratorTypeDef = _GetRequiredType("System.Compiler.Generator"); mCompilerBuildLogicTypeDef = _GetRequiredType("System.Compiler.BuildLogic"); + mConsoleTypeDef = _GetRequiredType("System.Console"); mDiagnosticsDebugTypeDef = _GetRequiredType("System.Diagnostics.Debug"); mIDisposableTypeDef = _GetRequiredType("System.IDisposable"); mIIntegerTypeDef = _GetRequiredType("System.IInteger"); diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index 09e606b01..f18c58ce0 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -394,6 +394,7 @@ class BfCompiler BfTypeDef* mCompilerTypeDef; BfTypeDef* mCompilerGeneratorTypeDef; BfTypeDef* mCompilerBuildLogicTypeDef; + BfTypeDef* mConsoleTypeDef; BfTypeDef* mDiagnosticsDebugTypeDef; BfTypeDef* mIDisposableTypeDef; BfTypeDef* mIIntegerTypeDef; diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index e72d9db06..e0377f990 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -6159,6 +6159,18 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* _Fail("Dynamic cast check failed"); return false; } + else if (checkFunction->mFunctionKind == CeFunctionKind_Console_PutChars) + { + if (mCeMachine->mWriteToOutputCallback != NULL) + { + int32 ptrVal = *(int32*)((uint8*)stackPtr + 0); + int32 size = *(int32*)(stackPtr + ceModule->mSystem->mPtrSize); + CE_CHECKADDR(ptrVal, size); + char* strPtr = (char*)(ptrVal + memStart); + + mCeMachine->mWriteToOutputCallback(mCeMachine->mWriteToOutputUserData, strPtr, size); + } + } else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite) { int32 ptrVal = *(int32*)((uint8*)stackPtr + 0); @@ -7049,21 +7061,6 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* CeSetAddrVal(stackPtr + 0, GetString(string), ptrSize); _FixVariables(); } - else if (checkFunction->mFunctionKind == CeFunctionKind_WriteToOutput) - { - if (mCeMachine->mWriteToOutputCallback != NULL) - { - addr_ce strViewPtr = *(addr_ce*)((uint8*)stackPtr); - String text; - if (!GetStringFromStringView(strViewPtr, text)) - { - _Fail("Invalid StringView"); - return false; - } - - mCeMachine->mWriteToOutputCallback(mCeMachine->mWriteToOutputUserData, text.GetPtr(), text.GetLength()); - } - } else if (checkFunction->mFunctionKind == CeFunctionKind_Sleep) { int32 sleepMS = *(int32*)((uint8*)stackPtr); @@ -10352,9 +10349,12 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction) { ceFunction->mFunctionKind = CeFunctionKind_GetStringById; } - else if (methodDef->mName == "Comptime_WriteToOutput") + } + else if (owner->IsInstanceOf(mCeModule->mCompiler->mConsoleTypeDef)) + { + if (methodDef->mName == "PutChars") { - ceFunction->mFunctionKind = CeFunctionKind_WriteToOutput; + ceFunction->mFunctionKind = CeFunctionKind_Console_PutChars; } } else if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef)) diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index 232f0ad16..b54ff0dac 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -428,6 +428,7 @@ enum CeFunctionKind CeFunctionKind_Free, CeFunctionKind_DynCheckFailed, CeFunctionKind_FatalError, + CeFunctionKind_Console_PutChars, CeFunctionKind_DebugWrite, CeFunctionKind_DebugWrite_Int, CeFunctionKind_GetReflectTypeDeclById, @@ -469,7 +470,6 @@ enum CeFunctionKind CeFunctionKind_EmitMethodExit, CeFunctionKind_EmitMixin, CeFunctionKind_GetStringById, - CeFunctionKind_WriteToOutput, CeFunctionKind_BfpDirectory_Create, CeFunctionKind_BfpDirectory_Rename, From d03cc39346d7e09ecc87c375884359831a51577f Mon Sep 17 00:00:00 2001 From: Rune Date: Mon, 23 Mar 2026 17:03:03 +0100 Subject: [PATCH 6/9] shell commands from comptime --- BeefLibs/corlib/src/Compiler.bf | 3 --- BeefLibs/corlib/src/Console.bf | 3 +++ IDE/src/Compiler/BfCompiler.bf | 16 ++++++++++++++++ IDEHelper/Compiler/BfCompiler.cpp | 6 ++++++ IDEHelper/Compiler/CeMachine.cpp | 27 +++++++++++++++++++++++++++ IDEHelper/Compiler/CeMachine.h | 5 +++++ 6 files changed, 57 insertions(+), 3 deletions(-) diff --git a/BeefLibs/corlib/src/Compiler.bf b/BeefLibs/corlib/src/Compiler.bf index 72b459e45..8ee77fc66 100644 --- a/BeefLibs/corlib/src/Compiler.bf +++ b/BeefLibs/corlib/src/Compiler.bf @@ -267,12 +267,9 @@ namespace System mCmdInfo.Append('\n'); } - [Comptime] public virtual void PreBuild() { } - - [Comptime] public virtual void PostBuild() { } diff --git a/BeefLibs/corlib/src/Console.bf b/BeefLibs/corlib/src/Console.bf index 5c1872eeb..f9a7e71b6 100644 --- a/BeefLibs/corlib/src/Console.bf +++ b/BeefLibs/corlib/src/Console.bf @@ -468,5 +468,8 @@ namespace System Write("\x1B[H\x1B[J"); #endif } + + [LinkName("system")] + public static extern int32 RunShellCommand(char8* command); } } diff --git a/IDE/src/Compiler/BfCompiler.bf b/IDE/src/Compiler/BfCompiler.bf index 731cab4df..7e16e22e2 100644 --- a/IDE/src/Compiler/BfCompiler.bf +++ b/IDE/src/Compiler/BfCompiler.bf @@ -160,6 +160,11 @@ namespace IDE.Compiler [CallingConvention(.Stdcall), CLink] static extern void BfCompiler_SetComptimeWriteToOutputCallback(void* bfCompiler, void* userdata, ComptimeWriteToOutputCallback callback); + [CallingConvention(.Stdcall)] + public function Platform.BfpSpawn* ComptimeRunShellCommandCallback(void* userdata, char8* cmd, int32* outExitCode); + [CallingConvention(.Stdcall), CLink] + static extern void BfCompiler_SetComptimeRunShellCommandCallback(void* bfCompiler, void* userdata, ComptimeRunShellCommandCallback callback); + [CallingConvention(.Stdcall), CLink] static extern void BfCompiler_ForceRebuild(void* bfCompiler); @@ -362,6 +367,11 @@ namespace IDE.Compiler BfCompiler_SetComptimeWriteToOutputCallback(mNativeBfCompiler, userdata, callback); } + public void SetComptimeRunShellCommandCallback(void* userdata, ComptimeRunShellCommandCallback callback) + { + BfCompiler_SetComptimeRunShellCommandCallback(mNativeBfCompiler, userdata, callback); + } + public void ForceRebuild() { BfCompiler_ForceRebuild(mNativeBfCompiler); @@ -808,6 +818,12 @@ namespace IDE.Compiler IDEApp app = (.)Internal.UnsafeCastToObject(userdata); app.Output(scope String(ptr, len)); }); + SetComptimeRunShellCommandCallback(Internal.UnsafeCastToPtr(IDEApp.sApp), (userdata, cmd, outExitCode) => + { + IDEApp app = (.)Internal.UnsafeCastToObject(userdata); + let inst = app.DoRun("", StringView(cmd), app.mWorkspace.mDir, .None, null, null, .ShellCommand); + return inst.mProcess.[Friend]mSpawn; + }); } } diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 3405a86d6..6415f4003 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -11341,6 +11341,12 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_SetComptimeWriteToOutputCallback(BfCompile bfCompiler->mCeMachine->mWriteToOutputCallback = callback; } +BF_EXPORT void BF_CALLTYPE BfCompiler_SetComptimeRunShellCommandCallback(BfCompiler* bfCompiler, void* userdata, CeRunShellCommandCallback callback) +{ + bfCompiler->mCeMachine->mRunShellCommandUserData = userdata; + bfCompiler->mCeMachine->mRunShellCommandCallback = callback; +} + BF_EXPORT void BF_CALLTYPE BfCompiler_ForceRebuild(BfCompiler* bfCompiler) { bfCompiler->mOptions.mForceRebuildIdx++; diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index e0377f990..340aef3fd 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -6171,6 +6171,26 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* mCeMachine->mWriteToOutputCallback(mCeMachine->mWriteToOutputUserData, strPtr, size); } } + else if (checkFunction->mFunctionKind == CeFunctionKind_Console_RunShellCommand) + { + if (mCeMachine->mRunShellCommandCallback == NULL) + { + _Fail("Console.RunShellCommand is only avaliable when building"); + } + else + { + int32 ptrVal = *(int32*)(stackPtr + 4); + char* strPtr = (char*)(ptrVal + memStart); + + int32 exitCode; + auto waitEvent = mCeMachine->mRunShellCommandCallback(mCeMachine->mRunShellCommandUserData, strPtr, &exitCode); + + if (waitEvent != NULL) + BfpSpawn_WaitFor(waitEvent, -1, &exitCode, NULL); + + *((int32*)stackPtr) = exitCode; + } + } else if (checkFunction->mFunctionKind == CeFunctionKind_DebugWrite) { int32 ptrVal = *(int32*)((uint8*)stackPtr + 0); @@ -9651,8 +9671,11 @@ CeMachine::CeMachine(BfCompiler* compiler) mRevisionExecuteTime = 0; mCurBuilder = NULL; mPreparingFunction = NULL; + mWriteToOutputUserData = NULL; mWriteToOutputCallback = NULL; + mRunShellCommandUserData = NULL; + mRunShellCommandCallback = NULL; mCurEmitContext = NULL; @@ -10356,6 +10379,10 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction) { ceFunction->mFunctionKind = CeFunctionKind_Console_PutChars; } + else if (methodDef->mName == "RunShellCommand") + { + ceFunction->mFunctionKind = CeFunctionKind_Console_RunShellCommand; + } } else if (owner->IsInstanceOf(mCeModule->mCompiler->mDiagnosticsDebugTypeDef)) { diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index b54ff0dac..ba18a2ec4 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -429,6 +429,7 @@ enum CeFunctionKind CeFunctionKind_DynCheckFailed, CeFunctionKind_FatalError, CeFunctionKind_Console_PutChars, + CeFunctionKind_Console_RunShellCommand, CeFunctionKind_DebugWrite, CeFunctionKind_DebugWrite_Int, CeFunctionKind_GetReflectTypeDeclById, @@ -1241,6 +1242,7 @@ class CeStepState }; typedef void (BF_CALLTYPE* CeWriteToOutputCallback)(void* userdata, const char* ptr, int len); +typedef BfpSpawn* (BF_CALLTYPE* CeRunShellCommandCallback)(void* userdata, const char* cmd, int* outExitcode); class CeMachine { @@ -1269,8 +1271,11 @@ class CeMachine CeCallSource* mCurCallSource; CeBuilder* mCurBuilder; CeFunction* mPreparingFunction; + void* mWriteToOutputUserData; CeWriteToOutputCallback mWriteToOutputCallback; + void* mRunShellCommandUserData; + CeRunShellCommandCallback mRunShellCommandCallback; BfParser* mTempParser; BfReducer* mTempReducer; From 7415a8fae549f457f4528b038b4623f105f070d7 Mon Sep 17 00:00:00 2001 From: Rune Date: Mon, 23 Mar 2026 17:45:15 +0100 Subject: [PATCH 7/9] getenv, setenv in comptime --- BeefBoot/BootApp.cpp | 9 +++++++++ IDEHelper/Compiler/CeMachine.cpp | 34 +++++++++++++++++++++++++++++--- IDEHelper/Compiler/CeMachine.h | 2 ++ 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/BeefBoot/BootApp.cpp b/BeefBoot/BootApp.cpp index d45e2f1ac..d5b701d49 100644 --- a/BeefBoot/BootApp.cpp +++ b/BeefBoot/BootApp.cpp @@ -30,6 +30,8 @@ BF_EXPORT void BF_CALLTYPE BfCompiler_SetOptions(void* bfCompiler, void* hotProj Beefy::BfCompilerOptionFlags optionFlags, const char* mallocLinkName, const char* freeLinkName); BF_EXPORT void BF_CALLTYPE BfCompiler_SetComptimeWriteToOutputCallback(void* bfCompiler, void* userdata, void (BF_CALLTYPE* callback)(void* userdata, char* ptr, int len)); +BF_EXPORT void BF_CALLTYPE BfCompiler_SetComptimeRunShellCommandCallback(void* bfCompiler, void* userdata, + void* (BF_CALLTYPE* callback)(void* userdata, char* cmd, int* outExitcode)); BF_IMPORT void BF_CALLTYPE BfCompiler_ClearBuildCache(void* bfCompiler); BF_IMPORT bool BF_CALLTYPE BfCompiler_Compile(void* bfCompiler, void* bfPassInstance, const char* outputPath); BF_IMPORT float BF_CALLTYPE BfCompiler_GetCompletionPercentage(void* bfCompiler); @@ -798,6 +800,12 @@ static void BF_CALLTYPE ComptimeWriteToOutputCallback(void* userdata, char* ptr, gApp->OutputLine(text, OutputPri_Normal); } +static void* BF_CALLTYPE ComptimeRunShellCommandCallback(void* userdata, char* cmd, int* outExitcode) +{ + *outExitcode = system(cmd); + return NULL; +} + bool BootApp::Compile() { DWORD startTick = BFTickCount(); @@ -822,6 +830,7 @@ bool BootApp::Compile() BfProjectFlags flags = BfProjectFlags_None; BfProject_SetOptions(mCELibProject, BfTargetType_BeefLib, "", mDefines.c_str(), mOptLevel, 0, 0, 0, flags); BfCompiler_SetComptimeWriteToOutputCallback(mCompiler, NULL, ComptimeWriteToOutputCallback); + BfCompiler_SetComptimeRunShellCommandCallback(mCompiler, NULL, ComptimeRunShellCommandCallback); } if (!mDefines.IsEmpty()) diff --git a/IDEHelper/Compiler/CeMachine.cpp b/IDEHelper/Compiler/CeMachine.cpp index 340aef3fd..859e7f1ad 100644 --- a/IDEHelper/Compiler/CeMachine.cpp +++ b/IDEHelper/Compiler/CeMachine.cpp @@ -2085,6 +2085,7 @@ void CeBuilder::Build() auto beModule = irCodeGen->mBeModule; mCeFunction->mFailed = true; + mIntPtrType = irCodeGen->mBeContext->GetPrimitiveType((mPtrSize == 4) ? BeTypeCode_Int32 : BeTypeCode_Int64); auto methodInstance = mCeFunction->mMethodInstance; @@ -2130,8 +2131,6 @@ void CeBuilder::Build() return; } - mIntPtrType = irCodeGen->mBeContext->GetPrimitiveType((mPtrSize == 4) ? BeTypeCode_Int32 : BeTypeCode_Int64); - for (int funcIdx = startFunctionCount; funcIdx < (int)beModule->mFunctions.size(); funcIdx++) { auto beFunction = beModule->mFunctions[funcIdx]; @@ -7104,6 +7103,31 @@ bool CeContext::Execute(CeFunction* startFunction, uint8* startStackPtr, uint8* int64& result = *(int64*)((uint8*)stackPtr + 0); result = BfpSystem_GetTimeStamp(); } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSystem_GetEnvironmentVariable) + { + intptr offset = 0; +#define CE_NEXT_PTR_ARG(type, name) \ + int32 name##PtrVal = *(int32*)((intptr)stackPtr + offset); \ + type name = (type)(name##PtrVal + memStart); \ + offset += ptrSize + + CE_NEXT_PTR_ARG(char*, varName); + CE_NEXT_PTR_ARG(char*, outStr); + CE_NEXT_PTR_ARG(int32*, inOutStrSize); + CE_NEXT_PTR_ARG(BfpSystemResult*, outResult); + + BfpSystem_GetEnvironmentVariable(varName, outStr, inOutStrSize, outResult); + } + else if (checkFunction->mFunctionKind == CeFunctionKind_BfpSystem_SetEnvironmentVariable) + { + intptr offset = 0; + CE_NEXT_PTR_ARG(char*, varName); + CE_NEXT_PTR_ARG(char*, value); + CE_NEXT_PTR_ARG(BfpSystemResult*, outResult); +#undef CE_NEXT_PTR_ARG + + BfpSystem_SetEnvironmentVariable(varName, value, outResult); + } else if (checkFunction->mFunctionKind == CeFunctionKind_Char32_ToLower) { int32& result = *(int32*)((uint8*)stackPtr + 0); @@ -10503,7 +10527,11 @@ void CeMachine::CheckFunctionKind(CeFunction* ceFunction) ceFunction->mFunctionKind = CeFunctionKind_BfpFindFileData_Release; else if (methodDef->mName == "BfpSystem_GetTimeStamp") - ceFunction->mFunctionKind = CeFunctionKind_BfpSystem_GetTimeStamp; + ceFunction->mFunctionKind = CeFunctionKind_BfpSystem_GetTimeStamp; + else if (methodDef->mName == "BfpSystem_GetEnvironmentVariable") + ceFunction->mFunctionKind = CeFunctionKind_BfpSystem_GetEnvironmentVariable; + else if (methodDef->mName == "BfpSystem_SetEnvironmentVariable") + ceFunction->mFunctionKind = CeFunctionKind_BfpSystem_SetEnvironmentVariable; } else if (owner->IsInstanceOf(mCeModule->mCompiler->mChar32TypeDef)) { diff --git a/IDEHelper/Compiler/CeMachine.h b/IDEHelper/Compiler/CeMachine.h index ba18a2ec4..951eecf93 100644 --- a/IDEHelper/Compiler/CeMachine.h +++ b/IDEHelper/Compiler/CeMachine.h @@ -518,6 +518,8 @@ enum CeFunctionKind CeFunctionKind_BfpSpawn_WaitFor, CeFunctionKind_BfpSystem_GetTimeStamp, + CeFunctionKind_BfpSystem_GetEnvironmentVariable, + CeFunctionKind_BfpSystem_SetEnvironmentVariable, CeFunctionKind_Sleep, CeFunctionKind_Char32_ToLower, From 432011276629b447e205c847cede0339e288aa07 Mon Sep 17 00:00:00 2001 From: Rune Date: Mon, 23 Mar 2026 18:42:35 +0100 Subject: [PATCH 8/9] make enum globs eval to enum type instead of int32 --- IDEHelper/Compiler/BfCompiler.cpp | 9 +++++++++ IDEHelper/Compiler/BfCompiler.h | 5 +++++ IDEHelper/Compiler/BfModule.cpp | 8 ++++---- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/IDEHelper/Compiler/BfCompiler.cpp b/IDEHelper/Compiler/BfCompiler.cpp index 6415f4003..73950313a 100644 --- a/IDEHelper/Compiler/BfCompiler.cpp +++ b/IDEHelper/Compiler/BfCompiler.cpp @@ -449,6 +449,10 @@ BfCompiler::BfCompiler(BfSystem* bfSystem, bool isResolveOnly) mIOnTypeDoneTypeDef = NULL; mIOnFieldInitTypeDef = NULL; mIOnMethodInitTypeDef = NULL; + mCompilerOptionsPlatformTypeTypeDef = NULL; + mCompilerOptionsMachineTypeTypeDef = NULL; + mCompilerOptionsToolsetTypeTypeDef = NULL; + mCompilerOptionsOptLevelTypeDef = NULL; mLinkNameAttributeTypeDef = NULL; mCallingConventionAttributeTypeDef = NULL; mMethodRefTypeDef = NULL; @@ -7337,6 +7341,11 @@ bool BfCompiler::DoCompile(const StringImpl& outputDirectory) mIOnFieldInitTypeDef = _GetRequiredType("System.IOnFieldInit"); mIOnMethodInitTypeDef = _GetRequiredType("System.IOnMethodInit"); + mCompilerOptionsPlatformTypeTypeDef = _GetRequiredType("System.Compiler.Options.PlatformType"); + mCompilerOptionsMachineTypeTypeDef = _GetRequiredType("System.Compiler.Options.MachineType"); + mCompilerOptionsToolsetTypeTypeDef = _GetRequiredType("System.Compiler.Options.ToolsetType"); + mCompilerOptionsOptLevelTypeDef = _GetRequiredType("System.Compiler.Options.OptLevel"); + mLinkNameAttributeTypeDef = _GetRequiredType("System.LinkNameAttribute"); mCallingConventionAttributeTypeDef = _GetRequiredType("System.CallingConventionAttribute"); mMethodRefTypeDef = _GetRequiredType("System.MethodReference", 1); diff --git a/IDEHelper/Compiler/BfCompiler.h b/IDEHelper/Compiler/BfCompiler.h index f18c58ce0..845677cc8 100644 --- a/IDEHelper/Compiler/BfCompiler.h +++ b/IDEHelper/Compiler/BfCompiler.h @@ -407,6 +407,11 @@ class BfCompiler BfTypeDef* mIOnFieldInitTypeDef; BfTypeDef* mIOnMethodInitTypeDef; + BfTypeDef* mCompilerOptionsPlatformTypeTypeDef; + BfTypeDef* mCompilerOptionsMachineTypeTypeDef; + BfTypeDef* mCompilerOptionsToolsetTypeTypeDef; + BfTypeDef* mCompilerOptionsOptLevelTypeDef; + BfTypeDef* mMethodRefTypeDef; BfTypeDef* mNullableTypeDef; diff --git a/IDEHelper/Compiler/BfModule.cpp b/IDEHelper/Compiler/BfModule.cpp index 6753f5d74..b1675a7fa 100644 --- a/IDEHelper/Compiler/BfModule.cpp +++ b/IDEHelper/Compiler/BfModule.cpp @@ -15750,15 +15750,15 @@ BfTypedValue BfModule::GetCompilerFieldValue(const StringImpl& str) } if (str == "#Platform") { - return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Int32, mCompiler->mOptions.mPlatformType), GetPrimitiveType(BfTypeCode_Int32)); + return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Int32, mCompiler->mOptions.mPlatformType), ResolveTypeDef(mCompiler->mCompilerOptionsPlatformTypeTypeDef)); } if (str == "#Architecture") { - return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Int32, mCompiler->mOptions.mMachineType), GetPrimitiveType(BfTypeCode_Int32)); + return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Int32, mCompiler->mOptions.mMachineType), ResolveTypeDef(mCompiler->mCompilerOptionsMachineTypeTypeDef)); } if (str == "#Toolset") { - return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Int32, mCompiler->mOptions.mToolsetType), GetPrimitiveType(BfTypeCode_Int32)); + return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Int32, mCompiler->mOptions.mToolsetType), ResolveTypeDef(mCompiler->mCompilerOptionsToolsetTypeTypeDef)); } if (str == "#TargetTriple") { @@ -15766,7 +15766,7 @@ BfTypedValue BfModule::GetCompilerFieldValue(const StringImpl& str) } if (str == "#OptimizationLevel") { - return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Int32, project->mCodeGenOptions.mOptLevel), GetPrimitiveType(BfTypeCode_Int32)); + return BfTypedValue(mBfIRBuilder->CreateConst(BfTypeCode_Int32, project->mCodeGenOptions.mOptLevel), ResolveTypeDef(mCompiler->mCompilerOptionsOptLevelTypeDef)); } if ((mCurMethodState != NULL) && (mCurMethodState->mMixinState != NULL)) From 49bbcd3483b33b954e5489a04708025b901eddeb Mon Sep 17 00:00:00 2001 From: Rune Date: Mon, 23 Mar 2026 19:05:48 +0100 Subject: [PATCH 9/9] remove AddLibPath --- BeefLibs/corlib/src/Compiler.bf | 4 ++-- IDE/src/IDEApp.bf | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/BeefLibs/corlib/src/Compiler.bf b/BeefLibs/corlib/src/Compiler.bf index 8ee77fc66..edec8ab7b 100644 --- a/BeefLibs/corlib/src/Compiler.bf +++ b/BeefLibs/corlib/src/Compiler.bf @@ -260,12 +260,12 @@ namespace System { public String mCmdInfo = new .() ~ delete _; - public void AddLibPath(StringView lib) + /*public void AddLibPath(StringView lib) { mCmdInfo.Append("addLibPath\t"); lib.QuoteString(mCmdInfo); mCmdInfo.Append('\n'); - } + }*/ public virtual void PreBuild() { diff --git a/IDE/src/IDEApp.bf b/IDE/src/IDEApp.bf index a0776ab55..fe949a4e0 100644 --- a/IDE/src/IDEApp.bf +++ b/IDE/src/IDEApp.bf @@ -9940,10 +9940,10 @@ namespace IDE switch (line[..