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