| /*========================================================================= |
| |
| Program: CMake - Cross-Platform Makefile Generator |
| Module: $RCSfile: cmExtraCodeBlocksGenerator.cxx,v $ |
| Language: C++ |
| Date: $Date: 2012/03/29 17:21:07 $ |
| Version: $Revision: 1.1.1.1 $ |
| |
| Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved. |
| Copyright (c) 2004 Alexander Neundorf neundorf@kde.org, All rights reserved. |
| See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details. |
| |
| This software is distributed WITHOUT ANY WARRANTY; without even |
| the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR |
| PURPOSE. See the above copyright notices for more information. |
| |
| =========================================================================*/ |
| |
| #include "cmExtraCodeBlocksGenerator.h" |
| #include "cmGlobalUnixMakefileGenerator3.h" |
| #include "cmLocalUnixMakefileGenerator3.h" |
| #include "cmMakefile.h" |
| #include "cmake.h" |
| #include "cmSourceFile.h" |
| #include "cmGeneratedFileStream.h" |
| #include "cmTarget.h" |
| #include "cmSystemTools.h" |
| |
| #include <cmsys/SystemTools.hxx> |
| |
| /* Some useful URLs: |
| Homepage: |
| http://www.codeblocks.org |
| |
| File format docs: |
| http://wiki.codeblocks.org/index.php?title=File_formats_description |
| http://wiki.codeblocks.org/index.php?title=Workspace_file |
| http://wiki.codeblocks.org/index.php?title=Project_file |
| |
| Discussion: |
| http://forums.codeblocks.org/index.php/topic,6789.0.html |
| */ |
| |
| //---------------------------------------------------------------------------- |
| void cmExtraCodeBlocksGenerator |
| ::GetDocumentation(cmDocumentationEntry& entry, const char*) const |
| { |
| entry.Name = this->GetName(); |
| entry.Brief = "Generates CodeBlocks project files."; |
| entry.Full = |
| "Project files for CodeBlocks will be created in the top directory " |
| "and in every subdirectory which features a CMakeLists.txt file " |
| "containing a PROJECT() call. " |
| "Additionally a hierarchy of makefiles is generated into the " |
| "build tree. The appropriate make program can build the project through " |
| "the default make target. A \"make install\" target is also provided."; |
| } |
| |
| cmExtraCodeBlocksGenerator::cmExtraCodeBlocksGenerator() |
| :cmExternalMakefileProjectGenerator() |
| { |
| #if defined(_WIN32) |
| this->SupportedGlobalGenerators.push_back("MinGW Makefiles"); |
| // disable until somebody actually tests it: |
| // this->SupportedGlobalGenerators.push_back("NMake Makefiles"); |
| // this->SupportedGlobalGenerators.push_back("MSYS Makefiles"); |
| #endif |
| this->SupportedGlobalGenerators.push_back("Unix Makefiles"); |
| } |
| |
| |
| void cmExtraCodeBlocksGenerator::SetGlobalGenerator( |
| cmGlobalGenerator* generator) |
| { |
| cmExternalMakefileProjectGenerator::SetGlobalGenerator(generator); |
| cmGlobalUnixMakefileGenerator3* mf = (cmGlobalUnixMakefileGenerator3*) |
| generator; |
| mf->SetToolSupportsColor(false); |
| mf->SetForceVerboseMakefiles(true); |
| } |
| |
| void cmExtraCodeBlocksGenerator::Generate() |
| { |
| // for each sub project in the project create a codeblocks project |
| for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator |
| it = this->GlobalGenerator->GetProjectMap().begin(); |
| it!= this->GlobalGenerator->GetProjectMap().end(); |
| ++it) |
| { |
| // create a project file |
| this->CreateProjectFile(it->second); |
| } |
| } |
| |
| |
| /* create the project file, if it already exists, merge it with the |
| existing one, otherwise create a new one */ |
| void cmExtraCodeBlocksGenerator::CreateProjectFile( |
| const std::vector<cmLocalGenerator*>& lgs) |
| { |
| const cmMakefile* mf=lgs[0]->GetMakefile(); |
| std::string outputDir=mf->GetStartOutputDirectory(); |
| std::string projectDir=mf->GetHomeDirectory(); |
| std::string projectName=mf->GetProjectName(); |
| |
| std::string filename=outputDir+"/"; |
| filename+=projectName+".cbp"; |
| std::string sessionFilename=outputDir+"/"; |
| sessionFilename+=projectName+".layout"; |
| |
| /* if (cmSystemTools::FileExists(filename.c_str())) |
| { |
| this->MergeProjectFiles(outputDir, projectDir, filename, |
| cmakeFilePattern, sessionFilename); |
| } |
| else */ |
| { |
| this->CreateNewProjectFile(lgs, filename); |
| } |
| |
| } |
| |
| |
| void cmExtraCodeBlocksGenerator |
| ::CreateNewProjectFile(const std::vector<cmLocalGenerator*>& lgs, |
| const std::string& filename) |
| { |
| const cmMakefile* mf=lgs[0]->GetMakefile(); |
| cmGeneratedFileStream fout(filename.c_str()); |
| if(!fout) |
| { |
| return; |
| } |
| |
| // figure out the compiler |
| std::string compiler = this->GetCBCompilerId(mf); |
| std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); |
| |
| fout<<"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\" ?>\n" |
| "<CodeBlocks_project_file>\n" |
| " <FileVersion major=\"1\" minor=\"6\" />\n" |
| " <Project>\n" |
| " <Option title=\"" << mf->GetProjectName()<<"\" />\n" |
| " <Option makefile_is_custom=\"1\" />\n" |
| " <Option compiler=\"" << compiler << "\" />\n" |
| " <Build>\n"; |
| |
| bool installTargetCreated = false; |
| bool installStripTargetCreated = false; |
| bool testTargetCreated = false; |
| bool experimentalTargetCreated = false; |
| bool nightlyTargetCreated = false; |
| bool packageTargetCreated = false; |
| bool packageSourceTargetCreated = false; |
| bool rebuildCacheTargetCreated = false; |
| |
| this->AppendTarget(fout, "all", 0, make.c_str(), mf, compiler.c_str()); |
| |
| // add all executable and library targets and some of the GLOBAL |
| // and UTILITY targets |
| for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin(); |
| lg!=lgs.end(); lg++) |
| { |
| cmMakefile* makefile=(*lg)->GetMakefile(); |
| cmTargets& targets=makefile->GetTargets(); |
| for (cmTargets::iterator ti = targets.begin(); |
| ti != targets.end(); ti++) |
| { |
| switch(ti->second.GetType()) |
| { |
| case cmTarget::UTILITY: |
| case cmTarget::GLOBAL_TARGET: |
| // only add these targets once |
| if ((ti->first=="install") && (installTargetCreated==false)) |
| { |
| installTargetCreated=true; |
| } |
| else if ((ti->first=="install/strip") |
| && (installStripTargetCreated==false)) |
| { |
| installStripTargetCreated=true; |
| } |
| else if ((ti->first=="test") && (testTargetCreated==false)) |
| { |
| testTargetCreated=true; |
| } |
| else if ((ti->first=="Experimental") |
| && (experimentalTargetCreated==false)) |
| { |
| experimentalTargetCreated=true; |
| } |
| else if ((ti->first=="Nightly") && (nightlyTargetCreated==false)) |
| { |
| nightlyTargetCreated=true; |
| } |
| else if ((ti->first=="package") && (packageTargetCreated==false)) |
| { |
| packageTargetCreated=true; |
| } |
| else if ((ti->first=="package_source") |
| && (packageSourceTargetCreated==false)) |
| { |
| packageSourceTargetCreated=true; |
| } |
| else if ((ti->first=="rebuild_cache") |
| && (rebuildCacheTargetCreated==false)) |
| { |
| rebuildCacheTargetCreated=true; |
| } |
| else |
| { |
| break; |
| } |
| this->AppendTarget(fout, ti->first.c_str(), 0, |
| make.c_str(), makefile, compiler.c_str()); |
| break; |
| case cmTarget::EXECUTABLE: |
| case cmTarget::STATIC_LIBRARY: |
| case cmTarget::SHARED_LIBRARY: |
| case cmTarget::MODULE_LIBRARY: |
| { |
| this->AppendTarget(fout, ti->first.c_str(), &ti->second, |
| make.c_str(), makefile, compiler.c_str()); |
| std::string fastTarget = ti->first; |
| fastTarget += "/fast"; |
| this->AppendTarget(fout, fastTarget.c_str(), &ti->second, |
| make.c_str(), makefile, compiler.c_str()); |
| } |
| break; |
| // ignore these: |
| case cmTarget::INSTALL_FILES: |
| case cmTarget::INSTALL_PROGRAMS: |
| case cmTarget::INSTALL_DIRECTORY: |
| default: |
| break; |
| } |
| } |
| } |
| |
| fout<<" </Build>\n"; |
| |
| |
| // Collect all used source files in the project |
| std::map<std::string, std::string> sourceFiles; |
| for (std::vector<cmLocalGenerator*>::const_iterator lg=lgs.begin(); |
| lg!=lgs.end(); lg++) |
| { |
| cmMakefile* makefile=(*lg)->GetMakefile(); |
| cmTargets& targets=makefile->GetTargets(); |
| for (cmTargets::iterator ti = targets.begin(); |
| ti != targets.end(); ti++) |
| { |
| switch(ti->second.GetType()) |
| { |
| case cmTarget::EXECUTABLE: |
| case cmTarget::STATIC_LIBRARY: |
| case cmTarget::SHARED_LIBRARY: |
| case cmTarget::MODULE_LIBRARY: |
| { |
| const std::vector<cmSourceFile*>&sources=ti->second.GetSourceFiles(); |
| for (std::vector<cmSourceFile*>::const_iterator si=sources.begin(); |
| si!=sources.end(); si++) |
| { |
| sourceFiles[(*si)->GetFullPath()] = ti->first; |
| } |
| } |
| default: // intended fallthrough |
| break; |
| } |
| } |
| } |
| |
| // insert all used source files in the CodeBlocks project |
| for (std::map<std::string, std::string>::const_iterator |
| sit=sourceFiles.begin(); |
| sit!=sourceFiles.end(); |
| ++sit) |
| { |
| fout<<" <Unit filename=\""<<sit->first <<"\">\n" |
| " </Unit>\n"; |
| } |
| |
| fout<<" </Project>\n" |
| "</CodeBlocks_project_file>\n"; |
| } |
| |
| |
| // Generate the xml code for one target. |
| void cmExtraCodeBlocksGenerator::AppendTarget(cmGeneratedFileStream& fout, |
| const char* targetName, |
| cmTarget* target, |
| const char* make, |
| const cmMakefile* makefile, |
| const char* compiler) |
| { |
| std::string makefileName = makefile->GetStartOutputDirectory(); |
| makefileName += "/Makefile"; |
| makefileName = cmSystemTools::ConvertToOutputPath(makefileName.c_str()); |
| |
| fout<<" <Target title=\"" << targetName << "\">\n"; |
| if (target!=0) |
| { |
| int cbTargetType = this->GetCBTargetType(target); |
| fout<<" <Option output=\"" << target->GetLocation(0) |
| << "\" prefix_auto=\"0\" extension_auto=\"0\" />\n" |
| " <Option working_dir=\"" |
| << makefile->GetStartOutputDirectory() << "\" />\n" |
| " <Option object_output=\"./\" />\n" |
| " <Option type=\"" << cbTargetType << "\" />\n" |
| " <Option compiler=\"" << compiler << "\" />\n" |
| " <Compiler>\n"; |
| // the include directories for this target |
| const std::vector<std::string>& incDirs = |
| target->GetMakefile()->GetIncludeDirectories(); |
| for(std::vector<std::string>::const_iterator dirIt=incDirs.begin(); |
| dirIt != incDirs.end(); |
| ++dirIt) |
| { |
| fout <<" <Add directory=\"" << dirIt->c_str() << "\" />\n"; |
| } |
| fout<<" </Compiler>\n"; |
| } |
| else // e.g. all and the GLOBAL and UTILITY targets |
| { |
| fout<<" <Option working_dir=\"" |
| << makefile->GetStartOutputDirectory() << "\" />\n" |
| <<" <Option type=\"" << 4 << "\" />\n"; |
| } |
| |
| fout<<" <MakeCommands>\n" |
| " <Build command=\"" |
| << this->BuildMakeCommand(make, makefileName.c_str(), targetName) |
| << "\" />\n" |
| " <CompileFile command=\"" |
| << this->BuildMakeCommand(make, makefileName.c_str(),""$file"") |
| << "\" />\n" |
| " <Clean command=\"" |
| << this->BuildMakeCommand(make, makefileName.c_str(), "clean") |
| << "\" />\n" |
| " <DistClean command=\"" |
| << this->BuildMakeCommand(make, makefileName.c_str(), "clean") |
| << "\" />\n" |
| " </MakeCommands>\n" |
| " </Target>\n"; |
| |
| } |
| |
| |
| // Translate the cmake compiler id into the CodeBlocks compiler id |
| std::string cmExtraCodeBlocksGenerator::GetCBCompilerId(const cmMakefile* mf) |
| { |
| // figure out which language to use |
| // for now care only for C and C++ |
| std::string compilerIdVar = "CMAKE_CXX_COMPILER_ID"; |
| if (this->GlobalGenerator->GetLanguageEnabled("CXX") == false) |
| { |
| compilerIdVar = "CMAKE_C_COMPILER_ID"; |
| } |
| |
| std::string hostSystemName = mf->GetSafeDefinition("CMAKE_HOST_SYSTEM_NAME"); |
| std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME"); |
| std::string compilerId = mf->GetRequiredDefinition(compilerIdVar.c_str()); |
| std::string compiler = "gcc"; |
| if (compilerId == "MSVC") |
| { |
| compiler = "msvc"; |
| } |
| else if (compilerId == "Borland") |
| { |
| compiler = "bcc"; |
| } |
| else if (compilerId == "SDCC") |
| { |
| compiler = "sdcc"; |
| } |
| else if (compilerId == "Intel") |
| { |
| compiler = "icc"; |
| } |
| else if (compilerId == "Watcom") |
| { |
| compiler = "ow"; |
| } |
| else if (compilerId == "GNU") |
| { |
| compiler = "gcc"; |
| } |
| return compiler; |
| } |
| |
| |
| // Translate the cmake target type into the CodeBlocks target type id |
| int cmExtraCodeBlocksGenerator::GetCBTargetType(cmTarget* target) |
| { |
| if ( target->GetType()==cmTarget::EXECUTABLE) |
| { |
| if ((target->GetPropertyAsBool("WIN32_EXECUTABLE")) |
| || (target->GetPropertyAsBool("MACOSX_BUNDLE"))) |
| { |
| return 0; |
| } |
| else |
| { |
| return 1; |
| } |
| } |
| else if ( target->GetType()==cmTarget::STATIC_LIBRARY) |
| { |
| return 2; |
| } |
| else if ((target->GetType()==cmTarget::SHARED_LIBRARY) |
| || (target->GetType()==cmTarget::MODULE_LIBRARY)) |
| { |
| return 3; |
| } |
| return 4; |
| } |
| |
| // Create the command line for building the given target using the selected |
| // make |
| std::string cmExtraCodeBlocksGenerator::BuildMakeCommand( |
| const std::string& make, const char* makefile, const char* target) |
| { |
| std::string command = make; |
| if (strcmp(this->GlobalGenerator->GetName(), "NMake Makefiles")==0) |
| { |
| command += " /NOLOGO /f ""; |
| command += makefile; |
| command += "" "; |
| command += target; |
| } |
| else |
| { |
| command += " -f ""; |
| command += makefile; |
| command += "" "; |
| command += target; |
| } |
| return command; |
| } |