ppDirectory.cxx 31 KB

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