@ -1,4 +1,5 @@
# Copyright 2015 The Meson development team
# Copyright © 2021 Intel Corporation
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -12,34 +13,95 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from mesonbuild . dependencies import find_external_dependency
import os
import shutil
import typing as T
import xml . etree . ElementTree as ET
from . . import mlog
from . import ModuleReturnValue , ExtensionModule
from . . import build
from . . import mesonlib
from . . mesonlib import MesonException , extract_as_list , File , unholder , version_compare
from . . dependencies import Dependency
import xml . etree . ElementTree as ET
from . import ModuleReturnValue , ExtensionModule
from . . interpreterbase import noPosargs , permittedKwargs , FeatureNew , FeatureNewKwargs
from . . import mlog
from . . dependencies import find_external_dependency
from . . interpreter import extract_required_kwarg
from . . interpreter . interpreterobjects import DependencyHolder , ExternalLibraryHolder , IncludeDirsHolder , FeatureOptionHolder , GeneratedListHolder
from . . interpreterbase import ContainerTypeInfo , FeatureDeprecated , KwargInfo , noPosargs , FeatureNew , typed_kwargs
from . . mesonlib import MesonException , File
from . . programs import NonExistingExternalProgram
if T . TYPE_CHECKING :
from . import ModuleState
from . . dependencies . qt import QtPkgConfigDependency , QmakeQtDependency
from . . interpreter import Interpreter
from . . dependencies . qt import QtBaseDependency
from . . environment import Environment
from . . interpreter import kwargs
from . . programs import ExternalProgram
QtDependencyType = T . Union [ QtPkgConfigDependency , QmakeQtDependency ]
from typing_extensions import TypedDict
class ResourceCompilerKwArgs ( TypedDict ) :
""" Keyword arguments for the Resource Compiler method. """
name : T . Optional [ str ]
sources : T . List [ mesonlib . FileOrString ]
extra_args : T . List [ str ]
method : str
class UICompilerKwArgs ( TypedDict ) :
""" Keyword arguments for the Ui Compiler method. """
sources : T . List [ mesonlib . FileOrString ]
extra_args : T . List [ str ]
method : str
class MocCompilerKwArgs ( TypedDict ) :
""" Keyword arguments for the Moc Compiler method. """
sources : T . List [ mesonlib . FileOrString ]
headers : T . List [ mesonlib . FileOrString ]
extra_args : T . List [ str ]
method : str
include_directories : T . List [ IncludeDirsHolder ]
dependencies : T . List [ T . Union [ DependencyHolder , ExternalLibraryHolder ] ]
class PreprocessKwArgs ( TypedDict ) :
sources : T . List [ mesonlib . FileOrString ]
moc_sources : T . List [ mesonlib . FileOrString ]
moc_headers : T . List [ mesonlib . FileOrString ]
qresources : T . List [ mesonlib . FileOrString ]
ui_files : T . List [ mesonlib . FileOrString ]
moc_extra_arguments : T . List [ str ]
rcc_extra_arguments : T . List [ str ]
uic_extra_arguments : T . List [ str ]
include_directories : T . List [ IncludeDirsHolder ]
dependencies : T . List [ T . Union [ DependencyHolder , ExternalLibraryHolder ] ]
method : str
class HasToolKwArgs ( kwargs . ExtractRequired ) :
method : str
class CompileTranslationsKwArgs ( TypedDict ) :
build_by_default : bool
install : bool
install_dir : T . Optional [ str ]
method : str
qresource : T . Optional [ str ]
rcc_extra_arguments : T . List [ str ]
ts_files : T . List [ str ]
class QtBaseModule ( ExtensionModule ) :
tools_detected = False
rcc_supports_depfiles = False
_ tools_detected = False
_ rcc_supports_depfiles = False
def __init__ ( self , interpreter : ' Interpreter ' , qt_version = 5 ) :
def __init__ ( self , interpreter : ' Interpreter ' , qt_version : int = 5 ) :
ExtensionModule . __init__ ( self , interpreter )
self . qt_version = qt_version
self . moc : ' ExternalProgram ' = NonExistingExternalProgram ( ' moc ' )
@ -50,9 +112,12 @@ class QtBaseModule(ExtensionModule):
' has_tools ' : self . has_tools ,
' preprocess ' : self . preprocess ,
' compile_translations ' : self . compile_translations ,
' compile_resources ' : self . compile_resources ,
' compile_ui ' : self . compile_ui ,
' compile_moc ' : self . compile_moc ,
} )
def compilers_detect ( self , state , qt_dep : ' QtBaseDependency ' ) - > None :
def compilers_detect ( self , state : ' ModuleState ' , qt_dep : ' QtDependencyType ' ) - > None :
""" Detect Qt (4 or 5) moc, uic, rcc in the specified bindir or in PATH """
# It is important that this list does not change order as the order of
# the returned ExternalPrograms will change as well
@ -96,18 +161,19 @@ class QtBaseModule(ExtensionModule):
if p . found ( ) :
setattr ( self , name , p )
def _detect_tools ( self , state , method , required = True ) :
if self . tools_detected :
def _detect_tools ( self , state : ' ModuleState ' , method : str , required : bool = True ) - > None :
if self . _ tools_detected:
return
self . tools_detected = True
self . _ tools_detected = True
mlog . log ( f ' Detecting Qt { self . qt_version } tools ' )
kwargs = { ' required ' : required , ' modules ' : ' Core ' , ' method ' : method }
qt = find_external_dependency ( f ' qt { self . qt_version } ' , state . environment , kwargs )
# Just pick one to make mypy happy
qt = T . cast ( ' QtPkgConfigDependency ' , find_external_dependency ( f ' qt { self . qt_version } ' , state . environment , kwargs ) )
if qt . found ( ) :
# Get all tools and then make sure that they are the right version
self . compilers_detect ( state , qt )
if version_compare ( qt . version , ' >=5.14.0 ' ) :
self . rcc_supports_depfiles = True
if mesonlib . version_compare ( qt . version , ' >=5.14.0 ' ) :
self . _ rcc_supports_depfiles = True
else :
mlog . warning ( ' rcc dependencies will not work properly until you move to Qt >= 5.14: ' ,
mlog . bold ( ' https://bugreports.qt.io/browse/QTBUG-45460 ' ) , fatal = False )
@ -118,21 +184,24 @@ class QtBaseModule(ExtensionModule):
self . rcc = NonExistingExternalProgram ( name = ' rcc ' + suffix )
self . lrelease = NonExistingExternalProgram ( name = ' lrelease ' + suffix )
def qrc_nodes ( self , state , rcc_file ) :
if type ( rcc_file ) is str :
@staticmethod
def _qrc_nodes ( state : ' ModuleState ' , rcc_file : ' mesonlib.FileOrString ' ) - > T . Tuple [ str , T . List [ str ] ] :
abspath : str
if isinstance ( rcc_file , str ) :
abspath = os . path . join ( state . environment . source_dir , state . subdir , rcc_file )
rcc_dirname = os . path . dirname ( abspath )
elif type ( rcc_file ) is Fil e :
els e :
abspath = rcc_file . absolute_path ( state . environment . source_dir , state . environment . build_dir )
rcc_dirname = os . path . dirname ( abspath )
# FIXME: what error are we actually tring to check here?
try :
tree = ET . parse ( abspath )
root = tree . getroot ( )
result = [ ]
result : T . List [ str ] = [ ]
for child in root [ 0 ] :
if child . tag != ' file ' :
mlog . warning ( " malformed rcc file: " , os . path . join ( state . subdir , rcc_file ) )
mlog . warning ( " malformed rcc file: " , os . path . join ( state . subdir , str ( rcc_file ) ) )
break
else :
result . append ( child . text )
@ -141,9 +210,9 @@ class QtBaseModule(ExtensionModule):
except Exception :
raise MesonException ( f ' Unable to parse resource file { abspath } ' )
def parse_qrc_deps ( self , state , rcc_file ) :
rcc_dirname , nodes = self . qrc_nodes ( state , rcc_file )
result = [ ]
def _ parse_qrc_deps( self , state : ' ModuleState ' , rcc_file : ' mesonlib.FileOrString ' ) - > T . List [ File ] :
rcc_dirname , nodes = self . _ qrc_nodes( state , rcc_file )
result : T . List [ File ] = [ ]
for resource_path in nodes :
# We need to guess if the pointed resource is:
# a) in build directory -> implies a generated file
@ -170,11 +239,18 @@ class QtBaseModule(ExtensionModule):
result . append ( File ( is_built = False , subdir = state . subdir , fname = path_from_rcc ) )
return result
@noPosargs
@permittedKwargs ( { ' method ' , ' required ' } )
@FeatureNew ( ' qt.has_tools ' , ' 0.54.0 ' )
def has_tools ( self , state , args , kwargs ) :
@noPosargs
@typed_kwargs (
' qt.has_tools ' ,
KwargInfo ( ' required ' , ( bool , FeatureOptionHolder ) , default = False ) ,
KwargInfo ( ' method ' , str , default = ' auto ' ) ,
)
def has_tools ( self , state : ' ModuleState ' , args : T . Tuple , kwargs : ' HasToolKwArgs ' ) - > bool :
method = kwargs . get ( ' method ' , ' auto ' )
# We have to cast here because TypedDicts are invariant, even though
# ExtractRequiredKwArgs is a subset of HasToolKwArgs, type checkers
# will insist this is wrong
disabled , required , feature = extract_required_kwarg ( kwargs , state . subproject , default = False )
if disabled :
mlog . log ( ' qt.has_tools skipped: feature ' , mlog . bold ( feature ) , ' disabled ' )
@ -187,117 +263,227 @@ class QtBaseModule(ExtensionModule):
return False
return True
@FeatureNewKwargs ( ' qt.preprocess ' , ' 0.49.0 ' , [ ' uic_extra_arguments ' ] )
@FeatureNewKwargs ( ' qt.preprocess ' , ' 0.44.0 ' , [ ' moc_extra_arguments ' ] )
@FeatureNewKwargs ( ' qt.preprocess ' , ' 0.49.0 ' , [ ' rcc_extra_arguments ' ] )
@permittedKwargs ( { ' moc_headers ' , ' moc_sources ' , ' uic_extra_arguments ' , ' moc_extra_arguments ' , ' rcc_extra_arguments ' , ' include_directories ' , ' dependencies ' , ' ui_files ' , ' qresources ' , ' method ' } )
def preprocess ( self , state , args , kwargs ) :
rcc_files , ui_files , moc_headers , moc_sources , uic_extra_arguments , moc_extra_arguments , rcc_extra_arguments , sources , include_directories , dependencies \
= [ extract_as_list ( kwargs , c , pop = True ) for c in [ ' qresources ' , ' ui_files ' , ' moc_headers ' , ' moc_sources ' , ' uic_extra_arguments ' , ' moc_extra_arguments ' , ' rcc_extra_arguments ' , ' sources ' , ' include_directories ' , ' dependencies ' ] ]
sources + = args [ 1 : ]
method = kwargs . get ( ' method ' , ' auto ' )
self . _detect_tools ( state , method )
err_msg = " {0} sources specified and couldn ' t find {1} , " \
" please check your qt {2} installation "
if ( moc_headers or moc_sources ) and not self . moc . found ( ) :
raise MesonException ( err_msg . format ( ' MOC ' , f ' moc-qt { self . qt_version } ' , self . qt_version ) )
if rcc_files :
if not self . rcc . found ( ) :
raise MesonException ( err_msg . format ( ' RCC ' , f ' rcc-qt { self . qt_version } ' , self . qt_version ) )
@FeatureNew ( ' qt.compile_resources ' , ' 0.59.0 ' )
@noPosargs
@typed_kwargs (
' qt.compile_resources ' ,
KwargInfo ( ' name ' , str ) ,
KwargInfo ( ' sources ' , ContainerTypeInfo ( list , ( File , str ) , allow_empty = False ) , listify = True , required = True ) ,
KwargInfo ( ' extra_args ' , ContainerTypeInfo ( list , str ) , listify = True , default = [ ] ) ,
KwargInfo ( ' method ' , str , default = ' auto ' )
)
def compile_resources ( self , state : ' ModuleState ' , args : T . Tuple , kwargs : ' ResourceCompilerKwArgs ' ) - > ModuleReturnValue :
""" Compile Qt resources files.
Uses CustomTargets to generate . cpp files from . qrc files .
"""
self . _detect_tools ( state , kwargs [ ' method ' ] )
if not self . rcc . found ( ) :
err_msg = ( " {0} sources specified and couldn ' t find {1} , "
" please check your qt {2} installation " )
raise MesonException ( err_msg . format ( ' RCC ' , f ' rcc-qt { self . qt_version } ' , self . qt_version ) )
# List of generated CustomTargets
targets : T . List [ build . CustomTarget ] = [ ]
# depfile arguments
DEPFILE_ARGS : T . List [ str ] = [ ' --depfile ' , ' @DEPFILE@ ' ] if self . _rcc_supports_depfiles else [ ]
name = kwargs [ ' name ' ]
sources = kwargs [ ' sources ' ]
extra_args = kwargs [ ' extra_args ' ]
# If a name was set generate a single .cpp file from all of the qrc
# files, otherwise generate one .cpp file per qrc file.
if name :
qrc_deps : T . List [ File ] = [ ]
for s in sources :
qrc_deps . extend ( self . _parse_qrc_deps ( state , s ) )
rcc_kwargs : T . Dict [ str , T . Any ] = { # TODO: if CustomTarget had typing information we could use that here...
' input ' : sources ,
' output ' : name + ' .cpp ' ,
' command ' : self . rcc . get_command ( ) + [ ' -name ' , name , ' -o ' , ' @OUTPUT@ ' ] + extra_args + [ ' @INPUT@ ' ] + DEPFILE_ARGS ,
' depend_files ' : qrc_deps ,
' depfile ' : f ' { name } .d ' ,
}
res_target = build . CustomTarget ( name , state . subdir , state . subproject , rcc_kwargs )
targets . append ( res_target )
else :
for rcc_file in sources :
qrc_deps = self . _parse_qrc_deps ( state , rcc_file )
if isinstance ( rcc_file , str ) :
basename = os . path . basename ( rcc_file )
else :
basename = os . path . basename ( rcc_file . fname )
name = f ' qt { self . qt_version } - { basename . replace ( " . " , " _ " ) } '
rcc_kwargs = {
' input ' : rcc_file ,
' output ' : f ' { name } .cpp ' ,
' command ' : self . rcc . get_command ( ) + [ ' -name ' , ' @BASENAME@ ' , ' -o ' , ' @OUTPUT@ ' ] + extra_args + [ ' @INPUT@ ' ] + DEPFILE_ARGS ,
' depend_files ' : qrc_deps ,
' depfile ' : f ' { name } .d ' ,
}
res_target = build . CustomTarget ( name , state . subdir , state . subproject , rcc_kwargs )
targets . append ( res_target )
return ModuleReturnValue ( targets , [ targets ] )
@FeatureNew ( ' qt.compile_ui ' , ' 0.59.0 ' )
@noPosargs
@typed_kwargs (
' qt.compile_ui ' ,
KwargInfo ( ' sources ' , ContainerTypeInfo ( list , ( File , str ) , allow_empty = False ) , listify = True , required = True ) ,
KwargInfo ( ' extra_args ' , ContainerTypeInfo ( list , str ) , listify = True , default = [ ] ) ,
KwargInfo ( ' method ' , str , default = ' auto ' )
)
def compile_ui ( self , state : ' ModuleState ' , args : T . Tuple , kwargs : ' ResourceCompilerKwArgs ' ) - > ModuleReturnValue :
""" Compile UI resources into cpp headers. """
self . _detect_tools ( state , kwargs [ ' method ' ] )
if not self . uic . found ( ) :
err_msg = ( " {0} sources specified and couldn ' t find {1} , "
" please check your qt {2} installation " )
raise MesonException ( err_msg . format ( ' UIC ' , f ' uic-qt { self . qt_version } ' , self . qt_version ) )
# TODO: This generator isn't added to the generator list in the Interpreter
gen = build . Generator (
self . uic ,
kwargs [ ' extra_args ' ] + [ ' -o ' , ' @OUTPUT@ ' , ' @INPUT@ ' ] ,
[ ' ui_@BASENAME@.h ' ] ,
name = f ' Qt { self . qt_version } ui ' )
out = GeneratedListHolder ( gen . process_files ( kwargs [ ' sources ' ] , state ) )
return ModuleReturnValue ( out , [ out ] )
@FeatureNew ( ' qt.compile_moc ' , ' 0.59.0 ' )
@noPosargs
@typed_kwargs (
' qt.compile_moc ' ,
KwargInfo ( ' sources ' , ContainerTypeInfo ( list , ( File , str ) ) , listify = True , default = [ ] ) ,
KwargInfo ( ' headers ' , ContainerTypeInfo ( list , ( File , str ) ) , listify = True , default = [ ] ) ,
KwargInfo ( ' extra_args ' , ContainerTypeInfo ( list , str ) , listify = True , default = [ ] ) ,
KwargInfo ( ' method ' , str , default = ' auto ' ) ,
KwargInfo ( ' include_directories ' , ContainerTypeInfo ( list , IncludeDirsHolder ) , listify = True , default = [ ] ) ,
KwargInfo ( ' dependencies ' , ContainerTypeInfo ( list , ( DependencyHolder , ExternalLibraryHolder ) ) , listify = True , default = [ ] ) ,
)
def compile_moc ( self , state : ' ModuleState ' , args : T . Tuple , kwargs : ' MocCompilerKwArgs ' ) - > ModuleReturnValue :
self . _detect_tools ( state , kwargs [ ' method ' ] )
if not self . moc . found ( ) :
err_msg = ( " {0} sources specified and couldn ' t find {1} , "
" please check your qt {2} installation " )
raise MesonException ( err_msg . format ( ' MOC ' , f ' uic-qt { self . qt_version } ' , self . qt_version ) )
if not ( kwargs [ ' headers ' ] or kwargs [ ' sources ' ] ) :
raise build . InvalidArguments ( ' At least one of the " headers " or " sources " keyword arguments must be provied and not empty ' )
inc = state . get_include_args ( include_dirs = kwargs [ ' include_directories ' ] )
compile_args : T . List [ str ] = [ ]
for dep in kwargs [ ' dependencies ' ] :
compile_args . extend ( [ a for a in dep . held_object . get_all_compile_args ( ) if a . startswith ( ( ' -I ' , ' -D ' ) ) ] )
output : T . List [ build . GeneratedList ] = [ ]
arguments = kwargs [ ' extra_args ' ] + inc + compile_args + [ ' @INPUT@ ' , ' -o ' , ' @OUTPUT@ ' ]
if kwargs [ ' headers ' ] :
moc_gen = build . Generator (
self . moc , arguments , [ ' moc_@BASENAME@.cpp ' ] ,
name = f ' Qt { self . qt_version } moc header ' )
output . append ( moc_gen . process_files ( kwargs [ ' headers ' ] , state ) )
if kwargs [ ' sources ' ] :
moc_gen = build . Generator (
self . moc , arguments , [ ' @BASENAME@.moc ' ] ,
name = f ' Qt { self . qt_version } moc source ' )
output . append ( moc_gen . process_files ( kwargs [ ' sources ' ] , state ) )
return ModuleReturnValue ( output , [ output ] )
# We can't use typed_pos_args here, the signature is ambiguious
@typed_kwargs (
' qt.preprocess ' ,
KwargInfo ( ' sources ' , ContainerTypeInfo ( list , ( File , str ) ) , listify = True , default = [ ] , deprecated = ' 0.59.0 ' ) ,
KwargInfo ( ' qresources ' , ContainerTypeInfo ( list , ( File , str ) ) , listify = True , default = [ ] ) ,
KwargInfo ( ' ui_files ' , ContainerTypeInfo ( list , ( File , str ) ) , listify = True , default = [ ] ) ,
KwargInfo ( ' moc_sources ' , ContainerTypeInfo ( list , ( File , str ) ) , listify = True , default = [ ] ) ,
KwargInfo ( ' moc_headers ' , ContainerTypeInfo ( list , ( File , str ) ) , listify = True , default = [ ] ) ,
KwargInfo ( ' moc_extra_arguments ' , ContainerTypeInfo ( list , str ) , listify = True , default = [ ] , since = ' 0.44.0 ' ) ,
KwargInfo ( ' rcc_extra_arguments ' , ContainerTypeInfo ( list , str ) , listify = True , default = [ ] , since = ' 0.49.0 ' ) ,
KwargInfo ( ' uic_extra_arguments ' , ContainerTypeInfo ( list , str ) , listify = True , default = [ ] , since = ' 0.49.0 ' ) ,
KwargInfo ( ' method ' , str , default = ' auto ' ) ,
KwargInfo ( ' include_directories ' , ContainerTypeInfo ( list , IncludeDirsHolder ) , listify = True , default = [ ] ) ,
KwargInfo ( ' dependencies ' , ContainerTypeInfo ( list , ( DependencyHolder , ExternalLibraryHolder ) ) , listify = True , default = [ ] ) ,
)
def preprocess ( self , state : ' ModuleState ' , args : T . List [ T . Union [ str , File ] ] , kwargs : ' PreprocessKwArgs ' ) - > ModuleReturnValue :
_sources = args [ 1 : ]
if _sources :
FeatureDeprecated . single_use ( ' qt.preprocess positional sources ' , ' 0.59 ' , state . subproject )
sources = _sources + kwargs [ ' sources ' ]
for s in sources :
if not isinstance ( s , ( str , File ) ) :
raise build . InvalidArguments ( ' Variadic arguments to qt.preprocess must be Strings or Files ' )
method = kwargs [ ' method ' ]
if kwargs [ ' qresources ' ] :
# custom output name set? -> one output file, multiple otherwise
rcc_kwargs : ' ResourceCompilerKwArgs ' = { ' name ' : ' ' , ' sources ' : kwargs [ ' qresources ' ] , ' extra_args ' : kwargs [ ' rcc_extra_arguments ' ] , ' method ' : method }
if args :
qrc_deps = [ ]
for i in rcc_files :
qrc_deps + = self . parse_qrc_deps ( state , i )
name = args [ 0 ]
rcc_kwargs = { ' input ' : rcc_files ,
' output ' : name + ' .cpp ' ,
' command ' : [ self . rcc , ' -name ' , name , ' -o ' , ' @OUTPUT@ ' , rcc_extra_arguments , ' @INPUT@ ' ] ,
' depend_files ' : qrc_deps }
res_target = build . CustomTarget ( name , state . subdir , state . subproject , rcc_kwargs )
sources . append ( res_target )
else :
for rcc_file in rcc_files :
qrc_deps = self . parse_qrc_deps ( state , rcc_file )
if type ( rcc_file ) is str :
basename = os . path . basename ( rcc_file )
elif type ( rcc_file ) is File :
basename = os . path . basename ( rcc_file . fname )
name = ' qt ' + str ( self . qt_version ) + ' - ' + basename . replace ( ' . ' , ' _ ' )
rcc_kwargs = { ' input ' : rcc_file ,
' output ' : name + ' .cpp ' ,
' command ' : [ self . rcc , ' -name ' , ' @BASENAME@ ' , ' -o ' , ' @OUTPUT@ ' , rcc_extra_arguments , ' @INPUT@ ' ] ,
' depend_files ' : qrc_deps }
if self . rcc_supports_depfiles :
rcc_kwargs [ ' depfile ' ] = name + ' .d '
rcc_kwargs [ ' command ' ] + = [ ' --depfile ' , ' @DEPFILE@ ' ]
res_target = build . CustomTarget ( name , state . subdir , state . subproject , rcc_kwargs )
sources . append ( res_target )
if ui_files :
if not self . uic . found ( ) :
raise MesonException ( err_msg . format ( ' UIC ' , f ' uic-qt { self . qt_version } ' , self . qt_version ) )
arguments = uic_extra_arguments + [ ' -o ' , ' @OUTPUT@ ' , ' @INPUT@ ' ]
ui_kwargs = { ' output ' : ' ui_@BASENAME@.h ' ,
' arguments ' : arguments }
ui_gen = build . Generator ( [ self . uic ] , ui_kwargs )
ui_output = ui_gen . process_files ( f ' Qt { self . qt_version } ui ' , ui_files , state )
sources . append ( ui_output )
inc = state . get_include_args ( include_dirs = include_directories )
compile_args = [ ]
for dep in unholder ( dependencies ) :
if isinstance ( dep , Dependency ) :
for arg in dep . get_all_compile_args ( ) :
if arg . startswith ( ' -I ' ) or arg . startswith ( ' -D ' ) :
compile_args . append ( arg )
else :
raise MesonException ( ' Argument is of an unacceptable type {!r} . \n Must be '
' either an external dependency (returned by find_library() or '
' dependency()) or an internal dependency (returned by '
' declare_dependency()). ' . format ( type ( dep ) . __name__ ) )
if moc_headers :
arguments = moc_extra_arguments + inc + compile_args + [ ' @INPUT@ ' , ' -o ' , ' @OUTPUT@ ' ]
moc_kwargs = { ' output ' : ' moc_@BASENAME@.cpp ' ,
' arguments ' : arguments }
moc_gen = build . Generator ( [ self . moc ] , moc_kwargs )
moc_output = moc_gen . process_files ( f ' Qt { self . qt_version } moc header ' , moc_headers , state )
sources . append ( moc_output )
if moc_sources :
arguments = moc_extra_arguments + inc + compile_args + [ ' @INPUT@ ' , ' -o ' , ' @OUTPUT@ ' ]
moc_kwargs = { ' output ' : ' @BASENAME@.moc ' ,
' arguments ' : arguments }
moc_gen = build . Generator ( [ self . moc ] , moc_kwargs )
moc_output = moc_gen . process_files ( f ' Qt { self . qt_version } moc source ' , moc_sources , state )
sources . append ( moc_output )
return ModuleReturnValue ( sources , sources )
if not isinstance ( args [ 0 ] , str ) :
raise build . InvalidArguments ( ' First argument to qt.preprocess must be a string ' )
rcc_kwargs [ ' name ' ] = args [ 0 ]
sources . extend ( self . compile_resources ( state , tuple ( ) , rcc_kwargs ) . return_value )
if kwargs [ ' ui_files ' ] :
ui_kwargs : ' UICompilerKwArgs ' = { ' sources ' : kwargs [ ' ui_files ' ] , ' extra_args ' : kwargs [ ' uic_extra_arguments ' ] , ' method ' : method }
sources . extend ( self . compile_ui ( state , tuple ( ) , ui_kwargs ) . return_value )
if kwargs [ ' moc_headers ' ] or kwargs [ ' moc_sources ' ] :
moc_kwargs : ' MocCompilerKwArgs ' = {
' extra_args ' : kwargs [ ' moc_extra_arguments ' ] ,
' sources ' : kwargs [ ' moc_sources ' ] ,
' headers ' : kwargs [ ' moc_headers ' ] ,
' include_directories ' : kwargs [ ' include_directories ' ] ,
' dependencies ' : kwargs [ ' dependencies ' ] ,
' method ' : method ,
}
sources . extend ( self . compile_moc ( state , tuple ( ) , moc_kwargs ) . return_value )
return ModuleReturnValue ( sources , [ sources ] )
@FeatureNew ( ' qt.compile_translations ' , ' 0.44.0 ' )
@FeatureNewKwargs ( ' qt.compile_translations ' , ' 0.56.0 ' , [ ' qresource ' ] )
@FeatureNewKwargs ( ' qt.compile_translations ' , ' 0.56.0 ' , [ ' rcc_extra_arguments ' ] )
@permittedKwargs ( { ' ts_files ' , ' qresource ' , ' rcc_extra_arguments ' , ' install ' , ' install_dir ' , ' build_by_default ' , ' method ' } )
def compile_translations ( self , state , args , kwargs ) :
ts_files , install_dir = [ extract_as_list ( kwargs , c , pop = True ) for c in [ ' ts_files ' , ' install_dir ' ] ]
qresource = kwargs . get ( ' qresource ' )
@noPosargs
@typed_kwargs (
' qt.compile_translations ' ,
KwargInfo ( ' build_by_default ' , bool , default = False ) ,
KwargInfo ( ' install ' , bool , default = False ) ,
KwargInfo ( ' install_dir ' , str ) ,
KwargInfo ( ' method ' , str , default = ' auto ' ) ,
KwargInfo ( ' qresource ' , str , since = ' 0.56.0 ' ) ,
KwargInfo ( ' rcc_extra_arguments ' , ContainerTypeInfo ( list , str ) , listify = True , default = [ ] , since = ' 0.56.0 ' ) ,
KwargInfo ( ' ts_files ' , ContainerTypeInfo ( list , ( str , File ) ) , listify = True , default = [ ] ) ,
)
def compile_translations ( self , state : ' ModuleState ' , args : T . Tuple , kwargs : ' CompileTranslationsKwArgs ' ) - > ModuleReturnValue :
ts_files = kwargs [ ' ts_files ' ]
install_dir = kwargs [ ' install_dir ' ]
qresource = kwargs [ ' qresource ' ]
if qresource :
if ts_files :
raise MesonException ( ' qt.compile_translations: Cannot specify both ts_files and qresource ' )
if os . path . dirname ( qresource ) != ' ' :
raise MesonException ( ' qt.compile_translations: qresource file name must not contain a subdirectory. ' )
qresource = File . from_built_file ( state . subdir , qresource )
infile_abs = os . path . join ( state . environment . source_dir , qresource . relative_name ( ) )
outfile_abs = os . path . join ( state . environment . build_dir , qresource . relative_name ( ) )
qresource_file = File . from_built_file ( state . subdir , qresource )
infile_abs = os . path . join ( state . environment . source_dir , qresource_file . relative_name ( ) )
outfile_abs = os . path . join ( state . environment . build_dir , qresource_file . relative_name ( ) )
os . makedirs ( os . path . dirname ( outfile_abs ) , exist_ok = True )
shutil . copy2 ( infile_abs , outfile_abs )
self . interpreter . add_build_def_file ( infile_abs )
rcc_file , nodes = self . qrc_nodes ( state , qresource )
_ , nodes = self . _qrc_nodes ( state , qresource_file )
for c in nodes :
if c . endswith ( ' .qm ' ) :
ts_files . append ( c . rstrip ( ' .qm ' ) + ' .ts ' )
ts_files . append ( c . rstrip ( ' .qm ' ) + ' .ts ' )
else :
raise MesonException ( f ' qt.compile_translations: qresource can only contain qm files, found { c } ' )
results = self . preprocess ( state , [ ] , { ' qresources ' : qresource , ' rcc_extra_arguments ' : kwargs . get ( ' rcc_extra_arguments ' , [ ] ) } )
self . _detect_tools ( state , kwargs . get ( ' method ' , ' auto ' ) )
translations = [ ]
results = self . preprocess ( state , [ ] , { ' qresources ' : qresource , ' rcc_extra_arguments ' : kwargs [ ' rcc_extra_arguments ' ] } )
self . _detect_tools ( state , kwargs [ ' method ' ] )
translations : T . List [ build . CustomTarget ] = [ ]
for ts in ts_files :
if not self . lrelease . found ( ) :
raise MesonException ( ' qt.compile_translations: ' +
@ -320,4 +506,4 @@ class QtBaseModule(ExtensionModule):
if qresource :
return ModuleReturnValue ( results . return_value [ 0 ] , [ results . new_objects , translations ] )
else :
return ModuleReturnValue ( translations , translations )
return ModuleReturnValue ( translations , [ translations ] )