ppDirectory.cxx 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962
  1. // Filename: ppDirectory.cxx
  2. // Created by: drose (28Sep00)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. #include "ppDirectory.h"
  6. #include "ppDirectoryTree.h"
  7. #include "ppScope.h"
  8. #include "ppNamedScopes.h"
  9. #include "ppCommandFile.h"
  10. #include "ppDependableFile.h"
  11. #include "tokenize.h"
  12. #include "ppremake.h"
  13. #ifdef HAVE_DIRENT_H
  14. #include <dirent.h>
  15. #endif
  16. #ifdef HAVE_UNISTD_H
  17. #include <unistd.h>
  18. #endif
  19. #ifdef HAVE_SYS_TYPES_H
  20. #include <sys/types.h>
  21. #endif
  22. #include <sys/stat.h>
  23. #include <algorithm>
  24. #include <iterator>
  25. #include <assert.h>
  26. #ifdef WIN32_VC
  27. #include <direct.h>
  28. #include <windows.h>
  29. #endif
  30. // How new must a pp.dep cache file be before we will believe it?
  31. static const int max_cache_minutes = 60;
  32. PPDirectory *current_output_directory = (PPDirectory *)NULL;
  33. // An STL object to sort directories in order by dependency and then
  34. // by name, used in get_child_dirnames().
  35. class SortDirectoriesByDependencyAndName {
  36. public:
  37. bool operator () (const PPDirectory *a, const PPDirectory *b) const {
  38. if (a->get_depends_index() != b->get_depends_index()) {
  39. return a->get_depends_index() < b->get_depends_index();
  40. }
  41. return a->get_dirname() < b->get_dirname();
  42. }
  43. };
  44. ////////////////////////////////////////////////////////////////////
  45. // Function: PPDirectory::Constructor
  46. // Access: Public
  47. // Description: Creates the root directory.
  48. ////////////////////////////////////////////////////////////////////
  49. PPDirectory::
  50. PPDirectory(PPDirectoryTree *tree) {
  51. _scope = (PPScope *)NULL;
  52. _source = (PPCommandFile *)NULL;
  53. _parent = (PPDirectory *)NULL;
  54. _tree = tree;
  55. _depth = 0;
  56. _depends_index = 0;
  57. _computing_depends_index = false;
  58. _dirname = "top";
  59. _tree->_dirnames.insert(PPDirectoryTree::Dirnames::value_type(_dirname, this));
  60. }
  61. ////////////////////////////////////////////////////////////////////
  62. // Function: PPDirectory::Constructor
  63. // Access: Public
  64. // Description: Creates a new directory level that automatically adds
  65. // itself to its parent's children list.
  66. ////////////////////////////////////////////////////////////////////
  67. PPDirectory::
  68. PPDirectory(const string &dirname, PPDirectory *parent) :
  69. _dirname(dirname),
  70. _parent(parent)
  71. {
  72. assert(_parent != (PPDirectory *)NULL);
  73. _scope = (PPScope *)NULL;
  74. _source = (PPCommandFile *)NULL;
  75. _parent->_children.push_back(this);
  76. _tree = _parent->_tree;
  77. _depth = _parent->_depth + 1;
  78. _depends_index = 0;
  79. _computing_depends_index = false;
  80. bool inserted =
  81. _tree->_dirnames.insert(PPDirectoryTree::Dirnames::value_type(_dirname, this)).second;
  82. if (!inserted) {
  83. cerr << "Warning: multiple directories encountered named "
  84. << _dirname << "\n";
  85. }
  86. }
  87. ////////////////////////////////////////////////////////////////////
  88. // Function: PPDirectory::Destructor
  89. // Access: Public
  90. // Description: When a tree root destructs, all of its children are
  91. // also destroyed.
  92. ////////////////////////////////////////////////////////////////////
  93. PPDirectory::
  94. ~PPDirectory() {
  95. Children::iterator ci;
  96. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  97. delete (*ci);
  98. }
  99. }
  100. ////////////////////////////////////////////////////////////////////
  101. // Function: PPDirectory::get_tree
  102. // Access: Public
  103. // Description: Returns the PPDirectoryTree object corresponding to
  104. // the source tree that this directory is a part of.
  105. ////////////////////////////////////////////////////////////////////
  106. PPDirectoryTree *PPDirectory::
  107. get_tree() const {
  108. return _tree;
  109. }
  110. ////////////////////////////////////////////////////////////////////
  111. // Function: PPDirectory::count_source_files
  112. // Access: Public
  113. // Description: Returns the number of directories within the tree
  114. // that actually have a Sources.pp file that was read.
  115. ////////////////////////////////////////////////////////////////////
  116. int PPDirectory::
  117. count_source_files() const {
  118. int count = 0;
  119. if (_source != (PPCommandFile *)NULL) {
  120. count++;
  121. }
  122. Children::const_iterator ci;
  123. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  124. count += (*ci)->count_source_files();
  125. }
  126. return count;
  127. }
  128. ////////////////////////////////////////////////////////////////////
  129. // Function: PPDirectory::get_dirname
  130. // Access: Public
  131. // Description: Returns the name of this particular directory level.
  132. ////////////////////////////////////////////////////////////////////
  133. const string &PPDirectory::
  134. get_dirname() const {
  135. return _dirname;
  136. }
  137. ////////////////////////////////////////////////////////////////////
  138. // Function: PPDirectory::get_depends_index
  139. // Access: Public
  140. // Description: Returns the dependency index associated with this
  141. // directory. It is generally true that if directory A
  142. // depends on B, then A.get_depends_index() >
  143. // B.get_depends_index().
  144. ////////////////////////////////////////////////////////////////////
  145. int PPDirectory::
  146. get_depends_index() const {
  147. return _depends_index;
  148. }
  149. ////////////////////////////////////////////////////////////////////
  150. // Function: PPDirectory::get_path
  151. // Access: Public
  152. // Description: Returns the relative path from the root to this
  153. // particular directory. This does not include the root
  154. // name itself, and does not include a trailing slash.
  155. ////////////////////////////////////////////////////////////////////
  156. string PPDirectory::
  157. get_path() const {
  158. if (_parent == (PPDirectory *)NULL) {
  159. return ".";
  160. }
  161. if (_parent->_parent == (PPDirectory *)NULL) {
  162. return _dirname;
  163. }
  164. return _parent->get_path() + "/" + _dirname;
  165. }
  166. ////////////////////////////////////////////////////////////////////
  167. // Function: PPDirectory::get_fullpath
  168. // Access: Public
  169. // Description: Returns the full path to this particular directory.
  170. // This does not include a trailing slash.
  171. ////////////////////////////////////////////////////////////////////
  172. string PPDirectory::
  173. get_fullpath() const {
  174. if (_parent == (PPDirectory *)NULL) {
  175. return _tree->get_fullpath();
  176. }
  177. return _tree->get_fullpath() + "/" + get_path();
  178. }
  179. ////////////////////////////////////////////////////////////////////
  180. // Function: PPDirectory::get_rel_to
  181. // Access: Public
  182. // Description: Returns the relative path to the other directory from
  183. // this one. This does not include a trailing slash.
  184. ////////////////////////////////////////////////////////////////////
  185. string PPDirectory::
  186. get_rel_to(const PPDirectory *other) const {
  187. const PPDirectory *a = this;
  188. const PPDirectory *b = other;
  189. if (a == b) {
  190. return ".";
  191. }
  192. if (a->_tree != b->_tree) {
  193. // If they're in different trees, just return the full path to b.
  194. return b->get_fullpath();
  195. }
  196. string prefix, postfix;
  197. while (a->_depth > b->_depth) {
  198. prefix += "../";
  199. a = a->_parent;
  200. assert(a != (PPDirectory *)NULL);
  201. }
  202. while (b->_depth > a->_depth) {
  203. postfix = b->_dirname + "/" + postfix;
  204. b = b->_parent;
  205. assert(b != (PPDirectory *)NULL);
  206. }
  207. while (a != b) {
  208. prefix += "../";
  209. postfix = b->_dirname + "/" + postfix;
  210. a = a->_parent;
  211. b = b->_parent;
  212. assert(a != (PPDirectory *)NULL);
  213. assert(b != (PPDirectory *)NULL);
  214. }
  215. string result = prefix + postfix;
  216. assert(!result.empty());
  217. return result.substr(0, result.length() - 1);
  218. }
  219. ////////////////////////////////////////////////////////////////////
  220. // Function: PPDirectory::get_source
  221. // Access: Public
  222. // Description: Returns the source file associated with this level
  223. // of the directory hierarchy. This *might* be NULL.
  224. ////////////////////////////////////////////////////////////////////
  225. PPCommandFile *PPDirectory::
  226. get_source() const {
  227. return _source;
  228. }
  229. ////////////////////////////////////////////////////////////////////
  230. // Function: PPDirectory::get_num_children
  231. // Access: Public
  232. // Description: Returns the number of subdirectories below this
  233. // level.
  234. ////////////////////////////////////////////////////////////////////
  235. int PPDirectory::
  236. get_num_children() const {
  237. return _children.size();
  238. }
  239. ////////////////////////////////////////////////////////////////////
  240. // Function: PPDirectory::get_child
  241. // Access: Public
  242. // Description: Returns the nth subdirectory below this level.
  243. ////////////////////////////////////////////////////////////////////
  244. PPDirectory *PPDirectory::
  245. get_child(int n) const {
  246. assert(n >= 0 && n < (int)_children.size());
  247. return _children[n];
  248. }
  249. ////////////////////////////////////////////////////////////////////
  250. // Function: PPDirectory::get_child_dirnames
  251. // Access: Public
  252. // Description: Returns a single string listing the names of all the
  253. // subdirectories of this level, delimited by spaces.
  254. //
  255. // The list is sorted in dependency order such that a
  256. // directory is listed after the other directories it
  257. // might depend on.
  258. ////////////////////////////////////////////////////////////////////
  259. string PPDirectory::
  260. get_child_dirnames() const {
  261. Children copy_children = _children;
  262. sort(copy_children.begin(), copy_children.end(),
  263. SortDirectoriesByDependencyAndName());
  264. vector<string> words;
  265. Children::const_iterator ci;
  266. for (ci = copy_children.begin(); ci != copy_children.end(); ++ci) {
  267. words.push_back((*ci)->get_dirname());
  268. }
  269. string result = repaste(words, " ");
  270. return result;
  271. }
  272. ////////////////////////////////////////////////////////////////////
  273. // Function: PPDirectory::get_complete_subtree
  274. // Access: Public
  275. // Description: Returns a single string listing the relative path
  276. // from the source root to each source directory at this
  277. // level and below, delimited by spaces.
  278. ////////////////////////////////////////////////////////////////////
  279. string PPDirectory::
  280. get_complete_subtree() const {
  281. Children copy_children = _children;
  282. sort(copy_children.begin(), copy_children.end(),
  283. SortDirectoriesByDependencyAndName());
  284. vector<string> words;
  285. words.push_back(get_path());
  286. Children::const_iterator ci;
  287. for (ci = copy_children.begin(); ci != copy_children.end(); ++ci) {
  288. words.push_back((*ci)->get_complete_subtree());
  289. }
  290. string result = repaste(words, " ");
  291. return result;
  292. }
  293. ////////////////////////////////////////////////////////////////////
  294. // Function: PPDirectory::get_dependable_file
  295. // Access: Public
  296. // Description: Returns a PPDependableFile object corresponding to
  297. // the named filename, creating one if it does not
  298. // already exist. This can be used to determine the
  299. // inter-file dependencies between source files.
  300. //
  301. // If is_header is true, then the file will be added to
  302. // the index at the top of the directory tree, so that
  303. // other directories may include this file. In this
  304. // case, if the filename is not unique, a warning
  305. // message will be issued.
  306. ////////////////////////////////////////////////////////////////////
  307. PPDependableFile *PPDirectory::
  308. get_dependable_file(const string &filename, bool is_header) {
  309. Dependables::iterator di;
  310. di = _dependables.find(filename);
  311. if (di != _dependables.end()) {
  312. return (*di).second;
  313. }
  314. // No such file found; create a new definition.
  315. PPDependableFile *dependable = new PPDependableFile(this, filename);
  316. _dependables.insert(Dependables::value_type(filename, dependable));
  317. if (is_header) {
  318. PPDirectoryTree *main_tree = _tree->get_main_tree();
  319. bool unique = main_tree->_dependables.insert
  320. (PPDirectoryTree::Dependables::value_type(filename, dependable)).second;
  321. if (!unique) {
  322. PPDependableFile *other = main_tree->find_dependable_file(filename);
  323. if (_tree != main_tree &&
  324. other->get_directory()->get_tree() != main_tree) {
  325. // Both files are in external dependable trees.
  326. cerr << "Error: header file " << dependable->get_fullpath()
  327. << " may be confused with " << other->get_fullpath()
  328. << ".\n";
  329. errors_occurred = true;
  330. } else if (other->get_directory()->get_tree() != _tree) {
  331. // This file is a source file in this tree, while the other
  332. // one is an external file. This is not a warning condition,
  333. // since maybe we've already installed the source file to the
  334. // global install directory on some previous build.
  335. } else {
  336. // Both files are within the same source tree.
  337. cerr << "Error: source file " << dependable->get_pathname()
  338. << " may be confused with " << other->get_pathname()
  339. << ".\n";
  340. errors_occurred = true;
  341. }
  342. }
  343. }
  344. return dependable;
  345. }
  346. ////////////////////////////////////////////////////////////////////
  347. // Function: PPDirectory::report_depends
  348. // Access: Public
  349. // Description: Reports all the directories that the current
  350. // directory depends on.
  351. ////////////////////////////////////////////////////////////////////
  352. void PPDirectory::
  353. report_depends() const {
  354. if (_i_depend_on.empty()) {
  355. cerr << _dirname << " depends on no other directories.\n";
  356. } else {
  357. // Get the complete set of directories we depend on.
  358. Depends dep;
  359. get_complete_i_depend_on(dep);
  360. cerr << _dirname << " depends directly on the following directories:";
  361. show_directories(_i_depend_on);
  362. cerr << "and directly or indirectly on the following directories:";
  363. show_directories(dep);
  364. }
  365. }
  366. ////////////////////////////////////////////////////////////////////
  367. // Function: PPDirectory::report_reverse_depends
  368. // Access: Public
  369. // Description: Reports all the directories that depend on the
  370. // current directory.
  371. ////////////////////////////////////////////////////////////////////
  372. void PPDirectory::
  373. report_reverse_depends() const {
  374. if (_depends_on_me.empty()) {
  375. cerr << _dirname << " is needed by no other directories.\n";
  376. } else {
  377. // Get the complete set of directories we depend on.
  378. Depends dep;
  379. get_complete_depends_on_me(dep);
  380. cerr << _dirname << " is needed directly by the following directories:";
  381. show_directories(_depends_on_me);
  382. cerr << "and directly or indirectly by the following directories:";
  383. show_directories(dep);
  384. }
  385. }
  386. ////////////////////////////////////////////////////////////////////
  387. // Function: PPDirectory::r_scan
  388. // Access: Private
  389. // Description: The recursive implementation of
  390. // PPDirectoryTree::scan_source().
  391. ////////////////////////////////////////////////////////////////////
  392. bool PPDirectory::
  393. r_scan(const string &prefix) {
  394. Filename root_name = ".";
  395. if (!prefix.empty()) {
  396. root_name = prefix.substr(0, prefix.length() - 1);
  397. }
  398. // Collect all the filenames in the directory in this vector first.
  399. vector<string> filenames;
  400. if (!root_name.scan_directory(filenames)) {
  401. cerr << "Unable to scan directory " << root_name << "\n";
  402. return false;
  403. }
  404. vector<string>::const_iterator fi;
  405. for (fi = filenames.begin(); fi != filenames.end(); ++fi) {
  406. string filename = (*fi);
  407. if (!filename.empty() && filename[0] != '.') {
  408. // Is this possibly a subdirectory with its own Sources.pp
  409. // within it?
  410. string next_prefix = prefix + filename + "/";
  411. Filename source_filename = next_prefix + SOURCE_FILENAME;
  412. if (source_filename.exists()) {
  413. PPDirectory *subtree = new PPDirectory(filename, this);
  414. if (!subtree->r_scan(next_prefix)) {
  415. return false;
  416. }
  417. }
  418. }
  419. }
  420. return true;
  421. }
  422. ////////////////////////////////////////////////////////////////////
  423. // Function: PPDirectory::scan_extra_depends
  424. // Access: Private
  425. // Description: The recursive implementation of
  426. // PPDirectoryTree::scan_extra_depends(). This simply
  427. // adds each *.h or *.I file in the directory as a
  428. // dependable file. It is assumed to be called for an
  429. // external directory named by DEPENDABLE_HEADER_DIRS.
  430. ////////////////////////////////////////////////////////////////////
  431. bool PPDirectory::
  432. scan_extra_depends(const string &cache_filename) {
  433. Filename root_name = get_fullpath();
  434. vector<string> filenames;
  435. if (!root_name.scan_directory(filenames)) {
  436. cerr << "Unable to scan directory " << root_name << "\n";
  437. return false;
  438. }
  439. if (verbose) {
  440. cerr << "Scanning external directory " << get_fullpath() << "\n";
  441. }
  442. vector<string>::const_iterator fi;
  443. for (fi = filenames.begin(); fi != filenames.end(); ++fi) {
  444. string filename = (*fi);
  445. if (!filename.empty() && filename[0] != '.' &&
  446. filename != string("CVS") &&
  447. filename != cache_filename) {
  448. get_dependable_file(filename, true);
  449. }
  450. }
  451. return true;
  452. }
  453. ////////////////////////////////////////////////////////////////////
  454. // Function: PPDirectory::read_source_file
  455. // Access: Private
  456. // Description: Recursively reads in the source file at each level,
  457. // if defined.
  458. ////////////////////////////////////////////////////////////////////
  459. bool PPDirectory::
  460. read_source_file(const string &prefix, PPNamedScopes *named_scopes) {
  461. Filename source_filename = prefix + SOURCE_FILENAME;
  462. source_filename.set_text();
  463. ifstream in;
  464. if (source_filename.open_read(in)) {
  465. if (verbose) {
  466. cerr << "Reading (dir) \"" << source_filename << "\"\n";
  467. }
  468. named_scopes->set_current(_dirname);
  469. _scope = named_scopes->make_scope("");
  470. _scope->define_variable("SOURCEFILE", SOURCE_FILENAME);
  471. _scope->define_variable("DIRNAME", _dirname);
  472. _scope->define_variable("DIRPREFIX", prefix);
  473. _scope->define_variable("PATH", get_path());
  474. _scope->define_variable("SUBDIRS", get_child_dirnames());
  475. _scope->define_variable("SUBTREE", get_complete_subtree());
  476. _scope->set_directory(this);
  477. _source = new PPCommandFile(_scope);
  478. if (!_source->read_stream(in, source_filename)) {
  479. return false;
  480. }
  481. }
  482. Children::iterator ci;
  483. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  484. if (!(*ci)->read_source_file(prefix + (*ci)->get_dirname() + "/",
  485. named_scopes)) {
  486. return false;
  487. }
  488. }
  489. return true;
  490. }
  491. ////////////////////////////////////////////////////////////////////
  492. // Function: PPDirectory::read_depends_file
  493. // Access: Private
  494. // Description: Recursively reads in the dependency definition file
  495. // for each source file.
  496. ////////////////////////////////////////////////////////////////////
  497. bool PPDirectory::
  498. read_depends_file(PPNamedScopes *named_scopes) {
  499. if (_scope != (PPScope *)NULL) {
  500. // Read the depends file, so we can determine the relationship
  501. // between this source file and all of the other source files.
  502. string depends_filename = _scope->expand_variable("DEPENDS_FILE");
  503. if (depends_filename.empty()) {
  504. cerr << "No definition given for $[DEPENDS_FILE], cannot process.\n";
  505. return false;
  506. }
  507. named_scopes->set_current(_dirname);
  508. current_output_directory = this;
  509. PPCommandFile depends(_scope);
  510. if (!depends.read_file(depends_filename)) {
  511. cerr << "Error reading dependency definition file "
  512. << depends_filename << ".\n";
  513. return false;
  514. }
  515. // This should have defined the variable DEPEND_DIRS, which lists
  516. // the various dirnames this source file depends on.
  517. vector<string> dirnames;
  518. tokenize_whitespace(_scope->expand_variable("DEPEND_DIRS"), dirnames);
  519. vector<string>::const_iterator ni;
  520. for (ni = dirnames.begin(); ni != dirnames.end(); ++ni) {
  521. const string &dirname = (*ni);
  522. PPDirectory *dir = _tree->find_dirname(dirname);
  523. if (dir == (PPDirectory *)NULL) {
  524. cerr << "Could not find dependent dirname " << dirname << "\n";
  525. } else {
  526. if (dir != this) {
  527. _i_depend_on.insert(dir);
  528. dir->_depends_on_me.insert(this);
  529. }
  530. }
  531. }
  532. // This may also have defined the variable DEPENDABLE_HEADERS,
  533. // which lists the header files in this directory that C/C++
  534. // source files in this and other directories might be including
  535. // (and will therefore depend on).
  536. vector<string> headers;
  537. tokenize_whitespace(_scope->expand_variable("DEPENDABLE_HEADERS"), headers);
  538. for (ni = headers.begin(); ni != headers.end(); ++ni) {
  539. get_dependable_file(*ni, true);
  540. }
  541. }
  542. Children::iterator ci;
  543. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  544. if (!(*ci)->read_depends_file(named_scopes)) {
  545. return false;
  546. }
  547. }
  548. return true;
  549. }
  550. ////////////////////////////////////////////////////////////////////
  551. // Function: PPDirectory::resolve_dependencies
  552. // Access: Private
  553. // Description: Visits each directory and assigns a correct
  554. // _depends_index to each one, such that if directory A
  555. // depends on directory B then A._depends_index >
  556. // B._depends_index.
  557. //
  558. // This also detects cycles in the directory dependency
  559. // graph.
  560. ////////////////////////////////////////////////////////////////////
  561. bool PPDirectory::
  562. resolve_dependencies() {
  563. if (!compute_depends_index()) {
  564. return false;
  565. }
  566. Children::iterator ci;
  567. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  568. if (!(*ci)->resolve_dependencies()) {
  569. return false;
  570. }
  571. }
  572. // Now that we've resolved all of our children's dependencies,
  573. // redefine our SUBDIRS and SUBTREE variables to put things in the
  574. // right order.
  575. if (_scope != (PPScope *)NULL) {
  576. _scope->define_variable("SUBDIRS", get_child_dirnames());
  577. _scope->define_variable("SUBTREE", get_complete_subtree());
  578. }
  579. return true;
  580. }
  581. ////////////////////////////////////////////////////////////////////
  582. // Function: PPDirectory::compute_depends_index
  583. // Access: Private
  584. // Description: Computes the dependency score for a particular
  585. // directory. See resolve_dependencies().
  586. ////////////////////////////////////////////////////////////////////
  587. bool PPDirectory::
  588. compute_depends_index() {
  589. if (_depends_index != 0) {
  590. return true;
  591. }
  592. if (_i_depend_on.empty()) {
  593. _depends_index = 1;
  594. return true;
  595. }
  596. _computing_depends_index = true;
  597. int max_index = 0;
  598. Depends::iterator di;
  599. for (di = _i_depend_on.begin(); di != _i_depend_on.end(); ++di) {
  600. if ((*di)->_computing_depends_index) {
  601. // Oops, we have a cycle!
  602. cerr << "Cycle detected in inter-directory dependencies!\n"
  603. << _dirname << " depends on " << (*di)->_dirname << "\n";
  604. return false;
  605. }
  606. if (!(*di)->compute_depends_index()) {
  607. // Keep reporting the cycle as we unroll the recursion.
  608. cerr << _dirname << " depends on " << (*di)->_dirname << "\n";
  609. return false;
  610. }
  611. max_index = max(max_index, (*di)->_depends_index);
  612. }
  613. _computing_depends_index = false;
  614. _depends_index = max_index + 1;
  615. return true;
  616. }
  617. ////////////////////////////////////////////////////////////////////
  618. // Function: PPDirectory::read_file_dependencies
  619. // Access: Private
  620. // Description: Before processing the source files, makes a pass and
  621. // reads in all of the dependency cache files so we'll
  622. // have a heads-up on which files depend on the others.
  623. ////////////////////////////////////////////////////////////////////
  624. void PPDirectory::
  625. read_file_dependencies(const string &cache_filename) {
  626. // Open up the dependency cache file in the directory.
  627. Filename cache_pathname(get_fullpath(), cache_filename);
  628. cache_pathname.set_text();
  629. ifstream in;
  630. // Does the cache file exist, and is it recent enough? We don't
  631. // trust old cache files on principle.
  632. string os_specific = cache_pathname.to_os_specific();
  633. time_t now = time(NULL);
  634. #ifdef WIN32_VC
  635. struct _stat this_buf;
  636. bool this_exists = false;
  637. if (_stat(os_specific.c_str(), &this_buf) == 0) {
  638. this_exists = true;
  639. }
  640. #else // WIN32_VC
  641. struct stat this_buf;
  642. bool this_exists = false;
  643. if (stat(os_specific.c_str(), &this_buf) == 0) {
  644. this_exists = true;
  645. }
  646. #endif
  647. if (!this_exists) {
  648. // The cache file doesn't exist. That's OK.
  649. if (verbose) {
  650. cerr << "No cache file: \"" << cache_pathname << "\"\n";
  651. }
  652. } else if (this_buf.st_mtime < now - 60 * max_cache_minutes) {
  653. // It exists, but it's too old.
  654. if (verbose) {
  655. cerr << "Cache file too old: \"" << cache_pathname << "\"\n";
  656. }
  657. } else {
  658. // It exists and is new enough; use it.
  659. if (!cache_pathname.open_read(in)) {
  660. cerr << "Couldn't read \"" << cache_pathname << "\"\n";
  661. } else {
  662. if (verbose) {
  663. cerr << "Loading cache \"" << cache_pathname << "\"\n";
  664. }
  665. bool okcache = true;
  666. string line;
  667. getline(in, line);
  668. while (!in.fail() && !in.eof()) {
  669. vector<string> words;
  670. tokenize_whitespace(line, words);
  671. if (words.size() >= 2) {
  672. PPDependableFile *file = get_dependable_file(words[0], false);
  673. if (!file->update_from_cache(words)) {
  674. // Hey, we asked for an invalid or absent file. Phooey.
  675. // Invalidate the cache, and also make sure that this
  676. // particular file (which maybe doesn't even exist) isn't
  677. // mentioned in the cache file any more.
  678. Dependables::iterator di;
  679. di = _dependables.find(words[0]);
  680. if (di != _dependables.end()) {
  681. _dependables.erase(di);
  682. }
  683. okcache = false;
  684. break;
  685. }
  686. }
  687. getline(in, line);
  688. }
  689. if (!okcache) {
  690. if (verbose) {
  691. cerr << "Cache \"" << cache_pathname << "\" is stale.\n";
  692. }
  693. Dependables::iterator di;
  694. for (di = _dependables.begin(); di != _dependables.end(); ++di) {
  695. (*di).second->clear_cache();
  696. }
  697. }
  698. }
  699. }
  700. Children::iterator ci;
  701. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  702. (*ci)->read_file_dependencies(cache_filename);
  703. }
  704. }
  705. ////////////////////////////////////////////////////////////////////
  706. // Function: PPDirectory::update_file_dependencies
  707. // Access: Private
  708. // Description: After all source processing has completed, makes one
  709. // more pass through the directory hierarchy and writes
  710. // out the inter-file dependency cache.
  711. ////////////////////////////////////////////////////////////////////
  712. void PPDirectory::
  713. update_file_dependencies(const string &cache_filename) {
  714. if (dry_run) {
  715. // If this is just a dry run, just report circularities.
  716. Dependables::const_iterator di;
  717. for (di = _dependables.begin(); di != _dependables.end(); ++di) {
  718. PPDependableFile *file = (*di).second;
  719. if (file->was_examined()) {
  720. if (file->is_circularity()) {
  721. cerr << "Warning: circular #include directives:\n"
  722. << " " << file->get_circularity() << "\n";
  723. }
  724. }
  725. }
  726. } else {
  727. // Open up the dependency cache file in the directory.
  728. Filename cache_pathname(get_fullpath(), cache_filename);
  729. cache_pathname.set_text();
  730. cache_pathname.unlink();
  731. // If we have no files, don't bother writing the cache.
  732. bool wrote_anything = false;
  733. if (!_dependables.empty()) {
  734. ofstream out;
  735. if (!cache_pathname.open_write(out)) {
  736. cerr << "Cannot update cache dependency file " << cache_pathname << "\n";
  737. return;
  738. }
  739. if (verbose) {
  740. cerr << "Rewriting cache " << cache_pathname << "\n";
  741. }
  742. // Walk through our list of dependable files, writing them out the
  743. // the cache file.
  744. bool external_tree = (_tree->get_main_tree() != _tree);
  745. Dependables::const_iterator di;
  746. for (di = _dependables.begin(); di != _dependables.end(); ++di) {
  747. PPDependableFile *file = (*di).second;
  748. if (file->was_examined() || (external_tree && file->was_cached())) {
  749. if (file->is_circularity()) {
  750. cerr << "Warning: circular #include directives:\n"
  751. << " " << file->get_circularity() << "\n";
  752. }
  753. file->write_cache(out);
  754. wrote_anything = true;
  755. }
  756. }
  757. out.close();
  758. }
  759. if (!wrote_anything) {
  760. // Well, if we didn't write anything, remove the cache file
  761. // after all.
  762. cache_pathname.unlink();
  763. }
  764. }
  765. Children::iterator ci;
  766. for (ci = _children.begin(); ci != _children.end(); ++ci) {
  767. (*ci)->update_file_dependencies(cache_filename);
  768. }
  769. }
  770. ////////////////////////////////////////////////////////////////////
  771. // Function: PPDirectory::get_complete_i_depend_on
  772. // Access: Private
  773. // Description: Gets the transitive closure of i_depend_on. This
  774. // fills the given set (which must have been empty
  775. // before this call) with the complete set of all
  776. // directories this directory depends on, directly or
  777. // indirectly.
  778. ////////////////////////////////////////////////////////////////////
  779. void PPDirectory::
  780. get_complete_i_depend_on(Depends &dep) const {
  781. Depends::const_iterator di;
  782. for (di = _i_depend_on.begin(); di != _i_depend_on.end(); ++di) {
  783. PPDirectory *dir = (*di);
  784. bool inserted = dep.insert(dir).second;
  785. if (inserted) {
  786. dir->get_complete_i_depend_on(dep);
  787. }
  788. }
  789. }
  790. ////////////////////////////////////////////////////////////////////
  791. // Function: PPDirectory::get_complete_depends_on_me
  792. // Access: Private
  793. // Description: Gets the transitive closure of depends_on_me. This
  794. // fills the given set (which must have been empty
  795. // before this call) with the complete set of all
  796. // directories this that depend on this directory,
  797. // directly or indirectly.
  798. ////////////////////////////////////////////////////////////////////
  799. void PPDirectory::
  800. get_complete_depends_on_me(Depends &dep) const {
  801. Depends::const_iterator di;
  802. for (di = _depends_on_me.begin(); di != _depends_on_me.end(); ++di) {
  803. PPDirectory *dir = (*di);
  804. bool inserted = dep.insert(dir).second;
  805. if (inserted) {
  806. dir->get_complete_depends_on_me(dep);
  807. }
  808. }
  809. }
  810. ////////////////////////////////////////////////////////////////////
  811. // Function: PPDirectory::show_directories
  812. // Access: Private
  813. // Description: Writes a set of dependency directory names to
  814. // standard error. The output begins with a newline.
  815. ////////////////////////////////////////////////////////////////////
  816. void PPDirectory::
  817. show_directories(const PPDirectory::Depends &dep) const {
  818. // Copy the set into a vector, so we can sort it into a nice order
  819. // for the user's pleasure.
  820. vector<PPDirectory *> dirs;
  821. copy(dep.begin(), dep.end(),
  822. back_insert_iterator<vector<PPDirectory *> >(dirs));
  823. sort(dirs.begin(), dirs.end(), SortDirectoriesByDependencyAndName());
  824. static const int max_col = 72;
  825. int col = max_col;
  826. vector<PPDirectory *>::const_iterator di;
  827. for (di = dirs.begin(); di != dirs.end(); ++di) {
  828. const string &dirname = (*di)->_dirname;
  829. col += dirname.length() + 1;
  830. if (col >= max_col) {
  831. col = dirname.length() + 2;
  832. cerr << "\n " << dirname;
  833. } else {
  834. cerr << " " << dirname;
  835. }
  836. }
  837. cerr << "\n";
  838. }