1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmLocalVisualStudio6Generator.cxx,v $
6 Date: $Date: 2008-09-09 17:04:30 $
7 Version: $Revision: 1.144 $
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() && sg
->GetGroupChildren().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
> const& 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());
1067 lib
= cmSystemTools::GetFilenameWithoutExtension
1068 (tgt
->GetFullName().c_str());
1069 libDebug
= cmSystemTools::GetFilenameWithoutExtension
1070 (tgt
->GetFullName("Debug").c_str());
1076 lib
= j
->first
.c_str();
1077 libDebug
= j
->first
.c_str();
1078 if(j
->first
.find(".lib") == std::string::npos
)
1084 lib
= this->ConvertToOptionallyRelativeOutputPath(lib
.c_str());
1086 this->ConvertToOptionallyRelativeOutputPath(libDebug
.c_str());
1088 if (j
->second
== cmTarget::GENERAL
)
1092 libMultiLineOptions
+= "# ADD LINK32 ";
1093 libMultiLineOptions
+= lib
;
1094 libMultiLineOptions
+= "\n";
1095 libMultiLineOptionsForDebug
+= "# ADD LINK32 ";
1096 libMultiLineOptionsForDebug
+= libDebug
;
1097 libMultiLineOptionsForDebug
+= "\n";
1099 if (j
->second
== cmTarget::DEBUG
)
1101 libDebugOptions
+= " ";
1102 libDebugOptions
+= lib
;
1104 libMultiLineDebugOptions
+= "# ADD LINK32 ";
1105 libMultiLineDebugOptions
+= libDebug
;
1106 libMultiLineDebugOptions
+= "\n";
1108 if (j
->second
== cmTarget::OPTIMIZED
)
1110 libOptimizedOptions
+= " ";
1111 libOptimizedOptions
+= lib
;
1113 libMultiLineOptimizedOptions
+= "# ADD LINK32 ";
1114 libMultiLineOptimizedOptions
+= lib
;
1115 libMultiLineOptimizedOptions
+= "\n";
1121 // Get extra linker options for this target type.
1122 std::string extraLinkOptions
;
1123 if(target
.GetType() == cmTarget::EXECUTABLE
)
1126 this->Makefile
->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1128 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1131 this->Makefile
->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1133 if(target
.GetType() == cmTarget::MODULE_LIBRARY
)
1136 this->Makefile
->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1139 // Get extra linker options for this target.
1140 if(const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS"))
1142 extraLinkOptions
+= " ";
1143 extraLinkOptions
+= targetLinkFlags
;
1146 // Get standard libraries for this language.
1147 if(target
.GetType() >= cmTarget::EXECUTABLE
&&
1148 target
.GetType() <= cmTarget::MODULE_LIBRARY
)
1150 // Get the language to use for linking.
1151 const char* linkLanguage
=
1152 target
.GetLinkerLanguage(this->GetGlobalGenerator());
1155 cmSystemTools::Error
1156 ("CMake can not determine linker language for target:",
1161 // Compute the variable name to lookup standard libraries for this
1163 std::string standardLibsVar
= "CMAKE_";
1164 standardLibsVar
+= linkLanguage
;
1165 standardLibsVar
+= "_STANDARD_LIBRARIES";
1167 // Add standard libraries.
1168 if(const char* stdLibs
=
1169 this->Makefile
->GetDefinition(standardLibsVar
.c_str()))
1171 extraLinkOptions
+= " ";
1172 extraLinkOptions
+= stdLibs
;
1176 // Compute version number information.
1177 std::string targetVersionFlag
;
1178 if(target
.GetType() == cmTarget::EXECUTABLE
||
1179 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1180 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1184 target
.GetTargetVersion(major
, minor
);
1185 cmOStringStream targetVersionStream
;
1186 targetVersionStream
<< "/version:" << major
<< "." << minor
;
1187 targetVersionFlag
= targetVersionStream
.str();
1190 // Compute the real name of the target.
1191 std::string outputName
=
1192 "(OUTPUT_NAME is for libraries and executables only)";
1193 std::string outputNameDebug
= outputName
;
1194 std::string outputNameRelease
= outputName
;
1195 std::string outputNameMinSizeRel
= outputName
;
1196 std::string outputNameRelWithDebInfo
= outputName
;
1197 if(target
.GetType() == cmTarget::EXECUTABLE
||
1198 target
.GetType() == cmTarget::STATIC_LIBRARY
||
1199 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1200 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1202 outputName
= target
.GetFullName();
1203 outputNameDebug
= target
.GetFullName("Debug");
1204 outputNameRelease
= target
.GetFullName("Release");
1205 outputNameMinSizeRel
= target
.GetFullName("MinSizeRel");
1206 outputNameRelWithDebInfo
= target
.GetFullName("RelWithDebInfo");
1209 // Compute the proper link information for the target.
1210 std::string optionsDebug
;
1211 std::string optionsRelease
;
1212 std::string optionsMinSizeRel
;
1213 std::string optionsRelWithDebInfo
;
1214 if(target
.GetType() == cmTarget::EXECUTABLE
||
1215 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1216 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1218 this->ComputeLinkOptions(target
, "Debug", extraLinkOptions
,
1220 this->ComputeLinkOptions(target
, "Release", extraLinkOptions
,
1222 this->ComputeLinkOptions(target
, "MinSizeRel", extraLinkOptions
,
1224 this->ComputeLinkOptions(target
, "RelWithDebInfo", extraLinkOptions
,
1225 optionsRelWithDebInfo
);
1228 // Compute the path of the import library.
1229 std::string targetImplibFlagDebug
;
1230 std::string targetImplibFlagRelease
;
1231 std::string targetImplibFlagMinSizeRel
;
1232 std::string targetImplibFlagRelWithDebInfo
;
1233 if(target
.GetType() == cmTarget::SHARED_LIBRARY
||
1234 target
.GetType() == cmTarget::MODULE_LIBRARY
||
1235 target
.GetType() == cmTarget::EXECUTABLE
)
1237 std::string fullPathImpDebug
= target
.GetDirectory("Debug", true);
1238 std::string fullPathImpRelease
= target
.GetDirectory("Release", true);
1239 std::string fullPathImpMinSizeRel
=
1240 target
.GetDirectory("MinSizeRel", true);
1241 std::string fullPathImpRelWithDebInfo
=
1242 target
.GetDirectory("RelWithDebInfo", true);
1243 fullPathImpDebug
+= "/";
1244 fullPathImpRelease
+= "/";
1245 fullPathImpMinSizeRel
+= "/";
1246 fullPathImpRelWithDebInfo
+= "/";
1247 fullPathImpDebug
+= target
.GetFullName("Debug", true);
1248 fullPathImpRelease
+= target
.GetFullName("Release", true);
1249 fullPathImpMinSizeRel
+= target
.GetFullName("MinSizeRel", true);
1250 fullPathImpRelWithDebInfo
+= target
.GetFullName("RelWithDebInfo", true);
1252 targetImplibFlagDebug
= "/implib:";
1253 targetImplibFlagRelease
= "/implib:";
1254 targetImplibFlagMinSizeRel
= "/implib:";
1255 targetImplibFlagRelWithDebInfo
= "/implib:";
1256 targetImplibFlagDebug
+=
1257 this->ConvertToOptionallyRelativeOutputPath(fullPathImpDebug
.c_str());
1258 targetImplibFlagRelease
+=
1259 this->ConvertToOptionallyRelativeOutputPath(fullPathImpRelease
.c_str());
1260 targetImplibFlagMinSizeRel
+=
1261 this->ConvertToOptionallyRelativeOutputPath(
1262 fullPathImpMinSizeRel
.c_str());
1263 targetImplibFlagRelWithDebInfo
+=
1264 this->ConvertToOptionallyRelativeOutputPath(
1265 fullPathImpRelWithDebInfo
.c_str());
1268 #ifdef CM_USE_OLD_VS6
1269 // Compute link information for the target.
1270 if(extraLinkOptions
.size())
1273 libOptions
+= extraLinkOptions
;
1275 libMultiLineOptions
+= "# ADD LINK32 ";
1276 libMultiLineOptions
+= extraLinkOptions
;
1277 libMultiLineOptions
+= " \n";
1278 libMultiLineOptionsForDebug
+= "# ADD LINK32 ";
1279 libMultiLineOptionsForDebug
+= extraLinkOptions
;
1280 libMultiLineOptionsForDebug
+= " \n";
1284 // are there any custom rules on the target itself
1285 // only if the target is a lib or exe
1286 std::string customRuleCodeRelease
1287 = this->CreateTargetRules(target
, "RELEASE", libName
);
1288 std::string customRuleCodeDebug
1289 = this->CreateTargetRules(target
, "DEBUG", libName
);
1290 std::string customRuleCodeMinSizeRel
1291 = this->CreateTargetRules(target
, "MINSIZEREL", libName
);
1292 std::string customRuleCodeRelWithDebInfo
1293 = this->CreateTargetRules(target
, "RELWITHDEBINFO", libName
);
1295 std::ifstream
fin(this->DSPHeaderTemplate
.c_str());
1298 cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate
.c_str());
1300 std::string staticLibOptions
;
1301 if(target
.GetType() == cmTarget::STATIC_LIBRARY
)
1303 if(const char* libflags
= target
.GetProperty("STATIC_LIBRARY_FLAGS"))
1305 staticLibOptions
= libflags
;
1309 // Add the export symbol definition for shared library objects.
1310 std::string exportSymbol
;
1311 if(const char* exportMacro
= target
.GetExportMacro())
1313 exportSymbol
= exportMacro
;
1317 std::string libnameExports
;
1318 if(exportSymbol
.size())
1320 libnameExports
= "/D \"";
1321 libnameExports
+= exportSymbol
;
1322 libnameExports
+= "\"";
1324 while(cmSystemTools::GetLineFromStream(fin
, line
))
1326 const char* mfcFlag
= this->Makefile
->GetDefinition("CMAKE_MFC_FLAG");
1331 cmSystemTools::ReplaceString(line
, "OUTPUT_LIBNAME_EXPORTS",
1332 libnameExports
.c_str());
1333 cmSystemTools::ReplaceString(line
, "CMAKE_MFC_FLAG",
1335 if(target
.GetType() == cmTarget::STATIC_LIBRARY
)
1337 cmSystemTools::ReplaceString(line
, "CM_STATIC_LIB_ARGS",
1338 staticLibOptions
.c_str());
1340 if(this->Makefile
->IsOn("CMAKE_VERBOSE_MAKEFILE"))
1342 cmSystemTools::ReplaceString(line
, "/nologo", "");
1345 #ifdef CM_USE_OLD_VS6
1346 cmSystemTools::ReplaceString(line
, "CM_LIBRARIES",
1347 libOptions
.c_str());
1348 cmSystemTools::ReplaceString(line
, "CM_DEBUG_LIBRARIES",
1349 libDebugOptions
.c_str());
1350 cmSystemTools::ReplaceString(line
, "CM_OPTIMIZED_LIBRARIES",
1351 libOptimizedOptions
.c_str());
1352 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_LIBRARIES_FOR_DEBUG",
1353 libMultiLineOptionsForDebug
.c_str());
1354 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_LIBRARIES",
1355 libMultiLineOptions
.c_str());
1356 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_DEBUG_LIBRARIES",
1357 libMultiLineDebugOptions
.c_str());
1358 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
1359 libMultiLineOptimizedOptions
.c_str());
1362 // Substitute the rules for custom command. When specifying just the
1363 // target name for the command the command can be different for
1364 // different configs
1365 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_RELEASE",
1366 customRuleCodeRelease
.c_str());
1367 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_DEBUG",
1368 customRuleCodeDebug
.c_str());
1369 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_MINSIZEREL",
1370 customRuleCodeMinSizeRel
.c_str());
1371 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO",
1372 customRuleCodeRelWithDebInfo
.c_str());
1374 // Substitute the real output name into the template.
1375 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_DEBUG",
1376 outputNameDebug
.c_str());
1377 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_RELEASE",
1378 outputNameRelease
.c_str());
1379 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_MINSIZEREL",
1380 outputNameMinSizeRel
.c_str());
1381 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_RELWITHDEBINFO",
1382 outputNameRelWithDebInfo
.c_str());
1383 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME", outputName
.c_str());
1385 // Substitute the proper link information into the template.
1386 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_DEBUG",
1387 optionsDebug
.c_str());
1388 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_RELEASE",
1389 optionsRelease
.c_str());
1390 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_MINSIZEREL",
1391 optionsMinSizeRel
.c_str());
1392 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_RELWITHDEBINFO",
1393 optionsRelWithDebInfo
.c_str());
1395 cmSystemTools::ReplaceString(line
, "BUILD_INCLUDES",
1396 this->IncludeOptions
.c_str());
1397 cmSystemTools::ReplaceString(line
, "TARGET_VERSION_FLAG",
1398 targetVersionFlag
.c_str());
1399 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_DEBUG",
1400 targetImplibFlagDebug
.c_str());
1401 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_RELEASE",
1402 targetImplibFlagRelease
.c_str());
1403 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_MINSIZEREL",
1404 targetImplibFlagMinSizeRel
.c_str());
1405 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_RELWITHDEBINFO",
1406 targetImplibFlagRelWithDebInfo
.c_str());
1407 cmSystemTools::ReplaceString(line
, "OUTPUT_LIBNAME",libName
);
1408 #ifdef CM_USE_OLD_VS6
1409 // because LIBRARY_OUTPUT_PATH and EXECUTABLE_OUTPUT_PATH
1410 // are already quoted in the template file,
1411 // we need to remove the quotes here, we still need
1412 // to convert to output path for unix to win32 conversion
1413 cmSystemTools::ReplaceString
1414 (line
, "LIBRARY_OUTPUT_PATH",
1415 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1416 (libPath
.c_str())).c_str());
1417 cmSystemTools::ReplaceString
1418 (line
, "EXECUTABLE_OUTPUT_PATH",
1419 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1420 (exePath
.c_str())).c_str());
1422 cmSystemTools::ReplaceString
1423 (line
, "OUTPUT_DIRECTORY",
1424 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1425 (outPath
.c_str())).c_str());
1427 cmSystemTools::ReplaceString(line
,
1429 this->Makefile
->GetDefineFlags());
1430 const char* debugPostfix
1431 = this->Makefile
->GetDefinition("CMAKE_DEBUG_POSTFIX");
1432 cmSystemTools::ReplaceString(line
, "DEBUG_POSTFIX",
1433 debugPostfix
?debugPostfix
:"");
1434 // store flags for each configuration
1435 std::string flags
= " ";
1436 std::string flagsRelease
= " ";
1437 std::string flagsMinSize
= " ";
1438 std::string flagsDebug
= " ";
1439 std::string flagsDebugRel
= " ";
1440 if(target
.GetType() >= cmTarget::EXECUTABLE
&&
1441 target
.GetType() <= cmTarget::MODULE_LIBRARY
)
1443 const char* linkLanguage
=
1444 target
.GetLinkerLanguage(this->GetGlobalGenerator());
1447 cmSystemTools::Error
1448 ("CMake can not determine linker language for target:",
1452 // if CXX is on and the target contains cxx code then add the cxx flags
1453 std::string baseFlagVar
= "CMAKE_";
1454 baseFlagVar
+= linkLanguage
;
1455 baseFlagVar
+= "_FLAGS";
1456 flags
= this->Makefile
->GetSafeDefinition(baseFlagVar
.c_str());
1458 std::string flagVar
= baseFlagVar
+ "_RELEASE";
1459 flagsRelease
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1460 flagsRelease
+= " -DCMAKE_INTDIR=\\\"Release\\\" ";
1461 if(const char* targetLinkFlags
=
1462 target
.GetProperty("LINK_FLAGS_RELEASE"))
1464 flagsRelease
+= targetLinkFlags
;
1465 flagsRelease
+= " ";
1467 flagVar
= baseFlagVar
+ "_MINSIZEREL";
1468 flagsMinSize
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1469 flagsMinSize
+= " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
1470 if(const char* targetLinkFlags
=
1471 target
.GetProperty("LINK_FLAGS_MINSIZEREL"))
1473 flagsMinSize
+= targetLinkFlags
;
1474 flagsMinSize
+= " ";
1477 flagVar
= baseFlagVar
+ "_DEBUG";
1478 flagsDebug
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1479 flagsDebug
+= " -DCMAKE_INTDIR=\\\"Debug\\\" ";
1480 if(const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS_DEBUG"))
1482 flagsDebug
+= targetLinkFlags
;
1486 flagVar
= baseFlagVar
+ "_RELWITHDEBINFO";
1487 flagsDebugRel
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1488 flagsDebugRel
+= " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
1489 if(const char* targetLinkFlags
=
1490 target
.GetProperty("LINK_FLAGS_RELWITHDEBINFO"))
1492 flagsDebugRel
+= targetLinkFlags
;
1493 flagsDebugRel
+= " ";
1498 // if unicode is not found, then add -D_MBCS
1499 std::string defs
= this->Makefile
->GetDefineFlags();
1500 if(flags
.find("D_UNICODE") == flags
.npos
&&
1501 defs
.find("D_UNICODE") == flags
.npos
)
1503 flags
+= " /D \"_MBCS\"";
1506 // Add per-target flags.
1507 if(const char* targetFlags
= target
.GetProperty("COMPILE_FLAGS"))
1510 flags
+= targetFlags
;
1513 // Add per-target and per-configuration preprocessor definitions.
1515 (flags
, this->Makefile
->GetProperty("COMPILE_DEFINITIONS"), 0);
1516 this->AppendDefines(flags
, target
.GetProperty("COMPILE_DEFINITIONS"), 0);
1519 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_DEBUG"), 0);
1520 this->AppendDefines(flagsDebug
,
1521 target
.GetProperty("COMPILE_DEFINITIONS_DEBUG"), 0);
1524 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1525 this->AppendDefines(flagsRelease
,
1526 target
.GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1529 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1532 target
.GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1535 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"), 0);
1538 target
.GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"), 0);
1540 // The template files have CXX FLAGS in them, that need to be replaced.
1541 // There are not separate CXX and C template files, so we use the same
1542 // variable names. The previous code sets up flags* variables to contain
1543 // the correct C or CXX flags
1544 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_MINSIZEREL",
1545 flagsMinSize
.c_str());
1546 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_DEBUG",
1547 flagsDebug
.c_str());
1548 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
1549 flagsDebugRel
.c_str());
1550 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_RELEASE",
1551 flagsRelease
.c_str());
1552 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS", flags
.c_str());
1553 fout
<< line
.c_str() << std::endl
;
1557 void cmLocalVisualStudio6Generator::WriteDSPFooter(std::ostream
& fout
)
1559 std::ifstream
fin(this->DSPFooterTemplate
.c_str());
1562 cmSystemTools::Error("Error Reading ",
1563 this->DSPFooterTemplate
.c_str());
1566 while(cmSystemTools::GetLineFromStream(fin
, line
))
1568 fout
<< line
<< std::endl
;
1572 //----------------------------------------------------------------------------
1573 void cmLocalVisualStudio6Generator
1574 ::ComputeLinkOptions(cmTarget
& target
,
1575 const char* configName
,
1576 const std::string extraOptions
,
1577 std::string
& options
)
1579 // Compute the link information for this configuration.
1580 cmComputeLinkInformation
* pcli
= target
.GetLinkInformation(configName
);
1585 cmComputeLinkInformation
& cli
= *pcli
;
1586 typedef cmComputeLinkInformation::ItemVector ItemVector
;
1587 ItemVector
const& linkLibs
= cli
.GetItems();
1588 std::vector
<std::string
> const& linkDirs
= cli
.GetDirectories();
1590 // Build the link options code.
1591 for(std::vector
<std::string
>::const_iterator d
= linkDirs
.begin();
1592 d
!= linkDirs
.end(); ++d
)
1594 std::string dir
= *d
;
1597 if(dir
[dir
.size()-1] != '/')
1602 options
+= "# ADD LINK32 /LIBPATH:";
1603 options
+= this->ConvertToOptionallyRelativeOutputPath(dir
.c_str());
1604 options
+= " /LIBPATH:";
1605 options
+= this->ConvertToOptionallyRelativeOutputPath(d
->c_str());
1609 for(ItemVector::const_iterator l
= linkLibs
.begin();
1610 l
!= linkLibs
.end(); ++l
)
1612 options
+= "# ADD LINK32 ";
1616 this->ConvertToOptionallyRelativeOutputPath(l
->Value
.c_str());
1620 options
+= l
->Value
;
1625 // Add extra options if any.
1626 if(!extraOptions
.empty())
1628 options
+= "# ADD LINK32 ";
1629 options
+= extraOptions
;
1635 cmLocalVisualStudio6Generator
1636 ::GetTargetDirectory(cmTarget
const&) const
1638 // No per-target directory for this generator (yet).
1642 void cmLocalVisualStudio6Generator
1643 ::GetTargetObjectFileDirectories(cmTarget
* ,
1644 std::vector
<std::string
>&
1647 std::string dir
= this->Makefile
->GetCurrentOutputDirectory();
1649 dir
+= this->GetGlobalGenerator()->GetCMakeCFGInitDirectory();
1650 dirs
.push_back(dir
);
1654 cmLocalVisualStudio6Generator
1655 ::GetConfigName(std::string
const& configuration
) const
1657 // Strip the subdirectory name out of the configuration name.
1658 std::string config
= configuration
;
1659 std::string::size_type pos
= config
.find_last_of(" ");
1660 config
= config
.substr(pos
+1, std::string::npos
);
1661 config
= config
.substr(0, config
.size()-1);
1665 //----------------------------------------------------------------------------
1667 cmLocalVisualStudio6Generator
1668 ::CheckDefinition(std::string
const& define
) const
1670 // Perform the standard check first.
1671 if(!this->cmLocalGenerator::CheckDefinition(define
))
1676 // Now do the VS6-specific check.
1677 if(define
.find_first_of("=") != define
.npos
)
1680 e
<< "WARNING: The VS6 IDE does not support preprocessor definitions "
1682 << "CMake is dropping a preprocessor definition: " << define
<< "\n"
1683 << "Consider defining the macro in a (configured) header file.\n";
1684 cmSystemTools::Message(e
.str().c_str());
1688 // Assume it is supported.