123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944 |
- #pragma warning(disable:4996)
- //#define BFBUILD_MAIN_THREAD_COMPILE
- #include "BootApp.h"
- #include <iostream>
- #include "BeefySysLib/util/String.h"
- #include "BeefySysLib/util/FileEnumerator.h"
- #include "BeefySysLib/util/WorkThread.h"
- #include "BeefySysLib/platform/PlatformHelper.h"
- #include "Compiler/BfSystem.h"
- #ifdef BF_PLATFORM_WINDOWS
- #include <direct.h>
- #endif
- BF_IMPORT void BF_CALLTYPE Targets_Create();
- BF_IMPORT void BF_CALLTYPE Targets_Delete();
- BF_IMPORT void BF_CALLTYPE BfSystem_ReportMemory(void* bfSystem);
- BF_EXPORT void BF_CALLTYPE BfCompiler_ProgramDone();
- BF_IMPORT void BF_CALLTYPE Debugger_FullReportMemory();
- //////////////////////////////////////////////////////////////////////////
- BF_IMPORT void BF_CALLTYPE BfCompiler_Delete(void* bfCompiler);
- BF_EXPORT void BF_CALLTYPE BfCompiler_SetOptions(void* bfCompiler, void* hotProject, int hotIdx,
- int machineType, int toolsetType, int simdSetting, int allocStackCount, int maxWorkerThreads,
- Beefy::BfCompilerOptionFlags optionFlags, const char* mallocLinkName, const char* freeLinkName);
- 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);
- BF_IMPORT const char* BF_CALLTYPE BfCompiler_GetOutputFileNames(void* bfCompiler, void* bfProject, bool* hadOutputChanges);
- BF_IMPORT const char* BF_CALLTYPE BfCompiler_GetUsedOutputFileNames(void* bfCompiler, void* bfProject, bool flushQueuedHotFiles, bool* hadOutputChanges);
- BF_IMPORT void* BF_CALLTYPE BfSystem_CreateParser(void* bfSystem, void* bfProject);
- BF_IMPORT void BF_CALLTYPE BfParser_SetSource(void* bfParser, const char* data, int length, const char* fileName);
- BF_IMPORT void BF_CALLTYPE BfParser_SetCharIdData(void* bfParser, uint8* data, int length);
- BF_IMPORT bool BF_CALLTYPE BfParser_Parse(void* bfParser, void* bfPassInstance, bool compatMode);
- BF_IMPORT bool BF_CALLTYPE BfParser_Reduce(void* bfParser, void* bfPassInstance);
- BF_IMPORT bool BF_CALLTYPE BfParser_BuildDefs(void* bfParser, void* bfPassInstance, void* resolvePassData, bool fullRefresh);
- //////////////////////////////////////////////////////////////////////////
- BF_IMPORT void* BF_CALLTYPE BfSystem_Create();
- BF_IMPORT void BF_CALLTYPE BfSystem_ReportMemory(void* bfSystem);
- BF_IMPORT void BF_CALLTYPE BfSystem_Delete(void* bfSystem);
- BF_IMPORT void* BF_CALLTYPE BfSystem_CreatePassInstance(void* bfSystem);
- BF_IMPORT void* BF_CALLTYPE BfSystem_CreateCompiler(void* bfSystem, bool isResolveOnly);
- BF_IMPORT void* BF_CALLTYPE BfSystem_CreateProject(void* bfSystem, const char* projectName);
- BF_IMPORT void BF_CALLTYPE BfParser_Delete(void* bfParser);
- BF_IMPORT void BF_CALLTYPE BfSystem_AddTypeOptions(void* bfSystem, const char* filter, int32 simdSetting, int32 optimizationLevel, int32 emitDebugInfo, int32 arrayBoundsCheck,
- int32 initLocalVariables, int32 emitDynamicCastCheck, int32 emitObjectAccessCheck, int32 allocStackTraceDepth);
- //////////////////////////////////////////////////////////////////////////
- BF_IMPORT void BF_CALLTYPE BfProject_SetDisabled(void* bfProject, bool disabled);
- BF_IMPORT void BF_CALLTYPE BfProject_SetOptions(void* bfProject, int targetType, const char* startupObject, const char* preprocessorMacros,
- int optLevel, int ltoType, int32 flags);
- BF_IMPORT void BF_CALLTYPE BfProject_ClearDependencies(void* bfProject);
- BF_IMPORT void BF_CALLTYPE BfProject_AddDependency(void* bfProject, void* depProject);
- //////////////////////////////////////////////////////////////////////////
- BF_IMPORT const char* BF_CALLTYPE BfPassInstance_PopOutString(void* bfPassInstance);
- BF_IMPORT void BF_CALLTYPE BfPassInstance_Delete(void* bfPassInstance);
- //////////////////////////////////////////////////////////////////////////
- BF_IMPORT const char* BF_CALLTYPE VSSupport_Find();
- //////////////////////////////////////////////////////////////////////////
- USING_NS_BF;
- BootApp* Beefy::gApp = NULL;
- uint32 gConsoleFGColor = 0;
- uint32 gConsoleBGColor = 0;
- static bool GetConsoleColor(uint32& fgColor, uint32& bgColor)
- {
- #ifdef _WIN32
- static uint32 consoleColors[16] = { 0xff000000, 0xff000080, 0xff008000, 0xff008080, 0xff800000, 0xff800080, 0xff808000, 0xffc0c0c0,
- 0xff808080, 0xff0000ff, 0xff00ff00, 0xff00ffff, 0xffff0000, 0xffff00ff, 0xffffff00, 0xffffffff };
- CONSOLE_SCREEN_BUFFER_INFO screenBuffInfo = { 0 };
- GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &screenBuffInfo);
- fgColor = consoleColors[screenBuffInfo.wAttributes & 0xF];
- bgColor = consoleColors[(screenBuffInfo.wAttributes >> 4) & 0xF];
- return true;
- #else
- fgColor = 0xFF808080;
- bgColor = 0xFF000000;
- return false;
- #endif
- }
- static WORD GetColorCode(uint32 color)
- {
- WORD code = 0;
- #ifdef _WIN32
- if (((color >> 0) & 0xFF) > 0x40)
- code |= FOREGROUND_BLUE;
- if (((color >> 8) & 0xFF) > 0x40)
- code |= FOREGROUND_GREEN;
- if (((color >> 16) & 0xFF) > 0x40)
- code |= FOREGROUND_RED;
- if ((((color >> 0) & 0xFF) > 0xC0) ||
- (((color >> 8) & 0xFF) > 0xC0) ||
- (((color >> 16) & 0xFF) > 0xC0))
- code |= FOREGROUND_INTENSITY;
- #endif
- return code;
- }
- static bool SetConsoleColor(uint32 fgColor, uint32 bgColor)
- {
- #ifdef _WIN32
- WORD attr = GetColorCode(fgColor) | (GetColorCode(bgColor) << 4);
- SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE), attr);
- SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), attr);
- return true;
- #else
- return false;
- #endif
- }
- BootApp::BootApp()
- {
- Targets_Create();
-
- mVerbosity = Verbosity_Normal;
- mTargetType = BfTargetType_BeefConsoleApplication;
- //char str[MAX_PATH];
- //GetModuleFileNameA(NULL, str, MAX_PATH);
- //mInstallDir = GetFileDir(str) + "/";
- //getcwd(str, MAX_PATH);
- //mStartupDir = str;
- //mStartupDir += "/";
- //mDoClean = false;
- mHadCmdLine = false;
- mShowedHelp = false;
- mHadErrors = false;
- mSystem = NULL;
- mCompiler = NULL;
- mProject = NULL;
- mCELibProject = NULL;
- mIsCERun = false;
- mAsmKind = BfAsmKind_None;
- mStartupObject = "Program";
- #ifdef BF_PLATFORM_WINDOWS
- mOptLevel = BfOptLevel_OgPlus;
- mToolset = BfToolsetType_Microsoft;
- #else
- mOptLevel = BfOptLevel_O0;
- mToolset = BfToolsetType_GNU;
- #endif
- mEmitIR = false;
-
- GetConsoleColor(gConsoleFGColor, gConsoleBGColor);
- }
- BootApp::~BootApp()
- {
- Targets_Delete();
- }
- void BootApp::OutputLine(const String& text, OutputPri outputPri)
- {
- if (mLogFile.IsOpen())
- {
- mLogFile.WriteSNZ(text);
- mLogFile.WriteSNZ("\n");
- }
- if (outputPri == OutputPri_Error)
- mHadErrors = true;
- switch (outputPri)
- {
- case OutputPri_Low:
- if (mVerbosity < Verbosity_Detailed)
- return;
- break;
- case OutputPri_Normal:
- if (mVerbosity < Verbosity_Normal)
- return;
- break;
- case OutputPri_High:
- case OutputPri_Warning:
- case OutputPri_Error:
- if (mVerbosity < Verbosity_Minimal)
- return;
- break;
- default: break;
- }
- if (outputPri == OutputPri_Warning)
- {
- SetConsoleColor(0xFFFFFF00, gConsoleBGColor);
- std::cerr << text.c_str() << std::endl;
- SetConsoleColor(gConsoleFGColor, gConsoleBGColor);
- }
- else if (outputPri == OutputPri_Error)
- {
- SetConsoleColor(0xFFFF0000, gConsoleBGColor);
- std::cerr << text.c_str() << std::endl;
- SetConsoleColor(gConsoleFGColor, gConsoleBGColor);
- }
- else
- std::cout << text.c_str() << std::endl;
- }
- void BootApp::Fail(const String& error)
- {
- if (mLogFile.IsOpen())
- mLogFile.WriteSNZ("FAIL: " + error + "\n");
- std::cerr << "FAIL: " << error.c_str() << std::endl;
- mHadErrors = true;
- }
- bool BootApp::HandleCmdLine(const String &cmd, const String& param)
- {
- mHadCmdLine = true;
- bool wantedParam = false;
- if ((!cmd.StartsWith("-")) && (mIsCERun) && (mCESrc.IsEmpty()))
- {
- mCESrc = cmd;
- return true;
- }
- if ((cmd == "-help") || (cmd == "-h") || (cmd == "/?"))
- {
- mShowedHelp = true;
- std::cout << "BeefBoot - Beef bootstrapping tool" << std::endl;
-
- return false;
- }
- else if (cmd == "-src")
- {
- mRequestedSrc.Add(param);
- wantedParam = true;
- }
- else if (cmd == "-verbosity")
- {
- if (param == "quiet")
- mVerbosity = Verbosity_Quiet;
- else if (param == "minimal")
- mVerbosity = Verbosity_Minimal;
- else if (param == "normal")
- mVerbosity = Verbosity_Normal;
- else if (param == "detailed")
- mVerbosity = Verbosity_Detailed;
- else if (param == "diagnostic")
- mVerbosity = Verbosity_Diagnostic;
- else
- {
- Fail(StrFormat("Invalid verbosity level: '%s'", param.c_str()));
- return false;
- }
- wantedParam = true;
- }
- else if (cmd == "-version")
- {
- BfpSystemResult sysResult;
- String exePath;
- BFP_GETSTR_HELPER(exePath, sysResult, BfpSystem_GetExecutablePath(__STR, __STRLEN, &sysResult));
- std::cout << "0.0.0" << std::endl;
- mShowedHelp = true;
- return true;
- }
- else if (cmd == "-define")
- {
- if (!mDefines.IsEmpty())
- mDefines += "\n";
- mDefines += param;
- wantedParam = true;
- }
- else if (cmd == "-startup")
- {
- mStartupObject = param;
- wantedParam = true;
- }
- else if (cmd == "-out")
- {
- mTargetPath = param;
- wantedParam = true;
- }
- else if (cmd == "-linkparams")
- {
- mLinkParams = param;
- wantedParam = true;
- }
- else if (cmd == "-Og+")
- {
- mOptLevel = BfOptLevel_OgPlus;
- }
- else if (cmd == "-O0")
- {
- mOptLevel = BfOptLevel_O0;
- }
- else if (cmd == "-O1")
- {
- mOptLevel = BfOptLevel_O1;
- }
- else if (cmd == "-O2")
- {
- mOptLevel = BfOptLevel_O2;
- }
- else if (cmd == "-O3")
- {
- mOptLevel = BfOptLevel_O3;
- }
- else if (cmd == "-gnu")
- {
- mToolset = BfToolsetType_GNU;
- }
- else if (cmd == "-emitir")
- {
- mEmitIR = true;
- }
- else if (cmd == "-cedest")
- {
- mIsCERun = true;
- mCEDest = param;
- wantedParam = true;
- }
- else if (cmd == "-cesrc")
- {
- mIsCERun = true;
- }
- else if (cmd == "-emitasm")
- {
- if (param.IsEmpty())
- {
- mAsmKind = BfAsmKind_Intel;
- }
- else
- {
- if (param == "att")
- mAsmKind = BfAsmKind_ATT;
- else
- mAsmKind = BfAsmKind_Intel;
- wantedParam = true;
- }
- }
- else
- {
- Fail("Unknown option: " + cmd);
- return false;
- }
- if ((wantedParam) && (param.empty()))
- {
- Fail(StrFormat("Parameter expected for '%s'", cmd.c_str()));
- return false;
- }
- else if ((!wantedParam) && (!param.empty()))
- {
- Fail(StrFormat("No parameter expected for '%s'", cmd.c_str()));
- return false;
- }
- return true;
- }
- bool BootApp::Init()
- {
- char* cwdPtr = getcwd(NULL, 0);
- mWorkingDir = cwdPtr;
- free(cwdPtr);
- if ((mTargetPath.IsEmpty()) && (mCESrc.IsEmpty()))
- {
- Fail("'Out' path not specified");
- }
- if (mRequestedSrc.IsEmpty())
- {
- Fail("No source specified");
- }
- return !mHadErrors;
- }
- void BootApp::QueueFile(const StringImpl& path, void* project)
- {
- String ext;
- ext = GetFileExtension(path);
- if ((ext.Equals(".bf", StringImpl::CompareKind_OrdinalIgnoreCase)) ||
- (ext.Equals(".cs", StringImpl::CompareKind_OrdinalIgnoreCase)))
- {
- int len;
- const char* data = LoadTextData(path, &len);
- if (data == NULL)
- {
- Fail(StrFormat("Unable to load file '%s'", path.c_str()));
- return;
- }
-
- bool worked = true;
- void* bfParser = BfSystem_CreateParser(mSystem, project);
- BfParser_SetSource(bfParser, data, len, path.c_str());
- //bfParser.SetCharIdData(charIdData);
- worked &= BfParser_Parse(bfParser, mPassInstance, false);
- worked &= BfParser_Reduce(bfParser, mPassInstance);
- worked &= BfParser_BuildDefs(bfParser, mPassInstance, NULL, false);
-
- delete data;
- }
- }
- void BootApp::QueuePath(const StringImpl& path)
- {
- if (DirectoryExists(path))
- {
- for (auto& fileEntry : FileEnumerator(path, FileEnumerator::Flags_Files))
- {
- String filePath = fileEntry.GetFilePath();
-
- String fileName;
- fileName = GetFileName(filePath);
- QueueFile(filePath, (mCELibProject != NULL) ? mCELibProject : mProject);
- }
- for (auto& fileEntry : FileEnumerator(path, FileEnumerator::Flags_Directories))
- {
- String childPath = fileEntry.GetFilePath();
- String dirName;
- dirName = GetFileName(childPath);
- if (dirName == "build")
- continue;
- QueuePath(childPath);
- }
- }
- else
- {
- QueueFile(path, mProject);
- }
- }
- static void CompileThread(void* param)
- {
- BfpThread_SetName(NULL, "CompileThread", NULL);
- BootApp* app = (BootApp*)param;
- BfCompiler_ClearBuildCache(app->mCompiler);
-
- if (!BfCompiler_Compile(app->mCompiler, app->mPassInstance, app->mBuildDir.c_str()))
- app->mHadErrors = true;
- }
- void BootApp::DoCompile()
- {
- #ifdef BFBUILD_MAIN_THREAD_COMPILE
- mOutputDirectory = outputDirectory;
- CompileThread(this);
- #else
- WorkThreadFunc workThread;
- workThread.Start(CompileThread, this);
- int lastProgressTicks = 0;
- bool showProgress = mVerbosity >= Verbosity_Normal;
- int progressSize = 30;
- if (showProgress)
- {
- std::cout << "[";
- for (int i = 0; i < progressSize; i++)
- std::cout << " ";
- std::cout << "]";
- for (int i = 0; i < progressSize + 1; i++)
- std::cout << "\b";
- std::cout.flush();
- }
- while (true)
- {
- bool isDone = workThread.WaitForFinish(100);
- float pct = BfCompiler_GetCompletionPercentage(mCompiler);
- if (isDone)
- pct = 1.0;
- int progressTicks = (int)(pct * progressSize + 0.5f);
- while (progressTicks > lastProgressTicks)
- {
- if (showProgress)
- {
- std::cout << "*";
- std::cout.flush();
- }
- lastProgressTicks++;
- }
- if (isDone)
- break;
- }
- if (showProgress)
- std::cout << std::endl;
- #endif
- }
- struct OutputContext
- {
- bool mIsError;
- BfpFile* mFile;
- };
- static void OutputThread(void* param)
- {
- OutputContext* context = (OutputContext*)param;
- String queuedStr;
-
- while (true)
- {
- char data[1024];
-
- BfpFileResult result;
- int bytesRead = (int)BfpFile_Read(context->mFile, data, 1023, -1, &result);
- if ((result != BfpFileResult_Ok) && (result != BfpFileResult_PartialData))
- return;
- data[bytesRead] = 0;
- if (context->mIsError)
- {
- std::cerr << data;
- std::cerr.flush();
- }
- else
- {
- std::cout << data;
- std::cout.flush();
- }
- if (gApp->mLogFile.IsOpen())
- {
- // This is to ensure that error and output lines are not merged together, though they may interleave
- queuedStr.Append(data, bytesRead);
- while (true)
- {
- int crPos = (int)queuedStr.IndexOf('\n');
- if (crPos == -1)
- break;
- AutoCrit autoCrit(gApp->mLogCritSect);
- if (context->mIsError)
- gApp->mLogFile.WriteSNZ("err> ");
- else
- gApp->mLogFile.WriteSNZ("out> ");
- int endPos = crPos;
- if ((endPos > 0) && (queuedStr[endPos - 1] == '\r'))
- endPos--;
- gApp->mLogFile.Write((void*)queuedStr.c_str(), endPos);
- gApp->mLogFile.WriteSNZ("\n");
- queuedStr.Remove(0, crPos + 1);
- }
- }
- }
- }
- bool BootApp::QueueRun(const String& fileName, const String& args, const String& workingDir, BfpSpawnFlags extraFlags)
- {
- OutputLine(StrFormat("EXECUTING: %s %s", fileName.c_str(), args.c_str()), OutputPri_Low);
- BfpSpawnFlags spawnFlags = (BfpSpawnFlags)(BfpSpawnFlag_NoWindow | BfpSpawnFlag_RedirectStdOutput | BfpSpawnFlag_RedirectStdError | extraFlags);
- BfpSpawn* spawn = BfpSpawn_Create(fileName.c_str(), args.c_str(), workingDir.c_str(), NULL, spawnFlags, NULL);
- if (spawn == NULL)
- {
- Fail(StrFormat("Failed to execute '%s'", fileName.c_str()));
- return false;
- }
- int exitCode = 0;
- OutputContext outputContext;;
- outputContext.mIsError = false;
- OutputContext errorContext;
- errorContext.mIsError = false;
- BfpSpawn_GetStdHandles(spawn, NULL, &outputContext.mFile, &errorContext.mFile);
- BfpThread* outputThread = BfpThread_Create(OutputThread, (void*)&outputContext);
- BfpThread* errorThread = BfpThread_Create(OutputThread, (void*)&errorContext);
-
- BfpSpawn_WaitFor(spawn, -1, &exitCode, NULL);
- if (outputContext.mFile != NULL)
- BfpFile_Close(outputContext.mFile, NULL);
- if (errorContext.mFile != NULL)
- BfpFile_Close(errorContext.mFile, NULL);
- BfpThread_WaitFor(outputThread, -1);
- BfpThread_WaitFor(errorThread, -1);
- BfpThread_Release(outputThread);
- BfpThread_Release(errorThread);
- BfpSpawn_Release(spawn);
- if (exitCode != 0)
- {
- Fail(StrFormat("Exit code returned: %d", exitCode));
- return false;
- }
- return true;
- }
- bool BootApp::CopyFile(const StringImpl& srcPath, const StringImpl& destPath)
- {
- BfpFileResult result = BfpFileResult_Ok;
- for (int i = 0; i < 20; i++)
- {
- BfpFile_Copy(srcPath.c_str(), destPath.c_str(), BfpFileCopyKind_Always, &result);
- if (result == BfpFileResult_Ok)
- return true;
- BfpThread_Sleep(100);
- }
- Fail(StrFormat("Failed to copy '%s' to '%s'", srcPath.c_str(), destPath.c_str()));
- return false;
- }
- #ifdef BF_PLATFORM_WINDOWS
- void BootApp::DoLinkMS()
- {
- String vsStr = VSSupport_Find();
-
- int toolIdx = (int)vsStr.IndexOf("TOOL64\t");
- int toolCrIdx = (int)vsStr.IndexOf('\n', toolIdx + 1);
- if ((toolIdx == -1) || (toolCrIdx == -1))
- {
- Fail("Failed to detect Visual Studio configuration. Is Visual Studio 2015 or later installed?");
- return;
- }
-
- String linkerPath = vsStr.Substring(toolIdx + 7, toolCrIdx - toolIdx - 7);
- linkerPath.Append("\\link.exe");
- String linkLine;
- String targetPath = mTargetPath;
- bool hadOutputChanges;
- const char* result = BfCompiler_GetUsedOutputFileNames(mCompiler, mProject, true, &hadOutputChanges);
- if (result == NULL)
- return;
- std::string fileNamesStr;
- fileNamesStr += result;
- if (fileNamesStr.length() == 0)
- return;
- int curIdx = -1;
- while (curIdx < (int)fileNamesStr.length())
- {
- int nextBr = (int)fileNamesStr.find('\n', curIdx + 1);
- if (nextBr == -1)
- nextBr = (int)fileNamesStr.length();
- linkLine.Append(fileNamesStr.substr(curIdx + 1, nextBr - curIdx - 1));
- linkLine.Append(" ");
- curIdx = nextBr;
- }
- linkLine.Append("-out:");
- IDEUtils::AppendWithOptionalQuotes(linkLine, targetPath);
- linkLine.Append(" ");
- if (mTargetType == BfTargetType_BeefConsoleApplication)
- linkLine.Append("-subsystem:console ");
- else
- linkLine.Append("-subsystem:windows ");
- linkLine.Append("-defaultlib:libcmtd ");
- linkLine.Append("-nologo ");
- linkLine.Append("-pdb:");
- int lastDotPos = (int)targetPath.LastIndexOf('.');
- if (lastDotPos == -1)
- lastDotPos = (int)targetPath.length();
- auto pdbName = String(targetPath, 0, lastDotPos);
- pdbName.Append(".pdb");
- IDEUtils::AppendWithOptionalQuotes(linkLine, pdbName);
- linkLine.Append(" ");
- linkLine.Append("-debug ");
- int checkIdx = 0;
- while (true)
- {
- int libIdx = (int)vsStr.IndexOf("LIB64\t", checkIdx);
- if (libIdx == -1)
- break;
- int libCrIdx = (int)vsStr.IndexOf('\n', libIdx + 1);
- if (libCrIdx == -1)
- break;
- String libPath = vsStr.Substring(libIdx + 6, libCrIdx - libIdx - 6);
- linkLine.Append("-libpath:\"");
- linkLine.Append(libPath);
- linkLine.Append("\" ");
- checkIdx = libCrIdx + 1;
- }
- linkLine.Append(mLinkParams);
- BfpSpawnFlags flags = BfpSpawnFlag_None;
- flags = (BfpSpawnFlags)(BfpSpawnFlag_UseArgsFile | BfpSpawnFlag_UseArgsFile_Native | BfpSpawnFlag_UseArgsFile_BOM);
- auto runCmd = QueueRun(linkerPath, linkLine, mWorkingDir, flags);
- }
- #endif
- void BootApp::DoLinkGNU()
- {
- String linkerPath = "/usr/bin/c++";
- String linkLine;
- String targetPath = mTargetPath;
- bool hadOutputChanges;
- const char* result = BfCompiler_GetUsedOutputFileNames(mCompiler, mProject, true, &hadOutputChanges);
- if (result == NULL)
- return;
- std::string fileNamesStr;
- fileNamesStr += result;
- if (fileNamesStr.length() == 0)
- return;
- int curIdx = -1;
- while (curIdx < (int)fileNamesStr.length())
- {
- int nextBr = (int)fileNamesStr.find('\n', curIdx + 1);
- if (nextBr == -1)
- nextBr = (int)fileNamesStr.length();
- linkLine.Append(fileNamesStr.substr(curIdx + 1, nextBr - curIdx - 1));
- linkLine.Append(" ");
- curIdx = nextBr;
- }
- linkLine.Append("-o ");
- IDEUtils::AppendWithOptionalQuotes(linkLine, targetPath);
- linkLine.Append(" ");
- linkLine.Append("-g ");
- linkLine.Append("-debug -no-pie ");
- linkLine.Append(mLinkParams);
- auto runCmd = QueueRun(linkerPath, linkLine, mWorkingDir, BfpSpawnFlag_UseArgsFile);
- }
- bool BootApp::Compile()
- {
- DWORD startTick = BFTickCount();
- mSystem = BfSystem_Create();
- mCompiler = BfSystem_CreateCompiler(mSystem, false);
- String projectName = GetFileName(mTargetPath);
- int dotPos = (int)projectName.IndexOf('.');
- if (dotPos != -1)
- projectName.RemoveToEnd(dotPos);
- if (projectName.IsEmpty())
- projectName.Append("BeefProject");
- mProject = BfSystem_CreateProject(mSystem, projectName.c_str());
-
- if (mIsCERun)
- {
- mCELibProject = BfSystem_CreateProject(mSystem, "BeefLib");
- BfProjectFlags flags = BfProjectFlags_None;
- BfProject_SetOptions(mCELibProject, BfTargetType_BeefLib, "", mDefines.c_str(), mOptLevel, 0, flags);
- }
- if (!mDefines.IsEmpty())
- mDefines.Append("\n");
- mDefines.Append("BF_64_BIT");
- mDefines.Append("\nBF_LITTLE_ENDIAN");
- mDefines.Append("\n");
- mDefines.Append(BF_PLATFORM_NAME);
- int ltoType = 0;
- BfProjectFlags flags = BfProjectFlags_None;
- if (mIsCERun)
- {
- flags = (BfProjectFlags)(flags | BfProjectFlags_SingleModule | BfProjectFlags_AlwaysIncludeAll);
- if (mAsmKind == BfAsmKind_ATT)
- flags = (BfProjectFlags)(flags | BfProjectFlags_AsmOutput | BfProjectFlags_AsmOutput_ATT);
- else if (mAsmKind == BfAsmKind_Intel)
- flags = (BfProjectFlags)(flags | BfProjectFlags_AsmOutput);
- }
- BfProject_SetOptions(mProject, mTargetType, mStartupObject.c_str(), mDefines.c_str(), mOptLevel, ltoType, flags);
- if (mCELibProject != NULL)
- BfProject_AddDependency(mProject, mCELibProject);
-
- mPassInstance = BfSystem_CreatePassInstance(mSystem);
-
- Beefy::String exePath;
- BfpGetStrHelper(exePath, [](char* outStr, int* inOutStrSize, BfpResult* result)
- {
- BfpSystem_GetExecutablePath(outStr, inOutStrSize, (BfpSystemResult*)result);
- });
- mBuildDir = GetFileDir(exePath) + "/build";
-
- RecursiveCreateDirectory(mBuildDir + "/" + projectName);
- if (mIsCERun)
- RecursiveCreateDirectory(mBuildDir + "/BeefLib");
- BfCompilerOptionFlags optionFlags = (BfCompilerOptionFlags)(BfCompilerOptionFlag_EmitDebugInfo | BfCompilerOptionFlag_EmitLineInfo | BfCompilerOptionFlag_GenerateOBJ | BfCompilerOptionFlag_OmitDebugHelpers);
- if (mEmitIR)
- optionFlags = (BfCompilerOptionFlags)(optionFlags | BfCompilerOptionFlag_WriteIR);
- int maxWorkerThreads = BfpSystem_GetNumLogicalCPUs(NULL);
- if (maxWorkerThreads <= 1)
- maxWorkerThreads = 6;
- BfCompiler_SetOptions(mCompiler, NULL, 0, BfMachineType_x64, mToolset, BfSIMDSetting_SSE2, 1, maxWorkerThreads, optionFlags, "malloc", "free");
-
- if (mIsCERun)
- {
- QueueFile(mCESrc, mProject);
- }
- for (auto& srcName : mRequestedSrc)
- {
- String absPath = GetAbsPath(srcName, mWorkingDir);
- QueuePath(absPath);
- }
- if (!mHadErrors)
- {
- DoCompile();
- OutputLine(StrFormat("TIMING: Beef compiling: %0.1fs", (BFTickCount() - startTick) / 1000.0), OutputPri_Normal);
- if (!mCEDest.IsEmpty())
- {
- String ext;
- String srcResult = mBuildDir + "/BeefProject/BeefProject";
- if (mAsmKind == BfAsmKind_None)
- srcResult += BF_OBJ_EXT;
- else
- srcResult += ".s";
-
- CopyFile(srcResult, mCEDest);
- }
- if ((mIsCERun) && (mEmitIR))
- {
- String ext;
- String srcResult = mBuildDir + "/BeefProject/BeefProject";
- String irDestPath = mCEDest;
- int dotPos = (int)irDestPath.LastIndexOf('.');
- if (dotPos != -1)
- irDestPath.RemoveToEnd(dotPos);
- if (mOptLevel == BfOptLevel_OgPlus)
- {
- srcResult += ".beir";
- irDestPath += ".ll";
- }
- else
- {
- srcResult += ".ll";
- irDestPath += ".ll";
- }
-
- CopyFile(srcResult, irDestPath);
- }
- }
- while (true)
- {
- const char* msg = BfPassInstance_PopOutString(mPassInstance);
- if (msg == NULL)
- break;
- if ((strncmp(msg, ":warn ", 6) == 0))
- {
- OutputLine(msg + 6, OutputPri_Warning);
- }
- else if ((strncmp(msg, ":error ", 7) == 0))
- {
- OutputLine(msg + 7, OutputPri_Error);
- }
- else if ((strncmp(msg, ":med ", 5) == 0))
- {
- OutputLine(msg + 5, OutputPri_Normal);
- }
- else if ((strncmp(msg, ":low ", 5) == 0))
- {
- OutputLine(msg + 5, OutputPri_Low);
- }
- else if ((strncmp(msg, "ERROR(", 6) == 0) || (strncmp(msg, "ERROR:", 6) == 0))
- {
- OutputLine(msg, OutputPri_Error);
- }
- else if ((strncmp(msg, "WARNING(", 8) == 0) || (strncmp(msg, "WARNING:", 8) == 0))
- {
- OutputLine(msg, OutputPri_Warning);
- }
- else
- OutputLine(msg);
- }
-
- if ((!mHadErrors) && (!mTargetPath.IsEmpty()))
- {
- if (mVerbosity == Verbosity_Normal)
- {
- std::cout << "Linking " << mTargetPath.c_str() << "...";
- std::cout.flush();
- }
- #ifdef BF_PLATFORM_WINDOWS
- DoLinkMS();
- #else
- DoLinkGNU();
- #endif
- if (mVerbosity == Verbosity_Normal)
- std::cout << std::endl;
- }
- BfPassInstance_Delete(mPassInstance);
- BfCompiler_Delete(mCompiler);
- BfSystem_Delete(mSystem);
- return !mHadErrors;
- }
|