Advertisement
Zgragselus

Compile source code

Nov 17th, 2023
905
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 5.91 KB | None | 0 0
  1.  
  2. /// <summary>
  3. /// Compile source (script) file into dll that can be loaded and used
  4. /// </summary>
  5. /// <param name="file">Path to source cpp file</param>
  6. void DirectoryTree::CompileSource(const std::string& file)
  7. {
  8.     std::string command = "";
  9.  
  10.     switch (mCompilerType)
  11.     {
  12.         // MSVC Compiler
  13.     case MSVC:
  14.         // Here is the deal, MSVC always generates .obj, .exp, .lib and .dll file in the current folder
  15.         // so, we will call the MSVC compiler with all settings, and let it build dll, writing output
  16.         // to Build.log
  17.         //
  18.         // Once this is done, we will delete .obj, .exp and .lib file as we don't need those anymore.
  19.         // Which is followed by copying .dll file into the folder where .cpp file originally was, this
  20.         // is not all though - as we just generated a new .dll plugin, we also need to queue it for
  21.         // loading!
  22.         //
  23.         // The loading only happens when .dll exists (otherwise the compilation has failed and the
  24.         // Build.log has to be examined.
  25.         //
  26.         // Uses system calls!
  27.  
  28.         // Compilation (differs for DEBUG vs RELEASE builds)
  29. #ifdef NDEBUG
  30.         command = std::string("cmd /S /C \"\"") + mCompilerPaths[0] + std::string("/vcvarsall.bat\" amd64 && \
  31.                     \"") + mCompilerPaths[1] + std::string("/cl.exe\" /O2 /EHsc /GL /MD \
  32.                     /I \"../Source/Engine/\" \
  33.                     /I \"../Dependencies/\" \
  34.                     /I \"../Dependencies/Bullet/include/\" \
  35.                     /LD \
  36.                     ") + file + std::string(" \
  37.                     \"Engine.lib\" \
  38.                     > Build.log\"");
  39. #else
  40.         command = std::string("cmd /S /C \"\"") + mCompilerPaths[0] + std::string("/vcvarsall.bat\" amd64 && \
  41.                     \"") + mCompilerPaths[1] + std::string("/cl.exe\" /O2 /EHsc /DEBUG /ZI /MDd \
  42.                     /I \"../Source/Engine/\" \
  43.                     /I \"../Dependencies/\" \
  44.                     /I \"../Dependencies/Bullet/include/\" \
  45.                     /LD \
  46.                     ") + file + std::string(" \
  47.                     \"Engine_d.lib\" \
  48.                     > Build.log\"");
  49. #endif
  50.         std::cout << command << std::endl;
  51.         system(command.c_str());
  52.  
  53.         // First, Check compilation results - check whether the output file exists
  54.         if (Engine::Files::Exists("Build.log"))
  55.         {
  56.             // Open the file and look for 'Finished generating code' - which points to compilation success
  57.             std::ifstream buildLog("Build.log");
  58.             bool buildSucessful = false;
  59.  
  60.             std::string line;
  61.             while (std::getline(buildLog, line))
  62.             {
  63.                 if (line.find("Finished generating code") != std::string::npos)
  64.                 {
  65.                     buildSucessful = true;
  66.                 }
  67.  
  68.                 // TODO - these lines can be appended to log at some level
  69.             }
  70.  
  71.             buildLog.close();
  72.  
  73.             // At this point we can start processing the new dll and loading it.
  74.             if (buildSucessful)
  75.             {
  76.                 // Get previous plugin node using this script
  77.                 Engine::Manager<Engine::Plugin>::Node* node = mPluginManager->GetNode(file.substr(0, file.length() - 4) + std::string(".dll"));
  78.  
  79.                 // In case node would exist, we need to store data for each instantiated component in the scene
  80.                 // as these also need to be deleted (and re-created after new library is loaded).
  81.                 std::map<Engine::GameObject*, std::string> tmp;
  82.  
  83.                 // If the node exists - we will need to unload associated dll, as we have to replace it with a newly compiled one
  84.                 if (node != nullptr)
  85.                 {
  86.                     // Get plugin name first
  87.                     void* name = node->Get()->GetProc<void*>("GetName");
  88.                     const char* (*fn)() = (const char* (*)())name;
  89.                     const char* pluginName = (*fn)();
  90.  
  91.                     // Loop through ALL components of given type, serialize them and delete them
  92.                     std::set<Engine::Component*>& components = Engine::ComponentTypeList::GetComponents(Engine::ComponentTypeId::Get(pluginName));
  93.                     for (auto it = components.begin(); it != components.end(); it++)
  94.                     {
  95.                         tmp.insert(std::pair<Engine::GameObject*, std::string>((*it)->mGameObject, (*it)->Serialize()));
  96.                         delete (*it);
  97.                     }
  98.                     components.clear();
  99.  
  100.                     // Unload the node
  101.                     node->Get()->Unload();
  102.                 }
  103.  
  104.                 // Delete .obj, .exp and .lib files in release builds
  105. #ifdef NDEBUG
  106.                 command = std::string("cmd /S /C \"del ")
  107.                     + std::string("\"") + Engine::Files::GetFile(file.substr(0, file.length() - 4)) + std::string(".obj") + std::string("\" ")
  108.                     + std::string("\"") + Engine::Files::GetFile(file.substr(0, file.length() - 4)) + std::string(".exp") + std::string("\" ")
  109.                     + std::string("\"") + Engine::Files::GetFile(file.substr(0, file.length() - 4)) + std::string(".lib") + std::string("\"\"");
  110.                 system(command.c_str());
  111. #endif
  112.  
  113.                 // Move .dll file
  114.                 command = std::string("cmd /S /C \"move ")
  115.                     + std::string("\"") + Engine::Files::GetFile(file.substr(0, file.length() - 4)) + std::string(".dll") + std::string("\" ")
  116.                     + Engine::Files::GetFolder(file) + std::string("\"");
  117.                 system(command.c_str());
  118.  
  119.                 if (node != nullptr)
  120.                 {
  121.                     node->Get()->Load(file.substr(0, file.length() - 4) + std::string(".dll"));
  122.  
  123.                     void* create = node->Get()->GetProc<void*>("CreateBehavior");
  124.                     void* name = node->Get()->GetProc<void*>("GetName");
  125.                     const char* (*fn)() = (const char* (*)())name;
  126.                     const char* pluginName = (*fn)();
  127.  
  128.                     Engine::ComponentId componentID = Engine::ComponentTypeId::Get(pluginName);
  129.  
  130.                     Engine::ComponentInterface* componentInterface = new Engine::ComponentInterface();
  131.                     componentInterface->CreateComponent = (Engine::Component * (*)())create;
  132.  
  133.                     delete Engine::ComponentFactory::GetScriptComponentManager().find(componentID)->second;
  134.                     Engine::ComponentFactory::GetScriptComponentManager().find(componentID)->second = componentInterface;
  135.  
  136.                     // Loop through ALL serialized components, create new ones on given entities and deserialize them
  137.                     for (auto it = tmp.begin(); it != tmp.end(); it++)
  138.                     {
  139.                         Engine::Component* component = componentInterface->CreateComponent();
  140.                         component->Deserialize(it->second);
  141.                         it->first->AddComponent(componentID, component);
  142.                     }
  143.                 }
  144.             }
  145.         }
  146.         break;
  147.  
  148.     default:
  149.         mLog->Print("Compiler", "Error: Invalid Compiler - Can't Compiler Any File!");
  150.         break;
  151.     }
  152. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement