[PyQt] PyQt: configure.py command line options check

Giovanni Bajo rasky at develer.com
Fri Jun 29 19:15:08 BST 2007


On 6/27/2007 3:13 PM, Phil Thompson wrote:

>>    -c, --concatenate     concatenate each module's C++ source files
>>    -j N, --concatenate-split=N
>>                          split the concatenated C++ source files into N
>>                          pieces [default: 1]
>>    -g, --consolidate     create a single Qt module which links against
>>                          all the Qt libraries
> 
> The Qt module is created anyway, it's the _qt module that gets created with 
> this option.

I dropped the "Qt" word from there.

I also found out about an undocumented "-z" option to add QScintilla to 
the consolidated module. I documented it and called "--consolidate-qsci".

The final version of the patch is attached. It's noisy because I renamed 
opt_* to opts.*, which follows the optparse convention. I also added 
some optparse-level check that directories are indeed directories and 
files are indeed files (which is also a good place where to convert them 
to absolute paths).

Finally, there's a set_console_width() function for people that don't 
have $COLUMNS in their env (Windows users and also Linux users through 
some terminals). It should be part of optparse (one day).
-- 
Giovanni Bajo

-------------- next part --------------
Index: configure.py
===================================================================
--- configure.py (revision 13281)
+++ configure.py (working copy)
@@ -17,7 +17,7 @@
 import os
 import string
 import glob
-import getopt
+import optparse
 import shutil
 import os.path
 
@@ -51,73 +51,175 @@
 # Get the SIP configuration.
 sipcfg = sipconfig.Configuration()
 
-# Command line options.
-opt_qmake = None
-opt_pyqtbindir = sipcfg.default_bin_dir
-opt_pyqtmoddir = sipcfg.default_mod_dir
-opt_pyqtsipdir = os.path.join(sipcfg.default_sip_dir, "PyQt4")
-opt_static = 0
-opt_debug = 0
-opt_concat = 0
-opt_split = 1
-opt_tracing = 0
-opt_verbose = 0
-opt_api = 0
-opt_qscidir = None
-opt_plugindir = None
-opt_bigqt = 0
-opt_qsci = None
-opt_enabled = []
-opt_staticplugins = []
-
-opt_vendorcheck = 0
-opt_vendincdir = sipcfg.py_inc_dir
-opt_vendlibdir = sipcfg.py_lib_dir
-
-opt_pydbusincdir = None
 pydbusmoddir = None
 dbusincdirs = []
 dbuslibdirs = []
 dbuslibs = []
 
