building wxPython on Windows using gcc

Hi,

I'm trying to build wxPython 2.9.2.4 on Windows XP using the stock
Windows Python and gcc. I've read the instructions here -
http://www.wxpython.org/BUILD-2.8.html and have read several
discussion threads on these mailing lists which suggest that this is
entirely possible.

The instructions linked above are for 2.8 and don't seem to work for
the latest wxPython. The current BUILD.html doesn't include specific
instructions for different platforms, compilers, etc.

I'm hoping the steps described in the old docs have been incorporated
into the build scripts and that if I invoke build-wxpython.py with the
right args it will compile using gcc instead of looking for the
Microsoft compiler. Unfortunately I haven't been able to figure it
out.

Have I overlooked some documentation? Is this build supported? Any
pointers would be greatly appreciated.

Greg

Not officially, but it should be able to be made to work. You'll probably need to not use build-wxpython.py however and instead build wxWidgets directly using configure/make (make sure to do a mingw32 build, not a cygwin build) and then building wxPython using setup.py. The code for using gcc in setup.py is still there, but it probably has not been tested since it was first merged in from a submitted patch so it is very likely that something has broken. You'll want to take a close look at the code in setup.py and config.py to make sure it is doing the right thing. Set COMPILER=mingw32 on the setyp.py command line to tell it you are using gcc.

···

On 10/19/11 11:58 PM, Greg wrote:

Hi,

I'm trying to build wxPython 2.9.2.4 on Windows XP using the stock
Windows Python and gcc. I've read the instructions here -
http://www.wxpython.org/BUILD-2.8.html and have read several
discussion threads on these mailing lists which suggest that this is
entirely possible.

The instructions linked above are for 2.8 and don't seem to work for
the latest wxPython. The current BUILD.html doesn't include specific
instructions for different platforms, compilers, etc.

I'm hoping the steps described in the old docs have been incorporated
into the build scripts and that if I invoke build-wxpython.py with the
right args it will compile using gcc instead of looking for the
Microsoft compiler. Unfortunately I haven't been able to figure it
out.

Have I overlooked some documentation? Is this build supported?

--
Robin Dunn
Software Craftsman

I'm making some progress. The build fails compiling the gdi extension
- undefined symbols (wxPostScriptDC). The easy fix is to rebuild
wxWidgets with PostScript enabled but ... I want to build wxPython
using an existing build of wxWidgets. I have a moderately sane reasons
for this, so I guess I'll be delving into the Swig interface files.
Wish me luck.

Greg

fingers crossed from me :wink:

···

Am 22.10.11 00:06, schrieb Greg:

I'm making some progress. The build fails compiling the gdi extension
- undefined symbols (wxPostScriptDC). The easy fix is to rebuild
wxWidgets with PostScript enabled but ... I want to build wxPython
using an existing build of wxWidgets. I have a moderately sane reasons
for this, so I guess I'll be delving into the Swig interface files.
Wish me luck.

Greg

--
--------------------------------------------------
Tobias Weber
CEO

The ROG Corporation GmbH
Donaustaufer Str. 200
93059 Regensburg
Tel: +49 941 4610 57 55
Fax: +49 941 4610 57 56

www.roglink.com

Gesch�ftsf�hrer: Tobias Weber
Registergericht: Amtsgericht Regensburg - HRB 8954
UStID DE225905250 - Steuer-Nr.184/59359
--------------------------------------------------

I had plenty of errors relating to the wxGraphicsContext while trying
to build the _gdi_ extension. It seems the wxGraphicsContext isn't
supported for a mingw gcc build. I made some progress by editing src/
_graphics.i and eventually resorted to just commenting out large
sections of the file as I don't think there's anything in there I want
to use anyway. It builds now. Of course a build without errors is not
necessarily a build that works.

  ActivePython 2.7.1.4 (ActiveState Software Inc.) based on
  Python 2.7.1 (r271:86832, Feb 7 2011, 11:30:38) [MSC v.1500 32 bit
(Intel)] on
  win32
  Type "help", "copyright", "credits" or "license" for more
