cmTarget.cxx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386
  1. /*=========================================================================
  2. Program: Insight Segmentation & Registration Toolkit
  3. Module: $RCSfile$
  4. Language: C++
  5. Date: $Date$
  6. Version: $Revision$
  7. Copyright (c) 2002 Insight Consortium. All rights reserved.
  8. See ITKCopyright.txt or http://www.itk.org/HTML/Copyright.htm for details.
  9. This software is distributed WITHOUT ANY WARRANTY; without even
  10. the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  11. PURPOSE. See the above copyright notices for more information.
  12. =========================================================================*/
  13. #include "cmTarget.h"
  14. #include "cmMakefile.h"
  15. #include <map>
  16. #include <set>
  17. void cmTarget::GenerateSourceFilesFromSourceLists( cmMakefile &mf)
  18. {
  19. // this is only done for non install targets
  20. if ((this->m_TargetType == cmTarget::INSTALL_FILES)
  21. || (this->m_TargetType == cmTarget::INSTALL_PROGRAMS))
  22. {
  23. return;
  24. }
  25. // for each src lists add the classes
  26. for (std::vector<std::string>::const_iterator s = m_SourceLists.begin();
  27. s != m_SourceLists.end(); ++s)
  28. {
  29. // replace any variables
  30. std::string temps = *s;
  31. mf.ExpandVariablesInString(temps);
  32. // look for a srclist
  33. if (mf.GetSources().find(temps) != mf.GetSources().end())
  34. {
  35. const std::vector<cmSourceFile*> &clsList =
  36. mf.GetSources().find(temps)->second;
  37. // if we ahave a limited build list, use it
  38. m_SourceFiles.insert(m_SourceFiles.end(),
  39. clsList.begin(),
  40. clsList.end());
  41. }
  42. // if one wasn't found then assume it is a single class
  43. else
  44. {
  45. cmSourceFile file;
  46. file.SetIsAnAbstractClass(false);
  47. file.SetName(temps.c_str(), mf.GetCurrentDirectory(),
  48. mf.GetSourceExtensions(),
  49. mf.GetHeaderExtensions());
  50. m_SourceFiles.push_back(mf.AddSource(file));
  51. }
  52. }
  53. // expand any link library variables whle we are at it
  54. LinkLibraries::iterator p = m_LinkLibraries.begin();
  55. for (;p != m_LinkLibraries.end(); ++p)
  56. {
  57. mf.ExpandVariablesInString(p->first);
  58. }
  59. }
  60. void cmTarget::MergeLibraries(const LinkLibraries &ll)
  61. {
  62. m_LinkLibraries.insert( m_LinkLibraries.end(), ll.begin(), ll.end() );
  63. }
  64. void cmTarget::MergeDirectories(const std::vector<std::string> &ld)
  65. {
  66. m_LinkDirectories.insert( m_LinkDirectories.end(), ld.begin(), ld.end() );
  67. }
  68. void cmTarget::AddLinkLibrary(const std::string& lib,
  69. LinkLibraryType llt)
  70. {
  71. m_LinkLibraries.push_back( std::pair<std::string, cmTarget::LinkLibraryType>(lib,llt) );
  72. }
  73. void cmTarget::AddLinkLibrary(cmMakefile& mf,
  74. const char *target, const char* lib,
  75. LinkLibraryType llt)
  76. {
  77. m_LinkLibraries.push_back( std::pair<std::string, cmTarget::LinkLibraryType>(lib,llt) );
  78. // Add the explicit dependency information for this target. This is
  79. // simply a set of libraries separated by ";". There should always
  80. // be a trailing ";". These library names are not canonical, in that
  81. // they may be "-framework x", "-ly", "/path/libz.a", etc.
  82. std::string cache_name( target );
  83. cache_name += "_LIB_DEPENDS";
  84. std::string dependencies;
  85. const char* old_val = mf.GetDefinition( cache_name.c_str() );
  86. if( old_val )
  87. {
  88. dependencies += old_val;
  89. }
  90. if( dependencies.find( lib ) == std::string::npos )
  91. {
  92. dependencies += lib;
  93. dependencies += ";";
  94. }
  95. mf.AddCacheDefinition( cache_name.c_str(), dependencies.c_str(),
  96. "Dependencies for the target", cmCacheManager::INTERNAL );
  97. }
  98. bool cmTarget::HasCxx() const
  99. {
  100. for(std::vector<cmSourceFile*>::const_iterator i = m_SourceFiles.begin();
  101. i != m_SourceFiles.end(); ++i)
  102. {
  103. if((*i)->GetSourceExtension() != "c")
  104. {
  105. return true;
  106. }
  107. }
  108. return false;
  109. }
  110. void
  111. cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
  112. {
  113. typedef std::map< std::string, std::pair<std::string,LinkLibraryType> > LibMap;
  114. typedef std::vector< std::string > LinkLine;
  115. // Maps the canonical names to the full objects of m_LinkLibraries.
  116. LibMap lib_map;
  117. // The list canonical names in the order they were orginally
  118. // specified on the link line (m_LinkLibraries).
  119. LinkLine lib_order;
  120. // The dependency maps.
  121. DependencyMap dep_map, dep_map_implicit;
  122. LinkLibraries::iterator lib;
  123. for(lib = m_LinkLibraries.begin(); lib != m_LinkLibraries.end(); ++lib)
  124. {
  125. // skip zero size library entries, this may happen
  126. // if a variable expands to nothing.
  127. if (lib->first.size() == 0) continue;
  128. std::string cname = CanonicalLibraryName(lib->first);
  129. lib_map[ cname ] = *lib;
  130. lib_order.push_back( cname );
  131. }
  132. // First, get the explicit dependencies for those libraries that
  133. // have specified them
  134. for( LibMap::iterator i = lib_map.begin(); i != lib_map.end(); ++i )
  135. {
  136. GatherDependencies( mf, i->first, dep_map );
  137. }
  138. // For the rest, get implicit dependencies. A library x depends
  139. // implicitly on a library y if x appears before y on the link
  140. // line. However, x does not implicitly depend on y if y
  141. // *explicitly* depends on x [*1]--such cyclic dependencies must be
  142. // explicitly specified. Note that implicit dependency cycles can
  143. // still occur: "-lx -ly -lx" will generate a implicit dependency
  144. // cycle provided that neither x nor y have explicit dependencies.
  145. //
  146. // [*1] This prevents external libraries from depending on libraries
  147. // generated by this project.
  148. for( LibMap::iterator i = lib_map.begin(); i != lib_map.end(); ++i )
  149. {
  150. if( dep_map.find( i->first ) == dep_map.end() )
  151. {
  152. LinkLine::iterator pos = std::find( lib_order.begin(), lib_order.end(), i->first );
  153. for( ; pos != lib_order.end(); ++pos )
  154. {
  155. std::set<std::string> visited;
  156. if( !DependsOn( *pos, i->first, dep_map, visited ) )
  157. {
  158. dep_map_implicit[ i->first ].insert( *pos );
  159. }
  160. }
  161. dep_map_implicit[ i->first ].erase( i->first ); // cannot depend on itself
  162. }
  163. }
  164. // Combine all the depedency information
  165. // dep_map.insert( dep_map_implicit.begin(), dep_map_implicit.end() );
  166. // doesn't work under MSVC++.
  167. for( DependencyMap::iterator i = dep_map_implicit.begin();
  168. i != dep_map_implicit.end(); ++i )
  169. {
  170. dep_map[ i->first ] = i->second;
  171. }
  172. // Create a new link line order.
  173. std::set<std::string> done, visited;
  174. std::vector<std::string> link_line;
  175. for( LibMap::iterator i = lib_map.begin(); i != lib_map.end(); ++i )
  176. {
  177. Emit( i->first, dep_map, done, visited, link_line );
  178. }
  179. // If LIBRARY_OUTPUT_PATH is not set, then we must add search paths
  180. // for all the new libraries added by the dependency analysis.
  181. const char* libOutPath = mf.GetDefinition("LIBRARY_OUTPUT_PATH");
  182. bool addLibDirs = (libOutPath==0 || strcmp(libOutPath,"")==0);
  183. m_LinkLibraries.clear();
  184. for( std::vector<std::string>::reverse_iterator i = link_line.rbegin();
  185. i != link_line.rend(); ++i )
  186. {
  187. // Some of the libraries in the new link line may not have been in
  188. // the orginal link line, but were added by the dependency
  189. // analysis. For these libraries, we assume the GENERAL type and
  190. // add the name of the library.
  191. if( lib_map.find(*i) == lib_map.end() )
  192. {
  193. if( addLibDirs )
  194. {
  195. const char* libpath = mf.GetDefinition( i->c_str() );
  196. if( libpath )
  197. {
  198. // Don't add a link directory that is already present.
  199. if(std::find(m_LinkDirectories.begin(),
  200. m_LinkDirectories.end(), libpath) == m_LinkDirectories.end())
  201. {
  202. m_LinkDirectories.push_back(libpath);
  203. }
  204. }
  205. }
  206. m_LinkLibraries.push_back( std::make_pair(*i,GENERAL) );
  207. }
  208. else
  209. {
  210. m_LinkLibraries.push_back( lib_map[ *i ] );
  211. }
  212. }
  213. }
  214. std::string cmTarget::CanonicalLibraryName( const std::string& lib ) const
  215. {
  216. cmRegularExpression reg("((^[ \t]*\\-l)|(^[ \t]*\\-framework[ \t]*))(.+)");
  217. if(lib.find('/') != std::string::npos
  218. && !reg.find(lib))
  219. {
  220. std::string dir, file;
  221. cmSystemTools::SplitProgramPath(lib.c_str(),
  222. dir, file);
  223. cmRegularExpression libname("lib(.*)(\\.so|\\.sl|\\.a|\\.dylib).*");
  224. cmRegularExpression libname_noprefix("(.*)(\\.so|\\.sl|\\.a|\\.dylib|\\.lib).*");
  225. if(libname.find(file))
  226. {
  227. return libname.match(1);
  228. }
  229. else if(libname_noprefix.find(file))
  230. {
  231. return libname_noprefix.match(1);
  232. }
  233. else
  234. {
  235. return file;
  236. }
  237. }
  238. else
  239. {
  240. if(!reg.find(lib))
  241. {
  242. return lib;
  243. }
  244. else
  245. {
  246. return reg.match(4);
  247. }
  248. }
  249. }
  250. void cmTarget::Emit( const std::string& lib,
  251. const DependencyMap& dep_map,
  252. std::set<std::string>& emitted,
  253. std::set<std::string>& visited,
  254. std::vector<std::string>& link_line ) const
  255. {
  256. // It's already been emitted
  257. if( emitted.find(lib) != emitted.end() )
  258. return;
  259. // If this library hasn't been visited before, then emit all its
  260. // dependencies before emitting the library itself. If it has been
  261. // visited before, then there is a dependency cycle. Just emit the
  262. // library itself, and let the recursion that got us here deal with
  263. // emitting the dependencies for the library.
  264. if( visited.insert(lib).second )
  265. {
  266. if( dep_map.find(lib) != dep_map.end() ) // does it have dependencies?
  267. {
  268. const std::set<std::string>& dep_on = dep_map.find( lib )->second;
  269. std::set<std::string>::const_iterator i;
  270. for( i = dep_on.begin(); i != dep_on.end(); ++i )
  271. {
  272. Emit( *i, dep_map, emitted, visited, link_line );
  273. }
  274. }
  275. }
  276. link_line.push_back( lib );
  277. emitted.insert(lib);
  278. }
  279. void cmTarget::GatherDependencies( const cmMakefile& mf,
  280. const std::string& lib,
  281. DependencyMap& dep_map ) const
  282. {
  283. // If the library is already in the dependency map, then it has
  284. // already been fully processed.
  285. if( dep_map.find(lib) != dep_map.end() )
  286. return;
  287. const char* deps = mf.GetDefinition( (lib+"_LIB_DEPENDS").c_str() );
  288. if( deps )
  289. {
  290. // Make sure this library is in the map, even if it has an empty
  291. // set of dependencies. This distinguishes the case of explicitly
  292. // no dependencies with that of unspecified dependencies.
  293. dep_map[lib];
  294. // Parse the dependency information, which is simply a set of
  295. // libraries separated by ";". There is always a trailing ";".
  296. std::string depline = deps;
  297. std::string::size_type start = 0;
  298. std::string::size_type end;
  299. end = depline.find( ";", start );
  300. while( end != std::string::npos )
  301. {
  302. std::string l = depline.substr( start, end-start );
  303. if( l.size() != 0 )
  304. {
  305. const std::string cname = CanonicalLibraryName(l);
  306. dep_map[ lib ].insert( cname );
  307. GatherDependencies( mf, cname, dep_map );
  308. }
  309. start = end+1; // skip the ;
  310. end = depline.find( ";", start );
  311. }
  312. dep_map[lib].erase(lib); // cannot depend on itself
  313. }
  314. }
  315. bool cmTarget::DependsOn( const std::string& lib1, const std::string& lib2,
  316. const DependencyMap& dep_map,
  317. std::set<std::string>& visited ) const
  318. {
  319. if( !visited.insert( lib1 ).second )
  320. return false; // already visited here
  321. if( lib1 == lib2 )
  322. return false;
  323. if( dep_map.find(lib1) == dep_map.end() )
  324. return false; // lib1 doesn't have any dependencies
  325. const std::set<std::string>& dep_set = dep_map.find(lib1)->second;
  326. if( dep_set.end() != dep_set.find( lib2 ) )
  327. return true; // lib1 doesn't directly depend on lib2.
  328. // Do a recursive check: does lib1 depend on x which depends on lib2?
  329. for( std::set<std::string>::const_iterator itr = dep_set.begin();
  330. itr != dep_set.end(); ++itr )
  331. {
  332. if( DependsOn( *itr, lib2, dep_map, visited ) )
  333. return true;
  334. }
  335. return false;
  336. }