1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileLibraryTargetGenerator.cxx,v $
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"
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();
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);
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);
90 // If language is not known, this is an error.
91 cmSystemTools::Error("Unknown Library Type");
95 // Write the requires target.
96 this->WriteTargetRequiresRules();
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();
106 this->CloseFileStreams();
109 //----------------------------------------------------------------------------
110 void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
112 const char* linkLanguage
=
113 this->Target
->GetLinkerLanguage(this->ConfigName
);
114 std::string linkRuleVar
= "CMAKE_";
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
);
135 const char* linkLanguage
=
136 this->Target
->GetLinkerLanguage(this->ConfigName
);
137 std::string linkRuleVar
= "CMAKE_";
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")
167 this->Makefile
->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
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_";
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_";
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 //----------------------------------------------------------------------------
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
,
242 // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
243 // drive rules to create these files at build time.
247 // Compute the location of the top-level foo.framework directory.
248 std::string top
= this->Target
->GetDirectory(this->ConfigName
);
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
;
261 version
+= this->FrameworkVersion
;
262 cmSystemTools::MakeDirectory(version
.c_str());
264 // Current -> version
265 oldName
= this->FrameworkVersion
;
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
;
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";
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";
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";
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
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
)
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.
360 cmSystemTools::Error("Cannot determine link language for target \"",
361 this->Target
->GetName(), "\".");
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
,
387 // Construct the full path version of the names.
389 std::string outpathImp
;
390 if(this->Target
->IsFrameworkOnApple())
392 outpath
= this->MacContentDirectory
;
393 this->CreateFramework(targetName
);
397 outpath
= this->Makefile
->GetStartOutputDirectory();
398 outpath
+= cmake::GetCMakeFilesDirectory();
399 outpath
+= "/CMakeRelink.dir";
400 cmSystemTools::MakeDirectory(outpath
.c_str());
402 if(!targetNameImport
.empty())
404 outpathImp
= outpath
;
409 outpath
= this->Target
->GetDirectory(this->ConfigName
);
410 cmSystemTools::MakeDirectory(outpath
.c_str());
412 if(!targetNameImport
.empty())
414 outpathImp
= this->Target
->GetDirectory(this->ConfigName
, true);
415 cmSystemTools::MakeDirectory(outpathImp
.c_str());
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
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 ";
454 case cmTarget::SHARED_LIBRARY
:
455 buildEcho
+= " shared library ";
457 case cmTarget::MODULE_LIBRARY
:
458 buildEcho
+= " shared module ";
461 buildEcho
+= " library ";
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";
475 case cmTarget::MODULE_LIBRARY
:
476 forbiddenFlagVar
= "_CREATE_SHARED_MODULE_FORBIDDEN_FLAGS";
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
));
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
));
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
535 this->Makefile
->GetStartOutputDirectory(),
536 cmLocalGenerator::HOME_OUTPUT
);
537 commands
.insert(commands
.end(), commands1
.begin(), commands1
.end());
541 // Add the pre-build and pre-link rules building but not when relinking.
545 ->AppendCustomCommands(commands
, this->Target
->GetPreBuildCommands(),
548 ->AppendCustomCommands(commands
, this->Target
->GetPreLinkCommands(),
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();
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
)
629 ->OutputLinkLibraries(linklibs
, *this->Target
, relink
);
632 // Construct object file lists that may be needed to expand the
634 std::string buildObjs
;
635 this->CreateObjectLists(useLinkScript
, useArchiveRules
, useResponseFile
,
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
;
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();
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.
682 this->Target
->GetInstallNameDirForBuildTree(this->ConfigName
);
684 // Set the rule variable replacement value.
685 if(install_name_dir
.empty())
687 vars
.TargetInstallNameDir
= "";
691 // Convert to a path for the native build tool.
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
;
701 ->AddLanguageFlags(langFlags
, linkLanguage
, this->ConfigName
);
702 // remove any language flags that might not work with the
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
;
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.
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
);
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.
779 // Use a link script.
780 const char* name
= (relink
? "relink.txt" : "link.txt");
781 this->CreateLinkScript(name
, real_link_commands
, commands1
, depends
);
785 // No link script. Just use the link rule directly.
786 commands1
= real_link_commands
;
788 this->LocalGenerator
->CreateCDCommand
790 this->Makefile
->GetStartOutputDirectory(),
791 cmLocalGenerator::HOME_OUTPUT
);
792 commands
.insert(commands
.end(), commands1
.begin(), commands1
.end());
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
;
801 symlink
+= targetOutPathSO
;
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());
811 // Add the post-build rules when building but not when relinking.
814 this->LocalGenerator
->
815 AppendCustomCommands(commands
, this->Target
->GetPostBuildCommands(),
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 //----------------------------------------------------------------------------
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_";
858 fvar
+= "_VERSION_FLAG";
859 const char* flag
= this->Makefile
->GetDefinition(fvar
.c_str());
861 // Skip if no such flag.
867 // Lookup the target version information.
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());