information.
  >>> import wx
  Traceback (most recent call last):
    File "<stdin>", line 1, in <module>
    File "wx\__init__.py", line 45, in <module>
      from wx._core import *
    File "wx\_core.py", line 4, in <module>
      import _core_
  ImportError: DLL load failed: Invalid access to memory location.
  >>>

My build command is -

  python setup.py COMPILER=mingw32 CORE_ONLY=1 WX_CONFIG="C:
\wxWidgets-2.9.2\bin\wx-config.exe" MONOLITHIC=1 USE_SWIG=1 build_ext
--inplace

I have the pre-patched SWIG-1.3.29-wx.tar.gz downloaded from
http://wxpython.kosoftworks.com/tools/

The MinGW and wxWidgets packages I'm using are those installed with
the CodeLite IDE. This provides gcc (TDM-2 mingw32) 4.4.1 and a
monolithic gcc build of wxWidgets 2.9.2 which was created using this
compiler.

I do see an awful lot of warnings about strict-aliasing rules. eg.

  src\msw\propgrid_wrap.cpp: In function 'PyObject*
_wrap_PropertyGridInterface_SetPropertyMaxLength(PyObject*, PyObject*,
PyObject*)':
  src\msw\propgrid_wrap.cpp:27862: warning: dereferencing pointer
'resultobj' does break strict-aliasing rules
  src\msw\propgrid_wrap.cpp:27862: warning: dereferencing pointer
'resultobj' does break strict-aliasing rules
  src\msw\propgrid_wrap.cpp:27862: note: initialized from here
  src\msw\propgrid_wrap.cpp:27862: note: initialized from here

Any thoughts?

I had plenty of errors relating to the wxGraphicsContext while trying
to build the _gdi_ extension. It seems the wxGraphicsContext isn't
supported for a mingw gcc build. I made some progress by editing src/
_graphics.i and eventually resorted to just commenting out large
sections of the file as I don't think there's anything in there I want
to use anyway. It builds now. Of course a build without errors is not
necessarily a build that works.

There has been some discussion on wx-dev in recent weeks about how to get GDI+ and GrpahicsContext support in wxWidgets when using gcc... OTOH, wxPython has some stub classes that should be used if wxUSE_GRAPHICS_CONTEXT is defined as 0, which should have made it unnecessary to do the hacking and slashing that you did. Perhaps it is still being set to 1 somewhere.

   ActivePython 2.7.1.4 (ActiveState Software Inc.) based on
   Python 2.7.1 (r271:86832, Feb 7 2011, 11:30:38) [MSC v.1500 32 bit
(Intel)] on
   win32
   Type "help", "copyright", "credits" or "license" for more
information.
   >>> import wx
   Traceback (most recent call last):
     File "<stdin>", line 1, in<module>
     File "wx\__init__.py", line 45, in<module>
       from wx._core import *
     File "wx\_core.py", line 4, in<module>
       import _core_
   ImportError: DLL load failed: Invalid access to memory location.
   >>>

This is probably unrelated to the GrpahicsContext stuff, but you'll probably have to build with debug info and run in gdb to find out more about what exactly is going wrong.

···

On 10/26/11 9:24 AM, Greg wrote:

--
Robin Dunn
Software Craftsman

wxUSE_GRAPHICS_CONTEXT is defined as 0. Perhaps the stub classes need
to be updated to reflect API changes in wxWidgets? The first error I
get building with an un-butchered _graphics.i is ...

src\msw\_gdi_wrap.cpp:32265: error: no matching function for call to
'wxGraphics
Context::Create(const wxEnhMetaFileDC&)'
src\msw\_gdi_wrap.cpp:4232: note: candidates are: static
wxGraphicsContext* wxGr
aphicsContext::Create()
src\msw\_gdi_wrap.cpp:4237: note: static
wxGraphicsContext* wxGr
aphicsContext::Create(const wxWindowDC&)
src\msw\_gdi_wrap.cpp:4243: note: static
wxGraphicsContext* wxGr
aphicsContext::Create(const wxMemoryDC&)
src\msw\_gdi_wrap.cpp:4249: note: static
wxGraphicsContext* wxGr
aphicsContext::Create(const wxPrinterDC&)
src\msw\_gdi_wrap.cpp:4267: note: static
wxGraphicsContext* wxGr
aphicsContext::Create(wxWindow*)

