diff options
author | Brad King <brad.king@kitware.com> | 2006-01-13 23:18:32 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2006-01-13 23:18:32 (GMT) |
commit | 22c62c9e65817e25b077f88222c682efa0188ccb (patch) | |
tree | 077abb80fc469c06f08cc4509ff72bcbee8384c7 /Source/cmTarget.cxx | |
parent | 262295615925c082ec3f98c3fc1f6c259d09ee6f (diff) | |
download | CMake-22c62c9e65817e25b077f88222c682efa0188ccb.zip CMake-22c62c9e65817e25b077f88222c682efa0188ccb.tar.gz CMake-22c62c9e65817e25b077f88222c682efa0188ccb.tar.bz2 |
BUG: Sweeping changes to cleanup computation of target names. This should
fix many bugs related to target names being computed inconsistently.
- Centralized computation of a target's file name to a method in
cmTarget. Now that global knowledge is always available the
*_CMAKE_PATH cache variables are no longer needed.
- Centralized computation of link library command lines and link
directory search order.
- Moved computation of link directories needed to link CMake targets
to be after evaluation of linking dependencies.
This also removed alot of duplicate code in which each version had its
own bugs.
This commit is surrounded by the tags
CMake-TargetNameCentralization1-pre
and
CMake-TargetNameCentralization1-post
so make the large set of changes easy to identify.
Diffstat (limited to 'Source/cmTarget.cxx')
-rw-r--r-- | Source/cmTarget.cxx | 310 |
1 files changed, 209 insertions, 101 deletions
diff --git a/Source/cmTarget.cxx b/Source/cmTarget.cxx index 3480794..c5471b8 100644 --- a/Source/cmTarget.cxx +++ b/Source/cmTarget.cxx @@ -24,6 +24,13 @@ #include <queue> #include <stdlib.h> // required for atof +//---------------------------------------------------------------------------- +cmTarget::cmTarget() +{ + m_Makefile = 0; + m_LinkLibrariesAnalyzed = false; + m_LinkDirectoriesComputed = false; +} void cmTarget::SetType(TargetType type, const char* name) { @@ -171,9 +178,7 @@ void cmTarget::TraceVSDependencies(std::string projFile, dep = cmSystemTools::GetFilenameWithoutLastExtension(dep); } // watch for target dependencies, - std::string libPath = dep + "_CMAKE_PATH"; - const char* cacheValue = makefile->GetDefinition(libPath.c_str()); - if (cacheValue && *cacheValue) + if(m_Makefile->GetLocalGenerator()->GetGlobalGenerator()->FindTarget(0, dep.c_str())) { // add the depend as a utility on the target this->AddUtility(dep.c_str()); @@ -271,14 +276,71 @@ void cmTarget::MergeLinkLibraries( cmMakefile& mf, m_PrevLinkedLibraries = libs; } +//---------------------------------------------------------------------------- void cmTarget::AddLinkDirectory(const char* d) { // Make sure we don't add unnecessary search directories. - if( std::find( m_LinkDirectories.begin(), m_LinkDirectories.end(), d ) - == m_LinkDirectories.end() ) - m_LinkDirectories.push_back( d ); + if(std::find(m_ExplicitLinkDirectories.begin(), + m_ExplicitLinkDirectories.end(), d) + == m_ExplicitLinkDirectories.end() ) + { + m_ExplicitLinkDirectories.push_back( d ); + m_LinkDirectoriesComputed = false; + } } +//---------------------------------------------------------------------------- +const std::vector<std::string>& cmTarget::GetLinkDirectories() +{ + // Make sure all library dependencies have been analyzed. + if(!m_LinkLibrariesAnalyzed && !m_LinkLibraries.empty()) + { + cmSystemTools::Error( + "cmTarget::GetLinkDirectories called before cmTarget::AnalyzeLibDependencies on target ", + m_Name.c_str()); + } + + // Make sure the complete set of link directories has been computed. + if(!m_LinkDirectoriesComputed) + { + // Compute the full set of link directories including the + // locations of targets that have been linked in. Start with the + // link directories given explicitly. + m_LinkDirectories = m_ExplicitLinkDirectories; + for(LinkLibraries::iterator ll = m_LinkLibraries.begin(); + ll != m_LinkLibraries.end(); ++ll) + { + // If this library is a CMake target then add its location as a + // link directory. + std::string lib = ll->first; + cmTarget* tgt = 0; + if(m_Makefile && m_Makefile->GetLocalGenerator() && + m_Makefile->GetLocalGenerator()->GetGlobalGenerator()) + { + tgt = (m_Makefile->GetLocalGenerator()->GetGlobalGenerator() + ->FindTarget(0, lib.c_str())); + } + if(tgt) + { + // Add the directory only if it is not already present. This + // is an N^2 algorithm for adding the directories, but N + // should not get very big. + const char* libpath = tgt->GetDirectory(); + if(std::find(m_LinkDirectories.begin(), m_LinkDirectories.end(), + libpath) == m_LinkDirectories.end()) + { + m_LinkDirectories.push_back(libpath); + } + } + } + + // The complete set of link directories has now been computed. + m_LinkDirectoriesComputed = true; + } + + // Return the complete set of link directories. + return m_LinkDirectories; +} void cmTarget::ClearDependencyInformation( cmMakefile& mf, const char* target ) { @@ -498,11 +560,6 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) // The dependency map. DependencyMap dep_map; - // If LIBRARY_OUTPUT_PATH is not set, then we must add search paths - // for all the new libraries added by the dependency analysis. - const char* libOutPath = mf.GetDefinition("LIBRARY_OUTPUT_PATH"); - bool addLibDirs = (libOutPath==0 || strcmp(libOutPath,"")==0); - // 1. Build the dependency graph // for(LinkLibraries::reverse_iterator lib = m_LinkLibraries.rbegin(); @@ -541,30 +598,11 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) } } - // 4. Add the new libraries to the link line. // for( std::vector<std::string>::reverse_iterator k = newLinkLibraries.rbegin(); k != newLinkLibraries.rend(); ++k ) { - if( addLibDirs ) - { - // who the hell knows what this is, I think that K contains the - // name of a library but ... Ken - // k contains the same stuff that are on the LINK_LIBRARIES - // commands. Normally, they would just be library names. -- Amitha. - std::string libPathStr = *k + "_CMAKE_PATH"; - const char* libpath = mf.GetDefinition( libPathStr.c_str() ); - if( libpath ) - { - // Don't add a link directory that is already present. - if(std::find(m_LinkDirectories.begin(), - m_LinkDirectories.end(), libpath) == m_LinkDirectories.end()) - { - m_LinkDirectories.push_back(libpath); - } - } - } std::string linkType = *k; linkType += "_LINK_TYPE"; cmTarget::LinkLibraryType llt = cmTarget::GENERAL; @@ -582,6 +620,7 @@ cmTarget::AnalyzeLibDependencies( const cmMakefile& mf ) } m_LinkLibraries.push_back( std::make_pair(*k,llt) ); } + m_LinkLibrariesAnalyzed = true; } @@ -724,6 +763,45 @@ void cmTarget::SetProperty(const char* prop, const char* value) m_Properties[prop] = value; } +const char* cmTarget::GetDirectory() +{ + switch( this->GetType() ) + { + case cmTarget::STATIC_LIBRARY: + case cmTarget::MODULE_LIBRARY: + case cmTarget::SHARED_LIBRARY: + m_Directory = m_Makefile->GetSafeDefinition("LIBRARY_OUTPUT_PATH"); + break; + case cmTarget::EXECUTABLE: + m_Directory = m_Makefile->GetSafeDefinition("EXECUTABLE_OUTPUT_PATH"); + break; + default: + return 0; + } + if(m_Directory.empty()) + { + m_Directory = m_Makefile->GetStartOutputDirectory(); + } + return m_Directory.c_str(); +} + +const char* cmTarget::GetLocation(const char* config) +{ + m_Location = this->GetDirectory(); + if(!m_Location.empty()) + { + m_Location += "/"; + } + const char* cfgid = m_Makefile->GetDefinition("CMAKE_CFG_INTDIR"); + if(cfgid && strcmp(cfgid, ".") != 0) + { + m_Location += cfgid; + m_Location += "/"; + } + m_Location += this->GetFullName(config); + return m_Location.c_str(); +} + void cmTarget::UpdateLocation() { // make sure we have a makefile @@ -908,12 +986,12 @@ const char* cmTarget::GetCreateRuleVariable() return ""; } -const char* cmTarget::GetSuffixVariable() +const char* cmTarget::GetSuffixVariable() { return this->GetSuffixVariableInternal(this->GetType()); } -const char* cmTarget::GetSuffixVariableInternal(TargetType type) +const char* cmTarget::GetSuffixVariableInternal(TargetType type) { switch(type) { @@ -958,15 +1036,81 @@ const char* cmTarget::GetPrefixVariableInternal(TargetType type) return ""; } -std::string cmTarget::GetFullName() +//---------------------------------------------------------------------------- +std::string cmTarget::GetFullName(const char* config) +{ + return this->GetFullNameInternal(this->GetType(), config); +} + +//---------------------------------------------------------------------------- +void cmTarget::GetFullName(std::string& prefix, std::string& base, + std::string& suffix, const char* config) +{ + this->GetFullNameInternal(this->GetType(), config, prefix, base, suffix); +} + +//---------------------------------------------------------------------------- +std::string cmTarget::GetFullPath(const char* config) +{ + // Start with the output directory for the target. + std::string fpath = this->GetDirectory(); + fpath += "/"; + + // Add the configuration's subdirectory. This may need to be replaced with + // a call into the generator found through m_Makefile so that each + // generator can map configuration names to output directories its own way. + if(config) + { + fpath += config; + fpath += "/"; + } + + // Add the full name of the target. + fpath += this->GetFullName(config); + return fpath; +} + +//---------------------------------------------------------------------------- +std::string cmTarget::GetFullNameInternal(TargetType type, const char* config) { - return this->GetFullNameInternal(this->GetType()); + std::string prefix; + std::string base; + std::string suffix; + this->GetFullNameInternal(type, config, prefix, base, suffix); + return prefix+base+suffix; } -std::string cmTarget::GetFullNameInternal(TargetType type) +//---------------------------------------------------------------------------- +void cmTarget::GetFullNameInternal(TargetType type, + const char* config, + std::string& outPrefix, + std::string& outBase, + std::string& outSuffix) { + // Use just the target name for non-main target types. + if(type != cmTarget::STATIC_LIBRARY && + type != cmTarget::SHARED_LIBRARY && + type != cmTarget::MODULE_LIBRARY && + type != cmTarget::EXECUTABLE) + { + outPrefix = ""; + outBase = this->GetName(); + outSuffix = ""; + return; + } + + // Compute the full name for main target types. const char* targetPrefix = this->GetProperty("PREFIX"); const char* targetSuffix = this->GetProperty("SUFFIX"); + const char* configPostfix = 0; + if(config && *config && type != cmTarget::EXECUTABLE) + { + std::string configVar = "CMAKE_"; + configVar += config; + configVar += "_POSTFIX"; + configVar = cmSystemTools::UpperCase(configVar); + configPostfix = m_Makefile->GetDefinition(configVar.c_str()); + } const char* prefixVar = this->GetPrefixVariableInternal(type); const char* suffixVar = this->GetSuffixVariableInternal(type); const char* ll = @@ -999,91 +1143,48 @@ std::string cmTarget::GetFullNameInternal(TargetType type) } // Begin the final name with the prefix. - std::string name = targetPrefix?targetPrefix:""; + outPrefix = targetPrefix?targetPrefix:""; // Append the target name or property-specified name. Support this // only for executable targets. const char* outname = this->GetProperty("OUTPUT_NAME"); if(outname && type == cmTarget::EXECUTABLE) { - name += outname; + outBase = outname; } else { - name += this->GetName(); + outBase = this->GetName(); } - // Append the suffix. - name += targetSuffix?targetSuffix:""; - - // Return the final name. - return name; -} - -std::string cmTarget::GetBaseName() -{ - return this->GetBaseNameInternal(this->GetType()); -} + // Append the per-configuration postfix. + outBase += configPostfix?configPostfix:""; -std::string -cmTarget::GetBaseNameInternal(TargetType type) -{ - std::string pathPrefix = ""; -#ifdef __APPLE__ - if(this->GetPropertyAsBool("MACOSX_BUNDLE")) - { - pathPrefix = this->GetName(); - pathPrefix += ".app/Contents/MacOS/"; - } -#endif - const char* targetPrefix = this->GetProperty("PREFIX"); - const char* prefixVar = this->GetPrefixVariableInternal(type); - // if there is no prefix on the target use the cmake definition - if(!targetPrefix && prefixVar) - { - // first check for a language specific suffix var - const char* ll = - this->GetLinkerLanguage( - m_Makefile->GetLocalGenerator()->GetGlobalGenerator()); - if(ll) - { - std::string langPrefix = prefixVar + std::string("_") + ll; - targetPrefix = m_Makefile->GetDefinition(langPrefix.c_str()); - } - // if there not a language specific suffix then use the general one - if(!targetPrefix) - { - targetPrefix = m_Makefile->GetSafeDefinition(prefixVar); - } - } - std::string name = pathPrefix; - name += targetPrefix?targetPrefix:""; - name += this->GetName(); - return name; + // Append the suffix. + outSuffix = targetSuffix?targetSuffix:""; } void cmTarget::GetLibraryNames(std::string& name, std::string& soName, std::string& realName, - std::string& baseName) + const char* config) { // Get the names based on the real type of the library. - this->GetLibraryNamesInternal(name, soName, realName, this->GetType()); - - // The library name without extension. - baseName = this->GetBaseName(); + this->GetLibraryNamesInternal(name, soName, realName, this->GetType(), + config); } void cmTarget::GetLibraryCleanNames(std::string& staticName, std::string& sharedName, std::string& sharedSOName, - std::string& sharedRealName) + std::string& sharedRealName, + const char* config) { // Get the name as if this were a static library. std::string soName; std::string realName; this->GetLibraryNamesInternal(staticName, soName, realName, - cmTarget::STATIC_LIBRARY); + cmTarget::STATIC_LIBRARY, config); // Get the names as if this were a shared library. if(this->GetType() == cmTarget::STATIC_LIBRARY) @@ -1094,20 +1195,23 @@ void cmTarget::GetLibraryCleanNames(std::string& staticName, // type will never be MODULE. Either way the only names that // might have to be cleaned are the shared library names. this->GetLibraryNamesInternal(sharedName, sharedSOName, - sharedRealName, cmTarget::SHARED_LIBRARY); + sharedRealName, cmTarget::SHARED_LIBRARY, + config); } else { // Use the name of the real type of the library (shared or module). this->GetLibraryNamesInternal(sharedName, sharedSOName, - sharedRealName, this->GetType()); + sharedRealName, this->GetType(), + config); } } void cmTarget::GetLibraryNamesInternal(std::string& name, std::string& soName, std::string& realName, - TargetType type) + TargetType type, + const char* config) { // Construct the name of the soname flag variable for this language. const char* ll = @@ -1140,7 +1244,7 @@ void cmTarget::GetLibraryNamesInternal(std::string& name, } // The library name. - name = this->GetFullNameInternal(type); + name = this->GetFullNameInternal(type, config); // The library's soname. soName = name; @@ -1165,22 +1269,26 @@ void cmTarget::GetLibraryNamesInternal(std::string& name, } void cmTarget::GetExecutableNames(std::string& name, - std::string& realName) + std::string& realName, + const char* config) { // Get the names based on the real type of the executable. - this->GetExecutableNamesInternal(name, realName, this->GetType()); + this->GetExecutableNamesInternal(name, realName, this->GetType(), config); } void cmTarget::GetExecutableCleanNames(std::string& name, - std::string& realName) + std::string& realName, + const char* config) { // Get the name and versioned name of this executable. - this->GetExecutableNamesInternal(name, realName, cmTarget::EXECUTABLE); + this->GetExecutableNamesInternal(name, realName, cmTarget::EXECUTABLE, + config); } void cmTarget::GetExecutableNamesInternal(std::string& name, std::string& realName, - TargetType type) + TargetType type, + const char* config) { // This versioning is supported only for executables and then only // when the platform supports symbolic links. @@ -1196,7 +1304,7 @@ void cmTarget::GetExecutableNamesInternal(std::string& name, #endif // The executable name. - name = this->GetFullNameInternal(type); + name = this->GetFullNameInternal(type, config); // The executable's real name on disk. realName = name; |