Code::Blocks  SVN r11506
compilerMINGW.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: 10770 $
6  * $Id: compilerMINGW.cpp 10770 2016-02-06 14:27:56Z mortenmacfly $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/plugins/compilergcc/compilerMINGW.cpp $
8  */
9 
10 #include <sdk.h>
11 #include "compilerMINGW.h"
12 #include <wx/intl.h>
13 #include <wx/regex.h>
14 #include <wx/config.h>
15 #include <wx/fileconf.h>
16 #include <wx/msgdlg.h>
17 #include <wx/filename.h>
18 #include <wx/filefn.h>
19 #include "manager.h"
20 #include "macrosmanager.h"
21 #include "logmanager.h"
22 #include "compilerMINGWgenerator.h"
23 
24 #include <configmanager.h>
25 
26 #ifdef __WXMSW__
27  #include <wx/dir.h>
28  #include <wx/msw/registry.h>
29 #endif
30 
32  : Compiler(name, ID)
33 {
34  m_Weight = 4;
35  Reset();
36 }
37 
39 {
40  //dtor
41 }
42 
44 {
45  return (new CompilerMINGW(*this));
46 }
47 
49 {
51  generator->Init(project);
52  return generator;
53 }
54 
56 {
57  // try to find MinGW in environment variable PATH first
58  wxString pathValues;
59  wxGetEnv(_T("PATH"), &pathValues);
60  if (!pathValues.IsEmpty())
61  {
62  wxString sep = platform::windows ? _T(";") : _T(":");
63  wxChar pathSep = platform::windows ? _T('\\') : _T('/');
64  wxArrayString pathArray = GetArrayFromString(pathValues, sep);
65  for (size_t i = 0; i < pathArray.GetCount(); ++i)
66  {
67  if (wxFileExists(pathArray[i] + pathSep + m_Programs.C))
68  {
69  if (pathArray[i].AfterLast(pathSep).IsSameAs(_T("bin")))
70  {
71  m_MasterPath = pathArray[i].BeforeLast(pathSep);
72  return adrDetected;
73  }
74  }
75  }
76  }
77 
79  if (platform::windows)
80  {
81  // look first if MinGW was installed with Code::Blocks (new in beta6)
83  if (!wxFileExists(m_MasterPath + sep + _T("bin") + sep + m_Programs.C))
84  // if that didn't do it, look under C::B\MinGW, too (new in 08.02)
85  m_MasterPath += sep + _T("MinGW");
86  if (!wxFileExists(m_MasterPath + sep + _T("bin") + sep + m_Programs.C))
87  {
88  // no... search for MinGW installation dir
89  wxString windir = wxGetOSDirectory();
90  wxFileConfig ini(_T(""), _T(""), windir + _T("/MinGW.ini"), _T(""), wxCONFIG_USE_LOCAL_FILE | wxCONFIG_USE_NO_ESCAPE_CHARACTERS);
91  m_MasterPath = ini.Read(_T("/InstallSettings/InstallPath"), _T("C:\\MinGW"));
92  if (!wxFileExists(m_MasterPath + sep + _T("bin") + sep + m_Programs.C))
93  {
94 #ifdef __WXMSW__ // for wxRegKey
95  // not found...
96  // look for dev-cpp installation
97  wxRegKey key; // defaults to HKCR
98  key.SetName(_T("HKEY_LOCAL_MACHINE\\Software\\Dev-C++"));
99  if (key.Exists() && key.Open(wxRegKey::Read))
100  {
101  // found; read it
102  key.QueryValue(_T("Install_Dir"), m_MasterPath);
103  }
104  else
105  {
106  // installed by inno-setup
107  // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Minimalist GNU for Windows 4.1_is1
108  // HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\TDM-GCC
109  wxString name;
110  long index;
111  key.SetName(_T("HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall"));
112  for (int i = 0; i < 2; ++i)
113  {
114  bool ok = key.GetFirstKey(name, index);
115  while (ok && !name.StartsWith(wxT("Minimalist GNU for Windows")) && name != wxT("TDM-GCC"))
116  {
117  ok = key.GetNextKey(name, index);
118  }
119  if (ok)
120  {
121  name = key.GetName() + wxT("\\") + name;
122  key.SetName(name);
123  if (key.Exists() && key.Open(wxRegKey::Read))
124  {
125  key.QueryValue(wxT("InstallLocation"), m_MasterPath);
126  // determine configuration, eg: "x86_64-w64-mingw32-gcc.exe"
127  wxDir binFolder(m_MasterPath + sep + wxT("bin"));
128  if (binFolder.IsOpened() && binFolder.GetFirst(&name, wxT("*mingw32-gcc*.exe"), wxDIR_FILES))
129  {
130  m_Programs.C = name;
131  while (binFolder.GetNext(&name))
132  {
133  if (name.Length() < m_Programs.C.Length())
134  m_Programs.C = name; // avoid "x86_64-w64-mingw32-gcc-4.8.1.exe"
135  }
137  m_Programs.CPP.Replace(wxT("mingw32-gcc"), wxT("mingw32-g++"));
139  break;
140  }
141  }
142  }
143  // on 64 bit Windows
144  key.SetName(wxT("HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Microsoft\\Windows\\CurrentVersion\\Uninstall"));
145  }
146  }
147 #endif
148  }
149  // check for PortableApps.com installation
150  if (!wxFileExists(m_MasterPath + sep + _T("bin") + sep + m_Programs.C))
151  {
153  if (wxFileExists(drive + wxT("PortableApps\\CommonFiles\\MinGW\\bin\\") + m_Programs.C))
154  m_MasterPath = drive + wxT("PortableApps\\CommonFiles\\MinGW");
155  else if (wxFileExists(drive + wxT("CommonFiles\\MinGW\\bin\\") + m_Programs.C))
156  m_MasterPath = drive + wxT("CommonFiles\\MinGW");
157  else if (wxFileExists(drive + wxT("MinGW\\bin\\") + m_Programs.C))
158  m_MasterPath = drive + wxT("MinGW");
159  }
160  }
161  }
162  else
163  m_MasterPath = _T("/usr");
164 
166  // don't add lib/include dirs. GCC knows where its files are located
167 
169  return ret;
170 }
171 
173 {
174 // Manager::Get()->GetLogManager()->DebugLog(_T("Compiler detection for compiler ID: '") + GetID() + _T("' (parent ID= '") + GetParentID() + _T("')"));
175 
176  wxArrayString output, errors;
178  wxString master_path = m_MasterPath;
179  wxString compiler_exe = m_Programs.C;
180 
181  /* We should read the master path from the configuration manager as
182  * the m_MasterPath is empty if AutoDetectInstallationDir() is not
183  * called
184  */
185  ConfigManager* cmgr = Manager::Get()->GetConfigManager(_T("compiler"));
186  if (cmgr)
187  {
188  wxString settings_path;
189  wxString compiler_path;
190  /* Differ between user-defined compilers (copies of base compilers) */
191  if (GetParentID().IsEmpty())
192  {
193  settings_path = _T("/sets/") + GetID() + _T("/master_path");
194  compiler_path = _T("/sets/") + GetID() + _T("/c_compiler");
195  }
196  else
197  {
198  settings_path = _T("/user_sets/") + GetID() + _T("/master_path");
199  compiler_path = _T("/user_sets/") + GetID() + _T("/c_compiler");
200  }
201  cmgr->Read(settings_path, &master_path);
202  cmgr->Read(compiler_path, &compiler_exe);
203  }
204  if (master_path.IsEmpty())
205  {
206  /* Notice: In general this is bad luck as e.g. all copies of a
207  * compiler have a different path, most likely.
208  * Thus the following might even return a wrong command!
209  */
210  if (platform::windows)
211  master_path = _T("C:\\MinGW");
212  else
213  master_path = _T("/usr");
214  }
215  wxString gcc_command = master_path + sep + _T("bin") + sep + compiler_exe;
216 
217  Manager::Get()->GetMacrosManager()->ReplaceMacros(gcc_command);
218  if (!wxFileExists(gcc_command))
219  {
220 // Manager::Get()->GetLogManager()->DebugLog(_T("Compiler version detection: Compiler not found: ") + gcc_command);
221  return;
222  }
223 
224 // Manager::Get()->GetLogManager()->DebugLog(_T("Compiler version detection: Issuing command: ") + gcc_command);
225 
226  int flags = wxEXEC_SYNC;
227 #if wxCHECK_VERSION(3, 0, 0)
228  // Stop event-loop while wxExecute runs, to avoid a deadlock on startup,
229  // that occurs from time to time on wx3
230  flags |= wxEXEC_NOEVENTS;
231 #else
232  flags |= wxEXEC_NODISABLE;
233 #endif
234  long result = wxExecute(gcc_command + _T(" --version"), output, errors, flags );
235  if(result != 0)
236  {
237 // Manager::Get()->GetLogManager()->DebugLog(_T("Compiler version detection: Error executing command."));
238  }
239  else
240  {
241  if (output.GetCount() > 0)
242  {
243 // Manager::Get()->GetLogManager()->DebugLog(_T("Extracting compiler version from: ") + output[0]);
244  wxRegEx reg_exp;
245  if (reg_exp.Compile(_T("[0-9][.][0-9][.][0-9]")) && reg_exp.Matches(output[0]))
246  {
247  m_VersionString = reg_exp.GetMatch(output[0]);
248 // Manager::Get()->GetLogManager()->DebugLog(_T("Compiler version via RegExp: ") + m_VersionString);
249  }
250  else
251  {
252  m_VersionString = output[0].Mid(10);
254  m_VersionString.Trim(false);
255 // Manager::Get()->GetLogManager()->DebugLog(_T("Compiler version: ") + m_VersionString);
256  }
257  }
258  }
259 }
wxString GetName(bool bShortPrefix=true) const
DLLIMPORT wxArrayString GetArrayFromString(const wxString &text, const wxString &separator=DEFAULT_ARRAY_SEP, bool trimSpaces=true)
Definition: globals.cpp:134
bool wxGetEnv(const wxString &var, wxString *value)
bool Read(const wxString &key, wxString *str) const
virtual AutoDetectResult AutoDetectInstallationDir()
Try to auto-detect the compiler&#39;s installation directory.
Generate command-lines needed to produce a build.
ConfigManager * GetConfigManager(const wxString &name_space) const
Definition: manager.cpp:474
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
bool IsOpened() const
bool GetFirst(wxString *filename, const wxString &filespec=wxEmptyString, int flags=wxDIR_DEFAULT) const
bool wxFileExists(const wxString &filename)
bool GetFirstKey(wxString &strKeyName, long &lIndex)
size_t Length() const
wxString CPP
Definition: compiler.h:200
bool Matches(const wxString &text, int flags=0) const
virtual void Reset()
Reset settings to defaults.
Definition: compiler.cpp:157
#define _T(string)
bool QueryValue(const wxString &szValue, wxString &strValue, bool raw) const
CompilerPrograms m_Programs
Definition: compiler.h:412
#define wxT(string)
virtual Compiler * CreateCopy()
Implement this in new compilers, to return a new copy.
AutoDetectResult
Definition: compiler.h:190
wxString LD
Definition: compiler.h:201
CompilerMINGW(const wxString &name=_("GNU GCC Compiler"), const wxString &ID=_T("gcc"))
virtual void Init(cbProject *project)
Initialize for use with the specified project.
wxUSE_UNICODE_dependent wxChar
const wxString & GetID() const
Get this compiler&#39;s unique ID.
Definition: compiler.h:351
virtual void SetVersionString()
Set the compiler version string.
Represents a Code::Blocks project.
Definition: cbproject.h:96
wxString m_VersionString
Definition: compiler.h:419
wxString Left(size_t count) const
size_t Replace(const wxString &strOld, const wxString &strNew, bool replaceAll=true)
wxString GetVolume() const
static const wxString sep
bool GetMatch(size_t *start, size_t *len, size_t index=0) const
virtual ~CompilerMINGW()
wxString Read(const wxString &key, const wxString &defaultVal=wxEmptyString)
static wxUniChar GetPathSeparator(wxPathFormat format=wxPATH_NATIVE)
wxString wxGetOSDirectory()
MacrosManager * GetMacrosManager() const
Definition: manager.cpp:454
wxString & Trim(bool fromRight=true)
void ReplaceMacros(wxString &buffer, ProjectBuildTarget *target=nullptr, bool subrequest=false)
Definition: id.h:15
Abstract base class for compilers.
Definition: compiler.h:274
bool GetNext(wxString *filename) const
bool IsEmpty() const
wxString C
Definition: compiler.h:199
const wxString & GetParentID() const
Get this compiler&#39;s parent&#39;s unique ID.
Definition: compiler.h:353
static wxString GetExecutableFolder()
bool GetNextKey(wxString &strKeyName, long &lIndex) const
wxString m_MasterPath
Definition: compiler.h:409
bool Exists() const
bool StartsWith(const wxString &prefix, wxString *rest=NULL) const
bool Open(AccessMode mode=Write)
bool Compile(const wxString &pattern, int flags=wxRE_DEFAULT)
size_t GetCount() const
virtual CompilerCommandGenerator * GetCommandGenerator(cbProject *project)
This is to be overridden, if compiler needs to alter the default command line generation.
int m_Weight
Definition: compiler.h:422
void SetName(const wxString &strKey)
long wxExecute(const wxString &command, int flags=wxEXEC_ASYNC, wxProcess *callback=NULL, const wxExecuteEnv *env=NULL)