which goes away with this patch

--- /home/gregh/wxPython-src-2.9.2.4.orig/wxPython/src/
_graphics.i 2011-09-
09 12:14:13.000000000 +1000
+++ _graphics.i 2011-10-27 12:10:19.419063900 +1100
@@ -307,6 +307,13 @@
                         "wx.GraphicsContext is not available on this
platform."
);
         return NULL;
     }

···

+
+ static wxGraphicsContext* Create( const wxEnhMetaFileDC& ) {
+ PyErr_SetString(PyExc_NotImplementedError,
+ "wx.GraphicsContext is not available on this
platform."
);
+ return NULL;
+ }
+
     static wxGraphicsContext* Create( const wxWindowDC& ) {
         PyErr_SetString(PyExc_NotImplementedError,
                         "wx.GraphicsContext is not available on this
platform."
);
@@ -956,6 +963,7 @@
     static wxGraphicsContext* Create( const wxPrinterDC& dc) ;
#ifdef __WXMSW__
     static wxGraphicsContext* Create( const wxMetaFileDC& dc) ;
+ static wxGraphicsContext* Create( const wxEnhMetaFileDC& dc) ;
#endif

     %pythonAppend Create "";

I made similar changes for a number of other unresolved functions but
was stumped by these two errors.

src\msw\_gdi_wrap.cpp: In function 'PyObject*
_wrap_GraphicsContext_CreateLinear
GradientBrush__SWIG_0(PyObject*, int, PyObject**)':
src\msw\_gdi_wrap.cpp:32738: error: passing 'const wxGraphicsContext'
as 'this'
argument of 'wxGraphicsBrush
wxGraphicsContext::CreateLinearGradientBrush(wxDoub
le, wxDouble, wxDouble, wxDouble, const wxColour&, const wxColour&)'
discards qu
alifiers
src\msw\_gdi_wrap.cpp: In function 'PyObject*
_wrap_GraphicsContext_CreateRadial
GradientBrush__SWIG_0(PyObject*, int, PyObject**)':
src\msw\_gdi_wrap.cpp:32900: error: passing 'const wxGraphicsContext'
as 'this'
argument of 'wxGraphicsBrush
wxGraphicsContext::CreateRadialGradientBrush(wxDoub
le, wxDouble, wxDouble, wxDouble, wxDouble, const wxColour&, const
wxColour&)' d
iscards qualifiers

In my previous message I forgot to mention that I'm also building with
wxUSE_POSTSCRIPT=0 which results in

src\msw\_gdi_wrap.cpp: In function 'void*
_p_wxPostScriptDCTo_p_wxDC(void*)':
src\msw\_gdi_wrap.cpp:45485: error: 'wxPostScriptDC' was not declared
in this sc
ope
src\msw\_gdi_wrap.cpp:45485: error: expected primary-expression before
')' token

src\msw\_gdi_wrap.cpp:45485: error: expected ')' before 'x'
src\msw\_gdi_wrap.cpp:45485: error: expected ')' before ';' token

I applied this patch to _dc.i to remove wxPostScriptDC

--- _dc.i 2011-10-27 11:20:55.393531300 +1100
+++ /home/gregh/wxPython-src-2.9.2.4.orig/wxPython/src/_dc.i
2011-09-09 12:30
:59.000000000 +1000
@@ -1948,8 +1948,6 @@
*mirror* is True.","");
};

-#if wxUSE_POSTSCRIPT
-
//---------------------------------------------------------------------------
%newgroup

@@ -1987,7 +1985,6 @@
//---------------------------------------------------------------------------
%newgroup

-#endif

MustHaveApp(wxMetaFile);
MustHaveApp(wxMetaFileDC);

This removes the definition of wxPostScriptDC and removes the build
error. Of course my swig skills are second to many, perhaps this is
not the right approach to solving the problem.

I see _dc.i wraps wxMetaFileDC but not wxEnhMetaFileDC. I wonder if it
should.

