mirror of
https://github.com/Kitware/CMake.git
synced 2026-01-01 19:30:13 -06:00
Not just short directory roots. The test suites did an improper generator check and masked them as the generator masks were put in place after the core development but before the autogen-specific logic tests were created.
1214 lines
43 KiB
C++
1214 lines
43 KiB
C++
/* Distributed under the OSI-approved BSD 3-Clause License. See accompanying
|
|
file LICENSE.rst or https://cmake.org/licensing for details. */
|
|
#include "cmExtraEclipseCDT4Generator.h"
|
|
|
|
#include <algorithm>
|
|
#include <cassert>
|
|
#include <cstdio>
|
|
#include <map>
|
|
#include <memory>
|
|
#include <sstream>
|
|
#include <utility>
|
|
|
|
#include "cmsys/RegularExpression.hxx"
|
|
|
|
#include "cmGeneratedFileStream.h"
|
|
#include "cmGeneratorExpression.h"
|
|
#include "cmGeneratorTarget.h"
|
|
#include "cmGlobalGenerator.h"
|
|
#include "cmList.h"
|
|
#include "cmLocalGenerator.h"
|
|
#include "cmMakefile.h"
|
|
#include "cmMessageType.h"
|
|
#include "cmSourceFile.h"
|
|
#include "cmSourceGroup.h"
|
|
#include "cmState.h"
|
|
#include "cmStateTypes.h"
|
|
#include "cmStringAlgorithms.h"
|
|
#include "cmSystemTools.h"
|
|
#include "cmValue.h"
|
|
#include "cmXMLWriter.h"
|
|
#include "cmake.h"
|
|
|
|
static void AppendAttribute(cmXMLWriter& xml, char const* keyval)
|
|
{
|
|
xml.StartElement("attribute");
|
|
xml.Attribute("key", keyval);
|
|
xml.Attribute("value", keyval);
|
|
xml.EndElement();
|
|
}
|
|
|
|
template <typename T>
|
|
void AppendDictionary(cmXMLWriter& xml, char const* key, T const& value)
|
|
{
|
|
xml.StartElement("dictionary");
|
|
xml.Element("key", key);
|
|
xml.Element("value", value);
|
|
xml.EndElement();
|
|
}
|
|
|
|
cmExtraEclipseCDT4Generator::cmExtraEclipseCDT4Generator()
|
|
{
|
|
this->IsOutOfSourceBuild = false;
|
|
this->GenerateSourceProject = false;
|
|
this->SupportsVirtualFolders = true;
|
|
this->GenerateLinkedResources = true;
|
|
this->SupportsGmakeErrorParser = true;
|
|
this->SupportsMachO64Parser = true;
|
|
this->CEnabled = false;
|
|
this->CXXEnabled = false;
|
|
}
|
|
|
|
cmExternalMakefileProjectGeneratorFactory*
|
|
cmExtraEclipseCDT4Generator::GetFactory()
|
|
{
|
|
static cmExternalMakefileProjectGeneratorSimpleFactory<
|
|
cmExtraEclipseCDT4Generator>
|
|
factory("Eclipse CDT4",
|
|
"Generates Eclipse CDT 4.0 project files (deprecated).");
|
|
|
|
if (factory.GetSupportedGlobalGenerators().empty()) {
|
|
// TODO: Verify if __CYGWIN__ should be checked.
|
|
// #if defined(_WIN32) && !defined(__CYGWIN__)
|
|
#if defined(_WIN32)
|
|
factory.AddSupportedGlobalGenerator("NMake Makefiles");
|
|
factory.AddSupportedGlobalGenerator("MinGW Makefiles");
|
|
// factory.AddSupportedGlobalGenerator("MSYS Makefiles");
|
|
#endif
|
|
factory.AddSupportedGlobalGenerator("Ninja");
|
|
factory.AddSupportedGlobalGenerator("Unix Makefiles");
|
|
}
|
|
|
|
return &factory;
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::EnableLanguage(
|
|
std::vector<std::string> const& languages, cmMakefile* /*unused*/,
|
|
bool /*optional*/)
|
|
{
|
|
for (std::string const& l : languages) {
|
|
if (l == "CXX") {
|
|
this->Natures.insert("org.eclipse.cdt.core.ccnature");
|
|
this->Natures.insert("org.eclipse.cdt.core.cnature");
|
|
this->CXXEnabled = true;
|
|
} else if (l == "C") {
|
|
this->Natures.insert("org.eclipse.cdt.core.cnature");
|
|
this->CEnabled = true;
|
|
} else if (l == "Java") {
|
|
this->Natures.insert("org.eclipse.jdt.core.javanature");
|
|
}
|
|
}
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::Generate()
|
|
{
|
|
auto const& lg = this->GlobalGenerator->GetLocalGenerators()[0];
|
|
cmMakefile const* mf = lg->GetMakefile();
|
|
|
|
std::string eclipseVersion = mf->GetSafeDefinition("CMAKE_ECLIPSE_VERSION");
|
|
cmsys::RegularExpression regex(".*([0-9]+\\.[0-9]+).*");
|
|
if (regex.find(eclipseVersion)) {
|
|
unsigned int majorVersion = 0;
|
|
unsigned int minorVersion = 0;
|
|
int res =
|
|
sscanf(regex.match(1).c_str(), "%u.%u", &majorVersion, &minorVersion);
|
|
if (res == 2) {
|
|
int version = majorVersion * 1000 + minorVersion;
|
|
if (version < 3006) // 3.6 is Helios
|
|
{
|
|
this->SupportsVirtualFolders = false;
|
|
this->SupportsMachO64Parser = false;
|
|
}
|
|
if (version < 3007) // 3.7 is Indigo
|
|
{
|
|
this->SupportsGmakeErrorParser = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// TODO: Decide if these are local or member variables
|
|
this->HomeDirectory = lg->GetSourceDirectory();
|
|
this->HomeOutputDirectory = lg->GetBinaryDirectory();
|
|
|
|
this->GenerateLinkedResources =
|
|
mf->IsOn("CMAKE_ECLIPSE_GENERATE_LINKED_RESOURCES");
|
|
|
|
this->IsOutOfSourceBuild =
|
|
(this->HomeDirectory != this->HomeOutputDirectory);
|
|
|
|
this->GenerateSourceProject =
|
|
(this->IsOutOfSourceBuild &&
|
|
mf->IsOn("CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT"));
|
|
|
|
if (!this->GenerateSourceProject &&
|
|
(mf->IsOn("ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT"))) {
|
|
mf->IssueMessage(
|
|
MessageType::WARNING,
|
|
"ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT is set to TRUE, "
|
|
"but this variable is not supported anymore since CMake 2.8.7.\n"
|
|
"Enable CMAKE_ECLIPSE_GENERATE_SOURCE_PROJECT instead.");
|
|
}
|
|
|
|
if (cmSystemTools::IsSubDirectory(this->HomeOutputDirectory,
|
|
this->HomeDirectory)) {
|
|
mf->IssueMessage(MessageType::WARNING,
|
|
"The build directory is a subdirectory "
|
|
"of the source directory.\n"
|
|
"This is not supported well by Eclipse. It is strongly "
|
|
"recommended to use a build directory which is a "
|
|
"sibling of the source directory.");
|
|
}
|
|
|
|
// NOTE: This is not good, since it pollutes the source tree. However,
|
|
// Eclipse doesn't allow CVS/SVN to work when the .project is not in
|
|
// the cvs/svn root directory. Hence, this is provided as an option.
|
|
if (this->GenerateSourceProject) {
|
|
// create .project file in the source tree
|
|
this->CreateSourceProjectFile();
|
|
}
|
|
|
|
// create a .project file
|
|
this->CreateProjectFile();
|
|
|
|
// create a .cproject file
|
|
this->CreateCProjectFile();
|
|
|
|
// create resource settings
|
|
this->CreateSettingsResourcePrefsFile();
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::CreateSettingsResourcePrefsFile()
|
|
{
|
|
auto const& lg = this->GlobalGenerator->GetLocalGenerators()[0];
|
|
cmMakefile* mf = lg->GetMakefile();
|
|
|
|
std::string const filename =
|
|
this->HomeOutputDirectory + "/.settings/org.eclipse.core.resources.prefs";
|
|
|
|
cmGeneratedFileStream fout(filename);
|
|
if (!fout) {
|
|
return;
|
|
}
|
|
|
|
fout << "eclipse.preferences.version=1\n";
|
|
cmValue encoding = mf->GetDefinition("CMAKE_ECLIPSE_RESOURCE_ENCODING");
|
|
if (encoding) {
|
|
fout << "encoding/<project>=" << *encoding << '\n';
|
|
}
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::CreateSourceProjectFile()
|
|
{
|
|
assert(this->HomeDirectory != this->HomeOutputDirectory);
|
|
|
|
// set up the project name: <project>-Source@<baseSourcePathName>
|
|
auto const& lg = this->GlobalGenerator->GetLocalGenerators()[0];
|
|
std::string name = cmExtraEclipseCDT4Generator::GenerateProjectName(
|
|
lg->GetProjectName(), "Source",
|
|
cmExtraEclipseCDT4Generator::GetPathBasename(this->HomeDirectory));
|
|
|
|
std::string const filename = this->HomeDirectory + "/.project";
|
|
cmGeneratedFileStream fout(filename);
|
|
if (!fout) {
|
|
return;
|
|
}
|
|
|
|
cmXMLWriter xml(fout);
|
|
xml.StartDocument("UTF-8");
|
|
xml.StartElement("projectDescription");
|
|
xml.Element("name", name);
|
|
xml.Element("comment", "");
|
|
xml.Element("projects", "");
|
|
xml.Element("buildSpec", "");
|
|
xml.Element("natures", "");
|
|
xml.StartElement("linkedResources");
|
|
|
|
if (this->SupportsVirtualFolders) {
|
|
this->CreateLinksToSubprojects(xml, this->HomeDirectory);
|
|
this->SrcLinkedResources.clear();
|
|
}
|
|
|
|
xml.EndElement(); // linkedResources
|
|
xml.EndElement(); // projectDescription
|
|
xml.EndDocument();
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::AddEnvVar(std::ostream& out,
|
|
char const* envVar,
|
|
cmLocalGenerator& lg)
|
|
{
|
|
cmMakefile* mf = lg.GetMakefile();
|
|
|
|
// get the variables from the environment and from the cache and then
|
|
// figure out which one to use:
|
|
|
|
std::string envVarValue;
|
|
bool const envVarSet = cmSystemTools::GetEnv(envVar, envVarValue);
|
|
|
|
std::string cacheEntryName = cmStrCat("CMAKE_ECLIPSE_ENVVAR_", envVar);
|
|
cmValue cacheValue = lg.GetState()->GetInitializedCacheValue(cacheEntryName);
|
|
|
|
// now we have both, decide which one to use
|
|
std::string valueToUse;
|
|
if (!envVarSet && !cacheValue) {
|
|
// nothing known, do nothing
|
|
valueToUse.clear();
|
|
} else if (envVarSet && !cacheValue) {
|
|
// The variable is in the env, but not in the cache. Use it and put it
|
|
// in the cache
|
|
valueToUse = envVarValue;
|
|
mf->AddCacheDefinition(cacheEntryName, valueToUse, cacheEntryName,
|
|
cmStateEnums::STRING, true);
|
|
mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory());
|
|
} else if (!envVarSet && cacheValue) {
|
|
// It is already in the cache, but not in the env, so use it from the cache
|
|
valueToUse = *cacheValue;
|
|
} else {
|
|
// It is both in the cache and in the env.
|
|
// Use the version from the env. except if the value from the env is
|
|
// completely contained in the value from the cache (for the case that we
|
|
// now have a PATH without MSVC dirs in the env. but had the full PATH with
|
|
// all MSVC dirs during the cmake run which stored the var in the cache:
|
|
valueToUse = *cacheValue;
|
|
if (valueToUse.find(envVarValue) == std::string::npos) {
|
|
valueToUse = envVarValue;
|
|
mf->AddCacheDefinition(cacheEntryName, valueToUse, cacheEntryName,
|
|
cmStateEnums::STRING, true);
|
|
mf->GetCMakeInstance()->SaveCache(lg.GetBinaryDirectory());
|
|
}
|
|
}
|
|
|
|
if (!valueToUse.empty()) {
|
|
out << envVar << "=" << valueToUse << "|";
|
|
}
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::CreateProjectFile()
|
|
{
|
|
auto const& lg = this->GlobalGenerator->GetLocalGenerators()[0];
|
|
cmMakefile* mf = lg->GetMakefile();
|
|
|
|
std::string const filename = this->HomeOutputDirectory + "/.project";
|
|
|
|
cmGeneratedFileStream fout(filename);
|
|
if (!fout) {
|
|
return;
|
|
}
|
|
|
|
std::string compilerId = mf->GetSafeDefinition("CMAKE_C_COMPILER_ID");
|
|
if (compilerId.empty()) // no C compiler, try the C++ compiler:
|
|
{
|
|
compilerId = mf->GetSafeDefinition("CMAKE_CXX_COMPILER_ID");
|
|
}
|
|
|
|
cmXMLWriter xml(fout);
|
|
|
|
xml.StartDocument("UTF-8");
|
|
xml.StartElement("projectDescription");
|
|
|
|
xml.Element("name",
|
|
cmExtraEclipseCDT4Generator::GenerateProjectName(
|
|
lg->GetProjectName(),
|
|
mf->GetSafeDefinition("CMAKE_BUILD_TYPE"),
|
|
cmExtraEclipseCDT4Generator::GetPathBasename(
|
|
this->HomeOutputDirectory)));
|
|
|
|
xml.Element("comment", "");
|
|
xml.Element("projects", "");
|
|
|
|
xml.StartElement("buildSpec");
|
|
xml.StartElement("buildCommand");
|
|
xml.Element("name", "org.eclipse.cdt.make.core.makeBuilder");
|
|
xml.Element("triggers", "clean,full,incremental,");
|
|
xml.StartElement("arguments");
|
|
|
|
// use clean target
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.cleanBuildTarget", "clean");
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.enableCleanBuild", "true");
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.append_environment",
|
|
"true");
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.stopOnError", "true");
|
|
|
|
// set the make command
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.enabledIncrementalBuild",
|
|
"true");
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.build.command",
|
|
cmExtraEclipseCDT4Generator::GetEclipsePath(
|
|
mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM")));
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.contents",
|
|
"org.eclipse.cdt.make.core.activeConfigSettings");
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.build.target.inc", "all");
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.build.arguments",
|
|
mf->GetSafeDefinition("CMAKE_ECLIPSE_MAKE_ARGUMENTS"));
|
|
AppendDictionary(
|
|
xml, "org.eclipse.cdt.make.core.buildLocation",
|
|
cmExtraEclipseCDT4Generator::GetEclipsePath(this->HomeOutputDirectory));
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.useDefaultBuildCmd",
|
|
"false");
|
|
|
|
// set project specific environment
|
|
std::ostringstream environment;
|
|
environment << "VERBOSE=1|CMAKE_NO_VERBOSE=1|"; // verbose Makefile output
|
|
// set vsvars32.bat environment available at CMake time,
|
|
// but not necessarily when eclipse is open
|
|
if (compilerId == "MSVC") {
|
|
AddEnvVar(environment, "PATH", *lg);
|
|
AddEnvVar(environment, "INCLUDE", *lg);
|
|
AddEnvVar(environment, "LIB", *lg);
|
|
AddEnvVar(environment, "LIBPATH", *lg);
|
|
} else if (compilerId == "Intel") {
|
|
// if the env.var is set, use this one and put it in the cache
|
|
// if the env.var is not set, but the value is in the cache,
|
|
// use it from the cache:
|
|
AddEnvVar(environment, "INTEL_LICENSE_FILE", *lg);
|
|
}
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.environment",
|
|
environment.str());
|
|
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.enableFullBuild", "true");
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.build.target.auto", "all");
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.enableAutoBuild", "false");
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.build.target.clean",
|
|
"clean");
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.fullBuildTarget", "all");
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.buildArguments", "");
|
|
AppendDictionary(
|
|
xml, "org.eclipse.cdt.make.core.build.location",
|
|
cmExtraEclipseCDT4Generator::GetEclipsePath(this->HomeOutputDirectory));
|
|
AppendDictionary(xml, "org.eclipse.cdt.make.core.autoBuildTarget", "all");
|
|
|
|
// set error parsers
|
|
std::ostringstream errorOutputParser;
|
|
|
|
if (compilerId == "MSVC") {
|
|
errorOutputParser << "org.eclipse.cdt.core.VCErrorParser;";
|
|
} else if (compilerId == "Intel") {
|
|
errorOutputParser << "org.eclipse.cdt.core.ICCErrorParser;";
|
|
}
|
|
|
|
if (this->SupportsGmakeErrorParser) {
|
|
errorOutputParser << "org.eclipse.cdt.core.GmakeErrorParser;";
|
|
} else {
|
|
errorOutputParser << "org.eclipse.cdt.core.MakeErrorParser;";
|
|
}
|
|
|
|
errorOutputParser << "org.eclipse.cdt.core.GCCErrorParser;"
|
|
"org.eclipse.cdt.core.GASErrorParser;"
|
|
"org.eclipse.cdt.core.GLDErrorParser;";
|
|
AppendDictionary(xml, "org.eclipse.cdt.core.errorOutputParser",
|
|
errorOutputParser.str());
|
|
|
|
xml.EndElement(); // arguments
|
|
xml.EndElement(); // buildCommand
|
|
xml.StartElement("buildCommand");
|
|
xml.Element("name", "org.eclipse.cdt.make.core.ScannerConfigBuilder");
|
|
xml.StartElement("arguments");
|
|
xml.EndElement(); // arguments
|
|
xml.EndElement(); // buildCommand
|
|
xml.EndElement(); // buildSpec
|
|
|
|
// set natures for c/c++ projects
|
|
xml.StartElement("natures");
|
|
xml.Element("nature", "org.eclipse.cdt.make.core.makeNature");
|
|
xml.Element("nature", "org.eclipse.cdt.make.core.ScannerConfigNature");
|
|
|
|
for (std::string const& n : this->Natures) {
|
|
xml.Element("nature", n);
|
|
}
|
|
|
|
if (cmValue extraNaturesProp =
|
|
mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_NATURES")) {
|
|
cmList extraNatures{ *extraNaturesProp };
|
|
for (std::string const& n : extraNatures) {
|
|
xml.Element("nature", n);
|
|
}
|
|
}
|
|
|
|
xml.EndElement(); // natures
|
|
|
|
xml.StartElement("linkedResources");
|
|
// create linked resources
|
|
if (this->IsOutOfSourceBuild) {
|
|
// create a linked resource to CMAKE_SOURCE_DIR
|
|
// (this is not done anymore for each project because of
|
|
// https://gitlab.kitware.com/cmake/cmake/-/issues/9978 and because I found
|
|
// it actually quite confusing in bigger projects with many directories and
|
|
// projects, Alex
|
|
|
|
std::string sourceLinkedResourceName = "[Source directory]";
|
|
std::string linkSourceDirectory =
|
|
cmExtraEclipseCDT4Generator::GetEclipsePath(
|
|
lg->GetCurrentSourceDirectory());
|
|
// .project dir can't be subdir of a linked resource dir
|
|
if (!cmSystemTools::IsSubDirectory(this->HomeOutputDirectory,
|
|
linkSourceDirectory)) {
|
|
cmExtraEclipseCDT4Generator::AppendLinkedResource(
|
|
xml, sourceLinkedResourceName,
|
|
cmExtraEclipseCDT4Generator::GetEclipsePath(linkSourceDirectory),
|
|
LinkToFolder);
|
|
this->SrcLinkedResources.push_back(std::move(sourceLinkedResourceName));
|
|
}
|
|
}
|
|
|
|
if (this->SupportsVirtualFolders) {
|
|
this->CreateLinksToSubprojects(xml, this->HomeOutputDirectory);
|
|
|
|
this->CreateLinksForTargets(xml);
|
|
}
|
|
|
|
xml.EndElement(); // linkedResources
|
|
xml.EndElement(); // projectDescription
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::WriteGroups(
|
|
std::vector<cmSourceGroup> const& sourceGroups, std::string& linkName,
|
|
cmXMLWriter& xml)
|
|
{
|
|
for (cmSourceGroup const& sg : sourceGroups) {
|
|
std::string linkName3 = cmStrCat(linkName, '/', sg.GetFullName());
|
|
|
|
std::replace(linkName3.begin(), linkName3.end(), '\\', '/');
|
|
|
|
cmExtraEclipseCDT4Generator::AppendLinkedResource(
|
|
xml, linkName3, "virtual:/virtual", VirtualFolder);
|
|
std::vector<cmSourceGroup> const& children = sg.GetGroupChildren();
|
|
if (!children.empty()) {
|
|
this->WriteGroups(children, linkName, xml);
|
|
}
|
|
std::vector<cmSourceFile const*> sFiles = sg.GetSourceFiles();
|
|
for (cmSourceFile const* file : sFiles) {
|
|
std::string const& fullPath = file->GetFullPath();
|
|
|
|
if (!cmSystemTools::FileIsDirectory(fullPath)) {
|
|
std::string linkName4 =
|
|
cmStrCat(linkName3, '/', cmSystemTools::GetFilenameName(fullPath));
|
|
cmExtraEclipseCDT4Generator::AppendLinkedResource(
|
|
xml, linkName4,
|
|
cmExtraEclipseCDT4Generator::GetEclipsePath(fullPath), LinkToFile);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::CreateLinksForTargets(cmXMLWriter& xml)
|
|
{
|
|
std::string linkName = "[Targets]";
|
|
cmExtraEclipseCDT4Generator::AppendLinkedResource(
|
|
xml, linkName, "virtual:/virtual", VirtualFolder);
|
|
|
|
for (auto const& lg : this->GlobalGenerator->GetLocalGenerators()) {
|
|
cmMakefile* makefile = lg->GetMakefile();
|
|
auto const& targets = lg->GetGeneratorTargets();
|
|
|
|
for (auto const& target : targets) {
|
|
std::string linkName2 = cmStrCat(linkName, '/');
|
|
switch (target->GetType()) {
|
|
case cmStateEnums::EXECUTABLE:
|
|
case cmStateEnums::STATIC_LIBRARY:
|
|
case cmStateEnums::SHARED_LIBRARY:
|
|
case cmStateEnums::MODULE_LIBRARY:
|
|
case cmStateEnums::OBJECT_LIBRARY: {
|
|
char const* prefix =
|
|
(target->GetType() == cmStateEnums::EXECUTABLE ? "[exe] "
|
|
: "[lib] ");
|
|
linkName2 += prefix;
|
|
linkName2 += target->GetName();
|
|
cmExtraEclipseCDT4Generator::AppendLinkedResource(
|
|
xml, linkName2, "virtual:/virtual", VirtualFolder);
|
|
if (!this->GenerateLinkedResources) {
|
|
break; // skip generating the linked resources to the source files
|
|
}
|
|
std::vector<cmSourceGroup> sourceGroups =
|
|
makefile->GetSourceGroups();
|
|
// get the files from the source lists then add them to the groups
|
|
std::vector<cmSourceFile*> files;
|
|
target->GetSourceFiles(
|
|
files, makefile->GetSafeDefinition("CMAKE_BUILD_TYPE"));
|
|
for (cmSourceFile* sf : files) {
|
|
// Add the file to the list of sources.
|
|
std::string const& source = sf->ResolveFullPath();
|
|
cmSourceGroup* sourceGroup =
|
|
makefile->FindSourceGroup(source, sourceGroups);
|
|
sourceGroup->AssignSource(sf);
|
|
}
|
|
|
|
this->WriteGroups(sourceGroups, linkName2, xml);
|
|
} break;
|
|
// ignore all others:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::CreateLinksToSubprojects(
|
|
cmXMLWriter& xml, std::string const& baseDir)
|
|
{
|
|
if (!this->GenerateLinkedResources) {
|
|
return;
|
|
}
|
|
|
|
// for each sub project create a linked resource to the source dir
|
|
// - only if it is an out-of-source build
|
|
cmExtraEclipseCDT4Generator::AppendLinkedResource(
|
|
xml, "[Subprojects]", "virtual:/virtual", VirtualFolder);
|
|
|
|
for (auto const& it : this->GlobalGenerator->GetProjectMap()) {
|
|
std::string linkSourceDirectory =
|
|
cmExtraEclipseCDT4Generator::GetEclipsePath(
|
|
it.second[0]->GetCurrentSourceDirectory());
|
|
// a linked resource must not point to a parent directory of .project or
|
|
// .project itself
|
|
if ((baseDir != linkSourceDirectory) &&
|
|
!cmSystemTools::IsSubDirectory(baseDir, linkSourceDirectory)) {
|
|
std::string linkName = cmStrCat("[Subprojects]/", it.first);
|
|
cmExtraEclipseCDT4Generator::AppendLinkedResource(
|
|
xml, linkName,
|
|
cmExtraEclipseCDT4Generator::GetEclipsePath(linkSourceDirectory),
|
|
LinkToFolder);
|
|
// Don't add it to the srcLinkedResources, because listing multiple
|
|
// directories confuses the Eclipse indexer (#13596).
|
|
}
|
|
}
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::AppendIncludeDirectories(
|
|
cmXMLWriter& xml, std::vector<std::string> const& includeDirs,
|
|
std::set<std::string>& emittedDirs)
|
|
{
|
|
for (std::string const& inc : includeDirs) {
|
|
if (!inc.empty()) {
|
|
std::string dir = cmSystemTools::CollapseFullPath(inc);
|
|
|
|
// handle framework include dirs on OSX, the remainder after the
|
|
// Frameworks/ part has to be stripped
|
|
// /System/Library/Frameworks/GLUT.framework/Headers
|
|
cmsys::RegularExpression frameworkRx("(.+/Frameworks)/.+\\.framework/");
|
|
if (frameworkRx.find(dir)) {
|
|
dir = frameworkRx.match(1);
|
|
}
|
|
|
|
if (emittedDirs.find(dir) == emittedDirs.end()) {
|
|
emittedDirs.insert(dir);
|
|
xml.StartElement("pathentry");
|
|
xml.Attribute("include",
|
|
cmExtraEclipseCDT4Generator::GetEclipsePath(dir));
|
|
xml.Attribute("kind", "inc");
|
|
xml.Attribute("path", "");
|
|
xml.Attribute("system", "true");
|
|
xml.EndElement();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
|
|
{
|
|
std::set<std::string> emitted;
|
|
|
|
auto const& lg = this->GlobalGenerator->GetLocalGenerators()[0];
|
|
cmMakefile const* mf = lg->GetMakefile();
|
|
|
|
std::string const filename = this->HomeOutputDirectory + "/.cproject";
|
|
|
|
cmGeneratedFileStream fout(filename);
|
|
if (!fout) {
|
|
return;
|
|
}
|
|
|
|
cmXMLWriter xml(fout);
|
|
|
|
// add header
|
|
xml.StartDocument("UTF-8");
|
|
xml.ProcessingInstruction("fileVersion", "4.0.0");
|
|
xml.StartElement("cproject");
|
|
xml.StartElement("storageModule");
|
|
xml.Attribute("moduleId", "org.eclipse.cdt.core.settings");
|
|
|
|
xml.StartElement("cconfiguration"); // noqa: spellcheck disable-line
|
|
xml.Attribute("id", "org.eclipse.cdt.core.default.config.1");
|
|
|
|
// Configuration settings...
|
|
xml.StartElement("storageModule");
|
|
xml.Attribute("buildSystemId",
|
|
"org.eclipse.cdt.core.defaultConfigDataProvider");
|
|
xml.Attribute("id", "org.eclipse.cdt.core.default.config.1");
|
|
xml.Attribute("moduleId", "org.eclipse.cdt.core.settings");
|
|
xml.Attribute("name", "Configuration");
|
|
xml.Element("externalSettings");
|
|
xml.StartElement("extensions");
|
|
|
|
// TODO: refactor this out...
|
|
std::string executableFormat =
|
|
mf->GetSafeDefinition("CMAKE_EXECUTABLE_FORMAT");
|
|
if (executableFormat == "ELF") {
|
|
xml.StartElement("extension");
|
|
xml.Attribute("id", "org.eclipse.cdt.core.ELF");
|
|
xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
|
|
xml.EndElement(); // extension
|
|
|
|
xml.StartElement("extension");
|
|
xml.Attribute("id", "org.eclipse.cdt.core.GNU_ELF");
|
|
xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
|
|
AppendAttribute(xml, "addr2line");
|
|
AppendAttribute(xml, "c++filt");
|
|
xml.EndElement(); // extension
|
|
} else {
|
|
std::string systemName = mf->GetSafeDefinition("CMAKE_SYSTEM_NAME");
|
|
if (systemName == "CYGWIN" || systemName == "MSYS") {
|
|
xml.StartElement("extension");
|
|
xml.Attribute("id", "org.eclipse.cdt.core.Cygwin_PE");
|
|
xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
|
|
AppendAttribute(xml, "addr2line");
|
|
AppendAttribute(xml, "c++filt");
|
|
AppendAttribute(xml, "cygpath");
|
|
AppendAttribute(xml, "nm");
|
|
xml.EndElement(); // extension
|
|
} else if (systemName == "Windows") {
|
|
xml.StartElement("extension");
|
|
xml.Attribute("id", "org.eclipse.cdt.core.PE");
|
|
xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
|
|
xml.EndElement(); // extension
|
|
} else if (systemName == "Darwin") {
|
|
xml.StartElement("extension");
|
|
xml.Attribute("id",
|
|
this->SupportsMachO64Parser
|
|
? "org.eclipse.cdt.core.MachO64"
|
|
: "org.eclipse.cdt.core.MachO");
|
|
xml.Attribute("point", "org.eclipse.cdt.core.BinaryParser");
|
|
AppendAttribute(xml, "c++filt");
|
|
xml.EndElement(); // extension
|
|
} else {
|
|
// *** Should never get here ***
|
|
xml.Element("error_toolchain_type");
|
|
}
|
|
}
|
|
|
|
xml.EndElement(); // extensions
|
|
xml.EndElement(); // storageModule
|
|
|
|
// ???
|
|
xml.StartElement("storageModule");
|
|
xml.Attribute("moduleId", "org.eclipse.cdt.core.language.mapping");
|
|
xml.Element("project-mappings");
|
|
xml.EndElement(); // storageModule
|
|
|
|
// ???
|
|
xml.StartElement("storageModule");
|
|
xml.Attribute("moduleId", "org.eclipse.cdt.core.externalSettings");
|
|
xml.EndElement(); // storageModule
|
|
|
|
// set the path entries (includes, libs, source dirs, etc.)
|
|
xml.StartElement("storageModule");
|
|
xml.Attribute("moduleId", "org.eclipse.cdt.core.pathentry");
|
|
|
|
// for each sub project with a linked resource to the source dir:
|
|
// - make it type 'src'
|
|
// - and exclude it from type 'out'
|
|
std::string excludeFromOut;
|
|
/* I don't know what the pathentry kind="src" are good for, e.g.
|
|
* autocompletion
|
|
* works also without them. Done wrong, the indexer complains, see #12417
|
|
* and #12213.
|
|
* According to #13596, this entry at least limits the directories the
|
|
* indexer is searching for files. So now the "src" entry contains only
|
|
* the linked resource to CMAKE_SOURCE_DIR.
|
|
* The CDT documentation is very terse on that:
|
|
* "CDT_SOURCE: Entry kind constant describing a path entry identifying a
|
|
* folder containing source code to be compiled."
|
|
* Also on the cdt-dev list didn't bring any information:
|
|
* http://web.archiveorange.com/archive/v/B4NlJDNIpYoOS1SbxFNy
|
|
* Alex */
|
|
// include subprojects directory to the src pathentry
|
|
// eclipse cdt indexer uses this entries as reference to index source files
|
|
if (this->GenerateLinkedResources) {
|
|
xml.StartElement("pathentry");
|
|
xml.Attribute("kind", "src");
|
|
xml.Attribute("path", "[Subprojects]");
|
|
xml.EndElement();
|
|
}
|
|
|
|
for (std::string const& p : this->SrcLinkedResources) {
|
|
xml.StartElement("pathentry");
|
|
xml.Attribute("kind", "src");
|
|
xml.Attribute("path", p);
|
|
xml.EndElement();
|
|
|
|
// exclude source directory from output search path
|
|
// - only if not named the same as an output directory
|
|
if (!cmSystemTools::FileIsDirectory(
|
|
cmStrCat(this->HomeOutputDirectory, '/', p))) {
|
|
excludeFromOut += p + "/|";
|
|
}
|
|
}
|
|
|
|
excludeFromOut += "**/CMakeFiles/";
|
|
|
|
xml.StartElement("pathentry");
|
|
xml.Attribute("excluding", excludeFromOut);
|
|
xml.Attribute("kind", "out");
|
|
xml.Attribute("path", "");
|
|
xml.EndElement();
|
|
|
|
// add pre-processor definitions to allow eclipse to gray out sections
|
|
emitted.clear();
|
|
for (auto const& lgen : this->GlobalGenerator->GetLocalGenerators()) {
|
|
|
|
if (cmValue cdefs =
|
|
lgen->GetMakefile()->GetProperty("COMPILE_DEFINITIONS")) {
|
|
// Expand the list.
|
|
std::vector<std::string> defs;
|
|
cmGeneratorExpression::Split(*cdefs, defs);
|
|
|
|
for (std::string const& d : defs) {
|
|
if (cmGeneratorExpression::Find(d) != std::string::npos) {
|
|
continue;
|
|
}
|
|
|
|
std::string::size_type equals = d.find('=', 0);
|
|
std::string::size_type enddef = d.length();
|
|
|
|
std::string def;
|
|
std::string val;
|
|
if (equals != std::string::npos && equals < enddef) {
|
|
// we have -DFOO=BAR
|
|
def = d.substr(0, equals);
|
|
val = d.substr(equals + 1, enddef - equals + 1);
|
|
} else {
|
|
// we have -DFOO
|
|
def = d;
|
|
}
|
|
|
|
// insert the definition if not already added.
|
|
if (emitted.find(def) == emitted.end()) {
|
|
emitted.insert(def);
|
|
xml.StartElement("pathentry");
|
|
xml.Attribute("kind", "mac");
|
|
xml.Attribute("name", def);
|
|
xml.Attribute("path", "");
|
|
xml.Attribute("value", val);
|
|
xml.EndElement();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// add system defined c macros
|
|
cmValue cDefs =
|
|
mf->GetDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_DEFINED_MACROS");
|
|
if (this->CEnabled && cDefs) {
|
|
// Expand the list.
|
|
cmList defs{ *cDefs, cmList::EmptyElements::Yes };
|
|
|
|
// the list must contain only definition-value pairs:
|
|
if ((defs.size() % 2) == 0) {
|
|
auto di = defs.begin();
|
|
while (di != defs.end()) {
|
|
std::string def = *di;
|
|
++di;
|
|
std::string val;
|
|
if (di != defs.end()) {
|
|
val = *di;
|
|
++di;
|
|
}
|
|
|
|
// insert the definition if not already added.
|
|
if (emitted.find(def) == emitted.end()) {
|
|
emitted.insert(def);
|
|
xml.StartElement("pathentry");
|
|
xml.Attribute("kind", "mac");
|
|
xml.Attribute("name", def);
|
|
xml.Attribute("path", "");
|
|
xml.Attribute("value", val);
|
|
xml.EndElement();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
// add system defined c++ macros
|
|
cmValue cxxDefs =
|
|
mf->GetDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_DEFINED_MACROS");
|
|
if (this->CXXEnabled && cxxDefs) {
|
|
// Expand the list.
|
|
cmList defs{ *cxxDefs, cmList::EmptyElements::Yes };
|
|
|
|
// the list must contain only definition-value pairs:
|
|
if ((defs.size() % 2) == 0) {
|
|
auto di = defs.begin();
|
|
while (di != defs.end()) {
|
|
std::string def = *di;
|
|
++di;
|
|
std::string val;
|
|
if (di != defs.end()) {
|
|
val = *di;
|
|
++di;
|
|
}
|
|
|
|
// insert the definition if not already added.
|
|
if (emitted.find(def) == emitted.end()) {
|
|
emitted.insert(def);
|
|
xml.StartElement("pathentry");
|
|
xml.Attribute("kind", "mac");
|
|
xml.Attribute("name", def);
|
|
xml.Attribute("path", "");
|
|
xml.Attribute("value", val);
|
|
xml.EndElement();
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// include dirs
|
|
emitted.clear();
|
|
for (auto const& lgen : this->GlobalGenerator->GetLocalGenerators()) {
|
|
auto const& targets = lgen->GetGeneratorTargets();
|
|
for (auto const& target : targets) {
|
|
if (target->GetType() == cmStateEnums::INTERFACE_LIBRARY) {
|
|
continue;
|
|
}
|
|
std::vector<std::string> includeDirs;
|
|
std::string config = mf->GetSafeDefinition("CMAKE_BUILD_TYPE");
|
|
lgen->GetIncludeDirectories(includeDirs, target.get(), "C", config);
|
|
this->AppendIncludeDirectories(xml, includeDirs, emitted);
|
|
}
|
|
}
|
|
// now also the system include directories, in case we found them in
|
|
// CMakeSystemSpecificInformation.cmake. This makes Eclipse find the
|
|
// standard headers.
|
|
std::string compiler = mf->GetSafeDefinition("CMAKE_C_COMPILER");
|
|
if (this->CEnabled && !compiler.empty()) {
|
|
std::string systemIncludeDirs =
|
|
mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_C_SYSTEM_INCLUDE_DIRS");
|
|
cmList dirs{ systemIncludeDirs };
|
|
this->AppendIncludeDirectories(xml, dirs, emitted);
|
|
}
|
|
compiler = mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
|
|
if (this->CXXEnabled && !compiler.empty()) {
|
|
std::string systemIncludeDirs =
|
|
mf->GetSafeDefinition("CMAKE_EXTRA_GENERATOR_CXX_SYSTEM_INCLUDE_DIRS");
|
|
cmList dirs{ systemIncludeDirs };
|
|
this->AppendIncludeDirectories(xml, dirs, emitted);
|
|
}
|
|
|
|
xml.EndElement(); // storageModule
|
|
|
|
// add build targets
|
|
xml.StartElement("storageModule");
|
|
xml.Attribute("moduleId", "org.eclipse.cdt.make.core.buildtargets");
|
|
xml.StartElement("buildTargets");
|
|
emitted.clear();
|
|
std::string const& make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
|
|
std::string const& makeArgs =
|
|
mf->GetSafeDefinition("CMAKE_ECLIPSE_MAKE_ARGUMENTS");
|
|
|
|
cmGlobalGenerator* generator =
|
|
const_cast<cmGlobalGenerator*>(this->GlobalGenerator);
|
|
|
|
std::string allTarget;
|
|
std::string cleanTarget;
|
|
if (generator->GetAllTargetName()) {
|
|
allTarget = generator->GetAllTargetName();
|
|
}
|
|
if (generator->GetCleanTargetName()) {
|
|
cleanTarget = generator->GetCleanTargetName();
|
|
}
|
|
|
|
// add all executable and library targets and some of the GLOBAL
|
|
// and UTILITY targets
|
|
for (auto const& lgen : this->GlobalGenerator->GetLocalGenerators()) {
|
|
auto const& targets = lgen->GetGeneratorTargets();
|
|
std::string subdir =
|
|
lgen->MaybeRelativeToTopBinDir(lgen->GetCurrentBinaryDirectory());
|
|
if (subdir == ".") {
|
|
subdir.clear();
|
|
}
|
|
|
|
for (auto const& target : targets) {
|
|
std::string targetName = target->GetName();
|
|
switch (target->GetType()) {
|
|
case cmStateEnums::GLOBAL_TARGET: {
|
|
// Only add the global targets from CMAKE_BINARY_DIR,
|
|
// not from the subdirs
|
|
if (subdir.empty()) {
|
|
cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make,
|
|
makeArgs, subdir, ": ");
|
|
}
|
|
} break;
|
|
case cmStateEnums::UTILITY:
|
|
// Add all utility targets, except the Nightly/Continuous/
|
|
// Experimental-"sub"targets as e.g. NightlyStart
|
|
if ((cmHasLiteralPrefix(targetName, "Nightly") &&
|
|
(targetName != "Nightly")) ||
|
|
(cmHasLiteralPrefix(targetName, "Continuous") &&
|
|
(targetName != "Continuous")) ||
|
|
(cmHasLiteralPrefix(targetName, "Experimental") &&
|
|
(targetName != "Experimental"))) {
|
|
break;
|
|
}
|
|
|
|
cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make,
|
|
makeArgs, subdir, ": ");
|
|
break;
|
|
case cmStateEnums::EXECUTABLE:
|
|
case cmStateEnums::STATIC_LIBRARY:
|
|
case cmStateEnums::SHARED_LIBRARY:
|
|
case cmStateEnums::MODULE_LIBRARY:
|
|
case cmStateEnums::OBJECT_LIBRARY: {
|
|
char const* prefix =
|
|
(target->GetType() == cmStateEnums::EXECUTABLE ? "[exe] "
|
|
: "[lib] ");
|
|
cmExtraEclipseCDT4Generator::AppendTarget(xml, targetName, make,
|
|
makeArgs, subdir, prefix);
|
|
std::string fastTarget = cmStrCat(targetName, "/fast");
|
|
cmExtraEclipseCDT4Generator::AppendTarget(xml, fastTarget, make,
|
|
makeArgs, subdir, prefix);
|
|
|
|
// Add Build and Clean targets in the virtual folder of targets:
|
|
if (this->SupportsVirtualFolders) {
|
|
std::string virtDir = cmStrCat("[Targets]/", prefix, targetName);
|
|
std::string buildArgs =
|
|
cmStrCat("-C \"", lgen->GetBinaryDirectory(), "\" ", makeArgs);
|
|
cmExtraEclipseCDT4Generator::AppendTarget(
|
|
xml, "Build", make, buildArgs, virtDir, "", targetName.c_str());
|
|
|
|
std::string cleanArgs =
|
|
cmStrCat("-E chdir \"", lgen->GetObjectOutputRoot(), "\" \"",
|
|
cmSystemTools::GetCMakeCommand(), "\" -P \"");
|
|
cleanArgs += lgen->GetTargetDirectory(
|
|
target.get(), cmStateEnums::IntermediateDirKind::ObjectFiles);
|
|
cleanArgs += "/cmake_clean.cmake\"";
|
|
cmExtraEclipseCDT4Generator::AppendTarget(
|
|
xml, "Clean", cmSystemTools::GetCMakeCommand(), cleanArgs,
|
|
virtDir, "", "");
|
|
}
|
|
} break;
|
|
case cmStateEnums::INTERFACE_LIBRARY:
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
// insert the all and clean targets in every subdir
|
|
if (!allTarget.empty()) {
|
|
cmExtraEclipseCDT4Generator::AppendTarget(xml, allTarget, make, makeArgs,
|
|
subdir, ": ");
|
|
}
|
|
if (!cleanTarget.empty()) {
|
|
cmExtraEclipseCDT4Generator::AppendTarget(xml, cleanTarget, make,
|
|
makeArgs, subdir, ": ");
|
|
}
|
|
|
|
// insert rules for compiling, preprocessing and assembling individual
|
|
// files
|
|
std::vector<std::string> objectFileTargets;
|
|
lg->GetIndividualFileTargets(objectFileTargets);
|
|
for (std::string const& f : objectFileTargets) {
|
|
char const* prefix = "[obj] ";
|
|
if (f.back() == 's') {
|
|
prefix = "[to asm] ";
|
|
} else if (f.back() == 'i') {
|
|
prefix = "[pre] ";
|
|
}
|
|
cmExtraEclipseCDT4Generator::AppendTarget(xml, f, make, makeArgs, subdir,
|
|
prefix);
|
|
}
|
|
}
|
|
|
|
xml.EndElement(); // buildTargets
|
|
xml.EndElement(); // storageModule
|
|
|
|
cmExtraEclipseCDT4Generator::AppendStorageScanners(xml, *mf);
|
|
|
|
// noqa: spellcheck off
|
|
xml.EndElement(); // cconfiguration
|
|
// noqa: spellcheck on
|
|
xml.EndElement(); // storageModule
|
|
|
|
xml.StartElement("storageModule");
|
|
xml.Attribute("moduleId", "cdtBuildSystem");
|
|
xml.Attribute("version", "4.0.0");
|
|
|
|
xml.StartElement("project");
|
|
xml.Attribute("id", std::string(lg->GetProjectName()) + ".null.1");
|
|
xml.Attribute("name", lg->GetProjectName());
|
|
xml.EndElement(); // project
|
|
|
|
xml.EndElement(); // storageModule
|
|
|
|
// Append additional cproject contents without applying any XML formatting
|
|
if (cmValue extraCProjectContents =
|
|
mf->GetState()->GetGlobalProperty("ECLIPSE_EXTRA_CPROJECT_CONTENTS")) {
|
|
fout << *extraCProjectContents;
|
|
}
|
|
|
|
xml.EndElement(); // cproject
|
|
}
|
|
|
|
std::string cmExtraEclipseCDT4Generator::GetEclipsePath(
|
|
std::string const& path)
|
|
{
|
|
#if defined(__CYGWIN__)
|
|
std::string cmd = "cygpath -m " + path;
|
|
std::string out;
|
|
if (!cmSystemTools::RunSingleCommand(cmd.c_str(), &out, &out)) {
|
|
return path;
|
|
} else {
|
|
out.erase(out.find_last_of('\n'));
|
|
return out;
|
|
}
|
|
#else
|
|
return path;
|
|
#endif
|
|
}
|
|
|
|
std::string cmExtraEclipseCDT4Generator::GetPathBasename(
|
|
std::string const& path)
|
|
{
|
|
std::string outputBasename = path;
|
|
while (!outputBasename.empty() &&
|
|
(outputBasename.back() == '/' || outputBasename.back() == '\\')) {
|
|
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;
|
|
}
|
|
|
|
std::string cmExtraEclipseCDT4Generator::GenerateProjectName(
|
|
std::string const& name, std::string const& type, std::string const& path)
|
|
{
|
|
return name + (type.empty() ? "" : "-") + type + "@" + path;
|
|
}
|
|
|
|
// Helper functions
|
|
void cmExtraEclipseCDT4Generator::AppendStorageScanners(
|
|
cmXMLWriter& xml, cmMakefile const& makefile)
|
|
{
|
|
// we need the "make" and the C (or C++) compiler which are used, Alex
|
|
std::string const& make =
|
|
makefile.GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
|
|
std::string compiler = makefile.GetSafeDefinition("CMAKE_C_COMPILER");
|
|
std::string arg1 = makefile.GetSafeDefinition("CMAKE_C_COMPILER_ARG1");
|
|
if (compiler.empty()) {
|
|
compiler = makefile.GetSafeDefinition("CMAKE_CXX_COMPILER");
|
|
arg1 = makefile.GetSafeDefinition("CMAKE_CXX_COMPILER_ARG1");
|
|
}
|
|
if (compiler.empty()) // Hmm, what to do now ?
|
|
{
|
|
compiler = "gcc";
|
|
}
|
|
|
|
// the following right now hardcodes gcc behavior :-/
|
|
std::string compilerArgs =
|
|
"-E -P -v -dD ${plugin_state_location}/${specs_file}";
|
|
if (!arg1.empty()) {
|
|
arg1 += " ";
|
|
compilerArgs = arg1 + compilerArgs;
|
|
}
|
|
|
|
xml.StartElement("storageModule");
|
|
xml.Attribute("moduleId", "scannerConfiguration");
|
|
|
|
xml.StartElement("autodiscovery");
|
|
xml.Attribute("enabled", "true");
|
|
xml.Attribute("problemReportingEnabled", "true");
|
|
xml.Attribute("selectedProfileId",
|
|
"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile");
|
|
xml.EndElement(); // autodiscovery
|
|
|
|
cmExtraEclipseCDT4Generator::AppendScannerProfile(
|
|
xml, "org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile", true,
|
|
"", true, "specsFile", compilerArgs, compiler, true, true);
|
|
cmExtraEclipseCDT4Generator::AppendScannerProfile(
|
|
xml, "org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile", true, "",
|
|
true, "makefileGenerator", "-f ${project_name}_scd.mk", make, true, true);
|
|
|
|
xml.EndElement(); // storageModule
|
|
}
|
|
|
|
// The prefix is prepended before the actual name of the target. The purpose
|
|
// of that is to sort the targets in the view of Eclipse, so that at first
|
|
// the global/utility/all/clean targets appear ": ", then the executable
|
|
// targets "[exe] ", then the libraries "[lib]", then the rules for the
|
|
// object files "[obj]", then for preprocessing only "[pre] " and
|
|
// finally the assembly files "[to asm] ". Note the "to" in "to asm",
|
|
// without it, "asm" would be the first targets in the list, with the "to"
|
|
// they are the last targets, which makes more sense.
|
|
void cmExtraEclipseCDT4Generator::AppendTarget(
|
|
cmXMLWriter& xml, std::string const& target, std::string const& make,
|
|
std::string const& makeArgs, std::string const& path, char const* prefix,
|
|
char const* makeTarget)
|
|
{
|
|
xml.StartElement("target");
|
|
xml.Attribute("name", prefix + target);
|
|
xml.Attribute("path", path);
|
|
xml.Attribute("targetID", "org.eclipse.cdt.make.MakeTargetBuilder");
|
|
xml.Element("buildCommand",
|
|
cmExtraEclipseCDT4Generator::GetEclipsePath(make));
|
|
xml.Element("buildArguments", makeArgs);
|
|
xml.Element("buildTarget", makeTarget ? makeTarget : target.c_str());
|
|
xml.Element("stopOnError", "true");
|
|
xml.Element("useDefaultCommand", "false");
|
|
xml.EndElement();
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::AppendScannerProfile(
|
|
cmXMLWriter& xml, std::string const& profileID, bool openActionEnabled,
|
|
std::string const& openActionFilePath, bool pParserEnabled,
|
|
std::string const& scannerInfoProviderID,
|
|
std::string const& runActionArguments, std::string const& runActionCommand,
|
|
bool runActionUseDefault, bool sipParserEnabled)
|
|
{
|
|
xml.StartElement("profile");
|
|
xml.Attribute("id", profileID);
|
|
|
|
xml.StartElement("buildOutputProvider");
|
|
xml.StartElement("openAction");
|
|
xml.Attribute("enabled", openActionEnabled ? "true" : "false");
|
|
xml.Attribute("filePath", openActionFilePath);
|
|
xml.EndElement(); // openAction
|
|
xml.StartElement("parser");
|
|
xml.Attribute("enabled", pParserEnabled ? "true" : "false");
|
|
xml.EndElement(); // parser
|
|
xml.EndElement(); // buildOutputProvider
|
|
|
|
xml.StartElement("scannerInfoProvider");
|
|
xml.Attribute("id", scannerInfoProviderID);
|
|
xml.StartElement("runAction");
|
|
xml.Attribute("arguments", runActionArguments);
|
|
xml.Attribute("command", runActionCommand);
|
|
xml.Attribute("useDefault", runActionUseDefault ? "true" : "false");
|
|
xml.EndElement(); // runAction
|
|
xml.StartElement("parser");
|
|
xml.Attribute("enabled", sipParserEnabled ? "true" : "false");
|
|
xml.EndElement(); // parser
|
|
xml.EndElement(); // scannerInfoProvider
|
|
|
|
xml.EndElement(); // profile
|
|
}
|
|
|
|
void cmExtraEclipseCDT4Generator::AppendLinkedResource(cmXMLWriter& xml,
|
|
std::string const& name,
|
|
std::string const& path,
|
|
LinkType linkType)
|
|
{
|
|
char const* locationTag = "location";
|
|
int typeTag = 2;
|
|
if (linkType == VirtualFolder) // ... and not a linked folder
|
|
{
|
|
locationTag = "locationURI";
|
|
}
|
|
if (linkType == LinkToFile) {
|
|
typeTag = 1;
|
|
}
|
|
|
|
xml.StartElement("link");
|
|
xml.Element("name", name);
|
|
xml.Element("type", typeTag);
|
|
xml.Element(locationTag, path);
|
|
xml.EndElement();
|
|
}
|