cmTarget.cxx 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423
  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::AddLinkLibrary(const std::string& lib,
  61. LinkLibraryType llt)
  62. {
  63. m_LinkLibraries.push_back( std::pair<std::string, cmTarget::LinkLibraryType>(lib,llt) );
  64. }
  65. void cmTarget::AddLinkLibrary(cmMakefile& mf,
  66. const char *target, const char* lib,
  67. LinkLibraryType llt)
  68. {
  69. m_LinkLibraries.push_back( std::pair<std::string, cmTarget::LinkLibraryType>(lib,llt) );
  70. if(llt != cmTarget::GENERAL)
  71. {
  72. std::string linkTypeName = this->CanonicalLibraryName(lib);
  73. linkTypeName += "_LINK_TYPE";
  74. switch(llt)
  75. {
  76. case cmTarget::DEBUG:
  77. mf.AddCacheDefinition(linkTypeName.c_str(),
  78. "debug", "Library is used for debug links only",
  79. cmCacheManager::STATIC);
  80. break;
  81. case cmTarget::OPTIMIZED:
  82. mf.AddCacheDefinition(linkTypeName.c_str(),
  83. "optimized", "Library is used for debug links only",
  84. cmCacheManager::STATIC);
  85. break;
  86. }
  87. }
  88. // Add the explicit dependency information for this target. This is
  89. // simply a set of libraries separated by ";". There should always
  90. // be a trailing ";". These library names are not canonical, in that
  91. // they may be "-framework x", "-ly", "/path/libz.a", etc.
  92. std::string targetEntry = target;
  93. targetEntry += "_LIB_DEPENDS";
  94. std::string dependencies;
  95. const char* old_val = mf.GetDefinition( targetEntry.c_str() );
  96. if( old_val )
  97. {
  98. dependencies += old_val;
  99. }
  100. if( dependencies.find( lib ) == std::string::npos )
  101. {
  102. dependencies += lib;
  103. dependencies += ";";
  104. }
  105. mf.AddCacheDefinition( targetEntry.c_str(), dependencies.c_str(),
  106. "Dependencies for the target", cmCacheManager::STATIC );
  107. }
  108. bool cmTarget::HasCxx() const
  109. {
  110. for(std::vector<cmSourceFile*>::const_iterator i = m_SourceFiles.begin();
  111. i != m_SourceFiles.end(); ++i)
  112. {
  113. if((*i)->GetSourceExtension() != "c")
  114. {
  115. return true;
  116. }
  117. }
  118. return false;
  119. }
  120. void
  121. cmTarget::AnalyzeLibDependencies( const cmMakefile& mf )
  122. {
  123. typedef std::vector< std::string > LinkLine;
  124. // Maps the canonical names to the full objects of m_LinkLibraries.
  125. LibTypeMap lib_map;
  126. // The unique list of libraries on the orginal link line. They
  127. // correspond to lib_map keys. However, lib_map will also get
  128. // further populated by the dependency analysis.
  129. LinkLine orig_libs;
  130. // The list canonical names in the order they were orginally
  131. // specified on the link line (m_LinkLibraries).
  132. LinkLine lib_order;
  133. // The dependency maps.
  134. DependencyMap dep_map, dep_map_implicit;
  135. LinkLibraries::iterator lib;
  136. for(lib = m_LinkLibraries.begin(); lib != m_LinkLibraries.end(); ++lib)
  137. {
  138. // skip zero size library entries, this may happen
  139. // if a variable expands to nothing.
  140. if (lib->first.size() == 0) continue;
  141. std::string cname = this->CanonicalLibraryName(lib->first);
  142. lib_order.push_back( cname );
  143. if( lib_map.end() == lib_map.find( cname ) )
  144. {
  145. lib_map[ cname ] = *lib;
  146. orig_libs.push_back( cname );
  147. }
  148. }
  149. // First, get the explicit dependencies for those libraries that
  150. // have specified them
  151. for( LinkLine::iterator i = orig_libs.begin(); i != orig_libs.end(); ++i )
  152. {
  153. this->GatherDependencies( mf, *i, dep_map, lib_map );
  154. }
  155. // For the rest, get implicit dependencies. A library x depends
  156. // implicitly on a library y if x appears before y on the link
  157. // line. However, x does not implicitly depend on y if y
  158. // *explicitly* depends on x [*1]--such cyclic dependencies must be
  159. // explicitly specified. Note that implicit dependency cycles can
  160. // still occur: "-lx -ly -lx" will generate a implicit dependency
  161. // cycle provided that neither x nor y have explicit dependencies.
  162. //
  163. // [*1] This prevents external libraries from depending on libraries
  164. // generated by this project.
  165. for( LinkLine::iterator i = orig_libs.begin(); i != orig_libs.end(); ++i )
  166. {
  167. if( dep_map.find( *i ) == dep_map.end() )
  168. {
  169. LinkLine::iterator pos = std::find( lib_order.begin(), lib_order.end(), *i );
  170. for( ; pos != lib_order.end(); ++pos )
  171. {
  172. std::set<std::string> visited;
  173. if( !DependsOn( *pos, *i, dep_map, visited ) )
  174. {
  175. dep_map_implicit[ *i ].insert( *pos );
  176. }
  177. }
  178. dep_map_implicit[ *i ].erase( *i ); // cannot depend on itself
  179. }
  180. }
  181. // Combine all the depedency information
  182. // dep_map.insert( dep_map_implicit.begin(), dep_map_implicit.end() );
  183. // doesn't work under MSVC++.
  184. for( DependencyMap::iterator i = dep_map_implicit.begin();
  185. i != dep_map_implicit.end(); ++i )
  186. {
  187. dep_map[ i->first ] = i->second;
  188. }
  189. // Create a new link line order.
  190. std::set<std::string> done, visited;
  191. std::vector<std::string> link_line;
  192. for( LinkLine::iterator i = orig_libs.begin(); i != orig_libs.end(); ++i )
  193. {
  194. Emit( *i, dep_map, done, visited, link_line );
  195. }
  196. // If LIBRARY_OUTPUT_PATH is not set, then we must add search paths
  197. // for all the new libraries added by the dependency analysis.
  198. const char* libOutPath = mf.GetDefinition("LIBRARY_OUTPUT_PATH");
  199. bool addLibDirs = (libOutPath==0 || strcmp(libOutPath,"")==0);
  200. m_LinkLibraries.clear();
  201. for( std::vector<std::string>::reverse_iterator i = link_line.rbegin();
  202. i != link_line.rend(); ++i )
  203. {
  204. // Some of the libraries in the new link line may not have been in
  205. // the orginal link line, but were added by the dependency
  206. // analysis. For these libraries, we assume the GENERAL type and
  207. // add the name of the library.
  208. if( lib_map.find(*i) == lib_map.end() )
  209. {
  210. if( addLibDirs )
  211. {
  212. const char* libpath = mf.GetDefinition( i->c_str() );
  213. if( libpath )
  214. {
  215. // Don't add a link directory that is already present.
  216. if(std::find(m_LinkDirectories.begin(),
  217. m_LinkDirectories.end(), libpath) == m_LinkDirectories.end())
  218. {
  219. m_LinkDirectories.push_back(libpath);
  220. }
  221. }
  222. }
  223. std::string linkType = *i;
  224. linkType += "_LINK_TYPE";
  225. cmTarget::LinkLibraryType llt = cmTarget::GENERAL;
  226. const char* linkTypeString = mf.GetDefinition( linkType.c_str() );
  227. if(linkTypeString)
  228. {
  229. if(strcmp(linkTypeString, "debug") == 0)
  230. {
  231. llt = cmTarget::DEBUG;
  232. }
  233. if(strcmp(linkTypeString, "optimized") == 0)
  234. {
  235. llt = cmTarget::OPTIMIZED;
  236. }
  237. }
  238. m_LinkLibraries.push_back( std::make_pair(*i,llt) );
  239. }
  240. else
  241. {
  242. m_LinkLibraries.push_back( lib_map[ *i ] );
  243. }
  244. }
  245. }
  246. std::string cmTarget::CanonicalLibraryName( const std::string& lib ) const
  247. {
  248. cmRegularExpression reg("((^[ \t]*\\-l)|(^[ \t]*\\-framework[ \t]*))(.+)");
  249. if(lib.find('/') != std::string::npos
  250. && !reg.find(lib))
  251. {
  252. std::string dir, file;
  253. cmSystemTools::SplitProgramPath(lib.c_str(),
  254. dir, file);
  255. cmRegularExpression libname("lib(.*)(\\.so|\\.sl|\\.a|\\.dylib).*");
  256. cmRegularExpression libname_noprefix("(.*)(\\.so|\\.sl|\\.a|\\.dylib|\\.lib).*");
  257. if(libname.find(file))
  258. {
  259. return libname.match(1);
  260. }
  261. else if(libname_noprefix.find(file))
  262. {
  263. return libname_noprefix.match(1);
  264. }
  265. else
  266. {
  267. return file;
  268. }
  269. }
  270. else
  271. {
  272. if(!reg.find(lib))
  273. {
  274. return lib;
  275. }
  276. else
  277. {
  278. return reg.match(4);
  279. }
  280. }
  281. }
  282. void cmTarget::Emit( const std::string& lib,
  283. const DependencyMap& dep_map,
  284. std::set<std::string>& emitted,
  285. std::set<std::string>& visited,
  286. std::vector<std::string>& link_line ) const
  287. {
  288. // It's already been emitted
  289. if( emitted.find(lib) != emitted.end() )
  290. {
  291. return;
  292. }
  293. // If this library hasn't been visited before, then emit all its
  294. // dependencies before emitting the library itself. If it has been
  295. // visited before, then there is a dependency cycle. Just emit the
  296. // library itself, and let the recursion that got us here deal with
  297. // emitting the dependencies for the library.
  298. if( visited.insert(lib).second )
  299. {
  300. if( dep_map.find(lib) != dep_map.end() ) // does it have dependencies?
  301. {
  302. const std::set<std::string>& dep_on = dep_map.find( lib )->second;
  303. std::set<std::string>::const_iterator i;
  304. for( i = dep_on.begin(); i != dep_on.end(); ++i )
  305. {
  306. Emit( *i, dep_map, emitted, visited, link_line );
  307. }
  308. }
  309. }
  310. link_line.push_back( lib );
  311. emitted.insert(lib);
  312. }
  313. void cmTarget::GatherDependencies( const cmMakefile& mf,
  314. const std::string& lib,
  315. DependencyMap& dep_map,
  316. LibTypeMap& lib_map ) const
  317. {
  318. // If the library is already in the dependency map, then it has
  319. // already been fully processed.
  320. if( dep_map.find(lib) != dep_map.end() )
  321. return;
  322. const char* deps = mf.GetDefinition( (lib+"_LIB_DEPENDS").c_str() );
  323. if( deps && strcmp(deps,"") != 0 )
  324. {
  325. // Make sure this library is in the map, even if it has an empty
  326. // set of dependencies. This distinguishes the case of explicitly
  327. // no dependencies with that of unspecified dependencies.
  328. dep_map[lib];
  329. // Parse the dependency information, which is simply a set of
  330. // libraries separated by ";". There is always a trailing ";".
  331. std::string depline = deps;
  332. std::string::size_type start = 0;
  333. std::string::size_type end;
  334. end = depline.find( ";", start );
  335. while( end != std::string::npos )
  336. {
  337. std::string l = depline.substr( start, end-start );
  338. if( l.size() != 0 )
  339. {
  340. const std::string cname = CanonicalLibraryName(l);
  341. lib_map[ cname ] = std::make_pair(l,GENERAL); // ** FIXME: we need to store the correct type here
  342. dep_map[ lib ].insert( cname );
  343. GatherDependencies( mf, cname, dep_map, lib_map );
  344. }
  345. start = end+1; // skip the ;
  346. end = depline.find( ";", start );
  347. }
  348. dep_map[lib].erase(lib); // cannot depend on itself
  349. }
  350. }
  351. bool cmTarget::DependsOn( const std::string& lib1, const std::string& lib2,
  352. const DependencyMap& dep_map,
  353. std::set<std::string>& visited ) const
  354. {
  355. if( !visited.insert( lib1 ).second )
  356. return false; // already visited here
  357. if( lib1 == lib2 )
  358. return false;
  359. if( dep_map.find(lib1) == dep_map.end() )
  360. return false; // lib1 doesn't have any dependencies
  361. const std::set<std::string>& dep_set = dep_map.find(lib1)->second;
  362. if( dep_set.end() != dep_set.find( lib2 ) )
  363. return true; // lib1 doesn't directly depend on lib2.
  364. // Do a recursive check: does lib1 depend on x which depends on lib2?
  365. for( std::set<std::string>::const_iterator itr = dep_set.begin();
  366. itr != dep_set.end(); ++itr )
  367. {
  368. if( DependsOn( *itr, lib2, dep_map, visited ) )
  369. return true;
  370. }
  371. return false;
  372. }