+def setup_console_width():
+    """Get the correct console width, and store it into $COLUMNS.
 
-def usage(rcode=2):
-    """Display a usage message and exit.
+    This function is needed for Windows and also for some Linux terminals.
+    It will be useless when optparse will include it (one day).
+    """
+    if "COLUMNS" not in os.environ:
+        if os.name == "nt":
+            try:
+                # Call the Windows API (requires ctypes library)
+                from ctypes import windll, create_string_buffer
+                h = windll.kernel32.GetStdHandle(-11)
+                csbi = create_string_buffer(22)
+                res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
+                if res:
+                    import struct
+                    (bufx, bufy,
+                     curx, cury, wattr,
+                     left, top, right, bottom,
+                     maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
+
+                    os.environ["COLUMNS"] = str(right - left + 1)
+            except ImportError:
+                pass
+
+        else:
+            # Parse the output of stty -a
+            out = os.popen("stty -a").read()
+            m = re.search(r"columns (\d+);", out)
+            if m:
+                os.environ["COLUMNS"] = m.group(1)
 
-    rcode is the return code passed back to the calling process.
+
+def find_default_qmake():
+    """Find a default qmake, ie. the first on the path.
     """
-    if opt_qmake:
-        def_qmake = opt_qmake
+    try:
+        path = os.environ["PATH"]
+    except KeyError:
+        path = ""
+
+    if sys.platform == "win32":
+        base_qmake = "qmake.exe"
     else:
-        def_qmake = "none"
+        base_qmake = "qmake"
 
-    print "Usage:"
-    print "    python configure.py [-h] [-a] [-b dir] [-c] [-d dir] [-e module] [-g] [-i] [-j #] [-k] [-l dir] [-m dir] [-n dir] [-p dir] [-q exe] [-r] [-s dir] [-t plugin] [-u] [-v dir] [-w] option=value option+=value ..."
-    print "where:"
-    print "  -h         display this help message"
-    print "  -a         install the PyQt API file for QScintilla [default only if QScintilla installed]"
-    print "  -b dir     where pyuic4, pyrcc4 and pylupdate4 will be installed [default %s]" % opt_pyqtbindir
-    print "  -c         concatenate each module's C++ source files"
-    print "  -d dir     where the PyQt4 Python package will be installed [default %s]" % opt_pyqtmoddir
-    print "  -e module  enable the module [default all modules will be enabled]"
-    print "  -g         link all Qt libraries against the Qt module [default normal linking]"
-    print "  -i         enable checking of signed interpreters using the VendorID package [default disabled]"
-    print "  -j n       split the concatenated C++ source files into n pieces [default 1]"
-    print "  -k         build the PyQt4 modules as static libraries"
-    print "  -l dir     the directory containing the VendorID header file [default %s]" % opt_vendincdir
-    print "  -m dir     the directory containing the VendorID library [default %s]" % opt_vendlibdir
-    print "  -n dir     where the PyQt API file for QScintilla will be installed [default QTDIR/qsci]"
-    print "  -p dir     where the Designer plugin will be installed [default QTDIR/plugins]"
-    print "  -q exe     the pathname of qmake [default %s]" % def_qmake
-    print "  -r         generate code with tracing enabled [default disabled]"
-    print "  -s dir     the directory containing the dbus/dbus-python.h header file [default supplied by pkg-config]"
-    print "  -t plugin  add plugin to the list be linked if Qt is built as static libraries"
-    print "  -u         build with debugging symbols"
-    print "  -v dir     where the PyQt4 .sip files will be installed [default %s]" % opt_pyqtsipdir
-    print "  -w         don't suppress compiler output during configuration"
+    for d in path.split(os.pathsep):
+        qmake = os.path.join(d, base_qmake)
 
-    sys.exit(rcode)
+        if os.access(qmake, os.X_OK):
+            return qmake
+    return ""
+
+def create_optparser():
+    """Create the parser for the command line.
+    """
+    setup_console_width()
+    qmake = find_default_qmake()
+
+    def store_abspath_dir(option, opt_str, value, parser):
+        if not os.path.isdir(value):
+            raise optparse.OptionValueError("'%s' is not a directory" % value)
+        setattr(parser.values, option.dest, os.path.abspath(value))
+        
+    def store_abspath_file(option, opt_str, value, parser):
+        if not os.path.isfile(value):
+            raise optparse.OptionValueError("'%s' is not a file" % value)
+        setattr(parser.values, option.dest, os.path.abspath(value))
+
+    p = optparse.OptionParser(usage="python %prog [opts] [macro=value] [macro+=value]",
+                              version=pyqt_version_str)
+
+    # Note: we don't use %default to be compatible with Python 2.3.
+    p.add_option("-k", "--static", action="store_true", default=False,
+                 help="build modules as static libraries")
+    p.add_option("-r", "--trace", action="store_true", default=False, dest="tracing",
+                 help="build modules with tracing enabled")
+    p.add_option("-u", "--debug", action="store_true", default=False,
+                 help="build modules with debugging symbols")
+    p.add_option("-w", "--verbose", action="count", default=0,
+                 help="verbose output during configuration")
+
+    p.add_option("-c", "--concatenate", action="store_true", default=False,
+                 dest="concat", help="concatenate each module's C++ source files")
+    p.add_option("-j", "--concatenate-split", type="int", default=1,
+                 metavar="N", dest="split",
+                 help="split the concatenated C++ source files into N pieces "
+                      "[default: 1]")
+    p.add_option("-g", "--consolidate", action="store_true", default=False, dest="bigqt",
+                 help="create a single module which links against all the Qt libraries")
+
+    # Configuration
+    g = optparse.OptionGroup(p, title="Configuration")
+    g.add_option("-e", "--enable", action="append", metavar="MODULE", dest="enabled",
+                 help="enable the specified MODULE "
+                      "[default: all modules will be enabled]")
+    g.add_option("-t", "--plugin", action="append", metavar="PLUGIN", dest="staticplugins", default=[],
+                 help="add PLUGIN to the list be linked (if Qt is built as static libraries)")
+    g.add_option("-q", "--qmake", action="callback", metavar="FILE",
+                 default=qmake, callback=store_abspath_file, type="string",
+                 help="the pathname of qmake [default: %s]" % (qmake or "none"))
+    g.add_option("-s", "--dbus", action="callback", metavar="DIR",
+                 dest="pydbusincdir", callback=store_abspath_dir, type="string",
+                 help="the directory containing the dbus/dbus-python.h header file "
+                      "[default: supplied by pkg-config]")
+    p.add_option_group(g)
+
+    # Installation
+    g = optparse.OptionGroup(p, title="Installation")
+    g.add_option("-b", "--bindir", action="callback",
+                 default=sipcfg.default_bin_dir, type="string",
+                 metavar="DIR", dest="pyqtbindir", callback=store_abspath_dir,
+                 help="where pyuic4, pyrcc4 and pylupdate4 will be installed "
+                      "[default: %s]" % sipcfg.default_bin_dir)
+    g.add_option("-d", "--destdir", action="callback",
+                 default=sipcfg.default_mod_dir, type="string",
+                 metavar="DIR", dest="pyqtmoddir", callback=store_abspath_dir,
+                 help="where the PyQt4 Python package will be installed "
+                      "[default: %s]" % sipcfg.default_mod_dir)
+    g.add_option("-p", "--plugin-destdir", action="callback", type="string",
+                 metavar="DIR", dest="plugindir", callback=store_abspath_dir,
+                 help="where the Designer plugin will be installed "
+                      "[default: QTDIR/plugins]")
+    g.add_option("-v", "--sipdir", action="callback", metavar="DIR",
+                 dest="pyqtsipdir", callback=store_abspath_dir, type="string",
+                 default=os.path.join(sipcfg.default_sip_dir, "PyQt4"),
+                 help="where the PyQt4 .sip files will be installed "
+                      "[default: %s]" % sipcfg.default_sip_dir)
+    p.add_option_group(g)
+
+    # Vendor ID
+    g = optparse.OptionGroup(p, title="VendorID support")
+    g.add_option("-i", "--vendorid", action="store_true", default=False, dest="vendorcheck",
+                 help="enable checking of signed interpreters using the VendorID package "
+                      "[default: disabled]")
+    g.add_option("-l", "--vendorid-incdir", action="callback",
+                 default=sipcfg.py_inc_dir, type="string",
+                 metavar="DIR", dest="vendincdir", callback=store_abspath_dir,
+                 help="the directory containing the VendorID header file "
+                      "[default: %s]" % sipcfg.py_inc_dir)
+    g.add_option("-m", "--vendorid-libdir", action="callback",
+                 default=sipcfg.py_lib_dir, type="string",
+                 metavar="DIR", dest="vendlibdir", callback=store_abspath_dir,
+                 help="the directory containing the VendorID library "
+                      "[default: %s]" % sipcfg.py_lib_dir)
+    p.add_option_group(g)
+
+    # QScintilla
+    g = optparse.OptionGroup(p, title="QScintilla support")
+    g.add_option("-a", "--qsci-api", action="store_true", default=None, dest="api",
+                 help="install the PyQt API file for QScintilla "
+                      "[default: only if QScintilla installed]")
+    g.add_option("-n", "--qsci-api-destdir", action="callback", dest="qscidir",
+                 metavar="DIR", callback=store_abspath_dir, type="string",
+                 help="where the PyQt API file for QScintilla will be installed "
+                      "[default: QTDIR/qsci]")
+    g.add_option("-z", "--consolidate-qsci", action="callback", default=None,
+                 metavar="DIR", callback=store_abspath_dir, type="string",
+                 help="the directory containing the PyQScintilla source code "
+                      "(only needed if you want to include PyQScintilla within "
+                      "consolidated build)")
+    p.add_option_group(g)
 
+    return p
 
 class ConfigurePyQt4:
     """This class defines the methods to configure PyQt4.
