|
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() |