/*============================================================================ CMake - Cross Platform Makefile Generator Copyright 2004-2009 Kitware, Inc. Copyright 2004 Alexander Neundorf (neundorf@kde.org) Distributed under the OSI-approved BSD License (the "License"); see accompanying file Copyright.txt for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the License for more information. ============================================================================*/ #include "cmExtraKateGenerator.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 "cmXMLSafe.h" #include //---------------------------------------------------------------------------- void cmExtraKateGenerator ::GetDocumentation(cmDocumentationEntry& entry, const std::string&) const { entry.Name = this->GetName(); entry.Brief = "Generates Kate project files."; } cmExtraKateGenerator::cmExtraKateGenerator() :cmExternalMakefileProjectGenerator() { #if defined(_WIN32) this->SupportedGlobalGenerators.push_back("MinGW Makefiles"); this->SupportedGlobalGenerators.push_back("NMake Makefiles"); // disable until somebody actually tests it: // this->SupportedGlobalGenerators.push_back("MSYS Makefiles"); #endif this->SupportedGlobalGenerators.push_back("Ninja"); this->SupportedGlobalGenerators.push_back("Unix Makefiles"); } void cmExtraKateGenerator::Generate() { const cmMakefile* mf = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile(); this->ProjectName = this->GenerateProjectName(mf->GetProjectName(), mf->GetSafeDefinition("CMAKE_BUILD_TYPE"), this->GetPathBasename(mf->GetHomeOutputDirectory())); this->UseNinja = (this->GlobalGenerator->GetName() == "Ninja"); this->CreateKateProjectFile(mf); this->CreateDummyKateProjectFile(mf); } void cmExtraKateGenerator::CreateKateProjectFile(const cmMakefile* mf) const { std::string filename = mf->GetHomeOutputDirectory(); filename += "/.kateproject"; cmGeneratedFileStream fout(filename.c_str()); if (!fout) { return; } std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); std::string args = mf->GetSafeDefinition("CMAKE_KATE_MAKE_ARGUMENTS"); fout << "{\n" "\t\"name\": \"" << this->ProjectName << "\",\n" "\t\"directory\": \"" << mf->GetHomeDirectory() << "\",\n" "\t\"files\": [ { " << this->GenerateFilesString(mf) << "} ],\n"; this->WriteTargets(mf, fout); fout << "}\n"; } void cmExtraKateGenerator::WriteTargets(const cmMakefile* mf, cmGeneratedFileStream& fout) const { const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM"); const std::string makeArgs = mf->GetSafeDefinition( "CMAKE_KATE_MAKE_ARGUMENTS"); const char* homeOutputDir = mf->GetHomeOutputDirectory(); fout << "\t\"build\": {\n" "\t\t\"directory\": \"" << mf->GetHomeOutputDirectory() << "\",\n" "\t\t\"default_target\": \"all\",\n" "\t\t\"clean_target\": \"clean\",\n"; // build, clean and quick are for the build plugin kate <= 4.12: fout << "\t\t\"build\": \"" << make << " -C \\\"" << homeOutputDir << "\\\" " << makeArgs << " " << "all\",\n"; fout << "\t\t\"clean\": \"" << make << " -C \\\"" << homeOutputDir << "\\\" " << makeArgs << " " << "clean\",\n"; fout << "\t\t\"quick\": \"" << make << " -C \\\"" << homeOutputDir << "\\\" " << makeArgs << " " << "install\",\n"; // this is for kate >= 4.13: fout << "\t\t\"targets\":[\n"; this->AppendTarget(fout, "all", make, makeArgs, homeOutputDir, homeOutputDir); this->AppendTarget(fout, "clean", make, makeArgs, homeOutputDir, homeOutputDir); // add all executable and library targets and some of the GLOBAL // and UTILITY targets for (std::vector::const_iterator it = this->GlobalGenerator->GetLocalGenerators().begin(); it != this->GlobalGenerator->GetLocalGenerators().end(); ++it) { const cmTargets& targets = (*it)->GetMakefile()->GetTargets(); cmMakefile* makefile=(*it)->GetMakefile(); std::string currentDir = makefile->GetCurrentBinaryDirectory(); bool topLevel = (currentDir == makefile->GetHomeOutputDirectory()); for(cmTargets::const_iterator ti=targets.begin(); ti!=targets.end(); ++ti) { switch(ti->second.GetType()) { case cmTarget::GLOBAL_TARGET: { bool insertTarget = false; // Only add the global targets from CMAKE_BINARY_DIR, // not from the subdirs if (topLevel) { insertTarget = true; // only add the "edit_cache" target if it's not ccmake, because // this will not work within the IDE if (ti->first == "edit_cache") { const char* editCommand = makefile->GetDefinition ("CMAKE_EDIT_COMMAND"); if (editCommand == 0) { insertTarget = false; } else if (strstr(editCommand, "ccmake")!=NULL) { insertTarget = false; } } } if (insertTarget) { this->AppendTarget(fout, ti->first, make, makeArgs, currentDir, homeOutputDir); } } break; case cmTarget::UTILITY: // Add all utility targets, except the Nightly/Continuous/ // Experimental-"sub"targets as e.g. NightlyStart if (((ti->first.find("Nightly")==0) &&(ti->first!="Nightly")) || ((ti->first.find("Continuous")==0)&&(ti->first!="Continuous")) || ((ti->first.find("Experimental")==0) && (ti->first!="Experimental"))) { break; } this->AppendTarget(fout, ti->first, make, makeArgs, currentDir, homeOutputDir); break; case cmTarget::EXECUTABLE: case cmTarget::STATIC_LIBRARY: case cmTarget::SHARED_LIBRARY: case cmTarget::MODULE_LIBRARY: case cmTarget::OBJECT_LIBRARY: { this->AppendTarget(fout, ti->first, make, makeArgs, currentDir, homeOutputDir); std::string fastTarget = ti->first; fastTarget += "/fast"; this->AppendTarget(fout, fastTarget, make, makeArgs, currentDir, homeOutputDir); } break; default: break; } } //insert rules for compiling, preprocessing and assembling individual files std::vector objectFileTargets; (*it)->GetIndividualFileTargets(objectFileTargets); for(std::vector::const_iterator fit=objectFileTargets.begin(); fit != objectFileTargets.end(); ++fit) { this->AppendTarget(fout, *fit, make, makeArgs, currentDir,homeOutputDir); } } fout << "\t] }\n"; } void cmExtraKateGenerator::AppendTarget(cmGeneratedFileStream& fout, const std::string& target, const std::string& make, const std::string& makeArgs, const std::string& path, const char* homeOutputDir ) const { static char JsonSep = ' '; fout << "\t\t\t" << JsonSep << "{\"name\":\"" << target << "\", " "\"build_cmd\":\"" << make << " -C \\\"" << (this->UseNinja ? homeOutputDir : path.c_str()) << "\\\" " << makeArgs << " " << target << "\"}\n"; JsonSep = ','; } void cmExtraKateGenerator::CreateDummyKateProjectFile(const cmMakefile* mf) const { std::string filename = mf->GetHomeOutputDirectory(); filename += "/"; filename += this->ProjectName; filename += ".kateproject"; cmGeneratedFileStream fout(filename.c_str()); if (!fout) { return; } fout << "#Generated by " << cmSystemTools::GetCMakeCommand() << ", do not edit.\n"; } std::string cmExtraKateGenerator::GenerateFilesString(const cmMakefile* mf) const { std::string s = mf->GetHomeDirectory(); s += "/.git"; if(cmSystemTools::FileExists(s.c_str())) { return std::string("\"git\": 1 "); } s = mf->GetHomeDirectory(); s += "/.svn"; if(cmSystemTools::FileExists(s.c_str())) { return std::string("\"svn\": 1 "); } s = mf->GetHomeDirectory(); s += "/"; std::set files; std::string tmp; const std::vector& lgs = this->GlobalGenerator->GetLocalGenerators(); for (std::vector::const_iterator it=lgs.begin(); it!=lgs.end(); it++) { cmMakefile* makefile=(*it)->GetMakefile(); const std::vector& listFiles=makefile->GetListFiles(); for (std::vector::const_iterator lt=listFiles.begin(); lt!=listFiles.end(); lt++) { tmp=*lt; { files.insert(tmp); } } const std::vector& sources = makefile->GetSourceFiles(); for (std::vector::const_iterator sfIt = sources.begin(); sfIt != sources.end(); sfIt++) { cmSourceFile* sf = *sfIt; if (sf->GetPropertyAsBool("GENERATED")) { continue; } tmp = sf->GetFullPath(); files.insert(tmp); } } const char* sep = ""; tmp = "\"list\": ["; for(std::set::const_iterator it = files.begin(); it != files.end(); ++it) { tmp += sep; tmp += " \""; tmp += *it; tmp += "\""; sep = ","; } tmp += "] "; return tmp; } std::string cmExtraKateGenerator::GenerateProjectName(const std::string& name, const std::string& type, const std::string& path) const { return name + (type.empty() ? "" : "-") + type + "@" + path; } std::string cmExtraKateGenerator::GetPathBasename(const std::string& path)const { std::string outputBasename = path; while (!outputBasename.empty() && (outputBasename[outputBasename.size() - 1] == '/' || outputBasename[outputBasename.size() - 1] == '\\')) { outputBasename.resize(outputBasename.size() - 1); } std::string::size_type loc = outputBasename.find_last_of("/\\"); if (loc != std::string::npos) { outputBasename = outputBasename.substr(loc + 1); } return outputBasename; }