1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  */
5 
6 #ifndef COMPILERGCC_H
7 #define COMPILERGCC_H
8 
9 #include <wx/choice.h>
10 #include <wx/dynarray.h>
11 #include <wx/process.h>
12 #include <wx/timer.h>
13 
14 #include <queue>
15 
16 #include <cbplugin.h>
17 #include <cbproject.h>
18 #include <compileoptionsbase.h>
19 #include <compilerfactory.h>
20 #include <logger.h>
21 #include <sdk_events.h>
22 #include <settings.h> // SDK
23 
24 #include "compilermessages.h"
25 #include "compilererrors.h"
26 #include "compiler_defs.h"
27 
28 enum CompilerOptionsType
29 {
30     cotGlobal = 0,
31     cotProjectOrTarget
32 };
33 
34 enum ErrorType
35 {
36     etNone = 0,
37     etError,
38     etWarning
39 };
40 
41 /// Helper enum for compiler's state. This state signifies the kind of build the compiler is working on.
42 enum BuildJob
43 {
44     bjIdle = 0, ///< Not currently building
45     bjWorkspace, ///< Building the workspace
46     bjProject, ///< Building the project
47     bjTarget ///< Building the target
48 };
49 
50 /// Defines the current state of the compiler.
51 enum BuildState
52 {
53     bsNone = 0,
54     bsProjectPreBuild,
55     bsTargetClean,
56     bsTargetPreBuild,
57     bsTargetBuild,
58     bsTargetPostBuild,
59     bsTargetDone,
60     bsProjectPostBuild,
61     bsProjectDone
62 };
63 
64 enum LogTarget
65 {
66     ltMessages  = 0x01,
67     ltFile      = 0x02,
68 
69     ltAll       = 0xff
70 };
71 
72 enum BuildAction
73 {
74     baClean = 0,
75     baBuild,
76     baRun,
77     baBuildFile
78 };
79 
80 class cbArtProvider;
81 class wxComboBox;
82 class wxGauge;
83 class wxStaticText;
84 
85 class BuildLogger;
86 class PipedProcess;
87 
88 class CompilerGCC : public cbCompilerPlugin
89 {
90     public:
91         CompilerGCC();
92         virtual ~CompilerGCC();
93 
94         virtual void OnAttach();
95         virtual void OnRelease(bool appShutDown);
96         virtual void BuildMenu(wxMenuBar* menuBar); // offer for menu space by host
97         virtual void BuildModuleMenu(const ModuleType type, wxMenu* menu, const FileTreeData* data = 0); // offer for menu space by a module
98         virtual bool BuildToolBar(wxToolBar* toolBar);
GetToolBarPriority()99         virtual int GetToolBarPriority() { return 1; }
100 
101         virtual int Run(ProjectBuildTarget* target = 0L);
102         virtual int Run(const wxString& target);
103         virtual int RunSingleFile(const wxString& filename);
104         virtual int Clean(const wxString& target);
105         virtual int Clean(ProjectBuildTarget* target = 0L);
106         virtual int DistClean(ProjectBuildTarget* target = 0L);
107         virtual int DistClean(const wxString& target);
108         virtual int Build(ProjectBuildTarget* target = 0L);
109         virtual int Build(const wxString& target);
110         virtual int Rebuild(ProjectBuildTarget* target = 0L);
111         virtual int Rebuild(const wxString& target);
112         virtual int CleanWorkspace(const wxString& target = wxEmptyString);
113         virtual int BuildWorkspace(const wxString& target = wxEmptyString);
114         virtual int RebuildWorkspace(const wxString& target = wxEmptyString);
115         virtual int CompileFile(const wxString& file);
116         virtual int CompileFileWithoutProject(const wxString& file);
117         virtual int CompileFileDefault(cbProject* project, ProjectFile* pf, ProjectBuildTarget* bt);
118         virtual int KillProcess();
119         virtual bool IsRunning() const;
GetExitCode()120         virtual int GetExitCode() const { return m_LastExitCode; }
121         virtual int Configure(cbProject* project, ProjectBuildTarget* target, wxWindow *parent);
122 
GetConfigurationPriority()123         int GetConfigurationPriority() const { return 0; }
GetConfigurationGroup()124         int GetConfigurationGroup() const { return cgCompiler; }
125         cbConfigurationPanel* GetConfigurationPanel(wxWindow* parent);
126 
127         bool IsValidTarget(const wxString& target) const;
128 
129         void SwitchCompiler(const wxString& id);
130         const wxString& GetCurrentCompilerID();
131 
132         // used to read from the external process
133         void OnIdle(wxIdleEvent& event);
134         void OnTimer(wxTimerEvent& event);
135 
136         void OnCompile(wxCommandEvent& event);
137         void OnCompileFile(wxCommandEvent& event);
138         void OnCleanFile(wxCommandEvent& event);
139         void OnRebuild(wxCommandEvent& event);
140         void OnCompileAll(wxCommandEvent& event);
141         void OnRebuildAll(wxCommandEvent& event);
142         void OnCleanAll(wxCommandEvent& event);
143         void OnClean(wxCommandEvent& event);
144         void OnRun(wxCommandEvent& event);
145         void OnProjectCompilerOptions(wxCommandEvent& event);
146         void OnTargetCompilerOptions(wxCommandEvent& event);
147         void OnCompileAndRun(wxCommandEvent& event);
148         void OnKillProcess(wxCommandEvent& event);
149         void OnSelectTarget(wxCommandEvent& event);
150         void OnNextError(wxCommandEvent& event);
151         void OnPreviousError(wxCommandEvent& event);
152         void OnClearErrors(wxCommandEvent& event);
153         void OnUpdateUI(wxUpdateUIEvent& event);
154         void OnConfig(wxCommandEvent& event);
155     private:
156         friend class CompilerOptionsDlg;
157 
158         void Dispatcher(wxCommandEvent& event);
159         void TextURL(wxTextUrlEvent& event);
160 
161         bool StopRunningDebugger();
162 
163         bool ReAllocProcesses();
164         void AllocProcesses();
165         void FreeProcesses();
166         bool IsProcessRunning(int idx = -1) const;
167         int GetNextAvailableProcessIndex() const;
168         int GetActiveProcessCount() const;
169 
170         void SetupEnvironment();
171         void OnProjectActivated(CodeBlocksEvent& event);
172         void OnProjectLoaded(CodeBlocksEvent& event);
173         void OnProjectUnloaded(CodeBlocksEvent& event);
174         void OnWorkspaceClosed(CodeBlocksEvent& event);
175         void OnCompileFileRequest(CodeBlocksEvent& event);
176         void OnGCCOutput(CodeBlocksEvent& event);
177         void OnGCCError(CodeBlocksEvent& event);
178         void OnGCCTerminated(CodeBlocksEvent& event);
179         void OnJobEnd(size_t procIndex, int exitCode);
180 
181         void SaveOptions();
182         void LoadOptions();
183         void DoRegisterCompilers();
184         void DoPrepareQueue(bool clearLog);
185         void NotifyCleanProject(const wxString& target);
186         void NotifyCleanWorkspace();
187         int DoRunQueue();
188         void DoClearTargetMenu();
189         void DoRecreateTargetMenu();
190         void DoUpdateTargetMenu(int targetIndex);
191         FileTreeData* DoSwitchProjectTemporarily();
192         ProjectBuildTarget* DoAskForTarget();
193         int DoGUIAskForTarget();
194         void ClearLog(bool switchToLog);
195         void PrepareCompileFile(wxFileName& file);
196         void PrepareCompileFilePM(wxFileName& file);
197         bool CheckProject();
198         void AskForActiveProject();
199         void StartCompileFile(wxFileName file);
200         void DoGotoNextError();
201         void DoGotoPreviousError();
202         void DoClearErrors();
203         wxString ProjectMakefile();
204         void AddOutputLine(const wxString& output, bool forceErrorColour = false);
205         void LogWarningOrError(CompilerLineType lt, cbProject* prj, const wxString& filename, const wxString& line, const wxString& msg);
206         void LogMessage(const wxString& message, CompilerLineType lt = cltNormal, LogTarget log = ltAll, bool forceErrorColour = false, bool isTitle = false, bool updateProgress = false);
207         void SaveBuildLog();
208         void InitBuildLog(bool workspaceBuild);
209         void PrintBanner(BuildAction action, cbProject* prj = 0, ProjectBuildTarget* target = 0);
210         bool UseMake(cbProject* project = 0);
211 
212         struct CompilerValidResult
213         {
214             Compiler *compiler = nullptr;
215             bool isValid = false;
216         };
217         CompilerValidResult CompilerValid(ProjectBuildTarget* target = 0);
218         void PrintInvalidCompiler(ProjectBuildTarget *target, Compiler *compiler, const wxString &finalMessage);
219         ProjectBuildTarget* GetBuildTargetForFile(ProjectFile* pf);
220         wxString GetMakeCommandFor(MakeCommand cmd, cbProject* project, ProjectBuildTarget* target);
221         int DoBuild(bool clean, bool build);
222         int DoBuild(const wxString& target, bool clean, bool build, bool clearLog=true);
223         int DoWorkspaceBuild(const wxString& target, bool clean, bool build, bool clearLog=true);
224         void CalculateWorkspaceDependencies(wxArrayInt& deps);
225         void CalculateProjectDependencies(cbProject* prj, wxArrayInt& deps);
226         void InitBuildState(BuildJob job, const wxString& target);
227         void ResetBuildState();
228         void BuildStateManagement(); ///< This uses m_BuildJob.
229         BuildState GetNextStateBasedOnJob();
230         void NotifyJobDone(bool showNothingToBeDone = false);
231 
232         // wxArrayString from DirectCommands
233         void AddToCommandQueue(const wxArrayString& commands);
234 
235         int GetTargetIndexFromName(cbProject* prj, const wxString& name);
236         void UpdateProjectTargets(cbProject* project);
237         wxString GetTargetString(int index = -1);
238         void DoClean(const wxArrayString& commands);
239         bool DoCleanWithMake(ProjectBuildTarget* bt);
240 
241         // active target, currently building project or active project
242         wxString GetCurrentCompilerID(ProjectBuildTarget* target);
243 
244         wxString GetErrWarnStr();
245         wxString GetMinSecStr();
246 
247         // when a build is about to start, a preprocessing step runs
248         // in PreprocessJob(), that fills m_BuildJobTargetsList with
249         // BuildJobTarget. It is a simple pair of project->target which
250         // are to be built in order
251         struct BuildJobTarget
252         {
projectBuildJobTarget253             BuildJobTarget(cbProject* p = 0, const wxString& n = wxEmptyString) : project(p), targetName(n) {}
254             cbProject* project;
255             wxString targetName;
256         };
257         typedef std::queue<BuildJobTarget> BuildJobTargetsList;
258         BuildJobTargetsList m_BuildJobTargetsList;
259 
260         void ExpandTargets(cbProject* project, const wxString& targetName, wxArrayString& result);
261         void PreprocessJob(cbProject* project, const wxString& targetName);
262         BuildJobTarget GetNextJob();
263         const BuildJobTarget& PeekNextJob();
264 
265         struct CompilerProcess
266         {
267             PipedProcess* pProcess;
268             wxString      OutputFile;
269             long int      PID;
270         };
271         typedef std::vector<CompilerProcess> CompilerProcessList;
272         CompilerProcessList m_CompilerProcessList;
273 
274         wxArrayString       m_Targets; // list of targets contained in the active project
275         int                 m_RealTargetsStartIndex;
276         int                 m_RealTargetIndex;
277 
278         CompilerQueue       m_CommandQueue;
279         wxString            m_CompilerId;
280         int                 m_PageIndex;
281         int                 m_ListPageIndex;
282         wxMenu*             m_Menu;
283         wxMenu*             m_TargetMenu;
284         int                 m_TargetIndex;
285         wxMenu*             m_pErrorsMenu;
286         cbProject*          m_pProject;
287         wxToolBar*          m_pTbar;
288         wxTimer             m_timerIdleWakeUp;
289         BuildLogger*        m_pLog;
290         CompilerMessages*   m_pListLog;
291         wxChoice*           m_pToolTarget;
292         bool                m_RunAfterCompile;
293         wxString            m_CdRun;
294         wxString            m_RunCmd;
295         int                 m_LastExitCode;
296         CompilerErrors      m_Errors;
297         wxString            m_LastTargetName;
298         bool                m_NotifiedMaxErrors;
299         wxLongLong          m_StartTime;
300 
301         // build state management
302         cbProject*          m_pBuildingProject; // +
303         wxString            m_BuildingTargetName; // +
304         BuildJob            m_BuildJob;
305         BuildState          m_BuildState;
306         BuildState          m_NextBuildState;
307         cbProject*          m_pLastBuildingProject;
308         ProjectBuildTarget* m_pLastBuildingTarget;
309         // Clean and Build
310         bool m_Clean;
311         bool m_Build;
312         // if set and we are reaching NotifyJobDone, we know that we have finished the
313         // last step in a clean/build (aka rebuild)-process and send the cbEVT_COMPILER_FINISHED
314         bool m_LastBuildStep;
315         // to decide if post-build steps should run
316         bool m_RunTargetPostBuild;
317         bool m_RunProjectPostBuild;
318 
319         bool m_IsWorkspaceOperation; // true for workspace commands
320 
321         wxString   m_BuildLogFilename;
322         wxString   m_BuildLogTitle;
323         wxString   m_BuildLogContents;
324         wxDateTime m_BuildStartTime;
325 
326         // build progress
327         size_t m_MaxProgress;
328         size_t m_CurrentProgress;
329         bool   m_LogBuildProgressPercentage;
330 
331         cbArtProvider *m_pArtProvider;
332 
333         DECLARE_EVENT_TABLE()
334 };
335 
336 #endif // COMPILERGCC_H
337