2
* This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3
* http://www.gnu.org/licenses/lgpl-3.0.html
6
* $Id: compiler.cpp 4909 2008-02-27 13:15:26Z mortenmacfly $
7
* $HeadURL: svn://svn.berlios.de/codeblocks/tags/8.02/src/sdk/compiler.cpp $
10
#include "sdk_precomp.h"
13
#include "cbexception.h"
16
#include "logmanager.h"
17
#include "configmanager.h"
18
#include "macrosmanager.h"
20
#include "compilerfactory.h"
26
#include "compilercommandgenerator.h"
27
#include <wx/filefn.h>
28
#include <wx/arrimpl.cpp>
29
WX_DEFINE_OBJARRAY(RegExArray);
32
wxArrayString Compiler::m_CompilerIDs; // map to guarantee unique IDs
34
// common regex that can be used by the different compiler for matching compiler output
35
// it can be used in the patterns for warnings, errors, ...
36
// NOTE : it is an approximation (for example the ':' can appear anywhere and several times)
37
const wxString Compiler::FilePathWithSpaces = _T("[][{}() \t#%$~A-Za-z0-9_:+/\\.-]+");
39
// version of compiler settings
40
// when this is different from what is saved in the config, a message appears
41
// to the user saying that default settings have changed and asks him if he wants to
42
// use his own settings or the new defaults
43
const wxString CompilerSettingsVersion = _T("0.0.2");
45
CompilerSwitches::CompilerSwitches()
46
{ // default based upon gnu
47
includeDirs = _T("-I");
51
genericSwitch = _T("-");
52
objectExtension = _T("o");
53
needDependencies = true;
54
forceFwdSlashes = false;
55
forceCompilerUseQuotes = false;
56
forceLinkerUseQuotes = false;
58
libPrefix = _T("lib");
59
libExtension = _T("a");
60
linkerNeedsLibPrefix = false;
61
linkerNeedsLibExtension = false;
63
PCHExtension = _T("h.gch");
64
UseFlatObjects = false;
65
UseFullSourcePaths = false;
66
} // end of constructor
69
wxString Compiler::CommandTypeDescriptions[ctCount] =
71
// These are the strings that describe each CommandType enumerator...
72
// No need to say that it must have the same order as the enumerators!
73
_("Compile single file to object file"),
74
_("Generate dependencies for file"),
75
_("Compile Win32 resource file"),
76
_("Link object files to executable"),
77
_("Link object files to console executable"),
78
_("Link object files to dynamic library"),
79
_("Link object files to static library"),
80
_("Link object files to native executable")
83
Compiler::Compiler(const wxString& name, const wxString& ID, const wxString& parentID)
86
m_ParentID(parentID.Lower()),
89
m_NeedValidityCheck(true),
95
m_Switches.supportsPCH = false;
96
m_Switches.forceFwdSlashes = false;
97
m_VersionString = wxEmptyString;
99
Manager::Get()->GetLogManager()->DebugLog(F(_T("Added compiler \"%s\""), m_Name.c_str()));
102
Compiler::Compiler(const Compiler& other)
103
: CompileOptionsBase(other),
104
m_ParentID(other.m_ParentID.IsEmpty() ? other.m_ID : other.m_ParentID),
106
m_Mirror(other.m_Mirror),
107
m_Mirrored(other.m_Mirrored)
109
m_Name = _("Copy of ") + other.m_Name;
110
// generate unique ID
111
// note that this copy constructor is protected and can only be called
112
// by our friend CompilerFactory. It knows what it's doing ;)
113
wxDateTime now = wxDateTime::UNow();
114
m_ID = now.Format(_T("%c"), wxDateTime::CET);
117
m_MasterPath = other.m_MasterPath;
118
m_Programs = other.m_Programs;
119
m_Switches = other.m_Switches;
120
m_Options = other.m_Options;
121
m_IncludeDirs = other.m_IncludeDirs;
122
m_LibDirs = other.m_LibDirs;
123
m_CompilerOptions = other.m_CompilerOptions;
124
m_LinkerOptions = other.m_LinkerOptions;
125
m_LinkLibs = other.m_LinkLibs;
126
m_CmdsBefore = other.m_CmdsBefore;
127
m_CmdsAfter = other.m_CmdsAfter;
128
m_RegExes = other.m_RegExes;
129
m_VersionString = other.m_VersionString;
130
for (int i = 0; i < ctCount; ++i)
132
m_Commands[(CommandType)i] = other.m_Commands[(CommandType)i];
135
m_Valid = other.m_Valid;
136
m_NeedValidityCheck = other.m_NeedValidityCheck;
139
Compiler::~Compiler()
145
bool Compiler::IsValid()
147
if (!m_NeedValidityCheck)
150
if (m_MasterPath.IsEmpty())
151
return true; // still initializing, don't try to test now
153
m_NeedValidityCheck = false;
155
if (!SupportsCurrentPlatform())
161
wxString tmp = m_MasterPath + _T("/bin/") + m_Programs.C;
162
Manager::Get()->GetMacrosManager()->ReplaceMacros(tmp);
163
m_Valid = wxFileExists(tmp);
165
{ // and try witout appending the 'bin'
166
tmp = m_MasterPath + _T("/") + m_Programs.C;
167
Manager::Get()->GetMacrosManager()->ReplaceMacros(tmp);
168
m_Valid = wxFileExists(tmp);
172
// look in extra paths too
173
for (size_t i = 0; i < m_ExtraPaths.GetCount(); ++i)
175
tmp = m_ExtraPaths[i] + _T("/") + m_Programs.C;
176
Manager::Get()->GetMacrosManager()->ReplaceMacros(tmp);
177
m_Valid = wxFileExists(tmp);
185
void Compiler::MakeValidID()
187
// basically, make it XML-element compatible
188
// only allow a-z, 0-9 and _
189
// (it is already lowercase)
190
// any non-conformant character will be removed
197
while (pos < m_ID.Length())
199
wxChar ch = m_ID[pos];
200
if (wxIsalnum(ch) || ch == _T('_'))
205
else if (wxIsspace(ch))
207
// convert spaces to underscores
208
newID.Append(_T('_'));
213
// make sure it's not starting with a number.
214
// if it is, prepend "cb"
215
if (wxIsdigit(newID.GetChar(0)))
216
newID.Prepend(_T("cb"));
221
cbThrow(_T("Can't create a valid compiler ID for ") + m_Name);
223
m_ID = newID.Lower();
225
// check for unique ID
226
if (!IsUniqueID(m_ID))
227
cbThrow(_T("Compiler ID already exists for ") + m_Name);
228
m_CompilerIDs.Add(m_ID);
231
CompilerCommandGenerator* Compiler::GetCommandGenerator()
233
return new CompilerCommandGenerator;
236
void Compiler::Init(cbProject* project)
239
m_pGenerator = GetCommandGenerator();
240
m_pGenerator->Init(project);
243
void Compiler::GenerateCommandLine(wxString& macro,
244
ProjectBuildTarget* target,
246
const wxString& file,
247
const wxString& object,
248
const wxString& FlatObject,
249
const wxString& deps)
252
cbThrow(_T("Compiler::Init() not called or generator invalid!"));
253
m_pGenerator->GenerateCommandLine(macro, target, pf, file, object, FlatObject, deps);
256
const wxArrayString& Compiler::GetCompilerSearchDirs(ProjectBuildTarget* target)
258
static wxArrayString retIfError;
263
return m_pGenerator->GetCompilerSearchDirs(target);
266
const wxArrayString& Compiler::GetLinkerSearchDirs(ProjectBuildTarget* target)
268
static wxArrayString retIfError;
273
return m_pGenerator->GetLinkerSearchDirs(target);
276
const wxString& Compiler::GetCommand(CommandType ct, const wxString& fileExtension) const
279
const CompilerToolsVector& vec = m_Commands[ct];
281
if (!fileExtension.IsEmpty())
283
for (size_t i = 0; i < vec.size(); ++i)
285
if (vec[i].extensions.GetCount() == 0)
290
for (size_t n = 0; n < vec[i].extensions.GetCount(); ++n)
292
if (vec[i].extensions[n] == fileExtension)
294
return vec[i].command;
299
return vec[catchAll].command;
302
const CompilerTool& Compiler::GetCompilerTool(CommandType ct, const wxString& fileExtension) const
305
const CompilerToolsVector& vec = m_Commands[ct];
307
if (!fileExtension.IsEmpty())
309
for (size_t i = 0; i < vec.size(); ++i)
311
if (vec[i].extensions.GetCount() == 0)
316
for (size_t n = 0; n < vec[i].extensions.GetCount(); ++n)
318
if (vec[i].extensions[n] == fileExtension)
325
return vec[catchAll];
328
void Compiler::MirrorCurrentSettings()
334
// keep the current settings safe
335
// so we can compare them when saving: this way we can only save what's
336
// different from the defaults
338
m_Mirror.Name = m_Name;
339
m_Mirror.MasterPath = m_MasterPath;
340
m_Mirror.ExtraPaths = m_ExtraPaths;
341
for (int i = 0; i < ctCount; ++i)
342
m_Mirror.Commands[i] = m_Commands[i];
343
m_Mirror.Programs = m_Programs;
344
m_Mirror.Switches = m_Switches;
345
m_Mirror.Options = m_Options;
346
m_Mirror.RegExes = m_RegExes;
348
m_Mirror.CompilerOptions_ = m_CompilerOptions;
349
m_Mirror.LinkerOptions = m_LinkerOptions;
350
m_Mirror.IncludeDirs = m_IncludeDirs;
351
m_Mirror.ResIncludeDirs = m_ResIncludeDirs;
352
m_Mirror.LibDirs = m_LibDirs;
353
m_Mirror.LinkLibs = m_LinkLibs;
354
m_Mirror.CmdsBefore = m_CmdsBefore;
355
m_Mirror.CmdsAfter = m_CmdsAfter;
360
void Compiler::SaveSettings(const wxString& baseKey)
362
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("compiler"));
364
// save settings version
365
cfg->Write(_T("settings_version"), CompilerSettingsVersion);
369
// delete old-style keys (using integer IDs)
370
tmp.Printf(_T("%s/set%3.3d"), baseKey.c_str(), CompilerFactory::GetCompilerIndex(this) + 1);
371
cfg->DeleteSubPath(tmp);
373
tmp.Printf(_T("%s/%s"), baseKey.c_str(), m_ID.c_str());
375
cfg->Write(tmp + _T("/name"), m_Name);
376
cfg->Write(tmp + _T("/parent"), m_ParentID, true);
378
if (m_Mirror.CompilerOptions_ != m_CompilerOptions)
380
wxString key = GetStringFromArray(m_CompilerOptions);
381
cfg->Write(tmp + _T("/compiler_options"), key, false);
383
if (m_Mirror.LinkerOptions != m_LinkerOptions)
385
wxString key = GetStringFromArray(m_LinkerOptions);
386
cfg->Write(tmp + _T("/linker_options"), key, false);
388
if (m_Mirror.IncludeDirs != m_IncludeDirs)
390
wxString key = GetStringFromArray(m_IncludeDirs);
391
cfg->Write(tmp + _T("/include_dirs"), key, false);
393
if (m_Mirror.ResIncludeDirs != m_ResIncludeDirs)
395
wxString key = GetStringFromArray(m_ResIncludeDirs);
396
cfg->Write(tmp + _T("/res_include_dirs"), key, false);
398
if (m_Mirror.LibDirs != m_LibDirs)
400
wxString key = GetStringFromArray(m_LibDirs);
401
cfg->Write(tmp + _T("/library_dirs"), key, false);
403
if (m_Mirror.LinkLibs != m_LinkLibs)
405
wxString key = GetStringFromArray(m_LinkLibs);
406
cfg->Write(tmp + _T("/libraries"), key, false);
408
if (m_Mirror.CmdsBefore != m_CmdsBefore)
410
wxString key = GetStringFromArray(m_CmdsBefore);
411
cfg->Write(tmp + _T("/commands_before"), key, true);
413
if (m_Mirror.CmdsAfter != m_CmdsAfter)
415
wxString key = GetStringFromArray(m_CmdsAfter);
416
cfg->Write(tmp + _T("/commands_after"), key, true);
419
if (m_Mirror.MasterPath != m_MasterPath)
420
cfg->Write(tmp + _T("/master_path"), m_MasterPath, true);
421
if (m_Mirror.ExtraPaths != m_ExtraPaths)
422
cfg->Write(tmp + _T("/extra_paths"), GetStringFromArray(m_ExtraPaths, _T(";")), true);
423
if (m_Mirror.Programs.C != m_Programs.C)
424
cfg->Write(tmp + _T("/c_compiler"), m_Programs.C, true);
425
if (m_Mirror.Programs.CPP != m_Programs.CPP)
426
cfg->Write(tmp + _T("/cpp_compiler"), m_Programs.CPP, true);
427
if (m_Mirror.Programs.LD != m_Programs.LD)
428
cfg->Write(tmp + _T("/linker"), m_Programs.LD, true);
429
if (m_Mirror.Programs.LIB != m_Programs.LIB)
430
cfg->Write(tmp + _T("/lib_linker"), m_Programs.LIB, true);
431
if (m_Mirror.Programs.WINDRES != m_Programs.WINDRES)
432
cfg->Write(tmp + _T("/res_compiler"), m_Programs.WINDRES, true);
433
if (m_Mirror.Programs.MAKE != m_Programs.MAKE)
434
cfg->Write(tmp + _T("/make"), m_Programs.MAKE, true);
435
if (m_Mirror.Programs.DBG != m_Programs.DBG)
436
cfg->Write(tmp + _T("/debugger"), m_Programs.DBG, true);
438
for (int i = 0; i < ctCount; ++i)
440
for (size_t n = 0; n < m_Commands[i].size(); ++n)
442
if (n >= m_Mirror.Commands[i].size() || m_Mirror.Commands[i][n] != m_Commands[i][n])
444
wxString key = wxString::Format(_T("%s/macros/%s/tool%d/"), tmp.c_str(), CommandTypeDescriptions[i].c_str(), n);
445
cfg->Write(key + _T("command"), m_Commands[i][n].command);
446
cfg->Write(key + _T("extensions"), m_Commands[i][n].extensions);
447
cfg->Write(key + _T("generatedFiles"), m_Commands[i][n].generatedFiles);
453
if (m_Mirror.Switches.includeDirs != m_Switches.includeDirs)
454
cfg->Write(tmp + _T("/switches/includes"), m_Switches.includeDirs, true);
455
if (m_Mirror.Switches.libDirs != m_Switches.libDirs)
456
cfg->Write(tmp + _T("/switches/libs"), m_Switches.libDirs, true);
457
if (m_Mirror.Switches.linkLibs != m_Switches.linkLibs)
458
cfg->Write(tmp + _T("/switches/link"), m_Switches.linkLibs, true);
459
if (m_Mirror.Switches.defines != m_Switches.defines)
460
cfg->Write(tmp + _T("/switches/define"), m_Switches.defines, true);
461
if (m_Mirror.Switches.genericSwitch != m_Switches.genericSwitch)
462
cfg->Write(tmp + _T("/switches/generic"), m_Switches.genericSwitch, true);
463
if (m_Mirror.Switches.objectExtension != m_Switches.objectExtension)
464
cfg->Write(tmp + _T("/switches/objectext"), m_Switches.objectExtension, true);
465
if (m_Mirror.Switches.needDependencies != m_Switches.needDependencies)
466
cfg->Write(tmp + _T("/switches/deps"), m_Switches.needDependencies);
467
if (m_Mirror.Switches.forceCompilerUseQuotes != m_Switches.forceCompilerUseQuotes)
468
cfg->Write(tmp + _T("/switches/forceCompilerQuotes"), m_Switches.forceCompilerUseQuotes);
469
if (m_Mirror.Switches.forceLinkerUseQuotes != m_Switches.forceLinkerUseQuotes)
470
cfg->Write(tmp + _T("/switches/forceLinkerQuotes"), m_Switches.forceLinkerUseQuotes);
471
if (m_Mirror.Switches.logging != m_Switches.logging)
472
cfg->Write(tmp + _T("/switches/logging"), m_Switches.logging);
473
if (m_Mirror.Switches.libPrefix != m_Switches.libPrefix)
474
cfg->Write(tmp + _T("/switches/libPrefix"), m_Switches.libPrefix, true);
475
if (m_Mirror.Switches.libExtension != m_Switches.libExtension)
476
cfg->Write(tmp + _T("/switches/libExtension"), m_Switches.libExtension, true);
477
if (m_Mirror.Switches.linkerNeedsLibPrefix != m_Switches.linkerNeedsLibPrefix)
478
cfg->Write(tmp + _T("/switches/linkerNeedsLibPrefix"), m_Switches.linkerNeedsLibPrefix);
479
if (m_Mirror.Switches.linkerNeedsLibExtension != m_Switches.linkerNeedsLibExtension)
480
cfg->Write(tmp + _T("/switches/linkerNeedsLibExtension"), m_Switches.linkerNeedsLibExtension);
481
if (m_Mirror.Switches.forceFwdSlashes != m_Switches.forceFwdSlashes)
482
cfg->Write(tmp + _T("/switches/forceFwdSlashes"), m_Switches.forceFwdSlashes);
483
if (m_Mirror.Switches.supportsPCH != m_Switches.supportsPCH)
484
cfg->Write(tmp + _T("/switches/supportsPCH"), m_Switches.supportsPCH);
485
if (m_Mirror.Switches.PCHExtension != m_Switches.PCHExtension)
486
cfg->Write(tmp + _T("/switches/pchExtension"), m_Switches.PCHExtension);
487
if (m_Mirror.Switches.UseFlatObjects != m_Switches.UseFlatObjects)
488
cfg->Write(tmp + _T("/switches/UseFlatObjects"), m_Switches.UseFlatObjects);
489
if (m_Mirror.Switches.UseFullSourcePaths != m_Switches.UseFullSourcePaths)
490
cfg->Write(tmp + _T("/switches/UseFullSourcePaths"), m_Switches.UseFullSourcePaths);
493
cfg->DeleteSubPath(tmp + _T("/regex"));
495
for (size_t i = 0; i < m_RegExes.Count(); ++i)
497
if (i < m_Mirror.RegExes.GetCount() && m_Mirror.RegExes[i] == m_RegExes[i])
500
group.Printf(_T("%s/regex/re%3.3d"), tmp.c_str(), i + 1);
501
RegExStruct& rs = m_RegExes[i];
502
cfg->Write(group + _T("/description"), rs.desc, true);
504
cfg->Write(group + _T("/type"), rs.lt);
505
cfg->Write(group + _T("/regex"), rs.regex, true);
507
cfg->Write(group + _T("/msg1"), rs.msg[0]);
509
cfg->Write(group + _T("/msg2"), rs.msg[1]);
511
cfg->Write(group + _T("/msg3"), rs.msg[2]);
512
if (rs.filename != 0)
513
cfg->Write(group + _T("/filename"), rs.filename);
515
cfg->Write(group + _T("/line"), rs.line);
519
wxString configpath = tmp + _T("/custom_variables/");
520
cfg->DeleteSubPath(configpath);
521
const StringHash& v = GetAllVars();
522
for (StringHash::const_iterator it = v.begin(); it != v.end(); ++it)
524
cfg->Write(configpath + it->first, it->second);
528
void Compiler::LoadSettings(const wxString& baseKey)
530
// before loading any compiler settings, keep the current settings safe
531
// so we can compare them when saving: this way we can only save what's
532
// different from the defaults
533
MirrorCurrentSettings();
535
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("compiler"));
537
// read settings version
538
wxString version = cfg->Read(_T("settings_version"));
539
bool versionMismatch = version != CompilerSettingsVersion;
543
// if using old-style keys (using integer IDs), notify user about the changes
544
static bool saidAboutCompilerIDs = false;
545
tmp.Printf(_T("%s/set%3.3d"), baseKey.c_str(), CompilerFactory::GetCompilerIndex(this) + 1);
546
if (cfg->Exists(tmp + _T("/name")))
548
if (!saidAboutCompilerIDs)
550
saidAboutCompilerIDs = true;
551
cbMessageBox(_("Compilers now use unique names instead of integer IDs.\n"
552
"Projects will be updated accordingly on load, mostly automatic."),
556
// at this point, we 'll be using the old style configuration to load settings
558
else // it's OK to use new style
559
tmp.Printf(_T("%s/%s"), baseKey.c_str(), m_ID.c_str());
561
if (!cfg->Exists(tmp + _T("/name")))
564
wxString sep = wxFileName::GetPathSeparator();
566
// if (m_ID > 255) // name changes are allowed only for user compilers
567
m_Name = cfg->Read(tmp + _T("/name"), m_Name);
569
m_MasterPath = cfg->Read(tmp + _T("/master_path"), m_MasterPath);
570
m_ExtraPaths = GetArrayFromString(cfg->Read(tmp + _T("/extra_paths"), _T("")), _T(";"));
571
m_Programs.C = cfg->Read(tmp + _T("/c_compiler"), m_Programs.C);
572
m_Programs.CPP = cfg->Read(tmp + _T("/cpp_compiler"), m_Programs.CPP);
573
m_Programs.LD = cfg->Read(tmp + _T("/linker"), m_Programs.LD);
574
m_Programs.LIB = cfg->Read(tmp + _T("/lib_linker"), m_Programs.LIB);
575
m_Programs.WINDRES = cfg->Read(tmp + _T("/res_compiler"), m_Programs.WINDRES);
576
m_Programs.MAKE = cfg->Read(tmp + _T("/make"), m_Programs.MAKE);
577
m_Programs.DBG = cfg->Read(tmp + _T("/debugger"), m_Programs.DBG);
579
SetCompilerOptions(GetArrayFromString(cfg->Read(tmp + _T("/compiler_options"), wxEmptyString)));
580
SetLinkerOptions(GetArrayFromString(cfg->Read(tmp + _T("/linker_options"), wxEmptyString)));
581
SetIncludeDirs(GetArrayFromString(cfg->Read(tmp + _T("/include_dirs"), wxEmptyString)));
582
SetResourceIncludeDirs(GetArrayFromString(cfg->Read(tmp + _T("/res_include_dirs"), wxEmptyString)));
583
SetLibDirs(GetArrayFromString(cfg->Read(tmp + _T("/library_dirs"), wxEmptyString)));
584
SetLinkLibs(GetArrayFromString(cfg->Read(tmp + _T("/libraries"), _T(""))));
585
SetCommandsBeforeBuild(GetArrayFromString(cfg->Read(tmp + _T("/commands_before"), wxEmptyString)));
586
SetCommandsAfterBuild(GetArrayFromString(cfg->Read(tmp + _T("/commands_after"), wxEmptyString)));
588
for (int i = 0; i < ctCount; ++i)
590
wxArrayString keys = cfg->EnumerateSubPaths(tmp + _T("/macros/") + CommandTypeDescriptions[i]);
591
for (size_t n = 0; n < keys.size(); ++n)
594
if (keys[n].Mid(4).ToULong(&index)) // skip 'tool'
596
while (index >= m_Commands[i].size())
597
m_Commands[i].push_back(CompilerTool());
598
CompilerTool& tool = m_Commands[i][index];
600
wxString key = wxString::Format(_T("%s/macros/%s/tool%d/"), tmp.c_str(), CommandTypeDescriptions[i].c_str(), index);
601
tool.command = cfg->Read(key + _T("command"));
602
tool.extensions = cfg->ReadArrayString(key + _T("extensions"));
603
tool.generatedFiles = cfg->ReadArrayString(key + _T("generatedFiles"));
609
m_Switches.includeDirs = cfg->Read(tmp + _T("/switches/includes"), m_Switches.includeDirs);
610
m_Switches.libDirs = cfg->Read(tmp + _T("/switches/libs"), m_Switches.libDirs);
611
m_Switches.linkLibs = cfg->Read(tmp + _T("/switches/link"), m_Switches.linkLibs);
612
m_Switches.defines = cfg->Read(tmp + _T("/switches/define"), m_Switches.defines);
613
m_Switches.genericSwitch = cfg->Read(tmp + _T("/switches/generic"), m_Switches.genericSwitch);
614
m_Switches.objectExtension = cfg->Read(tmp + _T("/switches/objectext"), m_Switches.objectExtension);
615
m_Switches.needDependencies = cfg->ReadBool(tmp + _T("/switches/deps"), m_Switches.needDependencies);
616
m_Switches.forceCompilerUseQuotes = cfg->ReadBool(tmp + _T("/switches/forceCompilerQuotes"), m_Switches.forceCompilerUseQuotes);
617
m_Switches.forceLinkerUseQuotes = cfg->ReadBool(tmp + _T("/switches/forceLinkerQuotes"), m_Switches.forceLinkerUseQuotes);
618
m_Switches.logging = (CompilerLoggingType)cfg->ReadInt(tmp + _T("/switches/logging"), m_Switches.logging);
619
m_Switches.libPrefix = cfg->Read(tmp + _T("/switches/libPrefix"), m_Switches.libPrefix);
620
m_Switches.libExtension = cfg->Read(tmp + _T("/switches/libExtension"), m_Switches.libExtension);
621
m_Switches.linkerNeedsLibPrefix = cfg->ReadBool(tmp + _T("/switches/linkerNeedsLibPrefix"), m_Switches.linkerNeedsLibPrefix);
622
m_Switches.linkerNeedsLibExtension = cfg->ReadBool(tmp + _T("/switches/linkerNeedsLibExtension"), m_Switches.linkerNeedsLibExtension);
623
m_Switches.forceFwdSlashes = cfg->ReadBool(tmp + _T("/switches/forceFwdSlashes"), m_Switches.forceFwdSlashes);
624
m_Switches.supportsPCH = cfg->ReadBool(tmp + _T("/switches/supportsPCH"), m_Switches.supportsPCH);
625
m_Switches.PCHExtension = cfg->Read(tmp + _T("/switches/pchExtension"), m_Switches.PCHExtension);
626
m_Switches.UseFlatObjects = cfg->ReadBool(tmp + _T("/switches/UseFlatObjects"), m_Switches.UseFlatObjects);
627
m_Switches.UseFullSourcePaths = cfg->ReadBool(tmp + _T("/switches/UseFullSourcePaths"), m_Switches.UseFullSourcePaths);
631
// because we 're only saving changed regexes, we can't just iterate like before.
632
// instead, we must iterate all child-keys and deduce the regex index number from
634
wxArrayString keys = cfg->EnumerateSubPaths(tmp + _T("/regex/"));
637
for (size_t i = 0; i < keys.GetCount(); ++i)
639
wxString key = keys[i];
642
if (!key.StartsWith(_T("re")))
645
if (!key.ToLong(&index, 10))
648
// 'index' now holds the regex index.
649
// read everything and either assign it to an existing regex
650
// if the index exists, or add a new regex
652
group.Printf(_T("%s/regex/re%3.3d"), tmp.c_str(), index);
653
if (!cfg->Exists(group+_T("/description")))
657
rs.desc = cfg->Read(group + _T("/description"));
658
rs.lt = (CompilerLineType)cfg->ReadInt(group + _T("/type"), 0);
659
rs.regex = cfg->Read(group + _T("/regex"));
660
rs.msg[0] = cfg->ReadInt(group + _T("/msg1"), 0);
661
rs.msg[1] = cfg->ReadInt(group + _T("/msg2"), 0);
662
rs.msg[2] = cfg->ReadInt(group + _T("/msg3"), 0);
663
rs.filename = cfg->ReadInt(group + _T("/filename"), 0);
664
rs.line = cfg->ReadInt(group + _T("/line"), 0);
666
if (index <= (long)m_RegExes.GetCount())
667
m_RegExes[index - 1] = rs;
673
wxString configpath = tmp + _T("/custom_variables/");
675
wxArrayString list = cfg->EnumerateKeys(configpath);
676
for (unsigned int i = 0; i < list.GetCount(); ++i)
677
SetVar(list[i], cfg->Read(configpath + _T('/') + list[i]), false);
682
msg << _("Some compiler settings defaults have changed in this version.\n"
683
"It is recommended that you allow updating of your settings to "
684
"the new defaults.\n"
685
"Only disallow this if you don't want to lose any customizations "
686
"you have done to this compiler's settings.\n\n"
687
"Note that the only settings that are affected are those found in "
688
"\"Advanced compiler options\"...\n\n"
689
"Do you want to update your current settings to the new defaults?");
690
// don't ask if the compiler is not valid (i.e. not installed), just update
691
if (!IsValid() || cbMessageBox(msg, m_Name, wxICON_QUESTION | wxYES_NO) == wxID_YES)
693
for (int i = 0; i < ctCount; ++i)
694
m_Commands[i] = m_Mirror.Commands[i];
695
m_Switches = m_Mirror.Switches;
696
m_Options = m_Mirror.Options;
697
m_RegExes = m_Mirror.RegExes;
702
CompilerLineType Compiler::CheckForWarningsAndErrors(const wxString& line)
704
m_ErrorFilename.Clear();
708
for (size_t i = 0; i < m_RegExes.Count(); ++i)
710
RegExStruct& rs = m_RegExes[i];
711
if (rs.regex.IsEmpty())
713
wxRegEx regex(rs.regex);
714
if (regex.Matches(line))
717
m_ErrorFilename = UnixFilename(regex.GetMatch(line, rs.filename));
719
m_ErrorLine = regex.GetMatch(line, rs.line);
720
for (int x = 0; x < 3; ++x)
724
if (!m_Error.IsEmpty())
726
m_Error << regex.GetMatch(line, rs.msg[x]);
732
return cltNormal; // default return value