I get a linker error creating a debug build as the ActiveState Python
installer doesn't provide a debug library for Python. I've compiled my
own debug and release builds of Python but I don't have access to them
today as I'm not in the office - I'll create a debug build and fire up
gdb tomorrow morning.

Greg

wxUSE_GRAPHICS_CONTEXT is defined as 0. Perhaps the stub classes need
to be updated to reflect API changes in wxWidgets?

Yep, that looks like the problem.

I made similar changes for a number of other unresolved functions but
was stumped by these two errors.

Those stub methods need to have the const keyword added to them.

···

On 10/26/11 6:56 PM, Greg wrote:

--
Robin Dunn
Software Craftsman

I should probably also provide a stub class in _dc.i for
wxPostScriptDC if wxUSE_POSTSCRIPT is not set.

I've modified _graphics.i to correct all the problems building with
MinGW gcc and I've added a stub class to _dc.i to provide
wxPostScriptDC if wxUSE_POSTSCRIPT not set. Everything swigs and
builds without fuss now. I'd be happy to pass on patches if anybody is
interested.

Just tried a clean build on 32 bit Windows XP against the pre-built
wxWidgets I'm targeting and ... it works. Must try running this build
on the 32 bit Windows 7 environment where I'd been working previously.
The latest build on that machine still fails.

import wx

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "wx\__init__.py", line 45, in <module>
    from wx._core import *
  File "wx\_core.py", line 4, in <module>
    import _core_
ImportError: DLL load failed: Invalid access to memory location.

Haven't had time to fire up the debugger yet, other commitments at
work today. Definitely making progress though.

Thanx for the update

Tobi

···

Am 28.10.2011 um 08:11 schrieb Greg <gregregreg@gmail.com>:

I've modified _graphics.i to correct all the problems building with
MinGW gcc and I've added a stub class to _dc.i to provide
wxPostScriptDC if wxUSE_POSTSCRIPT not set. Everything swigs and
builds without fuss now. I'd be happy to pass on patches if anybody is
interested.

Just tried a clean build on 32 bit Windows XP against the pre-built
wxWidgets I'm targeting and ... it works. Must try running this build
on the 32 bit Windows 7 environment where I'd been working previously.
The latest build on that machine still fails.

import wx

Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "wx\__init__.py", line 45, in <module>
   from wx._core import *
File "wx\_core.py", line 4, in <module>
   import _core_
ImportError: DLL load failed: Invalid access to memory location.

Haven't had time to fire up the debugger yet, other commitments at
work today. Definitely making progress though.

--
To unsubscribe, send email to wxPython-users+unsubscribe@googlegroups.com
or visit http://groups.google.com/group/wxPython-users?hl=en

Yes, please make a ticket at trac.wxwidgets.org for the patches.

···

On 10/27/11 11:11 PM, Greg wrote:

I've modified _graphics.i to correct all the problems building with
MinGW gcc and I've added a stub class to _dc.i to provide
wxPostScriptDC if wxUSE_POSTSCRIPT not set. Everything swigs and
builds without fuss now. I'd be happy to pass on patches if anybody is
interested.

--
Robin Dunn
Software Craftsman

Another smallish problem - finally got around to creating a debug
build of wxPython with gcc and discovered that config.py doesn't
define _DEBUG if COMPILER == 'mingw32'. This leads to a linker error -
undefined reference to `_imp__Py_InitModule4`.

The following trivial patch resolves the problem. I'll attach the
patch to the Trac ticket I created.

--- config.py.orig 2011-11-03 12:12:54.281250000 +1100
+++ config.py 2011-11-03 12:11:33.890625000 +1100
@@ -1077,9 +1077,9 @@
     cflags = adjustCFLAGS(cflags, defines, includes)
     lflags = adjustLFLAGS(lflags, libdirs, libs)

- if debug and WXPORT == 'msw' and COMPILER != 'mingw32':
+ if debug and WXPORT == 'msw':
         defines.append( ('_DEBUG', None) )

···

-
+
## from pprint import pprint
## print 'cflags:',; pprint(cflags)
## print 'defines:',; pprint(defines)

Attempting to import wx in python_d.exe I get an ImportError

    import _core_
ImportError: DLL load failed: The specified module could not be found.

No indication of which DLL is missing.

