1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmLocalVisualStudio6Generator.cxx,v $
6 Date: $Date: 2009-09-02 20:07:10 $
7 Version: $Revision: 1.159 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmGlobalGenerator.h"
18 #include "cmLocalVisualStudio6Generator.h"
19 #include "cmMakefile.h"
20 #include "cmSystemTools.h"
21 #include "cmSourceFile.h"
22 #include "cmCacheManager.h"
25 #include "cmComputeLinkInformation.h"
27 #include <cmsys/RegularExpression.hxx>
29 cmLocalVisualStudio6Generator::cmLocalVisualStudio6Generator()
33 cmLocalVisualStudio6Generator::~cmLocalVisualStudio6Generator()
37 //----------------------------------------------------------------------------
38 // Helper class to write build events.
39 class cmLocalVisualStudio6Generator::EventWriter
42 EventWriter(cmLocalVisualStudio6Generator
* lg
,
43 const char* config
, std::string
& code
):
44 LG(lg
), Config(config
), Code(code
), First(true) {}
45 void Start(const char* event
)
52 this->Code
+= (this->First
? "" : "\n");
54 void Write(std::vector
<cmCustomCommand
> const& ccs
)
56 for(std::vector
<cmCustomCommand
>::const_iterator ci
= ccs
.begin();
57 ci
!= ccs
.end(); ++ci
)
62 void Write(cmCustomCommand
const& cc
)
66 this->Code
+= this->Event
+ "_Cmds=";
71 this->Code
+= "\\\n\t";
74 this->LG
->ConstructScript(cc
.GetCommandLines(),
75 cc
.GetWorkingDirectory(),
77 cc
.GetEscapeOldStyle(),
78 cc
.GetEscapeAllowMakeVars(),
82 cmLocalVisualStudio6Generator
* LG
;
89 void cmLocalVisualStudio6Generator::AddHelperCommands()
91 std::set
<cmStdString
> lang
;
94 this->CreateCustomTargetsAndCommands(lang
);
97 void cmLocalVisualStudio6Generator::Generate()
99 this->OutputDSPFile();
102 void cmLocalVisualStudio6Generator::OutputDSPFile()
104 // If not an in source build, then create the output directory
105 if(strcmp(this->Makefile
->GetStartOutputDirectory(),
106 this->Makefile
->GetHomeDirectory()) != 0)
108 if(!cmSystemTools::MakeDirectory
109 (this->Makefile
->GetStartOutputDirectory()))
111 cmSystemTools::Error("Error creating directory ",
112 this->Makefile
->GetStartOutputDirectory());
116 // Setup /I and /LIBPATH options for the resulting DSP file. VS 6
117 // truncates long include paths so make it as short as possible if
118 // the length threatens this problem.
119 unsigned int maxIncludeLength
= 3000;
120 bool useShortPath
= false;
121 for(int j
=0; j
< 2; ++j
)
123 std::vector
<std::string
> includes
;
124 this->GetIncludeDirectories(includes
);
125 std::vector
<std::string
>::iterator i
;
126 for(i
= includes
.begin(); i
!= includes
.end(); ++i
)
129 this->ConvertToOptionallyRelativeOutputPath(i
->c_str());
132 cmSystemTools::GetShortPath(tmp
.c_str(), tmp
);
134 this->IncludeOptions
+= " /I ";
136 // quote if not already quoted
139 this->IncludeOptions
+= "\"";
140 this->IncludeOptions
+= tmp
;
141 this->IncludeOptions
+= "\"";
145 this->IncludeOptions
+= tmp
;
148 if(j
== 0 && this->IncludeOptions
.size() > maxIncludeLength
)
150 this->IncludeOptions
= "";
159 // Create the DSP or set of DSP's for libraries and executables
161 // clear project names
162 this->CreatedProjectNames
.clear();
163 cmTargets
&tgts
= this->Makefile
->GetTargets();
164 for(cmTargets::iterator l
= tgts
.begin();
165 l
!= tgts
.end(); l
++)
167 // Add a rule to regenerate the build system when the target
168 // specification source changes.
169 const char* suppRegenRule
=
170 this->Makefile
->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
171 if (!cmSystemTools::IsOn(suppRegenRule
))
173 this->AddDSPBuildRule(l
->second
);
178 for(cmTargets::iterator l
= tgts
.begin();
179 l
!= tgts
.end(); l
++)
181 switch(l
->second
.GetType())
183 case cmTarget::STATIC_LIBRARY
:
184 this->SetBuildType(STATIC_LIBRARY
, l
->first
.c_str(), l
->second
);
186 case cmTarget::SHARED_LIBRARY
:
187 case cmTarget::MODULE_LIBRARY
:
188 this->SetBuildType(DLL
, l
->first
.c_str(), l
->second
);
190 case cmTarget::EXECUTABLE
:
191 this->SetBuildType(EXECUTABLE
,l
->first
.c_str(), l
->second
);
193 case cmTarget::UTILITY
:
194 case cmTarget::GLOBAL_TARGET
:
195 this->SetBuildType(UTILITY
, l
->first
.c_str(), l
->second
);
198 cmSystemTools::Error("Bad target type", l
->first
.c_str());
201 // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
202 // so don't build a projectfile for it
204 l
->second
.GetProperty("EXTERNAL_MSPROJECT");
207 // check to see if the dsp is going into a sub-directory
208 std::string::size_type pos
= l
->first
.rfind('/');
209 if(pos
!= std::string::npos
)
211 std::string dir
= this->Makefile
->GetStartOutputDirectory();
213 dir
+= l
->first
.substr(0, pos
);
214 if(!cmSystemTools::MakeDirectory(dir
.c_str()))
216 cmSystemTools::Error("Error creating directory ", dir
.c_str());
219 this->CreateSingleDSP(l
->first
.c_str(),l
->second
);
224 // Utility function to make a valid VS6 *.dsp filename out
225 // of a CMake target name:
227 extern std::string
GetVS6TargetName(const std::string
& targetName
);
229 void cmLocalVisualStudio6Generator::CreateSingleDSP(const char *lname
,
232 // add to the list of projects
233 std::string pname
= GetVS6TargetName(lname
);
235 this->CreatedProjectNames
.push_back(pname
);
236 // create the dsp.cmake file
238 fname
= this->Makefile
->GetStartOutputDirectory();
242 // save the name of the real dsp file
243 std::string realDSP
= fname
;
245 std::ofstream
fout(fname
.c_str());
248 cmSystemTools::Error("Error Writing ", fname
.c_str());
249 cmSystemTools::ReportLastSystemError("");
251 this->WriteDSPFile(fout
,pname
.c_str(),target
);
253 // if the dsp file has changed, then write it.
254 cmSystemTools::CopyFileIfDifferent(fname
.c_str(), realDSP
.c_str());
258 void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmTarget
& tgt
)
260 std::string dspname
= GetVS6TargetName(tgt
.GetName());
261 dspname
+= ".dsp.cmake";
262 const char* dsprule
=
263 this->Makefile
->GetRequiredDefinition("CMAKE_COMMAND");
264 cmCustomCommandLine commandLine
;
265 commandLine
.push_back(dsprule
);
266 std::string makefileIn
= this->Makefile
->GetStartDirectory();
268 makefileIn
+= "CMakeLists.txt";
269 if(!cmSystemTools::FileExists(makefileIn
.c_str()))
273 std::string comment
= "Building Custom Rule ";
274 comment
+= makefileIn
;
277 args
+= this->Convert(this->Makefile
->GetHomeDirectory(),
278 START_OUTPUT
, UNCHANGED
, true);
279 commandLine
.push_back(args
);
282 this->Convert(this->Makefile
->GetHomeOutputDirectory(),
283 START_OUTPUT
, UNCHANGED
, true);
284 commandLine
.push_back(args
);
286 std::vector
<std::string
> const& listFiles
= this->Makefile
->GetListFiles();
288 cmCustomCommandLines commandLines
;
289 commandLines
.push_back(commandLine
);
290 const char* no_working_directory
= 0;
291 this->Makefile
->AddCustomCommandToOutput(dspname
.c_str(), listFiles
,
292 makefileIn
.c_str(), commandLines
,
294 no_working_directory
, true);
295 if(cmSourceFile
* file
= this->Makefile
->GetSource(makefileIn
.c_str()))
297 tgt
.AddSourceFile(file
);
301 cmSystemTools::Error("Error adding rule for ", makefileIn
.c_str());
306 void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream
& fout
,
310 // For utility targets need custom command since pre- and post-
311 // build does not do anything in Visual Studio 6. In order for the
312 // rules to run in the correct order as custom commands, we need
313 // special care for dependencies. The first rule must depend on all
314 // the dependencies of all the rules. The later rules must each
315 // depend only on the previous rule.
316 if ((target
.GetType() == cmTarget::UTILITY
||
317 target
.GetType() == cmTarget::GLOBAL_TARGET
) &&
318 (!target
.GetPreBuildCommands().empty() ||
319 !target
.GetPostBuildCommands().empty()))
321 // Accumulate the dependencies of all the commands.
322 std::vector
<std::string
> depends
;
323 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
324 target
.GetPreBuildCommands().begin();
325 cr
!= target
.GetPreBuildCommands().end(); ++cr
)
327 depends
.insert(depends
.end(),
328 cr
->GetDepends().begin(), cr
->GetDepends().end());
330 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
331 target
.GetPostBuildCommands().begin();
332 cr
!= target
.GetPostBuildCommands().end(); ++cr
)
334 depends
.insert(depends
.end(),
335 cr
->GetDepends().begin(), cr
->GetDepends().end());
338 // Add the pre- and post-build commands in order.
340 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
341 target
.GetPreBuildCommands().begin();
342 cr
!= target
.GetPreBuildCommands().end(); ++cr
)
344 this->AddUtilityCommandHack(target
, count
++, depends
, *cr
);
346 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
347 target
.GetPostBuildCommands().begin();
348 cr
!= target
.GetPostBuildCommands().end(); ++cr
)
350 this->AddUtilityCommandHack(target
, count
++, depends
, *cr
);
354 // We may be modifying the source groups temporarily, so make a copy.
355 std::vector
<cmSourceGroup
> sourceGroups
= this->Makefile
->GetSourceGroups();
357 // get the classes from the source lists then add them to the groups
358 std::vector
<cmSourceFile
*> const & classes
= target
.GetSourceFiles();
360 // now all of the source files have been properly assigned to the target
361 // now stick them into source groups using the reg expressions
362 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
363 i
!= classes
.end(); i
++)
365 // Add the file to the list of sources.
366 std::string source
= (*i
)->GetFullPath();
367 cmSourceGroup
& sourceGroup
=
368 this->Makefile
->FindSourceGroup(source
.c_str(), sourceGroups
);
369 sourceGroup
.AssignSource(*i
);
370 // while we are at it, if it is a .rule file then for visual studio 6 we
372 if ((*i
)->GetExtension() == "rule")
374 if(!cmSystemTools::FileExists(source
.c_str()))
376 cmSystemTools::ReplaceString(source
, "$(IntDir)/", "");
377 #if defined(_WIN32) || defined(__CYGWIN__)
378 std::ofstream
fout(source
.c_str(),
379 std::ios::binary
| std::ios::out
382 std::ofstream
fout(source
.c_str(),
383 std::ios::out
| std::ios::trunc
);
387 fout
.write("# generated from CMake",22);
395 // Compute which sources need unique object computation.
396 this->ComputeObjectNameRequirements(sourceGroups
);
398 // Write the DSP file's header.
399 this->WriteDSPHeader(fout
, libName
, target
, sourceGroups
);
402 // Loop through every source group.
403 for(std::vector
<cmSourceGroup
>::const_iterator sg
= sourceGroups
.begin();
404 sg
!= sourceGroups
.end(); ++sg
)
406 this->WriteGroup(&(*sg
), target
, fout
, libName
);
409 // Write the DSP file's footer.
410 this->WriteDSPFooter(fout
);
413 void cmLocalVisualStudio6Generator
414 ::WriteGroup(const cmSourceGroup
*sg
, cmTarget
& target
,
415 std::ostream
&fout
, const char *libName
)
417 const std::vector
<const cmSourceFile
*> &sourceFiles
=
418 sg
->GetSourceFiles();
419 // If the group is empty, don't write it at all.
421 if(sourceFiles
.empty() && sg
->GetGroupChildren().empty())
426 // If the group has a name, write the header.
427 std::string name
= sg
->GetName();
430 this->WriteDSPBeginGroup(fout
, name
.c_str(), "");
433 // Compute the maximum length configuration name.
434 std::string config_max
;
435 for(std::vector
<std::string
>::iterator i
= this->Configurations
.begin();
436 i
!= this->Configurations
.end(); ++i
)
438 // Strip the subdirectory name out of the configuration name.
439 std::string config
= this->GetConfigName(*i
);
440 if(config
.size() > config_max
.size())
446 // Compute the maximum length full path to the intermediate
447 // files directory for any configuration. This is used to construct
448 // object file names that do not produce paths that are too long.
450 dir_max
+= this->Makefile
->GetCurrentOutputDirectory();
452 dir_max
+= config_max
;
455 // Loop through each source in the source group.
456 for(std::vector
<const cmSourceFile
*>::const_iterator sf
=
457 sourceFiles
.begin(); sf
!= sourceFiles
.end(); ++sf
)
459 std::string source
= (*sf
)->GetFullPath();
460 const cmCustomCommand
*command
=
461 (*sf
)->GetCustomCommand();
462 std::string compileFlags
;
463 std::vector
<std::string
> depends
;
464 std::string objectNameDir
;
465 if(this->NeedObjectName
.find(*sf
) != this->NeedObjectName
.end())
468 cmSystemTools::GetFilenamePath(
469 this->GetObjectFileNameWithoutTarget(*(*sf
), dir_max
));
472 // Add per-source file flags.
473 if(const char* cflags
= (*sf
)->GetProperty("COMPILE_FLAGS"))
475 compileFlags
+= cflags
;
478 const char* lang
= this->GetSourceFileLanguage(*(*sf
));
481 if(strcmp(lang
, "CXX") == 0)
483 // force a C++ file type
484 compileFlags
+= " /TP ";
486 else if(strcmp(lang
, "C") == 0)
488 // force to c file type
489 compileFlags
+= " /TC ";
493 // Add per-source and per-configuration preprocessor definitions.
494 std::map
<cmStdString
, cmStdString
> cdmap
;
495 this->AppendDefines(compileFlags
,
496 (*sf
)->GetProperty("COMPILE_DEFINITIONS"), lang
);
497 if(const char* cdefs
= (*sf
)->GetProperty("COMPILE_DEFINITIONS_DEBUG"))
499 this->AppendDefines(cdmap
["DEBUG"], cdefs
, lang
);
501 if(const char* cdefs
= (*sf
)->GetProperty("COMPILE_DEFINITIONS_RELEASE"))
503 this->AppendDefines(cdmap
["RELEASE"], cdefs
, lang
);
505 if(const char* cdefs
=
506 (*sf
)->GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"))
508 this->AppendDefines(cdmap
["MINSIZEREL"], cdefs
, lang
);
510 if(const char* cdefs
=
511 (*sf
)->GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"))
513 this->AppendDefines(cdmap
["RELWITHDEBINFO"], cdefs
, lang
);
516 bool excludedFromBuild
=
517 (lang
&& (*sf
)->GetPropertyAsBool("HEADER_FILE_ONLY"));
519 // Check for extra object-file dependencies.
520 const char* dependsValue
= (*sf
)->GetProperty("OBJECT_DEPENDS");
523 cmSystemTools::ExpandListArgument(dependsValue
, depends
);
525 if (GetVS6TargetName(source
) != libName
||
526 target
.GetType() == cmTarget::UTILITY
||
527 target
.GetType() == cmTarget::GLOBAL_TARGET
)
529 fout
<< "# Begin Source File\n\n";
531 // Tell MS-Dev what the source is. If the compiler knows how to
532 // build it, then it will.
534 this->ConvertToOptionallyRelativeOutputPath(source
.c_str()) << "\n\n";
537 // Write out the dependencies for the rule.
538 fout
<< "USERDEP__HACK=";
539 for(std::vector
<std::string
>::const_iterator d
= depends
.begin();
540 d
!= depends
.end(); ++d
)
543 this->ConvertToOptionallyRelativeOutputPath(d
->c_str());
549 const char* flags
= compileFlags
.size() ? compileFlags
.c_str(): 0;
550 this->WriteCustomRule(fout
, source
.c_str(), *command
, flags
);
552 else if(!compileFlags
.empty() || !objectNameDir
.empty() ||
553 excludedFromBuild
|| !cdmap
.empty())
555 for(std::vector
<std::string
>::iterator i
556 = this->Configurations
.begin();
557 i
!= this->Configurations
.end(); ++i
)
559 // Strip the subdirectory name out of the configuration name.
560 std::string config
= this->GetConfigName(*i
);
561 if (i
== this->Configurations
.begin())
563 fout
<< "!IF \"$(CFG)\" == " << i
->c_str() << std::endl
;
567 fout
<< "!ELSEIF \"$(CFG)\" == " << i
->c_str() << std::endl
;
569 if(excludedFromBuild
)
571 fout
<< "# PROP Exclude_From_Build 1\n";
573 if(!compileFlags
.empty())
575 fout
<< "\n# ADD CPP " << compileFlags
<< "\n\n";
577 std::map
<cmStdString
, cmStdString
>::iterator cdi
=
578 cdmap
.find(cmSystemTools::UpperCase(config
));
579 if(cdi
!= cdmap
.end() && !cdi
->second
.empty())
581 fout
<< "\n# ADD CPP " << cdi
->second
<< "\n\n";
583 if(!objectNameDir
.empty())
585 // Setup an alternate object file directory.
586 fout
<< "\n# PROP Intermediate_Dir \""
587 << config
<< "/" << objectNameDir
<< "\"\n\n";
590 fout
<< "!ENDIF\n\n";
592 fout
<< "# End Source File\n";
596 std::vector
<cmSourceGroup
> const& children
= sg
->GetGroupChildren();
598 for(unsigned int i
=0;i
<children
.size();++i
)
600 this->WriteGroup(&children
[i
], target
, fout
, libName
);
606 // If the group has a name, write the footer.
609 this->WriteDSPEndGroup(fout
);
616 cmLocalVisualStudio6Generator
617 ::AddUtilityCommandHack(cmTarget
& target
, int count
,
618 std::vector
<std::string
>& depends
,
619 const cmCustomCommand
& origCommand
)
621 // Create a fake output that forces the rule to run.
622 char* output
= new char[(strlen(this->Makefile
->GetStartOutputDirectory()) +
623 strlen(target
.GetName()) + 30)];
624 sprintf(output
,"%s/%s_force_%i", this->Makefile
->GetStartOutputDirectory(),
625 target
.GetName(), count
);
626 std::string comment
= this->ConstructComment(origCommand
, "<hack>");
628 // Add the rule with the given dependencies and commands.
629 const char* no_main_dependency
= 0;
630 this->Makefile
->AddCustomCommandToOutput(output
,
633 origCommand
.GetCommandLines(),
635 origCommand
.GetWorkingDirectory());
637 // Replace the dependencies with the output of this rule so that the
638 // next rule added will run after this one.
640 depends
.push_back(output
);
642 // Add a source file representing this output to the project.
643 cmSourceFile
* outsf
= this->Makefile
->GetSourceFileWithOutput(output
);
644 target
.AddSourceFile(outsf
);
646 // Free the fake output name.
651 cmLocalVisualStudio6Generator
652 ::WriteCustomRule(std::ostream
& fout
,
654 const cmCustomCommand
& command
,
657 std::string comment
=
658 this->ConstructComment(command
, "Building Custom Rule $(InputPath)");
659 if(comment
== "<hack>")
664 // Write the rule for each configuration.
665 std::vector
<std::string
>::iterator i
;
666 for(i
= this->Configurations
.begin(); i
!= this->Configurations
.end(); ++i
)
668 std::string config
= this->GetConfigName(*i
);
670 this->ConstructScript(command
.GetCommandLines(),
671 command
.GetWorkingDirectory(),
673 command
.GetEscapeOldStyle(),
674 command
.GetEscapeAllowMakeVars(),
677 if (i
== this->Configurations
.begin())
679 fout
<< "!IF \"$(CFG)\" == " << i
->c_str() << std::endl
;
683 fout
<< "!ELSEIF \"$(CFG)\" == " << i
->c_str() << std::endl
;
687 fout
<< "\n# ADD CPP " << flags
<< "\n\n";
689 // Write out the dependencies for the rule.
690 fout
<< "USERDEP__HACK=";
691 for(std::vector
<std::string
>::const_iterator d
=
692 command
.GetDepends().begin();
693 d
!= command
.GetDepends().end();
696 // Lookup the real name of the dependency in case it is a CMake target.
697 std::string dep
= this->GetRealDependency(d
->c_str(),
700 this->ConvertToOptionallyRelativeOutputPath(dep
.c_str());
704 fout
<< "# PROP Ignore_Default_Tool 1\n";
705 fout
<< "# Begin Custom Build -";
708 fout
<< " " << comment
.c_str();
711 if(command
.GetOutputs().empty())
714 << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
715 fout
<< script
.c_str() << "\n\n";
719 for(std::vector
<std::string
>::const_iterator o
=
720 command
.GetOutputs().begin();
721 o
!= command
.GetOutputs().end();
724 // Write a rule for every output generated by this command.
725 fout
<< this->ConvertToOptionallyRelativeOutputPath(o
->c_str())
726 << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
727 fout
<< script
.c_str() << "\n\n";
730 fout
<< "# End Custom Build\n\n";
733 fout
<< "!ENDIF\n\n";
737 void cmLocalVisualStudio6Generator::WriteDSPBeginGroup(std::ostream
& fout
,
741 fout
<< "# Begin Group \"" << group
<< "\"\n"
742 "# PROP Default_Filter \"" << filter
<< "\"\n";
746 void cmLocalVisualStudio6Generator::WriteDSPEndGroup(std::ostream
& fout
)
748 fout
<< "# End Group\n";
754 void cmLocalVisualStudio6Generator::SetBuildType(BuildType b
,
758 std::string root
= this->Makefile
->GetRequiredDefinition("CMAKE_ROOT");
760 this->Makefile
->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
768 root
+= "/Templates";
774 this->DSPHeaderTemplate
= root
;
775 this->DSPHeaderTemplate
+= "/staticLibHeader.dsptemplate";
776 this->DSPFooterTemplate
= root
;
777 this->DSPFooterTemplate
+= "/staticLibFooter.dsptemplate";
780 this->DSPHeaderTemplate
= root
;
781 this->DSPHeaderTemplate
+= "/DLLHeader.dsptemplate";
782 this->DSPFooterTemplate
= root
;
783 this->DSPFooterTemplate
+= "/DLLFooter.dsptemplate";
786 if ( target
.GetPropertyAsBool("WIN32_EXECUTABLE") )
788 this->DSPHeaderTemplate
= root
;
789 this->DSPHeaderTemplate
+= "/EXEWinHeader.dsptemplate";
790 this->DSPFooterTemplate
= root
;
791 this->DSPFooterTemplate
+= "/EXEFooter.dsptemplate";
795 this->DSPHeaderTemplate
= root
;
796 this->DSPHeaderTemplate
+= "/EXEHeader.dsptemplate";
797 this->DSPFooterTemplate
= root
;
798 this->DSPFooterTemplate
+= "/EXEFooter.dsptemplate";
802 this->DSPHeaderTemplate
= root
;
803 this->DSPHeaderTemplate
+= "/UtilityHeader.dsptemplate";
804 this->DSPFooterTemplate
= root
;
805 this->DSPFooterTemplate
+= "/UtilityFooter.dsptemplate";
809 // once the build type is set, determine what configurations are
811 std::ifstream
fin(this->DSPHeaderTemplate
.c_str());
813 cmsys::RegularExpression
reg("# Name ");
816 cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate
.c_str());
819 // reset this->Configurations
820 this->Configurations
.erase(this->Configurations
.begin(),
821 this->Configurations
.end());
823 // now add all the configurations possible
824 std::string vs6name
= GetVS6TargetName(libName
);
826 while(cmSystemTools::GetLineFromStream(fin
, line
))
828 cmSystemTools::ReplaceString(line
, "OUTPUT_LIBNAME", vs6name
.c_str());
831 this->Configurations
.push_back(line
.substr(reg
.end()));
836 // look for custom rules on a target and collect them together
838 cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget
&target
,
839 const char* configName
,
840 const char * /* libName */)
842 if (target
.GetType() >= cmTarget::UTILITY
)
847 std::string customRuleCode
= "# Begin Special Build Tool\n";
848 EventWriter
event(this, configName
, customRuleCode
);
850 // Write the pre-build and pre-link together (VS6 does not support both).
851 event
.Start("PreLink");
852 event
.Write(target
.GetPreBuildCommands());
853 event
.Write(target
.GetPreLinkCommands());
854 cmsys::auto_ptr
<cmCustomCommand
> pcc(
855 this->MaybeCreateImplibDir(target
, configName
));
862 // Write the post-build rules.
863 event
.Start("PostBuild");
864 event
.Write(target
.GetPostBuildCommands());
867 customRuleCode
+= "# End Special Build Tool\n";
868 return customRuleCode
;
872 inline std::string
removeQuotes(const std::string
& s
)
874 if(s
[0] == '\"' && s
[s
.size()-1] == '\"')
876 return s
.substr(1, s
.size()-2);
881 // Code in blocks surrounded by a test for this definition is needed
882 // only for compatibility with user project's replacement DSP
883 // templates. The CMake templates no longer use them.
884 #define CM_USE_OLD_VS6
886 void cmLocalVisualStudio6Generator
887 ::WriteDSPHeader(std::ostream
& fout
,
888 const char *libName
, cmTarget
&target
,
889 std::vector
<cmSourceGroup
> &)
891 bool targetBuilds
= (target
.GetType() >= cmTarget::EXECUTABLE
&&
892 target
.GetType() <= cmTarget::MODULE_LIBRARY
);
893 #ifdef CM_USE_OLD_VS6
894 // Lookup the library and executable output directories.
896 if(this->Makefile
->GetDefinition("LIBRARY_OUTPUT_PATH"))
898 libPath
= this->Makefile
->GetDefinition("LIBRARY_OUTPUT_PATH");
901 if(this->Makefile
->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
903 exePath
= this->Makefile
->GetDefinition("EXECUTABLE_OUTPUT_PATH");
906 // Make sure there are trailing slashes.
909 if(libPath
[libPath
.size()-1] != '/')
916 if(exePath
[exePath
.size()-1] != '/')
922 std::set
<std::string
> pathEmitted
;
924 // determine the link directories
925 std::string libOptions
;
926 std::string libDebugOptions
;
927 std::string libOptimizedOptions
;
929 std::string libMultiLineOptions
;
930 std::string libMultiLineOptionsForDebug
;
931 std::string libMultiLineDebugOptions
;
932 std::string libMultiLineOptimizedOptions
;
937 this->ConvertToOptionallyRelativeOutputPath(libPath
.c_str());
938 if(lpath
.size() == 0)
942 std::string lpathIntDir
= libPath
+ "$(INTDIR)";
944 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir
.c_str());
945 if(pathEmitted
.insert(lpath
).second
)
947 libOptions
+= " /LIBPATH:";
948 libOptions
+= lpathIntDir
;
950 libOptions
+= " /LIBPATH:";
953 libMultiLineOptions
+= "# ADD LINK32 /LIBPATH:";
954 libMultiLineOptions
+= lpathIntDir
;
955 libMultiLineOptions
+= " ";
956 libMultiLineOptions
+= " /LIBPATH:";
957 libMultiLineOptions
+= lpath
;
958 libMultiLineOptions
+= " \n";
959 libMultiLineOptionsForDebug
+= "# ADD LINK32 /LIBPATH:";
960 libMultiLineOptionsForDebug
+= lpathIntDir
;
961 libMultiLineOptionsForDebug
+= " ";
962 libMultiLineOptionsForDebug
+= " /LIBPATH:";
963 libMultiLineOptionsForDebug
+= lpath
;
964 libMultiLineOptionsForDebug
+= " \n";
970 this->ConvertToOptionallyRelativeOutputPath(exePath
.c_str());
971 if(lpath
.size() == 0)
975 std::string lpathIntDir
= exePath
+ "$(INTDIR)";
977 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir
.c_str());
979 if(pathEmitted
.insert(lpath
).second
)
981 libOptions
+= " /LIBPATH:";
982 libOptions
+= lpathIntDir
;
984 libOptions
+= " /LIBPATH:";
987 libMultiLineOptions
+= "# ADD LINK32 /LIBPATH:";
988 libMultiLineOptions
+= lpathIntDir
;
989 libMultiLineOptions
+= " ";
990 libMultiLineOptions
+= " /LIBPATH:";
991 libMultiLineOptions
+= lpath
;
992 libMultiLineOptions
+= " \n";
993 libMultiLineOptionsForDebug
+= "# ADD LINK32 /LIBPATH:";
994 libMultiLineOptionsForDebug
+= lpathIntDir
;
995 libMultiLineOptionsForDebug
+= " ";
996 libMultiLineOptionsForDebug
+= " /LIBPATH:";
997 libMultiLineOptionsForDebug
+= lpath
;
998 libMultiLineOptionsForDebug
+= " \n";
1001 std::vector
<std::string
>::const_iterator i
;
1002 const std::vector
<std::string
>& libdirs
= target
.GetLinkDirectories();
1003 for(i
= libdirs
.begin(); i
!= libdirs
.end(); ++i
)
1005 std::string path
= *i
;
1006 if(path
[path
.size()-1] != '/')
1011 this->ConvertToOptionallyRelativeOutputPath(path
.c_str());
1012 if(lpath
.size() == 0)
1016 std::string lpathIntDir
= path
+ "$(INTDIR)";
1018 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir
.c_str());
1019 if(pathEmitted
.insert(lpath
).second
)
1021 libOptions
+= " /LIBPATH:";
1022 libOptions
+= lpathIntDir
;
1024 libOptions
+= " /LIBPATH:";
1025 libOptions
+= lpath
;
1028 libMultiLineOptions
+= "# ADD LINK32 /LIBPATH:";
1029 libMultiLineOptions
+= lpathIntDir
;
1030 libMultiLineOptions
+= " ";
1031 libMultiLineOptions
+= " /LIBPATH:";
1032 libMultiLineOptions
+= lpath
;
1033 libMultiLineOptions
+= " \n";
1034 libMultiLineOptionsForDebug
+= "# ADD LINK32 /LIBPATH:";
1035 libMultiLineOptionsForDebug
+= lpathIntDir
;
1036 libMultiLineOptionsForDebug
+= " ";
1037 libMultiLineOptionsForDebug
+= " /LIBPATH:";
1038 libMultiLineOptionsForDebug
+= lpath
;
1039 libMultiLineOptionsForDebug
+= " \n";
1042 // find link libraries
1043 const cmTarget::LinkLibraryVectorType
& libs
= target
.GetLinkLibraries();
1044 cmTarget::LinkLibraryVectorType::const_iterator j
;
1045 for(j
= libs
.begin(); j
!= libs
.end(); ++j
)
1047 // add libraries to executables and dlls (but never include
1048 // a library in a library, bad recursion)
1049 // NEVER LINK STATIC LIBRARIES TO OTHER STATIC LIBRARIES
1050 if ((target
.GetType() != cmTarget::SHARED_LIBRARY
1051 && target
.GetType() != cmTarget::STATIC_LIBRARY
1052 && target
.GetType() != cmTarget::MODULE_LIBRARY
) ||
1053 (target
.GetType()==cmTarget::SHARED_LIBRARY
1054 && libName
!= GetVS6TargetName(j
->first
)) ||
1055 (target
.GetType()==cmTarget::MODULE_LIBRARY
1056 && libName
!= GetVS6TargetName(j
->first
)))
1058 // Compute the proper name to use to link this library.
1060 std::string libDebug
;
1061 cmTarget
* tgt
= this->GlobalGenerator
->FindTarget(0, j
->first
.c_str());
1064 lib
= cmSystemTools::GetFilenameWithoutExtension
1065 (tgt
->GetFullName().c_str());
1066 libDebug
= cmSystemTools::GetFilenameWithoutExtension
1067 (tgt
->GetFullName("Debug").c_str());
1073 lib
= j
->first
.c_str();
1074 libDebug
= j
->first
.c_str();
1075 if(j
->first
.find(".lib") == std::string::npos
)
1081 lib
= this->ConvertToOptionallyRelativeOutputPath(lib
.c_str());
1083 this->ConvertToOptionallyRelativeOutputPath(libDebug
.c_str());
1085 if (j
->second
== cmTarget::GENERAL
)
1089 libMultiLineOptions
+= "# ADD LINK32 ";
1090 libMultiLineOptions
+= lib
;
1091 libMultiLineOptions
+= "\n";
1092 libMultiLineOptionsForDebug
+= "# ADD LINK32 ";
1093 libMultiLineOptionsForDebug
+= libDebug
;
1094 libMultiLineOptionsForDebug
+= "\n";
1096 if (j
->second
== cmTarget::DEBUG
)
1098 libDebugOptions
+= " ";
1099 libDebugOptions
+= lib
;
1101 libMultiLineDebugOptions
+= "# ADD LINK32 ";
1102 libMultiLineDebugOptions
+= libDebug
;
1103 libMultiLineDebugOptions
+= "\n";
1105 if (j
->second
== cmTarget::OPTIMIZED
)
1107 libOptimizedOptions
+= " ";
1108 libOptimizedOptions
+= lib
;
1110 libMultiLineOptimizedOptions
+= "# ADD LINK32 ";
1111 libMultiLineOptimizedOptions
+= lib
;
1112 libMultiLineOptimizedOptions
+= "\n";
1118 // Get extra linker options for this target type.
1119 std::string extraLinkOptions
;
1120 if(target
.GetType() == cmTarget::EXECUTABLE
)
1123 this->Makefile
->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1125 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1128 this->Makefile
->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1130 if(target
.GetType() == cmTarget::MODULE_LIBRARY
)
1133 this->Makefile
->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1136 // Get extra linker options for this target.
1137 if(const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS"))
1139 extraLinkOptions
+= " ";
1140 extraLinkOptions
+= targetLinkFlags
;
1143 // Get standard libraries for this language.
1146 // Get the language to use for linking.
1147 const char* linkLanguage
= target
.GetLinkerLanguage();
1150 cmSystemTools::Error
1151 ("CMake can not determine linker language for target:",
1156 // Compute the variable name to lookup standard libraries for this
1158 std::string standardLibsVar
= "CMAKE_";
1159 standardLibsVar
+= linkLanguage
;
1160 standardLibsVar
+= "_STANDARD_LIBRARIES";
1162 // Add standard libraries.
1163 if(const char* stdLibs
=
1164 this->Makefile
->GetDefinition(standardLibsVar
.c_str()))
1166 extraLinkOptions
+= " ";
1167 extraLinkOptions
+= stdLibs
;
1171 // Compute version number information.
1172 std::string targetVersionFlag
;
1173 if(target
.GetType() == cmTarget::EXECUTABLE
||
1174 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1175 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1179 target
.GetTargetVersion(major
, minor
);
1180 cmOStringStream targetVersionStream
;
1181 targetVersionStream
<< "/version:" << major
<< "." << minor
;
1182 targetVersionFlag
= targetVersionStream
.str();
1185 // Compute the real name of the target.
1186 std::string outputName
=
1187 "(OUTPUT_NAME is for libraries and executables only)";
1188 std::string outputNameDebug
= outputName
;
1189 std::string outputNameRelease
= outputName
;
1190 std::string outputNameMinSizeRel
= outputName
;
1191 std::string outputNameRelWithDebInfo
= outputName
;
1192 if(target
.GetType() == cmTarget::EXECUTABLE
||
1193 target
.GetType() == cmTarget::STATIC_LIBRARY
||
1194 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1195 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1197 outputName
= target
.GetFullName();
1198 outputNameDebug
= target
.GetFullName("Debug");
1199 outputNameRelease
= target
.GetFullName("Release");
1200 outputNameMinSizeRel
= target
.GetFullName("MinSizeRel");
1201 outputNameRelWithDebInfo
= target
.GetFullName("RelWithDebInfo");
1204 // Compute the proper link information for the target.
1205 std::string optionsDebug
;
1206 std::string optionsRelease
;
1207 std::string optionsMinSizeRel
;
1208 std::string optionsRelWithDebInfo
;
1209 if(target
.GetType() == cmTarget::EXECUTABLE
||
1210 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1211 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1213 this->ComputeLinkOptions(target
, "Debug", extraLinkOptions
,
1215 this->ComputeLinkOptions(target
, "Release", extraLinkOptions
,
1217 this->ComputeLinkOptions(target
, "MinSizeRel", extraLinkOptions
,
1219 this->ComputeLinkOptions(target
, "RelWithDebInfo", extraLinkOptions
,
1220 optionsRelWithDebInfo
);
1223 // Compute the path of the import library.
1224 std::string targetImplibFlagDebug
;
1225 std::string targetImplibFlagRelease
;
1226 std::string targetImplibFlagMinSizeRel
;
1227 std::string targetImplibFlagRelWithDebInfo
;
1228 if(target
.GetType() == cmTarget::SHARED_LIBRARY
||
1229 target
.GetType() == cmTarget::MODULE_LIBRARY
||
1230 target
.GetType() == cmTarget::EXECUTABLE
)
1232 std::string fullPathImpDebug
= target
.GetDirectory("Debug", true);
1233 std::string fullPathImpRelease
= target
.GetDirectory("Release", true);
1234 std::string fullPathImpMinSizeRel
=
1235 target
.GetDirectory("MinSizeRel", true);
1236 std::string fullPathImpRelWithDebInfo
=
1237 target
.GetDirectory("RelWithDebInfo", true);
1238 fullPathImpDebug
+= "/";
1239 fullPathImpRelease
+= "/";
1240 fullPathImpMinSizeRel
+= "/";
1241 fullPathImpRelWithDebInfo
+= "/";
1242 fullPathImpDebug
+= target
.GetFullName("Debug", true);
1243 fullPathImpRelease
+= target
.GetFullName("Release", true);
1244 fullPathImpMinSizeRel
+= target
.GetFullName("MinSizeRel", true);
1245 fullPathImpRelWithDebInfo
+= target
.GetFullName("RelWithDebInfo", true);
1247 targetImplibFlagDebug
= "/implib:";
1248 targetImplibFlagRelease
= "/implib:";
1249 targetImplibFlagMinSizeRel
= "/implib:";
1250 targetImplibFlagRelWithDebInfo
= "/implib:";
1251 targetImplibFlagDebug
+=
1252 this->ConvertToOptionallyRelativeOutputPath(fullPathImpDebug
.c_str());
1253 targetImplibFlagRelease
+=
1254 this->ConvertToOptionallyRelativeOutputPath(fullPathImpRelease
.c_str());
1255 targetImplibFlagMinSizeRel
+=
1256 this->ConvertToOptionallyRelativeOutputPath(
1257 fullPathImpMinSizeRel
.c_str());
1258 targetImplibFlagRelWithDebInfo
+=
1259 this->ConvertToOptionallyRelativeOutputPath(
1260 fullPathImpRelWithDebInfo
.c_str());
1263 #ifdef CM_USE_OLD_VS6
1264 // Compute link information for the target.
1265 if(extraLinkOptions
.size())
1268 libOptions
+= extraLinkOptions
;
1270 libMultiLineOptions
+= "# ADD LINK32 ";
1271 libMultiLineOptions
+= extraLinkOptions
;
1272 libMultiLineOptions
+= " \n";
1273 libMultiLineOptionsForDebug
+= "# ADD LINK32 ";
1274 libMultiLineOptionsForDebug
+= extraLinkOptions
;
1275 libMultiLineOptionsForDebug
+= " \n";
1279 // are there any custom rules on the target itself
1280 // only if the target is a lib or exe
1281 std::string customRuleCodeRelease
1282 = this->CreateTargetRules(target
, "RELEASE", libName
);
1283 std::string customRuleCodeDebug
1284 = this->CreateTargetRules(target
, "DEBUG", libName
);
1285 std::string customRuleCodeMinSizeRel
1286 = this->CreateTargetRules(target
, "MINSIZEREL", libName
);
1287 std::string customRuleCodeRelWithDebInfo
1288 = this->CreateTargetRules(target
, "RELWITHDEBINFO", libName
);
1290 std::ifstream
fin(this->DSPHeaderTemplate
.c_str());
1293 cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate
.c_str());
1295 std::string staticLibOptions
;
1296 if(target
.GetType() == cmTarget::STATIC_LIBRARY
)
1298 if(const char* libflags
= target
.GetProperty("STATIC_LIBRARY_FLAGS"))
1300 staticLibOptions
= libflags
;
1304 // Add the export symbol definition for shared library objects.
1305 std::string exportSymbol
;
1306 if(const char* exportMacro
= target
.GetExportMacro())
1308 exportSymbol
= exportMacro
;
1312 std::string libnameExports
;
1313 if(exportSymbol
.size())
1315 libnameExports
= "/D \"";
1316 libnameExports
+= exportSymbol
;
1317 libnameExports
+= "\"";
1319 while(cmSystemTools::GetLineFromStream(fin
, line
))
1321 const char* mfcFlag
= this->Makefile
->GetDefinition("CMAKE_MFC_FLAG");
1326 cmSystemTools::ReplaceString(line
, "OUTPUT_LIBNAME_EXPORTS",
1327 libnameExports
.c_str());
1328 cmSystemTools::ReplaceString(line
, "CMAKE_MFC_FLAG",
1330 if(target
.GetType() == cmTarget::STATIC_LIBRARY
)
1332 cmSystemTools::ReplaceString(line
, "CM_STATIC_LIB_ARGS",
1333 staticLibOptions
.c_str());
1335 if(this->Makefile
->IsOn("CMAKE_VERBOSE_MAKEFILE"))
1337 cmSystemTools::ReplaceString(line
, "/nologo", "");
1340 #ifdef CM_USE_OLD_VS6
1341 cmSystemTools::ReplaceString(line
, "CM_LIBRARIES",
1342 libOptions
.c_str());
1343 cmSystemTools::ReplaceString(line
, "CM_DEBUG_LIBRARIES",
1344 libDebugOptions
.c_str());
1345 cmSystemTools::ReplaceString(line
, "CM_OPTIMIZED_LIBRARIES",
1346 libOptimizedOptions
.c_str());
1347 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_LIBRARIES_FOR_DEBUG",
1348 libMultiLineOptionsForDebug
.c_str());
1349 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_LIBRARIES",
1350 libMultiLineOptions
.c_str());
1351 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_DEBUG_LIBRARIES",
1352 libMultiLineDebugOptions
.c_str());
1353 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
1354 libMultiLineOptimizedOptions
.c_str());
1357 // Substitute the rules for custom command. When specifying just the
1358 // target name for the command the command can be different for
1359 // different configs
1360 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_RELEASE",
1361 customRuleCodeRelease
.c_str());
1362 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_DEBUG",
1363 customRuleCodeDebug
.c_str());
1364 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_MINSIZEREL",
1365 customRuleCodeMinSizeRel
.c_str());
1366 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO",
1367 customRuleCodeRelWithDebInfo
.c_str());
1369 // Substitute the real output name into the template.
1370 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_DEBUG",
1371 outputNameDebug
.c_str());
1372 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_RELEASE",
1373 outputNameRelease
.c_str());
1374 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_MINSIZEREL",
1375 outputNameMinSizeRel
.c_str());
1376 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_RELWITHDEBINFO",
1377 outputNameRelWithDebInfo
.c_str());
1378 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME", outputName
.c_str());
1380 // Substitute the proper link information into the template.
1381 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_DEBUG",
1382 optionsDebug
.c_str());
1383 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_RELEASE",
1384 optionsRelease
.c_str());
1385 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_MINSIZEREL",
1386 optionsMinSizeRel
.c_str());
1387 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_RELWITHDEBINFO",
1388 optionsRelWithDebInfo
.c_str());
1390 cmSystemTools::ReplaceString(line
, "BUILD_INCLUDES",
1391 this->IncludeOptions
.c_str());
1392 cmSystemTools::ReplaceString(line
, "TARGET_VERSION_FLAG",
1393 targetVersionFlag
.c_str());
1394 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_DEBUG",
1395 targetImplibFlagDebug
.c_str());
1396 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_RELEASE",
1397 targetImplibFlagRelease
.c_str());
1398 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_MINSIZEREL",
1399 targetImplibFlagMinSizeRel
.c_str());
1400 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_RELWITHDEBINFO",
1401 targetImplibFlagRelWithDebInfo
.c_str());
1403 std::string vs6name
= GetVS6TargetName(libName
);
1404 cmSystemTools::ReplaceString(line
, "OUTPUT_LIBNAME", vs6name
.c_str());
1406 #ifdef CM_USE_OLD_VS6
1407 // because LIBRARY_OUTPUT_PATH and EXECUTABLE_OUTPUT_PATH
1408 // are already quoted in the template file,
1409 // we need to remove the quotes here, we still need
1410 // to convert to output path for unix to win32 conversion
1411 cmSystemTools::ReplaceString
1412 (line
, "LIBRARY_OUTPUT_PATH",
1413 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1414 (libPath
.c_str())).c_str());
1415 cmSystemTools::ReplaceString
1416 (line
, "EXECUTABLE_OUTPUT_PATH",
1417 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1418 (exePath
.c_str())).c_str());
1423 std::string outPath
= target
.GetDirectory();
1424 cmSystemTools::ReplaceString
1425 (line
, "OUTPUT_DIRECTORY",
1426 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1427 (outPath
.c_str())).c_str());
1430 cmSystemTools::ReplaceString(line
,
1432 this->Makefile
->GetDefineFlags());
1433 const char* debugPostfix
1434 = this->Makefile
->GetDefinition("CMAKE_DEBUG_POSTFIX");
1435 cmSystemTools::ReplaceString(line
, "DEBUG_POSTFIX",
1436 debugPostfix
?debugPostfix
:"");
1437 // store flags for each configuration
1438 std::string flags
= " ";
1439 std::string flagsRelease
= " ";
1440 std::string flagsMinSize
= " ";
1441 std::string flagsDebug
= " ";
1442 std::string flagsDebugRel
= " ";
1443 if(target
.GetType() >= cmTarget::EXECUTABLE
&&
1444 target
.GetType() <= cmTarget::MODULE_LIBRARY
)
1446 const char* linkLanguage
= target
.GetLinkerLanguage();
1449 cmSystemTools::Error
1450 ("CMake can not determine linker language for target:",
1454 // if CXX is on and the target contains cxx code then add the cxx flags
1455 std::string baseFlagVar
= "CMAKE_";
1456 baseFlagVar
+= linkLanguage
;
1457 baseFlagVar
+= "_FLAGS";
1458 flags
= this->Makefile
->GetSafeDefinition(baseFlagVar
.c_str());
1460 std::string flagVar
= baseFlagVar
+ "_RELEASE";
1461 flagsRelease
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1462 flagsRelease
+= " -DCMAKE_INTDIR=\\\"Release\\\" ";
1463 if(const char* targetLinkFlags
=
1464 target
.GetProperty("LINK_FLAGS_RELEASE"))
1466 flagsRelease
+= targetLinkFlags
;
1467 flagsRelease
+= " ";
1469 flagVar
= baseFlagVar
+ "_MINSIZEREL";
1470 flagsMinSize
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1471 flagsMinSize
+= " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
1472 if(const char* targetLinkFlags
=
1473 target
.GetProperty("LINK_FLAGS_MINSIZEREL"))
1475 flagsMinSize
+= targetLinkFlags
;
1476 flagsMinSize
+= " ";
1479 flagVar
= baseFlagVar
+ "_DEBUG";
1480 flagsDebug
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1481 flagsDebug
+= " -DCMAKE_INTDIR=\\\"Debug\\\" ";
1482 if(const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS_DEBUG"))
1484 flagsDebug
+= targetLinkFlags
;
1488 flagVar
= baseFlagVar
+ "_RELWITHDEBINFO";
1489 flagsDebugRel
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1490 flagsDebugRel
+= " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
1491 if(const char* targetLinkFlags
=
1492 target
.GetProperty("LINK_FLAGS_RELWITHDEBINFO"))
1494 flagsDebugRel
+= targetLinkFlags
;
1495 flagsDebugRel
+= " ";
1500 // if unicode is not found, then add -D_MBCS
1501 std::string defs
= this->Makefile
->GetDefineFlags();
1502 if(flags
.find("D_UNICODE") == flags
.npos
&&
1503 defs
.find("D_UNICODE") == flags
.npos
)
1505 flags
+= " /D \"_MBCS\"";
1508 // Add per-target flags.
1509 if(const char* targetFlags
= target
.GetProperty("COMPILE_FLAGS"))
1512 flags
+= targetFlags
;
1515 // Add per-target and per-configuration preprocessor definitions.
1516 std::string defines
= " ";
1517 std::string debugDefines
= " ";
1518 std::string releaseDefines
= " ";
1519 std::string minsizeDefines
= " ";
1520 std::string debugrelDefines
= " ";
1522 this->AppendDefines(
1524 this->Makefile
->GetProperty("COMPILE_DEFINITIONS"), 0);
1525 this->AppendDefines(
1527 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_DEBUG"),0);
1528 this->AppendDefines(
1530 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1531 this->AppendDefines(
1533 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1534 this->AppendDefines(
1536 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"), 0);
1538 this->AppendDefines(
1540 target
.GetProperty("COMPILE_DEFINITIONS"), 0);
1541 this->AppendDefines(
1543 target
.GetProperty("COMPILE_DEFINITIONS_DEBUG"), 0);
1544 this->AppendDefines(
1546 target
.GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1547 this->AppendDefines(
1549 target
.GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1550 this->AppendDefines(
1552 target
.GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"), 0);
1554 flagsDebug
+= debugDefines
;
1555 flagsRelease
+= releaseDefines
;
1556 flagsMinSize
+= minsizeDefines
;
1557 flagsDebugRel
+= debugrelDefines
;
1559 // The template files have CXX FLAGS in them, that need to be replaced.
1560 // There are not separate CXX and C template files, so we use the same
1561 // variable names. The previous code sets up flags* variables to contain
1562 // the correct C or CXX flags
1563 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_MINSIZEREL",
1564 flagsMinSize
.c_str());
1565 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_DEBUG",
1566 flagsDebug
.c_str());
1567 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
1568 flagsDebugRel
.c_str());
1569 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_RELEASE",
1570 flagsRelease
.c_str());
1571 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS", flags
.c_str());
1573 cmSystemTools::ReplaceString(line
, "COMPILE_DEFINITIONS_MINSIZE",
1574 minsizeDefines
.c_str());
1575 cmSystemTools::ReplaceString(line
, "COMPILE_DEFINITIONS_DEBUG",
1576 debugDefines
.c_str());
1577 cmSystemTools::ReplaceString(line
, "COMPILE_DEFINITIONS_RELWITHDEBINFO",
1578 debugrelDefines
.c_str());
1579 cmSystemTools::ReplaceString(line
, "COMPILE_DEFINITIONS_RELEASE",
1580 releaseDefines
.c_str());
1581 cmSystemTools::ReplaceString(line
, "COMPILE_DEFINITIONS", defines
.c_str());
1583 fout
<< line
.c_str() << std::endl
;
1587 void cmLocalVisualStudio6Generator::WriteDSPFooter(std::ostream
& fout
)
1589 std::ifstream
fin(this->DSPFooterTemplate
.c_str());
1592 cmSystemTools::Error("Error Reading ",
1593 this->DSPFooterTemplate
.c_str());
1596 while(cmSystemTools::GetLineFromStream(fin
, line
))
1598 fout
<< line
<< std::endl
;
1602 //----------------------------------------------------------------------------
1603 void cmLocalVisualStudio6Generator
1604 ::ComputeLinkOptions(cmTarget
& target
,
1605 const char* configName
,
1606 const std::string extraOptions
,
1607 std::string
& options
)
1609 // Compute the link information for this configuration.
1610 cmComputeLinkInformation
* pcli
= target
.GetLinkInformation(configName
);
1615 cmComputeLinkInformation
& cli
= *pcli
;
1616 typedef cmComputeLinkInformation::ItemVector ItemVector
;
1617 ItemVector
const& linkLibs
= cli
.GetItems();
1618 std::vector
<std::string
> const& linkDirs
= cli
.GetDirectories();
1620 // Build the link options code.
1621 for(std::vector
<std::string
>::const_iterator d
= linkDirs
.begin();
1622 d
!= linkDirs
.end(); ++d
)
1624 std::string dir
= *d
;
1627 if(dir
[dir
.size()-1] != '/')
1632 options
+= "# ADD LINK32 /LIBPATH:";
1633 options
+= this->ConvertToOptionallyRelativeOutputPath(dir
.c_str());
1634 options
+= " /LIBPATH:";
1635 options
+= this->ConvertToOptionallyRelativeOutputPath(d
->c_str());
1639 for(ItemVector::const_iterator l
= linkLibs
.begin();
1640 l
!= linkLibs
.end(); ++l
)
1642 options
+= "# ADD LINK32 ";
1646 this->ConvertToOptionallyRelativeOutputPath(l
->Value
.c_str());
1650 options
+= l
->Value
;
1655 // Add extra options if any.
1656 if(!extraOptions
.empty())
1658 options
+= "# ADD LINK32 ";
1659 options
+= extraOptions
;
1665 cmLocalVisualStudio6Generator
1666 ::GetTargetDirectory(cmTarget
const&) const
1668 // No per-target directory for this generator (yet).
1672 void cmLocalVisualStudio6Generator
1673 ::GetTargetObjectFileDirectories(cmTarget
* ,
1674 std::vector
<std::string
>&
1677 std::string dir
= this->Makefile
->GetCurrentOutputDirectory();
1679 dir
+= this->GetGlobalGenerator()->GetCMakeCFGInitDirectory();
1680 dirs
.push_back(dir
);
1684 cmLocalVisualStudio6Generator
1685 ::GetConfigName(std::string
const& configuration
) const
1687 // Strip the subdirectory name out of the configuration name.
1688 std::string config
= configuration
;
1689 std::string::size_type pos
= config
.find_last_of(" ");
1690 config
= config
.substr(pos
+1, std::string::npos
);
1691 config
= config
.substr(0, config
.size()-1);
1695 //----------------------------------------------------------------------------
1697 cmLocalVisualStudio6Generator
1698 ::CheckDefinition(std::string
const& define
) const
1700 // Perform the standard check first.
1701 if(!this->cmLocalGenerator::CheckDefinition(define
))
1706 // Now do the VS6-specific check.
1707 if(define
.find_first_of(" ") != define
.npos
&&
1708 define
.find_first_of("\"$;") != define
.npos
)
1711 e
<< "WARNING: The VS6 IDE does not support preprocessor definition "
1712 << "values with spaces and '\"', '$', or ';'.\n"
1713 << "CMake is dropping a preprocessor definition: " << define
<< "\n"
1714 << "Consider defining the macro in a (configured) header file.\n";
1715 cmSystemTools::Message(e
.str().c_str());
1719 // Assume it is supported.