@@ -179,12 +281,12 @@
         sp_libs, sp_libdirs = self._static_plugins("QtCore")
         sp_incdirs = []
 
-        if opt_vendorcheck:
-            sp_incdirs.append(opt_vendincdir)
-            sp_libdirs.append(opt_vendlibdir)
+        if opts.vendorcheck:
+            sp_incdirs.append(opts.vendincdir)
+            sp_libdirs.append(opts.vendlibdir)
             sp_libs.append("vendorid")
 
-        if opt_bigqt:
+        if opts.bigqt:
             cons_xtra_incdirs.extend(sp_incdirs)
             cons_xtra_libdirs.extend(sp_libdirs)
             cons_xtra_libs.extend(sp_libs)
@@ -197,7 +299,7 @@
         if "QtGui" in pyqt_modules:
             sp_libs, sp_libdirs = self._static_plugins("QtGui")
 
-            if opt_bigqt:
+            if opts.bigqt:
                 cons_xtra_libdirs.extend(sp_libdirs)
                 cons_xtra_libs.extend(sp_libs)
 
@@ -218,7 +320,7 @@
         if "QtSql" in pyqt_modules:
             sp_libs, sp_libdirs = self._static_plugins("QtSql")
 
-            if opt_bigqt:
+            if opts.bigqt:
                 cons_xtra_libdirs.extend(sp_libdirs)
                 cons_xtra_libs.extend(sp_libs)
 
