ppMain.cxx 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390
  1. // Filename: ppMain.cxx
  2. // Created by: drose (28Sep00)
  3. //
  4. ////////////////////////////////////////////////////////////////////
  5. #include "ppMain.h"
  6. #include "ppScope.h"
  7. #include "ppCommandFile.h"
  8. #include "ppDirectory.h"
  9. #include "tokenize.h"
  10. #include <unistd.h>
  11. #include <assert.h>
  12. #include <errno.h>
  13. #include <stdio.h> // for perror
  14. string PPMain::_root;
  15. ////////////////////////////////////////////////////////////////////
  16. // Function: PPMain::Constructor
  17. // Access: Public
  18. // Description:
  19. ////////////////////////////////////////////////////////////////////
  20. PPMain::
  21. PPMain(PPScope *global_scope) {
  22. _global_scope = global_scope;
  23. PPScope::push_scope(_global_scope);
  24. _def_scope = (PPScope *)NULL;
  25. _defs = (PPCommandFile *)NULL;
  26. // save current working dir
  27. char tmp[1024];
  28. string dirpath = getcwd(tmp,sizeof(tmp));
  29. size_t slash_pos = dirpath.rfind('/');
  30. if (slash_pos == string::npos) {
  31. _original_working_dir = dirpath;
  32. } else {
  33. _original_working_dir = dirpath.substr(slash_pos + 1);
  34. }
  35. }
  36. ////////////////////////////////////////////////////////////////////
  37. // Function: PPMain::Destructor
  38. // Access: Public
  39. // Description:
  40. ////////////////////////////////////////////////////////////////////
  41. PPMain::
  42. ~PPMain() {
  43. if (_def_scope != (PPScope *)NULL) {
  44. delete _def_scope;
  45. }
  46. if (_defs != (PPCommandFile *)NULL) {
  47. delete _defs;
  48. }
  49. }
  50. ////////////////////////////////////////////////////////////////////
  51. // Function: PPMain::read_source
  52. // Access: Public
  53. // Description: Reads the directory hierarchy of Sources.pp files, at
  54. // the indicated directory and below.
  55. ////////////////////////////////////////////////////////////////////
  56. bool PPMain::
  57. read_source(const string &root) {
  58. // First, find the top of the source tree, as indicated by the
  59. // presence of a Package.pp file.
  60. string trydir = root;
  61. string package_file = trydir + "/" + PACKAGE_FILENAME;
  62. while (access(package_file.c_str(), F_OK) != 0) {
  63. // We continue to walk up directories as long as we see a source
  64. // file in each directory. When we stop seeing source files, we
  65. // stop walking upstairs.
  66. string source_file = trydir + "/" + SOURCE_FILENAME;
  67. if (access(source_file.c_str(), F_OK) != 0) {
  68. cerr << "Could not find ppremake package file " << PACKAGE_FILENAME
  69. << ".\n\n"
  70. << "This file should be present in the top of the source directory tree;\n"
  71. << "it defines implementation-specific variables to control the output\n"
  72. << "of ppremake, as well as pointing out the installed location of\n"
  73. << "important ppremake config files.\n\n";
  74. return false;
  75. }
  76. trydir += "/..";
  77. package_file = trydir + "/" + PACKAGE_FILENAME;
  78. }
  79. // Now cd to the source root and get the actual path.
  80. if (chdir(trydir.c_str()) < 0) {
  81. perror("chdir");
  82. return false;
  83. }
  84. _root = get_cwd();
  85. cerr << "Root is " << _root << "\n";
  86. _def_scope = new PPScope(&_named_scopes);
  87. _def_scope->define_variable("PACKAGEFILE", package_file);
  88. _def_scope->define_variable("TOPDIR", _root);
  89. _defs = new PPCommandFile(_def_scope);
  90. if (!_defs->read_file(PACKAGE_FILENAME)) {
  91. return false;
  92. }
  93. // Now check the *_PLATFORM variables that System.pp was supposed to
  94. // set.
  95. if (!trim_blanks(_def_scope->expand_string("$[UNIX_PLATFORM]")).empty()) {
  96. unix_platform = true;
  97. }
  98. if (!trim_blanks(_def_scope->expand_string("$[WINDOWS_PLATFORM]")).empty()) {
  99. windows_platform = true;
  100. }
  101. PPScope::push_scope(_def_scope);
  102. if (!_tree.scan_source(&_named_scopes)) {
  103. return false;
  104. }
  105. _def_scope->define_variable("TREE", _tree.get_complete_tree());
  106. if (_tree.count_source_files() == 0) {
  107. cerr << "Could not find any source definition files named " << SOURCE_FILENAME
  108. << ".\n\n"
  109. << "A file by this name should be present in each directory of the source\n"
  110. << "hierarchy; it defines the source files and targets that should be\n"
  111. << "built in each directory, as well as the relationships between the\n"
  112. << "directories.\n\n";
  113. return false;
  114. }
  115. cerr << "Read " << _tree.count_source_files() << " " << SOURCE_FILENAME
  116. << " files.\n";
  117. if (!read_global_file()) {
  118. return false;
  119. }
  120. if (!_tree.scan_depends(&_named_scopes)) {
  121. return false;
  122. }
  123. return true;
  124. }
  125. ////////////////////////////////////////////////////////////////////
  126. // Function: PPMain::process_all
  127. // Access: Public
  128. // Description: Does all the processing on all known directories.
  129. // See process().
  130. ////////////////////////////////////////////////////////////////////
  131. bool PPMain::
  132. process_all() {
  133. string cache_filename = _def_scope->expand_variable("DEPENDENCY_CACHE_FILENAME");
  134. if (cache_filename.empty()) {
  135. cerr << "Warning: no definition given for $[DEPENDENCY_CACHE_FILENAME].\n";
  136. } else {
  137. _tree.read_file_dependencies(cache_filename);
  138. }
  139. if (!r_process_all(_tree.get_root())) {
  140. return false;
  141. }
  142. if (!cache_filename.empty()) {
  143. _tree.update_file_dependencies(cache_filename);
  144. }
  145. return true;
  146. }
  147. ////////////////////////////////////////////////////////////////////
  148. // Function: PPMain::process
  149. // Access: Public
  150. // Description: Does the processing associated with the source file
  151. // in the indicated subdirectory name. This involves
  152. // reading in the template file and generating whatever
  153. // output the template file indicates.
  154. ////////////////////////////////////////////////////////////////////
  155. bool PPMain::
  156. process(const string &dirnam) {
  157. string cache_filename = _def_scope->expand_variable("DEPENDENCY_CACHE_FILENAME");
  158. string dirname = dirnam;
  159. if (cache_filename.empty()) {
  160. cerr << "Warning: no definition given for $[DEPENDENCY_CACHE_FILENAME].\n";
  161. } else {
  162. _tree.read_file_dependencies(cache_filename);
  163. }
  164. if(dirname == ".") {
  165. dirname = _original_working_dir;
  166. }
  167. PPDirectory *dir = _tree.find_dirname(dirname);
  168. if (dir == (PPDirectory *)NULL) {
  169. cerr << "Unknown directory: " << dirname << "\n";
  170. return false;
  171. }
  172. if (dir->get_source() == (PPCommandFile *)NULL) {
  173. cerr << "No source file in " << dirname << "\n";
  174. return false;
  175. }
  176. if (!p_process(dir)) {
  177. return false;
  178. }
  179. if (!cache_filename.empty()) {
  180. _tree.update_file_dependencies(cache_filename);
  181. }
  182. return true;
  183. }
  184. ////////////////////////////////////////////////////////////////////
  185. // Function: PPMain::report_depends
  186. // Access: Public
  187. // Description: Reports all the directories that the named directory
  188. // depends on.
  189. ////////////////////////////////////////////////////////////////////
  190. void PPMain::
  191. report_depends(const string &dirname) const {
  192. PPDirectory *dir = _tree.find_dirname(dirname);
  193. if (dir == (PPDirectory *)NULL) {
  194. cerr << "Unknown directory: " << dirname << "\n";
  195. return;
  196. }
  197. dir->report_depends();
  198. }
  199. ////////////////////////////////////////////////////////////////////
  200. // Function: PPMain::report_needs
  201. // Access: Public
  202. // Description: Reports all the directories that depend on (need) the
  203. // named directory.
  204. ////////////////////////////////////////////////////////////////////
  205. void PPMain::
  206. report_needs(const string &dirname) const {
  207. PPDirectory *dir = _tree.find_dirname(dirname);
  208. if (dir == (PPDirectory *)NULL) {
  209. cerr << "Unknown directory: " << dirname << "\n";
  210. return;
  211. }
  212. dir->report_needs();
  213. }
  214. ////////////////////////////////////////////////////////////////////
  215. // Function: PPMain::get_root
  216. // Access: Public, Static
  217. // Description: Returns the full path to the root directory of the
  218. // source hierarchy; this is the directory in which the
  219. // runs most of the time.
  220. ////////////////////////////////////////////////////////////////////
  221. string PPMain::
  222. get_root() {
  223. return _root;
  224. }
  225. ////////////////////////////////////////////////////////////////////
  226. // Function: PPMain::chdir_root
  227. // Access: Public, Static
  228. // Description: Changes the current directory to the root directory
  229. // of the source hierarchy. This should be executed
  230. // after a temporary change to another directory, to
  231. // restore the current directory to a known state.
  232. ////////////////////////////////////////////////////////////////////
  233. void PPMain::
  234. chdir_root() {
  235. if (chdir(_root.c_str()) < 0) {
  236. perror("chdir");
  237. // This is a real error! We can't get back to our starting
  238. // directory!
  239. cerr << "Error! Source directory is invalid!\n";
  240. exit(1);
  241. }
  242. }
  243. ////////////////////////////////////////////////////////////////////
  244. // Function: PPMain::r_process_all
  245. // Access: Private
  246. // Description: The recursive implementation of process_all().
  247. ////////////////////////////////////////////////////////////////////
  248. bool PPMain::
  249. r_process_all(PPDirectory *dir) {
  250. if (dir->get_source() != (PPCommandFile *)NULL) {
  251. if (!p_process(dir)) {
  252. return false;
  253. }
  254. }
  255. int num_children = dir->get_num_children();
  256. for (int i = 0; i < num_children; i++) {
  257. if (!r_process_all(dir->get_child(i))) {
  258. return false;
  259. }
  260. }
  261. return true;
  262. }
  263. ////////////////////////////////////////////////////////////////////
  264. // Function: PPMain::p_process
  265. // Access: Private
  266. // Description: The private implementation of process().
  267. ////////////////////////////////////////////////////////////////////
  268. bool PPMain::
  269. p_process(PPDirectory *dir) {
  270. current_output_directory = dir;
  271. _named_scopes.set_current(dir->get_dirname());
  272. PPCommandFile *source = dir->get_source();
  273. assert(source != (PPCommandFile *)NULL);
  274. PPScope *scope = source->get_scope();
  275. string template_filename = scope->expand_variable("TEMPLATE_FILE");
  276. if (template_filename.empty()) {
  277. cerr << "No definition given for $[TEMPLATE_FILE], cannot process.\n";
  278. return false;
  279. }
  280. PPCommandFile template_file(scope);
  281. if (!template_file.read_file(template_filename)) {
  282. cerr << "Error reading template file " << template_filename << ".\n";
  283. return false;
  284. }
  285. return true;
  286. }
  287. ////////////////////////////////////////////////////////////////////
  288. // Function: PPMain::read_global_file
  289. // Access: Private
  290. // Description: Reads in the Global.pp file after all sources files
  291. // have been read and sorted into dependency order.
  292. ////////////////////////////////////////////////////////////////////
  293. bool PPMain::
  294. read_global_file() {
  295. assert(_def_scope != (PPScope *)NULL);
  296. string global_filename = _def_scope->expand_variable("GLOBAL_FILE");
  297. if (global_filename.empty()) {
  298. cerr << "No definition given for $[GLOBAL_FILE], cannot process.\n";
  299. return false;
  300. }
  301. PPCommandFile global(_def_scope);
  302. if (!global.read_file(global_filename)) {
  303. cerr << "Error reading global definition file "
  304. << global_filename << ".\n";
  305. return false;
  306. }
  307. return true;
  308. }
  309. ////////////////////////////////////////////////////////////////////
  310. // Function: PPMain::get_cwd
  311. // Access: Private, Static
  312. // Description: Calls the system getcwd(), automatically allocating a
  313. // large enough string.
  314. ////////////////////////////////////////////////////////////////////
  315. string PPMain::
  316. get_cwd() {
  317. static size_t bufsize = 1024;
  318. static char *buffer = NULL;
  319. if (buffer == (char *)NULL) {
  320. buffer = new char[bufsize];
  321. }
  322. while (getcwd(buffer, bufsize) == (char *)NULL) {
  323. if (errno != ERANGE) {
  324. perror("getcwd");
  325. return string();
  326. }
  327. delete[] buffer;
  328. bufsize = bufsize * 2;
  329. buffer = new char[bufsize];
  330. assert(buffer != (char *)NULL);
  331. }
  332. return string(buffer);
  333. }