Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/markdown/Builtin-options.md
Original file line number Diff line number Diff line change
Expand Up @@ -444,7 +444,7 @@ install prefix. For example: if the install prefix is `/usr` and the
| platlibdir | | Directory path | Directory for site-specific, platform-specific files (Since 0.60.0) |
| purelibdir | | Directory path | Directory for site-specific, non-platform-specific files (Since 0.60.0) |
| allow_limited_api | true | true, false | Disables project-wide use of the Python Limited API (Since 1.3.0) |
| build_config | | File path | Specifies the Python build configuration file (PEP 739) (Since 1.9.0) |
| build_config | | File path | Specifies the Python build configuration file (PEP 739) (Since 1.10.0) |

*Since 0.60.0* The `python.platlibdir` and `python.purelibdir` options are used
by the python module methods `python.install_sources()` and
Expand Down
7 changes: 5 additions & 2 deletions docs/markdown/Windows-module.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,11 @@ Compiles Windows `rc` files specified in the positional arguments.
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* CustomTargetIndexes and CustomTargets with more than out output
*may be used as positional arguments.
*Since 0.61.0* `CustomTargetIndexes` and `CustomTargets` with more than one output
*may* be used as positional arguments.

*Since 1.10.0* Changes to included header files are now detected when using
`rc.exe` resource compiler.

This method has the following keyword arguments:

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
## Methods from compiler object now accept strings for include_directories

The various [[@compiler]] methods with a `include_directories` keyword argument
now accept stings or array of strings, in addition to [[@inc]] objects
generated from [[include_directories]] function, as it was already the case for
[[build_target]] family of functions.
10 changes: 10 additions & 0 deletions docs/markdown/snippets/windows_rc_depfile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
## windows.compile_resources now detects header changes with rc.exe

The `rc.exe` resource compiler neither provides *depfile* support nor
allows showing includes, as is possible with C or C++ compilers.
Therefore, changes to files included by the `.rc` file did not trigger
recompilation of the resource file.

A workaround was added to *meson* by calling the preprocessor on the
`.rc` file to detect the included headers and adding the result as a
dependency to the resource compilation.
10 changes: 7 additions & 3 deletions docs/yaml/objects/compiler.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,12 @@ methods:
description: You have found a bug if you can see this!
kwargs:
include_directories:
type: inc | array[inc]
type: array[inc | str]
since: 0.38.0
description: Extra directories for header searches.
description: |
Extra directories for header searches, created with the
[[include_directories]] function.
*(Since 1.10.0)* Strings are also accepted.

- name: _dependencies
returns: void
Expand Down Expand Up @@ -484,11 +487,12 @@ methods:
When the `has_headers` kwarg is also used, this argument is passed to
[[compiler.has_header]] as `args`.
header_include_directories:
type: inc | array[inc]
type: array[inc | str]
since: 0.51.0
description: |
When the `has_headers` kwarg is also used, this argument is passed to
[[compiler.has_header]] as `include_directories`.
*(Since 1.10.0)* Strings are also accepted.
header_dependencies:
type: dep | array[dep]
since: 0.51.0
Expand Down
26 changes: 11 additions & 15 deletions mesonbuild/interpreter/compiler.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from ..interpreterbase.decorators import ContainerTypeInfo, typed_kwargs, KwargInfo, typed_pos_args
from ..options import OptionKey
from .interpreterobjects import (extract_required_kwarg, extract_search_dirs)
from .type_checking import REQUIRED_KW, in_set_validator, NoneType
from .type_checking import INCLUDE_DIRECTORIES, REQUIRED_KW, in_set_validator, NoneType

if T.TYPE_CHECKING:
from ..interpreter import Interpreter
Expand Down Expand Up @@ -86,15 +86,15 @@ class FindLibraryKW(ExtractRequired, ExtractSearchDirs):
# prepended to the key
header_args: T.List[str]
header_dependencies: T.List[dependencies.Dependency]
header_include_directories: T.List[build.IncludeDirs]
header_include_directories: T.List[T.Union[build.IncludeDirs, str]]
header_no_builtin_args: bool
header_prefix: str
header_required: T.Union[bool, options.UserFeatureOption]

class PreprocessKW(TypedDict):
output: str
compile_args: T.List[str]
include_directories: T.List[build.IncludeDirs]
include_directories: T.List[T.Union[build.IncludeDirs, str]]
dependencies: T.List[dependencies.Dependency]
depends: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]

