ENH: put the 64 bit paths first
[cmake.git] / Source / cmExtraEclipseCDT4Generator.cxx
blob8e5f81cb052c367647163e7555764281eb24d1cc
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmExtraEclipseCDT4Generator.cxx,v $
5 Language: C++
6 Date: $Date: 2009-03-13 21:04:57 $
7 Version: $Revision: 1.24 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 Copyright (c) 2004 Alexander Neundorf neundorf@kde.org, All rights reserved.
11 Copyright (c) 2007 Miguel A. Figueroa-Villanueva. All rights reserved.
12 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
14 This software is distributed WITHOUT ANY WARRANTY; without even
15 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
16 PURPOSE. See the above copyright notices for more information.
18 =========================================================================*/
20 #include "cmExtraEclipseCDT4Generator.h"
21 #include "cmGlobalUnixMakefileGenerator3.h"
22 #include "cmLocalUnixMakefileGenerator3.h"
23 #include "cmMakefile.h"
24 #include "cmGeneratedFileStream.h"
25 #include "cmTarget.h"
27 #include "cmSystemTools.h"
28 #include <stdlib.h>
29 #include <assert.h>
31 //----------------------------------------------------------------------------
32 cmExtraEclipseCDT4Generator
33 ::cmExtraEclipseCDT4Generator() : cmExternalMakefileProjectGenerator()
35 // TODO: Verify if __CYGWIN__ should be checked.
36 //#if defined(_WIN32) && !defined(__CYGWIN__)
37 #if defined(_WIN32)
38 this->SupportedGlobalGenerators.push_back("NMake Makefiles");
39 this->SupportedGlobalGenerators.push_back("MinGW Makefiles");
40 // this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
41 #endif
42 this->SupportedGlobalGenerators.push_back("Unix Makefiles");
44 // don't create these targets in Eclipse, they are too many and
45 // should be only rarely used directly
46 this->TargetsToIgnore.insert("preinstall");
47 this->TargetsToIgnore.insert("install/local");
48 this->TargetsToIgnore.insert("ContinuousBuild");
49 this->TargetsToIgnore.insert("ContinuousConfigure");
50 this->TargetsToIgnore.insert("ContinuousCoverage");
51 this->TargetsToIgnore.insert("ContinuousMemCheck");
52 this->TargetsToIgnore.insert("ContinuousStart");
53 this->TargetsToIgnore.insert("ContinuousSubmit");
54 this->TargetsToIgnore.insert("ContinuousTest");
55 this->TargetsToIgnore.insert("ContinuousUpdate");
56 this->TargetsToIgnore.insert("ExperimentalBuild");
57 this->TargetsToIgnore.insert("ExperimentalConfigure");
58 this->TargetsToIgnore.insert("ExperimentalCoverage");
59 this->TargetsToIgnore.insert("ExperimentalMemCheck");
60 this->TargetsToIgnore.insert("ExperimentalStart");
61 this->TargetsToIgnore.insert("ExperimentalSubmit");
62 this->TargetsToIgnore.insert("ExperimentalTest");
63 this->TargetsToIgnore.insert("ExperimentalUpdate");
64 this->TargetsToIgnore.insert("NightlyBuild");
65 this->TargetsToIgnore.insert("NightlyConfigure");
66 this->TargetsToIgnore.insert("NightlyCoverage");
67 this->TargetsToIgnore.insert("NightlyMemCheck");
68 this->TargetsToIgnore.insert("NightlyMemoryCheck");
69 this->TargetsToIgnore.insert("NightlyStart");
70 this->TargetsToIgnore.insert("NightlySubmit");
71 this->TargetsToIgnore.insert("NightlyTest");
72 this->TargetsToIgnore.insert("NightlyUpdate");
75 //----------------------------------------------------------------------------
76 void cmExtraEclipseCDT4Generator
77 ::GetDocumentation(cmDocumentationEntry& entry, const char*) const
79 entry.Name = this->GetName();
80 entry.Brief = "Generates Eclipse CDT 4.0 project files.";
81 entry.Full =
82 "Project files for Eclipse will be created in the top directory "
83 "and will have a linked resource to every subdirectory which "
84 "features a CMakeLists.txt file containing a PROJECT() call."
85 "Additionally a hierarchy of makefiles is generated into the "
86 "build tree. The appropriate make program can build the project through "
87 "the default make target. A \"make install\" target is also provided.";
90 //----------------------------------------------------------------------------
91 void cmExtraEclipseCDT4Generator
92 ::SetGlobalGenerator(cmGlobalGenerator* generator)
94 cmExternalMakefileProjectGenerator::SetGlobalGenerator(generator);
95 cmGlobalUnixMakefileGenerator3* mf
96 = static_cast<cmGlobalUnixMakefileGenerator3*>(generator);
97 mf->SetToolSupportsColor(true);
100 //----------------------------------------------------------------------------
101 void cmExtraEclipseCDT4Generator::Generate()
103 const cmMakefile* mf
104 = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
106 // TODO: Decide if these are local or member variables
107 this->HomeDirectory = mf->GetHomeDirectory();
108 this->HomeOutputDirectory = mf->GetHomeOutputDirectory();
110 this->IsOutOfSourceBuild = (this->HomeDirectory!=this->HomeOutputDirectory);
112 this->GenerateSourceProject = (this->IsOutOfSourceBuild &&
113 mf->IsOn("ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT"));
115 // NOTE: This is not good, since it pollutes the source tree. However,
116 // Eclipse doesn't allow CVS/SVN to work when the .project is not in
117 // the cvs/svn root directory. Hence, this is provided as an option.
118 if (this->GenerateSourceProject)
120 // create .project file in the source tree
121 this->CreateSourceProjectFile();
124 // create a .project file
125 this->CreateProjectFile();
127 // create a .cproject file
128 this->CreateCProjectFile();
131 void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() const
133 assert(this->HomeDirectory != this->HomeOutputDirectory);
135 // set up the project name: <project>-Source@<baseSourcePathName>
136 const cmMakefile* mf
137 = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
138 std::string name = this->GenerateProjectName(mf->GetProjectName(), "Source",
139 this->GetPathBasename(this->HomeDirectory));
141 const std::string filename = this->HomeDirectory + "/.project";
142 cmGeneratedFileStream fout(filename.c_str());
143 if (!fout)
145 return;
148 fout <<
149 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
150 "<projectDescription>\n"
151 "\t<name>" << name << "</name>\n"
152 "\t<comment></comment>\n"
153 "\t<projects>\n"
154 "\t</projects>\n"
155 "\t<buildSpec>\n"
156 "\t</buildSpec>\n"
157 "\t<natures>\n"
158 "\t</natures>\n"
159 "</projectDescription>\n"
163 //----------------------------------------------------------------------------
164 void cmExtraEclipseCDT4Generator::CreateProjectFile()
166 const cmMakefile* mf
167 = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
169 const std::string filename = this->HomeOutputDirectory + "/.project";
171 cmGeneratedFileStream fout(filename.c_str());
172 if (!fout)
174 return;
177 fout <<
178 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
179 "<projectDescription>\n"
180 "\t<name>" <<
181 this->GenerateProjectName(mf->GetProjectName(),
182 mf->GetDefinition("CMAKE_BUILD_TYPE"),
183 this->GetPathBasename(this->HomeOutputDirectory))
184 << "</name>\n"
185 "\t<comment></comment>\n"
186 "\t<projects>\n"
187 "\t</projects>\n"
188 "\t<buildSpec>\n"
189 "\t\t<buildCommand>\n"
190 "\t\t\t<name>org.eclipse.cdt.make.core.makeBuilder</name>\n"
191 "\t\t\t<triggers>clean,full,incremental,</triggers>\n"
192 "\t\t\t<arguments>\n"
195 // use clean target
196 fout <<
197 "\t\t\t\t<dictionary>\n"
198 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>\n"
199 "\t\t\t\t\t<value>clean</value>\n"
200 "\t\t\t\t</dictionary>\n"
201 "\t\t\t\t<dictionary>\n"
202 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableCleanBuild</key>\n"
203 "\t\t\t\t\t<value>true</value>\n"
204 "\t\t\t\t</dictionary>\n"
205 "\t\t\t\t<dictionary>\n"
206 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.append_environment</key>\n"
207 "\t\t\t\t\t<value>true</value>\n"
208 "\t\t\t\t</dictionary>\n"
209 "\t\t\t\t<dictionary>\n"
210 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.stopOnError</key>\n"
211 "\t\t\t\t\t<value>true</value>\n"
212 "\t\t\t\t</dictionary>\n"
215 // set the make command
216 std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
217 fout <<
218 "\t\t\t\t<dictionary>\n"
219 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>\n"
220 "\t\t\t\t\t<value>true</value>\n"
221 "\t\t\t\t</dictionary>\n"
222 "\t\t\t\t<dictionary>\n"
223 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.command</key>\n"
224 "\t\t\t\t\t<value>" + this->GetEclipsePath(make) + "</value>\n"
225 "\t\t\t\t</dictionary>\n"
226 "\t\t\t\t<dictionary>\n"
227 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.contents</key>\n"
228 "\t\t\t\t\t<value>org.eclipse.cdt.make.core.activeConfigSettings</value>\n"
229 "\t\t\t\t</dictionary>\n"
230 "\t\t\t\t<dictionary>\n"
231 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.inc</key>\n"
232 "\t\t\t\t\t<value>all</value>\n"
233 "\t\t\t\t</dictionary>\n"
234 "\t\t\t\t<dictionary>\n"
235 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.arguments</key>\n"
236 "\t\t\t\t\t<value></value>\n"
237 "\t\t\t\t</dictionary>\n"
238 "\t\t\t\t<dictionary>\n"
239 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.buildLocation</key>\n"
240 "\t\t\t\t\t<value>"
241 << this->GetEclipsePath(this->HomeOutputDirectory) << "</value>\n"
242 "\t\t\t\t</dictionary>\n"
243 "\t\t\t\t<dictionary>\n"
244 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>\n"
245 "\t\t\t\t\t<value>false</value>\n"
246 "\t\t\t\t</dictionary>\n"
249 // set project specific environment
250 fout <<
251 "\t\t\t\t<dictionary>\n"
252 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.environment</key>\n"
253 "\t\t\t\t\t<value>VERBOSE=1|</value>\n" // enforce VERBOSE Makefile output
254 "\t\t\t\t\t<value>"
256 // set vsvars32.bat environment available at CMake time,
257 // but not necessarily when eclipse is open
258 if (make.find("nmake") != std::string::npos)
260 if (getenv("PATH"))
262 fout << "PATH=" << getenv("PATH") << "|";
264 if (getenv("INCLUDE"))
266 fout << "INCLUDE=" << getenv("INCLUDE") << "|";
268 if (getenv("LIB"))
270 fout << "LIB=" << getenv("LIB") << "|";
272 if (getenv("LIBPATH"))
274 fout << "LIBPATH=" << getenv("LIBPATH") << "|";
277 fout <<
278 "</value>\n"
279 "\t\t\t\t</dictionary>\n"
282 fout <<
283 "\t\t\t\t<dictionary>\n"
284 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableFullBuild</key>\n"
285 "\t\t\t\t\t<value>true</value>\n"
286 "\t\t\t\t</dictionary>\n"
287 "\t\t\t\t<dictionary>\n"
288 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.auto</key>\n"
289 "\t\t\t\t\t<value>all</value>\n"
290 "\t\t\t\t</dictionary>\n"
291 "\t\t\t\t<dictionary>\n"
292 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableAutoBuild</key>\n"
293 "\t\t\t\t\t<value>false</value>\n"
294 "\t\t\t\t</dictionary>\n"
295 "\t\t\t\t<dictionary>\n"
296 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.clean</key>\n"
297 "\t\t\t\t\t<value>clean</value>\n"
298 "\t\t\t\t</dictionary>\n"
299 "\t\t\t\t<dictionary>\n"
300 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.fullBuildTarget</key>\n"
301 "\t\t\t\t\t<value>all</value>\n"
302 "\t\t\t\t</dictionary>\n"
303 "\t\t\t\t<dictionary>\n"
304 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.buildArguments</key>\n"
305 "\t\t\t\t\t<value></value>\n"
306 "\t\t\t\t</dictionary>\n"
307 "\t\t\t\t<dictionary>\n"
308 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.location</key>\n"
309 "\t\t\t\t\t<value>"
310 << this->GetEclipsePath(this->HomeOutputDirectory) << "</value>\n"
311 "\t\t\t\t</dictionary>\n"
312 "\t\t\t\t<dictionary>\n"
313 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.autoBuildTarget</key>\n"
314 "\t\t\t\t\t<value>all</value>\n"
315 "\t\t\t\t</dictionary>\n"
318 // set error parsers
319 fout <<
320 "\t\t\t\t<dictionary>\n"
321 "\t\t\t\t\t<key>org.eclipse.cdt.core.errorOutputParser</key>\n"
322 "\t\t\t\t\t<value>"
324 if (this->GetToolChainType(*mf) == EclipseToolchainOther)
326 fout << "org.eclipse.cdt.core.VCErrorParser;";
328 fout <<
329 "org.eclipse.cdt.core.MakeErrorParser;"
330 "org.eclipse.cdt.core.GCCErrorParser;"
331 "org.eclipse.cdt.core.GASErrorParser;"
332 "org.eclipse.cdt.core.GLDErrorParser;"
333 "</value>\n"
334 "\t\t\t\t</dictionary>\n"
337 fout <<
338 "\t\t\t</arguments>\n"
339 "\t\t</buildCommand>\n"
340 "\t\t<buildCommand>\n"
341 "\t\t\t<name>org.eclipse.cdt.make.core.ScannerConfigBuilder</name>\n"
342 "\t\t\t<arguments>\n"
343 "\t\t\t</arguments>\n"
344 "\t\t</buildCommand>\n"
345 "\t</buildSpec>\n"
348 // set natures for c/c++ projects
349 fout <<
350 "\t<natures>\n"
351 // TODO: ccnature only if it is c++ ???
352 "\t\t<nature>org.eclipse.cdt.core.ccnature</nature>\n"
353 "\t\t<nature>org.eclipse.cdt.make.core.makeNature</nature>\n"
354 "\t\t<nature>org.eclipse.cdt.make.core.ScannerConfigNature</nature>\n"
355 "\t\t<nature>org.eclipse.cdt.core.cnature</nature>\n"
356 "\t</natures>\n"
359 // TODO: refactor this
360 // create linked resources
361 if (this->IsOutOfSourceBuild)
363 fout << "\t<linkedResources>\n";
364 // for each sub project create a linked resource to the source dir
365 // - only if it is an out-of-source build
366 for (std::map<cmStdString, std::vector<cmLocalGenerator*> >::const_iterator
367 it = this->GlobalGenerator->GetProjectMap().begin();
368 it != this->GlobalGenerator->GetProjectMap().end();
369 ++it)
371 std::string linkSourceDirectory = this->GetEclipsePath(
372 it->second[0]->GetMakefile()->GetStartDirectory());
373 // .project dir can't be subdir of a linked resource dir
374 if (!cmSystemTools::IsSubDirectory(this->HomeOutputDirectory.c_str(),
375 linkSourceDirectory.c_str()))
377 this->AppendLinkedResource(fout, it->first,
378 this->GetEclipsePath(linkSourceDirectory));
379 this->SrcLinkedResources.push_back(it->first);
382 // for EXECUTABLE_OUTPUT_PATH when not in binary dir
383 this->AppendOutLinkedResource(fout,
384 mf->GetSafeDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY"),
385 mf->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH"));
386 // for LIBRARY_OUTPUT_PATH when not in binary dir
387 this->AppendOutLinkedResource(fout,
388 mf->GetSafeDefinition("CMAKE_LIBRARY_OUTPUT_DIRECTORY"),
389 mf->GetSafeDefinition("LIBRARY_OUTPUT_PATH"));
391 fout << "\t</linkedResources>\n";
394 fout << "</projectDescription>\n";
397 //----------------------------------------------------------------------------
398 void cmExtraEclipseCDT4Generator::AppendIncludeDirectories(
399 cmGeneratedFileStream& fout,
400 const std::vector<std::string>& includeDirs,
401 std::set<std::string>& emittedDirs)
403 for(std::vector<std::string>::const_iterator inc = includeDirs.begin();
404 inc != includeDirs.end();
405 ++inc)
407 if (!inc->empty())
409 std::string dir = cmSystemTools::CollapseFullPath(inc->c_str());
410 if(emittedDirs.find(dir) == emittedDirs.end())
412 emittedDirs.insert(dir);
413 fout << "<pathentry include=\""
414 << cmExtraEclipseCDT4Generator::GetEclipsePath(dir)
415 << "\" kind=\"inc\" path=\"\" system=\"true\"/>\n";
421 //----------------------------------------------------------------------------
422 void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
424 std::set<std::string> emmited;
426 const cmMakefile* mf
427 = this->GlobalGenerator->GetLocalGenerators()[0]->GetMakefile();
429 const std::string filename = this->HomeOutputDirectory + "/.cproject";
431 cmGeneratedFileStream fout(filename.c_str());
432 if (!fout)
434 return;
437 // add header
438 fout <<
439 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
440 "<?fileVersion 4.0.0?>\n\n"
441 "<cproject>\n"
442 "<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n"
445 fout << "<cconfiguration id=\"org.eclipse.cdt.core.default.config.1\">\n";
447 // Configuration settings...
448 fout <<
449 "<storageModule"
450 " buildSystemId=\"org.eclipse.cdt.core.defaultConfigDataProvider\""
451 " id=\"org.eclipse.cdt.core.default.config.1\""
452 " moduleId=\"org.eclipse.cdt.core.settings\" name=\"Configuration\">\n"
453 "<externalSettings/>\n"
454 "<extensions>\n"
456 // TODO: refactor this out...
457 switch (this->GetToolChainType(*mf))
459 case EclipseToolchainLinux :
460 fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
461 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
463 fout << "<extension id=\"org.eclipse.cdt.core.GNU_ELF\""
464 " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
465 "<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
466 "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
467 "</extension>\n"
469 break;
470 case EclipseToolchainCygwin :
471 fout << "<extension id=\"org.eclipse.cdt.core.Cygwin_PE\""
472 " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
473 "<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
474 "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
475 "<attribute key=\"cygpath\" value=\"cygpath\"/>\n"
476 "<attribute key=\"nm\" value=\"nm\"/>\n"
477 "</extension>\n"
479 break;
480 case EclipseToolchainMinGW :
481 fout << "<extension id=\"org.eclipse.cdt.core.PE\""
482 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
484 break;
485 case EclipseToolchainSolaris :
486 fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
487 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
489 break;
490 case EclipseToolchainMacOSX :
491 fout << "<extension id=\"org.eclipse.cdt.core.MachO\""
492 " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
493 "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
494 "</extension>\n"
496 break;
497 case EclipseToolchainOther :
498 fout << "<extension id=\"org.eclipse.cdt.core.PE\""
499 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
501 fout << "<extension id=\"org.eclipse.cdt.core.ELF\""
502 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
504 break;
505 default :
506 // *** Should never get here ***
507 fout << "<error_toolchain_type/>\n";
509 fout << "</extensions>\n"
510 "</storageModule>\n"
513 // ???
514 fout <<
515 "<storageModule moduleId=\"org.eclipse.cdt.core.language.mapping\">\n"
516 "<project-mappings/>\n"
517 "</storageModule>\n"
520 // ???
521 fout<<"<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n"
524 // set the path entries (includes, libs, source dirs, etc.)
525 fout << "<storageModule moduleId=\"org.eclipse.cdt.core.pathentry\">\n"
527 // for each sub project with a linked resource to the source dir:
528 // - make it type 'src'
529 // - and exclude it from type 'out'
530 std::string excludeFromOut;
531 for (std::vector<std::string>::const_iterator
532 it = this->SrcLinkedResources.begin();
533 it != this->SrcLinkedResources.end();
534 ++it)
536 fout << "<pathentry kind=\"src\" path=\"" << *it << "\"/>\n";
538 // exlude source directory from output search path
539 // - only if not named the same as an output directory
540 if (!cmSystemTools::FileIsDirectory(
541 std::string(this->HomeOutputDirectory + "/" + *it).c_str()))
543 excludeFromOut += *it + "/|";
546 excludeFromOut += "**/CMakeFiles/";
547 fout << "<pathentry excluding=\"" << excludeFromOut
548 << "\" kind=\"out\" path=\"\"/>\n";
549 // add output entry for EXECUTABLE_OUTPUT_PATH and LIBRARY_OUTPUT_PATH
550 // - if it is a subdir of homeOutputDirectory, there is no need to add it
551 // - if it is not then create a linked resource and add the linked name
552 // but check it doesn't conflict with other linked resources names
553 for (std::vector<std::string>::const_iterator
554 it = this->OutLinkedResources.begin();
555 it != this->OutLinkedResources.end();
556 ++it)
558 fout << "<pathentry kind=\"out\" path=\"" << *it << "\"/>\n";
561 // add pre-processor definitions to allow eclipse to gray out sections
562 emmited.clear();
563 for (std::vector<cmLocalGenerator*>::const_iterator
564 it = this->GlobalGenerator->GetLocalGenerators().begin();
565 it != this->GlobalGenerator->GetLocalGenerators().end();
566 ++it)
569 if(const char* cdefs = (*it)->GetMakefile()->GetProperty(
570 "COMPILE_DEFINITIONS"))
572 // Expand the list.
573 std::vector<std::string> defs;
574 cmSystemTools::ExpandListArgument(cdefs, defs);
576 for(std::vector<std::string>::const_iterator di = defs.begin();
577 di != defs.end(); ++di)
579 std::string::size_type equals = di->find('=', 0);
580 std::string::size_type enddef = di->length();
582 std::string def;
583 std::string val;
584 if (equals != std::string::npos && equals < enddef)
586 // we have -DFOO=BAR
587 def = di->substr(0, equals);
588 val = di->substr(equals + 1, enddef - equals + 1);
590 else
592 // we have -DFOO
593 def = *di;
596 // insert the definition if not already added.
597 if(emmited.find(def) == emmited.end())
599 emmited.insert(def);
600 fout << "<pathentry kind=\"mac\" name=\"" << def
601 << "\" path=\"\" value=\"" << this->EscapeForXML(val)
602 << "\"/>\n";
608 // include dirs
609 emmited.clear();
610 for (std::vector<cmLocalGenerator*>::const_iterator
611 it = this->GlobalGenerator->GetLocalGenerators().begin();
612 it != this->GlobalGenerator->GetLocalGenerators().end();
613 ++it)
615 const std::vector<std::string>& includeDirs
616 = (*it)->GetMakefile()->GetIncludeDirectories();
617 this->AppendIncludeDirectories(fout, includeDirs, emmited);
619 // now also the system include directories, in case we found them in
620 // CMakeSystemSpecificInformation.cmake. This makes Eclipse find the
621 // standard headers.
622 mf->GetDefinition("CMAKE_ECLIPSE_C_SYSTEM_INCLUDE_DIRS");
623 std::string compiler = mf->GetSafeDefinition("CMAKE_C_COMPILER");
624 if (!compiler.empty())
626 std::string systemIncludeDirs = mf->GetSafeDefinition(
627 "CMAKE_ECLIPSE_C_SYSTEM_INCLUDE_DIRS");
628 std::vector<std::string> dirs;
629 cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
630 this->AppendIncludeDirectories(fout, dirs, emmited);
632 compiler = mf->GetSafeDefinition("CMAKE_CXX_COMPILER");
633 if (!compiler.empty())
635 std::string systemIncludeDirs = mf->GetSafeDefinition(
636 "CMAKE_ECLIPSE_CXX_SYSTEM_INCLUDE_DIRS");
637 std::vector<std::string> dirs;
638 cmSystemTools::ExpandListArgument(systemIncludeDirs.c_str(), dirs);
639 this->AppendIncludeDirectories(fout, dirs, emmited);
642 fout << "</storageModule>\n";
644 // add build targets
645 fout <<
646 "<storageModule moduleId=\"org.eclipse.cdt.make.core.buildtargets\">\n"
647 "<buildTargets>\n"
649 emmited.clear();
650 const std::string make = mf->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
651 cmGlobalGenerator* generator
652 = const_cast<cmGlobalGenerator*>(this->GlobalGenerator);
653 if (generator->GetAllTargetName())
655 emmited.insert(generator->GetAllTargetName());
656 this->AppendTarget(fout, generator->GetAllTargetName(), make);
658 if (generator->GetCleanTargetName())
660 emmited.insert(generator->GetCleanTargetName());
661 this->AppendTarget(fout, generator->GetCleanTargetName(), make);
664 // add all executable and library targets and some of the GLOBAL
665 // and UTILITY targets
666 for (std::vector<cmLocalGenerator*>::const_iterator
667 it = this->GlobalGenerator->GetLocalGenerators().begin();
668 it != this->GlobalGenerator->GetLocalGenerators().end();
669 ++it)
671 const cmTargets& targets = (*it)->GetMakefile()->GetTargets();
672 for(cmTargets::const_iterator t = targets.begin(); t != targets.end(); ++t)
674 bool addFastTarget = false;
675 switch(t->second.GetType())
677 case cmTarget::EXECUTABLE:
678 case cmTarget::STATIC_LIBRARY:
679 case cmTarget::SHARED_LIBRARY:
680 case cmTarget::MODULE_LIBRARY:
681 addFastTarget = true;
682 // no break here
683 case cmTarget::UTILITY:
684 case cmTarget::GLOBAL_TARGET:
686 bool insertTarget = true;
687 if(insertTarget &&
688 (std::set<std::string>::const_iterator(
689 this->TargetsToIgnore.find(t->first)) !=
690 this->TargetsToIgnore.end()))
692 insertTarget = false;
695 if(insertTarget && (emmited.find(t->first) != emmited.end()))
697 insertTarget = false;
700 // add the edit_cache target only if it's not ccmake
701 // otherwise ccmake will be executed in the log view of Eclipse,
702 // which is no terminal, so curses don't work there, Alex
703 if (insertTarget && (t->first=="edit_cache"))
705 if (strstr(mf->GetRequiredDefinition("CMAKE_EDIT_COMMAND"),
706 "ccmake")!=NULL)
708 insertTarget = false;
712 if (insertTarget)
714 emmited.insert(t->first);
715 this->AppendTarget(fout, t->first, make);
716 if (addFastTarget || t->first=="install")
718 std::string fastTarget = t->first;
719 fastTarget = fastTarget + "/fast";
720 this->AppendTarget(fout, fastTarget, make);
723 break;
725 // ignore these:
726 case cmTarget::INSTALL_FILES:
727 case cmTarget::INSTALL_PROGRAMS:
728 case cmTarget::INSTALL_DIRECTORY:
729 default:
730 break;
734 fout << "</buildTargets>\n"
735 "</storageModule>\n"
738 this->AppendStorageScanners(fout, *mf);
740 fout << "</cconfiguration>\n"
741 "</storageModule>\n"
742 "<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n"
743 "<project id=\"" << mf->GetProjectName() << ".null.1\""
744 " name=\"" << mf->GetProjectName() << "\"/>\n"
745 "</storageModule>\n"
746 "</cproject>\n"
750 //----------------------------------------------------------------------------
751 cmExtraEclipseCDT4Generator::EclipseToolchainType
752 cmExtraEclipseCDT4Generator::GetToolChainType(const cmMakefile& makefile)
754 if (makefile.IsSet("UNIX"))
756 if (makefile.IsSet("CYGWIN"))
758 return EclipseToolchainCygwin;
760 if (makefile.IsSet("APPLE" ))
762 return EclipseToolchainMacOSX;
764 // *** how do I determine if it is Solaris ???
765 return EclipseToolchainLinux;
767 else if (makefile.IsSet("WIN32"))
769 if (makefile.IsSet("MINGW"))
771 return EclipseToolchainMinGW;
773 if (makefile.IsSet("MSYS" ))
775 return EclipseToolchainMinGW;
777 return EclipseToolchainOther;
779 else
781 return EclipseToolchainOther;
785 std::string
786 cmExtraEclipseCDT4Generator::GetEclipsePath(const std::string& path)
788 #if defined(__CYGWIN__)
789 std::string cmd = "cygpath -m " + path;
790 std::string out;
791 if (!cmSystemTools::RunCommand(cmd.c_str(), out, 0, false))
793 return path;
795 else
797 out.erase(out.find_last_of('\n'));
798 return out;
800 #else
801 return path;
802 #endif
805 std::string
806 cmExtraEclipseCDT4Generator::GetPathBasename(const std::string& path)
808 std::string outputBasename = path;
809 while (outputBasename.size() > 0 &&
810 (outputBasename[outputBasename.size() - 1] == '/' ||
811 outputBasename[outputBasename.size() - 1] == '\\'))
813 outputBasename.resize(outputBasename.size() - 1);
815 std::string::size_type loc = outputBasename.find_last_of("/\\");
816 if (loc != std::string::npos)
818 outputBasename = outputBasename.substr(loc + 1);
821 return outputBasename;
824 std::string
825 cmExtraEclipseCDT4Generator::GenerateProjectName(const std::string& name,
826 const std::string& type,
827 const std::string& path)
829 return name + (type.empty() ? "" : "-") + type + "@" + path;
832 std::string cmExtraEclipseCDT4Generator::EscapeForXML(const std::string& value)
834 std::string str = value;
835 cmSystemTools::ReplaceString(str, "&", "&amp;");
836 cmSystemTools::ReplaceString(str, "<", "&lt;");
837 cmSystemTools::ReplaceString(str, ">", "&gt;");
838 cmSystemTools::ReplaceString(str, "\"", "&quot;");
839 // NOTE: This one is not necessary, since as of Eclipse CDT4 it will
840 // automatically change this to the original value (').
841 //cmSystemTools::ReplaceString(str, "'", "&apos;");
842 return str;
845 //----------------------------------------------------------------------------
846 // Helper functions
847 //----------------------------------------------------------------------------
848 void cmExtraEclipseCDT4Generator
849 ::AppendStorageScanners(cmGeneratedFileStream& fout,
850 const cmMakefile& makefile)
852 // we need the "make" and the C (or C++) compiler which are used, Alex
853 std::string make = makefile.GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
854 std::string compiler = makefile.GetSafeDefinition("CMAKE_C_COMPILER");
855 if (compiler.empty())
857 compiler = makefile.GetSafeDefinition("CMAKE_CXX_COMPILER");
859 if (compiler.empty()) //Hmm, what to do now ?
861 compiler = "gcc";
865 // the following right now hardcodes gcc behaviour :-/
866 fout <<
867 "<storageModule moduleId=\"scannerConfiguration\">\n"
868 "<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\""
869 " selectedProfileId="
870 "\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\n"
872 cmExtraEclipseCDT4Generator::AppendScannerProfile(fout,
873 "org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile",
874 true, "", true, "specsFile",
875 "-E -P -v -dD ${plugin_state_location}/${specs_file}",
876 compiler, true, true);
877 cmExtraEclipseCDT4Generator::AppendScannerProfile(fout,
878 "org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile",
879 true, "", true, "makefileGenerator",
880 "-f ${project_name}_scd.mk",
881 make, true, true);
883 fout << "</storageModule>\n";
886 void cmExtraEclipseCDT4Generator::AppendTarget(cmGeneratedFileStream& fout,
887 const std::string& target,
888 const std::string& make)
890 fout <<
891 "<target name=\"" << target << "\""
892 " path=\"\""
893 " targetID=\"org.eclipse.cdt.make.MakeTargetBuilder\">\n"
894 "<buildCommand>"
895 << cmExtraEclipseCDT4Generator::GetEclipsePath(make)
896 << "</buildCommand>\n"
897 "<buildArguments/>\n"
898 "<buildTarget>" << target << "</buildTarget>\n"
899 "<stopOnError>true</stopOnError>\n"
900 "<useDefaultCommand>false</useDefaultCommand>\n"
901 "</target>\n"
905 void cmExtraEclipseCDT4Generator
906 ::AppendScannerProfile(cmGeneratedFileStream& fout,
907 const std::string& profileID,
908 bool openActionEnabled,
909 const std::string& openActionFilePath,
910 bool pParserEnabled,
911 const std::string& scannerInfoProviderID,
912 const std::string& runActionArguments,
913 const std::string& runActionCommand,
914 bool runActionUseDefault,
915 bool sipParserEnabled)
917 fout <<
918 "<profile id=\"" << profileID << "\">\n"
919 "<buildOutputProvider>\n"
920 "<openAction enabled=\"" << (openActionEnabled ? "true" : "false")
921 << "\" filePath=\"" << openActionFilePath << "\"/>\n"
922 "<parser enabled=\"" << (pParserEnabled ? "true" : "false") << "\"/>\n"
923 "</buildOutputProvider>\n"
924 "<scannerInfoProvider id=\"" << scannerInfoProviderID << "\">\n"
925 "<runAction arguments=\"" << runActionArguments << "\""
926 " command=\"" << runActionCommand
927 << "\" useDefault=\"" << (runActionUseDefault ? "true":"false") << "\"/>\n"
928 "<parser enabled=\"" << (sipParserEnabled ? "true" : "false") << "\"/>\n"
929 "</scannerInfoProvider>\n"
930 "</profile>\n"
934 void cmExtraEclipseCDT4Generator
935 ::AppendLinkedResource (cmGeneratedFileStream& fout,
936 const std::string& name,
937 const std::string& path)
939 fout <<
940 "\t\t<link>\n"
941 "\t\t\t<name>" << name << "</name>\n"
942 "\t\t\t<type>2</type>\n"
943 "\t\t\t<location>"
944 << path
945 << "</location>\n"
946 "\t\t</link>\n"
950 bool cmExtraEclipseCDT4Generator
951 ::AppendOutLinkedResource(cmGeneratedFileStream& fout,
952 const std::string& defname,
953 const std::string& altdefname)
955 if (defname.empty() && altdefname.empty())
957 return false;
960 std::string outputPath = (defname.empty() ? altdefname : defname);
962 if (!cmSystemTools::FileIsFullPath(outputPath.c_str()))
964 outputPath = this->HomeOutputDirectory + "/" + outputPath;
966 if (cmSystemTools::IsSubDirectory(outputPath.c_str(),
967 this->HomeOutputDirectory.c_str()))
969 return false;
972 std::string name = this->GetPathBasename(outputPath);
974 // make sure linked resource name is unique
975 while (this->GlobalGenerator->GetProjectMap().find(name)
976 != this->GlobalGenerator->GetProjectMap().end())
978 name += "_";
981 if (std::find(this->OutLinkedResources.begin(),
982 this->OutLinkedResources.end(),
983 name)
984 != this->OutLinkedResources.end())
986 return false;
988 else
990 this->AppendLinkedResource(fout, name,
991 this->GetEclipsePath(outputPath));
992 this->OutLinkedResources.push_back(name);
993 return true;