1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmExtraEclipseCDT4Generator.cxx,v $
6 Date: $Date: 2009-09-16 22:01:23 $
7 Version: $Revision: 1.27 $
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"
27 #include "cmSystemTools.h"
31 //----------------------------------------------------------------------------
32 cmExtraEclipseCDT4Generator
33 ::cmExtraEclipseCDT4Generator() : cmExternalMakefileProjectGenerator()
35 // TODO: Verify if __CYGWIN__ should be checked.
36 //#if defined(_WIN32) && !defined(__CYGWIN__)
38 this->SupportedGlobalGenerators
.push_back("NMake Makefiles");
39 this->SupportedGlobalGenerators
.push_back("MinGW Makefiles");
40 // this->SupportedGlobalGenerators.push_back("MSYS Makefiles");
42 this->SupportedGlobalGenerators
.push_back("Unix Makefiles");
45 //----------------------------------------------------------------------------
46 void cmExtraEclipseCDT4Generator
47 ::GetDocumentation(cmDocumentationEntry
& entry
, const char*) const
49 entry
.Name
= this->GetName();
50 entry
.Brief
= "Generates Eclipse CDT 4.0 project files.";
52 "Project files for Eclipse will be created in the top directory "
53 "and will have a linked resource to every subdirectory which "
54 "features a CMakeLists.txt file containing a PROJECT() call."
55 "Additionally a hierarchy of makefiles is generated into the "
56 "build tree. The appropriate make program can build the project through "
57 "the default make target. A \"make install\" target is also provided.";
60 //----------------------------------------------------------------------------
61 void cmExtraEclipseCDT4Generator
62 ::SetGlobalGenerator(cmGlobalGenerator
* generator
)
64 cmExternalMakefileProjectGenerator::SetGlobalGenerator(generator
);
65 cmGlobalUnixMakefileGenerator3
* mf
66 = static_cast<cmGlobalUnixMakefileGenerator3
*>(generator
);
67 mf
->SetToolSupportsColor(true);
70 //----------------------------------------------------------------------------
71 void cmExtraEclipseCDT4Generator::Generate()
74 = this->GlobalGenerator
->GetLocalGenerators()[0]->GetMakefile();
76 // TODO: Decide if these are local or member variables
77 this->HomeDirectory
= mf
->GetHomeDirectory();
78 this->HomeOutputDirectory
= mf
->GetHomeOutputDirectory();
80 this->IsOutOfSourceBuild
= (this->HomeDirectory
!=this->HomeOutputDirectory
);
82 this->GenerateSourceProject
= (this->IsOutOfSourceBuild
&&
83 mf
->IsOn("ECLIPSE_CDT4_GENERATE_SOURCE_PROJECT"));
85 // NOTE: This is not good, since it pollutes the source tree. However,
86 // Eclipse doesn't allow CVS/SVN to work when the .project is not in
87 // the cvs/svn root directory. Hence, this is provided as an option.
88 if (this->GenerateSourceProject
)
90 // create .project file in the source tree
91 this->CreateSourceProjectFile();
94 // create a .project file
95 this->CreateProjectFile();
97 // create a .cproject file
98 this->CreateCProjectFile();
101 void cmExtraEclipseCDT4Generator::CreateSourceProjectFile() const
103 assert(this->HomeDirectory
!= this->HomeOutputDirectory
);
105 // set up the project name: <project>-Source@<baseSourcePathName>
107 = this->GlobalGenerator
->GetLocalGenerators()[0]->GetMakefile();
108 std::string name
= this->GenerateProjectName(mf
->GetProjectName(), "Source",
109 this->GetPathBasename(this->HomeDirectory
));
111 const std::string filename
= this->HomeDirectory
+ "/.project";
112 cmGeneratedFileStream
fout(filename
.c_str());
119 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
120 "<projectDescription>\n"
121 "\t<name>" << name
<< "</name>\n"
122 "\t<comment></comment>\n"
129 "</projectDescription>\n"
133 //----------------------------------------------------------------------------
134 void cmExtraEclipseCDT4Generator::CreateProjectFile()
137 = this->GlobalGenerator
->GetLocalGenerators()[0]->GetMakefile();
139 const std::string filename
= this->HomeOutputDirectory
+ "/.project";
141 cmGeneratedFileStream
fout(filename
.c_str());
148 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
149 "<projectDescription>\n"
151 this->GenerateProjectName(mf
->GetProjectName(),
152 mf
->GetDefinition("CMAKE_BUILD_TYPE"),
153 this->GetPathBasename(this->HomeOutputDirectory
))
155 "\t<comment></comment>\n"
159 "\t\t<buildCommand>\n"
160 "\t\t\t<name>org.eclipse.cdt.make.core.makeBuilder</name>\n"
161 "\t\t\t<triggers>clean,full,incremental,</triggers>\n"
162 "\t\t\t<arguments>\n"
167 "\t\t\t\t<dictionary>\n"
168 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.cleanBuildTarget</key>\n"
169 "\t\t\t\t\t<value>clean</value>\n"
170 "\t\t\t\t</dictionary>\n"
171 "\t\t\t\t<dictionary>\n"
172 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableCleanBuild</key>\n"
173 "\t\t\t\t\t<value>true</value>\n"
174 "\t\t\t\t</dictionary>\n"
175 "\t\t\t\t<dictionary>\n"
176 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.append_environment</key>\n"
177 "\t\t\t\t\t<value>true</value>\n"
178 "\t\t\t\t</dictionary>\n"
179 "\t\t\t\t<dictionary>\n"
180 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.stopOnError</key>\n"
181 "\t\t\t\t\t<value>true</value>\n"
182 "\t\t\t\t</dictionary>\n"
185 // set the make command
186 std::string make
= mf
->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
188 "\t\t\t\t<dictionary>\n"
189 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enabledIncrementalBuild</key>\n"
190 "\t\t\t\t\t<value>true</value>\n"
191 "\t\t\t\t</dictionary>\n"
192 "\t\t\t\t<dictionary>\n"
193 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.command</key>\n"
194 "\t\t\t\t\t<value>" + this->GetEclipsePath(make
) + "</value>\n"
195 "\t\t\t\t</dictionary>\n"
196 "\t\t\t\t<dictionary>\n"
197 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.contents</key>\n"
198 "\t\t\t\t\t<value>org.eclipse.cdt.make.core.activeConfigSettings</value>\n"
199 "\t\t\t\t</dictionary>\n"
200 "\t\t\t\t<dictionary>\n"
201 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.inc</key>\n"
202 "\t\t\t\t\t<value>all</value>\n"
203 "\t\t\t\t</dictionary>\n"
204 "\t\t\t\t<dictionary>\n"
205 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.arguments</key>\n"
206 "\t\t\t\t\t<value></value>\n"
207 "\t\t\t\t</dictionary>\n"
208 "\t\t\t\t<dictionary>\n"
209 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.buildLocation</key>\n"
211 << this->GetEclipsePath(this->HomeOutputDirectory
) << "</value>\n"
212 "\t\t\t\t</dictionary>\n"
213 "\t\t\t\t<dictionary>\n"
214 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.useDefaultBuildCmd</key>\n"
215 "\t\t\t\t\t<value>false</value>\n"
216 "\t\t\t\t</dictionary>\n"
219 // set project specific environment
221 "\t\t\t\t<dictionary>\n"
222 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.environment</key>\n"
223 "\t\t\t\t\t<value>VERBOSE=1|</value>\n" // enforce VERBOSE Makefile output
226 // set vsvars32.bat environment available at CMake time,
227 // but not necessarily when eclipse is open
228 if (make
.find("nmake") != std::string::npos
)
232 fout
<< "PATH=" << getenv("PATH") << "|";
234 if (getenv("INCLUDE"))
236 fout
<< "INCLUDE=" << getenv("INCLUDE") << "|";
240 fout
<< "LIB=" << getenv("LIB") << "|";
242 if (getenv("LIBPATH"))
244 fout
<< "LIBPATH=" << getenv("LIBPATH") << "|";
249 "\t\t\t\t</dictionary>\n"
253 "\t\t\t\t<dictionary>\n"
254 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableFullBuild</key>\n"
255 "\t\t\t\t\t<value>true</value>\n"
256 "\t\t\t\t</dictionary>\n"
257 "\t\t\t\t<dictionary>\n"
258 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.auto</key>\n"
259 "\t\t\t\t\t<value>all</value>\n"
260 "\t\t\t\t</dictionary>\n"
261 "\t\t\t\t<dictionary>\n"
262 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.enableAutoBuild</key>\n"
263 "\t\t\t\t\t<value>false</value>\n"
264 "\t\t\t\t</dictionary>\n"
265 "\t\t\t\t<dictionary>\n"
266 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.target.clean</key>\n"
267 "\t\t\t\t\t<value>clean</value>\n"
268 "\t\t\t\t</dictionary>\n"
269 "\t\t\t\t<dictionary>\n"
270 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.fullBuildTarget</key>\n"
271 "\t\t\t\t\t<value>all</value>\n"
272 "\t\t\t\t</dictionary>\n"
273 "\t\t\t\t<dictionary>\n"
274 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.buildArguments</key>\n"
275 "\t\t\t\t\t<value></value>\n"
276 "\t\t\t\t</dictionary>\n"
277 "\t\t\t\t<dictionary>\n"
278 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.build.location</key>\n"
280 << this->GetEclipsePath(this->HomeOutputDirectory
) << "</value>\n"
281 "\t\t\t\t</dictionary>\n"
282 "\t\t\t\t<dictionary>\n"
283 "\t\t\t\t\t<key>org.eclipse.cdt.make.core.autoBuildTarget</key>\n"
284 "\t\t\t\t\t<value>all</value>\n"
285 "\t\t\t\t</dictionary>\n"
290 "\t\t\t\t<dictionary>\n"
291 "\t\t\t\t\t<key>org.eclipse.cdt.core.errorOutputParser</key>\n"
294 if (this->GetToolChainType(*mf
) == EclipseToolchainOther
)
296 fout
<< "org.eclipse.cdt.core.VCErrorParser;";
299 "org.eclipse.cdt.core.MakeErrorParser;"
300 "org.eclipse.cdt.core.GCCErrorParser;"
301 "org.eclipse.cdt.core.GASErrorParser;"
302 "org.eclipse.cdt.core.GLDErrorParser;"
304 "\t\t\t\t</dictionary>\n"
308 "\t\t\t</arguments>\n"
309 "\t\t</buildCommand>\n"
310 "\t\t<buildCommand>\n"
311 "\t\t\t<name>org.eclipse.cdt.make.core.ScannerConfigBuilder</name>\n"
312 "\t\t\t<arguments>\n"
313 "\t\t\t</arguments>\n"
314 "\t\t</buildCommand>\n"
318 // set natures for c/c++ projects
321 // TODO: ccnature only if it is c++ ???
322 "\t\t<nature>org.eclipse.cdt.core.ccnature</nature>\n"
323 "\t\t<nature>org.eclipse.cdt.make.core.makeNature</nature>\n"
324 "\t\t<nature>org.eclipse.cdt.make.core.ScannerConfigNature</nature>\n"
325 "\t\t<nature>org.eclipse.cdt.core.cnature</nature>\n"
329 // TODO: refactor this
330 // create linked resources
331 if (this->IsOutOfSourceBuild
)
333 fout
<< "\t<linkedResources>\n";
334 // for each sub project create a linked resource to the source dir
335 // - only if it is an out-of-source build
336 for (std::map
<cmStdString
, std::vector
<cmLocalGenerator
*> >::const_iterator
337 it
= this->GlobalGenerator
->GetProjectMap().begin();
338 it
!= this->GlobalGenerator
->GetProjectMap().end();
341 std::string linkSourceDirectory
= this->GetEclipsePath(
342 it
->second
[0]->GetMakefile()->GetStartDirectory());
343 // .project dir can't be subdir of a linked resource dir
344 if (!cmSystemTools::IsSubDirectory(this->HomeOutputDirectory
.c_str(),
345 linkSourceDirectory
.c_str()))
347 this->AppendLinkedResource(fout
, it
->first
,
348 this->GetEclipsePath(linkSourceDirectory
));
349 this->SrcLinkedResources
.push_back(it
->first
);
352 // for EXECUTABLE_OUTPUT_PATH when not in binary dir
353 this->AppendOutLinkedResource(fout
,
354 mf
->GetSafeDefinition("CMAKE_RUNTIME_OUTPUT_DIRECTORY"),
355 mf
->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH"));
356 // for LIBRARY_OUTPUT_PATH when not in binary dir
357 this->AppendOutLinkedResource(fout
,
358 mf
->GetSafeDefinition("CMAKE_LIBRARY_OUTPUT_DIRECTORY"),
359 mf
->GetSafeDefinition("LIBRARY_OUTPUT_PATH"));
361 fout
<< "\t</linkedResources>\n";
364 fout
<< "</projectDescription>\n";
367 //----------------------------------------------------------------------------
368 void cmExtraEclipseCDT4Generator::AppendIncludeDirectories(
369 cmGeneratedFileStream
& fout
,
370 const std::vector
<std::string
>& includeDirs
,
371 std::set
<std::string
>& emittedDirs
)
373 for(std::vector
<std::string
>::const_iterator inc
= includeDirs
.begin();
374 inc
!= includeDirs
.end();
379 std::string dir
= cmSystemTools::CollapseFullPath(inc
->c_str());
380 if(emittedDirs
.find(dir
) == emittedDirs
.end())
382 emittedDirs
.insert(dir
);
383 fout
<< "<pathentry include=\""
384 << cmExtraEclipseCDT4Generator::GetEclipsePath(dir
)
385 << "\" kind=\"inc\" path=\"\" system=\"true\"/>\n";
391 //----------------------------------------------------------------------------
392 void cmExtraEclipseCDT4Generator::CreateCProjectFile() const
394 std::set
<std::string
> emmited
;
397 = this->GlobalGenerator
->GetLocalGenerators()[0]->GetMakefile();
399 const std::string filename
= this->HomeOutputDirectory
+ "/.cproject";
401 cmGeneratedFileStream
fout(filename
.c_str());
409 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
410 "<?fileVersion 4.0.0?>\n\n"
412 "<storageModule moduleId=\"org.eclipse.cdt.core.settings\">\n"
415 fout
<< "<cconfiguration id=\"org.eclipse.cdt.core.default.config.1\">\n";
417 // Configuration settings...
420 " buildSystemId=\"org.eclipse.cdt.core.defaultConfigDataProvider\""
421 " id=\"org.eclipse.cdt.core.default.config.1\""
422 " moduleId=\"org.eclipse.cdt.core.settings\" name=\"Configuration\">\n"
423 "<externalSettings/>\n"
426 // TODO: refactor this out...
427 switch (this->GetToolChainType(*mf
))
429 case EclipseToolchainLinux
:
430 fout
<< "<extension id=\"org.eclipse.cdt.core.ELF\""
431 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
433 fout
<< "<extension id=\"org.eclipse.cdt.core.GNU_ELF\""
434 " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
435 "<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
436 "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
440 case EclipseToolchainCygwin
:
441 fout
<< "<extension id=\"org.eclipse.cdt.core.Cygwin_PE\""
442 " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
443 "<attribute key=\"addr2line\" value=\"addr2line\"/>\n"
444 "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
445 "<attribute key=\"cygpath\" value=\"cygpath\"/>\n"
446 "<attribute key=\"nm\" value=\"nm\"/>\n"
450 case EclipseToolchainMinGW
:
451 fout
<< "<extension id=\"org.eclipse.cdt.core.PE\""
452 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
455 case EclipseToolchainSolaris
:
456 fout
<< "<extension id=\"org.eclipse.cdt.core.ELF\""
457 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
460 case EclipseToolchainMacOSX
:
461 fout
<< "<extension id=\"org.eclipse.cdt.core.MachO\""
462 " point=\"org.eclipse.cdt.core.BinaryParser\">\n"
463 "<attribute key=\"c++filt\" value=\"c++filt\"/>\n"
467 case EclipseToolchainOther
:
468 fout
<< "<extension id=\"org.eclipse.cdt.core.PE\""
469 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
471 fout
<< "<extension id=\"org.eclipse.cdt.core.ELF\""
472 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
476 // *** Should never get here ***
477 fout
<< "<error_toolchain_type/>\n";
479 fout
<< "</extensions>\n"
485 "<storageModule moduleId=\"org.eclipse.cdt.core.language.mapping\">\n"
486 "<project-mappings/>\n"
491 fout
<<"<storageModule moduleId=\"org.eclipse.cdt.core.externalSettings\"/>\n"
494 // set the path entries (includes, libs, source dirs, etc.)
495 fout
<< "<storageModule moduleId=\"org.eclipse.cdt.core.pathentry\">\n"
497 // for each sub project with a linked resource to the source dir:
498 // - make it type 'src'
499 // - and exclude it from type 'out'
500 std::string excludeFromOut
;
501 for (std::vector
<std::string
>::const_iterator
502 it
= this->SrcLinkedResources
.begin();
503 it
!= this->SrcLinkedResources
.end();
506 fout
<< "<pathentry kind=\"src\" path=\"" << *it
<< "\"/>\n";
508 // exlude source directory from output search path
509 // - only if not named the same as an output directory
510 if (!cmSystemTools::FileIsDirectory(
511 std::string(this->HomeOutputDirectory
+ "/" + *it
).c_str()))
513 excludeFromOut
+= *it
+ "/|";
516 excludeFromOut
+= "**/CMakeFiles/";
517 fout
<< "<pathentry excluding=\"" << excludeFromOut
518 << "\" kind=\"out\" path=\"\"/>\n";
519 // add output entry for EXECUTABLE_OUTPUT_PATH and LIBRARY_OUTPUT_PATH
520 // - if it is a subdir of homeOutputDirectory, there is no need to add it
521 // - if it is not then create a linked resource and add the linked name
522 // but check it doesn't conflict with other linked resources names
523 for (std::vector
<std::string
>::const_iterator
524 it
= this->OutLinkedResources
.begin();
525 it
!= this->OutLinkedResources
.end();
528 fout
<< "<pathentry kind=\"out\" path=\"" << *it
<< "\"/>\n";
531 // add pre-processor definitions to allow eclipse to gray out sections
533 for (std::vector
<cmLocalGenerator
*>::const_iterator
534 it
= this->GlobalGenerator
->GetLocalGenerators().begin();
535 it
!= this->GlobalGenerator
->GetLocalGenerators().end();
539 if(const char* cdefs
= (*it
)->GetMakefile()->GetProperty(
540 "COMPILE_DEFINITIONS"))
543 std::vector
<std::string
> defs
;
544 cmSystemTools::ExpandListArgument(cdefs
, defs
);
546 for(std::vector
<std::string
>::const_iterator di
= defs
.begin();
547 di
!= defs
.end(); ++di
)
549 std::string::size_type equals
= di
->find('=', 0);
550 std::string::size_type enddef
= di
->length();
554 if (equals
!= std::string::npos
&& equals
< enddef
)
557 def
= di
->substr(0, equals
);
558 val
= di
->substr(equals
+ 1, enddef
- equals
+ 1);
566 // insert the definition if not already added.
567 if(emmited
.find(def
) == emmited
.end())
570 fout
<< "<pathentry kind=\"mac\" name=\"" << def
571 << "\" path=\"\" value=\"" << this->EscapeForXML(val
)
577 // add system defined c macros
578 const char* cDefs
=mf
->GetDefinition("CMAKE_ECLIPSE_C_SYSTEM_DEFINED_MACROS");
582 std::vector
<std::string
> defs
;
583 cmSystemTools::ExpandListArgument(cDefs
, defs
, true);
585 // the list must contain only definition-value pairs:
586 if ((defs
.size() % 2) == 0)
588 std::vector
<std::string
>::const_iterator di
= defs
.begin();
589 while (di
!= defs
.end())
591 std::string def
= *di
;
594 if (di
!= defs
.end())
600 // insert the definition if not already added.
601 if(emmited
.find(def
) == emmited
.end())
604 fout
<< "<pathentry kind=\"mac\" name=\"" << def
605 << "\" path=\"\" value=\"" << this->EscapeForXML(val
)
611 // add system defined c++ macros
612 const char* cxxDefs
= mf
->GetDefinition(
613 "CMAKE_ECLIPSE_CXX_SYSTEM_DEFINED_MACROS");
617 std::vector
<std::string
> defs
;
618 cmSystemTools::ExpandListArgument(cxxDefs
, defs
, true);
620 // the list must contain only definition-value pairs:
621 if ((defs
.size() % 2) == 0)
623 std::vector
<std::string
>::const_iterator di
= defs
.begin();
624 while (di
!= defs
.end())
626 std::string def
= *di
;
629 if (di
!= defs
.end())
635 // insert the definition if not already added.
636 if(emmited
.find(def
) == emmited
.end())
639 fout
<< "<pathentry kind=\"mac\" name=\"" << def
640 << "\" path=\"\" value=\"" << this->EscapeForXML(val
)
649 for (std::vector
<cmLocalGenerator
*>::const_iterator
650 it
= this->GlobalGenerator
->GetLocalGenerators().begin();
651 it
!= this->GlobalGenerator
->GetLocalGenerators().end();
654 const std::vector
<std::string
>& includeDirs
655 = (*it
)->GetMakefile()->GetIncludeDirectories();
656 this->AppendIncludeDirectories(fout
, includeDirs
, emmited
);
658 // now also the system include directories, in case we found them in
659 // CMakeSystemSpecificInformation.cmake. This makes Eclipse find the
661 mf
->GetDefinition("CMAKE_ECLIPSE_C_SYSTEM_INCLUDE_DIRS");
662 std::string compiler
= mf
->GetSafeDefinition("CMAKE_C_COMPILER");
663 if (!compiler
.empty())
665 std::string systemIncludeDirs
= mf
->GetSafeDefinition(
666 "CMAKE_ECLIPSE_C_SYSTEM_INCLUDE_DIRS");
667 std::vector
<std::string
> dirs
;
668 cmSystemTools::ExpandListArgument(systemIncludeDirs
.c_str(), dirs
);
669 this->AppendIncludeDirectories(fout
, dirs
, emmited
);
671 compiler
= mf
->GetSafeDefinition("CMAKE_CXX_COMPILER");
672 if (!compiler
.empty())
674 std::string systemIncludeDirs
= mf
->GetSafeDefinition(
675 "CMAKE_ECLIPSE_CXX_SYSTEM_INCLUDE_DIRS");
676 std::vector
<std::string
> dirs
;
677 cmSystemTools::ExpandListArgument(systemIncludeDirs
.c_str(), dirs
);
678 this->AppendIncludeDirectories(fout
, dirs
, emmited
);
681 fout
<< "</storageModule>\n";
685 "<storageModule moduleId=\"org.eclipse.cdt.make.core.buildtargets\">\n"
689 const std::string make
= mf
->GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
690 cmGlobalGenerator
* generator
691 = const_cast<cmGlobalGenerator
*>(this->GlobalGenerator
);
693 std::string allTarget
;
694 std::string cleanTarget
;
695 if (generator
->GetAllTargetName())
697 allTarget
= generator
->GetAllTargetName();
699 if (generator
->GetCleanTargetName())
701 cleanTarget
= generator
->GetCleanTargetName();
704 // add all executable and library targets and some of the GLOBAL
705 // and UTILITY targets
706 for (std::vector
<cmLocalGenerator
*>::const_iterator
707 it
= this->GlobalGenerator
->GetLocalGenerators().begin();
708 it
!= this->GlobalGenerator
->GetLocalGenerators().end();
711 const cmTargets
& targets
= (*it
)->GetMakefile()->GetTargets();
712 cmMakefile
* makefile
=(*it
)->GetMakefile();
713 std::string subdir
= (*it
)->Convert(makefile
->GetCurrentOutputDirectory(),
714 cmLocalGenerator::HOME_OUTPUT
);
720 for(cmTargets::const_iterator ti
=targets
.begin(); ti
!=targets
.end(); ++ti
)
722 switch(ti
->second
.GetType())
724 case cmTarget::GLOBAL_TARGET
:
726 bool insertTarget
= false;
727 // Only add the global targets from CMAKE_BINARY_DIR,
728 // not from the subdirs
732 // only add the "edit_cache" target if it's not ccmake, because
733 // this will not work within the IDE
734 if (ti
->first
== "edit_cache")
736 if (strstr(makefile
->GetRequiredDefinition
737 ("CMAKE_EDIT_COMMAND"), "ccmake")!=NULL
)
739 insertTarget
= false;
745 this->AppendTarget(fout
, ti
->first
, make
, subdir
, ": ");
749 case cmTarget::UTILITY
:
750 // Add all utility targets, except the Nightly/Continuous/
751 // Experimental-"sub"targets as e.g. NightlyStart
752 if (((ti
->first
.find("Nightly")==0) &&(ti
->first
!="Nightly"))
753 || ((ti
->first
.find("Continuous")==0)&&(ti
->first
!="Continuous"))
754 || ((ti
->first
.find("Experimental")==0)
755 && (ti
->first
!="Experimental")))
760 this->AppendTarget(fout
, ti
->first
, make
, subdir
, ": ");
762 case cmTarget::EXECUTABLE
:
763 case cmTarget::STATIC_LIBRARY
:
764 case cmTarget::SHARED_LIBRARY
:
765 case cmTarget::MODULE_LIBRARY
:
767 const char* prefix
= (ti
->second
.GetType()==cmTarget::EXECUTABLE
?
768 "[exe] " : "[lib] ");
769 this->AppendTarget(fout
, ti
->first
, make
, subdir
, prefix
);
770 std::string fastTarget
= ti
->first
;
771 fastTarget
+= "/fast";
772 this->AppendTarget(fout
, fastTarget
, make
, subdir
, prefix
);
776 case cmTarget::INSTALL_FILES
:
777 case cmTarget::INSTALL_PROGRAMS
:
778 case cmTarget::INSTALL_DIRECTORY
:
784 // insert the all and clean targets in every subdir
785 if (!allTarget
.empty())
787 this->AppendTarget(fout
, allTarget
, make
, subdir
, ": ");
789 if (!cleanTarget
.empty())
791 this->AppendTarget(fout
, cleanTarget
, make
, subdir
, ": ");
794 //insert rules for compiling, preprocessing and assembling individual files
795 cmLocalUnixMakefileGenerator3
* lumg
=(cmLocalUnixMakefileGenerator3
*)*it
;
796 std::vector
<std::string
> objectFileTargets
;
797 lumg
->GetIndividualFileTargets(objectFileTargets
);
798 for(std::vector
<std::string
>::const_iterator fit
=objectFileTargets
.begin();
799 fit
!= objectFileTargets
.end();
802 const char* prefix
= "[obj] ";
803 if ((*fit
)[fit
->length()-1] == 's')
805 prefix
= "[to asm] ";
807 else if ((*fit
)[fit
->length()-1] == 'i')
811 this->AppendTarget(fout
, *fit
, make
, subdir
, prefix
);
815 fout
<< "</buildTargets>\n"
819 this->AppendStorageScanners(fout
, *mf
);
821 fout
<< "</cconfiguration>\n"
823 "<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n"
824 "<project id=\"" << mf
->GetProjectName() << ".null.1\""
825 " name=\"" << mf
->GetProjectName() << "\"/>\n"
831 //----------------------------------------------------------------------------
832 cmExtraEclipseCDT4Generator::EclipseToolchainType
833 cmExtraEclipseCDT4Generator::GetToolChainType(const cmMakefile
& makefile
)
835 if (makefile
.IsSet("UNIX"))
837 if (makefile
.IsSet("CYGWIN"))
839 return EclipseToolchainCygwin
;
841 if (makefile
.IsSet("APPLE" ))
843 return EclipseToolchainMacOSX
;
845 // *** how do I determine if it is Solaris ???
846 return EclipseToolchainLinux
;
848 else if (makefile
.IsSet("WIN32"))
850 if (makefile
.IsSet("MINGW"))
852 return EclipseToolchainMinGW
;
854 if (makefile
.IsSet("MSYS" ))
856 return EclipseToolchainMinGW
;
858 return EclipseToolchainOther
;
862 return EclipseToolchainOther
;
867 cmExtraEclipseCDT4Generator::GetEclipsePath(const std::string
& path
)
869 #if defined(__CYGWIN__)
870 std::string cmd
= "cygpath -m " + path
;
872 if (!cmSystemTools::RunCommand(cmd
.c_str(), out
, 0, false))
878 out
.erase(out
.find_last_of('\n'));
887 cmExtraEclipseCDT4Generator::GetPathBasename(const std::string
& path
)
889 std::string outputBasename
= path
;
890 while (outputBasename
.size() > 0 &&
891 (outputBasename
[outputBasename
.size() - 1] == '/' ||
892 outputBasename
[outputBasename
.size() - 1] == '\\'))
894 outputBasename
.resize(outputBasename
.size() - 1);
896 std::string::size_type loc
= outputBasename
.find_last_of("/\\");
897 if (loc
!= std::string::npos
)
899 outputBasename
= outputBasename
.substr(loc
+ 1);
902 return outputBasename
;
906 cmExtraEclipseCDT4Generator::GenerateProjectName(const std::string
& name
,
907 const std::string
& type
,
908 const std::string
& path
)
910 return name
+ (type
.empty() ? "" : "-") + type
+ "@" + path
;
913 std::string
cmExtraEclipseCDT4Generator::EscapeForXML(const std::string
& value
)
915 std::string str
= value
;
916 cmSystemTools::ReplaceString(str
, "&", "&");
917 cmSystemTools::ReplaceString(str
, "<", "<");
918 cmSystemTools::ReplaceString(str
, ">", ">");
919 cmSystemTools::ReplaceString(str
, "\"", """);
920 // NOTE: This one is not necessary, since as of Eclipse CDT4 it will
921 // automatically change this to the original value (').
922 //cmSystemTools::ReplaceString(str, "'", "'");
926 //----------------------------------------------------------------------------
928 //----------------------------------------------------------------------------
929 void cmExtraEclipseCDT4Generator
930 ::AppendStorageScanners(cmGeneratedFileStream
& fout
,
931 const cmMakefile
& makefile
)
933 // we need the "make" and the C (or C++) compiler which are used, Alex
934 std::string make
= makefile
.GetRequiredDefinition("CMAKE_MAKE_PROGRAM");
935 std::string compiler
= makefile
.GetSafeDefinition("CMAKE_C_COMPILER");
936 if (compiler
.empty())
938 compiler
= makefile
.GetSafeDefinition("CMAKE_CXX_COMPILER");
940 if (compiler
.empty()) //Hmm, what to do now ?
946 // the following right now hardcodes gcc behaviour :-/
948 "<storageModule moduleId=\"scannerConfiguration\">\n"
949 "<autodiscovery enabled=\"true\" problemReportingEnabled=\"true\""
950 " selectedProfileId="
951 "\"org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile\"/>\n"
953 cmExtraEclipseCDT4Generator::AppendScannerProfile(fout
,
954 "org.eclipse.cdt.make.core.GCCStandardMakePerProjectProfile",
955 true, "", true, "specsFile",
956 "-E -P -v -dD ${plugin_state_location}/${specs_file}",
957 compiler
, true, true);
958 cmExtraEclipseCDT4Generator::AppendScannerProfile(fout
,
959 "org.eclipse.cdt.make.core.GCCStandardMakePerFileProfile",
960 true, "", true, "makefileGenerator",
961 "-f ${project_name}_scd.mk",
964 fout
<< "</storageModule>\n";
967 // The prefix is prepended before the actual name of the target. The purpose
968 // of that is to sort the targets in the view of Eclipse, so that at first
969 // the global/utility/all/clean targets appear ": ", then the executable
970 // targets "[exe] ", then the libraries "[lib]", then the rules for the
971 // object files "[obj]", then for preprocessing only "[pre] " and
972 // finally the assembly files "[to asm] ". Note the "to" in "to asm",
973 // without it, "asm" would be the first targets in the list, with the "to"
974 // they are the last targets, which makes more sense.
975 void cmExtraEclipseCDT4Generator::AppendTarget(cmGeneratedFileStream
& fout
,
976 const std::string
& target
,
977 const std::string
& make
,
978 const std::string
& path
,
982 "<target name=\"" << prefix
<< target
<< "\""
983 " path=\"" << path
.c_str() << "\""
984 " targetID=\"org.eclipse.cdt.make.MakeTargetBuilder\">\n"
986 << cmExtraEclipseCDT4Generator::GetEclipsePath(make
)
987 << "</buildCommand>\n"
988 "<buildArguments/>\n"
989 "<buildTarget>" << target
<< "</buildTarget>\n"
990 "<stopOnError>true</stopOnError>\n"
991 "<useDefaultCommand>false</useDefaultCommand>\n"
996 void cmExtraEclipseCDT4Generator
997 ::AppendScannerProfile(cmGeneratedFileStream
& fout
,
998 const std::string
& profileID
,
999 bool openActionEnabled
,
1000 const std::string
& openActionFilePath
,
1001 bool pParserEnabled
,
1002 const std::string
& scannerInfoProviderID
,
1003 const std::string
& runActionArguments
,
1004 const std::string
& runActionCommand
,
1005 bool runActionUseDefault
,
1006 bool sipParserEnabled
)
1009 "<profile id=\"" << profileID
<< "\">\n"
1010 "<buildOutputProvider>\n"
1011 "<openAction enabled=\"" << (openActionEnabled
? "true" : "false")
1012 << "\" filePath=\"" << openActionFilePath
<< "\"/>\n"
1013 "<parser enabled=\"" << (pParserEnabled
? "true" : "false") << "\"/>\n"
1014 "</buildOutputProvider>\n"
1015 "<scannerInfoProvider id=\"" << scannerInfoProviderID
<< "\">\n"
1016 "<runAction arguments=\"" << runActionArguments
<< "\""
1017 " command=\"" << runActionCommand
1018 << "\" useDefault=\"" << (runActionUseDefault
? "true":"false") << "\"/>\n"
1019 "<parser enabled=\"" << (sipParserEnabled
? "true" : "false") << "\"/>\n"
1020 "</scannerInfoProvider>\n"
1025 void cmExtraEclipseCDT4Generator
1026 ::AppendLinkedResource (cmGeneratedFileStream
& fout
,
1027 const std::string
& name
,
1028 const std::string
& path
)
1032 "\t\t\t<name>" << name
<< "</name>\n"
1033 "\t\t\t<type>2</type>\n"
1041 bool cmExtraEclipseCDT4Generator
1042 ::AppendOutLinkedResource(cmGeneratedFileStream
& fout
,
1043 const std::string
& defname
,
1044 const std::string
& altdefname
)
1046 if (defname
.empty() && altdefname
.empty())
1051 std::string outputPath
= (defname
.empty() ? altdefname
: defname
);
1053 if (!cmSystemTools::FileIsFullPath(outputPath
.c_str()))
1055 outputPath
= this->HomeOutputDirectory
+ "/" + outputPath
;
1057 if (cmSystemTools::IsSubDirectory(outputPath
.c_str(),
1058 this->HomeOutputDirectory
.c_str()))
1063 std::string name
= this->GetPathBasename(outputPath
);
1065 // make sure linked resource name is unique
1066 while (this->GlobalGenerator
->GetProjectMap().find(name
)
1067 != this->GlobalGenerator
->GetProjectMap().end())
1072 if (std::find(this->OutLinkedResources
.begin(),
1073 this->OutLinkedResources
.end(),
1075 != this->OutLinkedResources
.end())
1081 this->AppendLinkedResource(fout
, name
,
1082 this->GetEclipsePath(outputPath
));
1083 this->OutLinkedResources
.push_back(name
);