1 /*
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
4 *
5 * $Revision: 11884 $
6 * $Id: compiletargetbase.cpp 11884 2019-10-26 09:11:35Z fuscated $
7 * $HeadURL: svn://svn.code.sf.net/p/codeblocks/code/branches/release-20.xx/src/sdk/compiletargetbase.cpp $
8 */
9
10 #include "sdk_precomp.h"
11
12 #ifndef CB_PRECOMP
13 #include <wx/filename.h>
14
15 #include "compiletargetbase.h"
16 #include "compilerfactory.h"
17 #include "globals.h"
18 #include "logmanager.h" // Manager::Get()->GetLogManager()->DebugLog(F())
19 #endif
20
21 #include "filefilters.h"
22
CompileTargetBase()23 CompileTargetBase::CompileTargetBase()
24 : m_TargetType(ttExecutable),
25 m_RunHostApplicationInTerminal(false),
26 m_PrefixGenerationPolicy(tgfpPlatformDefault),
27 m_ExtensionGenerationPolicy(tgfpPlatformDefault)
28 {
29 //ctor
30 for (int i = 0; i < static_cast<int>(ortLast); ++i)
31 {
32 m_OptionsRelation[i] = orAppendToParentOptions;
33 }
34
35 // default "make" commands
36 m_MakeCommands[mcBuild] = _T("$make -f $makefile $target");
37 m_MakeCommands[mcCompileFile] = _T("$make -f $makefile $file");
38 m_MakeCommands[mcClean] = _T("$make -f $makefile clean$target");
39 m_MakeCommands[mcDistClean] = _T("$make -f $makefile distclean$target");
40 m_MakeCommands[mcAskRebuildNeeded] = _T("$make -q -f $makefile $target");
41 // m_MakeCommands[mcSilentBuild] = _T("$make -s -f $makefile $target");
42 m_MakeCommands[mcSilentBuild] = m_MakeCommands[mcBuild] + _T(" > $(CMD_NULL)");
43 m_MakeCommandsModified = false;
44 }
45
~CompileTargetBase()46 CompileTargetBase::~CompileTargetBase()
47 {
48 //dtor
49 }
50
SetTargetFilenameGenerationPolicy(TargetFilenameGenerationPolicy prefix,TargetFilenameGenerationPolicy extension)51 void CompileTargetBase::SetTargetFilenameGenerationPolicy(TargetFilenameGenerationPolicy prefix,
52 TargetFilenameGenerationPolicy extension)
53 {
54 m_PrefixGenerationPolicy = prefix;
55 m_ExtensionGenerationPolicy = extension;
56 SetModified(true);
57 }
58
GetTargetFilenameGenerationPolicy(TargetFilenameGenerationPolicy & prefixOut,TargetFilenameGenerationPolicy & extensionOut) const59 void CompileTargetBase::GetTargetFilenameGenerationPolicy(TargetFilenameGenerationPolicy& prefixOut,
60 TargetFilenameGenerationPolicy& extensionOut) const
61 {
62 prefixOut = m_PrefixGenerationPolicy;
63 extensionOut = m_ExtensionGenerationPolicy;
64 }
65
GetFilename() const66 const wxString& CompileTargetBase::GetFilename() const
67 {
68 return m_Filename;
69 }
70
GetTitle() const71 const wxString& CompileTargetBase::GetTitle() const
72 {
73 return m_Title;
74 }
75
SetTitle(const wxString & title)76 void CompileTargetBase::SetTitle(const wxString& title)
77 {
78 if (m_Title == title)
79 return;
80 m_Title = title;
81 SetModified(true);
82 }
83
SetOutputFilename(const wxString & filename)84 void CompileTargetBase::SetOutputFilename(const wxString& filename)
85 {
86 if (filename.IsEmpty())
87 {
88 m_OutputFilename = SuggestOutputFilename();
89 SetModified(true);
90 return;
91 }
92 else if (m_OutputFilename == filename)
93 return;
94 m_OutputFilename = UnixFilename(filename);
95 GenerateTargetFilename(m_OutputFilename);
96 SetModified(true);
97 }
98
SetImportLibraryFilename(const wxString & filename)99 void CompileTargetBase::SetImportLibraryFilename(const wxString& filename)
100 {
101 if (filename.IsEmpty())
102 {
103 m_ImportLibraryFilename = _T("$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME)");
104 SetModified(true);
105 return;
106 }
107 else if (m_ImportLibraryFilename == filename)
108 return;
109 m_ImportLibraryFilename = UnixFilename(filename);
110 }
111
SetDefinitionFileFilename(const wxString & filename)112 void CompileTargetBase::SetDefinitionFileFilename(const wxString& filename)
113 {
114 if (filename.IsEmpty())
115 {
116 m_DefinitionFileFilename = _T("$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME)");
117 SetModified(true);
118 return;
119 }
120 else if (m_DefinitionFileFilename == filename)
121 return;
122 m_DefinitionFileFilename = UnixFilename(filename);
123 }
124
SetWorkingDir(const wxString & dirname)125 void CompileTargetBase::SetWorkingDir(const wxString& dirname)
126 {
127 if (m_WorkingDir == dirname)
128 return;
129 m_WorkingDir = UnixFilename(dirname);
130 SetModified(true);
131 }
132
SetObjectOutput(const wxString & dirname)133 void CompileTargetBase::SetObjectOutput(const wxString& dirname)
134 {
135 if (m_ObjectOutput == dirname)
136 return;
137 m_ObjectOutput = UnixFilename(dirname);
138 SetModified(true);
139 }
140
SetDepsOutput(const wxString & dirname)141 void CompileTargetBase::SetDepsOutput(const wxString& dirname)
142 {
143 if (m_DepsOutput == dirname)
144 return;
145 m_DepsOutput = UnixFilename(dirname);
146 SetModified(true);
147 }
148
GetOptionRelation(OptionsRelationType type) const149 OptionsRelation CompileTargetBase::GetOptionRelation(OptionsRelationType type) const
150 {
151 return m_OptionsRelation[type];
152 }
153
SetOptionRelation(OptionsRelationType type,OptionsRelation rel)154 void CompileTargetBase::SetOptionRelation(OptionsRelationType type, OptionsRelation rel)
155 {
156 if (m_OptionsRelation[type] == rel)
157 return;
158 m_OptionsRelation[type] = rel;
159 SetModified(true);
160 }
161
GetOutputFilename() const162 wxString CompileTargetBase::GetOutputFilename() const
163 {
164 if (m_TargetType == ttCommandsOnly)
165 return wxEmptyString;
166 if (m_OutputFilename.IsEmpty())
167 m_OutputFilename = SuggestOutputFilename();
168 return m_OutputFilename;
169 }
170
SuggestOutputFilename() const171 wxString CompileTargetBase::SuggestOutputFilename() const
172 {
173 wxString suggestion;
174 switch (m_TargetType)
175 {
176 case ttConsoleOnly: // fall through
177 case ttExecutable: suggestion = GetExecutableFilename(); break;
178 case ttDynamicLib: suggestion = GetDynamicLibFilename(); break;
179 case ttStaticLib: suggestion = GetStaticLibFilename(); break;
180 case ttNative: suggestion = GetNativeFilename(); break;
181 case ttCommandsOnly: // fall through
182 default:
183 suggestion.Clear();
184 break;
185 }
186 wxFileName fname(suggestion);
187 return UnixFilename(fname.GetFullName());
188 }
189
GetWorkingDir()190 wxString CompileTargetBase::GetWorkingDir()
191 {
192 if (m_TargetType != ttConsoleOnly && m_TargetType != ttExecutable && m_TargetType != ttDynamicLib)
193 return wxEmptyString;
194 wxString out;
195 if (m_WorkingDir.IsEmpty())
196 {
197 out = GetOutputFilename();
198 return wxFileName(out).GetPath(wxPATH_GET_VOLUME);
199 }
200 return m_WorkingDir;
201 }
202
GetObjectOutput() const203 wxString CompileTargetBase::GetObjectOutput() const
204 {
205 if (m_TargetType == ttCommandsOnly)
206 return wxEmptyString;
207 wxString out;
208 if (m_ObjectOutput.IsEmpty())
209 {
210 out = GetBasePath();
211 if (out.IsEmpty() || out.Matches(_T(".")))
212 return _T(".objs");
213 else
214 return out + wxFileName::GetPathSeparator() + _T(".objs");
215 }
216 return m_ObjectOutput;
217 }
218
GetDepsOutput() const219 wxString CompileTargetBase::GetDepsOutput() const
220 {
221 if (m_TargetType == ttCommandsOnly)
222 return wxEmptyString;
223 wxString out;
224 if (m_DepsOutput.IsEmpty())
225 {
226 out = GetBasePath();
227 if (out.IsEmpty() || out.Matches(_T(".")))
228 return _T(".deps");
229 else
230 return out + wxFileName::GetPathSeparator() + _T(".deps");
231 }
232 return m_DepsOutput;
233 }
234
GenerateTargetFilename(wxString & filename) const235 void CompileTargetBase::GenerateTargetFilename(wxString& filename) const
236 {
237 // nothing to do if no auto-generation
238 if ( m_PrefixGenerationPolicy == tgfpNone
239 && m_ExtensionGenerationPolicy == tgfpNone )
240 return;
241
242 wxFileName fname(filename);
243 filename.Clear();
244 // path with volume and separator
245 filename << fname.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
246 // prefix + name + extension
247 switch (m_TargetType)
248 {
249 case ttConsoleOnly:
250 case ttExecutable:
251 {
252 if (m_ExtensionGenerationPolicy == tgfpPlatformDefault)
253 {
254 filename << fname.GetName();
255 filename << FileFilters::EXECUTABLE_DOT_EXT;
256 }
257 else
258 filename << fname.GetFullName();
259 break;
260 }
261 case ttDynamicLib:
262 {
263 if (m_PrefixGenerationPolicy == tgfpPlatformDefault)
264 {
265 wxString prefix = wxEmptyString;
266 // On linux, "lib" is the common prefix for this platform
267 if (platform::Linux)
268 prefix = wxT("lib");
269 // FIXME (Morten#5#): What about Mac (Windows is OK)?!
270
271 // avoid adding the prefix, if there is no prefix, or already its there
272 if (!prefix.IsEmpty() && !fname.GetName().StartsWith(prefix))
273 filename << prefix;
274 }
275 if (m_ExtensionGenerationPolicy == tgfpPlatformDefault)
276 filename << fname.GetName() << FileFilters::DYNAMICLIB_DOT_EXT;
277 else
278 filename << fname.GetFullName();
279 break;
280 }
281 case ttNative:
282 {
283 if (m_ExtensionGenerationPolicy == tgfpPlatformDefault)
284 filename << fname.GetName() << FileFilters::NATIVE_DOT_EXT;
285 else
286 filename << fname.GetFullName();
287 break;
288 }
289 case ttStaticLib:
290 {
291 if (m_PrefixGenerationPolicy == tgfpPlatformDefault)
292 {
293 Compiler* compiler = CompilerFactory::GetCompiler(m_CompilerId);
294 wxString prefix = compiler ? compiler->GetSwitches().libPrefix : _T("");
295 // avoid adding the prefix, if already there
296 if (!prefix.IsEmpty() && !fname.GetName().StartsWith(prefix))
297 filename << prefix;
298 }
299 if (m_ExtensionGenerationPolicy == tgfpPlatformDefault)
300 {
301 Compiler* compiler = CompilerFactory::GetCompiler(m_CompilerId);
302 wxString Ext = compiler ? compiler->GetSwitches().libExtension : FileFilters::STATICLIB_EXT;
303 filename << fname.GetName() << _T(".") << Ext;
304 }
305 else
306 filename << fname.GetFullName();
307 break;
308 }
309 case ttCommandsOnly: // fall through
310 default:
311 filename.Clear();
312 break;
313 }
314
315 #ifdef command_line_generation
316 Manager::Get()->GetLogManager()->DebugLog(F(_T("CompileTargetBase::GenerateTargetFilename got %s and returns: '%s'"), fname.GetFullPath().wx_str(), filename.wx_str()));
317 #endif
318 }
319
GetExecutableFilename() const320 wxString CompileTargetBase::GetExecutableFilename() const
321 {
322 if (m_TargetType == ttCommandsOnly)
323 return wxEmptyString;
324
325 if (m_PrefixGenerationPolicy != tgfpNone || m_ExtensionGenerationPolicy != tgfpNone)
326 {
327 wxString out = m_Filename;
328 GenerateTargetFilename(out);
329 return out;
330 }
331
332 wxFileName fname(m_Filename);
333 #ifdef __WXMSW__
334 fname.SetExt(FileFilters::EXECUTABLE_EXT);
335 #else
336 fname.SetExt(_T(""));
337 #endif
338 return fname.GetFullPath();
339 }
340
GetNativeFilename() const341 wxString CompileTargetBase::GetNativeFilename() const
342 {
343 if (m_TargetType == ttCommandsOnly)
344 return wxEmptyString;
345
346 if (m_Filename.IsEmpty())
347 m_Filename = m_OutputFilename;
348
349 if (m_PrefixGenerationPolicy != tgfpNone || m_ExtensionGenerationPolicy != tgfpNone)
350 {
351 wxString out = m_Filename;
352 GenerateTargetFilename(out);
353 return out;
354 }
355
356 wxFileName fname(m_Filename);
357 fname.SetName(fname.GetName());
358 fname.SetExt(FileFilters::NATIVE_EXT);
359 return fname.GetFullPath();
360 }
361
GetDynamicLibFilename() const362 wxString CompileTargetBase::GetDynamicLibFilename() const
363 {
364 if (m_TargetType == ttCommandsOnly)
365 return wxEmptyString;
366
367 if (m_Filename.IsEmpty())
368 m_Filename = m_OutputFilename;
369
370 if (m_PrefixGenerationPolicy != tgfpNone || m_ExtensionGenerationPolicy != tgfpNone)
371 {
372 wxString out = m_Filename;
373 GenerateTargetFilename(out);
374 #ifdef command_line_generation
375 Manager::Get()->GetLogManager()->DebugLog(F(_T("CompileTargetBase::GetDynamicLibFilename [0] returns: '%s'"), out.wx_str()));
376 #endif
377 return out;
378 }
379
380 wxFileName fname(m_Filename);
381 fname.SetName(fname.GetName());
382 fname.SetExt(FileFilters::DYNAMICLIB_EXT);
383
384 #ifdef command_line_generation
385 Manager::Get()->GetLogManager()->DebugLog(F(_T("CompileTargetBase::GetDynamicLibFilename [1] returns: '%s'"), fname.GetFullPath().wx_str()));
386 #endif
387 return fname.GetFullPath();
388 }
389
GetDynamicLibImportFilename()390 wxString CompileTargetBase::GetDynamicLibImportFilename()
391 {
392 if (m_TargetType == ttCommandsOnly)
393 return wxEmptyString;
394
395 if (m_ImportLibraryFilename.IsEmpty())
396 m_ImportLibraryFilename = _T("$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME)");
397
398 wxFileName fname(m_ImportLibraryFilename);
399
400 #ifdef command_line_generation
401 Manager::Get()->GetLogManager()->DebugLog(F(_T("CompileTargetBase::GetDynamicLibImportFilename returns: '%s'"), fname.GetFullPath().wx_str()));
402 #endif
403 return fname.GetFullPath();
404 }
405
GetDynamicLibDefFilename()406 wxString CompileTargetBase::GetDynamicLibDefFilename()
407 {
408 if (m_TargetType == ttCommandsOnly)
409 return wxEmptyString;
410
411 if (m_DefinitionFileFilename.IsEmpty())
412 m_DefinitionFileFilename = _T("$(TARGET_OUTPUT_DIR)$(TARGET_OUTPUT_BASENAME)");
413
414 wxFileName fname(m_DefinitionFileFilename);
415
416 #ifdef command_line_generation
417 Manager::Get()->GetLogManager()->DebugLog(F(_T("CompileTargetBase::GetDynamicLibDefFilename returns: '%s'"), fname.GetFullPath().wx_str()));
418 #endif
419 return fname.GetFullPath();
420 }
421
GetStaticLibFilename() const422 wxString CompileTargetBase::GetStaticLibFilename() const
423 {
424 if (m_TargetType == ttCommandsOnly)
425 return wxEmptyString;
426
427 if (m_Filename.IsEmpty())
428 m_Filename = m_OutputFilename;
429
430 /* NOTE: There is no need to check for Generation policy for import library
431 if target type is ttDynamicLib. */
432 if ( (m_TargetType == ttStaticLib)
433 && ( m_PrefixGenerationPolicy != tgfpNone
434 || m_ExtensionGenerationPolicy != tgfpNone) )
435 {
436 wxString out = m_Filename;
437 GenerateTargetFilename(out);
438 #ifdef command_line_generation
439 Manager::Get()->GetLogManager()->DebugLog(F(_T("CompileTargetBase::GetStaticLibFilename [0] returns: '%s'"), out.wx_str()));
440 #endif
441 return out;
442 }
443
444 wxFileName fname(m_Filename);
445
446 wxString prefix = _T("lib");
447 wxString suffix = FileFilters::STATICLIB_EXT;
448 Compiler* compiler = CompilerFactory::GetCompiler(m_CompilerId);
449 if (compiler)
450 {
451 prefix = compiler->GetSwitches().libPrefix;
452 suffix = compiler->GetSwitches().libExtension;
453 }
454 if (!fname.GetName().StartsWith(prefix))
455 fname.SetName(prefix + fname.GetName());
456 fname.SetExt(suffix);
457
458 #ifdef command_line_generation
459 Manager::Get()->GetLogManager()->DebugLog(F(_T("CompileTargetBase::GetStaticLibFilename [1] returns: '%s'"), fname.GetFullPath().wx_str()));
460 #endif
461 return fname.GetFullPath();
462 }
463
GetBasePath() const464 wxString CompileTargetBase::GetBasePath() const
465 {
466 if (m_Filename.IsEmpty())
467 return _T(".");
468
469 wxFileName basePath(m_Filename);
470 wxString base = basePath.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR);
471 return !base.IsEmpty() ? base : _T(".");
472 }
473
SetTargetType(TargetType pt)474 void CompileTargetBase::SetTargetType(TargetType pt)
475 {
476 if (m_TargetType == pt)
477 return;
478
479 m_TargetType = pt;
480 m_OutputFilename = SuggestOutputFilename();
481 SetModified(true);
482 }
483
GetTargetType() const484 TargetType CompileTargetBase::GetTargetType() const
485 {
486 return m_TargetType;
487 }
488
GetExecutionParameters() const489 const wxString& CompileTargetBase::GetExecutionParameters() const
490 {
491 return m_ExecutionParameters;
492 }
493
SetExecutionParameters(const wxString & params)494 void CompileTargetBase::SetExecutionParameters(const wxString& params)
495 {
496 if (m_ExecutionParameters == params)
497 return;
498
499 m_ExecutionParameters = params;
500 SetModified(true);
501 }
502
GetHostApplication() const503 const wxString& CompileTargetBase::GetHostApplication() const
504 {
505 return m_HostApplication;
506 }
507
SetHostApplication(const wxString & app)508 void CompileTargetBase::SetHostApplication(const wxString& app)
509 {
510 if (m_HostApplication == app)
511 return;
512
513 m_HostApplication = app;
514 SetModified(true);
515 }
516
GetRunHostApplicationInTerminal() const517 bool CompileTargetBase::GetRunHostApplicationInTerminal() const
518 {
519 return m_RunHostApplicationInTerminal;
520 }
521
SetRunHostApplicationInTerminal(bool in_terminal)522 void CompileTargetBase::SetRunHostApplicationInTerminal(bool in_terminal)
523 {
524 if (m_RunHostApplicationInTerminal == in_terminal)
525 return;
526 m_RunHostApplicationInTerminal = in_terminal;
527 SetModified(true);
528 }
529
SetCompilerID(const wxString & id)530 void CompileTargetBase::SetCompilerID(const wxString& id)
531 {
532 if (id == m_CompilerId)
533 return;
534
535 m_CompilerId = id;
536 SetModified(true);
537 }
538
SetMakeCommandFor(MakeCommand cmd,const wxString & make)539 void CompileTargetBase::SetMakeCommandFor(MakeCommand cmd, const wxString& make)
540 {
541 if (m_MakeCommands[cmd] == make)
542 return;
543
544 m_MakeCommands[cmd] = make;
545 m_MakeCommandsModified = true;
546 SetModified(true);
547 }
548