modules/gnome: use typed_kwargs for gtkdoc method

pull/9520/head
Dylan Baker 3 years ago
parent be1d013453
commit 566c2c9a9c
  1. 234
      mesonbuild/modules/gnome.py

@ -29,20 +29,19 @@ from .. import build
from .. import interpreter
from .. import mesonlib
from .. import mlog
from ..build import CustomTarget, CustomTargetIndex, GeneratedList
from ..build import CustomTarget, CustomTargetIndex, GeneratedList, InvalidArguments
from ..dependencies import Dependency, PkgConfigDependency, InternalDependency
from ..interpreter.type_checking import DEPEND_FILES_KW, INSTALL_KW, NoneType
from ..interpreter.type_checking import DEPEND_FILES_KW, INSTALL_KW, NoneType, in_set_validator
from ..interpreterbase import noPosargs, noKwargs, permittedKwargs, FeatureNew, FeatureNewKwargs, FeatureDeprecatedKwargs
from ..interpreterbase import typed_kwargs, KwargInfo, ContainerTypeInfo
from ..interpreterbase.decorators import typed_pos_args
from ..mesonlib import (
MachineChoice, MesonException, OrderedSet, Popen_safe, extract_as_list,
join_args, HoldableObject
MachineChoice, MesonException, OrderedSet, Popen_safe, join_args,
)
from ..programs import ExternalProgram, OverrideProgram
if T.TYPE_CHECKING:
from typing_extensions import TypedDict
from typing_extensions import Literal, TypedDict
from . import ModuleState
from ..compilers import Compiler
@ -101,6 +100,31 @@ if T.TYPE_CHECKING:
sources: T.List[T.Union[FileOrString, build.GeneratedTypes]]
symbol_prefix: T.List[str]
class GtkDoc(TypedDict):
src_dir: T.List[T.Union[str, build.IncludeDirs]]
main_sgml: str
main_xml: str
module_version: str
namespace: str
mode: Literal['xml', 'smgl', 'auto', 'none']
html_args: T.List[str]
scan_args: T.List[str]
scanobjs_args: T.List[str]
fixxref_args: T.List[str]
mkdb_args: T.List[str]
content_files: T.List[T.Union[build.GeneratedTypes, FileOrString]]
ignore_headers: T.List[str]
install_dir: T.List[str]
check: bool
install: bool
gobject_typesfile: T.List[str]
html_assets: T.List[str]
expand_content_files: T.List[str]
c_args: T.List[str]
include_directories: T.List[T.Union[str, build.IncludeDirs]]
dependencies: T.List[T.Union[Dependency, build.SharedLibrary, build.StaticLibrary]]
# Differs from the CustomTarget version in that it straight defaults to True
_BUILD_BY_DEFAULT: KwargInfo[bool] = KwargInfo(
'build_by_default', bool, default=True,
@ -1056,84 +1080,97 @@ class GnomeModule(ExtensionModule):
rv: T.List[T.Union[build.ExecutableSerialisation, build.RunTarget]] = [inscript, pottarget, potarget]
return ModuleReturnValue(None, rv)
@FeatureNewKwargs('gnome.gtkdoc', '0.52.0', ['check'])
@FeatureNewKwargs('gnome.gtkdoc', '0.48.0', ['c_args'])
@FeatureNewKwargs('gnome.gtkdoc', '0.48.0', ['module_version'])
@FeatureNewKwargs('gnome.gtkdoc', '0.37.0', ['namespace', 'mode'])
@permittedKwargs({'main_xml', 'main_sgml', 'src_dir', 'dependencies', 'install',
'install_dir', 'scan_args', 'scanobjs_args', 'gobject_typesfile',
'fixxref_args', 'html_args', 'html_assets', 'content_files',
'mkdb_args', 'ignore_headers', 'include_directories',
'namespace', 'mode', 'expand_content_files', 'module_version',
'c_args', 'check'})
@typed_pos_args('gnome.gtkdoc', str)
def gtkdoc(self, state: 'ModuleState', args: T.Tuple[str], kwargs):
@typed_kwargs(
'gnome.gtkdoc',
KwargInfo('c_args', ContainerTypeInfo(list, str), since='0.48.0', default=[], listify=True),
KwargInfo('check', bool, default=False, since='0.52.0'),
KwargInfo('content_files', ContainerTypeInfo(list, (str, mesonlib.File, build.GeneratedList, build.CustomTarget, build.CustomTargetIndex)), default=[], listify=True),
KwargInfo(
'dependencies',
ContainerTypeInfo(list, (Dependency, build.SharedLibrary, build.StaticLibrary)),
listify=True, default=[]),
KwargInfo('expand_content_files', ContainerTypeInfo(list, str), default=[], listify=True),
KwargInfo('fixxref_args', ContainerTypeInfo(list, str), default=[], listify=True),
KwargInfo('gobject_typesfile', ContainerTypeInfo(list, str), default=[], listify=True),
KwargInfo('html_args', ContainerTypeInfo(list, str), default=[], listify=True),
KwargInfo('html_assets', ContainerTypeInfo(list, str), default=[], listify=True),
KwargInfo('ignore_headers', ContainerTypeInfo(list, str), default=[], listify=True),
KwargInfo(
'include_directories',
ContainerTypeInfo(list, (str, build.IncludeDirs)),
listify=True, default=[]),
KwargInfo('install', bool, default=True),
KwargInfo('install_dir', ContainerTypeInfo(list, str), default=[], listify=True),
KwargInfo('main_sgml', (str, NoneType)),
KwargInfo('main_xml', (str, NoneType)),
KwargInfo('mkdb_args', ContainerTypeInfo(list, str), default=[], listify=True),
KwargInfo(
'mode', str, default='auto', since='0.37.0',
validator=in_set_validator({'xml', 'sgml', 'none', 'auto'})),
KwargInfo('module_version', str, default='', since='0.48.0'),
KwargInfo('namespace', str, default='', since='0.37.0'),
KwargInfo('scan_args', ContainerTypeInfo(list, str), default=[], listify=True),
KwargInfo('scanobjs_args', ContainerTypeInfo(list, str), default=[], listify=True),
KwargInfo('src_dir', ContainerTypeInfo(list, (str, build.IncludeDirs)), listify=True, required=True),
)
def gtkdoc(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'GtkDoc') -> ModuleReturnValue:
modulename = args[0]
if 'src_dir' not in kwargs:
raise MesonException('Keyword argument src_dir missing.')
main_file = kwargs.get('main_sgml', '')
if not isinstance(main_file, str):
raise MesonException('Main sgml keyword argument must be a string.')
main_xml = kwargs.get('main_xml', '')
if not isinstance(main_xml, str):
raise MesonException('Main xml keyword argument must be a string.')
moduleversion = kwargs.get('module_version', '')
if not isinstance(moduleversion, str):
raise MesonException('Module version keyword argument must be a string.')
if main_xml != '':
if main_file != '':
raise MesonException('You can only specify main_xml or main_sgml, not both.')
main_file = kwargs['main_sgml']
main_xml = kwargs['main_xml']
if main_xml is not None:
if main_file is not None:
raise InvalidArguments('gnome.gtkdoc: main_xml and main_xgml are exclusive arguments')
main_file = main_xml
moduleversion = kwargs['module_version']
targetname = modulename + ('-' + moduleversion if moduleversion else '') + '-doc'
command = state.environment.get_build_command()
namespace = kwargs.get('namespace', '')
mode = kwargs.get('mode', 'auto')
VALID_MODES = ('xml', 'sgml', 'none', 'auto')
if mode not in VALID_MODES:
raise MesonException(f'gtkdoc: Mode {mode} is not a valid mode: {VALID_MODES}')
namespace = kwargs['namespace']
def abs_filenames(files: T.Iterable['FileOrString']) -> T.Iterator[str]:
for f in files:
if isinstance(f, mesonlib.File):
yield f.absolute_path(state.environment.get_source_dir(), state.environment.get_build_dir())
else:
yield os.path.join(state.environment.get_source_dir(), state.subdir, f)
src_dirs = mesonlib.extract_as_list(kwargs, 'src_dir')
header_dirs = []
src_dirs = kwargs['src_dir']
header_dirs: T.List[str] = []
for src_dir in src_dirs:
if isinstance(src_dir, HoldableObject):
if not isinstance(src_dir, build.IncludeDirs):
raise MesonException('Invalid keyword argument for src_dir.')
for inc_dir in src_dir.get_incdirs():
header_dirs.append(os.path.join(state.environment.get_source_dir(),
src_dir.get_curdir(), inc_dir))
header_dirs.append(os.path.join(state.environment.get_build_dir(),
src_dir.get_curdir(), inc_dir))
if isinstance(src_dir, build.IncludeDirs):
header_dirs.extend(src_dir.to_string_list(state.environment.get_source_dir(),
state.environment.get_build_dir()))
else:
header_dirs.append(src_dir)
args = ['--internal', 'gtkdoc',
'--sourcedir=' + state.environment.get_source_dir(),
'--builddir=' + state.environment.get_build_dir(),
'--subdir=' + state.subdir,
'--headerdirs=' + '@@'.join(header_dirs),
'--mainfile=' + main_file,
'--modulename=' + modulename,
'--moduleversion=' + moduleversion,
'--mode=' + mode]
t_args = ['--internal', 'gtkdoc',
'--sourcedir=' + state.environment.get_source_dir(),
'--builddir=' + state.environment.get_build_dir(),
'--subdir=' + state.subdir,
'--headerdirs=' + '@@'.join(header_dirs),
'--mainfile=' + main_file,
'--modulename=' + modulename,
'--moduleversion=' + moduleversion,
'--mode=' + kwargs['mode']]
for tool in ['scan', 'scangobj', 'mkdb', 'mkhtml', 'fixxref']:
program_name = 'gtkdoc-' + tool
program = state.find_program(program_name)
path = program.get_path()
args.append(f'--{program_name}={path}')
t_args.append(f'--{program_name}={path}')
if namespace:
args.append('--namespace=' + namespace)
args += self._unpack_args('--htmlargs=', 'html_args', kwargs)
args += self._unpack_args('--scanargs=', 'scan_args', kwargs)
args += self._unpack_args('--scanobjsargs=', 'scanobjs_args', kwargs)
args += self._unpack_args('--gobjects-types-file=', 'gobject_typesfile', kwargs, state)
args += self._unpack_args('--fixxrefargs=', 'fixxref_args', kwargs)
args += self._unpack_args('--mkdbargs=', 'mkdb_args', kwargs)
args += self._unpack_args('--html-assets=', 'html_assets', kwargs, state)
depends = []
t_args.append('--namespace=' + namespace)
t_args.append(f'--htmlargs={"@@".join(kwargs["html_args"])}')
t_args.append(f'--scanargs={"@@".join(kwargs["scan_args"])}')
t_args.append(f'--scanobjsargs={"@@".join(kwargs["scanobjs_args"])}')
t_args.append(f'--gobjects-types-file={"@@".join(abs_filenames(kwargs["gobject_typesfile"]))}')
t_args.append(f'--fixxrefargs={"@@".join(kwargs["fixxref_args"])}')
t_args.append(f'--mkdbargs={"@@".join(kwargs["mkdb_args"])}')
t_args.append(f'--html-assets={"@@".join(abs_filenames(kwargs["html_assets"]))}')
depends: T.List['build.GeneratedTypes'] = []
content_files = []
for s in mesonlib.extract_as_list(kwargs, 'content_files'):
for s in kwargs['content_files']:
if isinstance(s, (build.CustomTarget, build.CustomTargetIndex)):
depends.append(s)
for o in s.get_outputs():
@ -1149,50 +1186,43 @@ class GnomeModule(ExtensionModule):
content_files.append(os.path.join(state.environment.get_source_dir(),
state.subdir,
gen_src))
elif isinstance(s, str):
else:
content_files.append(os.path.join(state.environment.get_source_dir(),
state.subdir,
s))
else:
raise MesonException(
f'Invalid object type: {s.__class__.__name__!r}')
args += ['--content-files=' + '@@'.join(content_files)]
t_args += ['--content-files=' + '@@'.join(content_files)]
args += self._unpack_args('--expand-content-files=', 'expand_content_files', kwargs, state)
args += self._unpack_args('--ignore-headers=', 'ignore_headers', kwargs)
args += self._unpack_args('--installdir=', 'install_dir', kwargs)
args += self._get_build_args(kwargs, state, depends)
t_args.append(f'--expand-content-files={"@@".join(abs_filenames(kwargs["expand_content_files"]))}')
t_args.append(f'--ignore-headers={"@@".join(kwargs["ignore_headers"])}')
t_args.append(f'--installdir={"@@".join(kwargs["install_dir"])}')
t_args += self._get_build_args(kwargs['c_args'], kwargs['include_directories'],
kwargs['dependencies'], state, depends)
custom_kwargs = {'output': modulename + '-decl.txt',
'command': command + args,
'command': command + t_args,
'depends': depends,
'build_always_stale': True,
}
custom_target = build.CustomTarget(targetname, state.subdir, state.subproject, custom_kwargs)
alias_target = build.AliasTarget(targetname, [custom_target], state.subdir, state.subproject)
if kwargs.get('check', False):
if kwargs['check']:
check_cmd = state.find_program('gtkdoc-check')
check_env = ['DOC_MODULE=' + modulename,
'DOC_MAIN_SGML_FILE=' + main_file]
check_args = [targetname + '-check', check_cmd]
check_args = (targetname + '-check', check_cmd)
check_workdir = os.path.join(state.environment.get_build_dir(), state.subdir)
state.test(check_args, env=check_env, workdir=check_workdir, depends=custom_target)
res = [custom_target, alias_target]
if kwargs.get('install', True):
res.append(state.backend.get_executable_serialisation(command + args, tag='doc'))
state.test(check_args, env=check_env, workdir=check_workdir, depends=[custom_target])
res: T.List[T.Union[build.Target, build.ExecutableSerialisation]] = [custom_target, alias_target]
if kwargs['install']:
res.append(state.backend.get_executable_serialisation(command + t_args, tag='doc'))
return ModuleReturnValue(custom_target, res)
def _get_build_args(self, kwargs: T.Dict[str, T.Any], state: 'ModuleState', depends: T.List[build.BuildTarget]) -> T.List[str]:
def _get_build_args(self, c_args: T.List[str], inc_dirs: T.List[T.Union[str, build.IncludeDirs]],
deps: T.List[T.Union[Dependency, build.SharedLibrary, build.StaticLibrary]],
state: 'ModuleState', depends: T.List[build.BuildTarget]) -> T.List[str]:
args: T.List[str] = []
deps = extract_as_list(kwargs, 'dependencies')
cflags: T.List[str] = []
cflags.extend(mesonlib.stringlistify(kwargs.pop('c_args', [])))
cflags = c_args.copy()
deps_cflags, internal_ldflags, external_ldflags, *_ = \
self._get_dependencies_flags(deps, state, depends, include_rpath=True)
inc_dirs = mesonlib.extract_as_list(kwargs, 'include_directories')
for incd in inc_dirs:
if not isinstance(incd, (str, build.IncludeDirs)):
raise MesonException(
'Gir include dirs should be include_directories().')
cflags.extend(deps_cflags)
cflags.extend(state.get_include_args(inc_dirs))
@ -1223,28 +1253,6 @@ class GnomeModule(ExtensionModule):
def gtkdoc_html_dir(self, state: 'ModuleState', args: T.Tuple[str], kwargs: 'TYPE_kwargs') -> str:
return os.path.join('share/gtk-doc/html', args[0])
@staticmethod
def _unpack_args(arg, kwarg_name: str, kwargs: T.Dict[str, T.Any], expend_file_state: T.Optional['ModuleState'] = None) -> T.List[str]:
if kwarg_name not in kwargs:
return []
new_args = mesonlib.extract_as_list(kwargs, kwarg_name)
args = []
for i in new_args:
if expend_file_state is not None:
if isinstance(i, mesonlib.File):
i = i.absolute_path(expend_file_state.environment.get_source_dir(), expend_file_state.environment.get_build_dir())
elif isinstance(i, str):
i = os.path.join(expend_file_state.environment.get_source_dir(), expend_file_state.subdir, i)
elif not isinstance(i, str):
raise MesonException(kwarg_name + ' values must be strings.')
args.append(i)
if args:
return [arg + '@@'.join(args)]
return []
def _get_autocleanup_args(self, kwargs: T.Dict[str, T.Any], glib_version: str) -> T.List[str]:
if not mesonlib.version_compare(glib_version, '>= 2.49.1'):
# Warn if requested, silently disable if not

Loading…
Cancel
Save