Do not call CollapseFullPath for PDB file names
[cmake.git] / Source / cmMakefileLibraryTargetGenerator.cxx
blobf6eb07ef5746b120319b2f9fd813e03375345335
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileLibraryTargetGenerator.cxx,v $
5 Language: C++
6 Date: $Date: 2009-09-17 12:42:30 $
7 Version: $Revision: 1.78 $
9 Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
10 See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
12 This software is distributed WITHOUT ANY WARRANTY; without even
13 the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
14 PURPOSE. See the above copyright notices for more information.
16 =========================================================================*/
17 #include "cmMakefileLibraryTargetGenerator.h"
19 #include "cmGeneratedFileStream.h"
20 #include "cmGlobalUnixMakefileGenerator3.h"
21 #include "cmLocalUnixMakefileGenerator3.h"
22 #include "cmMakefile.h"
23 #include "cmSourceFile.h"
24 #include "cmTarget.h"
25 #include "cmake.h"
27 #include <memory> // auto_ptr
29 //----------------------------------------------------------------------------
30 cmMakefileLibraryTargetGenerator
31 ::cmMakefileLibraryTargetGenerator(cmTarget* target):
32 cmMakefileTargetGenerator(target)
34 this->CustomCommandDriver = OnDepends;
35 this->Target->GetLibraryNames(
36 this->TargetNameOut, this->TargetNameSO, this->TargetNameReal,
37 this->TargetNameImport, this->TargetNamePDB, this->ConfigName);
39 if(this->Target->IsFrameworkOnApple())
41 this->FrameworkVersion = this->Target->GetFrameworkVersion();
42 this->MacContentDirectory = this->Target->GetDirectory(this->ConfigName);
43 this->MacContentDirectory += "/";
44 this->MacContentDirectory += this->TargetNameOut;
45 this->MacContentDirectory += ".framework/Versions/";
46 this->MacContentDirectory += this->FrameworkVersion;
47 this->MacContentDirectory += "/";
51 //----------------------------------------------------------------------------
52 void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
54 // create the build.make file and directory, put in the common blocks
55 this->CreateRuleFile();
57 // write rules used to help build object files
58 this->WriteCommonCodeRules();
60 // write in rules for object files and custom commands
61 this->WriteTargetBuildRules();
63 // write the per-target per-language flags
64 this->WriteTargetLanguageFlags();
66 // write the link rules
67 // Write the rule for this target type.
68 switch(this->Target->GetType())
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))
77 // Write rules to link an installable version of the target.
78 this->WriteSharedLibraryRules(true);
80 break;
81 case cmTarget::MODULE_LIBRARY:
82 this->WriteModuleLibraryRules(false);
83 if(this->Target->NeedRelinkBeforeInstall(this->ConfigName))
85 // Write rules to link an installable version of the target.
86 this->WriteModuleLibraryRules(true);
88 break;
89 default:
90 // If language is not known, this is an error.
91 cmSystemTools::Error("Unknown Library Type");
92 break;
95 // Write the requires target.
96 this->WriteTargetRequiresRules();
98 // Write clean target
99 this->WriteTargetCleanRules();
101 // Write the dependency generation rule. This must be done last so
102 // that multiple output pair information is available.
103 this->WriteTargetDependRules();
105 // close the streams
106 this->CloseFileStreams();
109 //----------------------------------------------------------------------------
110 void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
112 const char* linkLanguage =
113 this->Target->GetLinkerLanguage(this->ConfigName);
114 std::string linkRuleVar = "CMAKE_";
115 if (linkLanguage)
117 linkRuleVar += linkLanguage;
119 linkRuleVar += "_CREATE_STATIC_LIBRARY";
121 std::string extraFlags;
122 this->LocalGenerator->AppendFlags
123 (extraFlags,this->Target->GetProperty("STATIC_LIBRARY_FLAGS"));
124 this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), false);
127 //----------------------------------------------------------------------------
128 void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
130 if(this->Target->IsFrameworkOnApple())
132 this->WriteFrameworkRules(relink);
133 return;
135 const char* linkLanguage =
136 this->Target->GetLinkerLanguage(this->ConfigName);
137 std::string linkRuleVar = "CMAKE_";
138 if (linkLanguage)
140 linkRuleVar += linkLanguage;
142 linkRuleVar += "_CREATE_SHARED_LIBRARY";
144 std::string extraFlags;
145 this->LocalGenerator->AppendFlags
146 (extraFlags, this->Target->GetProperty("LINK_FLAGS"));
147 std::string linkFlagsConfig = "LINK_FLAGS_";
148 linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
149 this->LocalGenerator->AppendFlags
150 (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
152 this->LocalGenerator->AddConfigVariableFlags
153 (extraFlags, "CMAKE_SHARED_LINKER_FLAGS", this->ConfigName);
154 if(this->Makefile->IsOn("WIN32") && !(this->Makefile->IsOn("CYGWIN")
155 || this->Makefile->IsOn("MINGW")))
157 const std::vector<cmSourceFile*>& sources =
158 this->Target->GetSourceFiles();
159 for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
160 i != sources.end(); ++i)
162 cmSourceFile* sf = *i;
163 if(sf->GetExtension() == "def")
165 extraFlags += " ";
166 extraFlags +=
167 this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
168 extraFlags +=
169 this->Convert(sf->GetFullPath().c_str(),
170 cmLocalGenerator::START_OUTPUT,
171 cmLocalGenerator::SHELL);
175 this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
178 //----------------------------------------------------------------------------
179 void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
181 const char* linkLanguage =
182 this->Target->GetLinkerLanguage(this->ConfigName);
183 std::string linkRuleVar = "CMAKE_";
184 if (linkLanguage)
186 linkRuleVar += linkLanguage;
188 linkRuleVar += "_CREATE_SHARED_MODULE";
190 std::string extraFlags;
191 this->LocalGenerator->AppendFlags(extraFlags,
192 this->Target->GetProperty("LINK_FLAGS"));
193 std::string linkFlagsConfig = "LINK_FLAGS_";
194 linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
195 this->LocalGenerator->AppendFlags
196 (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
197 this->LocalGenerator->AddConfigVariableFlags
198 (extraFlags, "CMAKE_MODULE_LINKER_FLAGS", this->ConfigName);
200 // TODO: .def files should be supported here also.
201 this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
204 //----------------------------------------------------------------------------
205 void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink)
207 const char* linkLanguage =
208 this->Target->GetLinkerLanguage(this->ConfigName);
209 std::string linkRuleVar = "CMAKE_";
210 if (linkLanguage)
212 linkRuleVar += linkLanguage;
214 linkRuleVar += "_CREATE_MACOSX_FRAMEWORK";
216 std::string extraFlags;
217 this->LocalGenerator->AppendFlags(extraFlags,
218 this->Target->GetProperty("LINK_FLAGS"));
219 std::string linkFlagsConfig = "LINK_FLAGS_";
220 linkFlagsConfig += cmSystemTools::UpperCase(this->ConfigName);
221 this->LocalGenerator->AppendFlags
222 (extraFlags, this->Target->GetProperty(linkFlagsConfig.c_str()));
223 this->LocalGenerator->AddConfigVariableFlags
224 (extraFlags, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS", this->ConfigName);
226 // TODO: .def files should be supported here also.
227 this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
230 //----------------------------------------------------------------------------
231 void
232 cmMakefileLibraryTargetGenerator
233 ::CreateFramework(std::string const& targetName)
235 // Configure the Info.plist file into the Resources directory.
236 this->MacContentFolders.insert("Resources");
237 std::string plist = this->MacContentDirectory + "Resources/Info.plist";
238 this->LocalGenerator->GenerateFrameworkInfoPList(this->Target,
239 targetName.c_str(),
240 plist.c_str());
242 // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
243 // drive rules to create these files at build time.
244 std::string oldName;
245 std::string newName;
247 // Compute the location of the top-level foo.framework directory.
248 std::string top = this->Target->GetDirectory(this->ConfigName);
249 top += "/";
250 top += this->TargetNameOut;
251 top += ".framework/";
253 // Make foo.framework/Versions
254 std::string versions = top;
255 versions += "Versions";
256 cmSystemTools::MakeDirectory(versions.c_str());
258 // Make foo.framework/Versions/version
259 std::string version = versions;
260 version += "/";
261 version += this->FrameworkVersion;
262 cmSystemTools::MakeDirectory(version.c_str());
264 // Current -> version
265 oldName = this->FrameworkVersion;
266 newName = versions;
267 newName += "/Current";
268 cmSystemTools::RemoveFile(newName.c_str());
269 cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
270 this->Makefile->AddCMakeOutputFile(newName.c_str());
272 // foo -> Versions/Current/foo
273 oldName = "Versions/Current/";
274 oldName += this->TargetNameOut;
275 newName = top;
276 newName += this->TargetNameOut;
277 cmSystemTools::RemoveFile(newName.c_str());
278 cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
279 this->Makefile->AddCMakeOutputFile(newName.c_str());
281 // Resources -> Versions/Current/Resources
282 if(this->MacContentFolders.find("Resources") !=
283 this->MacContentFolders.end())
285 oldName = "Versions/Current/Resources";
286 newName = top;
287 newName += "Resources";
288 cmSystemTools::RemoveFile(newName.c_str());
289 cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
290 this->Makefile->AddCMakeOutputFile(newName.c_str());
293 // Headers -> Versions/Current/Headers
294 if(this->MacContentFolders.find("Headers") !=
295 this->MacContentFolders.end())
297 oldName = "Versions/Current/Headers";
298 newName = top;
299 newName += "Headers";
300 cmSystemTools::RemoveFile(newName.c_str());
301 cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
302 this->Makefile->AddCMakeOutputFile(newName.c_str());
305 // PrivateHeaders -> Versions/Current/PrivateHeaders
306 if(this->MacContentFolders.find("PrivateHeaders") !=
307 this->MacContentFolders.end())
309 oldName = "Versions/Current/PrivateHeaders";
310 newName = top;
311 newName += "PrivateHeaders";
312 cmSystemTools::RemoveFile(newName.c_str());
313 cmSystemTools::CreateSymlink(oldName.c_str(), newName.c_str());
314 this->Makefile->AddCMakeOutputFile(newName.c_str());
318 //----------------------------------------------------------------------------
319 void cmMakefileLibraryTargetGenerator::WriteLibraryRules
320 (const char* linkRuleVar, const char* extraFlags, bool relink)
322 // TODO: Merge the methods that call this method to avoid
323 // code duplication.
324 std::vector<std::string> commands;
326 std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
327 std::string objTarget;
329 // Build list of dependencies.
330 std::vector<std::string> depends;
331 for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
332 obj != this->Objects.end(); ++obj)
334 objTarget = relPath;
335 objTarget += *obj;
336 depends.push_back(objTarget);
339 // Add dependencies on targets that must be built first.
340 this->AppendTargetDepends(depends);
342 // Add a dependency on the rule file itself.
343 this->LocalGenerator->AppendRuleDepend(depends,
344 this->BuildFileNameFull.c_str());
346 for(std::vector<std::string>::const_iterator obj
347 = this->ExternalObjects.begin();
348 obj != this->ExternalObjects.end(); ++obj)
350 depends.push_back(*obj);
353 // Get the language to use for linking this library.
354 const char* linkLanguage =
355 this->Target->GetLinkerLanguage(this->ConfigName);
357 // Make sure we have a link language.
358 if(!linkLanguage)
360 cmSystemTools::Error("Cannot determine link language for target \"",
361 this->Target->GetName(), "\".");
362 return;
365 // Create set of linking flags.
366 std::string linkFlags;
367 this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
369 // Add OSX version flags, if any.
370 if(this->Target->GetType() == cmTarget::SHARED_LIBRARY ||
371 this->Target->GetType() == cmTarget::MODULE_LIBRARY)
373 this->AppendOSXVerFlag(linkFlags, linkLanguage, "COMPATIBILITY", true);
374 this->AppendOSXVerFlag(linkFlags, linkLanguage, "CURRENT", false);
377 // Construct the name of the library.
378 std::string targetName;
379 std::string targetNameSO;
380 std::string targetNameReal;
381 std::string targetNameImport;
382 std::string targetNamePDB;
383 this->Target->GetLibraryNames(
384 targetName, targetNameSO, targetNameReal, targetNameImport, targetNamePDB,
385 this->ConfigName);
387 // Construct the full path version of the names.
388 std::string outpath;
389 std::string outpathImp;
390 if(this->Target->IsFrameworkOnApple())
392 outpath = this->MacContentDirectory;
393 this->CreateFramework(targetName);
395 else if(relink)
397 outpath = this->Makefile->GetStartOutputDirectory();
398 outpath += cmake::GetCMakeFilesDirectory();
399 outpath += "/CMakeRelink.dir";
400 cmSystemTools::MakeDirectory(outpath.c_str());
401 outpath += "/";
402 if(!targetNameImport.empty())
404 outpathImp = outpath;
407 else
409 outpath = this->Target->GetDirectory(this->ConfigName);
410 cmSystemTools::MakeDirectory(outpath.c_str());
411 outpath += "/";
412 if(!targetNameImport.empty())
414 outpathImp = this->Target->GetDirectory(this->ConfigName, true);
415 cmSystemTools::MakeDirectory(outpathImp.c_str());
416 outpathImp += "/";
420 std::string targetFullPath = outpath + targetName;
421 std::string targetFullPathPDB = outpath + targetNamePDB;
422 std::string targetFullPathSO = outpath + targetNameSO;
423 std::string targetFullPathReal = outpath + targetNameReal;
424 std::string targetFullPathImport = outpathImp + targetNameImport;
426 // Construct the output path version of the names for use in command
427 // arguments.
428 std::string targetOutPathPDB =
429 this->Convert(targetFullPathPDB.c_str(),cmLocalGenerator::NONE,
430 cmLocalGenerator::SHELL);
431 std::string targetOutPath =
432 this->Convert(targetFullPath.c_str(),cmLocalGenerator::START_OUTPUT,
433 cmLocalGenerator::SHELL);
434 std::string targetOutPathSO =
435 this->Convert(targetFullPathSO.c_str(),cmLocalGenerator::START_OUTPUT,
436 cmLocalGenerator::SHELL);
437 std::string targetOutPathReal =
438 this->Convert(targetFullPathReal.c_str(),cmLocalGenerator::START_OUTPUT,
439 cmLocalGenerator::SHELL);
440 std::string targetOutPathImport =
441 this->Convert(targetFullPathImport.c_str(),cmLocalGenerator::START_OUTPUT,
442 cmLocalGenerator::SHELL);
444 if(!this->NoRuleMessages)
446 // Add the link message.
447 std::string buildEcho = "Linking ";
448 buildEcho += linkLanguage;
449 switch(this->Target->GetType())
451 case cmTarget::STATIC_LIBRARY:
452 buildEcho += " static library ";
453 break;
454 case cmTarget::SHARED_LIBRARY:
455 buildEcho += " shared library ";
456 break;
457 case cmTarget::MODULE_LIBRARY:
458 buildEcho += " shared module ";
459 break;
460 default:
461 buildEcho += " library ";
462 break;
464 buildEcho += targetOutPath.c_str();
465 this->LocalGenerator->AppendEcho(commands, buildEcho.c_str(),
466 cmLocalUnixMakefileGenerator3::EchoLink);
469 const char* forbiddenFlagVar = 0;
470 switch(this->Target->GetType())
472 case cmTarget::SHARED_LIBRARY:
473 forbiddenFlagVar = "_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS";
474 break;
475 case cmTarget::MODULE_LIBRARY:
476 forbiddenFlagVar = "_CREATE_SHARED_MODULE_FORBIDDEN_FLAGS";
477 break;
478 default: break;
481 // Clean files associated with this library.
482 std::vector<std::string> libCleanFiles;
483 libCleanFiles.push_back(this->Convert(targetFullPath.c_str(),
484 cmLocalGenerator::START_OUTPUT,
485 cmLocalGenerator::UNCHANGED));
486 if(targetNameReal != targetName)
488 libCleanFiles.push_back(this->Convert(targetFullPathReal.c_str(),
489 cmLocalGenerator::START_OUTPUT,
490 cmLocalGenerator::UNCHANGED));
492 if(targetNameSO != targetName &&
493 targetNameSO != targetNameReal)
495 libCleanFiles.push_back(this->Convert(targetFullPathSO.c_str(),
496 cmLocalGenerator::START_OUTPUT,
497 cmLocalGenerator::UNCHANGED));
499 if(!targetNameImport.empty())
501 libCleanFiles.push_back(this->Convert(targetFullPathImport.c_str(),
502 cmLocalGenerator::START_OUTPUT,
503 cmLocalGenerator::UNCHANGED));
506 // List the PDB for cleaning only when the whole target is
507 // cleaned. We do not want to delete the .pdb file just before
508 // linking the target.
509 this->CleanFiles.push_back
510 (this->Convert(targetFullPathPDB.c_str(),
511 cmLocalGenerator::START_OUTPUT,
512 cmLocalGenerator::UNCHANGED));
514 #ifdef _WIN32
515 // There may be a manifest file for this target. Add it to the
516 // clean set just in case.
517 if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
519 libCleanFiles.push_back(
520 this->Convert((targetFullPath+".manifest").c_str(),
521 cmLocalGenerator::START_OUTPUT,
522 cmLocalGenerator::UNCHANGED));
524 #endif
526 std::vector<std::string> commands1;
527 // Add a command to remove any existing files for this library.
528 // for static libs only
529 if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
531 this->LocalGenerator->AppendCleanCommand(commands1, libCleanFiles,
532 *this->Target, "target");
533 this->LocalGenerator->CreateCDCommand
534 (commands1,
535 this->Makefile->GetStartOutputDirectory(),
536 cmLocalGenerator::HOME_OUTPUT);
537 commands.insert(commands.end(), commands1.begin(), commands1.end());
538 commands1.clear();
541 // Add the pre-build and pre-link rules building but not when relinking.
542 if(!relink)
544 this->LocalGenerator
545 ->AppendCustomCommands(commands, this->Target->GetPreBuildCommands(),
546 this->Target);
547 this->LocalGenerator
548 ->AppendCustomCommands(commands, this->Target->GetPreLinkCommands(),
549 this->Target);
552 // Determine whether a link script will be used.
553 bool useLinkScript = this->GlobalGenerator->GetUseLinkScript();
555 // Select whether to use a response file for objects.
556 bool useResponseFile = false;
558 std::string responseVar = "CMAKE_";
559 responseVar += linkLanguage;
560 responseVar += "_USE_RESPONSE_FILE_FOR_OBJECTS";
561 if(this->Makefile->IsOn(responseVar.c_str()))
563 useResponseFile = true;
567 // For static libraries there might be archiving rules.
568 bool haveStaticLibraryRule = false;
569 std::vector<std::string> archiveCreateCommands;
570 std::vector<std::string> archiveAppendCommands;
571 std::vector<std::string> archiveFinishCommands;
572 std::string::size_type archiveCommandLimit = std::string::npos;
573 if(this->Target->GetType() == cmTarget::STATIC_LIBRARY)
575 haveStaticLibraryRule =
576 this->Makefile->GetDefinition(linkRuleVar)? true:false;
577 std::string arCreateVar = "CMAKE_";
578 arCreateVar += linkLanguage;
579 arCreateVar += "_ARCHIVE_CREATE";
580 if(const char* rule = this->Makefile->GetDefinition(arCreateVar.c_str()))
582 cmSystemTools::ExpandListArgument(rule, archiveCreateCommands);
584 std::string arAppendVar = "CMAKE_";
585 arAppendVar += linkLanguage;
586 arAppendVar += "_ARCHIVE_APPEND";
587 if(const char* rule = this->Makefile->GetDefinition(arAppendVar.c_str()))
589 cmSystemTools::ExpandListArgument(rule, archiveAppendCommands);
591 std::string arFinishVar = "CMAKE_";
592 arFinishVar += linkLanguage;
593 arFinishVar += "_ARCHIVE_FINISH";
594 if(const char* rule = this->Makefile->GetDefinition(arFinishVar.c_str()))
596 cmSystemTools::ExpandListArgument(rule, archiveFinishCommands);
600 // Decide whether to use archiving rules.
601 bool useArchiveRules =
602 !haveStaticLibraryRule &&
603 !archiveCreateCommands.empty() && !archiveAppendCommands.empty();
604 if(useArchiveRules)
606 // Archiving rules are always run with a link script.
607 useLinkScript = true;
609 // Archiving rules never use a response file.
610 useResponseFile = false;
612 // Limit the length of individual object lists to less than the
613 // 32K command line length limit on Windows. We could make this a
614 // platform file variable but this should work everywhere.
615 archiveCommandLimit = 30000;
618 // Expand the rule variables.
619 std::vector<std::string> real_link_commands;
621 // Set path conversion for link script shells.
622 this->LocalGenerator->SetLinkScriptShell(useLinkScript);
624 // Collect up flags to link in needed libraries.
625 cmOStringStream linklibs;
626 if(this->Target->GetType() != cmTarget::STATIC_LIBRARY)
628 this->LocalGenerator
629 ->OutputLinkLibraries(linklibs, *this->Target, relink);
632 // Construct object file lists that may be needed to expand the
633 // rule.
634 std::string buildObjs;
635 this->CreateObjectLists(useLinkScript, useArchiveRules, useResponseFile,
636 buildObjs, depends);
638 cmLocalGenerator::RuleVariables vars;
639 vars.TargetPDB = targetOutPathPDB.c_str();
641 // Setup the target version.
642 std::string targetVersionMajor;
643 std::string targetVersionMinor;
645 cmOStringStream majorStream;
646 cmOStringStream minorStream;
647 int major;
648 int minor;
649 this->Target->GetTargetVersion(major, minor);
650 majorStream << major;
651 minorStream << minor;
652 targetVersionMajor = majorStream.str();
653 targetVersionMinor = minorStream.str();
655 vars.TargetVersionMajor = targetVersionMajor.c_str();
656 vars.TargetVersionMinor = targetVersionMinor.c_str();
658 vars.RuleLauncher = "RULE_LAUNCH_LINK";
659 vars.CMTarget = this->Target;
660 vars.Language = linkLanguage;
661 vars.Objects = buildObjs.c_str();
662 std::string objdir = cmake::GetCMakeFilesDirectoryPostSlash();
663 objdir += this->Target->GetName();
664 objdir += ".dir";
665 objdir = this->Convert(objdir.c_str(),
666 cmLocalGenerator::START_OUTPUT,
667 cmLocalGenerator::SHELL);
668 vars.ObjectDir = objdir.c_str();
669 vars.Target = targetOutPathReal.c_str();
670 std::string linkString = linklibs.str();
671 vars.LinkLibraries = linkString.c_str();
672 vars.ObjectsQuoted = buildObjs.c_str();
673 vars.TargetSOName= targetNameSO.c_str();
674 vars.LinkFlags = linkFlags.c_str();
676 // Compute the directory portion of the install_name setting.
677 std::string install_name_dir;
678 if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
680 // Get the install_name directory for the build tree.
681 install_name_dir =
682 this->Target->GetInstallNameDirForBuildTree(this->ConfigName);
684 // Set the rule variable replacement value.
685 if(install_name_dir.empty())
687 vars.TargetInstallNameDir = "";
689 else
691 // Convert to a path for the native build tool.
692 install_name_dir =
693 this->LocalGenerator->Convert(install_name_dir.c_str(),
694 cmLocalGenerator::NONE,
695 cmLocalGenerator::SHELL, false);
696 vars.TargetInstallNameDir = install_name_dir.c_str();
699 std::string langFlags;
700 this->LocalGenerator
701 ->AddLanguageFlags(langFlags, linkLanguage, this->ConfigName);
702 // remove any language flags that might not work with the
703 // particular os
704 if(forbiddenFlagVar)
706 this->RemoveForbiddenFlags(forbiddenFlagVar,
707 linkLanguage, langFlags);
709 vars.LanguageCompileFlags = langFlags.c_str();
711 // Construct the main link rule and expand placeholders.
712 this->LocalGenerator->TargetImplib = targetOutPathImport;
713 if(useArchiveRules)
715 // Construct the individual object list strings.
716 std::vector<std::string> object_strings;
717 this->WriteObjectsStrings(object_strings, archiveCommandLimit);
719 // Create the archive with the first set of objects.
720 std::vector<std::string>::iterator osi = object_strings.begin();
722 vars.Objects = osi->c_str();
723 for(std::vector<std::string>::const_iterator
724 i = archiveCreateCommands.begin();
725 i != archiveCreateCommands.end(); ++i)
727 std::string cmd = *i;
728 this->LocalGenerator->ExpandRuleVariables(cmd, vars);
729 real_link_commands.push_back(cmd);
732 // Append to the archive with the other object sets.
733 for(++osi; osi != object_strings.end(); ++osi)
735 vars.Objects = osi->c_str();
736 for(std::vector<std::string>::const_iterator
737 i = archiveAppendCommands.begin();
738 i != archiveAppendCommands.end(); ++i)
740 std::string cmd = *i;
741 this->LocalGenerator->ExpandRuleVariables(cmd, vars);
742 real_link_commands.push_back(cmd);
745 // Finish the archive.
746 vars.Objects = "";
747 for(std::vector<std::string>::const_iterator
748 i = archiveFinishCommands.begin();
749 i != archiveFinishCommands.end(); ++i)
751 std::string cmd = *i;
752 this->LocalGenerator->ExpandRuleVariables(cmd, vars);
753 real_link_commands.push_back(cmd);
756 else
758 // Get the set of commands.
759 std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
760 cmSystemTools::ExpandListArgument(linkRule, real_link_commands);
762 // Expand placeholders.
763 for(std::vector<std::string>::iterator i = real_link_commands.begin();
764 i != real_link_commands.end(); ++i)
766 this->LocalGenerator->ExpandRuleVariables(*i, vars);
769 this->LocalGenerator->TargetImplib = "";
771 // Restore path conversion to normal shells.
772 this->LocalGenerator->SetLinkScriptShell(false);
775 // Optionally convert the build rule to use a script to avoid long
776 // command lines in the make shell.
777 if(useLinkScript)
779 // Use a link script.
780 const char* name = (relink? "relink.txt" : "link.txt");
781 this->CreateLinkScript(name, real_link_commands, commands1, depends);
783 else
785 // No link script. Just use the link rule directly.
786 commands1 = real_link_commands;
788 this->LocalGenerator->CreateCDCommand
789 (commands1,
790 this->Makefile->GetStartOutputDirectory(),
791 cmLocalGenerator::HOME_OUTPUT);
792 commands.insert(commands.end(), commands1.begin(), commands1.end());
793 commands1.clear();
795 // Add a rule to create necessary symlinks for the library.
796 if(targetOutPath != targetOutPathReal)
798 std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
799 symlink += targetOutPathReal;
800 symlink += " ";
801 symlink += targetOutPathSO;
802 symlink += " ";
803 symlink += targetOutPath;
804 commands1.push_back(symlink);
805 this->LocalGenerator->CreateCDCommand(commands1,
806 this->Makefile->GetStartOutputDirectory(),
807 cmLocalGenerator::HOME_OUTPUT);
808 commands.insert(commands.end(), commands1.begin(), commands1.end());
809 commands1.clear();
811 // Add the post-build rules when building but not when relinking.
812 if(!relink)
814 this->LocalGenerator->
815 AppendCustomCommands(commands, this->Target->GetPostBuildCommands(),
816 this->Target);
819 // Write the build rule.
820 this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
821 targetFullPathReal.c_str(),
822 depends, commands, false);
824 // Some targets have more than one output file. Create rules to
825 // drive the build if any extra outputs are missing.
826 std::vector<std::string> extraOutputs;
827 if(targetNameSO != targetNameReal)
829 this->GenerateExtraOutput(targetFullPathSO.c_str(),
830 targetFullPathReal.c_str());
832 if(targetName != targetNameSO &&
833 targetName != targetNameReal)
835 this->GenerateExtraOutput(targetFullPath.c_str(),
836 targetFullPathReal.c_str());
839 // Write the main driver rule to build everything in this target.
840 this->WriteTargetDriverRule(targetFullPath.c_str(), relink);
842 // Clean all the possible library names and symlinks.
843 this->CleanFiles.insert(this->CleanFiles.end(),
844 libCleanFiles.begin(),libCleanFiles.end());
847 //----------------------------------------------------------------------------
848 void
849 cmMakefileLibraryTargetGenerator
850 ::AppendOSXVerFlag(std::string& flags, const char* lang,
851 const char* name, bool so)
853 // Lookup the flag to specify the version.
854 std::string fvar = "CMAKE_";
855 fvar += lang;
856 fvar += "_OSX_";
857 fvar += name;
858 fvar += "_VERSION_FLAG";
859 const char* flag = this->Makefile->GetDefinition(fvar.c_str());
861 // Skip if no such flag.
862 if(!flag)
864 return;
867 // Lookup the target version information.
868 int major;
869 int minor;
870 int patch;
871 this->Target->GetTargetVersion(so, major, minor, patch);
872 if(major > 0 || minor > 0 || patch > 0)
874 // Append the flag since a non-zero version is specified.
875 cmOStringStream vflag;
876 vflag << flag << major << "." << minor << "." << patch;
877 this->LocalGenerator->AppendFlags(flags, vflag.str().c_str());