packaging: Initial packaging
[platform/upstream/cmake.git] / Source / cmExtraCodeBlocksGenerator.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2004-2009 Kitware, Inc.
4   Copyright 2004 Alexander Neundorf (neundorf@kde.org)
5
6   Distributed under the OSI-approved BSD License (the "License");
7   see accompanying file Copyright.txt for details.
8
9   This software is distributed WITHOUT ANY WARRANTY; without even the
10   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
11   See the License for more information.
12 ============================================================================*/
13 #include "cmExtraCodeBlocksGenerator.h"
14 #include "cmGlobalUnixMakefileGenerator3.h"
15 #include "cmLocalUnixMakefileGenerator3.h"
16 #include "cmMakefile.h"
17 #include "cmake.h"
18 #include "cmSourceFile.h"
19 #include "cmGeneratedFileStream.h"
20 #include "cmTarget.h"
21 #include "cmSystemTools.h"
22 #include "cmXMLSafe.h"
23
24 #include <cmsys/SystemTools.hxx>
25
26 /* Some useful URLs:
27 Homepage:
28 http://www.codeblocks.org
29
30 File format docs:
31 http://wiki.codeblocks.org/index.php?title=File_formats_description
32 http://wiki.codeblocks.org/index.php?title=Workspace_file
33 http://wiki.codeblocks.org/index.php?title=Project_file
34
35 Discussion:
36 http://forums.codeblocks.org/index.php/topic,6789.0.html
37 */
38
39 //----------------------------------------------------------------------------
40 void cmExtraCodeBlocksGenerator
41 ::GetDocumentation(cmDocumentationEntry& entry, const char*) const
42 {
43   entry.Name = this->GetName();
44   entry.Brief = "Generates CodeBlocks project files.";
45   entry.Full =
46     "Project files for CodeBlocks will be created in the top directory "
47     "and in every subdirectory which features a CMakeLists.txt file "
48     "containing a PROJECT() call. "
49     "Additionally a hierarchy of makefiles is generated into the "
50     "build tree.  The appropriate make program can build the project through "
51     "the default make target.  A \"make install\" target is also provided.";
52 }
53
54 cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator()
55 :cmExternalMakefileProjectGenerator()
56 {
57 #if defined(_WIN32)
58   this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
59   this->SupportedGlobalGenerators.push_back("NMake Makefiles");
60 // disable until somebody actually tests it:
61 //  this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
62 #endif
63   this->SupportedGlobalGenerators.push_back("Ninja");
64   this->SupportedGlobalGenerators.push_back("Unix Makefiles");
65 }
66
67
68 void cmExtraCodeBlocksGenerator::Generate()
69 {
70   // for each sub project in the project create a codeblocks project
71   for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
72        it = this->GlobalGenerator->GetProjectMap().begin();
73       it!= this->GlobalGenerator->GetProjectMap().end();
74       ++it)
75     {
76     // create a project file
77     this->CreateProjectFile(it->second);
78     }
79 }
80
81
82 /* create the project file */
83 void cmExtraCodeBlocksGenerator::CreateProjectFile(
84                                      const std::vector<cmLocalGenerator*>& lgs)
85 {
86   const cmMakefile* mf=lgs[0]->GetMakefile();
87   std::string outputDir=mf->GetStartOutputDirectory();
88   std::string projectName=mf->GetProjectName();
89
90   std::string filename=outputDir+"/";
91   filename+=projectName+".cbp";
92   std::string sessionFilename=outputDir+"/";
93   sessionFilename+=projectName+".layout";
94
95   this->CreateNewProjectFile(lgs, filename);
96 }
97
98
99 /* Tree is used to create a "Virtual Folder" in CodeBlocks, in which all
100  CMake files this project depends on will be put. This means additionally
101  to the "Sources" and "Headers" virtual folders of CodeBlocks, there will
102  now also be a "CMake Files" virtual folder.
103  Patch by Daniel Teske <daniel.teske AT nokia.com> (which use C::B project
104  files in QtCreator).*/
105 struct Tree
106 {
107   std::string path; //only one component of the path
108   std::vector<Tree> folders;
109   std::vector<std::string> files;
110   void InsertPath(const std::vector<std::string>& splitted,
111                   std::vector<std::string>::size_type start,
112                   const std::string& fileName);
113   void BuildVirtualFolder(std::string& virtualFolders) const;
114   void BuildVirtualFolderImpl(std::string& virtualFolders,
115                               const std::string& prefix) const;
116   void BuildUnit(std::string& unitString, const std::string& fsPath) const;
117   void BuildUnitImpl(std::string& unitString,
118                      const std::string& virtualFolderPath,
119                      const std::string& fsPath) const;
120 };
121
122
123 void Tree::InsertPath(const std::vector<std::string>& splitted,
124                       std::vector<std::string>::size_type start,
125                       const std::string& fileName)
126 {
127   if (start == splitted.size())
128     {
129     files.push_back(fileName);
130     return;
131     }
132   for (std::vector<Tree>::iterator
133        it = folders.begin();
134        it != folders.end();
135        ++it)
136     {
137     if ((*it).path == splitted[start])
138       {
139       if (start + 1 <  splitted.size())
140         {
141         it->InsertPath(splitted, start + 1, fileName);
142         return;
143         }
144       else
145         {
146         // last part of splitted
147         it->files.push_back(fileName);
148         return;
149         }
150       }
151     }
152   // Not found in folders, thus insert
153   Tree newFolder;
154   newFolder.path = splitted[start];
155   if (start + 1 <  splitted.size())
156     {
157     newFolder.InsertPath(splitted, start + 1, fileName);
158     folders.push_back(newFolder);
159     return;
160     }
161   else
162     {
163     // last part of splitted
164     newFolder.files.push_back(fileName);
165     folders.push_back(newFolder);
166     return;
167     }
168 }
169
170
171 void Tree::BuildVirtualFolder(std::string& virtualFolders) const
172 {
173   virtualFolders += "<Option virtualFolders=\"CMake Files\\;";
174   for (std::vector<Tree>::const_iterator it = folders.begin();
175      it != folders.end();
176      ++it)
177     {
178     it->BuildVirtualFolderImpl(virtualFolders, "");
179     }
180   virtualFolders += "\" />";
181 }
182
183
184 void Tree::BuildVirtualFolderImpl(std::string& virtualFolders,
185                                   const std::string& prefix) const
186 {
187   virtualFolders += "CMake Files\\" + prefix +  path + "\\;";
188   for (std::vector<Tree>::const_iterator it = folders.begin();
189        it != folders.end();
190      ++it)
191     {
192     it->BuildVirtualFolderImpl(virtualFolders, prefix + path + "\\");
193     }
194 }
195
196
197 void Tree::BuildUnit(std::string& unitString, const std::string& fsPath) const
198 {
199   for (std::vector<std::string>::const_iterator it = files.begin();
200        it != files.end();
201        ++it)
202     {
203     unitString += "      <Unit filename=\"" + fsPath + *it + "\">\n";
204     unitString += "          <Option virtualFolder=\"CMake Files\\\" />\n";
205     unitString += "      </Unit>\n";
206     }
207   for (std::vector<Tree>::const_iterator it = folders.begin();
208      it != folders.end();
209      ++it)
210     {
211     it->BuildUnitImpl(unitString, "", fsPath);
212     }
213 }
214
215
216 void Tree::BuildUnitImpl(std::string& unitString,
217                          const std::string& virtualFolderPath,
218                          const std::string& fsPath) const
219 {
220   for (std::vector<std::string>::const_iterator it = files.begin();
221        it != files.end();
222        ++it)
223     {
224     unitString += "      <Unit filename=\"" +fsPath+path+ "/" + *it + "\">\n";
225     unitString += "          <Option virtualFolder=\"CMake Files\\"
226                + virtualFolderPath + path + "\\\" />\n";
227     unitString += "      </Unit>\n";
228     }
229   for (std::vector<Tree>::const_iterator it = folders.begin();
230      it != folders.end();
231      ++it)
232     {
233     it->BuildUnitImpl(unitString,
234                       virtualFolderPath + path + "\\", fsPath + path + "/");
235     }
236 }
237
238
239 void cmExtraCodeBlocksGenerator
240   ::CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
241                          const std::string& filename)
242 {
243   const cmMakefile* mf=lgs[0]->GetMakefile();
244   cmGeneratedFileStream fout(filename.c_str());
245   if(!fout)
246     {
247     return;
248     }
249
250   Tree tree;
251
252   // build tree of virtual folders
253   for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
254           it = this->GlobalGenerator->GetProjectMap().begin();
255          it != this->GlobalGenerator->GetProjectMap().end();
256          ++it)
257     {
258     // Collect all files
259     std::vector<std::string> listFiles;
260     for (std::vector<cmLocalGenerator *>::const_iterator
261          jt = it->second.begin();
262          jt != it->second.end();
263          ++jt)
264       {
265       const std::vector<std::string> & files =
266                                           (*jt)->GetMakefile()->GetListFiles();
267       listFiles.insert(listFiles.end(), files.begin(), files.end());
268       }
269
270     // Convert
271     const char* cmakeRoot = mf->GetDefinition("CMAKE_ROOT");
272     for (std::vector<std::string>::const_iterator jt = listFiles.begin();
273          jt != listFiles.end();
274          ++jt)
275       {
276       // don't put cmake's own files into the project (#12110):
277       if (jt->find(cmakeRoot) == 0)
278         {
279         continue;
280         }
281
282       const std::string &relative = cmSystemTools::RelativePath(
283                          it->second[0]->GetMakefile()->GetHomeDirectory(),
284                          jt->c_str());
285       std::vector<std::string> splitted;
286       cmSystemTools::SplitPath(relative.c_str(), splitted, false);
287       // Split filename from path
288       std::string fileName = *(splitted.end()-1);
289       splitted.erase(splitted.end() - 1, splitted.end());
290
291       // We don't want paths with CMakeFiles in them
292       // or do we?
293       // In speedcrunch those where purely internal
294       if (splitted.size() >= 1
295           && relative.find("CMakeFiles") == std::string::npos)
296         {
297         tree.InsertPath(splitted, 1, fileName);
298         }
299       }
300     }
301
302   // Now build a virtual tree string
303   std::string virtualFolders;
304   tree.BuildVirtualFolder(virtualFolders);
305   // And one for <Unit>
306   std::string unitFiles;
307   tree.BuildUnit(unitFiles, std::string(mf->GetHomeDirectory()) + "/");
308
309   // figure out the compiler
310   std::string compiler = this->GetCBCompilerId(mf);
311   std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
312
313   fout<<"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"
314         "<CodeBlocks_project_file>\n"
315         "   <FileVersion major=\"1\" minor=\"6\" />\n"
316         "   <Project>\n"
317         "      <Option title=\"" << mf->GetProjectName()<<"\" />\n"
318         "      <Option makefile_is_custom=\"1\" />\n"
319         "      <Option compiler=\"" << compiler << "\" />\n"
320         "      "<<virtualFolders<<"\n"
321         "      <Build>\n";
322
323   this->AppendTarget(fout, "all", 0, make.c_str(), mf, compiler.c_str());
324
325   // add all executable and library targets and some of the GLOBAL
326   // and UTILITY targets
327   for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin();
328        lg!=lgs.end(); lg++)
329     {
330     cmMakefile* makefile=(*lg)->GetMakefile();
331     cmTargets& targets=makefile->GetTargets();
332     for (cmTargets::iterator ti = targets.begin();
333          ti != targets.end(); ti++)
334       {
335       switch(ti->second.GetType())
336         {
337         case cmTarget::GLOBAL_TARGET:
338           {
339           bool insertTarget = false;
340           // Only add the global targets from CMAKE_BINARY_DIR,
341           // not from the subdirs
342           if (strcmp(makefile->GetStartOutputDirectory(),
343                      makefile->GetHomeOutputDirectory())==0)
344             {
345             insertTarget = true;
346             // only add the "edit_cache" target if it's not ccmake, because
347             // this will not work within the IDE
348             if (ti->first == "edit_cache")
349               {
350               const char* editCommand = makefile->GetDefinition
351                                                         ("CMAKE_EDIT_COMMAND");
352               if (editCommand == 0)
353                 {
354                 insertTarget = false;
355                 }
356               else if (strstr(editCommand, "ccmake")!=NULL)
357                 {
358                 insertTarget = false;
359                 }
360               }
361             }
362           if (insertTarget)
363             {
364             this->AppendTarget(fout, ti->first.c_str(), 0,
365                                make.c_str(), makefile, compiler.c_str());
366             }
367           }
368           break;
369         case cmTarget::UTILITY:
370           // Add all utility targets, except the Nightly/Continuous/
371           // Experimental-"sub"targets as e.g. NightlyStart
372           if (((ti->first.find("Nightly")==0)   &&(ti->first!="Nightly"))
373              || ((ti->first.find("Continuous")==0)&&(ti->first!="Continuous"))
374              || ((ti->first.find("Experimental")==0)
375                                                && (ti->first!="Experimental")))
376             {
377             break;
378             }
379
380           this->AppendTarget(fout, ti->first.c_str(), 0,
381                                  make.c_str(), makefile, compiler.c_str());
382           break;
383         case cmTarget::EXECUTABLE:
384         case cmTarget::STATIC_LIBRARY:
385         case cmTarget::SHARED_LIBRARY:
386         case cmTarget::MODULE_LIBRARY:
387         case cmTarget::OBJECT_LIBRARY:
388           {
389           this->AppendTarget(fout, ti->first.c_str(), &ti->second,
390                              make.c_str(), makefile, compiler.c_str());
391           std::string fastTarget = ti->first;
392           fastTarget += "/fast";
393           this->AppendTarget(fout, fastTarget.c_str(), &ti->second,
394                              make.c_str(), makefile, compiler.c_str());
395           }
396           break;
397         default:
398           break;
399         }
400       }
401     }
402
403   fout<<"      </Build>\n";
404
405
406   // Collect all used source files in the project
407   // Sort them into two containers, one for C/C++ implementation files
408   // which may have an acompanying header, one for all other files
409   std::map<std::string, cmSourceFile*> cFiles;
410   std::set<std::string> otherFiles;
411   for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin();
412        lg!=lgs.end(); lg++)
413     {
414     cmMakefile* makefile=(*lg)->GetMakefile();
415     cmTargets& targets=makefile->GetTargets();
416     for (cmTargets::iterator ti = targets.begin();
417          ti != targets.end(); ti++)
418       {
419       switch(ti->second.GetType())
420         {
421         case cmTarget::EXECUTABLE:
422         case cmTarget::STATIC_LIBRARY:
423         case cmTarget::SHARED_LIBRARY:
424         case cmTarget::MODULE_LIBRARY:
425         case cmTarget::OBJECT_LIBRARY:
426         case cmTarget::UTILITY: // can have sources since 2.6.3
427           {
428           const std::vector<cmSourceFile*>&sources=ti->second.GetSourceFiles();
429           for (std::vector<cmSourceFile*>::const_iterator si=sources.begin();
430                si!=sources.end(); si++)
431             {
432             // don't add source files which have the GENERATED property set:
433             if ((*si)->GetPropertyAsBool("GENERATED"))
434               {
435               continue;
436               }
437
438             // check whether it is a C/C++ implementation file
439             bool isCFile = false;
440             if ((*si)->GetLanguage() && (*(*si)->GetLanguage() == 'C'))
441               {
442               for(std::vector<std::string>::const_iterator
443                   ext = mf->GetSourceExtensions().begin();
444                   ext !=  mf->GetSourceExtensions().end();
445                   ++ext)
446                 {
447                 if ((*si)->GetExtension() == *ext)
448                   {
449                   isCFile = true;
450                   break;
451                   }
452                 }
453               }
454
455             // then put it accordingly into one of the two containers
456             if (isCFile)
457               {
458               cFiles[(*si)->GetFullPath()] = *si ;
459               }
460             else
461               {
462               otherFiles.insert((*si)->GetFullPath());
463               }
464             }
465           }
466         default:  // intended fallthrough
467           break;
468         }
469       }
470     }
471
472   // The following loop tries to add header files matching to implementation
473   // files to the project. It does that by iterating over all source files,
474   // replacing the file name extension with ".h" and checks whether such a
475   // file exists. If it does, it is inserted into the map of files.
476   // A very similar version of that code exists also in the kdevelop
477   // project generator.
478   for (std::map<std::string, cmSourceFile*>::const_iterator
479        sit=cFiles.begin();
480        sit!=cFiles.end();
481        ++sit)
482     {
483     std::string headerBasename=cmSystemTools::GetFilenamePath(sit->first);
484     headerBasename+="/";
485     headerBasename+=cmSystemTools::GetFilenameWithoutExtension(sit->first);
486
487     // check if there's a matching header around
488     for(std::vector<std::string>::const_iterator
489         ext = mf->GetHeaderExtensions().begin();
490         ext !=  mf->GetHeaderExtensions().end();
491         ++ext)
492       {
493       std::string hname=headerBasename;
494       hname += ".";
495       hname += *ext;
496       // if it's already in the set, don't check if it exists on disk
497       std::set<std::string>::const_iterator headerIt=otherFiles.find(hname);
498       if (headerIt != otherFiles.end())
499         {
500         break;
501         }
502
503       if(cmSystemTools::FileExists(hname.c_str()))
504         {
505         otherFiles.insert(hname);
506         break;
507         }
508       }
509     }
510
511   // insert all source files in the CodeBlocks project
512   // first the C/C++ implementation files, then all others
513   for (std::map<std::string, cmSourceFile*>::const_iterator
514        sit=cFiles.begin();
515        sit!=cFiles.end();
516        ++sit)
517     {
518     fout<<"      <Unit filename=\""<< sit->first <<"\">\n"
519           "      </Unit>\n";
520     }
521   for (std::set<std::string>::const_iterator
522        sit=otherFiles.begin();
523        sit!=otherFiles.end();
524        ++sit)
525     {
526     fout<<"      <Unit filename=\""<< sit->c_str() <<"\">\n"
527           "      </Unit>\n";
528     }
529
530   // Add CMakeLists.txt
531   fout<<unitFiles;
532
533   fout<<"   </Project>\n"
534         "</CodeBlocks_project_file>\n";
535 }
536
537
538 // Write a dummy file for OBJECT libraries, so C::B can reference some file
539 std::string cmExtraCodeBlocksGenerator::CreateDummyTargetFile(
540                                         cmMakefile* mf, cmTarget* target) const
541 {
542   // this file doesn't seem to be used by C::B in custom makefile mode,
543   // but we generate a unique file for each OBJECT library so in case
544   // C::B uses it in some way, the targets don't interfere with each other.
545   std::string filename = mf->GetCurrentOutputDirectory();
546   filename += "/";
547   filename += mf->GetLocalGenerator()->GetTargetDirectory(*target);
548   filename += "/";
549   filename += target->GetName();
550   filename += ".objlib";
551   cmGeneratedFileStream fout(filename.c_str());
552   if(fout)
553     {
554     fout << "# This is a dummy file for the OBJECT library "
555          << target->GetName()
556          << " for the CMake CodeBlocks project generator.\n"
557          << "# Don't edit, this file will be overwritten.\n";
558     }
559   return filename;
560 }
561
562
563 // Generate the xml code for one target.
564 void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
565                                               const char* targetName,
566                                               cmTarget* target,
567                                               const char* make,
568                                               const cmMakefile* makefile,
569                                               const char* compiler)
570 {
571   std::string makefileName = makefile->GetStartOutputDirectory();
572   makefileName += "/Makefile";
573
574   fout<<"      <Target title=\"" << targetName << "\">\n";
575   if (target!=0)
576     {
577     int cbTargetType = this->GetCBTargetType(target);
578     std::string workingDir = makefile->GetStartOutputDirectory();
579     if ( target->GetType()==cmTarget::EXECUTABLE)
580       {
581       // Determine the directory where the executable target is created, and
582       // set the working directory to this dir.
583       const char* runtimeOutputDir = makefile->GetDefinition(
584                                              "CMAKE_RUNTIME_OUTPUT_DIRECTORY");
585       if (runtimeOutputDir != 0)
586         {
587         workingDir = runtimeOutputDir;
588         }
589       else
590         {
591         const char* executableOutputDir = makefile->GetDefinition(
592                                                      "EXECUTABLE_OUTPUT_PATH");
593         if (executableOutputDir != 0)
594           {
595           workingDir = executableOutputDir;
596           }
597         }
598       }
599
600     const char* buildType = makefile->GetDefinition("CMAKE_BUILD_TYPE");
601     std::string location;
602     if ( target->GetType()==cmTarget::OBJECT_LIBRARY)
603       {
604       location = this->CreateDummyTargetFile(const_cast<cmMakefile*>(makefile),
605                                              target);
606       }
607     else
608       {
609       location = target->GetLocation(buildType);
610       }
611
612     fout<<"         <Option output=\"" << location
613                             << "\" prefix_auto=\"0\" extension_auto=\"0\" />\n"
614           "         <Option working_dir=\"" << workingDir << "\" />\n"
615           "         <Option object_output=\"./\" />\n"
616           "         <Option type=\"" << cbTargetType << "\" />\n"
617           "         <Option compiler=\"" << compiler << "\" />\n"
618           "         <Compiler>\n";
619
620     cmGeneratorTarget *gtgt = this->GlobalGenerator
621                                   ->GetGeneratorTarget(target);
622
623     // the compilerdefines for this target
624     std::vector<std::string> cdefs;
625     target->GetCompileDefinitions(cdefs, buildType);
626
627     // Expand the list.
628     for(std::vector<std::string>::const_iterator di = cdefs.begin();
629         di != cdefs.end(); ++di)
630       {
631       cmXMLSafe safedef(di->c_str());
632       fout <<"            <Add option=\"-D" << safedef.str() << "\" />\n";
633       }
634
635     // the include directories for this target
636     std::set<std::string> uniqIncludeDirs;
637
638     std::vector<std::string> includes;
639     target->GetMakefile()->GetLocalGenerator()->
640       GetIncludeDirectories(includes, gtgt, "C", buildType);
641     for(std::vector<std::string>::const_iterator dirIt=includes.begin();
642         dirIt != includes.end();
643         ++dirIt)
644       {
645       uniqIncludeDirs.insert(*dirIt);
646       }
647
648     std::string systemIncludeDirs = makefile->GetSafeDefinition(
649                               "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
650     if (!systemIncludeDirs.empty())
651       {
652       std::vector<std::string> dirs;
653       cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
654       for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
655           dirIt != dirs.end();
656           ++dirIt)
657         {
658         uniqIncludeDirs.insert(*dirIt);
659         }
660       }
661
662     systemIncludeDirs = makefile->GetSafeDefinition(
663                             "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
664     if (!systemIncludeDirs.empty())
665       {
666       std::vector<std::string> dirs;
667       cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
668       for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
669           dirIt != dirs.end();
670           ++dirIt)
671         {
672         uniqIncludeDirs.insert(*dirIt);
673         }
674       }
675
676     for(std::set<std::string>::const_iterator dirIt=uniqIncludeDirs.begin();
677         dirIt != uniqIncludeDirs.end();
678         ++dirIt)
679       {
680       fout <<"            <Add directory=\"" << dirIt->c_str() << "\" />\n";
681       }
682
683     fout<<"         </Compiler>\n";
684     }
685   else // e.g. all and the GLOBAL and UTILITY targets
686     {
687     fout<<"         <Option working_dir=\""
688                             << makefile->GetStartOutputDirectory() << "\" />\n"
689         <<"         <Option type=\"" << 4 << "\" />\n";
690     }
691
692   fout<<"         <MakeCommands>\n"
693         "            <Build command=\""
694       << this->BuildMakeCommand(make, makefileName.c_str(), targetName)
695       << "\" />\n"
696         "            <CompileFile command=\""
697       << this->BuildMakeCommand(make, makefileName.c_str(),"&quot;$file&quot;")
698       << "\" />\n"
699         "            <Clean command=\""
700       << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
701       << "\" />\n"
702         "            <DistClean command=\""
703       << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
704       << "\" />\n"
705         "         </MakeCommands>\n"
706         "      </Target>\n";
707
708 }
709
710
711 // Translate the cmake compiler id into the CodeBlocks compiler id
712 std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf)
713 {
714   // figure out which language to use
715   // for now care only for C and C++
716   std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID";
717   if (this->GlobalGenerator->GetLanguageEnabled("CXX") == false)
718     {
719     compilerIdVar = "CMAKE_C_COMPILER_ID";
720     }
721
722   std::string hostSystemName = mf->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
723   std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
724   std::string compilerId = mf->GetSafeDefinition(compilerIdVar.c_str());
725   std::string compiler = "gcc";  // default to gcc
726   if (compilerId == "MSVC")
727     {
728     compiler = "msvc8";
729     }
730   else if (compilerId == "Borland")
731     {
732     compiler = "bcc";
733     }
734   else if (compilerId == "SDCC")
735     {
736     compiler = "sdcc";
737     }
738   else if (compilerId == "Intel")
739     {
740     compiler = "icc";
741     }
742   else if (compilerId == "Watcom")
743     {
744     compiler = "ow";
745     }
746   else if (compilerId == "GNU")
747     {
748     compiler = "gcc";
749     }
750   return compiler;
751 }
752
753
754 // Translate the cmake target type into the CodeBlocks target type id
755 int cmExtraCodeBlocksGenerator::GetCBTargetType(cmTarget* target)
756 {
757   if ( target->GetType()==cmTarget::EXECUTABLE)
758     {
759     if ((target->GetPropertyAsBool("WIN32_EXECUTABLE"))
760         || (target->GetPropertyAsBool("MACOSX_BUNDLE")))
761       {
762       return 0;
763       }
764     else
765       {
766       return 1;
767       }
768     }
769   else if (( target->GetType()==cmTarget::STATIC_LIBRARY)
770         || (target->GetType()==cmTarget::OBJECT_LIBRARY))
771     {
772     return 2;
773     }
774   else if ((target->GetType()==cmTarget::SHARED_LIBRARY)
775            || (target->GetType()==cmTarget::MODULE_LIBRARY))
776     {
777     return 3;
778     }
779   return 4;
780 }
781
782 // Create the command line for building the given target using the selected
783 // make
784 std::string cmExtraCodeBlocksGenerator::BuildMakeCommand(
785              const std::string& make, const char* makefile, const char* target)
786 {
787   std::string command = make;
788   if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0)
789     {
790     std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
791     command += " /NOLOGO /f &quot;";
792     command += makefileName;
793     command += "&quot; ";
794     command += " VERBOSE=1 ";
795     command += target;
796     }
797   else if (strcmp(this->GlobalGenerator->GetName(), "MinGW Makefiles")==0)
798     {
799     // no escaping of spaces in this case, see
800     // http://public.kitware.com/Bug/view.php?id=10014
801     std::string makefileName = makefile;
802     command += " -f &quot;";
803     command += makefileName;
804     command += "&quot; ";
805     command += " VERBOSE=1 ";
806     command += target;
807     }
808   else if (strcmp(this->GlobalGenerator->GetName(), "Ninja")==0)
809     {
810     command += " -v ";
811     command += target;
812     }
813   else
814     {
815     std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
816     command += " -f &quot;";
817     command += makefileName;
818     command += "&quot; ";
819     command += " VERBOSE=1 ";
820     command += target;
821     }
822   return command;
823 }