A more pressing problem is that importing wx into python.exe fails
intermittently. If it imports it seems to work reliably, I haven't had
any program crashes once the GUI is displayed. But ... I've just
repeatedly run the following command from the command line. (Don't be
alarmed by the cygwin path - I prefer working in a bash shell and
using my cygwin home directory avoids directory names with spaces
which upset most of the build tools but everything is compiled using
MinGW tools in a cmd.exe window)

C:\cygwin\home\gregh\stuff\wxPython>python -c "import wx"

C:\cygwin\home\gregh\stuff\wxPython>python -c "import wx"

C:\cygwin\home\gregh\stuff\wxPython>python -c "import wx"

C:\cygwin\home\gregh\stuff\wxPython>python -c "import wx"

C:\cygwin\home\gregh\stuff\wxPython>python -c "import wx"

C:\cygwin\home\gregh\stuff\wxPython>python -c "import wx"
Traceback (most recent call last):
  File "<string>", line 1, in <module>
  File "C:\cygwin\home\gregh\wxPython-src-2.9.2.4\wxPython\wx
\__init__.py", line
45, in <module>
    from wx._core import *
  File "C:\cygwin\home\gregh\wxPython-src-2.9.2.4\wxPython\wx
\_core.py", line 16
647, in <module>
    from _misc import *
  File "C:\cygwin\home\gregh\wxPython-src-2.9.2.4\wxPython\wx
\_misc.py", line 4,
in <module>
    import _misc_
ImportError: DLL load failed: Invalid access to memory location.

The exception is accompanied by an error dialog box. Same addresses
each time.

   The instruction at "0x63196b3e" referenced memory at "0x64986034".
The memory could not be "read".

I've also compiled the embedded.cpp source from the wxPython
subversion repo. It runs more often than not but occasionally exits
without displaying the GUI but with no error message. I've profiled it
using an interesting tool I found called DependencyWalker -
http://www.dependencywalker.com/

The program generates a full tree of all the external dependencies,
their dependencies and so on and also allows me to profile the running
program. There are a lot of heap errors, always immediately after
loading wxPython PYD files. Calling RtlFreeHeap with an invalid
address can't be a good thing and probably explains the intermittent
nature of the failure.

Loaded "_CORE_.PYD" at address 0x6F240000. Successfully hooked
module.DllMain(0x6F240000, DLL_PROCESS_ATTACH, 0x00000000) in
"_CORE_.PYD" called.HEAP[EMBEDDED.EXE]: Invalid Address specified to
RtlFreeHeap( 00A50000, 00BBFB78 )HEAP[EMBEDDED.EXE]: Invalid Address
specified to RtlFreeHeap( 00A50000, 00BC2C18 )HEAP[EMBEDDED.EXE]:
Invalid Address specified to RtlFreeHeap( 00A50000,
00BB6E48 )HEAP[EMBEDDED.EXE]: Invalid Address specified to
RtlFreeHeap( 00A50000, 00BC2D50 )DllMain(0x6F240000,
DLL_PROCESS_ATTACH, 0x00000000) in "_CORE_.PYD" returned 1 (0x1).
Perhaps I'm doing something wrong building wxPython? Maybe the setup.h
and build.cfg provided with my wxWidgets build don't reflect the
actual build settings? I build wxPython by setting WXWIN, PATH and
PYTHONPATH and then invoking setup.py like this ...

python setup.py COMPILER=mingw32 BUILD_GLCANVAS=0 BUILD_ACTIVEX=0 USE_SWIG=1 SWIG="C:\SWIG-1.3.29\SWIG.exe" WX_CONFIG="C:\wxWidgets-2.9.2\bin\wx-config.exe" MONOLITHIC=1 build_ext --inplace --force

I add --debug for a debug build.

I have uninstalled all other builds of wxWidgets, wxPython and Python
to avoid any DLL conflicts.

Any suggestions would be greatly appreciated. This is obviously very
close to working. I'm particularly pleased to see the embedded example
working. wxPython sharing a common event loop with a wxWidgets program
all compiled using gcc is potentially very useful, if I can just get
it to run consistently.

My first suggestion would have been to use DependencyWalker, but you've already found that...

