From: leanid Date: Thu, 20 Nov 2014 13:10:03 +0000 (+0300) Subject: fix windows build and successfully tested on windows with android NDK X-Git-Tag: v3.2.2~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=971a78da13c6f9f458e627d9550bc81f95102182;p=thirdparty%2Fccache.git fix windows build and successfully tested on windows with android NDK --- diff --git a/ccache.c b/ccache.c index 1be106b87..b6afe844e 100644 --- a/ccache.c +++ b/ccache.c @@ -802,9 +802,20 @@ to_cache(struct args *args) char *tmp_stderr2; tmp_stderr2 = format("%s.2", tmp_stderr); - if (x_rename(tmp_stderr, tmp_stderr2)) { +#ifdef _WIN32 + // on Windows file descriptor should be closed before rename + int prev_stderr_fd = tmp_stderr_fd; + close(tmp_stderr_fd); +#endif + int rename_result = x_rename(tmp_stderr, tmp_stderr2); +#ifdef _WIN32 + tmp_stderr_fd = create_tmp_fd(&tmp_stderr); + assert(prev_stderr_fd == tmp_stderr_fd); +#endif + if (rename_result) { + const char* err_str = strerror(errno); cc_log("Failed to rename %s to %s: %s", tmp_stderr, tmp_stderr2, - strerror(errno)); + err_str); failed(); } fd_cpp_stderr = open(cpp_stderr, O_RDONLY | O_BINARY); @@ -990,6 +1001,8 @@ get_object_name_from_cpp(struct args *args, struct mdfour *hash) time_of_compilation = time(NULL); + int path_stdout_fd = -1; + if (direct_i_file) { /* We are compiling a .i or .ii file - that means we can skip the cpp stage * and directly form the correct i_tmpfile. */ @@ -997,7 +1010,6 @@ get_object_name_from_cpp(struct args *args, struct mdfour *hash) status = 0; } else { /* Run cpp on the input file to obtain the .i. */ - int path_stdout_fd; path_stdout = format("%s/%s.stdout", temp_dir(), input_base); path_stdout_fd = create_tmp_fd(&path_stdout); add_pending_tmp_file(path_stdout); @@ -1046,7 +1058,21 @@ get_object_name_from_cpp(struct args *args, struct mdfour *hash) /* i_tmpfile needs the proper cpp_extension for the compiler to do its * thing correctly. */ i_tmpfile = format("%s.%s", path_stdout, conf->cpp_extension); +#ifdef _WIN32 + // on Windows rename only if file descriptor closed + if (path_stdout_fd != -1) + { + close(path_stdout_fd); + } +#endif x_rename(path_stdout, i_tmpfile); +#ifdef _WIN32 + if (path_stdout_fd != -1) + { + int tmp_fd = create_tmp_fd(&path_stdout); + assert(tmp_fd == path_stdout_fd); + } +#endif add_pending_tmp_file(i_tmpfile); } @@ -1150,11 +1176,32 @@ calculate_common_hash(struct args *args, struct mdfour *hash) hash_delimiter(hash, "ext"); hash_string(hash, conf->cpp_extension); +#ifdef _WIN32 + const char* ext = strchr(args->argv[0], '.'); + char full_path_win_ext[MAX_PATH] = {0}; + strncat(full_path_win_ext, args->argv[0], MAX_PATH); + if (!ext + || (strcmp(".exe", ext) != 0 + && strcmp(".bat", ext) != 0 + && strcmp(".EXE", ext) != 0 + && strcmp(".BAT", ext) != 0 + ) + ) + { + strncat(full_path_win_ext, ".exe", MAX_PATH); + } + if (stat(full_path_win_ext, &st) != 0) { + cc_log("Couldn't stat compiler %s: %s", args->argv[0], strerror(errno)); + stats_update(STATS_COMPILER); + failed(); + } +#else if (stat(args->argv[0], &st) != 0) { cc_log("Couldn't stat compiler %s: %s", args->argv[0], strerror(errno)); stats_update(STATS_COMPILER); failed(); } +#endif /* * Hash information about the compiler. diff --git a/ccache.h b/ccache.h index 6fdd55f6c..461831360 100644 --- a/ccache.h +++ b/ccache.h @@ -251,7 +251,7 @@ typedef int (*COMPAR_FN_T)(const void *, const void *); char *win32argvtos(char *prefix, char **argv); char *win32getshell(char *path); int win32execute(char *path, char **argv, int doreturn, - const char *path_stdout, const char *path_stderr); + int fd_stdout, int fd_stderr); # ifndef _WIN32_WINNT # define _WIN32_WINNT 0x0501 # endif @@ -259,8 +259,7 @@ int win32execute(char *path, char **argv, int doreturn, # define mkdir(a,b) mkdir(a) # define link(src,dst) (CreateHardLink(dst,src,NULL) ? 0 : -1) # define lstat(a,b) stat(a,b) -# define execv(a,b) win32execute(a,b,0,NULL,NULL) -#error TODO: Adapt win32execute to new execute API +# define execv(a,b) win32execute(a,b,0,0,0) # define execute(a,b,c) win32execute(*(a),a,1,b,c) # define PATH_DELIM ";" # define F_RDLCK 0 diff --git a/execute.c b/execute.c index 78f1e4b78..52a9b9897 100644 --- a/execute.c +++ b/execute.c @@ -119,7 +119,7 @@ win32getshell(char *path) int win32execute(char *path, char **argv, int doreturn, - const char *path_stdout, const char *path_stderr) + int fd_stdout, int fd_stderr) { PROCESS_INFORMATION pi; STARTUPINFO si; @@ -136,29 +136,60 @@ win32execute(char *path, char **argv, int doreturn, path = sh; si.cb = sizeof(STARTUPINFO); - if (path_stdout) { - SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE }; - si.hStdOutput = CreateFile(path_stdout, GENERIC_WRITE, 0, &sa, - CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | - FILE_FLAG_SEQUENTIAL_SCAN, NULL); - si.hStdError = CreateFile(path_stderr, GENERIC_WRITE, 0, &sa, - CREATE_ALWAYS, FILE_ATTRIBUTE_TEMPORARY | - FILE_FLAG_SEQUENTIAL_SCAN, NULL); - si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); - si.dwFlags = STARTF_USESTDHANDLES; - if (si.hStdOutput == INVALID_HANDLE_VALUE || - si.hStdError == INVALID_HANDLE_VALUE) + if (fd_stdout != -1) { + si.hStdOutput = (HANDLE)_get_osfhandle(fd_stdout); + si.hStdError = (HANDLE)_get_osfhandle(fd_stderr); + + si.hStdInput = GetStdHandle(STD_INPUT_HANDLE); + si.dwFlags = STARTF_USESTDHANDLES; + if (si.hStdOutput == INVALID_HANDLE_VALUE + || si.hStdError == INVALID_HANDLE_VALUE) { return -1; + } } args = win32argvtos(sh, argv); - ret = CreateProcess(path, args, NULL, NULL, 1, 0, NULL, NULL, &si, &pi); - free(args); - if (path_stdout) { - CloseHandle(si.hStdOutput); - CloseHandle(si.hStdError); + + const char* ext = strchr(path, '.'); + char full_path_win_ext[MAX_PATH] = { 0 }; + strncat(full_path_win_ext, path, MAX_PATH); + if (!ext + || (strcmp(".exe", ext) != 0 && strcmp(".bat", ext) != 0 + && strcmp(".EXE", ext) != 0 && strcmp(".BAT", ext) != 0)) { + strncat(full_path_win_ext, ".exe", MAX_PATH); } - if (ret == 0) + + ret = CreateProcess(full_path_win_ext, args, NULL, NULL, 1, 0, NULL, NULL, + &si, &pi); + free(args); + if (ret == 0) { + LPVOID lpMsgBuf; + LPVOID lpDisplayBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, + 0, NULL); + + lpDisplayBuf = + (LPVOID) LocalAlloc(LMEM_ZEROINIT, + (lstrlen((LPCTSTR) lpMsgBuf) + + lstrlen((LPCTSTR) __FILE__) + 200) + * sizeof(TCHAR)); + _snprintf((LPTSTR) lpDisplayBuf, + LocalSize(lpDisplayBuf) / sizeof(TCHAR), + TEXT("%s failed with error %d: %s"), __FILE__, dw, lpMsgBuf); + + cc_log("can't execute %s\nOS returned error: %s\n", + full_path_win_ext, (char*)lpDisplayBuf); + + LocalFree(lpMsgBuf); + LocalFree(lpDisplayBuf); + return -1; + } WaitForSingleObject(pi.hProcess, INFINITE); GetExitCodeProcess(pi.hProcess, &exitcode); CloseHandle(pi.hProcess); diff --git a/util.c b/util.c index 80eb58b6e..72e641f98 100644 --- a/util.c +++ b/util.c @@ -494,12 +494,73 @@ create_parent_dirs(const char *path) const char * get_hostname(void) { - static char hostname[200] = ""; + static char hostname[260] = ""; if (!hostname[0]) { strcpy(hostname, "unknown"); #if HAVE_GETHOSTNAME gethostname(hostname, sizeof(hostname)-1); +#elif defined(_WIN32) + + const char* computer_name = getenv("COMPUTERNAME"); + if (computer_name) + { + strncpy(hostname, computer_name, sizeof(hostname) -1); + return hostname; + } + + WORD wVersionRequested; + WSADATA wsaData; + int err; + + wVersionRequested = MAKEWORD(2, 2); + + err = WSAStartup(wVersionRequested, &wsaData); + if (err != 0) { + /* Tell the user that we could not find a usable */ + /* Winsock DLL. */ + cc_log("WSAStartup failed with error: %d\n", err); + return hostname; + } + + if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) { + /* Tell the user that we could not find a usable */ + /* WinSock DLL. */ + cc_log("Could not find a usable version of Winsock.dll\n"); + WSACleanup(); + return hostname; + } + + int result = gethostname(hostname, sizeof(hostname)-1); + if (result != 0) + { + int last_error = WSAGetLastError(); + LPVOID lpMsgBuf; + LPVOID lpDisplayBuf; + DWORD dw = last_error; + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + (LPTSTR) &lpMsgBuf, 0, NULL); + + lpDisplayBuf = (LPVOID) LocalAlloc(LMEM_ZEROINIT, + (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) __FILE__) + + 200) * sizeof(TCHAR)); + _snprintf((LPTSTR) lpDisplayBuf, + LocalSize(lpDisplayBuf) / sizeof(TCHAR), + TEXT("%s failed with error %d: %s"), __FILE__, dw, + lpMsgBuf); + + cc_log("can't get hostname OS returned error: %s\n", + (char*) lpDisplayBuf); + + LocalFree(lpMsgBuf); + LocalFree(lpDisplayBuf); + } + WSACleanup(); #endif hostname[sizeof(hostname)-1] = 0; } @@ -986,9 +1047,16 @@ x_realpath(const char *path) path_handle = CreateFile( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); - GetFinalPathNameByHandle(path_handle, ret, maxlen, FILE_NAME_NORMALIZED); - CloseHandle(path_handle); - p = ret+4;// strip the \\?\ from the file name + if(INVALID_HANDLE_VALUE != path_handle) + { + GetFinalPathNameByHandle(path_handle, ret, maxlen, FILE_NAME_NORMALIZED); + CloseHandle(path_handle); + p = ret+4;// strip the \\?\ from the file name + } else + { + strncpy(ret, path, maxlen); + p = ret; + } #else /* yes, there are such systems. This replacement relies on the fact that when we call x_realpath we only care about symlinks */ @@ -1301,14 +1369,47 @@ update_mtime(const char *path) /* * Rename oldpath to newpath (deleting newpath). */ + int x_rename(const char *oldpath, const char *newpath) { #ifdef _WIN32 /* Windows' rename() refuses to overwrite an existing file. */ unlink(newpath); /* not x_unlink, as x_unlink calls x_rename */ -#endif + /*If the function succeeds, the return value is nonzero.*/ + if (MoveFileA(oldpath, newpath) == 0) + { + LPVOID lpMsgBuf; + LPVOID lpDisplayBuf; + DWORD dw = GetLastError(); + + FormatMessage( + FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, + 0, NULL); + + lpDisplayBuf = (LPVOID) LocalAlloc(LMEM_ZEROINIT, + (lstrlen((LPCTSTR) lpMsgBuf) + lstrlen((LPCTSTR) __FILE__) + 40) + * sizeof(TCHAR)); + _snprintf((LPTSTR) lpDisplayBuf, + LocalSize(lpDisplayBuf) / sizeof(TCHAR), + TEXT("%s failed with error %d: %s"), __FILE__, dw, lpMsgBuf); + + cc_log("can't rename file %s to %s OS returned error: %s\n", + oldpath, newpath, (char*) lpDisplayBuf); + + LocalFree(lpMsgBuf); + LocalFree(lpDisplayBuf); + return -1; + } else + { + return 0; + } +#else return rename(oldpath, newpath); +#endif } /*