Author: cfinck Date: Sun Jul 6 15:49:03 2008 New Revision: 34343
URL: http://svn.reactos.org/svn/reactos?rev=34343&view=rev Log: Remixed our Win32 version of ccache: - Mix in parts of a patch by Brant Young, which itself is based on an old patch by Filip (see http://code.google.com/p/ccache-win32/wiki/WhyNativeWin32Ccache) - Change bInheritHandles for the CreateProcess call in failed() to TRUE, so that the compilation of the RC files works (they are preprocessed with gcc and piped to a file) - Add a safe version of mkstemp based on glibc sources, so that we don't run into race condition problems - Use CSIDL_LOCAL_APPDATA as the default base path for the ccache directory, not CSIDL_PROFILE
Added: trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/mkstemp.c (with props) Modified: trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/Makefile trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache-win32.vcproj trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache.c trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache.h trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/execute.c trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/unify.c trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/util.c
Modified: trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/Makefile URL: http://svn.reactos.org/svn/reactos/trunk/tools/RosBE/RosBE-Windows/Tools/cca... ============================================================================== --- trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/Makefile [iso-8859-1] (original) +++ trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/Makefile [iso-8859-1] Sun Jul 6 15:49:03 2008 @@ -9,7 +9,7 @@ CC=gcc CFLAGS := -Wall -pedantic -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0400 -O2 LFLAGS := -s -SRCS := args.c ccache.c cleanup.c execute.c getopt.c hash.c mdfour.c snprintf.c stats.c unify.c util.c win32-dirent.c +SRCS := args.c ccache.c cleanup.c execute.c getopt.c hash.c mdfour.c mkstemp.c snprintf.c stats.c unify.c util.c win32-dirent.c OBJS := $(SRCS:.c=.o)
$(TARGET): $(OBJS)
Modified: trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache-win32.vcproj URL: http://svn.reactos.org/svn/reactos/trunk/tools/RosBE/RosBE-Windows/Tools/cca... ============================================================================== --- trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache-win32.vcproj [iso-8859-1] (original) +++ trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache-win32.vcproj [iso-8859-1] Sun Jul 6 15:49:03 2008 @@ -112,7 +112,7 @@ /> <Tool Name="VCCLCompilerTool" - PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS" + PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS" RuntimeLibrary="2" UsePrecompiledHeader="0" WarningLevel="4" @@ -197,6 +197,10 @@ > </File> <File + RelativePath=".\mkstemp.c" + > + </File> + <File RelativePath=".\snprintf.c" > </File>
Modified: trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache.c URL: http://svn.reactos.org/svn/reactos/trunk/tools/RosBE/RosBE-Windows/Tools/cca... ============================================================================== --- trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache.c [iso-8859-1] (original) +++ trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache.c [iso-8859-1] Sun Jul 6 15:49:03 2008 @@ -165,7 +165,7 @@
si.cb = sizeof(STARTUPINFOA);
- if(!CreateProcessA(orig_args->argv[0], merged, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi)) + if(!CreateProcessA(orig_args->argv[0], merged, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) { perror(orig_args->argv[0]); exit(1);
Modified: trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache.h URL: http://svn.reactos.org/svn/reactos/trunk/tools/RosBE/RosBE-Windows/Tools/cca... ============================================================================== --- trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache.h [iso-8859-1] (original) +++ trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/ccache.h [iso-8859-1] Sun Jul 6 15:49:03 2008 @@ -42,8 +42,7 @@ #define mkdir(dirname, access) _mkdir(dirname) #define x_realpath(a) strdup(a) #define link(filename, linkname) CreateHardLinkA(linkname, filename, NULL) - #define PROT_READ 0x0001 - #define MAP_PRIVATE 0x02 + #define lstat(x, y) stat(x, y)
#ifdef _MSC_VER typedef unsigned int mode_t; @@ -55,7 +54,8 @@ #ifndef S_ISDIR #define S_ISDIR(m) (((m) & _S_IFDIR) == _S_IFDIR) #endif - #define lstat(x, y) stat(x, y) + + int mkstemp (char *template); #else #include <unistd.h> #include <sys/wait.h>
Modified: trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/execute.c URL: http://svn.reactos.org/svn/reactos/trunk/tools/RosBE/RosBE-Windows/Tools/cca... ============================================================================== --- trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/execute.c [iso-8859-1] (original) +++ trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/execute.c [iso-8859-1] Sun Jul 6 15:49:03 2008 @@ -18,16 +18,90 @@
#include "ccache.h"
+#ifdef _WIN32 +static char *argvtos(char **argv) +{ + int i, len; + char *ptr, *str; + + for (i = 0, len = 0; argv[i]; i++) { + len += strlen(argv[i]) + 3; + } + + str = ptr = (char *)malloc(len + 1); + if (str == NULL) + return NULL; + + for (i = 0; argv[i]; i++) { + len = strlen(argv[i]); + *ptr++ = '"'; + memcpy(ptr, argv[i], len); + ptr += len; + *ptr++ = '"'; + *ptr++ = ' '; + } + *ptr = 0; + + return str; +} +#endif
/* execute a compiler backend, capturing all output to the given paths the full path to the compiler to run is in argv[0] */ -int execute(char **argv, +int execute(char **argv, const char *path_stdout, const char *path_stderr) { -#ifndef _WIN32 +#ifdef _WIN32 + PROCESS_INFORMATION pinfo; + STARTUPINFOA sinfo; + BOOL ret; + DWORD exitcode; + char *args; + HANDLE fd_out, fd_err; + SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE}; + + fd_out = CreateFileA(path_stdout, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); + if (fd_out == INVALID_HANDLE_VALUE) { + return STATUS_NOCACHE; + } + + fd_err = CreateFileA(path_stderr, GENERIC_WRITE, 0, &sa, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + if (fd_err == INVALID_HANDLE_VALUE) { + return STATUS_NOCACHE; + } + + ZeroMemory(&pinfo, sizeof(PROCESS_INFORMATION)); + ZeroMemory(&sinfo, sizeof(STARTUPINFOA)); + + sinfo.cb = sizeof(STARTUPINFOA); + sinfo.hStdError = fd_err; + sinfo.hStdOutput = fd_out; + sinfo.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + sinfo.dwFlags |= STARTF_USESTDHANDLES; + + args = argvtos(argv); + + ret = CreateProcessA(argv[0], args, NULL, NULL, TRUE, 0, NULL, NULL, + &sinfo, &pinfo); + + free(args); + CloseHandle(fd_out); + CloseHandle(fd_err); + + if (ret == 0) + return -1; + + WaitForSingleObject(pinfo.hProcess, INFINITE); + GetExitCodeProcess(pinfo.hProcess, &exitcode); + CloseHandle(pinfo.hProcess); + CloseHandle(pinfo.hThread); + + return exitcode; +#else pid_t pid; int status;
@@ -65,46 +139,6 @@ }
return WEXITSTATUS(status); -#else /* Should be portable */ - int status = -2; - int fd, std_od = -1, std_ed = -1; - - unlink(path_stdout); - std_od = _dup(1); - fd = _open(path_stdout, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); - if (fd == -1) { - status = STATUS_NOCACHE; - cc_log("stdout error: failed to open %s\n", path_stdout); - goto out; - } - /*std_od = */ _dup2(fd, 1); - _close(fd); - - unlink(path_stderr); - fd = _open(path_stderr, O_WRONLY|O_CREAT|O_TRUNC|O_EXCL|O_BINARY, 0666); - std_ed = _dup(2); - if (fd == -1) { - status = STATUS_NOCACHE; - cc_log("stderr error: failed to open %s\n", path_stderr); - goto out; - } - /*std_ed =*/ _dup2(fd, 2); - _close(fd); - - /* Spawn process (_exec* familly doesn't return) */ - status = _spawnv(_P_WAIT, argv[0], (const char* const*)argv); - - out: - cc_log("%s:\n stdout -> %s\n stderr -> %s\n process status=%i\n", - argv[0], path_stdout, path_stderr, status); - if (status == -1) cc_log("Error %i: %s\n", errno, strerror(errno)); - - /* Restore descriptors */ - if (std_od != -1) _dup2(std_od, 1); - if (std_ed != -1) _dup2(std_ed, 2); - _flushall(); - - return (status>0); #endif }
@@ -158,11 +192,24 @@ */ char *find_executable(const char *name, const char *exclude_name) { +#ifdef _WIN32 + DWORD ret; + char namebuf[MAX_PATH]; + + UNREFERENCED_PARAMETER(exclude_name); + + ret = SearchPathA(getenv("CCACHE_PATH"), name, ".exe", sizeof(namebuf), namebuf, NULL); + if (ret != 0) { + return x_strdup(namebuf); + } + + return NULL; +#else char *path; char *tok; - const char *sep = ":"; - - if (*name == PATH_SEP_CHAR) { + struct stat st1, st2; + + if (*name == '/') { return x_strdup(name); }
@@ -177,37 +224,40 @@
path = x_strdup(path); - /* Determine path separator */ - if (strchr(path, ';')) sep = ";"; - /* search the path looking for the first compiler of the right name that isn't us */ - for (tok=strtok(path, sep); tok; tok = strtok(NULL, sep)) { + for (tok=strtok(path,":"); tok; tok = strtok(NULL, ":")) { char *fname; - x_asprintf(&fname, "%s"PATH_SEP"%s", tok, name); + x_asprintf(&fname, "%s/%s", tok, name); /* look for a normal executable file */ - - - if (is_exec_file(fname, exclude_name) > 0) - { + if (access(fname, X_OK) == 0 && + lstat(fname, &st1) == 0 && + stat(fname, &st2) == 0 && + S_ISREG(st2.st_mode)) { + /* if its a symlink then ensure it doesn't + point at something called exclude_name */ + if (S_ISLNK(st1.st_mode)) { + char *buf = x_realpath(fname); + if (buf) { + char *p = str_basename(buf); + if (strcmp(p, exclude_name) == 0) { + /* its a link to "ccache" ! */ + free(p); + free(buf); + continue; + } + free(buf); + free(p); + } + } + + /* found it! */ free(path); return fname; } free(fname); - - /* found it! */ -#ifdef _WIN32 /* Add .exe under win32 */ - x_asprintf(&fname, "%s"PATH_SEP"%s.exe", tok, name); - - /* look for a normal executable file */ - if (is_exec_file(fname, exclude_name) > 0) - { - free(path); - return fname; - } - free(fname); -#endif - } -free(path); + } + return NULL; -} +#endif +}
Added: trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/mkstemp.c URL: http://svn.reactos.org/svn/reactos/trunk/tools/RosBE/RosBE-Windows/Tools/cca... ============================================================================== --- trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/mkstemp.c (added) +++ trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/mkstemp.c [iso-8859-1] Sun Jul 6 15:49:03 2008 @@ -1,0 +1,84 @@ +#ifdef _WIN32 +/* Copyright (C) 1998, 1999, 2001, 2007 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, write to the Free + Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA + 02111-1307 USA. */ + +/* Ported for ccache-win32 by Colin Finck colin@reactos.org + Source: http://sources.redhat.com/cgi-bin/cvsweb.cgi/libc/sysdeps/posix/tempname.c?r... +*/ + +#include "ccache.h" + +/* These are the characters used in temporary filenames. */ +static const char letters[] = +"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; + +/* Generate a unique temporary file name from TEMPLATE. + The last six characters of TEMPLATE must be "XXXXXX"; + they are replaced with a string that makes the filename unique. + Then open the file and return a fd. */ +int +mkstemp (char *template) +{ + char *XXXXXX; + time_t value; + unsigned int count; + int fd; + + /* A lower bound on the number of temporary files to attempt to + generate. The maximum total number of temporary file names that + can exist for a given template is 62**6. It should never be + necessary to try all these combinations. Instead if a reasonable + number of names is tried (we define reasonable as 62**3) fail to + give the system administrator the chance to remove the problems. */ + unsigned int attempts = (62 * 62 * 62); + + /* This is where the Xs start. */ + XXXXXX = &template[ strlen(template) - 6 ]; + + /* Get some more or less random data. */ + value = time(NULL) ^ _getpid(); + + for (count = 0; count < attempts; value += 7777, ++count) + { + time_t v = value; + + /* Fill in the random bits. */ + XXXXXX[0] = letters[v % 62]; + v /= 62; + XXXXXX[1] = letters[v % 62]; + v /= 62; + XXXXXX[2] = letters[v % 62]; + v /= 62; + XXXXXX[3] = letters[v % 62]; + v /= 62; + XXXXXX[4] = letters[v % 62]; + v /= 62; + XXXXXX[5] = letters[v % 62]; + + fd = _open (template, O_RDWR | O_BINARY | O_CREAT | O_EXCL, 0600); + + if (fd >= 0) + return fd; + else if (errno != EEXIST) + return -1; + } + + /* We got out of the loop because we ran out of combinations to try. */ + return -1; +} +#endif
Propchange: trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/mkstemp.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/unify.c URL: http://svn.reactos.org/svn/reactos/trunk/tools/RosBE/RosBE-Windows/Tools/cca... ============================================================================== --- trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/unify.c [iso-8859-1] (original) +++ trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/unify.c [iso-8859-1] Sun Jul 6 15:49:03 2008 @@ -238,10 +238,40 @@ */ int unify_hash(const char *fname) { +#ifdef _WIN32 + HANDLE file; + HANDLE section; + MEMORY_BASIC_INFORMATION minfo; + char *map; + + file = CreateFileA(fname, GENERIC_READ, FILE_SHARE_READ, NULL, + OPEN_EXISTING, 0, NULL); + if (file == INVALID_HANDLE_VALUE) + return -1; + + section = CreateFileMappingA(file, NULL, PAGE_READONLY, 0, 0, NULL); + CloseHandle(file); + if (section == NULL) + return -1; + + map = MapViewOfFile(section, FILE_MAP_READ, 0, 0, 0); + CloseHandle(section); + if (map == NULL) + return -1; + + if (VirtualQuery(map, &minfo, sizeof(minfo)) != sizeof(minfo)) { + UnmapViewOfFile(map); + return -1; + } + + /* pass it through the unifier */ + unify((unsigned char *)map, minfo.RegionSize); + + UnmapViewOfFile(map); +#else int fd; struct stat st; char *map; - HANDLE view;
fd = open(fname, O_RDONLY|O_BINARY); if (fd == -1 || fstat(fd, &st) != 0) { @@ -250,33 +280,6 @@ return -1; }
-#ifdef _WIN32 - /* win32 equivalent of mmap is ViewMapOfFile, but malloc+read - may be better */ - view = CreateFileMapping((HANDLE)_get_osfhandle(fd), NULL, - PAGE_READONLY|SEC_COMMIT, 0,0 , NULL); - if (NULL == view) { - cc_log("Failed to create file mapping %s: %s\n", - fname, strerror(errno)); - stats_update(STATS_PREPROCESSOR); - return -1; - } - - map = MapViewOfFile(view, FILE_MAP_READ, 0, 0, st.st_size); - if (NULL == map) { - cc_log("Failed to map view of file %s: %s\n", - fname, strerror(errno)); - stats_update(STATS_PREPROCESSOR); - return -1; - } - - /* pass it through the unifier */ - unify((unsigned char *)map, st.st_size); - - UnmapViewOfFile(map); - CloseHandle(view); - close(fd); -#else /* we use mmap() to make it easy to handle arbitrarily long lines in preprocessor output. I have seen lines of over 100k in length, so this is well worth it */ @@ -292,6 +295,7 @@
munmap(map, st.st_size); #endif + return 0; }
Modified: trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/util.c URL: http://svn.reactos.org/svn/reactos/trunk/tools/RosBE/RosBE-Windows/Tools/cca... ============================================================================== --- trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/util.c [iso-8859-1] (original) +++ trunk/tools/RosBE/RosBE-Windows/Tools/ccache-2.4/util.c [iso-8859-1] Sun Jul 6 15:49:03 2008 @@ -20,19 +20,6 @@
static FILE *logfile;
-#ifdef _WIN32 -#define fchmod(a, b) -#endif - -#ifndef HAVE_MKSTEMP -/* cheap and nasty mkstemp replacement */ -int mkstemp(char *template) -{ - _mktemp(template); - return open(template, O_RDWR|O_CREAT|O_EXCL|O_BINARY, 0600); -} -#endif - /* log a message to the CCACHE_LOGFILE location */ void cc_log(const char *format, ...) { @@ -79,7 +66,10 @@ char buf[10240]; int n; char *tmp_name; + +#ifndef _WIN32 mode_t mask; +#endif
x_asprintf(&tmp_name, "%s.XXXXXX", dest);
@@ -109,9 +99,11 @@ close(fd1);
/* get perms right on the tmp file */ +#ifndef _WIN32 mask = umask(0); fchmod(fd2, 0666 & ~mask); umask(mask); +#endif
/* the close can fail on NFS if out of space */ if (close(fd2) == -1) { @@ -483,8 +475,8 @@ #ifdef _WIN32 static char szPath[MAX_PATH];
- /* "Documents and Settings\user\Application Data" is CSIDL_APPDATA */ - if(SHGetSpecialFolderPathA(NULL, szPath, CSIDL_PROFILE, FALSE)) + /* "Documents and Settings\user\Application Data" is CSIDL_LOCAL_APPDATA */ + if(SHGetSpecialFolderPathA(NULL, szPath, CSIDL_LOCAL_APPDATA, FALSE)) { return szPath; }