diff --git a/PC/VS9.0/_bz2.vcproj b/PC/VS9.0/_bz2.vcproj --- a/PC/VS9.0/_bz2.vcproj +++ b/PC/VS9.0/_bz2.vcproj @@ -1,7 +1,7 @@ diff --git a/PC/VS9.0/_ctypes.vcproj b/PC/VS9.0/_ctypes.vcproj --- a/PC/VS9.0/_ctypes.vcproj +++ b/PC/VS9.0/_ctypes.vcproj @@ -42,7 +42,7 @@ /> @@ -559,39 +559,39 @@ Name="Source Files" > @@ -511,7 +511,7 @@ Name="Source Files" > diff --git a/PC/VS9.0/_decimal.vcproj b/PC/VS9.0/_decimal.vcproj --- a/PC/VS9.0/_decimal.vcproj +++ b/PC/VS9.0/_decimal.vcproj @@ -1,7 +1,7 @@ @@ -605,67 +605,67 @@ Name="Source Files" > @@ -591,19 +591,19 @@ Name="Source Files" > diff --git a/PC/VS9.0/_hashlib.vcproj b/PC/VS9.0/_hashlib.vcproj --- a/PC/VS9.0/_hashlib.vcproj +++ b/PC/VS9.0/_hashlib.vcproj @@ -1,7 +1,7 @@ diff --git a/PC/VS9.0/_lzma.vcproj b/PC/VS9.0/_lzma.vcproj --- a/PC/VS9.0/_lzma.vcproj +++ b/PC/VS9.0/_lzma.vcproj @@ -1,7 +1,7 @@ diff --git a/PC/VS9.0/_msi.vcproj b/PC/VS9.0/_msi.vcproj --- a/PC/VS9.0/_msi.vcproj +++ b/PC/VS9.0/_msi.vcproj @@ -1,7 +1,7 @@ diff --git a/PC/VS9.0/_multiprocessing.vcproj b/PC/VS9.0/_multiprocessing.vcproj --- a/PC/VS9.0/_multiprocessing.vcproj +++ b/PC/VS9.0/_multiprocessing.vcproj @@ -1,7 +1,7 @@ @@ -527,11 +527,11 @@ Name="Source Files" > diff --git a/PC/VS9.0/_socket.vcproj b/PC/VS9.0/_socket.vcproj --- a/PC/VS9.0/_socket.vcproj +++ b/PC/VS9.0/_socket.vcproj @@ -1,7 +1,7 @@ @@ -527,7 +527,7 @@ Name="Source Files" > diff --git a/PC/VS9.0/_sqlite3.vcproj b/PC/VS9.0/_sqlite3.vcproj --- a/PC/VS9.0/_sqlite3.vcproj +++ b/PC/VS9.0/_sqlite3.vcproj @@ -527,43 +527,43 @@ Name="Header Files" > @@ -571,39 +571,39 @@ Name="Source Files" > diff --git a/PC/VS9.0/_ssl.vcproj b/PC/VS9.0/_ssl.vcproj --- a/PC/VS9.0/_ssl.vcproj +++ b/PC/VS9.0/_ssl.vcproj @@ -1,7 +1,7 @@ diff --git a/PC/VS9.0/_testbuffer.vcproj b/PC/VS9.0/_testbuffer.vcproj --- a/PC/VS9.0/_testbuffer.vcproj +++ b/PC/VS9.0/_testbuffer.vcproj @@ -511,7 +511,7 @@ Name="Source Files" > diff --git a/PC/VS9.0/_testcapi.vcproj b/PC/VS9.0/_testcapi.vcproj --- a/PC/VS9.0/_testcapi.vcproj +++ b/PC/VS9.0/_testcapi.vcproj @@ -1,7 +1,7 @@ diff --git a/PC/VS9.0/_tkinter.vcproj b/PC/VS9.0/_tkinter.vcproj --- a/PC/VS9.0/_tkinter.vcproj +++ b/PC/VS9.0/_tkinter.vcproj @@ -1,7 +1,7 @@ diff --git a/PC/VS9.0/bdist_wininst.vcproj b/PC/VS9.0/bdist_wininst.vcproj --- a/PC/VS9.0/bdist_wininst.vcproj +++ b/PC/VS9.0/bdist_wininst.vcproj @@ -20,7 +20,7 @@ @@ -247,7 +247,7 @@ Filter="h;hpp;hxx;hm;inl" > @@ -256,11 +256,11 @@ Filter="ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" > diff --git a/PC/VS9.0/kill_python.c b/PC/VS9.0/kill_python.c new file mode 100644 --- /dev/null +++ b/PC/VS9.0/kill_python.c @@ -0,0 +1,178 @@ +/* + * Helper program for killing lingering python[_d].exe processes before + * building, thus attempting to avoid build failures due to files being + * locked. + */ + +#include +#include +#include +#include + +#pragma comment(lib, "psapi") + +#ifdef _DEBUG +#define PYTHON_EXE (L"python_d.exe") +#define PYTHON_EXE_LEN (12) +#define KILL_PYTHON_EXE (L"kill_python_d.exe") +#define KILL_PYTHON_EXE_LEN (17) +#else +#define PYTHON_EXE (L"python.exe") +#define PYTHON_EXE_LEN (10) +#define KILL_PYTHON_EXE (L"kill_python.exe") +#define KILL_PYTHON_EXE_LEN (15) +#endif + +int +main(int argc, char **argv) +{ + HANDLE hp, hsp, hsm; /* process, snapshot processes, snapshot modules */ + DWORD dac, our_pid; + size_t len; + wchar_t path[MAX_PATH+1]; + + MODULEENTRY32W me; + PROCESSENTRY32W pe; + + me.dwSize = sizeof(MODULEENTRY32W); + pe.dwSize = sizeof(PROCESSENTRY32W); + + memset(path, 0, MAX_PATH+1); + + our_pid = GetCurrentProcessId(); + + hsm = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, our_pid); + if (hsm == INVALID_HANDLE_VALUE) { + printf("CreateToolhelp32Snapshot[1] failed: %d\n", GetLastError()); + return 1; + } + + if (!Module32FirstW(hsm, &me)) { + printf("Module32FirstW[1] failed: %d\n", GetLastError()); + CloseHandle(hsm); + return 1; + } + + /* + * Enumerate over the modules for the current process in order to find + * kill_process[_d].exe, then take a note of the directory it lives in. + */ + do { + if (_wcsnicmp(me.szModule, KILL_PYTHON_EXE, KILL_PYTHON_EXE_LEN)) + continue; + + len = wcsnlen_s(me.szExePath, MAX_PATH) - KILL_PYTHON_EXE_LEN; + wcsncpy_s(path, MAX_PATH+1, me.szExePath, len); + + break; + + } while (Module32NextW(hsm, &me)); + + CloseHandle(hsm); + + if (path == NULL) { + printf("failed to discern directory of running process\n"); + return 1; + } + + /* + * Take a snapshot of system processes. Enumerate over the snapshot, + * looking for python processes. When we find one, verify it lives + * in the same directory we live in. If it does, kill it. If we're + * unable to kill it, treat this as a fatal error and return 1. + * + * The rationale behind this is that we're called at the start of the + * build process on the basis that we'll take care of killing any + * running instances, such that the build won't encounter permission + * denied errors during linking. If we can't kill one of the processes, + * we can't provide this assurance, and the build shouldn't start. + */ + + hsp = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); + if (hsp == INVALID_HANDLE_VALUE) { + printf("CreateToolhelp32Snapshot[2] failed: %d\n", GetLastError()); + return 1; + } + + if (!Process32FirstW(hsp, &pe)) { + printf("Process32FirstW failed: %d\n", GetLastError()); + CloseHandle(hsp); + return 1; + } + + dac = PROCESS_QUERY_INFORMATION | PROCESS_VM_READ | PROCESS_TERMINATE; + do { + + /* + * XXX TODO: if we really wanted to be fancy, we could check the + * modules for all processes (not just the python[_d].exe ones) + * and see if any of our DLLs are loaded (i.e. python33[_d].dll), + * as that would also inhibit our ability to rebuild the solution. + * Not worth loosing sleep over though; for now, a simple check + * for just the python executable should be sufficient. + */ + + if (_wcsnicmp(pe.szExeFile, PYTHON_EXE, PYTHON_EXE_LEN)) + /* This isn't a python process. */ + continue; + + /* It's a python process, so figure out which directory it's in... */ + hsm = CreateToolhelp32Snapshot(TH32CS_SNAPMODULE, pe.th32ProcessID); + if (hsm == INVALID_HANDLE_VALUE) + /* + * If our module snapshot fails (which will happen if we don't own + * the process), just ignore it and continue. (It seems different + * versions of Windows return different values for GetLastError() + * in this situation; it's easier to just ignore it and move on vs. + * stopping the build for what could be a false positive.) + */ + continue; + + if (!Module32FirstW(hsm, &me)) { + printf("Module32FirstW[2] failed: %d\n", GetLastError()); + CloseHandle(hsp); + CloseHandle(hsm); + return 1; + } + + do { + if (_wcsnicmp(me.szModule, PYTHON_EXE, PYTHON_EXE_LEN)) + /* Wrong module, we're looking for python[_d].exe... */ + continue; + + if (_wcsnicmp(path, me.szExePath, len)) + /* Process doesn't live in our directory. */ + break; + + /* Python process residing in the right directory, kill it! */ + hp = OpenProcess(dac, FALSE, pe.th32ProcessID); + if (!hp) { + printf("OpenProcess failed: %d\n", GetLastError()); + CloseHandle(hsp); + CloseHandle(hsm); + return 1; + } + + if (!TerminateProcess(hp, 1)) { + printf("TerminateProcess failed: %d\n", GetLastError()); + CloseHandle(hsp); + CloseHandle(hsm); + CloseHandle(hp); + return 1; + } + + CloseHandle(hp); + break; + + } while (Module32NextW(hsm, &me)); + + CloseHandle(hsm); + + } while (Process32NextW(hsp, &pe)); + + CloseHandle(hsp); + + return 0; +} + +/* vi: set ts=8 sw=4 sts=4 expandtab */ diff --git a/PC/VS9.0/make_buildinfo.c b/PC/VS9.0/make_buildinfo.c new file mode 100644 --- /dev/null +++ b/PC/VS9.0/make_buildinfo.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include + +#define CMD_SIZE 500 + +/* This file creates the getbuildinfo.o object, by first + invoking subwcrev.exe (if found), and then invoking cl.exe. + As a side effect, it might generate PCBuild\getbuildinfo2.c + also. If this isn't a subversion checkout, or subwcrev isn't + found, it compiles ..\\..\\Modules\\getbuildinfo.c instead. + + Currently, subwcrev.exe is found from the registry entries + of TortoiseSVN. + + No attempt is made to place getbuildinfo.o into the proper + binary directory. This isn't necessary, as this tool is + invoked as a pre-link step for pythoncore, so that overwrites + any previous getbuildinfo.o. + + However, if a second argument is provided, this will be used + as a temporary directory where any getbuildinfo2.c and + getbuildinfo.o files are put. This is useful if multiple + configurations are being built in parallel, to avoid them + trampling each other's files. + +*/ + +int make_buildinfo2(const char *tmppath) +{ + struct _stat st; + HKEY hTortoise; + char command[CMD_SIZE+1]; + DWORD type, size; + if (_stat(".svn", &st) < 0) + return 0; + /* Allow suppression of subwcrev.exe invocation if a no_subwcrev file is present. */ + if (_stat("no_subwcrev", &st) == 0) + return 0; + if (RegOpenKey(HKEY_LOCAL_MACHINE, "Software\\TortoiseSVN", &hTortoise) != ERROR_SUCCESS && + RegOpenKey(HKEY_CURRENT_USER, "Software\\TortoiseSVN", &hTortoise) != ERROR_SUCCESS) + /* Tortoise not installed */ + return 0; + command[0] = '"'; /* quote the path to the executable */ + size = sizeof(command) - 1; + if (RegQueryValueEx(hTortoise, "Directory", 0, &type, command+1, &size) != ERROR_SUCCESS || + type != REG_SZ) + /* Registry corrupted */ + return 0; + strcat_s(command, CMD_SIZE, "bin\\subwcrev.exe"); + if (_stat(command+1, &st) < 0) + /* subwcrev.exe not part of the release */ + return 0; + strcat_s(command, CMD_SIZE, "\" ..\\.. ..\\..\\Modules\\getbuildinfo.c \""); + strcat_s(command, CMD_SIZE, tmppath); /* quoted tmppath */ + strcat_s(command, CMD_SIZE, "getbuildinfo2.c\""); + + puts(command); fflush(stdout); + if (system(command) < 0) + return 0; + return 1; +} + +const char DELIMS[] = { " \n" }; + +int get_mercurial_info(char * hgbranch, char * hgtag, char * hgrev, int size) +{ + int result = 0; + char filename[CMD_SIZE]; + char cmdline[CMD_SIZE]; + + strcpy_s(filename, CMD_SIZE, "tmpXXXXXX"); + if (_mktemp_s(filename, CMD_SIZE) == 0) { + int rc; + + strcpy_s(cmdline, CMD_SIZE, "hg id -bit > "); + strcat_s(cmdline, CMD_SIZE, filename); + rc = system(cmdline); + if (rc == 0) { + FILE * fp; + + if (fopen_s(&fp, filename, "r") == 0) { + char * cp = fgets(cmdline, CMD_SIZE, fp); + + if (cp) { + char * context = NULL; + char * tp = strtok_s(cp, DELIMS, &context); + if (tp) { + strcpy_s(hgrev, size, tp); + tp = strtok_s(NULL, DELIMS, &context); + if (tp) { + strcpy_s(hgbranch, size, tp); + tp = strtok_s(NULL, DELIMS, &context); + if (tp) { + strcpy_s(hgtag, size, tp); + result = 1; + } + } + } + } + fclose(fp); + } + } + _unlink(filename); + } + return result; +} + +int main(int argc, char*argv[]) +{ + char command[CMD_SIZE] = "cl.exe -c -D_WIN32 -DUSE_DL_EXPORT -D_WINDOWS -DWIN32 -D_WINDLL "; + char tmppath[CMD_SIZE] = ""; + int do_unlink, result; + char *tmpdir = NULL; + if (argc <= 2 || argc > 3) { + fprintf(stderr, "make_buildinfo $(ConfigurationName) [tmpdir]\n"); + return EXIT_FAILURE; + } + if (strcmp(argv[1], "Release") == 0) { + strcat_s(command, CMD_SIZE, "-MD "); + } + else if (strcmp(argv[1], "Debug") == 0) { + strcat_s(command, CMD_SIZE, "-D_DEBUG -MDd "); + } + else if (strcmp(argv[1], "ReleaseItanium") == 0) { + strcat_s(command, CMD_SIZE, "-MD /USECL:MS_ITANIUM "); + } + else if (strcmp(argv[1], "ReleaseAMD64") == 0) { + strcat_s(command, CMD_SIZE, "-MD "); + strcat_s(command, CMD_SIZE, "-MD /USECL:MS_OPTERON "); + } + else { + fprintf(stderr, "unsupported configuration %s\n", argv[1]); + return EXIT_FAILURE; + } + if (argc > 2) { + tmpdir = argv[2]; + strcat_s(tmppath, _countof(tmppath), tmpdir); + /* Hack fix for bad command line: If the command is issued like this: + * $(SolutionDir)make_buildinfo.exe" Debug "$(IntDir)" + * we will get a trailing quote because IntDir ends with a backslash that then + * escapes the final ". To simplify the life for developers, catch that problem + * here by cutting it off. + * The proper command line, btw is: + * $(SolutionDir)make_buildinfo.exe" Debug "$(IntDir)\" + * Hooray for command line parsing on windows. + */ + if (strlen(tmppath) > 0 && tmppath[strlen(tmppath)-1] == '"') + tmppath[strlen(tmppath)-1] = '\0'; + strcat_s(tmppath, _countof(tmppath), "\\"); + } + + if ((do_unlink = make_buildinfo2(tmppath))) { + strcat_s(command, CMD_SIZE, "\""); + strcat_s(command, CMD_SIZE, tmppath); + strcat_s(command, CMD_SIZE, "getbuildinfo2.c\" -DSUBWCREV "); + } + else { + char hgtag[CMD_SIZE]; + char hgbranch[CMD_SIZE]; + char hgrev[CMD_SIZE]; + + if (get_mercurial_info(hgbranch, hgtag, hgrev, CMD_SIZE)) { + strcat_s(command, CMD_SIZE, "-DHGBRANCH=\\\""); + strcat_s(command, CMD_SIZE, hgbranch); + strcat_s(command, CMD_SIZE, "\\\""); + + strcat_s(command, CMD_SIZE, " -DHGTAG=\\\""); + strcat_s(command, CMD_SIZE, hgtag); + strcat_s(command, CMD_SIZE, "\\\""); + + strcat_s(command, CMD_SIZE, " -DHGVERSION=\\\""); + strcat_s(command, CMD_SIZE, hgrev); + strcat_s(command, CMD_SIZE, "\\\" "); + } + strcat_s(command, CMD_SIZE, "..\\..\\Modules\\getbuildinfo.c"); + } + strcat_s(command, CMD_SIZE, " -Fo\""); + strcat_s(command, CMD_SIZE, tmppath); + strcat_s(command, CMD_SIZE, "getbuildinfo.o\" -I..\\..\\Include -I..\\..\\PC"); + puts(command); fflush(stdout); + result = system(command); + if (do_unlink) { + command[0] = '\0'; + strcat_s(command, CMD_SIZE, "\""); + strcat_s(command, CMD_SIZE, tmppath); + strcat_s(command, CMD_SIZE, "getbuildinfo2.c\""); + _unlink(command); + } + if (result < 0) + return EXIT_FAILURE; + return 0; +} diff --git a/PC/VS9.0/make_buildinfo.vcproj b/PC/VS9.0/make_buildinfo.vcproj --- a/PC/VS9.0/make_buildinfo.vcproj +++ b/PC/VS9.0/make_buildinfo.vcproj @@ -1,7 +1,7 @@ @@ -314,7 +314,7 @@ Name="Source Files" > diff --git a/PC/VS9.0/pcbuild.sln b/PC/VS9.0/pcbuild.sln --- a/PC/VS9.0/pcbuild.sln +++ b/PC/VS9.0/pcbuild.sln @@ -29,7 +29,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{553EC33E-9816-4996-A660-5D6186A0B0B3}" ProjectSection(SolutionItems) = preProject - ..\Modules\getbuildinfo.c = ..\Modules\getbuildinfo.c + ..\..\Modules\getbuildinfo.c = ..\..\Modules\getbuildinfo.c readme.txt = readme.txt EndProjectSection EndProject diff --git a/PC/VS9.0/pyexpat.vcproj b/PC/VS9.0/pyexpat.vcproj --- a/PC/VS9.0/pyexpat.vcproj +++ b/PC/VS9.0/pyexpat.vcproj @@ -1,7 +1,7 @@ @@ -531,19 +531,19 @@ Name="Source Files" > diff --git a/PC/VS9.0/pyproject.vsprops b/PC/VS9.0/pyproject.vsprops --- a/PC/VS9.0/pyproject.vsprops +++ b/PC/VS9.0/pyproject.vsprops @@ -11,7 +11,7 @@ Optimization="2" InlineFunctionExpansion="1" EnableIntrinsicFunctions="true" - AdditionalIncludeDirectories="..\Include; ..\PC" + AdditionalIncludeDirectories="..\..\Include; ..\..\PC" PreprocessorDefinitions="_WIN32" StringPooling="true" ExceptionHandling="0" @@ -34,7 +34,7 @@ /> @@ -627,7 +627,7 @@ Name="Source Files" > diff --git a/PC/VS9.0/python3dll.vcproj b/PC/VS9.0/python3dll.vcproj --- a/PC/VS9.0/python3dll.vcproj +++ b/PC/VS9.0/python3dll.vcproj @@ -1,7 +1,7 @@ @@ -54,7 +54,7 @@ Name="VCResourceCompilerTool" PreprocessorDefinitions="NDEBUG" Culture="1033" - AdditionalIncludeDirectories="..\Include" + AdditionalIncludeDirectories="..\..\Include" /> @@ -129,7 +129,7 @@ Name="VCResourceCompilerTool" PreprocessorDefinitions="NDEBUG" Culture="1033" - AdditionalIncludeDirectories="..\Include" + AdditionalIncludeDirectories="..\..\Include" /> @@ -207,7 +207,7 @@ Name="VCResourceCompilerTool" PreprocessorDefinitions="_DEBUG" Culture="1033" - AdditionalIncludeDirectories="..\Include" + AdditionalIncludeDirectories="..\..\Include" /> @@ -285,7 +285,7 @@ Name="VCResourceCompilerTool" PreprocessorDefinitions="_DEBUG" Culture="1033" - AdditionalIncludeDirectories="..\Include" + AdditionalIncludeDirectories="..\..\Include" /> @@ -359,7 +359,7 @@ Name="VCResourceCompilerTool" PreprocessorDefinitions="NDEBUG" Culture="1033" - AdditionalIncludeDirectories="..\Include" + AdditionalIncludeDirectories="..\..\Include" /> @@ -434,7 +434,7 @@ Name="VCResourceCompilerTool" PreprocessorDefinitions="NDEBUG" Culture="1033" - AdditionalIncludeDirectories="..\Include" + AdditionalIncludeDirectories="..\..\Include" /> @@ -509,7 +509,7 @@ Name="VCResourceCompilerTool" PreprocessorDefinitions="NDEBUG" Culture="1033" - AdditionalIncludeDirectories="..\Include" + AdditionalIncludeDirectories="..\..\Include" /> @@ -584,7 +584,7 @@ Name="VCResourceCompilerTool" PreprocessorDefinitions="NDEBUG" Culture="1033" - AdditionalIncludeDirectories="..\Include" + AdditionalIncludeDirectories="..\..\Include" /> @@ -991,222 +991,222 @@ Name="Modules" > @@ -1214,31 +1214,31 @@ Name="zlib" > @@ -1374,71 +1374,71 @@ Name="cjkcodecs" > @@ -1447,175 +1447,175 @@ Name="Objects" > @@ -1623,59 +1623,59 @@ Name="Parser" > @@ -1683,31 +1683,31 @@ Name="PC" > @@ -1715,191 +1715,191 @@ Name="Python" > @@ -1907,7 +1907,7 @@ Name="Resource Files" > diff --git a/PC/VS9.0/pythonw.vcproj b/PC/VS9.0/pythonw.vcproj --- a/PC/VS9.0/pythonw.vcproj +++ b/PC/VS9.0/pythonw.vcproj @@ -1,7 +1,7 @@ @@ -608,7 +608,7 @@ Name="Source Files" > diff --git a/PC/VS9.0/select.vcproj b/PC/VS9.0/select.vcproj --- a/PC/VS9.0/select.vcproj +++ b/PC/VS9.0/select.vcproj @@ -1,7 +1,7 @@ diff --git a/PC/VS9.0/sqlite3.vcproj b/PC/VS9.0/sqlite3.vcproj --- a/PC/VS9.0/sqlite3.vcproj +++ b/PC/VS9.0/sqlite3.vcproj @@ -1,7 +1,7 @@ @@ -523,7 +523,7 @@ Name="Source Files" > diff --git a/PC/VS9.0/w9xpopen.vcproj b/PC/VS9.0/w9xpopen.vcproj --- a/PC/VS9.0/w9xpopen.vcproj +++ b/PC/VS9.0/w9xpopen.vcproj @@ -1,7 +1,7 @@ diff --git a/PC/VS9.0/winsound.vcproj b/PC/VS9.0/winsound.vcproj --- a/PC/VS9.0/winsound.vcproj +++ b/PC/VS9.0/winsound.vcproj @@ -1,7 +1,7 @@ diff --git a/PC/VS9.0/xxlimited.vcproj b/PC/VS9.0/xxlimited.vcproj --- a/PC/VS9.0/xxlimited.vcproj +++ b/PC/VS9.0/xxlimited.vcproj @@ -1,7 +1,7 @@