ENH: keep cleaning up Tcl/Tk modules
[cmake.git] / Source / cmLocalVisualStudio6Generator.cxx
blob82f6c52f3e9e3ba52de9a4dd03df0a755f5cf4f2
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmLocalVisualStudio6Generator.cxx,v $
5 Language: C++
6 Date: $Date: 2008-01-22 14:13:03 $
7 Version: $Revision: 1.138 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmGlobalGenerator.h"
18 #include "cmLocalVisualStudio6Generator.h"
19 #include "cmMakefile.h"
20 #include "cmSystemTools.h"
21 #include "cmSourceFile.h"
22 #include "cmCacheManager.h"
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())
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> 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 false);
1066 if(tgt)
1068 lib = cmSystemTools::GetFilenameWithoutExtension
1069 (tgt->GetFullName().c_str());
1070 libDebug = cmSystemTools::GetFilenameWithoutExtension
1071 (tgt->GetFullName("Debug").c_str());
1072 lib += ".lib";
1073 libDebug += ".lib";
1075 else
1077 lib = j->first.c_str();
1078 libDebug = j->first.c_str();
1079 if(j->first.find(".lib") == std::string::npos)
1081 lib += ".lib";
1082 libDebug += ".lib";
1085 lib = this->ConvertToOptionallyRelativeOutputPath(lib.c_str());
1086 libDebug =
1087 this->ConvertToOptionallyRelativeOutputPath(libDebug.c_str());
1089 if (j->second == cmTarget::GENERAL)
1091 libOptions += " ";
1092 libOptions += lib;
1093 libMultiLineOptions += "# ADD LINK32 ";
1094 libMultiLineOptions += lib;
1095 libMultiLineOptions += "\n";
1096 libMultiLineOptionsForDebug += "# ADD LINK32 ";
1097 libMultiLineOptionsForDebug += libDebug;
1098 libMultiLineOptionsForDebug += "\n";
1100 if (j->second == cmTarget::DEBUG)
1102 libDebugOptions += " ";
1103 libDebugOptions += lib;
1105 libMultiLineDebugOptions += "# ADD LINK32 ";
1106 libMultiLineDebugOptions += libDebug;
1107 libMultiLineDebugOptions += "\n";
1109 if (j->second == cmTarget::OPTIMIZED)
1111 libOptimizedOptions += " ";
1112 libOptimizedOptions += lib;
1114 libMultiLineOptimizedOptions += "# ADD LINK32 ";
1115 libMultiLineOptimizedOptions += lib;
1116 libMultiLineOptimizedOptions += "\n";
1120 #endif
1122 // Get extra linker options for this target type.
1123 std::string extraLinkOptions;
1124 if(target.GetType() == cmTarget::EXECUTABLE)
1126 extraLinkOptions =
1127 this->Makefile->GetRequiredDefinition("CMAKE_EXE_LINKER_FLAGS");
1129 if(target.GetType() == cmTarget::SHARED_LIBRARY)
1131 extraLinkOptions =
1132 this->Makefile->GetRequiredDefinition("CMAKE_SHARED_LINKER_FLAGS");
1134 if(target.GetType() == cmTarget::MODULE_LIBRARY)
1136 extraLinkOptions =
1137 this->Makefile->GetRequiredDefinition("CMAKE_MODULE_LINKER_FLAGS");
1140 // Get extra linker options for this target.
1141 if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS"))
1143 extraLinkOptions += " ";
1144 extraLinkOptions += targetLinkFlags;
1147 // Get standard libraries for this language.
1148 if(target.GetType() >= cmTarget::EXECUTABLE &&
1149 target.GetType() <= cmTarget::MODULE_LIBRARY)
1151 // Get the language to use for linking.
1152 const char* linkLanguage =
1153 target.GetLinkerLanguage(this->GetGlobalGenerator());
1154 if(!linkLanguage)
1156 cmSystemTools::Error
1157 ("CMake can not determine linker language for target:",
1158 target.GetName());
1159 return;
1162 // Compute the variable name to lookup standard libraries for this
1163 // language.
1164 std::string standardLibsVar = "CMAKE_";
1165 standardLibsVar += linkLanguage;
1166 standardLibsVar += "_STANDARD_LIBRARIES";
1168 // Add standard libraries.
1169 if(const char* stdLibs =
1170 this->Makefile->GetDefinition(standardLibsVar.c_str()))
1172 extraLinkOptions += " ";
1173 extraLinkOptions += stdLibs;
1177 // Compute version number information.
1178 std::string targetVersionFlag;
1179 if(target.GetType() == cmTarget::EXECUTABLE ||
1180 target.GetType() == cmTarget::SHARED_LIBRARY ||
1181 target.GetType() == cmTarget::MODULE_LIBRARY)
1183 int major;
1184 int minor;
1185 target.GetTargetVersion(major, minor);
1186 cmOStringStream targetVersionStream;
1187 targetVersionStream << "/version:" << major << "." << minor;
1188 targetVersionFlag = targetVersionStream.str();
1191 // Compute the real name of the target.
1192 std::string outputName =
1193 "(OUTPUT_NAME is for libraries and executables only)";
1194 std::string outputNameDebug = outputName;
1195 std::string outputNameRelease = outputName;
1196 std::string outputNameMinSizeRel = outputName;
1197 std::string outputNameRelWithDebInfo = outputName;
1198 if(target.GetType() == cmTarget::EXECUTABLE ||
1199 target.GetType() == cmTarget::STATIC_LIBRARY ||
1200 target.GetType() == cmTarget::SHARED_LIBRARY ||
1201 target.GetType() == cmTarget::MODULE_LIBRARY)
1203 outputName = target.GetFullName();
1204 outputNameDebug = target.GetFullName("Debug");
1205 outputNameRelease = target.GetFullName("Release");
1206 outputNameMinSizeRel = target.GetFullName("MinSizeRel");
1207 outputNameRelWithDebInfo = target.GetFullName("RelWithDebInfo");
1210 // Compute the proper link information for the target.
1211 std::string optionsDebug;
1212 std::string optionsRelease;
1213 std::string optionsMinSizeRel;
1214 std::string optionsRelWithDebInfo;
1215 if(target.GetType() == cmTarget::EXECUTABLE ||
1216 target.GetType() == cmTarget::SHARED_LIBRARY ||
1217 target.GetType() == cmTarget::MODULE_LIBRARY)
1219 this->ComputeLinkOptions(target, "Debug", extraLinkOptions,
1220 optionsDebug);
1221 this->ComputeLinkOptions(target, "Release", extraLinkOptions,
1222 optionsRelease);
1223 this->ComputeLinkOptions(target, "MinSizeRel", extraLinkOptions,
1224 optionsMinSizeRel);
1225 this->ComputeLinkOptions(target, "RelWithDebInfo", extraLinkOptions,
1226 optionsRelWithDebInfo);
1229 // Compute the path of the import library.
1230 std::string targetImplibFlagDebug;
1231 std::string targetImplibFlagRelease;
1232 std::string targetImplibFlagMinSizeRel;
1233 std::string targetImplibFlagRelWithDebInfo;
1234 if(target.GetType() == cmTarget::SHARED_LIBRARY ||
1235 target.GetType() == cmTarget::MODULE_LIBRARY ||
1236 target.GetType() == cmTarget::EXECUTABLE)
1238 std::string fullPathImpDebug = target.GetDirectory("Debug", true);
1239 std::string fullPathImpRelease = target.GetDirectory("Release", true);
1240 std::string fullPathImpMinSizeRel =
1241 target.GetDirectory("MinSizeRel", true);
1242 std::string fullPathImpRelWithDebInfo =
1243 target.GetDirectory("RelWithDebInfo", true);
1244 fullPathImpDebug += "/";
1245 fullPathImpRelease += "/";
1246 fullPathImpMinSizeRel += "/";
1247 fullPathImpRelWithDebInfo += "/";
1248 fullPathImpDebug += target.GetFullName("Debug", true);
1249 fullPathImpRelease += target.GetFullName("Release", true);
1250 fullPathImpMinSizeRel += target.GetFullName("MinSizeRel", true);
1251 fullPathImpRelWithDebInfo += target.GetFullName("RelWithDebInfo", true);
1253 targetImplibFlagDebug = "/implib:";
1254 targetImplibFlagRelease = "/implib:";
1255 targetImplibFlagMinSizeRel = "/implib:";
1256 targetImplibFlagRelWithDebInfo = "/implib:";
1257 targetImplibFlagDebug +=
1258 this->ConvertToOptionallyRelativeOutputPath(fullPathImpDebug.c_str());
1259 targetImplibFlagRelease +=
1260 this->ConvertToOptionallyRelativeOutputPath(fullPathImpRelease.c_str());
1261 targetImplibFlagMinSizeRel +=
1262 this->ConvertToOptionallyRelativeOutputPath(
1263 fullPathImpMinSizeRel.c_str());
1264 targetImplibFlagRelWithDebInfo +=
1265 this->ConvertToOptionallyRelativeOutputPath(
1266 fullPathImpRelWithDebInfo.c_str());
1269 #ifdef CM_USE_OLD_VS6
1270 // Compute link information for the target.
1271 if(extraLinkOptions.size())
1273 libOptions += " ";
1274 libOptions += extraLinkOptions;
1275 libOptions += " ";
1276 libMultiLineOptions += "# ADD LINK32 ";
1277 libMultiLineOptions += extraLinkOptions;
1278 libMultiLineOptions += " \n";
1279 libMultiLineOptionsForDebug += "# ADD LINK32 ";
1280 libMultiLineOptionsForDebug += extraLinkOptions;
1281 libMultiLineOptionsForDebug += " \n";
1283 #endif
1285 // are there any custom rules on the target itself
1286 // only if the target is a lib or exe
1287 std::string customRuleCodeRelease
1288 = this->CreateTargetRules(target, "RELEASE", libName);
1289 std::string customRuleCodeDebug
1290 = this->CreateTargetRules(target, "DEBUG", libName);
1291 std::string customRuleCodeMinSizeRel
1292 = this->CreateTargetRules(target, "MINSIZEREL", libName);
1293 std::string customRuleCodeRelWithDebInfo
1294 = this->CreateTargetRules(target, "RELWITHDEBINFO", libName);
1296 std::ifstream fin(this->DSPHeaderTemplate.c_str());
1297 if(!fin)
1299 cmSystemTools::Error("Error Reading ", this->DSPHeaderTemplate.c_str());
1301 std::string staticLibOptions;
1302 if(target.GetType() == cmTarget::STATIC_LIBRARY )
1304 if(const char* libflags = target.GetProperty("STATIC_LIBRARY_FLAGS"))
1306 staticLibOptions = libflags;
1310 // Add the export symbol definition for shared library objects.
1311 std::string exportSymbol;
1312 if(const char* exportMacro = target.GetExportMacro())
1314 exportSymbol = exportMacro;
1317 std::string line;
1318 while(cmSystemTools::GetLineFromStream(fin, line))
1320 const char* mfcFlag = this->Makefile->GetDefinition("CMAKE_MFC_FLAG");
1321 if(!mfcFlag)
1323 mfcFlag = "0";
1325 cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME_EXPORTS",
1326 exportSymbol.c_str());
1327 cmSystemTools::ReplaceString(line, "CMAKE_MFC_FLAG",
1328 mfcFlag);
1329 if(target.GetType() == cmTarget::STATIC_LIBRARY )
1331 cmSystemTools::ReplaceString(line, "CM_STATIC_LIB_ARGS",
1332 staticLibOptions.c_str());
1334 if(this->Makefile->IsOn("CMAKE_VERBOSE_MAKEFILE"))
1336 cmSystemTools::ReplaceString(line, "/nologo", "");
1339 #ifdef CM_USE_OLD_VS6
1340 cmSystemTools::ReplaceString(line, "CM_LIBRARIES",
1341 libOptions.c_str());
1342 cmSystemTools::ReplaceString(line, "CM_DEBUG_LIBRARIES",
1343 libDebugOptions.c_str());
1344 cmSystemTools::ReplaceString(line, "CM_OPTIMIZED_LIBRARIES",
1345 libOptimizedOptions.c_str());
1346 cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES_FOR_DEBUG",
1347 libMultiLineOptionsForDebug.c_str());
1348 cmSystemTools::ReplaceString(line, "CM_MULTILINE_LIBRARIES",
1349 libMultiLineOptions.c_str());
1350 cmSystemTools::ReplaceString(line, "CM_MULTILINE_DEBUG_LIBRARIES",
1351 libMultiLineDebugOptions.c_str());
1352 cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIMIZED_LIBRARIES",
1353 libMultiLineOptimizedOptions.c_str());
1354 #endif
1356 // Substitute the rules for custom command. When specifying just the
1357 // target name for the command the command can be different for
1358 // different configs
1359 cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_RELEASE",
1360 customRuleCodeRelease.c_str());
1361 cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_DEBUG",
1362 customRuleCodeDebug.c_str());
1363 cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_MINSIZEREL",
1364 customRuleCodeMinSizeRel.c_str());
1365 cmSystemTools::ReplaceString(line, "CMAKE_CUSTOM_RULE_CODE_RELWITHDEBINFO",
1366 customRuleCodeRelWithDebInfo.c_str());
1368 // Substitute the real output name into the template.
1369 cmSystemTools::ReplaceString(line, "OUTPUT_NAME_DEBUG",
1370 outputNameDebug.c_str());
1371 cmSystemTools::ReplaceString(line, "OUTPUT_NAME_RELEASE",
1372 outputNameRelease.c_str());
1373 cmSystemTools::ReplaceString(line, "OUTPUT_NAME_MINSIZEREL",
1374 outputNameMinSizeRel.c_str());
1375 cmSystemTools::ReplaceString(line, "OUTPUT_NAME_RELWITHDEBINFO",
1376 outputNameRelWithDebInfo.c_str());
1377 cmSystemTools::ReplaceString(line, "OUTPUT_NAME", outputName.c_str());
1379 // Substitute the proper link information into the template.
1380 cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_DEBUG",
1381 optionsDebug.c_str());
1382 cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_RELEASE",
1383 optionsRelease.c_str());
1384 cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_MINSIZEREL",
1385 optionsMinSizeRel.c_str());
1386 cmSystemTools::ReplaceString(line, "CM_MULTILINE_OPTIONS_RELWITHDEBINFO",
1387 optionsRelWithDebInfo.c_str());
1389 cmSystemTools::ReplaceString(line, "BUILD_INCLUDES",
1390 this->IncludeOptions.c_str());
1391 cmSystemTools::ReplaceString(line, "TARGET_VERSION_FLAG",
1392 targetVersionFlag.c_str());
1393 cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_DEBUG",
1394 targetImplibFlagDebug.c_str());
1395 cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_RELEASE",
1396 targetImplibFlagRelease.c_str());
1397 cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_MINSIZEREL",
1398 targetImplibFlagMinSizeRel.c_str());
1399 cmSystemTools::ReplaceString(line, "TARGET_IMPLIB_FLAG_RELWITHDEBINFO",
1400 targetImplibFlagRelWithDebInfo.c_str());
1401 cmSystemTools::ReplaceString(line, "OUTPUT_LIBNAME",libName);
1402 #ifdef CM_USE_OLD_VS6
1403 // because LIBRARY_OUTPUT_PATH and EXECUTABLE_OUTPUT_PATH
1404 // are already quoted in the template file,
1405 // we need to remove the quotes here, we still need
1406 // to convert to output path for unix to win32 conversion
1407 cmSystemTools::ReplaceString
1408 (line, "LIBRARY_OUTPUT_PATH",
1409 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1410 (libPath.c_str())).c_str());
1411 cmSystemTools::ReplaceString
1412 (line, "EXECUTABLE_OUTPUT_PATH",
1413 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1414 (exePath.c_str())).c_str());
1415 #endif
1416 cmSystemTools::ReplaceString
1417 (line, "OUTPUT_DIRECTORY",
1418 removeQuotes(this->ConvertToOptionallyRelativeOutputPath
1419 (outPath.c_str())).c_str());
1421 cmSystemTools::ReplaceString(line,
1422 "EXTRA_DEFINES",
1423 this->Makefile->GetDefineFlags());
1424 const char* debugPostfix
1425 = this->Makefile->GetDefinition("CMAKE_DEBUG_POSTFIX");
1426 cmSystemTools::ReplaceString(line, "DEBUG_POSTFIX",
1427 debugPostfix?debugPostfix:"");
1428 // store flags for each configuration
1429 std::string flags = " ";
1430 std::string flagsRelease = " ";
1431 std::string flagsMinSize = " ";
1432 std::string flagsDebug = " ";
1433 std::string flagsDebugRel = " ";
1434 if(target.GetType() >= cmTarget::EXECUTABLE &&
1435 target.GetType() <= cmTarget::MODULE_LIBRARY)
1437 const char* linkLanguage =
1438 target.GetLinkerLanguage(this->GetGlobalGenerator());
1439 if(!linkLanguage)
1441 cmSystemTools::Error
1442 ("CMake can not determine linker language for target:",
1443 target.GetName());
1444 return;
1446 // if CXX is on and the target contains cxx code then add the cxx flags
1447 std::string baseFlagVar = "CMAKE_";
1448 baseFlagVar += linkLanguage;
1449 baseFlagVar += "_FLAGS";
1450 flags = this->Makefile->GetSafeDefinition(baseFlagVar.c_str());
1452 std::string flagVar = baseFlagVar + "_RELEASE";
1453 flagsRelease = this->Makefile->GetSafeDefinition(flagVar.c_str());
1454 flagsRelease += " -DCMAKE_INTDIR=\\\"Release\\\" ";
1455 if(const char* targetLinkFlags =
1456 target.GetProperty("LINK_FLAGS_RELEASE"))
1458 flagsRelease += targetLinkFlags;
1459 flagsRelease += " ";
1461 flagVar = baseFlagVar + "_MINSIZEREL";
1462 flagsMinSize = this->Makefile->GetSafeDefinition(flagVar.c_str());
1463 flagsMinSize += " -DCMAKE_INTDIR=\\\"MinSizeRel\\\" ";
1464 if(const char* targetLinkFlags =
1465 target.GetProperty("LINK_FLAGS_MINSIZEREL"))
1467 flagsMinSize += targetLinkFlags;
1468 flagsMinSize += " ";
1471 flagVar = baseFlagVar + "_DEBUG";
1472 flagsDebug = this->Makefile->GetSafeDefinition(flagVar.c_str());
1473 flagsDebug += " -DCMAKE_INTDIR=\\\"Debug\\\" ";
1474 if(const char* targetLinkFlags = target.GetProperty("LINK_FLAGS_DEBUG"))
1476 flagsDebug += targetLinkFlags;
1477 flagsDebug += " ";
1480 flagVar = baseFlagVar + "_RELWITHDEBINFO";
1481 flagsDebugRel = this->Makefile->GetSafeDefinition(flagVar.c_str());
1482 flagsDebugRel += " -DCMAKE_INTDIR=\\\"RelWithDebInfo\\\" ";
1483 if(const char* targetLinkFlags =
1484 target.GetProperty("LINK_FLAGS_RELWITHDEBINFO"))
1486 flagsDebugRel += targetLinkFlags;
1487 flagsDebugRel += " ";
1492 // if unicode is not found, then add -D_MBCS
1493 std::string defs = this->Makefile->GetDefineFlags();
1494 if(flags.find("D_UNICODE") == flags.npos &&
1495 defs.find("D_UNICODE") == flags.npos)
1497 flags += " /D \"_MBCS\"";
1500 // Add per-target flags.
1501 if(const char* targetFlags = target.GetProperty("COMPILE_FLAGS"))
1503 flags += " ";
1504 flags += targetFlags;
1507 // Add per-target and per-configuration preprocessor definitions.
1508 this->AppendDefines
1509 (flags, this->Makefile->GetProperty("COMPILE_DEFINITIONS"), 0);
1510 this->AppendDefines(flags, target.GetProperty("COMPILE_DEFINITIONS"), 0);
1511 this->AppendDefines
1512 (flagsDebug,
1513 this->Makefile->GetProperty("COMPILE_DEFINITIONS_DEBUG"), 0);
1514 this->AppendDefines(flagsDebug,
1515 target.GetProperty("COMPILE_DEFINITIONS_DEBUG"), 0);
1516 this->AppendDefines
1517 (flagsRelease,
1518 this->Makefile->GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1519 this->AppendDefines(flagsRelease,
1520 target.GetProperty("COMPILE_DEFINITIONS_RELEASE"), 0);
1521 this->AppendDefines
1522 (flagsMinSize,
1523 this->Makefile->GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1524 this->AppendDefines
1525 (flagsMinSize,
1526 target.GetProperty("COMPILE_DEFINITIONS_MINSIZEREL"), 0);
1527 this->AppendDefines
1528 (flagsDebugRel,
1529 this->Makefile->GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"), 0);
1530 this->AppendDefines
1531 (flagsDebugRel,
1532 target.GetProperty("COMPILE_DEFINITIONS_RELWITHDEBINFO"), 0);
1534 // The template files have CXX FLAGS in them, that need to be replaced.
1535 // There are not separate CXX and C template files, so we use the same
1536 // variable names. The previous code sets up flags* variables to contain
1537 // the correct C or CXX flags
1538 cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_MINSIZEREL",
1539 flagsMinSize.c_str());
1540 cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_DEBUG",
1541 flagsDebug.c_str());
1542 cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELWITHDEBINFO",
1543 flagsDebugRel.c_str());
1544 cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS_RELEASE",
1545 flagsRelease.c_str());
1546 cmSystemTools::ReplaceString(line, "CMAKE_CXX_FLAGS", flags.c_str());
1547 fout << line.c_str() << std::endl;
1551 void cmLocalVisualStudio6Generator::WriteDSPFooter(std::ostream& fout)
1553 std::ifstream fin(this->DSPFooterTemplate.c_str());
1554 if(!fin)
1556 cmSystemTools::Error("Error Reading ",
1557 this->DSPFooterTemplate.c_str());
1559 std::string line;
1560 while(cmSystemTools::GetLineFromStream(fin, line))
1562 fout << line << std::endl;
1566 //----------------------------------------------------------------------------
1567 void cmLocalVisualStudio6Generator
1568 ::ComputeLinkOptions(cmTarget& target,
1569 const char* configName,
1570 const std::string extraOptions,
1571 std::string& options)
1573 // Compute the link information for this configuration.
1574 cmComputeLinkInformation cli(&target, configName);
1575 if(!cli.Compute())
1577 return;
1579 typedef cmComputeLinkInformation::ItemVector ItemVector;
1580 ItemVector const& linkLibs = cli.GetItems();
1581 std::vector<std::string> const& linkDirs = cli.GetDirectories();
1583 // Build the link options code.
1584 for(std::vector<std::string>::const_iterator d = linkDirs.begin();
1585 d != linkDirs.end(); ++d)
1587 std::string dir = *d;
1588 if(!dir.empty())
1590 if(dir[dir.size()-1] != '/')
1592 dir += "/";
1594 dir += "$(IntDir)";
1595 options += "# ADD LINK32 /LIBPATH:";
1596 options += this->ConvertToOptionallyRelativeOutputPath(dir.c_str());
1597 options += " /LIBPATH:";
1598 options += this->ConvertToOptionallyRelativeOutputPath(d->c_str());
1599 options += "\n";
1602 for(ItemVector::const_iterator l = linkLibs.begin();
1603 l != linkLibs.end(); ++l)
1605 options += "# ADD LINK32 ";
1606 if(l->IsPath)
1608 options +=
1609 this->ConvertToOptionallyRelativeOutputPath(l->Value.c_str());
1611 else
1613 options += l->Value;
1615 options += "\n";
1618 // Add extra options if any.
1619 if(!extraOptions.empty())
1621 options += "# ADD LINK32 ";
1622 options += extraOptions;
1623 options += "\n";
1627 std::string
1628 cmLocalVisualStudio6Generator
1629 ::GetTargetDirectory(cmTarget const&) const
1631 // No per-target directory for this generator (yet).
1632 return "";
1635 void cmLocalVisualStudio6Generator
1636 ::GetTargetObjectFileDirectories(cmTarget* ,
1637 std::vector<std::string>&
1638 dirs)
1640 std::string dir = this->Makefile->GetCurrentOutputDirectory();
1641 dir += "/";
1642 dir += this->GetGlobalGenerator()->GetCMakeCFGInitDirectory();
1643 dirs.push_back(dir);
1646 std::string
1647 cmLocalVisualStudio6Generator
1648 ::GetConfigName(std::string const& configuration) const
1650 // Strip the subdirectory name out of the configuration name.
1651 std::string config = configuration;
1652 std::string::size_type pos = config.find_last_of(" ");
1653 config = config.substr(pos+1, std::string::npos);
1654 config = config.substr(0, config.size()-1);
1655 return config;
1658 //----------------------------------------------------------------------------
1659 bool
1660 cmLocalVisualStudio6Generator
1661 ::CheckDefinition(std::string const& define) const
1663 // Perform the standard check first.
1664 if(!this->cmLocalGenerator::CheckDefinition(define))
1666 return false;
1669 // Now do the VS6-specific check.
1670 if(define.find_first_of("=") != define.npos)
1672 cmOStringStream e;
1673 e << "WARNING: The VS6 IDE does not support preprocessor definitions "
1674 << "with values.\n"
1675 << "CMake is dropping a preprocessor definition: " << define << "\n"
1676 << "Consider defining the macro in a (configured) header file.\n";
1677 cmSystemTools::Message(e.str().c_str());
1678 return false;
1681 // Assume it is supported.
1682 return true;