1
//////////////////////////////////////////////////////////////////////////////
2
//////////////////////////////////////////////////////////////////////////////
4
// copyright : (C) 2008 by Eran Ifrah
5
// file name : build_config.cpp
7
// -------------------------------------------------------------------------
10
// / __ \ | | | | (_) |
11
// | / \/ ___ __| | ___| | _| |_ ___
12
// | | / _ \ / _ |/ _ \ | | | __/ _ )
13
// | \__/\ (_) | (_| | __/ |___| | || __/
14
// \____/\___/ \__,_|\___\_____/_|\__\___|
18
// This program is free software; you can redistribute it and/or modify
19
// it under the terms of the GNU General Public License as published by
20
// the Free Software Foundation; either version 2 of the License, or
21
// (at your option) any later version.
23
//////////////////////////////////////////////////////////////////////////////
24
//////////////////////////////////////////////////////////////////////////////
25
#include "build_config.h"
27
#include "wx/tokenzr.h"
30
#include "editor_config.h"
31
#include "build_settings_config.h"
32
#include "debuggermanager.h"
34
BuildConfig::BuildConfig(wxXmlNode *node)
37
m_name = XmlUtils::ReadString(node, wxT("Name"));
38
m_compilerType = XmlUtils::ReadString(node, wxT("CompilerType"));
39
m_debuggerType = XmlUtils::ReadString(node, wxT("DebuggerType"));
40
wxXmlNode *compile = XmlUtils::FindFirstByTagName(node, wxT("Compiler"));
41
m_projectType = XmlUtils::ReadString(node, wxT("Type"));
43
// read the compile options
45
m_compilerRequired = XmlUtils::ReadBool(compile, wxT("Required"), true);
46
m_compileOptions = XmlUtils::ReadString(compile, wxT("Options"));
47
wxXmlNode *child = compile->GetChildren();
49
if (child->GetName() == wxT("IncludePath")) {
50
m_includePath.Add(XmlUtils::ReadString(child, wxT("Value")));
51
} else if (child->GetName() == wxT("Preprocessor")) {
52
m_preprocessor.Add(XmlUtils::ReadString(child, wxT("Value")));
54
child = child->GetNext();
58
wxXmlNode *linker = XmlUtils::FindFirstByTagName(node, wxT("Linker"));
59
// read the linker options
61
m_linkerRequired = XmlUtils::ReadBool(linker, wxT("Required"), true);
62
m_linkOptions = XmlUtils::ReadString(linker, wxT("Options"));
63
wxXmlNode *child = linker->GetChildren();
65
if (child->GetName() == wxT("Library")) {
66
m_libs.Add(XmlUtils::ReadString(child, wxT("Value")));
67
} else if (child->GetName() == wxT("LibraryPath")) {
68
m_libPath.Add(XmlUtils::ReadString(child, wxT("Value")));
70
child = child->GetNext();
74
// read the postbuild commands
75
wxXmlNode *debugger = XmlUtils::FindFirstByTagName(node, wxT("Debugger"));
76
m_isDbgRemoteTarget = false;
79
m_isDbgRemoteTarget = XmlUtils::ReadBool(debugger, wxT("IsRemote"));
80
m_dbgHostName = XmlUtils::ReadString(debugger, wxT("RemoteHostName"));
81
m_dbgHostPort = XmlUtils::ReadString(debugger, wxT("RemoteHostPort"));
82
m_debuggerPath = XmlUtils::ReadString(debugger, wxT("DebuggerPath"));
84
wxXmlNode *child = debugger->GetChildren();
86
if (child->GetName() == wxT("StartupCommands")) {
87
m_debuggerStartupCmds = child->GetNodeContent();
88
} else if (child->GetName() == wxT("PostConnectCommands")) {
89
m_debuggerPostRemoteConnectCmds = child->GetNodeContent();
91
child = child->GetNext();
95
// read the resource compile options
96
wxXmlNode *resCmp = XmlUtils::FindFirstByTagName(node, wxT("ResourceCompiler"));
98
m_isResCmpNeeded = XmlUtils::ReadBool(resCmp, wxT("Required"), true);
99
m_resCompileOptions = XmlUtils::ReadString(resCmp, wxT("Options"));
100
wxXmlNode *child = resCmp->GetChildren();
102
if (child->GetName() == wxT("IncludePath")) {
103
m_resCmpIncludePath << XmlUtils::ReadString(child, wxT("Value")) << wxT(";");
105
child = child->GetNext();
109
// read the prebuild commands
110
wxXmlNode *preBuild = XmlUtils::FindFirstByTagName(node, wxT("PreBuild"));
112
wxXmlNode *child = preBuild->GetChildren();
114
if (child->GetName() == wxT("Command")) {
115
bool enabled = XmlUtils::ReadBool(child, wxT("Enabled"));
117
BuildCommand cmd(child->GetNodeContent(), enabled);
118
m_preBuildCommands.push_back(cmd);
120
child = child->GetNext();
123
// read the postbuild commands
124
wxXmlNode *postBuild = XmlUtils::FindFirstByTagName(node, wxT("PostBuild"));
126
wxXmlNode *child = postBuild->GetChildren();
128
if (child->GetName() == wxT("Command")) {
129
bool enabled = XmlUtils::ReadBool(child, wxT("Enabled"));
130
BuildCommand cmd(child->GetNodeContent(), enabled);
131
m_postBuildCommands.push_back(cmd);
133
child = child->GetNext();
137
wxXmlNode *customBuild = XmlUtils::FindFirstByTagName(node, wxT("CustomBuild"));
139
m_enableCustomBuild = XmlUtils::ReadBool(customBuild, wxT("Enabled"), false);
140
wxXmlNode *child = customBuild->GetChildren();
142
if (child->GetName() == wxT("BuildCommand")) {
143
m_customBuildCmd = child->GetNodeContent();
144
} else if (child->GetName() == wxT("CleanCommand")) {
145
m_customCleanCmd = child->GetNodeContent();
146
} else if (child->GetName() == wxT("SingleFileCommand")) {
147
m_singleFileBuildCommand = child->GetNodeContent();
148
} else if (child->GetName() == wxT("PreprocessFileCommand")) {
149
m_preprocessFileCommand = child->GetNodeContent();
150
} else if (child->GetName() == wxT("WorkingDirectory")) {
151
m_customBuildWorkingDir = child->GetNodeContent();
152
} else if (child->GetName() == wxT("ThirdPartyToolName")) {
153
m_toolName = child->GetNodeContent();
154
} else if (child->GetName() == wxT("MakefileGenerationCommand")) {
155
m_makeGenerationCommand = child->GetNodeContent();
156
} else if (child->GetName() == wxT("Target")) {
157
wxString target_name = child->GetPropVal(wxT("Name"), wxT(""));
158
wxString target_cmd = child->GetNodeContent();
159
if(target_name.IsEmpty() == false) {
160
m_customTargets[target_name] = target_cmd;
163
child = child->GetNext();
166
m_enableCustomBuild = false;
169
wxXmlNode *customPreBuild = XmlUtils::FindFirstByTagName(node, wxT("AdditionalRules"));
170
if (customPreBuild) {
171
wxXmlNode *child = customPreBuild->GetChildren();
173
if (child->GetName() == wxT("CustomPreBuild")) {
174
m_customPreBuildRule = child->GetNodeContent();
175
} else if (child->GetName() == wxT("CustomPostBuild")) {
176
m_customPostBuildRule = child->GetNodeContent();
178
child = child->GetNext();
182
wxXmlNode *general = XmlUtils::FindFirstByTagName(node, wxT("General"));
184
m_outputFile = XmlUtils::ReadString(general, wxT("OutputFile"));
185
m_intermediateDirectory = XmlUtils::ReadString(general, wxT("IntermediateDirectory"), wxT("."));
186
m_command = XmlUtils::ReadString(general, wxT("Command"));
187
m_commandArguments = XmlUtils::ReadString(general, wxT("CommandArguments"));
188
m_workingDirectory = XmlUtils::ReadString(general, wxT("WorkingDirectory"), wxT("."));
189
m_pauseWhenExecEnds = XmlUtils::ReadBool(general, wxT("PauseExecWhenProcTerminates"), true);
193
//create default project settings
194
m_name = wxT("Debug");
195
m_compilerRequired = true;
196
m_includePath.Add(wxT("."));
197
m_compileOptions = wxT("-g");
198
m_linkOptions = wxT("-O0");
199
m_libPath.Add(wxT("."));
200
m_libPath.Add(wxT("Debug"));
201
m_linkerRequired = true;
202
m_intermediateDirectory = wxT("./Debug");
203
m_workingDirectory = wxT("./Debug");
204
m_projectType = Project::EXECUTABLE;
205
m_enableCustomBuild = false;
206
m_customBuildCmd = wxEmptyString;
207
m_customCleanCmd = wxEmptyString;
208
m_isResCmpNeeded = false;
209
m_resCmpIncludePath = wxEmptyString;
210
m_resCompileOptions = wxEmptyString;
211
m_customPostBuildRule = wxEmptyString;
212
m_customPreBuildRule = wxEmptyString;
213
m_makeGenerationCommand = wxEmptyString;
214
m_toolName = wxEmptyString;
215
m_singleFileBuildCommand = wxEmptyString;
216
m_preprocessFileCommand = wxEmptyString;
217
m_debuggerStartupCmds = wxEmptyString;
218
m_debuggerPostRemoteConnectCmds = wxEmptyString;
219
m_isDbgRemoteTarget = false;
221
BuildSettingsConfigCookie cookie;
222
CompilerPtr cmp = BuildSettingsConfigST::Get()->GetFirstCompiler(cookie);
224
m_compilerType = cmp->GetName();
226
wxArrayString dbgs = DebuggerMgr::Get().GetAvailableDebuggers();
227
if (dbgs.GetCount() > 0) {
228
m_debuggerType = dbgs.Item(0);
233
BuildConfig::~BuildConfig()
237
wxString BuildConfig::NormalizePath(const wxString &path) const
239
wxString normalized_path(path);
240
normalized_path.Replace(wxT("\\"), wxT("/"));
241
return normalized_path;
244
BuildConfig *BuildConfig::Clone() const
246
wxXmlNode *node = ToXml();
247
BuildConfig *cloned = new BuildConfig(node);
252
wxXmlNode *BuildConfig::ToXml() const
254
wxXmlNode *node = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("Configuration"));
255
node->AddProperty(wxT("Name"), m_name);
256
node->AddProperty(wxT("CompilerType"), m_compilerType);
257
node->AddProperty(wxT("DebuggerType"), m_debuggerType);
258
node->AddProperty(wxT("Type"), m_projectType);
260
wxXmlNode *general = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("General"));
261
general->AddProperty(wxT("OutputFile"), m_outputFile);
262
general->AddProperty(wxT("IntermediateDirectory"), m_intermediateDirectory);
263
general->AddProperty(wxT("Command"), m_command );
264
general->AddProperty(wxT("CommandArguments"), m_commandArguments);
265
general->AddProperty(wxT("WorkingDirectory"), m_workingDirectory);
266
general->AddProperty(wxT("PauseExecWhenProcTerminates"), BoolToString(m_pauseWhenExecEnds));
267
node->AddChild(general);
269
//create the compile node
270
wxXmlNode *compile = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("Compiler"));
271
compile->AddProperty(wxT("Required"), BoolToString(m_compilerRequired));
272
compile->AddProperty(wxT("Options"), m_compileOptions);
273
node->AddChild(compile);
276
for (i=0; i<m_includePath.GetCount(); i++) {
277
wxXmlNode *option = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("IncludePath"));
278
option->AddProperty(wxT("Value"), m_includePath.Item(i));
279
compile->AddChild(option);
282
for (i=0; i<m_preprocessor.GetCount(); i++) {
283
wxXmlNode *prep = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("Preprocessor"));
284
prep->AddProperty(wxT("Value"), m_preprocessor.Item(i));
285
compile->AddChild(prep);
289
wxXmlNode *link = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("Linker"));
290
link->AddProperty(wxT("Required"), BoolToString(m_linkerRequired));
291
link->AddProperty(wxT("Options"), m_linkOptions);
292
node->AddChild(link);
294
for (i=0; i<m_libPath.GetCount(); i++) {
295
wxXmlNode *option = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("LibraryPath"));
296
option->AddProperty(wxT("Value"), m_libPath.Item(i));
297
link->AddChild(option);
300
for (i=0; i<m_libs.GetCount(); i++) {
301
wxXmlNode *option = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("Library"));
302
option->AddProperty(wxT("Value"), m_libs.Item(i));
303
link->AddChild(option);
306
wxXmlNode *debugger = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("Debugger"));
307
debugger->AddProperty(wxT("IsRemote"), BoolToString(m_isDbgRemoteTarget));
308
debugger->AddProperty(wxT("RemoteHostName"), m_dbgHostName);
309
debugger->AddProperty(wxT("RemoteHostPort"), m_dbgHostPort);
310
debugger->AddProperty(wxT("DebuggerPath"), m_debuggerPath);
312
wxXmlNode *dbgStartupCommands = new wxXmlNode(debugger, wxXML_ELEMENT_NODE, wxT("StartupCommands"));
313
XmlUtils::SetNodeContent(dbgStartupCommands, m_debuggerStartupCmds);
315
wxXmlNode *dbgPostConnectCommands = new wxXmlNode(debugger, wxXML_ELEMENT_NODE, wxT("PostConnectCommands"));
316
XmlUtils::SetNodeContent(dbgPostConnectCommands, m_debuggerPostRemoteConnectCmds);
318
node->AddChild(debugger);
320
//add the resource compiler node
321
wxXmlNode *resCmp = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("ResourceCompiler"));
322
resCmp->AddProperty(wxT("Required"), BoolToString(m_isResCmpNeeded));
323
resCmp->AddProperty(wxT("Options"), m_resCompileOptions);
324
node->AddChild(resCmp);
326
wxStringTokenizer tok(m_resCmpIncludePath, wxT(";"));
327
while (tok.HasMoreTokens()) {
328
wxXmlNode *option = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("IncludePath"));
329
option->AddProperty(wxT("Value"),tok.NextToken());
330
resCmp->AddChild(option);
333
//add prebuild commands
334
wxXmlNode *preBuild = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("PreBuild"));
335
node->AddChild(preBuild);
337
BuildCommandList::const_iterator iter = m_preBuildCommands.begin();
338
for (; iter != m_preBuildCommands.end(); iter++) {
339
wxXmlNode *command = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("Command"));
340
command->AddProperty(wxT("Enabled"), BoolToString(iter->GetEnabled()));
341
XmlUtils::SetNodeContent(command, iter->GetCommand());
342
preBuild->AddChild(command);
345
//add postbuild commands
346
wxXmlNode *postBuild = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("PostBuild"));
347
node->AddChild(postBuild);
348
iter = m_postBuildCommands.begin();
349
for (; iter != m_postBuildCommands.end(); iter++) {
350
wxXmlNode *command = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("Command"));
351
command->AddProperty(wxT("Enabled"), BoolToString(iter->GetEnabled()));
352
XmlUtils::SetNodeContent(command, iter->GetCommand());
353
postBuild->AddChild(command);
356
//add postbuild commands
357
wxXmlNode *customBuild = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("CustomBuild"));
358
node->AddChild(customBuild);
359
customBuild->AddProperty(wxT("Enabled"), BoolToString(m_enableCustomBuild));
361
//add the working directory of the custom build
362
wxXmlNode *customBuildWd = new wxXmlNode(customBuild, wxXML_ELEMENT_NODE, wxT("WorkingDirectory"));
363
XmlUtils::SetNodeContent(customBuildWd, m_customBuildWorkingDir);
365
//add the makefile generation command
366
wxXmlNode *toolName = new wxXmlNode(customBuild, wxXML_ELEMENT_NODE, wxT("ThirdPartyToolName"));
367
XmlUtils::SetNodeContent(toolName, m_toolName);
369
//add the makefile generation command
370
wxXmlNode *makeGenCmd = new wxXmlNode(customBuild, wxXML_ELEMENT_NODE, wxT("MakefileGenerationCommand"));
371
XmlUtils::SetNodeContent(makeGenCmd, m_makeGenerationCommand);
373
//add the makefile generation command
374
wxXmlNode *singleFileCmd = new wxXmlNode(customBuild, wxXML_ELEMENT_NODE, wxT("SingleFileCommand"));
375
XmlUtils::SetNodeContent(singleFileCmd, m_singleFileBuildCommand);
377
//add the makefile generation command
378
wxXmlNode *preprocessFileCmd = new wxXmlNode(customBuild, wxXML_ELEMENT_NODE, wxT("PreprocessFileCommand"));
379
XmlUtils::SetNodeContent(preprocessFileCmd, m_preprocessFileCommand);
381
//add build and clean commands
382
wxXmlNode *bldCmd = new wxXmlNode(customBuild, wxXML_ELEMENT_NODE, wxT("BuildCommand"));
383
XmlUtils::SetNodeContent(bldCmd, m_customBuildCmd);
385
wxXmlNode *clnCmd = new wxXmlNode(customBuild, wxXML_ELEMENT_NODE, wxT("CleanCommand"));
386
XmlUtils::SetNodeContent(clnCmd, m_customCleanCmd);
389
std::map<wxString, wxString>::const_iterator ir = m_customTargets.begin();
390
for(; ir != m_customTargets.end(); ir++) {
391
wxString target_name = ir->first;
392
wxString target_cmd = ir->second;
394
wxXmlNode *customTarget = new wxXmlNode(customBuild, wxXML_ELEMENT_NODE, wxT("Target"));
395
customTarget->AddProperty(wxT("Name"), target_name);
396
XmlUtils::SetNodeContent(customTarget, target_cmd);
399
//add the additional rules
400
wxXmlNode *additionalCmds = new wxXmlNode(NULL, wxXML_ELEMENT_NODE, wxT("AdditionalRules"));
401
node->AddChild(additionalCmds);
403
wxXmlNode *preCmd = new wxXmlNode(additionalCmds, wxXML_ELEMENT_NODE, wxT("CustomPreBuild"));
404
XmlUtils::SetNodeContent(preCmd, m_customPreBuildRule);
405
wxXmlNode *postCmd = new wxXmlNode(additionalCmds, wxXML_ELEMENT_NODE, wxT("CustomPostBuild"));
406
XmlUtils::SetNodeContent(postCmd, m_customPostBuildRule);
410
void BuildConfig::SetPreprocessor(const wxString &pre)
412
FillFromSmiColonString(m_preprocessor, pre);
415
void BuildConfig::SetIncludePath(const wxString &path)
417
FillFromSmiColonString(m_includePath, path);
420
void BuildConfig::SetLibraries(const wxString &libs)
422
FillFromSmiColonString(m_libs, libs);
425
void BuildConfig::SetLibPath(const wxString &paths)
427
FillFromSmiColonString(m_libPath, paths);
430
void BuildConfig::FillFromSmiColonString(wxArrayString &arr, const wxString &str)
433
wxStringTokenizer tkz(str, wxT(";"));
434
while (tkz.HasMoreTokens()) {
435
wxString token = tkz.NextToken();
436
arr.Add(token.Trim());
440
wxString BuildConfig::ArrayToSmiColonString(const wxArrayString &array) const
443
for (size_t i=0; i<array.GetCount(); i++) {
444
result += NormalizePath(array.Item(i));
447
return result.BeforeLast(wxT(';'));
450
void BuildConfig::StripSemiColons(wxString &str)
452
str.Replace(wxT(";"), wxT(" "));
455
wxString BuildConfig::GetLibPath() const
457
return ArrayToSmiColonString(m_libPath);
460
wxString BuildConfig::GetLibraries() const
462
return ArrayToSmiColonString(m_libs);
465
wxString BuildConfig::GetIncludePath() const
467
return ArrayToSmiColonString(m_includePath);
470
wxString BuildConfig::GetPreprocessor() const
472
return ArrayToSmiColonString(m_preprocessor);