You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

367 lines
11 KiB

  1. /*=========================================================================
  2. Program: CMake - Cross-Platform Makefile Generator
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
  8. Copyright (c) 2004 Alexander Neundorf neundorf@kde.org, All rights reserved.
  9. See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
  10. This software is distributed WITHOUT ANY WARRANTY; without even
  11. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  12. PURPOSE. See the above copyright notices for more information.
  13. =========================================================================*/
  14. #include "cmExtraCodeBlocksGenerator.h"
  15. #include "cmGlobalUnixMakefileGenerator3.h"
  16. #include "cmLocalUnixMakefileGenerator3.h"
  17. #include "cmMakefile.h"
  18. #include "cmake.h"
  19. #include "cmSourceFile.h"
  20. #include "cmGeneratedFileStream.h"
  21. #include "cmTarget.h"
  22. #include "cmSystemTools.h"
  23. #include <cmsys/SystemTools.hxx>
  24. /* Some useful URLs:
  25. Homepage:
  26. http://www.codeblocks.org
  27. File format docs:
  28. http://wiki.codeblocks.org/index.php?title=File_formats_description
  29. http://wiki.codeblocks.org/index.php?title=Workspace_file
  30. http://wiki.codeblocks.org/index.php?title=Project_file
  31. Discussion:
  32. http://forums.codeblocks.org/index.php/topic,6789.0.html
  33. */
  34. //----------------------------------------------------------------------------
  35. void cmExtraCodeBlocksGenerator
  36. ::GetDocumentation(cmDocumentationEntry& entry, const char*) const
  37. {
  38. entry.Name = this->GetName();
  39. entry.Brief = "Generates CodeBlocks project files.";
  40. entry.Full =
  41. "Project files for CodeBlocks will be created in the top directory "
  42. "and in every subdirectory which features a CMakeLists.txt file "
  43. "containing a PROJECT() call. "
  44. "Additionally a hierarchy of makefiles is generated into the "
  45. "build tree. The appropriate make program can build the project through "
  46. "the default make target. A \"make install\" target is also provided.";
  47. }
  48. cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator()
  49. :cmExternalMakefileProjectGenerator()
  50. {
  51. #if defined(_WIN32)
  52. this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
  53. // disable until somebody actually tests it:
  54. // this->SupportedGlobalGenerators.push_back("NMake Makefiles");
  55. // this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
  56. #endif
  57. this->SupportedGlobalGenerators.push_back("Unix Makefiles");
  58. }
  59. void cmExtraCodeBlocksGenerator::SetGlobalGenerator(
  60. cmGlobalGenerator* generator)
  61. {
  62. cmExternalMakefileProjectGenerator::SetGlobalGenerator(generator);
  63. cmGlobalUnixMakefileGenerator3* mf = (cmGlobalUnixMakefileGenerator3*)
  64. generator;
  65. mf->SetToolSupportsColor(false);
  66. mf->SetForceVerboseMakefiles(true);
  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. /* create the project file, if it already exists, merge it with the
  81. existing one, otherwise create a new one */
  82. void cmExtraCodeBlocksGenerator::CreateProjectFile(
  83. const std::vector<cmLocalGenerator*>& lgs)
  84. {
  85. const cmMakefile* mf=lgs[0]->GetMakefile();
  86. std::string outputDir=mf->GetStartOutputDirectory();
  87. std::string projectDir=mf->GetHomeDirectory();
  88. std::string projectName=mf->GetProjectName();
  89. std::string filename=outputDir+"/";
  90. filename+=projectName+".cbp";
  91. std::string sessionFilename=outputDir+"/";
  92. sessionFilename+=projectName+".layout";
  93. /* if (cmSystemTools::FileExists(filename.c_str()))
  94. {
  95. this->MergeProjectFiles(outputDir, projectDir, filename,
  96. cmakeFilePattern, sessionFilename);
  97. }
  98. else */
  99. {
  100. this->CreateNewProjectFile(lgs, filename);
  101. }
  102. }
  103. void cmExtraCodeBlocksGenerator
  104. ::CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs,
  105. const std::string& filename)
  106. {
  107. const cmMakefile* mf=lgs[0]->GetMakefile();
  108. cmGeneratedFileStream fout(filename.c_str());
  109. if(!fout)
  110. {
  111. return;
  112. }
  113. // figure out the compiler
  114. std::string compiler = this->GetCBCompilerId(mf);
  115. std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
  116. fout<<"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n"
  117. "<CodeBlocks_project_file>\n"
  118. " <FileVersion major=\"1\" minor=\"6\" />\n"
  119. " <Project>\n"
  120. " <Option title=\"" << mf->GetProjectName()<<"\" />\n"
  121. " <Option makefile_is_custom=\"1\" />\n"
  122. " <Option compiler=\"" << compiler << "\" />\n"
  123. " <Build>\n";
  124. bool installTargetCreated = false;
  125. bool testTargetCreated = false;
  126. bool packageTargetCreated = false;
  127. for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin();
  128. lg!=lgs.end(); lg++)
  129. {
  130. cmMakefile* makefile=(*lg)->GetMakefile();
  131. cmTargets& targets=makefile->GetTargets();
  132. for (cmTargets::iterator ti = targets.begin();
  133. ti != targets.end(); ti++)
  134. {
  135. switch(ti->second.GetType())
  136. {
  137. case cmTarget::GLOBAL_TARGET:
  138. if ((ti->first=="install") && (installTargetCreated==false))
  139. {
  140. installTargetCreated=true;
  141. }
  142. else if ((ti->first=="package") && (packageTargetCreated==false))
  143. {
  144. packageTargetCreated=true;
  145. }
  146. else if ((ti->first=="test") && (testTargetCreated==false))
  147. {
  148. testTargetCreated=true;
  149. }
  150. else
  151. {
  152. break;
  153. }
  154. case cmTarget::EXECUTABLE:
  155. case cmTarget::STATIC_LIBRARY:
  156. case cmTarget::SHARED_LIBRARY:
  157. case cmTarget::MODULE_LIBRARY:
  158. {
  159. int cbTargetType = this->GetCBTargetType(&ti->second);
  160. std::string makefileName = makefile->GetStartOutputDirectory();
  161. makefileName += "/Makefile";
  162. makefileName = cmSystemTools::ConvertToOutputPath(
  163. makefileName.c_str());
  164. fout<<" <Target title=\"" << ti->first << "\">\n"
  165. " <Option output=\"" << ti->second.GetLocation(0)
  166. << "\" prefix_auto=\"0\" extension_auto=\"0\" />\n"
  167. " <Option working_dir=\"" <<makefile->GetStartOutputDirectory()
  168. <<"\" />\n"
  169. " <Option object_output=\"./\" />\n"
  170. " <Option type=\"" << cbTargetType << "\" />\n"
  171. " <Option compiler=\"" << compiler << "\" />\n"
  172. " <Compiler>\n";
  173. // the include directories for this target
  174. const std::vector<std::string>& incDirs =
  175. ti->second.GetMakefile()->GetIncludeDirectories();
  176. for(std::vector<std::string>::const_iterator dirIt=incDirs.begin();
  177. dirIt != incDirs.end();
  178. ++dirIt)
  179. {
  180. fout <<" <Add directory=\"" << dirIt->c_str() << "\" />\n";
  181. }
  182. fout<<" </Compiler>\n"
  183. " <MakeCommands>\n"
  184. " <Build command=\""
  185. << this->BuildMakeCommand(make, makefileName.c_str(), ti->first.c_str())
  186. << "\" />\n"
  187. " <CompileFile command=\""
  188. << this->BuildMakeCommand(make, makefileName.c_str(),"&quot;$file&quot;")
  189. << "\" />\n"
  190. " <Clean command=\""
  191. << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
  192. << "\" />\n"
  193. " <DistClean command=\""
  194. << this->BuildMakeCommand(make, makefileName.c_str(), "clean")
  195. << "\" />\n"
  196. " </MakeCommands>\n"
  197. " </Target>\n";
  198. }
  199. break;
  200. default:
  201. break;
  202. }
  203. }
  204. }
  205. fout<<" </Build>\n";
  206. std::map<std::string, std::string> sourceFiles;
  207. for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin();
  208. lg!=lgs.end(); lg++)
  209. {
  210. cmMakefile* makefile=(*lg)->GetMakefile();
  211. cmTargets& targets=makefile->GetTargets();
  212. for (cmTargets::iterator ti = targets.begin();
  213. ti != targets.end(); ti++)
  214. {
  215. switch(ti->second.GetType())
  216. {
  217. case cmTarget::EXECUTABLE:
  218. case cmTarget::STATIC_LIBRARY:
  219. case cmTarget::SHARED_LIBRARY:
  220. case cmTarget::MODULE_LIBRARY:
  221. {
  222. const std::vector<cmSourceFile*>&sources=ti->second.GetSourceFiles();
  223. for (std::vector<cmSourceFile*>::const_iterator si=sources.begin();
  224. si!=sources.end(); si++)
  225. {
  226. sourceFiles[(*si)->GetFullPath()] = ti->first;
  227. }
  228. }
  229. default: // intended fallthrough
  230. break;
  231. }
  232. }
  233. }
  234. for (std::map<std::string, std::string>::const_iterator
  235. sit=sourceFiles.begin();
  236. sit!=sourceFiles.end();
  237. ++sit)
  238. {
  239. fout<<" <Unit filename=\""<<sit->first <<"\">\n"
  240. " </Unit>\n";
  241. }
  242. fout<<" </Project>\n"
  243. "</CodeBlocks_project_file>\n";
  244. }
  245. std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf)
  246. {
  247. // figure out which language to use
  248. // for now care only for C and C++
  249. std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID";
  250. if (this->GlobalGenerator->GetLanguageEnabled("CXX") == false)
  251. {
  252. compilerIdVar = "CMAKE_C_COMPILER_ID";
  253. }
  254. std::string hostSystemName = mf->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME");
  255. std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
  256. std::string compilerId = mf->GetRequiredDefinition(compilerIdVar.c_str());
  257. std::string compiler = "gcc";
  258. if (compilerId == "MSVC")
  259. {
  260. compiler = "msvc";
  261. }
  262. else if (compilerId == "Borland")
  263. {
  264. compiler = "bcc";
  265. }
  266. else if (compilerId == "SDCC")
  267. {
  268. compiler = "sdcc";
  269. }
  270. else if (compilerId == "Intel")
  271. {
  272. compiler = "icc";
  273. }
  274. else if (compilerId == "Watcom")
  275. {
  276. compiler = "ow";
  277. }
  278. else if (compilerId == "GNU")
  279. {
  280. compiler = "gcc";
  281. }
  282. return compiler;
  283. }
  284. int cmExtraCodeBlocksGenerator::GetCBTargetType(cmTarget* target)
  285. {
  286. if ( target->GetType()==cmTarget::EXECUTABLE)
  287. {
  288. if ((target->GetPropertyAsBool("WIN32_EXECUTABLE"))
  289. || (target->GetPropertyAsBool("MACOSX_BUNDLE")))
  290. {
  291. return 0;
  292. }
  293. else
  294. {
  295. return 1;
  296. }
  297. }
  298. else if ( target->GetType()==cmTarget::STATIC_LIBRARY)
  299. {
  300. return 2;
  301. }
  302. else if ((target->GetType()==cmTarget::SHARED_LIBRARY)
  303. || (target->GetType()==cmTarget::MODULE_LIBRARY))
  304. {
  305. return 3;
  306. }
  307. return 4;
  308. }
  309. std::string cmExtraCodeBlocksGenerator::BuildMakeCommand(
  310. const std::string& make, const char* makefile, const char* target)
  311. {
  312. std::string command = make;
  313. if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0)
  314. {
  315. command += " /NOLOGO /f &quot;";
  316. command += makefile;
  317. command += "&quot; ";
  318. command += target;
  319. }
  320. else
  321. {
  322. command += " -f &quot;";
  323. command += makefile;
  324. command += "&quot; ";
  325. command += target;
  326. }
  327. return command;
  328. }