@@ -243,14 +345,14 @@
             qpy_dir = os.path.abspath(os.path.join("qpy", "QtDesigner"))
 
             if sys.platform == "win32":
-                if opt_debug:
+                if opts.debug:
                     qpy_lib_dir = os.path.join(qpy_dir, "debug")
                 else:
                     qpy_lib_dir = os.path.join(qpy_dir, "release")
             else:
                 qpy_lib_dir = qpy_dir
 
-            if opt_bigqt:
+            if opts.bigqt:
                 cons_xtra_incdirs.append(qpy_dir)
                 cons_xtra_libdirs.append(qpy_lib_dir)
                 cons_xtra_libs.append("qpydesigner")
@@ -285,7 +387,7 @@
         generate_code("Qt")
 
         # Generate the consolidated module if required.
-        if opt_bigqt:
+        if opts.bigqt:
             _qtmod_sipdir = os.path.join("sip", "_qt")
             mk_clean_dir(_qtmod_sipdir)
 
@@ -299,12 +401,12 @@
             for m in pyqt_modules:
                 f.write("%%Include %s/%smod.sip\n" % (m, m))
 
-            if opt_qsci:
+            if opts.qsci:
                 f.write("%Include Qsci/Qscimod.sip\n")
                 cons_xtra_libs.append("qscintilla2")
 
                 # Copy in the QScintilla .sip files and fix the main one.
-                src_dir = os.path.join(opt_qsci, "Python", "sip")
+                src_dir = os.path.join(opts.qsci, "Python", "sip")
                 dst_dir = os.path.join("sip", "Qsci")
 
                 try:
@@ -323,8 +425,8 @@
                     cons_xtra_libs)
 
         # Tell the user about any plugins not found.
-        if opt_staticplugins:
-            sipconfig.inform("Unable to find the following static plugins: %s" % ", ".join(opt_staticplugins))
+        if opts.staticplugins:
+            sipconfig.inform("Unable to find the following static plugins: %s" % ", ".join(opts.staticplugins))
 
         # Generate the QScintilla API file.
         return #PORTING
@@ -362,9 +464,7 @@
         libs = []
         libdirs = []
 
-        global opt_staticplugins
-
-        for plug in opt_staticplugins:
+        for plug in opts.staticplugins:
             # Convert the plugin name to a platform specific filename.
             if self.generator in ("MSVC", "MSVC.NET", "BMAKE"):
                 pfname = plug + ".lib"
@@ -386,7 +486,7 @@
                     break
 
         # Remove those plugins we have handled.
-        opt_staticplugins = [p for p in opt_staticplugins if p not in libs]
+        opts.staticplugins = [p for p in opts.staticplugins if p not in libs]
 
         # If we have any plugins for this module then generate a .sip file that
         # will include the code needed to ensure the plugin gets linked.
@@ -449,7 +549,7 @@
 
                 pro = upro
 
-            run_command("%s %s %s" % (opt_qmake, qmake_args, pro))
+            run_command("%s %s %s" % (opts.qmake, qmake_args, pro))
             os.chdir(cwd)
 
         sipconfig.inform("Creating QPy libraries Makefile...")
@@ -474,7 +574,7 @@
                 dir="dbus",
                 install_dir=pydbusmoddir,
                 qt=["QtCore"],
-                debug=opt_debug,
+                debug=opts.debug,
                 universal=sipcfg.universal
             )
 
