Changeset 1008 in kBuild
- Timestamp:
- Jun 2, 2007 4:22:27 PM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kObjCache/kObjCache.c
r1005 r1008 74 74 # define IS_SLASH_DRV(ch) ((ch) == '/') 75 75 #endif 76 /** Use pipe instead of temp files when possible (speed). */ 77 #define USE_PIPE 1 76 78 77 79 … … 108 110 /** Set if the object needs to be (re)compiled. */ 109 111 unsigned fNeedCompiling; 112 /** Whether the precompiler runs in piped mode. If clear it's file 113 * mode (it could be redirected stdout, but that's essentially the 114 * same from our point of view). */ 115 unsigned fPiped; 110 116 111 117 /** The name of new precompiled output. */ … … 114 120 char *pszNewCppMapping; 115 121 /** The size of the new precompiled output 'mapping'. */ 116 size_t cbNewCpp Mapping;122 size_t cbNewCpp; 117 123 /** The new checksum. */ 118 124 KOCSUM NewSum; … … 124 130 /** Pointer to the 'mapping' of the old precompiled output. */ 125 131 char *pszOldCppMapping; 126 /** The size of the old precompiled output 'mapping'. */127 size_t cbOldCpp Mapping;132 /** The size of the old precompiled output. */ 133 size_t cbOldCpp; 128 134 129 135 /** The head of the checksum list. */ … … 333 339 break; 334 340 pEntry->pszOldCppName = xstrdup(pszVal); 341 } 342 else if (!strcmp(s_szLine, "cpp-size")) 343 { 344 char *pszNext; 345 if ((fBad = pEntry->cbOldCpp != 0)) 346 break; 347 pEntry->cbOldCpp = strtoul(pszVal, &pszNext, 0); 348 if ((fBad = pszNext && *pszNext)) 349 break; 335 350 } 336 351 else if (!strcmp(s_szLine, "cc-argc")) … … 462 477 CHECK_LEN(fprintf(pFile, "obj=%s\n", pEntry->pszNewObjName ? pEntry->pszNewObjName : pEntry->pszObjName)); 463 478 CHECK_LEN(fprintf(pFile, "cpp=%s\n", pEntry->pszNewCppName ? pEntry->pszNewCppName : pEntry->pszOldCppName)); 479 CHECK_LEN(fprintf(pFile, "cpp-size=%lu\n", pEntry->pszNewCppName ? pEntry->cbNewCpp : pEntry->cbOldCpp)); 464 480 CHECK_LEN(fprintf(pFile, "cc-argc=%u\n", pEntry->cArgvCompile)); 465 481 for (i = 0; i < pEntry->cArgvCompile; i++) … … 509 525 kObjCacheFatal(pEntry, "%s - failed to create stdout redirection file '%s': %s\n", 510 526 pszMsg, pszStdOut, strerror(errno)); 527 511 528 if (fdReDir != 1) 512 529 { … … 555 572 pszMsg, rc, errno, strerror(errno)); 556 573 } 574 if (pid == -1) 575 kObjCacheFatal(pEntry, "%s - fork() failed: %s\n", pszMsg, strerror(errno)); 576 557 577 pidWait = waitpid(pid, &iStatus); 558 578 while (pidWait < 0 && errno == EINTR) 559 579 pidWait = waitpid(pid, &iStatus); 560 580 if (pidWait != pid) 561 kObjCacheFatal(pEntry, "%s - waitpid failed rc=%d errno=%d%s\n",562 pszMsg, rc, errno, strerror(errno));581 kObjCacheFatal(pEntry, "%s - waitpid failed rc=%d: %s\n", 582 pszMsg, pidWait, strerror(errno)); 563 583 if (!WIFEXITED(iStatus)) 564 584 kObjCacheFatal(pEntry, "%s - abended (iStatus=%#x)\n", pszMsg, iStatus); … … 570 590 571 591 572 /** 573 * Worker for kObjCachePreCompile and calculates the checksum of 574 * the precompiler output. 575 * 576 * @param pEntry The cache entry. NewSum will be updated. 577 */ 578 static void kObjCacheCalcChecksum(PKOBJCACHE pEntry) 579 { 580 struct MD5Context MD5Ctx; 581 582 /* 583 * Read/maps the entire file into a buffer and does the crc sums 584 * on the buffer. This assumes the precompiler output isn't 585 * gigantic, but that's a pretty safe assumption I hope... 586 */ 587 pEntry->pszNewCppMapping = ReadFileInDir(pEntry->pszNewCppName, pEntry->pszDir, &pEntry->cbNewCppMapping); 592 #ifdef USE_PIPE 593 /** 594 * Spawns a child in a synchronous fashion. 595 * Terminating on failure. 596 * 597 * @param papszArgv Argument vector. The cArgv element is NULL. 598 * @param cArgv The number of arguments in the vector. 599 */ 600 static void kObjCacheSpawnPipe(PCKOBJCACHE pEntry, const char **papszArgv, unsigned cArgv, const char *pszMsg, char **ppszOutput, size_t *pcchOutput) 601 { 602 int fds[2]; 603 int iStatus; 604 #if defined(__WIN__) 605 intptr_t pid, pidWait; 606 #else 607 pid_t pid, pidWait; 608 #endif 609 int fdStdOut; 610 size_t cbAlloc; 611 size_t cbLeft; 612 char *psz; 613 614 /* 615 * Setup the pipe. 616 */ 617 #if defined(__WIN__) 618 if (_pipe(fds, 0, _O_NOINHERIT | _O_BINARY) < 0) 619 #else 620 if (pipe(fds) < 0) 621 #endif 622 kObjCacheFatal(pEntry, "pipe failed: %s\n", strerror(errno)); 623 fdStdOut = dup(1); 624 if (dup2(fds[1 /* write */], 1) < 0) 625 kObjCacheFatal(pEntry, "dup2(,1) failed: %s\n", strerror(errno)); 626 close(fds[1]); 627 fds[1] = -1; 628 #ifndef __WIN__ 629 fcntl(fds[0], F_SETFD, FD_CLOEXEC); 630 fcntl(fdStdOut, F_SETFD, FD_CLOEXEC); 631 #endif 632 633 /* 634 * Create the child process. 635 */ 636 #if defined(__OS2__) || defined(__WIN__) 637 errno = 0; 638 pid = _spawnvp(_P_NOWAIT, papszArgv[0], papszArgv); 639 if (pid == -1) 640 kObjCacheFatal(pEntry, "%s - _spawnvp failed: %s\n", pszMsg, strerror(errno)); 641 642 #else 643 pid = fork(); 644 if (!pid) 645 { 646 execvp(papszArgv[0], papszArgv); 647 kObjCacheFatal(pEntry, "%s - execvp failed rc=%d errno=%d %s\n", 648 pszMsg, rc, errno, strerror(errno)); 649 } 650 if (pid == -1) 651 kObjCacheFatal(pEntry, "%s - fork() failed: %s\n", pszMsg, strerror(errno)); 652 #endif 653 654 /* 655 * Restore stdout. 656 */ 657 close(1); 658 fdStdOut = dup2(fdStdOut, 1); 659 660 /* 661 * Read data from the child. 662 */ 663 cbAlloc = pEntry->cbOldCpp ? (pEntry->cbOldCpp + 4*1024*1024) & ~(4*1024*1024 - 1) : 4*1024*1024; 664 cbLeft = cbAlloc; 665 *ppszOutput = psz = xmalloc(cbAlloc); 666 for (;;) 667 { 668 long cbRead = _read(fds[0], psz, cbLeft); 669 if (!cbRead) 670 break; 671 if (cbRead < 0 && errno != EINTR) 672 kObjCacheFatal(pEntry, "%s - read(%d,,%ld) failed: %s\n", pszMsg, fds[0], (long)cbLeft, strerror(errno)); 673 psz += cbRead; 674 cbLeft -= cbRead; 675 676 /* expand the buffer? */ 677 if (!cbLeft) 678 { 679 size_t off = psz - *ppszOutput; 680 assert(off == cbAlloc); 681 cbLeft = 4*1024*1024; 682 cbAlloc += cbLeft; 683 *ppszOutput = xrealloc(*ppszOutput, cbAlloc); 684 psz = *ppszOutput + off; 685 } 686 } 687 close(fds[0]); 688 *pcchOutput = cbAlloc - cbLeft; 689 690 /* 691 * Reap the child. 692 */ 693 #ifdef __WIN__ 694 pidWait = _cwait(&iStatus, pid, _WAIT_CHILD); 695 if (pidWait == -1) 696 kObjCacheFatal(pEntry, "%s - waitpid failed: %s\n", 697 pszMsg, strerror(errno)); 698 if (iStatus) 699 kObjCacheFatal(pEntry, "%s - failed with rc %d\n", pszMsg, iStatus); 700 #else 701 pidWait = waitpid(pid, &iStatus); 702 while (pidWait < 0 && errno == EINTR) 703 pidWait = waitpid(pid, &iStatus); 704 if (pidWait != pid) 705 kObjCacheFatal(pEntry, "%s - waitpid failed rc=%d: %s\n", 706 pszMsg, pidWait, strerror(errno)); 707 if (!WIFEXITED(iStatus)) 708 kObjCacheFatal(pEntry, "%s - abended (iStatus=%#x)\n", pszMsg, iStatus); 709 if (WEXITSTATUS(iStatus)) 710 kObjCacheFatal(pEntry, "%s - failed with rc %d\n", pszMsg, WEXITSTATUS(iStatus)); 711 #endif 712 (void)cArgv; 713 } 714 #endif /* USE_PIPE */ 715 716 717 /** 718 * Reads the (new) output of the precompiler. 719 * 720 * Not used when using pipes. 721 * 722 * @param pEntry The cache entry. cbNewCpp and pszNewCppMapping will be updated. 723 */ 724 static void kObjCacheReadPrecompileOutput(PKOBJCACHE pEntry) 725 { 726 pEntry->pszNewCppMapping = ReadFileInDir(pEntry->pszNewCppName, pEntry->pszDir, &pEntry->cbNewCpp); 588 727 if (!pEntry->pszNewCppMapping) 589 728 kObjCacheFatal(pEntry, "failed to open/read '%s' in '%s': %s\n", 590 729 pEntry->pszNewCppName, pEntry->pszDir, strerror(errno)); 591 kObjCacheVerbose(pEntry, "precompiled file is %lu bytes long\n", (unsigned long)pEntry->cbNewCppMapping); 730 kObjCacheVerbose(pEntry, "precompiled file is %lu bytes long\n", (unsigned long)pEntry->cbNewCpp); 731 } 732 733 734 /** 735 * Worker for kObjCachePreCompile and calculates the checksum of 736 * the precompiler output. 737 * 738 * @param pEntry The cache entry. NewSum will be updated. 739 */ 740 static void kObjCacheCalcChecksum(PKOBJCACHE pEntry) 741 { 742 struct MD5Context MD5Ctx; 592 743 593 744 memset(&pEntry->NewSum, 0, sizeof(pEntry->NewSum)); 594 pEntry->NewSum.crc32 = crc32(0, pEntry->pszNewCppMapping, pEntry->cbNewCpp Mapping);745 pEntry->NewSum.crc32 = crc32(0, pEntry->pszNewCppMapping, pEntry->cbNewCpp); 595 746 MD5Init(&MD5Ctx); 596 MD5Update(&MD5Ctx, pEntry->pszNewCppMapping, pEntry->cbNewCpp Mapping);747 MD5Update(&MD5Ctx, pEntry->pszNewCppMapping, pEntry->cbNewCpp); 597 748 MD5Final(&pEntry->NewSum.md5[0], &MD5Ctx); 598 749 kObjCacheVerbose(pEntry, "crc32=%#lx md5=%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x\n", … … 617 768 static void kObjCachePreCompile(PKOBJCACHE pEntry, const char **papszArgvPreComp, unsigned cArgvPreComp, const char *pszPreCompName, int fRedirStdOut) 618 769 { 770 #ifdef USE_PIPE 771 /* 772 * Flag it as piped or non-piped. 773 */ 774 if (fRedirStdOut) 775 pEntry->fPiped = 1; 776 else 777 #endif 778 pEntry->fPiped = 0; 779 619 780 /* 620 781 * Rename the old precompiled output to '-old'. 621 782 * We'll discard the old output and keep the new output, but because 622 783 * we might with to do a quick matchup later we can't remove it just now. 784 * If we're using the pipe strategy, we will not do any renaming. 623 785 */ 624 786 if ( pEntry->pszOldCppName 787 && !pEntry->fPiped 625 788 && DoesFileInDirExist(pEntry->pszOldCppName, pEntry->pszDir)) 626 789 { … … 644 807 */ 645 808 kObjCacheVerbose(pEntry, "precompiling -> '%s'...\n", pEntry->pszNewCppName); 646 if (fRedirStdOut) 647 kObjCacheSpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", pszPreCompName); 809 #ifdef USE_PIPE 810 if (pEntry->fPiped) 811 kObjCacheSpawnPipe(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", &pEntry->pszNewCppMapping, &pEntry->cbNewCpp); 648 812 else 649 kObjCacheSpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", NULL); 813 #endif 814 { 815 if (fRedirStdOut) 816 kObjCacheSpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", pszPreCompName); 817 else 818 kObjCacheSpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", NULL); 819 kObjCacheReadPrecompileOutput(pEntry); 820 } 650 821 kObjCacheCalcChecksum(pEntry); 651 822 } … … 690 861 } 691 862 pEntry->pszNewObjName = CalcRelativeName(pszObjName, pEntry->pszDir); 863 864 /* 865 * If we executed the precompiled in piped mode we'll have to write the 866 * precompiler output to disk so the compile has some thing to chew on. 867 */ 868 if (pEntry->fPiped) 869 { 870 FILE *pFile = FOpenFileInDir(pEntry->pszNewCppName, pEntry->pszDir, "wb"); 871 if (!pFile) 872 kObjCacheFatal(pEntry, "failed to create file '%s' in '%s': %s\n", 873 pEntry->pszNewCppName, pEntry->pszDir, strerror(errno)); 874 if (fwrite(pEntry->pszNewCppMapping, pEntry->cbNewCpp, 1, pFile) != 1) 875 kObjCacheFatal(pEntry, "fwrite failed: %s\n", strerror(errno)); 876 if (fclose(pFile)) 877 kObjCacheFatal(pEntry, "fclose failed: %s\n", strerror(errno)); 878 } 692 879 693 880 /*
Note:
See TracChangeset
for help on using the changeset viewer.