Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1923 lines
47 KiB

  1. //========= Copyright � 1996-2006, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: VPC
  4. //
  5. //=====================================================================================//
  6. #include "vpc.h"
  7. CProjectFile::CProjectFile( CVCProjGenerator *pGenerator, const char *pFilename )
  8. {
  9. m_pGenerator = pGenerator;
  10. m_Name = pFilename;
  11. }
  12. CProjectFile::~CProjectFile()
  13. {
  14. m_Configs.PurgeAndDeleteElements();
  15. }
  16. bool CProjectFile::GetConfiguration( const char *pConfigName, CProjectConfiguration **ppConfig )
  17. {
  18. if ( !pConfigName || !pConfigName[0] )
  19. {
  20. g_pVPC->VPCError( "Empty or bad configuration name." );
  21. }
  22. if ( ppConfig )
  23. {
  24. // assume not found
  25. *ppConfig = NULL;
  26. }
  27. for ( int i = 0; i < m_Configs.Count(); i++ )
  28. {
  29. if ( !V_stricmp( m_Configs[i]->m_Name.Get(), pConfigName ) )
  30. {
  31. // found
  32. if ( ppConfig )
  33. {
  34. *ppConfig = m_Configs[i];
  35. }
  36. return true;
  37. }
  38. }
  39. // not found
  40. return false;
  41. }
  42. bool CProjectFile::AddConfiguration( const char *pConfigName, CProjectConfiguration **ppConfig )
  43. {
  44. if ( ppConfig )
  45. {
  46. // assume not found
  47. *ppConfig = NULL;
  48. }
  49. if ( GetConfiguration( pConfigName, NULL ) )
  50. {
  51. // found, cannot add duplicate
  52. return false;
  53. }
  54. // add in alphabetic order
  55. CProjectConfiguration *pNewConfig = new CProjectConfiguration( m_pGenerator, pConfigName, m_Name.Get() );
  56. int iIndex = 0;
  57. for ( iIndex = 0; iIndex < m_Configs.Count(); iIndex++ )
  58. {
  59. if ( V_stricmp( pConfigName, m_Configs[iIndex]->m_Name.Get() ) < 0 )
  60. {
  61. m_Configs.InsertBefore( iIndex, pNewConfig );
  62. break;
  63. }
  64. }
  65. if ( iIndex == m_Configs.Count() )
  66. {
  67. m_Configs.AddToTail( pNewConfig );
  68. }
  69. if ( ppConfig )
  70. {
  71. *ppConfig = pNewConfig;
  72. }
  73. return true;
  74. }
  75. bool CProjectFile::RemoveConfiguration( CProjectConfiguration *pConfiguration )
  76. {
  77. for ( int i = 0; i < m_Configs.Count(); i++ )
  78. {
  79. if ( m_Configs[i] == pConfiguration )
  80. {
  81. m_Configs.Remove( i );
  82. delete pConfiguration;
  83. return true;
  84. }
  85. }
  86. return false;
  87. }
  88. CProjectFolder::CProjectFolder( CVCProjGenerator *pGenerator, const char *pFolderName )
  89. {
  90. m_pGenerator = pGenerator;
  91. m_Name = pFolderName;
  92. }
  93. CProjectFolder::~CProjectFolder()
  94. {
  95. m_Folders.PurgeAndDeleteElements();
  96. m_Files.PurgeAndDeleteElements();
  97. }
  98. bool CProjectFolder::GetFolder( const char *pFolderName, CProjectFolder **pFolder )
  99. {
  100. if ( pFolder )
  101. {
  102. // assume not found
  103. *pFolder = NULL;
  104. }
  105. if ( !pFolderName || !pFolderName[0] )
  106. {
  107. g_pVPC->VPCError( "Empty or bad folder name." );
  108. }
  109. for ( int iIndex = m_Folders.Head(); iIndex != m_Folders.InvalidIndex(); iIndex = m_Folders.Next( iIndex ) )
  110. {
  111. if ( !V_stricmp( m_Folders[iIndex]->m_Name.Get(), pFolderName ) )
  112. {
  113. // found
  114. if ( pFolder )
  115. {
  116. *pFolder = m_Folders[iIndex];
  117. }
  118. return true;
  119. }
  120. }
  121. // not found
  122. return false;
  123. }
  124. bool CProjectFolder::AddFolder( const char *pFolderName, CProjectFolder **pFolder )
  125. {
  126. if ( pFolder )
  127. {
  128. // assume not added
  129. *pFolder = NULL;
  130. }
  131. if ( GetFolder( pFolderName, NULL ) )
  132. {
  133. // found, cannot add duplicate
  134. return false;
  135. }
  136. CProjectFolder *pNewFolder = new CProjectFolder( m_pGenerator, pFolderName );
  137. // maintain sorted ascending alphabetic order
  138. int iIndex;
  139. for ( iIndex = m_Folders.Head(); iIndex != m_Folders.InvalidIndex(); iIndex = m_Folders.Next( iIndex ) )
  140. {
  141. if ( V_stricmp( pFolderName, m_Folders[iIndex]->m_Name.Get() ) < 0 )
  142. {
  143. m_Folders.InsertBefore( iIndex, pNewFolder );
  144. break;
  145. }
  146. }
  147. if ( iIndex == m_Folders.InvalidIndex() )
  148. {
  149. m_Folders.AddToTail( pNewFolder );
  150. }
  151. if ( pFolder )
  152. {
  153. *pFolder = pNewFolder;
  154. }
  155. return true;
  156. }
  157. void CProjectFolder::AddFile( const char *pFilename, CProjectFile **ppFile )
  158. {
  159. if ( !pFilename || !pFilename[0] )
  160. {
  161. g_pVPC->VPCError( "Empty or bad filename." );
  162. }
  163. CProjectFile *pNewFile = new CProjectFile( m_pGenerator, pFilename );
  164. // maintain sorted ascending alphabetic order
  165. int iIndex;
  166. for ( iIndex = m_Files.Head(); iIndex != m_Files.InvalidIndex(); iIndex = m_Files.Next( iIndex ) )
  167. {
  168. if ( g_pVPC->IsPlatformDefined( "PS3" ) )
  169. {
  170. // temporary legacy behavior for diff ease until I can be sure project generation is equivalent
  171. iIndex = m_Files.InvalidIndex();
  172. break;
  173. }
  174. // the COM layer for WIN32 sorted by filename only, and NOT the entire path
  175. if ( V_stricmp( V_GetFileName( pFilename ), V_GetFileName( m_Files[iIndex]->m_Name.Get() ) ) < 0 )
  176. {
  177. m_Files.InsertBefore( iIndex, pNewFile );
  178. break;
  179. }
  180. }
  181. if ( iIndex == m_Files.InvalidIndex() )
  182. {
  183. m_Files.AddToTail( pNewFile );
  184. }
  185. if ( ppFile )
  186. {
  187. *ppFile = pNewFile;
  188. }
  189. }
  190. bool CProjectFolder::FindFile( const char *pFilename )
  191. {
  192. if ( !pFilename || !pFilename[0] )
  193. {
  194. g_pVPC->VPCError( "Empty or bad filename." );
  195. }
  196. for ( int iIndex = m_Files.Head(); iIndex != m_Files.InvalidIndex(); iIndex = m_Files.Next( iIndex ) )
  197. {
  198. if ( !V_stricmp( m_Files[iIndex]->m_Name.Get(), pFilename ) )
  199. {
  200. // found
  201. return true;
  202. }
  203. }
  204. return false;
  205. }
  206. bool CProjectFolder::RemoveFile( const char *pFilename )
  207. {
  208. if ( !pFilename || !pFilename[0] )
  209. {
  210. g_pVPC->VPCError( "Empty or bad filename." );
  211. }
  212. for ( int iIndex = m_Files.Head(); iIndex != m_Files.InvalidIndex(); iIndex = m_Files.Next( iIndex ) )
  213. {
  214. if ( !V_stricmp( m_Files[iIndex]->m_Name.Get(), pFilename ) )
  215. {
  216. // found, remove
  217. delete m_Files[iIndex];
  218. m_Files.Unlink( iIndex );
  219. return true;
  220. }
  221. }
  222. return false;
  223. }
  224. bool CPropertyStateLessFunc::Less( const int& lhs, const int& rhs, void *pContext )
  225. {
  226. int lhsPropertyId = (( CPropertyStates* )pContext)->m_Properties[lhs].m_pToolProperty->m_nPropertyId;
  227. int rhsPropertyId = (( CPropertyStates* )pContext)->m_Properties[rhs].m_pToolProperty->m_nPropertyId;
  228. return lhsPropertyId < rhsPropertyId;
  229. }
  230. CPropertyStates::CPropertyStates()
  231. {
  232. m_PropertiesInOutputOrder.SetLessContext( this );
  233. }
  234. PropertyState_t *CPropertyStates::GetProperty( int nPropertyId )
  235. {
  236. for ( int i = 0 ; i < m_Properties.Count(); i++ )
  237. {
  238. if ( m_Properties[i].m_pToolProperty->m_nPropertyId == nPropertyId )
  239. {
  240. return &m_Properties[i];
  241. }
  242. }
  243. return NULL;
  244. }
  245. PropertyState_t *CPropertyStates::GetProperty( const char *pPropertyName )
  246. {
  247. if ( pPropertyName[0] == '$' )
  248. {
  249. pPropertyName++;
  250. }
  251. for ( int i = 0; i < m_Properties.Count(); i++ )
  252. {
  253. const char *pParseString = m_Properties[i].m_pToolProperty->m_ParseString.Get();
  254. if ( pParseString[0] == '$' )
  255. {
  256. pParseString++;
  257. }
  258. if ( !V_stricmp( pPropertyName, pParseString ) )
  259. {
  260. return &m_Properties[i];
  261. }
  262. const char *pLegacyString = m_Properties[i].m_pToolProperty->m_LegacyString.Get();
  263. if ( pLegacyString[0] )
  264. {
  265. if ( pLegacyString[0] == '$' )
  266. {
  267. pLegacyString++;
  268. }
  269. if ( !V_stricmp( pPropertyName, pLegacyString ) )
  270. {
  271. return &m_Properties[i];
  272. }
  273. }
  274. }
  275. return NULL;
  276. }
  277. bool CPropertyStates::SetStringProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
  278. {
  279. // find possible current value
  280. const char *pCurrentValue = NULL;
  281. for ( int i = 0; i < m_Properties.Count(); i++ )
  282. {
  283. if ( m_Properties[i].m_pToolProperty == pToolProperty )
  284. {
  285. pCurrentValue = m_Properties[i].m_StringValue.Get();
  286. break;
  287. }
  288. }
  289. if ( !pCurrentValue && pRootTool )
  290. {
  291. // fallback to root tool's config to find current value
  292. for ( int i = 0; i < pRootTool->m_PropertyStates.m_Properties.Count(); i++ )
  293. {
  294. if ( pRootTool->m_PropertyStates.m_Properties[i].m_pToolProperty == pToolProperty )
  295. {
  296. pCurrentValue = pRootTool->m_PropertyStates.m_Properties[i].m_StringValue.Get();
  297. break;
  298. }
  299. }
  300. }
  301. // feed in current value to resolve $BASE
  302. // possibly culled or tokenized new value
  303. char buff[MAX_SYSTOKENCHARS];
  304. if ( !g_pVPC->GetScript().ParsePropertyValue( pCurrentValue, buff, sizeof( buff ) ) )
  305. return true;
  306. if ( pToolProperty->m_bFixSlashes )
  307. {
  308. V_FixSlashes( buff );
  309. }
  310. if ( pToolProperty->m_bPreferSemicolonNoComma )
  311. {
  312. CUtlString buffCopy = buff;
  313. V_StrSubst( buffCopy.Get(), ",", ";", buff, sizeof( buff ), false );
  314. }
  315. if ( pToolProperty->m_bPreferSemicolonNoSpace )
  316. {
  317. CUtlString buffCopy = buff;
  318. V_StrSubst( buffCopy.Get(), " ", ";", buff, sizeof( buff ), false );
  319. }
  320. if ( pToolProperty->m_bAppendSlash )
  321. {
  322. int len = strlen( buff );
  323. if ( len >= 1 && buff[len-1] != '\\' )
  324. {
  325. V_strncat( buff, "\\", sizeof( buff ) );
  326. }
  327. }
  328. if ( !V_stricmp( pToolProperty->m_ParseString.Get(), "$CommandLine" ) && !V_strnicmp( buff, "echo ", 5 ) )
  329. {
  330. // the COM layer auto appended a CR-LF for a command line with an echo
  331. int len = strlen( buff );
  332. if ( ( len >= 1 && buff[len-1] != '\n' ) &&
  333. ( len >= 12 && V_stricmp( buff + len - 12, "&#x0D;&#x0A;" ) ) )
  334. {
  335. V_strncat( buff, "\n", sizeof( buff ) );
  336. }
  337. }
  338. if ( pCurrentValue && !V_stricmp( pCurrentValue, buff ) )
  339. {
  340. g_pVPC->VPCWarning( "%s matches default setting, [%s line:%d]", pToolProperty->m_ParseString.Get(), g_pVPC->GetScript().GetName(), g_pVPC->GetScript().GetLine() );
  341. }
  342. if ( pCurrentValue )
  343. {
  344. // update existing state
  345. // always replace or add strings due to case changes
  346. for ( int i = 0; i < m_Properties.Count(); i++ )
  347. {
  348. if ( m_Properties[i].m_pToolProperty == pToolProperty )
  349. {
  350. m_Properties[i].m_StringValue = buff;
  351. return true;
  352. }
  353. }
  354. }
  355. // add
  356. int iIndex = m_Properties.AddToTail();
  357. m_Properties[iIndex].m_pToolProperty = pToolProperty;
  358. m_Properties[iIndex].m_StringValue = buff;
  359. m_PropertiesInOutputOrder.Insert( iIndex );
  360. return true;
  361. }
  362. bool CPropertyStates::SetListProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
  363. {
  364. char buff[MAX_SYSTOKENCHARS];
  365. if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) ) )
  366. return true;
  367. // resolve the parsed token to an expected ordinal
  368. const char *pNewOrdinalValue = NULL;
  369. for ( int i = 0; i < pToolProperty->m_Ordinals.Count() ;i++ )
  370. {
  371. if ( !V_stricmp( pToolProperty->m_Ordinals[i].m_ParseString.Get(), buff ) )
  372. {
  373. pNewOrdinalValue = pToolProperty->m_Ordinals[i].m_ValueString.Get();
  374. break;
  375. }
  376. }
  377. if ( !pNewOrdinalValue && !V_stricmp( buff, "default" ) )
  378. {
  379. // allow "default" if not explicitly provided
  380. // same as empty, state stays unaffected
  381. return true;
  382. }
  383. if ( !pNewOrdinalValue )
  384. {
  385. g_pVPC->VPCSyntaxError( "Unknown Ordinal for %s", pToolProperty->m_ParseString.Get() );
  386. }
  387. // find possible current value
  388. const char *pCurrentOrdinalValue = NULL;
  389. for ( int i = 0; i < m_Properties.Count(); i++ )
  390. {
  391. if ( m_Properties[i].m_pToolProperty == pToolProperty )
  392. {
  393. pCurrentOrdinalValue = m_Properties[i].m_StringValue.Get();
  394. break;
  395. }
  396. }
  397. if ( !pCurrentOrdinalValue && pRootTool )
  398. {
  399. // fallback to root tool's config to find current value
  400. for ( int i = 0; i < pRootTool->m_PropertyStates.m_Properties.Count(); i++ )
  401. {
  402. if ( pRootTool->m_PropertyStates.m_Properties[i].m_pToolProperty == pToolProperty )
  403. {
  404. pCurrentOrdinalValue = pRootTool->m_PropertyStates.m_Properties[i].m_StringValue.Get();
  405. break;
  406. }
  407. }
  408. }
  409. if ( pCurrentOrdinalValue && !V_stricmp( pCurrentOrdinalValue, pNewOrdinalValue ) )
  410. {
  411. g_pVPC->VPCWarning( "%s matches default setting, [%s line:%d]", pToolProperty->m_ParseString.Get(), g_pVPC->GetScript().GetName(), g_pVPC->GetScript().GetLine() );
  412. }
  413. if ( pCurrentOrdinalValue )
  414. {
  415. // update existing state
  416. for ( int i = 0; i < m_Properties.Count(); i++ )
  417. {
  418. if ( m_Properties[i].m_pToolProperty == pToolProperty )
  419. {
  420. m_Properties[i].m_OrdinalString = buff;
  421. m_Properties[i].m_StringValue = pNewOrdinalValue;
  422. return true;
  423. }
  424. }
  425. }
  426. // add
  427. int iIndex = m_Properties.AddToTail();
  428. m_Properties[iIndex].m_pToolProperty = pToolProperty;
  429. m_Properties[iIndex].m_OrdinalString = buff;
  430. m_Properties[iIndex].m_StringValue = pNewOrdinalValue;
  431. m_PropertiesInOutputOrder.Insert( iIndex );
  432. return true;
  433. }
  434. bool CPropertyStates::SetBoolProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool, bool bEnabled )
  435. {
  436. const char *pNewOrdinalValue = bEnabled ? "1" :"0";
  437. // find possible current value
  438. const char *pCurrentOrdinalValue = NULL;
  439. for ( int i = 0; i < m_Properties.Count(); i++ )
  440. {
  441. if ( m_Properties[i].m_pToolProperty == pToolProperty )
  442. {
  443. pCurrentOrdinalValue = m_Properties[i].m_StringValue.Get();
  444. break;
  445. }
  446. }
  447. if ( !pCurrentOrdinalValue && pRootTool )
  448. {
  449. // fallback to root tool's config to find current value
  450. for ( int i = 0; i < pRootTool->m_PropertyStates.m_Properties.Count(); i++ )
  451. {
  452. if ( pRootTool->m_PropertyStates.m_Properties[i].m_pToolProperty == pToolProperty )
  453. {
  454. pCurrentOrdinalValue = pRootTool->m_PropertyStates.m_Properties[i].m_StringValue.Get();
  455. break;
  456. }
  457. }
  458. }
  459. if ( pCurrentOrdinalValue && !V_stricmp( pCurrentOrdinalValue, pNewOrdinalValue ) )
  460. {
  461. g_pVPC->VPCWarning( "%s matches default setting, [%s line:%d]", pToolProperty->m_ParseString.Get(), g_pVPC->GetScript().GetName(), g_pVPC->GetScript().GetLine() );
  462. }
  463. if ( pCurrentOrdinalValue )
  464. {
  465. // update existing state
  466. for ( int i = 0; i < m_Properties.Count(); i++ )
  467. {
  468. if ( m_Properties[i].m_pToolProperty == pToolProperty )
  469. {
  470. m_Properties[i].m_StringValue = pNewOrdinalValue;
  471. return true;
  472. }
  473. }
  474. }
  475. // add
  476. int iIndex = m_Properties.AddToTail();
  477. m_Properties[iIndex].m_pToolProperty = pToolProperty;
  478. m_Properties[iIndex].m_StringValue = pNewOrdinalValue;
  479. m_PropertiesInOutputOrder.Insert( iIndex );
  480. return true;
  481. }
  482. bool CPropertyStates::SetBoolProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
  483. {
  484. char buff[MAX_SYSTOKENCHARS];
  485. if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) ) )
  486. return true;
  487. return SetBoolProperty( pToolProperty, pRootTool, Sys_StringToBool( buff ) );
  488. }
  489. bool CPropertyStates::SetBoolProperty( ToolProperty_t *pToolProperty, bool bEnabled )
  490. {
  491. return SetBoolProperty( pToolProperty, NULL, bEnabled );
  492. }
  493. bool CPropertyStates::SetIntegerProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
  494. {
  495. char buff[MAX_SYSTOKENCHARS];
  496. if ( !g_pVPC->GetScript().ParsePropertyValue( NULL, buff, sizeof( buff ) ) )
  497. return true;
  498. // ensure the parsed token is a real integer and not just quietly mapped to 0
  499. int nParsedValue = atoi( buff );
  500. if ( V_stricmp( CFmtStr( "%d", nParsedValue ), buff ) )
  501. {
  502. g_pVPC->VPCSyntaxError( "Unrecognized integer value: %s", buff );
  503. }
  504. // find possible current value
  505. const char *pCurrentOrdinalValue = NULL;
  506. for ( int i = 0; i < m_Properties.Count(); i++ )
  507. {
  508. if ( m_Properties[i].m_pToolProperty == pToolProperty )
  509. {
  510. pCurrentOrdinalValue = m_Properties[i].m_StringValue.Get();
  511. break;
  512. }
  513. }
  514. if ( !pCurrentOrdinalValue && pRootTool )
  515. {
  516. // fallback to root tool's config to find current value
  517. for ( int i = 0; i < pRootTool->m_PropertyStates.m_Properties.Count(); i++ )
  518. {
  519. if ( pRootTool->m_PropertyStates.m_Properties[i].m_pToolProperty == pToolProperty )
  520. {
  521. pCurrentOrdinalValue = pRootTool->m_PropertyStates.m_Properties[i].m_StringValue.Get();
  522. break;
  523. }
  524. }
  525. }
  526. if ( pCurrentOrdinalValue && ( atoi( pCurrentOrdinalValue ) == atoi( buff ) ) )
  527. {
  528. g_pVPC->VPCWarning( "%s matches default setting, [%s line:%d]", pToolProperty->m_ParseString.Get(), g_pVPC->GetScript().GetName(), g_pVPC->GetScript().GetLine() );
  529. }
  530. if ( pCurrentOrdinalValue )
  531. {
  532. // update existing state
  533. for ( int i = 0; i < m_Properties.Count(); i++ )
  534. {
  535. if ( m_Properties[i].m_pToolProperty == pToolProperty )
  536. {
  537. m_Properties[i].m_StringValue = buff;
  538. return true;
  539. }
  540. }
  541. }
  542. // add
  543. int iIndex = m_Properties.AddToTail();
  544. m_Properties[iIndex].m_pToolProperty = pToolProperty;
  545. m_Properties[iIndex].m_StringValue = buff;
  546. m_PropertiesInOutputOrder.Insert( iIndex );
  547. return true;
  548. }
  549. bool CPropertyStates::SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
  550. {
  551. bool bHandled = false;
  552. switch ( pToolProperty->m_nType )
  553. {
  554. case PT_BOOLEAN:
  555. bHandled = SetBoolProperty( pToolProperty, pRootTool );
  556. break;
  557. case PT_STRING:
  558. bHandled = SetStringProperty( pToolProperty, pRootTool );
  559. break;
  560. case PT_INTEGER:
  561. bHandled = SetIntegerProperty( pToolProperty, pRootTool );
  562. break;
  563. case PT_LIST:
  564. bHandled = SetListProperty( pToolProperty, pRootTool );
  565. break;
  566. case PT_IGNORE:
  567. bHandled = true;
  568. g_pVPC->GetScript().SkipRestOfLine();
  569. break;
  570. case PT_DEPRECATED:
  571. g_pVPC->VPCError( "SetProperty: Property %s has been deprecated and is no longer supported!", pToolProperty->m_ParseString.Get() );
  572. break;
  573. default:
  574. g_pVPC->VPCError( "SetProperty: Unknown type for %s - requires implementation", pToolProperty->m_ParseString.Get() );
  575. }
  576. return bHandled;
  577. }
  578. static bool FilesSortLessFunc( CProjectFile* const &pLHS, CProjectFile* const &pRHS )
  579. {
  580. return CaselessStringLessThan( pLHS->m_Name.Get(), pRHS->m_Name.Get() );
  581. }
  582. CProjectConfiguration::CProjectConfiguration( CVCProjGenerator *pGenerator, const char *pConfigName, const char *pFilename )
  583. {
  584. m_pGenerator = pGenerator;
  585. m_Name = pConfigName;
  586. m_bIsFileConfig = ( pFilename != NULL );
  587. m_pDebuggingTool = NULL;
  588. m_pCompilerTool = NULL;
  589. m_pLibrarianTool = NULL;
  590. m_pLinkerTool = NULL;
  591. m_pManifestTool = NULL;
  592. m_pXMLDocGenTool = NULL;
  593. m_pBrowseInfoTool = NULL;
  594. m_pResourcesTool = NULL;
  595. m_pPreBuildEventTool = NULL;
  596. m_pPreLinkEventTool = NULL;
  597. m_pPostBuildEventTool = NULL;
  598. m_pCustomBuildTool = NULL;
  599. m_pXboxImageTool = NULL;
  600. m_pXboxDeploymentTool = NULL;
  601. if ( !m_bIsFileConfig )
  602. {
  603. m_pDebuggingTool = new CDebuggingTool( pGenerator );
  604. m_pCompilerTool = new CCompilerTool( pGenerator, pConfigName, false );
  605. m_pLibrarianTool = new CLibrarianTool( pGenerator );
  606. m_pLinkerTool = new CLinkerTool( pGenerator );
  607. m_pManifestTool = new CManifestTool( pGenerator );
  608. m_pXMLDocGenTool = new CXMLDocGenTool( pGenerator );
  609. m_pBrowseInfoTool = new CBrowseInfoTool( pGenerator );
  610. m_pResourcesTool = new CResourcesTool( pGenerator );
  611. m_pPreBuildEventTool = new CPreBuildEventTool( pGenerator );
  612. m_pPreLinkEventTool = new CPreLinkEventTool( pGenerator );
  613. m_pPostBuildEventTool = new CPostBuildEventTool( pGenerator );
  614. m_pCustomBuildTool = new CCustomBuildTool( pGenerator, pConfigName, false );
  615. m_pXboxImageTool = new CXboxImageTool( pGenerator );
  616. m_pXboxDeploymentTool = new CXboxDeploymentTool( pGenerator );
  617. }
  618. else
  619. {
  620. // a file's config can only be the compiler or the custom build tool
  621. const char *pExtension = V_GetFileExtension( pFilename );
  622. bool bIsCPP = pExtension && ( !V_stricmp( pExtension, "cpp" ) || !V_stricmp( pExtension, "cxx" ) || !V_stricmp( pExtension, "c" ) || !V_stricmp( pExtension, "cc" ) );
  623. if ( bIsCPP )
  624. {
  625. m_pCompilerTool = new CCompilerTool( pGenerator, pConfigName, true );
  626. }
  627. else
  628. {
  629. m_pCustomBuildTool = new CCustomBuildTool( pGenerator, pConfigName, true );
  630. }
  631. }
  632. }
  633. CProjectConfiguration::~CProjectConfiguration()
  634. {
  635. delete m_pDebuggingTool;
  636. delete m_pCompilerTool;
  637. delete m_pLibrarianTool;
  638. delete m_pLinkerTool;
  639. delete m_pManifestTool;
  640. delete m_pXMLDocGenTool;
  641. delete m_pBrowseInfoTool;
  642. delete m_pResourcesTool;
  643. delete m_pPreBuildEventTool;
  644. delete m_pPreLinkEventTool;
  645. delete m_pPostBuildEventTool;
  646. delete m_pCustomBuildTool;
  647. delete m_pXboxImageTool;
  648. delete m_pXboxDeploymentTool;
  649. }
  650. bool CProjectConfiguration::IsEmpty()
  651. {
  652. if ( m_PropertyStates.m_Properties.Count() )
  653. return false;
  654. if ( m_pDebuggingTool && m_pDebuggingTool->m_PropertyStates.m_Properties.Count() )
  655. return false;
  656. if ( m_pCompilerTool && m_pCompilerTool->m_PropertyStates.m_Properties.Count() )
  657. return false;
  658. if ( m_pLibrarianTool && m_pLibrarianTool->m_PropertyStates.m_Properties.Count() )
  659. return false;
  660. if ( m_pLinkerTool && m_pLinkerTool->m_PropertyStates.m_Properties.Count() )
  661. return false;
  662. if ( m_pManifestTool && m_pManifestTool->m_PropertyStates.m_Properties.Count() )
  663. return false;
  664. if ( m_pXMLDocGenTool && m_pXMLDocGenTool->m_PropertyStates.m_Properties.Count() )
  665. return false;
  666. if ( m_pBrowseInfoTool && m_pBrowseInfoTool->m_PropertyStates.m_Properties.Count() )
  667. return false;
  668. if ( m_pResourcesTool && m_pResourcesTool->m_PropertyStates.m_Properties.Count() )
  669. return false;
  670. if ( m_pPreBuildEventTool && m_pPreBuildEventTool->m_PropertyStates.m_Properties.Count() )
  671. return false;
  672. if ( m_pPreLinkEventTool && m_pPreLinkEventTool->m_PropertyStates.m_Properties.Count() )
  673. return false;
  674. if ( m_pPostBuildEventTool && m_pPostBuildEventTool->m_PropertyStates.m_Properties.Count() )
  675. return false;
  676. if ( m_pCustomBuildTool && m_pCustomBuildTool->m_PropertyStates.m_Properties.Count() )
  677. return false;
  678. if ( m_pXboxImageTool && m_pXboxImageTool->m_PropertyStates.m_Properties.Count() )
  679. return false;
  680. if ( m_pXboxDeploymentTool && m_pXboxDeploymentTool->m_PropertyStates.m_Properties.Count() )
  681. return false;
  682. return true;
  683. }
  684. bool CProjectConfiguration::SetProperty( ToolProperty_t *pToolProperty )
  685. {
  686. bool bHandled = m_PropertyStates.SetProperty( pToolProperty );
  687. // have to mimic what the COM layer used to do which is to configure itself based on the type of application its building
  688. // VPC enforces a strict order, configuration blocks must come before any tool block to allow this to be rational
  689. if ( bHandled && !V_stricmp( pToolProperty->m_ParseString, "$ConfigurationType" ) )
  690. {
  691. PropertyState_t *pPropertyState = m_PropertyStates.GetProperty( pToolProperty->m_nPropertyId );
  692. if ( pPropertyState &&
  693. ( ( V_stristr( pPropertyState->m_OrdinalString.Get(), "static library" ) || !V_stricmp( pPropertyState->m_OrdinalString.Get(), "LIB" ) ) ) )
  694. {
  695. // static library does not get these tools
  696. delete m_pResourcesTool;
  697. m_pResourcesTool = NULL;
  698. delete m_pManifestTool;
  699. m_pManifestTool = NULL;
  700. delete m_pLinkerTool;
  701. m_pLinkerTool = NULL;
  702. delete m_pXboxImageTool;
  703. m_pXboxImageTool = NULL;
  704. delete m_pXboxDeploymentTool;
  705. m_pXboxDeploymentTool = NULL;
  706. }
  707. else
  708. {
  709. // exe/dlls do not get the librarian
  710. delete m_pLibrarianTool;
  711. m_pLibrarianTool = NULL;
  712. }
  713. }
  714. return bHandled;
  715. }
  716. bool CProjectTool::SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
  717. {
  718. return m_PropertyStates.SetProperty( pToolProperty, pRootTool );
  719. }
  720. //-----------------------------------------------------------------------------
  721. bool CCompilerTool::SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
  722. {
  723. if ( m_bIsFileConfig )
  724. {
  725. CProjectConfiguration *pConfig;
  726. if ( !GetGenerator()->GetRootConfiguration( m_ConfigName.Get(), &pConfig ) )
  727. return false;
  728. return CProjectTool::SetProperty( pToolProperty, pConfig->GetCompilerTool() );
  729. }
  730. return CProjectTool::SetProperty( pToolProperty );
  731. }
  732. //-----------------------------------------------------------------------------
  733. bool CCustomBuildTool::SetProperty( ToolProperty_t *pToolProperty, CProjectTool *pRootTool )
  734. {
  735. if ( m_bIsFileConfig )
  736. {
  737. CProjectConfiguration *pConfig;
  738. if ( !GetGenerator()->GetRootConfiguration( m_ConfigName.Get(), &pConfig ) )
  739. return false;
  740. return CProjectTool::SetProperty( pToolProperty, pConfig->GetCustomBuildTool() );
  741. }
  742. return CProjectTool::SetProperty( pToolProperty );
  743. }
  744. CVCProjGenerator::CVCProjGenerator() :
  745. BaseClass( NULL )
  746. {
  747. m_pGeneratorDefinition = NULL;
  748. m_pRootFolder = NULL;
  749. m_FileDictionary.SetLessFunc( FilesSortLessFunc );
  750. Clear();
  751. }
  752. void CVCProjGenerator::Clear()
  753. {
  754. m_nActivePropertySection = KEYWORD_UNKNOWN;
  755. m_pProjectFile = NULL;
  756. m_pConfig = NULL;
  757. m_pFileConfig = NULL;
  758. m_pDebuggingTool = NULL;
  759. m_pCompilerTool = NULL;
  760. m_pLibrarianTool = NULL;
  761. m_pLinkerTool = NULL;
  762. m_pManifestTool = NULL;
  763. m_pXMLDocGenTool = NULL;
  764. m_pBrowseInfoTool = NULL;
  765. m_pResourcesTool = NULL;
  766. m_pPreBuildEventTool = NULL;
  767. m_pPreLinkEventTool = NULL;
  768. m_pPostBuildEventTool = NULL;
  769. m_pCustomBuildTool = NULL;
  770. m_pXboxImageTool = NULL;
  771. m_pXboxDeploymentTool = NULL;
  772. m_spFolderStack.Purge();
  773. m_spCompilerStack.Purge();
  774. m_spCustomBuildToolStack.Purge();
  775. // undefined until set
  776. m_VSIType = PS3_VSI_TYPE_UNDEFINED;
  777. m_FileDictionary.Purge();
  778. // setup expected root folder
  779. delete m_pRootFolder;
  780. m_pRootFolder = new CProjectFolder( this, "???" );
  781. // setup the root configurations
  782. m_RootConfigurations.PurgeAndDeleteElements();
  783. CProjectConfiguration *pDebugConfig = new CProjectConfiguration( this, "Debug", NULL );
  784. m_RootConfigurations.AddToTail( pDebugConfig );
  785. CProjectConfiguration *pReleaseConfig = new CProjectConfiguration( this, "Release", NULL );
  786. m_RootConfigurations.AddToTail( pReleaseConfig );
  787. CProjectConfiguration *pProfileConfig = new CProjectConfiguration( this, "Profile", NULL );
  788. m_RootConfigurations.AddToTail( pProfileConfig );
  789. CProjectConfiguration *pRetailConfig = new CProjectConfiguration( this, "Retail", NULL );
  790. m_RootConfigurations.AddToTail( pRetailConfig );
  791. }
  792. void CVCProjGenerator::SetupGeneratorDefinition( IVCProjWriter *pVCProjWriter, const char *pDefinitionName, PropertyName_t *pPropertyNames )
  793. {
  794. m_pVCProjWriter = pVCProjWriter;
  795. delete m_pGeneratorDefinition;
  796. m_pGeneratorDefinition = new CGeneratorDefinition();
  797. m_pGeneratorDefinition->LoadDefinition( pDefinitionName, pPropertyNames );
  798. }
  799. const char* CVCProjGenerator::GetProjectFileExtension()
  800. {
  801. if ( g_pVPC->Is2010() )
  802. {
  803. return "vcxproj";
  804. }
  805. return "vcproj";
  806. }
  807. void CVCProjGenerator::StartProject()
  808. {
  809. if ( !m_pGeneratorDefinition )
  810. {
  811. g_pVPC->VPCError( "Missing a properly configured generator definition" );
  812. }
  813. BaseClass::StartProject();
  814. // create the default project
  815. // must have a root project for most operations
  816. m_ProjectName = "UNNAMED";
  817. m_OutputFilename = g_pVPC->GetOutputFilename();
  818. SetGUID( m_OutputFilename.Get() );
  819. }
  820. void CVCProjGenerator::EndProject()
  821. {
  822. BaseClass::EndProject();
  823. // push generator definition scripts into CRC check
  824. CRC32_t scriptCRC = 0;
  825. const char *pScriptName = m_pGeneratorDefinition->GetScriptName( &scriptCRC );
  826. char scriptPath[MAX_PATH];
  827. g_pVPC->ResolveMacrosInString( CFmtStr( "$SRCDIR\\%s", pScriptName ), scriptPath, sizeof( scriptPath ) );
  828. g_pVPC->AddScriptToCRCCheck( scriptPath, scriptCRC );
  829. // done once, right before save
  830. ApplyInternalPreprocessorDefinitions();
  831. VPC_FakeKeyword_SchemaFolder( this );
  832. #ifdef STEAM
  833. #error( "NEEDS TO BE FIXED" )
  834. // add the perforce integration magic
  835. bstr = "Perforce Project";
  836. g_spProject->put_SccProjectName( bstr );
  837. bstr = "..";
  838. g_spProject->put_SccLocalPath( bstr );
  839. bstr = "MSSCCI:Perforce SCM";
  840. g_spProject->put_SccProvider( bstr );
  841. #endif
  842. g_pVPC->VPCStatus( true, "Saving... Project: '%s' File: '%s'", GetProjectName().String(), g_pVPC->GetOutputFilename() );
  843. if ( m_ProjectName.IsEmpty() )
  844. {
  845. g_pVPC->VPCError( "Invalid Empty Project Name" );
  846. }
  847. if ( m_OutputFilename.IsEmpty() )
  848. {
  849. g_pVPC->VPCError( "Invalid Empty Output Filename" );
  850. }
  851. if ( m_GUIDString.IsEmpty() )
  852. {
  853. g_pVPC->VPCError( "Invalid Empty GUID String" );
  854. }
  855. // Save the .vcproj file.
  856. bool bValid = m_pVCProjWriter->Save( m_OutputFilename.Get() );
  857. if ( !bValid )
  858. {
  859. g_pVPC->VPCError( "Cannot save the specified project '%s' to '%s'", GetProjectName().Get(), m_OutputFilename.Get() );
  860. }
  861. // Expected to not be inside a property section.
  862. Assert( m_nActivePropertySection == KEYWORD_UNKNOWN );
  863. Clear();
  864. }
  865. void CVCProjGenerator::SetGUID( const char *pOutputFilename )
  866. {
  867. char szBasename[MAX_PATH];
  868. V_FileBase( pOutputFilename, szBasename, sizeof( szBasename ) );
  869. // set the GUID
  870. MD5Context_t ctx;
  871. unsigned char digest[MD5_DIGEST_LENGTH];
  872. V_memset( &ctx, 0, sizeof( ctx ) );
  873. V_memset( digest, 0, sizeof( digest ) );
  874. MD5Init( &ctx );
  875. MD5Update( &ctx, (unsigned char *)szBasename, strlen( szBasename ) );
  876. MD5Final( digest, &ctx );
  877. char szMD5[64];
  878. V_binarytohex( digest, MD5_DIGEST_LENGTH, szMD5, sizeof( szMD5 ) );
  879. V_strupr( szMD5 );
  880. char szGUID[MAX_PATH];
  881. V_snprintf( szGUID, sizeof( szGUID ), "{%8.8s-%4.4s-%4.4s-%4.4s-%12.12s}", szMD5, &szMD5[8], &szMD5[12], &szMD5[16], &szMD5[20] );
  882. m_GUIDString = szGUID;
  883. }
  884. CUtlString CVCProjGenerator::GetProjectName()
  885. {
  886. return m_ProjectName;
  887. }
  888. void CVCProjGenerator::SetProjectName( const char *pProjectName )
  889. {
  890. m_ProjectName = pProjectName;
  891. }
  892. void CVCProjGenerator::StartFolder( const char *pFolderName )
  893. {
  894. BaseClass::StartFolder( pFolderName );
  895. bool bValid;
  896. CProjectFolder *pFolder = NULL;
  897. if ( m_spFolderStack.Count() == 0 )
  898. {
  899. // add to root
  900. bValid = AddFolder( pFolderName, NULL, &pFolder );
  901. }
  902. else
  903. {
  904. // add as subfolder
  905. bValid = AddFolder( pFolderName, m_spFolderStack.Top(), &pFolder );
  906. }
  907. if ( !bValid )
  908. {
  909. // resolve failure
  910. // folder already exists, not an error
  911. // find the matching object
  912. pFolder = NULL;
  913. if ( m_spFolderStack.Count() == 0 )
  914. {
  915. // at root
  916. GetFolder( pFolderName, NULL, &pFolder );
  917. }
  918. else
  919. {
  920. // at subfolder
  921. GetFolder( pFolderName, m_spFolderStack.Top(), &pFolder );
  922. }
  923. if ( !pFolder )
  924. {
  925. g_pVPC->VPCError( "Cannot find expected folder %s", pFolderName );
  926. }
  927. }
  928. m_spFolderStack.Push( pFolder );
  929. }
  930. void CVCProjGenerator::EndFolder()
  931. {
  932. BaseClass::EndFolder();
  933. if ( m_spFolderStack.Count() == 0 )
  934. {
  935. g_pVPC->VPCError( "EndFolder called and no folder has been started." );
  936. }
  937. m_spFolderStack.Pop();
  938. }
  939. bool CVCProjGenerator::StartFile( const char *pFilename, bool bWarnIfAlreadyExists )
  940. {
  941. // normalize filename, filenames need to compare correctly
  942. char cleanFilename[MAX_PATH];
  943. V_strncpy( cleanFilename, pFilename, sizeof( cleanFilename ) );
  944. V_RemoveDotSlashes( cleanFilename, CORRECT_PATH_SEPARATOR );
  945. // some vpc scripts decided to unecessarily double quote their filenames
  946. // remove any incoming surrounding quotes, this only causes string handling problems (i.e. extension comparison, etc)
  947. // all files get serialized to xml output with mandatory surrounding quotes
  948. if ( cleanFilename[0] == '\"' )
  949. {
  950. int len = strlen( cleanFilename );
  951. if ( len > 1 && cleanFilename[len-1] == '\"' )
  952. {
  953. memcpy( cleanFilename, cleanFilename+1, len - 2 );
  954. cleanFilename[len-2] = '\0';
  955. }
  956. }
  957. pFilename = cleanFilename;
  958. BaseClass::StartFile( pFilename, bWarnIfAlreadyExists );
  959. CProjectFile *pFile = NULL;
  960. if ( m_spFolderStack.Count() == 0 )
  961. {
  962. // add at root
  963. AddFileToFolder( pFilename, NULL, bWarnIfAlreadyExists, &pFile );
  964. }
  965. else
  966. {
  967. // add at subfolder
  968. AddFileToFolder( pFilename, m_spFolderStack.Top(), bWarnIfAlreadyExists, &pFile );
  969. }
  970. m_pProjectFile = pFile;
  971. return ( pFile != NULL );
  972. }
  973. void CVCProjGenerator::EndFile()
  974. {
  975. BaseClass::EndFile();
  976. }
  977. bool CVCProjGenerator::RemoveFile( const char *pFilename )
  978. {
  979. // normalize filename, filenames need to compare correctly
  980. char cleanFilename[MAX_PATH];
  981. V_strncpy( cleanFilename, pFilename, sizeof( cleanFilename ) );
  982. V_RemoveDotSlashes( cleanFilename, CORRECT_PATH_SEPARATOR );
  983. pFilename = cleanFilename;
  984. BaseClass::RemoveFile( pFilename );
  985. bool bValid;
  986. if ( m_spFolderStack.Count() == 0 )
  987. {
  988. // remove from root
  989. bValid = RemoveFileFromFolder( pFilename, NULL );
  990. }
  991. else
  992. {
  993. // remove at subfolder
  994. bValid = RemoveFileFromFolder( pFilename, m_spFolderStack.Top() );
  995. }
  996. return bValid;
  997. }
  998. bool CVCProjGenerator::Config_GetConfigurations( const char *pszConfigName )
  999. {
  1000. CProjectConfiguration *pConfig = NULL;
  1001. bool bValid = GetRootConfiguration( pszConfigName, &pConfig );
  1002. if ( !bValid )
  1003. {
  1004. g_pVPC->VPCError( "Could not get configuration '%s'", pszConfigName );
  1005. }
  1006. m_pConfig = pConfig;
  1007. return true;
  1008. }
  1009. void CVCProjGenerator::StartConfigurationBlock( const char *pConfigName, bool bFileSpecific )
  1010. {
  1011. BaseClass::StartConfigurationBlock( pConfigName, bFileSpecific );
  1012. if ( bFileSpecific )
  1013. {
  1014. CProjectConfiguration *pFileConfig = NULL;
  1015. bool bValid = m_pProjectFile->GetConfiguration( pConfigName, &pFileConfig );
  1016. if ( !bValid )
  1017. {
  1018. // not found, must be valid config
  1019. // must match predefined configurations, prevents misspellings
  1020. if ( !IsConfigurationNameValid( pConfigName ) )
  1021. {
  1022. g_pVPC->VPCError( "File %s, Unknown configuration '%s'", m_pProjectFile->m_Name.Get(), pConfigName );
  1023. }
  1024. bValid = m_pProjectFile->AddConfiguration( pConfigName, &pFileConfig );
  1025. if ( !bValid )
  1026. {
  1027. g_pVPC->VPCError( "File %s, Could not get file configuration '%s'", m_pProjectFile->m_Name.Get(), pConfigName );
  1028. }
  1029. }
  1030. m_pFileConfig = pFileConfig;
  1031. }
  1032. else
  1033. {
  1034. Config_GetConfigurations( pConfigName );
  1035. }
  1036. }
  1037. void CVCProjGenerator::EndConfigurationBlock()
  1038. {
  1039. BaseClass::EndConfigurationBlock();
  1040. if ( m_pFileConfig && m_pFileConfig->IsEmpty() )
  1041. {
  1042. // any file configuration (after parsing) that has no property state gets purged
  1043. m_pProjectFile->RemoveConfiguration( m_pFileConfig );
  1044. }
  1045. m_pFileConfig = NULL;
  1046. }
  1047. void CVCProjGenerator::FileExcludedFromBuild( bool bExcluded )
  1048. {
  1049. if ( !m_pFileConfig )
  1050. {
  1051. g_pVPC->VPCSyntaxError( "Cannot set $ExcludedFromBuild unless in a $File configuration context" );
  1052. }
  1053. BaseClass::FileExcludedFromBuild( bExcluded );
  1054. ToolProperty_t* pToolProperty = m_pGeneratorDefinition->GetProperty( KEYWORD_GENERAL, "$ExcludedFromBuild" );
  1055. if ( !pToolProperty )
  1056. {
  1057. g_pVPC->VPCError( "Missing proper declaration for $ExcludedFromBuild" );
  1058. }
  1059. m_pFileConfig->m_PropertyStates.SetBoolProperty( pToolProperty, bExcluded );
  1060. }
  1061. bool CVCProjGenerator::StartPropertySection( configKeyword_e eKeyword, bool *pbShouldSkip )
  1062. {
  1063. BaseClass::StartPropertySection( eKeyword );
  1064. *pbShouldSkip = false;
  1065. m_nActivePropertySection = KEYWORD_UNKNOWN;
  1066. bool bHandled = false;
  1067. switch ( eKeyword )
  1068. {
  1069. case KEYWORD_GENERAL:
  1070. bHandled = true;
  1071. break;
  1072. case KEYWORD_DEBUGGING:
  1073. m_pDebuggingTool = m_pConfig->GetDebuggingTool();
  1074. if ( !m_pDebuggingTool )
  1075. {
  1076. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1077. }
  1078. bHandled = true;
  1079. break;
  1080. case KEYWORD_COMPILER:
  1081. case KEYWORD_PS3_SNCCOMPILER:
  1082. case KEYWORD_PS3_GCCCOMPILER:
  1083. eKeyword = SetPS3VisualStudioIntegrationType( eKeyword );
  1084. if ( eKeyword == KEYWORD_UNKNOWN )
  1085. {
  1086. // skip this section
  1087. break;
  1088. }
  1089. m_spCompilerStack.Push( m_pCompilerTool );
  1090. if ( m_pFileConfig )
  1091. {
  1092. m_pCompilerTool = m_pFileConfig->GetCompilerTool();
  1093. }
  1094. else
  1095. {
  1096. m_pCompilerTool = m_pConfig->GetCompilerTool();
  1097. }
  1098. if ( !m_pCompilerTool )
  1099. {
  1100. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1101. }
  1102. bHandled = true;
  1103. break;
  1104. case KEYWORD_LIBRARIAN:
  1105. m_pLibrarianTool = m_pConfig->GetLibrarianTool();
  1106. if ( !m_pLibrarianTool )
  1107. {
  1108. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1109. }
  1110. bHandled = true;
  1111. break;
  1112. case KEYWORD_LINKER:
  1113. case KEYWORD_PS3_SNCLINKER:
  1114. case KEYWORD_PS3_GCCLINKER:
  1115. eKeyword = SetPS3VisualStudioIntegrationType( eKeyword );
  1116. if ( eKeyword == KEYWORD_UNKNOWN )
  1117. {
  1118. // skip this section
  1119. break;
  1120. }
  1121. m_pLinkerTool = m_pConfig->GetLinkerTool();
  1122. if ( !m_pLinkerTool )
  1123. {
  1124. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1125. }
  1126. bHandled = true;
  1127. break;
  1128. case KEYWORD_MANIFEST:
  1129. if ( !( g_pVPC->IsPlatformDefined( "WIN32" ) || g_pVPC->IsPlatformDefined( "WIN64" ) ) )
  1130. {
  1131. // windows specific
  1132. break;
  1133. }
  1134. m_pManifestTool = m_pConfig->GetManifestTool();
  1135. if ( !m_pManifestTool )
  1136. {
  1137. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1138. }
  1139. bHandled = true;
  1140. break;
  1141. case KEYWORD_XMLDOCGEN:
  1142. if ( !( g_pVPC->IsPlatformDefined( "WIN32" ) || g_pVPC->IsPlatformDefined( "WIN64" ) ) )
  1143. {
  1144. // windows specific
  1145. break;
  1146. }
  1147. m_pXMLDocGenTool = m_pConfig->GetXMLDocGenTool();
  1148. if ( !m_pXMLDocGenTool )
  1149. {
  1150. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1151. }
  1152. bHandled = true;
  1153. break;
  1154. case KEYWORD_BROWSEINFO:
  1155. if ( g_pVPC->IsPlatformDefined( "PS3" ) )
  1156. {
  1157. // not for ps3
  1158. break;
  1159. }
  1160. m_pBrowseInfoTool = m_pConfig->GetBrowseInfoTool();
  1161. if ( !m_pBrowseInfoTool )
  1162. {
  1163. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1164. }
  1165. bHandled = true;
  1166. break;
  1167. case KEYWORD_RESOURCES:
  1168. if ( !( g_pVPC->IsPlatformDefined( "WIN32" ) || g_pVPC->IsPlatformDefined( "WIN64" ) ) )
  1169. {
  1170. // windows specific
  1171. break;
  1172. }
  1173. m_pResourcesTool = m_pConfig->GetResourcesTool();
  1174. if ( !m_pResourcesTool )
  1175. {
  1176. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1177. }
  1178. bHandled = true;
  1179. break;
  1180. case KEYWORD_PREBUILDEVENT:
  1181. m_pPreBuildEventTool = m_pConfig->GetPreBuildEventTool();
  1182. if ( !m_pPreBuildEventTool )
  1183. {
  1184. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1185. }
  1186. bHandled = true;
  1187. break;
  1188. case KEYWORD_PRELINKEVENT:
  1189. m_pPreLinkEventTool = m_pConfig->GetPreLinkEventTool();
  1190. if ( !m_pPreLinkEventTool )
  1191. {
  1192. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1193. }
  1194. bHandled = true;
  1195. break;
  1196. case KEYWORD_POSTBUILDEVENT:
  1197. m_pPostBuildEventTool = m_pConfig->GetPostBuildEventTool();
  1198. if ( !m_pPostBuildEventTool )
  1199. {
  1200. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1201. }
  1202. bHandled = true;
  1203. break;
  1204. case KEYWORD_CUSTOMBUILDSTEP:
  1205. m_spCustomBuildToolStack.Push( m_pCustomBuildTool );
  1206. if ( m_pFileConfig )
  1207. {
  1208. m_pCustomBuildTool = m_pFileConfig->GetCustomBuildTool();
  1209. }
  1210. else
  1211. {
  1212. m_pCustomBuildTool = m_pConfig->GetCustomBuildTool();
  1213. }
  1214. if ( !m_pCustomBuildTool )
  1215. {
  1216. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1217. }
  1218. bHandled = true;
  1219. break;
  1220. case KEYWORD_XBOXIMAGE:
  1221. if ( !g_pVPC->IsPlatformDefined( "X360" ) )
  1222. {
  1223. // xbox generator specific
  1224. break;
  1225. }
  1226. m_pXboxImageTool = m_pConfig->GetXboxImageTool();
  1227. if ( !m_pXboxImageTool )
  1228. {
  1229. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1230. }
  1231. bHandled = true;
  1232. break;
  1233. case KEYWORD_XBOXDEPLOYMENT:
  1234. if ( !g_pVPC->IsPlatformDefined( "X360" ) )
  1235. {
  1236. // xbox generator specific
  1237. break;
  1238. }
  1239. m_pXboxDeploymentTool = m_pConfig->GetXboxDeploymentTool();
  1240. if ( !m_pXboxDeploymentTool )
  1241. {
  1242. g_pVPC->VPCError( "Could not get %s tool interface from configuration", g_pVPC->KeywordToName( eKeyword ) );
  1243. }
  1244. bHandled = true;
  1245. break;
  1246. default:
  1247. // unknown
  1248. return false;
  1249. }
  1250. if ( bHandled )
  1251. {
  1252. // handled
  1253. m_nActivePropertySection = eKeyword;
  1254. }
  1255. else
  1256. {
  1257. // allow other platform specifc sections to just be quietly ignored
  1258. *pbShouldSkip = true;
  1259. }
  1260. return true;
  1261. }
  1262. void CVCProjGenerator::EndPropertySection( configKeyword_e eKeyword )
  1263. {
  1264. BaseClass::EndPropertySection( eKeyword );
  1265. switch( eKeyword )
  1266. {
  1267. case KEYWORD_CUSTOMBUILDSTEP:
  1268. m_spCustomBuildToolStack.Pop( m_pCustomBuildTool );
  1269. break;
  1270. case KEYWORD_COMPILER:
  1271. case KEYWORD_PS3_SNCCOMPILER:
  1272. case KEYWORD_PS3_GCCCOMPILER:
  1273. eKeyword = SetPS3VisualStudioIntegrationType( eKeyword );
  1274. m_spCompilerStack.Pop( m_pCompilerTool );
  1275. break;
  1276. }
  1277. m_nActivePropertySection = KEYWORD_UNKNOWN;
  1278. }
  1279. void CVCProjGenerator::HandleProperty( const char *pPropertyName, const char *pCustomScriptData )
  1280. {
  1281. // don't allow the baseclass to alter the script state
  1282. g_pVPC->GetScript().PushCurrentScript();
  1283. BaseClass::HandleProperty( pPropertyName, pCustomScriptData );
  1284. g_pVPC->GetScript().PopScript();
  1285. if ( pCustomScriptData )
  1286. {
  1287. g_pVPC->GetScript().PushScript( "HandleProperty custom data", pCustomScriptData );
  1288. }
  1289. ToolProperty_t *pToolProperty = m_pGeneratorDefinition->GetProperty( m_nActivePropertySection, pPropertyName );
  1290. if ( !pToolProperty )
  1291. {
  1292. // unknown property
  1293. g_pVPC->VPCSyntaxError( "Unknown property %s", pPropertyName );
  1294. }
  1295. const char *pToken = g_pVPC->GetScript().PeekNextToken( false );
  1296. if ( !pToken || !pToken[0] )
  1297. {
  1298. // quietly ignoring any property without a value
  1299. // not an error
  1300. if ( pCustomScriptData )
  1301. {
  1302. g_pVPC->GetScript().PopScript();
  1303. }
  1304. return;
  1305. }
  1306. CProjectConfiguration *pConfig = NULL;
  1307. CProjectTool *pTool = NULL;
  1308. switch ( m_nActivePropertySection )
  1309. {
  1310. case KEYWORD_GENERAL:
  1311. pConfig = m_pConfig;
  1312. break;
  1313. case KEYWORD_DEBUGGING:
  1314. pTool = m_pDebuggingTool;
  1315. break;
  1316. case KEYWORD_COMPILER:
  1317. case KEYWORD_PS3_SNCCOMPILER:
  1318. case KEYWORD_PS3_GCCCOMPILER:
  1319. pTool = m_pCompilerTool;
  1320. break;
  1321. case KEYWORD_LIBRARIAN:
  1322. pTool = m_pLibrarianTool;
  1323. break;
  1324. case KEYWORD_LINKER:
  1325. case KEYWORD_PS3_SNCLINKER:
  1326. case KEYWORD_PS3_GCCLINKER:
  1327. pTool = m_pLinkerTool;
  1328. break;
  1329. case KEYWORD_MANIFEST:
  1330. pTool = m_pManifestTool;
  1331. break;
  1332. case KEYWORD_XMLDOCGEN:
  1333. pTool = m_pXMLDocGenTool;
  1334. break;
  1335. case KEYWORD_BROWSEINFO:
  1336. pTool = m_pBrowseInfoTool;
  1337. break;
  1338. case KEYWORD_RESOURCES:
  1339. pTool = m_pResourcesTool;
  1340. break;
  1341. case KEYWORD_PREBUILDEVENT:
  1342. pTool = m_pPreBuildEventTool;
  1343. break;
  1344. case KEYWORD_PRELINKEVENT:
  1345. pTool = m_pPreLinkEventTool;
  1346. break;
  1347. case KEYWORD_POSTBUILDEVENT:
  1348. pTool = m_pPostBuildEventTool;
  1349. break;
  1350. case KEYWORD_CUSTOMBUILDSTEP:
  1351. pTool = m_pCustomBuildTool;
  1352. break;
  1353. case KEYWORD_XBOXIMAGE:
  1354. pTool = m_pXboxImageTool;
  1355. break;
  1356. case KEYWORD_XBOXDEPLOYMENT:
  1357. pTool = m_pXboxDeploymentTool;
  1358. break;
  1359. default:
  1360. g_pVPC->VPCError( "HandleProperty: No support for Tool:%s Property:%s - requires implementation", g_pVPC->KeywordToName( m_nActivePropertySection ), pPropertyName );
  1361. }
  1362. bool bHandled = false;
  1363. if ( pTool )
  1364. {
  1365. bHandled = pTool->SetProperty( pToolProperty );
  1366. }
  1367. else if ( pConfig )
  1368. {
  1369. bHandled = pConfig->SetProperty( pToolProperty );
  1370. }
  1371. if ( !bHandled )
  1372. {
  1373. g_pVPC->VPCError( "HandleProperty: Failed to set %s", pPropertyName );
  1374. }
  1375. if ( pCustomScriptData )
  1376. {
  1377. g_pVPC->GetScript().PopScript();
  1378. }
  1379. }
  1380. bool CVCProjGenerator::GetFolder( const char *pFolderName, CProjectFolder *pParentFolder, CProjectFolder **ppOutFolder )
  1381. {
  1382. bool bValid;
  1383. if ( !pParentFolder )
  1384. {
  1385. bValid = m_pRootFolder->GetFolder( pFolderName, ppOutFolder );
  1386. }
  1387. else
  1388. {
  1389. bValid = pParentFolder->GetFolder( pFolderName, ppOutFolder );
  1390. }
  1391. return bValid;
  1392. }
  1393. bool CVCProjGenerator::AddFolder( const char *pFolderName, CProjectFolder *pParentFolder, CProjectFolder **ppOutFolder )
  1394. {
  1395. bool bValid;
  1396. if ( !pParentFolder )
  1397. {
  1398. bValid = m_pRootFolder->AddFolder( pFolderName, ppOutFolder );
  1399. }
  1400. else
  1401. {
  1402. bValid = pParentFolder->AddFolder( pFolderName, ppOutFolder );
  1403. }
  1404. return bValid;
  1405. }
  1406. bool CVCProjGenerator::FindFile( const char *pFilename, CProjectFile **ppFile )
  1407. {
  1408. CProjectFile findProjectFile( this, pFilename );
  1409. int iIndex = m_FileDictionary.Find( &findProjectFile );
  1410. if ( iIndex != m_FileDictionary.InvalidIndex() )
  1411. {
  1412. // found
  1413. if ( ppFile )
  1414. {
  1415. *ppFile = m_FileDictionary[iIndex];
  1416. }
  1417. return true;
  1418. }
  1419. // not found
  1420. if ( ppFile )
  1421. {
  1422. *ppFile = NULL;
  1423. }
  1424. return false;
  1425. }
  1426. void CVCProjGenerator::AddFileToFolder( const char *pFilename, CProjectFolder *pFolder, bool bWarnIfAlreadyExists, CProjectFile **ppFile )
  1427. {
  1428. if ( FindFile( pFilename, ppFile ) )
  1429. {
  1430. // already present
  1431. if ( bWarnIfAlreadyExists )
  1432. {
  1433. g_pVPC->VPCWarning( "File %s already exists in project", pFilename );
  1434. }
  1435. return;
  1436. }
  1437. CProjectFile *pFile;
  1438. if ( !pFolder )
  1439. {
  1440. // add at root
  1441. m_pRootFolder->AddFile( pFilename, &pFile );
  1442. }
  1443. else
  1444. {
  1445. // add at folder
  1446. pFolder->AddFile( pFilename, &pFile );
  1447. }
  1448. // add to dictionary
  1449. m_FileDictionary.Insert( pFile );
  1450. if ( ppFile )
  1451. {
  1452. *ppFile = pFile;
  1453. }
  1454. }
  1455. bool CVCProjGenerator::RemoveFileFromFolder( const char *pFilename, CProjectFolder *pFolder )
  1456. {
  1457. bool bFound = false;
  1458. CProjectFile findProjectFile( this, pFilename );
  1459. int iIndex = m_FileDictionary.Find( &findProjectFile );
  1460. if ( iIndex != m_FileDictionary.InvalidIndex() )
  1461. {
  1462. bFound = true;
  1463. m_FileDictionary.RemoveAt( iIndex );
  1464. }
  1465. if ( !bFound )
  1466. return false;
  1467. if ( !pFolder )
  1468. {
  1469. m_pRootFolder->RemoveFile( pFilename );
  1470. }
  1471. else
  1472. {
  1473. pFolder->RemoveFile( pFilename );
  1474. }
  1475. return bFound;
  1476. }
  1477. void CVCProjGenerator::GetAllConfigurationNames( CUtlVector< CUtlString > &configurationNames )
  1478. {
  1479. configurationNames.Purge();
  1480. for ( int i = 0; i < m_RootConfigurations.Count(); i++ )
  1481. {
  1482. configurationNames.AddToTail( m_RootConfigurations[i]->m_Name.Get() );
  1483. }
  1484. }
  1485. bool CVCProjGenerator::GetRootConfiguration( const char *pConfigName, CProjectConfiguration **ppConfig )
  1486. {
  1487. if ( !pConfigName || !pConfigName[0] )
  1488. {
  1489. g_pVPC->VPCError( "Empty or bad configuration name." );
  1490. }
  1491. if ( ppConfig )
  1492. {
  1493. // assume not found
  1494. *ppConfig = NULL;
  1495. }
  1496. for ( int i = 0; i < m_RootConfigurations.Count(); i++ )
  1497. {
  1498. if ( !V_stricmp( m_RootConfigurations[i]->m_Name.Get(), pConfigName ) )
  1499. {
  1500. // found
  1501. if ( ppConfig )
  1502. {
  1503. *ppConfig = m_RootConfigurations[i];
  1504. }
  1505. return true;
  1506. }
  1507. }
  1508. return false;
  1509. }
  1510. bool CVCProjGenerator::IsConfigurationNameValid( const char *pConfigName )
  1511. {
  1512. return GetRootConfiguration( pConfigName, NULL );
  1513. }
  1514. configKeyword_e CVCProjGenerator::SetPS3VisualStudioIntegrationType( configKeyword_e eKeyword )
  1515. {
  1516. PS3VSIType_e vsiType = PS3_VSI_TYPE_UNDEFINED;
  1517. switch ( eKeyword )
  1518. {
  1519. case KEYWORD_COMPILER:
  1520. case KEYWORD_LINKER:
  1521. if ( !g_pVPC->IsPlatformDefined( "PS3" ) )
  1522. {
  1523. return eKeyword;
  1524. }
  1525. if ( m_VSIType == PS3_VSI_TYPE_UNDEFINED )
  1526. {
  1527. // PS3 defaults to SNC, unless explictly specified
  1528. vsiType = PS3_VSI_TYPE_SNC;
  1529. }
  1530. else
  1531. {
  1532. // already set
  1533. vsiType = m_VSIType;
  1534. }
  1535. break;
  1536. case KEYWORD_PS3_SNCCOMPILER:
  1537. case KEYWORD_PS3_SNCLINKER:
  1538. if ( !g_pVPC->IsPlatformDefined( "PS3" ) )
  1539. {
  1540. // ps3 generator specific
  1541. // not available for other platforms
  1542. return KEYWORD_UNKNOWN;
  1543. }
  1544. vsiType = PS3_VSI_TYPE_SNC;
  1545. break;
  1546. case KEYWORD_PS3_GCCCOMPILER:
  1547. case KEYWORD_PS3_GCCLINKER:
  1548. if ( !g_pVPC->IsPlatformDefined( "PS3" ) )
  1549. {
  1550. // ps3 generator specific
  1551. // not available for other platforms
  1552. return KEYWORD_UNKNOWN;
  1553. }
  1554. vsiType = PS3_VSI_TYPE_GCC;
  1555. break;
  1556. default:
  1557. g_pVPC->VPCError( "Unknown PS3 compiler/linker type" );
  1558. break;
  1559. }
  1560. if ( m_VSIType == PS3_VSI_TYPE_UNDEFINED )
  1561. {
  1562. // once set, compiler/linker choice (snc or gcc) cannot be changed
  1563. m_VSIType = vsiType;
  1564. }
  1565. else if ( m_VSIType != vsiType )
  1566. {
  1567. // cannot intermix tool properties, they must be exclusive
  1568. g_pVPC->VPCSyntaxError( "PS3 compiler/linker (GCC or SNC) already set, cannot be changed" );
  1569. }
  1570. // remap ambiguous compiler/linker tool to explicit SNC/GCC tool flavor
  1571. if ( eKeyword == KEYWORD_COMPILER )
  1572. {
  1573. eKeyword = ( m_VSIType == PS3_VSI_TYPE_SNC ) ? KEYWORD_PS3_SNCCOMPILER : KEYWORD_PS3_GCCCOMPILER;
  1574. }
  1575. else if ( eKeyword == KEYWORD_LINKER )
  1576. {
  1577. eKeyword = ( m_VSIType == PS3_VSI_TYPE_SNC ) ? KEYWORD_PS3_SNCLINKER : KEYWORD_PS3_GCCLINKER;
  1578. }
  1579. return eKeyword;
  1580. }
  1581. void CVCProjGenerator::ApplyInternalPreprocessorDefinitions()
  1582. {
  1583. // prep to add in vpc generated compiler defines
  1584. CUtlVector< macro_t* > macroDefines;
  1585. g_pVPC->GetMacrosMarkedForCompilerDefines( macroDefines );
  1586. if ( !macroDefines.Count() )
  1587. {
  1588. // nothing to fixup
  1589. return;
  1590. }
  1591. // get all the vpc macros that have been marked for auto adding as compiler define
  1592. CUtlString extraDefineString;
  1593. for ( int i = 0; i < macroDefines.Count(); i++ )
  1594. {
  1595. macro_t *pMacro = macroDefines[i];
  1596. CUtlString tempString;
  1597. tempString.Format( ";%s=%s", pMacro->name.String(), pMacro->value.String() );
  1598. extraDefineString += tempString;
  1599. }
  1600. // fixup root configurations
  1601. for ( int i = 0; i < m_RootConfigurations.Count(); i++ )
  1602. {
  1603. CCompilerTool *pCompilerTool = m_RootConfigurations[i]->GetCompilerTool();
  1604. if ( pCompilerTool )
  1605. {
  1606. PropertyState_t *pPropertyState = pCompilerTool->m_PropertyStates.GetProperty( "$PreprocessorDefinitions" );
  1607. if ( pPropertyState )
  1608. {
  1609. pPropertyState->m_StringValue += extraDefineString;
  1610. }
  1611. }
  1612. }
  1613. // fixup any file confiuration overrides
  1614. for ( int iIndex = m_FileDictionary.FirstInorder(); iIndex != m_FileDictionary.InvalidIndex(); iIndex = m_FileDictionary.NextInorder( iIndex ) )
  1615. {
  1616. CProjectFile *pProjectFile = m_FileDictionary[iIndex];
  1617. for ( int i = 0; i < pProjectFile->m_Configs.Count(); i++ )
  1618. {
  1619. CCompilerTool *pCompilerTool = pProjectFile->m_Configs[i]->GetCompilerTool();
  1620. if ( pCompilerTool )
  1621. {
  1622. PropertyState_t *pPropertyState = pCompilerTool->m_PropertyStates.GetProperty( "$PreprocessorDefinitions" );
  1623. if ( pPropertyState )
  1624. {
  1625. pPropertyState->m_StringValue += extraDefineString;
  1626. }
  1627. }
  1628. }
  1629. }
  1630. }