@@ -513,7 +613,7 @@
             dstdir=uicdir,
             srcdir="uic",
             dir="pyuic",
-            installs=[[os.path.basename(wrapper), opt_pyqtbindir]]
+            installs=[[os.path.basename(wrapper), opts.pyqtbindir]]
         )
 
         makefile.generate()
@@ -526,10 +626,10 @@
                 configuration=sipcfg,
                 build_file="pylupdate.sbf",
                 dir="pylupdate",
-                install_dir=opt_pyqtbindir,
+                install_dir=opts.pyqtbindir,
                 console=1,
                 qt=["QtCore", "QtGui", "QtXml"],
-                debug=opt_debug,
+                debug=opts.debug,
                 warnings=1,
                 universal=sipcfg.universal
             )
@@ -543,10 +643,10 @@
                 configuration=sipcfg,
                 build_file="pyrcc.sbf",
                 dir="pyrcc",
-                install_dir=opt_pyqtbindir,
+                install_dir=opts.pyqtbindir,
                 console=1,
                 qt=["QtCore", "QtXml"],
-                debug=opt_debug,
+                debug=opts.debug,
                 warnings=1,
                 universal=sipcfg.universal
             )
@@ -599,7 +699,7 @@
                 prj = prj.replace("@PYINCDIR@", sipcfg.py_inc_dir)
                 prj = prj.replace("@PYLINK@", link)
                 prj = prj.replace("@PYSHLIB@", pysh_lib)
-                prj = prj.replace("@QTPLUGINDIR@", opt_plugindir)
+                prj = prj.replace("@QTPLUGINDIR@", opts.plugindir)
 
                 fout = open("python.pro", "w+")
 
@@ -610,7 +710,7 @@
                 fout.write(prj)
                 fout.close()
 
-                run_command("%s %s" % (opt_qmake, qmake_args))
+                run_command("%s %s" % (opts.qmake, qmake_args))
                 os.chdir(cwd)
 
                 tool.append("designer")
@@ -642,20 +742,20 @@
     sipconfig.inform("The Qt binaries are in %s." % qt_bindir)
     sipconfig.inform("The Qt mkspecs directory is in %s." % qt_datadir)
     sipconfig.inform("These PyQt modules will be built: %s." % string.join(pyqt_modules))
-    sipconfig.inform("The PyQt Python package will be installed in %s." % opt_pyqtmoddir)
-    sipconfig.inform("The Designer plugin will be installed in %s." % os.path.join(opt_plugindir, "designer"))
+    sipconfig.inform("The PyQt Python package will be installed in %s." % opts.pyqtmoddir)
+    sipconfig.inform("The Designer plugin will be installed in %s." % os.path.join(opts.plugindir, "designer"))
 
-    if opt_api:
-        sipconfig.inform("The QScintilla API file will be installed in %s." % os.path.join(opt_qscidir, "api", "python"))
+    if opts.api:
+        sipconfig.inform("The QScintilla API file will be installed in %s." % os.path.join(opts.qscidir, "api", "python"))
 
     if pydbusmoddir:
         sipconfig.inform("The dbus support module will be installed in %s." % pydbusmoddir)
 
-    sipconfig.inform("The PyQt .sip files will be installed in %s." % opt_pyqtsipdir)
+    sipconfig.inform("The PyQt .sip files will be installed in %s." % opts.pyqtsipdir)
 
-    sipconfig.inform("pyuic4, pyrcc4 and pylupdate4 will be installed in %s." % opt_pyqtbindir)
+    sipconfig.inform("pyuic4, pyrcc4 and pylupdate4 will be installed in %s." % opts.pyqtbindir)
 
-    if opt_vendorcheck:
+    if opts.vendorcheck:
         sipconfig.inform("PyQt will only be usable with signed interpreters.")
 
 
@@ -673,9 +773,9 @@
         "pyqt_config_args":   sys.argv[1:],
         "pyqt_version":       pyqt_version,
         "pyqt_version_str":   pyqt_version_str,
-        "pyqt_bin_dir":       opt_pyqtbindir,
+        "pyqt_bin_dir":       opts.pyqtbindir,
         "pyqt_mod_dir":       pyqt_modroot,
-        "pyqt_sip_dir":       opt_pyqtsipdir,
+        "pyqt_sip_dir":       opts.pyqtsipdir,
         "pyqt_modules":       pyqt_modules,
         "pyqt_sip_flags":     qt_sip_flags,
         "qt_version":         qt_version,
