Leaked source code of windows server 2003
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.

2210 lines
76 KiB

  1. //+---------------------------------------------------------------------------
  2. //
  3. // Microsoft Windows
  4. // Copyright (C) Microsoft Corporation, 1989 - 1994.
  5. //
  6. // File: build.c
  7. //
  8. // Contents: Parameter processing and main entry point for Build.exe
  9. //
  10. // History: 16-May-89 SteveWo Created
  11. // ... See SLM log
  12. // 26-Jul-94 LyleC Cleanup/Add Pass0 support
  13. //
  14. //----------------------------------------------------------------------------
  15. #include "build.h"
  16. #include <ntverp.h>
  17. #ifdef _X86_
  18. extern PVOID __safe_se_handler_table; // Absolute symbol whose address is the count of entries.
  19. extern BYTE __safe_se_handler_count; // Base of the safe handler entry table
  20. extern DWORD_PTR __security_cookie;
  21. #endif
  22. //
  23. // Increase critical section timeout so people don't get
  24. // frightened when the CRT takes a long time to acquire
  25. // its critical section.
  26. //
  27. IMAGE_LOAD_CONFIG_DIRECTORY _load_config_used = {
  28. sizeof(_load_config_used), // Size
  29. 0, // Reserved
  30. 0, // Reserved
  31. 0, // Reserved
  32. 0, // GlobalFlagsClear
  33. 0, // GlobalFlagsSet
  34. 1000 * 60 * 60 * 24, // CriticalSectionTimeout (milliseconds)
  35. 0, // DeCommitFreeBlockThreshold
  36. 0, // DeCommitTotalFreeThreshold
  37. 0, // LockPrefixTable
  38. 0, 0, 0, 0, 0, 0, 0, // Reserved
  39. #ifdef _X86_
  40. (DWORD)&__security_cookie,
  41. (DWORD)&__safe_se_handler_table,
  42. (DWORD)&__safe_se_handler_count
  43. #else
  44. 0,
  45. 0,
  46. 0
  47. #endif
  48. };
  49. //
  50. // Target machine info:
  51. //
  52. // SourceSubDirMask, Description, Switch, MakeVariable,
  53. // SourceVariable, ObjectVariable, AssociateDirectory,
  54. // SourceDirectory, ObjectDirectory
  55. //
  56. TARGET_MACHINE_INFO i386TargetMachine = {
  57. TMIDIR_I386, "i386", "-386", "-x86", "386=1",
  58. "i386_SOURCES", "386_OBJECTS", "i386",
  59. "i386", "i386dirs", { "i386"},
  60. DIR_INCLUDE_X86 | DIR_INCLUDE_WIN32
  61. };
  62. TARGET_MACHINE_INFO ia64TargetMachine = {
  63. TMIDIR_IA64, "IA64", "-ia64", "-merced", "IA64=1",
  64. "IA64_SOURCES", "IA64_OBJECTS", "ia64",
  65. "ia64", "ia64dirs", { "ia64"},
  66. DIR_INCLUDE_IA64 | DIR_INCLUDE_RISC | DIR_INCLUDE_WIN64
  67. };
  68. TARGET_MACHINE_INFO Amd64TargetMachine = {
  69. TMIDIR_AMD64, "AMD64", "-amd64", "-amd64", "AMD64=1",
  70. "AMD64_SOURCES", "AMD64_OBJECTS", "amd64",
  71. "amd64", "amd64dirs", { "amd64"},
  72. DIR_INCLUDE_AMD64 | DIR_INCLUDE_RISC | DIR_INCLUDE_WIN64
  73. };
  74. TARGET_MACHINE_INFO ARMTargetMachine = {
  75. TMIDIR_ARM, "ARM", "-arm", "-arm", "ARM=1",
  76. "ARM_SOURCES", "ARM_OBJECTS", "arm",
  77. "arm", "armdirs", { "arm"},
  78. DIR_INCLUDE_ARM | DIR_INCLUDE_WIN32
  79. };
  80. TARGET_MACHINE_INFO *PossibleTargetMachines[MAX_TARGET_MACHINES] = {
  81. &i386TargetMachine,
  82. &ia64TargetMachine,
  83. &Amd64TargetMachine,
  84. &ARMTargetMachine
  85. };
  86. //
  87. // Global message color settings, set to default values.
  88. //
  89. MSG_COLOR_SETTINGS MsgColorSettings[MSG_COLOR_COUNT] = {
  90. "BUILD_COLOR_STATUS", FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN,
  91. "BUILD_COLOR_SUMMARY", FOREGROUND_INTENSITY | FOREGROUND_GREEN,
  92. "BUILD_COLOR_WARNING", FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN,
  93. "BUILD_COLOR_ERROR", FOREGROUND_INTENSITY | FOREGROUND_RED
  94. };
  95. //
  96. // Machine specific target dirs default. If one there is only one build
  97. // target and a target specific dirs file is selected, then this gets
  98. // filled with a pointer to the target specific dirs filename.
  99. //
  100. LPSTR pszTargetDirs = "";
  101. #define AltDirMaxSize 10 // Maximum size for alternate obj dir name
  102. CHAR LogDirectory[DB_MAX_PATH_LENGTH] = ".";
  103. CHAR LogFileName[DB_MAX_PATH_LENGTH] = "build";
  104. CHAR WrnFileName[DB_MAX_PATH_LENGTH] = "build";
  105. CHAR ErrFileName[DB_MAX_PATH_LENGTH] = "build";
  106. CHAR IncFileName[DB_MAX_PATH_LENGTH] = "build";
  107. CHAR XMLFileName[DB_MAX_PATH_LENGTH] = "build";
  108. CHAR szObjRoot[DB_MAX_PATH_LENGTH];
  109. CHAR *pszObjRoot;
  110. CHAR szObjDir[DB_MAX_PATH_LENGTH];
  111. CHAR szObjDirSlash[DB_MAX_PATH_LENGTH];
  112. CHAR szObjDirSlashStar[DB_MAX_PATH_LENGTH];
  113. CHAR szObjDirD[DB_MAX_PATH_LENGTH];
  114. CHAR szObjDirSlashD[DB_MAX_PATH_LENGTH];
  115. CHAR szObjDirSlashStarD[DB_MAX_PATH_LENGTH];
  116. CHAR *pszObjDir = szObjDir;
  117. CHAR *pszObjDirSlash = szObjDirSlash;
  118. CHAR *pszObjDirSlashStar = szObjDirSlashStar;
  119. CHAR *pszObjDirD = szObjDirD;
  120. BOOL fCheckedBuild = TRUE;
  121. ULONG iObjectDir = 0;
  122. BOOL fDependencySwitchUsed;
  123. BOOL fCmdLineDependencySwitchUsed;
  124. BOOL fCmdLineQuicky;
  125. BOOL fCmdLineSemiQuicky;
  126. BOOL fCmdLineQuickZero;
  127. BOOL fErrorBaseline;
  128. BOOL fBuildAltDirSet;
  129. CHAR *BuildProduct;
  130. char BaselinePathName[DB_MAX_PATH_LENGTH]; // The file name for -B
  131. BOOL bBaselineFailure; // Indicates if there is a build failure that is not in the baseline file
  132. DWORD dwLastBaselineSeekPos; // Keeps track on the passed baseline failures
  133. ULONG DefaultProcesses = 0;
  134. CHAR *szBuildTag;
  135. #define MAX_ENV_ARG 512
  136. const char szNewLine[] = "\r\n";
  137. const char szUsage[] =
  138. "Usage: BUILD [-?] display this message\n"
  139. "\t[-#] force _objects.mac to be regenerated\n"
  140. "\t[-0] pass 0 generation only, no compile, no link\n"
  141. "\t[-2] same as old -Z (only do a 2 pass build - no pass 0)\n"
  142. "\t[-3] same as -Z\n"
  143. "\t[-a] allows synchronized blocks and drains during link pass\n"
  144. "\t[-b] displays full error message text (doesn't truncate)\n"
  145. "\t[-B [baseline]] Checks the build failures against a baseline\n"
  146. "\t\tIf there is no baseline,terminates the build on the first error\n"
  147. "\t[-c] deletes all object files\n"
  148. "\t[-C] deletes all .lib files only\n"
  149. #if DBG
  150. "\t[-d] display debug information\n"
  151. #endif
  152. "\t[-D] check dependencies before building (on by default if BUILD_PRODUCT != NT)\n"
  153. "\t[-e] generates build.log, build.wrn & build.err files\n"
  154. "\t[-E] always keep the log/wrn/err files (use with -z)\n"
  155. "\t[-f] force rescan of all source and include files\n"
  156. "\t[-F] when displaying errors/warnings to stdout, print the full path\n"
  157. "\t[-g] Display warnings/errors/summary in color\n"
  158. "\t[-h] Hide console output\n"
  159. "\t[-G] enables target specific dirs files iff one target\n"
  160. "\t[-i] ignore extraneous dependency warning messages\n"
  161. "\t[-I] do not display thread index if multiprocessor build\n"
  162. "\t[-j filename] use 'filename' as the name for log files\n"
  163. "\t[-k] keep (don't delete) out-of-date targets\n"
  164. "\t[-l] link only, no compiles\n"
  165. "\t[-L] compile only, no link phase\n"
  166. "\t[-m] run build in the idle priority class\n"
  167. "\t[-M [n]] Multiprocessor build (for MP machines)\n"
  168. "\t[-n] No SYNCHRONIZE_BLOCK and SYNCHRONIZE_DRAIN directives\n"
  169. "\t[-o] display out-of-date files\n"
  170. "\t[-O] generate obj\\_objects.mac file for current directory\n"
  171. "\t[-p] pause' before compile and link phases\n"
  172. "\t[-P] Print elapsed time after every directory\n"
  173. "\t[-q] query only, don't run NMAKE\n"
  174. "\t[-r dirPath] restarts clean build at specified directory path\n"
  175. "\t[-s] display status line at top of display\n"
  176. "\t[-S] display status line with include file line counts\n"
  177. "\t[-t] display the first level of the dependency tree\n"
  178. "\t[-T] display the complete dependency tree\n"
  179. "\t[-$] display the complete dependency tree hierarchically\n"
  180. "\t[-u] display unused BUILD_OPTIONS\n"
  181. "\t[-v] enable include file version checking\n"
  182. "\t[-w] show warnings on screen\n"
  183. "\t[-x filename] exclude include file from dependency checks\n"
  184. "\t[-X] generates build.xml file\n"
  185. "\t[-Xv] generates verbose build.xml file\n"
  186. "\t[-y] show files scanned\n"
  187. "\t[-z] no dependency checking or scanning of source files -\n"
  188. "\t\tone pass compile/link\n"
  189. "\t[-Z] no dependency checking or scanning of source files -\n"
  190. "\t\tthree passes\n"
  191. "\t[-why] list reasons for building targets\n"
  192. "\n"
  193. "\t[-386] build targets for 32-bit Intel\n"
  194. "\t[-x86] Same as -i386\n"
  195. "\t[-ia64] build targets for IA64\n"
  196. "\t[-amd64] build targets for AMD64\n"
  197. "\t[-arm] build targets for ARM\n"
  198. "\n"
  199. "\t[-jpath pathname] use 'pathname' as the path for log files instead of \".\"\n"
  200. "\t[-nmake arg] argument to pass to NMAKE\n"
  201. "\t[-clean] equivalent to '-nmake clean'\n"
  202. "\tNon-switch parameters specify additional source directories\n"
  203. "\t* builds all optional source directories\n";
  204. BOOL
  205. ProcessParameters(int argc, LPSTR argv[], BOOL SkipFirst);
  206. VOID
  207. GetEnvParameters(
  208. LPSTR EnvVarName,
  209. LPSTR DefaultValue,
  210. int *pargc,
  211. int maxArgc,
  212. LPSTR argv[]);
  213. VOID
  214. FreeEnvParameters(int argc, LPSTR argv[]);
  215. VOID
  216. FreeCmdStrings(VOID);
  217. VOID
  218. MungePossibleTarget(
  219. PTARGET_MACHINE_INFO pti
  220. );
  221. VOID
  222. GetIncludePatterns(
  223. LPSTR EnvVarName,
  224. int maxArgc,
  225. LPSTR argv[]);
  226. VOID
  227. FreeIncludePatterns(
  228. int argc,
  229. LPSTR argv[]);
  230. BOOL
  231. LoadBaselineFile(VOID);
  232. VOID
  233. FreeBaselineFile(VOID);
  234. VOID
  235. ResetProducerEvents(VOID);
  236. BOOL
  237. WINAPI
  238. ControlCHandler(DWORD CtrlType)
  239. {
  240. if ((CtrlType == CTRL_C_EVENT) || (CtrlType == CTRL_BREAK_EVENT)) {
  241. SetConsoleTextAttribute(GetStdHandle(STD_ERROR_HANDLE), DefaultConsoleAttributes);
  242. }
  243. return FALSE;
  244. }
  245. //+---------------------------------------------------------------------------
  246. //
  247. // Function: main
  248. //
  249. //----------------------------------------------------------------------------
  250. int
  251. __cdecl main(
  252. int argc,
  253. LPSTR argv[]
  254. )
  255. {
  256. char c;
  257. PDIRREC DirDB;
  258. UINT i;
  259. int EnvArgc = 0;
  260. LPSTR EnvArgv[ MAX_ENV_ARG ] = {0};
  261. LPSTR s, s1;
  262. CONSOLE_SCREEN_BUFFER_INFO csbi;
  263. time_t ltime;
  264. LPSTR PostBuildCmd;
  265. BOOL fPauseDone = FALSE;
  266. #if DBG
  267. BOOL fDebugSave;
  268. fDebug = 0;
  269. #endif
  270. if ( getenv("NTMAKEENV") == NULL ) {
  271. printf("environment variable NTMAKEENV must be defined\n");
  272. exit(1);
  273. }
  274. strcpy(szObjDir, "obj");
  275. strcpy(szObjDirSlash, "obj\\");
  276. strcpy(szObjDirSlashStar, "obj\\*");
  277. strcpy(szObjDirD, "objd");
  278. strcpy(szObjDirSlashD, "objd\\");
  279. strcpy(szObjDirSlashStarD, "objd\\*");
  280. for (i=3; i<_NFILE; i++) {
  281. _close( i );
  282. }
  283. pGetFileAttributesExA = (BOOL (WINAPI *)(LPCSTR, GET_FILEEX_INFO_LEVELS, LPVOID))
  284. GetProcAddress(GetModuleHandle("kernel32.dll"), "GetFileAttributesExA");
  285. if (pGetFileAttributesExA) {
  286. pDateTimeFile = DateTimeFile2;
  287. } else {
  288. pDateTimeFile = DateTimeFile;
  289. }
  290. InitializeCriticalSection(&TTYCriticalSection);
  291. s1 = getenv("COMSPEC");
  292. if (s1) {
  293. cmdexe = s1;
  294. } else {
  295. cmdexe = ( _osver & 0x8000 ) ? "command.com" : "cmd.exe";
  296. }
  297. GetConsoleScreenBufferInfo(GetStdHandle(STD_ERROR_HANDLE), &csbi);
  298. DefaultConsoleAttributes = csbi.wAttributes;
  299. memset(&RunningTotals, 0, sizeof(RunningTotals));
  300. for (i = 0; i < MSG_COLOR_COUNT; i++) {
  301. s = getenv(MsgColorSettings[i].EnvVarName);
  302. if (s) {
  303. MsgColorSettings[i].Color = atoi(s) & (0x000f);
  304. }
  305. }
  306. SetConsoleCtrlHandler(ControlCHandler, TRUE);
  307. {
  308. SYSTEMTIME st;
  309. FILETIME ft;
  310. GetSystemTime(&st);
  311. SystemTimeToFileTime(&st, &ft);
  312. FileTimeToDosDateTime( &ft,
  313. ((LPWORD)&BuildStartTime)+1,
  314. (LPWORD)&BuildStartTime
  315. );
  316. }
  317. BigBufSize = 0xFFF0;
  318. AllocMem(BigBufSize, &BigBuf, MT_IOBUFFER);
  319. // All env parsing should happen here (after the cmd line is processed)
  320. s = getenv("BASEDIR");
  321. if (s) {
  322. strcpy(NtRoot, s);
  323. } else {
  324. s = getenv("_NTROOT");
  325. if (!s)
  326. s = "\\nt";
  327. s1 = getenv("_NTDRIVE");
  328. if (!s1)
  329. s1 = "";
  330. sprintf(NtRoot, "%s%s", s1, s);
  331. }
  332. sprintf(DbMasterName, "%s\\%s", NtRoot, DBMASTER_NAME);
  333. s = getenv("_OBJ_ROOT");
  334. if (s) {
  335. pszObjRoot = strcpy(szObjRoot, s);
  336. }
  337. s = getenv("BUILD_ALT_DIR");
  338. if (s) {
  339. if (strlen(s) > sizeof(szObjDir) - strlen(szObjDir) - 1) {
  340. BuildError("environment variable BUILD_ALT_DIR may not be longer than %d characters.\r\n",
  341. sizeof(szObjDir) - strlen(szObjDir) - 1);
  342. exit(1);
  343. }
  344. strcat(szObjDir, s);
  345. strcpy(szObjDirSlash, szObjDir);
  346. strcpy(szObjDirSlashStar, szObjDir);
  347. strcat(szObjDirSlash, "\\");
  348. strcat(szObjDirSlashStar, "\\*");
  349. strcat(LogFileName, s);
  350. strcat(WrnFileName, s);
  351. strcat(ErrFileName, s);
  352. strcat(IncFileName, s);
  353. strcat(XMLFileName, s);
  354. fBuildAltDirSet= TRUE;
  355. }
  356. s = getenv("NTDEBUG");
  357. if (!s || *s == '\0' || strcmp(s, "retail") == 0 || strcmp(s, "ntsdnodbg") == 0) {
  358. fCheckedBuild = FALSE;
  359. }
  360. s = getenv("OS2_INC_PATH");
  361. if (s) {
  362. MakeString(&pszIncOs2, s, TRUE, MT_DIRSTRING);
  363. } else {
  364. MakeExpandedString(&pszIncOs2, "\\public\\sdk\\inc\\os2");
  365. }
  366. s = getenv("POSIX_INC_PATH");
  367. if (s) {
  368. MakeString(&pszIncPosix, s, TRUE, MT_DIRSTRING);
  369. } else {
  370. MakeExpandedString(&pszIncPosix, "\\public\\sdk\\inc\\posix");
  371. }
  372. s = getenv("CHICAGO_INC_PATH");
  373. if (s) {
  374. MakeString(&pszIncChicago, s, TRUE, MT_DIRSTRING);
  375. } else {
  376. MakeExpandedString(&pszIncChicago, "\\public\\sdk\\inc\\chicago");
  377. }
  378. s = getenv("CRT_INC_PATH");
  379. if (s) {
  380. MakeString(&pszIncCrt, s, TRUE, MT_DIRSTRING);
  381. } else {
  382. MakeExpandedString(&pszIncCrt, "\\public\\sdk\\inc\\crt");
  383. }
  384. s = getenv("SDK_INC_PATH");
  385. if (s) {
  386. MakeString(&pszIncSdk, s, TRUE, MT_DIRSTRING);
  387. } else {
  388. MakeExpandedString(&pszIncSdk, "\\public\\sdk\\inc");
  389. }
  390. s = getenv("OAK_INC_PATH");
  391. if (s) {
  392. MakeString(&pszIncOak, s, TRUE, MT_DIRSTRING);
  393. } else {
  394. MakeExpandedString(&pszIncOak, "\\public\\oak\\inc");
  395. }
  396. s = getenv("DDK_INC_PATH");
  397. if (s) {
  398. MakeString(&pszIncDdk, s, TRUE, MT_DIRSTRING);
  399. } else {
  400. MakeExpandedString(&pszIncDdk, "\\public\\ddk\\inc");
  401. }
  402. s = getenv("WDM_INC_PATH");
  403. if (s) {
  404. MakeString(&pszIncWdm, s, TRUE, MT_DIRSTRING);
  405. } else {
  406. MakeExpandedString(&pszIncWdm, "\\public\\ddk\\inc\\wdm");
  407. }
  408. s = getenv("PRIVATE_INC_PATH");
  409. if (s) {
  410. MakeString(&pszIncPri, s, TRUE, MT_DIRSTRING);
  411. } else {
  412. MakeExpandedString(&pszIncPri, "\\private\\inc");
  413. }
  414. s = getenv("MFC_INCLUDES");
  415. if (s) {
  416. MakeString(&pszIncMfc, s, TRUE, MT_DIRSTRING);
  417. } else {
  418. MakeExpandedString(&pszIncMfc, "\\public\\sdk\\inc\\mfc42");
  419. }
  420. s = getenv("SDK_LIB_DEST");
  421. if (s) {
  422. MakeString(&pszSdkLibDest, s, TRUE, MT_DIRSTRING);
  423. } else {
  424. MakeExpandedString(&pszSdkLibDest, "\\public\\sdk\\lib");
  425. }
  426. s = getenv("DDK_LIB_DEST");
  427. if (s) {
  428. MakeString(&pszDdkLibDest, s, TRUE, MT_DIRSTRING);
  429. } else {
  430. MakeExpandedString(&pszDdkLibDest, "\\public\\sdk\\lib");
  431. }
  432. s = getenv("PUBLIC_INTERNAL_PATH");
  433. if (s) {
  434. MakeString(&pszPublicInternalPath, s, TRUE, MT_DIRSTRING);
  435. } else {
  436. MakeExpandedString(&pszPublicInternalPath, "\\public\\internal");
  437. }
  438. szBuildTag = getenv("BUILD_TAG");
  439. strcpy( MakeParameters, "" );
  440. MakeParametersTail = AppendString( MakeParameters,
  441. "/c BUILDMSG=Stop.",
  442. FALSE);
  443. RecurseLevel = 0;
  444. #if DBG
  445. if ((s = getenv("BUILD_DEBUG_FLAG")) != NULL) {
  446. i = atoi(s);
  447. if (!isdigit(*s)) {
  448. i = 1;
  449. }
  450. BuildMsg("Debug Output Enabled: %u ==> %u\r\n", fDebug, fDebug | i);
  451. fDebug |= i;
  452. }
  453. #endif
  454. if (!(MakeProgram = getenv( "BUILD_MAKE_PROGRAM" ))) {
  455. MakeProgram = "NMAKE.EXE";
  456. }
  457. if (s = getenv("BUILD_PATH")) {
  458. SetEnvironmentVariable("PATH", s);
  459. }
  460. if (s = getenv("COPYCMD")) {
  461. if (!strchr(s, 'y') && !strchr(s, 'Y')) {
  462. // COPYCMD is set, but /y isn't a part of it. Add /Y.
  463. BuildMsg("Adding /Y to COPYCMD so xcopy ops won't hang.\r\n");
  464. s1 = malloc(strlen(s) + sizeof(" /Y") + 1);
  465. if (s1) {
  466. strcpy(s1, s);
  467. strcat(s1, " /Y");
  468. SetEnvironmentVariable("COPYCMD", s1);
  469. }
  470. }
  471. } else {
  472. // COPYCMD not set. Do so.
  473. BuildMsg("Adding /Y to COPYCMD so xcopy ops won't hang.\r\n");
  474. SetEnvironmentVariable("COPYCMD", "/Y");
  475. }
  476. PostBuildCmd = getenv("BUILD_POST_PROCESS");
  477. SystemIncludeEnv = getenv( "INCLUDE" );
  478. GetCurrentDirectory( sizeof( CurrentDirectory ), CurrentDirectory );
  479. for (i = 0; i < MAX_TARGET_MACHINES; i++) {
  480. TargetMachines[i] = NULL;
  481. TargetToPossibleTarget[i] = 0;
  482. MungePossibleTarget(PossibleTargetMachines[i]);
  483. }
  484. // prepare the command line in the XML buffer in case we need it
  485. strcpy(szXMLBuffer, "CMDLINE=\"");
  486. XMLEncodeBuiltInEntitiesCopy(GetCommandLine(), szXMLBuffer + strlen(szXMLBuffer));
  487. strcat(szXMLBuffer, "\"");
  488. if (!(BuildProduct = getenv("BUILD_PRODUCT"))) {
  489. BuildProduct = "";
  490. }
  491. if (!ProcessParameters( argc, argv, TRUE )) {
  492. fUsage = TRUE;
  493. } else {
  494. int CurrentEnvArgc = EnvArgc;
  495. fCmdLineDependencySwitchUsed = fDependencySwitchUsed;
  496. fCmdLineQuicky = fQuicky;
  497. fCmdLineSemiQuicky = fSemiQuicky;
  498. fCmdLineQuickZero = fQuickZero;
  499. GetEnvParameters( "BUILD_DEFAULT", NULL, &EnvArgc, MAX_ENV_ARG, EnvArgv );
  500. if (CurrentEnvArgc != EnvArgc) {
  501. strcat(szXMLBuffer, " BUILD_DEFAULT=\"");
  502. while (CurrentEnvArgc < EnvArgc) {
  503. XMLEncodeBuiltInEntitiesCopy(EnvArgv[CurrentEnvArgc], szXMLBuffer + strlen(szXMLBuffer));
  504. strcat(szXMLBuffer, " ");
  505. CurrentEnvArgc++;
  506. }
  507. strcat(szXMLBuffer, "\"");
  508. }
  509. CurrentEnvArgc = EnvArgc;
  510. GetEnvParameters( "BUILD_OPTIONS", NULL, &EnvArgc, MAX_ENV_ARG, EnvArgv );
  511. if (CurrentEnvArgc != EnvArgc) {
  512. strcat(szXMLBuffer, " BUILD_OPTIONS=\"");
  513. while (CurrentEnvArgc < EnvArgc) {
  514. XMLEncodeBuiltInEntitiesCopy(EnvArgv[CurrentEnvArgc], szXMLBuffer + strlen(szXMLBuffer));
  515. strcat(szXMLBuffer, " ");
  516. CurrentEnvArgc++;
  517. }
  518. strcat(szXMLBuffer, "\"");
  519. }
  520. if (CountTargetMachines == 0) {
  521. if ( getenv("PROCESSOR_ARCHITECTURE") == NULL ) {
  522. BuildError("environment variable PROCESSOR_ARCHITECTURE must be defined\r\n");
  523. exit(1);
  524. }
  525. CurrentEnvArgc = EnvArgc;
  526. if (!strcmp(getenv("PROCESSOR_ARCHITECTURE"), "IA64"))
  527. GetEnvParameters( "BUILD_DEFAULT_TARGETS", "-ia64", &EnvArgc, MAX_ENV_ARG, EnvArgv );
  528. else
  529. if (!strcmp(getenv("PROCESSOR_ARCHITECTURE"), "AMD64"))
  530. GetEnvParameters( "BUILD_DEFAULT_TARGETS", "-amd64", &EnvArgc, MAX_ENV_ARG, EnvArgv );
  531. else
  532. if (!strcmp(getenv("PROCESSOR_ARCHITECTURE"), "ARM"))
  533. GetEnvParameters( "BUILD_DEFAULT_TARGETS", "-arm", &EnvArgc, MAX_ENV_ARG, EnvArgv );
  534. else
  535. GetEnvParameters( "BUILD_DEFAULT_TARGETS", "-386", &EnvArgc, MAX_ENV_ARG, EnvArgv );
  536. if (CurrentEnvArgc != EnvArgc) {
  537. strcat(szXMLBuffer, " BUILD_DEFAULT_TARGETS=\"");
  538. while (CurrentEnvArgc < EnvArgc) {
  539. XMLEncodeBuiltInEntitiesCopy(EnvArgv[CurrentEnvArgc], szXMLBuffer + strlen(szXMLBuffer));
  540. strcat(szXMLBuffer, " ");
  541. CurrentEnvArgc++;
  542. }
  543. strcat(szXMLBuffer, "\"");
  544. }
  545. }
  546. if (!ProcessParameters( EnvArgc, EnvArgv, FALSE )) {
  547. fUsage = TRUE;
  548. }
  549. }
  550. FreeEnvParameters(EnvArgc, EnvArgv);
  551. if (!fUsage && !fGenerateObjectsDotMacOnly) {
  552. if (!_stricmp(BuildProduct, "NT")) {
  553. if (fCmdLineDependencySwitchUsed) {
  554. fDependencySwitchUsed = fCmdLineDependencySwitchUsed;
  555. fQuicky = fCmdLineQuicky;
  556. fSemiQuicky = fCmdLineSemiQuicky;
  557. fQuickZero = fCmdLineQuickZero;
  558. }
  559. if (!fDependencySwitchUsed) {
  560. BuildError("(Fatal Error) One of either /D, /Z, /z, or /3 is required for NT builds\r\n");
  561. exit( 1 );
  562. } else {
  563. if (fDependencySwitchUsed == 1) {
  564. if (fQuicky) {
  565. BuildError("(Fatal Error) switch can not be used with /Z, /z, or /3\r\n");
  566. exit( 1 );
  567. }
  568. }
  569. if (fDependencySwitchUsed == 2) {
  570. if (fStopAfterPassZero) {
  571. BuildError("(Fatal Error) switch /0 can not be used with /z\r\n");
  572. exit( 1 );
  573. }
  574. }
  575. }
  576. }
  577. }
  578. GetIncludePatterns( "BUILD_ACCEPTABLE_INCLUDES", MAX_INCLUDE_PATTERNS, AcceptableIncludePatternList );
  579. GetIncludePatterns( "BUILD_UNACCEPTABLE_INCLUDES", MAX_INCLUDE_PATTERNS, UnacceptableIncludePatternList );
  580. if (( fCheckIncludePaths ) &&
  581. ( AcceptableIncludePatternList[ 0 ] == NULL ) &&
  582. ( UnacceptableIncludePatternList[ 0 ] == NULL )) {
  583. BuildMsgRaw( "WARNING: -# specified without BUILD_[UN]ACCEPTABLE_INCLUDES set\r\n" );
  584. }
  585. if (fCleanRestart) {
  586. if (fClean) {
  587. fClean = FALSE;
  588. fRestartClean = TRUE;
  589. } else
  590. if (fCleanLibs) {
  591. fCleanLibs = FALSE;
  592. fRestartCleanLibs = TRUE;
  593. } else {
  594. BuildError("/R switch only valid with /c or /C switch.\r\n");
  595. fUsage = TRUE;
  596. }
  597. }
  598. NumberProcesses = 1;
  599. if (fParallel || getenv("BUILD_MULTIPROCESSOR")) {
  600. SYSTEM_INFO SystemInfo;
  601. if (DefaultProcesses == 0) {
  602. GetSystemInfo(&SystemInfo);
  603. NumberProcesses = SystemInfo.dwNumberOfProcessors;
  604. } else {
  605. NumberProcesses = DefaultProcesses;
  606. }
  607. if (NumberProcesses == 1) {
  608. fParallel = FALSE;
  609. } else {
  610. if (NumberProcesses > 64) {
  611. BuildError("(Fatal Error) Number of Processes: %d exceeds max (64)\r\n", NumberProcesses);
  612. exit(1);
  613. }
  614. fParallel = TRUE;
  615. BuildMsg("Using %d child processes\r\n", NumberProcesses);
  616. }
  617. }
  618. XMLStartTicks = GetTickCount();
  619. time(&ltime);
  620. if (fPrintElapsed) {
  621. BuildColorMsg(COLOR_STATUS, "Start time: %s", ctime(&ltime));
  622. }
  623. if (fBuildAltDirSet) {
  624. BuildColorMsg(COLOR_STATUS, "Object root set to: ==> %s\r\n", szObjDir);
  625. }
  626. if (fUsage) {
  627. BuildMsgRaw(
  628. "\r\nBUILD: Version %x.%02x.%04d\r\n\r\n",
  629. BUILD_VERSION >> 8,
  630. BUILD_VERSION & 0xFF,
  631. VER_PRODUCTBUILD);
  632. BuildMsgRaw(szUsage);
  633. } else
  634. if (CountTargetMachines != 0) {
  635. BuildColorError(COLOR_STATUS,
  636. "%s for ",
  637. fLinkOnly? "Link" : (fCompileOnly? "Compile" : "Compile and Link"));
  638. for (i = 0; i < CountTargetMachines; i++) {
  639. BuildColorErrorRaw(COLOR_STATUS, i==0? "%s" : ", %s", TargetMachines[i]->Description);
  640. AppendString(
  641. MakeTargets,
  642. TargetMachines[i]->MakeVariable,
  643. TRUE);
  644. }
  645. BuildErrorRaw(szNewLine);
  646. //
  647. // If there is one and only one build target and target dirs has
  648. // been enabled, then fill in the appropriate target dirs name.
  649. //
  650. if (CountTargetMachines == 1) {
  651. if (fTargetDirs == TRUE) {
  652. pszTargetDirs = TargetMachines[0]->TargetDirs;
  653. FileDesc[0].pszPattern = TargetMachines[0]->TargetDirs;
  654. }
  655. }
  656. if (DEBUG_1) {
  657. if (CountExcludeIncs) {
  658. BuildError("Include files that will be excluded:");
  659. for (i = 0; i < CountExcludeIncs; i++) {
  660. BuildErrorRaw(i == 0? " %s" : ", %s", ExcludeIncs[i]);
  661. }
  662. BuildErrorRaw(szNewLine);
  663. }
  664. if (CountOptionalDirs) {
  665. BuildError("Optional Directories that will be built:");
  666. for (i = 0; i < CountOptionalDirs; i++) {
  667. BuildErrorRaw(i == 0? " %s" : ", %s", OptionalDirs[i]);
  668. }
  669. BuildErrorRaw(szNewLine);
  670. }
  671. if (CountExcludeDirs) {
  672. BuildError("Directories that will be NOT be built:");
  673. for (i = 0; i < CountExcludeDirs; i++) {
  674. BuildErrorRaw(i == 0? " %s" : ", %s", ExcludeDirs[i]);
  675. }
  676. BuildErrorRaw(szNewLine);
  677. }
  678. BuildMsg("MakeParameters == %s\r\n", MakeParameters);
  679. BuildMsg("MakeTargets == %s\r\n", MakeTargets);
  680. }
  681. #if DBG
  682. fDebugSave = fDebug;
  683. // fDebug = 0;
  684. #endif
  685. //
  686. // Generate the _objects.mac file if requested
  687. //
  688. if (fGenerateObjectsDotMacOnly) {
  689. DIRSUP DirSup;
  690. ULONG DateTimeSources;
  691. DirDB = ScanDirectory( CurrentDirectory );
  692. if (DirDB && (DirDB->DirFlags & (DIRDB_DIRS | DIRDB_SOURCES))) {
  693. FreeBaselineFile();
  694. if (!ReadSourcesFile(DirDB, &DirSup, &DateTimeSources)) {
  695. BuildError("Current directory not a SOURCES directory.\r\n");
  696. return ( 1 );
  697. }
  698. GenerateObjectsDotMac(DirDB, &DirSup, DateTimeSources);
  699. FreeDirSupData(&DirSup);
  700. ReportDirsUsage();
  701. FreeCmdStrings();
  702. ReportMemoryUsage();
  703. return (0);
  704. }
  705. }
  706. if (!fQuery && fErrorLog) {
  707. strcat(LogFileName, ".log");
  708. if (!MyOpenFile(LogDirectory, LogFileName, "wb", &LogFile, TRUE)) {
  709. BuildError("(Fatal Error) Unable to open log file\r\n");
  710. exit( 1 );
  711. }
  712. CreatedBuildFile(LogDirectory, LogFileName);
  713. strcat(WrnFileName, ".wrn");
  714. if (!MyOpenFile(LogDirectory, WrnFileName, "wb", &WrnFile, FALSE)) {
  715. BuildError("(Fatal Error) Unable to open warning file\r\n");
  716. exit( 1 );
  717. }
  718. CreatedBuildFile(LogDirectory, WrnFileName);
  719. strcat(ErrFileName, ".err");
  720. if (!MyOpenFile(LogDirectory, ErrFileName, "wb", &ErrFile, FALSE)) {
  721. BuildError("(Fatal Error) Unable to open error file\r\n");
  722. exit( 1 );
  723. }
  724. CreatedBuildFile(LogDirectory, ErrFileName);
  725. if ( fCheckIncludePaths ) {
  726. strcat( IncFileName, ".inc");
  727. if (!MyOpenFile( LogDirectory, IncFileName, "wb", &IncFile, FALSE ) ) {
  728. BuildError( "(Fatal Error) Unable to open include log file\r\n");
  729. exit( 1 );
  730. }
  731. CreatedBuildFile( LogDirectory, IncFileName );
  732. }
  733. } else {
  734. LogFile = NULL;
  735. WrnFile = NULL;
  736. ErrFile = NULL;
  737. IncFile = NULL;
  738. }
  739. // in case of query only we are not going to produce XML file
  740. if (fQuery) {
  741. fXMLOutput = FALSE;
  742. }
  743. // set the XML output file
  744. if (fXMLOutput) {
  745. strcat(XMLFileName, ".xml");
  746. if (!MyOpenFile(".", XMLFileName, "wb", &XMLFile, FALSE)) {
  747. BuildError("(Fatal Error) Unable to open XML file\r\n");
  748. exit( 1 );
  749. }
  750. CreatedBuildFile(".", XMLFileName);
  751. } else {
  752. XMLFile = NULL;
  753. }
  754. if (!XMLInit()) {
  755. exit( 1 );
  756. }
  757. sprintf(szXMLBuffer + strlen(szXMLBuffer), " TIME=\"%s\" CURRENTDIR=\"%s\"", ctime(&ltime), CurrentDirectory);
  758. if (fXMLOutput || fXMLFragment) {
  759. XMLGlobalWrite("<?xml version=\"1.0\"?>");
  760. XMLGlobalOpenTag("BUILD", "xmlns=\"x-schema:buildschema.xml\"");
  761. XMLGlobalWrite("<START %s/>", szXMLBuffer);
  762. XMLUpdateEndTag(FALSE);
  763. if (fXMLFragment) {
  764. XMLWriteFragmentFile("START", "<BUILD %s/>", szXMLBuffer);
  765. }
  766. }
  767. s = getenv("__MTSCRIPT_ENV_ID");
  768. if (s) {
  769. if (fDependencySwitchUsed == 2 && fPause) {
  770. BuildError("Cannot combine -z (or -2) and -p switches under MTScript");
  771. exit(1);
  772. }
  773. // Make sure any other build.exe's that get launched as child
  774. // processes don't try to connect to the script engine.
  775. SetEnvironmentVariable("__MTSCRIPT_ENV_ID", NULL);
  776. g_hMTEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
  777. if (g_hMTEvent != NULL) {
  778. g_hMTThread = CreateThread(NULL,
  779. 0,
  780. (LPTHREAD_START_ROUTINE)MTScriptThread,
  781. NULL,
  782. 0,
  783. &g_dwMTThreadId);
  784. if (g_hMTThread) {
  785. // Wait for the thread to tell us it's ready.
  786. WaitForSingleObject(g_hMTEvent, INFINITE);
  787. ResetEvent(g_hMTEvent);
  788. if (!g_hMTThread) {
  789. // An error occurred connecting to the script engine.
  790. // We can't continue.
  791. BuildError("Unable to connect to script engine. Exiting.");
  792. exit(2);
  793. }
  794. fMTScriptSync = TRUE;
  795. } else {
  796. BuildError("Failed to launch script handling thread! (%d)", GetLastError());
  797. CloseHandle(g_hMTEvent);
  798. g_hMTEvent = NULL;
  799. fPause = FALSE;
  800. }
  801. } else {
  802. BuildError("Failed to create script communication event! (%d)", GetLastError());
  803. fPause = FALSE;
  804. }
  805. }
  806. //
  807. // The user should not have CHICAGO_PRODUCT in
  808. // their environment, as it can cause problems on other machines with
  809. // other users that don't have them set. The following warning
  810. // messages are intended to alert the user to the presence of these
  811. // environment variables.
  812. //
  813. if (getenv("CHICAGO_PRODUCT") != NULL) {
  814. BuildError("CHICAGO_PRODUCT was detected in the environment.\r\n" );
  815. BuildMsg(" ALL directories will be built targeting Chicago!\r\n" );
  816. fChicagoProduct = TRUE;
  817. }
  818. if (!fQuicky) {
  819. LoadMasterDB();
  820. BuildError("Computing Include file dependencies:\r\n");
  821. ScanIncludeEnv(SystemIncludeEnv);
  822. ScanGlobalIncludeDirectory(pszIncMfc);
  823. ScanGlobalIncludeDirectory(pszIncOak);
  824. ScanGlobalIncludeDirectory(pszIncDdk);
  825. ScanGlobalIncludeDirectory(pszIncWdm);
  826. ScanGlobalIncludeDirectory(pszIncSdk);
  827. ScanGlobalIncludeDirectory(pszIncPri);
  828. CountSystemIncludeDirs = CountIncludeDirs;
  829. }
  830. #if DBG
  831. fDebug = fDebugSave;
  832. #endif
  833. fFirstScan = TRUE;
  834. fPassZero = FALSE;
  835. ScanSourceDirectories( CurrentDirectory );
  836. if (!fQuicky) {
  837. if (SaveMasterDB() == FALSE) {
  838. BuildError("Unable to save the dependency database: %s\r\n", DbMasterName);
  839. }
  840. }
  841. c = '\n';
  842. if ( !fLinkOnly && CountPassZeroDirs && !bBaselineFailure) {
  843. if (!fQuicky) {
  844. TotalFilesToCompile = 0;
  845. TotalLinesToCompile = 0L;
  846. for (i=0; i<CountPassZeroDirs; i++) {
  847. DirDB = PassZeroDirs[ i ];
  848. TotalFilesToCompile += DirDB->CountOfPassZeroFiles;
  849. TotalLinesToCompile += DirDB->PassZeroLines;
  850. }
  851. if (CountPassZeroDirs > 1 &&
  852. TotalFilesToCompile != 0 &&
  853. TotalLinesToCompile != 0L) {
  854. BuildMsgRaw(
  855. "Total of %d pass zero files (%s lines) to compile in %d directories\r\n\r\n",
  856. TotalFilesToCompile,
  857. FormatNumber( TotalLinesToCompile ),
  858. CountPassZeroDirs);
  859. }
  860. }
  861. TotalFilesCompiled = 0;
  862. TotalLinesCompiled = 0L;
  863. ElapsedCompileTime = 0L;
  864. if (fPause && !fMTScriptSync) {
  865. BuildMsg("Press enter to continue with compilations (or 'q' to quit)...");
  866. c = (char)getchar();
  867. }
  868. if ((CountPassZeroDirs > 0) && (c == '\n') && !bBaselineFailure) {
  869. DWORD dwStartTime = GetTickCount();
  870. if (fXMLOutput || fXMLFragment) {
  871. XMLGlobalOpenTag("PASS", "NUMBER=\"0\"");
  872. if (fXMLFragment) {
  873. Sleep(1);
  874. XMLWriteFragmentFile("PASS0", "<PASS NUMBER=\"0\"/>");
  875. Sleep(1);
  876. }
  877. }
  878. memset(&PassMetrics, 0, sizeof(PassMetrics));
  879. CompilePassZeroDirectories();
  880. WaitForParallelThreads(NULL);
  881. AddBuildMetrics(&BuildMetrics, &PassMetrics);
  882. if (fXMLOutput || fXMLFragment) {
  883. sprintf(szXMLBuffer, "DIRS=\"%d\" ELAPSED=\"%s\" ", CountPassZeroDirs, FormatElapsedTime(dwStartTime));
  884. strcat(szXMLBuffer, XMLBuildMetricsString(&PassMetrics));
  885. NumberPasses++;
  886. XMLGlobalWrite("<PASSSUMMARY %s/>", szXMLBuffer);
  887. XMLGlobalCloseTag();
  888. XMLUpdateEndTag(FALSE);
  889. if (fXMLFragment) {
  890. Sleep(1);
  891. XMLWriteFragmentFile("PASS0SUMMARY", "<PASSSUMMARY %s/>", szXMLBuffer);
  892. Sleep(1);
  893. }
  894. }
  895. //
  896. // Rescan now that we've generated all the generated files
  897. //
  898. CountPassZeroDirs = 0;
  899. CountCompileDirs = 0;
  900. CountLinkDirs = 0;
  901. UnsnapAllDirectories();
  902. // This will reset all the producer events which were signalled in Pass0 Phase
  903. ResetProducerEvents();
  904. fPassZero = FALSE;
  905. fFirstScan = FALSE;
  906. RecurseLevel = 0;
  907. if (fMTScriptSync) {
  908. WaitForResume(fPause, PE_PASS0_COMPLETE);
  909. fPauseDone = TRUE;
  910. }
  911. // This will compile directories if fQuicky is TRUE
  912. if (!fStopAfterPassZero) {
  913. ScanSourceDirectories( CurrentDirectory );
  914. }
  915. if (!fQuicky) {
  916. if (SaveMasterDB() == FALSE) {
  917. BuildError("Unable to save the dependency database: %s\r\n", DbMasterName);
  918. }
  919. }
  920. }
  921. }
  922. if (fMTScriptSync && !fPauseDone) {
  923. WaitForResume(fPause, PE_PASS0_COMPLETE);
  924. }
  925. if (fStopAfterPassZero) {
  926. BuildError("Stopping after pass zero requested: Pass0 done.\r\n");
  927. }
  928. if (!fStopAfterPassZero && !fLinkOnly && (c == '\n') && !bBaselineFailure) {
  929. if (!fQuicky) {
  930. TotalFilesToCompile = 0;
  931. TotalLinesToCompile = 0L;
  932. for (i=0; i<CountCompileDirs; i++) {
  933. DirDB = CompileDirs[ i ];
  934. TotalFilesToCompile += DirDB->CountOfFilesToCompile;
  935. TotalLinesToCompile += DirDB->SourceLinesToCompile;
  936. }
  937. if (CountCompileDirs > 1 &&
  938. TotalFilesToCompile != 0 &&
  939. TotalLinesToCompile != 0L) {
  940. BuildMsgRaw(
  941. "Total of %d source files (%s lines) to compile in %d directories\r\n\r\n",
  942. TotalFilesToCompile,
  943. FormatNumber( TotalLinesToCompile ),
  944. CountCompileDirs);
  945. }
  946. }
  947. TotalFilesCompiled = 0;
  948. TotalLinesCompiled = 0L;
  949. ElapsedCompileTime = 0L;
  950. if (fPause && !fMTScriptSync) {
  951. BuildMsg("Press enter to continue with compilations (or 'q' to quit)...");
  952. c = (char)getchar();
  953. }
  954. if (c == '\n' && !bBaselineFailure) {
  955. DWORD dwStartTime = GetTickCount();
  956. if (fXMLOutput || fXMLFragment) {
  957. XMLGlobalOpenTag("PASS", "NUMBER=\"1\"");
  958. if (fXMLFragment) {
  959. Sleep(1);
  960. XMLWriteFragmentFile("PASS1", "<PASS NUMBER=\"1\"/>");
  961. Sleep(1);
  962. }
  963. }
  964. memset(&PassMetrics, 0, sizeof(PassMetrics));
  965. // Does nothing if fQuicky is TRUE
  966. CompileSourceDirectories();
  967. WaitForParallelThreads(NULL);
  968. AddBuildMetrics(&BuildMetrics, &PassMetrics);
  969. if (fXMLOutput || fXMLFragment) {
  970. sprintf(szXMLBuffer, "DIRS=\"%d\" ELAPSED=\"%s\" ", CountCompileDirs, FormatElapsedTime(dwStartTime));
  971. strcat(szXMLBuffer, XMLBuildMetricsString(&PassMetrics));
  972. NumberPasses++;
  973. XMLGlobalWrite("<PASSSUMMARY %s/>", szXMLBuffer);
  974. XMLGlobalCloseTag();
  975. XMLUpdateEndTag(FALSE);
  976. if (fXMLFragment) {
  977. Sleep(1);
  978. XMLWriteFragmentFile("PASS1SUMMARY", "<PASSSUMMARY %s/>", szXMLBuffer);
  979. Sleep(1);
  980. }
  981. }
  982. }
  983. }
  984. if (fMTScriptSync) {
  985. WaitForResume(fPause, PE_PASS1_COMPLETE);
  986. }
  987. if (!fStopAfterPassZero && !fCompileOnly && (c == '\n') && !bBaselineFailure) {
  988. DWORD dwStartTime = GetTickCount();
  989. if (fXMLOutput || fXMLFragment) {
  990. XMLGlobalOpenTag("PASS", "NUMBER=\"2\"");
  991. if (fXMLFragment) {
  992. Sleep(1);
  993. XMLWriteFragmentFile("PASS2", "<PASS NUMBER=\"2\"/>");
  994. Sleep(1);
  995. }
  996. }
  997. memset(&PassMetrics, 0, sizeof(PassMetrics));
  998. LinkSourceDirectories();
  999. WaitForParallelThreads(NULL);
  1000. AddBuildMetrics(&BuildMetrics, &PassMetrics);
  1001. if (fXMLOutput || fXMLFragment) {
  1002. sprintf(szXMLBuffer, "DIRS=\"%d\" ELAPSED=\"%s\" ", CountLinkDirs, FormatElapsedTime(dwStartTime));
  1003. strcat(szXMLBuffer, XMLBuildMetricsString(&PassMetrics));
  1004. NumberPasses++;
  1005. XMLGlobalWrite("<PASSSUMMARY %s/>", szXMLBuffer);
  1006. XMLGlobalCloseTag();
  1007. XMLUpdateEndTag(FALSE);
  1008. if (fXMLFragment) {
  1009. Sleep(1);
  1010. XMLWriteFragmentFile("PASS2SUMMARY", "<PASSSUMMARY %s/>", szXMLBuffer);
  1011. Sleep(1);
  1012. }
  1013. }
  1014. }
  1015. if (!fStopAfterPassZero && PostBuildCmd && !fMTScriptSync) {
  1016. // If there's a post build process to invoke, do so but only if
  1017. // not running under the buildcon.
  1018. // PostBuildCmd is of the form <message to display><command to execute>
  1019. // The Message is delimiated with curly brackets. ie:
  1020. // POST_BUILD_PROCESS={Do randomness}randomness.cmd
  1021. // would display:
  1022. //
  1023. // BUILD: Do randomness
  1024. //
  1025. // while randomness.cmd was running. The process is run synchronously and
  1026. // we've still got the i/o pipes setup so any output will be logged to
  1027. // build.log (and wrn/err if formated correctly)
  1028. if (*PostBuildCmd == '{') {
  1029. LPSTR PostBuildMessage = PostBuildCmd+1;
  1030. LogMsg("Executing post build scripts %s\r\n", szAsterisks);
  1031. while (*PostBuildCmd && *PostBuildCmd != '}')
  1032. PostBuildCmd++;
  1033. if (*PostBuildCmd == '}') {
  1034. *PostBuildCmd = '\0';
  1035. PostBuildCmd++;
  1036. BuildMsg("%s\r\n", PostBuildMessage);
  1037. LogMsg("%s\r\n", PostBuildMessage);
  1038. ExecuteProgram(PostBuildCmd, "", "", TRUE, CurrentDirectory, "Executing Postbuild Step");
  1039. }
  1040. } else {
  1041. ExecuteProgram(PostBuildCmd, "", "", TRUE, CurrentDirectory, "Executing Postbuild Step");
  1042. }
  1043. }
  1044. if (fShowTree) {
  1045. for (i = 0; i < CountShowDirs; i++) {
  1046. PrintDirDB(ShowDirs[i], 1|4);
  1047. }
  1048. }
  1049. } else {
  1050. BuildError("No target machine specified\r\n");
  1051. }
  1052. // moved the end time before the log files are closed so we can put it into the XML file
  1053. time(&ltime);
  1054. if (fXMLOutput || fXMLFragment) {
  1055. XMLUpdateEndTag(TRUE);
  1056. XMLGlobalCloseTag(); // BUILD
  1057. if (fXMLFragment) {
  1058. sprintf(szXMLBuffer, "TIME=\"%s\" ELAPSED=\"%s\" PASSES=\"%d\" COMPLETED=\"1\" ", ctime(&ltime), FormatElapsedTime(XMLStartTicks), NumberPasses);
  1059. strcat(szXMLBuffer, XMLBuildMetricsString(&BuildMetrics));
  1060. XMLWriteFragmentFile("END", "<END %s/>", szXMLBuffer);
  1061. }
  1062. }
  1063. if (!fUsage && !fQuery && fErrorLog) {
  1064. ULONG cbLogMin = 32;
  1065. ULONG cbWarnMin = 0;
  1066. if (!fAlwaysKeepLogfile) {
  1067. if (fQuicky && !fSemiQuicky && ftell(ErrFile) == 0) {
  1068. cbLogMin = cbWarnMin = ULONG_MAX;
  1069. }
  1070. }
  1071. CloseOrDeleteFile(&LogFile, LogDirectory, LogFileName, cbLogMin);
  1072. CloseOrDeleteFile(&WrnFile, LogDirectory, WrnFileName, cbWarnMin);
  1073. CloseOrDeleteFile(&ErrFile, LogDirectory, ErrFileName, 0L);
  1074. if ( fCheckIncludePaths ) {
  1075. CloseOrDeleteFile(&IncFile, LogDirectory, IncFileName, cbLogMin);
  1076. }
  1077. CloseOrDeleteFile(&XMLFile, LogDirectory, XMLFileName, 0L);
  1078. }
  1079. if (bBaselineFailure) {
  1080. BuildError(BaselinePathName[0] != '\0' ?
  1081. "Diffs from baseline\r\n" :
  1082. "Terminated at the first error encountered\r\n");
  1083. }
  1084. if (fPrintElapsed) {
  1085. BuildColorMsg(COLOR_STATUS, "Finish time: %s", ctime(&ltime));
  1086. }
  1087. BuildColorError(COLOR_STATUS, "Done\r\n\r\n");
  1088. if (fMTScriptSync) {
  1089. WaitForResume(FALSE, PE_PASS2_COMPLETE);
  1090. }
  1091. if (RunningTotals.NumberCompiles) {
  1092. BuildColorMsgRaw(COLOR_SUMMARY, " %d file%s compiled", RunningTotals.NumberCompiles, RunningTotals.NumberCompiles == 1 ? "" : "s");
  1093. if (RunningTotals.NumberCompileWarnings) {
  1094. BuildColorMsgRaw(COLOR_WARNING, " - %d Warning%s", RunningTotals.NumberCompileWarnings, RunningTotals.NumberCompileWarnings == 1 ? "" : "s");
  1095. }
  1096. if (RunningTotals.NumberCompileErrors) {
  1097. BuildColorMsgRaw(COLOR_ERROR, " - %d Error%s", RunningTotals.NumberCompileErrors, RunningTotals.NumberCompileErrors == 1 ? "" : "s");
  1098. }
  1099. if (ElapsedCompileTime) {
  1100. BuildColorMsgRaw(COLOR_SUMMARY, " - %5ld LPS", TotalLinesCompiled / ElapsedCompileTime);
  1101. }
  1102. BuildMsgRaw(szNewLine);
  1103. }
  1104. if (RunningTotals.NumberLibraries) {
  1105. BuildColorMsgRaw(COLOR_SUMMARY, " %d librar%s built", RunningTotals.NumberLibraries, RunningTotals.NumberLibraries == 1 ? "y" : "ies");
  1106. if (RunningTotals.NumberLibraryWarnings) {
  1107. BuildColorMsgRaw(COLOR_WARNING, " - %d Warning%s", RunningTotals.NumberLibraryWarnings, RunningTotals.NumberLibraryWarnings == 1 ? "" : "s");
  1108. }
  1109. if (RunningTotals.NumberLibraryErrors) {
  1110. BuildColorMsgRaw(COLOR_ERROR, " - %d Error%s", RunningTotals.NumberLibraryErrors, RunningTotals.NumberLibraryErrors == 1 ? "" : "s");
  1111. }
  1112. BuildMsgRaw(szNewLine);
  1113. }
  1114. if (RunningTotals.NumberLinks) {
  1115. BuildColorMsgRaw(COLOR_SUMMARY, " %d executable%sbuilt", RunningTotals.NumberLinks, RunningTotals.NumberLinks == 1 ? " " : "s ");
  1116. if (RunningTotals.NumberLinkWarnings) {
  1117. BuildColorMsgRaw(COLOR_WARNING, " - %d Warning%s", RunningTotals.NumberLinkWarnings, RunningTotals.NumberLinkWarnings == 1 ? "" : "s");
  1118. }
  1119. if (RunningTotals.NumberLinkErrors) {
  1120. BuildColorMsgRaw(COLOR_ERROR, " - %d Error%s", RunningTotals.NumberLinkErrors, RunningTotals.NumberLinkErrors == 1 ? "" : "s");
  1121. }
  1122. BuildMsgRaw(szNewLine);
  1123. }
  1124. if (RunningTotals.NumberBSCMakes) {
  1125. BuildColorMsgRaw(COLOR_SUMMARY, " %d browse database%s built", RunningTotals.NumberBSCMakes, RunningTotals.NumberBSCMakes == 1 ? "" : "s");
  1126. if (RunningTotals.NumberBSCWarnings) {
  1127. BuildColorMsgRaw(COLOR_WARNING, " - %d Warning%s", RunningTotals.NumberBSCWarnings, RunningTotals.NumberBSCWarnings == 1 ? "" : "s");
  1128. }
  1129. if (RunningTotals.NumberBSCErrors) {
  1130. BuildColorMsgRaw(COLOR_ERROR, " - %d Error%s", RunningTotals.NumberBSCErrors, RunningTotals.NumberBSCErrors == 1 ? "" : "s");
  1131. }
  1132. BuildMsgRaw(szNewLine);
  1133. }
  1134. if (RunningTotals.NumberVSToolErrors + RunningTotals.NumberVSToolWarnings > 0) {
  1135. if (RunningTotals.NumberVSToolWarnings) {
  1136. BuildColorMsgRaw(COLOR_WARNING, " %d VS Tool Warnings\r\n", RunningTotals.NumberVSToolWarnings);
  1137. }
  1138. if (RunningTotals.NumberVSToolErrors) {
  1139. BuildColorMsgRaw(COLOR_ERROR, " %d VS Tool Errors\r\n", RunningTotals.NumberVSToolErrors);
  1140. }
  1141. }
  1142. if (RunningTotals.NumberBinplaces) {
  1143. BuildColorMsgRaw(COLOR_SUMMARY, " %d file%sbinplaced", RunningTotals.NumberBinplaces, RunningTotals.NumberBinplaces == 1 ? " " : "s ");
  1144. if (RunningTotals.NumberBinplaceWarnings) {
  1145. BuildColorMsgRaw(COLOR_WARNING, " - %d Warning%s", RunningTotals.NumberBinplaceWarnings, RunningTotals.NumberBinplaceWarnings == 1 ? "" : "s");
  1146. }
  1147. if (RunningTotals.NumberBinplaceErrors) {
  1148. BuildColorMsgRaw(COLOR_ERROR, " - %d Error%s", RunningTotals.NumberBinplaceErrors, RunningTotals.NumberBinplaceErrors == 1 ? "" : "s");
  1149. }
  1150. BuildMsgRaw(szNewLine);
  1151. }
  1152. ReportDirsUsage();
  1153. XMLUnInit();
  1154. FreeBaselineFile();
  1155. FreeCmdStrings();
  1156. FreeIncludePatterns( MAX_INCLUDE_PATTERNS, AcceptableIncludePatternList );
  1157. FreeIncludePatterns( MAX_INCLUDE_PATTERNS, UnacceptableIncludePatternList );
  1158. ReportMemoryUsage();
  1159. ExitMTScriptThread();
  1160. if (bBaselineFailure)
  1161. return 2;
  1162. if (RunningTotals.NumberCompileErrors ||
  1163. RunningTotals.NumberLibraryErrors ||
  1164. RunningTotals.NumberLinkErrors ||
  1165. RunningTotals.NumberBinplaceErrors ||
  1166. RunningTotals.NumberVSToolErrors ||
  1167. fUsage) {
  1168. return 1;
  1169. } else {
  1170. return ( 0 );
  1171. }
  1172. }
  1173. VOID
  1174. ReportDirsUsage( VOID )
  1175. {
  1176. ULONG i;
  1177. BOOLEAN fHeaderPrinted;
  1178. if (!fShowUnusedDirs) {
  1179. return;
  1180. }
  1181. fHeaderPrinted = FALSE;
  1182. for (i=0; i<CountOptionalDirs; i++) {
  1183. if (!OptionalDirsUsed[i]) {
  1184. if (!fHeaderPrinted) {
  1185. printf( "Unused BUILD_OPTIONS:" );
  1186. fHeaderPrinted = TRUE;
  1187. }
  1188. printf( " %s", OptionalDirs[i] );
  1189. }
  1190. }
  1191. for (i=0; i<CountExcludeDirs; i++) {
  1192. if (!ExcludeDirsUsed[i]) {
  1193. if (!fHeaderPrinted) {
  1194. printf( "Unused BUILD_OPTIONS:" );
  1195. fHeaderPrinted = TRUE;
  1196. }
  1197. printf( " ~%s", ExcludeDirs[i] );
  1198. }
  1199. }
  1200. if (fHeaderPrinted) {
  1201. printf( "\n" );
  1202. }
  1203. }
  1204. //+---------------------------------------------------------------------------
  1205. //
  1206. // Function: SetObjDir
  1207. //
  1208. //----------------------------------------------------------------------------
  1209. VOID
  1210. SetObjDir(BOOL fAlternate)
  1211. {
  1212. iObjectDir = 0;
  1213. if (fCheckedBuild) {
  1214. if (fAlternate) {
  1215. pszObjDir = szObjDirD;
  1216. pszObjDirSlash = szObjDirSlashD;
  1217. pszObjDirSlashStar = szObjDirSlashStarD;
  1218. iObjectDir = 1;
  1219. } else {
  1220. pszObjDir = szObjDir;
  1221. pszObjDirSlash = szObjDirSlash;
  1222. pszObjDirSlashStar = szObjDirSlashStar;
  1223. }
  1224. }
  1225. }
  1226. //+---------------------------------------------------------------------------
  1227. //
  1228. // Function: AddTargetMachine
  1229. //
  1230. //----------------------------------------------------------------------------
  1231. VOID
  1232. AddTargetMachine(UINT iTarget)
  1233. {
  1234. UINT i;
  1235. for (i = 0; i < CountTargetMachines; i++) {
  1236. if (TargetMachines[i] == PossibleTargetMachines[iTarget]) {
  1237. assert(TargetToPossibleTarget[i] == iTarget);
  1238. return;
  1239. }
  1240. }
  1241. assert(CountTargetMachines < MAX_TARGET_MACHINES);
  1242. TargetToPossibleTarget[CountTargetMachines] = iTarget;
  1243. TargetMachines[CountTargetMachines++] = PossibleTargetMachines[iTarget];
  1244. }
  1245. //+---------------------------------------------------------------------------
  1246. //
  1247. // Function: ProcessParameters
  1248. //
  1249. //----------------------------------------------------------------------------
  1250. BOOL
  1251. ProcessParameters(
  1252. int argc,
  1253. LPSTR argv[],
  1254. BOOL SkipFirst
  1255. )
  1256. {
  1257. char c, *p;
  1258. int i;
  1259. BOOL Result;
  1260. if (DEBUG_1) {
  1261. BuildMsg("Parsing:");
  1262. for (i=1; i<argc; i++) {
  1263. BuildMsgRaw(" %s", argv[i]);
  1264. }
  1265. BuildMsgRaw(szNewLine);
  1266. }
  1267. Result = TRUE;
  1268. if (SkipFirst) {
  1269. --argc;
  1270. ++argv;
  1271. }
  1272. while (argc) {
  1273. p = *argv;
  1274. if (*p == '/' || *p == '-') {
  1275. if (DEBUG_1) {
  1276. BuildMsg("Processing \"-%s\" switch\r\n", p+1);
  1277. }
  1278. for (i = 0; i < MAX_TARGET_MACHINES; i++) {
  1279. if (!_stricmp(p, PossibleTargetMachines[i]->Switch) ||
  1280. !_stricmp(p, PossibleTargetMachines[i]->Switch2)) {
  1281. AddTargetMachine(i);
  1282. break;
  1283. }
  1284. }
  1285. if (i < MAX_TARGET_MACHINES) {
  1286. } else
  1287. if (!_stricmp(p + 1, "all")) {
  1288. for (i = 0; i < MAX_TARGET_MACHINES; i++) {
  1289. AddTargetMachine(i);
  1290. }
  1291. } else
  1292. if (!_stricmp(p + 1, "why")) {
  1293. fWhyBuild = TRUE;
  1294. } else
  1295. while (c = *++p)
  1296. switch (toupper( c )) {
  1297. case '?':
  1298. fUsage = TRUE;
  1299. break;
  1300. case '$':
  1301. fDebug += 2; // yes, I want to *add* 2.
  1302. break;
  1303. case '#':
  1304. fCheckIncludePaths = TRUE;
  1305. fForce = TRUE;
  1306. break;
  1307. case '0':
  1308. fStopAfterPassZero = TRUE;
  1309. if (!fDependencySwitchUsed)
  1310. fDependencySwitchUsed = 3;
  1311. break;
  1312. case '1':
  1313. fQuicky = TRUE;
  1314. if (!fDependencySwitchUsed)
  1315. fDependencySwitchUsed = 2;
  1316. break;
  1317. case '2':
  1318. fSemiQuicky = TRUE;
  1319. fQuicky = TRUE;
  1320. if (!fDependencySwitchUsed)
  1321. fDependencySwitchUsed = 2;
  1322. break;
  1323. case '3':
  1324. fQuickZero = TRUE;
  1325. fSemiQuicky = TRUE;
  1326. fQuicky = TRUE;
  1327. if (!fDependencySwitchUsed)
  1328. fDependencySwitchUsed = 3;
  1329. break;
  1330. case 'A':
  1331. fSyncLink = TRUE;
  1332. break;
  1333. case 'B':
  1334. if (c == 'b') {
  1335. fFullErrors = TRUE;
  1336. } else {
  1337. fErrorBaseline = TRUE;
  1338. if (--argc) {
  1339. ++argv;
  1340. if (**argv != '/' && **argv != '-') {
  1341. if (ProbeFile(NULL, *argv) != -1) {
  1342. CanonicalizePathName(*argv, CANONICALIZE_ONLY, BaselinePathName);
  1343. Result = LoadBaselineFile();
  1344. } else {
  1345. BuildError("The specified baseline file doesn't exist\r\n");
  1346. Result = FALSE;
  1347. }
  1348. } else {
  1349. // the next parameter is a switch, reprocess it
  1350. --argv;
  1351. ++argc;
  1352. }
  1353. } else {
  1354. // no more parameters
  1355. ++argc;
  1356. }
  1357. }
  1358. break;
  1359. case 'C':
  1360. if (!_stricmp( p, "clean" )) {
  1361. MakeParametersTail = AppendString( MakeParametersTail,
  1362. "clean",
  1363. TRUE);
  1364. *p-- = '\0';
  1365. } else
  1366. if (c == 'C') {
  1367. fCleanLibs = TRUE;
  1368. } else {
  1369. fClean = TRUE;
  1370. }
  1371. break;
  1372. case 'D':
  1373. if (c == 'D') {
  1374. fDependencySwitchUsed = 1;
  1375. }
  1376. #if DBG
  1377. else {
  1378. fDebug |= 1;
  1379. }
  1380. break;
  1381. #endif
  1382. case 'E':
  1383. if (c == 'E') {
  1384. fAlwaysKeepLogfile = TRUE;
  1385. }
  1386. fErrorLog = TRUE;
  1387. break;
  1388. case 'F':
  1389. if (c == 'F') {
  1390. fAlwaysPrintFullPath = TRUE;
  1391. } else {
  1392. fForce = TRUE;
  1393. }
  1394. break;
  1395. case 'G':
  1396. if (c == 'G')
  1397. fTargetDirs = TRUE;
  1398. else
  1399. fColorConsole = TRUE;
  1400. break;
  1401. case 'H':
  1402. fSuppressOutput = TRUE;
  1403. case 'I':
  1404. if (c == 'I') {
  1405. fNoThreadIndex = TRUE;
  1406. } else {
  1407. fSilentDependencies = TRUE;
  1408. }
  1409. break;
  1410. case 'J': {
  1411. argc--, argv++;
  1412. if (!_stricmp( p, "jpath" )) {
  1413. // Allow BuildConsole to redirect the logfiles
  1414. strncpy(LogDirectory, *argv, sizeof(LogDirectory) - 1);
  1415. *p-- = '\0';
  1416. } else {
  1417. // Clear it out
  1418. memset(LogFileName, 0, sizeof(LogFileName));
  1419. memset(WrnFileName, 0, sizeof(WrnFileName));
  1420. memset(ErrFileName, 0, sizeof(ErrFileName));
  1421. memset(IncFileName, 0, sizeof(IncFileName));
  1422. memset(XMLFileName, 0, sizeof(XMLFileName));
  1423. // And set it to the arg passed in.
  1424. strncpy(LogFileName, *argv, sizeof(LogFileName) - 4);
  1425. strncpy(WrnFileName, *argv, sizeof(WrnFileName) - 4);
  1426. strncpy(ErrFileName, *argv, sizeof(ErrFileName) - 4);
  1427. strncpy(IncFileName, *argv, sizeof(IncFileName) - 4);
  1428. strncpy(XMLFileName, *argv, sizeof(XMLFileName) - 4);
  1429. }
  1430. break;
  1431. }
  1432. case 'K':
  1433. fKeep = TRUE;
  1434. break;
  1435. case 'L':
  1436. if (c == 'L') {
  1437. fCompileOnly = TRUE;
  1438. } else {
  1439. fLinkOnly = TRUE;
  1440. }
  1441. break;
  1442. case 'M':
  1443. if (c == 'M') {
  1444. fParallel = TRUE;
  1445. if (--argc) {
  1446. DefaultProcesses = atoi(*++argv);
  1447. if (DefaultProcesses == 0) {
  1448. --argv;
  1449. ++argc;
  1450. }
  1451. } else {
  1452. ++argc;
  1453. }
  1454. } else {
  1455. SetPriorityClass(GetCurrentProcess(),IDLE_PRIORITY_CLASS);
  1456. }
  1457. break;
  1458. case 'N':
  1459. if (_stricmp( p, "nmake") == 0) {
  1460. if (--argc) {
  1461. ++argv;
  1462. MakeParametersTail = AppendString( MakeParametersTail,
  1463. *argv,
  1464. TRUE);
  1465. } else {
  1466. argc++;
  1467. BuildError("Argument to /NMAKE switch missing\r\n");
  1468. Result = FALSE;
  1469. }
  1470. *p-- = '\0';
  1471. break;
  1472. } else {
  1473. fIgnoreSync = TRUE;
  1474. }
  1475. case 'O':
  1476. if (c == 'O') {
  1477. fGenerateObjectsDotMacOnly = TRUE;
  1478. } else {
  1479. fShowOutOfDateFiles = TRUE;
  1480. }
  1481. break;
  1482. case 'P':
  1483. if (c == 'P') {
  1484. fPrintElapsed = TRUE;
  1485. } else {
  1486. fPause = TRUE;
  1487. }
  1488. break;
  1489. case 'Q':
  1490. fQuery = TRUE;
  1491. break;
  1492. case 'R':
  1493. if (--argc) {
  1494. fCleanRestart = TRUE;
  1495. ++argv;
  1496. CopyString(RestartDir, *argv, TRUE);
  1497. } else {
  1498. argc++;
  1499. BuildError("Argument to /R switch missing\r\n");
  1500. Result = FALSE;
  1501. }
  1502. break;
  1503. case 'S':
  1504. fStatus = TRUE;
  1505. if (c == 'S') {
  1506. fStatusTree = TRUE;
  1507. }
  1508. break;
  1509. case 'T':
  1510. fShowTree = TRUE;
  1511. if (c == 'T') {
  1512. fShowTreeIncludes = TRUE;
  1513. }
  1514. break;
  1515. case 'U':
  1516. fShowUnusedDirs = TRUE;
  1517. break;
  1518. case 'V':
  1519. fEnableVersionCheck = TRUE;
  1520. break;
  1521. case 'W':
  1522. fShowWarningsOnScreen = TRUE;
  1523. break;
  1524. case 'X':
  1525. if (!strcmp(p, "Xf")) {
  1526. // The Xf switch produces XML fragments in a specified directory
  1527. if (--argc) {
  1528. ++argv;
  1529. if (!CanonicalizePathName(*argv, CANONICALIZE_DIR, XMLFragmentDirectory)) {
  1530. Result = FALSE;
  1531. } else {
  1532. fXMLFragment = TRUE;
  1533. }
  1534. } else {
  1535. ++argc;
  1536. BuildError("Argument to /Xf switch missing\r\n");
  1537. Result = FALSE;
  1538. }
  1539. } else
  1540. if (c == 'X') {
  1541. fXMLOutput = TRUE;
  1542. if (p[1] == 'v' ) {
  1543. ++p;
  1544. fXMLVerboseOutput = TRUE;
  1545. }
  1546. } else {
  1547. if (--argc) {
  1548. ++argv;
  1549. if (CountExcludeIncs >= MAX_EXCLUDE_INCS) {
  1550. static BOOL fError = FALSE;
  1551. if (!fError) {
  1552. BuildError(
  1553. "-x argument table overflow, using first %u entries\r\n",
  1554. MAX_EXCLUDE_INCS);
  1555. fError = TRUE;
  1556. }
  1557. } else {
  1558. MakeString(
  1559. &ExcludeIncs[CountExcludeIncs++],
  1560. *argv,
  1561. TRUE,
  1562. MT_CMDSTRING);
  1563. }
  1564. } else {
  1565. argc++;
  1566. BuildError("Argument to /X switch missing\r\n");
  1567. Result = FALSE;
  1568. }
  1569. }
  1570. break;
  1571. case 'Y':
  1572. fNoisyScan = TRUE;
  1573. break;
  1574. case 'Z':
  1575. fQuickZero = TRUE;
  1576. fSemiQuicky = TRUE;
  1577. fQuicky = TRUE;
  1578. if (!fDependencySwitchUsed)
  1579. fDependencySwitchUsed = 3;
  1580. break;
  1581. default:
  1582. BuildError("Invalid switch - /%c\r\n", c);
  1583. Result = FALSE;
  1584. break;
  1585. }
  1586. } else
  1587. if (*p == '~') {
  1588. if (CountExcludeDirs >= MAX_EXCLUDE_DIRECTORIES) {
  1589. static BOOL fError = FALSE;
  1590. if (!fError) {
  1591. BuildError(
  1592. "Exclude directory table overflow, using first %u entries\r\n",
  1593. MAX_EXCLUDE_DIRECTORIES);
  1594. fError = TRUE;
  1595. }
  1596. } else {
  1597. MakeString(
  1598. &ExcludeDirs[CountExcludeDirs++],
  1599. p + 1,
  1600. TRUE,
  1601. MT_CMDSTRING);
  1602. }
  1603. } else {
  1604. for (i = 0; i < MAX_TARGET_MACHINES; i++) {
  1605. if (!_stricmp(p, PossibleTargetMachines[i]->MakeVariable)) {
  1606. AddTargetMachine(i);
  1607. break;
  1608. }
  1609. }
  1610. if (i >= MAX_TARGET_MACHINES) {
  1611. if (iscsym(*p) || *p == '.') {
  1612. if (CountOptionalDirs >= MAX_OPTIONAL_DIRECTORIES) {
  1613. static BOOL fError = FALSE;
  1614. if (!fError) {
  1615. BuildError(
  1616. "Optional directory table overflow, using first %u entries\r\n",
  1617. MAX_OPTIONAL_DIRECTORIES);
  1618. fError = TRUE;
  1619. }
  1620. } else {
  1621. MakeString(
  1622. &OptionalDirs[CountOptionalDirs++],
  1623. p,
  1624. TRUE,
  1625. MT_CMDSTRING);
  1626. }
  1627. } else
  1628. if (!strcmp(p, "*")) {
  1629. BuildAllOptionalDirs = TRUE;
  1630. } else {
  1631. MakeParametersTail = AppendString(
  1632. MakeParametersTail,
  1633. p,
  1634. TRUE);
  1635. }
  1636. }
  1637. }
  1638. --argc;
  1639. ++argv;
  1640. }
  1641. return (Result);
  1642. }
  1643. //+---------------------------------------------------------------------------
  1644. //
  1645. // Function: GetEnvParameters
  1646. //
  1647. //----------------------------------------------------------------------------
  1648. VOID
  1649. GetEnvParameters(
  1650. LPSTR EnvVarName,
  1651. LPSTR DefaultValue,
  1652. int *pargc,
  1653. int maxArgc,
  1654. LPSTR argv[]
  1655. )
  1656. {
  1657. LPSTR p, p1, psz;
  1658. if (!(p = getenv(EnvVarName))) {
  1659. if (DefaultValue == NULL) {
  1660. return;
  1661. } else {
  1662. p = DefaultValue;
  1663. }
  1664. } else {
  1665. if (DEBUG_1) {
  1666. BuildMsg("Using %s=%s\r\n", EnvVarName, p);
  1667. }
  1668. }
  1669. MakeString(&psz, p, FALSE, MT_CMDSTRING);
  1670. p1 = psz;
  1671. while (*p1) {
  1672. while (*p1 <= ' ') {
  1673. if (!*p1) {
  1674. break;
  1675. }
  1676. p1++;
  1677. }
  1678. p = p1;
  1679. while (*p > ' ') {
  1680. if (*p == '#') {
  1681. *p = '=';
  1682. }
  1683. p++;
  1684. }
  1685. if (*p) {
  1686. *p++ = '\0';
  1687. }
  1688. MakeString(&argv[*pargc], p1, FALSE, MT_CMDSTRING);
  1689. if ((*pargc += 1) >= maxArgc) {
  1690. BuildError("Too many parameters (> %d)\r\n", maxArgc);
  1691. exit(1);
  1692. }
  1693. p1 = p;
  1694. }
  1695. FreeMem(&psz, MT_CMDSTRING);
  1696. }
  1697. //+---------------------------------------------------------------------------
  1698. //
  1699. // Function: FreeEnvParameters
  1700. //
  1701. //----------------------------------------------------------------------------
  1702. VOID
  1703. FreeEnvParameters(int argc, LPSTR argv[])
  1704. {
  1705. while (--argc >= 0) {
  1706. FreeMem(&argv[argc], MT_CMDSTRING);
  1707. }
  1708. }
  1709. //+---------------------------------------------------------------------------
  1710. //
  1711. // Function: FreeCmdStrings
  1712. //
  1713. //----------------------------------------------------------------------------
  1714. VOID
  1715. FreeCmdStrings(VOID)
  1716. {
  1717. #if DBG
  1718. UINT i;
  1719. for (i = 0; i < CountExcludeIncs; i++) {
  1720. FreeMem(&ExcludeIncs[i], MT_CMDSTRING);
  1721. }
  1722. for (i = 0; i < CountOptionalDirs; i++) {
  1723. FreeMem(&OptionalDirs[i], MT_CMDSTRING);
  1724. }
  1725. for (i = 0; i < CountExcludeDirs; i++) {
  1726. FreeMem(&ExcludeDirs[i], MT_CMDSTRING);
  1727. }
  1728. // It's possible the user may have done:
  1729. // <global macro> = <null>
  1730. // in a sources file. Don't free mem unless it's still set...
  1731. if (pszSdkLibDest)
  1732. FreeMem(&pszSdkLibDest, MT_DIRSTRING);
  1733. if (pszDdkLibDest)
  1734. FreeMem(&pszDdkLibDest, MT_DIRSTRING);
  1735. if (pszPublicInternalPath)
  1736. FreeMem(&pszPublicInternalPath, MT_DIRSTRING);
  1737. if (pszIncOs2)
  1738. FreeMem(&pszIncOs2, MT_DIRSTRING);
  1739. if (pszIncPosix)
  1740. FreeMem(&pszIncPosix, MT_DIRSTRING);
  1741. if (pszIncChicago)
  1742. FreeMem(&pszIncChicago, MT_DIRSTRING);
  1743. if (pszIncMfc)
  1744. FreeMem(&pszIncMfc, MT_DIRSTRING);
  1745. if (pszIncSdk)
  1746. FreeMem(&pszIncSdk, MT_DIRSTRING);
  1747. if (pszIncCrt)
  1748. FreeMem(&pszIncCrt, MT_DIRSTRING);
  1749. if (pszIncOak)
  1750. FreeMem(&pszIncOak, MT_DIRSTRING);
  1751. if (pszIncDdk)
  1752. FreeMem(&pszIncDdk, MT_DIRSTRING);
  1753. if (pszIncWdm)
  1754. FreeMem(&pszIncWdm, MT_DIRSTRING);
  1755. if (pszIncPri)
  1756. FreeMem(&pszIncPri, MT_DIRSTRING);
  1757. #endif
  1758. }
  1759. //+---------------------------------------------------------------------------
  1760. //
  1761. // Function: MungePossibleTarget
  1762. //
  1763. //----------------------------------------------------------------------------
  1764. VOID
  1765. MungePossibleTarget(
  1766. PTARGET_MACHINE_INFO pti
  1767. )
  1768. {
  1769. PCHAR s;
  1770. char *pszDir;
  1771. if (!pti) {
  1772. return;
  1773. }
  1774. // save "i386" string
  1775. pszDir = pti->ObjectDirectory[0];
  1776. // Create "$(_OBJ_DIR)\i386" string
  1777. s = malloc(12 + strlen(pszDir) + 1);
  1778. if (!s)
  1779. return;
  1780. sprintf(s, "$(_OBJ_DIR)\\%s", pszDir);
  1781. pti->ObjectMacro = s;
  1782. // Create "obj$(BUILD_ALT_DIR)\i386" string for default obj dir
  1783. s = malloc(strlen(szObjDir) + 1 + strlen(pszDir) + 1);
  1784. if (!s)
  1785. return;
  1786. sprintf(s, "%s\\%s", szObjDir, pszDir);
  1787. pti->ObjectDirectory[0] = s;
  1788. // Create "objd\i386" string for alternate checked obj dir
  1789. s = malloc(strlen(szObjDirD) + 1 + strlen(pszDir) + 1);
  1790. if (!s)
  1791. return;
  1792. sprintf(s, "%s\\%s", szObjDirD, pszDir);
  1793. pti->ObjectDirectory[1] = s;
  1794. }
  1795. //+---------------------------------------------------------------------------
  1796. //
  1797. // Function: GetIncludePatterns
  1798. //
  1799. //----------------------------------------------------------------------------
  1800. VOID
  1801. GetIncludePatterns(
  1802. LPSTR EnvVarName,
  1803. int maxArgc,
  1804. LPSTR argv[]
  1805. )
  1806. {
  1807. LPSTR p, p1, psz;
  1808. int argc;
  1809. argc = 0;
  1810. if ( ( p = getenv(EnvVarName ) ) == NULL ) {
  1811. return;
  1812. }
  1813. MakeString( &psz, p, FALSE, MT_DIRSTRING );
  1814. p1 = psz;
  1815. while ( *p1 ) {
  1816. while ( *p1 == ';' || *p1 == ' ' ) {
  1817. p1++;
  1818. }
  1819. p = p1;
  1820. while ( *p && *p != ';' ) {
  1821. p++;
  1822. }
  1823. if ( *p ) {
  1824. *p++ = '\0';
  1825. }
  1826. MakeString( &argv[argc], p1, FALSE, MT_DIRSTRING );
  1827. if ( ( argc += 1 ) == maxArgc ) {
  1828. BuildError( "Too many include patterns ( > %d)\r\n", maxArgc );
  1829. exit( 1 );
  1830. }
  1831. p1 = p;
  1832. }
  1833. FreeMem(&psz, MT_DIRSTRING);
  1834. }
  1835. //+---------------------------------------------------------------------------
  1836. //
  1837. // Function: FreeIncludePatterns
  1838. //
  1839. //----------------------------------------------------------------------------
  1840. VOID
  1841. FreeIncludePatterns(int argc, LPSTR argv[])
  1842. {
  1843. while ( argc ) {
  1844. if ( argv[--argc] ) {
  1845. FreeMem( &argv[argc], MT_DIRSTRING );
  1846. }
  1847. }
  1848. }
  1849. //+---------------------------------------------------------------------------
  1850. //
  1851. // Function: LoadBaselineFile
  1852. //
  1853. //----------------------------------------------------------------------------
  1854. BOOL
  1855. LoadBaselineFile(VOID)
  1856. {
  1857. BOOL Result = FALSE;
  1858. FILE* FBase = NULL;
  1859. long lSize = 0;
  1860. if (BaselinePathName[0] == '\0')
  1861. goto Cleanup;
  1862. if (!MyOpenFile("", BaselinePathName, "rb", &FBase, FALSE))
  1863. goto Cleanup;
  1864. if (fseek(FBase, 0, SEEK_END))
  1865. goto Cleanup;
  1866. if ((lSize = ftell(FBase)) == -1)
  1867. goto Cleanup;
  1868. if (lSize == 0) {
  1869. // if the baseline is zero-length file, do as if it weren't specified
  1870. Result = TRUE;
  1871. BaselinePathName[0] = '\0';
  1872. goto Cleanup;
  1873. }
  1874. if (fseek(FBase, 0, SEEK_SET))
  1875. goto Cleanup;
  1876. if ((pvBaselineContent = malloc(lSize)) == NULL)
  1877. goto Cleanup;
  1878. if (fread(pvBaselineContent, 1, lSize, FBase) != lSize) {
  1879. free(pvBaselineContent);
  1880. pvBaselineContent = NULL;
  1881. goto Cleanup;
  1882. }
  1883. cbBaselineContentSize = (DWORD)lSize;
  1884. Result = TRUE;
  1885. Cleanup:
  1886. if (FBase != NULL)
  1887. fclose(FBase);
  1888. return Result;
  1889. }
  1890. VOID
  1891. FreeBaselineFile(VOID)
  1892. {
  1893. if (NULL != pvBaselineContent)
  1894. free(pvBaselineContent);
  1895. pvBaselineContent = NULL;
  1896. cbBaselineContentSize = 0;
  1897. }
  1898. //+---------------------------------------------------------------------------
  1899. //
  1900. // Function: ResetProducerEvents
  1901. // This function sets all the events created by the producers to unsignalled state.
  1902. // This function will be called after pass0 and pass1
  1903. //
  1904. //----------------------------------------------------------------------------
  1905. VOID
  1906. ResetProducerEvents(VOID)
  1907. {
  1908. PDEPENDENCY Dependency;
  1909. Dependency = AllDependencies;
  1910. while (Dependency) {
  1911. Dependency->Done = FALSE;
  1912. ResetEvent(Dependency->hEvent);
  1913. Dependency = Dependency->Next;
  1914. }
  1915. }