Skip to content
18 changes: 18 additions & 0 deletions BeefBoot/BootApp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ 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_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);
Expand Down Expand Up @@ -790,6 +794,18 @@ 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);
}

static void* BF_CALLTYPE ComptimeRunShellCommandCallback(void* userdata, char* cmd, int* outExitcode)
{
*outExitcode = system(cmd);
return NULL;
}

bool BootApp::Compile()
{
DWORD startTick = BFTickCount();
Expand All @@ -813,6 +829,8 @@ 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())
Expand Down
32 changes: 32 additions & 0 deletions BeefLibs/corlib/src/Compiler.bf
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,38 @@ 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()
{
}
public virtual void PostBuild()
{
}

static String PreBuild<T>() where T : BuildLogic
{
T val = scope T();
val.PreBuild();
return val.mCmdInfo;
}
static String PostBuild<T>() where T : BuildLogic
{
T val = scope T();
val.PostBuild();
return val.mCmdInfo;
}
}

public struct MethodBuilder
{
void* mNative;
Expand Down
4 changes: 4 additions & 0 deletions BeefLibs/corlib/src/Console.bf
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -467,5 +468,8 @@ namespace System
Write("\x1B[H\x1B[J");
#endif
}

[LinkName("system")]
public static extern int32 RunShellCommand(char8* command);
}
}
16 changes: 16 additions & 0 deletions IDE/src/BuildContext.bf
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,18 @@ namespace IDE
return didCommands ? .HadCommands : .NoCommands;
}

public void QueueBuildLogic(Project project, IDEApp.StartCustomBuildLogicCmd.Stage stage)
{
if (project.mBeefGlobalOptions.mBuildLogicObject.IsEmpty)
return;

gApp.mExecutionQueue.Add(new IDEApp.StartCustomBuildLogicCmd()
{
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
Expand Down Expand Up @@ -1547,6 +1559,8 @@ namespace IDE
case .Failed:
completedCompileCmd.mFailed = true;
}

QueueBuildLogic(project, .PreBuild);
}

if (project.mGeneralOptions.mTargetType == .CustomBuild)
Expand Down Expand Up @@ -1745,6 +1759,8 @@ namespace IDE

if (WantsProjectBuild(project, compileKind))
{
QueueBuildLogic(project, .PostBuild);

switch (QueueProjectCustomBuildCommands(project, targetPath, compileKind.WantsRunAfter ? options.mBuildOptions.mBuildCommandsOnRun : options.mBuildOptions.mBuildCommandsOnCompile, options.mBuildOptions.mPostBuildCmds))
{
case .NoCommands:
Expand Down
56 changes: 56 additions & 0 deletions IDE/src/Compiler/BfCompiler.bf
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -146,6 +155,16 @@ 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)]
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);

Expand Down Expand Up @@ -343,6 +362,16 @@ 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 SetComptimeRunShellCommandCallback(void* userdata, ComptimeRunShellCommandCallback callback)
{
BfCompiler_SetComptimeRunShellCommandCallback(mNativeBfCompiler, userdata, callback);
}

public void ForceRebuild()
{
BfCompiler_ForceRebuild(mNativeBfCompiler);
Expand Down Expand Up @@ -783,6 +812,18 @@ 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));
});
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;
});
}
}

Expand Down Expand Up @@ -851,6 +892,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));
Expand Down
90 changes: 90 additions & 0 deletions IDE/src/IDEApp.bf
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,24 @@ namespace IDE
public String mPath ~ delete _;
}

public class StartCustomBuildLogicCmd : ExecutionCmd
{
public enum Stage { PreBuild, PostBuild }

public String mObject ~ delete _;
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,
Expand Down Expand Up @@ -9620,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)
{
Expand Down Expand Up @@ -9868,6 +9892,72 @@ namespace IDE
// Already handled
(void)scriptCmd;
}
else if (var cmd = next as StartCustomBuildLogicCmd) do
{
if (!mBfBuildCompiler.ValidateBuildLogic(cmd.mObject))
{
OutputErrorLine($"Invalid Compiler.BuildLogic: {cmd.mObject}");
ClearAndDeleteItems(mExecutionQueue);
break;
}

ProcessCustomBuildLogicCmd process = new .();
process.mOutput = new .();
process.mTypeName = new .(cmd.mObject);
process.mStage = cmd.mStage;
process.mStopwatch = new .();

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}");
CancelBuild();
continue;
}

switch (line[..<index])
{
/*case "addLibPath":
String path = new .();
line[(index+1)...].UnQuoteString(path);
mDynamicallyAddedLibPaths.Add(path);*/
case "!error":
OutputLineSmart($"{line[(index+1)...]}");
failed = true;
default:
OutputErrorLine($"Invalid build logic execution command: {_}");
failed = true;
}
}

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)
{
String projectName = new String(writeEmitCmd.mProjectName);
Expand Down
4 changes: 4 additions & 0 deletions IDE/src/Project.bf
Original file line number Diff line number Diff line change
Expand Up @@ -1105,6 +1105,8 @@ namespace IDE
[Reflect]
public String mStartupObject = new String("") ~ delete _;
[Reflect]
public String mBuildLogicObject = new String() ~ delete _;
[Reflect]
public String mDefaultNamespace = new String() ~ delete _;
[Reflect]
public List<String> mPreprocessorMacros = new List<String>() ~ DeleteContainerAndItems!(_);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down
1 change: 1 addition & 0 deletions IDE/src/ui/ProjectProperties.bf
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
Loading