CMake/Source/cmExtraEclipseCDT4Generator.cxx
Alexander Neundorf f40f867be6 ENH: don't enforce VERBOSE Makefiles, but set the env. var VERBOSE to 1 in
when make is executed from within Eclipse. This way when building from the
command line one can build also in non-verbose mode.

Alex
2009-03-13 17:04:57 -04:00

997 lines
34 KiB
C++

/*=========================================================================
Program: CMake - Cross-Platform Makefile Generator
Module: $RCSfile$
Language: C++
Date: $Date$
Version: $Revision$
Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
Copyright (c) 2004 Alexander Neundorf neundorf@kde.org, All rights reserved.
Copyright (c) 2007 Miguel A. Figueroa-Villanueva. 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 "cmExtraEclipseCDT4Generator.h"
#include "cmGlobalUnixMakefileGenerator3.h"
#include "cmLocalUnixMakefileGenerator3.h"
#include "cmMakefile.h"
#include "cmGeneratedFileStream.h"
#include "cmTarget.h"
#include "cmSystemTools.h"
#include <stdlib.h>
#include <assert.h>
//----------------------------------------------------------------------------
cmExtraEclipseCDT4Generator
::cmExtraEclipseCDT4Generator() : cmExternalMakefileProjectGenerator()
{
// TODO: Verify if __CYGWIN__ should be checked.
//#if defined(_WIN32) && !defined(__CYGWIN__)
#if defined(_WIN32)
this->SupportedGlobalGenerators.push_back("NMake Makefiles");
this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
// this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
#endif
this->SupportedGlobalGenerators.push_back("Unix Makefiles");
// don't create these targets in Eclipse, they are too many and
// should be only rarely used directly
this->TargetsToIgnore.insert("preinstall");
this->TargetsToIgnore.insert("install/local");
this->TargetsToIgnore.insert("ContinuousBuild");
this->TargetsToIgnore.insert("ContinuousConfigure");
this->TargetsToIgnore.insert("ContinuousCoverage");
this->TargetsToIgnore.insert("ContinuousMemCheck");
this->TargetsToIgnore.insert("ContinuousStart");
this->TargetsToIgnore.insert("ContinuousSubmit");
this->TargetsToIgnore.insert("ContinuousTest");
this->TargetsToIgnore.insert("ContinuousUpdate");
this->TargetsToIgnore.insert("ExperimentalBuild");
this->TargetsToIgnore.insert("ExperimentalConfigure");
this->TargetsToIgnore.insert("ExperimentalCoverage");
this->TargetsToIgnore.insert("ExperimentalMemCheck");
this->TargetsToIgnore.insert("ExperimentalStart");
this->TargetsToIgnore.insert("ExperimentalSubmit");
this->TargetsToIgnore.insert("ExperimentalTest");
this->TargetsToIgnore.insert("ExperimentalUpdate");
this->TargetsToIgnore.insert("NightlyBuild");
this->TargetsToIgnore.insert("NightlyConfigure");
this->TargetsToIgnore.insert("NightlyCoverage");
this->TargetsToIgnore.insert("NightlyMemCheck");
this->TargetsToIgnore.insert("NightlyMemoryCheck");
this->TargetsToIgnore.insert("NightlyStart");
this->TargetsToIgnore.insert("NightlySubmit");
this->TargetsToIgnore.insert("NightlyTest");
this->TargetsToIgnore.insert("NightlyUpdate");
}
//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator
::GetDocumentation(cmDocumentationEntry& entry, const char*) const
{
entry.Name = this->GetName();
entry.Brief = "Generates Eclipse CDT 4.0 project files.";
entry.Full =
"Project files for Eclipse will be created in the top directory "
"and will have a linked resource to 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.";
}
//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator
::SetGlobalGenerator(cmGlobalGenerator* generator)
{
cmExternalMakefileProjectGenerator::SetGlobalGenerator(generator);
cmGlobalUnixMakefileGenerator3* mf
= static_cast<cmGlobalUnixMakefileGenerator3*>(generator);
mf->SetToolSupportsColor(true);
}
//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator::Generate()
{
const cmMakefile* mf
= this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
// TODO: Decide if these are local or member variables
this->HomeDirectory = mf->GetHomeDirectory();
this->HomeOutputDirectory = mf->GetHomeOutputDirectory();
this->IsOutOfSourceBuild = (this->HomeDirectory!=this->HomeOutputDirectory);
this->GenerateSourceProject = (this->IsOutOfSourceBuild &&
mf->IsOn("ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT"));
// 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();
}
void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() const
{
assert(this->HomeDirectory != this->HomeOutputDirectory);
// set up the project name: <project>-Source@<baseSourcePathName>
const cmMakefile* mf
= this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
std::string name = this->GenerateProjectName(mf->GetProjectName(), "Source",
this->GetPathBasename(this->HomeDirectory));
const std::string filename = this->HomeDirectory + "/.project";
cmGeneratedFileStream fout(filename.c_str());
if (!fout)
{
return;
}
fout <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<projectDescription>\n"
"\t<name>" << name << "</name>\n"
"\t<comment></comment>\n"
"\t<projects>\n"
"\t</projects>\n"
"\t<buildSpec>\n"
"\t</buildSpec>\n"
"\t<natures>\n"
"\t</natures>\n"
"</projectDescription>\n"
;
}
//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator::CreateProjectFile()
{
const cmMakefile* mf
= this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
const std::string filename = this->HomeOutputDirectory + "/.project";
cmGeneratedFileStream fout(filename.c_str());
if (!fout)
{
return;
}
fout <<
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<projectDescription>\n"
"\t<name>" <<
this->GenerateProjectName(mf->GetProjectName(),
mf->GetDefinition("CMAKE_BUILD_TYPE"),
this->GetPathBasename(this->HomeOutputDirectory))
<< "</name>\n"
"\t<comment></comment>\n"
"\t<projects>\n"
"\t</projects>\n"
"\t<buildSpec>\n"
"\t\t<buildCommand>\n"
"\t\t\t<name>org.eclipse.cdt.make.core.makeBuilder</name>\n"
"\t\t\t<triggers>clean,full,incremental,</triggers>\n"
"\t\t\t<arguments>\n"
;
// use clean target
fout <<
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>\n"
"\t\t\t\t\t<value>clean</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableCleanBuild</key>\n"
"\t\t\t\t\t<value>true</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.append_environment</key>\n"
"\t\t\t\t\t<value>true</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.stopOnError</key>\n"
"\t\t\t\t\t<value>true</value>\n"
"\t\t\t\t</dictionary>\n"
;
// set the make command
std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
fout <<
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>\n"
"\t\t\t\t\t<value>true</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.command</key>\n"
"\t\t\t\t\t<value>" + this->GetEclipsePath(make) + "</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.contents</key>\n"
"\t\t\t\t\t<value>org.eclipse.cdt.make.core.activeConfigSettings</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.inc</key>\n"
"\t\t\t\t\t<value>all</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.arguments</key>\n"
"\t\t\t\t\t<value></value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.buildLocation</key>\n"
"\t\t\t\t\t<value>"
<< this->GetEclipsePath(this->HomeOutputDirectory) << "</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>\n"
"\t\t\t\t\t<value>false</value>\n"
"\t\t\t\t</dictionary>\n"
;
// set project specific environment
fout <<
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.environment</key>\n"
"\t\t\t\t\t<value>VERBOSE=1|</value>\n" // enforce VERBOSE Makefile output
"\t\t\t\t\t<value>"
;
// set vsvars32.bat environment available at CMake time,
// but not necessarily when eclipse is open
if (make.find("nmake") != std::string::npos)
{
if (getenv("PATH"))
{
fout << "PATH=" << getenv("PATH") << "|";
}
if (getenv("INCLUDE"))
{
fout << "INCLUDE=" << getenv("INCLUDE") << "|";
}
if (getenv("LIB"))
{
fout << "LIB=" << getenv("LIB") << "|";
}
if (getenv("LIBPATH"))
{
fout << "LIBPATH=" << getenv("LIBPATH") << "|";
}
}
fout <<
"</value>\n"
"\t\t\t\t</dictionary>\n"
;
fout <<
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableFullBuild</key>\n"
"\t\t\t\t\t<value>true</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.auto</key>\n"
"\t\t\t\t\t<value>all</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableAutoBuild</key>\n"
"\t\t\t\t\t<value>false</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.clean</key>\n"
"\t\t\t\t\t<value>clean</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.fullBuildTarget</key>\n"
"\t\t\t\t\t<value>all</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.buildArguments</key>\n"
"\t\t\t\t\t<value></value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.location</key>\n"
"\t\t\t\t\t<value>"
<< this->GetEclipsePath(this->HomeOutputDirectory) << "</value>\n"
"\t\t\t\t</dictionary>\n"
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.make.core.autoBuildTarget</key>\n"
"\t\t\t\t\t<value>all</value>\n"
"\t\t\t\t</dictionary>\n"
;
// set error parsers
fout <<
"\t\t\t\t<dictionary>\n"
"\t\t\t\t\t<key>org.eclipse.cdt.core.errorOutputParser</key>\n"
"\t\t\t\t\t<value>"
;
if (this->GetToolChainType(*mf) == EclipseToolchainOther)
{
fout << "org.eclipse.cdt.core.VCErrorParser;";
}
fout <<
"org.eclipse.cdt.core.MakeErrorParser;"
"org.eclipse.cdt.core.GCCErrorParser;"
"org.eclipse.cdt.core.GASErrorParser;"
"org.eclipse.cdt.core.GLDErrorParser;"
"</value>\n"
"\t\t\t\t</dictionary>\n"
;
fout <<
"\t\t\t</arguments>\n"
"\t\t</buildCommand>\n"
"\t\t<buildCommand>\n"
"\t\t\t<name>org.eclipse.cdt.make.core.ScannerConfigBuilder</name>\n"
"\t\t\t<arguments>\n"
"\t\t\t</arguments>\n"
"\t\t</buildCommand>\n"
"\t</buildSpec>\n"
;
// set natures for c/c++ projects
fout <<
"\t<natures>\n"
// TODO: ccnature only if it is c++ ???
"\t\t<nature>org.eclipse.cdt.core.ccnature</nature>\n"
"\t\t<nature>org.eclipse.cdt.make.core.makeNature</nature>\n"
"\t\t<nature>org.eclipse.cdt.make.core.ScannerConfigNature</nature>\n"
"\t\t<nature>org.eclipse.cdt.core.cnature</nature>\n"
"\t</natures>\n"
;
// TODO: refactor this
// create linked resources
if (this->IsOutOfSourceBuild)
{
fout << "\t<linkedResources>\n";
// for each sub project create a linked resource to the source dir
// - only if it is an out-of-source build
for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
it = this->GlobalGenerator->GetProjectMap().begin();
it != this->GlobalGenerator->GetProjectMap().end();
++it)
{
std::string linkSourceDirectory = this->GetEclipsePath(
it->second[0]->GetMakefile()->GetStartDirectory());
// .project dir can't be subdir of a linked resource dir
if (!cmSystemTools::IsSubDirectory(this->HomeOutputDirectory.c_str(),
linkSourceDirectory.c_str()))
{
this->AppendLinkedResource(fout, it->first,
this->GetEclipsePath(linkSourceDirectory));
this->SrcLinkedResources.push_back(it->first);
}
}
// for EXECUTABLE_OUTPUT_PATH when not in binary dir
this->AppendOutLinkedResource(fout,
mf->GetSafeDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY"),
mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH"));
// for LIBRARY_OUTPUT_PATH when not in binary dir
this->AppendOutLinkedResource(fout,
mf->GetSafeDefinition("CMAKE_LIBRARY_OUTPUT_DIRECTORY"),
mf->GetSafeDefinition("LIBRARY_OUTPUT_PATH"));
fout << "\t</linkedResources>\n";
}
fout << "</projectDescription>\n";
}
//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator::AppendIncludeDirectories(
cmGeneratedFileStream& fout,
const std::vector<std::string>& includeDirs,
std::set<std::string>& emittedDirs)
{
for(std::vector<std::string>::const_iterator inc = includeDirs.begin();
inc != includeDirs.end();
++inc)
{
if (!inc->empty())
{
std::string dir = cmSystemTools::CollapseFullPath(inc->c_str());
if(emittedDirs.find(dir) == emittedDirs.end())
{
emittedDirs.insert(dir);
fout << "<pathentry include=\""
<< cmExtraEclipseCDT4Generator::GetEclipsePath(dir)
<< "\" kind=\"inc\" path=\"\" system=\"true\"/>\n";
}
}
}
}
//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
{
std::set<std::string> emmited;
const cmMakefile* mf
= this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
const std::string filename = this->HomeOutputDirectory + "/.cproject";
cmGeneratedFileStream fout(filename.c_str());
if (!fout)
{
return;
}
// add header
fout <<
"<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
"<?fileVersion 4.0.0?>\n\n"
"<cproject>\n"
"<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n"
;
fout << "<cconfiguration id=\"org.eclipse.cdt.core.default.config.1\">\n";
// Configuration settings...
fout <<
"<storageModule"
" buildSystemId=\"org.eclipse.cdt.core.defaultConfigDataProvider\""
" id=\"org.eclipse.cdt.core.default.config.1\""
" moduleId=\"org.eclipse.cdt.core.settings\" name=\"Configuration\">\n"
"<externalSettings/>\n"
"<extensions>\n"
;
// TODO: refactor this out...
switch (this->GetToolChainType(*mf))
{
case EclipseToolchainLinux :
fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
;
fout << "<extension id=\"org.eclipse.cdt.core.GNU_ELF\""
" point=\"org.eclipse.cdt.core.BinaryParser\">\n"
"<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
"<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
"</extension>\n"
;
break;
case EclipseToolchainCygwin :
fout << "<extension id=\"org.eclipse.cdt.core.Cygwin_PE\""
" point=\"org.eclipse.cdt.core.BinaryParser\">\n"
"<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
"<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
"<attribute key=\"cygpath\" value=\"cygpath\"/>\n"
"<attribute key=\"nm\" value=\"nm\"/>\n"
"</extension>\n"
;
break;
case EclipseToolchainMinGW :
fout << "<extension id=\"org.eclipse.cdt.core.PE\""
" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
;
break;
case EclipseToolchainSolaris :
fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
;
break;
case EclipseToolchainMacOSX :
fout << "<extension id=\"org.eclipse.cdt.core.MachO\""
" point=\"org.eclipse.cdt.core.BinaryParser\">\n"
"<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
"</extension>\n"
;
break;
case EclipseToolchainOther :
fout << "<extension id=\"org.eclipse.cdt.core.PE\""
" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
;
fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
" point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
;
break;
default :
// *** Should never get here ***
fout << "<error_toolchain_type/>\n";
}
fout << "</extensions>\n"
"</storageModule>\n"
;
// ???
fout <<
"<storageModule moduleId=\"org.eclipse.cdt.core.language.mapping\">\n"
"<project-mappings/>\n"
"</storageModule>\n"
;
// ???
fout<<"<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n"
;
// set the path entries (includes, libs, source dirs, etc.)
fout << "<storageModule moduleId=\"org.eclipse.cdt.core.pathentry\">\n"
;
// 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;
for (std::vector<std::string>::const_iterator
it = this->SrcLinkedResources.begin();
it != this->SrcLinkedResources.end();
++it)
{
fout << "<pathentry kind=\"src\" path=\"" << *it << "\"/>\n";
// exlude source directory from output search path
// - only if not named the same as an output directory
if (!cmSystemTools::FileIsDirectory(
std::string(this->HomeOutputDirectory + "/" + *it).c_str()))
{
excludeFromOut += *it + "/|";
}
}
excludeFromOut += "**/CMakeFiles/";
fout << "<pathentry excluding=\"" << excludeFromOut
<< "\" kind=\"out\" path=\"\"/>\n";
// add output entry for EXECUTABLE_OUTPUT_PATH and LIBRARY_OUTPUT_PATH
// - if it is a subdir of homeOutputDirectory, there is no need to add it
// - if it is not then create a linked resource and add the linked name
// but check it doesn't conflict with other linked resources names
for (std::vector<std::string>::const_iterator
it = this->OutLinkedResources.begin();
it != this->OutLinkedResources.end();
++it)
{
fout << "<pathentry kind=\"out\" path=\"" << *it << "\"/>\n";
}
// add pre-processor definitions to allow eclipse to gray out sections
emmited.clear();
for (std::vector<cmLocalGenerator*>::const_iterator
it = this->GlobalGenerator->GetLocalGenerators().begin();
it != this->GlobalGenerator->GetLocalGenerators().end();
++it)
{
if(const char* cdefs = (*it)->GetMakefile()->GetProperty(
"COMPILE_DEFINITIONS"))
{
// Expand the list.
std::vector<std::string> defs;
cmSystemTools::ExpandListArgument(cdefs, defs);
for(std::vector<std::string>::const_iterator di = defs.begin();
di != defs.end(); ++di)
{
std::string::size_type equals = di->find('=', 0);
std::string::size_type enddef = di->length();
std::string def;
std::string val;
if (equals != std::string::npos && equals < enddef)
{
// we have -DFOO=BAR
def = di->substr(0, equals);
val = di->substr(equals + 1, enddef - equals + 1);
}
else
{
// we have -DFOO
def = *di;
}
// insert the definition if not already added.
if(emmited.find(def) == emmited.end())
{
emmited.insert(def);
fout << "<pathentry kind=\"mac\" name=\"" << def
<< "\" path=\"\" value=\"" << this->EscapeForXML(val)
<< "\"/>\n";
}
}
}
}
// include dirs
emmited.clear();
for (std::vector<cmLocalGenerator*>::const_iterator
it = this->GlobalGenerator->GetLocalGenerators().begin();
it != this->GlobalGenerator->GetLocalGenerators().end();
++it)
{
const std::vector<std::string>& includeDirs
= (*it)->GetMakefile()->GetIncludeDirectories();
this->AppendIncludeDirectories(fout, includeDirs, emmited);
}
// now also the system include directories, in case we found them in
// CMakeSystemSpecificInformation.cmake. This makes Eclipse find the
// standard headers.
mf->GetDefinition("CMAKE_ECLIPSE_C_SYSTEM_INCLUDE_DIRS");
std::string compiler = mf->GetSafeDefinition("CMAKE_C_COMPILER");
if (!compiler.empty())
{
std::string systemIncludeDirs = mf->GetSafeDefinition(
"CMAKE_ECLIPSE_C_SYSTEM_INCLUDE_DIRS");
std::vector<std::string> dirs;
cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
this->AppendIncludeDirectories(fout, dirs, emmited);
}
compiler = mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
if (!compiler.empty())
{
std::string systemIncludeDirs = mf->GetSafeDefinition(
"CMAKE_ECLIPSE_CXX_SYSTEM_INCLUDE_DIRS");
std::vector<std::string> dirs;
cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
this->AppendIncludeDirectories(fout, dirs, emmited);
}
fout << "</storageModule>\n";
// add build targets
fout <<
"<storageModule moduleId=\"org.eclipse.cdt.make.core.buildtargets\">\n"
"<buildTargets>\n"
;
emmited.clear();
const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
cmGlobalGenerator* generator
= const_cast<cmGlobalGenerator*>(this->GlobalGenerator);
if (generator->GetAllTargetName())
{
emmited.insert(generator->GetAllTargetName());
this->AppendTarget(fout, generator->GetAllTargetName(), make);
}
if (generator->GetCleanTargetName())
{
emmited.insert(generator->GetCleanTargetName());
this->AppendTarget(fout, generator->GetCleanTargetName(), make);
}
// 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 cmTargets& targets = (*it)->GetMakefile()->GetTargets();
for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
{
bool addFastTarget = false;
switch(t->second.GetType())
{
case cmTarget::EXECUTABLE:
case cmTarget::STATIC_LIBRARY:
case cmTarget::SHARED_LIBRARY:
case cmTarget::MODULE_LIBRARY:
addFastTarget = true;
// no break here
case cmTarget::UTILITY:
case cmTarget::GLOBAL_TARGET:
{
bool insertTarget = true;
if(insertTarget &&
(std::set<std::string>::const_iterator(
this->TargetsToIgnore.find(t->first)) !=
this->TargetsToIgnore.end()))
{
insertTarget = false;
}
if(insertTarget && (emmited.find(t->first) != emmited.end()))
{
insertTarget = false;
}
// add the edit_cache target only if it's not ccmake
// otherwise ccmake will be executed in the log view of Eclipse,
// which is no terminal, so curses don't work there, Alex
if (insertTarget && (t->first=="edit_cache"))
{
if (strstr(mf->GetRequiredDefinition("CMAKE_EDIT_COMMAND"),
"ccmake")!=NULL)
{
insertTarget = false;
}
}
if (insertTarget)
{
emmited.insert(t->first);
this->AppendTarget(fout, t->first, make);
if (addFastTarget || t->first=="install")
{
std::string fastTarget = t->first;
fastTarget = fastTarget + "/fast";
this->AppendTarget(fout, fastTarget, make);
}
}
break;
}
// ignore these:
case cmTarget::INSTALL_FILES:
case cmTarget::INSTALL_PROGRAMS:
case cmTarget::INSTALL_DIRECTORY:
default:
break;
}
}
}
fout << "</buildTargets>\n"
"</storageModule>\n"
;
this->AppendStorageScanners(fout, *mf);
fout << "</cconfiguration>\n"
"</storageModule>\n"
"<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n"
"<project id=\"" << mf->GetProjectName() << ".null.1\""
" name=\"" << mf->GetProjectName() << "\"/>\n"
"</storageModule>\n"
"</cproject>\n"
;
}
//----------------------------------------------------------------------------
cmExtraEclipseCDT4Generator::EclipseToolchainType
cmExtraEclipseCDT4Generator::GetToolChainType(const cmMakefile& makefile)
{
if (makefile.IsSet("UNIX"))
{
if (makefile.IsSet("CYGWIN"))
{
return EclipseToolchainCygwin;
}
if (makefile.IsSet("APPLE" ))
{
return EclipseToolchainMacOSX;
}
// *** how do I determine if it is Solaris ???
return EclipseToolchainLinux;
}
else if (makefile.IsSet("WIN32"))
{
if (makefile.IsSet("MINGW"))
{
return EclipseToolchainMinGW;
}
if (makefile.IsSet("MSYS" ))
{
return EclipseToolchainMinGW;
}
return EclipseToolchainOther;
}
else
{
return EclipseToolchainOther;
}
}
std::string
cmExtraEclipseCDT4Generator::GetEclipsePath(const std::string& path)
{
#if defined(__CYGWIN__)
std::string cmd = "cygpath -m " + path;
std::string out;
if (!cmSystemTools::RunCommand(cmd.c_str(), out, 0, false))
{
return path;
}
else
{
out.erase(out.find_last_of('\n'));
return out;
}
#else
return path;
#endif
}
std::string
cmExtraEclipseCDT4Generator::GetPathBasename(const std::string& path)
{
std::string outputBasename = path;
while (outputBasename.size() > 0 &&
(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;
}
std::string
cmExtraEclipseCDT4Generator::GenerateProjectName(const std::string& name,
const std::string& type,
const std::string& path)
{
return name + (type.empty() ? "" : "-") + type + "@" + path;
}
std::string cmExtraEclipseCDT4Generator::EscapeForXML(const std::string& value)
{
std::string str = value;
cmSystemTools::ReplaceString(str, "&", "&amp;");
cmSystemTools::ReplaceString(str, "<", "&lt;");
cmSystemTools::ReplaceString(str, ">", "&gt;");
cmSystemTools::ReplaceString(str, "\"", "&quot;");
// NOTE: This one is not necessary, since as of Eclipse CDT4 it will
// automatically change this to the original value (').
//cmSystemTools::ReplaceString(str, "'", "&apos;");
return str;
}
//----------------------------------------------------------------------------
// Helper functions
//----------------------------------------------------------------------------
void cmExtraEclipseCDT4Generator
::AppendStorageScanners(cmGeneratedFileStream& fout,
const cmMakefile& makefile)
{
// we need the "make" and the C (or C++) compiler which are used, Alex
std::string make = makefile.GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
std::string compiler = makefile.GetSafeDefinition("CMAKE_C_COMPILER");
if (compiler.empty())
{
compiler = makefile.GetSafeDefinition("CMAKE_CXX_COMPILER");
}
if (compiler.empty()) //Hmm, what to do now ?
{
compiler = "gcc";
}
// the following right now hardcodes gcc behaviour :-/
fout <<
"<storageModule moduleId=\"scannerConfiguration\">\n"
"<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\""
" selectedProfileId="
"\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\n"
;
cmExtraEclipseCDT4Generator::AppendScannerProfile(fout,
"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile",
true, "", true, "specsFile",
"-E -P -v -dD ${plugin_state_location}/${specs_file}",
compiler, true, true);
cmExtraEclipseCDT4Generator::AppendScannerProfile(fout,
"org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile",
true, "", true, "makefileGenerator",
"-f ${project_name}_scd.mk",
make, true, true);
fout << "</storageModule>\n";
}
void cmExtraEclipseCDT4Generator::AppendTarget(cmGeneratedFileStream& fout,
const std::string& target,
const std::string& make)
{
fout <<
"<target name=\"" << target << "\""
" path=\"\""
" targetID=\"org.eclipse.cdt.make.MakeTargetBuilder\">\n"
"<buildCommand>"
<< cmExtraEclipseCDT4Generator::GetEclipsePath(make)
<< "</buildCommand>\n"
"<buildArguments/>\n"
"<buildTarget>" << target << "</buildTarget>\n"
"<stopOnError>true</stopOnError>\n"
"<useDefaultCommand>false</useDefaultCommand>\n"
"</target>\n"
;
}
void cmExtraEclipseCDT4Generator
::AppendScannerProfile(cmGeneratedFileStream& fout,
const std::string& profileID,
bool openActionEnabled,
const std::string& openActionFilePath,
bool pParserEnabled,
const std::string& scannerInfoProviderID,
const std::string& runActionArguments,
const std::string& runActionCommand,
bool runActionUseDefault,
bool sipParserEnabled)
{
fout <<
"<profile id=\"" << profileID << "\">\n"
"<buildOutputProvider>\n"
"<openAction enabled=\"" << (openActionEnabled ? "true" : "false")
<< "\" filePath=\"" << openActionFilePath << "\"/>\n"
"<parser enabled=\"" << (pParserEnabled ? "true" : "false") << "\"/>\n"
"</buildOutputProvider>\n"
"<scannerInfoProvider id=\"" << scannerInfoProviderID << "\">\n"
"<runAction arguments=\"" << runActionArguments << "\""
" command=\"" << runActionCommand
<< "\" useDefault=\"" << (runActionUseDefault ? "true":"false") << "\"/>\n"
"<parser enabled=\"" << (sipParserEnabled ? "true" : "false") << "\"/>\n"
"</scannerInfoProvider>\n"
"</profile>\n"
;
}
void cmExtraEclipseCDT4Generator
::AppendLinkedResource (cmGeneratedFileStream& fout,
const std::string& name,
const std::string& path)
{
fout <<
"\t\t<link>\n"
"\t\t\t<name>" << name << "</name>\n"
"\t\t\t<type>2</type>\n"
"\t\t\t<location>"
<< path
<< "</location>\n"
"\t\t</link>\n"
;
}
bool cmExtraEclipseCDT4Generator
::AppendOutLinkedResource(cmGeneratedFileStream& fout,
const std::string& defname,
const std::string& altdefname)
{
if (defname.empty() && altdefname.empty())
{
return false;
}
std::string outputPath = (defname.empty() ? altdefname : defname);
if (!cmSystemTools::FileIsFullPath(outputPath.c_str()))
{
outputPath = this->HomeOutputDirectory + "/" + outputPath;
}
if (cmSystemTools::IsSubDirectory(outputPath.c_str(),
this->HomeOutputDirectory.c_str()))
{
return false;
}
std::string name = this->GetPathBasename(outputPath);
// make sure linked resource name is unique
while (this->GlobalGenerator->GetProjectMap().find(name)
!= this->GlobalGenerator->GetProjectMap().end())
{
name += "_";
}
if (std::find(this->OutLinkedResources.begin(),
this->OutLinkedResources.end(),
name)
!= this->OutLinkedResources.end())
{
return false;
}
else
{
this->AppendLinkedResource(fout, name,
this->GetEclipsePath(outputPath));
this->OutLinkedResources.push_back(name);
return true;
}
}