Author Topic: build/clean workspace using custom makefiles  (Read 4769 times)

Offline grischka

  • Multiple posting newcomer
  • *
  • Posts: 12
« Last Edit: October 28, 2008, 07:37:28 pm by grischka »

Offline gryphon

  • Multiple posting newcomer
  • *
  • Posts: 15
Re: build/clean workspace using custom makefiles
« Reply #1 on: November 02, 2008, 08:16:00 pm »
Nice patch. In fact it is very similar to one I've been working on for more complete custom makefile support (project files added based on dependencies etc.) I took your patch and merged it with a useful subset of what I've been doing and added it here.
https://developer.berlios.de/patch/?func=detailpatch&patch_id=2583&group_id=5358
You can also view it below.

Essentially this unifies how clean and build are treated placing all code into one place. This patch (like yours) removes more code than it adds. I used your patch as the basis for this one to make it easy for you to see what is different. I tested this with several complex custom make projects and building codeblocks itself.

The primary difference between how this works and the current code is in how workspaces are handled. With this patch Clean Workspace and Build Workspace are unchanged (but now use common code), but Rebuild workspace actually rebuilds each target in turn, rather than calling Clean Workspace followed by Build Workspace. Personally I believe this is how it should work and the code is again shared common code and trivial.

Please try this patch and let me know what you think of it.

Gryphon

Code
Index: src/plugins/compilergcc/compilergcc.h
===================================================================
--- src/plugins/compilergcc/compilergcc.h (revision 5296)
+++ src/plugins/compilergcc/compilergcc.h (working copy)
@@ -52,6 +52,7 @@
 {
     bsNone = 0,
     bsProjectPreBuild,
+    bsTargetClean,
     bsTargetPreBuild,
     bsTargetBuild,
     bsTargetPostBuild,
@@ -67,6 +68,12 @@
     ltAll       = 0xff
 };
 
+enum BuildAction
+{
+    baClean = 0,
+    baBuild
+};
+
 class wxTimerEvent;
 class wxComboBox;
 class wxStaticText;
@@ -187,13 +194,15 @@
         void LogMessage(const wxString& message, CompilerLineType lt = cltNormal, LogTarget log = ltAll, bool forceErrorColour = false, bool isTitle = false, bool updateProgress = false);
         void SaveBuildLog();
         void InitBuildLog(bool workspaceBuild);
-        void PrintBanner(cbProject* prj = 0, ProjectBuildTarget* target = 0);
-        bool UseMake(ProjectBuildTarget* target = 0);
+        void PrintBanner(BuildAction action, cbProject* prj = 0, ProjectBuildTarget* target = 0);
+        bool UseMake(cbProject *prj = 0);
         bool CompilerValid(ProjectBuildTarget* target = 0);
         ProjectBuildTarget* GetBuildTargetForFile(ProjectFile* pf);
         ProjectBuildTarget* GetBuildTargetForFile(const wxString& file);
         wxString GetMakeCommandFor(MakeCommand cmd, cbProject* project, ProjectBuildTarget* target);
-        int DoBuild();
+        int DoBuild(bool clean, bool build);
+        int DoBuild(const wxString& target, bool clean, bool build);
+        int DoWorkspaceBuild(const wxString& target, bool clean, bool build);
         void CalculateWorkspaceDependencies(wxArrayInt& deps);
         void CalculateProjectDependencies(cbProject* prj, wxArrayInt& deps);
         void InitBuildState(BuildJob job, const wxString& target);
@@ -276,6 +285,9 @@
         BuildState m_NextBuildState;
         cbProject* m_pLastBuildingProject;
         ProjectBuildTarget* m_pLastBuildingTarget;
+        // Clean and Build
+        bool m_Clean;
+        bool m_Build;
         // to decide if post-build steps should run
         bool m_RunTargetPostBuild;
         bool m_RunProjectPostBuild;
Index: src/plugins/compilergcc/compilergcc.cpp
===================================================================
--- src/plugins/compilergcc/compilergcc.cpp (revision 5296)
+++ src/plugins/compilergcc/compilergcc.cpp (working copy)
@@ -363,6 +363,8 @@
     m_pLastBuildingTarget = 0;
     m_RunTargetPostBuild = false;
     m_RunProjectPostBuild = false;
+    m_Clean = false;
+    m_Build = false;
     m_DeleteTempMakefile = true;
     m_IsWorkspaceOperation = false;
 
@@ -967,6 +969,9 @@
     if (m_IsWorkspaceOperation)
         return;
 
