PageRenderTime 47ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/Tools/projectGenerator/classes/Project.php

https://gitlab.com/illisogori/FreeRPG-Torque3D
PHP | 659 lines | 460 code | 123 blank | 76 comment | 93 complexity | e333947b2691625f515c85f675c4d33f MD5 | raw file
Possible License(s): BSD-2-Clause, CPL-1.0, BSD-3-Clause, LGPL-3.0, GPL-2.0, LGPL-2.0, MIT
  1. <?php
  2. //-----------------------------------------------------------------------------
  3. // Copyright (c) 2012 GarageGames, LLC
  4. //
  5. // Permission is hereby granted, free of charge, to any person obtaining a copy
  6. // of this software and associated documentation files (the "Software"), to
  7. // deal in the Software without restriction, including without limitation the
  8. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  9. // sell copies of the Software, and to permit persons to whom the Software is
  10. // furnished to do so, subject to the following conditions:
  11. //
  12. // The above copyright notice and this permission notice shall be included in
  13. // all copies or substantial portions of the Software.
  14. //
  15. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. // IN THE SOFTWARE.
  22. //-----------------------------------------------------------------------------
  23. ///
  24. /// Project info
  25. ///
  26. class Project
  27. {
  28. public static $TYPE_APP = 'app';
  29. public static $TYPE_SHARED_APP = 'sharedapp';
  30. public static $TYPE_LIB = 'lib';
  31. public static $TYPE_SHARED_LIB = 'shared';
  32. public static $TYPE_ACTIVEX = 'activex';
  33. public static $TYPE_SAFARI = 'safari';
  34. public static $TYPE_CSPROJECT = 'csproj';
  35. public $name; // Project name
  36. public $guid; // Project GUID
  37. public $type; // Application or Library?
  38. public $dir_list; // What directories are we checking in?
  39. public $outputs; // List of outputs we want to generate.
  40. public $game_dir; // Base product path
  41. public $defines; // Preprocessor directives
  42. public $disabledWarnings; // Additional warnings to disable
  43. public $includes; // Additional include paths
  44. public $libs; // Additional libraries to link against
  45. public $libsDebug; // Additional Debug build libraries to link against
  46. public $libsIgnore; // Ignore Specific Default Libraries
  47. public $lib_dirs; // Additional library search paths
  48. public $lib_includes; // libs to include (generated by modules)
  49. public $fileCopyPaths; // Source and desitnation (relative to project) paths of files to copy into project
  50. public $additionalExePath; // Additional section to inject into executable path
  51. public $dependencies; // Projects this project depends on
  52. public $references; // for managed projects, references to required assemblies
  53. public $moduleDefinitionFile; // definition file to control shared library exports on windows
  54. public $projectFileExt;
  55. public $commandDebug = "";
  56. public $commandOptimized = "";
  57. public $commandRelease = "";
  58. public $argsDebug = "";
  59. public $argsOptimized = "";
  60. public $argsRelease = "";
  61. public $projSubSystem = 2; // support for Windows/Console/Assembly linker subsystem (1 - Console, 2 - Windows, 3 - Assembly)
  62. private static $xUID = 1; // used for unique file IDs for Xcode projects
  63. public $uniformOutputFile = 0; // debug/release builds use same filename (necessary for np plugin)
  64. // $additionalExePath, $lib_dirs, $libs, all appear to be unused. [pauls 11/9/2007]
  65. public function Project( $name, $type, $guid = '', $game_dir = 'game', $output_name = '' )
  66. {
  67. if (strlen($output_name) == 0)
  68. $output_name = $name;
  69. $this->name = $name;
  70. $this->outputName = $output_name;
  71. $this->guid = $guid;
  72. $this->type = $type;
  73. $this->game_dir = $game_dir;
  74. $this->dir_list = array();
  75. $this->defines = array();
  76. $this->includes = array();
  77. $this->libs = array();
  78. $this->libsDebug = array();
  79. $this->libsIgnore = array();
  80. $this->lib_dirs = array();
  81. $this->lib_includes = array();
  82. $this->fileCopyPaths = array();
  83. $this->outputs = array();
  84. $this->dependencies = array();
  85. $this->disabledWarnings = array();
  86. $this->references = array();
  87. }
  88. public function isApp()
  89. {
  90. return $this->type == self::$TYPE_APP;
  91. }
  92. public function isSharedApp()
  93. {
  94. return $this->type == self::$TYPE_SHARED_APP;
  95. }
  96. public function isLib()
  97. {
  98. return $this->type == self::$TYPE_LIB;
  99. }
  100. public function isSharedLib()
  101. {
  102. return $this->type == self::$TYPE_SHARED_LIB;
  103. }
  104. public function isCSProject()
  105. {
  106. return $this->type == self::$TYPE_CSPROJECT;
  107. }
  108. public function isActiveX()
  109. {
  110. return $this->type == self::$TYPE_ACTIVEX;
  111. }
  112. public function isSafari()
  113. {
  114. return $this->type == self::$TYPE_SAFARI;
  115. }
  116. public function setUniformOutputFile()
  117. {
  118. return $this->uniformOutputFile = 1;
  119. }
  120. public function setSubSystem( $subSystem )
  121. {
  122. $this->projSubSystem = $subSystem;
  123. }
  124. public function validate()
  125. {
  126. // Sort the path list
  127. sort( $this->dir_list );
  128. // Make sure we don't have any duplicate paths
  129. $this->dir_list = array_unique( $this->dir_list );
  130. }
  131. public function addReference($refName, $version = "")
  132. {
  133. $this->references[$refName] = $version;
  134. }
  135. public function addIncludes( $includes )
  136. {
  137. $this->includes = array_merge( $includes, $this->includes );
  138. }
  139. public function validateDependencies()
  140. {
  141. $pguids = array();
  142. foreach( $this->dependencies as $pname )
  143. {
  144. $p = T3D_Generator::lookupProjectByName( $pname );
  145. if( $p )
  146. array_push( $pguids, $p->guid );
  147. else
  148. trigger_error( "Project dependency not found: " .$pname, E_USER_ERROR );
  149. }
  150. // todo: change to dependencyGuids
  151. $this->dependencies = $pguids;
  152. }
  153. private function generateXUID()
  154. {
  155. return sprintf( "%023X", Project::$xUID++ );
  156. }
  157. private function createFileEntry( $output, $curPath, $curFile )
  158. {
  159. // See if we need to reject it based on our rules..
  160. if( $output->ruleReject( $curFile ) )
  161. return null;
  162. // Get the extension - is it one of our allowed values?
  163. if( !$output->allowedFileExt( $curFile ) )
  164. return null;
  165. // Cool - note in the list!
  166. $newEntry = new stdClass();
  167. $newEntry->name = $curFile;
  168. $newEntry->path = FileUtil::collapsePath( $curPath . "/" . $curFile );
  169. if ( !FileUtil::isAbsolutePath( $newEntry->path ) )
  170. {
  171. // This could be consolidated into a single OR statement but it is easier to
  172. // read as two separate if's
  173. if ( !T3D_Generator::$absPath )
  174. $newEntry->path = $output->project_rel_path . $newEntry->path;
  175. if ( T3D_Generator::$absPath && !stristr($newEntry->path, T3D_Generator::$absPath) )
  176. $newEntry->path = $output->project_rel_path . $newEntry->path;
  177. }
  178. // Store a project-unique ID here for Xcode projects
  179. // It will be appended by a single char in the templates.
  180. $newEntry->hash = Project::generateXUID();
  181. return $newEntry;
  182. }
  183. function generateFileList( &$projectFiles, $outputName, &$output )
  184. {
  185. $projName = $this->name;
  186. $projectFiles[ $projName ] = array();
  187. foreach( $this->dir_list as $dir )
  188. {
  189. $dir = FileUtil::normalizeSlashes( $dir );
  190. // Build the path.
  191. if ( FileUtil::isAbsolutePath( $dir ) )
  192. $curPath = $dir;
  193. else
  194. $curPath = FileUtil::collapsePath( $output->base_dir . $dir );
  195. $pathWalk = &$projectFiles[ $projName ];
  196. if ( T3D_Generator::$absPath )
  197. {
  198. if ( stristr($curPath, getEngineSrcDir()) || stristr($curPath, getLibSrcDir()) )
  199. $curPath = T3D_Generator::$absPath . "/". str_replace("../", "", $curPath);
  200. }
  201. // Check if its a file or a directory.
  202. // If its a file just add it directly and build a containng filter/folder structure,
  203. // for it else if a dir add all files in it.
  204. if( is_file( $curPath ) )
  205. {
  206. // Get the file name
  207. $curFile = basename( $curPath );
  208. $curPath = dirname( $curPath );
  209. //echo( "FILE: " . $curFile . " PATH: " . $curPath . "\n" );
  210. }
  211. if( is_dir( $curPath ) )
  212. {
  213. //echo( "DIR: " . $curPath . "\n" );
  214. // Get the array we'll be adding things to...
  215. $pathParts = explode( '/', FileUtil::collapsePath( $dir ) );
  216. foreach( $pathParts as $part )
  217. {
  218. // Skip parts that are relative paths - only want meaningful directories.
  219. if( $part == '..' )
  220. continue;
  221. if( !is_array( $pathWalk[ $part ] ) )
  222. $pathWalk[ $part ] = array();
  223. $pathWalk = &$pathWalk[ $part ];
  224. }
  225. // Open directory.
  226. //echo( "SCANNING: " . $curPath . "\n");
  227. $dirHdl = opendir( $curPath );
  228. if( !$dirHdl )
  229. {
  230. echo( "Path " . $curPath . " not found, giving up.\n" );
  231. return false;
  232. }
  233. // Iterate over all the files in the path if not a single file spec.
  234. if( !$curFile )
  235. {
  236. while( $curFile = readdir( $dirHdl ) )
  237. {
  238. // Skip out if it's an uninteresting dir...
  239. if( $curFile == '.' || $curFile == '..' || $curFile == '.svn' || $curFile == 'CVS' )
  240. continue;
  241. $newEntry = $this->createFileEntry( $output, $curPath, $curFile );
  242. if( $newEntry )
  243. $pathWalk[] = $newEntry;
  244. }
  245. }
  246. else
  247. {
  248. $newEntry = $this->createFileEntry( $output, $curPath, $curFile );
  249. if( $newEntry )
  250. $pathWalk = $newEntry;
  251. $curFile = '';
  252. }
  253. // Clean up after ourselves!
  254. closedir( $dirHdl );
  255. }
  256. }
  257. FileUtil::trimFileList( $projectFiles );
  258. // Uncomment me to see the structure the file lister is returning.
  259. //print_r($projectFiles);
  260. return true;
  261. }
  262. private function setTemplateParams( $tpl, $output, &$projectFiles )
  263. {
  264. // Set the template delimiters
  265. $tpl->left_delimiter = $output->ldelim ? $output->ldelim : '{';
  266. $tpl->right_delimiter = $output->rdelim ? $output->rdelim : '}';
  267. $gameProjectName = getGameProjectName();
  268. // Evaluate template into a file.
  269. $tpl->assign_by_ref( 'projSettings', $this );
  270. $tpl->assign_by_ref( 'projOutput', $output );
  271. $tpl->assign_by_ref( 'fileArray', $projectFiles );
  272. $tpl->assign_by_ref( 'projName', $this->name );
  273. $tpl->assign_by_ref( 'projOutName', $this->outputName );
  274. $tpl->assign_by_ref( 'gameFolder', $this->game_dir );
  275. $tpl->assign_by_ref( 'GUID', $this->guid );
  276. $tpl->assign_by_ref( 'projDefines', $this->defines );
  277. $tpl->assign_by_ref( 'projDisabledWarnings', $this->disabledWarnings );
  278. $tpl->assign_by_ref( 'projIncludes', $this->includes );
  279. $tpl->assign_by_ref( 'projLibs', $this->libs );
  280. $tpl->assign_by_ref( 'projLibsDebug',$this->libsDebug);
  281. $tpl->assign_by_ref( 'projLibsIgnore',$this->libsIgnore);
  282. $tpl->assign_by_ref( 'projLibDirs', $this->lib_dirs );
  283. $tpl->assign_by_ref( 'projDepend', $this->dependencies );
  284. $tpl->assign_by_ref( 'gameProjectName', $gameProjectName );
  285. $tpl->assign_by_ref( 'projModuleDefinitionFile', $this->moduleDefinitionFile );
  286. $tpl->assign_by_ref( 'projSubSystem', $this->projSubSystem );
  287. if (T3D_Generator::$useDLLRuntime)
  288. {
  289. // /MD and /MDd
  290. $tpl->assign( 'projRuntimeRelease', 2 );
  291. $tpl->assign( 'projRuntimeDebug', 3 );
  292. }
  293. else
  294. {
  295. // /MT and /MTd
  296. $tpl->assign( 'projRuntimeRelease', 0 );
  297. $tpl->assign( 'projRuntimeDebug', 1 );
  298. }
  299. if (!$this->commandDebug && ( $this->isSharedLib() || $this->isSharedApp() ))
  300. {
  301. $command = "$(TargetDir)\\".$this->outputName;
  302. $tpl->assign( 'commandDebug' , $command."_DEBUG.exe");
  303. $tpl->assign( 'commandRelease' , $command.".exe");
  304. $tpl->assign( 'commandOptimized' , $command."_OPTIMIZEDDEBUG.exe");
  305. }
  306. else
  307. {
  308. $tpl->assign_by_ref( 'commandDebug' , $this->commandDebug);
  309. $tpl->assign_by_ref( 'commandRelease' , $this->commandRelease);
  310. $tpl->assign_by_ref( 'commandOptimized' , $this->commandOptimized);
  311. }
  312. $tpl->assign_by_ref( 'argsDebug' , $this->argsDebug);
  313. $tpl->assign_by_ref( 'argsRelease' , $this->argsRelease);
  314. $tpl->assign_by_ref( 'argsOptimized' , $this->argsOptimized);
  315. $ptypes = array();
  316. $projectDepends = array();
  317. foreach ($this->dependencies as $pname)
  318. {
  319. $p = T3D_Generator::lookupProjectByName( $pname );
  320. $projectDepends[$pname] = $p;
  321. if ( $p )
  322. $ptypes[$pname] = $p->isSharedLib() || $p->isSafari();
  323. }
  324. $tpl->assign_by_ref( 'projTypes', $ptypes );
  325. $tpl->assign_by_ref( 'projectDepends', $projectDepends );
  326. // Assign some handy paths for the template to reference
  327. $tpl->assign( 'projectOffset', $output->project_rel_path );
  328. if ( T3D_Generator::$absPath )
  329. $tpl->assign( 'srcDir', T3D_Generator::$absPath . "/". str_replace("../", "", getAppEngineSrcDir()) );
  330. else
  331. $tpl->assign( 'srcDir', $output->project_rel_path . getAppEngineSrcDir() );
  332. if ( T3D_Generator::$absPath )
  333. $tpl->assign( 'libDir', T3D_Generator::$absPath . "/". str_replace("../", "", getAppLibSrcDir()) );
  334. else
  335. $tpl->assign( 'libDir', $output->project_rel_path . getAppLibSrcDir() );
  336. if ( T3D_Generator::$absPath )
  337. $tpl->assign( 'binDir', T3D_Generator::$absPath . "/". str_replace("../", "", getAppEngineBinDir()) );
  338. else
  339. $tpl->assign( 'binDir', $output->project_rel_path . getAppEngineBinDir() );
  340. $tpl->assign( 'uniformOutputFile', $this->uniformOutputFile);
  341. }
  342. private function conditionDirectories( $output, &$projectFiles )
  343. {
  344. foreach ($this->includes as &$include)
  345. {
  346. if ( !FileUtil::isAbsolutePath( $include ) )
  347. $include = $output->project_rel_path . $include;
  348. }
  349. foreach ($this->lib_dirs as &$libDirs)
  350. {
  351. if ( !FileUtil::isAbsolutePath( $libDirs ) )
  352. $libDirs = $output->project_rel_path . $libDirs;
  353. }
  354. if ( T3D_Generator::$absPath )
  355. {
  356. foreach ($this->includes as &$include)
  357. {
  358. if ( stristr($include, getEngineSrcDir()) || stristr($include, getLibSrcDir()) )
  359. $include = T3D_Generator::$absPath . "/". str_replace("../", "", $include);
  360. }
  361. foreach ($this->lib_dirs as &$libDirs)
  362. {
  363. if ( stristr($libDirs, getEngineSrcDir()) || stristr($libDirs, getLibSrcDir()) )
  364. $libDirs = T3D_Generator::$absPath . "/". str_replace("../", "", $libDirs);
  365. }
  366. }
  367. }
  368. public function generate( $tpl, $platform, $base_dir )
  369. {
  370. // Alright, for each project scan and generate the file list.
  371. $projectFiles = array ();
  372. $rootPhpBuildDir = getcwd();
  373. // Iterate over this project's outputs.
  374. foreach( $this->outputs as $outputName => $output )
  375. {
  376. $saved_includes = $this->includes;
  377. $saved_lib_dirs = $this->lib_dirs;
  378. //print_r( $output );
  379. // Supported platform?
  380. if( !$output->supportsPlatform( $platform ) )
  381. {
  382. //echo( " # Skipping output: '$outputName'.\n" );
  383. continue;
  384. }
  385. // Get to the right working directory (first go back to root, then to relative)
  386. chdir( $base_dir );
  387. //echo( " - Changing CWD to " . $output->output_dir . "\n" );
  388. // echo(" (From: " . getcwd() . ")\n");
  389. if( !FileUtil::prepareOutputDir( $output->output_dir ) )
  390. continue;
  391. //echo( " - Scanning directory for output '.$outputName.'...\n" );
  392. if( !$this->generateFileList( $projectFiles, $outputName, $output ) )
  393. {
  394. echo( "File list generation failed. Giving up on this project.\n" );
  395. continue;
  396. }
  397. // Do any special work on the include/lib directories that we need
  398. $this->conditionDirectories( $output, $projectFiles[ $this->name ] );
  399. $this->projectFileExt = $output->output_ext;
  400. if ( $this->isCSProject() )
  401. $this->projectFileExt = ".csproj"; // always csproj C# project under VS/MonoDevelop
  402. $outfile = $output->project_dir . $this->name . $this->projectFileExt;
  403. echo( " o Writing project file " . $outfile . "\n" );
  404. $this->setTemplateParams( $tpl, $output, $projectFiles[ $this->name ] );
  405. // To put a bandaid on the tools/player output dir problem
  406. // CodeReview: This should be in the template. -- BJG, 3/13/2007
  407. // Moved into templates -- neo
  408. // Write file
  409. $outdir = dirname( $outfile );
  410. if( !file_exists( $outdir ) )
  411. mkdir_r( $outdir, 0777 );
  412. if( $hdl = fopen( $outfile, 'w' ) )
  413. {
  414. if ($this->isApp())
  415. $template = $output->template_app;
  416. else if ($this->isLib())
  417. $template = $output->template_lib;
  418. else if ($this->isSharedLib())
  419. $template = $output->template_shared_lib;
  420. else if ($this->isSharedApp())
  421. $template = $output->template_shared_app;
  422. else if ($this->isActiveX())
  423. $template = $output->template_activex;
  424. else if ($this->isSafari())
  425. $template = $output->template_activex; //rename template?
  426. else if ($this->isCSProject())
  427. $template = $output->template_csproj;
  428. fputs( $hdl, $tpl->fetch( $template ) );
  429. fclose( $hdl );
  430. }
  431. else
  432. trigger_error( "Could not write output file: " . $output->outputFile, E_USER_ERROR );
  433. if ($output->template_user)
  434. {
  435. $outfile = $output->project_dir . $this->name . $this->projectFileExt .'.'.getenv("COMPUTERNAME").'.'.getenv("USERNAME").'.user';
  436. if( !file_exists( $outfile ) )
  437. {
  438. if( $hdl = fopen( $outfile, 'w' ) )
  439. {
  440. $template = $output->template_user;
  441. fputs( $hdl, $tpl->fetch( $template ) );
  442. fclose( $hdl );
  443. }
  444. else
  445. trigger_error( "Could not write output file: " . $outfile, E_USER_ERROR );
  446. }
  447. }
  448. // Build the .filters file used by VS2010.
  449. if ( $output->template_filter )
  450. {
  451. $filterData = new FilterData();
  452. array_walk( $projectFiles[ $this->name ], array($filterData, 'callback'), '' );
  453. $tpl->assign_by_ref('Folders', $filterData->folders);
  454. $tpl->assign_by_ref('SrcFiles', $filterData->srcFiles);
  455. $tpl->assign_by_ref('IncFiles', $filterData->incFiles);
  456. $tpl->assign_by_ref('OtherFiles', $filterData->otherFiles);
  457. $tpl->register_function( 'gen_uuid', 'gen_uuid' );
  458. $outfile = $output->project_dir . $this->name . $this->projectFileExt . '.filters';
  459. if ( $hdl = fopen( $outfile, 'w' ) )
  460. {
  461. fputs( $hdl, $tpl->fetch( $output->template_filter ) );
  462. fclose( $hdl );
  463. }
  464. }
  465. $this->includes = $saved_includes;
  466. $this->lib_dirs = $saved_lib_dirs;
  467. }
  468. // Copy any files into the project
  469. foreach( $this->fileCopyPaths as $paths )
  470. {
  471. $source = $paths[0];
  472. $dest = $paths[1];
  473. // We need forward slashes for paths.
  474. $source = str_replace( "\\", "/", $source);
  475. $dest = str_replace( "\\", "/", $dest);
  476. // Remove trailing slashes.
  477. $source = rtrim($source, " /");
  478. $dest = rtrim($dest, " /");
  479. // Remove any beginning slash from the destination
  480. $dest = ltrim($dest, " /");
  481. // Build full destination path
  482. $fullDest = $base_dir . "/" . $dest;
  483. echo( " o Copying file " . $source . " to " . $fullDest . "\n" );
  484. if(!copy($source, $fullDest))
  485. {
  486. trigger_error(
  487. "\n*******************************************************************".
  488. "\n".
  489. "\n Unable to copy required file for project!".
  490. "\n".
  491. "Source file: " . $source . "\n" .
  492. "Destination file: " . $fullDest . "\n" .
  493. "\n".
  494. "\n*******************************************************************".
  495. "\n", E_USER_ERROR );
  496. }
  497. }
  498. }
  499. }
  500. class FilterData
  501. {
  502. public $folders = array();
  503. public $srcFiles = array();
  504. public $incFiles = array();
  505. public $otherFiles = array();
  506. public function callback( $value, $key, $dir )
  507. {
  508. if ( is_array( $value ) )
  509. {
  510. if ( $dir != '' )
  511. $dirpath = $dir . '\\' . $key;
  512. else
  513. $dirpath = $key;
  514. array_push( $this->folders, $dirpath );
  515. array_walk( $value, array($this, 'callback'), $dirpath );
  516. return;
  517. }
  518. $path = str_replace( '/', '\\', $value->path );
  519. $ext = strrchr( $path, '.' );
  520. if ( $ext == FALSE )
  521. return;
  522. if ( strcasecmp( $ext, '.c' ) == 0 ||
  523. strcasecmp( $ext, '.cpp' ) == 0 ||
  524. strcasecmp( $ext, '.cc' ) == 0 )
  525. $this->srcFiles[$path] = $dir;
  526. else if ( strcasecmp( $ext, '.h' ) == 0 ||
  527. strcasecmp( $ext, '.hpp' ) == 0 ||
  528. strcasecmp( $ext, '.inl' ) == 0 )
  529. $this->incFiles[$path] = $dir;
  530. else
  531. $this->otherFiles[$path] = $dir;
  532. }
  533. } // class FilterData
  534. ?>