# Copyright 2002-2006 Vladimir Prus # Copyright 2005 Alo Sarv # Copyright 2005-2006 Juergen Hunold # # Distributed under the Boost Software License, Version 1.0. (See # accompanying file LICENSE_1_0.txt or copy at # http://www.boost.org/LICENSE_1_0.txt) # Qt4 library support module # # The module attempts to auto-detect QT installation location from QTDIR # environment variable; failing that, installation location can be passed as # argument: # # toolset.using qt4 : /usr/local/Trolltech/Qt-4.0.0 ; # # The module supports code generation from .ui and .qrc files, as well as # running the moc preprocessor on headers. Note that you must list all your # moc-able headers in sources. # # Example: # # exe myapp : myapp.cpp myapp.h myapp.ui myapp.qrc # /qt4//QtGui /qt4//QtNetwork ; # # It's also possible to run moc on cpp sources: # # import cast ; # # exe myapp : myapp.cpp [ cast _ moccable-cpp : myapp.cpp ] /qt4//QtGui ; # # When moccing source file myapp.cpp you need to include "myapp.moc" from # myapp.cpp. When moccing .h files, the output of moc will be automatically # compiled and linked in, you don't need any includes. # # This is consistent with Qt guidelines: # http://doc.trolltech.com/4.0/moc.html import modules ; import feature ; import errors ; import type ; import "class" : new ; import generators ; import project ; import toolset : flags ; import os ; import virtual-target ; # Qt3Support control feature # # Qt4 configure defaults to build Qt4 libraries with Qt3Support. # The autodetection is missing, so we default to disable Qt3Support. # This prevents the user from inadvertedly using a deprecated API. # # The Qt3Support library can be activated by adding # "on" to requirements # # Use "on:QT3_SUPPORT_WARNINGS" # to get warnings about deprecated Qt3 support funtions and classes. # Files ported by the "qt3to4" conversion tool contain _tons_ of # warnings, so this define is not set as default. # # Todo: Detect Qt3Support from Qt's configure data. # Or add more auto-configuration (like python). feature.feature qt3support : off on : propagated link-incompatible ; project.initialize $(__name__) ; project qt ; # Save the project so that we tolerate 'import + using' combo. .project = [ project.current ] ; # Initialized the QT support module. The 'prefix' parameter # tells where QT is installed. rule init ( prefix ) { project.push-current $(.project) ; if $(.initialized) { if $(prefix) != $(.prefix) { errors.error "Attempt the reinitialize QT with different installation prefix" ; } } else { .initialized = true ; .prefix = $(prefix) ; # Generates cpp files from header files using "moc" tool generators.register-standard qt4.moc : H : CPP(moc_%) : qt4 ; # The OBJ result type is a fake, 'H' will be really produces. # See comments on the generator calss, defined below # the 'init' function. generators.register [ new uic-h-generator qt4.uic-h : UI : OBJ : qt4 ] ; # The OBJ result type is a fake here too. generators.register [ new moc-h-generator qt4.moc.inc : MOCCABLE_CPP : OBJ : qt4 ] ; generators.register [ new moc-inc-generator qt4.moc.inc : MOCCABLE_H : OBJ : qt4 ] ; # Generates .cpp file from qrc file generators.register-standard qt4.rcc : QRC : CPP(qrc_%) ; # Test for a buildable Qt. if [ glob $(.prefix)/Jamroot ] { # Import all Qt Modules local all-libraries = QtCore QtGui QtNetwork QtXml QtSql QtSvg QtOpenGL Qt3Support QtTest QtAssistantClient QtDesigner QtUiTools ; for local l in $(all-libraries) { alias $(l) : $(.prefix)//$(l) : : : qt4 ; explicit $(l) ; } } else # Use pre-built Qt { local usage-requirements = $(.prefix)/include $(.prefix)/lib $(.prefix)/lib multi qt4 ; local suffix ; if [ os.name ] = NT { # On NT, the libs have "4" suffix, and "d" suffix in debug builds # Also, on NT we must link against qtmain library (for WinMain) suffix_version = "4" ; suffix_debug = "d" ; lib qtmain : : qtmain$(suffix_debug) debug ; lib qtmain : : qtmain release ; main = qtmain ; } else { # On X11, debug versions of libs have "_debug" suffix suffix_version = "" ; suffix_debug = "_debug" ; } lib QtCore : $(main) : QtCore$(suffix_version) release : : # usage-requirements QT_CORE_LIB QT_NO_DEBUG $(.prefix)/include/QtCore $(usage-requirements) ; lib QtCore : $(main) : QtCore$(suffix_debug)$(suffix_version) debug : : # usage-requirements QT_CORE_LIB $(.prefix)/include/QtCore $(usage-requirements) ; lib QtGui : QtCore : QtGui$(suffix_version) release : : # usage-requirements QT_GUI_LIB $(.prefix)/include/QtGui gui ; lib QtGui : QtCore : QtGui$(suffix_debug)$(suffix_version) debug : : # usage-requirements QT_GUI_LIB $(.prefix)/include/QtGui gui ; lib QtNetwork : QtCore : QtNetwork$(suffix_version) release : : # usage-requirements QT_NETWORK_LIB $(.prefix)/include/QtNetwork ; lib QtNetwork : QtCore : QtNetwork$(suffix_debug)$(suffix_version) debug : : # usage-requirements QT_NETWORK_LIB $(.prefix)/include/QtNetwork ; lib QtSql : QtCore : QtSql$(suffix_version) release : : # usage-requirements QT_SQL_LIB $(.prefix)/include/QtSql ; lib QtSql : QtCore : QtSql$(suffix_debug)$(suffix_version) debug : : # usage-requirements QT_SQL_LIB $(.prefix)/include/QtSql ; lib QtXml : QtCore : QtXml$(suffix_version) release : : # usage-requirements QT_XML_LIB $(.prefix)/include/QtXml ; lib QtXml : QtCore : QtXml$(suffix_debug)$(suffix_version) debug : : # usage-requirements QT_XML_LIB $(.prefix)/include/QtXml ; lib Qt3Support : QtGui QtNetwork QtXml QtSql : Qt3Support$(suffix_version) release on : : # usage-requirements QT_QT3SUPPORT_LIB QT3_SUPPORT $(.prefix)/include/Qt3Support ; lib Qt3Support : QtGui QtNetwork QtXml QtSql : Qt3Support$(suffix_debug)$(suffix_version) debug on : : # usage-requirements QT_QT3SUPPORT_LIB QT3_SUPPORT $(.prefix)/include/Qt3Support ; # Dummy target to enable "off" and "/qt//Qt3Support" at the same time. # This enables quick switching from one to the other for test/porting purposes. alias Qt3Support : : off ; # OpenGl Support lib QtOpenGL : QtGui : QtOpenGL$(suffix_version) release : : # usage-requirements QT_OPENGL_LIB $(.prefix)/include/QtOpenGL ; lib QtOpenGL : QtGui : QtOpenGL$(suffix_debug)$(suffix_version) debug : : # usage-requirements QT_OPENGL_LIB $(.prefix)/include/QtOpenGL ; # SVG-Support (Qt 4.1) lib QtSvg : QtXml QtOpenGL : QtSvg$(suffix_version) release : : # usage-requirements QT_SVG_LIB $(.prefix)/include/QtSvg ; lib QtSvg : QtXml QtOpenGL : QtSvg$(suffix_debug)$(suffix_version) debug : : # usage-requirements QT_SVG_LIB $(.prefix)/include/QtSvg ; # Test-Support (Qt 4.1) lib QtTest : QtCore : QtTest$(suffix_version) release : : # usage-requirements $(.prefix)/include/QtTest ; lib QtTest : QtCore : QtTest$(suffix_debug)$(suffix_version) debug : : # usage-requirements $(.prefix)/include/QtTest ; # AssistantClient Support lib QtAssistantClient : QtGui : QtAssistantClient$(suffix_version) release : : # usage-requirements $(.prefix)/include/QtAssistant ; lib QtAssistantClient : QtGui : QtAssistantClient$(suffix_debug)$(suffix_version) debug : : # usage-requirements $(.prefix)/include/QtAssistant ; # Qt designer library lib QtDesigner : QtGui QtXml : QtDesigner$(suffix_version) release : : # usage-requirements $(.prefix)/include/QtDesigner ; lib QtDesigner : QtGui QtXml : QtDesigner$(suffix_debug)$(suffix_version) debug : : # usage-requirements $(.prefix)/include/QtDesigner ; # Support for dynamic Widgets (Qt 4.1) lib QtUiTools : QtGui QtXml : QtUiTools$(suffix_version) release : : # usage-requirements $(.prefix)/include/QtUiTools ; lib QtUiTools : QtGui QtXml : QtUiTools$(suffix_debug)$(suffix_version) debug : : # usage-requirements $(.prefix)/include/QtUiTools ; } } project.pop-current ; } rule initialized ( ) { return $(.initialized) ; } # This custom generator is needed because it QT4, UI files are translated # only in H files, and no C++ files are created. Further, the H files # need not be passed via MOC. The header is used only via inclusion. # If we define standard UI -> H generator, Boost.Build will run # MOC on H, and the compile resulting cpp. It will give a warning, since # output from moc will be empty. # # This generator is declared with UI -> OBJ signature, so it's # invoked when linking generator tries to convert sources to OBJ, # but it produces target of type H. This is non-standard, but allowed. # That header won't be mocced. # class uic-h-generator : generator { rule __init__ ( * : * ) { generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; } rule run ( project name ? : property-set : sources * ) { if ! $(name) { name = [ $(sources[0]).name ] ; name = $(name:B) ; } local a = [ new action $(sources[1]) : qt4.uic-h : $(property-set) ] ; # The 'ui_' prefix is to match qmake's default behavior. local target = [ new file-target ui_$(name) : H : $(project) : $(a) ] ; local r = [ virtual-target.register $(target) ] ; # Since this generator will return H target, the linking generator # won't use it at all, and won't set any dependency on it. # However, we need to target to be seen by bjam, so that dependency # from sources to this generated header is detected -- if jam does # not know about this target, it won't do anything. DEPENDS all : [ $(r).actualize ] ; return $(r) ; } } class moc-h-generator : generator { rule __init__ ( * : * ) { generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; } rule run ( project name ? : property-set : sources * ) { if ! $(sources[2]) && [ $(sources[1]).type ] = MOCCABLE_CPP { name = [ $(sources[0]).name ] ; name = $(name:B) ; local a = [ new action $(sources[1]) : qt4.moc.inc : $(property-set) ] ; local target = [ new file-target $(name) : MOC : $(project) : $(a) ] ; local r = [ virtual-target.register $(target) ] ; # Since this generator will return H target, the linking generator # won't use it at all, and won't set any dependency on it. # However, we need to target to be seen by bjam, so that dependency # from sources to this generated header is detected -- if jam does # not know about this target, it won't do anything. DEPENDS all : [ $(r).actualize ] ; return $(r) ; } } } class moc-inc-generator : generator { rule __init__ ( * : * ) { generator.__init__ $(1) : $(2) : $(3) : $(4) : $(5) : $(6) : $(7) : $(8) : $(9) ; } rule run ( project name ? : property-set : sources * ) { if ! $(sources[2]) && [ $(sources[1]).type ] = MOCCABLE_H { name = [ $(sources[0]).name ] ; name = $(name:B) ; local a = [ new action $(sources[1]) : qt4.moc.inc : $(property-set) ] ; local target = [ new file-target moc_$(name) : CPP : $(project) : $(a) ] ; # Since this generator will return H target, the linking generator # won't use it at all, and won't set any dependency on it. # However, we need to target to be seen by bjam, so that dependency # from sources to this generated header is detected -- if jam does # not know about this target, it won't do anything. DEPENDS all : [ $(target).actualize ] ; return [ virtual-target.register $(target) ] ; } } } # Query the installation directory # This is needed in at least two scenarios # First, when re-using sources from the Qt-Tree. # Second, to "install" custom Qt plugins to the Qt-Tree. rule directory { return $(.prefix) ; } # Get and from current toolset flags qt4.moc INCLUDES ; flags qt4.moc DEFINES ; # Processes headers to create Qt MetaObject information # Qt4-moc has its c++-parser, so pass INCLUDES and DEFINES. actions moc { $(.prefix)/bin/moc -I$(INCLUDES) -D$(DEFINES) -f $(>) -o $(<) } # When moccing files for include only, we don't need -f, # otherwise the generated code will include the .cpp # and we'll get duplicated symbols. actions moc.inc { $(.prefix)/bin/moc -I$(INCLUDES) -D$(DEFINES) $(>) -o $(<) } # Generates source files from resource files actions rcc { $(.prefix)/bin/rcc $(>) -name $(>:B) -o $(<) } # Generates user-interface source from .ui files actions uic-h { $(.prefix)/bin/uic $(>) -o $(<) }