Team Fortress 2 Source Code as on 22/4/2020
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.

491 lines
15 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. // valvelibaw.cpp : implementation file
  9. //
  10. #include "stdafx.h"
  11. #include "valvelib.h"
  12. #include "valvelibaw.h"
  13. #include "chooser.h"
  14. #include <assert.h>
  15. #include<atlbase.h>
  16. extern CComModule _Module;
  17. #include <atlcom.h>
  18. #include <initguid.h>
  19. #include<comdef.h>
  20. #ifdef _PSEUDO_DEBUG
  21. #undef THIS_FILE
  22. static char THIS_FILE[] = __FILE__;
  23. #endif
  24. #define STUPID_MS_BUG 1
  25. enum Config_t
  26. {
  27. CONFIG_DEBUG = 0,
  28. CONFIG_RELEASE
  29. };
  30. enum Project_t
  31. {
  32. PROJECT_LIB = 0,
  33. PROJECT_DLL,
  34. PROJECT_EXE
  35. };
  36. struct ProjectInfo_t
  37. {
  38. DSProjectSystem::IConfigurationPtr m_pConfig;
  39. long m_ConfigIndex;
  40. Config_t m_Config;
  41. Project_t m_Project;
  42. CString m_RelativeTargetPath;
  43. CString m_RelativeImplibPath;
  44. CString m_RelativeRootPath;
  45. CString m_RelativeSrcPath;
  46. CString m_TargetPath;
  47. CString m_RootName;
  48. CString m_BuildName;
  49. CString m_Ext;
  50. bool m_Tool;
  51. bool m_Console;
  52. bool m_Public;
  53. bool m_PublishImportLib;
  54. };
  55. // This is called immediately after the custom AppWizard is loaded. Initialize
  56. // the state of the custom AppWizard here.
  57. void CValvelibAppWiz::InitCustomAppWiz()
  58. {
  59. // Create a new dialog chooser; CDialogChooser's constructor initializes
  60. // its internal array with pointers to the steps.
  61. m_pChooser = new CDialogChooser;
  62. // Set the maximum number of steps.
  63. SetNumberOfSteps(LAST_DLG);
  64. // TODO: Add any other custom AppWizard-wide initialization here.
  65. }
  66. // This is called just before the custom AppWizard is unloaded.
  67. void CValvelibAppWiz::ExitCustomAppWiz()
  68. {
  69. // Deallocate memory used for the dialog chooser
  70. ASSERT(m_pChooser != NULL);
  71. delete m_pChooser;
  72. m_pChooser = NULL;
  73. // TODO: Add code here to deallocate resources used by the custom AppWizard
  74. }
  75. // This is called when the user clicks "Create..." on the New Project dialog
  76. // or "Next" on one of the custom AppWizard's steps.
  77. CAppWizStepDlg* CValvelibAppWiz::Next(CAppWizStepDlg* pDlg)
  78. {
  79. // Delegate to the dialog chooser
  80. return m_pChooser->Next(pDlg);
  81. }
  82. // This is called when the user clicks "Back" on one of the custom
  83. // AppWizard's steps.
  84. CAppWizStepDlg* CValvelibAppWiz::Back(CAppWizStepDlg* pDlg)
  85. {
  86. // Delegate to the dialog chooser
  87. return m_pChooser->Back(pDlg);
  88. }
  89. //-----------------------------------------------------------------------------
  90. // Deals with compiler settings
  91. //-----------------------------------------------------------------------------
  92. static void SetupCompilerSettings(ProjectInfo_t& info)
  93. {
  94. _bstr_t varTool;
  95. _bstr_t varSwitch;
  96. _variant_t varj = info.m_ConfigIndex;
  97. // We're going to modify settings associated with cl.exe
  98. varTool = "cl.exe";
  99. // Standard include directories
  100. CString includePath;
  101. if (info.m_Public)
  102. {
  103. includePath.Format("/I%spublic", info.m_RelativeSrcPath,
  104. info.m_RelativeSrcPath );
  105. info.m_pConfig->AddToolSettings(varTool, (char const*)includePath, varj);
  106. }
  107. // Control which version of the debug libraries to use (static single thread
  108. // for normal projects, multithread for tools)
  109. if (info.m_Tool)
  110. {
  111. if (info.m_Config == CONFIG_DEBUG)
  112. varSwitch = "/MTd";
  113. else
  114. varSwitch = "/MT";
  115. }
  116. else
  117. {
  118. // Suppress use of non-filesystem stuff in new non-tool projects...
  119. if (info.m_Config == CONFIG_DEBUG)
  120. varSwitch = "/D \"fopen=dont_use_fopen\" /MTd";
  121. else
  122. varSwitch = "/D \"fopen=dont_use_fopen\" /MT";
  123. }
  124. info.m_pConfig->AddToolSettings(varTool, varSwitch, varj);
  125. // If it's a DLL, define a standard exports macro...
  126. if (info.m_Project == PROJECT_DLL)
  127. {
  128. CString dllExport;
  129. dllExport.Format("/D \"%s_DLL_EXPORT\"", info.m_RootName );
  130. dllExport.MakeUpper();
  131. info.m_pConfig->AddToolSettings(varTool, (char const*)dllExport, varj);
  132. }
  133. // /W4 - Warning level 4
  134. // /FD - Generates file dependencies
  135. // /G6 - optimize for pentium pro
  136. // Add _WIN32, as that's what all our other code uses
  137. varSwitch = "/W4 /FD /G6 /D \"_WIN32\"";
  138. info.m_pConfig->AddToolSettings(varTool, varSwitch, varj);
  139. // Remove Preprocessor def for MFC DLL specifier, _AFXDLL
  140. // /GX - No exceptions,
  141. // /YX - no precompiled headers
  142. // Remove WIN32, it's put there by default
  143. varSwitch = "/D \"_AFXDLL\" /GX /YX /D \"WIN32\"";
  144. info.m_pConfig->RemoveToolSettings(varTool, varSwitch, varj);
  145. switch (info.m_Config)
  146. {
  147. case CONFIG_DEBUG:
  148. // Remove the following switches (avoid duplicates, in addition to other things)
  149. varSwitch = "/D \"NDEBUG\" /Zi /ZI /GZ";
  150. info.m_pConfig->RemoveToolSettings(varTool, varSwitch, varj);
  151. // Add the following switches:
  152. // /ZI - Includes debug information in a program database compatible with Edit and Continue.
  153. // /Zi - Includes debug information in a program database (no Edit and Continue)
  154. // /Od - Disable optimization
  155. // /GZ - Catch release build problems (uninitialized variables, fp stack problems)
  156. // /Op - Improves floating-point consistency
  157. // /Gm - Minimal rebuild
  158. // /FR - Generate Browse Info
  159. varSwitch = "/D \"_DEBUG\" /Od /GZ /Op /Gm /FR\"Debug/\"";
  160. info.m_pConfig->AddToolSettings(varTool, varSwitch, varj);
  161. if (info.m_Project == PROJECT_LIB)
  162. {
  163. // Static libraries cannot use edit-and-continue, why compile it in?
  164. varSwitch = "/Zi";
  165. info.m_pConfig->AddToolSettings(varTool, varSwitch, varj);
  166. }
  167. else
  168. {
  169. varSwitch = "/ZI";
  170. info.m_pConfig->AddToolSettings(varTool, varSwitch, varj);
  171. }
  172. break;
  173. case CONFIG_RELEASE:
  174. // Remove the following switches:
  175. // /Zi - Generates complete debugging information
  176. // /ZI - Includes debug information in a program database compatible with Edit and Continue.
  177. // /Gm - Minimal rebuild
  178. // /GZ - Catch release build problems (uninitialized variables, fp stack problems)
  179. varSwitch = "/D \"_DEBUG\" /Gm /Zi /ZI /GZ";
  180. info.m_pConfig->RemoveToolSettings(varTool, varSwitch, varj);
  181. // Add the following switches:
  182. // /Ox - Uses maximum optimization (/Ob1gity /Gs)
  183. // /Ow - Assumes aliasing across function calls
  184. // /Op - Improves floating-point consistency
  185. // /Gf - String pooling
  186. // /Oi - Generates intrinsic functions
  187. // /Ot - Favors fast code
  188. // /Og - Uses global optimizations
  189. // /Gy - Enable function level linking
  190. varSwitch = "/D \"NDEBUG\" /Ox /Ow /Op /Oi /Ot /Og /Gf /Gy";
  191. info.m_pConfig->AddToolSettings(varTool, varSwitch, varj);
  192. break;
  193. }
  194. }
  195. //-----------------------------------------------------------------------------
  196. // Deals with resource compiler
  197. //-----------------------------------------------------------------------------
  198. static void SetupResourceCompilerSettings(ProjectInfo_t& info)
  199. {
  200. _bstr_t varTool;
  201. _bstr_t varSwitch;
  202. _variant_t varj = info.m_ConfigIndex;
  203. // Remove Preprocessor def for MFC DLL specifier, _AFXDLL
  204. varTool = "rc.exe";
  205. varSwitch = "/d \"_AFXDLL\"";
  206. info.m_pConfig->RemoveToolSettings(varTool, varSwitch, varj);
  207. }
  208. //-----------------------------------------------------------------------------
  209. // Deals with linker settings
  210. //-----------------------------------------------------------------------------
  211. static void SetupLinkerSettings(ProjectInfo_t& info)
  212. {
  213. _bstr_t varTool;
  214. _bstr_t varSwitch;
  215. _variant_t varj = info.m_ConfigIndex;
  216. // We're going to modify settings associated with cl.exe
  217. varTool = "link.exe";
  218. // Remove windows libraries by default... hopefully we don't have windows dependencies
  219. varSwitch = "kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib";
  220. info.m_pConfig->RemoveToolSettings(varTool, varSwitch, varj);
  221. // Add libraries we always want to use
  222. varSwitch = "tier0.lib";
  223. info.m_pConfig->AddToolSettings(varTool, varSwitch, varj);
  224. // Hook in the static library path
  225. CString libPath;
  226. // FIXME: Still haven't decided on build-specific publish dir
  227. if (info.m_Public)
  228. {
  229. libPath.Format( "/libpath:\"%slib\\common\\\" /libpath:\"%slib\\public\\\"",
  230. info.m_RelativeSrcPath, info.m_RelativeSrcPath );
  231. }
  232. else
  233. {
  234. libPath.Format( "/libpath:\"%slib\\common\\\"", info.m_RelativeSrcPath );
  235. }
  236. info.m_pConfig->AddToolSettings(varTool, (char const*)libPath, varj);
  237. }
  238. //-----------------------------------------------------------------------------
  239. // Deals with lib settings
  240. //-----------------------------------------------------------------------------
  241. static void SetupLibSettings(ProjectInfo_t& info)
  242. {
  243. }
  244. //-----------------------------------------------------------------------------
  245. // Deals with custom build steps
  246. //-----------------------------------------------------------------------------
  247. static void SetupCustomBuildSteps(ProjectInfo_t& info)
  248. {
  249. // Create the custom build steps
  250. CString copySteps;
  251. CString targets;
  252. if (info.m_Project == PROJECT_LIB)
  253. {
  254. CString targetPath;
  255. targetPath.Format( "%s%s.%s", info.m_RelativeTargetPath, info.m_RootName, info.m_Ext );
  256. // NOTE: The second attrib is commented out because I'm fairly certain it causes
  257. // a bug in VSS to make it overwrite the target on a get
  258. copySteps.Format(
  259. "if exist %s attrib -r %s\n"
  260. "copy $(TargetPath) %s\n"
  261. "if exist $(TargetDir)\\%s.map copy $(TargetDir)\\%s.map %s%s.map",
  262. targetPath, targetPath,
  263. targetPath,
  264. info.m_RootName, info.m_RootName, info.m_RelativeTargetPath, info.m_RootName );
  265. targets.Format( "%s\n", targetPath );
  266. }
  267. else
  268. {
  269. CString targetPath;
  270. targetPath.Format( "%s%s.%s", info.m_RelativeTargetPath, info.m_RootName, info.m_Ext );
  271. // NOTE: The second attrib is commented out because I'm fairly certain it causes
  272. // a bug in VSS to make it overwrite the target on a get
  273. copySteps.Format(
  274. "if exist %s attrib -r %s\n"
  275. "copy $(TargetPath) %s\n"
  276. "if exist $(TargetDir)\\%s.map copy $(TargetDir)\\%s.map %s%s.map",
  277. targetPath, targetPath,
  278. targetPath,
  279. info.m_RootName, info.m_RootName, info.m_RelativeTargetPath, info.m_RootName );
  280. targets.Format( "%s", targetPath );
  281. if ((info.m_Project == PROJECT_DLL) && info.m_PublishImportLib)
  282. {
  283. CString targetPath;
  284. targetPath.Format( "%s%s.lib", info.m_RelativeImplibPath, info.m_RootName );
  285. CString impLibCopy;
  286. impLibCopy.Format(
  287. "\nif exist %s attrib -r %s\n"
  288. "if exist $(TargetDir)\\%s.lib copy $(TargetDir)\\%s.lib %s\n",
  289. targetPath, targetPath,
  290. info.m_RootName, info.m_RootName, targetPath
  291. );
  292. copySteps += impLibCopy;
  293. CString implibTarget;
  294. implibTarget.Format( "\n%s", targetPath );
  295. targets += implibTarget;
  296. }
  297. }
  298. CString publishDir;
  299. publishDir.Format( "Publishing to target directory (%s)...", info.m_RelativeTargetPath );
  300. info.m_pConfig->AddCustomBuildStep( (char const*)copySteps, (char const*)targets, (char const*)publishDir );
  301. }
  302. //-----------------------------------------------------------------------------
  303. // Deals with MIDL build steps
  304. //-----------------------------------------------------------------------------
  305. static void SetupMIDLSettings(ProjectInfo_t& info)
  306. {
  307. }
  308. //-----------------------------------------------------------------------------
  309. // Deals with browse build steps
  310. //-----------------------------------------------------------------------------
  311. static void SetupBrowseSettings(ProjectInfo_t& info)
  312. {
  313. }
  314. void CValvelibAppWiz::CustomizeProject(IBuildProject* pProject)
  315. {
  316. // This is called immediately after the default Debug and Release
  317. // configurations have been created for each platform. You may customize
  318. // existing configurations on this project by using the methods
  319. // of IBuildProject and IConfiguration such as AddToolSettings,
  320. // RemoveToolSettings, and AddCustomBuildStep. These are documented in
  321. // the Developer Studio object model documentation.
  322. // WARNING!! IBuildProject and all interfaces you can get from it are OLE
  323. // COM interfaces. You must be careful to release all new interfaces
  324. // you acquire. In accordance with the standard rules of COM, you must
  325. // NOT release pProject, unless you explicitly AddRef it, since pProject
  326. // is passed as an "in" parameter to this function. See the documentation
  327. // on CCustomAppWiz::CustomizeProject for more information.
  328. using namespace DSProjectSystem;
  329. long lNumConfigs;
  330. IConfigurationsPtr pConfigs;
  331. IBuildProjectPtr pProj;
  332. // Needed to convert IBuildProject to the DSProjectSystem namespace
  333. pProj.Attach((DSProjectSystem::IBuildProject*)pProject, true);
  334. // Add a release with symbols configuration
  335. pProj->get_Configurations(&pConfigs);
  336. pConfigs->get_Count(&lNumConfigs);
  337. // Needed for OLE2T below
  338. USES_CONVERSION;
  339. CComBSTR configName;
  340. ProjectInfo_t info;
  341. if (!Valvelibaw.m_Dictionary.Lookup("VALVE_RELATIVE_PATH", info.m_RelativeTargetPath))
  342. return;
  343. if (!Valvelibaw.m_Dictionary.Lookup("root", info.m_RootName))
  344. return;
  345. if (!Valvelibaw.m_Dictionary.Lookup("VALVE_TARGET_TYPE", info.m_Ext))
  346. return;
  347. if (!Valvelibaw.m_Dictionary.Lookup("VALVE_ROOT_RELATIVE_PATH", info.m_RelativeRootPath))
  348. return;
  349. if (!Valvelibaw.m_Dictionary.Lookup("VALVE_SRC_RELATIVE_PATH", info.m_RelativeSrcPath))
  350. return;
  351. if (!Valvelibaw.m_Dictionary.Lookup("VALVE_TARGET_PATH", info.m_TargetPath))
  352. return;
  353. CString tmp;
  354. info.m_Tool = (Valvelibaw.m_Dictionary.Lookup("VALVE_TOOL", tmp) != 0);
  355. info.m_Console = (Valvelibaw.m_Dictionary.Lookup("PROJTYPE_CON", tmp) != 0);
  356. info.m_Public = (Valvelibaw.m_Dictionary.Lookup("VALVE_PUBLIC_PROJECT", tmp) != 0);
  357. info.m_PublishImportLib = (Valvelibaw.m_Dictionary.Lookup("VALVE_PUBLISH_IMPORT_LIB", tmp) != 0);
  358. info.m_Project = PROJECT_LIB;
  359. if ( strstr( info.m_Ext, "dll" ) != 0 )
  360. {
  361. info.m_Project = PROJECT_DLL;
  362. if (!Valvelibaw.m_Dictionary.Lookup("VALVE_IMPLIB_RELATIVE_PATH", info.m_RelativeImplibPath))
  363. return;
  364. }
  365. else if ( strstr( info.m_Ext, "exe" ) != 0 )
  366. {
  367. info.m_Project = PROJECT_EXE;
  368. }
  369. //Get each individual configuration
  370. for (long j = 1 ; j <= lNumConfigs ; j++)
  371. {
  372. _bstr_t varTool;
  373. _bstr_t varSwitch;
  374. _variant_t varj = j;
  375. info.m_ConfigIndex = j;
  376. info.m_pConfig = pConfigs->Item(varj);
  377. // Figure if we're debug or release
  378. info.m_pConfig->get_Name( &configName );
  379. info.m_Config = CONFIG_RELEASE;
  380. info.m_BuildName = "Release";
  381. if ( strstr( OLE2T(configName), "Debug" ) != 0 )
  382. {
  383. info.m_Config = CONFIG_DEBUG;
  384. info.m_BuildName = "Debug";
  385. }
  386. // Not using MFC...
  387. info.m_pConfig->AddToolSettings("mfc", "0", varj);
  388. SetupCompilerSettings(info);
  389. SetupResourceCompilerSettings(info);
  390. if (info.m_Project != PROJECT_LIB)
  391. {
  392. SetupLinkerSettings(info);
  393. if (!info.m_Console)
  394. SetupMIDLSettings(info);
  395. }
  396. else
  397. {
  398. SetupLibSettings(info);
  399. }
  400. SetupCustomBuildSteps(info);
  401. SetupBrowseSettings(info);
  402. info.m_pConfig->MakeCurrentSettingsDefault();
  403. }
  404. }
  405. // Here we define one instance of the CValvelibAppWiz class. You can access
  406. // m_Dictionary and any other public members of this class through the
  407. // global Valvelibaw.
  408. CValvelibAppWiz Valvelibaw;