1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmExtraEclipseCDT4Generator.cxx,v $
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"
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");
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.";
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()
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>
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());
149 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
150 "<projectDescription>\n"
151 "\t<name>" << name
<< "</name>\n"
152 "\t<comment></comment>\n"
159 "</projectDescription>\n"
163 //----------------------------------------------------------------------------
164 void cmExtraEclipseCDT4Generator::CreateProjectFile()
167 = this->GlobalGenerator
->GetLocalGenerators()[0]->GetMakefile();
169 const std::string filename
= this->HomeOutputDirectory
+ "/.project";
171 cmGeneratedFileStream
fout(filename
.c_str());
178 "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
179 "<projectDescription>\n"
181 this->GenerateProjectName(mf
->GetProjectName(),
182 mf
->GetDefinition("CMAKE_BUILD_TYPE"),
183 this->GetPathBasename(this->HomeOutputDirectory
))
185 "\t<comment></comment>\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"
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");
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"
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
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
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
)
262 fout
<< "PATH=" << getenv("PATH") << "|";
264 if (getenv("INCLUDE"))
266 fout
<< "INCLUDE=" << getenv("INCLUDE") << "|";
270 fout
<< "LIB=" << getenv("LIB") << "|";
272 if (getenv("LIBPATH"))
274 fout
<< "LIBPATH=" << getenv("LIBPATH") << "|";
279 "\t\t\t\t</dictionary>\n"
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"
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"
320 "\t\t\t\t<dictionary>\n"
321 "\t\t\t\t\t<key>org.eclipse.cdt.core.errorOutputParser</key>\n"
324 if (this->GetToolChainType(*mf
) == EclipseToolchainOther
)
326 fout
<< "org.eclipse.cdt.core.VCErrorParser;";
329 "org.eclipse.cdt.core.MakeErrorParser;"
330 "org.eclipse.cdt.core.GCCErrorParser;"
331 "org.eclipse.cdt.core.GASErrorParser;"
332 "org.eclipse.cdt.core.GLDErrorParser;"
334 "\t\t\t\t</dictionary>\n"
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"
348 // set natures for c/c++ projects
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"
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();
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();
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
;
427 = this->GlobalGenerator
->GetLocalGenerators()[0]->GetMakefile();
429 const std::string filename
= this->HomeOutputDirectory
+ "/.cproject";
431 cmGeneratedFileStream
fout(filename
.c_str());
439 "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n"
440 "<?fileVersion 4.0.0?>\n\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...
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"
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"
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"
480 case EclipseToolchainMinGW
:
481 fout
<< "<extension id=\"org.eclipse.cdt.core.PE\""
482 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
485 case EclipseToolchainSolaris
:
486 fout
<< "<extension id=\"org.eclipse.cdt.core.ELF\""
487 " point=\"org.eclipse.cdt.core.BinaryParser\"/>\n"
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"
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"
506 // *** Should never get here ***
507 fout
<< "<error_toolchain_type/>\n";
509 fout
<< "</extensions>\n"
515 "<storageModule moduleId=\"org.eclipse.cdt.core.language.mapping\">\n"
516 "<project-mappings/>\n"
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();
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();
558 fout
<< "<pathentry kind=\"out\" path=\"" << *it
<< "\"/>\n";
561 // add pre-processor definitions to allow eclipse to gray out sections
563 for (std::vector
<cmLocalGenerator
*>::const_iterator
564 it
= this->GlobalGenerator
->GetLocalGenerators().begin();
565 it
!= this->GlobalGenerator
->GetLocalGenerators().end();
569 if(const char* cdefs
= (*it
)->GetMakefile()->GetProperty(
570 "COMPILE_DEFINITIONS"))
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();
584 if (equals
!= std::string::npos
&& equals
< enddef
)
587 def
= di
->substr(0, equals
);
588 val
= di
->substr(equals
+ 1, enddef
- equals
+ 1);
596 // insert the definition if not already added.
597 if(emmited
.find(def
) == emmited
.end())
600 fout
<< "<pathentry kind=\"mac\" name=\"" << def
601 << "\" path=\"\" value=\"" << this->EscapeForXML(val
)
610 for (std::vector
<cmLocalGenerator
*>::const_iterator
611 it
= this->GlobalGenerator
->GetLocalGenerators().begin();
612 it
!= this->GlobalGenerator
->GetLocalGenerators().end();
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
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";
646 "<storageModule moduleId=\"org.eclipse.cdt.make.core.buildtargets\">\n"
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();
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;
683 case cmTarget::UTILITY
:
684 case cmTarget::GLOBAL_TARGET
:
686 bool insertTarget
= true;
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"),
708 insertTarget
= false;
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
);
726 case cmTarget::INSTALL_FILES
:
727 case cmTarget::INSTALL_PROGRAMS
:
728 case cmTarget::INSTALL_DIRECTORY
:
734 fout
<< "</buildTargets>\n"
738 this->AppendStorageScanners(fout
, *mf
);
740 fout
<< "</cconfiguration>\n"
742 "<storageModule moduleId=\"cdtBuildSystem\" version=\"4.0.0\">\n"
743 "<project id=\"" << mf
->GetProjectName() << ".null.1\""
744 " name=\"" << mf
->GetProjectName() << "\"/>\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
;
781 return EclipseToolchainOther
;
786 cmExtraEclipseCDT4Generator::GetEclipsePath(const std::string
& path
)
788 #if defined(__CYGWIN__)
789 std::string cmd
= "cygpath -m " + path
;
791 if (!cmSystemTools::RunCommand(cmd
.c_str(), out
, 0, false))
797 out
.erase(out
.find_last_of('\n'));
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
;
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
, "&", "&");
836 cmSystemTools::ReplaceString(str
, "<", "<");
837 cmSystemTools::ReplaceString(str
, ">", ">");
838 cmSystemTools::ReplaceString(str
, "\"", """);
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, "'", "'");
845 //----------------------------------------------------------------------------
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 ?
865 // the following right now hardcodes gcc behaviour :-/
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",
883 fout
<< "</storageModule>\n";
886 void cmExtraEclipseCDT4Generator::AppendTarget(cmGeneratedFileStream
& fout
,
887 const std::string
& target
,
888 const std::string
& make
)
891 "<target name=\"" << target
<< "\""
893 " targetID=\"org.eclipse.cdt.make.MakeTargetBuilder\">\n"
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"
905 void cmExtraEclipseCDT4Generator
906 ::AppendScannerProfile(cmGeneratedFileStream
& fout
,
907 const std::string
& profileID
,
908 bool openActionEnabled
,
909 const std::string
& openActionFilePath
,
911 const std::string
& scannerInfoProviderID
,
912 const std::string
& runActionArguments
,
913 const std::string
& runActionCommand
,
914 bool runActionUseDefault
,
915 bool sipParserEnabled
)
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"
934 void cmExtraEclipseCDT4Generator
935 ::AppendLinkedResource (cmGeneratedFileStream
& fout
,
936 const std::string
& name
,
937 const std::string
& path
)
941 "\t\t\t<name>" << name
<< "</name>\n"
942 "\t\t\t<type>2</type>\n"
950 bool cmExtraEclipseCDT4Generator
951 ::AppendOutLinkedResource(cmGeneratedFileStream
& fout
,
952 const std::string
& defname
,
953 const std::string
& altdefname
)
955 if (defname
.empty() && altdefname
.empty())
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()))
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())
981 if (std::find(this->OutLinkedResources
.begin(),
982 this->OutLinkedResources
.end(),
984 != this->OutLinkedResources
.end())
990 this->AppendLinkedResource(fout
, name
,
991 this->GetEclipsePath(outputPath
));
992 this->OutLinkedResources
.push_back(name
);