1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileLibraryTargetGenerator.cxx,v $
6 Date: $Date: 2008-09-02 16:06:32 $
7 Version: $Revision: 1.64 $
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
,
38 this->LocalGenerator
->ConfigurationName
.c_str());
40 if(this->Target
->IsFrameworkOnApple())
42 this->FrameworkVersion
= this->Target
->GetFrameworkVersion();
43 this->MacContentDirectory
= this->Target
->GetDirectory();
44 this->MacContentDirectory
+= "/";
45 this->MacContentDirectory
+= this->TargetNameOut
;
46 this->MacContentDirectory
+= ".framework/Versions/";
47 this->MacContentDirectory
+= this->FrameworkVersion
;
48 this->MacContentDirectory
+= "/";
52 //----------------------------------------------------------------------------
53 void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
55 // create the build.make file and directory, put in the common blocks
56 this->CreateRuleFile();
58 // write rules used to help build object files
59 this->WriteCommonCodeRules();
61 // write in rules for object files and custom commands
62 this->WriteTargetBuildRules();
64 // write the per-target per-language flags
65 this->WriteTargetLanguageFlags();
67 // write the link rules
68 // Write the rule for this target type.
69 switch(this->Target
->GetType())
71 case cmTarget::STATIC_LIBRARY
:
72 this->WriteStaticLibraryRules();
74 case cmTarget::SHARED_LIBRARY
:
75 this->WriteSharedLibraryRules(false);
76 if(this->Target
->NeedRelinkBeforeInstall())
78 // Write rules to link an installable version of the target.
79 this->WriteSharedLibraryRules(true);
82 case cmTarget::MODULE_LIBRARY
:
83 this->WriteModuleLibraryRules(false);
84 if(this->Target
->NeedRelinkBeforeInstall())
86 // Write rules to link an installable version of the target.
87 this->WriteModuleLibraryRules(true);
91 // If language is not known, this is an error.
92 cmSystemTools::Error("Unknown Library Type");
96 // Write the requires target.
97 this->WriteTargetRequiresRules();
100 this->WriteTargetCleanRules();
102 // Write the dependency generation rule. This must be done last so
103 // that multiple output pair information is available.
104 this->WriteTargetDependRules();
107 this->CloseFileStreams();
110 //----------------------------------------------------------------------------
111 void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
113 const char* linkLanguage
=
114 this->Target
->GetLinkerLanguage(this->GlobalGenerator
);
115 std::string linkRuleVar
= "CMAKE_";
118 linkRuleVar
+= linkLanguage
;
120 linkRuleVar
+= "_CREATE_STATIC_LIBRARY";
122 std::string extraFlags
;
123 this->LocalGenerator
->AppendFlags
124 (extraFlags
,this->Target
->GetProperty("STATIC_LIBRARY_FLAGS"));
125 this->WriteLibraryRules(linkRuleVar
.c_str(), extraFlags
.c_str(), false);
128 //----------------------------------------------------------------------------
129 void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink
)
131 if(this->Target
->IsFrameworkOnApple())
133 this->WriteFrameworkRules(relink
);
136 const char* linkLanguage
=
137 this->Target
->GetLinkerLanguage(this->GlobalGenerator
);
138 std::string linkRuleVar
= "CMAKE_";
141 linkRuleVar
+= linkLanguage
;
143 linkRuleVar
+= "_CREATE_SHARED_LIBRARY";
145 std::string extraFlags
;
146 this->LocalGenerator
->AppendFlags
147 (extraFlags
, this->Target
->GetProperty("LINK_FLAGS"));
148 std::string linkFlagsConfig
= "LINK_FLAGS_";
150 cmSystemTools::UpperCase(this->LocalGenerator
->ConfigurationName
.c_str());
151 this->LocalGenerator
->AppendFlags
152 (extraFlags
, this->Target
->GetProperty(linkFlagsConfig
.c_str()));
154 this->LocalGenerator
->AddConfigVariableFlags
155 (extraFlags
, "CMAKE_SHARED_LINKER_FLAGS",
156 this->LocalGenerator
->ConfigurationName
.c_str());
157 if(this->Makefile
->IsOn("WIN32") && !(this->Makefile
->IsOn("CYGWIN")
158 || this->Makefile
->IsOn("MINGW")))
160 const std::vector
<cmSourceFile
*>& sources
=
161 this->Target
->GetSourceFiles();
162 for(std::vector
<cmSourceFile
*>::const_iterator i
= sources
.begin();
163 i
!= sources
.end(); ++i
)
165 cmSourceFile
* sf
= *i
;
166 if(sf
->GetExtension() == "def")
170 this->Makefile
->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
172 this->Convert(sf
->GetFullPath().c_str(),
173 cmLocalGenerator::START_OUTPUT
,
174 cmLocalGenerator::SHELL
);
178 this->WriteLibraryRules(linkRuleVar
.c_str(), extraFlags
.c_str(), relink
);
181 //----------------------------------------------------------------------------
182 void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink
)
184 const char* linkLanguage
=
185 this->Target
->GetLinkerLanguage(this->GlobalGenerator
);
186 std::string linkRuleVar
= "CMAKE_";
189 linkRuleVar
+= linkLanguage
;
191 linkRuleVar
+= "_CREATE_SHARED_MODULE";
193 std::string extraFlags
;
194 this->LocalGenerator
->AppendFlags(extraFlags
,
195 this->Target
->GetProperty("LINK_FLAGS"));
196 std::string linkFlagsConfig
= "LINK_FLAGS_";
198 cmSystemTools::UpperCase(this->LocalGenerator
->ConfigurationName
.c_str());
199 this->LocalGenerator
->AppendFlags
200 (extraFlags
, this->Target
->GetProperty(linkFlagsConfig
.c_str()));
201 this->LocalGenerator
->AddConfigVariableFlags
202 (extraFlags
, "CMAKE_MODULE_LINKER_FLAGS",
203 this->LocalGenerator
->ConfigurationName
.c_str());
205 // TODO: .def files should be supported here also.
206 this->WriteLibraryRules(linkRuleVar
.c_str(), extraFlags
.c_str(), relink
);
209 //----------------------------------------------------------------------------
210 void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink
)
212 const char* linkLanguage
=
213 this->Target
->GetLinkerLanguage(this->GlobalGenerator
);
214 std::string linkRuleVar
= "CMAKE_";
217 linkRuleVar
+= linkLanguage
;
219 linkRuleVar
+= "_CREATE_MACOSX_FRAMEWORK";
221 std::string extraFlags
;
222 this->LocalGenerator
->AppendFlags(extraFlags
,
223 this->Target
->GetProperty("LINK_FLAGS"));
224 std::string linkFlagsConfig
= "LINK_FLAGS_";
226 cmSystemTools::UpperCase(this->LocalGenerator
->ConfigurationName
.c_str());
227 this->LocalGenerator
->AppendFlags
228 (extraFlags
, this->Target
->GetProperty(linkFlagsConfig
.c_str()));
229 this->LocalGenerator
->AddConfigVariableFlags
230 (extraFlags
, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS",
231 this->LocalGenerator
->ConfigurationName
.c_str());
233 // TODO: .def files should be supported here also.
234 this->WriteLibraryRules(linkRuleVar
.c_str(), extraFlags
.c_str(), relink
);
237 //----------------------------------------------------------------------------
239 cmMakefileLibraryTargetGenerator
240 ::CreateFramework(std::string
const& targetName
)
242 // Configure the Info.plist file into the Resources directory.
243 this->MacContentFolders
.insert("Resources");
244 std::string plist
= this->MacContentDirectory
+ "Resources/Info.plist";
245 this->LocalGenerator
->GenerateFrameworkInfoPList(this->Target
,
249 // TODO: Use the cmMakefileTargetGenerator::ExtraFiles vector to
250 // drive rules to create these files at build time.
254 // Compute the location of the top-level foo.framework directory.
255 std::string top
= this->Target
->GetDirectory();
257 top
+= this->TargetNameOut
;
258 top
+= ".framework/";
260 // Make foo.framework/Versions
261 std::string versions
= top
;
262 versions
+= "Versions";
263 cmSystemTools::MakeDirectory(versions
.c_str());
265 // Make foo.framework/Versions/version
266 std::string version
= versions
;
268 version
+= this->FrameworkVersion
;
269 cmSystemTools::MakeDirectory(version
.c_str());
271 // Current -> version
272 oldName
= this->FrameworkVersion
;
274 newName
+= "/Current";
275 cmSystemTools::RemoveFile(newName
.c_str());
276 cmSystemTools::CreateSymlink(oldName
.c_str(), newName
.c_str());
277 this->Makefile
->AddCMakeOutputFile(newName
.c_str());
279 // foo -> Versions/Current/foo
280 oldName
= "Versions/Current/";
281 oldName
+= this->TargetNameOut
;
283 newName
+= this->TargetNameOut
;
284 cmSystemTools::RemoveFile(newName
.c_str());
285 cmSystemTools::CreateSymlink(oldName
.c_str(), newName
.c_str());
286 this->Makefile
->AddCMakeOutputFile(newName
.c_str());
288 // Resources -> Versions/Current/Resources
289 if(this->MacContentFolders
.find("Resources") !=
290 this->MacContentFolders
.end())
292 oldName
= "Versions/Current/Resources";
294 newName
+= "Resources";
295 cmSystemTools::RemoveFile(newName
.c_str());
296 cmSystemTools::CreateSymlink(oldName
.c_str(), newName
.c_str());
297 this->Makefile
->AddCMakeOutputFile(newName
.c_str());
300 // Headers -> Versions/Current/Headers
301 if(this->MacContentFolders
.find("Headers") !=
302 this->MacContentFolders
.end())
304 oldName
= "Versions/Current/Headers";
306 newName
+= "Headers";
307 cmSystemTools::RemoveFile(newName
.c_str());
308 cmSystemTools::CreateSymlink(oldName
.c_str(), newName
.c_str());
309 this->Makefile
->AddCMakeOutputFile(newName
.c_str());
312 // PrivateHeaders -> Versions/Current/PrivateHeaders
313 if(this->MacContentFolders
.find("PrivateHeaders") !=
314 this->MacContentFolders
.end())
316 oldName
= "Versions/Current/PrivateHeaders";
318 newName
+= "PrivateHeaders";
319 cmSystemTools::RemoveFile(newName
.c_str());
320 cmSystemTools::CreateSymlink(oldName
.c_str(), newName
.c_str());
321 this->Makefile
->AddCMakeOutputFile(newName
.c_str());
325 //----------------------------------------------------------------------------
326 void cmMakefileLibraryTargetGenerator::WriteLibraryRules
327 (const char* linkRuleVar
, const char* extraFlags
, bool relink
)
329 // TODO: Merge the methods that call this method to avoid
331 std::vector
<std::string
> commands
;
333 std::string relPath
= this->LocalGenerator
->GetHomeRelativeOutputPath();
334 std::string objTarget
;
336 // Build list of dependencies.
337 std::vector
<std::string
> depends
;
338 for(std::vector
<std::string
>::const_iterator obj
= this->Objects
.begin();
339 obj
!= this->Objects
.end(); ++obj
)
343 depends
.push_back(objTarget
);
346 // Add dependencies on targets that must be built first.
347 this->AppendTargetDepends(depends
);
349 // Add a dependency on the rule file itself.
350 this->LocalGenerator
->AppendRuleDepend(depends
,
351 this->BuildFileNameFull
.c_str());
353 for(std::vector
<std::string
>::const_iterator obj
354 = this->ExternalObjects
.begin();
355 obj
!= this->ExternalObjects
.end(); ++obj
)
357 depends
.push_back(*obj
);
360 // Get the language to use for linking this library.
361 const char* linkLanguage
=
362 this->Target
->GetLinkerLanguage(this->GlobalGenerator
);
364 // Make sure we have a link language.
367 cmSystemTools::Error("Cannot determine link language for target \"",
368 this->Target
->GetName(), "\".");
372 // Create set of linking flags.
373 std::string linkFlags
;
374 this->LocalGenerator
->AppendFlags(linkFlags
, extraFlags
);
376 // Add OSX version flags, if any.
377 if(this->Target
->GetType() == cmTarget::SHARED_LIBRARY
||
378 this->Target
->GetType() == cmTarget::MODULE_LIBRARY
)
380 this->AppendOSXVerFlag(linkFlags
, linkLanguage
, "COMPATIBILITY", true);
381 this->AppendOSXVerFlag(linkFlags
, linkLanguage
, "CURRENT", false);
384 // Construct the name of the library.
385 std::string targetName
;
386 std::string targetNameSO
;
387 std::string targetNameReal
;
388 std::string targetNameImport
;
389 std::string targetNamePDB
;
390 this->Target
->GetLibraryNames(
391 targetName
, targetNameSO
, targetNameReal
, targetNameImport
, targetNamePDB
,
392 this->LocalGenerator
->ConfigurationName
.c_str());
394 // Construct the full path version of the names.
396 std::string outpathImp
;
397 if(this->Target
->IsFrameworkOnApple())
399 outpath
= this->MacContentDirectory
;
400 this->CreateFramework(targetName
);
404 outpath
= this->Makefile
->GetStartOutputDirectory();
405 outpath
+= cmake::GetCMakeFilesDirectory();
406 outpath
+= "/CMakeRelink.dir";
407 cmSystemTools::MakeDirectory(outpath
.c_str());
409 if(!targetNameImport
.empty())
411 outpathImp
= outpath
;
416 outpath
= this->Target
->GetDirectory();
417 cmSystemTools::MakeDirectory(outpath
.c_str());
419 if(!targetNameImport
.empty())
421 outpathImp
= this->Target
->GetDirectory(0, true);
422 cmSystemTools::MakeDirectory(outpathImp
.c_str());
427 std::string targetFullPath
= outpath
+ targetName
;
428 std::string targetFullPathPDB
= outpath
+ targetNamePDB
;
429 std::string targetFullPathSO
= outpath
+ targetNameSO
;
430 std::string targetFullPathReal
= outpath
+ targetNameReal
;
431 std::string targetFullPathImport
= outpathImp
+ targetNameImport
;
433 // Construct the output path version of the names for use in command
435 std::string targetOutPathPDB
=
436 this->Convert(targetFullPathPDB
.c_str(),cmLocalGenerator::FULL
,
437 cmLocalGenerator::SHELL
);
438 std::string targetOutPath
=
439 this->Convert(targetFullPath
.c_str(),cmLocalGenerator::START_OUTPUT
,
440 cmLocalGenerator::SHELL
);
441 std::string targetOutPathSO
=
442 this->Convert(targetFullPathSO
.c_str(),cmLocalGenerator::START_OUTPUT
,
443 cmLocalGenerator::SHELL
);
444 std::string targetOutPathReal
=
445 this->Convert(targetFullPathReal
.c_str(),cmLocalGenerator::START_OUTPUT
,
446 cmLocalGenerator::SHELL
);
447 std::string targetOutPathImport
=
448 this->Convert(targetFullPathImport
.c_str(),cmLocalGenerator::START_OUTPUT
,
449 cmLocalGenerator::SHELL
);
451 // Add the link message.
452 std::string buildEcho
= "Linking ";
453 buildEcho
+= linkLanguage
;
454 const char* forbiddenFlagVar
= 0;
455 switch(this->Target
->GetType())
457 case cmTarget::STATIC_LIBRARY
:
458 buildEcho
+= " static library ";
460 case cmTarget::SHARED_LIBRARY
:
461 forbiddenFlagVar
= "_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS";
462 buildEcho
+= " shared library ";
464 case cmTarget::MODULE_LIBRARY
:
465 forbiddenFlagVar
= "_CREATE_SHARED_MODULE_FORBIDDEN_FLAGS";
466 buildEcho
+= " shared module ";
469 buildEcho
+= " library ";
472 buildEcho
+= targetOutPath
.c_str();
473 this->LocalGenerator
->AppendEcho(commands
, buildEcho
.c_str(),
474 cmLocalUnixMakefileGenerator3::EchoLink
);
476 // Construct a list of files associated with this library that may
477 // need to be cleaned.
478 std::vector
<std::string
> libCleanFiles
;
479 if(this->Target
->GetPropertyAsBool("CLEAN_DIRECT_OUTPUT"))
481 // The user has requested that only the files directly built
482 // by this target be cleaned instead of all possible names.
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
));
508 // This target may switch between static and shared based
509 // on a user option or the BUILD_SHARED_LIBS switch. Clean
510 // all possible names.
511 std::string cleanStaticName
;
512 std::string cleanSharedName
;
513 std::string cleanSharedSOName
;
514 std::string cleanSharedRealName
;
515 std::string cleanImportName
;
516 std::string cleanPDBName
;
517 this->Target
->GetLibraryCleanNames(
524 this->LocalGenerator
->ConfigurationName
.c_str());
525 std::string cleanFullStaticName
= outpath
+ cleanStaticName
;
526 std::string cleanFullSharedName
= outpath
+ cleanSharedName
;
527 std::string cleanFullSharedSOName
= outpath
+ cleanSharedSOName
;
528 std::string cleanFullSharedRealName
= outpath
+ cleanSharedRealName
;
529 std::string cleanFullImportName
= outpathImp
+ cleanImportName
;
530 std::string cleanFullPDBName
= outpath
+ cleanPDBName
;
531 libCleanFiles
.push_back
532 (this->Convert(cleanFullStaticName
.c_str(),
533 cmLocalGenerator::START_OUTPUT
,
534 cmLocalGenerator::UNCHANGED
));
535 if(cleanSharedRealName
!= cleanStaticName
)
537 libCleanFiles
.push_back(this->Convert(cleanFullSharedRealName
.c_str(),
538 cmLocalGenerator::START_OUTPUT
,
539 cmLocalGenerator::UNCHANGED
));
541 if(cleanSharedSOName
!= cleanStaticName
&&
542 cleanSharedSOName
!= cleanSharedRealName
)
544 libCleanFiles
.push_back(this->Convert(cleanFullSharedSOName
.c_str(),
545 cmLocalGenerator::START_OUTPUT
,
546 cmLocalGenerator::UNCHANGED
));
548 if(cleanSharedName
!= cleanStaticName
&&
549 cleanSharedName
!= cleanSharedSOName
&&
550 cleanSharedName
!= cleanSharedRealName
)
552 libCleanFiles
.push_back(this->Convert(cleanFullSharedName
.c_str(),
553 cmLocalGenerator::START_OUTPUT
,
554 cmLocalGenerator::UNCHANGED
));
556 if(!cleanImportName
.empty())
558 libCleanFiles
.push_back(this->Convert(cleanFullImportName
.c_str(),
559 cmLocalGenerator::START_OUTPUT
,
560 cmLocalGenerator::UNCHANGED
));
563 // List the PDB for cleaning only when the whole target is
564 // cleaned. We do not want to delete the .pdb file just before
565 // linking the target.
566 this->CleanFiles
.push_back
567 (this->Convert(cleanFullPDBName
.c_str(),
568 cmLocalGenerator::START_OUTPUT
,
569 cmLocalGenerator::UNCHANGED
));
573 // There may be a manifest file for this target. Add it to the
574 // clean set just in case.
575 if(this->Target
->GetType() != cmTarget::STATIC_LIBRARY
)
577 libCleanFiles
.push_back(
578 this->Convert((targetFullPath
+".manifest").c_str(),
579 cmLocalGenerator::START_OUTPUT
,
580 cmLocalGenerator::UNCHANGED
));
584 std::vector
<std::string
> commands1
;
585 // Add a command to remove any existing files for this library.
586 // for static libs only
587 if(this->Target
->GetType() == cmTarget::STATIC_LIBRARY
)
589 this->LocalGenerator
->AppendCleanCommand(commands1
, libCleanFiles
,
590 *this->Target
, "target");
591 this->LocalGenerator
->CreateCDCommand
593 this->Makefile
->GetStartOutputDirectory(),
594 this->Makefile
->GetHomeOutputDirectory());
595 commands
.insert(commands
.end(), commands1
.begin(), commands1
.end());
599 // Add the pre-build and pre-link rules building but not when relinking.
603 ->AppendCustomCommands(commands
, this->Target
->GetPreBuildCommands());
605 ->AppendCustomCommands(commands
, this->Target
->GetPreLinkCommands());
608 // Determine whether a link script will be used.
609 bool useLinkScript
= this->GlobalGenerator
->GetUseLinkScript();
611 // Select whether to use a response file for objects.
612 bool useResponseFile
= false;
614 std::string responseVar
= "CMAKE_";
615 responseVar
+= linkLanguage
;
616 responseVar
+= "_USE_RESPONSE_FILE_FOR_OBJECTS";
617 if(this->Makefile
->IsOn(responseVar
.c_str()))
619 useResponseFile
= true;
623 // For static libraries there might be archiving rules.
624 bool haveStaticLibraryRule
= false;
625 std::vector
<std::string
> archiveCreateCommands
;
626 std::vector
<std::string
> archiveAppendCommands
;
627 std::vector
<std::string
> archiveFinishCommands
;
628 std::string::size_type archiveCommandLimit
= std::string::npos
;
629 if(this->Target
->GetType() == cmTarget::STATIC_LIBRARY
)
631 haveStaticLibraryRule
=
632 this->Makefile
->GetDefinition(linkRuleVar
)? true:false;
633 std::string arCreateVar
= "CMAKE_";
634 arCreateVar
+= linkLanguage
;
635 arCreateVar
+= "_ARCHIVE_CREATE";
636 if(const char* rule
= this->Makefile
->GetDefinition(arCreateVar
.c_str()))
638 cmSystemTools::ExpandListArgument(rule
, archiveCreateCommands
);
640 std::string arAppendVar
= "CMAKE_";
641 arAppendVar
+= linkLanguage
;
642 arAppendVar
+= "_ARCHIVE_APPEND";
643 if(const char* rule
= this->Makefile
->GetDefinition(arAppendVar
.c_str()))
645 cmSystemTools::ExpandListArgument(rule
, archiveAppendCommands
);
647 std::string arFinishVar
= "CMAKE_";
648 arFinishVar
+= linkLanguage
;
649 arFinishVar
+= "_ARCHIVE_FINISH";
650 if(const char* rule
= this->Makefile
->GetDefinition(arFinishVar
.c_str()))
652 cmSystemTools::ExpandListArgument(rule
, archiveFinishCommands
);
656 // Decide whether to use archiving rules.
657 bool useArchiveRules
=
658 !haveStaticLibraryRule
&&
659 !archiveCreateCommands
.empty() && !archiveAppendCommands
.empty();
662 // Archiving rules are always run with a link script.
663 useLinkScript
= true;
665 // Archiving rules never use a response file.
666 useResponseFile
= false;
668 // Limit the length of individual object lists to less than the
669 // 32K command line length limit on Windows. We could make this a
670 // platform file variable but this should work everywhere.
671 archiveCommandLimit
= 30000;
674 // Expand the rule variables.
675 std::vector
<std::string
> real_link_commands
;
677 // Set path conversion for link script shells.
678 this->LocalGenerator
->SetLinkScriptShell(useLinkScript
);
680 // Collect up flags to link in needed libraries.
681 cmOStringStream linklibs
;
682 if(this->Target
->GetType() != cmTarget::STATIC_LIBRARY
)
685 ->OutputLinkLibraries(linklibs
, *this->Target
, relink
);
688 // Construct object file lists that may be needed to expand the
690 std::string variableName
;
691 std::string variableNameExternal
;
692 this->WriteObjectsVariable(variableName
, variableNameExternal
);
693 std::string buildObjs
;
697 this->WriteObjectsString(objects
);
698 std::string objects_rsp
=
699 this->CreateResponseFile("objects.rsp", objects
, depends
);
701 buildObjs
+= this->Convert(objects_rsp
.c_str(),
702 cmLocalGenerator::NONE
,
703 cmLocalGenerator::SHELL
);
705 else if(useLinkScript
)
709 this->WriteObjectsString(buildObjs
);
715 buildObjs
+= variableName
;
717 buildObjs
+= variableNameExternal
;
720 std::string cleanObjs
= "$(";
721 cleanObjs
+= variableName
;
723 cmLocalGenerator::RuleVariables vars
;
724 vars
.TargetPDB
= targetOutPathPDB
.c_str();
726 // Setup the target version.
727 std::string targetVersionMajor
;
728 std::string targetVersionMinor
;
730 cmOStringStream majorStream
;
731 cmOStringStream minorStream
;
734 this->Target
->GetTargetVersion(major
, minor
);
735 majorStream
<< major
;
736 minorStream
<< minor
;
737 targetVersionMajor
= majorStream
.str();
738 targetVersionMinor
= minorStream
.str();
740 vars
.TargetVersionMajor
= targetVersionMajor
.c_str();
741 vars
.TargetVersionMinor
= targetVersionMinor
.c_str();
743 vars
.Language
= linkLanguage
;
744 vars
.Objects
= buildObjs
.c_str();
745 std::string objdir
= cmake::GetCMakeFilesDirectoryPostSlash();
746 objdir
+= this->Target
->GetName();
748 objdir
= this->Convert(objdir
.c_str(),
749 cmLocalGenerator::START_OUTPUT
,
750 cmLocalGenerator::SHELL
);
751 vars
.ObjectDir
= objdir
.c_str();
752 vars
.Target
= targetOutPathReal
.c_str();
753 std::string linkString
= linklibs
.str();
754 vars
.LinkLibraries
= linkString
.c_str();
755 vars
.ObjectsQuoted
= buildObjs
.c_str();
756 vars
.TargetSOName
= targetNameSO
.c_str();
757 vars
.LinkFlags
= linkFlags
.c_str();
759 // Compute the directory portion of the install_name setting.
760 std::string install_name_dir
;
761 if(this->Target
->GetType() == cmTarget::SHARED_LIBRARY
)
763 // Get the install_name directory for the build tree.
764 const char* config
= this->LocalGenerator
->ConfigurationName
.c_str();
765 install_name_dir
= this->Target
->GetInstallNameDirForBuildTree(config
);
767 // Set the rule variable replacement value.
768 if(install_name_dir
.empty())
770 vars
.TargetInstallNameDir
= "";
774 // Convert to a path for the native build tool.
776 this->LocalGenerator
->Convert(install_name_dir
.c_str(),
777 cmLocalGenerator::NONE
,
778 cmLocalGenerator::SHELL
, false);
779 vars
.TargetInstallNameDir
= install_name_dir
.c_str();
782 std::string langFlags
;
784 ->AddLanguageFlags(langFlags
, linkLanguage
,
785 this->LocalGenerator
->ConfigurationName
.c_str());
786 // remove any language flags that might not work with the
790 this->RemoveForbiddenFlags(forbiddenFlagVar
,
791 linkLanguage
, langFlags
);
793 vars
.LanguageCompileFlags
= langFlags
.c_str();
795 // Construct the main link rule and expand placeholders.
796 this->LocalGenerator
->TargetImplib
= targetOutPathImport
;
799 // Construct the individual object list strings.
800 std::vector
<std::string
> object_strings
;
801 this->WriteObjectsStrings(object_strings
, archiveCommandLimit
);
803 // Create the archive with the first set of objects.
804 std::vector
<std::string
>::iterator osi
= object_strings
.begin();
806 vars
.Objects
= osi
->c_str();
807 for(std::vector
<std::string
>::const_iterator
808 i
= archiveCreateCommands
.begin();
809 i
!= archiveCreateCommands
.end(); ++i
)
811 std::string cmd
= *i
;
812 this->LocalGenerator
->ExpandRuleVariables(cmd
, vars
);
813 real_link_commands
.push_back(cmd
);
816 // Append to the archive with the other object sets.
817 for(++osi
; osi
!= object_strings
.end(); ++osi
)
819 vars
.Objects
= osi
->c_str();
820 for(std::vector
<std::string
>::const_iterator
821 i
= archiveAppendCommands
.begin();
822 i
!= archiveAppendCommands
.end(); ++i
)
824 std::string cmd
= *i
;
825 this->LocalGenerator
->ExpandRuleVariables(cmd
, vars
);
826 real_link_commands
.push_back(cmd
);
829 // Finish the archive.
831 for(std::vector
<std::string
>::const_iterator
832 i
= archiveFinishCommands
.begin();
833 i
!= archiveFinishCommands
.end(); ++i
)
835 std::string cmd
= *i
;
836 this->LocalGenerator
->ExpandRuleVariables(cmd
, vars
);
837 real_link_commands
.push_back(cmd
);
842 // Get the set of commands.
843 std::string linkRule
= this->Makefile
->GetRequiredDefinition(linkRuleVar
);
844 cmSystemTools::ExpandListArgument(linkRule
, real_link_commands
);
846 // Expand placeholders.
847 for(std::vector
<std::string
>::iterator i
= real_link_commands
.begin();
848 i
!= real_link_commands
.end(); ++i
)
850 this->LocalGenerator
->ExpandRuleVariables(*i
, vars
);
853 this->LocalGenerator
->TargetImplib
= "";
855 // Restore path conversion to normal shells.
856 this->LocalGenerator
->SetLinkScriptShell(false);
859 // Optionally convert the build rule to use a script to avoid long
860 // command lines in the make shell.
863 // Use a link script.
864 const char* name
= (relink
? "relink.txt" : "link.txt");
865 this->CreateLinkScript(name
, real_link_commands
, commands1
, depends
);
869 // No link script. Just use the link rule directly.
870 commands1
= real_link_commands
;
872 this->LocalGenerator
->CreateCDCommand
874 this->Makefile
->GetStartOutputDirectory(),
875 this->Makefile
->GetHomeOutputDirectory());
876 commands
.insert(commands
.end(), commands1
.begin(), commands1
.end());
879 // Add a rule to create necessary symlinks for the library.
880 if(targetOutPath
!= targetOutPathReal
)
882 std::string symlink
= "$(CMAKE_COMMAND) -E cmake_symlink_library ";
883 symlink
+= targetOutPathReal
;
885 symlink
+= targetOutPathSO
;
887 symlink
+= targetOutPath
;
888 commands1
.push_back(symlink
);
889 this->LocalGenerator
->CreateCDCommand(commands1
,
890 this->Makefile
->GetStartOutputDirectory(),
891 this->Makefile
->GetHomeOutputDirectory());
892 commands
.insert(commands
.end(), commands1
.begin(), commands1
.end());
895 // Add the post-build rules when building but not when relinking.
898 this->LocalGenerator
->
899 AppendCustomCommands(commands
, this->Target
->GetPostBuildCommands());
902 // Write the build rule.
903 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
904 targetFullPathReal
.c_str(),
905 depends
, commands
, false);
907 // Some targets have more than one output file. Create rules to
908 // drive the build if any extra outputs are missing.
909 std::vector
<std::string
> extraOutputs
;
910 if(targetNameSO
!= targetNameReal
)
912 this->GenerateExtraOutput(targetFullPathSO
.c_str(),
913 targetFullPathReal
.c_str());
915 if(targetName
!= targetNameSO
&&
916 targetName
!= targetNameReal
)
918 this->GenerateExtraOutput(targetFullPath
.c_str(),
919 targetFullPathReal
.c_str());
922 // Write the main driver rule to build everything in this target.
923 this->WriteTargetDriverRule(targetFullPath
.c_str(), relink
);
925 // Clean all the possible library names and symlinks.
926 this->CleanFiles
.insert(this->CleanFiles
.end(),
927 libCleanFiles
.begin(),libCleanFiles
.end());
930 //----------------------------------------------------------------------------
932 cmMakefileLibraryTargetGenerator
933 ::AppendOSXVerFlag(std::string
& flags
, const char* lang
,
934 const char* name
, bool so
)
936 // Lookup the flag to specify the version.
937 std::string fvar
= "CMAKE_";
941 fvar
+= "_VERSION_FLAG";
942 const char* flag
= this->Makefile
->GetDefinition(fvar
.c_str());
944 // Skip if no such flag.
950 // Lookup the target version information.
954 this->Target
->GetTargetVersion(so
, major
, minor
, patch
);
955 if(major
> 0 || minor
> 0 || patch
> 0)
957 // Append the flag since a non-zero version is specified.
958 cmOStringStream vflag
;
959 vflag
<< flag
<< major
<< "." << minor
<< "." << patch
;
960 this->LocalGenerator
->AppendFlags(flags
, vflag
.str().c_str());