@@ -697,7 +797,7 @@
 
     cmd is the command to run.
     """
-    if opt_verbose:
+    if opts.verbose:
         sys.stdout.write(cmd + "\n")
 
     fin, fout = os.popen4(cmd)
@@ -705,7 +805,7 @@
     # Read stdout and stderr until there is no more output.
     lout = fout.readline()
     while lout:
-        if opt_verbose:
+        if opts.verbose:
             sys.stdout.write(lout)
 
         lout = fout.readline()
@@ -742,7 +842,7 @@
     """
     opengl = (mname == "QtOpenGL")
 
-    makefile = sipconfig.ProgramMakefile(sipcfg, console=1, qt=[mname], warnings=0, opengl=opengl, debug=opt_debug)
+    makefile = sipconfig.ProgramMakefile(sipcfg, console=1, qt=[mname], warnings=0, opengl=opengl, debug=opts.debug)
 
     if lib:
         makefile.extra_libs.append(lib)
@@ -765,27 +865,25 @@
 def check_vendorid():
     """See if the VendorID library and include file can be found.
     """
-    global opt_vendorcheck
-
-    if opt_vendorcheck:
-        if os.access(os.path.join(opt_vendincdir, "vendorid.h"), os.F_OK):
-            if glob.glob(os.path.join(opt_vendlibdir, "*vendorid*")):
+    if opts.vendorcheck:
+        if os.access(os.path.join(opts.vendincdir, "vendorid.h"), os.F_OK):
+            if glob.glob(os.path.join(opts.vendlibdir, "*vendorid*")):
                 sipconfig.inform("The VendorID package was found.")
             else:
-                opt_vendorcheck = 0
+                opts.vendorcheck = 0
                 sipconfig.inform("The VendorID library could not be found in "
                                  "%s and so signed interpreter checking will "
                                  "be disabled. If the VendorID library is "
                                  "installed then use the -m argument to "
                                  "explicitly specify the correct "
-                                 "directory." % opt_vendlibdir)
+                                 "directory." % opts.vendlibdir)
         else:
-            opt_vendorcheck = 0
+            opts.vendorcheck = 0
             sipconfig.inform("vendorid.h could not be found in %s and so "
                              "signed interpreter checking will be disabled. "
                              "If the VendorID package is installed then use "
                              "the -l argument to explicitly specify the "
-                             "correct directory." % opt_vendincdir)
+                             "correct directory." % opts.vendincdir)
 
 
 def check_dbus():
@@ -821,8 +919,8 @@
     # for dbus-python (at least for versions up to and including v0.81.0).
     # Instead we look where DBus itself is installed - which in most cases will
     # be where dbus-python is also installed.
-    if opt_pydbusincdir:
-        dlist = [opt_pydbusincdir]
+    if opts.pydbusincdir:
+        dlist = [opts.pydbusincdir]
     else:
         dlist = dbusincdirs
 
@@ -852,7 +950,7 @@
     """
     # Check that the module is enabled if we are not automatically enabling all
     # modules.
-    if len(opt_enabled) > 0 and mname not in opt_enabled:
+    if len(opts.enabled) > 0 and mname not in opts.enabled:
         return
 
     # Check the module's main .sip file exists.
@@ -897,7 +995,7 @@
     """
     # If we don't check for signed interpreters, we exclude the 'VendorID'
     # feature
-    if not opt_vendorcheck:
+    if not opts.vendorcheck:
         qt_sip_flags.append("-x")
         qt_sip_flags.append("VendorID")
 
@@ -1011,7 +1109,7 @@
     # supposed to handle the consolidated module and its components.
     cons_args = []
 
-    if opt_bigqt:
+    if opts.bigqt:
         if mname == "_qt":
             qt_libs = []
 
@@ -1036,11 +1134,11 @@
     argv.extend(qt_sip_flags)
     argv.extend(cons_args)
 
-    if opt_concat:
+    if opts.concat:
         argv.append("-j")
-        argv.append(str(opt_split))
+        argv.append(str(opts.split))
 
-    if opt_tracing:
+    if opts.tracing:
         argv.append("-r")
 
     if mname not in ("Qt", "_qt", "Qsci"):
@@ -1062,7 +1160,7 @@
 
     cmd = string.join(argv)
 
