Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmExtraCodeBlocksGenerator.cxx
blobb89d979f2df6d5a6c1944089e2a358d327d2f635
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmExtraCodeBlocksGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2009-03-10 21:34:18 $
7 Version: $Revision: 1.22 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 Copyright (c) 2004 Alexander Neundorf neundorf@kde.org, All rights reserved.
11 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
13 This software is distributed WITHOUT ANY WARRANTY; without even
14 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 PURPOSE. See the above copyright notices for more information.
17 =========================================================================*/
19 #include "cmExtraCodeBlocksGenerator.h"
20 #include "cmGlobalUnixMakefileGenerator3.h"
21 #include "cmLocalUnixMakefileGenerator3.h"
22 #include "cmMakefile.h"
23 #include "cmake.h"
24 #include "cmSourceFile.h"
25 #include "cmGeneratedFileStream.h"
26 #include "cmTarget.h"
27 #include "cmSystemTools.h"
29 #include <cmsys/SystemTools.hxx>
31 /* Some useful URLs:
32 Homepage:
33 http://www.codeblocks.org
35 File format docs:
36 http://wiki.codeblocks.org/index.php?title=File_formats_description
37 http://wiki.codeblocks.org/index.php?title=Workspace_file
38 http://wiki.codeblocks.org/index.php?title=Project_file
40 Discussion:
41 http://forums.codeblocks.org/index.php/topic,6789.0.html
44 //----------------------------------------------------------------------------
45 void cmExtraCodeBlocksGenerator
46 ::GetDocumentation(cmDocumentationEntry& entry, const char*) const
48 entry.Name = this->GetName();
49 entry.Brief = "Generates CodeBlocks project files.";
50 entry.Full =
51 "Project files for CodeBlocks will be created in the top directory "
52 "and in every subdirectory which features a CMakeLists.txt file "
53 "containing a PROJECT() call. "
54 "Additionally a hierarchy of makefiles is generated into the "
55 "build tree. The appropriate make program can build the project through "
56 "the default make target. A \"make install\" target is also provided.";
59 cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator()
60 :cmExternalMakefileProjectGenerator()
62 #if defined(_WIN32)
63 this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
64 // disable until somebody actually tests it:
65 // this->SupportedGlobalGenerators.push_back("NMake Makefiles");
66 // this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
67 #endif
68 this->SupportedGlobalGenerators.push_back("Unix Makefiles");
72 void cmExtraCodeBlocksGenerator::SetGlobalGenerator(
73 cmGlobalGenerator* generator)
75 cmExternalMakefileProjectGenerator::SetGlobalGenerator(generator);
76 cmGlobalUnixMakefileGenerator3* mf = (cmGlobalUnixMakefileGenerator3*)
77 generator;
78 mf->SetToolSupportsColor(false);
79 mf->SetForceVerboseMakefiles(true);
82 void cmExtraCodeBlocksGenerator::Generate()
84 // for each sub project in the project create a codeblocks project
85 for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
86 it = this->GlobalGenerator->GetProjectMap().begin();
87 it!= this->GlobalGenerator->GetProjectMap().end();
88 ++it)
90 // create a project file
91 this->CreateProjectFile(it->second);
96 /* create the project file */
97 void cmExtraCodeBlocksGenerator::CreateProjectFile(
98 const std::vector<cmLocalGenerator*>& lgs)
100 const cmMakefile* mf=lgs[0]->GetMakefile();
101 std::string outputDir=mf->GetStartOutputDirectory();
102 std::string projectName=mf->GetProjectName();
104 std::string filename=outputDir+"/";
105 filename+=projectName+".cbp";
106 std::string sessionFilename=outputDir+"/";
107 sessionFilename+=projectName+".layout";
109 this->CreateNewProjectFile(lgs, filename);
113 void cmExtraCodeBlocksGenerator
114 ::CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
115 const std::string& filename)
117 const cmMakefile* mf=lgs[0]->GetMakefile();
118 cmGeneratedFileStream fout(filename.c_str());
119 if(!fout)
121 return;
124 // figure out the compiler
125 std::string compiler = this->GetCBCompilerId(mf);
126 std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
128 fout<<"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"
129 "<CodeBlocks_project_file>\n"
130 " <FileVersion major=\"1\" minor=\"6\" />\n"
131 " <Project>\n"
132 " <Option title=\"" << mf->GetProjectName()<<"\" />\n"
133 " <Option makefile_is_custom=\"1\" />\n"
134 " <Option compiler=\"" << compiler << "\" />\n"
135 " <Build>\n";
137 bool installTargetCreated = false;
138 bool installStripTargetCreated = false;
139 bool testTargetCreated = false;
140 bool experimentalTargetCreated = false;
141 bool nightlyTargetCreated = false;
142 bool packageTargetCreated = false;
143 bool packageSourceTargetCreated = false;
144 bool rebuildCacheTargetCreated = false;
146 this->AppendTarget(fout, "all", 0, make.c_str(), mf, compiler.c_str());
148 // add all executable and library targets and some of the GLOBAL
149 // and UTILITY targets
150 for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin();
151 lg!=lgs.end(); lg++)
153 cmMakefile* makefile=(*lg)->GetMakefile();
154 cmTargets& targets=makefile->GetTargets();
155 for (cmTargets::iterator ti = targets.begin();
156 ti != targets.end(); ti++)
158 switch(ti->second.GetType())
160 case cmTarget::UTILITY:
161 case cmTarget::GLOBAL_TARGET:
162 // only add these targets once
163 if ((ti->first=="install") && (installTargetCreated==false))
165 installTargetCreated=true;
167 else if ((ti->first=="install/strip")
168 && (installStripTargetCreated==false))
170 installStripTargetCreated=true;
172 else if ((ti->first=="test") && (testTargetCreated==false))
174 testTargetCreated=true;
176 else if ((ti->first=="Experimental")
177 && (experimentalTargetCreated==false))
179 experimentalTargetCreated=true;
181 else if ((ti->first=="Nightly") && (nightlyTargetCreated==false))
183 nightlyTargetCreated=true;
185 else if ((ti->first=="package") && (packageTargetCreated==false))
187 packageTargetCreated=true;
189 else if ((ti->first=="package_source")
190 && (packageSourceTargetCreated==false))
192 packageSourceTargetCreated=true;
194 else if ((ti->first=="rebuild_cache")
195 && (rebuildCacheTargetCreated==false))
197 rebuildCacheTargetCreated=true;
199 else
201 break;
203 this->AppendTarget(fout, ti->first.c_str(), 0,
204 make.c_str(), makefile, compiler.c_str());
205 break;
206 case cmTarget::EXECUTABLE:
207 case cmTarget::STATIC_LIBRARY:
208 case cmTarget::SHARED_LIBRARY:
209 case cmTarget::MODULE_LIBRARY:
211 this->AppendTarget(fout, ti->first.c_str(), &ti->second,
212 make.c_str(), makefile, compiler.c_str());
213 std::string fastTarget = ti->first;
214 fastTarget += "/fast";
215 this->AppendTarget(fout, fastTarget.c_str(), &ti->second,
216 make.c_str(), makefile, compiler.c_str());
218 break;
219 // ignore these:
220 case cmTarget::INSTALL_FILES:
221 case cmTarget::INSTALL_PROGRAMS:
222 case cmTarget::INSTALL_DIRECTORY:
223 default:
224 break;
229 fout<<" </Build>\n";
232 // Collect all used source files in the project
233 // Sort them into two containers, one for C/C++ implementation files
234 // which may have an acompanying header, one for all other files
235 std::map<std::string, cmSourceFile*> cFiles;
236 std::set<std::string> otherFiles;
237 for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin();
238 lg!=lgs.end(); lg++)
240 cmMakefile* makefile=(*lg)->GetMakefile();
241 cmTargets& targets=makefile->GetTargets();
242 for (cmTargets::iterator ti = targets.begin();
243 ti != targets.end(); ti++)
245 switch(ti->second.GetType())
247 case cmTarget::EXECUTABLE:
248 case cmTarget::STATIC_LIBRARY:
249 case cmTarget::SHARED_LIBRARY:
250 case cmTarget::MODULE_LIBRARY:
252 const std::vector<cmSourceFile*>&sources=ti->second.GetSourceFiles();
253 for (std::vector<cmSourceFile*>::const_iterator si=sources.begin();
254 si!=sources.end(); si++)
256 // check whether it is a C/C++ implementation file
257 bool isCFile = false;
258 if ((*si)->GetLanguage() && (*(*si)->GetLanguage() == 'C'))
260 for(std::vector<std::string>::const_iterator
261 ext = mf->GetSourceExtensions().begin();
262 ext != mf->GetSourceExtensions().end();
263 ++ext)
265 if ((*si)->GetExtension() == *ext)
267 isCFile = true;
268 break;
273 // then put it accordingly into one of the two containers
274 if (isCFile)
276 cFiles[(*si)->GetFullPath()] = *si ;
278 else
280 otherFiles.insert((*si)->GetFullPath());
284 default: // intended fallthrough
285 break;
290 // The following loop tries to add header files matching to implementation
291 // files to the project. It does that by iterating over all source files,
292 // replacing the file name extension with ".h" and checks whether such a
293 // file exists. If it does, it is inserted into the map of files.
294 // A very similar version of that code exists also in the kdevelop
295 // project generator.
296 for (std::map<std::string, cmSourceFile*>::const_iterator
297 sit=cFiles.begin();
298 sit!=cFiles.end();
299 ++sit)
301 std::string headerBasename=cmSystemTools::GetFilenamePath(sit->first);
302 headerBasename+="/";
303 headerBasename+=cmSystemTools::GetFilenameWithoutExtension(sit->first);
305 // check if there's a matching header around
306 for(std::vector<std::string>::const_iterator
307 ext = mf->GetHeaderExtensions().begin();
308 ext != mf->GetHeaderExtensions().end();
309 ++ext)
311 std::string hname=headerBasename;
312 hname += ".";
313 hname += *ext;
314 // if it's already in the set, don't check if it exists on disk
315 std::set<std::string>::const_iterator headerIt=otherFiles.find(hname);
316 if (headerIt != otherFiles.end())
318 break;
321 if(cmSystemTools::FileExists(hname.c_str()))
323 otherFiles.insert(hname);
324 break;
329 // insert all source files in the CodeBlocks project
330 // first the C/C++ implementation files, then all others
331 for (std::map<std::string, cmSourceFile*>::const_iterator
332 sit=cFiles.begin();
333 sit!=cFiles.end();
334 ++sit)
336 fout<<" <Unit filename=\""<< sit->first <<"\">\n"
337 " </Unit>\n";
339 for (std::set<std::string>::const_iterator
340 sit=otherFiles.begin();
341 sit!=otherFiles.end();
342 ++sit)
344 fout<<" <Unit filename=\""<< sit->c_str() <<"\">\n"
345 " </Unit>\n";
348 fout<<" </Project>\n"
349 "</CodeBlocks_project_file>\n";
353 // Generate the xml code for one target.
354 void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout,
355 const char* targetName,
356 cmTarget* target,
357 const char* make,
358 const cmMakefile* makefile,
359 const char* compiler)
361 std::string makefileName = makefile->GetStartOutputDirectory();
362 makefileName += "/Makefile";
363 makefileName = cmSystemTools::ConvertToOutputPath(makefileName.c_str());
365 fout<<" <Target title=\"" << targetName << "\">\n";
366 if (target!=0)
368 int cbTargetType = this->GetCBTargetType(target);
369 fout<<" <Option output=\"" << target->GetLocation(0)
370 << "\" prefix_auto=\"0\" extension_auto=\"0\" />\n"
371 " <Option working_dir=\""
372 << makefile->GetStartOutputDirectory() << "\" />\n"
373 " <Option object_output=\"./\" />\n"
374 " <Option type=\"" << cbTargetType << "\" />\n"
375 " <Option compiler=\"" << compiler << "\" />\n"
376 " <Compiler>\n";
377 // the include directories for this target
378 const std::vector<std::string>& incDirs =
379 target->GetMakefile()->GetIncludeDirectories();
380 for(std::vector<std::string>::const_iterator dirIt=incDirs.begin();
381 dirIt != incDirs.end();
382 ++dirIt)
384 fout <<" <Add directory=\"" << dirIt->c_str() << "\" />\n";
386 fout<<" </Compiler>\n";
388 else // e.g. all and the GLOBAL and UTILITY targets
390 fout<<" <Option working_dir=\""
391 << makefile->GetStartOutputDirectory() << "\" />\n"
392 <<" <Option type=\"" << 4 << "\" />\n";
395 fout<<" <MakeCommands>\n"
396 " <Build command=\""
397 << this->BuildMakeCommand(make, makefileName.c_str(), targetName)
398 << "\" />\n"
399 " <CompileFile command=\""
400 << this->BuildMakeCommand(make, makefileName.c_str(),"&quot;$file&quot;")
401 << "\" />\n"
402 " <Clean command=\""
403 << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
404 << "\" />\n"
405 " <DistClean command=\""
406 << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
407 << "\" />\n"
408 " </MakeCommands>\n"
409 " </Target>\n";
414 // Translate the cmake compiler id into the CodeBlocks compiler id
415 std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf)
417 // figure out which language to use
418 // for now care only for C and C++
419 std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID";
420 if (this->GlobalGenerator->GetLanguageEnabled("CXX") == false)
422 compilerIdVar = "CMAKE_C_COMPILER_ID";
425 std::string hostSystemName = mf->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
426 std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
427 std::string compilerId = mf->GetRequiredDefinition(compilerIdVar.c_str());
428 std::string compiler = "gcc";
429 if (compilerId == "MSVC")
431 compiler = "msvc";
433 else if (compilerId == "Borland")
435 compiler = "bcc";
437 else if (compilerId == "SDCC")
439 compiler = "sdcc";
441 else if (compilerId == "Intel")
443 compiler = "icc";
445 else if (compilerId == "Watcom")
447 compiler = "ow";
449 else if (compilerId == "GNU")
451 compiler = "gcc";
453 return compiler;
457 // Translate the cmake target type into the CodeBlocks target type id
458 int cmExtraCodeBlocksGenerator::GetCBTargetType(cmTarget* target)
460 if ( target->GetType()==cmTarget::EXECUTABLE)
462 if ((target->GetPropertyAsBool("WIN32_EXECUTABLE"))
463 || (target->GetPropertyAsBool("MACOSX_BUNDLE")))
465 return 0;
467 else
469 return 1;
472 else if ( target->GetType()==cmTarget::STATIC_LIBRARY)
474 return 2;
476 else if ((target->GetType()==cmTarget::SHARED_LIBRARY)
477 || (target->GetType()==cmTarget::MODULE_LIBRARY))
479 return 3;
481 return 4;
484 // Create the command line for building the given target using the selected
485 // make
486 std::string cmExtraCodeBlocksGenerator::BuildMakeCommand(
487 const std::string& make, const char* makefile, const char* target)
489 std::string command = make;
490 if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0)
492 command += " /NOLOGO /f &quot;";
493 command += makefile;
494 command += "&quot; ";
495 command += target;
497 else if (strcmp(this->GlobalGenerator->GetName(), "MinGW Makefiles")==0)
499 command += " -f ";
500 command += makefile;
501 command += " ";
502 command += target;
504 else
506 command += " -f &quot;";
507 command += makefile;
508 command += "&quot; ";
509 command += target;
511 return command;