Resync
[CMakeLuaTailorHgBridge.git] / CMakeLua / Source / cmMakefileLibraryTargetGenerator.cxx
blobb450954081fcf83c287e9eb7a16b8c4557ba0e1b
1 /*=========================================================================
3 Program: CMake - Cross-Platform Makefile Generator
4 Module: $RCSfile: cmMakefileLibraryTargetGenerator.cxx,v $
5 Language: C++
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"
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,
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;
50 else
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();
82 break;
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);
90 break;
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);
98 break;
99 default:
100 // If language is not known, this is an error.
101 cmSystemTools::Error("Unknown Library Type");
102 break;
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();
115 // close the streams
116 this->CloseFileStreams();
119 //----------------------------------------------------------------------------
120 void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
122 const char* linkLanguage =
123 this->Target->GetLinkerLanguage(this->GlobalGenerator);
124 std::string linkRuleVar = "CMAKE_";
125 if (linkLanguage)
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);
143 return;
145 const char* linkLanguage =
146 this->Target->GetLinkerLanguage(this->GlobalGenerator);
147 std::string linkRuleVar = "CMAKE_";
148 if (linkLanguage)
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_";
158 linkFlagsConfig +=
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")
177 extraFlags += " ";
178 extraFlags +=
179 this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
180 extraFlags +=
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_";
196 if (linkLanguage)
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_";
206 linkFlagsConfig +=
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_";
224 if (linkLanguage)
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_";
234 linkFlagsConfig +=
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)
251 std::string symlink;
252 std::string symlink2;
253 // Make foo.framework/Versions
254 std::string dir = outpath;
255 dir += "Versions";
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
298 // code duplication.
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)
309 objTarget = relPath;
310 objTarget += *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.
333 if(!linkLanguage)
335 cmSystemTools::Error("Cannot determine link language for target \"",
336 this->Target->GetName(), "\".");
337 return;
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.
355 std::string outpath;
356 std::string outpathImp;
357 if(relink)
359 outpath = this->Makefile->GetStartOutputDirectory();
360 outpath += cmake::GetCMakeFilesDirectory();
361 outpath += "/CMakeRelink.dir";
362 cmSystemTools::MakeDirectory(outpath.c_str());
363 outpath += "/";
364 if(!targetNameImport.empty())
366 outpathImp = outpath;
369 else
371 outpath = this->Target->GetDirectory();
372 outpath += "/";
373 if(!targetNameImport.empty())
375 outpathImp = this->Target->GetDirectory(0, true);
376 outpathImp += "/";
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
393 // arguments.
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 ";
418 break;
419 case cmTarget::SHARED_LIBRARY:
420 forbiddenFlagVar = "_CREATE_SHARED_LIBRARY_FORBIDDEN_FLAGS";
421 buildEcho += " shared library ";
422 break;
423 case cmTarget::MODULE_LIBRARY:
424 forbiddenFlagVar = "_CREATE_SHARED_MODULE_FORBIDDEN_FLAGS";
425 buildEcho += " shared module ";
426 break;
427 default:
428 buildEcho += " library ";
429 break;
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));
465 else
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(
477 cleanStaticName,
478 cleanSharedName,
479 cleanSharedSOName,
480 cleanSharedRealName,
481 cleanImportName,
482 cleanPDBName,
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));
531 #ifdef _WIN32
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));
541 #endif
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
551 (commands1,
552 this->Makefile->GetStartOutputDirectory(),
553 this->Makefile->GetHomeOutputDirectory());
554 commands.insert(commands.end(), commands1.begin(), commands1.end());
555 commands1.clear();
558 // Add the pre-build and pre-link rules building but not when relinking.
559 if(!relink)
561 this->LocalGenerator
562 ->AppendCustomCommands(commands, this->Target->GetPreBuildCommands());
563 this->LocalGenerator
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();
615 if(useArchiveRules)
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)
639 this->LocalGenerator
640 ->OutputLinkLibraries(linklibs, *this->Target, relink);
643 // Construct object file lists that may be needed to expand the
644 // rule.
645 std::string variableName;
646 std::string variableNameExternal;
647 this->WriteObjectsVariable(variableName, variableNameExternal);
648 std::string buildObjs;
649 if(useResponseFile)
651 std::string objects;
652 this->WriteObjectsString(objects);
653 std::string objects_rsp =
654 this->CreateResponseFile("objects.rsp", objects, depends);
655 buildObjs = "@";
656 buildObjs += this->Convert(objects_rsp.c_str(),
657 cmLocalGenerator::NONE,
658 cmLocalGenerator::SHELL);
660 else if(useLinkScript)
662 if(!useArchiveRules)
664 this->WriteObjectsString(buildObjs);
667 else
669 buildObjs = "$(";
670 buildObjs += variableName;
671 buildObjs += ") $(";
672 buildObjs += variableNameExternal;
673 buildObjs += ")";
675 std::string cleanObjs = "$(";
676 cleanObjs += variableName;
677 cleanObjs += ")";
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;
687 int major;
688 int minor;
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();
702 objdir += ".dir";
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 = "";
724 else
726 // Convert to a path for the native build tool.
727 install_name_dir =
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;
735 this->LocalGenerator
736 ->AddLanguageFlags(langFlags, linkLanguage,
737 this->LocalGenerator->ConfigurationName.c_str());
738 // remove any language flags that might not work with the
739 // particular os
740 if(forbiddenFlagVar)
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;
749 if(useArchiveRules)
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.
782 vars.Objects = "";
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);
792 else
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.
813 if(useLinkScript)
815 // Use a link script.
816 const char* name = (relink? "relink.txt" : "link.txt");
817 this->CreateLinkScript(name, real_link_commands, commands1, depends);
819 else
821 // No link script. Just use the link rule directly.
822 commands1 = real_link_commands;
824 this->LocalGenerator->CreateCDCommand
825 (commands1,
826 this->Makefile->GetStartOutputDirectory(),
827 this->Makefile->GetHomeOutputDirectory());
828 commands.insert(commands.end(), commands1.begin(), commands1.end());
829 commands1.clear();
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;
836 symlink += " ";
837 symlink += targetOutPathSO;
838 symlink += " ";
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());
845 commands1.clear();
847 // Add the post-build rules when building but not when relinking.
848 if(!relink)
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());