Changeset 2456 in kBuild
- Timestamp:
- Jul 7, 2011 11:25:30 PM (13 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kObjCache/kObjCache.c
r2413 r2456 5 5 6 6 /* 7 * Copyright (c) 2007-201 0knut st. osmundsen <[email protected]>7 * Copyright (c) 2007-2011 knut st. osmundsen <[email protected]> 8 8 * 9 9 * This file is part of kBuild. … … 50 50 # include <unistd.h> 51 51 # include <sys/wait.h> 52 # include <sys/time.h> 52 53 # endif 53 54 # if defined(_MSC_VER) … … 64 65 # include <unistd.h> 65 66 # include <sys/wait.h> 67 # include <sys/time.h> 66 68 # ifndef O_BINARY 67 69 # define O_BINARY 0 … … 235 237 char *xstrdup(const char *pszIn) 236 238 { 237 char *psz = strdup(pszIn); 238 if (!psz) 239 FatalDie("out of memory (%d)\n", (int)strlen(pszIn)); 239 char *psz; 240 if (pszIn) 241 { 242 psz = strdup(pszIn); 243 if (!psz) 244 FatalDie("out of memory (%d)\n", (int)strlen(pszIn)); 245 } 246 else 247 psz = NULL; 240 248 return psz; 241 249 } … … 252 260 253 261 262 263 264 /** 265 * Returns a millisecond timestamp. 266 * 267 * @returns Millisecond timestamp. 268 */ 269 static uint32_t NowMs(void) 270 { 271 #if defined(__WIN__) 272 return GetTickCount(); 273 #else 274 int iSavedErrno = errno; 275 struct timeval tv = {0, 0}; 276 277 gettimeofday(&tv, NULL); 278 errno = iSavedErrno; 279 280 return tv.tv_sec * 1000 + tv.tv_usec / 1000; 281 #endif 282 } 254 283 255 284 … … 1051 1080 /** Whether the compiler runs in piped mode (precompiler output on stdin). */ 1052 1081 unsigned fPipedCompile; 1082 /** The name of the pipe that we're feeding the precompiled output to the 1083 * compiler via. This is a Windows thing. */ 1084 char *pszNmPipeCompile; 1053 1085 /** Cache entry key that's used for some quick digest validation. */ 1054 1086 uint32_t uKey; … … 1065 1097 /** The precompiler output checksums that will produce the cached object. */ 1066 1098 KOCSUM SumHead; 1099 /** The number of milliseconds spent precompiling. */ 1100 uint32_t cMsCpp; 1101 1067 1102 /** The object filename (relative to the cache file). */ 1068 1103 char *pszObjName; … … 1073 1108 /** The checksum of the compiler argument vector. */ 1074 1109 KOCSUM SumCompArgv; 1110 /** The number of milliseconds spent compiling. */ 1111 uint32_t cMsCompile; 1112 /** @todo need a list of additional output files for MSC. */ 1113 1075 1114 /** The target os/arch identifier. */ 1076 1115 char *pszTarget; … … 1132 1171 static void kOCEntryDestroy(PKOCENTRY pEntry) 1133 1172 { 1173 /** @todo free pEntry->pszName? */ 1134 1174 free(pEntry->pszDir); 1135 1175 free(pEntry->pszAbsPath); 1176 free(pEntry->pszNmPipeCompile); 1136 1177 1137 1178 kOCSumDeleteChain(&pEntry->New.SumHead); … … 1213 1254 */ 1214 1255 if ( !fgets(g_szLine, sizeof(g_szLine), pFile) 1215 || strcmp(g_szLine, "magic=kObjCacheEntry-v0.1.0\n")) 1256 || ( strcmp(g_szLine, "magic=kObjCacheEntry-v0.1.0\n") 1257 && strcmp(g_szLine, "magic=kObjCacheEntry-v0.1.1\n")) 1258 ) 1216 1259 { 1217 1260 InfoMsg(2, "bad cache file (magic)\n"); … … 1270 1313 kOCSumAdd(&pEntry->Old.SumHead, &Sum); 1271 1314 } 1315 else if (!strcmp(g_szLine, "cpp-ms")) 1316 { 1317 char *pszNext; 1318 if ((fBad = pEntry->Old.cMsCpp != 0)) 1319 break; 1320 pEntry->Old.cMsCpp = strtoul(pszVal, &pszNext, 0); 1321 if ((fBad = pszNext && *pszNext)) 1322 break; 1323 } 1272 1324 else if (!strcmp(g_szLine, "cc-argc")) 1273 1325 { … … 1290 1342 break; 1291 1343 if ((fBad = kOCSumInitFromString(&pEntry->Old.SumCompArgv, pszVal))) 1344 break; 1345 } 1346 else if (!strcmp(g_szLine, "cc-ms")) 1347 { 1348 char *pszNext; 1349 if ((fBad = pEntry->Old.cMsCompile != 0)) 1350 break; 1351 pEntry->Old.cMsCompile = strtoul(pszVal, &pszNext, 0); 1352 if ((fBad = pszNext && *pszNext)) 1292 1353 break; 1293 1354 } … … 1405 1466 do { int cch = expr; if (cch >= KOBJCACHE_MAX_LINE_LEN) FatalDie("Line too long: %d (max %d)\nexpr: %s\n", cch, KOBJCACHE_MAX_LINE_LEN, #expr); } while (0) 1406 1467 1407 fprintf(pFile, "magic=kObjCacheEntry-v0.1. 0\n");1468 fprintf(pFile, "magic=kObjCacheEntry-v0.1.1\n"); 1408 1469 CHECK_LEN(fprintf(pFile, "target=%s\n", pEntry->New.pszTarget ? pEntry->New.pszTarget : pEntry->Old.pszTarget)); 1409 1470 CHECK_LEN(fprintf(pFile, "key=%lu\n", (unsigned long)pEntry->uKey)); 1410 CHECK_LEN(fprintf(pFile, "obj=%s\n", pEntry->New.pszObjName ? pEntry->New.pszObjName : pEntry->Old.pszObjName)); 1411 CHECK_LEN(fprintf(pFile, "cpp=%s\n", pEntry->New.pszCppName ? pEntry->New.pszCppName : pEntry->Old.pszCppName)); 1412 CHECK_LEN(fprintf(pFile, "cpp-size=%lu\n", pEntry->New.pszCppName ? pEntry->New.cbCpp : pEntry->Old.cbCpp)); 1471 CHECK_LEN(fprintf(pFile, "obj=%s\n", pEntry->New.pszObjName ? pEntry->New.pszObjName : pEntry->Old.pszObjName)); 1472 CHECK_LEN(fprintf(pFile, "cpp=%s\n", pEntry->New.pszCppName ? pEntry->New.pszCppName : pEntry->Old.pszCppName)); 1473 CHECK_LEN(fprintf(pFile, "cpp-size=%lu\n", pEntry->New.pszCppName ? pEntry->New.cbCpp : pEntry->Old.cbCpp)); 1474 CHECK_LEN(fprintf(pFile, "cpp-ms=%lu\n", pEntry->New.pszCppName ? pEntry->New.cMsCpp : pEntry->Old.cMsCpp)); 1475 CHECK_LEN(fprintf(pFile, "cc-ms=%lu\n", pEntry->New.pszCppName ? pEntry->New.cMsCompile : pEntry->Old.cMsCompile)); 1413 1476 1414 1477 if (!kOCSumIsEmpty(&pEntry->New.SumCompArgv)) … … 1585 1648 * @param fRedirPreCompStdOut Whether the precompiler is in piped mode. 1586 1649 * @param fRedirCompileStdIn Whether the compiler is in piped mode. 1587 */ 1588 static void kOCEntrySetPipedMode(PKOCENTRY pEntry, int fRedirPreCompStdOut, int fRedirCompileStdIn) 1650 * @param pszNmPipeCompile The name of the named pipe to use to feed 1651 * the microsoft compiler. 1652 */ 1653 static void kOCEntrySetPipedMode(PKOCENTRY pEntry, int fRedirPreCompStdOut, int fRedirCompileStdIn, 1654 const char *pszNmPipeCompile) 1589 1655 { 1590 1656 pEntry->fPipedPreComp = fRedirPreCompStdOut; 1591 pEntry->fPipedCompile = fRedirCompileStdIn; 1657 pEntry->fPipedCompile = fRedirCompileStdIn || pszNmPipeCompile; 1658 pEntry->pszNmPipeCompile = xstrdup(pszNmPipeCompile); 1592 1659 } 1593 1660 … … 1598 1665 * 1599 1666 * @param papszArgv Argument vector. The cArgv element is NULL. 1667 * @param pcMs The cache entry member use for time keeping. This 1668 * will be set to the current timestamp. 1600 1669 * @param cArgv The number of arguments in the vector. 1601 */ 1602 static void kOCEntrySpawn(PCKOCENTRY pEntry, const char * const *papszArgv, unsigned cArgv, const char *pszMsg, const char *pszStdOut) 1670 * @param pszMsg Which operation this is, for use in messages. 1671 * @param pszStdOut Where to redirect standard out. 1672 */ 1673 static void kOCEntrySpawn(PCKOCENTRY pEntry, uint32_t *pcMs, const char * const *papszArgv, unsigned cArgv, 1674 const char *pszMsg, const char *pszStdOut) 1603 1675 { 1604 1676 #if defined(__OS2__) || defined(__WIN__) … … 1623 1695 } 1624 1696 1697 *pcMs = NowMs(); 1625 1698 errno = 0; 1626 1699 # ifdef __WIN__ … … 1629 1702 rc = _spawnvp(_P_WAIT, papszArgv[0], papszArgv); 1630 1703 # endif 1704 *pcMs = NowMs() - *pcMs; 1631 1705 if (rc < 0) 1632 1706 FatalDie("%s - _spawnvp failed (rc=0x%p): %s\n", pszMsg, rc, strerror(errno)); … … 1643 1717 int iStatus; 1644 1718 pid_t pidWait; 1645 pid_t pid = fork(); 1719 pid_t pid; 1720 1721 *pcMs = NowMs(); 1722 pid = fork(); 1646 1723 if (!pid) 1647 1724 { … … 1673 1750 while (pidWait < 0 && errno == EINTR) 1674 1751 pidWait = waitpid(pid, &iStatus, 0); 1752 *pcMs = NowMs() - *pcMs; 1675 1753 if (pidWait != pid) 1676 1754 FatalDie("%s - waitpid failed rc=%d: %s\n", … … 1690 1768 * 1691 1769 * @param pEntry The cache entry. 1770 * @param pcMs The cache entry member use for time keeping. This 1771 * will be set to the current timestamp. 1692 1772 * @param papszArgv Argument vector. The cArgv element is NULL. 1693 1773 * @param cArgv The number of arguments in the vector. … … 1696 1776 * @param pszMsg Message to start the info/error messages with. 1697 1777 */ 1698 static pid_t kOCEntrySpawnChild(PCKOCENTRY pEntry, const char * const *papszArgv, unsigned cArgv, int fdStdIn, int fdStdOut, const char *pszMsg) 1778 static pid_t kOCEntrySpawnChild(PCKOCENTRY pEntry, uint32_t *pcMs, const char * const *papszArgv, unsigned cArgv, 1779 int fdStdIn, int fdStdOut, const char *pszMsg) 1699 1780 { 1700 1781 pid_t pid; … … 1729 1810 * Create the child process. 1730 1811 */ 1812 *pcMs = NowMs(); 1731 1813 #if defined(__OS2__) || defined(__WIN__) 1732 1814 errno = 0; … … 1777 1859 * 1778 1860 * @param pEntry The cache entry. 1861 * @param pcMs The millisecond timestamp that should be convert to 1862 * elapsed time. 1779 1863 * @param pid The child to wait for. 1780 1864 * @param pszMsg Message to start the info/error messages with. 1781 1865 */ 1782 static void kOCEntryWaitChild(PCKOCENTRY pEntry, pid_t pid, const char *pszMsg)1866 static void kOCEntryWaitChild(PCKOCENTRY pEntry, uint32_t *pcMs, pid_t pid, const char *pszMsg) 1783 1867 { 1784 1868 int iStatus = -1; … … 1788 1872 #ifdef __WIN__ 1789 1873 pidWait = _cwait(&iStatus, pid, _WAIT_CHILD); 1874 *pcMs = NowMs() - *pcMs; 1790 1875 if (pidWait == -1) 1791 1876 FatalDie("%s - waitpid failed: %s\n", pszMsg, strerror(errno)); … … 1796 1881 while (pidWait < 0 && errno == EINTR) 1797 1882 pidWait = waitpid(pid, &iStatus, 0); 1883 *pcMs = NowMs() - *pcMs; 1798 1884 if (pidWait != pid) 1799 1885 FatalDie("%s - waitpid failed rc=%d: %s\n", pidWait, strerror(errno)); … … 1813 1899 * @param pFDs Where to store the two file descriptors. 1814 1900 * @param pszMsg The operation message for info/error messages. 1815 */ 1816 static void kOCEntryCreatePipe(PKOCENTRY pEntry, int *pFDs, const char *pszMsg) 1901 * @param pszPipeName The pipe name if it is supposed to be named. (Windows only.) 1902 */ 1903 static void kOCEntryCreatePipe(PKOCENTRY pEntry, int *pFDs, const char *pszPipeName, const char *pszMsg) 1817 1904 { 1818 1905 pFDs[0] = pFDs[1] = -1; 1819 1906 #if defined(__WIN__) 1820 if (_pipe(pFDs, 0, _O_NOINHERIT | _O_BINARY) < 0) 1907 if (pszPipeName) 1908 { 1909 HANDLE hPipe = CreateNamedPipeA(pszPipeName, 1910 /*PIPE_ACCESS_OUTBOUND*/ PIPE_ACCESS_DUPLEX, 1911 PIPE_READMODE_BYTE | PIPE_WAIT, 1912 10 /* nMaxInstances */, 1913 0x10000 /* nOutBuffer */, 1914 0x10000 /* nInBuffer */, 1915 NMPWAIT_WAIT_FOREVER, 1916 NULL /* pSecurityAttributes */); 1917 1918 if (hPipe == INVALID_HANDLE_VALUE) 1919 FatalDie("%s - CreateNamedPipe(%s) failed: %d\n", pszMsg, pszPipeName, GetLastError()); 1920 1921 pFDs[1 /* write */] = _open_osfhandle((intptr_t)hPipe, _O_WRONLY | _O_TEXT | _O_NOINHERIT); 1922 if (pFDs[1 /* write */] == -1) 1923 FatalDie("%s - _open_osfhandle failed: %d\n", pszMsg, strerror(errno)); 1924 } 1925 else if (_pipe(pFDs, 0, _O_NOINHERIT | _O_BINARY) < 0) 1821 1926 #else 1822 1927 if (pipe(pFDs) < 0) … … 1847 1952 pid_t pid; 1848 1953 1849 kOCEntryCreatePipe(pEntry, fds, pszMsg);1850 pid = kOCEntrySpawnChild(pEntry, papszArgv, cArgv, -1, fds[1 /* write */], pszMsg);1954 kOCEntryCreatePipe(pEntry, fds, NULL, pszMsg); 1955 pid = kOCEntrySpawnChild(pEntry, &pEntry->New.cMsCpp, papszArgv, cArgv, -1, fds[1 /* write */], pszMsg); 1851 1956 1852 1957 pfnConsumer(pEntry, fds[0 /* read */]); 1853 1958 1854 kOCEntryWaitChild(pEntry, pid, pszMsg);1855 } 1856 1857 1858 /** 1859 * Spawns a child that consumes input on stdin .1959 kOCEntryWaitChild(pEntry, &pEntry->New.cMsCpp, pid, pszMsg); 1960 } 1961 1962 1963 /** 1964 * Spawns a child that consumes input on stdin or via a named pipe. 1860 1965 * 1861 1966 * @param papszArgv Argument vector. The cArgv element is NULL. … … 1871 1976 pid_t pid; 1872 1977 1873 kOCEntryCreatePipe(pEntry, fds, pszMsg); 1874 pid = kOCEntrySpawnChild(pEntry, papszArgv, cArgv, fds[0 /* read */], -1, pszMsg); 1978 kOCEntryCreatePipe(pEntry, fds, pEntry->pszNmPipeCompile, pszMsg); 1979 pid = kOCEntrySpawnChild(pEntry, &pEntry->New.cMsCompile, papszArgv, cArgv, fds[0 /* read */], -1, pszMsg); 1980 #ifdef __WIN__ 1981 if (pEntry->pszNmPipeCompile && !ConnectNamedPipe((HANDLE)_get_osfhandle(fds[1 /* write */]), NULL)) 1982 FatalDie("compile - ConnectNamedPipe failed: %d\n", GetLastError()); 1983 #endif 1875 1984 1876 1985 pfnProducer(pEntry, fds[1 /* write */]); 1877 1986 1878 kOCEntryWaitChild(pEntry, pid, pszMsg);1987 kOCEntryWaitChild(pEntry, &pEntry->New.cMsCompile, pid, pszMsg); 1879 1988 } 1880 1989 … … 1901 2010 * The producer. 1902 2011 */ 1903 kOCEntryCreatePipe(pEntry, fds, pszMsg);1904 pidConsumer = kOCEntrySpawnChild(pEntry, papszProdArgv, cProdArgv, -1, fds[1 /* write */], pszMsg);2012 kOCEntryCreatePipe(pEntry, fds, NULL, pszMsg); 2013 pidConsumer = kOCEntrySpawnChild(pEntry, &pEntry->New.cMsCpp, papszProdArgv, cProdArgv, -1, fds[1 /* write */], pszMsg); 1905 2014 fdIn = fds[0 /* read */]; 1906 2015 … … 1908 2017 * The consumer. 1909 2018 */ 1910 kOCEntryCreatePipe(pEntry, fds, p szMsg);1911 pidProducer = kOCEntrySpawnChild(pEntry, papszConsArgv, cConsArgv, fds[0 /* read */], -1, pszMsg);2019 kOCEntryCreatePipe(pEntry, fds, pEntry->pszNmPipeCompile, pszMsg); 2020 pidProducer = kOCEntrySpawnChild(pEntry, &pEntry->New.cMsCompile, papszConsArgv, cConsArgv, fds[0 /* read */], -1, pszMsg); 1912 2021 fdOut = fds[1 /* write */]; 1913 2022 … … 1920 2029 * Reap the children. 1921 2030 */ 1922 kOCEntryWaitChild(pEntry, pidProducer, pszMsg);1923 kOCEntryWaitChild(pEntry, pidConsumer, pszMsg);2031 kOCEntryWaitChild(pEntry, &pEntry->New.cMsCpp, pidProducer, pszMsg); 2032 kOCEntryWaitChild(pEntry, &pEntry->New.cMsCompile, pidConsumer, pszMsg); 1924 2033 } 1925 2034 … … 2072 2181 */ 2073 2182 InfoMsg(3, "precompiling -> '%s'...\n", pEntry->New.pszCppName); 2074 kOCEntrySpawn(pEntry, papszArgvPreComp, cArgvPreComp, "precompile", NULL);2183 kOCEntrySpawn(pEntry, &pEntry->New.cMsCpp, papszArgvPreComp, cArgvPreComp, "precompile", NULL); 2075 2184 kOCEntryReadCppOutput(pEntry, &pEntry->New, 0 /* fatal */); 2076 2185 kOCEntryCalcChecksum(pEntry); … … 2159 2268 if (errno == EINTR) 2160 2269 continue; 2270 #ifdef __WIN__ /* HACK */ 2271 if ( errno == EINVAL 2272 && pEntry->pszNmPipeCompile 2273 && DisconnectNamedPipe((HANDLE)_get_osfhandle(fdOut)) 2274 && ConnectNamedPipe((HANDLE)_get_osfhandle(fdOut), NULL)) 2275 { 2276 psz = pEntry->New.pszCppMapping; 2277 cbLeft = (long)pEntry->New.cbCpp; 2278 } 2279 FatalDie("compile - write(%d,,%ld) failed: %s - _doserrno=%d\n", fdOut, cbLeft, strerror(errno), _doserrno); 2280 #else 2161 2281 FatalDie("compile - write(%d,,%ld) failed: %s\n", fdOut, cbLeft, strerror(errno)); 2282 #endif 2162 2283 } 2163 2284 psz += cbWritten; … … 2202 2323 kOCEntryReadCppOutput(pEntry, &pEntry->New, 0 /* fatal */); 2203 2324 InfoMsg(3, "compiling -> '%s'...\n", pEntry->New.pszObjName); 2204 kOCEntrySpawnConsumer(pEntry, (const char * const *)pEntry->New.papszArgvCompile, pEntry->New.cArgvCompile,2205 "compile", kOCEntryCompileProducer);2325 kOCEntrySpawnConsumer(pEntry, (const char * const *)pEntry->New.papszArgvCompile, 2326 pEntry->New.cArgvCompile, "compile", kOCEntryCompileProducer); 2206 2327 } 2207 2328 else … … 2210 2331 kOCEntryWriteCppOutput(pEntry, 1 /* free it */); 2211 2332 InfoMsg(3, "compiling -> '%s'...\n", pEntry->New.pszObjName); 2212 kOCEntrySpawn(pEntry, (const char * const *)pEntry->New.papszArgvCompile, pEntry->New.cArgvCompile, "compile", NULL); 2333 kOCEntrySpawn(pEntry, &pEntry->New.cMsCompile, (const char * const *)pEntry->New.papszArgvCompile, 2334 pEntry->New.cArgvCompile, "compile", NULL); 2213 2335 } 2214 2336 } … … 2227 2349 static void kOCEntryTeeConsumer(PKOCENTRY pEntry, int fdIn, int fdOut) 2228 2350 { 2351 #ifdef __WIN__ 2352 unsigned fConnectedToCompiler = fdOut == -1 || pEntry->pszNmPipeCompile == NULL; 2353 #endif 2229 2354 KOCSUMCTX Ctx; 2230 2355 long cbLeft; … … 2259 2384 psz[cbRead] = '\0'; 2260 2385 kOCSumUpdate(&pEntry->New.SumHead, &Ctx, psz, cbRead); 2386 #ifdef __WIN__ 2387 if ( !fConnectedToCompiler 2388 && !(fConnectedToCompiler = ConnectNamedPipe((HANDLE)_get_osfhandle(fdOut), NULL))) 2389 FatalDie("precompile|compile - ConnectNamedPipe failed: %d\n", GetLastError()); 2390 #endif 2261 2391 do 2262 2392 { … … 3695 3825 " <-f|--file <local-cache-file>>\n" 3696 3826 " <-t|--target <target-name>>\n" 3697 " [-r|--redir-stdout] [-p|--passthru] \n"3827 " [-r|--redir-stdout] [-p|--passthru] [--named-pipe-compile <pipename>]\n" 3698 3828 " --kObjCache-cpp <filename> <precompiler + args>\n" 3699 3829 " --kObjCache-cc <object> <compiler + args>\n" … … 3733 3863 const char *pszObjName = NULL; 3734 3864 int fRedirCompileStdIn = 0; 3865 const char *pszNmPipeCompile; 3735 3866 3736 3867 const char *pszTarget = NULL; … … 3831 3962 pszTarget = argv[++i]; 3832 3963 } 3964 else if (!strcmp(argv[i], "--named-pipe-compile")) 3965 { 3966 if (i + 1 >= argc) 3967 return SyntaxError("%s requires a pipe name!\n", argv[i]); 3968 pszNmPipeCompile = argv[++i]; 3969 fRedirCompileStdIn = 0; 3970 } 3833 3971 else if (!strcmp(argv[i], "-p") || !strcmp(argv[i], "--passthru")) 3834 3972 fRedirPreCompStdOut = fRedirCompileStdIn = 1; … … 3848 3986 { 3849 3987 printf("kObjCache - kBuild version %d.%d.%d ($Revision$)\n" 3850 "Copyright (c) 2007-20 09knut st. osmundsen\n",3988 "Copyright (c) 2007-2011 knut st. osmundsen\n", 3851 3989 KBUILD_VERSION_MAJOR, KBUILD_VERSION_MINOR, KBUILD_VERSION_PATCH); 3852 3990 return 0; … … 3903 4041 kOCEntrySetTarget(pEntry, pszTarget); 3904 4042 kOCEntrySetCppName(pEntry, pszPreCompName); 3905 kOCEntrySetPipedMode(pEntry, fRedirPreCompStdOut, fRedirCompileStdIn );4043 kOCEntrySetPipedMode(pEntry, fRedirPreCompStdOut, fRedirCompileStdIn, pszNmPipeCompile); 3906 4044 3907 4045 /*
Note:
See TracChangeset
for help on using the changeset viewer.