]> git.saurik.com Git - wxWidgets.git/blob - wxPython/config.py
cleaning up strdup/isascii definitions for compilers which lack them (should fix...
[wxWidgets.git] / wxPython / config.py
1 #----------------------------------------------------------------------
2 # Name: wx.build.config
3 # Purpose: Most of the contents of this module used to be located
4 # in wxPython's setup.py script. It was moved here so
5 # it would be installed with the rest of wxPython and
6 # could therefore be used by the setup.py for other
7 # projects that needed this same info and functionality
8 # (most likely in order to be compatible with wxPython.)
9 #
10 # This split from setup.py is still fairly rough, and
11 # some things may still get shuffled back and forth,
12 # refactored, etc. Please send me any comments and
13 # suggestions about this.
14 #
15 # Author: Robin Dunn
16 #
17 # Created: 23-March-2004
18 # RCS-ID: $Id$
19 # Copyright: (c) 2004 by Total Control Software
20 # Licence: wxWindows license
21 #----------------------------------------------------------------------
22
23 import sys, os, glob, fnmatch, tempfile
24 from distutils.core import setup, Extension
25 from distutils.file_util import copy_file
26 from distutils.dir_util import mkpath
27 from distutils.dep_util import newer
28 from distutils.spawn import spawn
29
30 import distutils.command.install
31 import distutils.command.install_data
32 import distutils.command.install_headers
33 import distutils.command.clean
34
35 #----------------------------------------------------------------------
36 # flags and values that affect this script
37 #----------------------------------------------------------------------
38
39 VER_MAJOR = 2 # The first three must match wxWidgets
40 VER_MINOR = 5
41 VER_RELEASE = 3
42 VER_SUBREL = 0 # wxPython release num for x.y.z release of wxWidgets
43 VER_FLAGS = "p" # release flags, such as prerelease num, unicode, etc.
44
45 DESCRIPTION = "Cross platform GUI toolkit for Python"
46 AUTHOR = "Robin Dunn"
47 AUTHOR_EMAIL = "Robin Dunn <robin@alldunn.com>"
48 URL = "http://wxPython.org/"
49 DOWNLOAD_URL = "http://wxPython.org/download.php"
50 LICENSE = "wxWidgets Library License (LGPL derivative)"
51 PLATFORMS = "WIN32,OSX,POSIX"
52 KEYWORDS = "GUI,wx,wxWindows,wxWidgets,cross-platform"
53
54 LONG_DESCRIPTION = """\
55 wxPython is a GUI toolkit for Python that is a wrapper around the
56 wxWidgets C++ GUI library. wxPython provides a large variety of
57 window types and controls, all implemented with a native look and
58 feel (by using the native widgets) on the platforms it is supported
59 on.
60 """
61
62 CLASSIFIERS = """\
63 Development Status :: 6 - Mature
64 Environment :: MacOS X :: Carbon
65 Environment :: Win32 (MS Windows)
66 Environment :: X11 Applications :: GTK
67 Intended Audience :: Developers
68 License :: OSI Approved
69 Operating System :: MacOS :: MacOS X
70 Operating System :: Microsoft :: Windows :: Windows 95/98/2000
71 Operating System :: POSIX
72 Programming Language :: Python
73 Topic :: Software Development :: User Interfaces
74 """
75
76 ## License :: OSI Approved :: wxWidgets Library Licence
77
78
79 # Config values below this point can be reset on the setup.py command line.
80
81 BUILD_GLCANVAS = 1 # If true, build the contrib/glcanvas extension module
82 BUILD_OGL = 1 # If true, build the contrib/ogl extension module
83 BUILD_STC = 1 # If true, build the contrib/stc extension module
84 BUILD_GIZMOS = 1 # Build a module for the gizmos contrib library
85 BUILD_DLLWIDGET = 0# Build a module that enables unknown wx widgets
86 # to be loaded from a DLL and to be used from Python.
87
88 # Internet Explorer wrapper (experimental)
89 BUILD_IEWIN = (os.name == 'nt')
90 BUILD_ACTIVEX = (os.name == 'nt') # new version of IEWIN and more
91
92
93 CORE_ONLY = 0 # if true, don't build any of the above
94
95 PREP_ONLY = 0 # Only run the prepatory steps, not the actual build.
96
97 USE_SWIG = 0 # Should we actually execute SWIG, or just use the
98 # files already in the distribution?
99
100 SWIG = "swig" # The swig executable to use.
101
102 BUILD_RENAMERS = 1 # Should we build the renamer modules too?
103
104 FULL_DOCS = 0 # Some docstrings are split into a basic docstring and a
105 # details string. Setting this flag to 1 will
106 # cause the two strings to be combined and output
107 # as the full docstring.
108
109 UNICODE = 0 # This will pass the 'wxUSE_UNICODE' flag to SWIG and
110 # will ensure that the right headers are found and the
111 # right libs are linked.
112
113 UNDEF_NDEBUG = 1 # Python 2.2 on Unix/Linux by default defines NDEBUG,
114 # and distutils will pick this up and use it on the
115 # compile command-line for the extensions. This could
116 # conflict with how wxWidgets was built. If NDEBUG is
117 # set then wxWidgets' __WXDEBUG__ setting will be turned
118 # off. If wxWidgets was actually built with it turned
119 # on then you end up with mismatched class structures,
120 # and wxPython will crash.
121
122 NO_SCRIPTS = 0 # Don't install the tool scripts
123 NO_HEADERS = 0 # Don't install the wxPython *.h and *.i files
124
125 INSTALL_MULTIVERSION = 1 # Install the packages such that multiple versions
126 # can co-exist. When turned on the wx and wxPython
127 # pacakges will be installed in a versioned subdir
128 # of site-packages, and a *.pth file will be
129 # created that adds that dir to the sys.path. In
130 # addition, a wxselect.py module will be installed
131 # to site-pacakges that will allow applications to
132 # choose a specific version if more than one are
133 # installed.
134
135 FLAVOUR = "" # Optional flavour string to be appended to VERSION
136 # in MULTIVERSION installs
137
138 INSTALL_WXRC = 0 # Should the Python version of wxrc be installed?
139
140 WX_CONFIG = None # Usually you shouldn't need to touch this, but you can set
141 # it to pass an alternate version of wx-config or alternate
142 # flags, eg. as required by the .deb in-tree build. By
143 # default a wx-config command will be assembled based on
144 # version, port, etc. and it will be looked for on the
145 # default $PATH.
146
147 WXPORT = 'gtk2' # On Linux/Unix there are several ports of wxWidgets available.
148 # Setting this value lets you select which will be used for
149 # the wxPython build. Possibilites are 'gtk', 'gtk2' and
150 # 'x11'. Curently only gtk and gtk2 works.
151
152 BUILD_BASE = "build" # Directory to use for temporary build files.
153 # This name will be appended to if the WXPORT or
154 # the UNICODE flags are set to non-standard
155 # values. See below.
156
157
158 CONTRIBS_INC = "" # A dir to add as an -I flag when compiling the contribs
159
160
161 # Some MSW build settings
162
163 FINAL = 0 # Mirrors use of same flag in wx makefiles,
164 # (0 or 1 only) should probably find a way to
165 # autodetect this...
166
167 HYBRID = 1 # If set and not debug or FINAL, then build a
168 # hybrid extension that can be used by the
169 # non-debug version of python, but contains
170 # debugging symbols for wxWidgets and wxPython.
171 # wxWidgets must have been built with /MD, not /MDd
172 # (using FINAL=hybrid will do it.)
173
174 # Version part of wxWidgets LIB/DLL names
175 WXDLLVER = '%d%d' % (VER_MAJOR, VER_MINOR)
176
177 WXPY_SRC = '.' # Assume we're in the source tree already, but allow the
178 # user to change it, particularly for extension building.
179
180
181 #----------------------------------------------------------------------
182
183 def msg(text):
184 if hasattr(sys, 'setup_is_main') and sys.setup_is_main:
185 print text
186
187
188 def opj(*args):
189 path = os.path.join(*args)
190 return os.path.normpath(path)
191
192
193 def libFlag():
194 if FINAL:
195 rv = ''
196 elif HYBRID:
197 rv = 'h'
198 else:
199 rv = 'd'
200 if UNICODE:
201 rv = 'u' + rv
202 return rv
203
204
205 #----------------------------------------------------------------------
206 # Some other globals
207 #----------------------------------------------------------------------
208
209 PKGDIR = 'wx'
210 wxpExtensions = []
211 DATA_FILES = []
212 CLEANUP = []
213
214 force = '--force' in sys.argv or '-f' in sys.argv
215 debug = '--debug' in sys.argv or '-g' in sys.argv
216 cleaning = 'clean' in sys.argv
217
218
219 # change the PORT default for wxMac
220 if sys.platform[:6] == "darwin":
221 WXPORT = 'mac'
222
223 # and do the same for wxMSW, just for consistency
224 if os.name == 'nt':
225 WXPORT = 'msw'
226
227
228 #----------------------------------------------------------------------
229 # Check for build flags on the command line
230 #----------------------------------------------------------------------
231
232 # Boolean (int) flags
233 for flag in ['BUILD_GLCANVAS', 'BUILD_OGL', 'BUILD_STC',
234 'BUILD_GIZMOS', 'BUILD_DLLWIDGET', 'BUILD_IEWIN', 'BUILD_ACTIVEX',
235 'CORE_ONLY', 'PREP_ONLY', 'USE_SWIG', 'UNICODE',
236 'UNDEF_NDEBUG', 'NO_SCRIPTS', 'NO_HEADERS', 'BUILD_RENAMERS',
237 'FULL_DOCS', 'INSTALL_MULTIVERSION', 'INSTALL_WXRC',
238 'FINAL', 'HYBRID', ]:
239 for x in range(len(sys.argv)):
240 if sys.argv[x].find(flag) == 0:
241 pos = sys.argv[x].find('=') + 1
242 if pos > 0:
243 vars()[flag] = eval(sys.argv[x][pos:])
244 sys.argv[x] = ''
245
246 # String options
247 for option in ['WX_CONFIG', 'WXDLLVER', 'BUILD_BASE', 'WXPORT', 'SWIG',
248 'CONTRIBS_INC', 'WXPY_SRC', 'FLAVOUR',
249 ]:
250 for x in range(len(sys.argv)):
251 if sys.argv[x].find(option) == 0:
252 pos = sys.argv[x].find('=') + 1
253 if pos > 0:
254 vars()[option] = sys.argv[x][pos:]
255 sys.argv[x] = ''
256
257 sys.argv = filter(None, sys.argv)
258
259
260 #----------------------------------------------------------------------
261 # some helper functions
262 #----------------------------------------------------------------------
263
264 def Verify_WX_CONFIG():
265 """ Called below for the builds that need wx-config, if WX_CONFIG
266 is not set then determins the flags needed based on build
267 options and searches for wx-config on the PATH.
268 """
269 # if WX_CONFIG hasn't been set to an explicit value then construct one.
270 global WX_CONFIG
271 if WX_CONFIG is None:
272 WX_CONFIG='wx-config'
273 port = WXPORT
274 if port == "x11":
275 port = "x11univ"
276 flags = ' --toolkit=%s' % port
277 flags += ' --unicode=%s' % (UNICODE and 'yes' or 'no')
278 flags += ' --version=%s.%s' % (VER_MAJOR, VER_MINOR)
279
280 searchpath = os.environ["PATH"]
281 for p in searchpath.split(':'):
282 fp = os.path.join(p, 'wx-config')
283 if os.path.exists(fp) and os.access(fp, os.X_OK):
284 # success
285 msg("Found wx-config: " + fp)
286 msg(" Using flags: " + flags)
287 WX_CONFIG = fp + flags
288 break
289 else:
290 msg("ERROR: WX_CONFIG not specified and wx-config not found on the $PATH")
291 # should we exit?
292
293 # TODO: exeucte WX_CONFIG --list and verify a matching config is found
294
295
296 def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args,
297 swig_deps=[], add_under=False):
298 """Run SWIG the way I want it done"""
299
300 if USE_SWIG and not os.path.exists(os.path.join(dir, gendir)):
301 os.mkdir(os.path.join(dir, gendir))
302
303 if USE_SWIG and not os.path.exists(os.path.join("docs", "xml-raw")):
304 if not os.path.exists("docs"):
305 os.mkdir("docs")
306 os.mkdir(os.path.join("docs", "xml-raw"))
307
308 sources = []
309
310 if add_under: pre = '_'
311 else: pre = ''
312
313 for file in files:
314 basefile = os.path.splitext(file)[0]
315 i_file = os.path.join(dir, file)
316 py_file = os.path.join(dir, gendir, pre+basefile+'.py')
317 cpp_file = os.path.join(dir, gendir, pre+basefile+'_wrap.cpp')
318 xml_file = os.path.join("docs", "xml-raw", basefile+pre+'_swig.xml')
319
320 if add_under:
321 interface = ['-interface', '_'+basefile+'_']
322 else:
323 interface = []
324
325 sources.append(cpp_file)
326
327 if not cleaning and USE_SWIG:
328 for dep in swig_deps:
329 if newer(dep, py_file) or newer(dep, cpp_file):
330 force = 1
331 break
332
333 if force or newer(i_file, py_file) or newer(i_file, cpp_file):
334 ## we need forward slashes here even on win32
335 #cpp_file = opj(cpp_file) #'/'.join(cpp_file.split('\\'))
336 #i_file = opj(i_file) #'/'.join(i_file.split('\\'))
337
338 if BUILD_RENAMERS:
339 xmltemp = tempfile.mktemp('.xml')
340
341 # First run swig to produce the XML file, adding
342 # an extra -D that prevents the old rename
343 # directives from being used
344 cmd = [ swig_cmd ] + swig_args + \
345 [ '-DBUILDING_RENAMERS', '-xmlout', xmltemp ] + \
346 ['-I'+dir, '-o', cpp_file, i_file]
347 msg(' '.join(cmd))
348 spawn(cmd)
349
350 # Next run build_renamers to process the XML
351 myRenamer = BuildRenamers()
352 myRenamer.run(dir, pre+basefile, xmltemp)
353 os.remove(xmltemp)
354
355 # Then run swig for real
356 cmd = [ swig_cmd ] + swig_args + interface + \
357 ['-I'+dir, '-o', cpp_file, '-xmlout', xml_file, i_file]
358 msg(' '.join(cmd))
359 spawn(cmd)
360
361
362 # copy the generated python file to the package directory
363 copy_file(py_file, package, update=not force, verbose=0)
364 CLEANUP.append(opj(package, os.path.basename(py_file)))
365
366 return sources
367
368
369
370 # Specializations of some distutils command classes
371 class wx_smart_install_data(distutils.command.install_data.install_data):
372 """need to change self.install_dir to the actual library dir"""
373 def run(self):
374 install_cmd = self.get_finalized_command('install')
375 self.install_dir = getattr(install_cmd, 'install_lib')
376 return distutils.command.install_data.install_data.run(self)
377
378
379 class wx_extra_clean(distutils.command.clean.clean):
380 """
381 Also cleans stuff that this setup.py copies itself. If the
382 --all flag was used also searches for .pyc, .pyd, .so files
383 """
384 def run(self):
385 from distutils import log
386 from distutils.filelist import FileList
387 global CLEANUP
388
389 distutils.command.clean.clean.run(self)
390
391 if self.all:
392 fl = FileList()
393 fl.include_pattern("*.pyc", 0)
394 fl.include_pattern("*.pyd", 0)
395 fl.include_pattern("*.so", 0)
396 CLEANUP += fl.files
397
398 for f in CLEANUP:
399 if os.path.isdir(f):
400 try:
401 if not self.dry_run and os.path.exists(f):
402 os.rmdir(f)
403 log.info("removing '%s'", f)
404 except IOError:
405 log.warning("unable to remove '%s'", f)
406
407 else:
408 try:
409 if not self.dry_run and os.path.exists(f):
410 os.remove(f)
411 log.info("removing '%s'", f)
412 except IOError:
413 log.warning("unable to remove '%s'", f)
414
415
416
417 class wx_install(distutils.command.install.install):
418 """
419 Turns off install_path_file
420 """
421 def initialize_options(self):
422 distutils.command.install.install.initialize_options(self)
423 self.install_path_file = 0
424
425
426 class wx_install_headers(distutils.command.install_headers.install_headers):
427 """
428 Install the header files to the WXPREFIX, with an extra dir per
429 filename too
430 """
431 def initialize_options(self):
432 self.root = None
433 distutils.command.install_headers.install_headers.initialize_options(self)
434
435 def finalize_options(self):
436 self.set_undefined_options('install', ('root', 'root'))
437 distutils.command.install_headers.install_headers.finalize_options(self)
438
439 def run(self):
440 if os.name == 'nt':
441 return
442 headers = self.distribution.headers
443 if not headers:
444 return
445
446 root = self.root
447 if root is None or WXPREFIX.startswith(root):
448 root = ''
449 for header, location in headers:
450 install_dir = os.path.normpath(root +
451 WXPREFIX +
452 '/include/wx-%d.%d/wx' % (VER_MAJOR, VER_MINOR) +
453 location)
454 self.mkpath(install_dir)
455 (out, _) = self.copy_file(header, install_dir)
456 self.outfiles.append(out)
457
458
459
460
461 def build_locale_dir(destdir, verbose=1):
462 """Build a locale dir under the wxPython package for MSW"""
463 moFiles = glob.glob(opj(WXDIR, 'locale', '*.mo'))
464 for src in moFiles:
465 lang = os.path.splitext(os.path.basename(src))[0]
466 dest = opj(destdir, lang, 'LC_MESSAGES')
467 mkpath(dest, verbose=verbose)
468 copy_file(src, opj(dest, 'wxstd.mo'), update=1, verbose=verbose)
469 CLEANUP.append(opj(dest, 'wxstd.mo'))
470 CLEANUP.append(dest)
471
472
473 def build_locale_list(srcdir):
474 # get a list of all files under the srcdir, to be used for install_data
475 def walk_helper(lst, dirname, files):
476 for f in files:
477 filename = opj(dirname, f)
478 if not os.path.isdir(filename):
479 lst.append( (dirname, [filename]) )
480 file_list = []
481 os.path.walk(srcdir, walk_helper, file_list)
482 return file_list
483
484
485 def find_data_files(srcdir, *wildcards):
486 # get a list of all files under the srcdir matching wildcards,
487 # returned in a format to be used for install_data
488
489 def walk_helper(arg, dirname, files):
490 names = []
491 lst, wildcards = arg
492 for wc in wildcards:
493 for f in files:
494 filename = opj(dirname, f)
495 if fnmatch.fnmatch(filename, wc) and not os.path.isdir(filename):
496 names.append(filename)
497 if names:
498 lst.append( (dirname, names ) )
499
500 file_list = []
501 os.path.walk(srcdir, walk_helper, (file_list, wildcards))
502 return file_list
503
504
505 def makeLibName(name):
506 if os.name == 'posix':
507 libname = '%s_%s-%s' % (WXBASENAME, name, WXRELEASE)
508 else:
509 libname = 'wxmsw%s%s_%s' % (WXDLLVER, libFlag(), name)
510
511 return [libname]
512
513
514
515 def adjustCFLAGS(cflags, defines, includes):
516 '''Extract the raw -I, -D, and -U flags and put them into
517 defines and includes as needed.'''
518 newCFLAGS = []
519 for flag in cflags:
520 if flag[:2] == '-I':
521 includes.append(flag[2:])
522 elif flag[:2] == '-D':
523 flag = flag[2:]
524 if flag.find('=') == -1:
525 defines.append( (flag, None) )
526 else:
527 defines.append( tuple(flag.split('=')) )
528 elif flag[:2] == '-U':
529 defines.append( (flag[2:], ) )
530 else:
531 newCFLAGS.append(flag)
532 return newCFLAGS
533
534
535
536 def adjustLFLAGS(lfags, libdirs, libs):
537 '''Extract the -L and -l flags and put them in libdirs and libs as needed'''
538 newLFLAGS = []
539 for flag in lflags:
540 if flag[:2] == '-L':
541 libdirs.append(flag[2:])
542 elif flag[:2] == '-l':
543 libs.append(flag[2:])
544 else:
545 newLFLAGS.append(flag)
546
547 return newLFLAGS
548
549
550
551 def getExtraPath(shortVer=True, addOpts=False):
552 """Get the dirname that wxPython will be installed under."""
553
554 if shortVer:
555 # short version, just Major.Minor
556 ep = "wx-%d.%d" % (VER_MAJOR, VER_MINOR)
557 # plus release if minor is odd
558 if VER_MINOR % 2 == 1:
559 ep += ".%d" % VER_RELEASE
560 else:
561 # long version, full version
562 ep = "wx-%d.%d.%d.%d" % (VER_MAJOR, VER_MINOR, VER_RELEASE, VER_SUBREL)
563
564 if addOpts:
565 ep += "-%s-%s" % (WXPORT, (UNICODE and 'unicode' or 'ansi'))
566
567 if FLAVOUR:
568 ep += "-" + FLAVOUR
569
570 return ep
571
572
573
574 #----------------------------------------------------------------------
575 # sanity checks
576
577 if CORE_ONLY:
578 BUILD_GLCANVAS = 0
579 BUILD_OGL = 0
580 BUILD_STC = 0
581 BUILD_GIZMOS = 0
582 BUILD_DLLWIDGET = 0
583 BUILD_IEWIN = 0
584 BUILD_ACTIVEX = 0
585
586 if debug:
587 FINAL = 0
588 HYBRID = 0
589
590 if FINAL:
591 HYBRID = 0
592
593 if UNICODE and WXPORT not in ['msw', 'gtk2']:
594 raise SystemExit, "UNICODE mode not currently supported on this WXPORT: "+WXPORT
595
596
597 if CONTRIBS_INC:
598 CONTRIBS_INC = [ CONTRIBS_INC ]
599 else:
600 CONTRIBS_INC = []
601
602
603 #----------------------------------------------------------------------
604 # Setup some platform specific stuff
605 #----------------------------------------------------------------------
606
607 if os.name == 'nt':
608 # Set compile flags and such for MSVC. These values are derived
609 # from the wxWidgets makefiles for MSVC, other compilers settings
610 # will probably vary...
611 if os.environ.has_key('WXWIN'):
612 WXDIR = os.environ['WXWIN']
613 else:
614 msg("WARNING: WXWIN not set in environment.")
615 WXDIR = '..' # assumes in CVS tree
616 WXPLAT = '__WXMSW__'
617 GENDIR = 'msw'
618
619 includes = ['include', 'src',
620 opj(WXDIR, 'lib', 'vc_dll', 'msw' + libFlag()),
621 opj(WXDIR, 'include'),
622 opj(WXDIR, 'contrib', 'include'),
623 ]
624
625 defines = [ ('WIN32', None),
626 ('_WINDOWS', None),
627
628 (WXPLAT, None),
629 ('WXUSINGDLL', '1'),
630
631 ('SWIG_GLOBAL', None),
632 ('WXP_USE_THREAD', '1'),
633 ]
634
635 if UNDEF_NDEBUG:
636 defines.append( ('NDEBUG',) ) # using a 1-tuple makes it do an undef
637
638 if HYBRID:
639 defines.append( ('__NO_VC_CRTDBG__', None) )
640
641 if not FINAL or HYBRID:
642 defines.append( ('__WXDEBUG__', None) )
643
644 libdirs = [ opj(WXDIR, 'lib', 'vc_dll') ]
645 libs = [ 'wxbase' + WXDLLVER + libFlag(), # TODO: trim this down to what is really needed for the core
646 'wxbase' + WXDLLVER + libFlag() + '_net',
647 'wxbase' + WXDLLVER + libFlag() + '_xml',
648 makeLibName('core')[0],
649 makeLibName('adv')[0],
650 makeLibName('html')[0],
651 makeLibName('xrc')[0],
652 ]
653
654 libs = libs + ['kernel32', 'user32', 'gdi32', 'comdlg32',
655 'winspool', 'winmm', 'shell32', 'oldnames', 'comctl32',
656 'odbc32', 'ole32', 'oleaut32', 'uuid', 'rpcrt4',
657 'advapi32', 'wsock32']
658
659
660 cflags = [ '/Gy',
661 # '/GX-' # workaround for internal compiler error in MSVC on some machines
662 ]
663 lflags = None
664
665 # Other MSVC flags...
666 # Too bad I don't remember why I was playing with these, can they be removed?
667 if FINAL:
668 pass #cflags = cflags + ['/O1']
669 elif HYBRID :
670 pass #cflags = cflags + ['/Ox']
671 else:
672 pass # cflags = cflags + ['/Od', '/Z7']
673 # lflags = ['/DEBUG', ]
674
675
676
677 #----------------------------------------------------------------------
678
679 elif os.name == 'posix':
680 WXDIR = '..'
681 includes = ['include', 'src']
682 defines = [('SWIG_GLOBAL', None),
683 ('HAVE_CONFIG_H', None),
684 ('WXP_USE_THREAD', '1'),
685 ]
686 if UNDEF_NDEBUG:
687 defines.append( ('NDEBUG',) ) # using a 1-tuple makes it do an undef
688
689 Verify_WX_CONFIG()
690
691 libdirs = []
692 libs = []
693
694 # If you get unresolved symbol errors on Solaris and are using gcc, then
695 # uncomment this block to add the right flags to the link step and build
696 # again.
697 ## if os.uname()[0] == 'SunOS':
698 ## libs.append('gcc')
699 ## libdirs.append(commands.getoutput("gcc -print-search-dirs | grep '^install' | awk '{print $2}'")[:-1])
700
701 cflags = os.popen(WX_CONFIG + ' --cxxflags', 'r').read()[:-1]
702 cflags = cflags.split()
703 if debug:
704 cflags.append('-g')
705 cflags.append('-O0')
706 else:
707 cflags.append('-O3')
708
709 lflags = os.popen(WX_CONFIG + ' --libs', 'r').read()[:-1]
710 lflags = lflags.split()
711
712 WXBASENAME = os.popen(WX_CONFIG + ' --basename').read()[:-1]
713 WXRELEASE = os.popen(WX_CONFIG + ' --release').read()[:-1]
714 WXPREFIX = os.popen(WX_CONFIG + ' --prefix').read()[:-1]
715
716
717 if sys.platform[:6] == "darwin":
718 # Flags and such for a Darwin (Max OS X) build of Python
719 WXPLAT = '__WXMAC__'
720 GENDIR = 'mac'
721 libs = ['stdc++']
722 NO_SCRIPTS = 1
723
724
725 else:
726 # Set flags for other Unix type platforms
727 GENDIR = WXPORT
728
729 if WXPORT == 'gtk':
730 WXPLAT = '__WXGTK__'
731 portcfg = os.popen('gtk-config --cflags', 'r').read()[:-1]
732 elif WXPORT == 'gtk2':
733 WXPLAT = '__WXGTK__'
734 GENDIR = 'gtk' # no code differences so use the same generated sources
735 portcfg = os.popen('pkg-config gtk+-2.0 --cflags', 'r').read()[:-1]
736 BUILD_BASE = BUILD_BASE + '-' + WXPORT
737 elif WXPORT == 'x11':
738 WXPLAT = '__WXX11__'
739 portcfg = ''
740 BUILD_BASE = BUILD_BASE + '-' + WXPORT
741 else:
742 raise SystemExit, "Unknown WXPORT value: " + WXPORT
743
744 cflags += portcfg.split()
745
746 # Some distros (e.g. Mandrake) put libGLU in /usr/X11R6/lib, but
747 # wx-config doesn't output that for some reason. For now, just
748 # add it unconditionally but we should really check if the lib is
749 # really found there or wx-config should be fixed.
750 libdirs.append("/usr/X11R6/lib")
751
752
753 # Move the various -I, -D, etc. flags we got from the *config scripts
754 # into the distutils lists.
755 cflags = adjustCFLAGS(cflags, defines, includes)
756 lflags = adjustLFLAGS(lflags, libdirs, libs)
757
758
759 #----------------------------------------------------------------------
760 else:
761 raise 'Sorry, platform not supported...'
762
763
764 #----------------------------------------------------------------------
765 # post platform setup checks and tweaks, create the full version string
766 #----------------------------------------------------------------------
767
768 if UNICODE:
769 BUILD_BASE = BUILD_BASE + '.unicode'
770 VER_FLAGS += 'u'
771
772 if os.path.exists('DAILY_BUILD'):
773
774 VER_FLAGS += '.' + open('DAILY_BUILD').read().strip()
775
776 VERSION = "%s.%s.%s.%s%s" % (VER_MAJOR, VER_MINOR, VER_RELEASE,
777 VER_SUBREL, VER_FLAGS)
778
779
780 #----------------------------------------------------------------------
781 # SWIG defaults
782 #----------------------------------------------------------------------
783
784 swig_cmd = SWIG
785 swig_force = force
786 swig_args = ['-c++',
787 '-Wall',
788 '-nodefault',
789
790 '-python',
791 '-keyword',
792 '-new_repr',
793 '-modern',
794
795 '-I' + opj(WXPY_SRC, 'src'),
796 '-D'+WXPLAT,
797 '-noruntime'
798 ]
799 if UNICODE:
800 swig_args.append('-DwxUSE_UNICODE')
801
802 if FULL_DOCS:
803 swig_args.append('-D_DO_FULL_DOCS')
804
805
806 swig_deps = [ opj(WXPY_SRC, 'src/my_typemaps.i'),
807 opj(WXPY_SRC, 'src/my_fragments.i'),
808 opj(WXPY_SRC, 'src/common.swg'),
809 opj(WXPY_SRC, 'src/pyrun.swg'),
810 opj(WXPY_SRC, 'src/python.swg'),
811 ]
812
813 depends = [ #'include/wx/wxPython/wxPython.h',
814 #'include/wx/wxPython/wxPython_int.h',
815 #'src/pyclasses.h',
816 ]
817
818 #----------------------------------------------------------------------
819
820 ####################################
821 # BuildRenamers
822 ####################################
823
824 import pprint
825 import xml.sax
826
827 try:
828 import libxml2
829 FOUND_LIBXML2 = True
830 except ImportError:
831 FOUND_LIBXML2 = False
832
833 #---------------------------------------------------------------------------
834
835
836 renamerTemplateStart = """\
837 // A bunch of %rename directives generated by BuildRenamers in config.py
838 // in order to remove the wx prefix from all global scope names.
839
840 #ifndef BUILDING_RENAMERS
841
842 """
843
844 renamerTemplateEnd = """
845 #endif
846 """
847
848 wxPythonTemplateStart = """\
849 ## This file reverse renames symbols in the wx package to give
850 ## them their wx prefix again, for backwards compatibility.
851 ##
852 ## Generated by BuildRenamers in config.py
853
854 # This silly stuff here is so the wxPython.wx module doesn't conflict
855 # with the wx package. We need to import modules from the wx package
856 # here, then we'll put the wxPython.wx entry back in sys.modules.
857 import sys
858 _wx = None
859 if sys.modules.has_key('wxPython.wx'):
860 _wx = sys.modules['wxPython.wx']
861 del sys.modules['wxPython.wx']
862
863 import wx.%s
864
865 sys.modules['wxPython.wx'] = _wx
866 del sys, _wx
867
868
869 # Now assign all the reverse-renamed names:
870 """
871
872 wxPythonTemplateEnd = """
873
874 """
875
876
877
878 #---------------------------------------------------------------------------
879 class BuildRenamers:
880 def run(self, destdir, modname, xmlfile, wxPythonDir="wxPython"):
881
882 assert FOUND_LIBXML2, "The libxml2 module is required to use the BuildRenamers functionality."
883
884 if not os.path.exists(wxPythonDir):
885 os.mkdir(wxPythonDir)
886
887 swigDest = os.path.join(destdir, "_"+modname+"_rename.i")
888 pyDest = os.path.join(wxPythonDir, modname + '.py')
889
890 swigDestTemp = tempfile.mktemp('.tmp')
891 swigFile = open(swigDestTemp, "w")
892 swigFile.write(renamerTemplateStart)
893
894 pyDestTemp = tempfile.mktemp('.tmp')
895 pyFile = open(pyDestTemp, "w")
896 pyFile.write(wxPythonTemplateStart % modname)
897
898 print "Parsing XML and building renamers..."
899 self.processXML(xmlfile, modname, swigFile, pyFile)
900
901 self.checkOtherNames(pyFile, modname,
902 os.path.join(destdir, '_'+modname+'_reverse.txt'))
903 pyFile.write(wxPythonTemplateEnd)
904 pyFile.close()
905
906 swigFile.write(renamerTemplateEnd)
907 swigFile.close()
908
909 # Compare the files just created with the existing one and
910 # blow away the old one if they are different.
911 for dest, temp in [(swigDest, swigDestTemp),
912 (pyDest, pyDestTemp)]:
913 if not os.path.exists(dest):
914 os.rename(temp, dest)
915 elif open(dest).read() != open(temp).read():
916 os.unlink(dest)
917 os.rename(temp, dest)
918 else:
919 print dest + " not changed."
920 os.unlink(temp)
921
922 #---------------------------------------------------------------------------
923
924
925 def GetAttr(self, node, name):
926 path = "./attributelist/attribute[@name='%s']/@value" % name
927 n = node.xpathEval2(path)
928 if len(n):
929 return n[0].content
930 else:
931 return None
932
933
934 def processXML(self, xmlfile, modname, swigFile, pyFile):
935
936 topnode = libxml2.parseFile(xmlfile).children
937
938 # remove any import nodes as we don't need to do renamers for symbols found therein
939 imports = topnode.xpathEval2("*/import")
940 for n in imports:
941 n.unlinkNode()
942 n.freeNode()
943
944 # do a depth first iteration over what's left
945 for node in topnode:
946 doRename = False
947 doPtr = False
948 addWX = False
949 revOnly = False
950
951
952 if node.name == "class":
953 lastClassName = name = self.GetAttr(node, "name")
954 lastClassSymName = sym_name = self.GetAttr(node, "sym_name")
955 doRename = True
956 doPtr = True
957 if sym_name != name:
958 name = sym_name
959 addWX = True
960
961 # renamed constructors
962 elif node.name == "constructor":
963 name = self.GetAttr(node, "name")
964 sym_name = self.GetAttr(node, "sym_name")
965 if sym_name != name:
966 name = sym_name
967 addWX = True
968 doRename = True
969
970 # only enumitems at the top level
971 elif node.name == "enumitem" and node.parent.parent.name == "include":
972 name = self.GetAttr(node, "name")
973 sym_name = self.GetAttr(node, "sym_name")
974 doRename = True
975
976
977 elif node.name in ["cdecl", "constant"]:
978 name = self.GetAttr(node, "name")
979 sym_name = self.GetAttr(node, "sym_name")
980 toplevel = node.parent.name == "include"
981
982 # top-level functions
983 if toplevel and self.GetAttr(node, "view") == "globalfunctionHandler":
984 doRename = True
985
986 # top-level global vars
987 elif toplevel and self.GetAttr(node, "feature_immutable") == "1":
988 doRename = True
989
990 # static methods
991 elif self.GetAttr(node, "view") == "staticmemberfunctionHandler":
992 name = lastClassName + '_' + name
993 sym_name = lastClassSymName + '_' + sym_name
994 # only output the reverse renamer in this case
995 doRename = revOnly = True
996
997 if doRename and name != sym_name:
998 name = sym_name
999 addWX = True
1000
1001
1002 if doRename and name:
1003 old = new = name
1004 if old.startswith('wx') and not old.startswith('wxEVT_'):
1005 # remove all wx prefixes except wxEVT_ and write a %rename directive for it
1006 new = old[2:]
1007 if not revOnly:
1008 swigFile.write("%%rename(%s) %35s;\n" % (new, old))
1009
1010 # Write assignments to import into the old wxPython namespace
1011 if addWX and not old.startswith('wx'):
1012 old = 'wx'+old
1013 pyFile.write("%s = wx.%s.%s\n" % (old, modname, new))
1014 if doPtr:
1015 pyFile.write("%sPtr = wx.%s.%sPtr\n" % (old, modname, new))
1016
1017
1018 #---------------------------------------------------------------------------
1019
1020 def checkOtherNames(self, pyFile, moduleName, filename):
1021 if os.path.exists(filename):
1022 prefixes = []
1023 for line in file(filename):
1024 if line.endswith('\n'):
1025 line = line[:-1]
1026 if line and not line.startswith('#'):
1027 if line.endswith('*'):
1028 prefixes.append(line[:-1])
1029 elif line.find('=') != -1:
1030 pyFile.write("%s\n" % line)
1031 else:
1032 wxname = 'wx' + line
1033 if line.startswith('wx') or line.startswith('WX') or line.startswith('EVT'):
1034 wxname = line
1035 pyFile.write("%s = wx.%s.%s\n" % (wxname, moduleName, line))
1036
1037 if prefixes:
1038 pyFile.write(
1039 "\n\nd = globals()\nfor k, v in wx.%s.__dict__.iteritems():"
1040 % moduleName)
1041 first = True
1042 for p in prefixes:
1043 if first:
1044 pyFile.write("\n if ")
1045 first = False
1046 else:
1047 pyFile.write("\n elif ")
1048 pyFile.write("k.startswith('%s'):\n d[k] = v" % p)
1049 pyFile.write("\ndel d, k, v\n\n")
1050
1051
1052 #---------------------------------------------------------------------------