| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496 |
- /*=========================================================================
- Program: CMake - Cross-Platform Makefile Generator
- Module: $RCSfile$
- Language: C++
- Date: $Date$
- Version: $Revision$
- Copyright (c) 2002 Kitware, Inc., Insight Consortium. All rights reserved.
- See Copyright.txt or http://www.cmake.org/HTML/Copyright.html for details.
- This software is distributed WITHOUT ANY WARRANTY; without even
- the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- PURPOSE. See the above copyright notices for more information.
- =========================================================================*/
- #include "cmMakefileLibraryTargetGenerator.h"
- #include "cmGeneratedFileStream.h"
- #include "cmGlobalGenerator.h"
- #include "cmLocalUnixMakefileGenerator3.h"
- #include "cmMakefile.h"
- #include "cmSourceFile.h"
- #include "cmTarget.h"
- //----------------------------------------------------------------------------
- void cmMakefileLibraryTargetGenerator::WriteRuleFiles()
- {
- // create the build.make file and directory, put in the common blocks
- this->CreateRuleFile();
-
- // Add in any rules for custom commands
- this->WriteCustomCommandsForTarget();
- // write in rules for object files
- this->WriteCommonCodeRules();
-
- // Write the dependency generation rule.
- this->WriteTargetDependRules();
- // write the link rules
- // Write the rule for this target type.
- switch(this->Target->GetType())
- {
- case cmTarget::STATIC_LIBRARY:
- this->WriteStaticLibraryRules();
- break;
- case cmTarget::SHARED_LIBRARY:
- this->WriteSharedLibraryRules(false);
- if(this->Target->NeedRelinkBeforeInstall())
- {
- // Write rules to link an installable version of the target.
- this->WriteSharedLibraryRules(true);
- }
- break;
- case cmTarget::MODULE_LIBRARY:
- this->WriteModuleLibraryRules(false);
- if(this->Target->NeedRelinkBeforeInstall())
- {
- // Write rules to link an installable version of the target.
- this->WriteModuleLibraryRules(true);
- }
- break;
- default:
- // If language is not known, this is an error.
- cmSystemTools::Error("Unknown Library Type");
- break;
- }
- // Write the requires target.
- this->WriteTargetRequiresRules();
- // Write clean target
- this->WriteTargetCleanRules();
- // close the streams
- this->CloseFileStreams();
- }
- //----------------------------------------------------------------------------
- void cmMakefileLibraryTargetGenerator::WriteStaticLibraryRules()
- {
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(this->GlobalGenerator);
- std::string linkRuleVar = "CMAKE_";
- if (linkLanguage)
- {
- linkRuleVar += linkLanguage;
- }
- linkRuleVar += "_CREATE_STATIC_LIBRARY";
- std::string extraFlags;
- this->LocalGenerator->AppendFlags(extraFlags, this->Target->GetProperty("STATIC_LIBRARY_FLAGS"));
- this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), false);
- }
- //----------------------------------------------------------------------------
- void cmMakefileLibraryTargetGenerator::WriteSharedLibraryRules(bool relink)
- {
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(this->GlobalGenerator);
- std::string linkRuleVar = "CMAKE_";
- if (linkLanguage)
- {
- linkRuleVar += linkLanguage;
- }
- linkRuleVar += "_CREATE_SHARED_LIBRARY";
- std::string extraFlags;
- this->LocalGenerator->AppendFlags(extraFlags, this->Target->GetProperty("LINK_FLAGS"));
- this->LocalGenerator->AddConfigVariableFlags(extraFlags, "CMAKE_SHARED_LINKER_FLAGS",
- this->LocalGenerator->m_ConfigurationName.c_str());
- if(this->Makefile->IsOn("WIN32") && !(this->Makefile->IsOn("CYGWIN") || this->Makefile->IsOn("MINGW")))
- {
- const std::vector<cmSourceFile*>& sources = this->Target->GetSourceFiles();
- for(std::vector<cmSourceFile*>::const_iterator i = sources.begin();
- i != sources.end(); ++i)
- {
- if((*i)->GetSourceExtension() == "def")
- {
- extraFlags += " ";
- extraFlags += this->Makefile->GetSafeDefinition("CMAKE_LINK_DEF_FILE_FLAG");
- extraFlags +=
- this->Convert((*i)->GetFullPath().c_str(),cmLocalGenerator::START_OUTPUT,cmLocalGenerator::MAKEFILE);
- }
- }
- }
- this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
- }
- //----------------------------------------------------------------------------
- void cmMakefileLibraryTargetGenerator::WriteModuleLibraryRules(bool relink)
- {
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(this->GlobalGenerator);
- std::string linkRuleVar = "CMAKE_";
- if (linkLanguage)
- {
- linkRuleVar += linkLanguage;
- }
- linkRuleVar += "_CREATE_SHARED_MODULE";
- std::string extraFlags;
- this->LocalGenerator->AppendFlags(extraFlags, this->Target->GetProperty("LINK_FLAGS"));
- this->LocalGenerator->AddConfigVariableFlags(extraFlags, "CMAKE_MODULE_LINKER_FLAGS",
- this->LocalGenerator->m_ConfigurationName.c_str());
- // TODO: .def files should be supported here also.
- this->WriteLibraryRules(linkRuleVar.c_str(), extraFlags.c_str(), relink);
- }
- //----------------------------------------------------------------------------
- void cmMakefileLibraryTargetGenerator::WriteLibraryRules
- (const char* linkRuleVar, const char* extraFlags, bool relink)
- {
- // TODO: Merge the methods that call this method to avoid
- // code duplication.
- std::vector<std::string> commands;
- std::string relPath = this->LocalGenerator->GetHomeRelativeOutputPath();
- std::string objTarget;
- // Build list of dependencies.
- std::vector<std::string> depends;
- for(std::vector<std::string>::const_iterator obj = this->Objects.begin();
- obj != this->Objects.end(); ++obj)
- {
- objTarget = relPath;
- objTarget += *obj;
- depends.push_back(objTarget);
- }
- // Add dependencies on targets that must be built first.
- this->AppendTargetDepends(depends);
- // Add a dependency on the rule file itself.
- this->LocalGenerator->AppendRuleDepend(depends,
- this->BuildFileNameFull.c_str());
-
- for(std::vector<std::string>::const_iterator obj
- = this->ExternalObjects.begin();
- obj != this->ExternalObjects.end(); ++obj)
- {
- depends.push_back(*obj);
- }
-
- // Get the language to use for linking this library.
- const char* linkLanguage =
- this->Target->GetLinkerLanguage(this->GlobalGenerator);
- // Make sure we have a link language.
- if(!linkLanguage)
- {
- cmSystemTools::Error("Cannot determine link language for target \"",
- this->Target->GetName(), "\".");
- return;
- }
- // Create set of linking flags.
- std::string linkFlags;
- this->LocalGenerator->AppendFlags(linkFlags, extraFlags);
- // Construct the name of the library.
- std::string targetName;
- std::string targetNameSO;
- std::string targetNameReal;
- std::string targetNameImport;
- this->Target->GetLibraryNames(
- targetName, targetNameSO, targetNameReal, targetNameImport,
- this->LocalGenerator->m_ConfigurationName.c_str());
- // Construct the full path version of the names.
- std::string outpath = this->LocalGenerator->m_LibraryOutputPath;
- if(outpath.length() == 0)
- {
- outpath = this->Makefile->GetStartOutputDirectory();
- outpath += "/";
- }
- if(relink)
- {
- outpath = this->Makefile->GetStartOutputDirectory();
- outpath += "/CMakeFiles/CMakeRelink.dir";
- cmSystemTools::MakeDirectory(outpath.c_str());
- outpath += "/";
- }
- std::string targetFullPath = outpath + targetName;
- std::string targetFullPathSO = outpath + targetNameSO;
- std::string targetFullPathReal = outpath + targetNameReal;
- std::string targetFullPathImport = outpath + targetNameImport;
- // Construct the output path version of the names for use in command
- // arguments.
- std::string targetOutPath =
- this->Convert(targetFullPath.c_str(),cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- std::string targetOutPathSO =
- this->Convert(targetFullPathSO.c_str(),cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- std::string targetOutPathReal =
- this->Convert(targetFullPathReal.c_str(),cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- std::string targetOutPathImport =
- this->Convert(targetFullPathImport.c_str(),cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::MAKEFILE);
- // Add the link message.
- std::string buildEcho = "Linking ";
- buildEcho += linkLanguage;
- switch(this->Target->GetType())
- {
- case cmTarget::STATIC_LIBRARY:
- buildEcho += " static library "; break;
- case cmTarget::SHARED_LIBRARY:
- buildEcho += " shared library "; break;
- case cmTarget::MODULE_LIBRARY:
- buildEcho += " shared module "; break;
- default:
- buildEcho += " library "; break;
- }
- buildEcho += targetOutPath.c_str();
- this->LocalGenerator->AppendEcho(commands, buildEcho.c_str());
- // Construct a list of files associated with this library that may
- // need to be cleaned.
- std::vector<std::string> libCleanFiles;
- {
- std::string cleanStaticName;
- std::string cleanSharedName;
- std::string cleanSharedSOName;
- std::string cleanSharedRealName;
- std::string cleanImportName;
- this->Target->GetLibraryCleanNames(
- cleanStaticName,
- cleanSharedName,
- cleanSharedSOName,
- cleanSharedRealName,
- cleanImportName,
- this->LocalGenerator->m_ConfigurationName.c_str());
- std::string cleanFullStaticName = outpath + cleanStaticName;
- std::string cleanFullSharedName = outpath + cleanSharedName;
- std::string cleanFullSharedSOName = outpath + cleanSharedSOName;
- std::string cleanFullSharedRealName = outpath + cleanSharedRealName;
- std::string cleanFullImportName = outpath + cleanImportName;
- libCleanFiles.push_back
- (this->Convert(cleanFullStaticName.c_str(),cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- if(cleanSharedRealName != cleanStaticName)
- {
- libCleanFiles.push_back(this->Convert(cleanFullSharedRealName.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
- if(cleanSharedSOName != cleanStaticName &&
- cleanSharedSOName != cleanSharedRealName)
- {
- libCleanFiles.push_back(this->Convert(cleanFullSharedSOName.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
- if(cleanSharedName != cleanStaticName &&
- cleanSharedName != cleanSharedSOName &&
- cleanSharedName != cleanSharedRealName)
- {
- libCleanFiles.push_back(this->Convert(cleanFullSharedName.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
- if(!cleanImportName.empty() &&
- cleanImportName != cleanStaticName &&
- cleanImportName != cleanSharedSOName &&
- cleanImportName != cleanSharedRealName &&
- cleanImportName != cleanSharedName)
- {
- libCleanFiles.push_back(this->Convert(cleanFullImportName.c_str(),
- cmLocalGenerator::START_OUTPUT,
- cmLocalGenerator::UNCHANGED));
- }
- }
- // Add a command to remove any existing files for this library.
- std::vector<std::string> commands1;
- this->LocalGenerator->AppendCleanCommand(commands1, libCleanFiles,
- *this->Target, "target");
- this->LocalGenerator->CreateCDCommand(commands1,
- this->Makefile->GetStartOutputDirectory(),
- this->Makefile->GetHomeOutputDirectory());
- commands.insert(commands.end(), commands1.begin(), commands1.end());
- commands1.clear();
- // Add the pre-build and pre-link rules building but not when relinking.
- if(!relink)
- {
- this->LocalGenerator
- ->AppendCustomCommands(commands, this->Target->GetPreBuildCommands());
- this->LocalGenerator
- ->AppendCustomCommands(commands, this->Target->GetPreLinkCommands());
- }
- // Construct the main link rule.
- std::string linkRule = this->Makefile->GetRequiredDefinition(linkRuleVar);
- cmSystemTools::ExpandListArgument(linkRule, commands1);
- this->LocalGenerator->CreateCDCommand(commands1,
- this->Makefile->GetStartOutputDirectory(),
- this->Makefile->GetHomeOutputDirectory());
- commands.insert(commands.end(), commands1.begin(), commands1.end());
- // Add a rule to create necessary symlinks for the library.
- if(targetOutPath != targetOutPathReal)
- {
- std::string symlink = "$(CMAKE_COMMAND) -E cmake_symlink_library ";
- symlink += targetOutPathReal;
- symlink += " ";
- symlink += targetOutPathSO;
- symlink += " ";
- symlink += targetOutPath;
- commands1.clear();
- commands1.push_back(symlink);
- this->LocalGenerator->CreateCDCommand(commands1,
- this->Makefile->GetStartOutputDirectory(),
- this->Makefile->GetHomeOutputDirectory());
- commands.insert(commands.end(), commands1.begin(), commands1.end());
- }
- // Add the post-build rules when building but not when relinking.
- if(!relink)
- {
- this->LocalGenerator->
- AppendCustomCommands(commands, this->Target->GetPostBuildCommands());
- }
- // Collect up flags to link in needed libraries.
- cmOStringStream linklibs;
- this->LocalGenerator->OutputLinkLibraries(linklibs, *this->Target, relink);
- // Construct object file lists that may be needed to expand the
- // rule.
- std::string variableName;
- std::string variableNameExternal;
- this->WriteObjectsVariable(variableName, variableNameExternal);
- std::string buildObjs = "$(";
- buildObjs += variableName;
- buildObjs += ") $(";
- buildObjs += variableNameExternal;
- buildObjs += ")";
- std::string cleanObjs = "$(";
- cleanObjs += variableName;
- cleanObjs += ")";
- cmLocalGenerator::RuleVariables vars;
- vars.Language = linkLanguage;
- vars.Objects = buildObjs.c_str();
- vars.Target = targetOutPathReal.c_str();
- std::string linkString = linklibs.str();
- vars.LinkLibraries = linkString.c_str();
- vars.ObjectsQuoted = buildObjs.c_str();
- vars.TargetSOName= targetNameSO.c_str();
- vars.LinkFlags = linkFlags.c_str();
- // Compute the directory portion of the install_name setting.
- std::string install_name_dir;
- if(this->Target->GetType() == cmTarget::SHARED_LIBRARY)
- {
- // Select whether to generate an install_name directory for the
- // install tree or the build tree.
- const char* config = this->LocalGenerator->m_ConfigurationName.c_str();
- if(this->Target->GetPropertyAsBool("BUILD_WITH_INSTALL_RPATH"))
- {
- install_name_dir =
- this->Target->GetInstallNameDirForInstallTree(config);
- }
- else
- {
- install_name_dir =
- this->Target->GetInstallNameDirForBuildTree(config);
- }
- // Set the rule variable replacement value.
- if(install_name_dir.empty())
- {
- vars.TargetInstallNameDir = "";
- }
- else
- {
- // Convert to a path for the native build tool.
- install_name_dir =
- this->LocalGenerator->Convert(install_name_dir.c_str(),
- cmLocalGenerator::FULL,
- cmLocalGenerator::SHELL, false);
- // The Convert method seems to strip trailing slashes, which should
- // probably be fixed. Since the only platform supporting install_name
- // right now uses forward slashes just add one.
- install_name_dir += "/";
- vars.TargetInstallNameDir = install_name_dir.c_str();
- }
- }
- std::string langFlags;
- this->LocalGenerator
- ->AddLanguageFlags(langFlags, linkLanguage,
- this->LocalGenerator->m_ConfigurationName.c_str());
- vars.LanguageCompileFlags = langFlags.c_str();
- // Expand placeholders in the commands.
- this->LocalGenerator->m_TargetImplib = targetOutPathImport;
- for(std::vector<std::string>::iterator i = commands.begin();
- i != commands.end(); ++i)
- {
- this->LocalGenerator->ExpandRuleVariables(*i, vars);
- }
- this->LocalGenerator->m_TargetImplib = "";
- // Write the build rule.
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- targetFullPathReal.c_str(),
- depends, commands, false);
- // The symlink names for the target should depend on the real target
- // so if the target version changes it rebuilds and recreates the
- // symlinks.
- if(targetFullPathSO != targetFullPathReal)
- {
- depends.clear();
- commands.clear();
- depends.push_back(targetFullPathReal.c_str());
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- targetFullPathSO.c_str(),
- depends, commands, false);
- }
- if(targetFullPath != targetFullPathSO)
- {
- depends.clear();
- commands.clear();
- depends.push_back(targetFullPathSO.c_str());
- this->LocalGenerator->WriteMakeRule(*this->BuildFileStream, 0,
- targetFullPath.c_str(),
- depends, commands, false);
- }
- // Write convenience targets.
- std::string dir = this->Makefile->GetStartOutputDirectory();
- dir += "/";
- dir += this->LocalGenerator->GetTargetDirectory(*this->Target);
- std::string buildTargetRuleName = dir;
- buildTargetRuleName += relink?"/preinstall":"/build";
- buildTargetRuleName =
- this->Convert(buildTargetRuleName.c_str(),
- cmLocalGenerator::HOME_OUTPUT,cmLocalGenerator::MAKEFILE);
- this->LocalGenerator->WriteConvenienceRule(*this->BuildFileStream,
- targetFullPath.c_str(),
- buildTargetRuleName.c_str());
- // Clean all the possible library names and symlinks and object files.
- this->CleanFiles.insert(this->CleanFiles.end(),
- libCleanFiles.begin(),libCleanFiles.end());
- this->CleanFiles.insert(this->CleanFiles.end(),
- this->Objects.begin(),
- this->Objects.end());
- }
|