]>
git.saurik.com Git - wxWidgets.git/blob - utils/wxPython/distrib/build.py
2 #----------------------------------------------------------------------------
4 # Purpose: This script is used to build wxPython. It reads a build
5 # configuration file in the requested project directory and
6 # based on the contents of the file can build Makefiles for
7 # unix or win32, and can execute make with various options
8 # potentially automating the entire build/install/clean process
9 # from a single command.
13 # Created: 18-Aug-1999
15 # Copyright: (c) 1999 by Total Control Software
16 # Licence: wxWindows license
17 #----------------------------------------------------------------------------
21 This script is used to build wxPython. It reads a build configuration
22 file in the requested project directory and based on the contents of
23 the file can build Makefiles for unix or win32, and can execute make
24 with various options potentially automating the entire
25 build/install/clean process from a single command.
27 The default action is to build the Makefile and exit.
30 -C dir CD to dir before doing anything
31 -B file Use file as the build configuration (default ./build.cfg)
32 -M file Use file as the name of the makefile to create
35 -b Build the module (runs make)
36 -i Install the module (runs make install)
37 -c Cleanup (runs make clean)
38 -u Uninstall (runs make uninstall)
45 The build configuration file lists targets, source files and options
46 for the the build process. The contents of the build.cfg are used to
47 dynamically generate the Makefile.
49 To prevent you from getting screwed when the default build.cfg is
50 updated, you can override the values in build.cfg by putting your
51 custom definitions in a file named build.local. You can also place a
52 build.local file in the parent directory, or even in the grandparent
53 directory for project-wide overrides. Finally, command-line arguments
54 of the form NAME=VALUE can also be used to override simple configuration
55 values. The order of evaluation is:
57 0. comman-line flags (-M, -b, etc.)
59 2. ../../build.local (if present)
60 3. ../build.local (if present)
61 4. ./build.local (if present)
62 5. command-line NAME=VALUEs
64 The config files are actually just Python files that get exec'ed in a
65 separate namespace which is then used later as a configuration object.
66 This keeps the build script simple in that it doesn't have to parse
67 anything, and the config files can be much more than just names and
68 values as pretty much any python code can be executed. The global
69 variables set in the config namespace are what are used later as
75 The following variables can be set in the config files. Only a few are
76 required, the rest will either have suitable defaults or will be
77 calculated from your current Python runtime environment.
79 MODULE The name of the extension module to produce
80 SWIGFILES A list of files that should be run through SWIG
81 SWIGFLAGS Flags for SWIG
82 SOURCES Other C/C++ sources that should be part of the module
83 PYFILES Other Python files that should be installed with the module
84 CFLAGS Flags to be used by the compiler
85 LFLAGS Flags to be used at the link step
86 LIBS Libraries to be linked with
88 OTHERCFLAGS Extra flags to append to CFLAGS
89 OTHERLFLAGS Extra flags to append to LFLAGS
90 OTHERSWIGFLAGS Extra flags to append to SWIGFLAGS
91 OTHERLIBS Other libraries to be linked with, in addition to LIBS
92 OTHERTARGETS Other targets to be placed on the default rule line
94 Other targets to be placed on the install rule line
95 OTHERRULES This text is placed at the end of the makefile and
96 will typically be used for adding rules and such
97 DEFAULTRULE Text to be used for the default rule in the makefile
99 TARGETDIR Destination for the install step
101 MAKE The make program to use
102 MAKEFILE The name of the makefile
104 runBuild Setting this to 1 is eqivalent to the -b flag
105 runInstall Setting this to 1 is eqivalent to the -i flag
106 runClean Setting this to 1 is eqivalent to the -c flag
107 runUninstall Setting this to 1 is eqivalent to the -u flag
109 PYVERSION Version number of Python used in pathnames
110 PYPREFIX The root of the Python install
111 EXECPREFIX The root of the Python install for binary files
112 PYTHONLIB The Python link library
116 import sys
, os
, string
, getopt
118 #----------------------------------------------------------------------------
119 # This is really the wxPython version number, and will be placed in the
120 # Makefiles for use with the distribution related targets.
122 __version__
= '2.1.14'
124 #----------------------------------------------------------------------------
128 opts
, args
= getopt
.getopt(args
[1:], 'C:B:M:bicu')
133 if not os
.environ
.has_key('WXWIN'):
134 print "WARNING: WXWIN is not set in the environment. WXDIR may not\n"\
135 " be set properly in the makefile, you will have to \n"\
136 " set the environment variable or override in build.local."
139 bldCfgLocal
= 'build.local'
140 MAKEFILE
= 'Makefile'
146 for flag
, value
in opts
:
147 if flag
== '-C': os
.chdir(value
)
148 elif flag
== '-B': bldCfgFile
= value
149 elif flag
== '-M': makefile
= value
150 elif flag
== '-b': runBuild
= 1
151 elif flag
== '-c': runClean
= 1
152 elif flag
== '-i': runInstall
= 1
153 elif flag
== '-u': runUninstall
= 1
155 elif flag
== '-h': usage(); sys
.exit(1)
156 else: usage(); sys
.exit(1)
158 config
= BuildConfig(bldCfg
= bldCfg
,
159 bldCfgLocal
= bldCfgLocal
,
162 runInstall
= runInstall
,
164 runUninstall
= runUninstall
)
167 if config
.readConfigFiles(args
):
169 config
.makeMakefile()
172 cmd
= "%s -f %s" % (config
.MAKE
, config
.MAKEFILE
)
173 print "Running:", cmd
176 if not err
and config
.runInstall
:
177 cmd
= "%s -f %s install" % (config
.MAKE
, config
.MAKEFILE
)
178 print "Running:", cmd
182 if not err
and config
.runClean
:
183 cmd
= "%s -f %s clean" % (config
.MAKE
, config
.MAKEFILE
)
184 print "Running:", cmd
187 if not err
and config
.runUninstall
:
188 cmd
= "%s -f %s uninstall" % (config
.MAKE
, config
.MAKEFILE
)
189 print "Running:", cmd
195 #----------------------------------------------------------------------------
200 #----------------------------------------------------------------------------
203 if sys
.platform
!= 'win32':
204 st
= string
.join(string
.split(st
, '\\'), '/')
207 #----------------------------------------------------------------------------
210 return string
.join(string
.split(string
.strip(st
), ' '), ' \\\n\t')
212 #----------------------------------------------------------------------------
215 def __init__(self
, **kw
):
216 self
.__dict
__.update(kw
)
219 #------------------------------------------------------------
220 def setDefaults(self
):
221 self
.VERSION
= __version__
224 self
.SWIGFLAGS
= '-c++ -shadow -python -keyword -dnone -I$(WXPSRCDIR)'
228 self
.OTHERCFLAGS
= ''
229 self
.OTHERLFLAGS
= ''
230 self
.OTHERSWIGFLAGS
= ''
232 self
.OTHERTARGETS
= ''
233 self
.OTHERINSTALLTARGETS
= ''
234 self
.OTHERUNINSTALLTARGETS
= ''
236 self
.DEFAULTRULE
= 'default: $(GENCODEDIR) $(TARGET)'
237 self
.PYVERSION
= sys
.version
[:3]
238 self
.PYPREFIX
= sys
.prefix
239 self
.EXECPREFIX
= sys
.exec_prefix
240 self
.WXDIR
= '$(WXWIN)'
242 self
.WXP_USE_THREAD
= '1'
243 self
.WXUSINGDLL
= '1'
245 self
.WXPSRCDIR
= '$(WXDIR)/utils/wxPython/src'
250 if sys
.platform
== 'win32':
252 self
.PYTHONLIB
= '$(PYPREFIX)\\libs\\python15.lib'
253 self
.TARGETDIR
= '$(PYPREFIX)\\wxPython'
254 self
.LIBS
= '$(PYTHONLIB) $(WXPSRCDIR)\wxc.lib'
255 self
.GENCODEDIR
= 'msw'
256 self
.SWIGTOOLKITFLAG
= '-D__WXMSW__'
258 self
.TARGET
= '$(MODULE).pyd'
259 self
.CFLAGS
= '-I$(PYPREFIX)\include -I$(WXPSRCDIR) -I. /Fp$(MODULE).pch /YXhelpers.h -DSWIG_GLOBAL -DHAVE_CONFIG_H $(THREAD) '
260 self
.LFLAGS
= '$(DEBUGLFLAGS) /DLL /subsystem:windows,3.50 /machine:I386 /nologo'
263 self
.OVERRIDEFLAGS
= '/GX-'
264 self
.RMCMD
= '-erase '
265 self
.WXPSRCDIR
= os
.path
.normpath(self
.WXPSRCDIR
)
271 self
.PYLIB
= '$(EXECPREFIX)/lib/python$(PYVERSION)'
272 self
.LIBPL
= '$(PYLIB)/config'
273 self
.PYTHONLIB
= '$(LIBPL)/libpython$(PYVERSION).a'
274 self
.TARGETDIR
= '$(EXECPREFIX)/lib/python$(PYVERSION)/site-packages/wxPython'
275 self
.TARGET
= '$(MODULE)module$(SO)'
277 self
.HELPERLIB
= 'wxPyHelpers'
278 self
.HELPERLIBDIR
= '/usr/local/lib'
279 self
.CFLAGS
= '-DSWIG_GLOBAL -DHAVE_CONFIG_H $(THREAD) -I. '\
280 '`$(WXCONFIG) --cflags` -I$(PYINCLUDE) -I$(EXECINCLUDE) '\
282 self
.LFLAGS
= '-L$(WXPSRCDIR) `$(WXCONFIG) --libs`'
283 self
.LIBS
= '-l$(HELPERLIB)'
284 self
.RMCMD
= '-rm -f '
285 self
.WXCONFIG
= 'wx-config'
288 # **** What to do when I start supporting Motif, etc.???
289 self
.GENCODEDIR
= 'gtk'
290 self
.SWIGTOOLKITFLAG
= '-D__WXGTK__'
292 # Extract a few things from Python's Makefile...
294 filename
= os
.path
.join(self
.EXECPREFIX
,
295 'lib/python'+self
.PYVERSION
,
297 mfText
= string
.split(open(filename
, 'r').read(), '\n')
299 raise SystemExit, "Python development files not found"
301 self
.CCC
= self
.findMFValue(mfText
, 'CCC')
302 self
.CC
= self
.findMFValue(mfText
, 'CC')
303 self
.OPT
= self
.findMFValue(mfText
, 'OPT')
304 self
.SO
= self
.findMFValue(mfText
, 'SO')
305 self
.LDSHARED
= self
.findMFValue(mfText
, 'LDSHARED')
306 self
.CCSHARED
= self
.findMFValue(mfText
, 'CCSHARED')
307 #self.LINKFORSHARED = self.findMFValue(mfText, 'LINKFORSHARED')
308 #self. = self.findMFValue(mfText, '')
309 #self. = self.findMFValue(mfText, '')
312 # The majority of cases will require LDSHARED to be
313 # modified to use the C++ driver instead of the C driver
314 # for linking. We'll try to do it here and if we goof up
315 # then the user can correct it in their build.local file.
316 self
.LDSHARED
= string
.join(['$(CCC)'] +
317 string
.split(self
.LDSHARED
, ' ')[1:],
321 #------------------------------------------------------------
323 # This is called after the config files have been evaluated
324 # so we can do some sanity checking...
325 if sys
.platform
!= 'win32':
327 self
.CCC
= os
.popen('%(WXCONFIG)s --cxx' % self
.__dict
__, 'r').read()[:-1]
329 print "Warning: C++ compiler not specified (CCC). Assuming c++"
332 self
.CCC
= os
.popen('%(WXCONFIG)s --cc' % self
.__dict
__, 'r').read()[:-1]
334 print "Warning: C compiler not specified (CC). Assuming cc"
337 #------------------------------------------------------------
338 def findMFValue(self
, mfText
, st
):
339 # Find line begining with st= and return the value
340 # Regex would probably be to cooler way to do this, but
341 # I think this is the most understandable.
343 if string
.find(line
, st
+'=') == 0:
344 st
= string
.strip(line
[len(st
)+1:])
348 #------------------------------------------------------------
349 def makeMakefile(self
):
351 # make a list of object file names
353 for name
in self
.SWIGFILES
:
354 objects
= objects
+ os
.path
.splitext(name
)[0] + self
.OBJEXT
+ ' '
355 for name
in self
.SOURCES
:
356 obj
= os
.path
.basename(name
)
357 objects
= objects
+ os
.path
.splitext(obj
)[0] + self
.OBJEXT
+ ' '
358 self
.OBJECTS
= splitlines(objects
)
361 # now build the text for the dependencies
363 for name
in self
.SWIGFILES
:
364 rootname
= os
.path
.splitext(name
)[0]
365 text
= '$(GENCODEDIR)/%s.cpp $(GENCODEDIR)/%s.py : %s.i %s\n' \
366 '$(TARGETDIR)\\%s.py : $(GENCODEDIR)\\%s.py\n' % \
367 (rootname
, rootname
, rootname
, self
.SWIGDEPS
, rootname
, rootname
)
368 depends
= depends
+ text
370 text
= '%s%s : %s\n' % \
371 (os
.path
.splitext(name
)[0], self
.OBJEXT
, self
.OTHERDEPS
)
372 depends
= depends
+ text
373 for name
in self
.PYFILES
:
374 text
= '$(TARGETDIR)\\%s.py : %s.py\n' % \
375 tuple([os
.path
.splitext(name
)[0]] * 2)
376 depends
= depends
+ text
378 for name
in self
.SOURCES
:
379 name
= os
.path
.basename(name
)
380 text
= '%s%s : %s\n' % \
381 (os
.path
.splitext(name
)[0], self
.OBJEXT
, self
.OTHERDEPS
)
382 depends
= depends
+ text
384 self
.DEPENDS
= swapslash(depends
)
387 # and the list of .py files
389 for name
in self
.SWIGFILES
:
390 pymodules
= pymodules
+ '$(TARGETDIR)\\%s.py ' % os
.path
.splitext(name
)[0]
391 for name
in self
.PYFILES
:
392 pymodules
= pymodules
+ '$(TARGETDIR)\\%s.py ' % os
.path
.splitext(name
)[0]
393 self
.PYMODULES
= splitlines(swapslash(pymodules
))
396 # now make a list of the python files that would need uninstalled
398 for name
in self
.SWIGFILES
:
399 pycleanup
= pycleanup
+ self
.makeCleanupList(name
)
400 for name
in self
.PYFILES
:
401 pycleanup
= pycleanup
+ self
.makeCleanupList(name
)
402 self
.PYCLEANUP
= swapslash(pycleanup
)
405 # finally, build the makefile
406 if sys
.platform
== 'win32':
408 self
.RESFILE
= '$(MODULE).res'
409 self
.RESRULE
= '$(MODULE).res : $(MODULE).rc $(WXDIR)\\include\\wx\\msw\\wx.rc\n\t'\
410 '$(rc) -r /i$(WXDIR)\\include -fo$@ $(MODULE).rc'
411 text
= win32Template
% self
.__dict
__
413 text
= unixTemplate
% self
.__dict
__
414 f
= open(self
.MAKEFILE
, 'w')
418 print "Makefile created: ", self
.MAKEFILE
422 #------------------------------------------------------------
423 def makeCleanupList(self
, name
):
425 st
= st
+ '\t%s$(TARGETDIR)\\%s.py\n' % (self
.RMCMD
, os
.path
.splitext(name
)[0])
426 st
= st
+ '\t%s$(TARGETDIR)\\%s.pyc\n' % (self
.RMCMD
, os
.path
.splitext(name
)[0])
427 st
= st
+ '\t%s$(TARGETDIR)\\%s.pyo\n' % (self
.RMCMD
, os
.path
.splitext(name
)[0])
431 #------------------------------------------------------------
432 def readConfigFiles(self
, args
):
433 return self
.processFile(self
.bldCfg
, 1) and \
434 self
.processFile(os
.path
.join('../..', self
.bldCfgLocal
)) and \
435 self
.processFile(os
.path
.join('..', self
.bldCfgLocal
)) and \
436 self
.processFile(os
.path
.join('.', self
.bldCfgLocal
)) and \
437 self
.processArgs(args
)
439 #------------------------------------------------------------
440 def processFile(self
, filename
, required
=0):
442 text
= open(filename
, 'r').read()
445 print "Unable to open %s" % filename
451 exec(text
, self
.__dict
__)
453 print "Error evaluating %s" % filename
455 traceback
.print_exc()
460 #------------------------------------------------------------
461 def processArgs(self
, args
):
464 pair
= string
.split(st
, '=')
467 self
.__dict
__[name
] = value
469 print "Error parsing command-line: %s" % st
475 #------------------------------------------------------------
481 #----------------------------------------------------------------------------
482 #----------------------------------------------------------------------------
483 #----------------------------------------------------------------------------
486 #----------------------------------------------------------------------
487 # This makefile was autogenerated from build.py. Your changes will be
488 # lost if the generator is run again. You have been warned.
489 #----------------------------------------------------------------------
492 VERSION = %(VERSION)s
494 SWIGFLAGS = %(SWIGFLAGS)s %(SWIGTOOLKITFLAG)s %(OTHERSWIGFLAGS)s
497 PYVERSION = %(PYVERSION)s
498 PYPREFIX = %(PYPREFIX)s
499 EXECPREFIX = %(EXECPREFIX)s
500 PYTHONLIB = %(PYTHONLIB)s
502 WXP_USE_THREAD = %(WXP_USE_THREAD)s
503 WXUSINGDLL = %(WXUSINGDLL)s
504 GENCODEDIR = %(GENCODEDIR)s
505 RESFILE = %(RESFILE)s
506 WXPSRCDIR = %(WXPSRCDIR)s
509 TARGETDIR = %(TARGETDIR)s
511 OBJECTS = %(OBJECTS)s
512 PYMODULES = %(PYMODULES)s
518 !if "$(FINAL)" == "0"
519 DEBUGLFLAGS = /DEBUG /INCREMENTAL:YES
521 DEBUGLFLAGS = /INCREMENTAL:NO
523 !if "$(WXP_USE_THREAD)" == "1"
524 THREAD=-DWXP_USE_THREAD=1
531 OVERRIDEFLAGS=%(OVERRIDEFLAGS)s
532 EXTRAFLAGS = $(CFLAGS) %(OTHERCFLAGS)s
534 LFLAGS = %(LFLAGS)s %(OTHERLFLAGS)s
535 EXTRALIBS = %(LIBS)s %(OTHERLIBS)s
539 #----------------------------------------------------------------------
541 !include $(WXDIR)\\src\\makevc.env
543 #----------------------------------------------------------------------
545 %(DEFAULTRULE)s %(OTHERTARGETS)s
549 install: $(TARGETDIR) $(TARGETDIR)\\$(TARGET) pycfiles %(OTHERINSTALLTARGETS)s
565 uninstall: %(OTHERUNINSTALLTARGETS)s
566 -erase $(TARGETDIR)\\$(TARGET)
570 #----------------------------------------------------------------------
571 # implicit rule for compiling .cpp and .c files
574 $(CPPFLAGS) /c /Tp $<
577 {$(GENCODEDIR)}.cpp{}.obj:
579 $(CPPFLAGS) /c /Tp $<
589 # Implicit rules to run SWIG
590 {}.i{$(GENCODEDIR)}.cpp:
591 swig $(SWIGFLAGS) -c -o $@ $<
593 {}.i{$(GENCODEDIR)}.py:
594 swig $(SWIGFLAGS) -c -o $(GENCODEDIR)\\tmp_wrap.cpp $<
595 -erase $(GENCODEDIR)\\tmp_wrap.cpp
598 {$(GENCODEDIR)}.py{$(TARGETDIR)}.py:
601 {}.py{$(TARGETDIR)}.py:
604 #----------------------------------------------------------------------
606 $(TARGET) : $(DUMMYOBJ) $(WXLIB) $(OBJECTS) $(RESFILE)
609 $(LFLAGS) /export:init$(MODULE) /implib:./$(MODULE).lib
610 $(DUMMYOBJ) $(OBJECTS) $(RESFILE)
618 $(TARGETDIR)\\$(TARGET) : $(TARGET)
622 pycfiles : $(PYMODULES)
623 $(EXECPREFIX)\\python $(PYPREFIX)\\Lib\\compileall.py -l $(TARGETDIR)
624 $(EXECPREFIX)\\python -O $(PYPREFIX)\Lib\\compileall.py -l $(TARGETDIR)
633 #----------------------------------------------------------------------
637 #----------------------------------------------------------------------
650 #----------------------------------------------------------------------------
651 #----------------------------------------------------------------------------
652 #----------------------------------------------------------------------------
655 #----------------------------------------------------------------------
656 # This makefile was autogenerated from build.py. Your changes will be
657 # lost if the generator is run again. You have been warned.
658 #----------------------------------------------------------------------
663 VERSION = %(VERSION)s
665 SWIGFLAGS = %(SWIGFLAGS)s %(SWIGTOOLKITFLAG)s %(OTHERSWIGFLAGS)s
666 CFLAGS = %(CFLAGS)s $(OPT) %(OTHERCFLAGS)s
667 LFLAGS = %(LFLAGS)s %(OTHERLFLAGS)s
668 LIBS = %(LIBS)s %(OTHERLIBS)s
669 PYVERSION = %(PYVERSION)s
670 PYPREFIX = %(PYPREFIX)s
671 EXECPREFIX = %(EXECPREFIX)s
672 PYINCLUDE = $(PYPREFIX)/include/python$(PYVERSION)
673 EXECINCLUDE = $(EXECPREFIX)/include/python$(PYVERSION)
676 PYTHONLIB = %(PYTHONLIB)s
678 WXP_USE_THREAD = %(WXP_USE_THREAD)s
679 GENCODEDIR = %(GENCODEDIR)s
680 WXPSRCDIR = %(WXPSRCDIR)s
681 HELPERLIB = %(HELPERLIB)s
682 HELPERLIBDIR = %(HELPERLIBDIR)s
683 WXCONFIG=%(WXCONFIG)s
684 TARGETDIR = %(TARGETDIR)s
691 LDSHARED = %(LDSHARED)s
692 CCSHARED = %(CCSHARED)s
695 OBJECTS = %(OBJECTS)s
696 PYMODULES = %(PYMODULES)s
700 ifeq ($(WXP_USE_THREAD), 1)
701 THREAD=-DWXP_USE_THREAD
704 #----------------------------------------------------------------------
706 %(DEFAULTRULE)s %(OTHERTARGETS)s
708 install: $(TARGETDIR) $(TARGETDIR)/$(TARGET) pycfiles %(OTHERINSTALLTARGETS)s
714 uninstall: %(OTHERUNINSTALLTARGETS)s
715 -rm -f $(TARGETDIR)/$(TARGET)
719 #----------------------------------------------------------------------
722 $(CCC) $(CCSHARED) $(CFLAGS) $(OTHERCFLAGS) -c $<
724 %%.o : $(GENCODEDIR)/%%.cpp
725 $(CCC) $(CCSHARED) $(CFLAGS) $(OTHERCFLAGS) -c $<
728 $(CC) $(CCSHARED) $(CFLAGS) $(OTHERCFLAGS) -c $<
730 %%.o : $(GENCODEDIR)/%%.c
731 $(CC) $(CCSHARED) $(CFLAGS) $(OTHERCFLAGS) -c $<
734 $(GENCODEDIR)/%%.cpp : %%.i
735 swig $(SWIGFLAGS) -c -o $@ $<
737 $(GENCODEDIR)/%%.py : %%.i
738 swig $(SWIGFLAGS) -c -o $(GENCODEDIR)/tmp_wrap.cpp $<
739 rm $(GENCODEDIR)/tmp_wrap.cpp
746 $(TARGETDIR)/%% : $(GENCODEDIR)/%%
749 #----------------------------------------------------------------------
753 #----------------------------------------------------------------------
755 $(TARGET) : $(OBJECTS)
756 $(LDSHARED) $(OBJECTS) $(LFLAGS) $(LIBS) $(OTHERLIBS) -o $(TARGET)
760 pycfiles : $(PYMODULES)
761 $(EXECPREFIX)/bin/python $(PYLIB)/compileall.py -l $(TARGETDIR)
762 $(EXECPREFIX)/bin/python -O $(PYLIB)/compileall.py -l $(TARGETDIR)
766 mkdir -p $(TARGETDIR)
771 #----------------------------------------------------------------------
781 #----------------------------------------------------------------------------
783 if __name__
== '__main__':
787 #----------------------------------------------------------------------------