1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmLocalVisualStudio6Generator.cxx,v $
6 Date: $Date: 2009-03-23 18:48:09 $
7 Version: $Revision: 1.151 $
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 threatens 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 // Utility function to make a valid VS6 *.dsp filename out
171 // of a CMake target name:
173 extern std::string
GetVS6TargetName(const std::string
& targetName
);
175 void cmLocalVisualStudio6Generator::CreateSingleDSP(const char *lname
,
178 // add to the list of projects
179 std::string pname
= GetVS6TargetName(lname
);
181 this->CreatedProjectNames
.push_back(pname
);
182 // create the dsp.cmake file
184 fname
= this->Makefile
->GetStartOutputDirectory();
188 // save the name of the real dsp file
189 std::string realDSP
= fname
;
191 std::ofstream
fout(fname
.c_str());
194 cmSystemTools::Error("Error Writing ", fname
.c_str());
195 cmSystemTools::ReportLastSystemError("");
197 this->WriteDSPFile(fout
,pname
.c_str(),target
);
199 // if the dsp file has changed, then write it.
200 cmSystemTools::CopyFileIfDifferent(fname
.c_str(), realDSP
.c_str());
204 void cmLocalVisualStudio6Generator::AddDSPBuildRule(cmTarget
& tgt
)
206 std::string dspname
= GetVS6TargetName(tgt
.GetName());
207 dspname
+= ".dsp.cmake";
208 const char* dsprule
=
209 this->Makefile
->GetRequiredDefinition("CMAKE_COMMAND");
210 cmCustomCommandLine commandLine
;
211 commandLine
.push_back(dsprule
);
212 std::string makefileIn
= this->Makefile
->GetStartDirectory();
214 makefileIn
+= "CMakeLists.txt";
215 std::string comment
= "Building Custom Rule ";
216 comment
+= makefileIn
;
219 args
+= this->Convert(this->Makefile
->GetHomeDirectory(),
220 START_OUTPUT
, UNCHANGED
, true);
221 commandLine
.push_back(args
);
224 this->Convert(this->Makefile
->GetHomeOutputDirectory(),
225 START_OUTPUT
, UNCHANGED
, true);
226 commandLine
.push_back(args
);
228 std::vector
<std::string
> const& listFiles
= this->Makefile
->GetListFiles();
230 cmCustomCommandLines commandLines
;
231 commandLines
.push_back(commandLine
);
232 const char* no_working_directory
= 0;
233 this->Makefile
->AddCustomCommandToOutput(dspname
.c_str(), listFiles
,
234 makefileIn
.c_str(), commandLines
,
236 no_working_directory
, true);
237 if(cmSourceFile
* file
= this->Makefile
->GetSource(makefileIn
.c_str()))
239 tgt
.AddSourceFile(file
);
243 cmSystemTools::Error("Error adding rule for ", makefileIn
.c_str());
248 void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream
& fout
,
252 // For utility targets need custom command since pre- and post-
253 // build does not do anything in Visual Studio 6. In order for the
254 // rules to run in the correct order as custom commands, we need
255 // special care for dependencies. The first rule must depend on all
256 // the dependencies of all the rules. The later rules must each
257 // depend only on the previous rule.
258 if ((target
.GetType() == cmTarget::UTILITY
||
259 target
.GetType() == cmTarget::GLOBAL_TARGET
) &&
260 (!target
.GetPreBuildCommands().empty() ||
261 !target
.GetPostBuildCommands().empty()))
263 // Accumulate the dependencies of all the commands.
264 std::vector
<std::string
> depends
;
265 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
266 target
.GetPreBuildCommands().begin();
267 cr
!= target
.GetPreBuildCommands().end(); ++cr
)
269 depends
.insert(depends
.end(),
270 cr
->GetDepends().begin(), cr
->GetDepends().end());
272 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
273 target
.GetPostBuildCommands().begin();
274 cr
!= target
.GetPostBuildCommands().end(); ++cr
)
276 depends
.insert(depends
.end(),
277 cr
->GetDepends().begin(), cr
->GetDepends().end());
280 // Add the pre- and post-build commands in order.
282 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
283 target
.GetPreBuildCommands().begin();
284 cr
!= target
.GetPreBuildCommands().end(); ++cr
)
286 this->AddUtilityCommandHack(target
, count
++, depends
, *cr
);
288 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
289 target
.GetPostBuildCommands().begin();
290 cr
!= target
.GetPostBuildCommands().end(); ++cr
)
292 this->AddUtilityCommandHack(target
, count
++, depends
, *cr
);
296 // We may be modifying the source groups temporarily, so make a copy.
297 std::vector
<cmSourceGroup
> sourceGroups
= this->Makefile
->GetSourceGroups();
299 // get the classes from the source lists then add them to the groups
300 std::vector
<cmSourceFile
*> const & classes
= target
.GetSourceFiles();
302 // now all of the source files have been properly assigned to the target
303 // now stick them into source groups using the reg expressions
304 for(std::vector
<cmSourceFile
*>::const_iterator i
= classes
.begin();
305 i
!= classes
.end(); i
++)
307 // Add the file to the list of sources.
308 std::string source
= (*i
)->GetFullPath();
309 cmSourceGroup
& sourceGroup
=
310 this->Makefile
->FindSourceGroup(source
.c_str(), sourceGroups
);
311 sourceGroup
.AssignSource(*i
);
312 // while we are at it, if it is a .rule file then for visual studio 6 we
314 if ((*i
)->GetExtension() == "rule")
316 if(!cmSystemTools::FileExists(source
.c_str()))
318 cmSystemTools::ReplaceString(source
, "$(IntDir)/", "");
319 #if defined(_WIN32) || defined(__CYGWIN__)
320 std::ofstream
fout(source
.c_str(),
321 std::ios::binary
| std::ios::out
324 std::ofstream
fout(source
.c_str(),
325 std::ios::out
| std::ios::trunc
);
329 fout
.write("# generated from CMake",22);
337 // Compute which sources need unique object computation.
338 this->ComputeObjectNameRequirements(sourceGroups
);
340 // Write the DSP file's header.
341 this->WriteDSPHeader(fout
, libName
, target
, sourceGroups
);
344 // Loop through every source group.
345 for(std::vector
<cmSourceGroup
>::const_iterator sg
= sourceGroups
.begin();
346 sg
!= sourceGroups
.end(); ++sg
)
348 this->WriteGroup(&(*sg
), target
, fout
, libName
);
351 // Write the DSP file's footer.
352 this->WriteDSPFooter(fout
);
355 void cmLocalVisualStudio6Generator
356 ::WriteGroup(const cmSourceGroup
*sg
, cmTarget
& target
,
357 std::ostream
&fout
, const char *libName
)
359 const std::vector
<const cmSourceFile
*> &sourceFiles
=
360 sg
->GetSourceFiles();
361 // If the group is empty, don't write it at all.
363 if(sourceFiles
.empty() && sg
->GetGroupChildren().empty())
368 // If the group has a name, write the header.
369 std::string name
= sg
->GetName();
372 this->WriteDSPBeginGroup(fout
, name
.c_str(), "");
375 // Compute the maximum length configuration name.
376 std::string config_max
;
377 for(std::vector
<std::string
>::iterator i
= this->Configurations
.begin();
378 i
!= this->Configurations
.end(); ++i
)
380 // Strip the subdirectory name out of the configuration name.
381 std::string config
= this->GetConfigName(*i
);
382 if(config
.size() > config_max
.size())
388 // Compute the maximum length full path to the intermediate
389 // files directory for any configuration. This is used to construct
390 // object file names that do not produce paths that are too long.
392 dir_max
+= this->Makefile
->GetCurrentOutputDirectory();
394 dir_max
+= config_max
;
397 // Loop through each source in the source group.
398 for(std::vector
<const cmSourceFile
*>::const_iterator sf
=
399 sourceFiles
.begin(); sf
!= sourceFiles
.end(); ++sf
)
401 std::string source
= (*sf
)->GetFullPath();
402 const cmCustomCommand
*command
=
403 (*sf
)->GetCustomCommand();
404 std::string compileFlags
;
405 std::vector
<std::string
> depends
;
406 std::string objectNameDir
;
407 if(this->NeedObjectName
.find(*sf
) != this->NeedObjectName
.end())
410 cmSystemTools::GetFilenamePath(
411 this->GetObjectFileNameWithoutTarget(*(*sf
), dir_max
));
414 // Add per-source file flags.
415 if(const char* cflags
= (*sf
)->GetProperty("COMPILE_FLAGS"))
417 compileFlags
+= cflags
;
420 const char* lang
= this->GetSourceFileLanguage(*(*sf
));
423 if(strcmp(lang
, "CXX") == 0)
425 // force a C++ file type
426 compileFlags
+= " /TP ";
428 else if(strcmp(lang
, "C") == 0)
430 // force to c file type
431 compileFlags
+= " /TC ";
435 // Add per-source and per-configuration preprocessor definitions.
436 std::map
<cmStdString
, cmStdString
> cdmap
;
437 this->AppendDefines(compileFlags
,
438 (*sf
)->GetProperty("COMPILE_DEFINITIONS"), lang
);
439 if(const char* cdefs
= (*sf
)->GetProperty("COMPILE_DEFINITIONS_DEBUG"))
441 this->AppendDefines(cdmap
["DEBUG"], cdefs
, lang
);
443 if(const char* cdefs
= (*sf
)->GetProperty("COMPILE_DEFINITIONS_RELEASE"))
445 this->AppendDefines(cdmap
["RELEASE"], cdefs
, lang
);
447 if(const char* cdefs
=
448 (*sf
)->GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"))
450 this->AppendDefines(cdmap
["MINSIZEREL"], cdefs
, lang
);
452 if(const char* cdefs
=
453 (*sf
)->GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"))
455 this->AppendDefines(cdmap
["RELWITHDEBINFO"], cdefs
, lang
);
458 bool excludedFromBuild
=
459 (lang
&& (*sf
)->GetPropertyAsBool("HEADER_FILE_ONLY"));
461 // Check for extra object-file dependencies.
462 const char* dependsValue
= (*sf
)->GetProperty("OBJECT_DEPENDS");
465 cmSystemTools::ExpandListArgument(dependsValue
, depends
);
467 if (GetVS6TargetName(source
) != libName
||
468 target
.GetType() == cmTarget::UTILITY
||
469 target
.GetType() == cmTarget::GLOBAL_TARGET
)
471 fout
<< "# Begin Source File\n\n";
473 // Tell MS-Dev what the source is. If the compiler knows how to
474 // build it, then it will.
476 this->ConvertToOptionallyRelativeOutputPath(source
.c_str()) << "\n\n";
479 // Write out the dependencies for the rule.
480 fout
<< "USERDEP__HACK=";
481 for(std::vector
<std::string
>::const_iterator d
= depends
.begin();
482 d
!= depends
.end(); ++d
)
485 this->ConvertToOptionallyRelativeOutputPath(d
->c_str());
491 const char* flags
= compileFlags
.size() ? compileFlags
.c_str(): 0;
492 this->WriteCustomRule(fout
, source
.c_str(), *command
, flags
);
494 else if(!compileFlags
.empty() || !objectNameDir
.empty() ||
495 excludedFromBuild
|| !cdmap
.empty())
497 for(std::vector
<std::string
>::iterator i
498 = this->Configurations
.begin();
499 i
!= this->Configurations
.end(); ++i
)
501 // Strip the subdirectory name out of the configuration name.
502 std::string config
= this->GetConfigName(*i
);
503 if (i
== this->Configurations
.begin())
505 fout
<< "!IF \"$(CFG)\" == " << i
->c_str() << std::endl
;
509 fout
<< "!ELSEIF \"$(CFG)\" == " << i
->c_str() << std::endl
;
511 if(excludedFromBuild
)
513 fout
<< "# PROP Exclude_From_Build 1\n";
515 if(!compileFlags
.empty())
517 fout
<< "\n# ADD CPP " << compileFlags
<< "\n\n";
519 std::map
<cmStdString
, cmStdString
>::iterator cdi
=
520 cdmap
.find(cmSystemTools::UpperCase(config
));
521 if(cdi
!= cdmap
.end() && !cdi
->second
.empty())
523 fout
<< "\n# ADD CPP " << cdi
->second
<< "\n\n";
525 if(!objectNameDir
.empty())
527 // Setup an alternate object file directory.
528 fout
<< "\n# PROP Intermediate_Dir \""
529 << config
<< "/" << objectNameDir
<< "\"\n\n";
532 fout
<< "!ENDIF\n\n";
534 fout
<< "# End Source File\n";
538 std::vector
<cmSourceGroup
> const& children
= sg
->GetGroupChildren();
540 for(unsigned int i
=0;i
<children
.size();++i
)
542 this->WriteGroup(&children
[i
], target
, fout
, libName
);
548 // If the group has a name, write the footer.
551 this->WriteDSPEndGroup(fout
);
558 cmLocalVisualStudio6Generator
559 ::AddUtilityCommandHack(cmTarget
& target
, int count
,
560 std::vector
<std::string
>& depends
,
561 const cmCustomCommand
& origCommand
)
563 // Create a fake output that forces the rule to run.
564 char* output
= new char[(strlen(this->Makefile
->GetStartOutputDirectory()) +
565 strlen(target
.GetName()) + 30)];
566 sprintf(output
,"%s/%s_force_%i", this->Makefile
->GetStartOutputDirectory(),
567 target
.GetName(), count
);
568 std::string comment
= this->ConstructComment(origCommand
, "<hack>");
570 // Add the rule with the given dependencies and commands.
571 const char* no_main_dependency
= 0;
572 this->Makefile
->AddCustomCommandToOutput(output
,
575 origCommand
.GetCommandLines(),
577 origCommand
.GetWorkingDirectory());
579 // Replace the dependencies with the output of this rule so that the
580 // next rule added will run after this one.
582 depends
.push_back(output
);
584 // Add a source file representing this output to the project.
585 cmSourceFile
* outsf
= this->Makefile
->GetSourceFileWithOutput(output
);
586 target
.AddSourceFile(outsf
);
588 // Free the fake output name.
593 cmLocalVisualStudio6Generator
594 ::WriteCustomRule(std::ostream
& fout
,
596 const cmCustomCommand
& command
,
599 std::string comment
=
600 this->ConstructComment(command
, "Building Custom Rule $(InputPath)");
601 if(comment
== "<hack>")
606 // Write the rule for each configuration.
607 std::vector
<std::string
>::iterator i
;
608 for(i
= this->Configurations
.begin(); i
!= this->Configurations
.end(); ++i
)
610 std::string config
= this->GetConfigName(*i
);
612 this->ConstructScript(command
.GetCommandLines(),
613 command
.GetWorkingDirectory(),
615 command
.GetEscapeOldStyle(),
616 command
.GetEscapeAllowMakeVars(),
619 if (i
== this->Configurations
.begin())
621 fout
<< "!IF \"$(CFG)\" == " << i
->c_str() << std::endl
;
625 fout
<< "!ELSEIF \"$(CFG)\" == " << i
->c_str() << std::endl
;
629 fout
<< "\n# ADD CPP " << flags
<< "\n\n";
631 // Write out the dependencies for the rule.
632 fout
<< "USERDEP__HACK=";
633 for(std::vector
<std::string
>::const_iterator d
=
634 command
.GetDepends().begin();
635 d
!= command
.GetDepends().end();
638 // Lookup the real name of the dependency in case it is a CMake target.
639 std::string dep
= this->GetRealDependency(d
->c_str(),
642 this->ConvertToOptionallyRelativeOutputPath(dep
.c_str());
646 fout
<< "# PROP Ignore_Default_Tool 1\n";
647 fout
<< "# Begin Custom Build -";
650 fout
<< " " << comment
.c_str();
653 if(command
.GetOutputs().empty())
656 << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
657 fout
<< script
.c_str() << "\n\n";
661 for(std::vector
<std::string
>::const_iterator o
=
662 command
.GetOutputs().begin();
663 o
!= command
.GetOutputs().end();
666 // Write a rule for every output generated by this command.
667 fout
<< this->ConvertToOptionallyRelativeOutputPath(o
->c_str())
668 << " : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
669 fout
<< script
.c_str() << "\n\n";
672 fout
<< "# End Custom Build\n\n";
675 fout
<< "!ENDIF\n\n";
679 void cmLocalVisualStudio6Generator::WriteDSPBeginGroup(std::ostream
& fout
,
683 fout
<< "# Begin Group \"" << group
<< "\"\n"
684 "# PROP Default_Filter \"" << filter
<< "\"\n";
688 void cmLocalVisualStudio6Generator::WriteDSPEndGroup(std::ostream
& fout
)
690 fout
<< "# End Group\n";
696 void cmLocalVisualStudio6Generator::SetBuildType(BuildType b
,
700 std::string root
= this->Makefile
->GetRequiredDefinition("CMAKE_ROOT");
702 this->Makefile
->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
710 root
+= "/Templates";
716 this->DSPHeaderTemplate
= root
;
717 this->DSPHeaderTemplate
+= "/staticLibHeader.dsptemplate";
718 this->DSPFooterTemplate
= root
;
719 this->DSPFooterTemplate
+= "/staticLibFooter.dsptemplate";
722 this->DSPHeaderTemplate
= root
;
723 this->DSPHeaderTemplate
+= "/DLLHeader.dsptemplate";
724 this->DSPFooterTemplate
= root
;
725 this->DSPFooterTemplate
+= "/DLLFooter.dsptemplate";
728 if ( target
.GetPropertyAsBool("WIN32_EXECUTABLE") )
730 this->DSPHeaderTemplate
= root
;
731 this->DSPHeaderTemplate
+= "/EXEWinHeader.dsptemplate";
732 this->DSPFooterTemplate
= root
;
733 this->DSPFooterTemplate
+= "/EXEFooter.dsptemplate";
737 this->DSPHeaderTemplate
= root
;
738 this->DSPHeaderTemplate
+= "/EXEHeader.dsptemplate";
739 this->DSPFooterTemplate
= root
;
740 this->DSPFooterTemplate
+= "/EXEFooter.dsptemplate";
744 this->DSPHeaderTemplate
= root
;
745 this->DSPHeaderTemplate
+= "/UtilityHeader.dsptemplate";
746 this->DSPFooterTemplate
= root
;
747 this->DSPFooterTemplate
+= "/UtilityFooter.dsptemplate";
751 // once the build type is set, determine what configurations are
753 std::ifstream
fin(this->DSPHeaderTemplate
.c_str());
755 cmsys::RegularExpression
reg("# Name ");
758 cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate
.c_str());
761 // reset this->Configurations
762 this->Configurations
.erase(this->Configurations
.begin(),
763 this->Configurations
.end());
765 // now add all the configurations possible
766 std::string vs6name
= GetVS6TargetName(libName
);
768 while(cmSystemTools::GetLineFromStream(fin
, line
))
770 cmSystemTools::ReplaceString(line
, "OUTPUT_LIBNAME", vs6name
.c_str());
773 this->Configurations
.push_back(line
.substr(reg
.end()));
778 // look for custom rules on a target and collect them together
780 cmLocalVisualStudio6Generator::CreateTargetRules(cmTarget
&target
,
781 const char* configName
,
782 const char * /* libName */)
784 std::string customRuleCode
= "";
786 if (target
.GetType() >= cmTarget::UTILITY
)
788 return customRuleCode
;
791 // are there any rules?
792 if (target
.GetPreBuildCommands().size() +
793 target
.GetPreLinkCommands().size() +
794 target
.GetPostBuildCommands().size() == 0)
796 return customRuleCode
;
799 customRuleCode
= "# Begin Special Build Tool\n";
801 // Write the pre-build and pre-link together (VS6 does not support
802 // both). Make sure no continuation character is put on the last
804 int prelink_total
= (static_cast<int>(target
.GetPreBuildCommands().size())+
805 static_cast<int>(target
.GetPreLinkCommands().size()));
806 int prelink_count
= 0;
807 if(prelink_total
> 0)
810 customRuleCode
+= "PreLink_Cmds=";
812 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
813 target
.GetPreBuildCommands().begin();
814 cr
!= target
.GetPreBuildCommands().end(); ++cr
)
816 if(prelink_count
++ > 0)
818 customRuleCode
+= "\\\n\t";
820 customRuleCode
+= this->ConstructScript(cr
->GetCommandLines(),
821 cr
->GetWorkingDirectory(),
823 cr
->GetEscapeOldStyle(),
824 cr
->GetEscapeAllowMakeVars(),
827 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
828 target
.GetPreLinkCommands().begin();
829 cr
!= target
.GetPreLinkCommands().end(); ++cr
)
831 if(prelink_count
++ > 0)
833 customRuleCode
+= "\\\n\t";
835 customRuleCode
+= this->ConstructScript(cr
->GetCommandLines(),
836 cr
->GetWorkingDirectory(),
838 cr
->GetEscapeOldStyle(),
839 cr
->GetEscapeAllowMakeVars(),
842 if(prelink_total
> 0)
844 customRuleCode
+= "\n";
847 // Write the post-build rules. Make sure no continuation character
848 // is put on the last line.
849 int postbuild_total
=
850 static_cast<int>(target
.GetPostBuildCommands().size());
851 int postbuild_count
= 0;
852 if(postbuild_total
> 0)
854 customRuleCode
+= "PostBuild_Cmds=";
856 for (std::vector
<cmCustomCommand
>::const_iterator cr
=
857 target
.GetPostBuildCommands().begin();
858 cr
!= target
.GetPostBuildCommands().end(); ++cr
)
860 if(postbuild_count
++ > 0)
862 customRuleCode
+= "\\\n\t";
864 customRuleCode
+= this->ConstructScript(cr
->GetCommandLines(),
865 cr
->GetWorkingDirectory(),
867 cr
->GetEscapeOldStyle(),
868 cr
->GetEscapeAllowMakeVars(),
871 if(postbuild_total
> 0)
873 customRuleCode
+= "\n";
876 customRuleCode
+= "# End Special Build Tool\n";
877 return customRuleCode
;
881 inline std::string
removeQuotes(const std::string
& s
)
883 if(s
[0] == '\"' && s
[s
.size()-1] == '\"')
885 return s
.substr(1, s
.size()-2);
890 // Code in blocks surrounded by a test for this definition is needed
891 // only for compatibility with user project's replacement DSP
892 // templates. The CMake templates no longer use them.
893 #define CM_USE_OLD_VS6
895 void cmLocalVisualStudio6Generator
896 ::WriteDSPHeader(std::ostream
& fout
,
897 const char *libName
, cmTarget
&target
,
898 std::vector
<cmSourceGroup
> &)
900 // Lookup the output directory for the target.
901 std::string outPath
= target
.GetDirectory();
903 #ifdef CM_USE_OLD_VS6
904 // Lookup the library and executable output directories.
906 if(this->Makefile
->GetDefinition("LIBRARY_OUTPUT_PATH"))
908 libPath
= this->Makefile
->GetDefinition("LIBRARY_OUTPUT_PATH");
911 if(this->Makefile
->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
913 exePath
= this->Makefile
->GetDefinition("EXECUTABLE_OUTPUT_PATH");
916 // Make sure there are trailing slashes.
919 if(libPath
[libPath
.size()-1] != '/')
926 if(exePath
[exePath
.size()-1] != '/')
932 std::set
<std::string
> pathEmitted
;
934 // determine the link directories
935 std::string libOptions
;
936 std::string libDebugOptions
;
937 std::string libOptimizedOptions
;
939 std::string libMultiLineOptions
;
940 std::string libMultiLineOptionsForDebug
;
941 std::string libMultiLineDebugOptions
;
942 std::string libMultiLineOptimizedOptions
;
947 this->ConvertToOptionallyRelativeOutputPath(libPath
.c_str());
948 if(lpath
.size() == 0)
952 std::string lpathIntDir
= libPath
+ "$(INTDIR)";
954 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir
.c_str());
955 if(pathEmitted
.insert(lpath
).second
)
957 libOptions
+= " /LIBPATH:";
958 libOptions
+= lpathIntDir
;
960 libOptions
+= " /LIBPATH:";
963 libMultiLineOptions
+= "# ADD LINK32 /LIBPATH:";
964 libMultiLineOptions
+= lpathIntDir
;
965 libMultiLineOptions
+= " ";
966 libMultiLineOptions
+= " /LIBPATH:";
967 libMultiLineOptions
+= lpath
;
968 libMultiLineOptions
+= " \n";
969 libMultiLineOptionsForDebug
+= "# ADD LINK32 /LIBPATH:";
970 libMultiLineOptionsForDebug
+= lpathIntDir
;
971 libMultiLineOptionsForDebug
+= " ";
972 libMultiLineOptionsForDebug
+= " /LIBPATH:";
973 libMultiLineOptionsForDebug
+= lpath
;
974 libMultiLineOptionsForDebug
+= " \n";
980 this->ConvertToOptionallyRelativeOutputPath(exePath
.c_str());
981 if(lpath
.size() == 0)
985 std::string lpathIntDir
= exePath
+ "$(INTDIR)";
987 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir
.c_str());
989 if(pathEmitted
.insert(lpath
).second
)
991 libOptions
+= " /LIBPATH:";
992 libOptions
+= lpathIntDir
;
994 libOptions
+= " /LIBPATH:";
997 libMultiLineOptions
+= "# ADD LINK32 /LIBPATH:";
998 libMultiLineOptions
+= lpathIntDir
;
999 libMultiLineOptions
+= " ";
1000 libMultiLineOptions
+= " /LIBPATH:";
1001 libMultiLineOptions
+= lpath
;
1002 libMultiLineOptions
+= " \n";
1003 libMultiLineOptionsForDebug
+= "# ADD LINK32 /LIBPATH:";
1004 libMultiLineOptionsForDebug
+= lpathIntDir
;
1005 libMultiLineOptionsForDebug
+= " ";
1006 libMultiLineOptionsForDebug
+= " /LIBPATH:";
1007 libMultiLineOptionsForDebug
+= lpath
;
1008 libMultiLineOptionsForDebug
+= " \n";
1011 std::vector
<std::string
>::const_iterator i
;
1012 const std::vector
<std::string
>& libdirs
= target
.GetLinkDirectories();
1013 for(i
= libdirs
.begin(); i
!= libdirs
.end(); ++i
)
1015 std::string path
= *i
;
1016 if(path
[path
.size()-1] != '/')
1021 this->ConvertToOptionallyRelativeOutputPath(path
.c_str());
1022 if(lpath
.size() == 0)
1026 std::string lpathIntDir
= path
+ "$(INTDIR)";
1028 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir
.c_str());
1029 if(pathEmitted
.insert(lpath
).second
)
1031 libOptions
+= " /LIBPATH:";
1032 libOptions
+= lpathIntDir
;
1034 libOptions
+= " /LIBPATH:";
1035 libOptions
+= lpath
;
1038 libMultiLineOptions
+= "# ADD LINK32 /LIBPATH:";
1039 libMultiLineOptions
+= lpathIntDir
;
1040 libMultiLineOptions
+= " ";
1041 libMultiLineOptions
+= " /LIBPATH:";
1042 libMultiLineOptions
+= lpath
;
1043 libMultiLineOptions
+= " \n";
1044 libMultiLineOptionsForDebug
+= "# ADD LINK32 /LIBPATH:";
1045 libMultiLineOptionsForDebug
+= lpathIntDir
;
1046 libMultiLineOptionsForDebug
+= " ";
1047 libMultiLineOptionsForDebug
+= " /LIBPATH:";
1048 libMultiLineOptionsForDebug
+= lpath
;
1049 libMultiLineOptionsForDebug
+= " \n";
1052 // find link libraries
1053 const cmTarget::LinkLibraryVectorType
& libs
= target
.GetLinkLibraries();
1054 cmTarget::LinkLibraryVectorType::const_iterator j
;
1055 for(j
= libs
.begin(); j
!= libs
.end(); ++j
)
1057 // add libraries to executables and dlls (but never include
1058 // a library in a library, bad recursion)
1059 // NEVER LINK STATIC LIBRARIES TO OTHER STATIC LIBRARIES
1060 if ((target
.GetType() != cmTarget::SHARED_LIBRARY
1061 && target
.GetType() != cmTarget::STATIC_LIBRARY
1062 && target
.GetType() != cmTarget::MODULE_LIBRARY
) ||
1063 (target
.GetType()==cmTarget::SHARED_LIBRARY
1064 && libName
!= GetVS6TargetName(j
->first
)) ||
1065 (target
.GetType()==cmTarget::MODULE_LIBRARY
1066 && libName
!= GetVS6TargetName(j
->first
)))
1068 // Compute the proper name to use to link this library.
1070 std::string libDebug
;
1071 cmTarget
* tgt
= this->GlobalGenerator
->FindTarget(0, j
->first
.c_str());
1074 lib
= cmSystemTools::GetFilenameWithoutExtension
1075 (tgt
->GetFullName().c_str());
1076 libDebug
= cmSystemTools::GetFilenameWithoutExtension
1077 (tgt
->GetFullName("Debug").c_str());
1083 lib
= j
->first
.c_str();
1084 libDebug
= j
->first
.c_str();
1085 if(j
->first
.find(".lib") == std::string::npos
)
1091 lib
= this->ConvertToOptionallyRelativeOutputPath(lib
.c_str());
1093 this->ConvertToOptionallyRelativeOutputPath(libDebug
.c_str());
1095 if (j
->second
== cmTarget::GENERAL
)
1099 libMultiLineOptions
+= "# ADD LINK32 ";
1100 libMultiLineOptions
+= lib
;
1101 libMultiLineOptions
+= "\n";
1102 libMultiLineOptionsForDebug
+= "# ADD LINK32 ";
1103 libMultiLineOptionsForDebug
+= libDebug
;
1104 libMultiLineOptionsForDebug
+= "\n";
1106 if (j
->second
== cmTarget::DEBUG
)
1108 libDebugOptions
+= " ";
1109 libDebugOptions
+= lib
;
1111 libMultiLineDebugOptions
+= "# ADD LINK32 ";
1112 libMultiLineDebugOptions
+= libDebug
;
1113 libMultiLineDebugOptions
+= "\n";
1115 if (j
->second
== cmTarget::OPTIMIZED
)
1117 libOptimizedOptions
+= " ";
1118 libOptimizedOptions
+= lib
;
1120 libMultiLineOptimizedOptions
+= "# ADD LINK32 ";
1121 libMultiLineOptimizedOptions
+= lib
;
1122 libMultiLineOptimizedOptions
+= "\n";
1128 // Get extra linker options for this target type.
1129 std::string extraLinkOptions
;
1130 if(target
.GetType() == cmTarget::EXECUTABLE
)
1133 this->Makefile
->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1135 if(target
.GetType() == cmTarget::SHARED_LIBRARY
)
1138 this->Makefile
->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1140 if(target
.GetType() == cmTarget::MODULE_LIBRARY
)
1143 this->Makefile
->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1146 // Get extra linker options for this target.
1147 if(const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS"))
1149 extraLinkOptions
+= " ";
1150 extraLinkOptions
+= targetLinkFlags
;
1153 // Get standard libraries for this language.
1154 if(target
.GetType() >= cmTarget::EXECUTABLE
&&
1155 target
.GetType() <= cmTarget::MODULE_LIBRARY
)
1157 // Get the language to use for linking.
1158 const char* linkLanguage
=
1159 target
.GetLinkerLanguage(this->GetGlobalGenerator());
1162 cmSystemTools::Error
1163 ("CMake can not determine linker language for target:",
1168 // Compute the variable name to lookup standard libraries for this
1170 std::string standardLibsVar
= "CMAKE_";
1171 standardLibsVar
+= linkLanguage
;
1172 standardLibsVar
+= "_STANDARD_LIBRARIES";
1174 // Add standard libraries.
1175 if(const char* stdLibs
=
1176 this->Makefile
->GetDefinition(standardLibsVar
.c_str()))
1178 extraLinkOptions
+= " ";
1179 extraLinkOptions
+= stdLibs
;
1183 // Compute version number information.
1184 std::string targetVersionFlag
;
1185 if(target
.GetType() == cmTarget::EXECUTABLE
||
1186 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1187 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1191 target
.GetTargetVersion(major
, minor
);
1192 cmOStringStream targetVersionStream
;
1193 targetVersionStream
<< "/version:" << major
<< "." << minor
;
1194 targetVersionFlag
= targetVersionStream
.str();
1197 // Compute the real name of the target.
1198 std::string outputName
=
1199 "(OUTPUT_NAME is for libraries and executables only)";
1200 std::string outputNameDebug
= outputName
;
1201 std::string outputNameRelease
= outputName
;
1202 std::string outputNameMinSizeRel
= outputName
;
1203 std::string outputNameRelWithDebInfo
= outputName
;
1204 if(target
.GetType() == cmTarget::EXECUTABLE
||
1205 target
.GetType() == cmTarget::STATIC_LIBRARY
||
1206 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1207 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1209 outputName
= target
.GetFullName();
1210 outputNameDebug
= target
.GetFullName("Debug");
1211 outputNameRelease
= target
.GetFullName("Release");
1212 outputNameMinSizeRel
= target
.GetFullName("MinSizeRel");
1213 outputNameRelWithDebInfo
= target
.GetFullName("RelWithDebInfo");
1216 // Compute the proper link information for the target.
1217 std::string optionsDebug
;
1218 std::string optionsRelease
;
1219 std::string optionsMinSizeRel
;
1220 std::string optionsRelWithDebInfo
;
1221 if(target
.GetType() == cmTarget::EXECUTABLE
||
1222 target
.GetType() == cmTarget::SHARED_LIBRARY
||
1223 target
.GetType() == cmTarget::MODULE_LIBRARY
)
1225 this->ComputeLinkOptions(target
, "Debug", extraLinkOptions
,
1227 this->ComputeLinkOptions(target
, "Release", extraLinkOptions
,
1229 this->ComputeLinkOptions(target
, "MinSizeRel", extraLinkOptions
,
1231 this->ComputeLinkOptions(target
, "RelWithDebInfo", extraLinkOptions
,
1232 optionsRelWithDebInfo
);
1235 // Compute the path of the import library.
1236 std::string targetImplibFlagDebug
;
1237 std::string targetImplibFlagRelease
;
1238 std::string targetImplibFlagMinSizeRel
;
1239 std::string targetImplibFlagRelWithDebInfo
;
1240 if(target
.GetType() == cmTarget::SHARED_LIBRARY
||
1241 target
.GetType() == cmTarget::MODULE_LIBRARY
||
1242 target
.GetType() == cmTarget::EXECUTABLE
)
1244 std::string fullPathImpDebug
= target
.GetDirectory("Debug", true);
1245 std::string fullPathImpRelease
= target
.GetDirectory("Release", true);
1246 std::string fullPathImpMinSizeRel
=
1247 target
.GetDirectory("MinSizeRel", true);
1248 std::string fullPathImpRelWithDebInfo
=
1249 target
.GetDirectory("RelWithDebInfo", true);
1250 fullPathImpDebug
+= "/";
1251 fullPathImpRelease
+= "/";
1252 fullPathImpMinSizeRel
+= "/";
1253 fullPathImpRelWithDebInfo
+= "/";
1254 fullPathImpDebug
+= target
.GetFullName("Debug", true);
1255 fullPathImpRelease
+= target
.GetFullName("Release", true);
1256 fullPathImpMinSizeRel
+= target
.GetFullName("MinSizeRel", true);
1257 fullPathImpRelWithDebInfo
+= target
.GetFullName("RelWithDebInfo", true);
1259 targetImplibFlagDebug
= "/implib:";
1260 targetImplibFlagRelease
= "/implib:";
1261 targetImplibFlagMinSizeRel
= "/implib:";
1262 targetImplibFlagRelWithDebInfo
= "/implib:";
1263 targetImplibFlagDebug
+=
1264 this->ConvertToOptionallyRelativeOutputPath(fullPathImpDebug
.c_str());
1265 targetImplibFlagRelease
+=
1266 this->ConvertToOptionallyRelativeOutputPath(fullPathImpRelease
.c_str());
1267 targetImplibFlagMinSizeRel
+=
1268 this->ConvertToOptionallyRelativeOutputPath(
1269 fullPathImpMinSizeRel
.c_str());
1270 targetImplibFlagRelWithDebInfo
+=
1271 this->ConvertToOptionallyRelativeOutputPath(
1272 fullPathImpRelWithDebInfo
.c_str());
1275 #ifdef CM_USE_OLD_VS6
1276 // Compute link information for the target.
1277 if(extraLinkOptions
.size())
1280 libOptions
+= extraLinkOptions
;
1282 libMultiLineOptions
+= "# ADD LINK32 ";
1283 libMultiLineOptions
+= extraLinkOptions
;
1284 libMultiLineOptions
+= " \n";
1285 libMultiLineOptionsForDebug
+= "# ADD LINK32 ";
1286 libMultiLineOptionsForDebug
+= extraLinkOptions
;
1287 libMultiLineOptionsForDebug
+= " \n";
1291 // are there any custom rules on the target itself
1292 // only if the target is a lib or exe
1293 std::string customRuleCodeRelease
1294 = this->CreateTargetRules(target
, "RELEASE", libName
);
1295 std::string customRuleCodeDebug
1296 = this->CreateTargetRules(target
, "DEBUG", libName
);
1297 std::string customRuleCodeMinSizeRel
1298 = this->CreateTargetRules(target
, "MINSIZEREL", libName
);
1299 std::string customRuleCodeRelWithDebInfo
1300 = this->CreateTargetRules(target
, "RELWITHDEBINFO", libName
);
1302 std::ifstream
fin(this->DSPHeaderTemplate
.c_str());
1305 cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate
.c_str());
1307 std::string staticLibOptions
;
1308 if(target
.GetType() == cmTarget::STATIC_LIBRARY
)
1310 if(const char* libflags
= target
.GetProperty("STATIC_LIBRARY_FLAGS"))
1312 staticLibOptions
= libflags
;
1316 // Add the export symbol definition for shared library objects.
1317 std::string exportSymbol
;
1318 if(const char* exportMacro
= target
.GetExportMacro())
1320 exportSymbol
= exportMacro
;
1324 std::string libnameExports
;
1325 if(exportSymbol
.size())
1327 libnameExports
= "/D \"";
1328 libnameExports
+= exportSymbol
;
1329 libnameExports
+= "\"";
1331 while(cmSystemTools::GetLineFromStream(fin
, line
))
1333 const char* mfcFlag
= this->Makefile
->GetDefinition("CMAKE_MFC_FLAG");
1338 cmSystemTools::ReplaceString(line
, "OUTPUT_LIBNAME_EXPORTS",
1339 libnameExports
.c_str());
1340 cmSystemTools::ReplaceString(line
, "CMAKE_MFC_FLAG",
1342 if(target
.GetType() == cmTarget::STATIC_LIBRARY
)
1344 cmSystemTools::ReplaceString(line
, "CM_STATIC_LIB_ARGS",
1345 staticLibOptions
.c_str());
1347 if(this->Makefile
->IsOn("CMAKE_VERBOSE_MAKEFILE"))
1349 cmSystemTools::ReplaceString(line
, "/nologo", "");
1352 #ifdef CM_USE_OLD_VS6
1353 cmSystemTools::ReplaceString(line
, "CM_LIBRARIES",
1354 libOptions
.c_str());
1355 cmSystemTools::ReplaceString(line
, "CM_DEBUG_LIBRARIES",
1356 libDebugOptions
.c_str());
1357 cmSystemTools::ReplaceString(line
, "CM_OPTIMIZED_LIBRARIES",
1358 libOptimizedOptions
.c_str());
1359 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_LIBRARIES_FOR_DEBUG",
1360 libMultiLineOptionsForDebug
.c_str());
1361 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_LIBRARIES",
1362 libMultiLineOptions
.c_str());
1363 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_DEBUG_LIBRARIES",
1364 libMultiLineDebugOptions
.c_str());
1365 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
1366 libMultiLineOptimizedOptions
.c_str());
1369 // Substitute the rules for custom command. When specifying just the
1370 // target name for the command the command can be different for
1371 // different configs
1372 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_RELEASE",
1373 customRuleCodeRelease
.c_str());
1374 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_DEBUG",
1375 customRuleCodeDebug
.c_str());
1376 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_MINSIZEREL",
1377 customRuleCodeMinSizeRel
.c_str());
1378 cmSystemTools::ReplaceString(line
, "CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO",
1379 customRuleCodeRelWithDebInfo
.c_str());
1381 // Substitute the real output name into the template.
1382 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_DEBUG",
1383 outputNameDebug
.c_str());
1384 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_RELEASE",
1385 outputNameRelease
.c_str());
1386 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_MINSIZEREL",
1387 outputNameMinSizeRel
.c_str());
1388 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME_RELWITHDEBINFO",
1389 outputNameRelWithDebInfo
.c_str());
1390 cmSystemTools::ReplaceString(line
, "OUTPUT_NAME", outputName
.c_str());
1392 // Substitute the proper link information into the template.
1393 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_DEBUG",
1394 optionsDebug
.c_str());
1395 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_RELEASE",
1396 optionsRelease
.c_str());
1397 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_MINSIZEREL",
1398 optionsMinSizeRel
.c_str());
1399 cmSystemTools::ReplaceString(line
, "CM_MULTILINE_OPTIONS_RELWITHDEBINFO",
1400 optionsRelWithDebInfo
.c_str());
1402 cmSystemTools::ReplaceString(line
, "BUILD_INCLUDES",
1403 this->IncludeOptions
.c_str());
1404 cmSystemTools::ReplaceString(line
, "TARGET_VERSION_FLAG",
1405 targetVersionFlag
.c_str());
1406 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_DEBUG",
1407 targetImplibFlagDebug
.c_str());
1408 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_RELEASE",
1409 targetImplibFlagRelease
.c_str());
1410 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_MINSIZEREL",
1411 targetImplibFlagMinSizeRel
.c_str());
1412 cmSystemTools::ReplaceString(line
, "TARGET_IMPLIB_FLAG_RELWITHDEBINFO",
1413 targetImplibFlagRelWithDebInfo
.c_str());
1415 std::string vs6name
= GetVS6TargetName(libName
);
1416 cmSystemTools::ReplaceString(line
, "OUTPUT_LIBNAME", vs6name
.c_str());
1418 #ifdef CM_USE_OLD_VS6
1419 // because LIBRARY_OUTPUT_PATH and EXECUTABLE_OUTPUT_PATH
1420 // are already quoted in the template file,
1421 // we need to remove the quotes here, we still need
1422 // to convert to output path for unix to win32 conversion
1423 cmSystemTools::ReplaceString
1424 (line
, "LIBRARY_OUTPUT_PATH",
1425 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1426 (libPath
.c_str())).c_str());
1427 cmSystemTools::ReplaceString
1428 (line
, "EXECUTABLE_OUTPUT_PATH",
1429 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1430 (exePath
.c_str())).c_str());
1432 cmSystemTools::ReplaceString
1433 (line
, "OUTPUT_DIRECTORY",
1434 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1435 (outPath
.c_str())).c_str());
1437 cmSystemTools::ReplaceString(line
,
1439 this->Makefile
->GetDefineFlags());
1440 const char* debugPostfix
1441 = this->Makefile
->GetDefinition("CMAKE_DEBUG_POSTFIX");
1442 cmSystemTools::ReplaceString(line
, "DEBUG_POSTFIX",
1443 debugPostfix
?debugPostfix
:"");
1444 // store flags for each configuration
1445 std::string flags
= " ";
1446 std::string flagsRelease
= " ";
1447 std::string flagsMinSize
= " ";
1448 std::string flagsDebug
= " ";
1449 std::string flagsDebugRel
= " ";
1450 if(target
.GetType() >= cmTarget::EXECUTABLE
&&
1451 target
.GetType() <= cmTarget::MODULE_LIBRARY
)
1453 const char* linkLanguage
=
1454 target
.GetLinkerLanguage(this->GetGlobalGenerator());
1457 cmSystemTools::Error
1458 ("CMake can not determine linker language for target:",
1462 // if CXX is on and the target contains cxx code then add the cxx flags
1463 std::string baseFlagVar
= "CMAKE_";
1464 baseFlagVar
+= linkLanguage
;
1465 baseFlagVar
+= "_FLAGS";
1466 flags
= this->Makefile
->GetSafeDefinition(baseFlagVar
.c_str());
1468 std::string flagVar
= baseFlagVar
+ "_RELEASE";
1469 flagsRelease
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1470 flagsRelease
+= " -DCMAKE_INTDIR=\\\"Release\\\" ";
1471 if(const char* targetLinkFlags
=
1472 target
.GetProperty("LINK_FLAGS_RELEASE"))
1474 flagsRelease
+= targetLinkFlags
;
1475 flagsRelease
+= " ";
1477 flagVar
= baseFlagVar
+ "_MINSIZEREL";
1478 flagsMinSize
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1479 flagsMinSize
+= " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
1480 if(const char* targetLinkFlags
=
1481 target
.GetProperty("LINK_FLAGS_MINSIZEREL"))
1483 flagsMinSize
+= targetLinkFlags
;
1484 flagsMinSize
+= " ";
1487 flagVar
= baseFlagVar
+ "_DEBUG";
1488 flagsDebug
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1489 flagsDebug
+= " -DCMAKE_INTDIR=\\\"Debug\\\" ";
1490 if(const char* targetLinkFlags
= target
.GetProperty("LINK_FLAGS_DEBUG"))
1492 flagsDebug
+= targetLinkFlags
;
1496 flagVar
= baseFlagVar
+ "_RELWITHDEBINFO";
1497 flagsDebugRel
= this->Makefile
->GetSafeDefinition(flagVar
.c_str());
1498 flagsDebugRel
+= " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
1499 if(const char* targetLinkFlags
=
1500 target
.GetProperty("LINK_FLAGS_RELWITHDEBINFO"))
1502 flagsDebugRel
+= targetLinkFlags
;
1503 flagsDebugRel
+= " ";
1508 // if unicode is not found, then add -D_MBCS
1509 std::string defs
= this->Makefile
->GetDefineFlags();
1510 if(flags
.find("D_UNICODE") == flags
.npos
&&
1511 defs
.find("D_UNICODE") == flags
.npos
)
1513 flags
+= " /D \"_MBCS\"";
1516 // Add per-target flags.
1517 if(const char* targetFlags
= target
.GetProperty("COMPILE_FLAGS"))
1520 flags
+= targetFlags
;
1523 // Add per-target and per-configuration preprocessor definitions.
1524 std::string defines
= " ";
1525 std::string debugDefines
= " ";
1526 std::string releaseDefines
= " ";
1527 std::string minsizeDefines
= " ";
1528 std::string debugrelDefines
= " ";
1530 this->AppendDefines(
1532 this->Makefile
->GetProperty("COMPILE_DEFINITIONS"), 0);
1533 this->AppendDefines(
1535 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_DEBUG"),0);
1536 this->AppendDefines(
1538 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1539 this->AppendDefines(
1541 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1542 this->AppendDefines(
1544 this->Makefile
->GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"), 0);
1546 this->AppendDefines(
1548 target
.GetProperty("COMPILE_DEFINITIONS"), 0);
1549 this->AppendDefines(
1551 target
.GetProperty("COMPILE_DEFINITIONS_DEBUG"), 0);
1552 this->AppendDefines(
1554 target
.GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1555 this->AppendDefines(
1557 target
.GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1558 this->AppendDefines(
1560 target
.GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"), 0);
1562 flagsDebug
+= debugDefines
;
1563 flagsRelease
+= releaseDefines
;
1564 flagsMinSize
+= minsizeDefines
;
1565 flagsDebugRel
+= debugrelDefines
;
1567 // The template files have CXX FLAGS in them, that need to be replaced.
1568 // There are not separate CXX and C template files, so we use the same
1569 // variable names. The previous code sets up flags* variables to contain
1570 // the correct C or CXX flags
1571 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_MINSIZEREL",
1572 flagsMinSize
.c_str());
1573 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_DEBUG",
1574 flagsDebug
.c_str());
1575 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
1576 flagsDebugRel
.c_str());
1577 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS_RELEASE",
1578 flagsRelease
.c_str());
1579 cmSystemTools::ReplaceString(line
, "CMAKE_CXX_FLAGS", flags
.c_str());
1581 cmSystemTools::ReplaceString(line
, "COMPILE_DEFINITIONS_MINSIZE",
1582 minsizeDefines
.c_str());
1583 cmSystemTools::ReplaceString(line
, "COMPILE_DEFINITIONS_DEBUG",
1584 debugDefines
.c_str());
1585 cmSystemTools::ReplaceString(line
, "COMPILE_DEFINITIONS_RELWITHDEBINFO",
1586 debugrelDefines
.c_str());
1587 cmSystemTools::ReplaceString(line
, "COMPILE_DEFINITIONS_RELEASE",
1588 releaseDefines
.c_str());
1589 cmSystemTools::ReplaceString(line
, "COMPILE_DEFINITIONS", defines
.c_str());
1591 fout
<< line
.c_str() << std::endl
;
1595 void cmLocalVisualStudio6Generator::WriteDSPFooter(std::ostream
& fout
)
1597 std::ifstream
fin(this->DSPFooterTemplate
.c_str());
1600 cmSystemTools::Error("Error Reading ",
1601 this->DSPFooterTemplate
.c_str());
1604 while(cmSystemTools::GetLineFromStream(fin
, line
))
1606 fout
<< line
<< std::endl
;
1610 //----------------------------------------------------------------------------
1611 void cmLocalVisualStudio6Generator
1612 ::ComputeLinkOptions(cmTarget
& target
,
1613 const char* configName
,
1614 const std::string extraOptions
,
1615 std::string
& options
)
1617 // Compute the link information for this configuration.
1618 cmComputeLinkInformation
* pcli
= target
.GetLinkInformation(configName
);
1623 cmComputeLinkInformation
& cli
= *pcli
;
1624 typedef cmComputeLinkInformation::ItemVector ItemVector
;
1625 ItemVector
const& linkLibs
= cli
.GetItems();
1626 std::vector
<std::string
> const& linkDirs
= cli
.GetDirectories();
1628 // Build the link options code.
1629 for(std::vector
<std::string
>::const_iterator d
= linkDirs
.begin();
1630 d
!= linkDirs
.end(); ++d
)
1632 std::string dir
= *d
;
1635 if(dir
[dir
.size()-1] != '/')
1640 options
+= "# ADD LINK32 /LIBPATH:";
1641 options
+= this->ConvertToOptionallyRelativeOutputPath(dir
.c_str());
1642 options
+= " /LIBPATH:";
1643 options
+= this->ConvertToOptionallyRelativeOutputPath(d
->c_str());
1647 for(ItemVector::const_iterator l
= linkLibs
.begin();
1648 l
!= linkLibs
.end(); ++l
)
1650 options
+= "# ADD LINK32 ";
1654 this->ConvertToOptionallyRelativeOutputPath(l
->Value
.c_str());
1658 options
+= l
->Value
;
1663 // Add extra options if any.
1664 if(!extraOptions
.empty())
1666 options
+= "# ADD LINK32 ";
1667 options
+= extraOptions
;
1673 cmLocalVisualStudio6Generator
1674 ::GetTargetDirectory(cmTarget
const&) const
1676 // No per-target directory for this generator (yet).
1680 void cmLocalVisualStudio6Generator
1681 ::GetTargetObjectFileDirectories(cmTarget
* ,
1682 std::vector
<std::string
>&
1685 std::string dir
= this->Makefile
->GetCurrentOutputDirectory();
1687 dir
+= this->GetGlobalGenerator()->GetCMakeCFGInitDirectory();
1688 dirs
.push_back(dir
);
1692 cmLocalVisualStudio6Generator
1693 ::GetConfigName(std::string
const& configuration
) const
1695 // Strip the subdirectory name out of the configuration name.
1696 std::string config
= configuration
;
1697 std::string::size_type pos
= config
.find_last_of(" ");
1698 config
= config
.substr(pos
+1, std::string::npos
);
1699 config
= config
.substr(0, config
.size()-1);
1703 //----------------------------------------------------------------------------
1705 cmLocalVisualStudio6Generator
1706 ::CheckDefinition(std::string
const& define
) const
1708 // Perform the standard check first.
1709 if(!this->cmLocalGenerator::CheckDefinition(define
))
1714 // Now do the VS6-specific check.
1715 if(define
.find_first_of(" ") != define
.npos
)
1718 e
<< "WARNING: The VS6 IDE does not support preprocessor definition "
1719 << "values with spaces.\n"
1720 << "CMake is dropping a preprocessor definition: " << define
<< "\n"
1721 << "Consider defining the macro in a (configured) header file.\n";
1722 cmSystemTools::Message(e
.str().c_str());
1726 // Assume it is supported.