The only other thing that comes to mind at the moment is to be sure that the C runtime library settings used for wxWidgets and wxPython are the same as what was used for Python. If you're using a stock Python build then that would be whatever mingw32's equivalent of /MD is, or /MDd for debug builds. Otherwise you could end up with different versions of the C runtime in memory and they will conflict with each other and it could end up with things like the RtlFreeHeap problems if a memory block was allocated with one runtime but freed with the other.

···

On 11/3/11 11:57 PM, Greg wrote:

The program generates a full tree of all the external dependencies,
their dependencies and so on and also allows me to profile the running
program. There are a lot of heap errors, always immediately after
loading wxPython PYD files. Calling RtlFreeHeap with an invalid
address can't be a good thing and probably explains the intermittent
nature of the failure.

Loaded "_CORE_.PYD" at address 0x6F240000. Successfully hooked
module.DllMain(0x6F240000, DLL_PROCESS_ATTACH, 0x00000000) in
"_CORE_.PYD" called.HEAP[EMBEDDED.EXE]: Invalid Address specified to
RtlFreeHeap( 00A50000, 00BBFB78 )HEAP[EMBEDDED.EXE]: Invalid Address
specified to RtlFreeHeap( 00A50000, 00BC2C18 )HEAP[EMBEDDED.EXE]:
Invalid Address specified to RtlFreeHeap( 00A50000,
00BB6E48 )HEAP[EMBEDDED.EXE]: Invalid Address specified to
RtlFreeHeap( 00A50000, 00BC2D50 )DllMain(0x6F240000,
DLL_PROCESS_ATTACH, 0x00000000) in "_CORE_.PYD" returned 1 (0x1).
Perhaps I'm doing something wrong building wxPython? Maybe the setup.h
and build.cfg provided with my wxWidgets build don't reflect the
actual build settings? I build wxPython by setting WXWIN, PATH and
PYTHONPATH and then invoking setup.py like this ...

python setup.py COMPILER=mingw32 BUILD_GLCANVAS=0 BUILD_ACTIVEX=0 USE_SWIG=1 SWIG="C:\SWIG-1.3.29\SWIG.exe" WX_CONFIG="C:\wxWidgets-2.9.2\bin\wx-config.exe" MONOLITHIC=1 build_ext --inplace --force

I add --debug for a debug build.

I have uninstalled all other builds of wxWidgets, wxPython and Python
to avoid any DLL conflicts.

Any suggestions would be greatly appreciated. This is obviously very
close to working. I'm particularly pleased to see the embedded example
working. wxPython sharing a common event loop with a wxWidgets program
all compiled using gcc is potentially very useful, if I can just get
it to run consistently.

--
Robin Dunn
Software Craftsman

Definitely looks like a problem with conflicting CRTs.

objdump reports some things I would expect ...

Hello, World.
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll

Minimal embedded Python example.
        DLL Name: KERNEL32.dll
        DLL Name: msvcrt.dll
        DLL Name: python27.dll

An abridged list of just the interesting DLLs used by my monolithic
gcc build of wxWidgets
        DLL Name: KERNEL32.dll
        DLL Name: mingwm10.dll
        DLL Name: msvcrt.dll

And something I wasn't expecting. My wxPython pyd files list
msvcrt.dll and msvcr90.dll.
        DLL Name: python27.dll
        DLL Name: wxmsw292u_gcc_custom.dll
        DLL Name: KERNEL32.dll
        DLL Name: mingwm10.dll
        DLL Name: msvcrt.dll
        DLL Name: msvcr90.dll
        DLL Name: msvcrt.dll

That can't be good.

I monkey patched `distutils.cygwinccompiler.get_msvcr()` in wxPython/
config.py to return an empty list rather than the CRT used by
python.exe. This prevents msvcr90.dll being linked in the pyd files,
just msvcrt.dll. I can import wx consistently without errors and
Dependency Walker doesn't report anything ugly. I'm also able to
import wx on Windows 7. Previously it only worked (intermittently) on
XP.

I haven't had a chance to test this with my embedded Python project
yet but I'm quietly hopeful. I'll keep you posted and, assuming it
works, post some documentation.