1 
2 #include "makefilegen.h"
3 
4 #include <sdk.h>
5 #ifndef CB_PRECOMP
6     #include <wx/file.h>
7 
8     #include <cbproject.h>
9     #include <compiler.h>
10     #include <compilerfactory.h>
11 #endif
12 
13 #include "makefiledlg.h"
14 #include "nativeparserf.h"
15 
16 void MakefileGen::GenerateMakefile(cbProject* project, ProjectDependencies* projDep, NativeParserF* pNativeParser)
17 {
18     if (!project || !projDep)
19         return;
20 
21     ProjectBuildTarget* buildTarget = project->GetBuildTarget(project->GetActiveBuildTarget());
22     if (!buildTarget)
23         return;
24 
25     wxString projDir = project->GetBasePath();
26     wxFileName mffn = wxFileName(projDir,_T("Makefile"));
\x21mffn.IsOknull27     if (!mffn.IsOk())
28         return;
29     if (!SelectMikefileName(mffn))
30         return;
31 
32     wxFile mfile;
mffn.GetFullPathnull33     if(!mfile.Create(mffn.GetFullPath(), true))
34     {
35         cbMessageBox(_T("Makefile can't be created!"), _("Error"), wxICON_ERROR);
36         return;
37     }
38 
39     mfile.Write(_T("#\n# This Makefile was generated by Code::Blocks IDE.\n#\n"));
40 
41 
42     FilesList& filesList = buildTarget->GetFilesList();
43 
44     wxArrayString src_dirs;
45     wxArrayString src_ext;
46     wxArrayString src_files;
47     wxArrayString obj_files;
48     wxString sfiles;
49     wxString ofiles;
50 
51 
52 
53     FilesList::iterator it;
filesList.endnull54     for( it = filesList.begin(); it != filesList.end(); ++it )
55     {
56         ProjectFile* projFile = *it;
57         const pfDetails& pfd = projFile->GetFileDetails(buildTarget);
58 
59         wxFileName sfn(pfd.source_file_absolute_native);
60         sfn.MakeRelativeTo(mffn.GetPath(wxPATH_GET_SEPARATOR));
61         wxString dir = sfn.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR, wxPATH_UNIX);
62         int didx = src_dirs.Index(dir);
63         if (didx == wxNOT_FOUND)
64             didx = src_dirs.Add(dir);
sfn.GetExtnull65         wxString ext = sfn.GetExt();
66         ext << _T("d") << didx+1;
67         int eidx = src_ext.Index(ext);
68         if (eidx == wxNOT_FOUND)
69         {
70             eidx = src_ext.Add(ext);
71             sfiles = wxEmptyString;
72             src_files.Add(wxEmptyString);
73             ofiles = wxEmptyString;
74             obj_files.Add(wxEmptyString);
75         }
76         else
77         {
78             sfiles = src_files.Item(eidx);
79             ofiles = obj_files.Item(eidx);
80         }
81 
82         sfiles << sfn.GetFullName() << _T(" \\\n");
83         src_files[eidx] = sfiles;
84 
85         if (projFile->compile)
86         {
87             ofiles << sfn.GetName() << _T(".o") << _T(" \\\n");
88             obj_files[eidx] = ofiles;
89         }
90     }
91     for (size_t i=0; i<src_ext.Count(); i++)
92     {
93         wxString str;
94         str << _T("\nSRCS_") << src_ext.Item(i) << _T(" = \\\n");
95         mfile.Write(str);
96         mfile.Write(src_files[i].Mid(0,src_files[i].Find('\\', true)));
97         mfile.Write(_T("\n"));
98     }
99     for (size_t i=0; i<src_ext.Count(); i++)
100     {
101         wxString str;
102         str << _T("\nOBJS_") << src_ext.Item(i) << _T(" = \\\n");
103         mfile.Write(str);
104         mfile.Write(obj_files[i].Mid(0,obj_files[i].Find('\\', true)));
105         mfile.Write(_T("\n"));
106     }
107 
108     wxString objdir = _T("OBJS_DIR = ");
109 
110     for( it = filesList.begin(); it != filesList.end(); ++it )
111     {
112         ProjectFile* projFile = *it;
113         const pfDetails& pfd = projFile->GetFileDetails(buildTarget);
114 
115         wxFileName sfn(pfd.source_file_absolute_native);
116         wxString ffpath = sfn.GetFullName();
117         if (pNativeParser->IsFileFortran(ffpath) && projFile->compile)
118         {
119             wxFileName ofn(pfd.object_file_absolute_native);
120             ofn.MakeRelativeTo(mffn.GetPath(wxPATH_GET_SEPARATOR));
121             ofn.SetExt(_T("o"));
122             objdir << ofn.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR, wxPATH_UNIX) + _T("\n");
123             break;
124         }
125     }
126 
127     bool containsNonFortranFiles = false;
128 
129     wxString depsFiles;
130     for( it = filesList.begin(); it != filesList.end(); ++it )
131     {
132         ProjectFile* projFile = *it;
133         const pfDetails& pfd = projFile->GetFileDetails(buildTarget);
134 
135         if (pNativeParser->IsFileFortran(pfd.source_file) && projFile->compile)
136         {
137             wxFileName sfn(pfd.source_file);
138             sfn.SetExt(_T("o"));
139             depsFiles << sfn.GetFullName();
140             wxFileName sfn2(pfd.source_file);
141             depsFiles << _T(": \\\n    ") << sfn2.GetFullName();
142             wxArrayString use;
143             projDep->GetUseFilesFile(pfd.source_file_absolute_native, use);
144             for (size_t i=0; i<use.size(); i++)
145             {
146                 wxFileName ufn(use.Item(i));
147                 ufn.SetExt(_T("o"));
148                 depsFiles << _T(" \\\n    ") << ufn.GetFullName();
149             }
150 
151             wxArrayString extends;
152             projDep->GetExtendsFilesFile(pfd.source_file_absolute_native, extends);
153             for (size_t i=0; i<extends.size(); i++)
154             {
155                 wxFileName ufn(extends.Item(i));
156                 ufn.SetExt(_T("o"));
157                 depsFiles << _T(" \\\n    ") << ufn.GetFullName();
158             }
159 
160             wxArrayString incl;
161             projDep->GetIncludeFilesFile(pfd.source_file_absolute_native, incl);
162             for (size_t i=0; i<incl.size(); i++)
163             {
164                 wxFileName ifn(incl.Item(i));
165                 depsFiles << _T(" \\\n    ") << ifn.GetFullName();
166             }
167             depsFiles << _T("\n");
168         }
169         else if (!pNativeParser->IsFileFortran(pfd.source_file) && projFile->compile)
170         {
171             containsNonFortranFiles = true;
172         }
173     }
174 
175     for (size_t i=0; i<src_ext.Count(); i++)
176     {
177         wxString sdir;
178         wxString ext = src_ext.Item(i);
179         sdir << _T("\nSRC_DIR_") << ext << _T(" = ");
180         int dpos = ext.Find('d', true);
181         if (dpos != wxNOT_FOUND)
182         {
183             wxString idxstr;
184             idxstr = ext.Mid(dpos+1);
185             long longint;
186             if (idxstr.ToLong(&longint))
187             {
188                 sdir << src_dirs.Item(longint-1);
189             }
190         }
191         sdir << _T("\n");
192         mfile.Write(sdir);
193     }
194     mfile.Write(objdir);
195 
196     TargetType tagTyp = buildTarget->GetTargetType();
197     wxFileName exefile(buildTarget->GetOutputFilename());
198     wxFileName basepath;
199     basepath.Assign(buildTarget->GetBasePath(), wxEmptyString, wxEmptyString);
200     wxArrayString bpdirs = basepath.GetDirs();
201     if (bpdirs.GetCount() > 0)
202     {
203         for (size_t i=bpdirs.GetCount(); i>0; i--)
204             exefile.PrependDir(bpdirs.Item(i-1));
205         exefile.SetVolume(basepath.GetVolume()+wxFileName::GetVolumeSeparator());
206     }
207 
208     wxString exeStr;
209     if (basepath.HasVolume())
210         exeStr << basepath.GetVolume() << wxFileName::GetVolumeSeparator() << wxFileName::GetPathSeparator();
211     else
212     {
213         wxString sep = wxFileName::GetPathSeparator();
214         if (!exefile.GetPath(wxPATH_GET_SEPARATOR).StartsWith(sep))
215             exeStr << wxFileName::GetPathSeparator();
216     }
217     exeStr << exefile.GetPath(wxPATH_GET_SEPARATOR);
218     exefile = wxFileName(exeStr, exefile.GetName(), exefile.GetExt());
219     exefile.MakeRelativeTo(mffn.GetPath(wxPATH_GET_SEPARATOR));
220 
221     mfile.Write(_T("EXE_DIR = ") + exefile.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR, wxPATH_UNIX) + _T("\n"));
222     mfile.Write(_T("\nEXE = ") + exefile.GetFullName() + _T("\n"));
223     Compiler * compiler = CompilerFactory::GetCompiler(buildTarget->GetCompilerID());
224     wxString compStr = _T("FC = ");
225     wxString linkerStr = _T("LD = ");
226     if (compiler)
227     {
228         compStr << compiler->GetPrograms().C;
229         compStr << _T("\n");
230         if (tagTyp == ttDynamicLib)
231             linkerStr << compiler->GetPrograms().LD;
232         else if (tagTyp == ttStaticLib)
233             linkerStr << compiler->GetPrograms().LIB;
234         else
235             linkerStr << compiler->GetPrograms().LD;
236         linkerStr << _T("\n");
237     }
238     else
239         compStr << _T("\n");
240     mfile.Write(compStr);
241     mfile.Write(linkerStr);
242 
243     wxString idir = _T("IDIR = ");
244     const wxArrayString& idirs = project->GetIncludeDirs();
245     for(size_t i=0; i<idirs.size(); i++)
246     {
247         idir << _T("-I") << idirs.Item(i) << _T(" ");
248     }
249     const wxArrayString& idirst = buildTarget->GetIncludeDirs();
250     for(size_t i=0; i<idirst.size(); i++)
251     {
252         idir << _T("-I") << idirst.Item(i) << _T(" ");
253     }
254     mfile.Write(idir + _T("\n"));
255 
256     wxString cflags = _T("CFLAGS = ");
257     const wxArrayString& copt = project->GetCompilerOptions();
258     for(size_t i=0; i<copt.size(); i++)
259     {
260         cflags << copt.Item(i) << _T(" ");
261     }
262     const wxArrayString& copt_t = buildTarget->GetCompilerOptions();
263     for(size_t i=0; i<copt_t.size(); i++)
264     {
265         cflags << copt_t.Item(i) << _T(" ");
266     }
267 
268     if(compiler)
269     {
270         const wxArrayString& copt2 = compiler->GetCompilerOptions();
271         for(size_t i=0; i<copt2.size(); i++)
272         {
273             cflags << copt2.Item(i) << _T(" ");
274         }
275     }
276 
277     if (CompilerFactory::CompilerInheritsFrom(buildTarget->GetCompilerID(), _T("g95")))
278         cflags << _T(" -fmod=$(OBJS_DIR) $(IDIR)");
279     else if (CompilerFactory::CompilerInheritsFrom(buildTarget->GetCompilerID(), _T("ifclin")))
280         cflags << _T(" -module $(OBJS_DIR) $(IDIR)");
281     else if (CompilerFactory::CompilerInheritsFrom(buildTarget->GetCompilerID(), _T("ifcwin")))
282         cflags << _T(" /nologo /module:$(OBJS_DIR) $(IDIR)");
283     else if (CompilerFactory::CompilerInheritsFrom(buildTarget->GetCompilerID(), _T("pgfortran")))
284         cflags << _T(" -module $(OBJS_DIR) $(IDIR)");
285     else //gfortran
286         cflags << _T(" -J$(OBJS_DIR) $(IDIR)");
287 
288     mfile.Write(cflags + _T("\n"));
289 
290     wxString lflags = _T("LFLAGS = ");
291     const wxArrayString& lopt = project->GetLinkerOptions();
292     for(size_t i=0; i<lopt.size(); i++)
293     {
294         wxString optstr = lopt.Item(i);
295         optstr.Trim();
296         int ipos = optstr.Find(_T("--rpath=\\\\$$$ORIGIN"));
297         if (ipos != wxNOT_FOUND)
298         {
299             wxString optstr1 = optstr.Mid(0, ipos+8);
300             wxString optstr2 = _T("'$$ORIGIN") + optstr.Mid(ipos+19) + _T("'");
301             optstr = optstr1 + optstr2;
302         }
303         lflags << optstr << _T(" ");
304     }
305     const wxArrayString& lopt_t = buildTarget->GetLinkerOptions();
306     for(size_t i=0; i<lopt_t.size(); i++)
307     {
308         wxString optstr = lopt_t.Item(i);
309         optstr.Trim();
310         int ipos = optstr.Find(_T("--rpath=\\\\$$$ORIGIN"));
311         if (ipos != wxNOT_FOUND)
312         {
313             wxString optstr1 = optstr.Mid(0, ipos+8);
314             wxString optstr2 = _T("'$$ORIGIN") + optstr.Mid(ipos+19) + _T("'");
315             optstr = optstr1 + optstr2;
316         }
317         lflags << optstr << _T(" ");
318     }
319     mfile.Write(lflags + _T("\n"));
320 
321     wxString libs = _T("LIBS = ");
322     const wxArrayString& ldirs = project->GetLibDirs();
323     for(size_t i=0; i<ldirs.size(); i++)
324     {
325         libs << _T("-L") << ldirs.Item(i) << _T(" ");
326     }
327     const wxArrayString& ldirst = buildTarget->GetLibDirs();
328     for(size_t i=0; i<ldirst.size(); i++)
329     {
330         libs << _T("-L") << ldirst.Item(i) << _T(" ");
331     }
332     const wxArrayString& lbsarr = project->GetLinkLibs();
333     for(size_t i=0; i<lbsarr.size(); i++)
334     {
335         wxString lnam;
336         if (lbsarr.Item(i).StartsWith(_T("lib")))
337             lnam = lbsarr.Item(i).Mid(3);
338         else
339             lnam = lbsarr.Item(i);
340         libs << _T("-l") << lnam << _T(" ");
341     }
342     const wxArrayString& lbsarrt = buildTarget->GetLinkLibs();
343     for(size_t i=0; i<lbsarrt.size(); i++)
344     {
345         wxString lnam;
346         if (lbsarrt.Item(i).StartsWith(_T("lib")))
347             lnam = lbsarrt.Item(i).Mid(3);
348         else
349             lnam = lbsarrt.Item(i);
350         libs << _T("-l") << lnam << _T(" ");
351     }
352     mfile.Write(libs + _T("\n"));
353 
354 
355     wxString vpath;
356     vpath << _T("\nVPATH = ");
357     for (size_t i=0; i<src_ext.Count(); i++)
358     {
359         vpath << _T("$(SRC_DIR_") << src_ext.Item(i) << _T(")");
360         vpath << _T(":$(OBJS_DIR)");
361         if (i < src_ext.Count()-1)
362         {
363             vpath << _T(":");
364         }
365     }
366 //    vpath << _T("\nendif\n");
367     vpath << _T("\n");
368     mfile.Write(vpath);
369 
370     wxString objsstr = _T("OBJS = $(addprefix $(OBJS_DIR),");
371     for (size_t i=0; i<src_ext.Count(); i++)
372     {
373         objsstr << _T(" $(OBJS_") << src_ext.Item(i) << _T(")");
374     }
375     objsstr << _T(")\n");
376     mfile.Write(objsstr);
377 
378     mfile.Write(_T("\nall : $(EXE)\n"));
379 
380     wxString lstr = _T("\n$(EXE) :");
381 
382     for (size_t i=0; i<src_ext.Count(); i++)
383     {
384         lstr << _T(" $(OBJS_") << src_ext.Item(i) << _T(")");
385     }
386     lstr << _T("\n\t@mkdir -p $(EXE_DIR)");
387     if (tagTyp == ttDynamicLib)
388     {
389         lstr << _T("\n\t$(LD)");
390         lstr << _T(" -shared $(OBJS) -o $(EXE_DIR)$(EXE) $(LFLAGS) $(LIBS)\n");
391     }
392     else if (tagTyp == ttStaticLib)
393     {
394         lstr << _T("\n\trm -f $(EXE_DIR)$(EXE)");
395         lstr << _T("\n\t$(LD)");
396         lstr << _T(" -r -s $(EXE_DIR)$(EXE) $(OBJS)\n");
397     }
398     else
399     {
400         lstr << _T("\n\t$(LD)");
401         lstr << _T(" -o $(EXE_DIR)$(EXE) $(OBJS) $(LFLAGS) $(LIBS)\n");
402     }
403     mfile.Write(lstr);
404 
405     for (size_t i=0; i<src_ext.Count(); i++)
406     {
407         wxString sdir;
408         sdir << _T("$(SRC_DIR_") << src_ext.Item(i) << _T(")");
409 
410         wxString ext = src_ext.Item(i);
411         int dpos = ext.Find('d',true);
412         if (dpos != wxNOT_FOUND)
413             ext = ext.Mid(0,dpos);
414 
415         wxString cstr;
416         cstr << _T("\n$(OBJS_") << src_ext.Item(i) << _T("):\n");
417         cstr << _T("\t@mkdir -p $(OBJS_DIR)\n");
418         if (CompilerFactory::CompilerInheritsFrom(buildTarget->GetCompilerID(), _T("ifcwin")))
419             cstr << _T("\t$(FC) $(CFLAGS) /c ") << sdir << _T("$(@:.o=.") << ext << _T(")") << _T(" /object: $(OBJS_DIR)$@\n");
420         else
421             cstr << _T("\t$(FC) $(CFLAGS) -c ") << sdir << _T("$(@:.o=.") << ext << _T(")") << _T(" -o $(OBJS_DIR)$@\n");
422 
423         mfile.Write(cstr);
424     }
425 
426     wxString clean;
427     clean << _T("\nclean :\n");
428 	clean << _T("\trm -f $(OBJS_DIR)*.*\n");
429 	clean << _T("\trm -f $(EXE_DIR)$(EXE)\n");
430     mfile.Write(clean);
431 
432     mfile.Write(_T("\n# Dependencies of files\n"));
433     mfile.Write(depsFiles);
434     mfile.Write(_T("\n"));
435 
436 
437     if (containsNonFortranFiles)
438         cbMessageBox(_("The build target includes non Fortran files. They were added to the list of files, however the plugin doesn't know how to handle these files correctly."), _("Warning"), wxICON_WARNING);
439 
440     wxString msg = _("The make file \"");
441     msg << mffn.GetFullPath();
442     msg << _("\" was generated seccessfully.");
443     cbMessageBox(msg);
444 }
445 
446 bool MakefileGen::SelectMikefileName(wxFileName& mffn)
447 {
448     MakefileDlg mfdlg(Manager::Get()->GetAppWindow());
449     mfdlg.SetFilename(mffn.GetFullPath());
450     int imax = 5;
451     int i;
452     for (i=0; i<imax; i++)
453     {
454         if (mfdlg.ShowModal() != wxID_OK)
455             return false;
456         mffn = mfdlg.GetFilename();
457         if (!mffn.IsOk())
458         {
459             cbMessageBox(_("Error in the file name!"), _("Error"), wxICON_ERROR);
460             continue;
461         }
462 
463         if (mffn.FileExists())
464         {
465             int answ = cbMessageBox(_T("File \"")+mffn.GetFullPath()+_T("\" already exist.\nWould you like to overwrite it?"), _("Question"), wxYES_NO | wxICON_QUESTION);
466             if (answ == wxID_YES)
467                 break;
468         }
469         else
470             break;
471     }
472 
473     if (i == imax)
474     {
475         cbMessageBox(_("I am tired. Maybe next time..."), _("Info"), wxICON_INFORMATION);
476         return false;
477     }
478     return true;
479 }
480