-    if opt_verbose:
+    if opts.verbose:
         sys.stdout.write(cmd + "\n")
 
     os.system(cmd)
@@ -1080,7 +1178,7 @@
     for s in glob.glob("sip/" + mname + "/*.sip"):
         sipfiles.append(os.path.join("..", "sip", mname, os.path.basename(s)))
 
-    #installs.append([sipfiles, os.path.join(opt_pyqtsipdir, mname)])
+    #installs.append([sipfiles, os.path.join(opts.pyqtsipdir, mname)])
 
     opengl = (mname == "QtOpenGL")
 
@@ -1093,8 +1191,8 @@
         qt=qt_libs,
         opengl=opengl,
         warnings=1,
-        static=opt_static,
-        debug=opt_debug,
+        static=opts.static,
+        debug=opts.debug,
         universal=sipcfg.universal
     )
 
@@ -1152,7 +1250,7 @@
         oldfilename = "cache/"+newfilename
         if isDifferent(newfilename, oldfilename, start=5):
             shutil.copy2(newfilename, oldfilename)
-            if opt_verbose:
+            if opts.verbose:
                 sipconfig.inform("--> %s changed" % newfilename)
         else:
             shutil.copystat(oldfilename, newfilename)
@@ -1407,7 +1505,7 @@
 
     qt_lib = "QtCore"
 
-    if opt_debug and sys.platform != "win32":
+    if opts.debug and sys.platform != "win32":
         # Qt v4.2 and later for X11 platforms doesn't have separate debug
         # libraries.
         if qt_version < 0x040200 or sys.platform == "darwin":
