STYLE: Fix typo in GetFilenameLastExtension docs
[cmake.git] / Source / cmLocalVisualStudio6Generator.cxx
blob50ab17fbbeaf3caef81ffd3512efd0495a06061b
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmLocalVisualStudio6Generator.cxx,v $
5 Language: C++
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"
23 #include "cmake.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;
40 lang.insert("C");
41 lang.insert("CXX");
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)
76 std::string tmp =
77 this->ConvertToOptionallyRelativeOutputPath(i->c_str());
78 if(useShortPath)
80 cmSystemTools::GetShortPath(tmp.c_str(), tmp);
82 this->IncludeOptions += " /I ";
84 // quote if not already quoted
85 if (tmp[0] != '"')
87 this->IncludeOptions += "\"";
88 this->IncludeOptions += tmp;
89 this->IncludeOptions += "\"";
91 else
93 this->IncludeOptions += tmp;
96 if(j == 0 && this->IncludeOptions.size() > maxIncludeLength)
98 this->IncludeOptions = "";
99 useShortPath = true;
101 else
103 break;
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);
125 // build any targets
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);
133 break;
134 case cmTarget::SHARED_LIBRARY:
135 case cmTarget::MODULE_LIBRARY:
136 this->SetBuildType(DLL, l->first.c_str(), l->second);
137 break;
138 case cmTarget::EXECUTABLE:
139 this->SetBuildType(EXECUTABLE,l->first.c_str(), l->second);
140 break;
141 case cmTarget::UTILITY:
142 case cmTarget::GLOBAL_TARGET:
143 this->SetBuildType(UTILITY, l->first.c_str(), l->second);
144 break;
145 default:
146 cmSystemTools::Error("Bad target type", l->first.c_str());
147 break;
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();
158 dir += "/";
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,
171 cmTarget &target)
173 // add to the list of projects
174 std::string pname = lname;
175 this->CreatedProjectNames.push_back(pname);
176 // create the dsp.cmake file
177 std::string fname;
178 fname = this->Makefile->GetStartOutputDirectory();
179 fname += "/";
180 fname += lname;
181 fname += ".dsp";
182 // save the name of the real dsp file
183 std::string realDSP = fname;
184 fname += ".cmake";
185 std::ofstream fout(fname.c_str());
186 if(!fout)
188 cmSystemTools::Error("Error Writing ", fname.c_str());
189 cmSystemTools::ReportLastSystemError("");
191 this->WriteDSPFile(fout,lname,target);
192 fout.close();
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();
207 makefileIn += "/";
208 makefileIn += "CMakeLists.txt";
209 std::string comment = "Building Custom Rule ";
210 comment += makefileIn;
211 std::string args;
212 args = "-H";
213 args += this->Convert(this->Makefile->GetHomeDirectory(),
214 START_OUTPUT, UNCHANGED, true);
215 commandLine.push_back(args);
216 args = "-B";
217 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,
229 comment.c_str(),
230 no_working_directory, true);
231 if(cmSourceFile* file = this->Makefile->GetSource(makefileIn.c_str()))
233 tgt.AddSourceFile(file);
235 else
237 cmSystemTools::Error("Error adding rule for ", makefileIn.c_str());
242 void cmLocalVisualStudio6Generator::WriteDSPFile(std::ostream& fout,
243 const char *libName,
244 cmTarget &target)
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.
275 int count = 1;
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
311 // must generate it
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
320 | std::ios::trunc);
321 #else
322 std::ofstream fout(source.c_str(),
323 std::ios::out | std::ios::trunc);
324 #endif
325 if(fout)
327 fout.write("# generated from CMake",22);
328 fout.flush();
329 fout.close();
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())
363 return;
366 // If the group has a name, write the header.
367 std::string name = sg->GetName();
368 if(name != "")
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());
391 dir_len += 1;
392 dir_len += config_len_max;
393 dir_len += 1;
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())
407 objectNameDir =
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));
419 if(lang)
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");
461 if(dependsValue)
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.
472 fout << "SOURCE=" <<
473 this->ConvertToOptionallyRelativeOutputPath(source.c_str()) << "\n\n";
474 if(!depends.empty())
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)
481 fout << "\\\n\t" <<
482 this->ConvertToOptionallyRelativeOutputPath(d->c_str());
484 fout << "\n";
486 if (command)
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;
504 else
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.
546 if(name != "")
548 this->WriteDSPEndGroup(fout);
554 void
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,
570 depends,
571 no_main_dependency,
572 origCommand.GetCommandLines(),
573 comment.c_str(),
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.
578 depends.clear();
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.
586 delete [] output;
589 void
590 cmLocalVisualStudio6Generator
591 ::WriteCustomRule(std::ostream& fout,
592 const char* source,
593 const cmCustomCommand& command,
594 const char* flags)
596 std::string comment =
597 this->ConstructComment(command, "Building Custom Rule $(InputPath)");
598 if(comment == "<hack>")
600 comment = "";
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);
608 std::string script =
609 this->ConstructScript(command.GetCommandLines(),
610 command.GetWorkingDirectory(),
611 config.c_str(),
612 command.GetEscapeOldStyle(),
613 command.GetEscapeAllowMakeVars(),
614 "\\\n\t");
616 if (i == this->Configurations.begin())
618 fout << "!IF \"$(CFG)\" == " << i->c_str() << std::endl;
620 else
622 fout << "!ELSEIF \"$(CFG)\" == " << i->c_str() << std::endl;
624 if(flags)
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();
633 ++d)
635 // Lookup the real name of the dependency in case it is a CMake target.
636 std::string dep = this->GetRealDependency(d->c_str(),
637 config.c_str());
638 fout << "\\\n\t" <<
639 this->ConvertToOptionallyRelativeOutputPath(dep.c_str());
641 fout << "\n";
643 fout << "# PROP Ignore_Default_Tool 1\n";
644 fout << "# Begin Custom Build -";
645 if(!comment.empty())
647 fout << " " << comment.c_str();
649 fout << "\n\n";
650 if(command.GetOutputs().empty())
652 fout << source
653 << "_force : \"$(SOURCE)\" \"$(INTDIR)\" \"$(OUTDIR)\"\n\t";
654 fout << script.c_str() << "\n\n";
656 else
658 for(std::vector<std::string>::const_iterator o =
659 command.GetOutputs().begin();
660 o != command.GetOutputs().end();
661 ++o)
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,
677 const char* group,
678 const char* filter)
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,
694 const char* libName,
695 cmTarget& target)
697 std::string root= this->Makefile->GetRequiredDefinition("CMAKE_ROOT");
698 const char *def=
699 this->Makefile->GetDefinition( "MSPROJECT_TEMPLATE_DIRECTORY");
701 if( def)
703 root = def;
705 else
707 root += "/Templates";
710 switch(b)
712 case STATIC_LIBRARY:
713 this->DSPHeaderTemplate = root;
714 this->DSPHeaderTemplate += "/staticLibHeader.dsptemplate";
715 this->DSPFooterTemplate = root;
716 this->DSPFooterTemplate += "/staticLibFooter.dsptemplate";
717 break;
718 case DLL:
719 this->DSPHeaderTemplate = root;
720 this->DSPHeaderTemplate += "/DLLHeader.dsptemplate";
721 this->DSPFooterTemplate = root;
722 this->DSPFooterTemplate += "/DLLFooter.dsptemplate";
723 break;
724 case EXECUTABLE:
725 if ( target.GetPropertyAsBool("WIN32_EXECUTABLE") )
727 this->DSPHeaderTemplate = root;
728 this->DSPHeaderTemplate += "/EXEWinHeader.dsptemplate";
729 this->DSPFooterTemplate = root;
730 this->DSPFooterTemplate += "/EXEFooter.dsptemplate";
732 else
734 this->DSPHeaderTemplate = root;
735 this->DSPHeaderTemplate += "/EXEHeader.dsptemplate";
736 this->DSPFooterTemplate = root;
737 this->DSPFooterTemplate += "/EXEFooter.dsptemplate";
739 break;
740 case UTILITY:
741 this->DSPHeaderTemplate = root;
742 this->DSPHeaderTemplate += "/UtilityHeader.dsptemplate";
743 this->DSPFooterTemplate = root;
744 this->DSPFooterTemplate += "/UtilityFooter.dsptemplate";
745 break;
748 // once the build type is set, determine what configurations are
749 // possible
750 std::ifstream fin(this->DSPHeaderTemplate.c_str());
752 cmsys::RegularExpression reg("# Name ");
753 if(!fin)
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
762 std::string line;
763 while(cmSystemTools::GetLineFromStream(fin, line))
765 cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
766 if (reg.find(line))
768 this->Configurations.push_back(line.substr(reg.end()));
773 // look for custom rules on a target and collect them together
774 std::string
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
798 // line.
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)
804 // header stuff
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(),
817 configName,
818 cr->GetEscapeOldStyle(),
819 cr->GetEscapeAllowMakeVars(),
820 "\\\n\t");
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(),
832 configName,
833 cr->GetEscapeOldStyle(),
834 cr->GetEscapeAllowMakeVars(),
835 "\\\n\t");
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(),
861 configName,
862 cr->GetEscapeOldStyle(),
863 cr->GetEscapeAllowMakeVars(),
864 "\\\n\t");
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);
882 return s;
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.
900 std::string libPath;
901 if(this->Makefile->GetDefinition("LIBRARY_OUTPUT_PATH"))
903 libPath = this->Makefile->GetDefinition("LIBRARY_OUTPUT_PATH");
905 std::string exePath;
906 if(this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH"))
908 exePath = this->Makefile->GetDefinition("EXECUTABLE_OUTPUT_PATH");
911 // Make sure there are trailing slashes.
912 if(!libPath.empty())
914 if(libPath[libPath.size()-1] != '/')
916 libPath += "/";
919 if(!exePath.empty())
921 if(exePath[exePath.size()-1] != '/')
923 exePath += "/";
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;
939 if(libPath.size())
941 std::string lpath =
942 this->ConvertToOptionallyRelativeOutputPath(libPath.c_str());
943 if(lpath.size() == 0)
945 lpath = ".";
947 std::string lpathIntDir = libPath + "$(INTDIR)";
948 lpathIntDir =
949 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
950 if(pathEmitted.insert(lpath).second)
952 libOptions += " /LIBPATH:";
953 libOptions += lpathIntDir;
954 libOptions += " ";
955 libOptions += " /LIBPATH:";
956 libOptions += lpath;
957 libOptions += " ";
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";
972 if(exePath.size())
974 std::string lpath =
975 this->ConvertToOptionallyRelativeOutputPath(exePath.c_str());
976 if(lpath.size() == 0)
978 lpath = ".";
980 std::string lpathIntDir = exePath + "$(INTDIR)";
981 lpathIntDir =
982 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
984 if(pathEmitted.insert(lpath).second)
986 libOptions += " /LIBPATH:";
987 libOptions += lpathIntDir;
988 libOptions += " ";
989 libOptions += " /LIBPATH:";
990 libOptions += lpath;
991 libOptions += " ";
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] != '/')
1013 path += "/";
1015 std::string lpath =
1016 this->ConvertToOptionallyRelativeOutputPath(path.c_str());
1017 if(lpath.size() == 0)
1019 lpath = ".";
1021 std::string lpathIntDir = path + "$(INTDIR)";
1022 lpathIntDir =
1023 this->ConvertToOptionallyRelativeOutputPath(lpathIntDir.c_str());
1024 if(pathEmitted.insert(lpath).second)
1026 libOptions += " /LIBPATH:";
1027 libOptions += lpathIntDir;
1028 libOptions += " ";
1029 libOptions += " /LIBPATH:";
1030 libOptions += lpath;
1031 libOptions += " ";
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.
1062 std::string lib;
1063 std::string libDebug;
1064 cmTarget* tgt = this->GlobalGenerator->FindTarget(0, j->first.c_str());
1065 if(tgt)
1067 lib = cmSystemTools::GetFilenameWithoutExtension
1068 (tgt->GetFullName().c_str());
1069 libDebug = cmSystemTools::GetFilenameWithoutExtension
1070 (tgt->GetFullName("Debug").c_str());
1071 lib += ".lib";
1072 libDebug += ".lib";
1074 else
1076 lib = j->first.c_str();
1077 libDebug = j->first.c_str();
1078 if(j->first.find(".lib") == std::string::npos)
1080 lib += ".lib";
1081 libDebug += ".lib";
1084 lib = this->ConvertToOptionallyRelativeOutputPath(lib.c_str());
1085 libDebug =
1086 this->ConvertToOptionallyRelativeOutputPath(libDebug.c_str());
1088 if (j->second == cmTarget::GENERAL)
1090 libOptions += " ";
1091 libOptions += lib;
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";
1119 #endif
1121 // Get extra linker options for this target type.
1122 std::string extraLinkOptions;
1123 if(target.GetType() == cmTarget::EXECUTABLE)
1125 extraLinkOptions =
1126 this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1128 if(target.GetType() == cmTarget::SHARED_LIBRARY)
1130 extraLinkOptions =
1131 this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1133 if(target.GetType() == cmTarget::MODULE_LIBRARY)
1135 extraLinkOptions =
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());
1153 if(!linkLanguage)
1155 cmSystemTools::Error
1156 ("CMake can not determine linker language for target:",
1157 target.GetName());
1158 return;
1161 // Compute the variable name to lookup standard libraries for this
1162 // language.
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)
1182 int major;
1183 int minor;
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,
1219 optionsDebug);
1220 this->ComputeLinkOptions(target, "Release", extraLinkOptions,
1221 optionsRelease);
1222 this->ComputeLinkOptions(target, "MinSizeRel", extraLinkOptions,
1223 optionsMinSizeRel);
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())
1272 libOptions += " ";
1273 libOptions += extraLinkOptions;
1274 libOptions += " ";
1275 libMultiLineOptions += "# ADD LINK32 ";
1276 libMultiLineOptions += extraLinkOptions;
1277 libMultiLineOptions += " \n";
1278 libMultiLineOptionsForDebug += "# ADD LINK32 ";
1279 libMultiLineOptionsForDebug += extraLinkOptions;
1280 libMultiLineOptionsForDebug += " \n";
1282 #endif
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());
1296 if(!fin)
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;
1316 std::string line;
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");
1327 if(!mfcFlag)
1329 mfcFlag = "0";
1331 cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS",
1332 libnameExports.c_str());
1333 cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
1334 mfcFlag);
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());
1360 #endif
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());
1421 #endif
1422 cmSystemTools::ReplaceString
1423 (line, "OUTPUT_DIRECTORY",
1424 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1425 (outPath.c_str())).c_str());
1427 cmSystemTools::ReplaceString(line,
1428 "EXTRA_DEFINES",
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());
1445 if(!linkLanguage)
1447 cmSystemTools::Error
1448 ("CMake can not determine linker language for target:",
1449 target.GetName());
1450 return;
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;
1483 flagsDebug += " ";
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"))
1509 flags += " ";
1510 flags += targetFlags;
1513 // Add per-target and per-configuration preprocessor definitions.
1514 this->AppendDefines
1515 (flags, this->Makefile->GetProperty("COMPILE_DEFINITIONS"), 0);
1516 this->AppendDefines(flags, target.GetProperty("COMPILE_DEFINITIONS"), 0);
1517 this->AppendDefines
1518 (flagsDebug,
1519 this->Makefile->GetProperty("COMPILE_DEFINITIONS_DEBUG"), 0);
1520 this->AppendDefines(flagsDebug,
1521 target.GetProperty("COMPILE_DEFINITIONS_DEBUG"), 0);
1522 this->AppendDefines
1523 (flagsRelease,
1524 this->Makefile->GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1525 this->AppendDefines(flagsRelease,
1526 target.GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1527 this->AppendDefines
1528 (flagsMinSize,
1529 this->Makefile->GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1530 this->AppendDefines
1531 (flagsMinSize,
1532 target.GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1533 this->AppendDefines
1534 (flagsDebugRel,
1535 this->Makefile->GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"), 0);
1536 this->AppendDefines
1537 (flagsDebugRel,
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());
1560 if(!fin)
1562 cmSystemTools::Error("Error Reading ",
1563 this->DSPFooterTemplate.c_str());
1565 std::string line;
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);
1581 if(!pcli)
1583 return;
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;
1595 if(!dir.empty())
1597 if(dir[dir.size()-1] != '/')
1599 dir += "/";
1601 dir += "$(IntDir)";
1602 options += "# ADD LINK32 /LIBPATH:";
1603 options += this->ConvertToOptionallyRelativeOutputPath(dir.c_str());
1604 options += " /LIBPATH:";
1605 options += this->ConvertToOptionallyRelativeOutputPath(d->c_str());
1606 options += "\n";
1609 for(ItemVector::const_iterator l = linkLibs.begin();
1610 l != linkLibs.end(); ++l)
1612 options += "# ADD LINK32 ";
1613 if(l->IsPath)
1615 options +=
1616 this->ConvertToOptionallyRelativeOutputPath(l->Value.c_str());
1618 else
1620 options += l->Value;
1622 options += "\n";
1625 // Add extra options if any.
1626 if(!extraOptions.empty())
1628 options += "# ADD LINK32 ";
1629 options += extraOptions;
1630 options += "\n";
1634 std::string
1635 cmLocalVisualStudio6Generator
1636 ::GetTargetDirectory(cmTarget const&) const
1638 // No per-target directory for this generator (yet).
1639 return "";
1642 void cmLocalVisualStudio6Generator
1643 ::GetTargetObjectFileDirectories(cmTarget* ,
1644 std::vector<std::string>&
1645 dirs)
1647 std::string dir = this->Makefile->GetCurrentOutputDirectory();
1648 dir += "/";
1649 dir += this->GetGlobalGenerator()->GetCMakeCFGInitDirectory();
1650 dirs.push_back(dir);
1653 std::string
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);
1662 return config;
1665 //----------------------------------------------------------------------------
1666 bool
1667 cmLocalVisualStudio6Generator
1668 ::CheckDefinition(std::string const& define) const
1670 // Perform the standard check first.
1671 if(!this->cmLocalGenerator::CheckDefinition(define))
1673 return false;
1676 // Now do the VS6-specific check.
1677 if(define.find_first_of("=") != define.npos)
1679 cmOStringStream e;
1680 e << "WARNING: The VS6 IDE does not support preprocessor definitions "
1681 << "with values.\n"
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());
1685 return false;
1688 // Assume it is supported.
1689 return true;