1 /*============================================================================
2 CMake - Cross Platform Makefile Generator
3 Copyright 2000-2009 Kitware, Inc., Insight Software Consortium
5 Distributed under the OSI-approved BSD License (the "License");
6 see accompanying file Copyright.txt for details.
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"
14 #include "cmGeneratedFileStream.h"
15 #include "cmGlobalUnixMakefileGenerator3.h"
16 #include "cmLocalUnixMakefileGenerator3.h"
17 #include "cmMakefile.h"
18 #include "cmSourceFile.h"
22 //----------------------------------------------------------------------------
23 cmMakefileLibraryTargetGenerator
24 ::cmMakefileLibraryTargetGenerator(cmTarget* target):
25 cmMakefileTargetGenerator(target)
27 this->CustomCommandDriver = OnDepends;
28 this->Target->GetLibraryNames(
29 this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
30 this->TargetNameImport, this->TargetNamePDB, this->ConfigName);
32 this->OSXBundleGenerator = new cmOSXBundleGenerator(this->Target,
34 this->OSXBundleGenerator->SetMacContentFolders(&this->MacContentFolders);
37 //----------------------------------------------------------------------------
38 cmMakefileLibraryTargetGenerator
39 ::~cmMakefileLibraryTargetGenerator()
41 delete this->OSXBundleGenerator;
44 //----------------------------------------------------------------------------
45 void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
47 // create the build.make file and directory, put in the common blocks
48 this->CreateRuleFile();
50 // write rules used to help build object files
51 this->WriteCommonCodeRules();
53 // write the per-target per-language flags
54 this->WriteTargetLanguageFlags();
56 // write in rules for object files and custom commands
57 this->WriteTargetBuildRules();
59 // write the link rules
60 // Write the rule for this target type.
61 switch(this->Target->GetType())
63 case cmTarget::STATIC_LIBRARY:
64 this->WriteStaticLibraryRules();
66 case cmTarget::SHARED_LIBRARY:
67 this->WriteSharedLibraryRules(false);
68 if(this->Target->NeedRelinkBeforeInstall(this->ConfigName))
70 // Write rules to link an installable version of the target.
71 this->WriteSharedLibraryRules(true);
74 case cmTarget::MODULE_LIBRARY:
75 this->WriteModuleLibraryRules(false);
76 if(this->Target->NeedRelinkBeforeInstall(this->ConfigName))
78 // Write rules to link an installable version of the target.
79 this->WriteModuleLibraryRules(true);
82 case cmTarget::OBJECT_LIBRARY:
83 this->WriteObjectLibraryRules();
86 // If language is not known, this is an error.
87 cmSystemTools::Error("Unknown Library Type");
91 // Write the requires target.
92 this->WriteTargetRequiresRules();
95 this->WriteTargetCleanRules();
97 // Write the dependency generation rule. This must be done last so
98 // that multiple output pair information is available.
99 this->WriteTargetDependRules();
102 this->CloseFileStreams();
105 //----------------------------------------------------------------------------
106 void cmMakefileLibraryTargetGenerator::WriteObjectLibraryRules()
108 std::vector<std::string> commands;
109 std::vector<std::string> depends;
111 // Add post-build rules.
112 this->LocalGenerator->
113 AppendCustomCommands(commands, this->Target->GetPostBuildCommands(),
116 // Depend on the object files.
117 this->AppendObjectDepends(depends);
120 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
121 this->Target->GetName(),
122 depends, commands, true);
124 // Write the main driver rule to build everything in this target.
125 this->WriteTargetDriverRule(this->Target->GetName(), false);
128 //----------------------------------------------------------------------------
129 void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
131 const char* linkLanguage =
132 this->Target->GetLinkerLanguage(this->ConfigName);
133 std::string linkRuleVar = "CMAKE_";
136 linkRuleVar += linkLanguage;
138 linkRuleVar += "_CREATE_STATIC_LIBRARY";
140 if(this->GetFeatureAsBool("INTERPROCEDURAL_OPTIMIZATION") &&
141 this->Makefile->GetDefinition((linkRuleVar+"_IPO").c_str()))
143 linkRuleVar += "_IPO";
146 std::string extraFlags;
147 this->LocalGenerator->GetStaticLibraryFlags(extraFlags,
148 cmSystemTools::UpperCase(this->ConfigName), this->Target);
149 this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), false);
152 //----------------------------------------------------------------------------
153 void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
155 if(this->Target->IsFrameworkOnApple())
157 this->WriteFrameworkRules(relink);
160 const char* linkLanguage =
161 this->Target->GetLinkerLanguage(this->ConfigName);
162 std::string linkRuleVar = "CMAKE_";
165 linkRuleVar += linkLanguage;
167 linkRuleVar += "_CREATE_SHARED_LIBRARY";
169 std::string extraFlags;
170 this->LocalGenerator->AppendFlags
171 (extraFlags, this->Target->GetProperty("LINK_FLAGS"));
172 std::string linkFlagsConfig = "LINK_FLAGS_";
173 linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
174 this->LocalGenerator->AppendFlags
175 (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
177 this->LocalGenerator->AddConfigVariableFlags
178 (extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
179 this->AddModuleDefinitionFlag(extraFlags);
181 this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
184 //----------------------------------------------------------------------------
185 void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
187 const char* linkLanguage =
188 this->Target->GetLinkerLanguage(this->ConfigName);
189 std::string linkRuleVar = "CMAKE_";
192 linkRuleVar += linkLanguage;
194 linkRuleVar += "_CREATE_SHARED_MODULE";
196 std::string extraFlags;
197 this->LocalGenerator->AppendFlags(extraFlags,
198 this->Target->GetProperty("LINK_FLAGS"));
199 std::string linkFlagsConfig = "LINK_FLAGS_";
200 linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
201 this->LocalGenerator->AppendFlags
202 (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
203 this->LocalGenerator->AddConfigVariableFlags
204 (extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName);
205 this->AddModuleDefinitionFlag(extraFlags);
207 this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
210 //----------------------------------------------------------------------------
211 void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
213 const char* linkLanguage =
214 this->Target->GetLinkerLanguage(this->ConfigName);
215 std::string linkRuleVar = "CMAKE_";
218 linkRuleVar += linkLanguage;
220 linkRuleVar += "_CREATE_MACOSX_FRAMEWORK";
222 std::string extraFlags;
223 this->LocalGenerator->AppendFlags(extraFlags,
224 this->Target->GetProperty("LINK_FLAGS"));
225 std::string linkFlagsConfig = "LINK_FLAGS_";
226 linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
227 this->LocalGenerator->AppendFlags
228 (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
229 this->LocalGenerator->AddConfigVariableFlags
230 (extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName);
232 this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
235 //----------------------------------------------------------------------------
236 void cmMakefileLibraryTargetGenerator::WriteLibraryRules
237 (const char* linkRuleVar, const char* extraFlags, bool relink)
239 // TODO: Merge the methods that call this method to avoid
241 std::vector<std::string> commands;
243 // Build list of dependencies.
244 std::vector<std::string> depends;
245 this->AppendLinkDepends(depends);
247 // Get the language to use for linking this library.
248 const char* linkLanguage =
249 this->Target->GetLinkerLanguage(this->ConfigName);
251 // Make sure we have a link language.
254 cmSystemTools::Error("Cannot determine link language for target \"",
255 this->Target->GetName(), "\".");
259 // Create set of linking flags.
260 std::string linkFlags;
261 this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
263 // Add OSX version flags, if any.
264 if(this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
265 this->Target->GetType() == cmTarget::MODULE_LIBRARY)
267 this->AppendOSXVerFlag(linkFlags, linkLanguage, "COMPATIBILITY", true);
268 this->AppendOSXVerFlag(linkFlags, linkLanguage, "CURRENT", false);
271 // Construct the name of the library.
272 std::string targetName;
273 std::string targetNameSO;
274 std::string targetNameReal;
275 std::string targetNameImport;
276 std::string targetNamePDB;
277 this->Target->GetLibraryNames(
278 targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB,
281 // Construct the full path version of the names.
283 std::string outpathImp;
284 if(this->Target->IsFrameworkOnApple())
286 outpath = this->Target->GetDirectory(this->ConfigName);
287 this->OSXBundleGenerator->CreateFramework(targetName, outpath);
290 else if(this->Target->IsCFBundleOnApple())
292 outpath = this->Target->GetDirectory(this->ConfigName);
293 this->OSXBundleGenerator->CreateCFBundle(targetName, outpath);
298 outpath = this->Makefile->GetStartOutputDirectory();
299 outpath += cmake::GetCMakeFilesDirectory();
300 outpath += "/CMakeRelink.dir";
301 cmSystemTools::MakeDirectory(outpath.c_str());
303 if(!targetNameImport.empty())
305 outpathImp = outpath;
310 outpath = this->Target->GetDirectory(this->ConfigName);
311 cmSystemTools::MakeDirectory(outpath.c_str());
313 if(!targetNameImport.empty())
315 outpathImp = this->Target->GetDirectory(this->ConfigName, true);
316 cmSystemTools::MakeDirectory(outpathImp.c_str());
321 std::string pdbOutputPath = this->Target->GetPDBDirectory();
322 cmSystemTools::MakeDirectory(pdbOutputPath.c_str());
323 pdbOutputPath += "/";
325 std::string targetFullPath = outpath + targetName;
326 std::string targetFullPathPDB = pdbOutputPath + targetNamePDB;
327 std::string targetFullPathSO = outpath + targetNameSO;
328 std::string targetFullPathReal = outpath + targetNameReal;
329 std::string targetFullPathImport = outpathImp + targetNameImport;
331 // Construct the output path version of the names for use in command
333 std::string targetOutPathPDB =
334 this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
335 cmLocalGenerator::SHELL);
336 std::string targetOutPath =
337 this->Convert(targetFullPath.c_str(),cmLocalGenerator::START_OUTPUT,
338 cmLocalGenerator::SHELL);
339 std::string targetOutPathSO =
340 this->Convert(targetFullPathSO.c_str(),cmLocalGenerator::START_OUTPUT,
341 cmLocalGenerator::SHELL);
342 std::string targetOutPathReal =
343 this->Convert(targetFullPathReal.c_str(),cmLocalGenerator::START_OUTPUT,
344 cmLocalGenerator::SHELL);
345 std::string targetOutPathImport =
346 this->Convert(targetFullPathImport.c_str(),cmLocalGenerator::START_OUTPUT,
347 cmLocalGenerator::SHELL);
349 if(!this->NoRuleMessages)
351 // Add the link message.
352 std::string buildEcho = "Linking ";
353 buildEcho += linkLanguage;
354 switch(this->Target->GetType())
356 case cmTarget::STATIC_LIBRARY:
357 buildEcho += " static library ";
359 case cmTarget::SHARED_LIBRARY:
360 buildEcho += " shared library ";
362 case cmTarget::MODULE_LIBRARY:
363 if (this->Target->IsCFBundleOnApple())
364 buildEcho += " CFBundle";
365 buildEcho += " shared module ";
368 buildEcho += " library ";
371 buildEcho += targetOutPath.c_str();
372 this->LocalGenerator->AppendEcho(commands, buildEcho.c_str(),
373 cmLocalUnixMakefileGenerator3::EchoLink);
376 const char* forbiddenFlagVar = 0;
377 switch(this->Target->GetType())
379 case cmTarget::SHARED_LIBRARY:
380 forbiddenFlagVar = "_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS";
382 case cmTarget::MODULE_LIBRARY:
383 forbiddenFlagVar = "_CREATE_SHARED_MODULE_FORBIDDEN_FLAGS";
388 // Clean files associated with this library.
389 std::vector<std::string> libCleanFiles;
390 libCleanFiles.push_back(this->Convert(targetFullPath.c_str(),
391 cmLocalGenerator::START_OUTPUT,
392 cmLocalGenerator::UNCHANGED));
393 if(targetNameReal != targetName)
395 libCleanFiles.push_back(this->Convert(targetFullPathReal.c_str(),
396 cmLocalGenerator::START_OUTPUT,
397 cmLocalGenerator::UNCHANGED));
399 if(targetNameSO != targetName &&
400 targetNameSO != targetNameReal)
402 libCleanFiles.push_back(this->Convert(targetFullPathSO.c_str(),
403 cmLocalGenerator::START_OUTPUT,
404 cmLocalGenerator::UNCHANGED));
406 if(!targetNameImport.empty())
408 libCleanFiles.push_back(this->Convert(targetFullPathImport.c_str(),
409 cmLocalGenerator::START_OUTPUT,
410 cmLocalGenerator::UNCHANGED));
412 if(this->Target->GetImplibGNUtoMS(targetFullPathImport, implib))
414 libCleanFiles.push_back(this->Convert(implib.c_str(),
415 cmLocalGenerator::START_OUTPUT,
416 cmLocalGenerator::UNCHANGED));
420 // List the PDB for cleaning only when the whole target is
421 // cleaned. We do not want to delete the .pdb file just before
422 // linking the target.
423 this->CleanFiles.push_back
424 (this->Convert(targetFullPathPDB.c_str(),
425 cmLocalGenerator::START_OUTPUT,
426 cmLocalGenerator::UNCHANGED));
429 // There may be a manifest file for this target. Add it to the
430 // clean set just in case.
431 if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
433 libCleanFiles.push_back(
434 this->Convert((targetFullPath+".manifest").c_str(),
435 cmLocalGenerator::START_OUTPUT,
436 cmLocalGenerator::UNCHANGED));
440 std::vector<std::string> commands1;
441 // Add a command to remove any existing files for this library.
442 // for static libs only
443 if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
445 this->LocalGenerator->AppendCleanCommand(commands1, libCleanFiles,
446 *this->Target, "target");
447 this->LocalGenerator->CreateCDCommand
449 this->Makefile->GetStartOutputDirectory(),
450 cmLocalGenerator::HOME_OUTPUT);
451 commands.insert(commands.end(), commands1.begin(), commands1.end());
455 // Add the pre-build and pre-link rules building but not when relinking.
459 ->AppendCustomCommands(commands, this->Target->GetPreBuildCommands(),
462 ->AppendCustomCommands(commands, this->Target->GetPreLinkCommands(),
466 // Determine whether a link script will be used.
467 bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
469 // Select whether to use a response file for objects.
470 bool useResponseFile = false;
472 std::string responseVar = "CMAKE_";
473 responseVar += linkLanguage;
474 responseVar += "_USE_RESPONSE_FILE_FOR_OBJECTS";
475 if(this->Makefile->IsOn(responseVar.c_str()))
477 useResponseFile = true;
481 // For static libraries there might be archiving rules.
482 bool haveStaticLibraryRule = false;
483 std::vector<std::string> archiveCreateCommands;
484 std::vector<std::string> archiveAppendCommands;
485 std::vector<std::string> archiveFinishCommands;
486 std::string::size_type archiveCommandLimit = std::string::npos;
487 if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
489 haveStaticLibraryRule =
490 this->Makefile->GetDefinition(linkRuleVar)? true:false;
491 std::string arCreateVar = "CMAKE_";
492 arCreateVar += linkLanguage;
493 arCreateVar += "_ARCHIVE_CREATE";
494 if(const char* rule = this->Makefile->GetDefinition(arCreateVar.c_str()))
496 cmSystemTools::ExpandListArgument(rule, archiveCreateCommands);
498 std::string arAppendVar = "CMAKE_";
499 arAppendVar += linkLanguage;
500 arAppendVar += "_ARCHIVE_APPEND";
501 if(const char* rule = this->Makefile->GetDefinition(arAppendVar.c_str()))
503 cmSystemTools::ExpandListArgument(rule, archiveAppendCommands);
505 std::string arFinishVar = "CMAKE_";
506 arFinishVar += linkLanguage;
507 arFinishVar += "_ARCHIVE_FINISH";
508 if(const char* rule = this->Makefile->GetDefinition(arFinishVar.c_str()))
510 cmSystemTools::ExpandListArgument(rule, archiveFinishCommands);
514 // Decide whether to use archiving rules.
515 bool useArchiveRules =
516 !haveStaticLibraryRule &&
517 !archiveCreateCommands.empty() && !archiveAppendCommands.empty();
520 // Archiving rules are always run with a link script.
521 useLinkScript = true;
523 // Archiving rules never use a response file.
524 useResponseFile = false;
526 // Limit the length of individual object lists to less than the
527 // 32K command line length limit on Windows. We could make this a
528 // platform file variable but this should work everywhere.
529 archiveCommandLimit = 30000;
532 // Expand the rule variables.
533 std::vector<std::string> real_link_commands;
535 // Set path conversion for link script shells.
536 this->LocalGenerator->SetLinkScriptShell(useLinkScript);
538 // Collect up flags to link in needed libraries.
539 std::string linkLibs;
540 if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
542 std::string frameworkPath;
543 std::string linkPath;
545 ->OutputLinkLibraries(linkLibs, frameworkPath, linkPath,
546 *this->GeneratorTarget, relink);
547 linkLibs = frameworkPath + linkPath + linkLibs;
550 // Construct object file lists that may be needed to expand the
552 std::string buildObjs;
553 this->CreateObjectLists(useLinkScript, useArchiveRules, useResponseFile,
556 cmLocalGenerator::RuleVariables vars;
557 vars.TargetPDB = targetOutPathPDB.c_str();
559 // Setup the target version.
560 std::string targetVersionMajor;
561 std::string targetVersionMinor;
563 cmOStringStream majorStream;
564 cmOStringStream minorStream;
567 this->Target->GetTargetVersion(major, minor);
568 majorStream << major;
569 minorStream << minor;
570 targetVersionMajor = majorStream.str();
571 targetVersionMinor = minorStream.str();
573 vars.TargetVersionMajor = targetVersionMajor.c_str();
574 vars.TargetVersionMinor = targetVersionMinor.c_str();
576 vars.RuleLauncher = "RULE_LAUNCH_LINK";
577 vars.CMTarget = this->Target;
578 vars.Language = linkLanguage;
579 vars.Objects = buildObjs.c_str();
580 std::string objectDir = this->Target->GetSupportDirectory();
581 objectDir = this->Convert(objectDir.c_str(),
582 cmLocalGenerator::START_OUTPUT,
583 cmLocalGenerator::SHELL);
584 vars.ObjectDir = objectDir.c_str();
585 vars.Target = targetOutPathReal.c_str();
586 vars.LinkLibraries = linkLibs.c_str();
587 vars.ObjectsQuoted = buildObjs.c_str();
588 if (this->Target->HasSOName(this->ConfigName))
590 vars.SONameFlag = this->Makefile->GetSONameFlag(linkLanguage);
591 vars.TargetSOName= targetNameSO.c_str();
593 vars.LinkFlags = linkFlags.c_str();
595 // Compute the directory portion of the install_name setting.
596 std::string install_name_dir;
597 if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
599 // Get the install_name directory for the build tree.
601 this->Target->GetInstallNameDirForBuildTree(this->ConfigName);
603 // Set the rule variable replacement value.
604 if(install_name_dir.empty())
606 vars.TargetInstallNameDir = "";
610 // Convert to a path for the native build tool.
612 this->LocalGenerator->Convert(install_name_dir.c_str(),
613 cmLocalGenerator::NONE,
614 cmLocalGenerator::SHELL, false);
615 vars.TargetInstallNameDir = install_name_dir.c_str();
619 // Add language feature flags.
620 std::string langFlags;
621 this->AddFeatureFlags(langFlags, linkLanguage);
623 this->LocalGenerator->AddArchitectureFlags(langFlags, this->GeneratorTarget,
624 linkLanguage, this->ConfigName);
626 // remove any language flags that might not work with the
630 this->RemoveForbiddenFlags(forbiddenFlagVar,
631 linkLanguage, langFlags);
633 vars.LanguageCompileFlags = langFlags.c_str();
635 // Construct the main link rule and expand placeholders.
636 this->LocalGenerator->TargetImplib = targetOutPathImport;
639 // Construct the individual object list strings.
640 std::vector<std::string> object_strings;
641 this->WriteObjectsStrings(object_strings, archiveCommandLimit);
643 // Create the archive with the first set of objects.
644 std::vector<std::string>::iterator osi = object_strings.begin();
646 vars.Objects = osi->c_str();
647 for(std::vector<std::string>::const_iterator
648 i = archiveCreateCommands.begin();
649 i != archiveCreateCommands.end(); ++i)
651 std::string cmd = *i;
652 this->LocalGenerator->ExpandRuleVariables(cmd, vars);
653 real_link_commands.push_back(cmd);
656 // Append to the archive with the other object sets.
657 for(++osi; osi != object_strings.end(); ++osi)
659 vars.Objects = osi->c_str();
660 for(std::vector<std::string>::const_iterator
661 i = archiveAppendCommands.begin();
662 i != archiveAppendCommands.end(); ++i)
664 std::string cmd = *i;
665 this->LocalGenerator->ExpandRuleVariables(cmd, vars);
666 real_link_commands.push_back(cmd);
669 // Finish the archive.
671 for(std::vector<std::string>::const_iterator
672 i = archiveFinishCommands.begin();
673 i != archiveFinishCommands.end(); ++i)
675 std::string cmd = *i;
676 this->LocalGenerator->ExpandRuleVariables(cmd, vars);
677 real_link_commands.push_back(cmd);
682 // Get the set of commands.
683 std::string linkRule = this->GetLinkRule(linkRuleVar);
684 cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
686 // Expand placeholders.
687 for(std::vector<std::string>::iterator i = real_link_commands.begin();
688 i != real_link_commands.end(); ++i)
690 this->LocalGenerator->ExpandRuleVariables(*i, vars);
693 this->LocalGenerator->TargetImplib = "";
695 // Restore path conversion to normal shells.
696 this->LocalGenerator->SetLinkScriptShell(false);
699 // Optionally convert the build rule to use a script to avoid long
700 // command lines in the make shell.
703 // Use a link script.
704 const char* name = (relink? "relink.txt" : "link.txt");
705 this->CreateLinkScript(name, real_link_commands, commands1, depends);
709 // No link script. Just use the link rule directly.
710 commands1 = real_link_commands;
712 this->LocalGenerator->CreateCDCommand
714 this->Makefile->GetStartOutputDirectory(),
715 cmLocalGenerator::HOME_OUTPUT);
716 commands.insert(commands.end(), commands1.begin(), commands1.end());
719 // Add a rule to create necessary symlinks for the library.
720 // Frameworks are handled by cmOSXBundleGenerator.
721 if(targetOutPath != targetOutPathReal && !this->Target->IsFrameworkOnApple())
723 std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
724 symlink += targetOutPathReal;
726 symlink += targetOutPathSO;
728 symlink += targetOutPath;
729 commands1.push_back(symlink);
730 this->LocalGenerator->CreateCDCommand(commands1,
731 this->Makefile->GetStartOutputDirectory(),
732 cmLocalGenerator::HOME_OUTPUT);
733 commands.insert(commands.end(), commands1.begin(), commands1.end());
736 // Add the post-build rules when building but not when relinking.
739 this->LocalGenerator->
740 AppendCustomCommands(commands, this->Target->GetPostBuildCommands(),
744 // Write the build rule.
745 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
746 targetFullPathReal.c_str(),
747 depends, commands, false);
749 // Some targets have more than one output file. Create rules to
750 // drive the build if any extra outputs are missing.
751 std::vector<std::string> extraOutputs;
752 if(targetNameSO != targetNameReal)
754 this->GenerateExtraOutput(targetFullPathSO.c_str(),
755 targetFullPathReal.c_str());
757 if(targetName != targetNameSO &&
758 targetName != targetNameReal)
760 this->GenerateExtraOutput(targetFullPath.c_str(),
761 targetFullPathReal.c_str());
764 // Write the main driver rule to build everything in this target.
765 this->WriteTargetDriverRule(targetFullPath.c_str(), relink);
767 // Clean all the possible library names and symlinks.
768 this->CleanFiles.insert(this->CleanFiles.end(),
769 libCleanFiles.begin(),libCleanFiles.end());
772 //----------------------------------------------------------------------------
774 cmMakefileLibraryTargetGenerator
775 ::AppendOSXVerFlag(std::string& flags, const char* lang,
776 const char* name, bool so)
778 // Lookup the flag to specify the version.
779 std::string fvar = "CMAKE_";
783 fvar += "_VERSION_FLAG";
784 const char* flag = this->Makefile->GetDefinition(fvar.c_str());
786 // Skip if no such flag.
792 // Lookup the target version information.
796 this->Target->GetTargetVersion(so, major, minor, patch);
797 if(major > 0 || minor > 0 || patch > 0)
799 // Append the flag since a non-zero version is specified.
800 cmOStringStream vflag;
801 vflag << flag << major << "." << minor << "." << patch;
802 this->LocalGenerator->AppendFlags(flags, vflag.str().c_str());