@@ -1457,7 +1555,7 @@
     """
     sipconfig.inform("Determining the layout of your Qt installation...")
 
-    if not opt_qmake:
+    if not opts.qmake:
         sipconfig.error("Make sure you have a working Qt v4 qmake on your PATH or use the -q argument to explicitly specify a working Qt v4 qmake.")
 
     # The file names we will use to get the directory information.
@@ -1554,10 +1652,10 @@
 
     # Create the makefile, first making sure it doesn't already exist.
     remove_file(make_file)
-    run_command("%s %s %s" % (opt_qmake, qmake_args, pro_file))
+    run_command("%s %s %s" % (opts.qmake, qmake_args, pro_file))
 
     if not os.access(make_file, os.F_OK):
-        sipconfig.error("%s failed to create a makefile. Make sure you have a working Qt v4 qmake on your PATH or use the -q argument to explicitly specify a working Qt v4 qmake." % opt_qmake)
+        sipconfig.error("%s failed to create a makefile. Make sure you have a working Qt v4 qmake on your PATH or use the -q argument to explicitly specify a working Qt v4 qmake." % opts.qmake)
 
     # Try and work out the name of make.
     if sipcfg.platform.startswith("win32-msvc"):
@@ -1600,7 +1698,7 @@
     qt_shared = lines[6]
     qt_xfeatures = lines[7:]
 
-    if qt_shared and opt_staticplugins:
+    if qt_shared and opts.staticplugins:
         sipconfig.error("You cannot specify static plugins when Qt has been built as shared libraries.")
 
 
@@ -1614,121 +1712,44 @@
         if sipcfg.sip_version < sip_min_version:
             sipconfig.error("This version of PyQt requires SIP v%s or later" % sipconfig.version_to_string(sip_min_version))
 
-    # The process to find the Qt installation to use is driven by qmake, so
-    # first try and find a default qmake, ie. the first on the path.
-    try:
-        path = os.environ["PATH"]
-    except KeyError:
-        path = ""
-
-    if sys.platform == "win32":
-        base_qmake = "qmake.exe"
-    else:
-        base_qmake = "qmake"
-
-    global opt_qmake
-
-    for d in path.split(os.pathsep):
-        opt_qmake = os.path.join(d, base_qmake)
-
-        if os.access(opt_qmake, os.X_OK):
-            break
-    else:
-        opt_qmake = None
+    global opts
 
     # Parse the command line.
-    try:
-        optlist, args = getopt.getopt(argv[1:], "hab:cd:e:gij:kl:m:n:p:q:rs:t:uv:wz:")
-    except getopt.GetoptError:
-        usage()
-
-    global opt_pyqtbindir, opt_pyqtmoddir, opt_pyqtsipdir, opt_static
-    global opt_debug, opt_concat, opt_split, opt_tracing, opt_verbose
-    global opt_vendorcheck, opt_vendincdir, opt_vendlibdir, opt_api
-    global opt_pydbusincdir, opt_qscidir, opt_plugindir, opt_bigqt, opt_qsci
-
-    for opt, arg in optlist:
-        if opt == "-h":
-            usage(0)
-        elif opt == "-a":
-            opt_api = 1
-        elif opt == "-b":
-            opt_pyqtbindir = os.path.abspath(arg)
-        elif opt == "-c":
-            opt_concat = 1
-        elif opt == "-d":
-            opt_pyqtmoddir = os.path.abspath(arg)
-        elif opt == "-e":
-            opt_enabled.append(arg)
-        elif opt == "-g":
-            opt_bigqt = 1
-        elif opt == "-i":
-            opt_vendorcheck = 1
-        elif opt == "-j":
-            try:
-                opt_split = int(arg)
-            except:
-                usage()
-        elif opt == "-k":
-            opt_static = 1
-        elif opt == "-l":
-            opt_vendincdir = arg
-        elif opt == "-m":
-            opt_vendlibdir = arg
-        elif opt == "-n":
-            opt_qscidir = os.path.abspath(arg)
-        elif opt == "-p":
-            opt_plugindir = os.path.abspath(arg)
-        elif opt == "-q":
-            opt_qmake = os.path.abspath(arg)
-        elif opt == "-r":
-            opt_tracing = 1
-        elif opt == "-s":
-            opt_pydbusincdir = os.path.abspath(arg)
-        elif opt == "-t":
-            opt_staticplugins.append(arg)
-        elif opt == "-u":
-            opt_debug = 1
-        elif opt == "-v":
-            opt_pyqtsipdir = os.path.abspath(arg)
-        elif opt == "-w":
-            opt_verbose = 1
-        elif opt == "-z":
-            # Note that this is for internal use for including QScintilla in a
-            # a mega-package.
-            opt_qsci = os.path.abspath(arg)
+    p = create_optparser()
+    opts, args = p.parse_args()
 
     # Where the modules will be placed.
     global pyqt_modroot
-    pyqt_modroot = os.path.join(opt_pyqtmoddir, "PyQt4")
+    pyqt_modroot = os.path.join(opts.pyqtmoddir, "PyQt4")
 
     # When building static libraries, signed interpreter checking makes no
     # sense.
-    if opt_vendorcheck and opt_static:
+    if opts.vendorcheck and opts.static:
         sipconfig.error("Using the VendorID package when building static libraries makes no sense.")
 
     # Get the details of the Qt installation.
     get_qt_configuration()
 
     # Provide some defaults that are based on the Qt configuration.
-    if not opt_plugindir:
-        opt_plugindir = qt_pluginsdir
+    if not opts.plugindir:
+        opts.plugindir = qt_pluginsdir
 
-    if opt_qscidir:
+    if opts.qscidir:
         # An explicit directory implies installing the API file.
-        opt_api = 1
+        opts.api = 1
     elif False: # FIXME the path is not always writable!
-        opt_qscidir = os.path.join(qt_datadir, "qsci")
+        opts.qscidir = os.path.join(qt_datadir, "qsci")
 
-        if os.path.isdir(opt_qscidir):
+        if os.path.isdir(opts.qscidir):
             # Install the API file if the default directory exists.
-            opt_api = 1
+            opts.api = 1
 
     # Replace the existing build macros with the ones from the Qt installation.
     macros = get_build_macros(args)
 
     if macros is None:
-        usage()
+        p.print_help()
+        sys.exit(2)
 
     sipcfg.set_build_macros(macros)
 
@@ -1758,15 +1779,15 @@
 
     installs=[(pyqt.module_installs(), pyqt_modroot)]
 
-    if opt_api:
-        installs.append(("PyQt4.api", os.path.join(opt_qscidir, "api", "python")))
+    if opts.api:
+        installs.append(("PyQt4.api", os.path.join(opts.qscidir, "api", "python")))
 
     xtra_modules = ["Qt"]
 
-    if opt_bigqt:
+    if opts.bigqt:
         xtra_modules.append("_qt")
 
-        if opt_qsci:
+        if opts.qsci:
             xtra_modules.append("Qsci")
 
     sipconfig.ParentMakefile(


More information about the PyQt mailing list