2
0
mirror of https://github.com/boostorg/build.git synced 2026-02-16 13:22:11 +00:00
Files
build/v2/tools/qt4.jam
Jürgen Hunold 40dcb724bf Fix: correct library names of static Qt on Windows.
Static Qt libraries do not have the "4" suffix.
And it is not necessary to enhance the dll path when using static libraries.

[SVN r78801]
2012-06-03 15:13:05 +00:00

734 lines
23 KiB
Plaintext

# Copyright 2002-2006 Vladimir Prus
# Copyright 2005 Alo Sarv
# Copyright 2005-2009 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 ;
import scanner ;
# 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
# "<qt3support>on" to requirements
#
# Use "<qt3support>on:<define>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 ;
# The Qt version used for requirements
# Valid are <qt>4.4 or <qt>4.5.0
# Auto-detection via qmake sets '<qt>major.minor.patch'
feature.feature qt : : propagated ;
project.initialize $(__name__) ;
project qt ;
# Save the project so that we tolerate 'import + using' combo.
.project = [ project.current ] ;
# Helper utils for easy debug output
if [ MATCH (--debug-configuration) : [ modules.peek : ARGV ] ]
{
.debug-configuration = TRUE ;
}
local rule debug-message ( message * )
{
if $(.debug-configuration) = TRUE
{
ECHO notice: [qt4-cfg] $(message) ;
}
}
# Capture qmake output line by line
local rule read-output ( content )
{
local lines ;
local nl = "
" ;
local << = "([^$(nl)]*)[$(nl)](.*)" ;
local line+ = [ MATCH "$(<<)" : "$(content)" ] ;
while $(line+)
{
lines += $(line+[1]) ;
line+ = [ MATCH "$(<<)" : "$(line+[2])" ] ;
}
return $(lines) ;
}
# Capture Qt version from qmake
local rule check-version ( bin_prefix )
{
full-cmd = $(bin_prefix)"/qmake -v" ;
debug-message Running '$(full-cmd)' ;
local output = [ SHELL $(full-cmd) ] ;
for line in [ read-output $(output) ]
{
# Parse the output to get all the results.
if [ MATCH "QMake" : $(line) ]
{
# Skip first line of output
}
else
{
temp = [ MATCH "([0-9]*)\\.([0-9]*)\\.([0-9]*)" : $(line) ] ;
}
}
return $(temp) ;
}
# Validate the version string and extract the major/minor part we care about.
#
local rule split-version ( version )
{
local major-minor = [ MATCH ^([0-9]+)\.([0-9]+)(.*)$ : $(version) : 1 2 3 ] ;
if ! $(major-minor[2]) || $(major-minor[3])
{
ECHO "Warning: 'using qt' expects a two part (major, minor) version number; got" $(version) instead ;
# Add a zero to account for the missing digit if necessary.
major-minor += 0 ;
}
return $(major-minor[1]) $(major-minor[2]) ;
}
# Initialize the QT support module.
# Parameters:
# - 'prefix' parameter tells where Qt is installed.
# - 'full_bin' optional full path to Qt binaries (qmake,moc,uic,rcc)
# - 'full_inc' optional full path to Qt top-level include directory
# - 'full_lib' optional full path to Qt library directory
# - 'version' optional version of Qt, else autodetected via 'qmake -v'
# - 'condition' optional requirements
rule init ( prefix : full_bin ? : full_inc ? : full_lib ? : version ? : condition * )
{
project.push-current $(.project) ;
debug-message "==== Configuring Qt ... ====" ;
for local v in version cmd-or-prefix includes libraries condition
{
if $($(v))
{
debug-message " user-specified "$(v): '$($(v))' ;
}
}
# Needed as default value
.prefix = $(prefix) ;
# pre-build paths to detect reinitializations changes
local inc_prefix lib_prefix bin_prefix ;
if $(full_inc)
{
inc_prefix = $(full_inc) ;
}
else
{
inc_prefix = $(prefix)/include ;
}
if $(full_lib)
{
lib_prefix = $(full_lib) ;
}
else
{
lib_prefix = $(prefix)/lib ;
}
if $(full_bin)
{
bin_prefix = $(full_bin) ;
}
else
{
bin_prefix = $(prefix)/bin ;
}
# Globally needed variables
.incprefix = $(inc_prefix) ;
.libprefix = $(lib_prefix) ;
.binprefix = $(bin_prefix) ;
if ! $(.initialized)
{
# Make sure this is initialised only once
.initialized = true ;
# Generates cpp files from header files using "moc" tool
generators.register-standard qt4.moc : H : CPP(moc_%) : <allow>qt4 ;
# The OBJ result type is a fake, 'H' will be really produced. See
# comments on the generator class, defined below the 'init' function.
generators.register [ new uic-generator qt4.uic : UI : OBJ :
<allow>qt4 ] ;
# The OBJ result type is a fake here too.
generators.register [ new moc-h-generator
qt4.moc.inc : MOCCABLE_CPP : OBJ : <allow>qt4 ] ;
generators.register [ new moc-inc-generator
qt4.moc.inc : MOCCABLE_H : OBJ : <allow>qt4 ] ;
# Generates .cpp files from .qrc files.
generators.register-standard qt4.rcc : QRC : CPP(qrc_%) ;
# dependency scanner for wrapped files.
type.set-scanner QRC : qrc-scanner ;
# Save value of first occuring prefix
.PREFIX = $(prefix) ;
}
if $(version)
{
major-minor = [ split-version $(version) ] ;
version = $(major-minor:J=.) ;
}
else
{
version = [ check-version $(bin_prefix) ] ;
if $(version)
{
version = $(version:J=.) ;
}
debug-message Detected version '$(version)' ;
}
local target-requirements = $(condition) ;
# Add the version, if any, to the target requirements.
if $(version)
{
if ! $(version) in [ feature.values qt ]
{
feature.extend qt : $(version) ;
}
target-requirements += <qt>$(version:E=default) ;
}
local target-os = [ feature.get-values target-os : $(condition) ] ;
if ! $(target-os)
{
target-os ?= [ feature.defaults target-os ] ;
target-os = $(target-os:G=) ;
target-requirements += <target-os>$(target-os) ;
}
# Build exact requirements for the tools
local tools-requirements = $(target-requirements:J=/) ;
debug-message "Details of this Qt configuration:" ;
debug-message " prefix: " '$(prefix:E=<empty>)' ;
debug-message " binary path: " '$(bin_prefix:E=<empty>)' ;
debug-message " include path:" '$(inc_prefix:E=<empty>)' ;
debug-message " library path:" '$(lib_prefix:E=<empty>)' ;
debug-message " target requirements:" '$(target-requirements)' ;
debug-message " tool requirements: " '$(tools-requirements)' ;
# setup the paths for the tools
toolset.flags qt4.moc .BINPREFIX $(tools-requirements) : $(bin_prefix) ;
toolset.flags qt4.rcc .BINPREFIX $(tools-requirements) : $(bin_prefix) ;
toolset.flags qt4.uic .BINPREFIX $(tools-requirements) : $(bin_prefix) ;
# TODO: 2009-02-12: Better support for directories
# Most likely needed are separate getters for: include,libraries,binaries and sources.
toolset.flags qt4.directory .PREFIX $(tools-requirements) : $(prefix) ;
# Test for a buildable Qt.
if [ glob $(.prefix)/Jamroot ]
{
.bjam-qt = true
# this will declare QtCore (and qtmain on <target-os>windows)
add-shared-library QtCore ;
}
else
# Setup common pre-built Qt.
# Special setup for QtCore on which everything depends
{
local link = [ feature.get-values link : $(condition) ] ;
local usage-requirements =
<include>$(.incprefix)
<library-path>$(.libprefix)
<threading>multi
<allow>qt4 ;
if $(link) in shared
{
usage-requirements += <dll-path>$(.libprefix) ;
}
local suffix ;
# Since Qt-4.2, debug versions on unix have to be built
# separately and therefore have no suffix.
.suffix_version = "" ;
.suffix_debug = "" ;
# Control flag for auto-configuration of the debug libraries.
# This setup requires Qt 'configure -debug-and-release'.
# Only available on some platforms.
# ToDo: 2009-02-12: Maybe throw this away and
# require separate setup with <variant>debug as condition.
.have_separate_debug = FALSE ;
# Setup other platforms
if $(target-os) in windows cygwin
{
.have_separate_debug = TRUE ;
# On NT, the shared libs have "4" suffix, and "d" suffix in debug builds.
if $(link) in shared
{
.suffix_version = "4" ;
}
.suffix_debug = "d" ;
# On Windows we must link against the qtmain library
lib qtmain
: # sources
: # requirements
<name>qtmain$(.suffix_debug)
<variant>debug
$(target-requirements)
;
lib qtmain
: # sources
: # requirements
<name>qtmain
$(target-requirements)
;
}
else if $(target-os) = darwin
{
# On MacOS X, both debug and release libraries are available.
.suffix_debug = "_debug" ;
.have_separate_debug = TRUE ;
alias qtmain ;
}
else
{
alias qtmain : : $(target-requirements) ;
}
lib QtCore : qtmain
: # requirements
<name>QtCore$(.suffix_version)
$(target-requirements)
: # default-build
: # usage-requirements
<define>QT_CORE_LIB
<define>QT_NO_DEBUG
<include>$(.incprefix)/QtCore
$(usage-requirements)
;
if $(.have_separate_debug) = TRUE
{
debug-message Configure debug libraries with suffix '$(.suffix_debug)' ;
lib QtCore : $(main)
: # requirements
<name>QtCore$(.suffix_debug)$(.suffix_version)
<variant>debug
$(target-requirements)
: # default-build
: # usage-requirements
<define>QT_CORE_LIB
<include>$(.incprefix)/QtCore
$(usage-requirements)
;
}
}
# Initialising the remaining libraries is canonical
# parameters 'module' : 'depends-on' : 'usage-define' : 'requirements' : 'include'
# 'include' only for non-canonical include paths.
add-shared-library QtGui : QtCore : QT_GUI_LIB : $(target-requirements) ;
add-shared-library QtNetwork : QtCore : QT_NETWORK_LIB : $(target-requirements) ;
add-shared-library QtSql : QtCore : QT_SQL_LIB : $(target-requirements) ;
add-shared-library QtXml : QtCore : QT_XML_LIB : $(target-requirements) ;
add-shared-library Qt3Support : QtGui QtNetwork QtXml QtSql
: QT_QT3SUPPORT_LIB QT3_SUPPORT
: <qt3support>on $(target-requirements) ;
# Dummy target to enable "<qt3support>off" and
# "<library>/qt//Qt3Support" at the same time. This enables quick
# switching from one to the other for test/porting purposes.
alias Qt3Support : : <qt3support>off $(target-requirements) ;
# OpenGl Support
add-shared-library QtOpenGL : QtGui : QT_OPENGL_LIB : $(target-requirements) ;
# SVG-Support (Qt 4.1)
add-shared-library QtSvg : QtXml QtOpenGL : QT_SVG_LIB : $(target-requirements) ;
# Test-Support (Qt 4.1)
add-shared-library QtTest : QtCore : : $(target-requirements) ;
# Qt designer library
add-shared-library QtDesigner : QtGui QtXml : : $(target-requirements) ;
add-shared-library QtDesignerComponents : QtGui QtXml : : $(target-requirements) ;
# Support for dynamic Widgets (Qt 4.1)
add-static-library QtUiTools : QtGui QtXml : $(target-requirements) ;
# DBus-Support (Qt 4.2)
add-shared-library QtDBus : QtXml : : $(target-requirements) ;
# Script-Engine (Qt 4.3)
add-shared-library QtScript : QtGui QtXml : QT_SCRIPT_LIB : $(target-requirements) ;
# Tools for the Script-Engine (Qt 4.5)
add-shared-library QtScriptTools : QtScript : QT_SCRIPTTOOLS_LIB : $(target-requirements) ;
# WebKit (Qt 4.4)
add-shared-library QtWebKit : QtGui : QT_WEBKIT_LIB : $(target-requirements) ;
# Phonon Multimedia (Qt 4.4)
add-shared-library phonon : QtGui QtXml : QT_PHONON_LIB : $(target-requirements) ;
# Multimedia engine (Qt 4.6)
add-shared-library QtMultimedia : QtGui : QT_MULTIMEDIA_LIB : $(target-requirements) ;
# XmlPatterns-Engine (Qt 4.4)
add-shared-library QtXmlPatterns : QtNetwork : QT_XMLPATTERNS_LIB : $(target-requirements) ;
# Help-Engine (Qt 4.4)
add-shared-library QtHelp : QtGui QtSql QtXml : : $(target-requirements) ;
add-shared-library QtCLucene : QCore QtSql QtXml : : $(target-requirements) ;
# QML-Engine (Qt 4.7)
add-shared-library QtDeclarative : QtGui QtXml : : $(target-requirements) ;
# AssistantClient Support
# Compat library removed in 4.7.0
# Pre-4.4 help system, use QtHelp for new programs
if $(version) < "4.7"
{
add-shared-library QtAssistantClient : QtGui : : $(target-requirements) : QtAssistant ;
}
debug-message "==== Configured Qt-$(version) ====" ;
project.pop-current ;
}
rule initialized ( )
{
return $(.initialized) ;
}
# This custom generator is needed because in QT4, UI files are translated only
# into 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 a standard
# UI -> H generator, Boost.Build will run MOC on H, and then compile the
# resulting cpp. It will give a warning, since output from moc will be empty.
#
# This generator is declared with a UI -> OBJ signature, so it gets 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-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 : $(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 a H target, the linking generator
# won't use it at all, and won't set any dependency on it. However, we
# need the 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 a H target, the linking generator
# won't use it at all, and won't set any dependency on it. However,
# we need the 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 a H target, the linking generator
# won't use it at all, and won't set any dependency on it. However,
# we need the 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) ;
}
# Add a shared Qt library.
rule add-shared-library ( lib-name : depends-on * : usage-defines * : requirements * : include ? )
{
add-library $(lib-name) : $(.suffix_version) : $(depends-on) : $(usage-defines) : $(requirements) : $(include) ;
}
# Add a static Qt library.
rule add-static-library ( lib-name : depends-on * : usage-defines * : requirements * : include ? )
{
add-library $(lib-name) : : $(depends-on) : $(usage-defines) : $(requirements) : $(include) ;
}
# Add a Qt library.
# Static libs are unversioned, whereas shared libs have the major number as suffix.
# Creates both release and debug versions on platforms where both are enabled by Qt configure.
# Flags:
# - lib-name Qt library Name
# - version Qt major number used as shared library suffix (QtCore4.so)
# - depends-on other Qt libraries
# - usage-defines those are set by qmake, so set them when using this library
# - requirements addional requirements
# - include non-canonical include path. The canonical path is $(.incprefix)/$(lib-name).
rule add-library ( lib-name : version ? : depends-on * : usage-defines * : requirements * : include ? )
{
if $(.bjam-qt)
{
# Import Qt module
# Eveything will be setup there
alias $(lib-name)
: $(.prefix)//$(lib-name)
:
:
: <allow>qt4 ;
}
else
{
local real_include ;
real_include ?= $(include) ;
real_include ?= $(lib-name) ;
lib $(lib-name)
: # sources
$(depends-on)
: # requirements
<name>$(lib-name)$(version)
$(requirements)
: # default-build
: # usage-requirements
<define>$(usage-defines)
<include>$(.incprefix)/$(real_include)
;
if $(.have_separate_debug) = TRUE
{
lib $(lib-name)
: # sources
$(depends-on)
: # requirements
<name>$(lib-name)$(.suffix_debug)$(version)
$(requirements)
<variant>debug
: # default-build
: # usage-requirements
<define>$(usage-defines)
<include>$(.incprefix)/$(real_include)
;
}
}
# Make library explicit so that a simple <use>qt4 will not bring in everything.
# And some components like QtDBus/Phonon may not be available on all platforms.
explicit $(lib-name) ;
}
# Use $(.BINPREFIX[-1]) for the paths as several tools-requirements can match.
# The exact match is the last one.
# Get <include> and <defines> from current toolset.
flags qt4.moc INCLUDES <include> ;
flags qt4.moc DEFINES <define> ;
# need a newline for expansion of DEFINES and INCLUDES in the response file.
.nl = "
" ;
# Processes headers to create Qt MetaObject information. Qt4-moc has its
# c++-parser, so pass INCLUDES and DEFINES.
# We use response file with one INCLUDE/DEFINE per line
#
actions moc
{
$(.BINPREFIX[-1])/moc -f $(>) -o $(<) @"@($(<).rsp:E=-D$(DEFINES)$(.nl) -I$(INCLUDES:T)$(.nl))"
}
# 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
{
$(.BINPREFIX[-1])/moc $(>) -o $(<) @"@($(<).rsp:E=-D$(DEFINES)$(.nl) -I$(INCLUDES:T)$(.nl))"
}
# Generates source files from resource files.
#
actions rcc
{
$(.BINPREFIX[-1])/rcc $(>) -name $(>:B) -o $(<)
}
# Generates user-interface source from .ui files.
#
actions uic
{
$(.BINPREFIX[-1])/uic $(>) -o $(<)
}
# Scanner for .qrc files. Look for the CDATA section of the <file> tag. Ignore
# the "alias" attribute. See http://doc.trolltech.com/qt/resources.html for
# detailed documentation of the Qt Resource System.
#
class qrc-scanner : common-scanner
{
rule pattern ( )
{
return "<file.*>(.*)</file>" ;
}
}
# Wrapped files are "included".
scanner.register qrc-scanner : include ;