Imported Upstream version 2.8.9
[platform/upstream/cmake.git] / Source / cmMakefileTargetGenerator.cxx
1 /*============================================================================
2   CMake - Cross Platform Makefile Generator
3   Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
4
5   Distributed under the OSI-approved BSD License (the "License");
6   see accompanying file Copyright.txt for details.
7
8   This software is distributed WITHOUT ANY WARRANTY; without even the
9   implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
10   See the License for more information.
11 ============================================================================*/
12 #include "cmMakefileTargetGenerator.h"
13
14 #include "cmGeneratorTarget.h"
15 #include "cmGeneratedFileStream.h"
16 #include "cmGlobalGenerator.h"
17 #include "cmGlobalUnixMakefileGenerator3.h"
18 #include "cmLocalUnixMakefileGenerator3.h"
19 #include "cmMakefile.h"
20 #include "cmSourceFile.h"
21 #include "cmTarget.h"
22 #include "cmake.h"
23 #include "cmComputeLinkInformation.h"
24
25 #include "cmMakefileExecutableTargetGenerator.h"
26 #include "cmMakefileLibraryTargetGenerator.h"
27 #include "cmMakefileUtilityTargetGenerator.h"
28
29
30 cmMakefileTargetGenerator::cmMakefileTargetGenerator(cmTarget* target)
31   : OSXBundleGenerator(0)
32   , MacOSXContentGenerator(0)
33 {
34   this->BuildFileStream = 0;
35   this->InfoFileStream = 0;
36   this->FlagFileStream = 0;
37   this->CustomCommandDriver = OnBuild;
38   this->FortranModuleDirectoryComputed = false;
39   this->Target = target;
40   this->Makefile = this->Target->GetMakefile();
41   this->LocalGenerator =
42     static_cast<cmLocalUnixMakefileGenerator3*>(
43       this->Makefile->GetLocalGenerator());
44   this->ConfigName = this->LocalGenerator->ConfigurationName.c_str();
45   this->GlobalGenerator =
46     static_cast<cmGlobalUnixMakefileGenerator3*>(
47       this->LocalGenerator->GetGlobalGenerator());
48   this->GeneratorTarget = this->GlobalGenerator->GetGeneratorTarget(target);
49   cmake* cm = this->GlobalGenerator->GetCMakeInstance();
50   this->NoRuleMessages = false;
51   if(const char* ruleStatus = cm->GetProperty("RULE_MESSAGES"))
52     {
53     this->NoRuleMessages = cmSystemTools::IsOff(ruleStatus);
54     }
55   MacOSXContentGenerator = new MacOSXContentGeneratorType(this);
56 }
57
58 cmMakefileTargetGenerator::~cmMakefileTargetGenerator()
59 {
60   delete MacOSXContentGenerator;
61 }
62
63 cmMakefileTargetGenerator *
64 cmMakefileTargetGenerator::New(cmTarget *tgt)
65 {
66   cmMakefileTargetGenerator *result = 0;
67
68   switch (tgt->GetType())
69     {
70     case cmTarget::EXECUTABLE:
71       result = new cmMakefileExecutableTargetGenerator(tgt);
72       break;
73     case cmTarget::STATIC_LIBRARY:
74     case cmTarget::SHARED_LIBRARY:
75     case cmTarget::MODULE_LIBRARY:
76     case cmTarget::OBJECT_LIBRARY:
77       result = new cmMakefileLibraryTargetGenerator(tgt);
78       break;
79     case cmTarget::UTILITY:
80       result = new cmMakefileUtilityTargetGenerator(tgt);
81       break;
82     default:
83       return result;
84       // break; /* unreachable */
85     }
86   return result;
87 }
88
89 //----------------------------------------------------------------------------
90 void cmMakefileTargetGenerator::CreateRuleFile()
91 {
92   // Create a directory for this target.
93   this->TargetBuildDirectory =
94     this->LocalGenerator->GetTargetDirectory(*this->Target);
95   this->TargetBuildDirectoryFull =
96     this->LocalGenerator->ConvertToFullPath(this->TargetBuildDirectory);
97   cmSystemTools::MakeDirectory(this->TargetBuildDirectoryFull.c_str());
98
99   // Construct the rule file name.
100   this->BuildFileName = this->TargetBuildDirectory;
101   this->BuildFileName += "/build.make";
102   this->BuildFileNameFull = this->TargetBuildDirectoryFull;
103   this->BuildFileNameFull += "/build.make";
104
105   // Construct the rule file name.
106   this->ProgressFileNameFull = this->TargetBuildDirectoryFull;
107   this->ProgressFileNameFull += "/progress.make";
108
109   // reset the progress count
110   this->NumberOfProgressActions = 0;
111
112   // Open the rule file.  This should be copy-if-different because the
113   // rules may depend on this file itself.
114   this->BuildFileStream =
115     new cmGeneratedFileStream(this->BuildFileNameFull.c_str());
116   this->BuildFileStream->SetCopyIfDifferent(true);
117   if(!this->BuildFileStream)
118     {
119     return;
120     }
121   this->LocalGenerator->WriteDisclaimer(*this->BuildFileStream);
122   this->LocalGenerator->WriteSpecialTargetsTop(*this->BuildFileStream);
123 }
124
125 //----------------------------------------------------------------------------
126 void cmMakefileTargetGenerator::WriteTargetBuildRules()
127 {
128   // write the custom commands for this target
129   // Look for files registered for cleaning in this directory.
130   if(const char* additional_clean_files =
131      this->Makefile->GetProperty
132      ("ADDITIONAL_MAKE_CLEAN_FILES"))
133     {
134     cmSystemTools::ExpandListArgument(additional_clean_files,
135                                       this->CleanFiles);
136     }
137
138   // add custom commands to the clean rules?
139   const char* clean_no_custom =
140     this->Makefile->GetProperty("CLEAN_NO_CUSTOM");
141   bool clean = cmSystemTools::IsOff(clean_no_custom);
142
143   // First generate the object rule files.  Save a list of all object
144   // files for this target.
145   for(std::vector<cmSourceFile*>::const_iterator
146         si = this->GeneratorTarget->CustomCommands.begin();
147       si != this->GeneratorTarget->CustomCommands.end(); ++si)
148     {
149     cmCustomCommand const* cc = (*si)->GetCustomCommand();
150     this->GenerateCustomRuleFile(*cc);
151     if (clean)
152       {
153       const std::vector<std::string>& outputs = cc->GetOutputs();
154       for(std::vector<std::string>::const_iterator o = outputs.begin();
155           o != outputs.end(); ++o)
156         {
157         this->CleanFiles.push_back
158           (this->Convert(o->c_str(),
159                          cmLocalGenerator::START_OUTPUT,
160                          cmLocalGenerator::UNCHANGED));
161         }
162       }
163     }
164   this->OSXBundleGenerator->GenerateMacOSXContentStatements(
165     this->GeneratorTarget->HeaderSources,
166     this->MacOSXContentGenerator);
167   this->OSXBundleGenerator->GenerateMacOSXContentStatements(
168     this->GeneratorTarget->ExtraSources,
169     this->MacOSXContentGenerator);
170   for(std::vector<cmSourceFile*>::const_iterator
171         si = this->GeneratorTarget->ExternalObjects.begin();
172       si != this->GeneratorTarget->ExternalObjects.end(); ++si)
173     {
174     this->ExternalObjects.push_back((*si)->GetFullPath());
175     }
176   for(std::vector<cmSourceFile*>::const_iterator
177         si = this->GeneratorTarget->ObjectSources.begin();
178       si != this->GeneratorTarget->ObjectSources.end(); ++si)
179     {
180     // Generate this object file's rule file.
181     this->WriteObjectRuleFiles(**si);
182     }
183
184   // Add object library contents as external objects.
185   this->GeneratorTarget->UseObjectLibraries(this->ExternalObjects);
186 }
187
188 //----------------------------------------------------------------------------
189 void cmMakefileTargetGenerator::WriteCommonCodeRules()
190 {
191   const char* root = (this->Makefile->IsOn("CMAKE_MAKE_INCLUDE_FROM_ROOT")?
192                       "$(CMAKE_BINARY_DIR)/" : "");
193
194   // Include the dependencies for the target.
195   std::string dependFileNameFull = this->TargetBuildDirectoryFull;
196   dependFileNameFull += "/depend.make";
197   *this->BuildFileStream
198     << "# Include any dependencies generated for this target.\n"
199     << this->LocalGenerator->IncludeDirective << " " << root
200     << this->Convert(dependFileNameFull.c_str(),
201                      cmLocalGenerator::HOME_OUTPUT,
202                      cmLocalGenerator::MAKEFILE)
203     << "\n\n";
204
205   if(!this->NoRuleMessages)
206     {
207     // Include the progress variables for the target.
208     *this->BuildFileStream
209       << "# Include the progress variables for this target.\n"
210       << this->LocalGenerator->IncludeDirective << " " << root
211       << this->Convert(this->ProgressFileNameFull.c_str(),
212                        cmLocalGenerator::HOME_OUTPUT,
213                        cmLocalGenerator::MAKEFILE)
214       << "\n\n";
215     }
216
217   // make sure the depend file exists
218   if (!cmSystemTools::FileExists(dependFileNameFull.c_str()))
219     {
220     // Write an empty dependency file.
221     cmGeneratedFileStream depFileStream(dependFileNameFull.c_str());
222     depFileStream
223       << "# Empty dependencies file for " << this->Target->GetName() << ".\n"
224       << "# This may be replaced when dependencies are built." << std::endl;
225     }
226
227   // Open the flags file.  This should be copy-if-different because the
228   // rules may depend on this file itself.
229   this->FlagFileNameFull = this->TargetBuildDirectoryFull;
230   this->FlagFileNameFull += "/flags.make";
231   this->FlagFileStream =
232     new cmGeneratedFileStream(this->FlagFileNameFull.c_str());
233   this->FlagFileStream->SetCopyIfDifferent(true);
234   if(!this->FlagFileStream)
235     {
236     return;
237     }
238   this->LocalGenerator->WriteDisclaimer(*this->FlagFileStream);
239
240   // Include the flags for the target.
241   *this->BuildFileStream
242     << "# Include the compile flags for this target's objects.\n"
243     << this->LocalGenerator->IncludeDirective << " " << root
244     << this->Convert(this->FlagFileNameFull.c_str(),
245                                      cmLocalGenerator::HOME_OUTPUT,
246                                      cmLocalGenerator::MAKEFILE)
247     << "\n\n";
248 }
249
250 //----------------------------------------------------------------------------
251 std::string cmMakefileTargetGenerator::GetFlags(const std::string &l)
252 {
253   ByLanguageMap::iterator i = this->FlagsByLanguage.find(l);
254   if (i == this->FlagsByLanguage.end())
255     {
256     std::string flags;
257     const char *lang = l.c_str();
258
259     // Add language feature flags.
260     this->AddFeatureFlags(flags, lang);
261
262     this->LocalGenerator->AddArchitectureFlags(flags, this->Target,
263                                                lang, this->ConfigName);
264
265     // Fortran-specific flags computed for this target.
266     if(l == "Fortran")
267       {
268       this->AddFortranFlags(flags);
269       }
270
271     this->LocalGenerator->AddCMP0018Flags(flags, this->Target, lang);
272
273     // Add include directory flags.
274     this->AddIncludeFlags(flags, lang);
275
276     // Append old-style preprocessor definition flags.
277     this->LocalGenerator->
278       AppendFlags(flags, this->Makefile->GetDefineFlags());
279
280     // Add include directory flags.
281     this->LocalGenerator->
282       AppendFlags(flags,this->GetFrameworkFlags().c_str());
283
284     ByLanguageMap::value_type entry(l, flags);
285     i = this->FlagsByLanguage.insert(entry).first;
286     }
287   return i->second;
288 }
289
290 std::string cmMakefileTargetGenerator::GetDefines(const std::string &l)
291 {
292   ByLanguageMap::iterator i = this->DefinesByLanguage.find(l);
293   if (i == this->DefinesByLanguage.end())
294     {
295     std::string defines;
296     const char *lang = l.c_str();
297     // Add the export symbol definition for shared library objects.
298     if(const char* exportMacro = this->Target->GetExportMacro())
299       {
300       this->LocalGenerator->AppendDefines(defines, exportMacro, lang);
301       }
302
303     // Add preprocessor definitions for this target and configuration.
304     this->LocalGenerator->AppendDefines
305       (defines, this->Makefile->GetProperty("COMPILE_DEFINITIONS"), lang);
306     this->LocalGenerator->AppendDefines
307       (defines, this->Target->GetProperty("COMPILE_DEFINITIONS"), lang);
308     std::string defPropName = "COMPILE_DEFINITIONS_";
309     defPropName +=
310       cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
311     this->LocalGenerator->AppendDefines
312       (defines, this->Makefile->GetProperty(defPropName.c_str()), lang);
313     this->LocalGenerator->AppendDefines
314       (defines, this->Target->GetProperty(defPropName.c_str()), lang);
315
316     ByLanguageMap::value_type entry(l, defines);
317     i = this->DefinesByLanguage.insert(entry).first;
318     }
319   return i->second;
320 }
321
322 void cmMakefileTargetGenerator::WriteTargetLanguageFlags()
323 {
324   // write language flags for target
325   std::set<cmStdString> languages;
326   this->Target->GetLanguages(languages);
327     // put the compiler in the rules.make file so that if it changes
328   // things rebuild
329   for(std::set<cmStdString>::const_iterator l = languages.begin();
330       l != languages.end(); ++l)
331     {
332     cmStdString compiler = "CMAKE_";
333     compiler += *l;
334     compiler += "_COMPILER";
335     *this->FlagFileStream << "# compile " << l->c_str() << " with " <<
336       this->Makefile->GetSafeDefinition(compiler.c_str()) << "\n";
337     }
338
339   for(std::set<cmStdString>::const_iterator l = languages.begin();
340       l != languages.end(); ++l)
341     {
342     *this->FlagFileStream << *l << "_FLAGS = " << this->GetFlags(*l) << "\n\n";
343     *this->FlagFileStream << *l << "_DEFINES = " << this->GetDefines(*l) <<
344       "\n\n";
345     }
346
347   // Add target-specific flags.
348   if(this->Target->GetProperty("COMPILE_FLAGS"))
349     {
350     std::string flags;
351     this->LocalGenerator->AppendFlags
352       (flags, this->Target->GetProperty("COMPILE_FLAGS"));
353     *this->FlagFileStream << "# TARGET_FLAGS = " << flags << "\n\n";
354     }
355 }
356
357
358 //----------------------------------------------------------------------------
359 void
360 cmMakefileTargetGenerator::MacOSXContentGeneratorType::operator()
361   (cmSourceFile& source, const char* pkgloc)
362 {
363   // Skip OS X content when not building a Framework or Bundle.
364   if(this->Generator->MacContentDirectory.empty())
365     {
366     return;
367     }
368
369   std::string macdir =
370     this->Generator->OSXBundleGenerator->InitMacOSXContentDirectory(pkgloc);
371
372   // Get the input file location.
373   std::string input = source.GetFullPath();
374
375   // Get the output file location.
376   std::string output = macdir;
377   output += "/";
378   output += cmSystemTools::GetFilenameName(input);
379   this->Generator->CleanFiles.push_back(
380     this->Generator->Convert(output.c_str(),
381                              cmLocalGenerator::START_OUTPUT));
382   output = this->Generator->Convert(output.c_str(),
383                                     cmLocalGenerator::HOME_OUTPUT);
384
385   // Create a rule to copy the content into the bundle.
386   std::vector<std::string> depends;
387   std::vector<std::string> commands;
388   depends.push_back(input);
389   std::string copyEcho = "Copying OS X content ";
390   copyEcho += output;
391   this->Generator->LocalGenerator->AppendEcho(
392     commands, copyEcho.c_str(),
393     cmLocalUnixMakefileGenerator3::EchoBuild);
394   std::string copyCommand = "$(CMAKE_COMMAND) -E copy ";
395   copyCommand += this->Generator->Convert(input.c_str(),
396                                           cmLocalGenerator::NONE,
397                                           cmLocalGenerator::SHELL);
398   copyCommand += " ";
399   copyCommand += this->Generator->Convert(output.c_str(),
400                                           cmLocalGenerator::NONE,
401                                           cmLocalGenerator::SHELL);
402   commands.push_back(copyCommand);
403   this->Generator->LocalGenerator->WriteMakeRule(
404     *this->Generator->BuildFileStream, 0,
405     output.c_str(),
406     depends, commands, false);
407   this->Generator->ExtraFiles.insert(output);
408 }
409
410 //----------------------------------------------------------------------------
411 void cmMakefileTargetGenerator::WriteObjectRuleFiles(cmSourceFile& source)
412 {
413   // Identify the language of the source file.
414   const char* lang = this->LocalGenerator->GetSourceFileLanguage(source);
415   if(!lang)
416     {
417     // don't know anything about this file so skip it
418     return;
419     }
420
421   // Get the full path name of the object file.
422   std::string const& objectName = this->GeneratorTarget->Objects[&source];
423   std::string obj = this->LocalGenerator->GetTargetDirectory(*this->Target);
424   obj += "/";
425   obj += objectName;
426
427   // Avoid generating duplicate rules.
428   if(this->ObjectFiles.find(obj) == this->ObjectFiles.end())
429     {
430     this->ObjectFiles.insert(obj);
431     }
432   else
433     {
434     cmOStringStream err;
435     err << "Warning: Source file \""
436         << source.GetFullPath()
437         << "\" is listed multiple times for target \""
438         << this->Target->GetName()
439         << "\".";
440     cmSystemTools::Message(err.str().c_str(), "Warning");
441     return;
442     }
443
444   // Create the directory containing the object file.  This may be a
445   // subdirectory under the target's directory.
446   std::string dir = cmSystemTools::GetFilenamePath(obj.c_str());
447   cmSystemTools::MakeDirectory
448     (this->LocalGenerator->ConvertToFullPath(dir).c_str());
449
450   // Save this in the target's list of object files.
451   this->Objects.push_back(obj);
452   this->CleanFiles.push_back(obj);
453
454   // TODO: Remove
455   //std::string relativeObj
456   //= this->LocalGenerator->GetHomeRelativeOutputPath();
457   //relativeObj += obj;
458
459   // we compute some depends when writing the depend.make that we will also
460   // use in the build.make, same with depMakeFile
461   std::vector<std::string> depends;
462   std::string depMakeFile;
463
464   // generate the build rule file
465   this->WriteObjectBuildFile(obj, lang, source, depends);
466
467   // The object file should be checked for dependency integrity.
468   std::string objFullPath = this->Makefile->GetCurrentOutputDirectory();
469   objFullPath += "/";
470   objFullPath += obj;
471   objFullPath =
472     this->Convert(objFullPath.c_str(), cmLocalGenerator::FULL);
473   std::string srcFullPath =
474     this->Convert(source.GetFullPath().c_str(), cmLocalGenerator::FULL);
475   this->LocalGenerator->
476     AddImplicitDepends(*this->Target, lang,
477                        objFullPath.c_str(),
478                        srcFullPath.c_str());
479 }
480
481 //----------------------------------------------------------------------------
482 void
483 cmMakefileTargetGenerator
484 ::AppendFortranFormatFlags(std::string& flags, cmSourceFile& source)
485 {
486   const char* srcfmt = source.GetProperty("Fortran_FORMAT");
487   cmLocalGenerator::FortranFormat format =
488     this->LocalGenerator->GetFortranFormat(srcfmt);
489   if(format == cmLocalGenerator::FortranFormatNone)
490     {
491     const char* tgtfmt = this->Target->GetProperty("Fortran_FORMAT");
492     format = this->LocalGenerator->GetFortranFormat(tgtfmt);
493     }
494   const char* var = 0;
495   switch (format)
496     {
497     case cmLocalGenerator::FortranFormatFixed:
498       var = "CMAKE_Fortran_FORMAT_FIXED_FLAG"; break;
499     case cmLocalGenerator::FortranFormatFree:
500       var = "CMAKE_Fortran_FORMAT_FREE_FLAG"; break;
501     default: break;
502     }
503   if(var)
504     {
505     this->LocalGenerator->AppendFlags(
506       flags, this->Makefile->GetDefinition(var));
507     }
508 }
509
510 //----------------------------------------------------------------------------
511 void
512 cmMakefileTargetGenerator
513 ::WriteObjectBuildFile(std::string &obj,
514                        const char *lang,
515                        cmSourceFile& source,
516                        std::vector<std::string>& depends)
517 {
518   this->LocalGenerator->AppendRuleDepend(depends,
519                                          this->FlagFileNameFull.c_str());
520   this->LocalGenerator->AppendRuleDepends(depends,
521                                           this->FlagFileDepends[lang]);
522
523   // generate the depend scanning rule
524   this->WriteObjectDependRules(source, depends);
525
526   std::string relativeObj = this->LocalGenerator->GetHomeRelativeOutputPath();
527   relativeObj += obj;
528   // Write the build rule.
529
530   // Build the set of compiler flags.
531   std::string flags;
532
533   // Add language-specific flags.
534   std::string langFlags = "$(";
535   langFlags += lang;
536   langFlags += "_FLAGS)";
537   this->LocalGenerator->AppendFlags(flags, langFlags.c_str());
538
539   // Add target-specific flags.
540   if(this->Target->GetProperty("COMPILE_FLAGS"))
541     {
542     std::string langIncludeExpr = "CMAKE_";
543     langIncludeExpr += lang;
544     langIncludeExpr += "_FLAG_REGEX";
545     const char* regex = this->Makefile->
546       GetDefinition(langIncludeExpr.c_str());
547     if(regex)
548       {
549       cmsys::RegularExpression r(regex);
550       std::vector<std::string> args;
551       cmSystemTools::ParseWindowsCommandLine(
552         this->Target->GetProperty("COMPILE_FLAGS"),
553         args);
554       for(std::vector<std::string>::iterator i = args.begin();
555           i != args.end(); ++i)
556         {
557         if(r.find(i->c_str()))
558           {
559           this->LocalGenerator->AppendFlags
560             (flags, i->c_str());
561           }
562         }
563       }
564     else
565       {
566       this->LocalGenerator->AppendFlags
567         (flags, this->Target->GetProperty("COMPILE_FLAGS"));
568       }
569     }
570
571   // Add Fortran format flags.
572   if(strcmp(lang, "Fortran") == 0)
573     {
574     this->AppendFortranFormatFlags(flags, source);
575     }
576
577   // Add flags from source file properties.
578   if (source.GetProperty("COMPILE_FLAGS"))
579     {
580     this->LocalGenerator->AppendFlags
581       (flags, source.GetProperty("COMPILE_FLAGS"));
582     *this->FlagFileStream << "# Custom flags: "
583                           << relativeObj << "_FLAGS = "
584                           << source.GetProperty("COMPILE_FLAGS")
585                           << "\n"
586                           << "\n";
587     }
588
589   // Add language-specific defines.
590   std::string defines = "$(";
591   defines += lang;
592   defines += "_DEFINES)";
593
594   // Add source-sepcific preprocessor definitions.
595   if(const char* compile_defs = source.GetProperty("COMPILE_DEFINITIONS"))
596     {
597     this->LocalGenerator->AppendDefines(defines, compile_defs, lang);
598     *this->FlagFileStream << "# Custom defines: "
599                           << relativeObj << "_DEFINES = "
600                           << compile_defs << "\n"
601                           << "\n";
602     }
603   std::string configUpper =
604     cmSystemTools::UpperCase(this->LocalGenerator->ConfigurationName);
605   std::string defPropName = "COMPILE_DEFINITIONS_";
606   defPropName += configUpper;
607   if(const char* config_compile_defs =
608      source.GetProperty(defPropName.c_str()))
609     {
610     this->LocalGenerator->AppendDefines(defines, config_compile_defs, lang);
611     *this->FlagFileStream
612       << "# Custom defines: "
613       << relativeObj << "_DEFINES_" << configUpper
614       << " = " << config_compile_defs << "\n"
615       << "\n";
616     }
617
618   // Get the output paths for source and object files.
619   std::string sourceFile = source.GetFullPath();
620   if(this->LocalGenerator->UseRelativePaths)
621     {
622     sourceFile = this->Convert(sourceFile.c_str(),
623                                cmLocalGenerator::START_OUTPUT);
624     }
625   sourceFile = this->Convert(sourceFile.c_str(),
626                              cmLocalGenerator::NONE,
627                              cmLocalGenerator::SHELL);
628
629   // Construct the build message.
630   std::vector<std::string> no_commands;
631   std::vector<std::string> commands;
632
633   // add in a progress call if needed
634   this->AppendProgress(commands);
635
636   if(!this->NoRuleMessages)
637     {
638     std::string buildEcho = "Building ";
639     buildEcho += lang;
640     buildEcho += " object ";
641     buildEcho += relativeObj;
642     this->LocalGenerator->AppendEcho
643       (commands, buildEcho.c_str(), cmLocalUnixMakefileGenerator3::EchoBuild);
644     }
645
646   std::string targetOutPathPDB;
647   {
648   std::string targetFullPathPDB;
649   if(this->Target->GetType() == cmTarget::EXECUTABLE ||
650      this->Target->GetType() == cmTarget::STATIC_LIBRARY ||
651      this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
652      this->Target->GetType() == cmTarget::MODULE_LIBRARY)
653     {
654     targetFullPathPDB = this->Target->GetDirectory(this->ConfigName);
655     targetFullPathPDB += "/";
656     targetFullPathPDB += this->Target->GetPDBName(this->ConfigName);
657     }
658   targetOutPathPDB =
659     this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
660                   cmLocalGenerator::SHELL);
661   }
662   cmLocalGenerator::RuleVariables vars;
663   vars.RuleLauncher = "RULE_LAUNCH_COMPILE";
664   vars.CMTarget = this->Target;
665   vars.Language = lang;
666   vars.TargetPDB = targetOutPathPDB.c_str();
667   vars.Source = sourceFile.c_str();
668   std::string shellObj =
669     this->Convert(obj.c_str(),
670                   cmLocalGenerator::NONE,
671                   cmLocalGenerator::SHELL).c_str();
672   vars.Object = shellObj.c_str();
673   std::string objectDir = cmSystemTools::GetFilenamePath(obj);
674   objectDir = this->Convert(objectDir.c_str(),
675                             cmLocalGenerator::START_OUTPUT,
676                             cmLocalGenerator::SHELL);
677   vars.ObjectDir = objectDir.c_str();
678   vars.Flags = flags.c_str();
679   vars.Defines = defines.c_str();
680
681   bool lang_is_c_or_cxx = ((strcmp(lang, "C") == 0) ||
682                            (strcmp(lang, "CXX") == 0));
683
684   // Construct the compile rules.
685   {
686   std::string compileRuleVar = "CMAKE_";
687   compileRuleVar += lang;
688   compileRuleVar += "_COMPILE_OBJECT";
689   std::string compileRule =
690     this->Makefile->GetRequiredDefinition(compileRuleVar.c_str());
691   std::vector<std::string> compileCommands;
692   cmSystemTools::ExpandListArgument(compileRule, compileCommands);
693
694   if (this->Makefile->IsOn("CMAKE_EXPORT_COMPILE_COMMANDS") &&
695       lang_is_c_or_cxx && compileCommands.size() == 1)
696     {
697     std::string compileCommand = compileCommands[0];
698     this->LocalGenerator->ExpandRuleVariables(compileCommand, vars);
699     std::string workingDirectory =
700       this->LocalGenerator->Convert(
701         this->Makefile->GetStartOutputDirectory(), cmLocalGenerator::FULL);
702     compileCommand.replace(compileCommand.find(langFlags),
703                            langFlags.size(), this->GetFlags(lang));
704     std::string langDefines = std::string("$(") + lang + "_DEFINES)";
705     compileCommand.replace(compileCommand.find(langDefines),
706                            langDefines.size(), this->GetDefines(lang));
707     this->GlobalGenerator->AddCXXCompileCommand(
708       source.GetFullPath(), workingDirectory, compileCommand);
709     }
710
711   // Expand placeholders in the commands.
712   for(std::vector<std::string>::iterator i = compileCommands.begin();
713       i != compileCommands.end(); ++i)
714     {
715     this->LocalGenerator->ExpandRuleVariables(*i, vars);
716     }
717
718   // Change the command working directory to the local build tree.
719   this->LocalGenerator->CreateCDCommand
720     (compileCommands,
721      this->Makefile->GetStartOutputDirectory(),
722      cmLocalGenerator::HOME_OUTPUT);
723   commands.insert(commands.end(),
724                   compileCommands.begin(), compileCommands.end());
725   }
726
727   // Write the rule.
728   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
729                                       relativeObj.c_str(),
730                                       depends, commands, false);
731
732   // Check for extra outputs created by the compilation.
733   if(const char* extra_outputs_str =
734      source.GetProperty("OBJECT_OUTPUTS"))
735     {
736     std::vector<std::string> extra_outputs;
737     cmSystemTools::ExpandListArgument(extra_outputs_str, extra_outputs);
738     for(std::vector<std::string>::const_iterator eoi = extra_outputs.begin();
739         eoi != extra_outputs.end(); ++eoi)
740       {
741       // Register this as an extra output for the object file rule.
742       // This will cause the object file to be rebuilt if the extra
743       // output is missing.
744       this->GenerateExtraOutput(eoi->c_str(), relativeObj.c_str(), false);
745
746       // Register this as an extra file to clean.
747       this->CleanFiles.push_back(eoi->c_str());
748       }
749     }
750
751   bool do_preprocess_rules = lang_is_c_or_cxx &&
752     this->LocalGenerator->GetCreatePreprocessedSourceRules();
753   bool do_assembly_rules = lang_is_c_or_cxx &&
754     this->LocalGenerator->GetCreateAssemblySourceRules();
755   if(do_preprocess_rules || do_assembly_rules)
756     {
757     std::vector<std::string> force_depends;
758     force_depends.push_back("cmake_force");
759     std::string::size_type dot_pos = relativeObj.rfind(".");
760     std::string relativeObjBase = relativeObj.substr(0, dot_pos);
761     dot_pos = obj.rfind(".");
762     std::string objBase = obj.substr(0, dot_pos);
763
764     if(do_preprocess_rules)
765       {
766       commands.clear();
767       std::string relativeObjI = relativeObjBase + ".i";
768       std::string objI = objBase + ".i";
769
770       std::string preprocessEcho = "Preprocessing ";
771       preprocessEcho += lang;
772       preprocessEcho += " source to ";
773       preprocessEcho += objI;
774       this->LocalGenerator->AppendEcho(
775         commands, preprocessEcho.c_str(),
776         cmLocalUnixMakefileGenerator3::EchoBuild
777         );
778
779       std::string preprocessRuleVar = "CMAKE_";
780       preprocessRuleVar += lang;
781       preprocessRuleVar += "_CREATE_PREPROCESSED_SOURCE";
782       if(const char* preprocessRule =
783          this->Makefile->GetDefinition(preprocessRuleVar.c_str()))
784         {
785         std::vector<std::string> preprocessCommands;
786         cmSystemTools::ExpandListArgument(preprocessRule, preprocessCommands);
787
788         std::string shellObjI =
789           this->Convert(objI.c_str(),
790                         cmLocalGenerator::NONE,
791                         cmLocalGenerator::SHELL).c_str();
792         vars.PreprocessedSource = shellObjI.c_str();
793
794         // Expand placeholders in the commands.
795         for(std::vector<std::string>::iterator i = preprocessCommands.begin();
796             i != preprocessCommands.end(); ++i)
797           {
798           this->LocalGenerator->ExpandRuleVariables(*i, vars);
799           }
800
801         this->LocalGenerator->CreateCDCommand
802           (preprocessCommands,
803            this->Makefile->GetStartOutputDirectory(),
804            cmLocalGenerator::HOME_OUTPUT);
805         commands.insert(commands.end(),
806                         preprocessCommands.begin(),
807                         preprocessCommands.end());
808         }
809       else
810         {
811         std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
812         cmd += preprocessRuleVar;
813         commands.push_back(cmd);
814         }
815
816       this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
817                                           relativeObjI.c_str(),
818                                           force_depends, commands, false);
819       }
820
821     if(do_assembly_rules)
822       {
823       commands.clear();
824       std::string relativeObjS = relativeObjBase + ".s";
825       std::string objS = objBase + ".s";
826
827       std::string assemblyEcho = "Compiling ";
828       assemblyEcho += lang;
829       assemblyEcho += " source to assembly ";
830       assemblyEcho += objS;
831       this->LocalGenerator->AppendEcho(
832         commands, assemblyEcho.c_str(),
833         cmLocalUnixMakefileGenerator3::EchoBuild
834         );
835
836       std::string assemblyRuleVar = "CMAKE_";
837       assemblyRuleVar += lang;
838       assemblyRuleVar += "_CREATE_ASSEMBLY_SOURCE";
839       if(const char* assemblyRule =
840          this->Makefile->GetDefinition(assemblyRuleVar.c_str()))
841         {
842         std::vector<std::string> assemblyCommands;
843         cmSystemTools::ExpandListArgument(assemblyRule, assemblyCommands);
844
845         std::string shellObjS =
846           this->Convert(objS.c_str(),
847                         cmLocalGenerator::NONE,
848                         cmLocalGenerator::SHELL).c_str();
849         vars.AssemblySource = shellObjS.c_str();
850
851         // Expand placeholders in the commands.
852         for(std::vector<std::string>::iterator i = assemblyCommands.begin();
853             i != assemblyCommands.end(); ++i)
854           {
855           this->LocalGenerator->ExpandRuleVariables(*i, vars);
856           }
857
858         this->LocalGenerator->CreateCDCommand
859           (assemblyCommands,
860            this->Makefile->GetStartOutputDirectory(),
861            cmLocalGenerator::HOME_OUTPUT);
862         commands.insert(commands.end(),
863                         assemblyCommands.begin(),
864                         assemblyCommands.end());
865         }
866       else
867         {
868         std::string cmd = "$(CMAKE_COMMAND) -E cmake_unimplemented_variable ";
869         cmd += assemblyRuleVar;
870         commands.push_back(cmd);
871         }
872
873       this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
874                                           relativeObjS.c_str(),
875                                           force_depends, commands, false);
876       }
877     }
878
879   // If the language needs provides-requires mode, create the
880   // corresponding targets.
881   std::string objectRequires = relativeObj;
882   objectRequires += ".requires";
883   std::vector<std::string> p_depends;
884   // always provide an empty requires target
885   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
886                                       objectRequires.c_str(), p_depends,
887                                       no_commands, true);
888
889   // write a build rule to recursively build what this obj provides
890   std::string objectProvides = relativeObj;
891   objectProvides += ".provides";
892   std::string temp = relativeObj;
893   temp += ".provides.build";
894   std::vector<std::string> r_commands;
895   std::string tgtMakefileName =
896     this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
897   tgtMakefileName += "/build.make";
898   r_commands.push_back
899     (this->LocalGenerator->GetRecursiveMakeCall(tgtMakefileName.c_str(),
900                                                 temp.c_str()));
901
902   p_depends.clear();
903   p_depends.push_back(objectRequires);
904   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
905                                       objectProvides.c_str(), p_depends,
906                                       r_commands, true);
907
908   // write the provides.build rule dependency on the obj file
909   p_depends.clear();
910   p_depends.push_back(relativeObj);
911   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
912                                       temp.c_str(), p_depends, no_commands,
913                                       false);
914 }
915
916 //----------------------------------------------------------------------------
917 void cmMakefileTargetGenerator::WriteTargetRequiresRules()
918 {
919   std::vector<std::string> depends;
920   std::vector<std::string> no_commands;
921
922   // Construct the name of the dependency generation target.
923   std::string depTarget =
924     this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
925   depTarget += "/requires";
926
927   // This target drives dependency generation for all object files.
928   std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
929   std::string objTarget;
930   for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
931       obj != this->Objects.end(); ++obj)
932     {
933     objTarget = relPath;
934     objTarget += *obj;
935     objTarget += ".requires";
936     depends.push_back(objTarget);
937     }
938
939   // Write the rule.
940   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
941                                       depTarget.c_str(),
942                                       depends, no_commands, true);
943 }
944
945 //----------------------------------------------------------------------------
946 void cmMakefileTargetGenerator::WriteTargetCleanRules()
947 {
948   std::vector<std::string> depends;
949   std::vector<std::string> commands;
950
951   // Construct the clean target name.
952   std::string cleanTarget =
953     this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
954   cleanTarget += "/clean";
955
956   // Construct the clean command.
957   this->LocalGenerator->AppendCleanCommand(commands, this->CleanFiles,
958                                            *this->Target);
959   this->LocalGenerator->CreateCDCommand
960     (commands,
961      this->Makefile->GetStartOutputDirectory(),
962      cmLocalGenerator::HOME_OUTPUT);
963
964   // Write the rule.
965   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
966                                       cleanTarget.c_str(),
967                                       depends, commands, true);
968 }
969
970
971 //----------------------------------------------------------------------------
972 void cmMakefileTargetGenerator::WriteTargetDependRules()
973 {
974   // must write the targets depend info file
975   std::string dir = this->LocalGenerator->GetTargetDirectory(*this->Target);
976   this->InfoFileNameFull = dir;
977   this->InfoFileNameFull += "/DependInfo.cmake";
978   this->InfoFileNameFull =
979     this->LocalGenerator->ConvertToFullPath(this->InfoFileNameFull);
980   this->InfoFileStream =
981     new cmGeneratedFileStream(this->InfoFileNameFull.c_str());
982   this->InfoFileStream->SetCopyIfDifferent(true);
983   if(!*this->InfoFileStream)
984     {
985     return;
986     }
987   this->LocalGenerator->
988     WriteDependLanguageInfo(*this->InfoFileStream,*this->Target);
989
990   // Store multiple output pairs in the depend info file.
991   if(!this->MultipleOutputPairs.empty())
992     {
993     *this->InfoFileStream
994       << "\n"
995       << "# Pairs of files generated by the same build rule.\n"
996       << "SET(CMAKE_MULTIPLE_OUTPUT_PAIRS\n";
997     for(MultipleOutputPairsType::const_iterator pi =
998           this->MultipleOutputPairs.begin();
999         pi != this->MultipleOutputPairs.end(); ++pi)
1000       {
1001       *this->InfoFileStream
1002         << "  " << this->LocalGenerator->EscapeForCMake(pi->first.c_str())
1003         << " "  << this->LocalGenerator->EscapeForCMake(pi->second.c_str())
1004         << "\n";
1005       }
1006     *this->InfoFileStream << "  )\n\n";
1007     }
1008
1009   // Store list of targets linked directly or transitively.
1010   {
1011   *this->InfoFileStream
1012     << "\n"
1013     << "# Targets to which this target links.\n"
1014     << "SET(CMAKE_TARGET_LINKED_INFO_FILES\n";
1015   std::set<cmTarget const*> emitted;
1016   const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1017   if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1018     {
1019     cmComputeLinkInformation::ItemVector const& items = cli->GetItems();
1020     for(cmComputeLinkInformation::ItemVector::const_iterator
1021           i = items.begin(); i != items.end(); ++i)
1022       {
1023       cmTarget const* linkee = i->Target;
1024       if(linkee && !linkee->IsImported() && emitted.insert(linkee).second)
1025         {
1026         cmMakefile* mf = linkee->GetMakefile();
1027         cmLocalGenerator* lg = mf->GetLocalGenerator();
1028         std::string di = mf->GetStartOutputDirectory();
1029         di += "/";
1030         di += lg->GetTargetDirectory(*linkee);
1031         di += "/DependInfo.cmake";
1032         *this->InfoFileStream << "  \"" << di << "\"\n";
1033         }
1034       }
1035     }
1036   *this->InfoFileStream
1037     << "  )\n";
1038   }
1039
1040   // Check for a target-specific module output directory.
1041   if(const char* mdir = this->GetFortranModuleDirectory())
1042     {
1043     *this->InfoFileStream
1044       << "\n"
1045       << "# Fortran module output directory.\n"
1046       << "SET(CMAKE_Fortran_TARGET_MODULE_DIR \"" << mdir << "\")\n";
1047     }
1048
1049   // Target-specific include directories:
1050   *this->InfoFileStream
1051     << "\n"
1052     << "# The include file search paths:\n";
1053   *this->InfoFileStream
1054     << "SET(CMAKE_C_TARGET_INCLUDE_PATH\n";
1055   std::vector<std::string> includes;
1056   this->LocalGenerator->GetIncludeDirectories(includes, this->Target);
1057   for(std::vector<std::string>::iterator i = includes.begin();
1058       i != includes.end(); ++i)
1059     {
1060     *this->InfoFileStream
1061       << "  \""
1062       << this->LocalGenerator->Convert(i->c_str(),
1063                                        cmLocalGenerator::HOME_OUTPUT)
1064       << "\"\n";
1065     }
1066   *this->InfoFileStream
1067     << "  )\n";
1068   *this->InfoFileStream
1069     << "SET(CMAKE_CXX_TARGET_INCLUDE_PATH "
1070     << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1071   *this->InfoFileStream
1072     << "SET(CMAKE_Fortran_TARGET_INCLUDE_PATH "
1073     << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1074   *this->InfoFileStream
1075     << "SET(CMAKE_ASM_TARGET_INCLUDE_PATH "
1076     << "${CMAKE_C_TARGET_INCLUDE_PATH})\n";
1077
1078   // and now write the rule to use it
1079   std::vector<std::string> depends;
1080   std::vector<std::string> commands;
1081
1082   // Construct the name of the dependency generation target.
1083   std::string depTarget =
1084     this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1085   depTarget += "/depend";
1086
1087   // Add a command to call CMake to scan dependencies.  CMake will
1088   // touch the corresponding depends file after scanning dependencies.
1089   cmOStringStream depCmd;
1090   // TODO: Account for source file properties and directory-level
1091   // definitions when scanning for dependencies.
1092 #if !defined(_WIN32) || defined(__CYGWIN__)
1093   // This platform supports symlinks, so cmSystemTools will translate
1094   // paths.  Make sure PWD is set to the original name of the home
1095   // output directory to help cmSystemTools to create the same
1096   // translation table for the dependency scanning process.
1097   depCmd << "cd "
1098          << (this->LocalGenerator->Convert(
1099                this->Makefile->GetHomeOutputDirectory(),
1100                cmLocalGenerator::FULL, cmLocalGenerator::SHELL))
1101          << " && ";
1102 #endif
1103   // Generate a call this signature:
1104   //
1105   //   cmake -E cmake_depends <generator>
1106   //                          <home-src-dir> <start-src-dir>
1107   //                          <home-out-dir> <start-out-dir>
1108   //                          <dep-info> --color=$(COLOR)
1109   //
1110   // This gives the dependency scanner enough information to recreate
1111   // the state of our local generator sufficiently for its needs.
1112   depCmd << "$(CMAKE_COMMAND) -E cmake_depends \""
1113          << this->GlobalGenerator->GetName() << "\" "
1114          << this->Convert(this->Makefile->GetHomeDirectory(),
1115                           cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1116          << " "
1117          << this->Convert(this->Makefile->GetStartDirectory(),
1118                           cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1119          << " "
1120          << this->Convert(this->Makefile->GetHomeOutputDirectory(),
1121                           cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1122          << " "
1123          << this->Convert(this->Makefile->GetStartOutputDirectory(),
1124                           cmLocalGenerator::FULL, cmLocalGenerator::SHELL)
1125          << " "
1126          << this->Convert(this->InfoFileNameFull.c_str(),
1127                           cmLocalGenerator::FULL, cmLocalGenerator::SHELL);
1128   if(this->LocalGenerator->GetColorMakefile())
1129     {
1130     depCmd << " --color=$(COLOR)";
1131     }
1132   commands.push_back(depCmd.str());
1133
1134   // Make sure all custom command outputs in this target are built.
1135   if(this->CustomCommandDriver == OnDepends)
1136     {
1137     this->DriveCustomCommands(depends);
1138     }
1139
1140   // Write the rule.
1141   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1142                                       depTarget.c_str(),
1143                                       depends, commands, true);
1144 }
1145
1146 //----------------------------------------------------------------------------
1147 void
1148 cmMakefileTargetGenerator
1149 ::DriveCustomCommands(std::vector<std::string>& depends)
1150 {
1151   // Depend on all custom command outputs.
1152   const std::vector<cmSourceFile*>& sources =
1153     this->Target->GetSourceFiles();
1154   for(std::vector<cmSourceFile*>::const_iterator source = sources.begin();
1155       source != sources.end(); ++source)
1156     {
1157     if(cmCustomCommand* cc = (*source)->GetCustomCommand())
1158       {
1159       const std::vector<std::string>& outputs = cc->GetOutputs();
1160       for(std::vector<std::string>::const_iterator o = outputs.begin();
1161           o != outputs.end(); ++o)
1162         {
1163         depends.push_back(*o);
1164         }
1165       }
1166     }
1167 }
1168
1169 //----------------------------------------------------------------------------
1170 void cmMakefileTargetGenerator
1171 ::WriteObjectDependRules(cmSourceFile& source,
1172                          std::vector<std::string>& depends)
1173 {
1174   // Create the list of dependencies known at cmake time.  These are
1175   // shared between the object file and dependency scanning rule.
1176   depends.push_back(source.GetFullPath());
1177   if(const char* objectDeps = source.GetProperty("OBJECT_DEPENDS"))
1178     {
1179     std::vector<std::string> deps;
1180     cmSystemTools::ExpandListArgument(objectDeps, deps);
1181     for(std::vector<std::string>::iterator i = deps.begin();
1182         i != deps.end(); ++i)
1183       {
1184       depends.push_back(i->c_str());
1185       }
1186     }
1187 }
1188
1189 //----------------------------------------------------------------------------
1190 void cmMakefileTargetGenerator
1191 ::GenerateCustomRuleFile(const cmCustomCommand& cc)
1192 {
1193   // Collect the commands.
1194   std::vector<std::string> commands;
1195   std::string comment = this->LocalGenerator->ConstructComment(cc);
1196   if(!comment.empty())
1197     {
1198     // add in a progress call if needed
1199     this->AppendProgress(commands);
1200     if(!this->NoRuleMessages)
1201       {
1202       this->LocalGenerator
1203         ->AppendEcho(commands, comment.c_str(),
1204                      cmLocalUnixMakefileGenerator3::EchoGenerate);
1205       }
1206     }
1207
1208   // Now append the actual user-specified commands.
1209   cmOStringStream content;
1210   this->LocalGenerator->AppendCustomCommand(commands, cc, this->Target, false,
1211                                             cmLocalGenerator::HOME_OUTPUT,
1212                                             &content);
1213
1214   // Collect the dependencies.
1215   std::vector<std::string> depends;
1216   this->LocalGenerator->AppendCustomDepend(depends, cc);
1217
1218   // Check whether we need to bother checking for a symbolic output.
1219   bool need_symbolic = this->GlobalGenerator->GetNeedSymbolicMark();
1220
1221   // Write the rule.
1222   const std::vector<std::string>& outputs = cc.GetOutputs();
1223   std::vector<std::string>::const_iterator o = outputs.begin();
1224   {
1225   bool symbolic = false;
1226   if(need_symbolic)
1227     {
1228     if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1229       {
1230       symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1231       }
1232     }
1233   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1234                                       o->c_str(), depends, commands,
1235                                       symbolic);
1236
1237   // If the rule has changed make sure the output is rebuilt.
1238   if(!symbolic)
1239     {
1240     this->GlobalGenerator->AddRuleHash(cc.GetOutputs(), content.str());
1241     }
1242   }
1243
1244   // Write rules to drive building any outputs beyond the first.
1245   const char* in = o->c_str();
1246   for(++o; o != outputs.end(); ++o)
1247     {
1248     bool symbolic = false;
1249     if(need_symbolic)
1250       {
1251       if(cmSourceFile* sf = this->Makefile->GetSource(o->c_str()))
1252         {
1253         symbolic = sf->GetPropertyAsBool("SYMBOLIC");
1254         }
1255       }
1256     this->GenerateExtraOutput(o->c_str(), in, symbolic);
1257     }
1258
1259   // Setup implicit dependency scanning.
1260   for(cmCustomCommand::ImplicitDependsList::const_iterator
1261         idi = cc.GetImplicitDepends().begin();
1262       idi != cc.GetImplicitDepends().end(); ++idi)
1263     {
1264     std::string objFullPath =
1265       this->Convert(outputs[0].c_str(), cmLocalGenerator::FULL);
1266     std::string srcFullPath =
1267       this->Convert(idi->second.c_str(), cmLocalGenerator::FULL);
1268     this->LocalGenerator->
1269       AddImplicitDepends(*this->Target, idi->first.c_str(),
1270                          objFullPath.c_str(),
1271                          srcFullPath.c_str());
1272     }
1273 }
1274
1275 //----------------------------------------------------------------------------
1276 void
1277 cmMakefileTargetGenerator
1278 ::GenerateExtraOutput(const char* out, const char* in, bool symbolic)
1279 {
1280   // Add a rule to build the primary output if the extra output needs
1281   // to be created.
1282   std::vector<std::string> commands;
1283   std::vector<std::string> depends;
1284   std::string emptyCommand = this->GlobalGenerator->GetEmptyRuleHackCommand();
1285   if(!emptyCommand.empty())
1286     {
1287     commands.push_back(emptyCommand);
1288     }
1289   depends.push_back(in);
1290   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
1291                                       out, depends, commands,
1292                                       symbolic);
1293
1294   // Register the extra output as paired with the first output so that
1295   // the check-build-system step will remove the primary output if any
1296   // extra outputs are missing.  This forces the rule to regenerate
1297   // all outputs.
1298   this->AddMultipleOutputPair(out, in);
1299 }
1300
1301 //----------------------------------------------------------------------------
1302 void
1303 cmMakefileTargetGenerator::AppendProgress(std::vector<std::string>& commands)
1304 {
1305   this->NumberOfProgressActions++;
1306   if(this->NoRuleMessages)
1307     {
1308     return;
1309     }
1310   std::string progressDir = this->Makefile->GetHomeOutputDirectory();
1311   progressDir += cmake::GetCMakeFilesDirectory();
1312   cmOStringStream progCmd;
1313   progCmd << "$(CMAKE_COMMAND) -E cmake_progress_report ";
1314   progCmd << this->LocalGenerator->Convert(progressDir.c_str(),
1315                                            cmLocalGenerator::FULL,
1316                                            cmLocalGenerator::SHELL);
1317   progCmd << " $(CMAKE_PROGRESS_" << this->NumberOfProgressActions << ")";
1318   commands.push_back(progCmd.str());
1319 }
1320
1321 //----------------------------------------------------------------------------
1322 void
1323 cmMakefileTargetGenerator
1324 ::WriteObjectsVariable(std::string& variableName,
1325                        std::string& variableNameExternal)
1326 {
1327   // Write a make variable assignment that lists all objects for the
1328   // target.
1329   variableName =
1330     this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1331                                              "_OBJECTS");
1332   *this->BuildFileStream
1333     << "# Object files for target " << this->Target->GetName() << "\n"
1334     << variableName.c_str() << " =";
1335   std::string object;
1336   const char* objName =
1337     this->Makefile->GetDefinition("CMAKE_NO_QUOTED_OBJECTS");
1338   const char* lineContinue =
1339     this->Makefile->GetDefinition("CMAKE_MAKE_LINE_CONTINUE");
1340   if(!lineContinue)
1341     {
1342     lineContinue = "\\";
1343     }
1344   for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1345       i != this->Objects.end(); ++i)
1346     {
1347     *this->BuildFileStream << " " << lineContinue << "\n";
1348     if(objName)
1349       {
1350       *this->BuildFileStream <<
1351         this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1352                       cmLocalGenerator::MAKEFILE);
1353       }
1354     else
1355       {
1356       *this->BuildFileStream  <<
1357         this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1358       }
1359     }
1360   *this->BuildFileStream << "\n";
1361
1362   // Write a make variable assignment that lists all external objects
1363   // for the target.
1364   variableNameExternal =
1365     this->LocalGenerator->CreateMakeVariable(this->Target->GetName(),
1366                                              "_EXTERNAL_OBJECTS");
1367   *this->BuildFileStream
1368     << "\n"
1369     << "# External object files for target "
1370     << this->Target->GetName() << "\n"
1371     << variableNameExternal.c_str() << " =";
1372   for(std::vector<std::string>::const_iterator i =
1373         this->ExternalObjects.begin();
1374       i != this->ExternalObjects.end(); ++i)
1375     {
1376     object = this->Convert(i->c_str(),cmLocalGenerator::START_OUTPUT);
1377     *this->BuildFileStream
1378       << " " << lineContinue << "\n"
1379       << this->Makefile->GetSafeDefinition("CMAKE_OBJECT_NAME");
1380     if(objName)
1381       {
1382       *this->BuildFileStream  <<
1383         this->Convert(i->c_str(), cmLocalGenerator::START_OUTPUT,
1384                       cmLocalGenerator::MAKEFILE);
1385       }
1386     else
1387       {
1388       *this->BuildFileStream  <<
1389         this->LocalGenerator->ConvertToQuotedOutputPath(i->c_str());
1390       }
1391     }
1392   *this->BuildFileStream << "\n" << "\n";
1393 }
1394
1395 //----------------------------------------------------------------------------
1396 void
1397 cmMakefileTargetGenerator
1398 ::WriteObjectsString(std::string& buildObjs)
1399 {
1400   std::vector<std::string> objStrings;
1401   this->WriteObjectsStrings(objStrings);
1402   buildObjs = objStrings[0];
1403 }
1404
1405 //----------------------------------------------------------------------------
1406 class cmMakefileTargetGeneratorObjectStrings
1407 {
1408 public:
1409   cmMakefileTargetGeneratorObjectStrings(std::vector<std::string>& strings,
1410                                          cmLocalUnixMakefileGenerator3* lg,
1411                                          std::string::size_type limit):
1412     Strings(strings), LocalGenerator(lg), LengthLimit(limit)
1413     {
1414     this->Space = "";
1415     }
1416   void Feed(std::string const& obj)
1417     {
1418     // Construct the name of the next object.
1419     this->NextObject =
1420       this->LocalGenerator->Convert(obj.c_str(),
1421                                     cmLocalGenerator::START_OUTPUT,
1422                                     cmLocalGenerator::RESPONSE);
1423
1424     // Roll over to next string if the limit will be exceeded.
1425     if(this->LengthLimit != std::string::npos &&
1426        (this->CurrentString.length() + 1 + this->NextObject.length()
1427         > this->LengthLimit))
1428       {
1429       this->Strings.push_back(this->CurrentString);
1430       this->CurrentString = "";
1431       this->Space = "";
1432       }
1433
1434     // Separate from previous object.
1435     this->CurrentString += this->Space;
1436     this->Space = " ";
1437
1438     // Append this object.
1439     this->CurrentString += this->NextObject;
1440     }
1441   void Done()
1442     {
1443     this->Strings.push_back(this->CurrentString);
1444     }
1445 private:
1446   std::vector<std::string>& Strings;
1447   cmLocalUnixMakefileGenerator3* LocalGenerator;
1448   std::string::size_type LengthLimit;
1449   std::string CurrentString;
1450   std::string NextObject;
1451   const char* Space;
1452 };
1453
1454 //----------------------------------------------------------------------------
1455 void
1456 cmMakefileTargetGenerator
1457 ::WriteObjectsStrings(std::vector<std::string>& objStrings,
1458                       std::string::size_type limit)
1459 {
1460   cmMakefileTargetGeneratorObjectStrings
1461     helper(objStrings, this->LocalGenerator, limit);
1462   for(std::vector<std::string>::const_iterator i = this->Objects.begin();
1463       i != this->Objects.end(); ++i)
1464     {
1465     helper.Feed(*i);
1466     }
1467   for(std::vector<std::string>::const_iterator i =
1468         this->ExternalObjects.begin();
1469       i != this->ExternalObjects.end(); ++i)
1470     {
1471     helper.Feed(*i);
1472     }
1473   helper.Done();
1474 }
1475
1476 //----------------------------------------------------------------------------
1477 void cmMakefileTargetGenerator::WriteTargetDriverRule(const char* main_output,
1478                                                       bool relink)
1479 {
1480   // Compute the name of the driver target.
1481   std::string dir =
1482     this->LocalGenerator->GetRelativeTargetDirectory(*this->Target);
1483   std::string buildTargetRuleName = dir;
1484   buildTargetRuleName += relink?"/preinstall":"/build";
1485   buildTargetRuleName = this->Convert(buildTargetRuleName.c_str(),
1486                                       cmLocalGenerator::HOME_OUTPUT,
1487                                       cmLocalGenerator::UNCHANGED);
1488
1489   // Build the list of target outputs to drive.
1490   std::vector<std::string> depends;
1491   if(main_output)
1492     {
1493     depends.push_back(main_output);
1494     }
1495
1496   const char* comment = 0;
1497   if(relink)
1498     {
1499     // Setup the comment for the preinstall driver.
1500     comment = "Rule to relink during preinstall.";
1501     }
1502   else
1503     {
1504     // Setup the comment for the main build driver.
1505     comment = "Rule to build all files generated by this target.";
1506
1507     // Make sure all custom command outputs in this target are built.
1508     if(this->CustomCommandDriver == OnBuild)
1509       {
1510       this->DriveCustomCommands(depends);
1511       }
1512
1513     // Make sure the extra files are built.
1514     for(std::set<cmStdString>::const_iterator i = this->ExtraFiles.begin();
1515         i != this->ExtraFiles.end(); ++i)
1516       {
1517       depends.push_back(*i);
1518       }
1519     }
1520
1521   // Write the driver rule.
1522   std::vector<std::string> no_commands;
1523   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, comment,
1524                                       buildTargetRuleName.c_str(),
1525                                       depends, no_commands, true);
1526 }
1527
1528 //----------------------------------------------------------------------------
1529 std::string cmMakefileTargetGenerator::GetFrameworkFlags()
1530 {
1531  if(!this->Makefile->IsOn("APPLE"))
1532    {
1533    return std::string();
1534    }
1535
1536  std::set<cmStdString> emitted;
1537 #ifdef __APPLE__  /* don't insert this when crosscompiling e.g. to iphone */
1538   emitted.insert("/System/Library/Frameworks");
1539 #endif
1540   std::vector<std::string> includes;
1541   this->LocalGenerator->GetIncludeDirectories(includes, this->Target);
1542   std::vector<std::string>::iterator i;
1543   // check all include directories for frameworks as this
1544   // will already have added a -F for the framework
1545   for(i = includes.begin(); i != includes.end(); ++i)
1546     {
1547     if(this->Target->NameResolvesToFramework(i->c_str()))
1548       {
1549       std::string frameworkDir = *i;
1550       frameworkDir += "/../";
1551       frameworkDir = cmSystemTools::CollapseFullPath(frameworkDir.c_str());
1552       emitted.insert(frameworkDir);
1553       }
1554     }
1555
1556   std::string flags;
1557   std::vector<std::string>& frameworks = this->Target->GetFrameworks();
1558   for(i = frameworks.begin();
1559       i != frameworks.end(); ++i)
1560     {
1561     if(emitted.insert(*i).second)
1562       {
1563       flags += "-F";
1564       flags += this->Convert(i->c_str(),
1565                              cmLocalGenerator::START_OUTPUT,
1566                              cmLocalGenerator::SHELL, true);
1567       flags += " ";
1568       }
1569     }
1570   return flags;
1571 }
1572
1573 //----------------------------------------------------------------------------
1574 void cmMakefileTargetGenerator
1575 ::AppendTargetDepends(std::vector<std::string>& depends)
1576 {
1577   // Static libraries never depend on anything for linking.
1578   if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
1579     {
1580     return;
1581     }
1582
1583   // Loop over all library dependencies.
1584   const char* cfg = this->LocalGenerator->ConfigurationName.c_str();
1585   if(cmComputeLinkInformation* cli = this->Target->GetLinkInformation(cfg))
1586     {
1587     std::vector<std::string> const& libDeps = cli->GetDepends();
1588     for(std::vector<std::string>::const_iterator j = libDeps.begin();
1589         j != libDeps.end(); ++j)
1590       {
1591       depends.push_back(*j);
1592       }
1593     }
1594 }
1595
1596 //----------------------------------------------------------------------------
1597 void cmMakefileTargetGenerator
1598 ::AppendObjectDepends(std::vector<std::string>& depends)
1599 {
1600   // Add dependencies on the compiled object files.
1601   std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
1602   std::string objTarget;
1603   for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
1604       obj != this->Objects.end(); ++obj)
1605     {
1606     objTarget = relPath;
1607     objTarget += *obj;
1608     depends.push_back(objTarget);
1609     }
1610
1611   // Add dependencies on the external object files.
1612   for(std::vector<std::string>::const_iterator obj
1613         = this->ExternalObjects.begin();
1614       obj != this->ExternalObjects.end(); ++obj)
1615     {
1616     depends.push_back(*obj);
1617     }
1618
1619   // Add a dependency on the rule file itself.
1620   this->LocalGenerator->AppendRuleDepend(depends,
1621                                          this->BuildFileNameFull.c_str());
1622 }
1623
1624 //----------------------------------------------------------------------------
1625 void cmMakefileTargetGenerator
1626 ::AppendLinkDepends(std::vector<std::string>& depends)
1627 {
1628   this->AppendObjectDepends(depends);
1629
1630   // Add dependencies on targets that must be built first.
1631   this->AppendTargetDepends(depends);
1632
1633   // Add a dependency on the link definitions file, if any.
1634   if(!this->GeneratorTarget->ModuleDefinitionFile.empty())
1635     {
1636     depends.push_back(this->GeneratorTarget->ModuleDefinitionFile);
1637     }
1638
1639   // Add user-specified dependencies.
1640   if(const char* linkDepends =
1641      this->Target->GetProperty("LINK_DEPENDS"))
1642     {
1643     cmSystemTools::ExpandListArgument(linkDepends, depends);
1644     }
1645 }
1646
1647 //----------------------------------------------------------------------------
1648 std::string cmMakefileTargetGenerator::GetLinkRule(const char* linkRuleVar)
1649 {
1650   std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
1651   if(this->Target->HasImplibGNUtoMS())
1652     {
1653     std::string ruleVar = "CMAKE_";
1654     ruleVar += this->Target->GetLinkerLanguage(this->ConfigName);
1655     ruleVar += "_GNUtoMS_RULE";
1656     if(const char* rule = this->Makefile->GetDefinition(ruleVar.c_str()))
1657       {
1658       linkRule += rule;
1659       }
1660     }
1661   return linkRule;
1662 }
1663
1664 //----------------------------------------------------------------------------
1665 void cmMakefileTargetGenerator
1666 ::CloseFileStreams()
1667 {
1668   delete this->BuildFileStream;
1669   delete this->InfoFileStream;
1670   delete this->FlagFileStream;
1671 }
1672
1673 void cmMakefileTargetGenerator::RemoveForbiddenFlags(const char* flagVar,
1674                                                      const char* linkLang,
1675                                                      std::string& linkFlags)
1676 {
1677   // check for language flags that are not allowed at link time, and
1678   // remove them, -w on darwin for gcc -w -dynamiclib sends -w to libtool
1679   // which fails, there may be more]
1680
1681   std::string removeFlags = "CMAKE_";
1682   removeFlags += linkLang;
1683   removeFlags += flagVar;
1684   std::string removeflags =
1685     this->Makefile->GetSafeDefinition(removeFlags.c_str());
1686   std::vector<std::string> removeList;
1687   cmSystemTools::ExpandListArgument(removeflags, removeList);
1688   for(std::vector<std::string>::iterator i = removeList.begin();
1689       i != removeList.end(); ++i)
1690     {
1691     cmSystemTools::ReplaceString(linkFlags, i->c_str(), "");
1692     }
1693 }
1694
1695 //----------------------------------------------------------------------------
1696 void
1697 cmMakefileTargetGenerator
1698 ::AddMultipleOutputPair(const char* depender, const char* dependee)
1699 {
1700   MultipleOutputPairsType::value_type p(depender, dependee);
1701   this->MultipleOutputPairs.insert(p);
1702 }
1703
1704 //----------------------------------------------------------------------------
1705 void
1706 cmMakefileTargetGenerator
1707 ::CreateLinkScript(const char* name,
1708                    std::vector<std::string> const& link_commands,
1709                    std::vector<std::string>& makefile_commands,
1710                    std::vector<std::string>& makefile_depends)
1711 {
1712   // Create the link script file.
1713   std::string linkScriptName = this->TargetBuildDirectoryFull;
1714   linkScriptName += "/";
1715   linkScriptName += name;
1716   cmGeneratedFileStream linkScriptStream(linkScriptName.c_str());
1717   linkScriptStream.SetCopyIfDifferent(true);
1718   for(std::vector<std::string>::const_iterator cmd = link_commands.begin();
1719       cmd != link_commands.end(); ++cmd)
1720     {
1721     // Do not write out empty commands or commands beginning in the
1722     // shell no-op ":".
1723     if(!cmd->empty() && (*cmd)[0] != ':')
1724       {
1725       linkScriptStream << *cmd << "\n";
1726       }
1727     }
1728
1729   // Create the makefile command to invoke the link script.
1730   std::string link_command = "$(CMAKE_COMMAND) -E cmake_link_script ";
1731   link_command += this->Convert(linkScriptName.c_str(),
1732                                 cmLocalGenerator::START_OUTPUT,
1733                                 cmLocalGenerator::SHELL);
1734   link_command += " --verbose=$(VERBOSE)";
1735   makefile_commands.push_back(link_command);
1736   makefile_depends.push_back(linkScriptName);
1737 }
1738
1739 //----------------------------------------------------------------------------
1740 std::string
1741 cmMakefileTargetGenerator
1742 ::CreateResponseFile(const char* name, std::string const& options,
1743                      std::vector<std::string>& makefile_depends)
1744 {
1745   // Create the response file.
1746   std::string responseFileNameFull = this->TargetBuildDirectoryFull;
1747   responseFileNameFull += "/";
1748   responseFileNameFull += name;
1749   cmGeneratedFileStream responseStream(responseFileNameFull.c_str());
1750   responseStream.SetCopyIfDifferent(true);
1751   responseStream << options << "\n";
1752
1753   // Add a dependency so the target will rebuild when the set of
1754   // objects changes.
1755   makefile_depends.push_back(responseFileNameFull);
1756
1757   // Construct the name to be used on the command line.
1758   std::string responseFileName = this->TargetBuildDirectory;
1759   responseFileName += "/";
1760   responseFileName += name;
1761   return responseFileName;
1762 }
1763
1764 //----------------------------------------------------------------------------
1765 void
1766 cmMakefileTargetGenerator
1767 ::CreateObjectLists(bool useLinkScript, bool useArchiveRules,
1768                     bool useResponseFile, std::string& buildObjs,
1769                     std::vector<std::string>& makefile_depends)
1770 {
1771   std::string variableName;
1772   std::string variableNameExternal;
1773   this->WriteObjectsVariable(variableName, variableNameExternal);
1774   if(useResponseFile)
1775     {
1776     // MSVC response files cannot exceed 128K.
1777     std::string::size_type const responseFileLimit = 131000;
1778
1779     // Construct the individual object list strings.
1780     std::vector<std::string> object_strings;
1781     this->WriteObjectsStrings(object_strings, responseFileLimit);
1782
1783     // Lookup the response file reference flag.
1784     std::string responseFlagVar = "CMAKE_";
1785     responseFlagVar += this->Target->GetLinkerLanguage(this->ConfigName);
1786     responseFlagVar += "_RESPONSE_FILE_LINK_FLAG";
1787     const char* responseFlag =
1788       this->Makefile->GetDefinition(responseFlagVar.c_str());
1789     if(!responseFlag)
1790       {
1791       responseFlag = "@";
1792       }
1793
1794     // Write a response file for each string.
1795     const char* sep = "";
1796     for(unsigned int i = 0; i < object_strings.size(); ++i)
1797       {
1798       // Number the response files.
1799       char rsp[32];
1800       sprintf(rsp, "objects%u.rsp", i+1);
1801
1802       // Create this response file.
1803       std::string objects_rsp =
1804         this->CreateResponseFile(rsp, object_strings[i], makefile_depends);
1805
1806       // Separate from previous response file references.
1807       buildObjs += sep;
1808       sep = " ";
1809
1810       // Reference the response file.
1811       buildObjs += responseFlag;
1812       buildObjs += this->Convert(objects_rsp.c_str(),
1813                                  cmLocalGenerator::NONE,
1814                                  cmLocalGenerator::SHELL);
1815       }
1816     }
1817   else if(useLinkScript)
1818     {
1819     if(!useArchiveRules)
1820       {
1821       this->WriteObjectsString(buildObjs);
1822       }
1823     }
1824   else
1825     {
1826     buildObjs = "$(";
1827     buildObjs += variableName;
1828     buildObjs += ") $(";
1829     buildObjs += variableNameExternal;
1830     buildObjs += ")";
1831     }
1832 }
1833
1834 //----------------------------------------------------------------------------
1835 void cmMakefileTargetGenerator::AddIncludeFlags(std::string& flags,
1836                                                 const char* lang)
1837 {
1838   std::string responseVar = "CMAKE_";
1839   responseVar += lang;
1840   responseVar += "_USE_RESPONSE_FILE_FOR_INCLUDES";
1841   bool useResponseFile = this->Makefile->IsOn(responseVar.c_str());
1842
1843
1844   std::vector<std::string> includes;
1845   this->LocalGenerator->GetIncludeDirectories(includes, this->Target, lang);
1846
1847   std::string includeFlags =
1848     this->LocalGenerator->GetIncludeFlags(includes, lang, useResponseFile);
1849   if(includeFlags.empty())
1850     {
1851     return;
1852     }
1853
1854   if(useResponseFile)
1855     {
1856     std::string name = "includes_";
1857     name += lang;
1858     name += ".rsp";
1859     std::string arg = "@" +
1860       this->CreateResponseFile(name.c_str(), includeFlags,
1861                                this->FlagFileDepends[lang]);
1862     this->LocalGenerator->AppendFlags(flags, arg.c_str());
1863     }
1864   else
1865     {
1866     this->LocalGenerator->AppendFlags(flags, includeFlags.c_str());
1867     }
1868 }
1869
1870 //----------------------------------------------------------------------------
1871 const char* cmMakefileTargetGenerator::GetFortranModuleDirectory()
1872 {
1873   // Compute the module directory.
1874   if(!this->FortranModuleDirectoryComputed)
1875     {
1876     const char* target_mod_dir =
1877       this->Target->GetProperty("Fortran_MODULE_DIRECTORY");
1878     const char* moddir_flag =
1879       this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_FLAG");
1880     if(target_mod_dir && moddir_flag)
1881       {
1882       // Compute the full path to the module directory.
1883       if(cmSystemTools::FileIsFullPath(target_mod_dir))
1884         {
1885         // Already a full path.
1886         this->FortranModuleDirectory = target_mod_dir;
1887         }
1888       else
1889         {
1890         // Interpret relative to the current output directory.
1891         this->FortranModuleDirectory =
1892           this->Makefile->GetCurrentOutputDirectory();
1893         this->FortranModuleDirectory += "/";
1894         this->FortranModuleDirectory += target_mod_dir;
1895         }
1896
1897       // Make sure the module output directory exists.
1898       cmSystemTools::MakeDirectory(this->FortranModuleDirectory.c_str());
1899       }
1900     this->FortranModuleDirectoryComputed = true;
1901     }
1902
1903   // Return the computed directory.
1904   if(this->FortranModuleDirectory.empty())
1905     {
1906     return 0;
1907     }
1908   else
1909     {
1910     return this->FortranModuleDirectory.c_str();
1911     }
1912 }
1913
1914 //----------------------------------------------------------------------------
1915 void cmMakefileTargetGenerator::AddFortranFlags(std::string& flags)
1916 {
1917   // Enable module output if necessary.
1918   if(const char* modout_flag =
1919      this->Makefile->GetDefinition("CMAKE_Fortran_MODOUT_FLAG"))
1920     {
1921     this->LocalGenerator->AppendFlags(flags, modout_flag);
1922     }
1923
1924   // Add a module output directory flag if necessary.
1925   const char* mod_dir = this->GetFortranModuleDirectory();
1926   if(!mod_dir)
1927     {
1928     mod_dir = this->Makefile->GetDefinition("CMAKE_Fortran_MODDIR_DEFAULT");
1929     }
1930   if(mod_dir)
1931     {
1932     const char* moddir_flag =
1933       this->Makefile->GetRequiredDefinition("CMAKE_Fortran_MODDIR_FLAG");
1934     std::string modflag = moddir_flag;
1935     modflag += this->Convert(mod_dir,
1936                              cmLocalGenerator::START_OUTPUT,
1937                              cmLocalGenerator::SHELL);
1938     this->LocalGenerator->AppendFlags(flags, modflag.c_str());
1939     }
1940
1941   // If there is a separate module path flag then duplicate the
1942   // include path with it.  This compiler does not search the include
1943   // path for modules.
1944   if(const char* modpath_flag =
1945      this->Makefile->GetDefinition("CMAKE_Fortran_MODPATH_FLAG"))
1946     {
1947     std::vector<std::string> includes;
1948     this->LocalGenerator->GetIncludeDirectories(includes, this->Target);
1949     for(std::vector<std::string>::const_iterator idi = includes.begin();
1950         idi != includes.end(); ++idi)
1951       {
1952       std::string flg = modpath_flag;
1953       flg += this->Convert(idi->c_str(),
1954                            cmLocalGenerator::NONE,
1955                            cmLocalGenerator::SHELL);
1956       this->LocalGenerator->AppendFlags(flags, flg.c_str());
1957       }
1958     }
1959 }
1960
1961 //----------------------------------------------------------------------------
1962 void cmMakefileTargetGenerator::AddModuleDefinitionFlag(std::string& flags)
1963 {
1964   if(this->GeneratorTarget->ModuleDefinitionFile.empty())
1965     {
1966     return;
1967     }
1968
1969   // TODO: Create a per-language flag variable.
1970   const char* defFileFlag =
1971     this->Makefile->GetDefinition("CMAKE_LINK_DEF_FILE_FLAG");
1972   if(!defFileFlag)
1973     {
1974     return;
1975     }
1976
1977   // Append the flag and value.  Use ConvertToLinkReference to help
1978   // vs6's "cl -link" pass it to the linker.
1979   std::string flag = defFileFlag;
1980   flag += (this->LocalGenerator->ConvertToLinkReference(
1981              this->GeneratorTarget->ModuleDefinitionFile.c_str()));
1982   this->LocalGenerator->AppendFlags(flags, flag.c_str());
1983 }
1984
1985 //----------------------------------------------------------------------------
1986 const char* cmMakefileTargetGenerator::GetFeature(const char* feature)
1987 {
1988   return this->Target->GetFeature(feature, this->ConfigName);
1989 }
1990
1991 //----------------------------------------------------------------------------
1992 bool cmMakefileTargetGenerator::GetFeatureAsBool(const char* feature)
1993 {
1994   return cmSystemTools::IsOn(this->GetFeature(feature));
1995 }
1996
1997 //----------------------------------------------------------------------------
1998 void cmMakefileTargetGenerator::AddFeatureFlags(
1999   std::string& flags, const char* lang
2000   )
2001 {
2002   // Add language-specific flags.
2003   this->LocalGenerator->AddLanguageFlags(flags, lang, this->ConfigName);
2004
2005   if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION"))
2006     {
2007     this->LocalGenerator->AppendFeatureOptions(flags, lang, "IPO");
2008     }
2009 }