From 14efb1cbaf63c6bc6218a06833f084a640360113 Mon Sep 17 00:00:00 2001 From: David Rose Date: Thu, 30 Jul 2009 19:28:27 +0000 Subject: [PATCH] support a windows debug plugin --- .../extension_native_helpers.py | 13 ++++--- direct/src/plugin/make_package.py | 7 ++-- direct/src/plugin/p3dPythonRun.cxx | 8 +++++ direct/src/plugin/p3dWinSplashWindow.cxx | 26 ++++++++------ direct/src/showutil/FreezeTool.py | 36 +++++++++++++++---- 5 files changed, 66 insertions(+), 24 deletions(-) diff --git a/direct/src/extensions_native/extension_native_helpers.py b/direct/src/extensions_native/extension_native_helpers.py index 243736c053..e8cc97e8ac 100644 --- a/direct/src/extensions_native/extension_native_helpers.py +++ b/direct/src/extensions_native/extension_native_helpers.py @@ -16,10 +16,15 @@ if sys.platform == "win32": # On Windows, dynamic libraries end in ".dll". dll_ext = '.dll' - # If we launched from python_d.exe, we need to load - # libpanda_d.dll, etc. - if sys.executable.endswith('_d.exe'): - dll_suffix = '_d' + # We allow the caller to preload dll_suffix into the sys module. + dll_suffix = getattr(sys, 'dll_suffix', None) + + if dll_suffix is None: + # Otherwise, we try to determine it from the executable name: + # python_d.exe implies _d across the board. + if sys.executable.endswith('_d.exe'): + dll_suffix = '_d' + elif sys.platform == "darwin": # On OSX, the dynamic libraries usually end in .dylib, but # sometimes we need .so. diff --git a/direct/src/plugin/make_package.py b/direct/src/plugin/make_package.py index ecba59460d..c53a80f918 100755 --- a/direct/src/plugin/make_package.py +++ b/direct/src/plugin/make_package.py @@ -23,9 +23,9 @@ Options: the local machine that will be filled with the contents of the package directory for the web server. - -p name_version[_platform] + -p name[_platform]_version - Specify the package name, version, and optional platfom, of the + Specify the package name, (optional) platform, and version of the package to build. """ @@ -210,8 +210,9 @@ def makePackage(args): if len(tokens) >= 1: pm.packageName = tokens[0] if len(tokens) >= 2: - pm.packagePlatform = tokens[1] + pm.packageVersion = tokens[1] if len(tokens) >= 3: + pm.packagePlatform = pm.packageVersion pm.packageVersion = tokens[2] if len(tokens) >= 4: raise ArgumentError, 'Too many tokens in string: %s' % (value) diff --git a/direct/src/plugin/p3dPythonRun.cxx b/direct/src/plugin/p3dPythonRun.cxx index 1151f5477a..46fa90c2a0 100755 --- a/direct/src/plugin/p3dPythonRun.cxx +++ b/direct/src/plugin/p3dPythonRun.cxx @@ -98,6 +98,14 @@ P3DPythonRun:: //////////////////////////////////////////////////////////////////// bool P3DPythonRun:: run_python() { +#if defined(_WIN32) && defined(USE_DEBUG_PYTHON) + // On Windows, in a debug build, we have to preload sys.dll_suffix = + // "_d", so that the Panda DLL preloader can import the correct + // filenames. + PyRun_SimpleString("import sys; sys.dll_suffix = '_d'"); + +#endif + // First, load runp3d_frozen.pyd. Since this is a magic frozen pyd, // importing it automatically makes all of its frozen contents // available to import as well. diff --git a/direct/src/plugin/p3dWinSplashWindow.cxx b/direct/src/plugin/p3dWinSplashWindow.cxx index 80984419ca..8392a84e94 100755 --- a/direct/src/plugin/p3dWinSplashWindow.cxx +++ b/direct/src/plugin/p3dWinSplashWindow.cxx @@ -205,9 +205,11 @@ unregister_window_class() { void P3DWinSplashWindow:: start_thread() { _thread_continue = true; + _thread_running = true; _thread = CreateThread(NULL, 0, &win_thread_run, this, 0, &_thread_id); - if (_thread != NULL) { - _thread_running = true; + if (_thread == NULL) { + // Thread never got started. + _thread_running = false; } } @@ -226,16 +228,17 @@ stop_thread() { } if (_thread != NULL){ - // We can't actually wait for the thread to finish, since there - // might be a deadlock there: the thread can't finish deleting its - // window unless we're pumping the message loop for the parent, - // which won't happen if we're sitting here waiting. No worries; - // we don't *really* need to wait for the thread. - - // WaitForSingleObject(_thread, INFINITE); + WaitForSingleObject(_thread, INFINITE); CloseHandle(_thread); _thread = NULL; + + // Now that the thread has exited, we can safely close its window. + // (We couldn't close the window in the thread, because that would + // cause a deadlock situation--the thread can't acknowledge the + // window closing until we spin the event loop in the parent + // thread.) + close_window(); } } @@ -295,7 +298,7 @@ thread_run() { retval = GetMessage(&msg, NULL, 0, 0); } - close_window(); + // Tell our parent thread that we're done. _thread_running = false; } @@ -566,7 +569,8 @@ update_image_filename(const string &image_filename, bool image_filename_temp) { //////////////////////////////////////////////////////////////////// // Function: P3DWinSplashWindow::close_window // Access: Private -// Description: Closes the window created above. +// Description: Closes the window created above. This call is +// actually made in the main thread. //////////////////////////////////////////////////////////////////// void P3DWinSplashWindow:: close_window() { diff --git a/direct/src/showutil/FreezeTool.py b/direct/src/showutil/FreezeTool.py index 5ef62cc191..bcafa01bc7 100644 --- a/direct/src/showutil/FreezeTool.py +++ b/direct/src/showutil/FreezeTool.py @@ -12,6 +12,14 @@ from distutils.sysconfig import PREFIX, get_python_inc, get_python_version import direct from pandac.PandaModules import * +# Check to see if we are running python_d, which implies we have a +# debug build, and we have to build the module with debug options. +# This is only relevant on Windows. + +# I wonder if there's a better way to determine this? +python = os.path.splitext(os.path.split(sys.executable)[1])[0] +isDebugBuild = (python.lower().endswith('_d')) + # These are modules that Python always tries to import up-front. They # must be frozen in any main.exe. startupModules = [ @@ -44,6 +52,14 @@ MSVC = None # Directory to Windows Platform SDK (if relevant) PSDK = None +# The setting to control release vs. debug builds. Only relevant on +# Windows. +MD = None + +# The _d extension to add to dll filenames on Windows in debug builds. +dllext = '' + + if sys.platform == 'win32': Python = PREFIX @@ -66,18 +82,24 @@ if sys.platform == 'win32': else: print 'Could not locate the Microsoft Windows Platform SDK! Try running from the Visual Studio Command Prompt.' sys.exit(1) + + # We need to use the correct compiler setting for debug vs. release builds. + MD = '/MD' + if isDebugBuild: + MD = '/MDd' + dllext = '_d' # If it is run by makepanda, it handles the MSVC and PlatformSDK paths itself. if ('MAKEPANDA' in os.environ): - compileObj = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c /MD /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" %(filename)s' + compileObj = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" %(filename)s' linkExe = 'link /nologo /MAP:NUL /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO /LIBPATH:"%(python)s\libs" /out:%(basename)s.exe %(basename)s.obj' - linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(python)s\libs" /out:%(basename)s.pyd %(basename)s.obj' + linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(python)s\libs" /out:%(basename)s%(dllext)s.pyd %(basename)s.obj' else: os.environ['PATH'] += ';' + MSVC + '\\bin;' + MSVC + '\\Common7\\IDE;' + PSDK + '\\bin' - compileObj = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c /MD /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" /I"%(PSDK)s\include" /I"%(MSVC)s\include" %(filename)s' + compileObj = 'cl /wd4996 /Fo%(basename)s.obj /nologo /c %(MD)s /Zi /O2 /Ob2 /EHsc /Zm300 /W3 /I"%(pythonIPath)s" /I"%(PSDK)s\include" /I"%(MSVC)s\include" %(filename)s' linkExe = 'link /nologo /MAP:NUL /FIXED:NO /OPT:REF /STACK:4194304 /INCREMENTAL:NO /LIBPATH:"%(PSDK)s\lib" /LIBPATH:"%(MSVC)s\lib" /LIBPATH:"%(python)s\libs" /out:%(basename)s.exe %(basename)s.obj' - linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(PSDK)s\lib" /LIBPATH:"%(MSVC)s\lib" /LIBPATH:"%(python)s\libs" /out:%(basename)s.pyd %(basename)s.obj' + linkDll = 'link /nologo /DLL /MAP:NUL /FIXED:NO /OPT:REF /INCREMENTAL:NO /LIBPATH:"%(PSDK)s\lib" /LIBPATH:"%(MSVC)s\lib" /LIBPATH:"%(python)s\libs" /out:%(basename)s%(dllext)s.pyd %(basename)s.obj' elif sys.platform == 'darwin': # OSX @@ -457,7 +479,6 @@ class Freezer: """ moduleName = moduleName.replace("/", ".").replace("direct.src", "direct") - if implicit: token = self.MTAuto else: @@ -768,7 +789,7 @@ class Freezer: dllexport = '' if self.platform == 'win32': dllexport = '__declspec(dllexport) ' - target = basename + '.pyd' + target = basename + dllext + '.pyd' else: target = basename + '.so' @@ -804,6 +825,7 @@ class Freezer: 'python' : Python, 'MSVC' : MSVC, 'PSDK' : PSDK, + 'MD' : MD, 'pythonIPath' : PythonIPath, 'pythonVersion' : PythonVersion, 'filename' : filename, @@ -831,6 +853,7 @@ class Freezer: 'python' : Python, 'MSVC' : MSVC, 'PSDK' : PSDK, + 'MD' : MD, 'pythonIPath' : PythonIPath, 'pythonVersion' : PythonVersion, 'filename' : filename, @@ -848,6 +871,7 @@ class Freezer: 'pythonVersion' : PythonVersion, 'filename' : filename, 'basename' : basename, + 'dllext' : dllext, } print >> sys.stderr, link if os.system(link) != 0: