Imported Upstream version 2.8.9
[platform/upstream/cmake.git] / Source / cmMakefileLibraryTargetGenerator.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 "cmMakefileLibraryTargetGenerator.h"
13
14 #include "cmGeneratedFileStream.h"
15 #include "cmGlobalUnixMakefileGenerator3.h"
16 #include "cmLocalUnixMakefileGenerator3.h"
17 #include "cmMakefile.h"
18 #include "cmSourceFile.h"
19 #include "cmTarget.h"
20 #include "cmake.h"
21
22 #include <memory> // auto_ptr
23
24 //----------------------------------------------------------------------------
25 cmMakefileLibraryTargetGenerator
26 ::cmMakefileLibraryTargetGenerator(cmTarget* target):
27   cmMakefileTargetGenerator(target)
28 {
29   cmOSXBundleGenerator::PrepareTargetProperties(this->Target);
30
31   this->CustomCommandDriver = OnDepends;
32   this->Target->GetLibraryNames(
33     this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
34     this->TargetNameImport, this->TargetNamePDB, this->ConfigName);
35
36   this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
37                                                       this->TargetNameOut,
38                                                       this->ConfigName);
39   this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
40   this->MacContentDirectory =
41     this->OSXBundleGenerator->GetMacContentDirectory();
42 }
43
44 //----------------------------------------------------------------------------
45 cmMakefileLibraryTargetGenerator
46 ::~cmMakefileLibraryTargetGenerator()
47 {
48   delete this->OSXBundleGenerator;
49 }
50
51 //----------------------------------------------------------------------------
52 void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
53 {
54   // create the build.make file and directory, put in the common blocks
55   this->CreateRuleFile();
56
57   // write rules used to help build object files
58   this->WriteCommonCodeRules();
59
60   // write the per-target per-language flags
61   this->WriteTargetLanguageFlags();
62
63   // write in rules for object files and custom commands
64   this->WriteTargetBuildRules();
65
66   // write the link rules
67   // Write the rule for this target type.
68   switch(this->Target->GetType())
69     {
70     case cmTarget::STATIC_LIBRARY:
71       this->WriteStaticLibraryRules();
72       break;
73     case cmTarget::SHARED_LIBRARY:
74       this->WriteSharedLibraryRules(false);
75       if(this->Target->NeedRelinkBeforeInstall(this->ConfigName))
76         {
77         // Write rules to link an installable version of the target.
78         this->WriteSharedLibraryRules(true);
79         }
80       break;
81     case cmTarget::MODULE_LIBRARY:
82       this->WriteModuleLibraryRules(false);
83       if(this->Target->NeedRelinkBeforeInstall(this->ConfigName))
84         {
85         // Write rules to link an installable version of the target.
86         this->WriteModuleLibraryRules(true);
87         }
88       break;
89     case cmTarget::OBJECT_LIBRARY:
90       this->WriteObjectLibraryRules();
91       break;
92     default:
93       // If language is not known, this is an error.
94       cmSystemTools::Error("Unknown Library Type");
95       break;
96     }
97
98   // Write the requires target.
99   this->WriteTargetRequiresRules();
100
101   // Write clean target
102   this->WriteTargetCleanRules();
103
104   // Write the dependency generation rule.  This must be done last so
105   // that multiple output pair information is available.
106   this->WriteTargetDependRules();
107
108   // close the streams
109   this->CloseFileStreams();
110 }
111
112 //----------------------------------------------------------------------------
113 void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules()
114 {
115   std::vector<std::string> commands;
116   std::vector<std::string> depends;
117
118   // Add post-build rules.
119   this->LocalGenerator->
120     AppendCustomCommands(commands, this->Target->GetPostBuildCommands(),
121                          this->Target);
122
123   // Depend on the object files.
124   this->AppendObjectDepends(depends);
125
126   // Write the rule.
127   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
128                                       this->Target->GetName(),
129                                       depends, commands, true);
130
131   // Write the main driver rule to build everything in this target.
132   this->WriteTargetDriverRule(this->Target->GetName(), false);
133 }
134
135 //----------------------------------------------------------------------------
136 void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
137 {
138   const char* linkLanguage =
139     this->Target->GetLinkerLanguage(this->ConfigName);
140   std::string linkRuleVar = "CMAKE_";
141   if (linkLanguage)
142     {
143     linkRuleVar += linkLanguage;
144     }
145   linkRuleVar += "_CREATE_STATIC_LIBRARY";
146
147   if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION") &&
148      this->Makefile->GetDefinition((linkRuleVar+"_IPO").c_str()))
149     {
150     linkRuleVar += "_IPO";
151     }
152
153   std::string extraFlags;
154   this->LocalGenerator->AppendFlags
155     (extraFlags,this->Target->GetProperty("STATIC_LIBRARY_FLAGS"));
156   std::string staticLibraryFlagsConfig = "STATIC_LIBRARY_FLAGS_";
157   staticLibraryFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
158   this->LocalGenerator->AppendFlags
159     (extraFlags, this->Target->GetProperty(staticLibraryFlagsConfig.c_str()));
160   this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), false);
161 }
162
163 //----------------------------------------------------------------------------
164 void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
165 {
166   if(this->Target->IsFrameworkOnApple())
167     {
168     this->WriteFrameworkRules(relink);
169     return;
170     }
171   const char* linkLanguage =
172     this->Target->GetLinkerLanguage(this->ConfigName);
173   std::string linkRuleVar = "CMAKE_";
174   if (linkLanguage)
175     {
176     linkRuleVar += linkLanguage;
177     }
178   linkRuleVar += "_CREATE_SHARED_LIBRARY";
179
180   std::string extraFlags;
181   this->LocalGenerator->AppendFlags
182     (extraFlags, this->Target->GetProperty("LINK_FLAGS"));
183   std::string linkFlagsConfig = "LINK_FLAGS_";
184   linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
185   this->LocalGenerator->AppendFlags
186     (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
187
188   this->LocalGenerator->AddConfigVariableFlags
189     (extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
190   this->AddModuleDefinitionFlag(extraFlags);
191
192   this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
193 }
194
195 //----------------------------------------------------------------------------
196 void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
197 {
198   const char* linkLanguage =
199     this->Target->GetLinkerLanguage(this->ConfigName);
200   std::string linkRuleVar = "CMAKE_";
201   if (linkLanguage)
202     {
203     linkRuleVar += linkLanguage;
204     }
205   linkRuleVar += "_CREATE_SHARED_MODULE";
206
207   std::string extraFlags;
208   this->LocalGenerator->AppendFlags(extraFlags,
209                                     this->Target->GetProperty("LINK_FLAGS"));
210   std::string linkFlagsConfig = "LINK_FLAGS_";
211   linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
212   this->LocalGenerator->AppendFlags
213     (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
214   this->LocalGenerator->AddConfigVariableFlags
215     (extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName);
216   this->AddModuleDefinitionFlag(extraFlags);
217
218   this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
219 }
220
221 //----------------------------------------------------------------------------
222 void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
223 {
224   const char* linkLanguage =
225     this->Target->GetLinkerLanguage(this->ConfigName);
226   std::string linkRuleVar = "CMAKE_";
227   if (linkLanguage)
228     {
229     linkRuleVar += linkLanguage;
230     }
231   linkRuleVar += "_CREATE_MACOSX_FRAMEWORK";
232
233   std::string extraFlags;
234   this->LocalGenerator->AppendFlags(extraFlags,
235                                     this->Target->GetProperty("LINK_FLAGS"));
236   std::string linkFlagsConfig = "LINK_FLAGS_";
237   linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
238   this->LocalGenerator->AppendFlags
239     (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
240   this->LocalGenerator->AddConfigVariableFlags
241     (extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName);
242
243   this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
244 }
245
246 //----------------------------------------------------------------------------
247 void cmMakefileLibraryTargetGenerator::WriteLibraryRules
248 (const char* linkRuleVar, const char* extraFlags, bool relink)
249 {
250   // TODO: Merge the methods that call this method to avoid
251   // code duplication.
252   std::vector<std::string> commands;
253
254   // Build list of dependencies.
255   std::vector<std::string> depends;
256   this->AppendLinkDepends(depends);
257
258   // Get the language to use for linking this library.
259   const char* linkLanguage =
260     this->Target->GetLinkerLanguage(this->ConfigName);
261
262   // Make sure we have a link language.
263   if(!linkLanguage)
264     {
265     cmSystemTools::Error("Cannot determine link language for target \"",
266                          this->Target->GetName(), "\".");
267     return;
268     }
269
270   // Create set of linking flags.
271   std::string linkFlags;
272   this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
273
274   // Add OSX version flags, if any.
275   if(this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
276      this->Target->GetType() == cmTarget::MODULE_LIBRARY)
277     {
278     this->AppendOSXVerFlag(linkFlags, linkLanguage, "COMPATIBILITY", true);
279     this->AppendOSXVerFlag(linkFlags, linkLanguage, "CURRENT", false);
280     }
281
282   // Construct the name of the library.
283   std::string targetName;
284   std::string targetNameSO;
285   std::string targetNameReal;
286   std::string targetNameImport;
287   std::string targetNamePDB;
288   this->Target->GetLibraryNames(
289     targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB,
290     this->ConfigName);
291
292   // Construct the full path version of the names.
293   std::string outpath;
294   std::string outpathImp;
295   if(this->Target->IsFrameworkOnApple())
296     {
297     outpath = this->MacContentDirectory;
298     this->OSXBundleGenerator->CreateFramework(targetName);
299     }
300   else if(this->Target->IsCFBundleOnApple())
301     {
302     outpath = this->Target->GetDirectory(this->ConfigName);
303     outpath += "/";
304     this->OSXBundleGenerator->CreateCFBundle(targetName, outpath);
305     }
306   else if(relink)
307     {
308     outpath = this->Makefile->GetStartOutputDirectory();
309     outpath += cmake::GetCMakeFilesDirectory();
310     outpath += "/CMakeRelink.dir";
311     cmSystemTools::MakeDirectory(outpath.c_str());
312     outpath += "/";
313     if(!targetNameImport.empty())
314       {
315       outpathImp = outpath;
316       }
317     }
318   else
319     {
320     outpath = this->Target->GetDirectory(this->ConfigName);
321     cmSystemTools::MakeDirectory(outpath.c_str());
322     outpath += "/";
323     if(!targetNameImport.empty())
324       {
325       outpathImp = this->Target->GetDirectory(this->ConfigName, true);
326       cmSystemTools::MakeDirectory(outpathImp.c_str());
327       outpathImp += "/";
328       }
329     }
330
331   std::string targetFullPath = outpath + targetName;
332   std::string targetFullPathPDB = outpath + targetNamePDB;
333   std::string targetFullPathSO = outpath + targetNameSO;
334   std::string targetFullPathReal = outpath + targetNameReal;
335   std::string targetFullPathImport = outpathImp + targetNameImport;
336
337   // Construct the output path version of the names for use in command
338   // arguments.
339   std::string targetOutPathPDB =
340     this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
341                   cmLocalGenerator::SHELL);
342   std::string targetOutPath =
343     this->Convert(targetFullPath.c_str(),cmLocalGenerator::START_OUTPUT,
344                   cmLocalGenerator::SHELL);
345   std::string targetOutPathSO =
346     this->Convert(targetFullPathSO.c_str(),cmLocalGenerator::START_OUTPUT,
347                   cmLocalGenerator::SHELL);
348   std::string targetOutPathReal =
349     this->Convert(targetFullPathReal.c_str(),cmLocalGenerator::START_OUTPUT,
350                   cmLocalGenerator::SHELL);
351   std::string targetOutPathImport =
352     this->Convert(targetFullPathImport.c_str(),cmLocalGenerator::START_OUTPUT,
353                   cmLocalGenerator::SHELL);
354
355   if(!this->NoRuleMessages)
356     {
357     // Add the link message.
358     std::string buildEcho = "Linking ";
359     buildEcho += linkLanguage;
360     switch(this->Target->GetType())
361       {
362       case cmTarget::STATIC_LIBRARY:
363         buildEcho += " static library ";
364         break;
365       case cmTarget::SHARED_LIBRARY:
366         buildEcho += " shared library ";
367         break;
368       case cmTarget::MODULE_LIBRARY:
369         if (this->Target->IsCFBundleOnApple())
370             buildEcho += " CFBundle";
371         buildEcho += " shared module ";
372         break;
373       default:
374         buildEcho += " library ";
375         break;
376       }
377     buildEcho += targetOutPath.c_str();
378     this->LocalGenerator->AppendEcho(commands, buildEcho.c_str(),
379                                      cmLocalUnixMakefileGenerator3::EchoLink);
380     }
381
382   const char* forbiddenFlagVar = 0;
383   switch(this->Target->GetType())
384     {
385     case cmTarget::SHARED_LIBRARY:
386       forbiddenFlagVar = "_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS";
387       break;
388     case cmTarget::MODULE_LIBRARY:
389       forbiddenFlagVar = "_CREATE_SHARED_MODULE_FORBIDDEN_FLAGS";
390       break;
391     default: break;
392     }
393
394   // Clean files associated with this library.
395   std::vector<std::string> libCleanFiles;
396   libCleanFiles.push_back(this->Convert(targetFullPath.c_str(),
397         cmLocalGenerator::START_OUTPUT,
398         cmLocalGenerator::UNCHANGED));
399   if(targetNameReal != targetName)
400     {
401     libCleanFiles.push_back(this->Convert(targetFullPathReal.c_str(),
402         cmLocalGenerator::START_OUTPUT,
403         cmLocalGenerator::UNCHANGED));
404     }
405   if(targetNameSO != targetName &&
406      targetNameSO != targetNameReal)
407     {
408     libCleanFiles.push_back(this->Convert(targetFullPathSO.c_str(),
409         cmLocalGenerator::START_OUTPUT,
410         cmLocalGenerator::UNCHANGED));
411     }
412   if(!targetNameImport.empty())
413     {
414     libCleanFiles.push_back(this->Convert(targetFullPathImport.c_str(),
415         cmLocalGenerator::START_OUTPUT,
416         cmLocalGenerator::UNCHANGED));
417     std::string implib;
418     if(this->Target->GetImplibGNUtoMS(targetFullPathImport, implib))
419       {
420       libCleanFiles.push_back(this->Convert(implib.c_str(),
421                                             cmLocalGenerator::START_OUTPUT,
422                                             cmLocalGenerator::UNCHANGED));
423       }
424     }
425
426   // List the PDB for cleaning only when the whole target is
427   // cleaned.  We do not want to delete the .pdb file just before
428   // linking the target.
429   this->CleanFiles.push_back
430     (this->Convert(targetFullPathPDB.c_str(),
431                    cmLocalGenerator::START_OUTPUT,
432                    cmLocalGenerator::UNCHANGED));
433
434 #ifdef _WIN32
435   // There may be a manifest file for this target.  Add it to the
436   // clean set just in case.
437   if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
438     {
439     libCleanFiles.push_back(
440       this->Convert((targetFullPath+".manifest").c_str(),
441                     cmLocalGenerator::START_OUTPUT,
442                     cmLocalGenerator::UNCHANGED));
443     }
444 #endif
445
446   std::vector<std::string> commands1;
447   // Add a command to remove any existing files for this library.
448   // for static libs only
449   if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
450     {
451     this->LocalGenerator->AppendCleanCommand(commands1, libCleanFiles,
452                                              *this->Target, "target");
453     this->LocalGenerator->CreateCDCommand
454       (commands1,
455        this->Makefile->GetStartOutputDirectory(),
456        cmLocalGenerator::HOME_OUTPUT);
457     commands.insert(commands.end(), commands1.begin(), commands1.end());
458     commands1.clear();
459     }
460
461   // Add the pre-build and pre-link rules building but not when relinking.
462   if(!relink)
463     {
464     this->LocalGenerator
465       ->AppendCustomCommands(commands, this->Target->GetPreBuildCommands(),
466                              this->Target);
467     this->LocalGenerator
468       ->AppendCustomCommands(commands, this->Target->GetPreLinkCommands(),
469                              this->Target);
470     }
471
472   // Determine whether a link script will be used.
473   bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
474
475   // Select whether to use a response file for objects.
476   bool useResponseFile = false;
477   {
478   std::string responseVar = "CMAKE_";
479   responseVar += linkLanguage;
480   responseVar += "_USE_RESPONSE_FILE_FOR_OBJECTS";
481   if(this->Makefile->IsOn(responseVar.c_str()))
482     {
483     useResponseFile = true;
484     }
485   }
486
487   // For static libraries there might be archiving rules.
488   bool haveStaticLibraryRule = false;
489   std::vector<std::string> archiveCreateCommands;
490   std::vector<std::string> archiveAppendCommands;
491   std::vector<std::string> archiveFinishCommands;
492   std::string::size_type archiveCommandLimit = std::string::npos;
493   if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
494     {
495     haveStaticLibraryRule =
496       this->Makefile->GetDefinition(linkRuleVar)? true:false;
497     std::string arCreateVar = "CMAKE_";
498     arCreateVar += linkLanguage;
499     arCreateVar += "_ARCHIVE_CREATE";
500     if(const char* rule = this->Makefile->GetDefinition(arCreateVar.c_str()))
501       {
502       cmSystemTools::ExpandListArgument(rule, archiveCreateCommands);
503       }
504     std::string arAppendVar = "CMAKE_";
505     arAppendVar += linkLanguage;
506     arAppendVar += "_ARCHIVE_APPEND";
507     if(const char* rule = this->Makefile->GetDefinition(arAppendVar.c_str()))
508       {
509       cmSystemTools::ExpandListArgument(rule, archiveAppendCommands);
510       }
511     std::string arFinishVar = "CMAKE_";
512     arFinishVar += linkLanguage;
513     arFinishVar += "_ARCHIVE_FINISH";
514     if(const char* rule = this->Makefile->GetDefinition(arFinishVar.c_str()))
515       {
516       cmSystemTools::ExpandListArgument(rule, archiveFinishCommands);
517       }
518     }
519
520   // Decide whether to use archiving rules.
521   bool useArchiveRules =
522     !haveStaticLibraryRule &&
523     !archiveCreateCommands.empty() && !archiveAppendCommands.empty();
524   if(useArchiveRules)
525     {
526     // Archiving rules are always run with a link script.
527     useLinkScript = true;
528
529     // Archiving rules never use a response file.
530     useResponseFile = false;
531
532     // Limit the length of individual object lists to less than the
533     // 32K command line length limit on Windows.  We could make this a
534     // platform file variable but this should work everywhere.
535     archiveCommandLimit = 30000;
536     }
537
538   // Expand the rule variables.
539   std::vector<std::string> real_link_commands;
540   {
541   // Set path conversion for link script shells.
542   this->LocalGenerator->SetLinkScriptShell(useLinkScript);
543
544   // Collect up flags to link in needed libraries.
545   cmOStringStream linklibs;
546   if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
547     {
548     this->LocalGenerator
549       ->OutputLinkLibraries(linklibs, *this->Target, relink);
550     }
551
552   // Construct object file lists that may be needed to expand the
553   // rule.
554   std::string buildObjs;
555   this->CreateObjectLists(useLinkScript, useArchiveRules, useResponseFile,
556                           buildObjs, depends);
557
558   cmLocalGenerator::RuleVariables vars;
559   vars.TargetPDB = targetOutPathPDB.c_str();
560
561   // Setup the target version.
562   std::string targetVersionMajor;
563   std::string targetVersionMinor;
564   {
565   cmOStringStream majorStream;
566   cmOStringStream minorStream;
567   int major;
568   int minor;
569   this->Target->GetTargetVersion(major, minor);
570   majorStream << major;
571   minorStream << minor;
572   targetVersionMajor = majorStream.str();
573   targetVersionMinor = minorStream.str();
574   }
575   vars.TargetVersionMajor = targetVersionMajor.c_str();
576   vars.TargetVersionMinor = targetVersionMinor.c_str();
577
578   vars.RuleLauncher = "RULE_LAUNCH_LINK";
579   vars.CMTarget = this->Target;
580   vars.Language = linkLanguage;
581   vars.Objects = buildObjs.c_str();
582   std::string objdir = cmake::GetCMakeFilesDirectoryPostSlash();
583   objdir += this->Target->GetName();
584   objdir += ".dir";
585   objdir = this->Convert(objdir.c_str(),
586                          cmLocalGenerator::START_OUTPUT,
587                          cmLocalGenerator::SHELL);
588   vars.ObjectDir = objdir.c_str();
589   vars.Target = targetOutPathReal.c_str();
590   std::string linkString = linklibs.str();
591   vars.LinkLibraries = linkString.c_str();
592   vars.ObjectsQuoted = buildObjs.c_str();
593   if (this->Target->HasSOName(this->ConfigName))
594     {
595     vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
596     vars.TargetSOName= targetNameSO.c_str();
597     }
598   vars.LinkFlags = linkFlags.c_str();
599
600   // Compute the directory portion of the install_name setting.
601   std::string install_name_dir;
602   if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
603     {
604     // Get the install_name directory for the build tree.
605     install_name_dir =
606       this->Target->GetInstallNameDirForBuildTree(this->ConfigName);
607
608     // Set the rule variable replacement value.
609     if(install_name_dir.empty())
610       {
611       vars.TargetInstallNameDir = "";
612       }
613     else
614       {
615       // Convert to a path for the native build tool.
616       install_name_dir =
617         this->LocalGenerator->Convert(install_name_dir.c_str(),
618                                       cmLocalGenerator::NONE,
619                                       cmLocalGenerator::SHELL, false);
620       vars.TargetInstallNameDir = install_name_dir.c_str();
621       }
622     }
623
624   // Add language feature flags.
625   std::string langFlags;
626   this->AddFeatureFlags(langFlags, linkLanguage);
627
628   this->LocalGenerator->AddArchitectureFlags(langFlags, this->Target,
629                                              linkLanguage, this->ConfigName);
630
631   // remove any language flags that might not work with the
632   // particular os
633   if(forbiddenFlagVar)
634     {
635     this->RemoveForbiddenFlags(forbiddenFlagVar,
636                                linkLanguage, langFlags);
637     }
638   vars.LanguageCompileFlags = langFlags.c_str();
639
640   // Construct the main link rule and expand placeholders.
641   this->LocalGenerator->TargetImplib = targetOutPathImport;
642   if(useArchiveRules)
643     {
644     // Construct the individual object list strings.
645     std::vector<std::string> object_strings;
646     this->WriteObjectsStrings(object_strings, archiveCommandLimit);
647
648     // Create the archive with the first set of objects.
649     std::vector<std::string>::iterator osi = object_strings.begin();
650     {
651     vars.Objects = osi->c_str();
652     for(std::vector<std::string>::const_iterator
653           i = archiveCreateCommands.begin();
654         i != archiveCreateCommands.end(); ++i)
655       {
656       std::string cmd = *i;
657       this->LocalGenerator->ExpandRuleVariables(cmd, vars);
658       real_link_commands.push_back(cmd);
659       }
660     }
661     // Append to the archive with the other object sets.
662     for(++osi; osi != object_strings.end(); ++osi)
663       {
664       vars.Objects = osi->c_str();
665       for(std::vector<std::string>::const_iterator
666             i = archiveAppendCommands.begin();
667           i != archiveAppendCommands.end(); ++i)
668         {
669         std::string cmd = *i;
670         this->LocalGenerator->ExpandRuleVariables(cmd, vars);
671         real_link_commands.push_back(cmd);
672         }
673       }
674     // Finish the archive.
675     vars.Objects = "";
676     for(std::vector<std::string>::const_iterator
677           i = archiveFinishCommands.begin();
678         i != archiveFinishCommands.end(); ++i)
679       {
680       std::string cmd = *i;
681       this->LocalGenerator->ExpandRuleVariables(cmd, vars);
682       real_link_commands.push_back(cmd);
683       }
684     }
685   else
686     {
687     // Get the set of commands.
688     std::string linkRule = this->GetLinkRule(linkRuleVar);
689     cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
690
691     // Expand placeholders.
692     for(std::vector<std::string>::iterator i = real_link_commands.begin();
693         i != real_link_commands.end(); ++i)
694       {
695       this->LocalGenerator->ExpandRuleVariables(*i, vars);
696       }
697     }
698   this->LocalGenerator->TargetImplib = "";
699
700   // Restore path conversion to normal shells.
701   this->LocalGenerator->SetLinkScriptShell(false);
702   }
703
704   // Optionally convert the build rule to use a script to avoid long
705   // command lines in the make shell.
706   if(useLinkScript)
707     {
708     // Use a link script.
709     const char* name = (relink? "relink.txt" : "link.txt");
710     this->CreateLinkScript(name, real_link_commands, commands1, depends);
711     }
712   else
713     {
714     // No link script.  Just use the link rule directly.
715     commands1 = real_link_commands;
716     }
717   this->LocalGenerator->CreateCDCommand
718     (commands1,
719      this->Makefile->GetStartOutputDirectory(),
720      cmLocalGenerator::HOME_OUTPUT);
721   commands.insert(commands.end(), commands1.begin(), commands1.end());
722   commands1.clear();
723
724   // Add a rule to create necessary symlinks for the library.
725   if(targetOutPath != targetOutPathReal)
726     {
727     std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
728     symlink += targetOutPathReal;
729     symlink += " ";
730     symlink += targetOutPathSO;
731     symlink += " ";
732     symlink += targetOutPath;
733     commands1.push_back(symlink);
734     this->LocalGenerator->CreateCDCommand(commands1,
735                                   this->Makefile->GetStartOutputDirectory(),
736                                   cmLocalGenerator::HOME_OUTPUT);
737     commands.insert(commands.end(), commands1.begin(), commands1.end());
738     commands1.clear();
739     }
740   // Add the post-build rules when building but not when relinking.
741   if(!relink)
742     {
743     this->LocalGenerator->
744       AppendCustomCommands(commands, this->Target->GetPostBuildCommands(),
745                            this->Target);
746     }
747
748   // Write the build rule.
749   this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
750                                       targetFullPathReal.c_str(),
751                                       depends, commands, false);
752
753   // Some targets have more than one output file.  Create rules to
754   // drive the build if any extra outputs are missing.
755   std::vector<std::string> extraOutputs;
756   if(targetNameSO != targetNameReal)
757     {
758     this->GenerateExtraOutput(targetFullPathSO.c_str(),
759                               targetFullPathReal.c_str());
760     }
761   if(targetName != targetNameSO &&
762      targetName != targetNameReal)
763     {
764     this->GenerateExtraOutput(targetFullPath.c_str(),
765                               targetFullPathReal.c_str());
766     }
767
768   // Write the main driver rule to build everything in this target.
769   this->WriteTargetDriverRule(targetFullPath.c_str(), relink);
770
771   // Clean all the possible library names and symlinks.
772   this->CleanFiles.insert(this->CleanFiles.end(),
773                           libCleanFiles.begin(),libCleanFiles.end());
774 }
775
776 //----------------------------------------------------------------------------
777 void
778 cmMakefileLibraryTargetGenerator
779 ::AppendOSXVerFlag(std::string& flags, const char* lang,
780                    const char* name, bool so)
781 {
782   // Lookup the flag to specify the version.
783   std::string fvar = "CMAKE_";
784   fvar += lang;
785   fvar += "_OSX_";
786   fvar += name;
787   fvar += "_VERSION_FLAG";
788   const char* flag = this->Makefile->GetDefinition(fvar.c_str());
789
790   // Skip if no such flag.
791   if(!flag)
792     {
793     return;
794     }
795
796   // Lookup the target version information.
797   int major;
798   int minor;
799   int patch;
800   this->Target->GetTargetVersion(so, major, minor, patch);
801   if(major > 0 || minor > 0 || patch > 0)
802     {
803     // Append the flag since a non-zero version is specified.
804     cmOStringStream vflag;
805     vflag << flag << major << "." << minor << "." << patch;
806     this->LocalGenerator->AppendFlags(flags, vflag.str().c_str());
807     }
808 }