ENH: mark some vars as advanced (and resort the list)
[cmake.git] / Source / cmTarget.cxx
blob04cce9893468f5970e1b3c65171c1240b3300a07
1 /*=========================================================================
3 Program: Insight Segmentation & Registration Toolkit
4 Module: $RCSfile: cmTarget.cxx,v $
5 Language: C++
6 Date: $Date: 2002-10-06 16:12:59 $
7 Version: $Revision: 1.38 $
9 Copyright (c) 2002 Insight Consortium. All rights reserved.
10 See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm 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 "cmTarget.h"
18 #include "cmMakefile.h"
19 #include "cmSourceFile.h"
21 #include <map>
22 #include <set>
25 void cmTarget::GenerateSourceFilesFromSourceLists( cmMakefile &mf)
27 // this is only done for non install targets
28 if ((this->m_TargetType == cmTarget::INSTALL_FILES)
29 || (this->m_TargetType == cmTarget::INSTALL_PROGRAMS))
31 return;
34 // for each src lists add the classes
35 for (std::vector<std::string>::const_iterator s = m_SourceLists.begin();
36 s != m_SourceLists.end(); ++s)
38 int done = 0;
39 // replace any variables
40 std::string temps = *s;
41 mf.ExpandVariablesInString(temps);
43 // Next if one wasn't found then assume it is a single class
44 if (!done && mf.GetSource(temps.c_str()))
46 m_SourceFiles.push_back(mf.GetSource(temps.c_str()));
47 done = 1;
50 // if it wasn't a source file listed with the makefile
51 // see if it is a variable. This is for old CMake 1.2 compatability
52 // where a source list would be passed into here, by making it
53 // a vector we need to possibly lookup the variable to maintain
54 // CMake 1.2 compatability.
55 const char* versionValue
56 = mf.GetDefinition("CMAKE_MINIMUM_REQUIRED_VERSION");
57 if (!done)
59 if (!versionValue || atof(versionValue) <= 1.2)
61 const char* varValue =
62 mf.GetDefinition(temps.c_str());
63 // if the definition exists
64 if (varValue)
66 std::vector<std::string> tval;
67 tval.push_back(varValue);
68 std::vector<std::string> args;
69 cmSystemTools::ExpandListArguments(tval, args);
70 unsigned int i;
71 for (i = 0; i < args.size(); ++i)
73 if (mf.GetSource(args[i].c_str()))
75 m_SourceFiles.push_back(mf.GetSource(args[i].c_str()));
77 else
79 cmSourceFile file;
80 file.SetProperty("ABSTRACT","0");
81 file.SetName(args[i].c_str(), mf.GetCurrentDirectory(),
82 mf.GetSourceExtensions(),
83 mf.GetHeaderExtensions());
84 m_SourceFiles.push_back(mf.AddSource(file));
87 done = 1;
92 // if we still are not done, try to create the SourceFile structure
93 if (!done)
95 cmSourceFile file;
96 file.SetProperty("ABSTRACT","0");
97 file.SetName(temps.c_str(), mf.GetCurrentDirectory(),
98 mf.GetSourceExtensions(),
99 mf.GetHeaderExtensions());
100 m_SourceFiles.push_back(mf.AddSource(file));
101 done = 1;
105 // expand any link library variables whle we are at it
106 LinkLibraries::iterator p = m_LinkLibraries.begin();
107 for (;p != m_LinkLibraries.end(); ++p)
109 mf.ExpandVariablesInString(p->first);
114 void cmTarget::MergeLinkLibraries( cmMakefile& mf,
115 const char *selfname,
116 const LinkLibraries& libs )
118 // Only add on libraries we haven't added on before.
119 // Assumption: the global link libraries could only grow, never shrink
120 LinkLibraries::const_iterator i = libs.begin();
121 i += m_PrevLinkedLibraries.size();
122 for( ; i != libs.end(); ++i )
124 // We call this so that the dependencies get written to the cache
125 this->AddLinkLibrary( mf, selfname, i->first.c_str(), i->second );
127 m_PrevLinkedLibraries = libs;
130 void cmTarget::AddLinkDirectory(const char* d)
132 // Make sure we don't add unnecessary search directories.
133 if( std::find( m_LinkDirectories.begin(), m_LinkDirectories.end(), d )
134 == m_LinkDirectories.end() )
135 m_LinkDirectories.push_back( d );
140 void cmTarget::AddLinkLibrary(const std::string& lib,
141 LinkLibraryType llt)
143 m_LinkLibraries.push_back( std::pair<std::string, cmTarget::LinkLibraryType>(lib,llt) );
146 void cmTarget::AddLinkLibrary(cmMakefile& mf,
147 const char *target, const char* lib,
148 LinkLibraryType llt)
150 // Never add a self dependency, even if the user asks for it.
151 if(strcmp( target, lib ) == 0)
153 return;
156 m_LinkLibraries.push_back( std::pair<std::string, cmTarget::LinkLibraryType>(lib,llt) );
158 if(llt != cmTarget::GENERAL)
160 std::string linkTypeName = lib;
161 linkTypeName += "_LINK_TYPE";
162 switch(llt)
164 case cmTarget::DEBUG:
165 mf.AddCacheDefinition(linkTypeName.c_str(),
166 "debug", "Library is used for debug links only",
167 cmCacheManager::STATIC);
168 break;
169 case cmTarget::OPTIMIZED:
170 mf.AddCacheDefinition(linkTypeName.c_str(),
171 "optimized", "Library is used for debug links only",
172 cmCacheManager::STATIC);
173 break;
174 case cmTarget::GENERAL: break;
177 // Add the explicit dependency information for this target. This is
178 // simply a set of libraries separated by ";". There should always
179 // be a trailing ";". These library names are not canonical, in that
180 // they may be "-framework x", "-ly", "/path/libz.a", etc.
181 // only add depend information for library targets
182 if(m_TargetType >= STATIC_LIBRARY && m_TargetType <= MODULE_LIBRARY)
184 std::string targetEntry = target;
185 targetEntry += "_LIB_DEPENDS";
186 std::string dependencies;
187 const char* old_val = mf.GetDefinition( targetEntry.c_str() );
188 if( old_val )
190 dependencies += old_val;
192 if( dependencies.find( lib ) == std::string::npos )
194 dependencies += lib;
195 dependencies += ";";
197 mf.AddCacheDefinition( targetEntry.c_str(), dependencies.c_str(),
198 "Dependencies for the target",
199 cmCacheManager::STATIC );
204 bool cmTarget::HasCxx() const
206 for(std::vector<cmSourceFile*>::const_iterator i = m_SourceFiles.begin();
207 i != m_SourceFiles.end(); ++i)
209 if((*i)->GetSourceExtension() != "c" &&
210 (*i)->GetSourceExtension() != "h")
212 return true;
215 return false;
222 void
223 cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
225 // There are two key parts of the dependency analysis: (1)
226 // determining the libraries in the link line, and (2) constructing
227 // the dependency graph for those libraries.
229 // The latter is done using the cache entries that record the
230 // dependencies of each library.
232 // The former is a more thorny issue, since it is not clear how to
233 // determine if two libraries listed on the link line refer to the a
234 // single library or not. For example, consider the link "libraries"
235 // /usr/lib/libtiff.so -ltiff
236 // Is this one library or two? The solution implemented here is the
237 // simplest (and probably the only practical) one: two libraries are
238 // the same if their "link strings" are identical. Thus, the two
239 // libraries above are considered distinct. This also means that for
240 // dependency analysis to be effective, the CMake user must specify
241 // libraries build by his project without using any linker flags or
242 // file extensions. That is,
243 // LINK_LIBRARIES( One Two )
244 // instead of
245 // LINK_LIBRARIES( -lOne ${binarypath}/libTwo.a )
246 // The former is probably what most users would do, but it never
247 // hurts to document the assumptions. :-) Therefore, in the analysis
248 // code, the "canonical name" of a library is simply its name as
249 // given to a LINK_LIBRARIES command.
251 // Also, we will leave the original link line intact; we will just add any
252 // dependencies that were missing.
254 typedef std::vector< std::string > LinkLine;
256 // The dependency map.
257 DependencyMap dep_map;
259 // Keeps track of which dependencies have already been emitted for a given
260 // target. This could be via this function, or because they were already
261 // satisfied on the original link line.
262 DependencyMap satisfied;
264 // If LIBRARY_OUTPUT_PATH is not set, then we must add search paths
265 // for all the new libraries added by the dependency analysis.
266 const char* libOutPath = mf.GetDefinition("LIBRARY_OUTPUT_PATH");
267 bool addLibDirs = (libOutPath==0 || strcmp(libOutPath,"")==0);
269 // 1. Determine the dependencies already satisfied by the original link
270 // line.
271 for(LinkLibraries::iterator lib = m_LinkLibraries.begin();
272 lib != m_LinkLibraries.end(); ++lib)
274 for( LinkLibraries::iterator lib2 = lib;
275 lib2 != m_LinkLibraries.end(); ++lib2)
277 satisfied[ lib->first ].insert( lib2->first );
281 // 2. Build the explicit dependency map
282 for(LinkLibraries::reverse_iterator lib = m_LinkLibraries.rbegin();
283 lib != m_LinkLibraries.rend(); ++lib)
285 this->GatherDependencies( mf, lib->first, dep_map );
288 // 3. Create the new link line by simply emitting any dependencies that are
289 // missing. Start from the back and keep adding.
291 std::set<cmStdString> done, visited;
292 std::vector<std::string> newLinkLibraries;
293 for(LinkLibraries::reverse_iterator lib = m_LinkLibraries.rbegin();
294 lib != m_LinkLibraries.rend(); ++lib)
296 // skip zero size library entries, this may happen
297 // if a variable expands to nothing.
298 if (lib->first.size() == 0) continue;
300 // Emit all the dependencies that are not already satisfied on the
301 // original link line.
302 if( dep_map.find(lib->first) != dep_map.end() ) // does it have dependencies?
304 const std::set<cmStdString>& dep_on = dep_map.find( lib->first )->second;
305 std::set<cmStdString>::const_iterator i;
306 for( i = dep_on.begin(); i != dep_on.end(); ++i )
308 if( satisfied[lib->first].end() == satisfied[lib->first].find( *i ) )
310 Emit( *i, dep_map, done, visited, newLinkLibraries );
316 // 4. Add the new libraries to the link line.
318 for( std::vector<std::string>::reverse_iterator k = newLinkLibraries.rbegin();
319 k != newLinkLibraries.rend(); ++k )
321 if( addLibDirs )
323 // who the hell knows what this is, I think that K contains the
324 // name of a library but ... Ken
325 std::string libPathStr = *k + "_CMAKE_PATH";
326 const char* libpath = mf.GetDefinition( libPathStr.c_str() );
327 if( libpath )
329 // Don't add a link directory that is already present.
330 if(std::find(m_LinkDirectories.begin(),
331 m_LinkDirectories.end(), libpath) == m_LinkDirectories.end())
333 m_LinkDirectories.push_back(libpath);
337 std::string linkType = *k;
338 linkType += "_LINK_TYPE";
339 cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
340 const char* linkTypeString = mf.GetDefinition( linkType.c_str() );
341 if(linkTypeString)
343 if(strcmp(linkTypeString, "debug") == 0)
345 llt = cmTarget::DEBUG;
347 if(strcmp(linkTypeString, "optimized") == 0)
349 llt = cmTarget::OPTIMIZED;
352 m_LinkLibraries.push_back( std::make_pair(*k,llt) );
359 void cmTarget::Emit( const std::string& lib,
360 const DependencyMap& dep_map,
361 std::set<cmStdString>& emitted,
362 std::set<cmStdString>& visited,
363 std::vector<std::string>& link_line ) const
365 // It's already been emitted
366 if( emitted.find(lib) != emitted.end() )
368 return;
371 // If this library hasn't been visited before, then emit all its
372 // dependencies before emitting the library itself. If it has been
373 // visited before, then there is a dependency cycle. Just emit the
374 // library itself, and let the recursion that got us here deal with
375 // emitting the dependencies for the library.
377 if( visited.insert(lib).second )
379 if( dep_map.find(lib) != dep_map.end() ) // does it have dependencies?
381 const std::set<cmStdString>& dep_on = dep_map.find( lib )->second;
382 std::set<cmStdString>::const_iterator i;
383 for( i = dep_on.begin(); i != dep_on.end(); ++i )
385 Emit( *i, dep_map, emitted, visited, link_line );
389 link_line.push_back( lib );
390 emitted.insert(lib);
394 void cmTarget::GatherDependencies( const cmMakefile& mf,
395 const std::string& lib,
396 DependencyMap& dep_map )
398 // If the library is already in the dependency map, then it has
399 // already been fully processed.
400 if( dep_map.find(lib) != dep_map.end() )
401 return;
403 const char* deps = mf.GetDefinition( (lib+"_LIB_DEPENDS").c_str() );
404 if( deps && strcmp(deps,"") != 0 )
406 // Make sure this library is in the map, even if it has an empty
407 // set of dependencies. This distinguishes the case of explicitly
408 // no dependencies with that of unspecified dependencies.
409 dep_map[lib];
411 // Parse the dependency information, which is simply a set of
412 // libraries separated by ";". There is always a trailing ";".
413 std::string depline = deps;
414 std::string::size_type start = 0;
415 std::string::size_type end;
416 end = depline.find( ";", start );
417 while( end != std::string::npos )
419 std::string l = depline.substr( start, end-start );
420 if( l.size() != 0 )
422 dep_map[ lib ].insert( l );
423 GatherDependencies( mf, l, dep_map );
425 start = end+1; // skip the ;
426 end = depline.find( ";", start );
428 dep_map[lib].erase(lib); // cannot depend on itself
433 // return true if lib1 depends on lib2
435 bool cmTarget::DependsOn( const std::string& lib1, const std::string& lib2,
436 const DependencyMap& dep_map,
437 std::set<cmStdString>& visited ) const
439 if( !visited.insert( lib1 ).second )
441 return false; // already visited here
445 if( lib1 == lib2 )
447 return false;
450 if( dep_map.find(lib1) == dep_map.end() )
452 return false; // lib1 doesn't have any dependencies
455 const std::set<cmStdString>& dep_set = dep_map.find(lib1)->second;
457 if( dep_set.end() != dep_set.find( lib2 ) )
459 return true; // lib1 doesn't directly depend on lib2.
462 // Do a recursive check: does lib1 depend on x which depends on lib2?
463 for( std::set<cmStdString>::const_iterator itr = dep_set.begin();
464 itr != dep_set.end(); ++itr )
466 if( this->DependsOn( *itr, lib2, dep_map, visited ) )
468 return true;
472 return false;