Run swig from the main setup.py when building the renamer's XML
instead of from build_renamers.py. This makes it easy to ensure that the same flags are used. Also, use the new swig flag to generate the XML after the python language module has run, rather than instead of. This gives us more info in the xml output. Updated build_renamers.py to expect the xml file to already be generated, and also allow it to run with a xml doc tree from libxml2 rather than the xml.sax module. This makes the extraction of info much cleaner and logical since we usually need info from child or grandchild nodes. git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@24780 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
parent
7cb55566ba
commit
8994c3c20c
@ -1,12 +1,12 @@
|
||||
#!/usr/bin/env python
|
||||
#---------------------------------------------------------------------------
|
||||
"""
|
||||
Usage: build_renamers.py filename.i
|
||||
Usage: build_renamers.py destdir modulename filename.xml
|
||||
|
||||
Run SWIG on file.i using the XML language module and then scan the XML
|
||||
file produced and generate the %rename directives needed to implement
|
||||
the new wx namespace. The rename directives are output in a file
|
||||
named _filename_rename.i in the same dir as filename.i.
|
||||
Scans the XML file produced by SWIG (see setup.py) and generate the
|
||||
%rename directives needed to implement the new wx namespace. The
|
||||
rename directives are output in a file named _modulename_rename.i in
|
||||
the destdir given.
|
||||
|
||||
Also output a reverse 'renamer' Python module located in
|
||||
wxPython/filename.py (relative the the current dir) to make a
|
||||
@ -14,37 +14,25 @@ backwards compatibility interface for the old wxPython packages.
|
||||
"""
|
||||
|
||||
import sys, os, tempfile, pprint
|
||||
import xml.sax
|
||||
import xml.sax
|
||||
from distutils.spawn import spawn
|
||||
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
DO_UNLINK = True
|
||||
try:
|
||||
import libxml2
|
||||
USE_LIBXML2 = True
|
||||
except ImportError:
|
||||
USE_LIBXML2 = False
|
||||
|
||||
wxPythonDir = "wxPython"
|
||||
swig_cmd = "/opt/swig/bin/swig"
|
||||
if os.name == 'nt':
|
||||
swig_cmd = 'e:/projects/SWIG-cvs/swig.exe'
|
||||
|
||||
swig_args = ['-c++',
|
||||
'-Wall',
|
||||
'-nodefault',
|
||||
|
||||
'-xml',
|
||||
'-xmllite',
|
||||
|
||||
'-I./src',
|
||||
'-noruntime'
|
||||
]
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
|
||||
renamerTemplateStart = """\
|
||||
// A bunch of %%rename directives generated by %s
|
||||
// in order to remove the wx prefix from all global scope names.
|
||||
|
||||
#ifndef SWIGXML
|
||||
#ifndef BUILDING_RENAMERS
|
||||
|
||||
"""
|
||||
|
||||
@ -86,7 +74,7 @@ wxPythonTemplateEnd = """
|
||||
|
||||
def main(args):
|
||||
# check args
|
||||
if len(args) < 1:
|
||||
if len(args) < 3:
|
||||
print __doc__
|
||||
sys.exit(1)
|
||||
|
||||
@ -97,70 +85,148 @@ def main(args):
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
source = args[0]
|
||||
sourcePath, sourceBase = os.path.split(source)
|
||||
sourceBase = os.path.splitext(sourceBase)[0]
|
||||
|
||||
tempfile.tempdir = sourcePath
|
||||
xmlDest = tempfile.mktemp('.xml')
|
||||
swigDest = os.path.join(sourcePath, "_"+sourceBase+"_rename.i")
|
||||
pyDest = os.path.join(wxPythonDir, sourceBase + '.py')
|
||||
|
||||
#print "source: ", source
|
||||
#print "xmlDest: ", xmlDest
|
||||
#print "swigDest: ", swigDest
|
||||
#print "pyDest: ", pyDest
|
||||
|
||||
cmd = [ swig_cmd ] + swig_args + args[1:] + ['-I'+sourcePath, '-o', xmlDest, source]
|
||||
print ' '.join(cmd)
|
||||
spawn(cmd)
|
||||
destdir = args[0]
|
||||
modname = args[1]
|
||||
xmlfile = args[2]
|
||||
|
||||
swigDest = os.path.join(destdir, "_"+modname+"_rename.i")
|
||||
pyDest = os.path.join(wxPythonDir, modname + '.py')
|
||||
|
||||
swigDestTemp = tempfile.mktemp('.tmp')
|
||||
swigFile = open(swigDestTemp, "w")
|
||||
swigFile.write(renamerTemplateStart % sys.argv[0])
|
||||
|
||||
pyFile = open(pyDest, "w")
|
||||
pyFile.write(wxPythonTemplateStart % (sys.argv[0], sourceBase))
|
||||
|
||||
print "Parsing and building renamers",
|
||||
pyDestTemp = tempfile.mktemp('.tmp')
|
||||
pyFile = open(pyDestTemp, "w")
|
||||
pyFile.write(wxPythonTemplateStart % (sys.argv[0], modname))
|
||||
|
||||
try:
|
||||
## try:
|
||||
## import libxml2
|
||||
## print "using libxml2..."
|
||||
## ctxt = libxml2.createPushParser(ContentHandler(source, sourceBase, swigFile, pyFile),
|
||||
## '', 0, xmlDest)
|
||||
## for line in file(xmlDest):
|
||||
## if not line:
|
||||
## ctxt.parseChunck('', 0, 1)
|
||||
## break
|
||||
## ctxt.parseChunk(line, len(line), 0)
|
||||
|
||||
## except ImportError:
|
||||
print "using xml.sax..."
|
||||
xml.sax.parse(xmlDest, ContentHandler(source, sourceBase, swigFile, pyFile))
|
||||
print "Parsing and building renamers",
|
||||
if USE_LIBXML2:
|
||||
processXML(xmlfile, modname, swigFile, pyFile)
|
||||
else:
|
||||
print "using xml.sax..."
|
||||
xml.sax.parse(xmlfile, ContentHandler(modname, swigFile, pyFile))
|
||||
|
||||
finally:
|
||||
checkOtherNames(pyFile, sourceBase,
|
||||
os.path.join(sourcePath, '_'+sourceBase+'_reverse.txt'))
|
||||
|
||||
checkOtherNames(pyFile, modname,
|
||||
os.path.join(destdir, '_'+modname+'_reverse.txt'))
|
||||
pyFile.write(wxPythonTemplateEnd)
|
||||
pyFile.close()
|
||||
|
||||
swigFile.write(renamerTemplateEnd)
|
||||
swigFile.close()
|
||||
|
||||
# Compare the file just created with the existing one and
|
||||
# Compare the files just created with the existing one and
|
||||
# blow away the old one if they are different.
|
||||
if open(swigDest).read() != open(swigDestTemp).read():
|
||||
os.unlink(swigDest)
|
||||
os.rename(swigDestTemp, swigDest)
|
||||
else:
|
||||
print swigDest + " not changed."
|
||||
os.unlink(swigDestTemp)
|
||||
for dest, temp in [(swigDest, swigDestTemp),
|
||||
(pyDest, pyDestTemp)]:
|
||||
if open(dest).read() != open(temp).read():
|
||||
os.unlink(dest)
|
||||
os.rename(temp, dest)
|
||||
else:
|
||||
print dest + " not changed."
|
||||
os.unlink(temp)
|
||||
|
||||
if DO_UNLINK:
|
||||
os.unlink(xmlDest)
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
|
||||
def GetAttr(node, name):
|
||||
path = "./attributelist/attribute[@name='%s']/@value" % name
|
||||
n = node.xpathEval(path)
|
||||
if len(n):
|
||||
return n[0].content
|
||||
else:
|
||||
return None
|
||||
|
||||
|
||||
def processXML(xmlfile, modname, swigFile, pyFile):
|
||||
import libxml2
|
||||
print "using libxml2..."
|
||||
|
||||
topnode = libxml2.parseFile(xmlfile).children
|
||||
|
||||
# remove any import nodes as we don't need to do renamers for symbols found therein
|
||||
imports = topnode.xpathEval("*/import")
|
||||
for n in imports:
|
||||
n.unlinkNode()
|
||||
n.freeNode()
|
||||
|
||||
# do a depth first iteration over what's left
|
||||
for node in topnode:
|
||||
doRename = False
|
||||
doPtr = False
|
||||
addWX = False
|
||||
revOnly = False
|
||||
|
||||
|
||||
if node.name == "class":
|
||||
lastClassName = name = GetAttr(node, "name")
|
||||
lastClassSymName = sym_name = GetAttr(node, "sym_name")
|
||||
doRename = True
|
||||
doPtr = True
|
||||
if sym_name != name:
|
||||
name = sym_name
|
||||
addWX = True
|
||||
|
||||
# renamed constructors
|
||||
elif node.name == "constructor":
|
||||
name = GetAttr(node, "name")
|
||||
sym_name = GetAttr(node, "sym_name")
|
||||
if sym_name != name:
|
||||
name = sym_name
|
||||
addWX = True
|
||||
doRename = True
|
||||
|
||||
# only enumitems at the top level
|
||||
elif node.name == "enumitem" and node.parent.parent.name == "include":
|
||||
name = GetAttr(node, "name")
|
||||
sym_name = GetAttr(node, "sym_name")
|
||||
doRename = True
|
||||
|
||||
|
||||
elif node.name in ["cdecl", "constant"]:
|
||||
name = GetAttr(node, "name")
|
||||
sym_name = GetAttr(node, "sym_name")
|
||||
toplevel = node.parent.name == "include"
|
||||
|
||||
# top-level functions
|
||||
if toplevel and GetAttr(node, "view") == "globalfunctionHandler":
|
||||
doRename = True
|
||||
|
||||
# top-level global vars
|
||||
elif toplevel and GetAttr(node, "feature_immutable") == "1":
|
||||
doRename = True
|
||||
|
||||
# static methods
|
||||
elif GetAttr(node, "view") == "staticmemberfunctionHandler":
|
||||
name = lastClassName + '_' + name
|
||||
sym_name = lastClassSymName + '_' + sym_name
|
||||
# only output the reverse renamer in this case
|
||||
doRename = revOnly = True
|
||||
|
||||
if doRename and name != sym_name:
|
||||
name = sym_name
|
||||
addWX = True
|
||||
|
||||
|
||||
if doRename:
|
||||
old = new = name
|
||||
if old.startswith('wx') and not old.startswith('wxEVT_'):
|
||||
# remove all wx prefixes except wxEVT_ and write a %rename directive for it
|
||||
new = old[2:]
|
||||
if not revOnly:
|
||||
swigFile.write("%%rename(%s) %35s;\n" % (new, old))
|
||||
|
||||
# Write assignments to import into the old wxPython namespace
|
||||
if addWX and not old.startswith('wx'):
|
||||
old = 'wx'+old
|
||||
pyFile.write("%s = wx.%s.%s\n" % (old, modname, new))
|
||||
if doPtr:
|
||||
pyFile.write("%sPtr = wx.%s.%sPtr\n" % (old, modname, new))
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
def checkOtherNames(pyFile, moduleName, filename):
|
||||
@ -304,10 +370,9 @@ class Element:
|
||||
#---------------------------------------------------------------------------
|
||||
|
||||
class ContentHandler(xml.sax.ContentHandler):
|
||||
def __init__(self, source, sourceBase, swigFile, pyFile):
|
||||
def __init__(self, modname, swigFile, pyFile):
|
||||
xml.sax.ContentHandler.__init__(self)
|
||||
self.source = source
|
||||
self.sourceBase = sourceBase
|
||||
self.modname = modname
|
||||
self.swigFile = swigFile
|
||||
self.pyFile = pyFile
|
||||
self.elements = []
|
||||
@ -398,7 +463,7 @@ class ContentHandler(xml.sax.ContentHandler):
|
||||
|
||||
if self.imports == 0:
|
||||
# only write for items that are in this file, not imported
|
||||
ce.write(self.sourceBase, self.swigFile, self.pyFile)
|
||||
ce.write(self.modname, self.swigFile, self.pyFile)
|
||||
|
||||
if name == 'import':
|
||||
self.imports -= 1
|
||||
|
@ -246,6 +246,9 @@ def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args, swig_deps=
|
||||
if not os.path.exists(os.path.join(dir, gendir)):
|
||||
os.mkdir(os.path.join(dir, gendir))
|
||||
|
||||
if not os.path.exists(os.path.join("docs", "xml-raw")):
|
||||
os.mkdir(os.path.join("docs", "xml-raw"))
|
||||
|
||||
sources = []
|
||||
|
||||
for file in files:
|
||||
@ -253,6 +256,7 @@ def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args, swig_deps=
|
||||
i_file = os.path.join(dir, file)
|
||||
py_file = os.path.join(dir, gendir, basefile+'.py')
|
||||
cpp_file = os.path.join(dir, gendir, basefile+'_wrap.cpp')
|
||||
xml_file = os.path.join("docs", "xml-raw", basefile+'_swig.xml')
|
||||
|
||||
sources.append(cpp_file)
|
||||
|
||||
@ -268,14 +272,28 @@ def run_swig(files, dir, gendir, package, USE_SWIG, force, swig_args, swig_deps=
|
||||
#i_file = opj(i_file) #'/'.join(i_file.split('\\'))
|
||||
|
||||
if BUILD_RENAMERS:
|
||||
# first run build_renamers
|
||||
cmd = [ sys.executable, '-u',
|
||||
'./distrib/build_renamers.py',
|
||||
i_file, '-D'+WXPLAT, ] + \
|
||||
[x for x in swig_args if x.startswith('-I')]
|
||||
#info_file = "./distrib/swig_info"
|
||||
#info_dict = { 'cmd' : swig_cmd,
|
||||
# 'args' : swig_args + ['-I'+dir]
|
||||
# }
|
||||
#open(info_file, "w").write(str(args_dict))
|
||||
|
||||
# First run swig to produce the XML file, adding
|
||||
# an extra -D that prevents the old rename
|
||||
# directives from being used
|
||||
cmd = [ swig_cmd ] + swig_args + \
|
||||
[ '-DBUILDING_RENAMERS', '-xmlout', xml_file ] + \
|
||||
['-I'+dir, '-o', cpp_file, i_file]
|
||||
msg(' '.join(cmd))
|
||||
spawn(cmd)
|
||||
|
||||
# Next run build_renamers to process the XML
|
||||
cmd = [ sys.executable, '-u',
|
||||
'./distrib/build_renamers.py', dir, basefile, xml_file]
|
||||
msg(' '.join(cmd))
|
||||
spawn(cmd)
|
||||
#os.remove(info_file)
|
||||
|
||||
# Then run swig for real
|
||||
cmd = [ swig_cmd ] + swig_args + ['-I'+dir, '-o', cpp_file, i_file]
|
||||
msg(' '.join(cmd))
|
||||
|
Loading…
Reference in New Issue
Block a user