ppMain.cxx 12 KB

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