|
|
|
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
|
|
file Copyright.txt or https://cmake.org/licensing for details. */
|
|
|
|
#include "cmExtraKateGenerator.h"
|
|
|
|
|
|
|
|
#include "cmGeneratedFileStream.h"
|
|
|
|
#include "cmGeneratorTarget.h"
|
|
|
|
#include "cmGlobalGenerator.h"
|
|
|
|
#include "cmLocalGenerator.h"
|
|
|
|
#include "cmMakefile.h"
|
|
|
|
#include "cmSourceFile.h"
|
|
|
|
#include "cmState.h"
|
|
|
|
#include "cmSystemTools.h"
|
|
|
|
|
|
|
|
#include <ostream>
|
|
|
|
#include <set>
|
|
|
|
#include <string.h>
|
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
cmExtraKateGenerator::cmExtraKateGenerator()
|
|
|
|
: cmExternalMakefileProjectGenerator()
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
cmExternalMakefileProjectGeneratorFactory* cmExtraKateGenerator::GetFactory()
|
|
|
|
{
|
|
|
|
static cmExternalMakefileProjectGeneratorSimpleFactory<cmExtraKateGenerator>
|
|
|
|
factory("Kate", "Generates Kate project files.");
|
|
|
|
|
|
|
|
if (factory.GetSupportedGlobalGenerators().empty()) {
|
|
|
|
#if defined(_WIN32)
|
|
|
|
factory.AddSupportedGlobalGenerator("MinGW Makefiles");
|
|
|
|
factory.AddSupportedGlobalGenerator("NMake Makefiles");
|
|
|
|
// disable until somebody actually tests it:
|
|
|
|
// factory.AddSupportedGlobalGenerator("MSYS Makefiles");
|
|
|
|
#endif
|
|
|
|
factory.AddSupportedGlobalGenerator("Ninja");
|
|
|
|
factory.AddSupportedGlobalGenerator("Unix Makefiles");
|
|
|
|
}
|
|
|
|
|
|
|
|
return &factory;
|
|
|
|
}
|
|
|
|
|
|
|
|
void cmExtraKateGenerator::Generate()
|
|
|
|
{
|
|
|
|
cmLocalGenerator* lg = this->GlobalGenerator->GetLocalGenerators()[0];
|
|
|
|
const cmMakefile* mf = lg->GetMakefile();
|
|
|
|
this->ProjectName = this->GenerateProjectName(
|
|
|
|
lg->GetProjectName(), mf->GetSafeDefinition("CMAKE_BUILD_TYPE"),
|
|
|
|
this->GetPathBasename(lg->GetBinaryDirectory()));
|
|
|
|
this->UseNinja = (this->GlobalGenerator->GetName() == "Ninja");
|
|
|
|
|
|
|
|
this->CreateKateProjectFile(lg);
|
|
|
|
this->CreateDummyKateProjectFile(lg);
|
|
|
|
}
|
|
|
|
|
|
|
|
void cmExtraKateGenerator::CreateKateProjectFile(
|
|
|
|
const cmLocalGenerator* lg) const
|
|
|
|
{
|
|
|
|
std::string filename = lg->GetBinaryDirectory();
|
|
|
|
filename += "/.kateproject";
|
|
|
|
cmGeneratedFileStream fout(filename.c_str());
|
|
|
|
if (!fout) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* clang-format off */
|
|
|
|
fout <<
|
|
|
|
"{\n"
|
|
|
|
"\t\"name\": \"" << this->ProjectName << "\",\n"
|
|
|
|
"\t\"directory\": \"" << lg->GetSourceDirectory() << "\",\n"
|
|
|
|
"\t\"files\": [ { " << this->GenerateFilesString(lg) << "} ],\n";
|
|
|
|
/* clang-format on */
|
|
|
|
this->WriteTargets(lg, fout);
|
|
|
|
fout << "}\n";
|
|
|
|
}
|
|
|
|
|
|
|
|
void cmExtraKateGenerator::WriteTargets(const cmLocalGenerator* lg,
|
|
|
|
cmGeneratedFileStream& fout) const
|
|
|
|
{
|
|
|
|
cmMakefile const* mf = lg->GetMakefile();
|
|
|
|
const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
|
|
|
|
const std::string makeArgs =
|
|
|
|
mf->GetSafeDefinition("CMAKE_KATE_MAKE_ARGUMENTS");
|
|
|
|
const char* homeOutputDir = lg->GetBinaryDirectory();
|
|
|
|
|
|
|
|
/* clang-format off */
|
|
|
|
fout <<
|
|
|
|
"\t\"build\": {\n"
|
|
|
|
"\t\t\"directory\": \"" << lg->GetBinaryDirectory() << "\",\n"
|
|
|
|
"\t\t\"default_target\": \"all\",\n"
|
|
|
|
"\t\t\"clean_target\": \"clean\",\n";
|
|
|
|
/* clang-format on */
|
|
|
|
|
|
|
|
// 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<cmLocalGenerator*>::const_iterator it =
|
|
|
|
this->GlobalGenerator->GetLocalGenerators().begin();
|
|
|
|
it != this->GlobalGenerator->GetLocalGenerators().end(); ++it) {
|
|
|
|
const std::vector<cmGeneratorTarget*> targets =
|
|
|
|
(*it)->GetGeneratorTargets();
|
|
|
|
std::string currentDir = (*it)->GetCurrentBinaryDirectory();
|
|
|
|
bool topLevel = (currentDir == (*it)->GetBinaryDirectory());
|
|
|
|
|
|
|
|
for (std::vector<cmGeneratorTarget*>::const_iterator ti = targets.begin();
|
|
|
|
ti != targets.end(); ++ti) {
|
|
|
|
std::string targetName = (*ti)->GetName();
|
|
|
|
switch ((*ti)->GetType()) {
|
|
|
|
case cmState::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 (targetName == "edit_cache") {
|
|
|
|
const char* editCommand =
|
|
|
|
(*it)->GetMakefile()->GetDefinition("CMAKE_EDIT_COMMAND");
|
|
|
|
if (editCommand == CM_NULLPTR) {
|
|
|
|
insertTarget = false;
|
|
|
|
} else if (strstr(editCommand, "ccmake") != CM_NULLPTR) {
|
|
|
|
insertTarget = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if (insertTarget) {
|
|
|
|
this->AppendTarget(fout, targetName, make, makeArgs, currentDir,
|
|
|
|
homeOutputDir);
|
|
|
|
}
|
|
|
|
} break;
|
|
|
|
case cmState::UTILITY:
|
|
|
|
// Add all utility targets, except the Nightly/Continuous/
|
|
|
|
// Experimental-"sub"targets as e.g. NightlyStart
|
|
|
|
if (((targetName.find("Nightly") == 0) &&
|
|
|
|
(targetName != "Nightly")) ||
|
|
|
|
((targetName.find("Continuous") == 0) &&
|
|
|
|
(targetName != "Continuous")) ||
|
|
|
|
((targetName.find("Experimental") == 0) &&
|
|
|
|
(targetName != "Experimental"))) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
this->AppendTarget(fout, targetName, make, makeArgs, currentDir,
|
|
|
|
homeOutputDir);
|
|
|
|
break;
|
|
|
|
case cmState::EXECUTABLE:
|
|
|
|
case cmState::STATIC_LIBRARY:
|
|
|
|
case cmState::SHARED_LIBRARY:
|
|
|
|
case cmState::MODULE_LIBRARY:
|
|
|
|
case cmState::OBJECT_LIBRARY: {
|
|
|
|
this->AppendTarget(fout, targetName, make, makeArgs, currentDir,
|
|
|
|
homeOutputDir);
|
|
|
|
std::string fastTarget = targetName;
|
|
|
|
fastTarget += "/fast";
|
|
|
|
this->AppendTarget(fout, fastTarget, make, makeArgs, currentDir,
|
|
|
|
homeOutputDir);
|
|
|
|
|
|
|
|
} break;
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// insert rules for compiling, preprocessing and assembling individual
|
|
|
|
// files
|
|
|
|
std::vector<std::string> objectFileTargets;
|
|
|
|
(*it)->GetIndividualFileTargets(objectFileTargets);
|
|
|
|
for (std::vector<std::string>::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 cmLocalGenerator* lg) const
|
|
|
|
{
|
|
|
|
std::string filename = lg->GetBinaryDirectory();
|
|
|
|
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 cmLocalGenerator* lg) const
|
|
|
|
{
|
|
|
|
std::string s = lg->GetSourceDirectory();
|
|
|
|
s += "/.git";
|
|
|
|
if (cmSystemTools::FileExists(s.c_str())) {
|
|
|
|
return std::string("\"git\": 1 ");
|
|
|
|
}
|
|
|
|
|
|
|
|
s = lg->GetSourceDirectory();
|
|
|
|
s += "/.svn";
|
|
|
|
if (cmSystemTools::FileExists(s.c_str())) {
|
|
|
|
return std::string("\"svn\": 1 ");
|
|
|
|
}
|
|
|
|
|
|
|
|
s = lg->GetSourceDirectory();
|
|
|
|
s += "/";
|
|
|
|
|
|
|
|
std::set<std::string> files;
|
|
|
|
std::string tmp;
|
|
|
|
const std::vector<cmLocalGenerator*>& lgs =
|
|
|
|
this->GlobalGenerator->GetLocalGenerators();
|
|
|
|
|
|
|
|
for (std::vector<cmLocalGenerator*>::const_iterator it = lgs.begin();
|
|
|
|
it != lgs.end(); it++) {
|
|
|
|
cmMakefile* makefile = (*it)->GetMakefile();
|
|
|
|
const std::vector<std::string>& listFiles = makefile->GetListFiles();
|
|
|
|
for (std::vector<std::string>::const_iterator lt = listFiles.begin();
|
|
|
|
lt != listFiles.end(); lt++) {
|
|
|
|
tmp = *lt;
|
|
|
|
{
|
|
|
|
files.insert(tmp);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
const std::vector<cmSourceFile*>& sources = makefile->GetSourceFiles();
|
|
|
|
for (std::vector<cmSourceFile*>::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<std::string>::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;
|
|
|
|
}
|