Imported Upstream version 2.8.9
[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     // the compilerdefines for this target
621     const char* cdefs = target->GetMakefile()->GetProperty(
622                                                         "COMPILE_DEFINITIONS");
623     if(cdefs)
624       {
625       // Expand the list.
626       std::vector<std::string> defs;
627       cmSystemTools::ExpandListArgument(cdefs, defs);
628       for(std::vector<std::string>::const_iterator di = defs.begin();
629           di != defs.end(); ++di)
630         {
631         cmXMLSafe safedef(di->c_str());
632         fout <<"            <Add option=\"-D" << safedef.str() << "\" />\n";
633         }
634       }
635
636       // the include directories for this target
637       std::set<std::string> uniqIncludeDirs;
638
639       std::vector<std::string> includes;
640       target->GetMakefile()->GetLocalGenerator()->
641         GetIncludeDirectories(includes, target);
642       for(std::vector<std::string>::const_iterator dirIt=includes.begin();
643           dirIt != includes.end();
644           ++dirIt)
645         {
646         uniqIncludeDirs.insert(*dirIt);
647         }
648
649       std::string systemIncludeDirs = makefile->GetSafeDefinition(
650                                 "CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
651       if (!systemIncludeDirs.empty())
652         {
653         std::vector<std::string> dirs;
654         cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
655         for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
656             dirIt != dirs.end();
657             ++dirIt)
658           {
659           uniqIncludeDirs.insert(*dirIt);
660           }
661         }
662
663       systemIncludeDirs = makefile->GetSafeDefinition(
664                               "CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
665       if (!systemIncludeDirs.empty())
666         {
667         std::vector<std::string> dirs;
668         cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
669         for(std::vector<std::string>::const_iterator dirIt=dirs.begin();
670             dirIt != dirs.end();
671             ++dirIt)
672           {
673           uniqIncludeDirs.insert(*dirIt);
674           }
675         }
676
677       for(std::set<std::string>::const_iterator dirIt=uniqIncludeDirs.begin();
678           dirIt != uniqIncludeDirs.end();
679           ++dirIt)
680         {
681         fout <<"            <Add directory=\"" << dirIt->c_str() << "\" />\n";
682         }
683
684       fout<<"         </Compiler>\n";
685       }
686     else // e.g. all and the GLOBAL and UTILITY targets
687     {
688     fout<<"         <Option working_dir=\""
689                             << makefile->GetStartOutputDirectory() << "\" />\n"
690         <<"         <Option type=\"" << 4 << "\" />\n";
691     }
692
693   fout<<"         <MakeCommands>\n"
694         "            <Build command=\""
695       << this->BuildMakeCommand(make, makefileName.c_str(), targetName)
696       << "\" />\n"
697         "            <CompileFile command=\""
698       << this->BuildMakeCommand(make, makefileName.c_str(),"&quot;$file&quot;")
699       << "\" />\n"
700         "            <Clean command=\""
701       << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
702       << "\" />\n"
703         "            <DistClean command=\""
704       << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
705       << "\" />\n"
706         "         </MakeCommands>\n"
707         "      </Target>\n";
708
709 }
710
711
712 // Translate the cmake compiler id into the CodeBlocks compiler id
713 std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf)
714 {
715   // figure out which language to use
716   // for now care only for C and C++
717   std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID";
718   if (this->GlobalGenerator->GetLanguageEnabled("CXX") == false)
719     {
720     compilerIdVar = "CMAKE_C_COMPILER_ID";
721     }
722
723   std::string hostSystemName = mf->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
724   std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
725   std::string compilerId = mf->GetSafeDefinition(compilerIdVar.c_str());
726   std::string compiler = "gcc";  // default to gcc
727   if (compilerId == "MSVC")
728     {
729     compiler = "msvc8";
730     }
731   else if (compilerId == "Borland")
732     {
733     compiler = "bcc";
734     }
735   else if (compilerId == "SDCC")
736     {
737     compiler = "sdcc";
738     }
739   else if (compilerId == "Intel")
740     {
741     compiler = "icc";
742     }
743   else if (compilerId == "Watcom")
744     {
745     compiler = "ow";
746     }
747   else if (compilerId == "GNU")
748     {
749     compiler = "gcc";
750     }
751   return compiler;
752 }
753
754
755 // Translate the cmake target type into the CodeBlocks target type id
756 int cmExtraCodeBlocksGenerator::GetCBTargetType(cmTarget* target)
757 {
758   if ( target->GetType()==cmTarget::EXECUTABLE)
759     {
760     if ((target->GetPropertyAsBool("WIN32_EXECUTABLE"))
761         || (target->GetPropertyAsBool("MACOSX_BUNDLE")))
762       {
763       return 0;
764       }
765     else
766       {
767       return 1;
768       }
769     }
770   else if (( target->GetType()==cmTarget::STATIC_LIBRARY)
771         || (target->GetType()==cmTarget::OBJECT_LIBRARY))
772     {
773     return 2;
774     }
775   else if ((target->GetType()==cmTarget::SHARED_LIBRARY)
776            || (target->GetType()==cmTarget::MODULE_LIBRARY))
777     {
778     return 3;
779     }
780   return 4;
781 }
782
783 // Create the command line for building the given target using the selected
784 // make
785 std::string cmExtraCodeBlocksGenerator::BuildMakeCommand(
786              const std::string& make, const char* makefile, const char* target)
787 {
788   std::string command = make;
789   if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0)
790     {
791     std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
792     command += " /NOLOGO /f &quot;";
793     command += makefileName;
794     command += "&quot; ";
795     command += " VERBOSE=1 ";
796     command += target;
797     }
798   else if (strcmp(this->GlobalGenerator->GetName(), "MinGW Makefiles")==0)
799     {
800     // no escaping of spaces in this case, see
801     // http://public.kitware.com/Bug/view.php?id=10014
802     std::string makefileName = makefile;
803     command += " -f &quot;";
804     command += makefileName;
805     command += "&quot; ";
806     command += " VERBOSE=1 ";
807     command += target;
808     }
809   else
810     {
811     std::string makefileName = cmSystemTools::ConvertToOutputPath(makefile);
812     command += " -f &quot;";
813     command += makefileName;
814     command += "&quot; ";
815     command += " VERBOSE=1 ";
816     command += target;
817     }
818   return command;
819 }