1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileLibraryTargetGenerator.cxx,v $
6 Date: $Date: 2008/02/27 22:10:45 $
7 Version: $Revision: 1.58 $
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 if(const char* fversion
= this->Target
->GetProperty("FRAMEWORK_VERSION"))
44 this->FrameworkVersion
= fversion
;
46 else if(const char* tversion
= this->Target
->GetProperty("VERSION"))
48 this->FrameworkVersion
= tversion
;
52 this->FrameworkVersion
= "A";
54 this->MacContentDirectory
= this->Target
->GetDirectory();
55 this->MacContentDirectory
+= "/Versions/";
56 this->MacContentDirectory
+= this->FrameworkVersion
;
57 this->MacContentDirectory
+= "/";
61 //----------------------------------------------------------------------------
62 void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
64 // create the build.make file and directory, put in the common blocks
65 this->CreateRuleFile();
67 // write rules used to help build object files
68 this->WriteCommonCodeRules();
70 // write in rules for object files and custom commands
71 this->WriteTargetBuildRules();
73 // write the per-target per-language flags
74 this->WriteTargetLanguageFlags();
76 // write the link rules
77 // Write the rule for this target type.
78 switch(this->Target
->GetType())
80 case cmTarget::STATIC_LIBRARY
:
81 this->WriteStaticLibraryRules();
83 case cmTarget::SHARED_LIBRARY
:
84 this->WriteSharedLibraryRules(false);
85 if(this->Target
->NeedRelinkBeforeInstall())
87 // Write rules to link an installable version of the target.
88 this->WriteSharedLibraryRules(true);
91 case cmTarget::MODULE_LIBRARY
:
92 this->WriteModuleLibraryRules(false);
93 if(this->Target
->NeedRelinkBeforeInstall())
95 // Write rules to link an installable version of the target.
96 this->WriteModuleLibraryRules(true);
100 // If language is not known, this is an error.
101 cmSystemTools::Error("Unknown Library Type");
105 // Write the requires target.
106 this->WriteTargetRequiresRules();
108 // Write clean target
109 this->WriteTargetCleanRules();
111 // Write the dependency generation rule. This must be done last so
112 // that multiple output pair information is available.
113 this->WriteTargetDependRules();
116 this->CloseFileStreams();
119 //----------------------------------------------------------------------------
120 void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
122 const char* linkLanguage
=
123 this->Target
->GetLinkerLanguage(this->GlobalGenerator
);
124 std::string linkRuleVar
= "CMAKE_";
127 linkRuleVar
+= linkLanguage
;
129 linkRuleVar
+= "_CREATE_STATIC_LIBRARY";
131 std::string extraFlags
;
132 this->LocalGenerator
->AppendFlags
133 (extraFlags
,this->Target
->GetProperty("STATIC_LIBRARY_FLAGS"));
134 this->WriteLibraryRules(linkRuleVar
.c_str(), extraFlags
.c_str(), false);
137 //----------------------------------------------------------------------------
138 void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink
)
140 if(this->Target
->IsFrameworkOnApple())
142 this->WriteFrameworkRules(relink
);
145 const char* linkLanguage
=
146 this->Target
->GetLinkerLanguage(this->GlobalGenerator
);
147 std::string linkRuleVar
= "CMAKE_";
150 linkRuleVar
+= linkLanguage
;
152 linkRuleVar
+= "_CREATE_SHARED_LIBRARY";
154 std::string extraFlags
;
155 this->LocalGenerator
->AppendFlags
156 (extraFlags
, this->Target
->GetProperty("LINK_FLAGS"));
157 std::string linkFlagsConfig
= "LINK_FLAGS_";
159 cmSystemTools::UpperCase(this->LocalGenerator
->ConfigurationName
.c_str());
160 this->LocalGenerator
->AppendFlags
161 (extraFlags
, this->Target
->GetProperty(linkFlagsConfig
.c_str()));
163 this->LocalGenerator
->AddConfigVariableFlags
164 (extraFlags
, "CMAKE_SHARED_LINKER_FLAGS",
165 this->LocalGenerator
->ConfigurationName
.c_str());
166 if(this->Makefile
->IsOn("WIN32") && !(this->Makefile
->IsOn("CYGWIN")
167 || this->Makefile
->IsOn("MINGW")))
169 const std::vector
<cmSourceFile
*>& sources
=
170 this->Target
->GetSourceFiles();
171 for(std::vector
<cmSourceFile
*>::const_iterator i
= sources
.begin();
172 i
!= sources
.end(); ++i
)
174 cmSourceFile
* sf
= *i
;
175 if(sf
->GetExtension() == "def")
179 this->Makefile
->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
181 this->Convert(sf
->GetFullPath().c_str(),
182 cmLocalGenerator::START_OUTPUT
,
183 cmLocalGenerator::SHELL
);
187 this->WriteLibraryRules(linkRuleVar
.c_str(), extraFlags
.c_str(), relink
);
190 //----------------------------------------------------------------------------
191 void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink
)
193 const char* linkLanguage
=
194 this->Target
->GetLinkerLanguage(this->GlobalGenerator
);
195 std::string linkRuleVar
= "CMAKE_";
198 linkRuleVar
+= linkLanguage
;
200 linkRuleVar
+= "_CREATE_SHARED_MODULE";
202 std::string extraFlags
;
203 this->LocalGenerator
->AppendFlags(extraFlags
,
204 this->Target
->GetProperty("LINK_FLAGS"));
205 std::string linkFlagsConfig
= "LINK_FLAGS_";
207 cmSystemTools::UpperCase(this->LocalGenerator
->ConfigurationName
.c_str());
208 this->LocalGenerator
->AppendFlags
209 (extraFlags
, this->Target
->GetProperty(linkFlagsConfig
.c_str()));
210 this->LocalGenerator
->AddConfigVariableFlags
211 (extraFlags
, "CMAKE_MODULE_LINKER_FLAGS",
212 this->LocalGenerator
->ConfigurationName
.c_str());
214 // TODO: .def files should be supported here also.
215 this->WriteLibraryRules(linkRuleVar
.c_str(), extraFlags
.c_str(), relink
);
218 //----------------------------------------------------------------------------
219 void cmMakefileLibraryTargetGenerator::WriteFrameworkRules(bool relink
)
221 const char* linkLanguage
=
222 this->Target
->GetLinkerLanguage(this->GlobalGenerator
);
223 std::string linkRuleVar
= "CMAKE_";
226 linkRuleVar
+= linkLanguage
;
228 linkRuleVar
+= "_CREATE_MACOSX_FRAMEWORK";
230 std::string extraFlags
;
231 this->LocalGenerator
->AppendFlags(extraFlags
,
232 this->Target
->GetProperty("LINK_FLAGS"));
233 std::string linkFlagsConfig
= "LINK_FLAGS_";
235 cmSystemTools::UpperCase(this->LocalGenerator
->ConfigurationName
.c_str());
236 this->LocalGenerator
->AppendFlags
237 (extraFlags
, this->Target
->GetProperty(linkFlagsConfig
.c_str()));
238 this->LocalGenerator
->AddConfigVariableFlags
239 (extraFlags
, "CMAKE_MACOSX_FRAMEWORK_LINKER_FLAGS",
240 this->LocalGenerator
->ConfigurationName
.c_str());
242 // TODO: .def files should be supported here also.
243 this->WriteLibraryRules(linkRuleVar
.c_str(), extraFlags
.c_str(), relink
);
246 //----------------------------------------------------------------------------
247 void cmMakefileLibraryTargetGenerator::CreateFramework(
248 std::string
& targetName
,
249 std::string
& outpath
)
252 std::string symlink2
;
253 // Make foo.framework/Versions
254 std::string dir
= outpath
;
256 cmSystemTools::MakeDirectory(dir
.c_str());
257 std::string cwd
= cmSystemTools::GetCurrentWorkingDirectory();
258 // cd foo.framework to setup symlinks with relative paths
259 cmSystemTools::ChangeDirectory((outpath
+"Versions").c_str());
260 // Current -> version
261 symlink
= this->FrameworkVersion
;
262 symlink2
= "Current";
263 cmSystemTools::RemoveFile("Current");
264 cmSystemTools::CreateSymlink(symlink
.c_str(), symlink2
.c_str());
265 this->Makefile
->AddCMakeOutputFile((outpath
+ "Versions/Current").c_str());
266 // change to top level of framework to create next set of symlinks
267 cmSystemTools::ChangeDirectory(outpath
.c_str());
268 // foo -> Versions/Current/foo
269 symlink
= "Versions/Current/";
270 symlink
+= targetName
;
271 symlink2
= targetName
;
272 cmSystemTools::CreateSymlink(symlink
.c_str(), symlink2
.c_str());
273 this->Makefile
->AddCMakeOutputFile((outpath
+ targetName
).c_str());
274 // Resources -> Versions/Current/Resources
275 symlink
= "Versions/Current/Resources";
276 symlink2
= "Resources";
277 cmSystemTools::CreateSymlink(symlink
.c_str(), symlink2
.c_str());
278 this->Makefile
->AddCMakeOutputFile((outpath
+ "Resources").c_str());
279 // Headers -> Versions/Current/Headers
280 symlink
= "Versions/Current/Headers";
281 symlink2
= "Headers";
282 cmSystemTools::CreateSymlink(symlink
.c_str(), symlink2
.c_str());
283 this->Makefile
->AddCMakeOutputFile((outpath
+ "Headers").c_str());
284 // PrivateHeaders -> Versions/Current/PrivateHeaders
285 symlink
= "Versions/Current/PrivateHeaders";
286 symlink2
= "PrivateHeaders";
287 cmSystemTools::CreateSymlink(symlink
.c_str(), symlink2
.c_str());
288 this->Makefile
->AddCMakeOutputFile((outpath
+ "PrivateHeaders").c_str());
289 // go back to where we were
290 cmSystemTools::ChangeDirectory(cwd
.c_str());
293 //----------------------------------------------------------------------------
294 void cmMakefileLibraryTargetGenerator::WriteLibraryRules
295 (const char* linkRuleVar
, const char* extraFlags
, bool relink
)
297 // TODO: Merge the methods that call this method to avoid
299 std::vector
<std::string
> commands
;
301 std::string relPath
= this->LocalGenerator
->GetHomeRelativeOutputPath();
302 std::string objTarget
;
304 // Build list of dependencies.
305 std::vector
<std::string
> depends
;
306 for(std::vector
<std::string
>::const_iterator obj
= this->Objects
.begin();
307 obj
!= this->Objects
.end(); ++obj
)
311 depends
.push_back(objTarget
);
314 // Add dependencies on targets that must be built first.
315 this->AppendTargetDepends(depends
);
317 // Add a dependency on the rule file itself.
318 this->LocalGenerator
->AppendRuleDepend(depends
,
319 this->BuildFileNameFull
.c_str());
321 for(std::vector
<std::string
>::const_iterator obj
322 = this->ExternalObjects
.begin();
323 obj
!= this->ExternalObjects
.end(); ++obj
)
325 depends
.push_back(*obj
);
328 // Get the language to use for linking this library.
329 const char* linkLanguage
=
330 this->Target
->GetLinkerLanguage(this->GlobalGenerator
);
332 // Make sure we have a link language.
335 cmSystemTools::Error("Cannot determine link language for target \"",
336 this->Target
->GetName(), "\".");
340 // Create set of linking flags.
341 std::string linkFlags
;
342 this->LocalGenerator
->AppendFlags(linkFlags
, extraFlags
);
344 // Construct the name of the library.
345 std::string targetName
;
346 std::string targetNameSO
;
347 std::string targetNameReal
;
348 std::string targetNameImport
;
349 std::string targetNamePDB
;
350 this->Target
->GetLibraryNames(
351 targetName
, targetNameSO
, targetNameReal
, targetNameImport
, targetNamePDB
,
352 this->LocalGenerator
->ConfigurationName
.c_str());
354 // Construct the full path version of the names.
356 std::string outpathImp
;
359 outpath
= this->Makefile
->GetStartOutputDirectory();
360 outpath
+= cmake::GetCMakeFilesDirectory();
361 outpath
+= "/CMakeRelink.dir";
362 cmSystemTools::MakeDirectory(outpath
.c_str());
364 if(!targetNameImport
.empty())
366 outpathImp
= outpath
;
371 outpath
= this->Target
->GetDirectory();
373 if(!targetNameImport
.empty())
375 outpathImp
= this->Target
->GetDirectory(0, true);
380 // If we're creating a framework, place the output into a framework directory
381 if(this->Target
->IsFrameworkOnApple())
383 this->CreateFramework(targetName
, outpath
);
386 std::string targetFullPath
= outpath
+ targetName
;
387 std::string targetFullPathPDB
= outpath
+ targetNamePDB
;
388 std::string targetFullPathSO
= outpath
+ targetNameSO
;
389 std::string targetFullPathReal
= outpath
+ targetNameReal
;
390 std::string targetFullPathImport
= outpathImp
+ targetNameImport
;
392 // Construct the output path version of the names for use in command
394 std::string targetOutPathPDB
=
395 this->Convert(targetFullPathPDB
.c_str(),cmLocalGenerator::FULL
,
396 cmLocalGenerator::SHELL
);
397 std::string targetOutPath
=
398 this->Convert(targetFullPath
.c_str(),cmLocalGenerator::START_OUTPUT
,
399 cmLocalGenerator::SHELL
);
400 std::string targetOutPathSO
=
401 this->Convert(targetFullPathSO
.c_str(),cmLocalGenerator::START_OUTPUT
,
402 cmLocalGenerator::SHELL
);
403 std::string targetOutPathReal
=
404 this->Convert(targetFullPathReal
.c_str(),cmLocalGenerator::START_OUTPUT
,
405 cmLocalGenerator::SHELL
);
406 std::string targetOutPathImport
=
407 this->Convert(targetFullPathImport
.c_str(),cmLocalGenerator::START_OUTPUT
,
408 cmLocalGenerator::SHELL
);
410 // Add the link message.
411 std::string buildEcho
= "Linking ";
412 buildEcho
+= linkLanguage
;
413 const char* forbiddenFlagVar
= 0;
414 switch(this->Target
->GetType())
416 case cmTarget::STATIC_LIBRARY
:
417 buildEcho
+= " static library ";
419 case cmTarget::SHARED_LIBRARY
:
420 forbiddenFlagVar
= "_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS";
421 buildEcho
+= " shared library ";
423 case cmTarget::MODULE_LIBRARY
:
424 forbiddenFlagVar
= "_CREATE_SHARED_MODULE_FORBIDDEN_FLAGS";
425 buildEcho
+= " shared module ";
428 buildEcho
+= " library ";
431 buildEcho
+= targetOutPath
.c_str();
432 this->LocalGenerator
->AppendEcho(commands
, buildEcho
.c_str(),
433 cmLocalUnixMakefileGenerator3::EchoLink
);
435 // Construct a list of files associated with this library that may
436 // need to be cleaned.
437 std::vector
<std::string
> libCleanFiles
;
438 if(this->Target
->GetPropertyAsBool("CLEAN_DIRECT_OUTPUT"))
440 // The user has requested that only the files directly built
441 // by this target be cleaned instead of all possible names.
442 libCleanFiles
.push_back(this->Convert(targetFullPath
.c_str(),
443 cmLocalGenerator::START_OUTPUT
,
444 cmLocalGenerator::UNCHANGED
));
445 if(targetNameReal
!= targetName
)
447 libCleanFiles
.push_back(this->Convert(targetFullPathReal
.c_str(),
448 cmLocalGenerator::START_OUTPUT
,
449 cmLocalGenerator::UNCHANGED
));
451 if(targetNameSO
!= targetName
&&
452 targetNameSO
!= targetNameReal
)
454 libCleanFiles
.push_back(this->Convert(targetFullPathSO
.c_str(),
455 cmLocalGenerator::START_OUTPUT
,
456 cmLocalGenerator::UNCHANGED
));
458 if(!targetNameImport
.empty())
460 libCleanFiles
.push_back(this->Convert(targetFullPathImport
.c_str(),
461 cmLocalGenerator::START_OUTPUT
,
462 cmLocalGenerator::UNCHANGED
));
467 // This target may switch between static and shared based
468 // on a user option or the BUILD_SHARED_LIBS switch. Clean
469 // all possible names.
470 std::string cleanStaticName
;
471 std::string cleanSharedName
;
472 std::string cleanSharedSOName
;
473 std::string cleanSharedRealName
;
474 std::string cleanImportName
;
475 std::string cleanPDBName
;
476 this->Target
->GetLibraryCleanNames(
483 this->LocalGenerator
->ConfigurationName
.c_str());
484 std::string cleanFullStaticName
= outpath
+ cleanStaticName
;
485 std::string cleanFullSharedName
= outpath
+ cleanSharedName
;
486 std::string cleanFullSharedSOName
= outpath
+ cleanSharedSOName
;
487 std::string cleanFullSharedRealName
= outpath
+ cleanSharedRealName
;
488 std::string cleanFullImportName
= outpathImp
+ cleanImportName
;
489 std::string cleanFullPDBName
= outpath
+ cleanPDBName
;
490 libCleanFiles
.push_back
491 (this->Convert(cleanFullStaticName
.c_str(),
492 cmLocalGenerator::START_OUTPUT
,
493 cmLocalGenerator::UNCHANGED
));
494 if(cleanSharedRealName
!= cleanStaticName
)
496 libCleanFiles
.push_back(this->Convert(cleanFullSharedRealName
.c_str(),
497 cmLocalGenerator::START_OUTPUT
,
498 cmLocalGenerator::UNCHANGED
));
500 if(cleanSharedSOName
!= cleanStaticName
&&
501 cleanSharedSOName
!= cleanSharedRealName
)
503 libCleanFiles
.push_back(this->Convert(cleanFullSharedSOName
.c_str(),
504 cmLocalGenerator::START_OUTPUT
,
505 cmLocalGenerator::UNCHANGED
));
507 if(cleanSharedName
!= cleanStaticName
&&
508 cleanSharedName
!= cleanSharedSOName
&&
509 cleanSharedName
!= cleanSharedRealName
)
511 libCleanFiles
.push_back(this->Convert(cleanFullSharedName
.c_str(),
512 cmLocalGenerator::START_OUTPUT
,
513 cmLocalGenerator::UNCHANGED
));
515 if(!cleanImportName
.empty())
517 libCleanFiles
.push_back(this->Convert(cleanFullImportName
.c_str(),
518 cmLocalGenerator::START_OUTPUT
,
519 cmLocalGenerator::UNCHANGED
));
522 // List the PDB for cleaning only when the whole target is
523 // cleaned. We do not want to delete the .pdb file just before
524 // linking the target.
525 this->CleanFiles
.push_back
526 (this->Convert(cleanFullPDBName
.c_str(),
527 cmLocalGenerator::START_OUTPUT
,
528 cmLocalGenerator::UNCHANGED
));
532 // There may be a manifest file for this target. Add it to the
533 // clean set just in case.
534 if(this->Target
->GetType() != cmTarget::STATIC_LIBRARY
)
536 libCleanFiles
.push_back(
537 this->Convert((targetFullPath
+".manifest").c_str(),
538 cmLocalGenerator::START_OUTPUT
,
539 cmLocalGenerator::UNCHANGED
));
543 std::vector
<std::string
> commands1
;
544 // Add a command to remove any existing files for this library.
545 // for static libs only
546 if(this->Target
->GetType() == cmTarget::STATIC_LIBRARY
)
548 this->LocalGenerator
->AppendCleanCommand(commands1
, libCleanFiles
,
549 *this->Target
, "target");
550 this->LocalGenerator
->CreateCDCommand
552 this->Makefile
->GetStartOutputDirectory(),
553 this->Makefile
->GetHomeOutputDirectory());
554 commands
.insert(commands
.end(), commands1
.begin(), commands1
.end());
558 // Add the pre-build and pre-link rules building but not when relinking.
562 ->AppendCustomCommands(commands
, this->Target
->GetPreBuildCommands());
564 ->AppendCustomCommands(commands
, this->Target
->GetPreLinkCommands());
567 // Determine whether a link script will be used.
568 bool useLinkScript
= this->GlobalGenerator
->GetUseLinkScript();
570 // Select whether to use a response file for objects.
571 bool useResponseFile
= false;
573 std::string responseVar
= "CMAKE_";
574 responseVar
+= linkLanguage
;
575 responseVar
+= "_USE_RESPONSE_FILE_FOR_OBJECTS";
576 if(this->Makefile
->IsOn(responseVar
.c_str()))
578 useResponseFile
= true;
582 // For static libraries there might be archiving rules.
583 std::vector
<std::string
> archiveCreateCommands
;
584 std::vector
<std::string
> archiveAppendCommands
;
585 std::vector
<std::string
> archiveFinishCommands
;
586 std::string::size_type archiveCommandLimit
= std::string::npos
;
587 if(this->Target
->GetType() == cmTarget::STATIC_LIBRARY
)
589 std::string arCreateVar
= "CMAKE_";
590 arCreateVar
+= linkLanguage
;
591 arCreateVar
+= "_ARCHIVE_CREATE";
592 if(const char* rule
= this->Makefile
->GetDefinition(arCreateVar
.c_str()))
594 cmSystemTools::ExpandListArgument(rule
, archiveCreateCommands
);
596 std::string arAppendVar
= "CMAKE_";
597 arAppendVar
+= linkLanguage
;
598 arAppendVar
+= "_ARCHIVE_APPEND";
599 if(const char* rule
= this->Makefile
->GetDefinition(arAppendVar
.c_str()))
601 cmSystemTools::ExpandListArgument(rule
, archiveAppendCommands
);
603 std::string arFinishVar
= "CMAKE_";
604 arFinishVar
+= linkLanguage
;
605 arFinishVar
+= "_ARCHIVE_FINISH";
606 if(const char* rule
= this->Makefile
->GetDefinition(arFinishVar
.c_str()))
608 cmSystemTools::ExpandListArgument(rule
, archiveFinishCommands
);
612 // Decide whether to use archiving rules.
613 bool useArchiveRules
=
614 !archiveCreateCommands
.empty() && !archiveAppendCommands
.empty();
617 // Archiving rules are always run with a link script.
618 useLinkScript
= true;
620 // Archiving rules never use a response file.
621 useResponseFile
= false;
623 // Limit the length of individual object lists to less than the
624 // 32K command line length limit on Windows. We could make this a
625 // platform file variable but this should work everywhere.
626 archiveCommandLimit
= 30000;
629 // Expand the rule variables.
630 std::vector
<std::string
> real_link_commands
;
632 // Set path conversion for link script shells.
633 this->LocalGenerator
->SetLinkScriptShell(useLinkScript
);
635 // Collect up flags to link in needed libraries.
636 cmOStringStream linklibs
;
637 if(this->Target
->GetType() != cmTarget::STATIC_LIBRARY
)
640 ->OutputLinkLibraries(linklibs
, *this->Target
, relink
);
643 // Construct object file lists that may be needed to expand the
645 std::string variableName
;
646 std::string variableNameExternal
;
647 this->WriteObjectsVariable(variableName
, variableNameExternal
);
648 std::string buildObjs
;
652 this->WriteObjectsString(objects
);
653 std::string objects_rsp
=
654 this->CreateResponseFile("objects.rsp", objects
, depends
);
656 buildObjs
+= this->Convert(objects_rsp
.c_str(),
657 cmLocalGenerator::NONE
,
658 cmLocalGenerator::SHELL
);
660 else if(useLinkScript
)
664 this->WriteObjectsString(buildObjs
);
670 buildObjs
+= variableName
;
672 buildObjs
+= variableNameExternal
;
675 std::string cleanObjs
= "$(";
676 cleanObjs
+= variableName
;
678 cmLocalGenerator::RuleVariables vars
;
679 vars
.TargetPDB
= targetOutPathPDB
.c_str();
681 // Setup the target version.
682 std::string targetVersionMajor
;
683 std::string targetVersionMinor
;
685 cmOStringStream majorStream
;
686 cmOStringStream minorStream
;
689 this->Target
->GetTargetVersion(major
, minor
);
690 majorStream
<< major
;
691 minorStream
<< minor
;
692 targetVersionMajor
= majorStream
.str();
693 targetVersionMinor
= minorStream
.str();
695 vars
.TargetVersionMajor
= targetVersionMajor
.c_str();
696 vars
.TargetVersionMinor
= targetVersionMinor
.c_str();
698 vars
.Language
= linkLanguage
;
699 vars
.Objects
= buildObjs
.c_str();
700 std::string objdir
= cmake::GetCMakeFilesDirectoryPostSlash();
701 objdir
+= this->Target
->GetName();
703 vars
.ObjectDir
= objdir
.c_str();
704 vars
.Target
= targetOutPathReal
.c_str();
705 std::string linkString
= linklibs
.str();
706 vars
.LinkLibraries
= linkString
.c_str();
707 vars
.ObjectsQuoted
= buildObjs
.c_str();
708 vars
.TargetSOName
= targetNameSO
.c_str();
709 vars
.LinkFlags
= linkFlags
.c_str();
711 // Compute the directory portion of the install_name setting.
712 std::string install_name_dir
;
713 if(this->Target
->GetType() == cmTarget::SHARED_LIBRARY
)
715 // Get the install_name directory for the build tree.
716 const char* config
= this->LocalGenerator
->ConfigurationName
.c_str();
717 install_name_dir
= this->Target
->GetInstallNameDirForBuildTree(config
);
719 // Set the rule variable replacement value.
720 if(install_name_dir
.empty())
722 vars
.TargetInstallNameDir
= "";
726 // Convert to a path for the native build tool.
728 this->LocalGenerator
->Convert(install_name_dir
.c_str(),
729 cmLocalGenerator::NONE
,
730 cmLocalGenerator::SHELL
, false);
731 vars
.TargetInstallNameDir
= install_name_dir
.c_str();
734 std::string langFlags
;
736 ->AddLanguageFlags(langFlags
, linkLanguage
,
737 this->LocalGenerator
->ConfigurationName
.c_str());
738 // remove any language flags that might not work with the
742 this->RemoveForbiddenFlags(forbiddenFlagVar
,
743 linkLanguage
, langFlags
);
745 vars
.LanguageCompileFlags
= langFlags
.c_str();
747 // Construct the main link rule and expand placeholders.
748 this->LocalGenerator
->TargetImplib
= targetOutPathImport
;
751 // Construct the individual object list strings.
752 std::vector
<std::string
> object_strings
;
753 this->WriteObjectsStrings(object_strings
, archiveCommandLimit
);
755 // Create the archive with the first set of objects.
756 std::vector
<std::string
>::iterator osi
= object_strings
.begin();
758 vars
.Objects
= osi
->c_str();
759 for(std::vector
<std::string
>::const_iterator
760 i
= archiveCreateCommands
.begin();
761 i
!= archiveCreateCommands
.end(); ++i
)
763 std::string cmd
= *i
;
764 this->LocalGenerator
->ExpandRuleVariables(cmd
, vars
);
765 real_link_commands
.push_back(cmd
);
768 // Append to the archive with the other object sets.
769 for(++osi
; osi
!= object_strings
.end(); ++osi
)
771 vars
.Objects
= osi
->c_str();
772 for(std::vector
<std::string
>::const_iterator
773 i
= archiveAppendCommands
.begin();
774 i
!= archiveAppendCommands
.end(); ++i
)
776 std::string cmd
= *i
;
777 this->LocalGenerator
->ExpandRuleVariables(cmd
, vars
);
778 real_link_commands
.push_back(cmd
);
781 // Finish the archive.
783 for(std::vector
<std::string
>::const_iterator
784 i
= archiveFinishCommands
.begin();
785 i
!= archiveFinishCommands
.end(); ++i
)
787 std::string cmd
= *i
;
788 this->LocalGenerator
->ExpandRuleVariables(cmd
, vars
);
789 real_link_commands
.push_back(cmd
);
794 // Get the set of commands.
795 std::string linkRule
= this->Makefile
->GetRequiredDefinition(linkRuleVar
);
796 cmSystemTools::ExpandListArgument(linkRule
, real_link_commands
);
798 // Expand placeholders.
799 for(std::vector
<std::string
>::iterator i
= real_link_commands
.begin();
800 i
!= real_link_commands
.end(); ++i
)
802 this->LocalGenerator
->ExpandRuleVariables(*i
, vars
);
805 this->LocalGenerator
->TargetImplib
= "";
807 // Restore path conversion to normal shells.
808 this->LocalGenerator
->SetLinkScriptShell(false);
811 // Optionally convert the build rule to use a script to avoid long
812 // command lines in the make shell.
815 // Use a link script.
816 const char* name
= (relink
? "relink.txt" : "link.txt");
817 this->CreateLinkScript(name
, real_link_commands
, commands1
, depends
);
821 // No link script. Just use the link rule directly.
822 commands1
= real_link_commands
;
824 this->LocalGenerator
->CreateCDCommand
826 this->Makefile
->GetStartOutputDirectory(),
827 this->Makefile
->GetHomeOutputDirectory());
828 commands
.insert(commands
.end(), commands1
.begin(), commands1
.end());
831 // Add a rule to create necessary symlinks for the library.
832 if(targetOutPath
!= targetOutPathReal
)
834 std::string symlink
= "$(CMAKE_COMMAND) -E cmake_symlink_library ";
835 symlink
+= targetOutPathReal
;
837 symlink
+= targetOutPathSO
;
839 symlink
+= targetOutPath
;
840 commands1
.push_back(symlink
);
841 this->LocalGenerator
->CreateCDCommand(commands1
,
842 this->Makefile
->GetStartOutputDirectory(),
843 this->Makefile
->GetHomeOutputDirectory());
844 commands
.insert(commands
.end(), commands1
.begin(), commands1
.end());
847 // Add the post-build rules when building but not when relinking.
850 this->LocalGenerator
->
851 AppendCustomCommands(commands
, this->Target
->GetPostBuildCommands());
854 // Write the build rule.
855 this->LocalGenerator
->WriteMakeRule(*this->BuildFileStream
, 0,
856 targetFullPathReal
.c_str(),
857 depends
, commands
, false);
859 // Some targets have more than one output file. Create rules to
860 // drive the build if any extra outputs are missing.
861 std::vector
<std::string
> extraOutputs
;
862 if(targetNameSO
!= targetNameReal
)
864 this->GenerateExtraOutput(targetFullPathSO
.c_str(),
865 targetFullPathReal
.c_str());
867 if(targetName
!= targetNameSO
&&
868 targetName
!= targetNameReal
)
870 this->GenerateExtraOutput(targetFullPath
.c_str(),
871 targetFullPathReal
.c_str());
874 // Write the main driver rule to build everything in this target.
875 this->WriteTargetDriverRule(targetFullPath
.c_str(), relink
);
877 // Clean all the possible library names and symlinks.
878 this->CleanFiles
.insert(this->CleanFiles
.end(),
879 libCleanFiles
.begin(),libCleanFiles
.end());