From 856043703326223befc1652da647848ef59d9e62 Mon Sep 17 00:00:00 2001 From: David Rose Date: Wed, 29 Sep 2004 16:45:39 +0000 Subject: [PATCH] add DEPENDABLE_HEADER_DIRS --- panda/src/doc/ppremake-variables.txt | 7 ++ ppremake/config_msvc.h | 2 +- ppremake/configure.in | 2 +- ppremake/ppDependableFile.cxx | 22 +++++-- ppremake/ppDependableFile.h | 1 + ppremake/ppDirectory.cxx | 86 +++++++++++++++++++++--- ppremake/ppDirectory.h | 2 + ppremake/ppDirectoryTree.cxx | 99 +++++++++++++++++++++++++++- ppremake/ppDirectoryTree.h | 14 +++- ppremake/ppMain.cxx | 11 ++++ 10 files changed, 227 insertions(+), 19 deletions(-) diff --git a/panda/src/doc/ppremake-variables.txt b/panda/src/doc/ppremake-variables.txt index 9f572e4727..2b5ec0a352 100644 --- a/panda/src/doc/ppremake-variables.txt +++ b/panda/src/doc/ppremake-variables.txt @@ -154,6 +154,13 @@ $DTOOL/pptempl/System.pp: Like $[DEPEND_DIRS], this is set by the $[DEPENDS_FILE] script, and has a different value within each source directory. + $[DEPENDABLE_HEADER_DIRS] - the list of directories outside of the + current source tree in which additional header files ("dependable + headers") may be found. This is used to implement inter-package + dependencies. Any files found in the directories named here are + deemed to be dependable headers, and the $[depdencies] variable + will include these files. + The following functions are built into the ppremake executable. In general, these operate on one word or a group of words separated by diff --git a/ppremake/config_msvc.h b/ppremake/config_msvc.h index b37b052671..a1b5f73a6a 100644 --- a/ppremake/config_msvc.h +++ b/ppremake/config_msvc.h @@ -86,5 +86,5 @@ ** Also be sure to change the version number ** ** at the beginning of configure.in. ** **************** ****************/ -#define VERSION "1.16" +#define VERSION "1.17" /**************** UPDATE VERSION NUMBER HERE ****************/ diff --git a/ppremake/configure.in b/ppremake/configure.in index c6f97a978a..5aa574139b 100644 --- a/ppremake/configure.in +++ b/ppremake/configure.in @@ -5,7 +5,7 @@ dnl **************** UPDATE VERSION NUMBER HERE **************** dnl ** Also be sure to change the version number ** dnl ** at the end of config_msvc.h. ** dnl **************** **************** -AM_INIT_AUTOMAKE(ppremake, 1.16) +AM_INIT_AUTOMAKE(ppremake, 1.17) dnl **************** UPDATE VERSION NUMBER HERE **************** AM_CONFIG_HEADER(config.h) diff --git a/ppremake/ppDependableFile.cxx b/ppremake/ppDependableFile.cxx index e85873b506..65e4ea3bb8 100644 --- a/ppremake/ppDependableFile.cxx +++ b/ppremake/ppDependableFile.cxx @@ -73,7 +73,7 @@ update_from_cache(const vector &words) { time_t mtime = strtol(words[1].c_str(), (char **)NULL, 10); if (mtime == get_mtime()) { // The modification matches; preserve the cache information. - PPDirectoryTree *tree = _directory->get_tree(); + PPDirectoryTree *tree = _directory->get_tree()->get_main_tree(); _dependencies.clear(); vector::const_iterator wi; @@ -173,6 +173,16 @@ get_pathname() const { return _directory->get_path() + "/" + _filename; } +//////////////////////////////////////////////////////////////////// +// Function: PPDependableFile::get_fullpath +// Access: Public +// Description: Returns the full pathname to this particular filename. +//////////////////////////////////////////////////////////////////// +string PPDependableFile:: +get_fullpath() const { + return _directory->get_fullpath() + "/" + _filename; +} + //////////////////////////////////////////////////////////////////// // Function: PPDependableFile::get_dirpath // Access: Public @@ -351,19 +361,19 @@ compute_dependencies(string &circularity) { if ((_flags & F_from_cache) == 0) { // Now open the file and scan it for #include statements. - ifstream in(get_pathname().c_str()); + ifstream in(get_fullpath().c_str()); if (!in) { // Can't read the file, or the file doesn't exist. Interesting. if (exists()) { - cerr << "Warning: dependent file " << get_pathname() + cerr << "Warning: dependent file " << get_fullpath() << " exists but cannot be read.\n"; } else { - cerr << "Warning: dependent file " << get_pathname() + cerr << "Warning: dependent file " << get_fullpath() << " does not exist.\n"; } } else { - PPDirectoryTree *tree = _directory->get_tree(); + PPDirectoryTree *tree = _directory->get_tree()->get_main_tree(); bool okcircular = false; string line; @@ -442,7 +452,7 @@ stat_file() { _flags |= F_statted; struct stat st; - Filename pathname(get_pathname()); + Filename pathname(get_fullpath()); string ospath = pathname.to_os_specific(); if (stat(ospath.c_str(), &st) < 0) { // The file doesn't exist! diff --git a/ppremake/ppDependableFile.h b/ppremake/ppDependableFile.h index 83ea4f9ed5..a4339435f9 100644 --- a/ppremake/ppDependableFile.h +++ b/ppremake/ppDependableFile.h @@ -35,6 +35,7 @@ public: PPDirectory *get_directory() const; const string &get_filename() const; string get_pathname() const; + string get_fullpath() const; string get_dirpath() const; bool exists(); diff --git a/ppremake/ppDirectory.cxx b/ppremake/ppDirectory.cxx index 1991b7b3cb..662871239a 100644 --- a/ppremake/ppDirectory.cxx +++ b/ppremake/ppDirectory.cxx @@ -179,6 +179,20 @@ get_path() const { return _parent->get_path() + "/" + _dirname; } +//////////////////////////////////////////////////////////////////// +// Function: PPDirectory::get_fullpath +// Access: Public +// Description: Returns the full path to this particular directory. +// This does not include a trailing slash. +//////////////////////////////////////////////////////////////////// +string PPDirectory:: +get_fullpath() const { + if (_parent == (PPDirectory *)NULL) { + return _tree->get_fullpath(); + } + return _tree->get_fullpath() + "/" + get_path(); +} + //////////////////////////////////////////////////////////////////// // Function: PPDirectory::get_rel_to // Access: Public @@ -194,6 +208,11 @@ get_rel_to(const PPDirectory *other) const { return "."; } + if (a->_tree != b->_tree) { + // If they're in different trees, just return the full path to b. + return b->get_fullpath(); + } + string prefix, postfix; while (a->_depth > b->_depth) { prefix += "../"; @@ -332,14 +351,31 @@ get_dependable_file(const string &filename, bool is_header) { _dependables.insert(Dependables::value_type(filename, dependable)); if (is_header) { - bool unique = _tree->_dependables.insert + PPDirectoryTree *main_tree = _tree->get_main_tree(); + bool unique = main_tree->_dependables.insert (PPDirectoryTree::Dependables::value_type(filename, dependable)).second; if (!unique) { - cerr << "Warning: source file " << dependable->get_pathname() - << " may be confused with " - << _tree->find_dependable_file(filename)->get_pathname() - << ".\n"; + PPDependableFile *other = main_tree->find_dependable_file(filename); + if (_tree != main_tree) { + // Both files are in external dependable trees. + cerr << "Warning: header file " << dependable->get_fullpath() + << " may be confused with " << other->get_fullpath() + << ".\n"; + + } else if (other->get_directory()->get_tree() != _tree) { + // This file is a source file in this tree, while the other + // one is an external file. + cerr << "Warning: source file " << dependable->get_pathname() + << " may be confused with " << other->get_fullpath() + << ".\n"; + + } else { + // Both files are within the same source tree. + cerr << "Warning: source file " << dependable->get_pathname() + << " may be confused with " << other->get_pathname() + << ".\n"; + } } } @@ -397,7 +433,8 @@ report_reverse_depends() const { //////////////////////////////////////////////////////////////////// // Function: PPDirectory::r_scan // Access: Private -// Description: The recursive implementation of scan_source(). +// Description: The recursive implementation of +// PPDirectoryTree::scan_source(). //////////////////////////////////////////////////////////////////// bool PPDirectory:: r_scan(const string &prefix) { @@ -406,8 +443,7 @@ r_scan(const string &prefix) { root_name = prefix.substr(0, prefix.length() - 1); } - // Collect all the filenames in the directory in this vector first, - // so we can sort them. + // Collect all the filenames in the directory in this vector first. vector filenames; if (!root_name.scan_directory(filenames)) { cerr << "Unable to scan directory " << root_name << "\n"; @@ -436,6 +472,38 @@ r_scan(const string &prefix) { return true; } +//////////////////////////////////////////////////////////////////// +// Function: PPDirectory::scan_extra_depends +// Access: Private +// Description: The recursive implementation of +// PPDirectoryTree::scan_extra_depends(). This simply +// adds each *.h or *.I file in the directory as a +// dependable file. It is assumed to be called for an +// external directory named by DEPENDABLE_HEADER_DIRS. +//////////////////////////////////////////////////////////////////// +bool PPDirectory:: +scan_extra_depends(const string &cache_filename) { + Filename root_name = get_fullpath(); + + vector filenames; + if (!root_name.scan_directory(filenames)) { + cerr << "Unable to scan directory " << root_name << "\n"; + return false; + } + + vector::const_iterator fi; + for (fi = filenames.begin(); fi != filenames.end(); ++fi) { + string filename = (*fi); + + if (!filename.empty() && filename[0] != '.' && + filename != cache_filename) { + get_dependable_file(filename, true); + } + } + + return true; +} + //////////////////////////////////////////////////////////////////// // Function: PPDirectory::read_source_file // Access: Private @@ -690,7 +758,7 @@ update_file_dependencies(const string &cache_filename) { } else { // Open up the dependency cache file in the directory. - Filename cache_pathname(get_path(), cache_filename); + Filename cache_pathname(get_fullpath(), cache_filename); cache_pathname.set_text(); cache_pathname.unlink(); diff --git a/ppremake/ppDirectory.h b/ppremake/ppDirectory.h index a0d747c7af..fc4033cc79 100644 --- a/ppremake/ppDirectory.h +++ b/ppremake/ppDirectory.h @@ -38,6 +38,7 @@ public: const string &get_dirname() const; int get_depends_index() const; string get_path() const; + string get_fullpath() const; string get_rel_to(const PPDirectory *other) const; PPCommandFile *get_source() const; @@ -58,6 +59,7 @@ private: typedef set Depends; bool r_scan(const string &prefix); + bool scan_extra_depends(const string &cache_filename); bool read_source_file(const string &prefix, PPNamedScopes *named_scopes); bool read_depends_file(PPNamedScopes *named_scopes); bool resolve_dependencies(); diff --git a/ppremake/ppDirectoryTree.cxx b/ppremake/ppDirectoryTree.cxx index 63467f1bf9..be2a0e6bc1 100644 --- a/ppremake/ppDirectoryTree.cxx +++ b/ppremake/ppDirectoryTree.cxx @@ -5,6 +5,7 @@ #include "ppDirectoryTree.h" #include "ppDirectory.h" +#include "tokenize.h" //////////////////////////////////////////////////////////////////// // Function: PPDirectoryTree::Constructor @@ -12,7 +13,13 @@ // Description: //////////////////////////////////////////////////////////////////// PPDirectoryTree:: -PPDirectoryTree() { +PPDirectoryTree(PPDirectoryTree *main_tree) { + if (main_tree == NULL) { + _main_tree = this; + } else { + _main_tree = main_tree; + } + _root = new PPDirectory(this); } @@ -24,6 +31,35 @@ PPDirectoryTree() { PPDirectoryTree:: ~PPDirectoryTree() { delete _root; + + RelatedTrees::iterator ri; + for (ri = _related_trees.begin(); ri != _related_trees.end(); ++ri) { + delete (*ri); + } +} + +//////////////////////////////////////////////////////////////////// +// Function: PPDirectoryTree::get_main_tree +// Access: Public +// Description: Returns the PPDirectoryTree that represents the +// actual source hierarchy. If the return value is +// something other than this, it indicates that this +// tree is an external dependable tree. +//////////////////////////////////////////////////////////////////// +PPDirectoryTree *PPDirectoryTree:: +get_main_tree() { + return _main_tree; +} + +//////////////////////////////////////////////////////////////////// +// Function: PPDirectoryTree::set_fullpath +// Access: Public +// Description: Indicates the full path to the root of this +// particular tree. +//////////////////////////////////////////////////////////////////// +void PPDirectoryTree:: +set_fullpath(const string &fullpath) { + _fullpath = fullpath; } //////////////////////////////////////////////////////////////////// @@ -64,6 +100,52 @@ scan_depends(PPNamedScopes *named_scopes) { return true; } +//////////////////////////////////////////////////////////////////// +// Function: PPDirectoryTree::scan_extra_depends +// Access: Public +// Description: Accepts the value of DEPENDABLE_HEADER_DIRS, which +// was presumably set by the various Config.pp and/or +// Depends.pp scripts that were read in, and treats each +// named filename there as the name of a directory that +// contains header files in a separate but related tree, +// for which we also need to generate dependency rules +// in this tree. +//////////////////////////////////////////////////////////////////// +bool PPDirectoryTree:: +scan_extra_depends(const string &dependable_header_dirs, + const string &cache_filename) { + bool okflag = true; + + vector dirnames; + tokenize_whitespace(dependable_header_dirs, dirnames); + + // Sort dirnames and remove duplicates. + sort(dirnames.begin(), dirnames.end()); + dirnames.erase(unique(dirnames.begin(), dirnames.end()), dirnames.end()); + + vector::const_iterator ni; + for (ni = dirnames.begin(); ni != dirnames.end(); ++ni) { + string dirname = (*ni); + + if (dirname[0] != '/') { + // Insist that the external dirname be a full pathname. + dirname = _fullpath + "/" + dirname; + } + + // Now we need to make up a different tree for each external + // dirname. + PPDirectoryTree *tree = new PPDirectoryTree(this); + tree->set_fullpath(dirname); + _related_trees.push_back(tree); + + if (!tree->get_root()->scan_extra_depends(cache_filename)) { + okflag = false; + } + } + + return okflag; +} + //////////////////////////////////////////////////////////////////// // Function: PPDirectoryTree::count_source_files // Access: Public @@ -85,6 +167,16 @@ get_root() const { return _root; } +//////////////////////////////////////////////////////////////////// +// Function: PPDirectoryTree::get_fullpath +// Access: Public +// Description: Returns the full path to the root of the tree. +//////////////////////////////////////////////////////////////////// +const string &PPDirectoryTree:: +get_fullpath() const { + return _fullpath; +} + //////////////////////////////////////////////////////////////////// // Function: PPDirectoryTree::get_complete_tree // Access: Public @@ -197,5 +289,10 @@ read_file_dependencies(const string &cache_filename) { void PPDirectoryTree:: update_file_dependencies(const string &cache_filename) { _root->update_file_dependencies(cache_filename); + + RelatedTrees::iterator ri; + for (ri = _related_trees.begin(); ri != _related_trees.end(); ++ri) { + (*ri)->update_file_dependencies(cache_filename); + } } diff --git a/ppremake/ppDirectoryTree.h b/ppremake/ppDirectoryTree.h index 5c30439ff9..c98e5e20d2 100644 --- a/ppremake/ppDirectoryTree.h +++ b/ppremake/ppDirectoryTree.h @@ -9,6 +9,7 @@ #include "ppremake.h" #include +#include class PPNamedScopes; class PPDirectory; @@ -23,14 +24,20 @@ class PPDependableFile; //////////////////////////////////////////////////////////////////// class PPDirectoryTree { public: - PPDirectoryTree(); + PPDirectoryTree(PPDirectoryTree *main_tree = NULL); ~PPDirectoryTree(); + PPDirectoryTree *get_main_tree(); + + void set_fullpath(const string &fullpath); bool scan_source(PPNamedScopes *named_scopes); bool scan_depends(PPNamedScopes *named_scopes); + bool scan_extra_depends(const string &dependable_header_dirs, + const string &cache_filename); int count_source_files() const; PPDirectory *get_root() const; + const string &get_fullpath() const; string get_complete_tree() const; @@ -44,7 +51,9 @@ public: void update_file_dependencies(const string &cache_filename); private: + PPDirectoryTree *_main_tree; PPDirectory *_root; + string _fullpath; typedef map Dirnames; Dirnames _dirnames; @@ -52,6 +61,9 @@ private: typedef map Dependables; Dependables _dependables; + typedef vector RelatedTrees; + RelatedTrees _related_trees; + friend class PPDirectory; }; diff --git a/ppremake/ppMain.cxx b/ppremake/ppMain.cxx index 6f6554831a..c19772e4f9 100644 --- a/ppremake/ppMain.cxx +++ b/ppremake/ppMain.cxx @@ -116,11 +116,13 @@ read_source(const string &root) { } _root = get_cwd(); + _tree.set_fullpath(_root); cerr << "Root is " << _root << "\n"; _def_scope = new PPScope(&_named_scopes); _def_scope->define_variable("PACKAGEFILE", package_file); _def_scope->define_variable("TOPDIR", _root); + _def_scope->define_variable("DEPENDABLE_HEADER_DIRS", ""); _defs = new PPCommandFile(_def_scope); if (!_defs->read_file(PACKAGE_FILENAME)) { @@ -165,6 +167,15 @@ read_source(const string &root) { return false; } + string dependable_header_dirs = + _def_scope->expand_variable("DEPENDABLE_HEADER_DIRS"); + string cache_filename = + _def_scope->expand_variable("DEPENDENCY_CACHE_FILENAME"); + + if (!_tree.scan_extra_depends(dependable_header_dirs, cache_filename)) { + return false; + } + return true; }