+    if (IsProcessRunning())
+        return;
+
     CodeBlocksLogEvent evtSwitch(cbEVT_SWITCH_TO_LOG_WINDOW, m_Log);
     Manager::Get()->ProcessEvent(evtSwitch);
 
@@ -1475,15 +1480,16 @@
     m_LastTempMakefile = _T("");
 }
 
-bool CompilerGCC::UseMake(ProjectBuildTarget* target)
+bool CompilerGCC::UseMake(cbProject *prj)
 {
-    if (!m_Project)
+    if (!prj)
+        prj = m_Project;
+    if (!prj)
         return false;
-    wxString idx = m_Project->GetCompilerID();
+    wxString idx = prj->GetCompilerID();
     if (CompilerFactory::GetCompiler(idx))
     {
-        if (m_Project->IsMakefileCustom())
-            return true;
+        return prj->IsMakefileCustom();
     }
     return false;
 }
@@ -1553,7 +1559,7 @@
         }
     }
 
-    PrintBanner();
+    PrintBanner(baBuild);
     wxSetWorkingDirectory(m_Project->GetBasePath());
 
     if (UseMake())
@@ -1572,7 +1578,7 @@
     return true;
 }
 
-void CompilerGCC::PrintBanner(cbProject* prj, ProjectBuildTarget* target)
+void CompilerGCC::PrintBanner(BuildAction action, cbProject* prj, ProjectBuildTarget* target)
 {
     if (!CompilerValid(target))
         return;
@@ -1583,8 +1589,14 @@
     if (!prj)
         prj = m_Project;
 
+    wxString Action = _("Build");
+    if (action ==  baClean)
+    {
+        Action = _("Clean");
+    }
     wxString banner;
-    banner.Printf(_("-------------- Build: %s in %s ---------------"),
+    banner.Printf(_("-------------- %s: %s in %s ---------------"),
+                    Action.c_str(),
                     target
                         ? target->GetTitle().c_str()
                         : _("\"no target\""),
@@ -1922,63 +1934,7 @@
 
 int CompilerGCC::Clean(const wxString& target)
 {
-    wxString realTarget = target;
-    if (realTarget.IsEmpty())
-        realTarget = GetTargetString();
-    if (realTarget.IsEmpty())
-        return -1;
-
-    if (!m_IsWorkspaceOperation)
-    {
-        DoPrepareQueue();
-    }
-
-    wxArrayString clean;
-    if (!m_Project)
-    {
-        if (!Manager::Get()->GetEditorManager()->GetActiveEditor())
-          return -1;
-
-        DirectCommands dc(this, CompilerFactory::GetDefaultCompiler(), 0, m_PageIndex);
-        clean = dc.GetCleanSingleFileCommand(Manager::Get()->GetEditorManager()->GetActiveEditor()->GetFilename());
-        DoClean(clean);
-        Manager::Get()->GetLogManager()->Log(_("Cleaned object and output files"), m_PageIndex);
-    }
-
-    // generate build jobs
-    PreprocessJob(m_Project, realTarget);
-    if (m_BuildJobTargetsList.empty())
-        return -1;
-
-    // loop all jobs and add them in the queue
-    while (!m_BuildJobTargetsList.empty())
-    {
-        BuildJobTarget bjt = GetNextJob();
-        wxSetWorkingDirectory(bjt.project->GetBasePath());
-        ProjectBuildTarget* bt = bjt.project->GetBuildTarget(bjt.targetName);
-        CompilerFactory::GetCompiler(bt->GetCompilerID())->Init(bjt.project);
-
-        if (UseMake())
-        {
-            wxString cmd = GetMakeCommandFor(mcClean, bjt.project, bt);
-            m_CommandQueue.Add(new CompilerCommand(cmd, wxEmptyString, bjt.project, bt));
-            return DoRunQueue();
-        }
-        else
-        {
-            DirectCommands dc(this, CompilerFactory::GetCompiler(bt->GetCompilerID()), bjt.project, m_PageIndex);
-            clean = dc.GetCleanCommands(bt, true);
-            DoClean(clean);
-            Manager::Get()->GetLogManager()->Log(F(_("Cleaned \"%s - %s\""), bjt.project->GetTitle().c_str(), bt ? bt->GetTitle().c_str() : _("<all targets>")), m_PageIndex);
-        }
-    }
-
-    if (!m_IsWorkspaceOperation)
-    {
-        Manager::Get()->GetLogManager()->Log(_("Done."), m_PageIndex);
-//        Manager::Get()->GetLogManager()->Close();
-    }
-    return 0;
+    return DoBuild(target, true, false);
 }
 
 int CompilerGCC::DistClean(const wxString& target)
@@ -2005,7 +1961,7 @@
         wxSetWorkingDirectory(m_Project->GetBasePath());
     CompilerFactory::GetCompiler(m_CompilerId)->Init(m_Project);
 
-    if (UseMake(target))
+    if (UseMake())
     {
         wxString cmd = GetMakeCommandFor(mcDistClean, m_Project, target);
         m_CommandQueue.Add(new CompilerCommand(cmd, wxEmptyString, m_Project, target));
@@ -2099,6 +2055,7 @@
         case bsNone: return _T("bsNone");
         case bsProjectPreBuild: return _T("bsProjectPreBuild");
         case bsTargetPreBuild: return _T("bsTargetPreBuild");
+        case bsTargetClean: return _T("bsTargetClean");
         case bsTargetBuild: return _T("bsTargetBuild");
         case bsTargetPostBuild: return _T("bsTargetPostBuild");
         case bsProjectPostBuild: return _T("bsProjectPostBuild");
@@ -2109,10 +2066,42 @@
 
 BuildState CompilerGCC::GetNextStateBasedOnJob()
 {
+    bool clean = m_Clean;
+    bool build = m_Build;
+
     switch (m_BuildState)
     {
         case bsProjectPreBuild: return bsTargetPreBuild;
-        case bsTargetPreBuild: return bsTargetBuild;
+        {
+            if (clean && !build)
+            {
+                return bsTargetClean;
+            }
+            return bsTargetPreBuild;
+        }
+
+        case bsTargetPreBuild:
+        {
+            if (clean)
+            {
+                return bsTargetClean;
+            }
+            else if (build)
+            {
+                return bsTargetBuild;
+            }
+            return bsTargetPostBuild;
+        }
+
+        case bsTargetClean:
+        {
+            if (build)
+            {
+                return bsTargetBuild;
+            }
+            return bsTargetPostBuild;
+        }
+
         case bsTargetBuild: return bsTargetPostBuild;
 
         // advance target in the project
@@ -2127,7 +2116,12 @@
                     // same project, switch target
                     bj = GetNextJob(); // remove job from queue
                     m_BuildingTargetName = bj.targetName;
-                    return bsTargetPreBuild; // switching targets
+                    // switching targets
+                    if (clean && !build)
+                    {
+                        return bsTargetClean;
+                    }
+                    return bsTargetPreBuild;
                 }
                 // switch project
                 return bsProjectPostBuild;
@@ -2144,7 +2138,7 @@
             if (m_pBuildingProject)
                 m_pBuildingProject->SetCurrentlyCompilingTarget(0);
             m_NextBuildState = bsProjectPreBuild;
-            return DoBuild() >= 0 ? bsProjectPreBuild : bsNone;
+            return DoBuild(clean, build) >= 0 ? bsProjectPreBuild : bsNone;
         }
 
         default:
@@ -2182,10 +2176,10 @@
             SwitchCompiler(bt->GetCompilerID());
 
 //        Manager::Get()->GetLogManager()->Log(m_PageIndex, _T("CHANGE *****> m_BuildState=%s, m_NextBuildState=%s, m_pBuildingProject=%p, bt=%p (%p)"), StateToString(m_BuildState).c_str(), StateToString(m_NextBuildState).c_str(), m_pBuildingProject, bt, m_pLastBuildingTarget);
-        if ((m_pBuildingProject == m_pLastBuildingProject && m_NextBuildState == bsTargetPreBuild) || m_NextBuildState == bsProjectPreBuild)
-        {
-            PrintBanner(m_pBuildingProject, bt);
-        }
+//        if ((m_pBuildingProject == m_pLastBuildingProject && m_NextBuildState == bsTargetPreBuild) || m_NextBuildState == bsProjectPreBuild)
+//        {
+//            PrintBanner(baBuild, m_pBuildingProject, bt);
+//        }
 
         // avoid calling Compiler::Init() twice below, if it is the same compiler
         Compiler* initCompiler = 0;
@@ -2238,10 +2232,39 @@
             break;
         }
 
+        case bsTargetClean:
+        {
+            PrintBanner(baClean, m_pBuildingProject, bt);
+
+            if (UseMake(m_pBuildingProject))
+            {
+                wxString cmd = GetMakeCommandFor(mcClean, m_pBuildingProject, bt);
+                cmds.Add(cmd);
+            }
+            else
+            {
+                wxArrayString clean = dc.GetCleanCommands(bt, true);
+                DoClean(clean);
+                Manager::Get()->GetLogManager()->Log(F(_("Cleaned \"%s - %s\""), m_pBuildingProject->GetTitle().c_str(), bt ? bt->GetTitle().c_str() : _("<all targets>")), m_PageIndex);
+            }
+            break;
+        }
+
         case bsTargetBuild:
         {
+            PrintBanner(baBuild, m_pBuildingProject, bt);
+
             // run target build
-            cmds = dc.GetCompileCommands(bt);
+            if (UseMake(m_pBuildingProject))
+            {
+                wxString cmd = GetMakeCommandFor(mcBuild, m_pBuildingProject, bt);
+                cmds.Add(cmd);
+            }
+            else
+            {
+                cmds = dc.GetCompileCommands(bt);
+            }
+
             bool hasCommands = cmds.GetCount();
             m_RunTargetPostBuild = hasCommands;
             m_RunProjectPostBuild = hasCommands;
@@ -2412,7 +2435,7 @@
     return m_BuildJobTargetsList.front();
 }
 
-int CompilerGCC::DoBuild()
+int CompilerGCC::DoBuild(bool clean, bool build)
 {
     BuildJobTarget bj = GetNextJob();
 
@@ -2431,19 +2454,14 @@
     m_pBuildingProject = bj.project;
     m_BuildingTargetName = bj.targetName;
     ProjectBuildTarget* bt = bj.project->GetBuildTarget(bj.targetName);
+
+    m_Clean = clean;
+    m_Build = build;
+
     if (!bt || !CompilerValid(bt))
         return -2;
 
-    wxString cmd;
-    if (UseMake())
-    {
-        wxString cmd = GetMakeCommandFor(mcBuild, bj.project, bt);
-        m_CommandQueue.Add(new CompilerCommand(cmd, wxEmptyString, bj.project, bt));
-    }
-    else
-    {
-        BuildStateManagement();
-    }
+    BuildStateManagement();
     return 0;
 }
 
@@ -2507,7 +2525,7 @@
     }
 }
 
-int CompilerGCC::Build(const wxString& target)
+int CompilerGCC::DoBuild(const wxString& target, bool clean, bool build)
 {
     wxString realTarget = target;
     if (realTarget.IsEmpty())
@@ -2527,47 +2545,32 @@
     if (realTarget.IsEmpty())
         return -1;
 
-    DoClearErrors();
-    InitBuildLog(false);
-
     if (!m_IsWorkspaceOperation)
+    {
+        DoClearErrors();
+        InitBuildLog(false);
+//    if (!m_IsWorkspaceOperation)
         DoPrepareQueue();
+    }
 
-    if (UseMake())
+    PreprocessJob(m_Project, realTarget);
+    if (m_BuildJobTargetsList.empty())
     {
-        // make sure all project files are saved
-        if (m_Project && !m_Project->SaveAllFiles())
-            Manager::Get()->GetLogManager()->Log(_("Could not save all files..."));
-
-        // generate build jobs
-        PreprocessJob(m_Project, realTarget);
-        if (m_BuildJobTargetsList.empty())
-            return -1;
-
-        // loop all jobs and add them in the queue
-        while (!m_BuildJobTargetsList.empty())
-        {
-            BuildJobTarget bjt = GetNextJob();
-            ProjectBuildTarget* bt = bjt.project->GetBuildTarget(bjt.targetName);
-            if (bt)
-            {
-                wxString cmd = GetMakeCommandFor(mcBuild, bjt.project, bt);
-                m_CommandQueue.Add(new CompilerCommand(cmd, wxEmptyString, bjt.project, bt));
-            }
-        }
+        return -1;
     }
-    else
+    InitBuildState(bjProject, realTarget);
+    if (DoBuild(clean, build))
     {
-        PreprocessJob(m_Project, realTarget);
-        if (m_BuildJobTargetsList.empty())
-            return -1;
-        InitBuildState(bjProject, realTarget);
-        if (DoBuild())
-            return -2;
+        return -2;
     }
     return DoRunQueue();
 }
 
+int CompilerGCC::Build(const wxString& target)
+{
+    return DoBuild(target, false, true);
+}
+
 int CompilerGCC::Build(ProjectBuildTarget* target)
 {
     return Build(target ? target->GetTitle() : _T(""));
@@ -2580,65 +2583,10 @@
 
 int CompilerGCC::Rebuild(const wxString& target)
 {
-    wxString realTarget = target;
-    if (realTarget.IsEmpty())
-        realTarget = GetTargetString();
-    if (realTarget.IsEmpty())
-        return -1;
-
-    if (!StopRunningDebugger())
-        return -1;
-
-    // make sure all project files are saved
-    if (m_Project && !m_Project->SaveAllFiles())
-        Manager::Get()->GetLogManager()->Log(_("Could not save all files..."));
-
-    if (!m_IsWorkspaceOperation)
-        DoPrepareQueue();
-
-//    Manager::Get()->GetMacrosManager()->Reset();
-
-    Compiler* cmp = CompilerFactory::GetCompiler(m_CompilerId);
-    if (cmp)
-        cmp->Init(m_Project);
-
-    if (UseMake())
-    {
-        CompilerCommand* cc;
-        wxString cmd;
-
-        // generate build jobs
-        PreprocessJob(m_Project, realTarget);
-        if (m_BuildJobTargetsList.empty())
-            return -1;
-
-        // loop all jobs and add them in the queue
-        while (!m_BuildJobTargetsList.empty())
-        {
-            BuildJobTarget bjt = GetNextJob();
-            ProjectBuildTarget* bt = bjt.project->GetBuildTarget(bjt.targetName);
-            if (bt)
-            {
-                cmd = GetMakeCommandFor(mcClean, bjt.project, bt);
-                cc = new CompilerCommand(cmd, wxEmptyString, bjt.project, bt);
-                m_CommandQueue.Add(cc);
-
-                cmd = GetMakeCommandFor(mcBuild, bjt.project, bt);
-                cc = new CompilerCommand(cmd, wxEmptyString, bjt.project, bt);
-                cc->mustWait = true; // wait for clean commands to finish
-                m_CommandQueue.Add(cc);
-            }
-        }
-    }
-    else
-    {
-        Clean(realTarget);
-        Build(realTarget);
-    }
-    return DoRunQueue();
+    return DoBuild(target, true, true);
 }
 
-int CompilerGCC::BuildWorkspace(const wxString& target)
+int CompilerGCC::DoWorkspaceBuild(const wxString& target, bool clean, bool build)
 {
     wxString realTarget = target;
     if (realTarget.IsEmpty())
@@ -2674,44 +2622,24 @@
 
     InitBuildState(bjWorkspace, realTarget);
 
-    DoBuild();
+    DoBuild(clean,build);
     m_IsWorkspaceOperation = false;
     return DoRunQueue();
 }
 
+int CompilerGCC::BuildWorkspace(const wxString& target)
+{
+    return DoWorkspaceBuild(target, false, true);
+}
+
 int CompilerGCC::RebuildWorkspace(const wxString& target)
 {
-    int ret = CleanWorkspace(target);
-    if (ret != 0)
-        return ret;
-    ret = BuildWorkspace(target);
-    return ret;
+    return DoWorkspaceBuild(target, true, true);
 }
 
 int CompilerGCC::CleanWorkspace(const wxString& target)
 {
-    if (!StopRunningDebugger())
-        return -1;
-
-    DoPrepareQueue();
-    ClearLog();
-    m_IsWorkspaceOperation = true;
-
-    ResetBuildState();
-    cbProject* bak = m_Project;
-    ProjectsArray* arr = Manager::Get()->GetProjectManager()->GetProjects();
-    for (size_t i = 0; i < arr->GetCount(); ++i)
-    {
-        m_Project = arr->Item(i);
-        Clean(target);
-    }
-    ResetBuildState();
-    m_Project = bak;
-
-    m_IsWorkspaceOperation = false;
-    Manager::Get()->GetLogManager()->Log(_("Done."), m_PageIndex);
-//    Manager::Get()->GetLogManager()->Close();
-    return 0;
+    return DoWorkspaceBuild(target, true, false);
 }
 
 int CompilerGCC::KillProcess()
@@ -2811,7 +2739,7 @@
 
     ProjectFile* pf = m_Project ? m_Project->GetFileByFilename(file, true, false) : 0;
     ProjectBuildTarget* bt = GetBuildTargetForFile(pf);
-    bool useMake = UseMake(bt);
+    bool useMake = UseMake();
 
     if (!pf)
     {

Offline grischka

  • Multiple posting newcomer
  • *
  • Posts: 12
Re: build/clean workspace using custom makefiles
« Reply #2 on: November 07, 2008, 05:51:32 am »
Quote from: gryphon
Essentially this unifies how clean and build are treated placing all code into one place ...

Except that build commands are added to a queue while clean commands are still run immediately.  Well, as long as it works.

Quote from: gryphon
... but Rebuild workspace actually rebuilds each target in turn, rather than calling Clean Workspace followed by Build Workspace. Personally I believe this is how it should work ...

I don't quite see why but interestingly different behavior anyway.

Quote from: gryphon
Please try this patch and let me know what you think of it.

Good, of course.  Now, could somebody with svn-access commit this, please?