aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJussi Pakkanen <jpakkane@gmail.com>2021-10-29 22:45:04 +0300
committerGitHub <noreply@github.com>2021-10-29 22:45:04 +0300
commitaf85738dafc8b371c8b6dbcfba23e1cdb621dc8c (patch)
treeec0996a81a0a237080b9c674284b47426f3f28c9
parent7a12c911bf5478b0a762432985535a6a823b13ab (diff)
parent6849baa47633d2986c049cd68916bc9ce95ba2d0 (diff)
downloadmeson-af85738dafc8b371c8b6dbcfba23e1cdb621dc8c.zip
meson-af85738dafc8b371c8b6dbcfba23e1cdb621dc8c.tar.gz
meson-af85738dafc8b371c8b6dbcfba23e1cdb621dc8c.tar.bz2
Merge pull request #9375 from dcbaker/submit/windows-module-typing
Typing for the Windows module
-rw-r--r--docs/markdown/Windows-module.md18
-rw-r--r--docs/markdown/snippets/windows_custom_targets.md22
-rw-r--r--mesonbuild/build.py2
-rw-r--r--mesonbuild/interpreter/type_checking.py9
-rw-r--r--mesonbuild/modules/windows.py131
-rwxr-xr-xrun_mypy.py1
6 files changed, 125 insertions, 58 deletions
diff --git a/docs/markdown/Windows-module.md b/docs/markdown/Windows-module.md
index a7131a7..06b3eb2 100644
--- a/docs/markdown/Windows-module.md
+++ b/docs/markdown/Windows-module.md
@@ -7,10 +7,22 @@ Windows.
### compile_resources
+```
+ windows.compile_resources(...(string | File | CustomTarget | CustomTargetIndex),
+ args: []string,
+ depend_files: [](string | File),
+ depends: [](BuildTarget | CustomTarget)
+ include_directories: [](IncludeDirectories | string)): []CustomTarget
+```
+
Compiles Windows `rc` files specified in the positional arguments.
-Returns an opaque object that you put in the list of sources for the
-target you want to have the resources in. This method has the
-following keyword argument.
+Returns a list of `CustomTarget` objects that you put in the list of sources for
+the target you want to have the resources in.
+
+*Since 0.61.0* CustomTargetIndexs and CustomTargets with more than out output
+*may be used as positional arguments.
+
+This method has the following keyword arguments:
- `args` lists extra arguments to pass to the resource compiler
- `depend_files` lists resource files that the resource script depends on
diff --git a/docs/markdown/snippets/windows_custom_targets.md b/docs/markdown/snippets/windows_custom_targets.md
new file mode 100644
index 0000000..cbc2f9d
--- /dev/null
+++ b/docs/markdown/snippets/windows_custom_targets.md
@@ -0,0 +1,22 @@
+## Windows.compile_resources CustomTarget
+
+Previously the Windows module only accepted CustomTargets with one output, it
+now accepts them with more than one output, and creates a windows resource
+target for each output. Additionally it now accepts indexes of CustomTargets
+
+```meson
+
+ct = custom_target(
+ 'multiple',
+ output : ['resource', 'another resource'],
+ ...
+)
+
+ct2 = custom_target(
+ 'slice',
+ output : ['resource', 'not a resource'],
+ ...
+)
+
+resources = windows.compile_resources(ct, ct2[0])
+```
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
index e2251ea..02e8da9 100644
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -2700,7 +2700,7 @@ class CustomTargetIndex(HoldableObject):
def get_filename(self) -> str:
return self.output
- def get_id(self):
+ def get_id(self) -> str:
return self.target.get_id()
def get_all_link_deps(self):
diff --git a/mesonbuild/interpreter/type_checking.py b/mesonbuild/interpreter/type_checking.py
index 03091bb..9e443ae 100644
--- a/mesonbuild/interpreter/type_checking.py
+++ b/mesonbuild/interpreter/type_checking.py
@@ -6,7 +6,7 @@
import typing as T
from .. import compilers
-from ..build import EnvironmentVariables, CustomTarget, BuildTarget, CustomTargetIndex, ExtractedObjects, GeneratedList
+from ..build import EnvironmentVariables, CustomTarget, BuildTarget, CustomTargetIndex, ExtractedObjects, GeneratedList, IncludeDirs
from ..coredata import UserFeatureOption
from ..interpreterbase import TYPE_var
from ..interpreterbase.decorators import KwargInfo, ContainerTypeInfo
@@ -278,3 +278,10 @@ CT_INSTALL_DIR_KW: KwargInfo[T.List[T.Union[str, bool]]] = KwargInfo(
)
CT_BUILD_BY_DEFAULT: KwargInfo[T.Optional[bool]] = KwargInfo('build_by_default', (bool, type(None)), since='0.40.0')
+
+INCLUDE_DIRECTORIES: KwargInfo[T.List[T.Union[str, IncludeDirs]]] = KwargInfo(
+ 'include_dirs',
+ ContainerTypeInfo(list, (str, IncludeDirs)),
+ listify=True,
+ default=[],
+)
diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py
index 8f1af2c..4aa7e3a 100644
--- a/mesonbuild/modules/windows.py
+++ b/mesonbuild/modules/windows.py
@@ -15,40 +15,58 @@
import enum
import os
import re
+import typing as T
+
-from .. import mlog
-from .. import mesonlib, build
-from ..mesonlib import MachineChoice, MesonException, extract_as_list
-from . import ModuleReturnValue
from . import ExtensionModule
-from ..interpreterbase import permittedKwargs, FeatureNewKwargs, flatten
+from . import ModuleReturnValue
+from .. import mesonlib, build
+from .. import mlog
+from ..interpreter.type_checking import DEPEND_FILES_KW, DEPENDS_KW, INCLUDE_DIRECTORIES
+from ..interpreterbase.decorators import ContainerTypeInfo, FeatureNew, KwargInfo, typed_kwargs, typed_pos_args
+from ..mesonlib import MachineChoice, MesonException
from ..programs import ExternalProgram
+if T.TYPE_CHECKING:
+ from . import ModuleState
+ from ..compilers import Compiler
+ from ..interpreter import Interpreter
+
+ from typing_extensions import TypedDict
+
+ class CompileResources(TypedDict):
+
+ depend_files: T.List[mesonlib.FileOrString]
+ depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]]
+ include_directories: T.List[T.Union[str, build.IncludeDirs]]
+ args: T.List[str]
+
class ResourceCompilerType(enum.Enum):
windres = 1
rc = 2
wrc = 3
class WindowsModule(ExtensionModule):
- def __init__(self, interpreter):
+ def __init__(self, interpreter: 'Interpreter'):
super().__init__(interpreter)
+ self._rescomp: T.Optional[T.Tuple[ExternalProgram, ResourceCompilerType]] = None
self.methods.update({
'compile_resources': self.compile_resources,
})
- def detect_compiler(self, compilers):
+ def detect_compiler(self, compilers: T.Dict[str, 'Compiler']) -> 'Compiler':
for l in ('c', 'cpp'):
if l in compilers:
return compilers[l]
raise MesonException('Resource compilation requires a C or C++ compiler.')
- def _find_resource_compiler(self, state):
+ def _find_resource_compiler(self, state: 'ModuleState') -> T.Tuple[ExternalProgram, ResourceCompilerType]:
# FIXME: Does not handle `native: true` executables, see
# See https://github.com/mesonbuild/meson/issues/1531
# Take a parameter instead of the hardcoded definition below
for_machine = MachineChoice.HOST
- if hasattr(self, '_rescomp'):
+ if self._rescomp:
return self._rescomp
# Will try cross / native file and then env var
@@ -80,22 +98,26 @@ class WindowsModule(ExtensionModule):
return self._rescomp
- @FeatureNewKwargs('windows.compile_resources', '0.47.0', ['depend_files', 'depends'])
- @permittedKwargs({'args', 'include_directories', 'depend_files', 'depends'})
- def compile_resources(self, state, args, kwargs):
- extra_args = mesonlib.stringlistify(flatten(kwargs.get('args', [])))
- wrc_depend_files = extract_as_list(kwargs, 'depend_files', pop = True)
- wrc_depends = extract_as_list(kwargs, 'depends', pop = True)
+ @typed_pos_args('windows.compile_resources', varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex), min_varargs=1)
+ @typed_kwargs(
+ 'winddows.compile_resoures',
+ DEPEND_FILES_KW.evolve(since='0.47.0'),
+ DEPENDS_KW.evolve(since='0.47.0'),
+ INCLUDE_DIRECTORIES.evolve(name='include_directories'),
+ KwargInfo('args', ContainerTypeInfo(list, str), default=[], listify=True),
+ )
+ def compile_resources(self, state: 'ModuleState',
+ args: T.Tuple[T.List[T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex]]],
+ kwargs: 'CompileResources') -> ModuleReturnValue:
+ extra_args = kwargs['args'].copy()
+ wrc_depend_files = kwargs['depend_files']
+ wrc_depends = kwargs['depends']
for d in wrc_depends:
if isinstance(d, build.CustomTarget):
extra_args += state.get_include_args([
build.IncludeDirs('', [], False, [os.path.join('@BUILD_ROOT@', self.interpreter.backend.get_target_dir(d))])
])
- inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True)
- for incd in inc_dirs:
- if not isinstance(incd, (str, build.IncludeDirs)):
- raise MesonException('Resource include dirs should be include_directories().')
- extra_args += state.get_include_args(inc_dirs)
+ extra_args += state.get_include_args(kwargs['include_directories'])
rescomp, rescomp_type = self._find_resource_compiler(state)
if rescomp_type == ResourceCompilerType.rc:
@@ -119,53 +141,56 @@ class WindowsModule(ExtensionModule):
suffix = 'o'
res_args = extra_args + ['@INPUT@', '-o', '@OUTPUT@']
- res_targets = []
-
- def add_target(src):
- if isinstance(src, list):
- for subsrc in src:
- add_target(subsrc)
- return
-
- if isinstance(src, str):
- name_formatted = src
- name = os.path.join(state.subdir, src)
- elif isinstance(src, mesonlib.File):
- name_formatted = src.fname
- name = src.relative_name()
- elif isinstance(src, build.CustomTarget):
- if len(src.get_outputs()) > 1:
- raise MesonException('windows.compile_resources does not accept custom targets with more than 1 output.')
-
- # Chances are that src.get_filename() is already the name of that
- # target, add a prefix to avoid name clash.
- name_formatted = 'windows_compile_resources_' + src.get_filename()
- name = src.get_id()
- else:
- raise MesonException(f'Unexpected source type {src!r}. windows.compile_resources accepts only strings, files, custom targets, and lists thereof.')
-
+ res_targets: T.List[build.CustomTarget] = []
+
+ def get_names() -> T.Iterable[T.Tuple[str, str, T.Union[str, mesonlib.File, build.CustomTargetIndex]]]:
+ for src in args[0]:
+ if isinstance(src, str):
+ yield os.path.join(state.subdir, src), src, src
+ elif isinstance(src, mesonlib.File):
+ yield src.relative_name(), src.fname, src
+ elif isinstance(src, build.CustomTargetIndex):
+ FeatureNew.single_use('windows.compile_resource CustomTargetIndex in positional arguments', '0.61.0', state.subproject)
+ # This dance avoids a case where two indexs of the same
+ # target are given as separate arguments.
+ yield (f'{src.get_id()}_{src.target.get_outputs().index(src.output)}',
+ f'windows_compile_resources_{src.get_filename()}', src)
+ else:
+ if len(src.get_outputs()) > 1:
+ FeatureNew.single_use('windows.compile_resource CustomTarget with multiple outputs in positional arguments', '0.61.0', state.subproject)
+ for i, out in enumerate(src.get_outputs()):
+ # Chances are that src.get_filename() is already the name of that
+ # target, add a prefix to avoid name clash.
+ yield f'{src.get_id()}_{i}', f'windows_compile_resources_{i}_{out}', src[i]
+
+ for name, name_formatted, src in get_names():
# Path separators are not allowed in target names
name = name.replace('/', '_').replace('\\', '_').replace(':', '_')
name_formatted = name_formatted.replace('/', '_').replace('\\', '_').replace(':', '_')
+ output = f'{name}_@BASENAME@.{suffix}'
+ command: T.List[T.Union[str, ExternalProgram]] = []
+ command.append(rescomp)
+ command.extend(res_args)
res_kwargs = {
- 'output': name + '_@BASENAME@.' + suffix,
+ 'output': output,
'input': [src],
- 'command': [rescomp] + res_args,
'depend_files': wrc_depend_files,
'depends': wrc_depends,
}
# instruct binutils windres to generate a preprocessor depfile
if rescomp_type == ResourceCompilerType.windres:
- res_kwargs['depfile'] = res_kwargs['output'] + '.d'
- res_kwargs['command'] += ['--preprocessor-arg=-MD', '--preprocessor-arg=-MQ@OUTPUT@', '--preprocessor-arg=-MF@DEPFILE@']
+ res_kwargs['depfile'] = f'{output}.d'
+ command.extend(['--preprocessor-arg=-MD',
+ '--preprocessor-arg=-MQ@OUTPUT@',
+ '--preprocessor-arg=-MF@DEPFILE@'])
- res_targets.append(build.CustomTarget(name_formatted, state.subdir, state.subproject, res_kwargs))
+ res_kwargs['command'] = command
- add_target(args)
+ res_targets.append(build.CustomTarget(name_formatted, state.subdir, state.subproject, res_kwargs))
return ModuleReturnValue(res_targets, [res_targets])
-def initialize(*args, **kwargs):
- return WindowsModule(*args, **kwargs)
+def initialize(interp: 'Interpreter') -> WindowsModule:
+ return WindowsModule(interp)
diff --git a/run_mypy.py b/run_mypy.py
index d6903f5..38ac676 100755
--- a/run_mypy.py
+++ b/run_mypy.py
@@ -44,6 +44,7 @@ modules = [
'mesonbuild/modules/qt.py',
'mesonbuild/modules/unstable_external_project.py',
'mesonbuild/modules/unstable_rust.py',
+ 'mesonbuild/modules/windows.py',
'mesonbuild/mparser.py',
'mesonbuild/msetup.py',
'mesonbuild/mtest.py',