Code::Blocks  SVN r11506
compilergcc.cpp
Go to the documentation of this file.
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  * $Revision: 11499 $
6  * $Id: compilergcc.cpp 11499 2018-10-07 09:45:50Z fuscated $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/plugins/compilergcc/compilergcc.cpp $
8  */
9 
10 #include <sdk.h>
11 
12 #include <wx/frame.h> // GetMenuBar
13 #include <wx/gauge.h> // Needs to be before compilergcc.h if NOPCH on wxMSW
14 #include <wx/listctrl.h>
15 #include <wx/xrc/xmlres.h>
16 #include <wx/sizer.h>
17 #include <wx/button.h>
18 #include <wx/stattext.h>
19 #include <wx/statline.h>
20 #include <wx/ffile.h>
21 #include <wx/utils.h>
22 #include <wx/uri.h>
23 #include <wx/xml/xml.h>
24 
25 #ifndef CB_PRECOMP
26  #include <wx/app.h>
27  #include <wx/toolbar.h>
28 #endif
29 
30 #include <prep.h>
31 #include <manager.h>
32 #include <sdk_events.h>
33 #include <pipedprocess.h>
34 #include <configmanager.h>
36 #include <debuggermanager.h>
38 #include <logmanager.h>
39 #include <macrosmanager.h>
40 #include <projectmanager.h>
41 #include <editormanager.h>
42 #include <scriptingmanager.h>
43 #include <configurationpanel.h>
44 #include <pluginmanager.h>
45 #include <cbeditor.h>
46 #include <annoyingdialog.h>
47 #include <filefilters.h>
48 #include <infowindow.h>
49 
50 #include "compilergcc.h"
51 #include "compileroptionsdlg.h"
52 #include "directcommands.h"
53 #include "globals.h"
54 #include "cbworkspace.h"
55 #include "cbstyledtextctrl.h"
56 
57 
58 #include "compilerMINGW.h"
59 #include "compilerGNUARM.h"
60 #include "compilerMSVC.h"
61 #include "compilerMSVC8.h"
62 #include "compilerMSVC10.h"
63 #include "compilerOW.h"
64 #include "compilerGNUARM.h"
65 #include "compilerCYGWIN.h"
66 #include "compilerLCC.h"
67 #include "compilerKeilC51.h"
68 #include "compilerIAR.h"
69 #include "compilerICC.h"
70 #include "compilerGDC.h"
71 #include "compilerGNUFortran.h"
72 #include "compilerG95.h"
73 #include "compilerXML.h"
74 
76 
77 namespace ScriptBindings
78 {
79  static int gBuildLogId = -1;
80 
81  // global funcs
82  void gBuildLog(const wxString& msg)
83  {
84  Manager::Get()->GetLogManager()->Log(msg, gBuildLogId);
85  }
86 }
87 
88 const int idBuildLog = wxNewId();
89 
91 {
94 public:
96 
97  BuildLogger() : TextCtrlLogger(true), panel(0), sizer(0), progress(0) {}
98 
99  void UpdateSettings() override
100  {
102 
103  style[caption].SetAlignment(wxTEXT_ALIGNMENT_DEFAULT);
104  style[caption].SetFont(style[error].GetFont());
105  style[error].SetFont(style[info].GetFont());
106  }
107 
108  wxWindow* CreateControl(wxWindow* parent) override
109  {
110  panel = new wxPanel(parent);
111 
113  control->SetId(idBuildLog);
114 
115  sizer = new wxBoxSizer(wxVERTICAL);
116  sizer->Add(control, 1, wxEXPAND, 0);
117  panel->SetSizer(sizer);
118 
119  return panel;
120  }
121 
123  {
124  if (!progress)
125  {
126  progress = new wxGauge(panel, -1, 0, wxDefaultPosition, wxSize(-1, 12));
127  sizer->Add(progress, 0, wxEXPAND);
128  sizer->Layout();
129  }
130  }
131 
133  {
134  if (progress)
135  {
136  sizer->Detach(progress);
137  progress->Destroy();
138  progress = 0;
139  sizer->Layout();
140  }
141  }
142 
143  void OpenLink(long urlStart, long urlEnd)
144  {
145  if (!control)
146  return;
147  wxString url = control->GetRange(urlStart, urlEnd);
148  if (platform::windows && url.StartsWith(_T("file://")))
149  url.Remove(0, 7);
151  if (p)
152  p->OpenFile(url);
153  else
155  }
156 };
157 
158 namespace
159 {
160  PluginRegistrant<CompilerGCC> reg(_T("Compiler"));
161 
162  static const wxString strCONSOLE_RUNNER(platform::windows ? _T("cb_console_runner.exe") : _T("cb_console_runner"));
163  static const wxString strSLASH(_T("/"));
164  static const wxString strSPACE(_T(" "));
165  static const wxString strQUOTE(platform::windows ? _T("\"") : _T("'"));
166 }
167 
168 // menu IDS
169 // just because we don't know other plugins' used identifiers,
170 // we use wxNewId() to generate a guaranteed unique ID ;), instead of enum
171 // (don't forget that, especially in a plugin)
172 int idTimerPollCompiler = XRCID("idTimerPollCompiler");
173 int idMenuCompile = XRCID("idCompilerMenuCompile");
180 int idMenuCompileFile = XRCID("idCompilerMenuCompileFile");
183 int idMenuRebuild = XRCID("idCompilerMenuRebuild");
186 int idMenuClean = XRCID("idCompilerMenuClean");
187 int idMenuBuildWorkspace = XRCID("idCompilerMenuBuildWorkspace");
188 int idMenuRebuildWorkspace = XRCID("idCompilerMenuRebuildWorkspace");
189 int idMenuCleanWorkspace = XRCID("idCompilerMenuCleanWorkspace");
192 int idMenuCompileAndRun = XRCID("idCompilerMenuCompileAndRun");
193 int idMenuRun = XRCID("idCompilerMenuRun");
194 int idMenuKillProcess = XRCID("idCompilerMenuKillProcess");
195 int idMenuSelectTarget = XRCID("idCompilerMenuSelectTarget");
196 
197 // Limit the number of menu items to try to make them all visible on the screen.
198 // Scrolling menus is not the best user experience.
199 const int maxTargetInMenus = 40;
200 int idMenuSelectTargetOther[maxTargetInMenus]; // initialized in ctor
201 int idMenuSelectTargetDialog = XRCID("idMenuSelectTargetDialog");
203 
204 int idMenuNextError = XRCID("idCompilerMenuNextError");
205 int idMenuPreviousError = XRCID("idCompilerMenuPreviousError");
206 int idMenuClearErrors = XRCID("idCompilerMenuClearErrors");
207 int idMenuSettings = XRCID("idCompilerMenuSettings");
208 
209 int idToolTarget = XRCID("idToolTarget");
210 
212 
213 BEGIN_EVENT_TABLE(CompilerGCC, cbCompilerPlugin)
214  EVT_UPDATE_UI(idMenuCompile, CompilerGCC::OnUpdateUI)
223  EVT_UPDATE_UI(idMenuRebuild, CompilerGCC::OnUpdateUI)
228  EVT_UPDATE_UI(idMenuClean, CompilerGCC::OnUpdateUI)
233  EVT_UPDATE_UI(idMenuRun, CompilerGCC::OnUpdateUI)
240  EVT_UPDATE_UI(idToolTarget, CompilerGCC::OnUpdateUI)
242 
243  EVT_IDLE( CompilerGCC::OnIdle)
245 
268 
269  EVT_TEXT_URL(idBuildLog, CompilerGCC::TextURL)
270 
273 
277 END_EVENT_TABLE()
278 
280  m_RealTargetsStartIndex(0),
281  m_RealTargetIndex(0),
282  m_PageIndex(-1),
283  m_ListPageIndex(-1),
284  m_Menu(0L),
285  m_TargetMenu(0L),
286  m_TargetIndex(-1),
287  m_pErrorsMenu(0L),
288  m_pProject(0L),
289  m_pTbar(0L),
290  m_pLog(0L),
291  m_pListLog(0L),
292  m_pToolTarget(0L),
293  m_RunAfterCompile(false),
294  m_LastExitCode(0),
295  m_NotifiedMaxErrors(false),
296  m_pBuildingProject(0),
297  m_BuildJob(bjIdle),
298  m_NextBuildState(bsNone),
299  m_pLastBuildingProject(0),
300  m_pLastBuildingTarget(0),
301  m_Clean(false),
302  m_Build(false),
303  m_LastBuildStep(true),
304  m_RunTargetPostBuild(false),
305  m_RunProjectPostBuild(false),
306  m_IsWorkspaceOperation(false),
307  m_LogBuildProgressPercentage(false)
308 {
309  if (!Manager::LoadResource(_T("compiler.zip")))
310  NotifyMissingFile(_T("compiler.zip"));
311 }
312 
314 {
315 }
316 
318 {
319  // reset all vars
320  m_RealTargetsStartIndex = 0;
321  m_RealTargetIndex = 0;
322  m_PageIndex = -1;
323  m_ListPageIndex = -1;
324  m_Menu = 0L;
325  m_TargetMenu = 0L;
326  m_TargetIndex = -1;
327  m_pErrorsMenu = 0L;
328  m_pProject = 0L;
329  m_pTbar = 0L;
330  m_pLog = 0L;
331  m_pListLog = 0L;
332  m_pToolTarget = 0L;
333  m_RunAfterCompile = false;
334  m_LastExitCode = 0;
335  m_NotifiedMaxErrors = false;
336  m_pBuildingProject = 0;
337  m_BuildJob = bjIdle;
338  m_NextBuildState = bsNone;
339  m_pLastBuildingProject = 0;
340  m_pLastBuildingTarget = 0;
341  m_RunTargetPostBuild = false;
342  m_RunProjectPostBuild = false;
343  m_Clean = false;
344  m_Build = false;
345  m_LastBuildStep = true;
346  m_IsWorkspaceOperation = false;
347 
348  m_timerIdleWakeUp.SetOwner(this, idTimerPollCompiler);
349 
350  for (int i = 0; i < maxTargetInMenus; ++i)
352 
353  DoRegisterCompilers();
354 
355  AllocProcesses();
356 
357  LogManager* msgMan = Manager::Get()->GetLogManager();
358 
359  // create compiler's log
360  m_pLog = new BuildLogger();
361  m_PageIndex = msgMan->SetLog(m_pLog);
362  msgMan->Slot(m_PageIndex).title = _("Build log");
363 // msgMan->SetBatchBuildLog(m_PageIndex);
364  // set log image
365  wxString prefix = ConfigManager::GetDataFolder() + _T("/images/");
366  wxBitmap* bmp = new wxBitmap(cbLoadBitmap(prefix + _T("misc_16x16.png"), wxBITMAP_TYPE_PNG));
367  msgMan->Slot(m_PageIndex).icon = bmp;
368 
369  // create warnings/errors log
370  wxArrayString titles;
371  wxArrayInt widths;
372  titles.Add(_("File"));
373  titles.Add(_("Line"));
374  titles.Add(_("Message"));
375  widths.Add(128);
376  widths.Add(48);
377  widths.Add(640);
378 
379  m_pListLog = new CompilerMessages(titles, widths);
380  m_pListLog->SetCompilerErrors(&m_Errors);
381  m_ListPageIndex = msgMan->SetLog(m_pListLog);
382  msgMan->Slot(m_ListPageIndex).title = _("Build messages");
383  // set log image
384  bmp = new wxBitmap(cbLoadBitmap(prefix + _T("flag_16x16.png"), wxBITMAP_TYPE_PNG));
385  msgMan->Slot(m_ListPageIndex).icon = bmp;
386 
387  CodeBlocksLogEvent evtAdd1(cbEVT_ADD_LOG_WINDOW, m_pLog, msgMan->Slot(m_PageIndex).title, msgMan->Slot(m_PageIndex).icon);
388  Manager::Get()->ProcessEvent(evtAdd1);
389  if (!Manager::IsBatchBuild())
390  {
391  CodeBlocksLogEvent evtAdd2(cbEVT_ADD_LOG_WINDOW, m_pListLog, msgMan->Slot(m_ListPageIndex).title, msgMan->Slot(m_ListPageIndex).icon);
392  Manager::Get()->ProcessEvent(evtAdd2);
393  }
394 
395  m_LogBuildProgressPercentage = Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/build_progress/percentage"), false);
396  bool hasBuildProg = Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/build_progress/bar"), false);
397  if (hasBuildProg)
398  m_pLog->AddBuildProgressBar();
399 
400  // set default compiler for new projects
401  CompilerFactory::SetDefaultCompiler(Manager::Get()->GetConfigManager(_T("compiler"))->Read(_T("/default_compiler"), _T("gcc")));
402  LoadOptions();
403 
404  // register compiler's script functions
405  // make sure the VM is initialized
407  if (SquirrelVM::GetVMPtr())
408  {
409  ScriptBindings::gBuildLogId = m_PageIndex;
410  SqPlus::RegisterGlobal(ScriptBindings::gBuildLog, "LogBuild");
411  }
412  else
414 
415  // register event sink
421 
423 }
424 
425 void CompilerGCC::OnRelease(bool appShutDown)
426 {
427  // disable script functions
429 
430  SaveOptions();
431  Manager::Get()->GetConfigManager(_T("compiler"))->Write(_T("/default_compiler"), CompilerFactory::GetDefaultCompilerID());
432  if (Manager::Get()->GetLogManager())
433  {
434  // for batch builds, the log is deleted by the manager
435  if (!Manager::IsBatchBuild())
436  {
438  Manager::Get()->ProcessEvent(evt);
439  }
440  m_pLog = 0;
441 
443  m_pListLog->DestroyControls();
444  Manager::Get()->ProcessEvent(evt);
445  m_pListLog = 0;
446  }
447 
448  // let wx handle this on shutdown ( if we return here Valgrind will be sad :'( )
449  if (!appShutDown)
450  DoClearTargetMenu();
451 
452  m_timerIdleWakeUp.Stop();
453 
454  FreeProcesses();
455 
457 }
458 
460 {
461  cbConfigurationDialog dlg(Manager::Get()->GetAppWindow(), wxID_ANY, _("Project build options"));
462  cbConfigurationPanel* panel = new CompilerOptionsDlg(&dlg, this, project, target);
463  panel->SetParentDialog(&dlg);
464  dlg.AttachConfigurationPanel(panel);
465  PlaceWindow(&dlg);
466  if (dlg.ShowModal() == wxID_OK)
467  {
468  SaveOptions();
470 
471  bool hasBuildProg = Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/build_progress/bar"), false);
472  if (hasBuildProg)
473  m_pLog->AddBuildProgressBar();
474  else
475  m_pLog->RemoveBuildProgressBar();
476  }
477 // delete panel;
478  return 0;
479 }
480 
482 {
483  CompilerOptionsDlg* dlg = new CompilerOptionsDlg(parent, this, 0, 0);
484  return dlg;
485 }
486 
487 void CompilerGCC::OnConfig(cb_unused wxCommandEvent& event)
488 {
489  Configure(NULL);
490 }
491 
493 {
494  if (!IsAttached())
495  return;
496 
497  m_Menu = Manager::Get()->LoadMenu(_T("compiler_menu"),true);
498 
499  // target selection menu
500  wxMenuItem *tmpitem=m_Menu->FindItem(idMenuSelectTarget,NULL);
501  m_TargetMenu = tmpitem ? tmpitem->GetSubMenu() : new wxMenu(_T(""));
502  DoRecreateTargetMenu();
503  //m_Menu->Append(idMenuSelectTarget, _("Select target..."), m_TargetMenu);
504 
505  // ok, now, where do we insert?
506  // three possibilities here:
507  // a) locate "Debug" menu and insert before it
508  // b) locate "Project" menu and insert after it
509  // c) if not found (?), insert at pos 5
510  int finalPos = 5;
511  int projMenuPos = menuBar->FindMenu(_("&Debug"));
512  if (projMenuPos != wxNOT_FOUND)
513  finalPos = projMenuPos;
514  else
515  {
516  projMenuPos = menuBar->FindMenu(_("&Project"));
517  if (projMenuPos != wxNOT_FOUND)
518  finalPos = projMenuPos + 1;
519  }
520  menuBar->Insert(finalPos, m_Menu, _("&Build"));
521 
522  // now add some entries in Project menu
523  projMenuPos = menuBar->FindMenu(_("&Project"));
524  if (projMenuPos != wxNOT_FOUND)
525  {
526  wxMenu* prj = menuBar->GetMenu(projMenuPos);
527  // look if we have a "Properties" item. If yes, we 'll insert
528  // before it, else we 'll just append...
529  size_t propsPos = prj->GetMenuItemCount(); // append
530  const int idMenuProjectProperties = prj->FindItem(_("Properties..."));
531  if (idMenuProjectProperties != wxNOT_FOUND)
532  prj->FindChildItem(idMenuProjectProperties, &propsPos);
533  prj->Insert(propsPos, idMenuProjectCompilerOptions, _("Build options..."), _("Set the project's build options"));
534  prj->InsertSeparator(propsPos);
535  }
536 }
537 
538 void CompilerGCC::BuildModuleMenu(const ModuleType type, wxMenu* menu, const FileTreeData* data)
539 {
540  if (!IsAttached())
541  return;
542  // we 're only interested in project manager's menus
543  if (type != mtProjectManager || !menu)
544  return;
545 
546  if (!CheckProject())
547  return;
548 
549  if (!data || data->GetKind() == FileTreeData::ftdkUndefined)
550  {
551  // popup menu in empty space in ProjectManager
552  if (menu->GetMenuItemCount() > 0)
553  menu->AppendSeparator();
554  menu->Append(idMenuBuildWorkspace, _("Build workspace"));
555  menu->Append(idMenuRebuildWorkspace, _("Rebuild workspace"));
556  menu->Append(idMenuCleanWorkspace, _("Clean workspace"));
557 
558  if (IsRunning())
559  {
560  menu->Enable(idMenuBuildWorkspace, false);
561  menu->Enable(idMenuRebuildWorkspace, false);
562  menu->Enable(idMenuCleanWorkspace, false);
563  }
564  }
565  else if (data && data->GetKind() == FileTreeData::ftdkProject)
566  {
567  // popup menu on a project
568  wxMenuItem* itm = menu->FindItemByPosition(menu->GetMenuItemCount() - 1);
569  if (itm && !itm->IsSeparator())
570  menu->AppendSeparator();
571  menu->Append(idMenuCompileFromProjectManager, _("Build"));
572  menu->Append(idMenuRebuildFromProjectManager, _("Rebuild"));
573  menu->Append(idMenuCleanFromProjectManager, _("Clean"));
574  menu->AppendSeparator();
575  menu->Append(idMenuProjectCompilerOptionsFromProjectManager, _("Build options..."));
576 
577  cbPlugin *otherRunning = Manager::Get()->GetProjectManager()->GetIsRunning();
578  if (IsRunning() || (otherRunning && otherRunning != this))
579  {
584  }
585  }
586  else if (data && data->GetKind() == FileTreeData::ftdkFile)
587  {
589  if (ft == ftSource || ft == ftHeader || ft == ftTemplateSource)
590  {
591  // popup menu on a compilable file
592  menu->AppendSeparator();
593  menu->Append(idMenuCompileFileFromProjectManager, _("Build file"));
594  menu->Append(idMenuCleanFileFromProjectManager, _("Clean file"));
595  if (IsRunning())
596  {
599  }
600  }
601  }
602 }
603 
605 {
606  if (!IsAttached() || !toolBar)
607  return false;
608 
609  m_pTbar = toolBar;
610  wxString my_16x16 = Manager::isToolBar16x16(toolBar) ? _T("_16x16") : _T("");
611  Manager::Get()->AddonToolBar(toolBar,_T("compiler_toolbar")+my_16x16);
612  m_pToolTarget = XRCCTRL(*toolBar, "idToolTarget", wxChoice);
613  toolBar->Realize();
614  toolBar->SetInitialSize();
615  DoRecreateTargetMenu(); // make sure the tool target combo is up-to-date
616  return true;
617 }
618 
620 {
621  int eventId = event.GetId();
622 
623 // Manager::Get()->GetMessageManager()->Log(wxT("Dispatcher")));
624 
625  if (eventId == idMenuRun)
626  OnRun(event);
627  else if (eventId == idMenuCompileAndRun)
628  OnCompileAndRun(event);
629  else if (eventId == idMenuCompile)
630  OnCompile(event);
631  else if (eventId == idMenuCompileFromProjectManager)
632  OnCompile(event);
633  else if (eventId == idMenuCompileFile)
634  OnCompileFile(event);
635  else if (eventId == idMenuCompileFileFromProjectManager)
636  OnCompileFile(event);
637  else if (eventId == idMenuCleanFileFromProjectManager)
638  OnCleanFile(event);
639  else if (eventId == idMenuRebuild)
640  OnRebuild(event);
641  else if (eventId == idMenuRebuildFromProjectManager)
642  OnRebuild(event);
643  else if (eventId == idMenuBuildWorkspace)
644  OnCompileAll(event);
645  else if (eventId == idMenuRebuildWorkspace)
646  OnRebuildAll(event);
647  else if ( eventId == idMenuProjectCompilerOptions
649  OnProjectCompilerOptions(event);
650  else if (eventId == idMenuTargetCompilerOptions)
651  OnTargetCompilerOptions(event);
652  else if (eventId == idMenuClean)
653  OnClean(event);
654  else if (eventId == idMenuCleanWorkspace)
655  OnCleanAll(event);
656  else if (eventId == idMenuCleanFromProjectManager)
657  OnClean(event);
658  else if (eventId == idMenuKillProcess)
659  OnKillProcess(event);
660  else if (eventId == idMenuNextError)
661  OnNextError(event);
662  else if (eventId == idMenuPreviousError)
663  OnPreviousError(event);
664  else if (eventId == idMenuClearErrors)
665  OnClearErrors(event);
666  else if (eventId == idMenuSettings)
667  OnConfig(event);
668 
669  // Return focus to current editor
670  cbEditor* ed = 0;
671  if ( (ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor()) )
672  ed->GetControl()->SetFocus();
673 }
674 
676 {
677  if (event.GetId() == idBuildLog && event.GetMouseEvent().ButtonDown(wxMOUSE_BTN_LEFT))
678  m_pLog->OpenLink(event.GetURLStart(), event.GetURLEnd());
679  else
680  event.Skip();
681 }
682 
684 {
685  // Special case so "No Compiler" is valid, but I'm not sure there is
686  // any valid reason to continue with this function.
687  // If we do continue there are wx3 asserts, because of empty paths.
688  if (m_CompilerId == wxT("null"))
689  return;
690 
691  Compiler* compiler = CompilerFactory::GetCompiler(m_CompilerId);
692  if (!compiler)
693  return;
694 
695  wxString currentPath;
696  if ( !wxGetEnv(_T("PATH"), &currentPath) )
697  {
698  InfoWindow::Display(_("Environment error"),
699  _("Could not read the PATH environment variable!\n"
700  "This can't be good. There may be problems running\n"
701  "system commands and the application might not behave\n"
702  "the way it was designed to..."),
703  15000, 3000);
704  return;
705  }
706 
707 // Manager::Get()->GetLogManager()->DebugLogError(_T("PATH environment:"));
708 // Manager::Get()->GetLogManager()->DebugLogError(currentPath);
709 
710  const wxString pathApp = platform::windows ? _T(";") : _T(":");
711  const wxString pathSep = wxFileName::GetPathSeparator(); // "\" or "/"
712  const bool caseSens = !(platform::windows);
713 
714  wxString cApp = compiler->GetPrograms().C;
716  wxArrayString extraPaths = compiler->GetExtraPaths();
717  wxString extraPathsBinPath(wxEmptyString);
718 
719  // Get configured masterpath, expand macros and remove trailing separators
720  wxString masterPath = compiler->GetMasterPath();
721 
722  Manager::Get()->GetMacrosManager()->ReplaceMacros(masterPath);
723  while ( !masterPath.IsEmpty()
724  && ((masterPath.Last() == '\\') || (masterPath.Last() == '/')) )
725  masterPath.RemoveLast();
726 
727  // Compile new PATH list...
728  wxPathList pathList;
729  // [1] Pre-pend "master path" and "master path\bin"...
730  if ( !masterPath.Trim().IsEmpty() ) // Would be very bad, if it *is* empty
731  {
732  pathList.Add(masterPath + pathSep + _T("bin"));
733  pathList.Add(masterPath); // in case there is no "bin" sub-folder
734  }
735  // [2] Get configured extrapath(s), expand macros and remove trailing separators
736  for (size_t i=0; i<extraPaths.GetCount(); ++i)
737  {
738  wxString extraPath = extraPaths[i];
740  while (extraPath.Last() == '\\' || extraPath.Last() == '/')
741  extraPath.RemoveLast();
742  if (!extraPath.Trim().IsEmpty())
743  {
744  // Remember, if we found the C application in the extra path's:
745  if ( extraPathsBinPath.IsEmpty()
746  && wxFileExists(extraPath + pathSep + cApp ) )
747  extraPathsBinPath = extraPath;
748  pathList.Add(extraPath);
749  }
750  }
751  // [3] Append what has already been in the PATH envvar...
752  // If we do it this way, paths are automatically normalized and doubles are removed
753  wxPathList pathArray;
754  pathArray.AddEnvList(_T("PATH"));
755  pathList.Add(pathArray);
756 
757  // Try to locate the path to the C compiler:
758  wxString binPath = pathList.FindAbsoluteValidPath(cApp);
759 
760  // It seems, under Win32, the above command doesn't search in paths with spaces...
761  // Look directly for the file in question in masterPath if it is not already found.
762  if ( binPath.IsEmpty()
763  || (pathList.Index(wxPathOnly(binPath), caseSens)==wxNOT_FOUND) )
764  {
765  if (wxFileExists(masterPath + pathSep + _T("bin") + pathSep + cApp))
766  binPath = masterPath + pathSep + _T("bin");
767  else if (wxFileExists(masterPath + pathSep + cApp))
768  binPath = masterPath;
769  else if (!extraPathsBinPath.IsEmpty())
770  binPath = extraPathsBinPath;
771  }
772  else
773  binPath = wxPathOnly(binPath);
774 
775  /* TODO (jens#1#): Is the above correct ?
776  Or should we search in the whole systempath (pathList in this case) for the executable? */
777  // Try again...
778  if ((binPath.IsEmpty() || (pathList.Index(binPath, caseSens)==wxNOT_FOUND)))
779  {
780  InfoWindow::Display(_("Environment error"),
781  _("Can't find compiler executable in your configured search path's for ") + compiler->GetName() + _T('\n'));
782  Manager::Get()->GetLogManager()->DebugLogError(F(_T("Can't find compiler executable in your configured search path's (for %s)..."), compiler->GetName().wx_str()));
783 
784  return; // Failed to locate compiler executable in path's as provided!
785  }
786 
787  // Convert the pathList into a string to apply.
788  wxString envPath(binPath); // make sure the bin-path we found is in front
789  // and remove it from pathList
790  pathList.Remove(binPath);
791  for (size_t i=0; i<pathList.GetCount(); ++i)
792  envPath += ( pathApp + pathList[i] );
793 
794 // Manager::Get()->GetLogManager()->DebugLogError(_T("Updating compiler PATH environment:"));
795 // Manager::Get()->GetLogManager()->DebugLogError(envPath);
796 
797  if ( !wxSetEnv(_T("PATH"), envPath) )
798  {
799  InfoWindow::Display(_("Environment error"),
800  _("Can't set PATH environment variable! That's bad and the compiler might not work."));
801  Manager::Get()->GetLogManager()->DebugLog(_T("Can't set PATH environment variable! That's bad and the compiler might not work.\n"));
802  }
803 }
804 
806 {
808  // is the debugger running?
809  if (dbg && dbg->IsRunning())
810  {
811  int ret = cbMessageBox(_("The debugger must be stopped to do a (re-)build.\n"
812  "Do you want to stop the debugger now?"),
813  _("Information"),
815  switch (ret)
816  {
817  case wxID_YES:
818  {
819  m_pLog->Clear();
820  Manager::Get()->GetLogManager()->Log(_("Stopping debugger..."), m_PageIndex);
821  dbg->Stop();
822  break;
823  }
824  case wxID_NO: // fall through
825  default:
826  Manager::Get()->GetLogManager()->Log(_("Aborting (re-)build."), m_PageIndex);
827  return false;
828  }
829  }
830 
831  return true;
832 }
833 
835 {
836  // save compiler sets
838 }
839 
841 {
842  // load compiler sets
844 }
845 
847 {
848  bool nonPlatComp = Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/non_plat_comp"), false);
849 
850  // register built-in compilers
852  if (platform::windows || nonPlatComp)
853  {
864  }
869  if (platform::windows || platform::Linux || nonPlatComp)
871 
872  // register pure XML compilers
873  // user paths first
874  wxDir dir;
875  wxString filename;
876  wxArrayString compilers;
877  wxString path = ConfigManager::GetFolder(sdDataUser) + wxT("/compilers/");
878  if (wxDirExists(path) && dir.Open(path))
879  {
880  bool ok = dir.GetFirst(&filename, wxT("compiler_*.xml"), wxDIR_FILES);
881  while (ok)
882  {
883  compilers.Add(path + filename);
884  ok = dir.GetNext(&filename);
885  }
886  }
887  // global paths next
888  path = ConfigManager::GetFolder(sdDataGlobal) + wxT("/compilers/");
889  if (wxDirExists(path) && dir.Open(path))
890  {
891  bool ok = dir.GetFirst(&filename, wxT("compiler_*.xml"), wxDIR_FILES);
892  while (ok)
893  {
894  for (size_t i = 0; i < compilers.GetCount(); ++i)
895  {
896  if (compilers[i].EndsWith(filename))
897  {
898  ok = false;
899  break;
900  }
901  }
902  if (ok) // user compilers of the same name take precedence
903  compilers.Add(path + filename);
904  ok = dir.GetNext(&filename);
905  }
906  }
907  for (size_t i = 0; i < compilers.GetCount(); ++i)
908  {
909  wxXmlDocument compiler;
910  if (!compiler.Load(compilers[i]) || compiler.GetRoot()->GetName() != wxT("CodeBlocks_compiler"))
911  Manager::Get()->GetLogManager()->Log(_("Error: Invalid Code::Blocks compiler definition '") + compilers[i] + wxT("'."));
912  else
913  {
914  bool val = true;
915  wxString test;
916  if (!nonPlatComp && compiler.GetRoot()->GetAttribute(wxT("platform"), &test))
917  {
918  if (test == wxT("windows"))
919  val = platform::windows;
920  else if (test == wxT("macosx"))
921  val = platform::macosx;
922  else if (test == wxT("linux"))
923  val = platform::Linux;
924  else if (test == wxT("freebsd"))
925  val = platform::freebsd;
926  else if (test == wxT("netbsd"))
927  val = platform::netbsd;
928  else if (test == wxT("openbsd"))
929  val = platform::openbsd;
930  else if (test == wxT("darwin"))
931  val = platform::darwin;
932  else if (test == wxT("solaris"))
933  val = platform::solaris;
934  else if (test == wxT("unix"))
935  val = platform::Unix;
936  }
937  if (val)
939  new CompilerXML(compiler.GetRoot()->GetAttribute(wxT("name"), wxEmptyString),
940  compiler.GetRoot()->GetAttribute(wxT("id"), wxEmptyString),
941  compilers[i]));
942  }
943  }
944 
945  // register (if any) user-copies of built-in compilers
947 }
948 
950 {
951  static wxString def = wxEmptyString;//_T("gcc");
952  return CompilerFactory::GetCompiler(m_CompilerId) ? m_CompilerId : def;
953 }
954 
956 {
958  return;
959 
960  m_CompilerId = id;
961 
962  SetupEnvironment();
963 }
964 
966 {
967  // we 're called from a menu in ProjectManager
968  // let's check the selected project...
969  FileTreeData* ftd = DoSwitchProjectTemporarily();
970  ProjectFile* pf = ftd->GetProjectFile();
971  if (!pf)
972  return;
973 
974  file = pf->file;
975  CheckProject();
976 }
977 
979 {
981  if (ed)
982  {
983  // make sure it is saved
984  ed->Save();
985  file.Assign(ed->GetFilename());
986  }
987 
988  // Now activate the project this file belongs to
989  ProjectFile* pf = ed->GetProjectFile();
990  if (pf)
991  {
992  cbProject* CurProject = pf->GetParentProject();
993  if (CurProject)
994  {
995  Manager::Get()->GetProjectManager()->SetProject(CurProject, true);
996  CheckProject();
997  }
998  }
999 }
1000 
1002 {
1003  AskForActiveProject();
1004 
1005  // switch compiler for the project (if needed)
1006  if ( m_pProject && m_pProject->GetCompilerID() != m_CompilerId)
1007  SwitchCompiler(m_pProject->GetCompilerID());
1008  // switch compiler for single file (if needed)
1009  else if (!m_pProject && m_CompilerId != CompilerFactory::GetDefaultCompilerID())
1010  SwitchCompiler(CompilerFactory::GetDefaultCompilerID());
1011 
1012  return (m_pProject != 0L);
1013 }
1014 
1016 {
1017  m_pProject = m_pBuildingProject
1018  ? m_pBuildingProject
1020 }
1021 
1023 {
1024  if (m_pProject)
1025  {
1026  if (!m_pProject->SaveAllFiles())
1027  Manager::Get()->GetLogManager()->Log(_("Could not save all files..."));
1028 
1029  file.MakeRelativeTo(m_pProject->GetBasePath());
1030  }
1031 
1032  wxString fname = file.GetFullPath();
1033  if (!fname.IsEmpty())
1034  {
1036  Manager::Get()->ProcessEvent(evtSwitch);
1037 
1038  CompileFile( UnixFilename(fname) );
1039  }
1040 }
1041 
1043 {
1044  AskForActiveProject();
1045 
1046  if (!m_pProject)
1047  return wxEmptyString;
1048 
1049  return m_pProject->GetMakefile();
1050 }
1051 
1052 void CompilerGCC::ClearLog(bool switchToLog)
1053 {
1054  if (m_IsWorkspaceOperation)
1055  return;
1056 
1057  if (IsProcessRunning())
1058  return;
1059 
1060  if (switchToLog)
1061  {
1063  Manager::Get()->ProcessEvent(evtSwitch);
1064  }
1065 
1066  if (m_pLog)
1067  m_pLog->Clear();
1068 }
1069 
1071 {
1073  wxTreeCtrl* tree = manager->GetUI().GetTree();
1074  wxTreeItemId sel = manager->GetUI().GetTreeSelection();
1075  FileTreeData* ftd = sel.IsOk() ? (FileTreeData*)tree->GetItemData(sel) : nullptr;
1076  if (!ftd)
1077  return nullptr;
1078  // We're not rebuilding the tree, so the ftd pointer is still valid after the call.
1079  Manager::Get()->GetProjectManager()->SetProject(ftd->GetProject(), false);
1080  AskForActiveProject();
1081 
1082  return ftd;
1083 }
1084 
1086 {
1087  ProjectBuildTarget* bt = m_pBuildingProject ? m_pBuildingProject->GetBuildTarget(GetTargetIndexFromName(m_pBuildingProject, m_BuildingTargetName)) : 0;
1088  m_CurrentProgress = 0;
1089  m_MaxProgress = 0;
1090  bool isLink = false;
1091  bool mustWait = false;
1092  size_t count = commands.GetCount();
1093  for (size_t i = 0; i < count; ++i)
1094  {
1095  wxString cmd = commands[i];
1096 
1097  // logging
1099  {
1100  cmd.Remove(0, COMPILER_SIMPLE_LOG.Length());
1101  m_CommandQueue.Add(new CompilerCommand(wxEmptyString, cmd, m_pBuildingProject, bt));
1102  }
1103  // compiler change
1104  else if (cmd.StartsWith(COMPILER_TARGET_CHANGE))
1105  {
1106  ; // nothing to do for now
1107  }
1108  else if (cmd.StartsWith(COMPILER_WAIT))
1109  {
1110  mustWait = true;
1111  }
1112  else if (cmd.StartsWith(COMPILER_WAIT_LINK))
1113  {
1114  isLink = true;
1115  }
1116  else
1117  {
1118  // compiler command
1119  CompilerCommand* p = new CompilerCommand(cmd, wxEmptyString, m_pBuildingProject, bt);
1120  p->mustWait = mustWait;
1121  p->isLink = isLink;
1122  m_CommandQueue.Add(p);
1123  isLink = false;
1124  mustWait = false;
1125  ++m_MaxProgress;
1126  }
1127  }
1128 
1129  if (m_pLog->progress)
1130  {
1131  m_pLog->progress->SetRange(m_MaxProgress);
1132  m_pLog->progress->SetValue(m_CurrentProgress);
1133  }
1134 }
1135 
1137 {
1138  // create the parallel processes array
1139  size_t parallel_processes = Manager::Get()->GetConfigManager(_T("compiler"))->ReadInt(_T("/parallel_processes"), 0);
1140  if (parallel_processes == 0)
1141  parallel_processes = std::max(1, wxThread::GetCPUCount());
1142  m_CompilerProcessList.resize(parallel_processes);
1143  for (CompilerProcess &p : m_CompilerProcessList)
1144  {
1145  p.pProcess = nullptr;
1146  p.PID = 0;
1147  }
1148 }
1149 
1151 {
1152  // free the parallel processes array
1153  for (CompilerProcess &p : m_CompilerProcessList)
1154  Delete(p.pProcess);
1155  m_CompilerProcessList.clear();
1156 }
1157 
1159 {
1160  FreeProcesses();
1161  AllocProcesses();
1162  return true;
1163 }
1164 
1166 {
1167  // invalid process index
1168  if (m_CompilerProcessList.empty() || idx >= (int)m_CompilerProcessList.size())
1169  return false;
1170 
1171  // specific process
1172  if (idx >= 0)
1173  return (m_CompilerProcessList.at(static_cast<size_t>(idx)).pProcess != 0);
1174 
1175  // any process (idx = -1)
1176  for (const CompilerProcess &p : m_CompilerProcessList)
1177  {
1178  if (p.pProcess)
1179  return true;
1180  }
1181  return false;
1182 }
1183 
1185 {
1186  for (size_t i = 0; i < m_CompilerProcessList.size(); ++i)
1187  {
1188  const CompilerProcess &p = m_CompilerProcessList[i];
1189  if (!p.pProcess && p.PID == 0)
1190  return i;
1191  }
1192  return -1;
1193 }
1194 
1196 {
1197  int count = 0;
1198  for (const CompilerProcess &p : m_CompilerProcessList)
1199  {
1200  if (p.pProcess)
1201  ++count;
1202  }
1203  return count;
1204 }
1205 
1207 {
1208  // leave if already running
1209  int procIndex = GetNextAvailableProcessIndex();
1210  if (procIndex == -1)
1211  return -2;
1212 
1213  // if next command is linking and compilation is still in progress, abort
1214  if (IsProcessRunning())
1215  {
1216  CompilerCommand* cmd = m_CommandQueue.Peek();
1217  if (cmd && (cmd->mustWait || cmd->isLink))
1218  return -3;
1219  }
1220 
1221  CompilerCommand* cmd = m_CommandQueue.Next();
1222  if (!cmd)
1223  {
1224  if (IsProcessRunning())
1225  return 0;
1226 
1227  while (1)
1228  {
1229  // keep switching build states until we have commands to run or reach end of states
1230  BuildStateManagement();
1231  cmd = m_CommandQueue.Next();
1232  if (!cmd && m_BuildState == bsNone && m_NextBuildState == bsNone)
1233  {
1234  NotifyJobDone(true);
1235  ResetBuildState();
1236  if (m_RunAfterCompile)
1237  {
1238  m_RunAfterCompile = false;
1239  if (Run() == 0)
1240  DoRunQueue();
1241  }
1242  return 0;
1243  }
1244 
1245  if (cmd)
1246  break;
1247  }
1248  }
1249 
1250  wxString dir = cmd->dir;
1251 
1252  // log file
1253  bool hasLog = Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/save_html_build_log"), false);
1254  bool saveFull = Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/save_html_build_log/full_command_line"), false);
1255  if (hasLog)
1256  {
1257  if (!cmd->command.IsEmpty() && saveFull)
1258  LogMessage(cmd->command, cltNormal, ltFile);
1259  else if (!cmd->message.IsEmpty() && !saveFull)
1260  LogMessage(cmd->message, cltNormal, ltFile);
1261  }
1262 
1263  // log message
1264  if (!cmd->message.IsEmpty())
1265  LogMessage(cmd->message, cltNormal, ltMessages, false, false, true);
1266 
1267  if (cmd->command.IsEmpty())
1268  {
1269  int ret = DoRunQueue();
1270  delete cmd;
1271  return ret;
1272  }
1273  else if (cmd->command.StartsWith(_T("#run_script")))
1274  {
1275  // special "run_script" command
1276  wxString script = cmd->command.AfterFirst(_T(' '));
1277  if (script.IsEmpty())
1278  {
1279  wxString msg = _("The #run_script command must be followed by a script filename");
1280  LogMessage(msg, cltError);
1281  }
1282  else
1283  {
1285  wxString msg = _("Running script: ") + script;
1286  LogMessage(msg);
1287 
1289  }
1290  int ret = DoRunQueue();
1291  delete cmd;
1292  return ret;
1293  }
1294 
1295  wxString oldLibPath; // keep old PATH/LD_LIBRARY_PATH contents
1296  wxGetEnv(CB_LIBRARY_ENVVAR, &oldLibPath);
1297 
1298  bool pipe = true;
1299  int flags = wxEXEC_ASYNC | wxEXEC_MAKE_GROUP_LEADER;
1300  if (cmd->isRun)
1301  {
1302  pipe = false; // no need to pipe output channels...
1303  flags |= wxEXEC_NOHIDE;
1304  dir = m_CdRun;
1305 
1306  // setup dynamic linker path
1307  wxString newLibPath = cbGetDynamicLinkerPathForTarget(m_pProject, cmd->target);
1308  newLibPath = cbMergeLibPaths(oldLibPath, newLibPath);
1309  wxSetEnv(CB_LIBRARY_ENVVAR, newLibPath);
1310  }
1311 
1312  // special shell used only for build commands
1313  if (!cmd->isRun)
1314  {
1315  ExpandBackticks(cmd->command);
1316 
1317  // Run the command in a shell, so stream redirections (<, >, << and >>),
1318  // piping and other shell features can be evaluated.
1319  if (!platform::windows)
1320  {
1321  wxString shell = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/console_shell"), DEFAULT_CONSOLE_SHELL);
1322  cmd->command = shell + _T(" '") + cmd->command + _T("'");
1323  }
1324  }
1325 
1326  // create a new process
1327  CompilerProcess &process = m_CompilerProcessList.at(procIndex);
1328  process.OutputFile = (cmd->isLink && cmd->target) ? cmd->target->GetOutputFilename() : wxString(wxEmptyString);
1329  process.pProcess = new PipedProcess(&(process.pProcess), this, idGCCProcess, pipe, dir, procIndex);
1330 
1331  process.PID = wxExecute(cmd->command, flags, process.pProcess);
1332  if (!process.PID)
1333  {
1334  wxString err = wxString::Format(_("Execution of '%s' in '%s' failed."),
1335  cmd->command.wx_str(), wxGetCwd().wx_str());
1336  LogMessage(err, cltError);
1337  LogWarningOrError(cltError, 0, wxEmptyString, wxEmptyString, err);
1338  if (!m_CommandQueue.LastCommandWasRun())
1339  {
1340  if ( !IsProcessRunning() )
1341  {
1342  wxString msg = wxString::Format(_("%s (%s)"), GetErrWarnStr().wx_str(), GetMinSecStr().wx_str());
1343  LogMessage(msg, cltError, ltAll, true);
1344  LogWarningOrError(cltNormal, 0, wxEmptyString, wxEmptyString,
1345  wxString::Format(_("=== Build failed: %s ==="), msg.wx_str()));
1346  m_pListLog->AutoFitColumns(2);
1347  SaveBuildLog();
1348  }
1349  if (!Manager::IsBatchBuild() && m_pLog->progress)
1350  m_pLog->progress->SetValue(0);
1351  }
1352  Delete(process.pProcess);
1353  m_CommandQueue.Clear();
1354  ResetBuildState();
1355  }
1356  else
1357  m_timerIdleWakeUp.Start(100);
1358 
1359  // restore dynamic linker path
1360  wxSetEnv(CB_LIBRARY_ENVVAR, oldLibPath);
1361 
1362  delete cmd;
1363  return DoRunQueue();
1364 }
1365 
1367 {
1368  if (m_TargetMenu)
1369  {
1370  wxMenuItemList& items = m_TargetMenu->GetMenuItems();
1371  for (wxMenuItemList::iterator it = items.begin(); it != items.end(); )
1372  {
1373  wxMenuItem *item = *it;
1374  // Make sure we increment valid iterator (Delete will invalidate it).
1375  ++it;
1376  if (item)
1377  m_TargetMenu->Delete(item);
1378  }
1379 // mandrav: The following lines DO NOT clear the menu!
1380 // wxMenuItemList& items = m_TargetMenu->GetMenuItems();
1381 // bool olddelete=items.GetDeleteContents();
1382 // items.DeleteContents(true);
1383 // items.Clear();
1384 // items.DeleteContents(olddelete);
1385  }
1386 }
1387 
1388 bool CompilerGCC::IsValidTarget(const wxString &target) const
1389 {
1390  if ( target.IsEmpty() )
1391  return false;
1392  if ( m_Targets.Index(target) == -1 )
1393  return false;
1395  if ( tgt && ! tgt->SupportsCurrentPlatform() )
1396  return false;
1397  return true;
1398 }
1399 
1401 {
1402  if (!IsAttached())
1403  return;
1404 
1405  if (m_pToolTarget)
1406  m_pToolTarget->Freeze();
1407  wxMenuBar* mbar = Manager::Get()->GetAppFrame()->GetMenuBar();
1408  if (mbar)
1409  mbar->Freeze();
1410 
1411  do
1412  {
1413  // clear menu and combo
1414  DoClearTargetMenu();
1415  if (m_pToolTarget)
1416  m_pToolTarget->Clear();
1417 
1418  // if no project, leave
1419  if (!CheckProject())
1420  break;
1421 
1422  // if no targets, leave
1423  if (!m_Targets.GetCount())
1424  break;
1425 
1426  wxString tgtStr(m_pProject->GetFirstValidBuildTargetName());
1427 
1428  // find out the should-be-selected target
1430  {
1431  const wxString preferredTarget = wsp->GetPreferredTarget();
1432  tgtStr = preferredTarget;
1433  if ( !IsValidTarget(tgtStr) )
1434  tgtStr = m_pProject->GetActiveBuildTarget();
1435  if ( !IsValidTarget(tgtStr) )
1436  tgtStr = m_pProject->GetFirstValidBuildTargetName(); // last-chance default
1437  if ( preferredTarget.IsEmpty() )
1438  wsp->SetPreferredTarget(tgtStr);
1439  }
1440 
1441  if (m_TargetMenu)
1442  {
1443  m_TargetMenu->Append(idMenuSelectTargetDialog, _("Select target..."), _("Shows a dialog with all targets"));
1444  m_TargetMenu->AppendSeparator();
1445  }
1446 
1447  // fill the menu and combo
1448  for (int x = 0; x < int(m_Targets.size()); ++x)
1449  {
1450  if (m_TargetMenu && x < maxTargetInMenus)
1451  {
1452  wxString help;
1453  help.Printf(_("Build target '%s' in current project"), GetTargetString(x).wx_str());
1454  m_TargetMenu->AppendCheckItem(idMenuSelectTargetOther[x], GetTargetString(x), help);
1455  }
1456  if (m_pToolTarget)
1457  m_pToolTarget->Append(GetTargetString(x));
1458  }
1459 
1460  if (m_TargetMenu && int(m_Targets.size()) > maxTargetInMenus)
1461  {
1462  m_TargetMenu->Append(idMenuSelectTargetHasMore, _("More targets available..."),
1463  _("Use the select target menu item to see them!"));
1464  m_TargetMenu->Enable(idMenuSelectTargetHasMore, false);
1465  }
1466 
1467  // connect menu events
1469  wxEVT_COMMAND_MENU_SELECTED,
1470  (wxObjectEventFunction) (wxEventFunction) (wxCommandEventFunction)
1472 
1473  // housekeeping
1474  m_TargetIndex = m_Targets.Index(tgtStr);
1475  m_RealTargetIndex = m_TargetIndex - m_RealTargetsStartIndex;
1476  if (m_RealTargetIndex < 0)
1477  m_RealTargetIndex = -1;
1478 
1479  DoUpdateTargetMenu(m_TargetIndex);
1480 
1481  // update combo
1482  if (m_pToolTarget)
1483  m_pToolTarget->SetSelection(m_TargetIndex);
1484 
1485  // finally, make sure we 're using the correct compiler for the project
1486  SwitchCompiler(m_pProject->GetCompilerID());
1487  }
1488  while (false);
1489 
1490  if (mbar)
1491  mbar->Thaw();
1492  if (m_pToolTarget)
1493  m_pToolTarget->Thaw();
1494 }
1495 
1496 void CompilerGCC::DoUpdateTargetMenu(int targetIndex)
1497 {
1498  // update indices
1499  m_TargetIndex = targetIndex;
1500  m_RealTargetIndex = m_TargetIndex - m_RealTargetsStartIndex;
1501  if (m_RealTargetIndex < 0)
1502  m_RealTargetIndex = -1;
1503 
1504  if (m_TargetIndex == -1)
1505  m_TargetIndex = 0;
1506 
1507  if (m_pProject)
1508  m_pProject->SetActiveBuildTarget(GetTargetString(m_TargetIndex));
1509 
1510  // update menu
1511  if (m_TargetMenu)
1512  {
1513  for (int i = 0; i < maxTargetInMenus; ++i)
1514  {
1515  wxMenuItem* item = m_TargetMenu->FindItem(idMenuSelectTargetOther[i]);
1516  if (!item || !item->IsCheckable())
1517  continue;
1518  item->Check(i == m_TargetIndex);
1519  }
1520  }
1521 
1522  // the tool combo is updated in DoRecreateTargetMenu()
1523  // can't set it here, because this function is called by the
1524  // tool combo's event handler
1525 // DBGLOG(_T("m_TargetIndex=%d, m_pToolTarget->GetCurrentSelection()=%d, m_RealTargetsStartIndex=%d"), m_TargetIndex, m_pToolTarget->GetCurrentSelection(), m_RealTargetsStartIndex);
1526 }
1527 
1529 {
1530  m_Targets.Clear();
1531  if (!project)
1532  return;
1533 
1534  // update the list of targets (virtual + real)
1535  wxArrayString virtuals = project->GetVirtualBuildTargets();
1536  for (size_t i = 0; i < virtuals.GetCount(); ++i)
1537  m_Targets.Add(virtuals[i]);
1538 
1539  for (int i = 0; i < project->GetBuildTargetsCount(); ++i)
1540  {
1541  ProjectBuildTarget *tgt = project->GetBuildTarget(i);
1542  if ( tgt->SupportsCurrentPlatform() )
1543  m_Targets.Add( tgt->GetTitle() );
1544  }
1545 
1546  // keep the index for the first real target
1547  m_RealTargetsStartIndex = virtuals.GetCount();
1548 
1549  // actually rebuild menu and combo
1550  DoRecreateTargetMenu();
1551 }
1552 
1554 {
1555  if (index == -1)
1556  index = m_TargetIndex;
1557  if (index >= 0 && index < (int)m_Targets.GetCount())
1558  return m_Targets[index];
1559  return wxEmptyString;
1560 }
1561 
1562 void CompilerGCC::DoPrepareQueue(bool clearLog)
1563 {
1564  if (m_CommandQueue.GetCount() == 0)
1565  {
1566  CodeBlocksEvent evt(cbEVT_COMPILER_STARTED, 0, m_pProject, 0, this);
1567  Manager::Get()->ProcessEvent(evt);
1568 
1569  if (clearLog)
1570  {
1571  ClearLog(true);
1572  DoClearErrors();
1573  }
1574  // wxStartTimer();
1575  m_StartTime = wxGetLocalTimeMillis();
1576  }
1577  Manager::Yield();
1578 }
1579 
1581 {
1582  if (m_CommandQueue.GetCount() == 0)
1583  {
1584  CodeBlocksEvent evt(cbEVT_CLEAN_PROJECT_STARTED, 0, m_pProject, 0, this);
1585  evt.SetBuildTargetName(target);
1586  Manager::Get()->ProcessEvent(evt);
1587  }
1588  Manager::Yield();
1589 }
1590 
1592 {
1593  if (m_CommandQueue.GetCount() == 0)
1594  {
1595  CodeBlocksEvent evt(cbEVT_CLEAN_WORKSPACE_STARTED, 0, 0, 0, this);
1596  Manager::Get()->ProcessEvent(evt);
1597  }
1598  Manager::Yield();
1599 }
1600 
1602 {
1603  if (!CheckProject())
1604  return 0L;
1605 
1606  return m_pProject->GetBuildTarget(m_RealTargetIndex);
1607 }
1608 
1610 {
1611  if (!CheckProject())
1612  return -1;
1613 
1614  return m_pProject->SelectTarget(m_RealTargetIndex);
1615 }
1616 
1618 {
1619  if (!project)
1620  project = m_pProject;
1621  if (!project)
1622  return false;
1623  wxString idx = project->GetCompilerID();
1625  return project->IsMakefileCustom();
1626 
1627  return false;
1628 }
1629 
1631 {
1632  if (target)
1633  return target->GetCompilerID();
1634  if (m_pBuildingProject)
1635  return m_pBuildingProject->GetCompilerID();
1636  if (m_pProject)
1637  return m_pProject->GetCompilerID();
1638  return wxEmptyString;
1639 }
1640 
1642 {
1643  CompilerValidResult result;
1644  if (!target)
1646  else
1647  {
1648  wxString idx = GetCurrentCompilerID(target);
1649  result.compiler = CompilerFactory::GetCompiler(idx);
1650  }
1651  if (result.compiler)
1652  result.isValid = result.compiler->IsValid();
1653  return result;
1654 }
1655 
1656 void CompilerGCC::PrintInvalidCompiler(ProjectBuildTarget *target, Compiler *compiler, const wxString &finalMessage)
1657 {
1658  wxString compilerName, compilerName2(wxT("unknown"));
1659  if (compiler)
1660  {
1661  compilerName = wxT("(") + compiler->GetName() + wxT(") ");
1662  compilerName2 = compiler->GetName();
1663  }
1664 
1665  wxString title;
1666  if (target)
1667  title = target->GetFullTitle();
1668  else
1669  title = wxT("unknown");
1670 
1671  wxString msg;
1672  msg.Printf(_T("Project/Target: \"%s\":\n")
1673  _T(" The compiler's setup %sis invalid, so Code::Blocks cannot find/run the compiler.\n")
1674  _T(" Probably the toolchain path within the compiler options is not setup correctly?!\n")
1675  _T(" Do you have a compiler installed?\n")
1676  _T("Goto \"Settings->Compiler...->Global compiler settings->%s->Toolchain executables\"")
1677  _T(" and fix the compiler's setup.\n"),
1678  title.wx_str(), compilerName.wx_str(), compilerName2.wx_str());
1679 
1680  LogManager *logger = Manager::Get()->GetLogManager();
1681  logger->LogError(msg, m_PageIndex);
1682  if (compiler)
1683  logger->LogError(compiler->MakeInvalidCompilerMessages(), m_PageIndex);
1684  logger->LogError(finalMessage, m_PageIndex);
1685 }
1686 
1688 {
1689  if (!CompilerValid(target).isValid)
1690  return;
1691 
1693  Manager::Get()->ProcessEvent(evtShow);
1694 
1695  if (!prj)
1696  prj = m_pProject;
1697 
1698  wxString Action;
1699  switch (action)
1700  {
1701  case baClean:
1702  Action = _("Clean");
1703  break;
1704  case baRun:
1705  Action = _("Run");
1706  break;
1707  case baBuildFile:
1708  Action = _("Build file");
1709  break;
1710  default:
1711  case baBuild:
1712  Action = _("Build");
1713  break;
1714  }
1715 
1716  wxString compilerName(_("unknown"));
1717  Compiler *compiler = CompilerFactory::GetCompiler(GetCurrentCompilerID(target));
1718  if (compiler)
1719  compilerName = compiler->GetName();
1720 
1721  wxString targetName = target ? target->GetTitle() : wxString(_("\"no target\""));
1722  wxString projectName = prj ? prj->GetTitle() : wxString(_("\"no project\""));
1723 
1724  wxString banner;
1725  banner.Printf(_("%s: %s in %s (compiler: %s)"),
1726  Action.wx_str(), targetName.wx_str(), projectName.wx_str(), compilerName.wx_str());
1727  LogWarningOrError(cltNormal, 0, wxEmptyString, wxEmptyString, wxT("=== ") + banner + wxT(" ==="));
1728  LogMessage(wxT("-------------- ") + banner + wxT("---------------"), cltNormal, ltAll, false, true);
1729  m_pListLog->AutoFitColumns(2);
1730 }
1731 
1733 {
1734  CodeBlocksLogEvent eventSwitchLog(cbEVT_SWITCH_TO_LOG_WINDOW, m_pListLog);
1735  Manager::Get()->ProcessEvent(eventSwitchLog);
1736 
1737  m_Errors.Next();
1738  m_pListLog->FocusError(m_Errors.GetFocusedError());
1739 }
1740 
1742 {
1743  CodeBlocksLogEvent eventSwitchLog(cbEVT_SWITCH_TO_LOG_WINDOW, m_pListLog);
1744  Manager::Get()->ProcessEvent(eventSwitchLog);
1745 
1746  m_Errors.Previous();
1747  m_pListLog->FocusError(m_Errors.GetFocusedError());
1748 }
1749 
1751 {
1752  m_Errors.Clear();
1753  m_pListLog->Clear();
1754  m_NotifiedMaxErrors = false;
1755 }
1756 
1758 {
1759  wxFileName fname(filename);
1760 
1761  if (fname.GetExt() == _T("script"))
1762  {
1764  return 0;
1765  }
1766 
1767  m_CdRun = fname.GetPath();
1769  wxString exe_filename = fname.GetFullPath();
1770  wxString command;
1771 
1772  if (!platform::windows)
1773  {
1774  // for non-win platforms, use m_ConsoleTerm to run the console app
1775  wxString term = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/console_terminal"), DEFAULT_CONSOLE_TERM);
1776  term.Replace(_T("$TITLE"), _T("'") + exe_filename + _T("'"));
1777  command << term << strSPACE;
1778  }
1779 
1781  wxString crunnStr = strQUOTE + baseDir + strSLASH + strCONSOLE_RUNNER + strQUOTE;
1782  if ( wxFileExists(baseDir + strSLASH + strCONSOLE_RUNNER) )
1783  command << crunnStr << strSPACE;
1784 
1785  if (!command.Replace(_T("$SCRIPT"), exe_filename))
1786  command << strQUOTE << exe_filename << strQUOTE; // if they didn't specify $SCRIPT, append:
1787 
1788  Manager::Get()->GetLogManager()->Log(_("Checking for existence: ") + exe_filename, m_PageIndex);
1789  if ( !wxFileExists(exe_filename) )
1790  {
1791  int ret = cbMessageBox(_("It seems that this file has not been built yet.\n"
1792  "Do you want to build it now?"),
1793  _("Information"),
1795  switch (ret)
1796  {
1797  case wxID_YES:
1798  {
1799  m_RunAfterCompile = true;
1800  Build(wxEmptyString);
1801  return -1;
1802  }
1803  case wxID_NO:
1804  break;
1805  default:
1806  return -1;
1807  }
1808  }
1809 
1811  Manager::Get()->GetLogManager()->Log(F(_("Executing: '%s' (in '%s')"), command.wx_str(), m_CdRun.wx_str()), m_PageIndex);
1812  m_CommandQueue.Add(new CompilerCommand(command, wxEmptyString, 0, 0, true));
1813  return 0;
1814 }
1815 
1816 int CompilerGCC::Run(const wxString& target)
1817 {
1818  if (!CheckProject())
1819  return -1;
1820  return Run(m_pProject->GetBuildTarget(target.IsEmpty() ? m_LastTargetName : target));
1821 }
1822 
1824 {
1825  bool commandIsQuoted = false; // remember if we quoted the command, avoid unneeded quotes, because they break execution with "konsole" under KDE
1826  if (!CheckProject())
1827  {
1828  if (Manager::Get()->GetEditorManager()->GetActiveEditor())
1829  return RunSingleFile(Manager::Get()->GetEditorManager()->GetActiveEditor()->GetFilename());
1830  return -1;
1831  }
1832  else
1833  {
1834  target = m_pProject->GetBuildTarget(m_pProject->GetActiveBuildTarget());
1835  }
1836  PrintBanner(baRun, m_pProject, target);
1837 
1838  DoPrepareQueue(false);
1839  if ( !(target && ( target->GetTargetType() == ttCommandsOnly // do not require compiler for commands-only target
1840  || target->GetCompilerID() == wxT("null") ))) // do not require compiler for "No Compiler" (why would you?)
1841  {
1842  CompilerValidResult result = CompilerValid(target);
1843  if (!result.isValid)
1844  {
1845  PrintInvalidCompiler(target, result.compiler, _("Run aborted..."));
1846  return -1;
1847  }
1848  }
1849 // DBGLOG(_T("1) target=%s, m_RealTargetIndex=%d, m_TargetIndex=%d"), target ? target->GetTitle().c_str() : _T("null"), m_RealTargetIndex, m_TargetIndex);
1850 
1851  if (!target)
1852  {
1853  if (m_RealTargetIndex == -1) // only ask for target if a virtual target is selected
1854  {
1855  int idx = -1;
1856  int bak = m_RealTargetIndex;
1857  if (m_pProject->GetBuildTargetsCount() == 1)
1858  idx = 0;
1859  else
1860  idx = DoGUIAskForTarget();
1861 
1862  m_RealTargetIndex = idx;
1863  target = DoAskForTarget();
1864  m_RealTargetIndex = bak;
1865  }
1866  else
1867  target = DoAskForTarget();
1868  }
1869 // DBGLOG(_T("2) target=%s, m_RealTargetIndex=%d, m_TargetIndex=%d"), target ? target->GetTitle().c_str() : _T("null"), m_RealTargetIndex, m_TargetIndex);
1870 
1871  if (!target)
1872  return -1;
1873 
1874  m_pProject->SetCurrentlyCompilingTarget(target); // help macros manager
1875 
1876  wxString out = UnixFilename(target->GetOutputFilename());
1878 
1879  wxString cmd;
1880  wxString command;
1881  wxFileName f(out);
1882  f.MakeAbsolute(m_pProject->GetBasePath());
1883 
1884  m_CdRun = target->GetWorkingDir();
1886  wxFileName cd(m_CdRun);
1887  if (cd.IsRelative())
1888  cd.MakeAbsolute(m_pProject->GetBasePath());
1889  m_CdRun = cd.GetFullPath();
1891 
1892  wxString titleStr = platform::windows
1893  ? strQUOTE + m_pProject->GetTitle() + strQUOTE
1894  : EscapeSpaces(m_pProject->GetTitle());
1895  wxString dirStr = platform::windows
1896  ? strQUOTE + m_CdRun + strQUOTE
1897  : EscapeSpaces(m_CdRun);
1898  wxString crunnStr = platform::windows
1899  ? strQUOTE + baseDir + strSLASH + strCONSOLE_RUNNER + strQUOTE
1900  : EscapeSpaces(baseDir + strSLASH + strCONSOLE_RUNNER);
1901  wxString hostapStr = platform::windows
1902  ? strQUOTE + target->GetHostApplication() + strQUOTE
1903  : EscapeSpaces(target->GetHostApplication());
1904  wxString execStr = platform::windows
1905  ? strQUOTE + f.GetFullPath() + strQUOTE
1906  : EscapeSpaces(f.GetFullPath());
1907 
1908  // for console projects, use helper app to wait for a key after
1909  // execution ends...
1910  if (target->GetTargetType() == ttConsoleOnly || target->GetRunHostApplicationInTerminal())
1911  {
1912  if (!platform::windows)
1913  {
1914  // for non-win platforms, use m_ConsoleTerm to run the console app
1915  wxString term = Manager::Get()->GetConfigManager(_T("app"))->Read(_T("/console_terminal"), DEFAULT_CONSOLE_TERM);
1916  term.Replace(_T("$TITLE"), titleStr);
1917  term.Replace(_T("$WORKDIR"), dirStr);
1918  cmd << term << strSPACE;
1919 
1920  wxString shell;
1921  wxGetEnv(_T("SHELL"), &shell);
1922  if (shell.Contains(_T("csh")))
1923  {
1924  // "The csh is a tool utterly inadequate for programming,
1925  // and its use for such purposes should be strictly banned!"
1926  // -- Csh Programming Considered Harmful
1927  command << DEFAULT_CONSOLE_SHELL << strSPACE;
1928  // each shell execution must be enclosed to "":
1929  // xterm -T X -e /bin/sh -c "/usr/bin/cb_console_runner X"
1930  // here is first \"
1931  command << strQUOTE;
1932  commandIsQuoted = true;
1933  }
1934  }
1935 
1936  if (target->GetUseConsoleRunner())
1937  {
1938  if (wxFileExists(baseDir + strSLASH + strCONSOLE_RUNNER))
1939  {
1940  command << crunnStr << strSPACE;
1941 
1942  if (!platform::windows)
1943  {
1944  // set LD_LIBRARY_PATH
1945  command << CB_LIBRARY_ENVVAR << _T("=$") << CB_LIBRARY_ENVVAR << _T(':');
1946  // we have to quote the string, just escape the spaces does not work
1947  wxString strLinkerPath=cbGetDynamicLinkerPathForTarget(m_pProject, target);
1948  QuoteStringIfNeeded(strLinkerPath);
1949  command << strLinkerPath << strSPACE;
1950  }
1951  }
1952  }
1953  }
1954 
1955  if ( target->GetTargetType() == ttDynamicLib
1956  || target->GetTargetType() == ttStaticLib )
1957  {
1958  // check for hostapp
1959  if (target->GetHostApplication().IsEmpty())
1960  {
1961  cbMessageBox(_("You must select a host application to \"run\" a library..."));
1962  m_pProject->SetCurrentlyCompilingTarget(0);
1963  return -1;
1964  }
1965  Manager::Get()->GetMacrosManager()->ReplaceEnvVars(hostapStr);
1966  command << hostapStr << strSPACE;
1967  command << target->GetExecutionParameters();
1968  }
1969  else if (target->GetTargetType() != ttCommandsOnly)
1970  {
1971  command << execStr << strSPACE;
1972  command << target->GetExecutionParameters();
1973  // each shell execution must be enclosed to "":
1974  // xterm -T X -e /bin/sh -c "/usr/bin/cb_console_runner X"
1975  // here is last \"
1976  if (commandIsQuoted)
1977  command << strQUOTE;
1978  }
1979  else
1980  {
1981  // commands-only target?
1982  if (target->GetHostApplication().IsEmpty())
1983  {
1984  cbMessageBox(_("You must select a host application to \"run\" a commands-only target..."));
1985  m_pProject->SetCurrentlyCompilingTarget(0);
1986  return -1;
1987  }
1988  command << hostapStr << strSPACE;
1989  command << target->GetExecutionParameters();
1990  Manager::Get()->GetMacrosManager()->ReplaceMacros(command, target);
1992  }
1993 
1994  wxString script = command;
1995 
1996  if (platform::macosx)
1997  {
1998  if (target->GetTargetType() == ttConsoleOnly &&
1999  script.GetChar(0) == '\'' && script.GetChar(script.length()-1) == '\'')
2000  script = script.Mid(1,script.length()-2); // skip outmost single-quotes
2001 
2002  // convert embedded quotes to AppleScript syntax
2003  script.Replace(_T("\""), _T("\"&quote&\""), true);
2004  script.Replace(_T("\'"), _T("\"&ASCII character 39&\""), true);
2005  }
2006 
2007  if (!cmd.Replace(_T("$SCRIPT"), script))
2008  // if they didn't specify $SCRIPT, append:
2009  cmd << command;
2010 
2011  Manager::Get()->GetLogManager()->Log(_("Checking for existence: ") + f.GetFullPath(), m_PageIndex);
2012  if ( (target->GetTargetType() != ttCommandsOnly) && !wxFileExists(f.GetFullPath()) )
2013  {
2014  int ret = cbMessageBox(_("It seems that this project has not been built yet.\n"
2015  "Do you want to build it now?"),
2016  _("Information"),
2018  switch (ret)
2019  {
2020  case wxID_YES:
2021  {
2022  m_pProject->SetCurrentlyCompilingTarget(0);
2023  m_RunAfterCompile = true;
2024  Build(target);
2025  return -1;
2026  }
2027  case wxID_NO:
2028  break;
2029  default:
2030  m_pProject->SetCurrentlyCompilingTarget(0);
2031  return -1;
2032  }
2033  }
2034 
2035  Manager::Get()->GetLogManager()->Log(F(_("Executing: %s (in %s)"), cmd.wx_str(), m_CdRun.wx_str()), m_PageIndex);
2036  m_CommandQueue.Add(new CompilerCommand(cmd, wxEmptyString, m_pProject, target, true));
2037 
2038  m_pProject->SetCurrentlyCompilingTarget(0);
2039 
2041  return 0;
2042 }
2043 
2045 {
2046  if (!project)
2047  return wxEmptyString;
2048 
2049  wxString compilerId = target ? target->GetCompilerID() : project->GetCompilerID();
2050  if (!CompilerFactory::IsValidCompilerID(compilerId))
2052  wxString command = target && !target->GetMakeCommandFor(cmd).empty() ?
2053  target->GetMakeCommandFor(cmd) : project->GetMakeCommandFor(cmd);
2054 
2055  Compiler* compiler = CompilerFactory::GetCompiler(compilerId);
2056  command.Replace(_T("$makefile"), project->GetMakefile());
2057  command.Replace(_T("$make"), compiler ? compiler->GetPrograms().MAKE : _T("make"));
2058  command.Replace(_T("$target"), target ? target->GetTitle() : _T(""));
2060 
2061 // Manager::Get()->GetMessageManager()->Log(m_PageIndex, _T("Make: %s"), command.c_str()));
2062  return command;
2063 }
2064 
2066 {
2067  for (unsigned int i = 0; i < commands.GetCount(); ++i)
2068  wxRemoveFile(commands[i]);
2069 }
2070 
2072 {
2073  return Clean(target ? target->GetTitle() : _T(""));
2074 }
2075 
2076 int CompilerGCC::Clean(const wxString& target)
2077 {
2078  m_LastBuildStep = true;
2079  return DoBuild(target, true, false);
2080 }
2081 
2083 {
2084  return bt ? bt->GetTitle() : wxString(_("<all targets>"));
2085 }
2086 
2088 {
2089  wxString cmd = GetMakeCommandFor(mcClean, m_pBuildingProject, bt);
2090  if (cmd.empty())
2091  {
2092  LogMessage(COMPILER_ERROR_LOG +
2093  wxT("Make command for 'Clean project/target' is empty. Nothing will be cleaned!"),
2094  cltError);
2095  return false;
2096  }
2097  Compiler* tgtCompiler = CompilerFactory::GetCompiler(bt->GetCompilerID());
2098  if (!tgtCompiler)
2099  {
2100  const wxString &message = F(_("Invalid compiler selected for target '%s'!"), getBuildTargetName(bt).wx_str());
2101 
2102  LogMessage(COMPILER_ERROR_LOG + message, cltError);
2103  return false;
2104  }
2105 
2106  bool showOutput = (tgtCompiler->GetSwitches().logging == clogFull);
2107 
2108  wxArrayString output, errors;
2109  wxSetWorkingDirectory(m_pBuildingProject->GetExecutionDir());
2110 
2111  ExpandBackticks(cmd);
2112  if (showOutput)
2113  LogMessage(F(_("Executing clean command: %s"), cmd.wx_str()), cltNormal);
2114 
2115  long result = wxExecute(cmd, output, errors, wxEXEC_SYNC);
2116  if (showOutput)
2117  {
2118  for(size_t i = 0; i < output.GetCount(); i++)
2119  LogMessage(F(_("%s"), output[i].wx_str()), cltNormal);
2120  for(size_t i = 0; i < errors.GetCount(); i++)
2121  LogMessage(F(_("%s"), errors[i].wx_str()), cltNormal);
2122  }
2123 
2124  return (result == 0);
2125 }
2126 
2128 {
2129  if (!CheckProject())
2130  return -1;
2131  return DistClean(m_pProject->GetBuildTarget(target.IsEmpty() ? m_LastTargetName : target));
2132 }
2133 
2135 {
2136  // make sure all project files are saved
2137  if (m_pProject && !m_pProject->SaveAllFiles())
2138  Manager::Get()->GetLogManager()->Log(_("Could not save all files..."));
2139 
2140  if (!m_IsWorkspaceOperation)
2141  DoPrepareQueue(true);
2142  if (!CompilerValid(target).isValid)
2143  return -1;
2144 
2145 // Manager::Get()->GetMacrosManager()->Reset();
2146 
2147  if (m_pProject)
2148  wxSetWorkingDirectory(m_pProject->GetBasePath());
2149 
2150  if ( UseMake() )
2151  {
2152  wxString cmd = GetMakeCommandFor(mcDistClean, m_pProject, target);
2153  m_CommandQueue.Add(new CompilerCommand(cmd, wxEmptyString, m_pProject, target));
2154  return DoRunQueue();
2155  }
2156  else
2157  {
2158  NotImplemented(_T("CompilerGCC::DistClean() without a custom Makefile"));
2159  return -1;
2160  }
2161  return 0;
2162 }
2163 
2165 {
2166  m_BuildJob = job;
2167  m_BuildState = bsNone;
2168  m_NextBuildState = bsProjectPreBuild;
2169  m_pBuildingProject = 0;
2170  m_pLastBuildingProject = 0;
2171  m_pLastBuildingTarget = 0;
2172  m_BuildingTargetName = target;
2173  m_CommandQueue.Clear();
2174 }
2175 
2177 {
2178  if (m_pBuildingProject)
2179  m_pBuildingProject->SetCurrentlyCompilingTarget(0);
2180  else if (m_pProject)
2181  m_pProject->SetCurrentlyCompilingTarget(0);
2182 
2183  // reset state
2184  m_BuildJob = bjIdle;
2185  m_BuildState = bsNone;
2186  m_NextBuildState = bsNone;
2187  m_pBuildingProject = 0;
2188  m_BuildingTargetName.Clear();
2189 
2190  m_pLastBuildingProject = 0;
2191  m_pLastBuildingTarget = 0;
2192 
2193  m_CommandQueue.Clear();
2194 
2195  // Clear the Active Project's currently compiling target
2196  // NOTE (rickg22#1#): This way we can prevent Codeblocks from shutting down
2197  // when a project is being compiled.
2198  // NOTE (mandrav#1#): Make sure no open project is marked as compiling
2199  ProjectsArray* arr = Manager::Get()->GetProjectManager()->GetProjects();
2200  for (size_t i = 0; i < arr->GetCount(); ++i)
2201  {
2202  arr->Item(i)->SetCurrentlyCompilingTarget(0);
2203  }
2204 }
2205 
2207 {
2208  switch (bs)
2209  {
2210  case bsNone: return _T("bsNone");
2211  case bsProjectPreBuild: return _T("bsProjectPreBuild");
2212  case bsTargetPreBuild: return _T("bsTargetPreBuild");
2213  case bsTargetClean: return _T("bsTargetClean");
2214  case bsTargetBuild: return _T("bsTargetBuild");
2215  case bsTargetPostBuild: return _T("bsTargetPostBuild");
2216  case bsTargetDone: return _T("bsTargetDone");
2217  case bsProjectPostBuild: return _T("bsProjectPostBuild");
2218  case bsProjectDone: return _T("bsProjectDone");
2219  default: break;
2220  }
2221  return _T("Huh!?!");
2222 }
2223 
2225 {
2226  bool clean = m_Clean;
2227  bool build = m_Build;
2228 
2229  switch (m_BuildState)
2230  {
2231  case bsProjectPreBuild:
2232  {
2233  if (clean && !build)
2234  return bsTargetClean;
2235 
2236  return bsTargetPreBuild;
2237  }
2238 
2239  case bsTargetPreBuild:
2240  {
2241  if (clean)
2242  return bsTargetClean;
2243  else if (build)
2244  return bsTargetBuild;
2245 
2246  return bsTargetPostBuild;
2247  }
2248 
2249  case bsTargetClean:
2250  {
2251  if (build)
2252  return bsTargetBuild;
2253 
2254  return bsTargetDone;
2255  }
2256 
2257  case bsTargetBuild:
2258  return bsTargetPostBuild;
2259 
2260  case bsTargetPostBuild:
2261  return bsTargetDone;
2262 
2263  // advance target in the project
2264  case bsTargetDone:
2265  {
2266  // get next build job
2267  if (m_BuildJob != bjTarget)
2268  {
2269  const BuildJobTarget& bj = PeekNextJob();
2270  if (bj.project && bj.project == m_pBuildingProject)
2271  {
2272  // same project, switch target
2273  m_BuildingTargetName = bj.targetName;
2274  GetNextJob(); // remove job from queue, bj points to a destructed object
2275  // switching targets
2276  if (clean && !build)
2277  return bsTargetClean;
2278 
2279  return bsTargetPreBuild;
2280  }
2281  // switch project
2282  // don't run postbuild step, if we only clean the project
2283  if (build)
2284  return bsProjectPostBuild;
2285 
2286  return bsProjectDone;
2287  }
2288  m_pBuildingProject->SetCurrentlyCompilingTarget(0);
2289  break; // all done
2290  }
2291 
2292  case bsProjectPostBuild:
2293  return bsProjectDone;
2294 
2295  case bsProjectDone:
2296  {
2297  // switch to next project in workspace
2298  if (m_pBuildingProject)
2299  m_pBuildingProject->SetCurrentlyCompilingTarget(0);
2300  m_NextBuildState = bsProjectPreBuild;
2301  // DoBuild runs ProjectPreBuild, next step has to be TargetClean or TargetPreBuild
2302  if (DoBuild(clean, build) >= 0)
2303  {
2304  if (clean && !build)
2305  return bsTargetClean;
2306 
2307  return bsTargetPreBuild;
2308  }
2309  else
2310  return bsNone;
2311  }
2312 
2313  case bsNone: // fall-through
2314  default:
2315  break;
2316  }
2317  return bsNone;
2318 }
2319 
2321 {
2322 // Manager::Get()->GetMessageManager()->Log(m_PageIndex, _T("BuildStateManagement")));
2323  if (IsProcessRunning())
2324  return;
2325 
2326  Manager::Yield();
2327  if (!m_pBuildingProject)
2328  {
2329  ResetBuildState();
2330  return;
2331  }
2332 
2333  ProjectBuildTarget* bt = m_pBuildingProject->GetBuildTarget(GetTargetIndexFromName(m_pBuildingProject, m_BuildingTargetName));
2334  if (!bt)
2335  {
2336  ResetBuildState();
2337  return;
2338  }
2339 
2340  if (m_pBuildingProject != m_pLastBuildingProject || bt != m_pLastBuildingTarget)
2341  {
2342  Manager::Get()->GetMacrosManager()->RecalcVars(m_pBuildingProject, Manager::Get()->GetEditorManager()->GetActiveEditor(), bt);
2343  if (bt)
2344  SwitchCompiler(bt->GetCompilerID());
2345 
2346  if (m_pBuildingProject != m_pLastBuildingProject)
2347  {
2348  m_pLastBuildingProject = m_pBuildingProject;
2349  wxSetWorkingDirectory(m_pBuildingProject->GetBasePath());
2350  }
2351  if (bt != m_pLastBuildingTarget)
2352  m_pLastBuildingTarget = bt;
2353  }
2354 
2355  m_pBuildingProject->SetCurrentlyCompilingTarget(bt);
2356  DirectCommands dc(this, CompilerFactory::GetCompiler(bt->GetCompilerID()), m_pBuildingProject, m_PageIndex);
2357  dc.m_doYield = true;
2358 
2359  m_BuildState = m_NextBuildState;
2360  wxArrayString cmds;
2361  switch (m_NextBuildState)
2362  {
2363  case bsProjectPreBuild:
2364  {
2365  // don't run project pre-build steps if we only clean it
2366  if (m_Build)
2367  cmds = dc.GetPreBuildCommands(0);
2368  break;
2369  }
2370 
2371  case bsTargetPreBuild:
2372  {
2373  // check if it should build with "All"
2374  // run target pre-build steps
2375  cmds = dc.GetPreBuildCommands(bt);
2376  break;
2377  }
2378 
2379  case bsTargetClean:
2380  {
2381  PrintBanner(baClean, m_pBuildingProject, bt);
2382 
2383  bool result;
2384  if ( UseMake(m_pBuildingProject) )
2385  result = DoCleanWithMake(bt);
2386  else
2387  {
2388  wxArrayString clean = dc.GetCleanCommands(bt, true);
2389  DoClean(clean);
2390  result = true;
2391  }
2392 
2393  if (result)
2394  {
2395  const wxString &message = F(_("Cleaned \"%s - %s\""), m_pBuildingProject->GetTitle().wx_str(),
2396  getBuildTargetName(bt).wx_str());
2397  LogMessage(message, cltNormal);
2398  }
2399  else
2400  {
2401  const wxString &message = F(_("Error cleaning \"%s - %s\""), m_pBuildingProject->GetTitle().wx_str(),
2402  getBuildTargetName(bt).wx_str());
2403  LogMessage(COMPILER_ERROR_LOG + message, cltError);
2404  }
2405  break;
2406  }
2407 
2408  case bsTargetBuild:
2409  {
2410  PrintBanner(baBuild, m_pBuildingProject, bt);
2411 
2412  // run target build
2413  if ( UseMake(m_pBuildingProject) )
2414  {
2415  wxArrayString output, error;
2416  wxSetWorkingDirectory(m_pBuildingProject->GetExecutionDir());
2417 
2418  const wxString &askCmd = GetMakeCommandFor(mcAskRebuildNeeded, m_pBuildingProject, bt);
2419 
2420  Compiler* tgtCompiler = CompilerFactory::GetCompiler(bt->GetCompilerID());
2421 
2422  bool runMake = false;
2423  if (!askCmd.empty())
2424  {
2425  if (tgtCompiler && tgtCompiler->GetSwitches().logging == clogFull)
2426  cmds.Add(COMPILER_SIMPLE_LOG + _("Checking if target is up-to-date: ") + askCmd);
2427 
2428  runMake = (wxExecute(askCmd, output, error, wxEXEC_SYNC | wxEXEC_NODISABLE) != 0);
2429  }
2430  else
2431  {
2432  cmds.Add(COMPILER_SIMPLE_LOG +
2433  _("The command that asks if a rebuild is needed is empty. Assuming rebuild is needed!"));
2434  runMake = true;
2435  }
2436 
2437  if (runMake && tgtCompiler)
2438  {
2439  bool isEmpty = false;
2440  switch (tgtCompiler->GetSwitches().logging)
2441  {
2442  case clogFull:
2443  {
2444  const wxString &cmd = GetMakeCommandFor(mcBuild, m_pBuildingProject, bt);
2445  if (!cmd.empty())
2446  {
2447  cmds.Add(COMPILER_SIMPLE_LOG + _("Running command: ") + cmd);
2448  cmds.Add(cmd);
2449  }
2450  else
2451  isEmpty = true;
2452  break;
2453  }
2454 
2455  case clogSimple:
2456  cmds.Add(COMPILER_SIMPLE_LOG + _("Using makefile: ") + m_pBuildingProject->GetMakefile());
2457  case clogNone:
2458  {
2459  const wxString &cmd = GetMakeCommandFor(mcSilentBuild, m_pBuildingProject, bt);
2460  if (!cmd.empty())
2461  cmds.Add(cmd);
2462  else
2463  isEmpty = true;
2464  break;
2465  }
2466 
2467  default:
2468  break;
2469  }
2470 
2471  if (isEmpty)
2472  {
2473  cmds.Add(COMPILER_ERROR_LOG +
2474  _("Make command for 'Build/Project target' is empty. Nothing will be built!"));
2475  }
2476 
2477  }
2478  }
2479  else
2480  cmds = dc.GetCompileCommands(bt);
2481 
2482  bool hasCommands = cmds.GetCount();
2483  m_RunTargetPostBuild = hasCommands;
2484  m_RunProjectPostBuild = hasCommands;
2485  if (!hasCommands)
2486  LogMessage(_("Target is up to date."));
2487  break;
2488  }
2489 
2490  case bsTargetPostBuild:
2491  {
2492  // run target post-build steps
2493  if (m_RunTargetPostBuild || bt->GetAlwaysRunPostBuildSteps())
2494  cmds = dc.GetPostBuildCommands(bt);
2495  // reset
2496  m_RunTargetPostBuild = false;
2497  break;
2498  }
2499 
2500  case bsProjectPostBuild:
2501  {
2502  // run project post-build steps
2503  if (m_RunProjectPostBuild || m_pBuildingProject->GetAlwaysRunPostBuildSteps())
2504  cmds = dc.GetPostBuildCommands(0);
2505  // reset
2506  m_pLastBuildingTarget = 0;
2507  m_RunProjectPostBuild = false;
2508  break;
2509  }
2510 
2511  case bsProjectDone:
2512  {
2513  m_pLastBuildingProject = 0;
2514  break;
2515  }
2516 
2517  case bsTargetDone: // fall-through
2518  case bsNone: // fall-through
2519  default:
2520  break;
2521  }
2522  m_NextBuildState = GetNextStateBasedOnJob();
2523  AddToCommandQueue(cmds);
2524  Manager::Yield();
2525 }
2526 
2528 {
2529  if (!prj || name.IsEmpty())
2530  return -1;
2531  for (int i = 0; i < prj->GetBuildTargetsCount(); ++i)
2532  {
2533  ProjectBuildTarget* bt_search = prj->GetBuildTarget(i);
2534  if (bt_search->GetTitle() == name)
2535  return i;
2536  }
2537  return -1;
2538 }
2539 
2540 void CompilerGCC::ExpandTargets(cbProject* project, const wxString& targetName, wxArrayString& result)
2541 {
2542  result.Clear();
2543  if (project)
2544  {
2545  ProjectBuildTarget* bt = project->GetBuildTarget(targetName);
2546  if (bt) // real target
2547  result.Add(targetName);
2548  else // virtual target
2549  result = project->GetExpandedVirtualBuildTargetGroup(targetName);
2550  }
2551 }
2552 
2553 void CompilerGCC::PreprocessJob(cbProject* project, const wxString& targetName)
2554 {
2555  wxArrayString tlist;
2556 
2557  // if not a workspace operation, clear any remaining (old) build jobs
2558  if (!m_IsWorkspaceOperation)
2559  {
2560  while (!m_BuildJobTargetsList.empty())
2561  m_BuildJobTargetsList.pop();
2562  }
2563 
2564  // calculate project/workspace dependencies
2565  wxArrayInt deps;
2566  if (!project)
2567  CalculateWorkspaceDependencies(deps);
2568  else
2569  CalculateProjectDependencies(project, deps);
2570 
2571  // loop all projects in the dependencies list
2572 // Manager::Get()->GetMessageManager()->Log(m_PageIndex, _T("** Creating deps")));
2573  for (size_t i = 0; i < deps.GetCount(); ++i)
2574  {
2575  cbProject* prj = Manager::Get()->GetProjectManager()->GetProjects()->Item(deps[i]);
2576 
2577  if (!prj->SupportsCurrentPlatform())
2578  {
2579  wxString msg;
2580  msg.Printf(_T("\"%s\" does not support the current platform. Skipping..."),
2581  prj->GetTitle().wx_str());
2582  Manager::Get()->GetLogManager()->LogWarning(msg, m_PageIndex);
2583  continue;
2584  }
2585 
2586  ExpandTargets(prj, targetName, tlist);
2587 
2588  if (tlist.GetCount() == 0)
2589  Manager::Get()->GetLogManager()->LogWarning(F(_T("Warning: No target named '%s' in project '%s'. Project will not be built..."), targetName.wx_str(), prj->GetTitle().wx_str()));
2590 
2591  // add all matching targets in the job list
2592  for (size_t x = 0; x < tlist.GetCount(); ++x)
2593  {
2594  ProjectBuildTarget* tgt = prj->GetBuildTarget(tlist[x]);
2595  CompilerValidResult result = CompilerValid(tgt);
2596  if (!result.isValid)
2597  {
2598  PrintInvalidCompiler(tgt, result.compiler, _T("Skipping..."));
2599  continue;
2600  }
2601  else if (!tgt->SupportsCurrentPlatform())
2602  {
2603  wxString msg;
2604  msg.Printf(_T("\"%s - %s\" does not support the current platform. Skipping..."),
2605  prj->GetTitle().wx_str(), tlist[x].wx_str());
2606  Manager::Get()->GetLogManager()->LogWarning(msg, m_PageIndex);
2607  continue;
2608  }
2609  BuildJobTarget bjt;
2610  bjt.project = prj;
2611  bjt.targetName = tlist[x];
2612 
2613  m_BuildJobTargetsList.push(bjt);
2614 
2615 // Manager::Get()->GetMessageManager()->Log(m_PageIndex, _T("Job: %s - %s"), prj->GetTitle().c_str(), prj->GetBuildTarget(tlist[x])->GetTitle().c_str()));
2616  }
2617  }
2618 
2619  // were there any jobs generated?
2620  if (m_BuildJobTargetsList.empty())
2621  NotifyJobDone(true);
2622 
2623 // Manager::Get()->GetMessageManager()->Log(m_PageIndex, _T("** Done creating deps")));
2624 }
2625 
2627 {
2628  BuildJobTarget ret;
2629  if (m_BuildJobTargetsList.empty())
2630  return ret;
2631  ret = m_BuildJobTargetsList.front();
2632  m_BuildJobTargetsList.pop();
2633  return ret;
2634 }
2635 
2637 {
2638  static BuildJobTarget ret;
2639 
2640  if (m_BuildJobTargetsList.empty())
2641  return ret;
2642  return m_BuildJobTargetsList.front();
2643 }
2644 
2645 int CompilerGCC::DoBuild(bool clean, bool build)
2646 {
2647  BuildJobTarget bj = GetNextJob();
2648 
2649  // no jobs list?
2650  if (!bj.project)
2651  return -2;
2652 
2653  // make sure all project files are saved
2654  if ( bj.project
2655  && (bj.project != m_pBuildingProject)
2656  && !bj.project->SaveAllFiles() ) // avoid saving when we only switch targets
2657  {
2658  Manager::Get()->GetLogManager()->Log(_("Could not save all files..."));
2659  }
2660 
2661  m_pBuildingProject = bj.project;
2662  m_BuildingTargetName = bj.targetName;
2664 
2665  m_Clean = clean;
2666  m_Build = build;
2667 
2668  if (!bt || !CompilerValid(bt).isValid)
2669  return -2;
2670 
2671  BuildStateManagement();
2672 
2673  return 0;
2674 }
2675 
2677 {
2678  deps.Clear();
2679  ProjectsArray* arr = Manager::Get()->GetProjectManager()->GetProjects();
2680  for (size_t i = 0; i < arr->GetCount(); ++i)
2681  {
2682  CalculateProjectDependencies(arr->Item(i), deps);
2683  }
2684 }
2685 
2687 {
2688  int prjidx = Manager::Get()->GetProjectManager()->GetProjects()->Index(prj);
2689  const ProjectsArray* arr = Manager::Get()->GetProjectManager()->GetDependenciesForProject(prj);
2690  if (!arr || !arr->GetCount())
2691  {
2692  // no dependencies; add the project in question and exit
2693  if (deps.Index(prjidx) == wxNOT_FOUND)
2694  {
2695 // Manager::Get()->GetMessageManager()->Log(m_PageIndex, _T("Adding dependency: %s"), prj->GetTitle().c_str()));
2696  deps.Add(prjidx);
2697  }
2698  return;
2699  }
2700 
2701  for (size_t i = 0; i < arr->GetCount(); ++i)
2702  {
2703  cbProject* thisprj = arr->Item(i);
2704  if (!Manager::Get()->GetProjectManager()->CausesCircularDependency(prj, thisprj))
2705  {
2706  // recursively check dependencies
2707  CalculateProjectDependencies(thisprj, deps);
2708 
2709  // find out project's index in full (open) projects array
2710  ProjectsArray* parr = Manager::Get()->GetProjectManager()->GetProjects();
2711  int idx = parr->Index(thisprj);
2712  if (idx != wxNOT_FOUND)
2713  {
2714  // avoid duplicates
2715  if (deps.Index(idx) == wxNOT_FOUND)
2716  {
2717 // Manager::Get()->GetMessageManager()->Log(m_PageIndex, _T("Adding dependency: %s"), thisprj->GetTitle().c_str()));
2718  deps.Add(idx);
2719  }
2720  }
2721  }
2722  else
2723  Manager::Get()->GetLogManager()->Log(F(_("Circular dependency detected between \"%s\" and \"%s\". Skipping..."), prj->GetTitle().wx_str(), thisprj->GetTitle().wx_str()), m_PageIndex, Logger::warning);
2724  }
2725 
2726  // always add the project in question
2727  if (deps.Index(prjidx) == wxNOT_FOUND)
2728  {
2729 // Manager::Get()->GetMessageManager()->Log(m_PageIndex, _T("Adding dependency: %s"), prj->GetTitle().c_str()));
2730  deps.Add(prjidx);
2731  }
2732 }
2733 
2734 int CompilerGCC::DoBuild(const wxString& target, bool clean, bool build, bool clearLog)
2735 {
2736  wxString realTarget = target;
2737  if (realTarget.IsEmpty())
2738  realTarget = GetTargetString();
2739 
2740  if (!StopRunningDebugger())
2741  return -1;
2742 
2743  if (!CheckProject())
2744  {
2745  // no active project
2747  return CompileFile(Manager::Get()->GetEditorManager()->GetActiveEditor()->GetFilename());
2748  return -1;
2749  }
2750 
2751  if (realTarget.IsEmpty())
2752  return -1;
2753 
2754  if (!m_IsWorkspaceOperation)
2755  {
2756  DoClearErrors();
2757  InitBuildLog(false);
2758  DoPrepareQueue(clearLog);
2759  if (clean)
2760  NotifyCleanProject(realTarget);
2761  }
2762 
2763  PreprocessJob(m_pProject, realTarget);
2764  if (m_BuildJobTargetsList.empty())
2765  return -1;
2766 
2767  InitBuildState(bjProject, realTarget);
2768  if (DoBuild(clean, build))
2769  return -2;
2770 
2771  return DoRunQueue();
2772 }
2773 
2774 int CompilerGCC::Build(const wxString& target)
2775 {
2776  m_LastBuildStep = true;
2777  return DoBuild(target, false, true);
2778 }
2779 
2781 {
2782  return Build(target ? target->GetTitle() : _T(""));
2783 }
2784 
2786 {
2787  return Rebuild(target ? target->GetTitle() : _T(""));
2788 }
2789 
2790 int CompilerGCC::Rebuild(const wxString& target)
2791 {
2792  m_LastBuildStep = Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/rebuild_seperately"), false);
2793  if (m_LastBuildStep)
2794  return DoBuild(target, true, true);
2795 
2796  int result = DoBuild(target, true, false);
2797  m_LastBuildStep = true;
2798  return result + DoBuild(target, false, true, false);
2799 }
2800 
2801 int CompilerGCC::DoWorkspaceBuild(const wxString& target, bool clean, bool build, bool clearLog)
2802 {
2803  wxString realTarget = target;
2804  if (realTarget.IsEmpty())
2805  realTarget = GetTargetString();
2806  if (realTarget.IsEmpty())
2807  return -1;
2808 
2809  if (!StopRunningDebugger())
2810  return -1;
2811 
2812  DoPrepareQueue(clearLog);
2813  if (clean)
2814  NotifyCleanWorkspace();
2815  m_IsWorkspaceOperation = true;
2816 
2817  InitBuildLog(true);
2818 
2819  // save files from all projects as they might require each other...
2820  ProjectsArray* arr = Manager::Get()->GetProjectManager()->GetProjects();
2821  if (arr)
2822  {
2823  for (size_t i = 0; i < arr->GetCount(); ++i)
2824  {
2825  cbProject* prj = arr->Item(i);
2826  if (prj && !prj->SaveAllFiles())
2827  Manager::Get()->GetLogManager()->Log(F(_("Could not save all files of %s..."), prj->GetTitle().wx_str()), m_PageIndex);
2828  }
2829  }
2830 
2831  // create list of jobs to run (project->realTarget pairs)
2832  PreprocessJob(0, realTarget);
2833  if (m_BuildJobTargetsList.empty())
2834  return -1;
2835 
2836  InitBuildState(bjWorkspace, realTarget);
2837 
2838  DoBuild(clean,build);
2839  m_IsWorkspaceOperation = false;
2840 
2841  return DoRunQueue();
2842 }
2843 
2845 {
2846  return DoWorkspaceBuild(target, false, true);
2847 }
2848 
2850 {
2851  m_LastBuildStep = Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/rebuild_seperately"), false);
2852  if (m_LastBuildStep)
2853  return DoWorkspaceBuild(target, true, true);
2854 
2855  int result = DoWorkspaceBuild(target, true, false);
2856  m_LastBuildStep = true;
2857  return result + DoWorkspaceBuild(target, false, true, false);
2858 }
2859 
2861 {
2862  return DoWorkspaceBuild(target, true, false);
2863 }
2864 
2866 {
2867  ResetBuildState();
2868  m_RunAfterCompile = false;
2869  if (!IsProcessRunning())
2870  return 0;
2871  if (!m_CommandQueue.LastCommandWasRun())
2872  LogMessage(_("Aborting build..."), cltInfo, ltMessages);
2873  wxKillError ret = wxKILL_OK;
2874 
2875  m_CommandQueue.Clear();
2876 
2877  for (CompilerProcess &p : m_CompilerProcessList)
2878  {
2879  if (!p.pProcess)
2880  continue;
2881 
2882  #if defined(WIN32) && defined(ENABLE_SIGTERM)
2883  ::GenerateConsoleCtrlEvent(0, p.PID);
2884  #endif
2885 
2886  // Close input pipe
2887  p.pProcess->CloseOutput();
2888  ((PipedProcess*) p.pProcess)->ForfeitStreams();
2889 
2890  wxLogNull nullLog;
2891  ret = wxProcess::Kill(p.PID, wxSIGKILL, wxKILL_CHILDREN);
2892 
2893  if (!platform::windows)
2894  {
2895  if (ret != wxKILL_OK)
2896  {
2897  // No need to tell the user about the errors - just keep him waiting.
2898  Manager::Get()->GetLogManager()->Log(F(_("Aborting process %ld ..."), p.PID), m_PageIndex);
2899  }
2900  else switch (ret)
2901  {
2902  case wxKILL_OK:
2903  Manager::Get()->GetLogManager()->Log(_("Process aborted (killed)."), m_PageIndex);
2904 // case wxKILL_ACCESS_DENIED: cbMessageBox(_("Access denied")); break;
2905 // case wxKILL_NO_PROCESS: cbMessageBox(_("No process")); break;
2906 // case wxKILL_BAD_SIGNAL: cbMessageBox(_("Bad signal")); break;
2907 // case wxKILL_ERROR: cbMessageBox(_("Unspecified error")); break;
2908  case wxKILL_ACCESS_DENIED: // fall-through
2909  case wxKILL_NO_PROCESS: // fall-through
2910  case wxKILL_BAD_SIGNAL: // fall-through
2911  case wxKILL_ERROR: // fall-through
2912  default: break;
2913  }
2914  }
2915  }
2916 
2917  ProjectManager *projectManager = Manager::Get()->GetProjectManager();
2918  if (projectManager->GetIsRunning() == this)
2919  projectManager->SetIsRunning(NULL);
2920  return ret;
2921 }
2922 
2924 {
2925  return m_BuildJob != bjIdle || IsProcessRunning() || m_CommandQueue.GetCount();
2926 }
2927 
2929 {
2930  if (!pf)
2931  return nullptr;
2932 
2933  if (!pf->buildTargets.GetCount())
2934  {
2935  cbMessageBox(_("That file isn't assigned to any target."),
2936  _("Information"), wxICON_INFORMATION);
2937  return nullptr;
2938  }
2939  // If a virtual target is selected, ask for build target.
2940  if (m_RealTargetIndex == -1)
2941  {
2942  int idx = DoGUIAskForTarget();
2943  if (idx == -1)
2944  return nullptr;
2945  return m_pProject->GetBuildTarget(idx);
2946  }
2947 
2948  // Use currently selected non-virtual target.
2949  // If the file is not added to this target return nullptr.
2950  const wxString &targetName = m_Targets[m_TargetIndex];
2951  if (std::find(pf->buildTargets.begin(), pf->buildTargets.end(), targetName) == pf->buildTargets.end())
2952  return nullptr;
2953  return m_pProject->GetBuildTarget(targetName);
2954 }
2955 
2957 {
2958  CheckProject();
2959  DoClearErrors();
2960  DoPrepareQueue(false);
2961 
2962  ProjectFile* pf = m_pProject ? m_pProject->GetFileByFilename(file, true, false) : 0;
2963  ProjectBuildTarget* bt = GetBuildTargetForFile(pf);
2964 
2965  PrintBanner(baBuildFile, m_pProject, bt);
2966 
2967  if ( !CompilerValid(bt).isValid )
2968  return -1;
2969  if (!pf) // compile single file not belonging to a project
2970  return CompileFileWithoutProject(file);
2971  if (!bt)
2972  {
2973  const wxString err(_("error: Cannot find target for file"));
2974  LogMessage(pf->relativeToCommonTopLevelPath + _(": ") + err, cltError);
2975  LogWarningOrError(cltError, m_pProject, pf->relativeToCommonTopLevelPath, wxEmptyString, err);
2976  return -2;
2977  }
2978  if (m_pProject)
2979  wxSetWorkingDirectory(m_pProject->GetBasePath());
2980  return CompileFileDefault(m_pProject, pf, bt); // compile file using default build system
2981 }
2982 
2984 {
2985  // compile single file not belonging to a project
2986  Manager::Get()->GetEditorManager()->Save(file);
2987 
2988  // switch to the default compiler
2989  SwitchCompiler(CompilerFactory::GetDefaultCompilerID());
2991 
2993 
2994  // get compile commands for file (always linked as console-executable)
2995  DirectCommands dc(this, compiler, 0, m_PageIndex);
2996  wxArrayString compile = dc.GetCompileSingleFileCommand(file);
2997  AddToCommandQueue(compile);
2998 
2999  return DoRunQueue();
3000 }
3001 
3003 {
3005  if (!compiler)
3006  {
3007  const wxString &err = wxString::Format(_("error: Cannot build file for target '%s'. Compiler '%s' cannot be found!"),
3008  bt->GetTitle().wx_str(), bt->GetCompilerID().wx_str());
3009  LogMessage(pf->relativeToCommonTopLevelPath + _(": ") + err, cltError);
3010  LogWarningOrError(cltError, project, pf->relativeToCommonTopLevelPath, wxEmptyString, err);
3011  return -3;
3012  }
3013 
3014  DirectCommands dc(this, compiler, project, m_PageIndex);
3015  wxArrayString compile = dc.CompileFile(bt, pf);
3016  AddToCommandQueue(compile);
3017 
3018  return DoRunQueue();
3019 }
3020 
3021 // events
3022 
3024 {
3025  if (IsProcessRunning())
3026  {
3027  for (const CompilerProcess &p : m_CompilerProcessList)
3028  {
3029  if (p.pProcess && (static_cast<PipedProcess*>(p.pProcess))->HasInput())
3030  {
3031  event.RequestMore();
3032  break;
3033  }
3034  }
3035  }
3036  else
3037  event.Skip();
3038 }
3039 
3040 void CompilerGCC::OnTimer(cb_unused wxTimerEvent& event)
3041 {
3042  wxWakeUpIdle();
3043 }
3044 
3045 void CompilerGCC::OnRun(cb_unused wxCommandEvent& event)
3046 {
3047  if (Run() == 0)
3048  DoRunQueue();
3049 }
3050 
3052 {
3053  ProjectBuildTarget* target = 0;
3054  m_RunAfterCompile = true;
3055  Build(target);
3056 }
3057 
3059 {
3060  int bak = m_RealTargetIndex;
3061  if (event.GetId() == idMenuCompileFromProjectManager)
3062  {
3063  // we 're called from a menu in ProjectManager
3064  // let's check the selected project...
3065  DoSwitchProjectTemporarily();
3066  }
3067  ProjectBuildTarget* target = 0;
3068  Build(target);
3069  m_RealTargetIndex = bak;
3070 }
3071 
3073 {
3074  // TODO (Rick#1#): Clean the file so it will always recompile
3075  wxFileName file;
3076  if (event.GetId() == idMenuCompileFileFromProjectManager)
3077  PrepareCompileFilePM(file);
3078  else
3079  PrepareCompileFile(file);
3080 
3081  StartCompileFile(file);
3082 }
3083 
3085 {
3086  if (event.GetId() == idMenuCleanFileFromProjectManager)
3087  {
3088  FileTreeData* ftd = DoSwitchProjectTemporarily();
3089  ProjectFile* pf = ftd->GetProjectFile();
3090  if (!pf)
3091  return;
3092 
3093  ProjectBuildTarget* bt = GetBuildTargetForFile(pf);
3094  if (!bt)
3095  return;
3096 
3098  if (!compiler)
3099  return;
3100 
3101  if ( !CheckProject() ) // ensures m_pProject is not NULL
3102  return;
3103 
3104  wxSetWorkingDirectory(m_pProject->GetBasePath());
3105 
3106  wxFileName fn(pf->GetObjName());
3107  wxString obj_name = (compiler->GetSwitches().UseFlatObjects) ? fn.GetFullName() : fn.GetFullPath();
3108  wxString obj_file = wxFileName(bt->GetObjectOutput() + wxFILE_SEP_PATH + obj_name).GetFullPath();
3110 
3111  wxFileName obj_fn(obj_file);
3112  if ( obj_fn.FileExists() )
3113  {
3114  if ( wxRemoveFile(obj_file) )
3115  Manager::Get()->GetLogManager()->DebugLog(F(_T("File has been removed: %s"), obj_file.wx_str()));
3116  else
3117  Manager::Get()->GetLogManager()->DebugLog(F(_T("Removing file failed for: %s"), obj_file.wx_str()));
3118  }
3119  else
3120  Manager::Get()->GetLogManager()->DebugLog(F(_T("File to remove does not exist: %s"), obj_file.wx_str()));
3121  }
3122 }
3123 
3125 {
3126  CheckProject();
3127  AnnoyingDialog dlg(_("Rebuild project"),
3128  _("Rebuilding the project will cause the deletion of all "
3129  "object files and building it from scratch.\nThis action "
3130  "might take a while, especially if your project contains "
3131  "more than a few files.\nAnother factor is your CPU "
3132  "and the available system memory.\n\n"
3133  "Are you sure you want to rebuild the entire project?"),
3134  wxART_QUESTION);
3135  if (m_pProject && dlg.ShowModal() == AnnoyingDialog::rtNO)
3136  return;
3137 
3138  int bak = m_RealTargetIndex;
3139  if (event.GetId() == idMenuRebuildFromProjectManager)
3140  {
3141  // we 're called from a menu in ProjectManager
3142  // let's check the selected project...
3143  DoSwitchProjectTemporarily();
3144  }
3145  ProjectBuildTarget* target = 0;
3146  Rebuild(target);
3147  m_RealTargetIndex = bak;
3148 }
3149 
3151 {
3152  BuildWorkspace();
3153 }
3154 
3156 {
3157  AnnoyingDialog dlg(_("Rebuild workspace"),
3158  _("Rebuilding ALL the open projects will cause the deletion of all "
3159  "object files and building them from scratch.\nThis action "
3160  "might take a while, especially if your projects contain "
3161  "more than a few files.\nAnother factor is your CPU "
3162  "and the available system memory.\n\n"
3163  "Are you sure you want to rebuild ALL the projects?"),
3164  wxART_QUESTION);
3165  if (dlg.ShowModal() == AnnoyingDialog::rtNO)
3166  return;
3167 
3168  RebuildWorkspace();
3169 }
3170 
3172 {
3173  AnnoyingDialog dlg(_("Clean project"),
3174  _("Cleaning ALL the open projects will cause the deletion "
3175  "of all relevant object files.\nThis means that you will "
3176  "have to build ALL your projects from scratch next time you "
3177  "'ll want to build them.\nThat action "
3178  "might take a while, especially if your projects contain "
3179  "more than a few files.\nAnother factor is your CPU "
3180  "and the available system memory.\n\n"
3181  "Are you sure you want to proceed to cleaning?"),
3182  wxART_QUESTION);
3183  if (dlg.ShowModal() == AnnoyingDialog::rtNO)
3184  return;
3185 
3186  CleanWorkspace();
3187 }
3188 
3190 {
3191  CheckProject();
3192  AnnoyingDialog dlg(_("Clean project"),
3193  _("Cleaning the target or project will cause the deletion "
3194  "of all relevant object files.\nThis means that you will "
3195  "have to build your project from scratch next time you "
3196  "'ll want to build it.\nThat action "
3197  "might take a while, especially if your project contains "
3198  "more than a few files.\nAnother factor is your CPU "
3199  "and the available system memory.\n\n"
3200  "Are you sure you want to proceed to cleaning?"),
3201  wxART_QUESTION);
3202  if (m_pProject && dlg.ShowModal() == AnnoyingDialog::rtNO)
3203  return;
3204 
3205  int bak = m_RealTargetIndex;
3206  if (event.GetId() == idMenuCleanFromProjectManager)
3207  {
3208  // we 're called from a menu in ProjectManager
3209  // let's check the selected project...
3210  DoSwitchProjectTemporarily();
3211  }
3212  ProjectBuildTarget* target = 0;
3213  Clean(target);
3214  m_RealTargetIndex = bak;
3215 }
3216 
3218 {
3220  wxTreeCtrl* tree = manager->GetUI().GetTree();
3221  wxTreeItemId sel = manager->GetUI().GetTreeSelection();
3222  FileTreeData* ftd = sel.IsOk() ? (FileTreeData*)tree->GetItemData(sel) : 0;
3223  if (ftd)
3224  {
3225  // 'configure' selected target, if other than 'All'
3226  ProjectBuildTarget* target = 0;
3227  cbProject *currentProject = ftd->GetProject();
3228  if (currentProject == m_pProject)
3229  {
3230  if (m_RealTargetIndex != -1)
3231  target = m_pProject->GetBuildTarget(m_RealTargetIndex);
3232  }
3233  else if (m_RealTargetIndex != -1 && m_pProject)
3234  {
3235  // If the users wants to change the options for the non-active project,
3236  // we try to find a target with the same name as the currently selected
3237  // target in the active project (if the target is not 'All').
3238  ProjectBuildTarget *activeTarget = m_pProject->GetBuildTarget(m_RealTargetIndex);
3239  if (activeTarget)
3240  target = currentProject->GetBuildTarget(activeTarget->GetTitle());
3241  }
3242  Configure(currentProject, target);
3243  }
3244  else
3245  {
3246  if (cbProject* prj = Manager::Get()->GetProjectManager()->GetActiveProject())
3247  Configure(prj);
3248  }
3249 }
3250 
3252 {
3253  int bak = m_RealTargetIndex;
3254  // we 're called from a menu in ProjectManager
3255  int idx = DoGUIAskForTarget();
3256  if (idx == -1)
3257  return;
3258  else
3259  m_RealTargetIndex = idx; // TODO: check
3260 
3261  // let's check the selected project...
3262  DoSwitchProjectTemporarily();
3263 
3264  ProjectBuildTarget* target = 0;
3265  m_RealTargetIndex = bak;
3266  Configure(m_pProject, target);
3267 }
3268 
3270 {
3271  KillProcess();
3272 }
3273 
3275 {
3276  int selection = -1;
3277  bool updateTools = false;
3278 
3279  if (event.GetId() == idToolTarget)
3280  { // through the toolbar
3281  selection = event.GetSelection();
3282  }
3283  else if (event.GetId() == idMenuSelectTargetDialog)
3284  {
3285  // The select target menu is clicked, so we want to show a dialog with all targets
3286  IncrementalSelectArrayIterator iterator(m_Targets);
3287  IncrementalSelectDialog dlg(Manager::Get()->GetAppWindow(), &iterator, _("Select target..."),
3288  _("Choose target:"));
3289  if (dlg.ShowModal() == wxID_OK)
3290  {
3291  selection = dlg.GetSelection();
3292  updateTools = true;
3293  }
3294  }
3295  else
3296  { // through Build->SelectTarget
3297  selection = event.GetId() - idMenuSelectTargetOther[0];
3298  updateTools = true;
3299  }
3300 
3301  if (selection >= 0)
3302  {
3303  Manager::Get()->GetProjectManager()->GetWorkspace()->SetPreferredTarget( GetTargetString(selection) );
3304  DoUpdateTargetMenu(selection);
3305  if (updateTools)
3306  m_pToolTarget->SetSelection(selection);
3307  }
3308 }
3309 
3311 {
3312  DoGotoNextError();
3313 }
3314 
3316 {
3317  DoGotoPreviousError();
3318 }
3319 
3321 {
3322  DoClearErrors();
3323 }
3324 
3326 {
3329  wxMenuBar* mbar = Manager::Get()->GetAppFrame()->GetMenuBar();
3330  bool running = IsRunning();
3331 
3332  cbPlugin *runningPlugin = Manager::Get()->GetProjectManager()->GetIsRunning();
3333  bool otherRunning = runningPlugin && runningPlugin != this;
3334  if (mbar)
3335  {
3336  mbar->Enable(idMenuCompile, !running && (prj || ed) && !otherRunning);
3337  mbar->Enable(idMenuBuildWorkspace, !running && prj && !otherRunning);
3338 // mbar->Enable(idMenuCompileFromProjectManager, !running && prj);
3339  mbar->Enable(idMenuCompileFile, !running && ed && !otherRunning);
3340 // mbar->Enable(idMenuCompileFileFromProjectManager, !running && prj);
3341 // mbar->Enable(idMenuCleanFileFromProjectManager, !running && prj);
3342  mbar->Enable(idMenuRebuild, !running && prj && !otherRunning);
3343  mbar->Enable(idMenuRebuildWorkspace, !running && prj && !otherRunning);
3344 // mbar->Enable(idMenuRebuildFromProjectManager, !running && prj);
3345  mbar->Enable(idMenuClean, !running && prj && !otherRunning);
3346  mbar->Enable(idMenuCleanWorkspace, !running && prj && !otherRunning);
3347 // mbar->Enable(idMenuCleanFromProjectManager, !running && prj);
3348  mbar->Enable(idMenuCompileAndRun, !running && (prj || ed) && !otherRunning);
3349  mbar->Enable(idMenuRun, !running && (prj || ed) && !otherRunning);
3350  mbar->Enable(idMenuKillProcess, running);
3351  mbar->Enable(idMenuSelectTarget, !running && prj && !otherRunning);
3352 
3353  mbar->Enable(idMenuNextError, !running && (prj || ed) && m_Errors.HasNextError() && !otherRunning);
3354  mbar->Enable(idMenuPreviousError, !running && (prj || ed) && m_Errors.HasPreviousError() && !otherRunning);
3355  mbar->Enable(idMenuClearErrors, !otherRunning);
3356 
3357  // Project menu
3358  mbar->Enable(idMenuProjectCompilerOptions, !running && prj && !otherRunning);
3359  }
3360 
3361  // enable/disable compiler toolbar buttons
3362  wxToolBar* tbar = m_pTbar;//Manager::Get()->GetAppWindow()->GetToolBar();
3363  if (tbar)
3364  {
3365  tbar->EnableTool(idMenuCompile, !running && (prj || ed) && !otherRunning);
3366  tbar->EnableTool(idMenuRun, !running && (prj || ed) && !otherRunning);
3367  tbar->EnableTool(idMenuCompileAndRun, !running && (prj || ed) && !otherRunning);
3368  tbar->EnableTool(idMenuRebuild, !running && prj && !otherRunning);
3369  tbar->EnableTool(idMenuKillProcess, running && prj);
3370  tbar->EnableTool(idMenuSelectTargetDialog, !running && prj && !otherRunning);
3371 
3372  m_pToolTarget = XRCCTRL(*tbar, "idToolTarget", wxChoice);
3373  if (m_pToolTarget)
3374  m_pToolTarget->Enable(!running && prj && !otherRunning);
3375  }
3376 
3377  // allow other UpdateUI handlers to process this event
3378  // *very* important! don't forget it...
3379  event.Skip();
3380 }
3381 
3383 {
3384  //NOTE: this function is also called on PROJECT_TARGETS_MODIFIED events
3385  // to keep the combobox in sync
3386 
3388 // DBGLOG(_T("Active: %s, Event: %s"),
3389 // active ? active->GetTitle().c_str() : _T("<none>"),
3390 // event.GetProject()->GetTitle().c_str());
3391  if (event.GetProject() == active)
3392  UpdateProjectTargets(event.GetProject());
3393 }
3394 
3396 {
3397 }
3398 
3400 {
3401  // just make sure we don't keep an invalid pointer around
3402  if (m_pProject == event.GetProject())
3403  m_pProject = 0;
3404 }
3405 
3407 {
3408  ClearLog(false);
3409  DoClearErrors();
3410 }
3411 
3413 {
3414  cbProject* prj = event.GetProject();
3415  EditorBase* eb = event.GetEditor();
3416  if (!prj || !eb)
3417  {
3418 // Manager::Get()->GetLogManager()->DebugLog(_T("Compile file request skipped due to missing project or editor."));
3419  return;
3420  }
3421 
3422  const wxString& ed_filename = eb->GetFilename();
3423  wxFileName wx_filename;
3424  wx_filename.Assign(ed_filename);
3425  wx_filename.MakeRelativeTo( prj->GetBasePath() );
3426 
3427  wxString filepath = wx_filename.GetFullPath();
3428  if (filepath.IsEmpty())
3429  {
3430 // Manager::Get()->GetLogManager()->DebugLog(_T("Compile file request skipped due to unresolvable file."));
3431  return;
3432  }
3433 
3434  ProjectFile* pf = prj->GetFileByFilename(UnixFilename(filepath), true, false);
3435  if (!pf || !pf->buildTargets.GetCount())
3436  {
3437 // Manager::Get()->GetLogManager()->DebugLog(F(_T("Skipping incoming compile file request for '%s' (no project file or build targets)."), filepath.wx_str()));
3438  return;
3439  }
3440 
3441  ProjectBuildTarget* bt = 0;
3442  if (pf->buildTargets.GetCount() == 1)
3443  bt = prj->GetBuildTarget(pf->buildTargets[0]);
3444  else // belongs to two or more build targets, but maybe a valid virtual target is selected
3445  bt = prj->GetBuildTarget(m_RealTargetIndex); // pick the selected target
3446  if (!bt)
3447  {
3448 // Manager::Get()->GetLogManager()->DebugLog(F(_T("Skipping incoming compile file request for '%s' (no build target)."), filepath.wx_str()));
3449  return;
3450  }
3451 
3452  Manager::Get()->GetLogManager()->DebugLog(F(_T("Executing incoming compile file request for '%s'."), filepath.wx_str()));
3453  CompileFileDefault(prj, pf, bt);
3454 }
3455 
3457 {
3458  wxString msg = event.GetString();
3459  if (!msg.IsEmpty() &&
3460  !msg.Matches(_T("# ??*"))) // gcc 3.4 started displaying a line like this filter
3461  // when calculating dependencies. Until I check out
3462  // why this happens (and if there is a switch to
3463  // turn it off), I put this condition here to avoid
3464  // displaying it...
3465  {
3466  AddOutputLine(msg);
3467  }
3468 }
3469 
3471 {
3472  wxString msg = event.GetString();
3473  if (!msg.IsEmpty())
3474  AddOutputLine(msg);
3475 }
3476 
3478 {
3479  const int index = event.GetX();
3480  OnJobEnd(index, event.GetInt());
3481 }
3482 
3483 void CompilerGCC::AddOutputLine(const wxString& output, bool forceErrorColour)
3484 {
3485  wxArrayString ignore_output = Manager::Get()->GetConfigManager(_T("compiler"))->ReadArrayString(_T("/ignore_output"));
3486  if (!ignore_output.IsEmpty())
3487  {
3488  for (size_t i = 0; i<ignore_output.GetCount(); ++i)
3489  {
3490  if (output.Find(ignore_output.Item(i)) != wxNOT_FOUND)
3491  {
3492  Manager::Get()->GetLogManager()->DebugLog(F(_T("Ignoring compiler output: %s"), output.wx_str()));
3493  return;
3494  }
3495  }
3496  }
3497 
3498  Compiler* compiler = CompilerFactory::GetCompiler(m_CompilerId);
3499  if (!compiler)
3500  return;
3501  CompilerLineType clt = compiler->CheckForWarningsAndErrors(output);
3502 
3503  // if max_errors reached, display a one-time message and do not log any more
3504  size_t maxErrors = Manager::Get()->GetConfigManager(_T("compiler"))->ReadInt(_T("/max_reported_errors"), 50);
3505  if (maxErrors > 0 && m_Errors.GetCount(cltError) == maxErrors)
3506  {
3507  // no matter what, everything goes into the build log
3508  LogMessage(output, clt, ltFile, forceErrorColour);
3509 
3510  if (!m_NotifiedMaxErrors)
3511  {
3512  m_NotifiedMaxErrors = true;
3513 
3514  // if we reached the max errors count, notify about it
3515  LogWarningOrError(cltNormal, 0, wxEmptyString, wxEmptyString, _("More errors follow but not being shown."));
3516  LogWarningOrError(cltNormal, 0, wxEmptyString, wxEmptyString, _("Edit the max errors limit in compiler options..."));
3517  }
3518  return;
3519  }
3520 
3521  // log to build messages if info/warning/error (aka != normal)
3522  if (clt != cltNormal)
3523  {
3524  // actually log message
3525  wxString last_error_filename = compiler->GetLastErrorFilename();
3526  if ( UseMake() )
3527  {
3528  wxFileName last_error_file(last_error_filename);
3529  if (!last_error_file.IsAbsolute())
3530  {
3531  cbProject* project = m_pProject;
3532  if (m_pLastBuildingTarget)
3533  project = m_pLastBuildingTarget->GetParentProject();
3534  else
3535  {
3536  AskForActiveProject();
3537  project = m_pProject;
3538  }
3539  last_error_file = project->GetExecutionDir() + wxFileName::GetPathSeparator() + last_error_file.GetFullPath();
3540  last_error_file.MakeRelativeTo(project->GetBasePath());
3541  last_error_filename = last_error_file.GetFullPath();
3542  }
3543  }
3544  wxString msg = compiler->GetLastError();
3545  if (!compiler->WithMultiLineMsg() || (compiler->WithMultiLineMsg() && !msg.IsEmpty()))
3546  LogWarningOrError(clt, m_pBuildingProject, last_error_filename, compiler->GetLastErrorLine(), msg);
3547  }
3548 
3549  // add to log
3550  LogMessage(output, clt, ltAll, forceErrorColour);
3551 }
3552 
3553 void CompilerGCC::LogWarningOrError(CompilerLineType lt, cbProject* prj, const wxString& filename, const wxString& line, const wxString& msg)
3554 {
3555  // add build message
3556  wxArrayString errors;
3557  errors.Add(filename);
3558  errors.Add(line);
3559 
3560  wxString msgFix = msg; msgFix.Replace(wxT("\t"), wxT(" "));
3561  errors.Add(msgFix);
3562 
3563  Logger::level lv = (lt == cltError) ? Logger::error
3564  : (lt == cltWarning) ? Logger::warning : Logger::info;
3565 
3566  // when there are many lines (thousands) of output, auto fitting column width
3567  // is very expensive, so rate limit it to a maximum of 1 fit per 3 seconds
3568  static wxDateTime lastAutofitTime = wxDateTime((time_t)0);
3569  if ( lastAutofitTime < (wxDateTime::Now() - wxTimeSpan::Seconds(3)) )
3570  {
3571  lastAutofitTime = wxDateTime::Now();
3572  m_pListLog->Append(errors, lv, 2); // auto fit the 'Message' column
3573  }
3574  else
3575  m_pListLog->Append(errors, lv);
3576 
3577  // add to error keeping struct
3578  m_Errors.AddError(lt, prj, filename, line.IsEmpty() ? 0 : atoi(wxSafeConvertWX2MB(line.wc_str())), msg);
3579 }
3580 
3581 void CompilerGCC::LogMessage(const wxString& message, CompilerLineType lt, LogTarget log, bool forceErrorColour, bool isTitle, bool updateProgress)
3582 {
3583  // Strip the
3584  wxString msgInput, msg;
3585  if (message.StartsWith(COMPILER_SIMPLE_LOG, &msg))
3586  msgInput = msg;
3587  else
3588  msgInput = message;
3589 
3590  if (msgInput.StartsWith(COMPILER_NOTE_ID_LOG, &msg))
3591  LogWarningOrError(lt, 0, wxEmptyString, wxEmptyString, msg);
3592  else if (msgInput.StartsWith(COMPILER_WARNING_ID_LOG, &msg))
3593  {
3594  if (lt != cltError)
3595  lt = cltWarning;
3596  LogWarningOrError(lt, nullptr, wxEmptyString, wxEmptyString, msg);
3597  }
3598  else if (msgInput.StartsWith(COMPILER_ERROR_ID_LOG, &msg))
3599  {
3600  if (lt != cltError)
3601  lt = cltWarning;
3602  LogWarningOrError(cltError, nullptr, wxEmptyString, wxEmptyString, msg);
3603  }
3604  else
3605  msg = msgInput;
3606 
3607  // log file
3608  if (log & ltFile)
3609  {
3610  if (forceErrorColour)
3611  m_BuildLogContents << _T("<font color=\"#a00000\">");
3612  else if (lt == cltError)
3613  m_BuildLogContents << _T("<font color=\"#ff0000\">");
3614  else if (lt == cltWarning)
3615  m_BuildLogContents << _T("<font color=\"#0000ff\">");
3616 
3617  if (isTitle)
3618  m_BuildLogContents << _T("<b>");
3619 
3620  // Replace the script quotation marks family by "
3621  // Using UTF codes to avoid "error: converting to execution character set: Illegal byte sequence"
3622  // -> for UTF codes see here: http://www.utf8-chartable.de/unicode-utf8-table.pl
3623  wxString sQuoted(msg);
3624  wxString sGA = wxString::FromUTF8("\x60"); // GRAVE ACCENT
3625  wxString sAA = wxString::FromUTF8("\xC2\xB4"); // ACUTE ACCENT
3626  sQuoted.Replace(sGA, _T("\""), true);
3627  sQuoted.Replace(sAA, _T("\""), true);
3628  // avoid conflicts with html-tags
3629  sQuoted.Replace(_T("&"), _T("&amp;"), true);
3630  sQuoted.Replace(_T("<"), _T("&lt;"), true);
3631  sQuoted.Replace(_T(">"), _T("&gt;"), true);
3632  m_BuildLogContents << sQuoted;
3633 
3634  if (isTitle)
3635  m_BuildLogContents << _T("</b>");
3636 
3637  if (lt == cltWarning || lt == cltError || forceErrorColour)
3638  m_BuildLogContents << _T("</font>");
3639 
3640  m_BuildLogContents << _T("<br />\n");
3641  }
3642 
3643  // log window
3644  if (log & ltMessages)
3645  {
3646  Logger::level lv = isTitle ? Logger::caption : Logger::info;
3647  if (forceErrorColour)
3648  lv = Logger::critical;
3649  else if (lt == cltError)
3650  lv = Logger::error;
3651  else if (lt == cltWarning)
3652  lv = Logger::warning;
3653 
3654  wxString progressMsg;
3655  if (updateProgress && m_CurrentProgress < m_MaxProgress)
3656  {
3657  ++m_CurrentProgress;
3658  if (m_LogBuildProgressPercentage)
3659  {
3660  float p = (float)(m_CurrentProgress * 100.0f) / (float)m_MaxProgress;
3661  progressMsg.Printf(_T("[%5.1f%%] "), p);
3662  }
3663  if (m_pLog->progress)
3664  {
3665  m_pLog->progress->SetRange(m_MaxProgress);
3666  m_pLog->progress->SetValue(m_CurrentProgress);
3667  }
3668  }
3669 
3670  Manager::Get()->GetLogManager()->Log(progressMsg + msg, m_PageIndex, lv);
3671  Manager::Get()->GetLogManager()->LogToStdOut(progressMsg + msg);
3672  }
3673 }
3674 
3675 void CompilerGCC::InitBuildLog(bool workspaceBuild)
3676 {
3677  wxString title;
3678  wxString basepath;
3679  wxString basename;
3680  if (!workspaceBuild && m_pProject)
3681  {
3682  title = m_pProject->GetTitle();
3683  basepath = m_pProject->GetBasePath();
3684  basename = wxFileName(m_pProject->GetFilename()).GetName();
3685  }
3686  else if (workspaceBuild)
3687  {
3689  title = wksp->GetTitle();
3690  basepath = wxFileName(wksp->GetFilename()).GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
3691  basename = wxFileName(wksp->GetFilename()).GetName();
3692  }
3693 
3694  if (basename.IsEmpty())
3695  basename = _T("unnamed");
3696 
3697  // init HTML build log
3698  m_BuildStartTime = wxDateTime::Now();
3699  m_BuildLogTitle = title + _(" build log");
3700  m_BuildLogFilename = basepath;
3701  m_BuildLogFilename << basename << _T("_build_log.html");
3702  m_BuildLogContents.Clear();
3703  m_MaxProgress = 0;
3704  m_CurrentProgress = 0;
3705 }
3706 
3708 {
3709  // if not enabled in the configuration, leave
3710  if (!Manager::Get()->GetConfigManager(_T("compiler"))->ReadBool(_T("/save_html_build_log"), false))
3711  return;
3712 
3713  if (m_BuildLogFilename.IsEmpty())
3714  return;
3715 
3716  // NOTE: if we want to add a CSS later on, we 'd have to edit:
3717  // - this function and
3718  // - LogMessage()
3719 
3720  wxFile f(m_BuildLogFilename, wxFile::write);
3721  if (!f.IsOpened())
3722  return;
3723 
3724  // first output the standard header blurb
3725  f.Write(_T("<html>\n"));
3726  f.Write(_T("<head>\n"));
3727  f.Write(_T("<title>") + m_BuildLogTitle + _T("</title>\n"));
3728  f.Write(_T("<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"));
3729 
3730  f.Write(_T("</head>\n"));
3731  f.Write(_T("<body>\n"));
3732 
3733  // use fixed-width font
3734  f.Write(_T("<tt>\n"));
3735 
3736  // write the start-end time of the build
3737  f.Write(_("Build started on: "));
3738  f.Write(_T("<u>"));
3739  f.Write(m_BuildStartTime.Format(_T("%d-%m-%Y at %H:%M.%S")));
3740  f.Write(_T("</u><br />\n"));
3741  f.Write(_("Build ended on: "));
3742  f.Write(_T("<u>"));
3743  f.Write(wxDateTime::Now().Format(_T("%d-%m-%Y at %H:%M.%S")));
3744  f.Write(_T("</u><p />\n"));
3745 
3746  // output the main body
3747  f.Write(m_BuildLogContents);
3748 
3749  // done with fixed-width font
3750  f.Write(_T("</tt>\n"));
3751 
3752  // finally output the footer
3753  f.Write(_T("</body>\n"));
3754  f.Write(_T("</html>\n"));
3755 
3756  Manager::Get()->GetLogManager()->Log(_("Build log saved as: "), m_PageIndex);
3757  wxString tempBuildLogFilename = m_BuildLogFilename;
3758  tempBuildLogFilename.Replace(_("\\"), _("/"));
3759  wxURI tmpFilename = tempBuildLogFilename;
3760 
3761  Manager::Get()->GetLogManager()->Log(F(_T("file://%s"), tmpFilename.BuildURI().wx_str()), m_PageIndex, Logger::warning);
3762 }
3763 
3764 void CompilerGCC::OnJobEnd(size_t procIndex, int exitCode)
3765 {
3766 // Manager::Get()->GetMessageManager()->Log(m_PageIndex, _T("JobDone: index=%u, exitCode=%d"), procIndex, exitCode));
3767  m_timerIdleWakeUp.Stop();
3768  CompilerProcess &process = m_CompilerProcessList.at(procIndex);
3769  process.PID = 0;
3770  process.pProcess = nullptr;
3771  wxString oFile = UnixFilename(process.OutputFile);
3772 
3773  if (m_LastExitCode == 0 || exitCode != 0) // prevent exit errors from being overwritten during multi-threaded build
3774  m_LastExitCode = exitCode;
3775  bool success(exitCode == 0);
3776  Compiler* compiler = CompilerFactory::GetCompiler(m_CompilerId);
3777  if (compiler)
3778  success = (exitCode >= 0) && (exitCode <= compiler->GetSwitches().statusSuccess);
3779 
3780  Manager::Get()->GetMacrosManager()->ReplaceMacros(oFile); // might contain macros!
3781  if (success && !oFile.IsEmpty())
3782  {
3783  wxLogNull silence; // In case opening the file fails
3784  wxFFile f(oFile.wx_str(), _T("r"));
3785  if (f.IsOpened())
3786  {
3787  size_t size = f.Length();
3788  f.Close();
3789 
3790  float displaySize;
3791  wxString units;
3792  if (size < 1024)
3793  {
3794  displaySize = (float)size;
3795  units = _("bytes");
3796  }
3797  else if (size < 1048576)
3798  {
3799  displaySize = (float)size / 1024.0f;
3800  units = _("KB");
3801  }
3802  else
3803  {
3804  displaySize = (float)size / 1048576.0f;
3805  units = _("MB");
3806  }
3807  wxString msg;
3808  msg.Printf(_("Output file is %s with size %.2f %s"), oFile.wx_str(), displaySize, units.wx_str());
3809  LogMessage(msg, cltNormal);
3810  }
3811  }
3812  if (success)
3813  m_LastExitCode = 0;
3814  if (m_CommandQueue.GetCount() != 0 && success)
3815  DoRunQueue(); // continue running commands while last exit code was 0.
3816  else
3817  {
3818  if (success)
3819  {
3820  if (IsProcessRunning())
3821  {
3822  DoRunQueue();
3823  return;
3824  }
3825 
3826  while (1)
3827  {
3828  BuildStateManagement();
3829  if (m_CommandQueue.GetCount())
3830  {
3831  DoRunQueue();
3832  return;
3833  }
3834  if (m_BuildState == bsNone && m_NextBuildState == bsNone)
3835  break;
3836  }
3837  }
3838  m_CommandQueue.Clear();
3839  ResetBuildState();
3840  // clear any remaining jobs (e.g. in case of build errors)
3841  while (!m_BuildJobTargetsList.empty())
3842  m_BuildJobTargetsList.pop();
3843 
3844  wxString msg = wxString::Format(_("Process terminated with status %d (%s)"), exitCode, GetMinSecStr().wx_str());
3845  if (m_LastExitCode == exitCode) // do not log extra if there is failure during multi-threaded build
3846  LogMessage(msg, success ? cltWarning : cltError, ltAll, !success);
3847  if (!m_CommandQueue.LastCommandWasRun())
3848  {
3849  if ( !IsProcessRunning() )
3850  {
3851  msg = wxString::Format(_("%s (%s)"), GetErrWarnStr().wx_str(), GetMinSecStr().wx_str());
3852  success = (m_LastExitCode >= 0) && (m_LastExitCode <= compiler->GetSwitches().statusSuccess);
3853  LogMessage(msg, success ? cltWarning : cltError, ltAll, !success);
3854  LogWarningOrError(cltNormal, 0, wxEmptyString, wxEmptyString,
3855  wxString::Format(_("=== Build %s: %s ==="),
3856  wxString(m_LastExitCode == 0 ? _("finished") : _("failed")).wx_str(), msg.wx_str()));
3857  m_pListLog->AutoFitColumns(2);
3858  SaveBuildLog();
3859  }
3860  if (!Manager::IsBatchBuild() && m_pLog->progress)
3861  m_pLog->progress->SetValue(0);
3862  }
3863  else
3864  {
3865  // last command was "Run"
3866  // force exit code to zero (0) or else debugger will think build failed if last run returned non-zero...
3867 // TODO (mandrav##): Maybe create and use GetLastRunExitCode()? Is it needed?
3868  m_LastExitCode = 0; // *might* not be needed any more, see NotifyJobDone()
3869  }
3870  Manager::Get()->GetLogManager()->Log(_T(" "), m_PageIndex); // blank line
3871 
3872  NotifyJobDone();
3873 
3874  if (!Manager::IsBatchBuild() && m_Errors.GetCount(cltError))
3875  {
3876  if (Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_show_build_errors"), true))
3877  {
3879  Manager::Get()->ProcessEvent(evtShow);
3880  }
3881  CodeBlocksLogEvent evtSwitch(cbEVT_SWITCH_TO_LOG_WINDOW, m_pListLog);
3882  Manager::Get()->ProcessEvent(evtSwitch);
3883 
3884  if (Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_focus_build_errors"), true))
3885  m_pListLog->FocusError(m_Errors.GetFirstError());
3886  }
3887  else
3888  {
3889  if (m_RunAfterCompile)
3890  {
3891  m_RunAfterCompile = false;
3892  if (Run() == 0)
3893  DoRunQueue();
3894  }
3895  else if (!Manager::IsBatchBuild())
3896  {
3897  // switch to the "Build messages" window only if the active log window is "Build log"
3899  Manager::Get()->ProcessEvent(evtGetActive);
3900  if (evtGetActive.logger == m_pLog)
3901  {
3902  // don't close the message manager (if auto-hiding), if warnings are required to keep it open
3903  if (m_Errors.GetCount(cltWarning) &&
3904  Manager::Get()->GetConfigManager(_T("message_manager"))->ReadBool(_T("/auto_show_build_warnings"), true))
3905  {
3907  Manager::Get()->ProcessEvent(evtShow);
3908 
3909  CodeBlocksLogEvent evtSwitch(cbEVT_SWITCH_TO_LOG_WINDOW, m_pListLog);
3910  Manager::Get()->ProcessEvent(evtSwitch);
3911  }
3912  else // if message manager is auto-hiding, unlock it (i.e. close it)
3913  {
3915  Manager::Get()->ProcessEvent(evtShow);
3916  }
3917  }
3918  }
3919  }
3920 
3921  m_RunAfterCompile = false;
3922 
3923  // no matter what happened with the build, return the focus to the active editor
3924  cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinEditor(Manager::Get()->GetEditorManager()->GetActiveEditor());
3925  if (ed)
3926  ed->GetControl()->SetFocus();
3927  }
3928 }
3929 
3930 void CompilerGCC::NotifyJobDone(bool showNothingToBeDone)
3931 {
3932  if (!m_LastBuildStep)
3933  return;
3934 
3935  m_BuildJob = bjIdle;
3936  if (showNothingToBeDone && m_Errors.GetCount(cltError) == 0)
3937  {
3938  LogMessage(m_Clean ? _("Done.\n") : _("Nothing to be done (all items are up-to-date).\n"));
3939  // if message manager is auto-hiding, unlock it (i.e. close it)
3941  Manager::Get()->ProcessEvent(evtShow);
3942  }
3943 
3944  if (!IsProcessRunning())
3945  {
3947 
3948  // Check if this was a run operation and the application has been closed.
3949  // If this is the case we don't need to send cbEVT_COMPILER_FINISHED event.
3950  if (manager->GetIsRunning() == this)
3951  manager->SetIsRunning(NULL);
3952  else
3953  {
3954  CodeBlocksEvent evt(cbEVT_COMPILER_FINISHED, 0, m_pProject, 0, this);
3955  evt.SetInt(m_LastExitCode);
3956  Manager::Get()->ProcessEvent(evt);
3957  }
3958  m_LastExitCode = 0;
3959  }
3960 }
3961 
3963 {
3964 #ifdef NO_TRANSLATION
3965  return wxString::Format(wxT("%u error%s, %u warning%s"),
3966  m_Errors.GetCount(cltError), wxString(m_Errors.GetCount(cltError) == 1 ? wxT("") : wxT("s")).wx_str(),
3967  m_Errors.GetCount(cltWarning), wxString(m_Errors.GetCount(cltWarning) == 1 ? wxT("") : wxT("s")).wx_str());
3968 #else
3969  return wxString::Format(_("%u error(s), %u warning(s)"),
3970  m_Errors.GetCount(cltError), m_Errors.GetCount(cltWarning));
3971 #endif // NO_TRANSLATION
3972 }
3973 
3975 {
3976  long int elapsed = (wxGetLocalTimeMillis() - m_StartTime).ToLong() / 1000;
3977  int mins = elapsed / 60;
3978  int secs = (elapsed % 60);
3979 #ifdef NO_TRANSLATION
3980  return wxString::Format(wxT("%d minute%s, %d second%s"),
3981  mins, wxString(mins == 1 ? wxT("") : wxT("s")).wx_str(),
3982  secs, wxString(secs == 1 ? wxT("") : wxT("s")).wx_str());
3983 #else
3984  return wxString::Format(_("%d minute(s), %d second(s)"), mins, secs);
3985 #endif // NO_TRANSLATION
3986 }
ProjectFile * GetFileByFilename(const wxString &filename, bool isRelative=true, bool isUnixFilename=false)
Access a file of the project.
Definition: cbproject.cpp:1049
void OnKillProcess(wxCommandEvent &event)
A simple dialog that wraps a cbConfigurationPanel.
void OnJobEnd(size_t procIndex, int exitCode)
const wxString COMPILER_SIMPLE_LOG(_T("SLOG:"))
wxString F(const wxChar *msg,...)
sprintf-like function
Definition: logmanager.h:20
void OnCompileFileRequest(CodeBlocksEvent &event)
virtual bool IsRunning() const
Is the plugin currently compiling?
wxString FindAbsoluteValidPath(const wxString &file) const
static void Display(const wxString &title, const wxString &message, unsigned int delay=5000, unsigned int hysteresis=1)
Definition: infowindow.cpp:294
Base class for plugins.
Definition: cbplugin.h:84
CompilerLoggingType logging
Definition: compiler.h:222
virtual void OnRelease(bool appShutDown)
wxString relativeToCommonTopLevelPath
The relative filename to the common top-level path.
Definition: projectfile.h:135
bool IsValidTarget(const wxString &target) const
void TextURL(wxTextUrlEvent &event)
cbDebuggerPlugin * GetActiveDebugger()
const BuildJobTarget & PeekNextJob()
void Remove(const wxString &sz)
const int maxTargetInMenus
EVTIMPORT const wxEventType cbEVT_WORKSPACE_CLOSING_COMPLETE
Definition: sdk_events.cpp:114
static wxString GetFolder(SearchDirs dir)
Access one of Code::Blocks&#39; folders.
bool wxGetEnv(const wxString &var, wxString *value)
virtual bool Detach(wxWindow *window)
bool Matches(const wxString &mask) const
void gBuildLog(const wxString &msg)
Definition: compilergcc.cpp:82
static bool IsValidCompilerID(const wxString &id)
virtual int Clean(const wxString &target)
Same as Clean(ProjectBuildTarget*) but with a wxString argument.
int wxNewId()
PluginManager * GetPluginManager() const
Definition: manager.cpp:444
void PrepareCompileFilePM(wxFileName &file)
bool wxRemoveFile(const wxString &file)
#define wxICON_QUESTION
Data folder in user&#39;s dir.
Definition: configmanager.h:75
virtual wxString GetLastError()
Returns warning/error actual string.
Definition: compiler.h:291
virtual const wxString & GetMasterPath() const
Get the compiler&#39;s master path (must contain "bin", "include" and "lib")
Definition: compiler.h:295
void UpdateProjectTargets(cbProject *project)
wxString relativeFilename
The relative (to the project) filename of this file.
Definition: projectfile.h:131
virtual bool Insert(size_t pos, wxMenu *menu, const wxString &title)
virtual bool GetUseConsoleRunner() const
Valid only for targets generating a console executable.
int idGCCProcess
wxFileOffset Length() const
void SetIsRunning(cbPlugin *plugin)
This method should be called when the applications is started by a plugin.
static bool LoadResource(const wxString &file)
Definition: manager.cpp:499
int idMenuBuildWorkspace
void Delete(std::vector< T > &s)
Definition: safedelete.h:20
void Assign(const wxFileName &filepath)
bool IsProcessRunning(int idx=-1) const
virtual void BuildMenu(wxMenuBar *menuBar)
ConfigManager * GetConfigManager(const wxString &name_space) const
Definition: manager.cpp:474
wxXmlNode * GetRoot() const
void DebugLogError(const wxString &msg)
Definition: logmanager.h:147
void OnProjectCompilerOptions(wxCommandEvent &event)
void DoRegisterCompilers()
int ReadInt(const wxString &name, int defaultVal=0)
Base class for debugger plugins.
Definition: cbplugin.h:397
bool IsOk() const
void OnConfig(wxCommandEvent &event)
virtual bool SupportsCurrentPlatform() const
static Manager * Get()
Use Manager::Get() to get a pointer to its instance Manager::Get() is guaranteed to never return an i...
Definition: manager.cpp:182
wxMenuItem * FindItemByPosition(size_t position) const
void SetBuildTargetName(const wxString &target)
Definition: sdk_events.h:60
int idMenuClearErrors
wxMenuItem * InsertSeparator(size_t pos)
BuildState
Defines the current state of the compiler.
Definition: compilergcc.h:51
virtual const wxString & GetExecutionParameters() const
Read the target&#39;s execution parameters.
EVTIMPORT const wxEventType cbEVT_COMPILER_FINISHED
Definition: sdk_events.cpp:149
void OnCleanFile(wxCommandEvent &event)
MakeCommand
virtual ~CompilerGCC()
DLLIMPORT const wxString DEFAULT_CONSOLE_TERM
Definition: globals.cpp:59
void OnCompileAll(wxCommandEvent &event)
int idMenuPreviousError
virtual const wxString & GetHostApplication() const
Read the target&#39;s host application.
EVTIMPORT const wxEventType cbEVT_CLEAN_PROJECT_STARTED
Definition: sdk_events.cpp:151
void AddToCommandQueue(const wxArrayString &commands)
int idMenuSettings
void SwitchCompiler(const wxString &id)
bool GetAttribute(const wxString &attrName, wxString *value) const
size_t length() const
virtual void BuildModuleMenu(const ModuleType type, wxMenu *menu, const FileTreeData *data=0)
bool GetFirst(wxString *filename, const wxString &filespec=wxEmptyString, int flags=wxDIR_DEFAULT) const
wxBoxSizer * sizer
Definition: compilergcc.cpp:93
DLLIMPORT wxBitmap cbLoadBitmap(const wxString &filename, wxBitmapType bitmapType=wxBITMAP_TYPE_PNG)
This function loads a bitmap from disk.
Definition: globals.cpp:1102
static wxTimeSpan Seconds(wxLongLong sec)
void Enable(int id, bool enable)
bool wxFileExists(const wxString &filename)
const wxString & GetObjName()
void OnRebuild(wxCommandEvent &event)
void LogWarning(const wxString &msg, int i=app_log)
Definition: logmanager.h:141
wxFileName file
The full filename of this file.
Definition: projectfile.h:126
static Compiler * GetDefaultCompiler()
void DoClean(const wxArrayString &commands)
int idMenuSelectTargetOther[maxTargetInMenus]
void OnNextError(wxCommandEvent &event)
void PrintBanner(BuildAction action, cbProject *prj=0, ProjectBuildTarget *target=0)
bool mustWait
wait for all previous commands to finish (for parallel builds).
Definition: compiler_defs.h:29
bool ReadBool(const wxString &name, bool defaultVal=false)
virtual wxString GetFilename() const
Get the workspace file&#39;s name.
Definition: cbworkspace.h:60
static wxDateTime Now()
wxKillError
int Index(const wxString &sz, bool bCase=true, bool bFromEnd=false) const
wxWindow * CreateControl(wxWindow *parent) override
void LogToStdOut(const wxString &msg, Logger::level lv=Logger::info)
Definition: logmanager.h:149
wxString MakeInvalidCompilerMessages() const
Returns messages which might be useful to the use for debugging why the compiler is invalid...
Definition: compiler.cpp:233
void OnTargetCompilerOptions(wxCommandEvent &event)
#define wxCANCEL
EVTIMPORT const wxEventType cbEVT_PROJECT_ACTIVATE
Definition: sdk_events.cpp:99
Event used to request from the main app to add a log.
Definition: sdk_events.h:182
size_t Length() const
bool Open(const wxString &dir)
static void AddonToolBar(wxToolBar *toolBar, wxString resid)
Definition: manager.cpp:405
wxString StateToString(BuildState bs)
virtual void EnableTool(int toolId, bool enable)
const wxString COMPILER_ERROR_ID_LOG
bool IsSeparator() const
virtual void OnAttach()
Any descendent plugin should override this virtual method and perform any necessary initialization...
bool wxDirExists(const wxString &dirname)
wxString GetExecutionDir()
Definition: cbproject.cpp:1023
wxMenuItem * Append(int id, const wxString &item=wxEmptyString, const wxString &helpString=wxEmptyString, wxItemKind kind=wxITEM_NORMAL)
const int idBuildLog
Definition: compilergcc.cpp:88
static Compiler * GetCompiler(size_t index)
void wxWakeUpIdle()
wxWindow * CreateControl(wxWindow *parent) override
Definition: loggers.cpp:168
void OnProjectActivated(CodeBlocksEvent &event)
#define _T(string)
BuildState GetNextStateBasedOnJob()
FileType
Known file types.
Definition: globals.h:49
cbProject * GetProject() const
Definition: sdk_events.h:41
static const wxString & GetDefaultCompilerID()
int GetNextAvailableProcessIndex() const
int idMenuCompileFileFromProjectManager
#define wxYES_NO
static wxMenu * LoadMenu(wxString menu_id, bool createonfailure=false)
Loads Menu from XRC.
Definition: manager.cpp:368
virtual int BuildWorkspace(const wxString &target=wxEmptyString)
Build all open projects.
wxString message
Definition: compiler_defs.h:24
virtual int RunSingleFile(const wxString &filename)
void DoPrepareQueue(bool clearLog)
const wxString & GetCurrentCompilerID()
cbProjectManagerUI & GetUI()
void OnSelectTarget(wxCommandEvent &event)
wxString GetTargetString(int index=-1)
void BuildStateManagement()
This uses m_BuildJob.
virtual int CompileFileWithoutProject(const wxString &file)
void OnCleanAll(wxCommandEvent &event)
void DoUpdateTargetMenu(int targetIndex)
virtual int CleanWorkspace(const wxString &target=wxEmptyString)
Clean all open projects.
ProjectBuildTarget * DoAskForTarget()
bool IsAbsolute(wxPathFormat format=wxPATH_NATIVE) const
DLLIMPORT FileType FileTypeOf(const wxString &filename)
Definition: globals.cpp:285
int idMenuRebuildWorkspace
#define wxICON_INFORMATION
virtual wxTreeItemData * GetItemData(const wxTreeItemId &item) const
ProjectFile * GetProjectFile() const
Definition: cbproject.h:61
int idMenuRebuild
wxString & Remove(size_t pos)
void CalculateWorkspaceDependencies(wxArrayInt &deps)
static bool isToolBar16x16(wxToolBar *toolBar)
Definition: manager.cpp:412
virtual int RebuildWorkspace(const wxString &target=wxEmptyString)
Rebuild all open projects.
const wxString COMPILER_WARNING_ID_LOG
int idMenuRun
void UpdateSettings() override
Definition: compilergcc.cpp:99
const wxString & GetName() const
void NotifyMissingFile(const wxString &name)
Definition: globals.h:370
wxString GetMinSecStr()
wxString AfterFirst(wxUniChar ch) const
Base class for mime plugins.
Definition: cbplugin.h:684
#define wxT(string)
void NotifyJobDone(bool showNothingToBeDone=false)
virtual wxString GetLastErrorLine()
Returns warning/error line number (as a string).
Definition: compiler.h:289
static void UnregisterCompilers()
Unregister all compilers.
#define wxNOT_FOUND
int idMenuTargetCompilerOptionsSub
Represents a file in a Code::Blocks project.
Definition: projectfile.h:39
const wxString COMPILER_TARGET_CHANGE(_T("TGT:"))
LogTarget
Definition: compilergcc.h:64
EVTIMPORT const wxEventType cbEVT_CLEAN_WORKSPACE_STARTED
Definition: sdk_events.cpp:152
wxString GetErrWarnStr()
size_t GetMenuItemCount() const
bool isRun
if it&#39;s a command to run the target.
Definition: compiler_defs.h:28
wxArrayString ReadArrayString(const wxString &name)
bool empty() const
A generic Code::Blocks event.
Definition: sdk_events.h:20
virtual wxString GetOutputFilename()
Read the target&#39;s output filename.
wxString ProjectMakefile()
void Dispatcher(wxCommandEvent &event)
Base class for compiler plugins.
Definition: cbplugin.h:263
virtual wxString GetFullTitle() const
CompilerLineType
Enum categorizing compiler&#39;s output line as warning/error/info/normal.
Definition: compiler.h:66
void OnProjectLoaded(CodeBlocksEvent &event)
wxArrayString GetCompileSingleFileCommand(const wxString &filename) const
This is to be used only for files not belonging to a project!!!
cbMimePlugin * GetMIMEHandlerForFile(const wxString &filename)
FileTreeData * DoSwitchProjectTemporarily()
int idMenuCompileFile
int idMenuRebuildFromProjectManager
virtual bool GetRunHostApplicationInTerminal() const
Get the flag if the host app should be run in terminal.
EditorManager * GetEditorManager() const
Definition: manager.cpp:434
wxLongLong wxGetLocalTimeMillis()
void LogError(const wxString &msg, int i=app_log)
Definition: logmanager.h:142
virtual TargetType GetTargetType() const
Read the target&#39;s type.
int idMenuCompileFromProjectManager
int idMenuCleanFileFromProjectManager
const wxString & GetMakefile()
Definition: cbproject.cpp:988
int idMenuKillProcess
void DoGotoNextError()
EVTIMPORT const wxEventType cbEVT_COMPILE_FILE_REQUEST
Definition: sdk_events.cpp:155
const wxString COMPILER_WAIT(_T("WAIT"))
ProjectManager * GetProjectManager() const
Functions returning pointers to the respective sub-manager instances.
Definition: manager.cpp:429
const wxString COMPILER_ERROR_LOG(_T("SLOG:ELOG:"))
bool LoadScript(const wxString &filename)
Loads a script.
bool MakeRelativeTo(const wxString &pathBase=wxEmptyString, wxPathFormat format=wxPATH_NATIVE)
wxArrayString GetPreBuildCommands(ProjectBuildTarget *target) const
void OnRebuildAll(wxCommandEvent &event)
bool Contains(const wxString &str) const
void Write(const wxString &name, const wxString &value, bool ignoreEmpty=false)
DebuggerManager * GetDebuggerManager() const
Definition: manager.cpp:484
virtual int KillProcess()
Abort the current build process.
virtual const wxString & GetFilename() const
Get the editor&#39;s filename (if applicable).
Definition: editorbase.h:45
BuildJobTarget GetNextJob()
DLLIMPORT wxString UnixFilename(const wxString &filename, wxPathFormat format=wxPATH_NATIVE)
Definition: globals.cpp:228
wxString GetExt() const
virtual bool IsValid()
Check if the compiler is actually valid (installed).
Definition: compiler.cpp:190
Not currently building.
Definition: compilergcc.h:44
Event functor class.
Definition: cbfunctor.h:37
Represents a Code::Blocks project.
Definition: cbproject.h:96
bool wxSetWorkingDirectory(const wxString &dir)
DLLIMPORT wxString cbGetDynamicLinkerPathForTarget(cbProject *project, ProjectBuildTarget *target)
Returns a string valid to be used as LD_LIBRARY_PATH (or equivalent).
Definition: cbproject.cpp:1755
EditorBase * GetActiveEditor()
void RecalcVars(cbProject *project, EditorBase *editor, ProjectBuildTarget *target)
int idMenuCompileAndRun
void DoGotoPreviousError()
wxArtID wxART_QUESTION
wxString & RemoveLast(size_t n=1)
EVTIMPORT const wxEventType cbEVT_ADD_LOG_WINDOW
Definition: sdk_events.cpp:162
virtual bool BuildToolBar(wxToolBar *toolBar)
cbStyledTextCtrl * GetControl() const
Returns a pointer to the underlying cbStyledTextCtrl object (which itself is the wxWindows implementa...
Definition: cbeditor.cpp:842
cbPlugin * GetIsRunning() const
Return a pointer to the plugin which is running the application.
DLLIMPORT const wxString DEFAULT_CONSOLE_SHELL
Definition: globals.cpp:63
EVTIMPORT const wxEventType cbEVT_REMOVE_LOG_WINDOW
Definition: sdk_events.cpp:163
virtual wxString GetMakeCommandFor(MakeCommand cmd) const
Get the "make" command used for cmd.
ModuleType
The type of module offering a context menu.
Definition: globals.h:38
long GetURLStart() const
virtual const wxString & GetTitle() const
Read the target&#39;s title.
#define EVT_PIPEDPROCESS_TERMINATED(id, fn)
Definition: sdk_events.h:366
static wxString FromUTF8(const char *s)
void OnCompileAndRun(wxCommandEvent &event)
wxString MAKE
Definition: compiler.h:204
wxArrayString GetCompileCommands(ProjectBuildTarget *target, bool force=false) const
wxSizerItem * Add(wxWindow *window, const wxSizerFlags &flags)
int idMenuSelectTargetHasMore
int GetTargetIndexFromName(cbProject *prj, const wxString &name)
void AskForActiveProject()
wxArrayString GetCleanCommands(ProjectBuildTarget *target, bool distclean=false) const
void InitBuildState(BuildJob job, const wxString &target)
Target produces a dynamic library.
wxString wxPathOnly(const wxString &path)
size_t Replace(const wxString &strOld, const wxString &strNew, bool replaceAll=true)
bool CheckProject()
wxFrame * GetAppFrame() const
Definition: manager.cpp:419
a logger which prints messages to a wxTextCtrl
Definition: loggers.h:90
cbEditor * GetBuiltinActiveEditor()
Definition: editormanager.h:95
const wxPoint wxDefaultPosition
A workspace class.
Definition: cbworkspace.h:26
int idMenuClean
static void SetDefaultCompiler(size_t index)
static void RegisterCompiler(Compiler *compiler)
Register a supported (builtin) compiler.
static bool IsBatchBuild()
Definition: manager.h:66
virtual cbTreeCtrl * GetTree()=0
Retrieve a pointer to the project manager&#39;s tree (GUI).
virtual const CompilerPrograms & GetPrograms() const
Get the compiler&#39;s programs.
Definition: compiler.h:299
wxMenuItem * AppendSeparator()
virtual const wxArrayString & GetExtraPaths() const
Get the compiler&#39;s extra paths.
Definition: compiler.h:297
EVTIMPORT const wxEventType cbEVT_HIDE_LOG_MANAGER
Definition: sdk_events.cpp:168
Base class that all "editors" should inherit from.
Definition: editorbase.h:30
LogManager * GetLogManager() const
Definition: manager.cpp:439
void UpdateSettings() override
Definition: loggers.cpp:69
bool UseMake(cbProject *project=0)
EVTIMPORT const wxEventType cbEVT_SWITCH_TO_LOG_WINDOW
Definition: sdk_events.cpp:165
wxString & Item(size_t nIndex)
cbProject * GetActiveProject()
Retrieve the active project.
wxString Read(const wxString &key, const wxString &defaultVal=wxEmptyString)
static void RegisterUserCompilers()
Register all user-defined compiler copies.
void SetPreferredTarget(const wxString &target)
Set the preferred target for this workspace.
virtual wxString GetBasePath() const
Read the target&#39;s base path, e.g. if GetFilename() returns "/usr/local/bin/xxx", base path will retur...
bool IsEmpty() const
wxString GetMakeCommandFor(MakeCommand cmd, cbProject *project, ProjectBuildTarget *target)
bool IsOpened() const
wxString title
Definition: logmanager.h:64
static void SaveSettings()
virtual wxString GetWorkingDir()
Read the target&#39;s working dir for execution (valid only for executable targets)
static wxUniChar GetPathSeparator(wxPathFormat format=wxPATH_NATIVE)
wxArrayString CompileFile(ProjectBuildTarget *target, ProjectFile *pf, bool force=false) const
const wxStringCharType * wx_str() const
virtual int ShowModal()
void DoClearTargetMenu()
void ResetBuildState()
bool Save(const wxString &filename)
void DoRecreateTargetMenu()
EVTIMPORT const wxEventType cbEVT_GET_ACTIVE_LOG_WINDOW
Definition: sdk_events.cpp:166
void OnTimer(wxTimerEvent &event)
static void LoadSettings()
bool Add(const wxString &path)
wxMenu * GetMenu(size_t menuIndex) const
void AddOutputLine(const wxString &output, bool forceErrorColour=false)
wxString wxEmptyString
void OnWorkspaceClosed(CodeBlocksEvent &event)
virtual int CompileFile(const wxString &file)
Compile a specific file.
const wchar_t * wc_str() const
virtual int Configure(cbProject *project, ProjectBuildTarget *target=0L)
Display configuration dialog.
int idMenuCleanTarget
BuildJob
Helper enum for compiler&#39;s state. This state signifies the kind of build the compiler is working on...
Definition: compilergcc.h:42
virtual void Stop()=0
Stop the debugging process (exit debugging).
bool SaveAllFiles()
Save all project files.
Definition: cbproject.cpp:1117
EVTIMPORT const wxEventType cbEVT_PROJECT_TARGETS_MODIFIED
Definition: sdk_events.cpp:108
wxString BuildURI() const
MacrosManager * GetMacrosManager() const
Definition: manager.cpp:454
Building the workspace.
Definition: compilergcc.h:45
int DoWorkspaceBuild(const wxString &target, bool clean, bool build, bool clearLog=true)
int idMenuTargetCompilerOptions
const wxString & _(const wxString &string)
DLLIMPORT void QuoteStringIfNeeded(wxString &str)
Definition: globals.cpp:260
wxString & Trim(bool fromRight=true)
BuildAction
Definition: compilergcc.h:72
int FindMenu(const wxString &title) const
void ReplaceMacros(wxString &buffer, ProjectBuildTarget *target=nullptr, bool subrequest=false)
ProjectBuildTarget * GetBuildTargetForFile(ProjectFile *pf)
Base class for plugin configuration panels.
cbEditor * GetBuiltinEditor(EditorBase *eb)
int GetActiveProcessCount() const
bool IsMakefileCustom()
Definition: cbproject.h:159
int GetBuildTargetsCount()
Definition: cbproject.h:200
Plugin registration object.
Definition: cbplugin.h:1099
void StartCompileFile(wxFileName file)
void OnCompile(wxCommandEvent &event)
static void Yield()
Whenever you need to call wxYield(), call Manager::Yield(). It&#39;s safer.
Definition: manager.cpp:221
void OnPreviousError(wxCommandEvent &event)
void SaveOptions()
wxArray< int > wxArrayInt
wxArrayString GetVirtualBuildTargets() const
Get a list of all defined virtual build targets.
Definition: cbproject.cpp:1487
Target produces a static library.
int idTimerPollCompiler
bool WithMultiLineMsg()
Do compiler writes multi-line messages?
Definition: compiler.h:379
static wxString GetDataFolder(bool global=true)
wxArrayString GetExpandedVirtualBuildTargetGroup(const wxString &alias) const
Access a virtual build target&#39;s expanded group of build targets.
Definition: cbproject.cpp:1507
ProjectBuildTarget * GetBuildTarget(int index)
Access a build target.
Definition: cbproject.cpp:1392
void OnGCCOutput(CodeBlocksEvent &event)
cbWorkspace * GetWorkspace()
Get the current workspace filename.
const DLLIMPORT wxString EXECUTABLE_EXT
Logger * logger
The logger.
Definition: sdk_events.h:192
wxString command
Definition: compiler_defs.h:23
wxArrayString GetPostBuildCommands(ProjectBuildTarget *target) const
Abstract base class for compilers.
Definition: compiler.h:274
void ExpandTargets(cbProject *project, const wxString &targetName, wxArrayString &result)
int idMenuSelectTargetDialog
virtual int Rebuild(ProjectBuildTarget *target=0L)
Rebuild the project/target.
bool IsCheckable() const
wxString & Append(const char *psz)
void SetProject(cbProject *project, bool refresh=true)
Set the active project.
A file editor.
Definition: cbeditor.h:43
virtual int FindItem(const wxString &itemString) const
#define EVT_PIPEDPROCESS_STDERR(id, fn)
Definition: sdk_events.h:363
static wxString getBuildTargetName(const ProjectBuildTarget *bt)
int idMenuNextError
bool GetNext(wxString *filename) const
bool IsEmpty() const
DLLIMPORT void PlaceWindow(wxTopLevelWindow *w, cbPlaceDialogMode mode=pdlBest, bool enforce=false)
Definition: globals.cpp:1177
virtual bool GetAlwaysRunPostBuildSteps() const
void NotifyCleanWorkspace()
void Clear()
void AllocProcesses()
cbProject * GetProject() const
Definition: cbproject.h:59
void LogWarningOrError(CompilerLineType lt, cbProject *prj, const wxString &filename, const wxString &line, const wxString &msg)
wxString GetPath(int flags=wxPATH_GET_VOLUME, wxPathFormat format=wxPATH_NATIVE) const
EVTIMPORT const wxEventType cbEVT_COMPILER_STARTED
Definition: sdk_events.cpp:148
virtual CompilerLineType CheckForWarningsAndErrors(const wxString &line)
Check if the supplied string is a compiler warning/error.
Definition: compiler.cpp:773
int idMenuProjectCompilerOptions
The entry point singleton for working with projects.
ProjectBuildTarget * target
Definition: compiler_defs.h:27
static int GetCPUCount()
LogSlot & Slot(int i)
Definition: logmanager.cpp:147
virtual const wxString & GetCompilerID() const
Read the target&#39;s compiler.
level
Definition: logger.h:37
void SaveBuildLog()
void ReplaceEnvVars(wxString &buffer)
Definition: macrosmanager.h:32
Target produces a console executable (without GUI) (distinction between ttExecutable and ttConsoleOnl...
virtual int CompileFileDefault(cbProject *project, ProjectFile *pf, ProjectBuildTarget *bt)
bool IsRelative(wxPathFormat format=wxPATH_NATIVE) const
const wxString COMPILER_NOTE_ID_LOG
int idMenuSelectTarget
Building the target.
Definition: compilergcc.h:47
wxString C
Definition: compiler.h:199
void Log(const wxString &msg, int i=app_log, Logger::level lv=Logger::info)
Definition: logmanager.h:140
void RemoveBuildProgressBar()
FileTreeDataKind GetKind() const
Definition: cbproject.h:58
wxGauge * progress
Definition: compilergcc.cpp:95
void CalculateProjectDependencies(cbProject *prj, wxArrayInt &deps)
virtual const wxString & GetName() const
Get the compiler&#39;s name.
Definition: compiler.h:293
static wxString GetExecutableFolder()
#define EVT_PIPEDPROCESS_STDOUT(id, fn)
Definition: sdk_events.h:360
int idMenuCompile
CompilerValidResult CompilerValid(ProjectBuildTarget *target=0)
void DebugLog(const wxString &msg, Logger::level lv=Logger::info)
Definition: logmanager.h:146
virtual const CompilerSwitches & GetSwitches() const
Get the compiler&#39;s generic switches.
Definition: compiler.h:301
void OnIdle(wxIdleEvent &event)
bool ProcessEvent(CodeBlocksEvent &event)
Definition: manager.cpp:246
void OnClearErrors(wxCommandEvent &event)
int idMenuRebuildTarget
virtual int Build(ProjectBuildTarget *target=0L)
Build the project/target.
int ShowModal() override
void SetExt(const wxString &ext)
void InitBuildLog(bool workspaceBuild)
EVTIMPORT const wxEventType cbEVT_PROJECT_OPEN
Definition: sdk_events.cpp:97
void OnCompileFile(wxCommandEvent &event)
void RegisterEventSink(wxEventType eventType, IEventFunctorBase< CodeBlocksEvent > *functor)
Definition: manager.cpp:550
virtual bool IsRunning() const =0
Is the plugin currently debugging?
virtual wxString GetLastErrorFilename()
Returns warning/error filename.
Definition: compiler.h:287
wxMenuItem * FindChildItem(int id, size_t *pos=NULL) const
size_t Add(const wxString &str, size_t copies=1)
virtual void Check(bool check=true)
void LogMessage(const wxString &message, CompilerLineType lt=cltNormal, LogTarget log=ltAll, bool forceErrorColour=false, bool isTitle=false, bool updateProgress=false)
bool DoCleanWithMake(ProjectBuildTarget *bt)
cbProject * GetParentProject()
Definition: projectfile.h:93
bool Save() override
Save editor contents.
Definition: cbeditor.cpp:1789
bool StartsWith(const wxString &prefix, wxString *rest=NULL) const
Represents a Code::Blocks project build target.
EVTIMPORT const wxEventType cbEVT_PROJECT_CLOSE
Definition: sdk_events.cpp:96
size_t GetCount() const
void OnClean(wxCommandEvent &event)
virtual bool Load(const wxString &filename, const wxString &encoding="UTF-8", int flags=wxXMLDOC_NONE)
int Find(wxUniChar ch, bool fromEnd=false) const
ProjectFile * GetProjectFile() const
Read the ProjectFile pointer associated with this editor.
Definition: cbeditor.h:123
void PrepareCompileFile(wxFileName &file)
Simple iterator that uses wxArrayString as data source.
wxUniChar GetChar(size_t n) const
Simple incremental select dialog that shows a single column and doesn&#39;t have much ui elements...
int idMenuCleanFromProjectManager
wxUniChar Last() const
int idToolTarget
ProjectsArray * GetProjects()
Retrieve an array of all the opened projects.
void AddBuildProgressBar()
wxMenu * GetSubMenu() const
bool wxLaunchDefaultBrowser(const wxString &url, int flags=0)
DLLIMPORT wxString ExpandBackticks(wxString &str)
Definition: globals.cpp:861
int DoGUIAskForTarget()
ScriptingManager * GetScriptingManager() const
Definition: manager.cpp:469
void PrintInvalidCompiler(ProjectBuildTarget *target, Compiler *compiler, const wxString &finalMessage)
int idMenuCompileTarget
void OnRun(wxCommandEvent &event)
void AttachConfigurationPanel(cbConfigurationPanel *panel)
bool MakeAbsolute(const wxString &cwd=wxEmptyString, wxPathFormat format=wxPATH_NATIVE)
Data folder in base dir.
Definition: configmanager.h:81
bool FileExists() const
void PreprocessJob(cbProject *project, const wxString &targetName)
cbConfigurationPanel * GetConfigurationPanel(wxWindow *parent)
DLLIMPORT wxString EscapeSpaces(const wxString &str)
Escapes spaces and tabs (NOT quoting the string)
Definition: globals.cpp:273
bool wxSetEnv(const wxString &var, const wxString &value)
int Printf(const wxString &pszFormat,...)
virtual wxString GetObjectOutput() const
Read the target&#39;s objects output dir.
int DoBuild(bool clean, bool build)
void AddEnvList(const wxString &env_variable)
static int gBuildLogId
Definition: compilergcc.cpp:79
bool StopRunningDebugger()
void OnGCCTerminated(CodeBlocksEvent &event)
wxString GetFullPath(wxPathFormat format=wxPATH_NATIVE) const
virtual int OpenFile(const wxString &filename)=0
Open the file.
void OnUpdateUI(wxUpdateUIEvent &event)
void SetParentDialog(wxWindow *dialog)
Sets the panel&#39;s parent dialog.
#define NULL
Definition: prefix.cpp:59
int idMenuProjectCompilerOptionsFromProjectManager
DLLIMPORT wxString cbMergeLibPaths(const wxString &oldPath, const wxString &newPath)
Merges to LD_LIBRARY_PATH/PATH strings together to form a new valid string.
Definition: cbproject.cpp:1777
size_t SetLog(Logger *l, int index=no_index)
Definition: logmanager.cpp:110
virtual wxString GetTitle() const
Get the workspace&#39;s title.
Definition: cbworkspace.h:69
int idMenuCleanWorkspace
void OnProjectUnloaded(CodeBlocksEvent &event)
void LoadOptions()
static wxString Format(const wxString &format,...)
size_t Write(const void *buffer, size_t count)
void OnGCCError(CodeBlocksEvent &event)
wxString Mid(size_t first, size_t nCount=wxString::npos) const
bool ReAllocProcesses()
void Enable(int id, bool enable)
virtual int Run(ProjectBuildTarget *target=0L)
Run the project/target.
virtual int DistClean(ProjectBuildTarget *target=0L)
DistClean the project/target.
Dialog that contains a "Don&#39;t annoy me" checkbox.
wxBitmap * icon
Definition: logmanager.h:63
void DoClearErrors()
virtual void Layout()
wxMenuItem * Insert(size_t pos, wxMenuItem *menuItem)
void SetupEnvironment()
const ProjectsArray * GetDependenciesForProject(cbProject *base)
Get the array of projects base depends on.
DLLIMPORT int cbMessageBox(const wxString &message, const wxString &caption=wxEmptyString, int style=wxOK, wxWindow *parent=NULL, int x=-1, int y=-1)
wxMessageBox wrapper.
Definition: globals.cpp:1395
const wxString lt(_T("<"))
void NotifyCleanProject(const wxString &target)
Building the project.
Definition: compilergcc.h:46
void FreeProcesses()
wxPanel * panel
Definition: compilergcc.cpp:92
EVTIMPORT const wxEventType cbEVT_SHOW_LOG_MANAGER
Definition: sdk_events.cpp:167
void ClearLog(bool switchToLog)
virtual bool Realize()
virtual wxTreeItemId GetTreeSelection()=0
Get the selection of the project manager&#39;s tree (GUI).
static wxKillError Kill(int pid, wxSignal sig=wxSIGTERM, int flags=wxKILL_NOCHILDREN)
wxArrayString buildTargets
An array of strings, containing the names of all the build targets this file belongs to...
Definition: projectfile.h:190
long wxExecute(const wxString &command, int flags=wxEXEC_ASYNC, wxProcess *callback=NULL, const wxExecuteEnv *env=NULL)
wxString wxGetCwd()
Target only runs commands in pre-build and/or post-build steps.
bool UseFlatObjects
Definition: compiler.h:230