Expand Down Expand Up @@ -154,12 +154,6 @@ def stderr_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:
listify=True,
default=[],
)
_INCLUDE_DIRS_KW: KwargInfo[T.List[build.IncludeDirs]] = KwargInfo(
'include_directories',
ContainerTypeInfo(list, build.IncludeDirs),
default=[],
listify=True,
)
_PREFIX_KW: KwargInfo[str] = KwargInfo(
'prefix',
(str, ContainerTypeInfo(list, str)),
Expand All @@ -173,10 +167,10 @@ def stderr_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> str:

# Many of the compiler methods take this kwarg signature exactly, this allows
# simplifying the `typed_kwargs` calls
_COMMON_KWS: T.List[KwargInfo] = [_ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _PREFIX_KW, _NO_BUILTIN_ARGS_KW]
_COMMON_KWS: T.List[KwargInfo] = [_ARGS_KW, _DEPENDENCIES_KW, INCLUDE_DIRECTORIES, _PREFIX_KW, _NO_BUILTIN_ARGS_KW]

# Common methods of compiles, links, runs, and similar
_COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, _INCLUDE_DIRS_KW, _NO_BUILTIN_ARGS_KW,
_COMPILES_KWS: T.List[KwargInfo] = [_NAME_KW, _ARGS_KW, _DEPENDENCIES_KW, INCLUDE_DIRECTORIES, _NO_BUILTIN_ARGS_KW,
_WERROR_KW,
REQUIRED_KW.evolve(since='1.5.0', default=False)]

Expand Down Expand Up @@ -232,7 +226,7 @@ def cmd_array_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwargs') -> T
def _determine_args(self, kwargs: BaseCompileKW,
mode: CompileCheckMode = CompileCheckMode.LINK) -> T.List[str]:
args: T.List[str] = []
for i in kwargs['include_directories']:
for i in self.interpreter.extract_incdirs(kwargs, strings_since='1.10.0'):
for idir in i.to_string_list(self.environment.get_source_dir(), self.environment.get_build_dir()):
args.extend(self.compiler.get_include_args(idir, False))
if not kwargs['no_builtin_args']:
Expand Down Expand Up @@ -687,13 +681,15 @@ def find_library_method(self, args: T.Tuple[str], kwargs: 'FindLibraryKW') -> 'd
mlog.log('Library', mlog.bold(libname), 'skipped: feature', mlog.bold(feature), 'disabled')
return self.notfound_library(libname)

include_directories = self.interpreter.extract_incdirs(kwargs, key='header_include_directories', strings_since='1.10.0')

# This could be done with a comprehension, but that confuses the type
# checker, and having it check this seems valuable
has_header_kwargs: 'HeaderKW' = {
'required': required,
'args': kwargs['header_args'],
'dependencies': kwargs['header_dependencies'],
'include_directories': kwargs['header_include_directories'],
'include_directories': include_directories,
'prefix': kwargs['header_prefix'],
'no_builtin_args': kwargs['header_no_builtin_args'],
}
Expand Down Expand Up @@ -890,7 +886,7 @@ def get_argument_syntax_method(self, args: T.List['TYPE_var'], kwargs: 'TYPE_kwa
'compiler.preprocess',
KwargInfo('output', str, default='@[email protected]'),
KwargInfo('compile_args', ContainerTypeInfo(list, str), listify=True, default=[]),
_INCLUDE_DIRS_KW,
INCLUDE_DIRECTORIES,
_DEPENDENCIES_KW.evolve(since='1.1.0'),
_DEPENDS_KW.evolve(since='1.4.0'),
)
Expand Down Expand Up @@ -918,7 +914,7 @@ def preprocess_method(self, args: T.Tuple[T.List['mesonlib.FileOrString']], kwar
compiler,
self.interpreter.backend,
kwargs['compile_args'],
kwargs['include_directories'],
self.interpreter.extract_incdirs(kwargs, strings_since='1.10.0'),
kwargs['dependencies'],
kwargs['depends'])
self.interpreter.add_target(tg.name, tg)
Expand Down
10 changes: 5 additions & 5 deletions mesonbuild/interpreter/interpreter.py
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ def func_files(self, node: mparser.FunctionNode, args: T.Tuple[T.List[str]], kwa
def func_declare_dependency(self, node: mparser.BaseNode, args: T.List[TYPE_var],
kwargs: kwtypes.FuncDeclareDependency) -> dependencies.Dependency:
deps = kwargs['dependencies']
incs = self.extract_incdirs(kwargs)
incs = self.extract_incdirs(kwargs, strings_since='0.50.0')
libs = kwargs['link_with']
libs_whole = kwargs['link_whole']
objects = kwargs['objects']
Expand Down Expand Up @@ -2788,12 +2788,12 @@ def func_configure_file(self, node: mparser.BaseNode, args: T.List[TYPE_var],
install_tag=install_tag, data_type='configure'))
return mesonlib.File.from_built_file(self.subdir, output)

def extract_incdirs(self, kwargs, key: str = 'include_directories') -> T.List[build.IncludeDirs]:
def extract_incdirs(self, kwargs, key: str = 'include_directories', strings_since: T.Optional[str] = None) -> T.List[build.IncludeDirs]:
prospectives = extract_as_list(kwargs, key)
if key == 'include_directories':
if strings_since:
for i in prospectives:
if isinstance(i, str):
FeatureNew.single_use('include_directories kwarg of type string', '0.50.0', self.subproject,
FeatureNew.single_use(f'{key} kwarg of type string', strings_since, self.subproject,
f'Use include_directories({i!r}) instead', location=self.current_node)
break

Expand Down Expand Up @@ -3461,7 +3461,7 @@ def build_target(self, node: mparser.BaseNode, args: T.Tuple[str, SourcesVarargs
node=node)
outputs.update(o)

kwargs['include_directories'] = self.extract_incdirs(kwargs)
kwargs['include_directories'] = self.extract_incdirs(kwargs, strings_since='0.50.0')

if targetclass is build.Executable:
kwargs = T.cast('kwtypes.Executable', kwargs)
Expand Down
46 changes: 41 additions & 5 deletions mesonbuild/modules/windows.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,13 @@
from . import ModuleState
from ..compilers import Compiler
from ..interpreter import Interpreter
from ..interpreter.interpreter import SourceOutputs

from typing_extensions import TypedDict

class CompileResources(TypedDict):

depend_files: T.List[mesonlib.FileOrString]
depends: T.List[T.Union[build.BuildTarget, build.CustomTarget]]
depends: T.List[T.Union[build.BuildTarget, build.CustomTarget, build.CustomTargetIndex]]
include_directories: T.List[T.Union[str, build.IncludeDirs]]
args: T.List[str]

Expand Down Expand Up @@ -102,6 +102,33 @@ def _find_resource_compiler(self, state: 'ModuleState') -> T.Tuple[ExternalProgr

return self._rescomp

def get_preprocessor_target(self,
name_formatted: str,
src: T.Union[str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex],
include_directories: T.List[build.IncludeDirs],
state: ModuleState) -> build.CustomTargetIndex:
compiler = self.detect_compiler(state.environment.coredata.compilers[MachineChoice.HOST])
_sources: T.List[T.Union[mesonlib.File, build.CustomTarget, build.CustomTargetIndex, build.GeneratedList]] = self.interpreter.source_strings_to_files([src])
sources = T.cast('T.List[SourceOutputs]', _sources)

tg = build.CompileTarget(
name_formatted,
state.subdir,
state.subproject,
state.environment,
sources,
'@[email protected]',
compiler.get_preprocessor(),
state.backend,
['-DRC_INVOKED'],
include_directories,
[],
[])
self.interpreter.add_target(tg.name, tg)

private_dir = os.path.relpath(state.backend.get_target_private_dir(tg), state.subdir)
return build.CustomTargetIndex(tg, os.path.join(private_dir, tg.outputs[0]))

@typed_pos_args('windows.compile_resources', varargs=(str, mesonlib.File, build.CustomTarget, build.CustomTargetIndex), min_varargs=1)
@typed_kwargs(
'windows.compile_resources',
Expand All @@ -121,7 +148,8 @@ def compile_resources(self, state: 'ModuleState',
extra_args += state.get_include_args([
build.IncludeDirs('', [], False, [os.path.join('@BUILD_ROOT@', self.interpreter.backend.get_target_dir(d))])
])
extra_args += state.get_include_args(kwargs['include_directories'])
include_directories = self.interpreter.extract_incdirs(kwargs)
extra_args += state.get_include_args(include_directories)

rescomp, rescomp_type = self._find_resource_compiler(state)
if rescomp_type == ResourceCompilerType.rc:
Expand Down Expand Up @@ -178,12 +206,20 @@ def get_names() -> T.Iterable[T.Tuple[str, str, T.Union[str, mesonlib.File, buil
command.append(rescomp)
command.extend(res_args)
depfile: T.Optional[str] = None
# instruct binutils windres to generate a preprocessor depfile
extra_depends = wrc_depends.copy()
if rescomp_type == ResourceCompilerType.windres:
# instruct binutils windres to generate a preprocessor depfile
depfile = f'{output}.d'
command.extend(['--preprocessor-arg=-MD',
'--preprocessor-arg=-MQ@OUTPUT@',
'--preprocessor-arg=-MF@DEPFILE@'])
elif rescomp_type == ResourceCompilerType.rc:
# use preprocessor to detect header dependencies
extra_depends.append(self.get_preprocessor_target(
name_formatted + '_i',
src,
include_directories,
state))

res_targets.append(build.CustomTarget(
name_formatted,
Expand All @@ -195,7 +231,7 @@ def get_names() -> T.Iterable[T.Tuple[str, str, T.Union[str, mesonlib.File, buil
[output],
depfile=depfile,
depend_files=wrc_depend_files,
extra_depends=wrc_depends,
extra_depends=extra_depends,
description='Compiling Windows resource {}',
))

Expand Down
Loading