configure.py
changeset 0 16d8024aca5e
child 1 f7ac710697a9
equal deleted inserted replaced
-1:000000000000 0:16d8024aca5e
       
     1 #!/usr/bin/env python
       
     2 # -*- coding: utf-8 -*-
       
     3 #
       
     4 #############################################################################
       
     5 ##
       
     6 ## Copyright (C) 2008-2010 Nokia Corporation and/or its subsidiary(-ies).
       
     7 ## All rights reserved.
       
     8 ## Contact: Nokia Corporation (developer.feedback@nokia.com)
       
     9 ##
       
    10 ## This file is part of the UI Extensions for Mobile.
       
    11 ##
       
    12 ## GNU Lesser General Public License Usage
       
    13 ## This file may be used under the terms of the GNU Lesser General Public
       
    14 ## License version 2.1 as published by the Free Software Foundation and
       
    15 ## appearing in the file LICENSE.LGPL included in the packaging of this file.
       
    16 ## Please review the following information to ensure the GNU Lesser General
       
    17 ## Public License version 2.1 requirements will be met:
       
    18 ## http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
       
    19 ##
       
    20 ## In addition, as a special exception, Nokia gives you certain additional
       
    21 ## rights.  These rights are described in the Nokia Qt LGPL Exception
       
    22 ## version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
       
    23 ##
       
    24 ## If you have questions regarding the use of this file, please contact
       
    25 ## Nokia at developer.feedback@nokia.com.
       
    26 ##
       
    27 #############################################################################
       
    28 
       
    29 import re
       
    30 import os
       
    31 import sys
       
    32 import shutil
       
    33 import tempfile
       
    34 import optparse
       
    35 if sys.version_info[0] == 2 and sys.version_info[1] < 4:
       
    36     # for scratchbox compatibility
       
    37     import popen2
       
    38 else:
       
    39     import subprocess
       
    40 
       
    41 # ============================================================================
       
    42 # Globals
       
    43 # ============================================================================
       
    44 HB_MAKE_PARTS = [ "tutorials" ]
       
    45 HB_NOMAKE_PARTS = [ "tests", "performance", "localization" ]
       
    46 
       
    47 # ============================================================================
       
    48 # Utils
       
    49 # ============================================================================
       
    50 def add_remove_part(part, add):
       
    51     global HB_MAKE_PARTS, HB_NOMAKE_PARTS
       
    52     if add:
       
    53         while part in HB_NOMAKE_PARTS:
       
    54             HB_NOMAKE_PARTS.remove(part)
       
    55         if not part in HB_MAKE_PARTS:
       
    56             HB_MAKE_PARTS.append(part)
       
    57     else:
       
    58         while part in HB_MAKE_PARTS:
       
    59             HB_MAKE_PARTS.remove(part)
       
    60         if not part in HB_NOMAKE_PARTS:
       
    61             HB_NOMAKE_PARTS.append(part)
       
    62 
       
    63 def run_process(command, cwd=None):
       
    64     code = 0
       
    65     output = ""
       
    66     try:
       
    67         if cwd != None:
       
    68             oldcwd = os.getcwd()
       
    69             os.chdir(cwd)
       
    70         if sys.version_info[0] == 2 and sys.version_info[1] < 4:
       
    71             process = popen2.Popen4(command)
       
    72             code = process.wait()
       
    73             output = process.fromchild.read()
       
    74         else:
       
    75             process = subprocess.Popen(command, stderr=subprocess.PIPE, stdout=subprocess.PIPE)
       
    76             (stdout, stderr) = process.communicate()
       
    77             code = process.returncode
       
    78             output = stdout + stderr
       
    79         if cwd != None:
       
    80             os.chdir(oldcwd)
       
    81     except:
       
    82         code = -1
       
    83     return [code, output]
       
    84 
       
    85 # ============================================================================
       
    86 # OptionParser
       
    87 # ============================================================================
       
    88 class OptionParser(optparse.OptionParser):
       
    89     def __init__(self, platform, make, prefix):
       
    90         optparse.OptionParser.__init__(self, formatter=optparse.TitledHelpFormatter())
       
    91         self.add_option("-v", "--verbose", action="store_true", dest="verbose",
       
    92                         help="Print verbose information during the configure.")
       
    93         self.set_defaults(verbose=False)
       
    94 
       
    95         if platform != "symbian":
       
    96             group = optparse.OptionGroup(self, "Installation options")
       
    97             group.add_option("--prefix", dest="prefix", metavar="dir",
       
    98                              help="Install everything relative to <dir>. The default value is '%s'. "
       
    99                                   "NOTE: Use '--prefix .' to configure a local setup. A local "
       
   100                                   "setup will install nothing else than the qmake "
       
   101                                   "feature file." % prefix)
       
   102             self.add_option_group(group)
       
   103         self.set_defaults(prefix=None)
       
   104 
       
   105         group = optparse.OptionGroup(self, "Configure options")
       
   106         group.add_option("--platform", dest="platform", metavar="platform",
       
   107                          help="Specify the platform (symbian/win32/unix). "
       
   108                               "The one detected by qmake is used by default "
       
   109                               "if not specified.")
       
   110         group.add_option("--make-bin", dest="makebin", metavar="path",
       
   111                          help="Specify the make tool (make, nmake, mingw32-make, gmake...). "
       
   112                               "The one detected in PATH is used by default if not specified.")
       
   113         if platform == "win32" and make == "nmake":
       
   114             group.add_option("--msvc", action="store_true", dest="msvc",
       
   115                              help="Generate a MSVC solution.")
       
   116         group.add_option("--release", action="store_const", dest="config", const="release",
       
   117                          help="Build in release mode.")
       
   118         group.add_option("--debug", action="store_const", dest="config", const="debug",
       
   119                          help="Build in debug mode.")
       
   120         group.add_option("--debug_and_release", action="store_const", dest="config", const="debug_and_release",
       
   121                          help="Build in both debug and release modes.")
       
   122         if platform != "symbian":
       
   123             group.add_option("--silent", action="store_true", dest="silent",
       
   124                              help="Suppress verbose compiler output.")
       
   125             group.add_option("--fast", action="store_true", dest="fast",
       
   126                              help="Run qmake in non-recursive mode. Running qmake "
       
   127                                   "in recursive mode (default) is more reliable but "
       
   128                                   "takes relatively long due to deep project hierarchy. "
       
   129                                   "The build tree should be clean ie. no existing "
       
   130                                   "makefiles in subdirs, because those won't be "
       
   131                                   "regenerated if this option is enabled.")
       
   132         group.add_option("--defines", dest="defines", metavar="defines",
       
   133                          help="Define compiler macros for selecting features "
       
   134                               "and debugging purposes eg. --defines HB_FOO_DEBUG,HB_BAR_ENABLED")
       
   135         self.add_option_group(group)
       
   136         self.set_defaults(platform=None)
       
   137         self.set_defaults(makebin=None)
       
   138         self.set_defaults(msvc=None)
       
   139         self.set_defaults(config=None)
       
   140         self.set_defaults(silent=False)
       
   141         self.set_defaults(fast=False)
       
   142         self.set_defaults(defines=None)
       
   143 
       
   144         group = optparse.OptionGroup(self, "qmake options")
       
   145         group.add_option("--qmake-bin", dest="qmakebin", metavar="path",
       
   146                          help="Specify the path to the qmake. The one "
       
   147                               "in PATH is used by default if not specified.")
       
   148         group.add_option("--qmake-spec", dest="qmakespec", metavar="spec",
       
   149                          help="The operating system and compiler you are building on.")
       
   150         group.add_option("--qmake-options", dest="qmakeopt", metavar="options",
       
   151                          help="Additional qmake options "
       
   152                               "eg. --qmake-options \"CONFIG+=foo DEFINES+=BAR\".")
       
   153         self.add_option_group(group)
       
   154         self.set_defaults(qmakebin=None)
       
   155         self.set_defaults(qmakespec=None)
       
   156         self.set_defaults(qmakeopt=None)
       
   157 
       
   158         group = optparse.OptionGroup(self, "Feature options")
       
   159         group.add_option("--make", action="append", dest="make", metavar="part",
       
   160                          help="Do build <part>. Valid parts: tests localization performance")
       
   161         group.add_option("--nomake", action="append", dest="nomake", metavar="part",
       
   162                          help="Do not build <part>. Valid parts: <collection> tutorials tests fute unit localization performance")
       
   163         group.add_option("--no-effects", action="store_false", dest="effects",
       
   164                          help="Do not build effects.")
       
   165         group.add_option("--no-gestures", action="store_false", dest="gestures",
       
   166                          help="Do not build gestures.")
       
   167         group.add_option("--no-text-measurement", action="store_false", dest="textMeasurement",
       
   168                          help="Do not build text measurement support (needed for localization).")
       
   169         group.add_option("--no-inputs", action="store_false", dest="inputs",
       
   170                          help="DEPRECATED: Use --nomake hbinput.")
       
   171         group.add_option("--no-feedback", action="store_false", dest="feedback",
       
   172                          help="DEPRECATED: Use --nomake hbfeedback.")
       
   173         group.add_option("--no-tutorials", action="store_false", dest="tutorials",
       
   174                          help="DEPRECATED: Use --nomake tutorials.")
       
   175         self.add_option_group(group)
       
   176         self.set_defaults(make=None)
       
   177         self.set_defaults(nomake=None)
       
   178         self.set_defaults(effects=True)
       
   179         self.set_defaults(gestures=True)
       
   180         self.set_defaults(textMeasurement=True)
       
   181         self.set_defaults(inputs=None)
       
   182         self.set_defaults(feedback=None)
       
   183         self.set_defaults(tutorials=None)
       
   184 
       
   185         group = optparse.OptionGroup(self, "Qt options")
       
   186         group.add_option("--qt-mobility", action="store_true", dest="qtmobility",
       
   187                          help="Assumes that Qt Mobility is available without performing a compilation test.")
       
   188         group.add_option("--no-qt-mobility", action="store_false", dest="qtmobility",
       
   189                          help="Assumes that Qt Mobility is not available without performing a compilation test.")
       
   190         group.add_option("--qt-animation", action="store_true", dest="qtanimation",
       
   191                          help="DEPRECATED: Qt 4.6 includes the animation framework.")
       
   192         group.add_option("--no-qt-animation", action="store_false", dest="qtanimation",
       
   193                          help="DEPRECATED: Qt 4.6 includes the animation framework.")
       
   194         group.add_option("--qt-gestures", action="store_true", dest="qtgestures",
       
   195                          help="DEPRECATED: Qt 4.6 includes the gestures framework.")
       
   196         group.add_option("--no-qt-gestures", action="store_false", dest="qtgestures",
       
   197                          help="DEPRECATED: Qt 4.6 includes the gestures framework.")
       
   198         if platform == "symbian" or platform == None:
       
   199             group.add_option("--qt-symbian-eventfilter", action="store_false", dest="s60eventfilter",
       
   200                              help="DEPRECATED: Qt 4.6 includes QApplication::symbianEventFilter().")
       
   201             group.add_option("--qt-s60-eventfilter", action="store_true", dest="s60eventfilter",
       
   202                              help="DEPRECATED: Qt 4.6 includes QApplication::symbianEventFilter().")
       
   203         self.add_option_group(group)
       
   204         self.set_defaults(qtmobility=None)
       
   205         self.set_defaults(qtanimation=None)
       
   206         self.set_defaults(qtgestures=None)
       
   207         self.set_defaults(qts60eventfilter=None)
       
   208 
       
   209         group = optparse.OptionGroup(self, "Developer options")
       
   210         group.add_option("--developer", action="store_true", dest="developer",
       
   211                          help="Enables the developer mode ie. builds tests and exports necessary symbols. "
       
   212                               "NOTE: The developer mode implies a local setup by default.")
       
   213         if platform != "symbian":
       
   214             group.add_option("--coverage", action="store_true", dest="coverage",
       
   215                              help="Builds with test coverage measurement support. "
       
   216                                   "This implies the developer mode.")
       
   217         group.add_option("--tests", action="store_true", dest="tests",
       
   218                          help="DEPRECATED: Use --make tests.")
       
   219         group.add_option("--performance", action="store_true", dest="performance",
       
   220                          help="DEPRECATED: Use --make performance.")
       
   221         group.add_option("--localization", action="store_true", dest="localization",
       
   222                          help="DEPRECATED: Use --make localization.")
       
   223         self.add_option_group(group)
       
   224         self.set_defaults(developer=False)
       
   225         self.set_defaults(coverage=False)
       
   226         self.set_defaults(tests=None)
       
   227         self.set_defaults(performance=None)
       
   228         self.set_defaults(localization=None)
       
   229 
       
   230 # ============================================================================
       
   231 # Platform
       
   232 # ============================================================================
       
   233 class Platform:
       
   234     def __init__(self, qmake):
       
   235         self._platform = None
       
   236         self._make = None
       
   237         self._error = None
       
   238         self._qmake = qmake
       
   239         self._spec = None
       
   240 
       
   241     def name(self):
       
   242         if not self._platform:
       
   243             self._platform = self._detect_platform()
       
   244         return self._platform
       
   245 
       
   246     def make(self):
       
   247         if not self._make:
       
   248             self._make = self._detect_make()
       
   249         return self._make
       
   250 
       
   251     def qmake(self):
       
   252         return self._qmake
       
   253 
       
   254     def error(self):
       
   255         return self._error
       
   256 
       
   257     def spec(self):
       
   258         return self._spec
       
   259 
       
   260     def _detect_platform(self):
       
   261         lines = list()
       
   262         lines.append("symbian:message(symbian)\n")
       
   263         lines.append("else:macx:message(macx)\n")
       
   264         lines.append("else:unix:message(unix)\n")
       
   265         lines.append("else:win32:message(win32)\n")
       
   266 
       
   267         try:
       
   268             if not os.path.exists("tmp"):
       
   269                 os.makedirs("tmp")
       
   270             fd, filepath = tempfile.mkstemp(dir="tmp", text=True, suffix=".pro")
       
   271             file = os.fdopen(fd, "w+")
       
   272             file.writelines(lines)
       
   273             file.close()
       
   274         except Exception, e:
       
   275             print(e)
       
   276             self._error = "Unable to write a temporary file. Make sure to configure in a writable directory."
       
   277             return None
       
   278 
       
   279         # do not use .qmake.cache when detecting the platform
       
   280         args = []
       
   281         if os.name == "nt":
       
   282             args += "cmd.exe", "/C"
       
   283         args += [self._qmake, "-nocache", os.path.split(filepath)[1]]
       
   284         if self._spec:
       
   285             args += ["-spec", self._spec]
       
   286         (code, output) = run_process(args, "tmp")
       
   287         shutil.rmtree("tmp", ignore_errors=True)
       
   288         if code != 0:
       
   289             self._error = "Unable to execute %s" % self._qmake
       
   290             if self._qmake == "qmake":
       
   291                 self._error += ". Add qmake to PATH or pass --qmake-bin <path/to/qmake>."
       
   292             return None
       
   293 
       
   294         try:
       
   295             return re.match("Project MESSAGE: (\w+)", output).group(1)
       
   296         except:
       
   297             self._error = "Unable to parse qmake output (%s)" % output.strip()
       
   298             if output.find("QMAKESPEC") != -1:
       
   299                 self._error += ". Set QMAKESPEC environment variable or pass --qmake-spec <spec>."
       
   300         return None
       
   301 
       
   302     def _detect_make(self):
       
   303         if self.name() == "win32" and Platform._test_make("nmake", "/?"):
       
   304             return "nmake"
       
   305         if Platform._test_make("make", "-v"):
       
   306             return "make"
       
   307         if Platform._test_make("gmake", "-v"):
       
   308             return "gmake"
       
   309         if self.name() == "win32" and Platform._test_make("mingw32-make", "-v"):
       
   310             return "mingw32-make"
       
   311         return "(n)make"
       
   312 
       
   313     def _test_make(command, param):
       
   314         try:
       
   315             return run_process([command, param])[0] == 0
       
   316         except:
       
   317             return False
       
   318 
       
   319     _test_make = staticmethod(_test_make)
       
   320 
       
   321 # ============================================================================
       
   322 # ConfigTest
       
   323 # ============================================================================
       
   324 class ConfigTest:
       
   325     def __init__(self, platform):
       
   326         self._make = platform.make()
       
   327         self._qmake = platform.qmake()
       
   328         self._platform = platform.name()
       
   329         self._spec = platform.spec()
       
   330 
       
   331     def setup(self, sourcedir, builddir):
       
   332         self._sourcedir = sourcedir
       
   333         self._builddir = builddir
       
   334 
       
   335     def compile(self, test, patterns=None):
       
   336         code = -1
       
   337         prevdir = os.getcwd()
       
   338         try:
       
   339             sourcedir = os.path.join(self._sourcedir, test)
       
   340             filepath = os.path.join(sourcedir, os.path.basename(sourcedir) + ".pro")
       
   341             builddir = os.path.join(self._builddir, test)
       
   342 
       
   343             if not os.path.exists(builddir):
       
   344                 os.makedirs(builddir)
       
   345             os.chdir(builddir)
       
   346 
       
   347             args = [self._qmake, filepath]
       
   348             if self._spec:
       
   349                 args += ["-spec", self._spec]
       
   350             run_process(args)
       
   351             (code, output) = run_process(self._make)
       
   352             if code == 0 and patterns:
       
   353                 for pattern in patterns:
       
   354                     if re.search(pattern, output) != None:
       
   355                         code = -1
       
   356                         break
       
   357             run_process([self._make, "clean"])
       
   358         except:
       
   359             code = -1
       
   360         os.chdir(prevdir)
       
   361         return code == 0
       
   362 
       
   363 # ============================================================================
       
   364 # ConfigFile
       
   365 # ============================================================================
       
   366 class ConfigFile:
       
   367     def __init__(self):
       
   368         self._lines = list()
       
   369 
       
   370     def set_value(self, key, value):
       
   371         self._lines.append("%s = %s\n" % (key, value))
       
   372 
       
   373     def add_value(self, key, value):
       
   374         self._lines.append("%s += %s\n" % (key, value))
       
   375 
       
   376     def remove_value(self, key, value):
       
   377         self._lines.append("%s -= %s\n" % (key, value))
       
   378 
       
   379     def format_dir(dir):
       
   380         return "$$quote(%s)" % dir.replace("\\", "/")
       
   381     format_dir = staticmethod(format_dir)
       
   382 
       
   383     def quote_dir(dir):
       
   384         return "\\\"\\\\\\\"%s\\\\\\\"\\\"" % ConfigFile.format_dir(dir)
       
   385     quote_dir = staticmethod(quote_dir)
       
   386 
       
   387     def write(self, filename):
       
   388         try:
       
   389             file = open(filename, "w+")
       
   390             file.writelines(self._lines)
       
   391             file.close()
       
   392         except IOError, e:
       
   393             print(e)
       
   394             return False
       
   395         return True
       
   396 
       
   397 # ============================================================================
       
   398 # main()
       
   399 # ============================================================================
       
   400 def main():
       
   401     global HB_MAKE_PARTS, HB_NOMAKE_PARTS
       
   402 
       
   403     qmake = "qmake"
       
   404     cmdline = " ".join(sys.argv[1:])
       
   405     match = re.search("--qmake-bin[=\s](\S+)", cmdline)
       
   406     if match:
       
   407         qmake = match.group(1)
       
   408 
       
   409     # detect platform
       
   410     platform = Platform(qmake)
       
   411     match = re.search("--platform[=\s](\S+)", cmdline)
       
   412     if match:
       
   413         platform._platform = match.group(1)
       
   414 
       
   415     match = re.search("--qmake-spec[=\s](\S+)", cmdline)
       
   416     if match:
       
   417         platform._spec = match.group(1)
       
   418 
       
   419     help = False
       
   420     match = re.search("--help\s*", cmdline)
       
   421     if match or re.search("-h\s*", cmdline):
       
   422         help = True
       
   423 
       
   424     if not help and not platform.name():
       
   425         print("ERROR: %s" % platform.error())
       
   426         return
       
   427 
       
   428     # detect make
       
   429     match = re.search("--make-bin[=\s](\S+)", cmdline)
       
   430     if match:
       
   431         platform._make = match.group(1)
       
   432     if not platform.make():
       
   433         print("ERROR: %s" % platform.error())
       
   434         return
       
   435 
       
   436     currentdir = os.path.abspath(os.getcwd())
       
   437     sourcedir = os.path.abspath(sys.path[0])
       
   438 
       
   439     # default prefixes
       
   440     symbianprefix = None
       
   441     if platform.name() == "symbian":
       
   442         if os.path.isdir("/s60"):
       
   443             symbianprefix = "$${EPOCROOT}epoc32/include/hb"
       
   444         else:
       
   445             symbianprefix = "$${EPOCROOT}epoc32/include/mw/hb"
       
   446     prefixes = { "symbian" : symbianprefix,
       
   447                  "unix"    : "/usr/local/hb",
       
   448                  "win32"   : "C:/hb" }
       
   449 
       
   450     # parse command line options
       
   451     parser = OptionParser(platform.name(), platform.make(), prefixes.get(platform.name(), currentdir))
       
   452     (options, args) = parser.parse_args()
       
   453 
       
   454     # coverage implies developer mode
       
   455     if options.coverage:
       
   456         options.developer = True
       
   457 
       
   458     print("Configuring Hb...")
       
   459     print("INFO: Platform: %s" % platform.name())
       
   460     print("INFO: Make: %s" % platform.make())
       
   461 
       
   462     # warn about deprecated options
       
   463     if options.qtanimation != None:
       
   464         print("WARNING: --qt-animation and --qt-no-animation are DEPRECATED. Qt 4.6 includes the animation framework.")
       
   465     if options.qtgestures != None:
       
   466         print("WARNING: --qt-gestures and --qt-no-gestures are DEPRECATED. Qt 4.6 includes the gestures framework.")
       
   467     if options.qts60eventfilter != None:
       
   468         print("WARNING: --qt-symbian-eventfilter and --qt-s60-eventfilter are DEPRECATED. Qt 4.6 includes QApplication::symbianEventFilter().")
       
   469     if options.inputs != None:
       
   470         print("WARNING: --no-inputs is DEPRECATED. Use --nomake hbinput.")
       
   471         add_remove_part("hbinput", options.inputs)
       
   472     if options.feedback != None:
       
   473         print("WARNING: --no-feedback is DEPRECATED. Use --nomake hbfeedback.")
       
   474         add_remove_part("hbfeedback", options.feedback)
       
   475     if options.tutorials != None:
       
   476         print("WARNING: --no-tutorials is DEPRECATED. Use --nomake tutorials.")
       
   477         add_remove_part("tutorials", options.tutorials)
       
   478     if options.tests != None:
       
   479         print("WARNING: --tests is DEPRECATED. Use --make tests.")
       
   480         add_remove_part("tests", options.tests)
       
   481     if options.performance != None:
       
   482         print("WARNING: --performance is DEPRECATED. Use --make performance.")
       
   483         add_remove_part("performance", options.performance)
       
   484     if options.localization != None:
       
   485         print("WARNING: --localization is DEPRECATED. Use --make localization.")
       
   486         add_remove_part("localization", options.localization)
       
   487 
       
   488     # sort out directories
       
   489     if not options.prefix:
       
   490         # developer mode implies local setup
       
   491         if options.developer:
       
   492             options.prefix = currentdir
       
   493         else:
       
   494             options.prefix = prefixes.get(platform.name(), currentdir)
       
   495     basedir = options.prefix
       
   496     if platform.name() != "symbian":
       
   497         basedir = os.path.abspath(basedir)
       
   498 
       
   499     local = os.path.isdir(basedir) and (basedir == currentdir)
       
   500     if not local:
       
   501         resourcedir = basedir + "/resources"
       
   502     else:
       
   503         resourcedir = sourcedir + "/src/hbcore/resources"
       
   504 
       
   505     # generate local build wrapper headers
       
   506     synchb = "bin/synchb.py"
       
   507     if options.verbose:
       
   508         synchb = "%s -v" % synchb
       
   509         print("INFO: Running %s" % synchb)
       
   510     os.system("python %s/%s -i %s -o %s" % (sourcedir, synchb, sourcedir, currentdir))
       
   511 
       
   512     # write config
       
   513     config = ConfigFile()
       
   514     config.set_value("HB_INSTALL_DIR", ConfigFile.format_dir(basedir))
       
   515     config.set_value("HB_RESOURCES_DIR", ConfigFile.format_dir(resourcedir))
       
   516 
       
   517     # generate a qrc for resources
       
   518     args = [os.path.join(sourcedir, "bin/resourcifier.py")]
       
   519     args += ["-i", "%s" % os.path.join(sys.path[0], "src/hbcore/resources")]
       
   520     # TODO: make it currentdir
       
   521     args += ["-o", "%s" % os.path.join(sourcedir, "src/hbcore/resources/resources.qrc")]
       
   522     args += ["--exclude", "\"*distribution.policy.s60\""]
       
   523     args += ["--exclude", "\"*readme.txt\""]
       
   524     args += ["--exclude", "\"*.pr?\""]
       
   525     args += ["--exclude", "\"*.qrc\""]
       
   526     args += ["--exclude", "\"*~\""]
       
   527     args += ["--exclude", "variant/*"]
       
   528     if options.verbose:
       
   529         print("INFO: Running %s" % " ".join(args))
       
   530     os.system("python %s" % " ".join(args))
       
   531 
       
   532     # compilation tests to detect available features
       
   533     test = ConfigTest(platform)
       
   534     test.setup(sourcedir, currentdir)
       
   535     print("INFO: Detecting available features...")
       
   536     patterns = { "symbian" : ["\\*\\*\\*", "Errors caused tool to abort"],
       
   537                  "unix"    : ["\\*\\*\\*"],
       
   538                  "win32"   : ["\\*\\*\\*"] }
       
   539     if options.qtmobility == None:
       
   540         options.qtmobility = test.compile("config.tests/all/mobility", patterns.get(platform.name(), None))
       
   541         print("INFO:\tQt Mobility:\t\t\t%s" % options.qtmobility)
       
   542     if options.qtmobility:
       
   543         config.add_value("DEFINES", "HB_HAVE_QT_MOBILITY")
       
   544     if platform.name() == "symbian":
       
   545         advanced_tactile_result = test.compile("config.tests/symbian/advancedtactile", patterns.get(platform.name(), None))
       
   546         if advanced_tactile_result:
       
   547             config.add_value("CONFIG", "advanced_tactile_support")
       
   548         print("INFO:\tAdvanced Tactile:\t\t%s" % advanced_tactile_result)
       
   549         #sgimagelite_result = test.compile("config.tests/symbian/sgimagelite", patterns.get(platform.name(), None))
       
   550         #if sgimagelite_result:
       
   551         #    config.add_value("CONFIG", "sgimage")
       
   552         #print("INFO:\tSgImage-Lite:\t\t\t%s" % sgimagelite_result)
       
   553         print("NOTE:\t(For SgImage-Lite support, pass --qmake-options \"CONFIG+=sgimage\")")
       
   554 
       
   555     config.set_value("HB_BIN_DIR", ConfigFile.format_dir(basedir + "/bin"))
       
   556     config.set_value("HB_LIB_DIR", ConfigFile.format_dir(basedir + "/lib"))
       
   557     config.set_value("HB_DOC_DIR", ConfigFile.format_dir(basedir + "/doc"))
       
   558     if not options.developer and platform.name() == "symbian":
       
   559         config.set_value("HB_INCLUDE_DIR", ConfigFile.format_dir(basedir))
       
   560     else:
       
   561         config.set_value("HB_INCLUDE_DIR", ConfigFile.format_dir(basedir + "/include"))
       
   562 
       
   563     if platform.name() == "symbian":
       
   564         plugins_dir = "$${EPOCROOT}resource/qt/plugins/hb"
       
   565     else:
       
   566         plugins_dir = basedir + "/plugins"
       
   567     config.set_value("HB_PLUGINS_DIR", ConfigFile.format_dir(plugins_dir))
       
   568     if platform.name() == "symbian":
       
   569         config.set_value("HB_PLUGINS_EXPORT_DIR", ConfigFile.format_dir("$${EPOCROOT}epoc32/winscw/c/resource/qt/plugins/hb"))
       
   570 
       
   571     if options.gestures:
       
   572         config.add_value("DEFINES", "HB_GESTURE_FW")
       
   573     if options.effects:
       
   574         config.add_value("DEFINES", "HB_EFFECTS")
       
   575     if options.textMeasurement:
       
   576         config.add_value("DEFINES", "HB_TEXT_MEASUREMENT_UTILITY")
       
   577     if options.defines:
       
   578         config.add_value("DEFINES", " ".join(options.defines.split(",")))
       
   579 
       
   580     if options.verbose:
       
   581         print("INFO: Writing hb_install.prf")
       
   582     if not config.write("hb_install.prf"):
       
   583         print("ERROR: Unable to write hb_install_prf.")
       
   584         return
       
   585 
       
   586     config.set_value("HB_BUILD_DIR", ConfigFile.format_dir(currentdir))
       
   587     config.set_value("HB_SOURCE_DIR", ConfigFile.format_dir(sourcedir))
       
   588 
       
   589     if platform.name() == "symbian":
       
   590         if os.path.isdir("/s60"):
       
   591             config.set_value("HB_EXPORT_DIR", "hb/%1/%2")
       
   592             config.set_value("HB_PRIVATE_EXPORT_DIR", "hb/%1/private/%2")
       
   593         else:
       
   594             config.set_value("HB_EXPORT_DIR", "$${EPOCROOT}epoc32/include/mw/hb/%1/%2")
       
   595             config.set_value("HB_PRIVATE_EXPORT_DIR", "$${EPOCROOT}epoc32/include/mw/hb/%1/private/%2")
       
   596 
       
   597     if options.developer:
       
   598         add_remove_part("tests", True)
       
   599         add_remove_part("performance", True)
       
   600         add_remove_part("localization", True)
       
   601 
       
   602     if options.make:
       
   603         for part in options.make:
       
   604             add_remove_part(part, True)
       
   605     if options.nomake:
       
   606         for part in options.nomake:
       
   607             add_remove_part(part, False)
       
   608 
       
   609     for part in HB_MAKE_PARTS:
       
   610         add_remove_part(part, True)
       
   611 
       
   612     for nomake in HB_NOMAKE_PARTS:
       
   613         config.add_value("HB_NOMAKE_PARTS", nomake)
       
   614 
       
   615     if local:
       
   616         config.add_value("CONFIG", "local")
       
   617     if options.silent:
       
   618         config.add_value("CONFIG", "silent")
       
   619     if options.effects:
       
   620         config.add_value("CONFIG", "effects")
       
   621     if options.gestures:
       
   622         config.add_value("CONFIG", "gestures")
       
   623     if options.developer:
       
   624         config.add_value("CONFIG", "developer")
       
   625     if options.coverage:
       
   626         config.add_value("CONFIG", "coverage")
       
   627     if options.config:
       
   628         config.add_value("CONFIG", options.config)
       
   629 
       
   630     # disable debug & warning outputs for non-developer symbian-armv5-release builds
       
   631     if not options.developer and platform.name() == "symbian":
       
   632         config._lines.append("no_output = \\ \n")
       
   633         config._lines.append("\"$${LITERAL_HASH}if defined(ARMV5) && defined(UREL)\" \\ \n")
       
   634         config._lines.append("\"MACRO\tQT_NO_DEBUG_OUTPUT\" \\ \n")
       
   635         config._lines.append("\"MACRO\tQT_NO_WARNING_OUTPUT\" \\ \n")
       
   636         config._lines.append("\"$${LITERAL_HASH}endif\" \n")
       
   637         config._lines.append("MMP_RULES += no_output \n")
       
   638 
       
   639     # TODO: is there any better way to expose functions to the whole source tree?
       
   640     config._lines.append("include(%s)\n" % (os.path.splitdrive(sourcedir)[1] + "/src/functions.prf"))
       
   641 
       
   642     if options.verbose:
       
   643         print("INFO: Writing .qmake.cache")
       
   644     if not config.write(".qmake.cache"):
       
   645         print("ERROR: Unable to write .qmake.cache.")
       
   646         return
       
   647 
       
   648     # run qmake
       
   649     if options.qmakebin:
       
   650         qmake = options.qmakebin
       
   651     profile = os.path.join(sourcedir, "hb.pro")
       
   652     cachefile = os.path.join(currentdir, ".qmake.cache")
       
   653     if options.msvc:
       
   654         qmake = "%s -tp vc" % qmake
       
   655     if not options.fast:
       
   656         qmake = "%s -r" % qmake
       
   657     if options.qmakespec:
       
   658         qmake = "%s -spec %s" % (qmake, options.qmakespec)
       
   659     if options.qmakeopt:
       
   660         qmake = "%s \\\"%s\\\"" % (qmake, options.qmakeopt)
       
   661     if options.verbose:
       
   662         print("INFO: Running %s" % qmake)
       
   663     try:
       
   664         ret = os.system("%s -cache %s %s" % (qmake, cachefile, profile))
       
   665     except KeyboardInterrupt:
       
   666         ret = -1
       
   667     if ret != 0:
       
   668         print("")
       
   669         print("ERROR: Aborted!")
       
   670         print("")
       
   671         return
       
   672 
       
   673     if "tests" not in HB_NOMAKE_PARTS:
       
   674         # run qmake for tests
       
   675         profile = "%s/tsrc/tsrc.pro" % sourcedir
       
   676         if os.path.exists(profile):
       
   677             tsrcdir = os.path.join(currentdir, "tsrc")
       
   678             if not os.path.exists(tsrcdir):
       
   679                 os.makedirs(tsrcdir)
       
   680             os.chdir(tsrcdir)
       
   681             os.system("%s %s" % (qmake, profile))
       
   682             os.chdir(currentdir)
       
   683 
       
   684             # create output dirs
       
   685             outputdir = os.path.join(currentdir, "autotest")
       
   686             if not os.path.exists(outputdir):
       
   687                 os.makedirs(outputdir)
       
   688             outputdir = os.path.join(currentdir, "coverage")
       
   689             if not os.path.exists(outputdir):
       
   690                 os.makedirs(outputdir)
       
   691 
       
   692     # print summary
       
   693     print("")
       
   694     if platform.make() == "nmake" and options.msvc:
       
   695         conf = "MSVC"
       
   696         act = "open 'hb.sln'"
       
   697     elif options.coverage:
       
   698         conf = "test coverage measurement"
       
   699         act = "run '%s coverage'" % platform.make()
       
   700     elif options.developer:
       
   701         conf = "development"
       
   702         act = "run '%s'" % platform.make()
       
   703     else:
       
   704         conf = "building"
       
   705         act = "run '%s'" % platform.make()
       
   706     print("Hb is now configured for %s. Just %s." % (conf, act))
       
   707 
       
   708     if not options.coverage:
       
   709         if platform.name() == "symbian" or local:
       
   710             print("You must run '%s install' to copy the .prf file in place." % platform.make())
       
   711         else:
       
   712             print("Once everything is built, you must run '%s install'." % platform.make())
       
   713         if platform != "symbian":
       
   714             if local:
       
   715                 print("Hb will be used from '%s'." % sourcedir)
       
   716             else:
       
   717                 print("Hb will be installed to '%s'." % basedir)
       
   718     if platform.name() == "win32":
       
   719         path = os.path.join(basedir, "bin")
       
   720         if local:
       
   721             path = os.path.join(currentdir, "bin")
       
   722         print("NOTE: Make sure that '%s' is in PATH." % path)
       
   723         if options.coverage:
       
   724             print("Test code coverage measurement will FAIL if wrong Hb DLLs are found in PATH before '%s'." % path)
       
   725 
       
   726     print("")
       
   727     print("To reconfigure, run '%s clean' and '%s'." % (platform.make(), sys.argv[0]))
       
   728     print("")
       
   729 
       
   730 if __name__ == "__main__":
       
   731     main()