1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmLocalVisualStudio6Generator.cxx,v $
6 Date: $Date: 2008-01-22 14:13:03 $
7 Version: $Revision: 1.138 $
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 void cmLocalVisualStudio6Generator::AddHelperCommands()
39 std::set
<cmStdString
> lang
;
42 this->CreateCustomTargetsAndCommands(lang
);
45 void cmLocalVisualStudio6Generator::Generate()
47 this->OutputDSPFile();
50 void cmLocalVisualStudio6Generator::OutputDSPFile()
52 // If not an in source build, then create the output directory
53 if(strcmp(this->Makefile
->GetStartOutputDirectory(),
54 this->Makefile
->GetHomeDirectory()) != 0)
56 if(!cmSystemTools::MakeDirectory
57 (this->Makefile
->GetStartOutputDirectory()))
59 cmSystemTools::Error("Error creating directory ",
60 this->Makefile
->GetStartOutputDirectory());
64 // Setup /I and /LIBPATH options for the resulting DSP file. VS 6
65 // truncates long include paths so make it as short as possible if
66 // the length threatents this problem.
67 unsigned int maxIncludeLength
= 3000;
68 bool useShortPath
= false;
69 for(int j
=0; j
< 2; ++j
)
71 std::vector
<std::string
> includes
;
72 this->GetIncludeDirectories(includes
);
73 std::vector
<std::string
>::iterator i
;
74 for(i
= includes
.begin(); i
!= includes
.end(); ++i
)
77 this->ConvertToOptionallyRelativeOutputPath(i
->c_str());
80 cmSystemTools::GetShortPath(tmp
.c_str(), tmp
);
82 this->IncludeOptions
+= " /I ";
84 // quote if not already quoted
87 this->IncludeOptions
+= "\"";
88 this->IncludeOptions
+= tmp
;
89 this->IncludeOptions
+= "\"";
93 this->IncludeOptions
+= tmp
;
96 if(j
== 0 && this->IncludeOptions
.size() > maxIncludeLength
)
98 this->IncludeOptions
= "";
107 // Create the DSP or set of DSP's for libraries and executables
109 // clear project names
110 this->CreatedProjectNames
.clear();
111 cmTargets
&tgts
= this->Makefile
->GetTargets();
112 for(cmTargets::iterator l
= tgts
.begin();
113 l
!= tgts
.end(); l
++)
115 // Add a rule to regenerate the build system when the target
116 // specification source changes.
117 const char* suppRegenRule
=
118 this->Makefile
->GetDefinition("CMAKE_SUPPRESS_REGENERATION");
119 if (!cmSystemTools::IsOn(suppRegenRule
))
121 this->AddDSPBuildRule(l
->second
);
126 for(cmTargets::iterator l
= tgts
.begin();
127 l
!= tgts
.end(); l
++)
129 switch(l
->second
.GetType())
131 case cmTarget::STATIC_LIBRARY
:
132 this->SetBuildType(STATIC_LIBRARY
, l
->first
.c_str(), l
->second
);
134 case cmTarget::SHARED_LIBRARY
:
135 case cmTarget::MODULE_LIBRARY
:
136 this->SetBuildType(DLL
, l
->first
.c_str(), l
->second
);
138 case cmTarget::EXECUTABLE
:
139 this->SetBuildType(EXECUTABLE
,l
->first
.c_str(), l
->second
);
141 case cmTarget::UTILITY
:
142 case cmTarget::GLOBAL_TARGET
:
143 this->SetBuildType(UTILITY
, l
->first
.c_str(), l
->second
);
146 cmSystemTools::Error("Bad target type", l
->first
.c_str());
149 // INCLUDE_EXTERNAL_MSPROJECT command only affects the workspace
150 // so don't build a projectfile for it
151 if (strncmp(l
->first
.c_str(), "INCLUDE_EXTERNAL_MSPROJECT", 26) != 0)
153 // check to see if the dsp is going into a sub-directory
154 std::string::size_type pos
= l
->first
.rfind('/');
155 if(pos
!= std::string::npos
)
157 std::string dir
= this->Makefile
->GetStartOutputDirectory();
159 dir
+= l
->first
.substr(0, pos
);
160 if(!cmSystemTools::MakeDirectory(dir
.c_str()))
162 cmSystemTools::Error("Error creating directory ", dir
.c_str());
165 this->CreateSingleDSP(l
->first
.c_str(),l
->second
);
170 void cmLocalVisualStudio6Generator::CreateSingleDSP(const char *lname
,
173 // add to the list of projects
174 std::string pname
= lname
;
175 this->CreatedProjectNames
.push_back(pname
);
176 // create the dsp.cmake file
178 fname
= this->Makefile
->GetStartOutputDirectory();
182 // save the name of the real dsp file
183 std::string realDSP
= fname
;
185 std::ofstream
fout(fname
.c_str());
188 cmSystemTools::Error("Error Writing ", fname
.c_str());
189 cmSystemTools::ReportLastSystemError("");
191 this->WriteDSPFile(fout
,lname
,target
);
193 // if the dsp file has changed, then write it.
194 cmSystemTools::CopyFileIfDifferent(fname
.c_str(), realDSP
.c_str());
198 void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmTarget
& tgt
)
200 std::string dspname
= tgt
.GetName();
201 dspname
+= ".dsp.cmake";
202 const char* dsprule
=
203 this->Makefile
->GetRequiredDefinition("CMAKE_COMMAND");
204 cmCustomCommandLine commandLine
;
205 commandLine
.push_back(dsprule
);
206 std::string makefileIn
= this->Makefile
->GetStartDirectory();
208 makefileIn
+= "CMakeLists.txt";
209 std::string comment
= "Building Custom Rule ";
210 comment
+= makefileIn
;
213 args
+= this->Convert(this->Makefile
->GetHomeDirectory(),
214 START_OUTPUT
, UNCHANGED
, true);
215 commandLine
.push_back(args
);
218 this->Convert(this->Makefile
->GetHomeOutputDirectory(),
219 START_OUTPUT
, UNCHANGED
, true);
220 commandLine
.push_back(args
);
222 std::vector
<std::string
> const& listFiles
= this->Makefile
->GetListFiles();
224 cmCustomCommandLines commandLines
;
225 commandLines
.push_back(commandLine
);
226 const char* no_working_directory
= 0;
227 this->Makefile
->AddCustomCommandToOutput(dspname
.c_str(), listFiles
,
228 makefileIn
.c_str(), commandLines
,
230 no_working_directory
, true);
231 if(cmSourceFile
* file
= this->Makefile
->GetSource(makefileIn
.c_str()))
233 tgt
.AddSourceFile(file
);
237 cmSystemTools::Error("Error adding rule for ", makefileIn
.c_str());
242 void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream
& fout
,
246 // For utility targets need custom command since pre- and post-
247 // build does not do anything in Visual Studio 6. In order for the
248 // rules to run in the correct order as custom commands, we need
249 // special care for dependencies. The first rule must depend on all
250 // the dependencies of all the rules. The later rules must each
251 // depend only on the previous rule.
252 if ((target
.GetType() == cmTarget::UTILITY
||
253 target
.GetType() == cmTarget::GLOBAL_TARGET
) &&
254 (!target
.GetPreBuildCommands().empty() ||
255 !target
.GetPostBuildCommands().empty()))
257 // Accumulate the dependencies of all the commands.
258 std::vector
<std::string
> depends
;
259 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
260 target
.GetPreBuildCommands().begin();
261 cr
!= target
.GetPreBuildCommands().end(); ++cr
)
263 depends
.insert(depends
.end(),
264 cr
->GetDepends().begin(), cr
->GetDepends().end());
266 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
267 target
.GetPostBuildCommands().begin();
268 cr
!= target
.GetPostBuildCommands().end(); ++cr
)
270 depends
.insert(depends
.end(),
271 cr
->GetDepends().begin(), cr
->GetDepends().end());
274 // Add the pre- and post-build commands in order.
276 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
277 target
.GetPreBuildCommands().begin();
278 cr
!= target
.GetPreBuildCommands().end(); ++cr
)
280 this->AddUtilityCommandHack(target
, count
++, depends
, *cr
);
282 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
283 target
.GetPostBuildCommands().begin();
284 cr
!= target
.GetPostBuildCommands().end(); ++cr
)
286 this->AddUtilityCommandHack(target
, count
++, depends
, *cr
);
290 // trace the visual studio dependencies
291 std::string name
= libName
;
292 name
+= ".dsp.cmake";
294 // We may be modifying the source groups temporarily, so make a copy.
295 std::vector
<cmSourceGroup
> sourceGroups
= this->Makefile
->GetSourceGroups();
297 // get the classes from the source lists then add them to the groups
298 std::vector
<cmSourceFile
*> const & classes
= target
.GetSourceFiles();
300 // now all of the source files have been properly assigned to the target
301 // now stick them into source groups using the reg expressions
302 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
303 i
!= classes
.end(); i
++)
305 // Add the file to the list of sources.
306 std::string source
= (*i
)->GetFullPath();
307 cmSourceGroup
& sourceGroup
=
308 this->Makefile
->FindSourceGroup(source
.c_str(), sourceGroups
);
309 sourceGroup
.AssignSource(*i
);
310 // while we are at it, if it is a .rule file then for visual studio 6 we
312 if ((*i
)->GetExtension() == "rule")
314 if(!cmSystemTools::FileExists(source
.c_str()))
316 cmSystemTools::ReplaceString(source
, "$(IntDir)/", "");
317 #if defined(_WIN32) || defined(__CYGWIN__)
318 std::ofstream
fout(source
.c_str(),
319 std::ios::binary
| std::ios::out
322 std::ofstream
fout(source
.c_str(),
323 std::ios::out
| std::ios::trunc
);
327 fout
.write("# generated from CMake",22);
335 // Compute which sources need unique object computation.
336 this->ComputeObjectNameRequirements(sourceGroups
);
338 // Write the DSP file's header.
339 this->WriteDSPHeader(fout
, libName
, target
, sourceGroups
);
342 // Loop through every source group.
343 for(std::vector
<cmSourceGroup
>::const_iterator sg
= sourceGroups
.begin();
344 sg
!= sourceGroups
.end(); ++sg
)
346 this->WriteGroup(&(*sg
), target
, fout
, libName
);
349 // Write the DSP file's footer.
350 this->WriteDSPFooter(fout
);
353 void cmLocalVisualStudio6Generator
354 ::WriteGroup(const cmSourceGroup
*sg
, cmTarget target
,
355 std::ostream
&fout
, const char *libName
)
357 const std::vector
<const cmSourceFile
*> &sourceFiles
=
358 sg
->GetSourceFiles();
359 // If the group is empty, don't write it at all.
361 if(sourceFiles
.empty())
366 // If the group has a name, write the header.
367 std::string name
= sg
->GetName();
370 this->WriteDSPBeginGroup(fout
, name
.c_str(), "");
373 // Compute the maximum length of a configuration name.
374 std::string::size_type config_len_max
= 0;
375 for(std::vector
<std::string
>::iterator i
= this->Configurations
.begin();
376 i
!= this->Configurations
.end(); ++i
)
378 // Strip the subdirectory name out of the configuration name.
379 std::string config
= this->GetConfigName(*i
);
380 if(config
.size() > config_len_max
)
382 config_len_max
= config
.size();
386 // Compute the maximum length of the full path to the intermediate
387 // files directory for any configuration. This is used to construct
388 // object file names that do not produce paths that are too long.
389 std::string::size_type dir_len
= 0;
390 dir_len
+= strlen(this->Makefile
->GetCurrentOutputDirectory());
392 dir_len
+= config_len_max
;
395 // Loop through each source in the source group.
396 for(std::vector
<const cmSourceFile
*>::const_iterator sf
=
397 sourceFiles
.begin(); sf
!= sourceFiles
.end(); ++sf
)
399 std::string source
= (*sf
)->GetFullPath();
400 const cmCustomCommand
*command
=
401 (*sf
)->GetCustomCommand();
402 std::string compileFlags
;
403 std::vector
<std::string
> depends
;
404 std::string objectNameDir
;
405 if(this->NeedObjectName
.find(*sf
) != this->NeedObjectName
.end())
408 cmSystemTools::GetFilenamePath(
409 this->GetObjectFileNameWithoutTarget(*(*sf
), dir_len
));
412 // Add per-source file flags.
413 if(const char* cflags
= (*sf
)->GetProperty("COMPILE_FLAGS"))
415 compileFlags
+= cflags
;
418 const char* lang
= this->GetSourceFileLanguage(*(*sf
));
421 if(strcmp(lang
, "CXX") == 0)
423 // force a C++ file type
424 compileFlags
+= " /TP ";
426 else if(strcmp(lang
, "C") == 0)
428 // force to c file type
429 compileFlags
+= " /TC ";
433 // Add per-source and per-configuration preprocessor definitions.
434 std::map
<cmStdString
, cmStdString
> cdmap
;
435 this->AppendDefines(compileFlags
,
436 (*sf
)->GetProperty("COMPILE_DEFINITIONS"), lang
);
437 if(const char* cdefs
= (*sf
)->GetProperty("COMPILE_DEFINITIONS_DEBUG"))
439 this->AppendDefines(cdmap
["DEBUG"], cdefs
, lang
);
441 if(const char* cdefs
= (*sf
)->GetProperty("COMPILE_DEFINITIONS_RELEASE"))
443 this->AppendDefines(cdmap
["RELEASE"], cdefs
, lang
);
445 if(const char* cdefs
=
446 (*sf
)->GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"))
448 this->AppendDefines(cdmap
["MINSIZEREL"], cdefs
, lang
);
450 if(const char* cdefs
=
451 (*sf
)->GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"))
453 this->AppendDefines(cdmap
["RELWITHDEBINFO"], cdefs
, lang
);
456 bool excludedFromBuild
=
457 (lang
&& (*sf
)->GetPropertyAsBool("HEADER_FILE_ONLY"));
459 // Check for extra object-file dependencies.
460 const char* dependsValue
= (*sf
)->GetProperty("OBJECT_DEPENDS");
463 cmSystemTools::ExpandListArgument(dependsValue
, depends
);
465 if (source
!= libName
|| target
.GetType() == cmTarget::UTILITY
||
466 target
.GetType() == cmTarget::GLOBAL_TARGET
)
468 fout
<< "# Begin Source File\n\n";
470 // Tell MS-Dev what the source is. If the compiler knows how to
471 // build it, then it will.
473 this->ConvertToOptionallyRelativeOutputPath(source
.c_str()) << "\n\n";
476 // Write out the dependencies for the rule.
477 fout
<< "USERDEP__HACK=";
478 for(std::vector
<std::string
>::const_iterator d
= depends
.begin();
479 d
!= depends
.end(); ++d
)
482 this->ConvertToOptionallyRelativeOutputPath(d
->c_str());
488 const char* flags
= compileFlags
.size() ? compileFlags
.c_str(): 0;
489 this->WriteCustomRule(fout
, source
.c_str(), *command
, flags
);
491 else if(!compileFlags
.empty() || !objectNameDir
.empty() ||
492 excludedFromBuild
|| !cdmap
.empty())
494 for(std::vector
<std::string
>::iterator i
495 = this->Configurations
.begin();
496 i
!= this->Configurations
.end(); ++i
)
498 // Strip the subdirectory name out of the configuration name.
499 std::string config
= this->GetConfigName(*i
);
500 if (i
== this->Configurations
.begin())
502 fout
<< "!IF \"$(CFG)\" == " << i
->c_str() << std::endl
;
506 fout
<< "!ELSEIF \"$(CFG)\" == " << i
->c_str() << std::endl
;
508 if(excludedFromBuild
)
510 fout
<< "# PROP Exclude_From_Build 1\n";
512 if(!compileFlags
.empty())
514 fout
<< "\n# ADD CPP " << compileFlags
<< "\n\n";
516 std::map
<cmStdString
, cmStdString
>::iterator cdi
=
517 cdmap
.find(cmSystemTools::UpperCase(config
));
518 if(cdi
!= cdmap
.end() && !cdi
->second
.empty())
520 fout
<< "\n# ADD CPP " << cdi
->second
<< "\n\n";
522 if(!objectNameDir
.empty())
524 // Setup an alternate object file directory.
525 fout
<< "\n# PROP Intermediate_Dir \""
526 << config
<< "/" << objectNameDir
<< "\"\n\n";
529 fout
<< "!ENDIF\n\n";
531 fout
<< "# End Source File\n";
535 std::vector
<cmSourceGroup
> children
= sg
->GetGroupChildren();
537 for(unsigned int i
=0;i
<children
.size();++i
)
539 this->WriteGroup(&children
[i
], target
, fout
, libName
);
545 // If the group has a name, write the footer.
548 this->WriteDSPEndGroup(fout
);
555 cmLocalVisualStudio6Generator
556 ::AddUtilityCommandHack(cmTarget
& target
, int count
,
557 std::vector
<std::string
>& depends
,
558 const cmCustomCommand
& origCommand
)
560 // Create a fake output that forces the rule to run.
561 char* output
= new char[(strlen(this->Makefile
->GetStartOutputDirectory()) +
562 strlen(target
.GetName()) + 30)];
563 sprintf(output
,"%s/%s_force_%i", this->Makefile
->GetStartOutputDirectory(),
564 target
.GetName(), count
);
565 std::string comment
= this->ConstructComment(origCommand
, "<hack>");
567 // Add the rule with the given dependencies and commands.
568 const char* no_main_dependency
= 0;
569 this->Makefile
->AddCustomCommandToOutput(output
,
572 origCommand
.GetCommandLines(),
574 origCommand
.GetWorkingDirectory());
576 // Replace the dependencies with the output of this rule so that the
577 // next rule added will run after this one.
579 depends
.push_back(output
);
581 // Add a source file representing this output to the project.
582 cmSourceFile
* outsf
= this->Makefile
->GetSourceFileWithOutput(output
);
583 target
.AddSourceFile(outsf
);
585 // Free the fake output name.
590 cmLocalVisualStudio6Generator
591 ::WriteCustomRule(std::ostream
& fout
,
593 const cmCustomCommand
& command
,
596 std::string comment
=
597 this->ConstructComment(command
, "Building Custom Rule $(InputPath)");
598 if(comment
== "<hack>")
603 // Write the rule for each configuration.
604 std::vector
<std::string
>::iterator i
;
605 for(i
= this->Configurations
.begin(); i
!= this->Configurations
.end(); ++i
)
607 std::string config
= this->GetConfigName(*i
);
609 this->ConstructScript(command
.GetCommandLines(),
610 command
.GetWorkingDirectory(),
612 command
.GetEscapeOldStyle(),
613 command
.GetEscapeAllowMakeVars(),
616 if (i
== this->Configurations
.begin())
618 fout
<< "!IF \"$(CFG)\" == " << i
->c_str() << std::endl
;
622 fout
<< "!ELSEIF \"$(CFG)\" == " << i
->c_str() << std::endl
;
626 fout
<< "\n# ADD CPP " << flags
<< "\n\n";
628 // Write out the dependencies for the rule.
629 fout
<< "USERDEP__HACK=";
630 for(std::vector
<std::string
>::const_iterator d
=
631 command
.GetDepends().begin();
632 d
!= command
.GetDepends().end();
635 // Lookup the real name of the dependency in case it is a CMake target.
636 std::string dep
= this->GetRealDependency(d
->c_str(),
639 this->ConvertToOptionallyRelativeOutputPath(dep
.c_str());
643 fout
<< "# PROP Ignore_Default_Tool 1\n";
644 fout
<< "# Begin Custom Build -";
647 fout
<< " " << comment
.c_str();
650 if(command
.GetOutputs().empty())
653 << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
654 fout
<< script
.c_str() << "\n\n";
658 for(std::vector
<std::string
>::const_iterator o
=
659 command
.GetOutputs().begin();
660 o
!= command
.GetOutputs().end();
663 // Write a rule for every output generated by this command.
664 fout
<< this->ConvertToOptionallyRelativeOutputPath(o
->c_str())
665 << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
666 fout
<< script
.c_str() << "\n\n";
669 fout
<< "# End Custom Build\n\n";
672 fout
<< "!ENDIF\n\n";
676 void cmLocalVisualStudio6Generator::WriteDSPBeginGroup(std::ostream
& fout
,
680 fout
<< "# Begin Group \"" << group
<< "\"\n"
681 "# PROP Default_Filter \"" << filter
<< "\"\n";
685 void cmLocalVisualStudio6Generator::WriteDSPEndGroup(std::ostream
& fout
)
687 fout
<< "# End Group\n";
693 void cmLocalVisualStudio6Generator::SetBuildType(BuildType b
,
697 std::string root
= this->Makefile
->GetRequiredDefinition("CMAKE_ROOT");
699 this->Makefile
->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
707 root
+= "/Templates";
713 this->DSPHeaderTemplate
= root
;
714 this->DSPHeaderTemplate
+= "/staticLibHeader.dsptemplate";
715 this->DSPFooterTemplate
= root
;
716 this->DSPFooterTemplate
+= "/staticLibFooter.dsptemplate";
719 this->DSPHeaderTemplate
= root
;
720 this->DSPHeaderTemplate
+= "/DLLHeader.dsptemplate";
721 this->DSPFooterTemplate
= root
;
722 this->DSPFooterTemplate
+= "/DLLFooter.dsptemplate";
725 if ( target
.GetPropertyAsBool("WIN32_EXECUTABLE") )
727 this->DSPHeaderTemplate
= root
;
728 this->DSPHeaderTemplate
+= "/EXEWinHeader.dsptemplate";
729 this->DSPFooterTemplate
= root
;
730 this->DSPFooterTemplate
+= "/EXEFooter.dsptemplate";
734 this->DSPHeaderTemplate
= root
;
735 this->DSPHeaderTemplate
+= "/EXEHeader.dsptemplate";
736 this->DSPFooterTemplate
= root
;
737 this->DSPFooterTemplate
+= "/EXEFooter.dsptemplate";
741 this->DSPHeaderTemplate
= root
;
742 this->DSPHeaderTemplate
+= "/UtilityHeader.dsptemplate";
743 this->DSPFooterTemplate
= root
;
744 this->DSPFooterTemplate
+= "/UtilityFooter.dsptemplate";
748 // once the build type is set, determine what configurations are
750 std::ifstream
fin(this->DSPHeaderTemplate
.c_str());
752 cmsys::RegularExpression
reg("# Name ");
755 cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate
.c_str());
758 // reset this->Configurations
759 this->Configurations
.erase(this->Configurations
.begin(),
760 this->Configurations
.end());
761 // now add all the configurations possible
763 while(cmSystemTools::GetLineFromStream(fin
, line
))
765 cmSystemTools::ReplaceString(line
, "OUTPUT_LIBNAME",libName
);
768 this->Configurations
.push_back(line
.substr(reg
.end()));
773 // look for custom rules on a target and collect them together
775 cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget
&target
,
776 const char* configName
,
777 const char * /* libName */)
779 std::string customRuleCode
= "";
781 if (target
.GetType() >= cmTarget::UTILITY
)
783 return customRuleCode
;
786 // are there any rules?
787 if (target
.GetPreBuildCommands().size() +
788 target
.GetPreLinkCommands().size() +
789 target
.GetPostBuildCommands().size() == 0)
791 return customRuleCode
;
794 customRuleCode
= "# Begin Special Build Tool\n";
796 // Write the pre-build and pre-link together (VS6 does not support
797 // both). Make sure no continuation character is put on the last
799 int prelink_total
= (static_cast<int>(target
.GetPreBuildCommands().size())+
800 static_cast<int>(target
.GetPreLinkCommands().size()));
801 int prelink_count
= 0;
802 if(prelink_total
> 0)
805 customRuleCode
+= "PreLink_Cmds=";
807 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
808 target
.GetPreBuildCommands().begin();
809 cr
!= target
.GetPreBuildCommands().end(); ++cr
)
811 if(prelink_count
++ > 0)
813 customRuleCode
+= "\\\n\t";
815 customRuleCode
+= this->ConstructScript(cr
->GetCommandLines(),
816 cr
->GetWorkingDirectory(),
818 cr
->GetEscapeOldStyle(),
819 cr
->GetEscapeAllowMakeVars(),
822 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
823 target
.GetPreLinkCommands().begin();
824 cr
!= target
.GetPreLinkCommands().end(); ++cr
)
826 if(prelink_count
++ > 0)
828 customRuleCode
+= "\\\n\t";
830 customRuleCode
+= this->ConstructScript(cr
->GetCommandLines(),
831 cr
->GetWorkingDirectory(),
833 cr
->GetEscapeOldStyle(),
834 cr
->GetEscapeAllowMakeVars(),
837 if(prelink_total
> 0)
839 customRuleCode
+= "\n";
842 // Write the post-build rules. Make sure no continuation character
843 // is put on the last line.
844 int postbuild_total
=
845 static_cast<int>(target
.GetPostBuildCommands().size());
846 int postbuild_count
= 0;
847 if(postbuild_total
> 0)
849 customRuleCode
+= "PostBuild_Cmds=";
851 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
852 target
.GetPostBuildCommands().begin();
853 cr
!= target
.GetPostBuildCommands().end(); ++cr
)
855 if(postbuild_count
++ > 0)
857 customRuleCode
+= "\\\n\t";
859 customRuleCode
+= this->ConstructScript(cr
->GetCommandLines(),
860 cr
->GetWorkingDirectory(),
862 cr
->GetEscapeOldStyle(),
863 cr
->GetEscapeAllowMakeVars(),
866 if(postbuild_total
> 0)
868 customRuleCode
+= "\n";
871 customRuleCode
+= "# End Special Build Tool\n";
872 return customRuleCode
;
876 inline std::string
removeQuotes(const std::string
& s
)
878 if(s
[0] == '\"' && s
[s
.size()-1] == '\"')
880 return s
.substr(1, s
.size()-2);
885 // Code in blocks surrounded by a test for this definition is needed
886 // only for compatibility with user project's replacement DSP
887 // templates. The CMake templates no longer use them.
888 #define CM_USE_OLD_VS6
890 void cmLocalVisualStudio6Generator
891 ::WriteDSPHeader(std::ostream
& fout
,
892 const char *libName
, cmTarget
&target
,
893 std::vector
<cmSourceGroup
> &)
895 // Lookup the output directory for the target.
896 std::string outPath
= target
.GetDirectory();
898 #ifdef CM_USE_OLD_VS6
899 // Lookup the library and executable output directories.
901 if(this->Makefile
->GetDefinition("LIBRARY_OUTPUT_PATH"))
903 libPath
= this->Makefile
->GetDefinition("LIBRARY_OUTPUT_PATH");
906 if(this->Makefile
->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
908 exePath
= this->Makefile
->GetDefinition("EXECUTABLE_OUTPUT_PATH");
911 // Make sure there are trailing slashes.
914 if(libPath
[libPath
.size()-1] != '/')
921 if(exePath
[exePath
.size()-1] != '/')
927 std::set
<std::string
> pathEmitted
;
929 // determine the link directories
930 std::string libOptions
;
931 std::string libDebugOptions
;
932 std::string libOptimizedOptions
;
934 std::string libMultiLineOptions
;
935 std::string libMultiLineOptionsForDebug
;
936 std::string libMultiLineDebugOptions
;
937 std::string libMultiLineOptimizedOptions
;
942 this->ConvertToOptionallyRelativeOutputPath(libPath
.c_str());
943 if(lpath
.size() == 0)
947 std::string lpathIntDir
= libPath
+ "$(INTDIR)";
949 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir
.c_str());
950 if(pathEmitted
.insert(lpath
).second
)
952 libOptions
+= " /LIBPATH:";
953 libOptions
+= lpathIntDir
;
955 libOptions
+= " /LIBPATH:";
958 libMultiLineOptions
+= "# ADD LINK32 /LIBPATH:";
959 libMultiLineOptions
+= lpathIntDir
;
960 libMultiLineOptions
+= " ";
961 libMultiLineOptions
+= " /LIBPATH:";
962 libMultiLineOptions
+= lpath
;
963 libMultiLineOptions
+= " \n";
964 libMultiLineOptionsForDebug
+= "# ADD LINK32 /LIBPATH:";
965 libMultiLineOptionsForDebug
+= lpathIntDir
;
966 libMultiLineOptionsForDebug
+= " ";
967 libMultiLineOptionsForDebug
+= " /LIBPATH:";
968 libMultiLineOptionsForDebug
+= lpath
;
969 libMultiLineOptionsForDebug
+= " \n";
975 this->ConvertToOptionallyRelativeOutputPath(exePath
.c_str());
976 if(lpath
.size() == 0)
980 std::string lpathIntDir
= exePath
+ "$(INTDIR)";
982 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir
.c_str());
984 if(pathEmitted
.insert(lpath
).second
)
986 libOptions
+= " /LIBPATH:";
987 libOptions
+= lpathIntDir
;
989 libOptions
+= " /LIBPATH:";
992 libMultiLineOptions
+= "# ADD LINK32 /LIBPATH:";
993 libMultiLineOptions
+= lpathIntDir
;
994 libMultiLineOptions
+= " ";
995 libMultiLineOptions
+= " /LIBPATH:";
996 libMultiLineOptions
+= lpath
;
997 libMultiLineOptions
+= " \n";
998 libMultiLineOptionsForDebug
+= "# ADD LINK32 /LIBPATH:";
999 libMultiLineOptionsForDebug
+= lpathIntDir
;
1000 libMultiLineOptionsForDebug
+= " ";
1001 libMultiLineOptionsForDebug
+= " /LIBPATH:";
1002 libMultiLineOptionsForDebug
+= lpath
;
1003 libMultiLineOptionsForDebug
+= " \n";
1006 std::vector
<std::string
>::const_iterator i
;
1007 const std::vector
<std::string
>& libdirs
= target
.GetLinkDirectories();
1008 for(i
= libdirs
.begin(); i
!= libdirs
.end(); ++i
)
1010 std::string path
= *i
;
1011 if(path
[path
.size()-1] != '/')
1016 this->ConvertToOptionallyRelativeOutputPath(path
.c_str());
1017 if(lpath
.size() == 0)
1021 std::string lpathIntDir
= path
+ "$(INTDIR)";
1023 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir
.c_str());
1024 if(pathEmitted
.insert(lpath
).second
)
1026 libOptions
+= " /LIBPATH:";
1027 libOptions
+= lpathIntDir
;
1029 libOptions
+= " /LIBPATH:";
1030 libOptions
+= lpath
;
1033 libMultiLineOptions
+= "# ADD LINK32 /LIBPATH:";
1034 libMultiLineOptions
+= lpathIntDir
;
1035 libMultiLineOptions
+= " ";
1036 libMultiLineOptions
+= " /LIBPATH:";
1037 libMultiLineOptions
+= lpath
;
1038 libMultiLineOptions
+= " \n";
1039 libMultiLineOptionsForDebug
+= "# ADD LINK32 /LIBPATH:";
1040 libMultiLineOptionsForDebug
+= lpathIntDir
;
1041 libMultiLineOptionsForDebug
+= " ";
1042 libMultiLineOptionsForDebug
+= " /LIBPATH:";
1043 libMultiLineOptionsForDebug
+= lpath
;
1044 libMultiLineOptionsForDebug
+= " \n";
1047 // find link libraries
1048 const cmTarget::LinkLibraryVectorType
& libs
= target
.GetLinkLibraries();
1049 cmTarget::LinkLibraryVectorType::const_iterator j
;
1050 for(j
= libs
.begin(); j
!= libs
.end(); ++j
)
1052 // add libraries to executables and dlls (but never include
1053 // a library in a library, bad recursion)
1054 // NEVER LINK STATIC LIBRARIES TO OTHER STATIC LIBRARIES
1055 if ((target
.GetType() != cmTarget::SHARED_LIBRARY
1056 && target
.GetType() != cmTarget::STATIC_LIBRARY
1057 && target
.GetType() != cmTarget::MODULE_LIBRARY
) ||
1058 (target
.GetType()==cmTarget::SHARED_LIBRARY
&& libName
!= j
->first
) ||
1059 (target
.GetType()==cmTarget::MODULE_LIBRARY
&& libName
!= j
->first
))
1061 // Compute the proper name to use to link this library.
1063 std::string libDebug
;
1064 cmTarget
* tgt
= this->GlobalGenerator
->FindTarget(0, j
->first
.c_str(),
1068 lib
= cmSystemTools::GetFilenameWithoutExtension
1069 (tgt
->GetFullName().c_str());
1070 libDebug
= cmSystemTools::GetFilenameWithoutExtension
1071 (tgt
->GetFullName("Debug").c_str());
1077 lib
= j
->first
.c_str();
1078 libDebug
= j
->first
.c_str();
1079 if(j
->first
.find(".lib") == std::string::npos
)
1085 lib
= this->ConvertToOptionallyRelativeOutputPath(lib
.c_str());
1087 this->ConvertToOptionallyRelativeOutputPath(libDebug
.c_str());
1089 if (j
->second
== cmTarget::GENERAL
)
1093 libMultiLineOptions
+= "# ADD LINK32 ";
1094 libMultiLineOptions
+= lib
;
1095 libMultiLineOptions
+= "\n";
1096 libMultiLineOptionsForDebug
+= "# ADD LINK32 ";
1097 libMultiLineOptionsForDebug
+= libDebug
;
1098 libMultiLineOptionsForDebug
+= "\n";
1100 if (j
->second
== cmTarget::DEBUG
)
1102 libDebugOptions
+= " ";
1103 libDebugOptions
+= lib
;
1105 libMultiLineDebugOptions
+= "# ADD LINK32 ";
1106 libMultiLineDebugOptions
+= libDebug
;
1107 libMultiLineDebugOptions
+= "\n";
1109 if (j
->second
== cmTarget::OPTIMIZED
)
1111 libOptimizedOptions
+= " ";
1112 libOptimizedOptions
+= lib
;
1114 libMultiLineOptimizedOptions
+= "# ADD LINK32 ";
1115 libMultiLineOptimizedOptions
+= lib
;
1116 libMultiLineOptimizedOptions
+= "\n";
1122 // Get extra linker options for this target type.
1123 std::string extraLinkOptions
;
1124 if(target
.GetType() == cmTarget::EXECUTABLE
)
1127 this->Makefile
->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1129 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1132 this->Makefile
->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1134 if(target
.GetType() == cmTarget::MODULE_LIBRARY
)
1137 this->Makefile
->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1140 // Get extra linker options for this target.
1141 if(const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS"))
1143 extraLinkOptions
+= " ";
1144 extraLinkOptions
+= targetLinkFlags
;
1147 // Get standard libraries for this language.
1148 if(target
.GetType() >= cmTarget::EXECUTABLE
&&
1149 target
.GetType() <= cmTarget::MODULE_LIBRARY
)
1151 // Get the language to use for linking.
1152 const char* linkLanguage
=
1153 target
.GetLinkerLanguage(this->GetGlobalGenerator());
1156 cmSystemTools::Error
1157 ("CMake can not determine linker language for target:",
1162 // Compute the variable name to lookup standard libraries for this
1164 std::string standardLibsVar
= "CMAKE_";
1165 standardLibsVar
+= linkLanguage
;
1166 standardLibsVar
+= "_STANDARD_LIBRARIES";
1168 // Add standard libraries.
1169 if(const char* stdLibs
=
1170 this->Makefile
->GetDefinition(standardLibsVar
.c_str()))
1172 extraLinkOptions
+= " ";
1173 extraLinkOptions
+= stdLibs
;
1177 // Compute version number information.
1178 std::string targetVersionFlag
;
1179 if(target
.GetType() == cmTarget::EXECUTABLE
||
1180 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1181 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1185 target
.GetTargetVersion(major
, minor
);
1186 cmOStringStream targetVersionStream
;
1187 targetVersionStream
<< "/version:" << major
<< "." << minor
;
1188 targetVersionFlag
= targetVersionStream
.str();
1191 // Compute the real name of the target.
1192 std::string outputName
=
1193 "(OUTPUT_NAME is for libraries and executables only)";
1194 std::string outputNameDebug
= outputName
;
1195 std::string outputNameRelease
= outputName
;
1196 std::string outputNameMinSizeRel
= outputName
;
1197 std::string outputNameRelWithDebInfo
= outputName
;
1198 if(target
.GetType() == cmTarget::EXECUTABLE
||
1199 target
.GetType() == cmTarget::STATIC_LIBRARY
||
1200 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1201 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1203 outputName
= target
.GetFullName();
1204 outputNameDebug
= target
.GetFullName("Debug");
1205 outputNameRelease
= target
.GetFullName("Release");
1206 outputNameMinSizeRel
= target
.GetFullName("MinSizeRel");
1207 outputNameRelWithDebInfo
= target
.GetFullName("RelWithDebInfo");
1210 // Compute the proper link information for the target.
1211 std::string optionsDebug
;
1212 std::string optionsRelease
;
1213 std::string optionsMinSizeRel
;
1214 std::string optionsRelWithDebInfo
;
1215 if(target
.GetType() == cmTarget::EXECUTABLE
||
1216 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1217 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1219 this->ComputeLinkOptions(target
, "Debug", extraLinkOptions
,
1221 this->ComputeLinkOptions(target
, "Release", extraLinkOptions
,
1223 this->ComputeLinkOptions(target
, "MinSizeRel", extraLinkOptions
,
1225 this->ComputeLinkOptions(target
, "RelWithDebInfo", extraLinkOptions
,
1226 optionsRelWithDebInfo
);
1229 // Compute the path of the import library.
1230 std::string targetImplibFlagDebug
;
1231 std::string targetImplibFlagRelease
;
1232 std::string targetImplibFlagMinSizeRel
;
1233 std::string targetImplibFlagRelWithDebInfo
;
1234 if(target
.GetType() == cmTarget::SHARED_LIBRARY
||
1235 target
.GetType() == cmTarget::MODULE_LIBRARY
||
1236 target
.GetType() == cmTarget::EXECUTABLE
)
1238 std::string fullPathImpDebug
= target
.GetDirectory("Debug", true);
1239 std::string fullPathImpRelease
= target
.GetDirectory("Release", true);
1240 std::string fullPathImpMinSizeRel
=
1241 target
.GetDirectory("MinSizeRel", true);
1242 std::string fullPathImpRelWithDebInfo
=
1243 target
.GetDirectory("RelWithDebInfo", true);
1244 fullPathImpDebug
+= "/";
1245 fullPathImpRelease
+= "/";
1246 fullPathImpMinSizeRel
+= "/";
1247 fullPathImpRelWithDebInfo
+= "/";
1248 fullPathImpDebug
+= target
.GetFullName("Debug", true);
1249 fullPathImpRelease
+= target
.GetFullName("Release", true);
1250 fullPathImpMinSizeRel
+= target
.GetFullName("MinSizeRel", true);
1251 fullPathImpRelWithDebInfo
+= target
.GetFullName("RelWithDebInfo", true);
1253 targetImplibFlagDebug
= "/implib:";
1254 targetImplibFlagRelease
= "/implib:";
1255 targetImplibFlagMinSizeRel
= "/implib:";
1256 targetImplibFlagRelWithDebInfo
= "/implib:";
1257 targetImplibFlagDebug
+=
1258 this->ConvertToOptionallyRelativeOutputPath(fullPathImpDebug
.c_str());
1259 targetImplibFlagRelease
+=
1260 this->ConvertToOptionallyRelativeOutputPath(fullPathImpRelease
.c_str());
1261 targetImplibFlagMinSizeRel
+=
1262 this->ConvertToOptionallyRelativeOutputPath(
1263 fullPathImpMinSizeRel
.c_str());
1264 targetImplibFlagRelWithDebInfo
+=
1265 this->ConvertToOptionallyRelativeOutputPath(
1266 fullPathImpRelWithDebInfo
.c_str());
1269 #ifdef CM_USE_OLD_VS6
1270 // Compute link information for the target.
1271 if(extraLinkOptions
.size())
1274 libOptions
+= extraLinkOptions
;
1276 libMultiLineOptions
+= "# ADD LINK32 ";
1277 libMultiLineOptions
+= extraLinkOptions
;
1278 libMultiLineOptions
+= " \n";
1279 libMultiLineOptionsForDebug
+= "# ADD LINK32 ";
1280 libMultiLineOptionsForDebug
+= extraLinkOptions
;
1281 libMultiLineOptionsForDebug
+= " \n";
1285 // are there any custom rules on the target itself
1286 // only if the target is a lib or exe
1287 std::string customRuleCodeRelease
1288 = this->CreateTargetRules(target
, "RELEASE", libName
);
1289 std::string customRuleCodeDebug
1290 = this->CreateTargetRules(target
, "DEBUG", libName
);
1291 std::string customRuleCodeMinSizeRel
1292 = this->CreateTargetRules(target
, "MINSIZEREL", libName
);
1293 std::string customRuleCodeRelWithDebInfo
1294 = this->CreateTargetRules(target
, "RELWITHDEBINFO", libName
);
1296 std::ifstream
fin(this->DSPHeaderTemplate
.c_str());
1299 cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate
.c_str());
1301 std::string staticLibOptions
;
1302 if(target
.GetType() == cmTarget::STATIC_LIBRARY
)
1304 if(const char* libflags
= target
.GetProperty("STATIC_LIBRARY_FLAGS"))
1306 staticLibOptions
= libflags
;
1310 // Add the export symbol definition for shared library objects.
1311 std::string exportSymbol
;
1312 if(const char* exportMacro
= target
.GetExportMacro())
1314 exportSymbol
= exportMacro
;
1318 while(cmSystemTools::GetLineFromStream(fin
, line
))
1320 const char* mfcFlag
= this->Makefile
->GetDefinition("CMAKE_MFC_FLAG");
1325 cmSystemTools::ReplaceString(line
, "OUTPUT_LIBNAME_EXPORTS",
1326 exportSymbol
.c_str());
1327 cmSystemTools::ReplaceString(line
, "CMAKE_MFC_FLAG",
1329 if(target
.GetType() == cmTarget::STATIC_LIBRARY
)
1331 cmSystemTools::ReplaceString(line
, "CM_STATIC_LIB_ARGS",
1332 staticLibOptions
.c_str());
1334 if(this->Makefile
->IsOn("CMAKE_VERBOSE_MAKEFILE"))
1336 cmSystemTools::ReplaceString(line
, "/nologo", "");
1339 #ifdef CM_USE_OLD_VS6
1340 cmSystemTools::ReplaceString(line
, "CM_LIBRARIES",
1341 libOptions
.c_str());
1342 cmSystemTools::ReplaceString(line
, "CM_DEBUG_LIBRARIES",
1343 libDebugOptions
.c_str());
1344 cmSystemTools::ReplaceString(line
, "CM_OPTIMIZED_LIBRARIES",
1345 libOptimizedOptions
.c_str());
1346 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_LIBRARIES_FOR_DEBUG",
1347 libMultiLineOptionsForDebug
.c_str());
1348 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_LIBRARIES",
1349 libMultiLineOptions
.c_str());
1350 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_DEBUG_LIBRARIES",
1351 libMultiLineDebugOptions
.c_str());
1352 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
1353 libMultiLineOptimizedOptions
.c_str());
1356 // Substitute the rules for custom command. When specifying just the
1357 // target name for the command the command can be different for
1358 // different configs
1359 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_RELEASE",
1360 customRuleCodeRelease
.c_str());
1361 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_DEBUG",
1362 customRuleCodeDebug
.c_str());
1363 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_MINSIZEREL",
1364 customRuleCodeMinSizeRel
.c_str());
1365 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO",
1366 customRuleCodeRelWithDebInfo
.c_str());
1368 // Substitute the real output name into the template.
1369 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_DEBUG",
1370 outputNameDebug
.c_str());
1371 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_RELEASE",
1372 outputNameRelease
.c_str());
1373 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_MINSIZEREL",
1374 outputNameMinSizeRel
.c_str());
1375 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_RELWITHDEBINFO",
1376 outputNameRelWithDebInfo
.c_str());
1377 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME", outputName
.c_str());
1379 // Substitute the proper link information into the template.
1380 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_DEBUG",
1381 optionsDebug
.c_str());
1382 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_RELEASE",
1383 optionsRelease
.c_str());
1384 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_MINSIZEREL",
1385 optionsMinSizeRel
.c_str());
1386 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_RELWITHDEBINFO",
1387 optionsRelWithDebInfo
.c_str());
1389 cmSystemTools::ReplaceString(line
, "BUILD_INCLUDES",
1390 this->IncludeOptions
.c_str());
1391 cmSystemTools::ReplaceString(line
, "TARGET_VERSION_FLAG",
1392 targetVersionFlag
.c_str());
1393 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_DEBUG",
1394 targetImplibFlagDebug
.c_str());
1395 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_RELEASE",
1396 targetImplibFlagRelease
.c_str());
1397 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_MINSIZEREL",
1398 targetImplibFlagMinSizeRel
.c_str());
1399 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_RELWITHDEBINFO",
1400 targetImplibFlagRelWithDebInfo
.c_str());
1401 cmSystemTools::ReplaceString(line
, "OUTPUT_LIBNAME",libName
);
1402 #ifdef CM_USE_OLD_VS6
1403 // because LIBRARY_OUTPUT_PATH and EXECUTABLE_OUTPUT_PATH
1404 // are already quoted in the template file,
1405 // we need to remove the quotes here, we still need
1406 // to convert to output path for unix to win32 conversion
1407 cmSystemTools::ReplaceString
1408 (line
, "LIBRARY_OUTPUT_PATH",
1409 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1410 (libPath
.c_str())).c_str());
1411 cmSystemTools::ReplaceString
1412 (line
, "EXECUTABLE_OUTPUT_PATH",
1413 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1414 (exePath
.c_str())).c_str());
1416 cmSystemTools::ReplaceString
1417 (line
, "OUTPUT_DIRECTORY",
1418 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1419 (outPath
.c_str())).c_str());
1421 cmSystemTools::ReplaceString(line
,
1423 this->Makefile
->GetDefineFlags());
1424 const char* debugPostfix
1425 = this->Makefile
->GetDefinition("CMAKE_DEBUG_POSTFIX");
1426 cmSystemTools::ReplaceString(line
, "DEBUG_POSTFIX",
1427 debugPostfix
?debugPostfix
:"");
1428 // store flags for each configuration
1429 std::string flags
= " ";
1430 std::string flagsRelease
= " ";
1431 std::string flagsMinSize
= " ";
1432 std::string flagsDebug
= " ";
1433 std::string flagsDebugRel
= " ";
1434 if(target
.GetType() >= cmTarget::EXECUTABLE
&&
1435 target
.GetType() <= cmTarget::MODULE_LIBRARY
)
1437 const char* linkLanguage
=
1438 target
.GetLinkerLanguage(this->GetGlobalGenerator());
1441 cmSystemTools::Error
1442 ("CMake can not determine linker language for target:",
1446 // if CXX is on and the target contains cxx code then add the cxx flags
1447 std::string baseFlagVar
= "CMAKE_";
1448 baseFlagVar
+= linkLanguage
;
1449 baseFlagVar
+= "_FLAGS";
1450 flags
= this->Makefile
->GetSafeDefinition(baseFlagVar
.c_str());
1452 std::string flagVar
= baseFlagVar
+ "_RELEASE";
1453 flagsRelease
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1454 flagsRelease
+= " -DCMAKE_INTDIR=\\\"Release\\\" ";
1455 if(const char* targetLinkFlags
=
1456 target
.GetProperty("LINK_FLAGS_RELEASE"))
1458 flagsRelease
+= targetLinkFlags
;
1459 flagsRelease
+= " ";
1461 flagVar
= baseFlagVar
+ "_MINSIZEREL";
1462 flagsMinSize
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1463 flagsMinSize
+= " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
1464 if(const char* targetLinkFlags
=
1465 target
.GetProperty("LINK_FLAGS_MINSIZEREL"))
1467 flagsMinSize
+= targetLinkFlags
;
1468 flagsMinSize
+= " ";
1471 flagVar
= baseFlagVar
+ "_DEBUG";
1472 flagsDebug
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1473 flagsDebug
+= " -DCMAKE_INTDIR=\\\"Debug\\\" ";
1474 if(const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS_DEBUG"))
1476 flagsDebug
+= targetLinkFlags
;
1480 flagVar
= baseFlagVar
+ "_RELWITHDEBINFO";
1481 flagsDebugRel
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1482 flagsDebugRel
+= " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
1483 if(const char* targetLinkFlags
=
1484 target
.GetProperty("LINK_FLAGS_RELWITHDEBINFO"))
1486 flagsDebugRel
+= targetLinkFlags
;
1487 flagsDebugRel
+= " ";
1492 // if unicode is not found, then add -D_MBCS
1493 std::string defs
= this->Makefile
->GetDefineFlags();
1494 if(flags
.find("D_UNICODE") == flags
.npos
&&
1495 defs
.find("D_UNICODE") == flags
.npos
)
1497 flags
+= " /D \"_MBCS\"";
1500 // Add per-target flags.
1501 if(const char* targetFlags
= target
.GetProperty("COMPILE_FLAGS"))
1504 flags
+= targetFlags
;
1507 // Add per-target and per-configuration preprocessor definitions.
1509 (flags
, this->Makefile
->GetProperty("COMPILE_DEFINITIONS"), 0);
1510 this->AppendDefines(flags
, target
.GetProperty("COMPILE_DEFINITIONS"), 0);
1513 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_DEBUG"), 0);
1514 this->AppendDefines(flagsDebug
,
1515 target
.GetProperty("COMPILE_DEFINITIONS_DEBUG"), 0);
1518 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1519 this->AppendDefines(flagsRelease
,
1520 target
.GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1523 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1526 target
.GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1529 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"), 0);
1532 target
.GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"), 0);
1534 // The template files have CXX FLAGS in them, that need to be replaced.
1535 // There are not separate CXX and C template files, so we use the same
1536 // variable names. The previous code sets up flags* variables to contain
1537 // the correct C or CXX flags
1538 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_MINSIZEREL",
1539 flagsMinSize
.c_str());
1540 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_DEBUG",
1541 flagsDebug
.c_str());
1542 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
1543 flagsDebugRel
.c_str());
1544 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_RELEASE",
1545 flagsRelease
.c_str());
1546 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS", flags
.c_str());
1547 fout
<< line
.c_str() << std::endl
;
1551 void cmLocalVisualStudio6Generator::WriteDSPFooter(std::ostream
& fout
)
1553 std::ifstream
fin(this->DSPFooterTemplate
.c_str());
1556 cmSystemTools::Error("Error Reading ",
1557 this->DSPFooterTemplate
.c_str());
1560 while(cmSystemTools::GetLineFromStream(fin
, line
))
1562 fout
<< line
<< std::endl
;
1566 //----------------------------------------------------------------------------
1567 void cmLocalVisualStudio6Generator
1568 ::ComputeLinkOptions(cmTarget
& target
,
1569 const char* configName
,
1570 const std::string extraOptions
,
1571 std::string
& options
)
1573 // Compute the link information for this configuration.
1574 cmComputeLinkInformation
cli(&target
, configName
);
1579 typedef cmComputeLinkInformation::ItemVector ItemVector
;
1580 ItemVector
const& linkLibs
= cli
.GetItems();
1581 std::vector
<std::string
> const& linkDirs
= cli
.GetDirectories();
1583 // Build the link options code.
1584 for(std::vector
<std::string
>::const_iterator d
= linkDirs
.begin();
1585 d
!= linkDirs
.end(); ++d
)
1587 std::string dir
= *d
;
1590 if(dir
[dir
.size()-1] != '/')
1595 options
+= "# ADD LINK32 /LIBPATH:";
1596 options
+= this->ConvertToOptionallyRelativeOutputPath(dir
.c_str());
1597 options
+= " /LIBPATH:";
1598 options
+= this->ConvertToOptionallyRelativeOutputPath(d
->c_str());
1602 for(ItemVector::const_iterator l
= linkLibs
.begin();
1603 l
!= linkLibs
.end(); ++l
)
1605 options
+= "# ADD LINK32 ";
1609 this->ConvertToOptionallyRelativeOutputPath(l
->Value
.c_str());
1613 options
+= l
->Value
;
1618 // Add extra options if any.
1619 if(!extraOptions
.empty())
1621 options
+= "# ADD LINK32 ";
1622 options
+= extraOptions
;
1628 cmLocalVisualStudio6Generator
1629 ::GetTargetDirectory(cmTarget
const&) const
1631 // No per-target directory for this generator (yet).
1635 void cmLocalVisualStudio6Generator
1636 ::GetTargetObjectFileDirectories(cmTarget
* ,
1637 std::vector
<std::string
>&
1640 std::string dir
= this->Makefile
->GetCurrentOutputDirectory();
1642 dir
+= this->GetGlobalGenerator()->GetCMakeCFGInitDirectory();
1643 dirs
.push_back(dir
);
1647 cmLocalVisualStudio6Generator
1648 ::GetConfigName(std::string
const& configuration
) const
1650 // Strip the subdirectory name out of the configuration name.
1651 std::string config
= configuration
;
1652 std::string::size_type pos
= config
.find_last_of(" ");
1653 config
= config
.substr(pos
+1, std::string::npos
);
1654 config
= config
.substr(0, config
.size()-1);
1658 //----------------------------------------------------------------------------
1660 cmLocalVisualStudio6Generator
1661 ::CheckDefinition(std::string
const& define
) const
1663 // Perform the standard check first.
1664 if(!this->cmLocalGenerator::CheckDefinition(define
))
1669 // Now do the VS6-specific check.
1670 if(define
.find_first_of("=") != define
.npos
)
1673 e
<< "WARNING: The VS6 IDE does not support preprocessor definitions "
1675 << "CMake is dropping a preprocessor definition: " << define
<< "\n"
1676 << "Consider defining the macro in a (configured) header file.\n";
1677 cmSystemTools::Message(e
.str().c_str());
1681 // Assume it is supported.