1# Copyright 2002-2006 Vladimir Prus
2# Copyright 2005 Alo Sarv
3# Copyright 2005-2012 Juergen Hunold
4#
5# Distributed under the Boost Software License, Version 1.0. (See
6# accompanying file LICENSE_1_0.txt or copy at
7# http://www.boost.org/LICENSE_1_0.txt)
8
9# Qt5 library support module
10#
11# The module attempts to auto-detect QT installation location from QTDIR
12# environment variable; failing that, installation location can be passed as
13# argument:
14#
15# toolset.using qt5 : /usr/local/Trolltech/Qt-5.0.0 ;
16#
17# The module supports code generation from .ui and .qrc files, as well as
18# running the moc preprocessor on headers. Note that you must list all your
19# moc-able headers in sources.
20#
21# Example:
22#
23#     exe myapp : myapp.cpp myapp.h myapp.ui myapp.qrc
24#                 /qt5//QtGui /qt5//QtNetwork ;
25#
26# It's also possible to run moc on cpp sources:
27#
28#   import cast ;
29#
30#   exe myapp : myapp.cpp [ cast _ moccable-cpp : myapp.cpp ] /qt5//QtGui ;
31#
32# When moccing source file myapp.cpp you need to include "myapp.moc" from
33# myapp.cpp. When moccing .h files, the output of moc will be automatically
34# compiled and linked in, you don't need any includes.
35#
36# This is consistent with Qt guidelines:
37# http://qt-project.org/doc/qt-5.0/moc.html
38
39# The .qrc processing utility supports various command line option (see
40# http://qt-project.org/doc/qt-5.0/rcc.html for a complete list). The
41# module provides default arguments for the "output file" and
42# "initialization function name" options. Other options can be set through
43# the <rccflags> build property. E.g. if you wish the compression settings
44# to be more aggressive than the defaults, you can apply them too all .qrc
45# files like this:
46#
47#   project my-qt-project :
48#               requirements
49#               <rccflags>"-compress 9 -threshold 10"
50#           ;
51#
52# Of course, this property can also be specified on individual targets.
53
54
55import modules ;
56import feature ;
57import errors ;
58import type ;
59import "class" : new ;
60import generators ;
61import project ;
62import toolset : flags ;
63import os ;
64import virtual-target ;
65import scanner ;
66
67# The Qt version used for requirements
68# Valid are <qt>5.0 or <qt>5.1.0
69# Auto-detection via qmake sets '<qt>major.minor.patch'
70feature.feature qt5 : : propagated ;
71
72# Extra flags for rcc
73# $TODO: figure out how to declare this only once
74# feature.feature rccflags : : free ;
75
76project.initialize $(__name__) ;
77project qt5 ;
78
79# Save the project so that we tolerate 'import + using' combo.
80.project = [ project.current ] ;
81
82# Helper utils for easy debug output
83if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
84{
85    .debug-configuration = TRUE ;
86}
87
88local rule debug-message ( message * )
89{
90    if $(.debug-configuration) = TRUE
91    {
92        ECHO notice\: "[qt5-cfg]" $(message) ;
93    }
94}
95
96# Capture qmake output line by line
97local rule read-output ( content )
98{
99    local lines ;
100    local nl = "
101" ;
102    local << = "([^$(nl)]*)[$(nl)](.*)" ;
103    local line+ = [ MATCH "$(<<)" : "$(content)" ] ;
104    while $(line+)
105    {
106        lines += $(line+[1]) ;
107        line+ = [ MATCH "$(<<)" : "$(line+[2])" ] ;
108    }
109    return $(lines) ;
110}
111
112# Capture Qt version from qmake
113local rule check-version ( bin_prefix )
114{
115    full-cmd = $(bin_prefix)"/qmake -v" ;
116    debug-message Running '$(full-cmd)' ;
117    local output = [ SHELL $(full-cmd) ] ;
118    for line in [ read-output $(output) ]
119    {
120        # Parse the output to get all the results.
121        if [ MATCH "QMake" : $(line) ]
122        {
123            # Skip first line of output
124        }
125        else
126        {
127            temp = [ MATCH "([0-9]*)\\.([0-9]*)\\.([0-9]*)" : $(line) ] ;
128        }
129    }
130    return $(temp) ;
131}
132
133# Validate the version string and extract the major/minor part we care about.
134#
135local rule split-version ( version )
136{
137    local major-minor = [ MATCH "^([0-9]+)\.([0-9]+)(.*)$" : $(version) : 1 2 3 ] ;
138    if ! $(major-minor[2]) || $(major-minor[3])
139    {
140        ECHO "Warning: 'using qt' expects a two part (major, minor) version number; got" $(version) instead ;
141
142        # Add a zero to account for the missing digit if necessary.
143        major-minor += 0 ;
144    }
145
146    return $(major-minor[1]) $(major-minor[2]) ;
147}
148
149# Initialize the QT support module.
150# Parameters:
151# - 'prefix'    parameter tells where Qt is installed.
152# - 'version'   optional version of Qt, else autodetected via 'qmake -v'
153# - 'condition' optional requirements
154# - 'namespace' optional support for configure -qtnamespace
155# - 'infix'     optional support for configure -qtlibinfix
156# - 'full_bin'  optional full path to Qt binaries (qmake,moc,uic,rcc)
157# - 'full_inc'  optional full path to Qt top-level include directory
158# - 'full_lib'  optional full path to Qt library directory
159rule init ( prefix : version ? : condition * : namespace ? : infix ? : full_bin ? : full_inc ? : full_lib ? )
160{
161    project.push-current $(.project) ;
162
163    debug-message "==== Configuring Qt ... ====" ;
164    for local v in version prefix condition namespace infix full_bin full_inc full_lib
165    {
166        if $($(v))
167        {
168            debug-message "  user-specified $(v):" '$($(v))' ;
169        }
170    }
171
172    # Needed as default value
173    .prefix = $(prefix) ;
174
175    # pre-build paths to detect reinitializations changes
176    local inc_prefix lib_prefix bin_prefix ;
177    if $(full_inc)
178    {
179        inc_prefix = $(full_inc) ;
180    }
181    else
182    {
183        inc_prefix = $(prefix)/include ;
184    }
185    if $(full_lib)
186    {
187        lib_prefix = $(full_lib) ;
188    }
189    else
190    {
191        lib_prefix = $(prefix)/lib ;
192    }
193    if $(full_bin)
194    {
195        bin_prefix = $(full_bin) ;
196    }
197    else
198    {
199        bin_prefix = $(prefix)/bin ;
200    }
201
202    # Globally needed variables
203    .incprefix = $(inc_prefix) ;
204    .libprefix = $(lib_prefix) ;
205    .binprefix = $(bin_prefix) ;
206
207    if ! $(.initialized)
208    {
209        # Make sure this is initialised only once
210        .initialized = true ;
211
212        # Generates cpp files from header files using "moc" tool
213        generators.register-standard qt5.moc : H : CPP(moc_%) : <allow>qt5 ;
214
215        # The OBJ result type is a fake, 'H' will be really produced. See
216        # comments on the generator class, defined below the 'init' function.
217        generators.register [ new uic-5-generator qt5.uic : UI : OBJ :
218            <allow>qt5  ] ;
219
220        # The OBJ result type is a fake here too.
221        generators.register [ new moc-h-5-generator
222            qt5.moc.inc : MOCCABLE5_CPP : OBJ : <allow>qt5 ] ;
223
224        generators.register [ new moc-inc-5-generator
225            qt5.moc.inc : MOCCABLE5_H : OBJ : <allow>qt5 ] ;
226
227        # Generates .cpp files from .qrc files.
228        generators.register-standard qt5.rcc : QRC : CPP(qrc_%) : <allow>qt5 ;
229
230        # dependency scanner for wrapped files.
231        type.set-scanner QRC : qrc-5-scanner ;
232
233        # Save value of first occurring prefix
234        .PREFIX = $(prefix) ;
235    }
236
237    if $(version)
238    {
239        major-minor = [ split-version $(version) ] ;
240        version = $(major-minor:J=.) ;
241    }
242    else
243    {
244        version = [ check-version $(bin_prefix) ] ;
245        if $(version)
246        {
247            version = $(version:J=.) ;
248        }
249        debug-message Detected version '$(version)' ;
250    }
251
252    local target-requirements = $(condition) ;
253
254    # Add the version, if any, to the target requirements.
255    if $(version)
256    {
257        if ! $(version) in [ feature.values qt5 ]
258        {
259            feature.extend qt5 : $(version) ;
260        }
261        target-requirements += <qt5>$(version:E=default) ;
262    }
263
264    local target-os = [ feature.get-values target-os : $(condition) ] ;
265    if ! $(target-os)
266    {
267        target-os ?= [ feature.defaults target-os ] ;
268        target-os = $(target-os:G=) ;
269        target-requirements += <target-os>$(target-os) ;
270    }
271
272    # Build exact requirements for the tools
273    local tools-requirements = $(target-requirements:J=/) ;
274
275    debug-message "Details of this Qt configuration:" ;
276    debug-message "  prefix:      " '$(prefix:E=<empty>)' ;
277    debug-message "  binary path: " '$(bin_prefix:E=<empty>)' ;
278    debug-message "  include path:" '$(inc_prefix:E=<empty>)' ;
279    debug-message "  library path:" '$(lib_prefix:E=<empty>)' ;
280    debug-message "  target requirements:" '$(target-requirements)' ;
281    debug-message "  tool requirements:  " '$(tools-requirements)' ;
282
283    # setup the paths for the tools
284    toolset.flags qt5.moc .BINPREFIX $(tools-requirements) : $(bin_prefix) ;
285    toolset.flags qt5.rcc .BINPREFIX $(tools-requirements) : $(bin_prefix) ;
286    toolset.flags qt5.uic .BINPREFIX $(tools-requirements) : $(bin_prefix) ;
287
288    # TODO: 2009-02-12: Better support for directories
289    # Most likely needed are separate getters for: include,libraries,binaries and sources.
290    toolset.flags qt5.directory .PREFIX $(tools-requirements) : $(prefix) ;
291
292    # Test for a buildable Qt.
293    if [ glob $(.prefix)/Jamroot ]
294    {
295       .bjam-qt = true
296
297       # this will declare QtCore (and qtmain on <target-os>windows)
298       add-shared-library QtCore ;
299   }
300   else
301   # Setup common pre-built Qt.
302   # Special setup for QtCore on which everything depends
303   {
304       local link = [ feature.get-values link : $(condition) ] ;
305
306       local usage-requirements =
307           <include>$(.incprefix)
308           <library-path>$(.libprefix)
309           <threading>multi
310           <allow>qt5 ;
311
312       if $(link) in shared
313       {
314           usage-requirements += <dll-path>$(.libprefix) ;
315           usage-requirements += <target-os>windows:<dll-path>$(.binprefix) ;
316       }
317
318       local suffix ;
319
320       # debug versions on unix have to be built
321       # separately and therefore have no suffix.
322       .infix_version = "" ;
323       .suffix_debug = "" ;
324
325       # Control flag for auto-configuration of the debug libraries.
326       # This setup requires Qt 'configure -debug-and-release'.
327       # Only available on some platforms.
328       # ToDo: 2009-02-12: Maybe throw this away and
329       # require separate setup with <variant>debug as condition.
330       .have_separate_debug = FALSE ;
331
332       # Setup other platforms
333       if $(target-os) in windows cygwin
334       {
335           .have_separate_debug = TRUE ;
336
337           # On NT, the libs have "d" suffix in debug builds.
338           .suffix_debug = "d" ;
339
340           .infix_version = "5" ;
341
342           # On Windows we must link against the qtmain library
343           lib qtmain
344               : # sources
345               : # requirements
346                  <name>qtmain$(.suffix_debug)
347                  <variant>debug
348                  $(target-requirements)
349               ;
350
351           lib qtmain
352               : # sources
353               : # requirements
354                   <name>qtmain
355                   $(target-requirements)
356               ;
357       }
358       else if $(target-os) = darwin
359       {
360           # On MacOS X, both debug and release libraries are available.
361           .suffix_debug = "_debug" ;
362
363           .have_separate_debug = TRUE ;
364
365           alias qtmain ;
366       }
367       else
368       {
369           alias qtmain : : $(target-requirements) ;
370           .infix_version = "5" ;
371       }
372
373       lib QtCore : qtmain
374           : # requirements
375             <name>Qt$(.infix_version)Core
376             $(target-requirements)
377           : # default-build
378           : # usage-requirements
379             <define>QT_CORE_LIB
380             <define>QT_NO_DEBUG
381             <include>$(.incprefix)/QtCore
382             $(usage-requirements)
383           ;
384
385       if $(.have_separate_debug) = TRUE
386       {
387           debug-message Configure debug libraries with suffix '$(.suffix_debug)' ;
388
389           lib QtCore : $(main)
390               : # requirements
391                 <name>Qt$(.infix_version)Core$(.suffix_debug)
392                 <variant>debug
393                 $(target-requirements)
394               : # default-build
395               : # usage-requirements
396                 <define>QT_CORE_LIB
397                 <include>$(.incprefix)/QtCore
398                 $(usage-requirements)
399               ;
400        }
401    }
402
403    if [ glob $(.incprefix)/QtAngle ]
404    {
405        # Setup support of ANGLE builds.
406        alias QtAngle
407            : # sources
408            : # requirements
409                $(target-requirements)
410            : # default-build
411            : # usage-requirements
412                <define>QT_OPENGL_ES_2
413                <define>QT_OPENGL_ES_2_ANGLE
414                <include>$(.incprefix)/QtAngle
415                $(usage-requirements)
416            ;
417    }
418    else
419    {
420         alias QtAngle
421            : # sources
422            : # requirements
423                $(target-requirements)
424            ;
425    }
426
427    # Initialising the remaining libraries is canonical
428    # parameters 'module' : 'depends-on' : 'usage-define' : 'requirements' : 'include'
429    # 'include' only for non-canonical include paths.
430    add-shared-library QtGui     : QtCore QtAngle : QT_GUI_LIB : $(target-requirements) ;
431    add-shared-library QtWidgets : QtGui  : QT_WIDGETS_LIB : $(target-requirements) ;
432    add-shared-library QtNetwork : QtCore : QT_NETWORK_LIB : $(target-requirements) ;
433    add-shared-library QtSql     : QtCore : QT_SQL_LIB     : $(target-requirements) ;
434    add-shared-library QtXml     : QtCore : QT_XML_LIB     : $(target-requirements) ;
435    add-shared-library QtPrintSupport : QtGui : QT_PRINTSUPPORT_LIB : $(target-requirements) ;
436    add-shared-library QtConcurrent : QtCore : QT_CONCURRENT_LIB : $(target-requirements) ;
437
438    add-shared-library QtPositioning : QtCore : QT_POSITIONING_LIB : $(target-requirements) ;
439
440    add-shared-library QtOpenGL : QtGui : QT_OPENGL_LIB : $(target-requirements) ;
441    add-shared-library QtSvg : QtXml QtOpenGL : QT_SVG_LIB : $(target-requirements) ;
442
443    add-shared-library QtTest : QtCore : : $(target-requirements) ;
444
445    # Qt designer library et. al.
446    add-shared-library QtDesigner : QtGui QtXml : : $(target-requirements) ;
447    add-shared-library QtDesignerComponents : QtGui QtXml : : $(target-requirements) ;
448    add-static-library QtUiTools : QtGui QtXml : $(target-requirements) ;
449
450    # DBus-Support
451    add-shared-library QtDBus : QtXml : : $(target-requirements) ;
452
453    # Script-Engine and Tools
454    add-shared-library QtScript : QtGui QtXml : QT_SCRIPT_LIB : $(target-requirements) ;
455    add-shared-library QtScriptTools : QtScript : QT_SCRIPTTOOLS_LIB : $(target-requirements) ;
456
457    # WebKit
458    add-shared-library QtWebKit        : QtGui : QT_WEBKIT_LIB : $(target-requirements) ;
459    add-shared-library QtWebKitWidgets : QtGui : QT_WEBKITWIDGETS_LIB : $(target-requirements) ;
460
461    # Multimedia engine
462    add-shared-library QtMultimedia : QtGui : QT_MULTIMEDIA_LIB : $(target-requirements) ;
463    add-shared-library QtMultimediaWidgets : QtMultimedia : QT_MULTIMEDIAWIDGETS_LIB : $(target-requirements) ;
464
465    #
466    add-shared-library QtXmlPatterns : QtNetwork : QT_XMLPATTERNS_LIB : $(target-requirements) ;
467
468    # Help-Engine
469    add-shared-library QtHelp    : QtGui QtSql QtXml : : $(target-requirements) ;
470    add-shared-library QtCLucene : QCore QtSql QtXml : : $(target-requirements) ;
471
472    # QtQuick
473    add-shared-library QtQml            : QtCore QtNetwork QtGui : QT_QML_LIB : $(target-requirements) ;
474    add-shared-library QtQuick          : QtQml : QT_QUICK_LIB : $(target-requirements) ;
475    add-shared-library QtQuickParticles : QtQml : : $(target-requirements) ;
476    add-shared-library QtQuickTest      : QtQml : : $(target-requirements) ;
477
478    add-shared-library QtSerialPort : QtCore : QT_SERIALPORT_LIB : $(target-requirements) ;
479
480    # QtLocation (since 5.4)
481    add-shared-library QtLocation : QtQuick QtPositioning : QT_LOCATION_LIB : $(target-requirements) ;
482
483    # Webengine support (since 5.4)
484    add-shared-library QtWebEngine        : QtGui       : QT_WEBENGINE_LIB : $(target-requirements) ;
485    add-shared-library QtWebEngineCore    : QtWebEngine : QT_WEBENGINECORE_LIB : $(target-requirements) ;
486    add-shared-library QtWebEngineWidgets : QtWebEngineCore QtWidgets : QT_WEBENGINEWIDGETS_LIB : $(target-requirements) ;
487
488    add-shared-library QtWebChannel : QtQml     : QT_WEBCHANNEL_LIB : $(target-requirements) ;
489    add-shared-library QtWebSockets : QtNetwork : QT_WEBSOCKETS_LIB : $(target-requirements) ;
490
491    add-shared-library QtWebView    : QtWebEngineCore QtWebChannel : QT_WEBVIEW_LIB : $(target-requirements) ;
492
493    # Qt3d libraries (since 5.6)
494    add-shared-library Qt3DCore   : QtGui                 : QT_3DCORE_LIB   : $(target-requirements) ;
495    add-shared-library Qt3DRender : Qt3DCore QtConcurrent : QT_3DRENDER_LIB : $(target-requirements) ;
496    add-shared-library Qt3DLogic  : Qt3DCore              : QT_3DLOGIC_LIB  : $(target-requirements) ;
497    add-shared-library Qt3DInput  : Qt3DRender            : QT_3DINPUT_LIB  : $(target-requirements) ;
498
499    # QtCharts (since 5.7)
500    add-shared-library QtCharts : QtWidgets : QT_CHARTS_LIB : $(target-requirements) ;
501
502    # 3D data visualization (since 5.7)
503    add-shared-library QtDataVisualization : QtGui : QT_DATAVISUALIZATION_LIB : $(target-requirements) ;
504
505    # In-App purchase API (since 5.7)
506    add-shared-library QtPurchasing : QtCore : QT_PURCHASING_LIB : $(target-requirements) ;
507
508    # Qt Connectivity (since 5.3)
509    add-shared-library QtBluetooth  : QtCore : QT_BLUETOOTH_LIB : $(target-requirements) ;
510    add-shared-library QtNfc        : QtCore : QT_NFC_LIB : $(target-requirements) ;
511
512    # Gamepad (since 5.7)
513    add-shared-library QtGamepad : QtCore : QT_GAMEPAD_LIB : $(target-requirements) ;
514
515    # SCXML state machine (since 5.7)
516    add-shared-library QtScxml : QtCore : QT_SCXML_LIB : $(target-requirements) ;
517
518    # Tech Preview QtQuick
519    # SerialBus (since 5.7)
520    add-shared-library QtSerialBus : QtCore : QT_SERIALBUS_LIB : $(target-requirements) ;
521
522    # Platform dependent libraries
523    # Regular expression support
524    add-shared-library QtV8 : QtCore : : $(target-requirements) ;
525
526    # QML-Engine version1
527    add-shared-library QtDeclarative : QtXml : : $(target-requirements) ;
528
529    debug-message "==== Configured Qt-$(version) ====" ;
530
531    project.pop-current ;
532}
533
534rule initialized ( )
535{
536    return $(.initialized) ;
537}
538
539
540
541# This custom generator is needed because in QT5, UI files are translated only
542# into H files, and no C++ files are created. Further, the H files need not be
543# passed via MOC. The header is used only via inclusion. If we define a standard
544# UI -> H generator, B2 will run MOC on H, and then compile the
545# resulting cpp. It will give a warning, since output from moc will be empty.
546#
547# This generator is declared with a UI -> OBJ signature, so it gets invoked when
548# linking generator tries to convert sources to OBJ, but it produces target of
549# type H. This is non-standard, but allowed. That header won't be mocced.
550#
551class uic-5-generator : generator
552{
553    rule __init__ ( * : * )
554    {
555        generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
556    }
557
558    rule run ( project name ? : property-set : sources * )
559    {
560        if ! $(name)
561        {
562            name = [ $(sources[0]).name ] ;
563            name = $(name:B) ;
564        }
565
566        local a = [ new action $(sources[1]) : qt5.uic : $(property-set) ] ;
567
568        # The 'ui_' prefix is to match qmake's default behavior.
569        local target = [ new file-target ui_$(name) : H : $(project) : $(a) ] ;
570
571        local r = [ virtual-target.register $(target) ] ;
572
573        # Since this generator will return a H target, the linking generator
574        # won't use it at all, and won't set any dependency on it. However, we
575        # need the target to be seen by bjam, so that dependency from sources to
576        # this generated header is detected -- if jam does not know about this
577        # target, it won't do anything.
578        DEPENDS all : [ $(r).actualize ] ;
579
580        return $(r) ;
581    }
582}
583
584
585class moc-h-5-generator : generator
586{
587    rule __init__ ( * : * )
588    {
589        generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
590    }
591
592    rule run ( project name ? : property-set : sources * )
593    {
594        if ! $(sources[2]) && [ $(sources[1]).type ] = MOCCABLE5_CPP
595        {
596            name = [ $(sources[0]).name ] ;
597            name = $(name:B) ;
598
599            local a = [ new action $(sources[1]) : qt5.moc.inc :
600                $(property-set) ] ;
601
602            local target = [ new file-target $(name) : MOC : $(project) : $(a)
603                ] ;
604
605            local r = [ virtual-target.register $(target) ] ;
606
607            # Since this generator will return a H target, the linking generator
608            # won't use it at all, and won't set any dependency on it. However,
609            # we need the target to be seen by bjam, so that dependency from
610            # sources to this generated header is detected -- if jam does not
611            # know about this target, it won't do anything.
612            DEPENDS all : [ $(r).actualize ] ;
613
614            return $(r) ;
615        }
616    }
617}
618
619
620class moc-inc-5-generator : generator
621{
622    rule __init__ ( * : * )
623    {
624        generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ;
625    }
626
627    rule run ( project name ? : property-set : sources * )
628    {
629        if ! $(sources[2]) && [ $(sources[1]).type ] = MOCCABLE5_H
630        {
631            name = [ $(sources[0]).name ] ;
632            name = $(name:B) ;
633
634            local a = [ new action $(sources[1]) : qt5.moc.inc :
635                $(property-set) ] ;
636
637            local target = [ new file-target moc_$(name) : CPP : $(project) :
638                $(a) ] ;
639
640            # Since this generator will return a H target, the linking generator
641            # won't use it at all, and won't set any dependency on it. However,
642            # we need the target to be seen by bjam, so that dependency from
643            # sources to this generated header is detected -- if jam does not
644            # know about this target, it won't do anything.
645            DEPENDS all : [ $(target).actualize ] ;
646
647            return [ virtual-target.register $(target) ] ;
648        }
649    }
650}
651
652
653# Query the installation directory. This is needed in at least two scenarios.
654# First, when re-using sources from the Qt-Tree. Second, to "install" custom Qt
655# plugins to the Qt-Tree.
656#
657rule directory
658{
659    return $(.PREFIX) ;
660}
661
662# Add a shared Qt library.
663rule add-shared-library ( lib-name : depends-on * : usage-defines * : requirements * :  include ? )
664{
665     add-library $(lib-name) : $(.infix_version) : $(depends-on) : $(usage-defines) : $(requirements) : $(include) ;
666}
667
668# Add a static Qt library.
669rule add-static-library ( lib-name : depends-on * : usage-defines * : requirements * : include ? )
670{
671     add-library $(lib-name) : $(.infix_version) : $(depends-on) : $(usage-defines) : $(requirements) : $(include) ;
672}
673
674# Add a Qt library.
675# Static libs are unversioned, whereas shared libs have the major number as suffix.
676# Creates both release and debug versions on platforms where both are enabled by Qt configure.
677# Flags:
678# - lib-name Qt library Name
679# - version  Qt major number used as shared library suffix (QtCore5.so)
680# - depends-on other Qt libraries
681# - usage-defines those are set by qmake, so set them when using this library
682# - requirements additional requirements
683# - include non-canonical include path. The canonical path is $(.incprefix)/$(lib-name).
684rule add-library ( lib-name : version ? : depends-on * : usage-defines * : requirements * : include ? )
685{
686    if $(.bjam-qt)
687    {
688        # Import Qt module
689        # Eveything will be setup there
690        alias $(lib-name)
691           : $(.prefix)//$(lib-name)
692           :
693           :
694           : <allow>qt5 ;
695    }
696    else
697    {
698        local real_include ;
699        real_include ?= $(include) ;
700        real_include ?= $(lib-name) ;
701
702        local real_name = [ MATCH ^Qt(.*) : $(lib-name) ] ;
703
704        lib $(lib-name)
705           : # sources
706             $(depends-on)
707           : # requirements
708             <name>Qt$(version)$(real_name)
709             $(requirements)
710           : # default-build
711           : # usage-requirements
712             <define>$(usage-defines)
713             <include>$(.incprefix)/$(real_include)
714           ;
715
716        if $(.have_separate_debug) = TRUE
717        {
718            lib $(lib-name)
719               : # sources
720                 $(depends-on)
721               : # requirements
722                 <name>Qt$(version)$(real_name)$(.suffix_debug)
723                 $(requirements)
724                 <variant>debug
725               : # default-build
726               : # usage-requirements
727                 <define>$(usage-defines)
728                 <include>$(.incprefix)/$(real_include)
729               ;
730        }
731    }
732
733    # Make library explicit so that a simple <use>qt5 will not bring in everything.
734    # And some components like QtDBus/Phonon may not be available on all platforms.
735    explicit $(lib-name) ;
736}
737
738# Use $(.BINPREFIX[-1]) for the paths as several tools-requirements can match.
739# The exact match is the last one.
740
741# Get <include> and <defines> from current toolset.
742flags qt5.moc INCLUDES <include> ;
743flags qt5.moc DEFINES <define> ;
744
745# need a newline for expansion of DEFINES and INCLUDES in the response file.
746.nl  = "
747" ;
748
749# Processes headers to create Qt MetaObject information. Qt5-moc has its
750# c++-parser, so pass INCLUDES and DEFINES.
751# We use response file with one INCLUDE/DEFINE per line
752#
753actions moc
754{
755    $(.BINPREFIX[-1])/moc $(>) -o $(<) @"@($(<).rsp:E=-D$(DEFINES)$(.nl) -I$(INCLUDES:T)$(.nl))"
756}
757
758# When moccing files for include only, we don't need -f, otherwise the generated
759# code will include the .cpp and we'll get duplicated symbols.
760#
761actions moc.inc
762{
763    $(.BINPREFIX[-1])/moc $(>) -o $(<) @"@($(<).rsp:E=-D$(DEFINES)$(.nl) -I$(INCLUDES:T)$(.nl))"
764}
765
766
767# Get extra options for RCC
768flags qt5.rcc RCC_OPTIONS <rccflags> ;
769
770# Generates source files from resource files.
771#
772actions rcc
773{
774    $(.BINPREFIX[-1])/rcc $(>) -name $(>:B) $(RCC_OPTIONS) -o $(<)
775}
776
777
778# Generates user-interface source from .ui files.
779#
780actions uic
781{
782    $(.BINPREFIX[-1])/uic $(>) -o $(<)
783}
784
785
786# Scanner for .qrc files. Look for the CDATA section of the <file> tag. Ignore
787# the "alias" attribute. See http://doc.trolltech.com/qt/resources.html for
788# detailed documentation of the Qt Resource System.
789#
790class qrc-5-scanner : common-scanner
791{
792    rule pattern ( )
793    {
794        return "<file.*>(.*)</file>" ;
795    }
796}
797
798
799# Wrapped files are "included".
800scanner.register qrc-5-scanner : include ;
801