From d769de316d311fbb672abba678c0e2043e93b0c8 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Sun, 30 Sep 2018 16:43:32 +0100 Subject: [PATCH 1/2] Factor out windows resource compiler determination Factor out determination of the windows resource compiler as _find_resource_compiler(). Cache the result, so the work is only done once. --- mesonbuild/modules/windows.py | 42 +++++++++++++++++++++-------------- 1 file changed, 25 insertions(+), 17 deletions(-) diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index 59e845cdb..17cb87524 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -32,26 +32,14 @@ class WindowsModule(ExtensionModule): return compilers[l] raise MesonException('Resource compilation requires a C or C++ compiler.') - @FeatureNewKwargs('windows.compile_resources', '0.47.0', ['depend_files', 'depends']) - @permittedKwargs({'args', 'include_directories', 'depend_files', 'depends'}) - def compile_resources(self, state, args, kwargs): - comp = self.detect_compiler(state.compilers) + def _find_resource_compiler(self, state): + # FIXME: Does not handle `native: true` executables, see + # See https://github.com/mesonbuild/meson/issues/1531 - extra_args = mesonlib.stringlistify(kwargs.get('args', [])) - wrc_depend_files = extract_as_list(kwargs, 'depend_files', pop = True) - wrc_depends = extract_as_list(kwargs, 'depends', pop = True) - for d in wrc_depends: - if isinstance(d, CustomTargetHolder): - extra_args += get_include_args([d.outdir_include()]) - inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True) - for incd in inc_dirs: - if not isinstance(incd.held_object, (str, build.IncludeDirs)): - raise MesonException('Resource include dirs should be include_directories().') - extra_args += get_include_args(inc_dirs) + if hasattr(self, '_rescomp'): + return self._rescomp rescomp = None - # FIXME: Does not handle `native: true` executables, see - # https://github.com/mesonbuild/meson/issues/1531 if state.environment.is_cross_build(): # If cross compiling see if windres has been specified in the # cross file before trying to find it another way. @@ -65,6 +53,7 @@ class WindowsModule(ExtensionModule): rescomp = ExternalProgram('windres', command=os.environ.get('WINDRES'), silent=True) if not rescomp or not rescomp.found(): + comp = self.detect_compiler(state.compilers) if comp.id == 'msvc': rescomp = ExternalProgram('rc', silent=True) else: @@ -73,6 +62,25 @@ class WindowsModule(ExtensionModule): if not rescomp.found(): raise MesonException('Could not find Windows resource compiler') + self._rescomp = rescomp + 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(kwargs.get('args', [])) + wrc_depend_files = extract_as_list(kwargs, 'depend_files', pop = True) + wrc_depends = extract_as_list(kwargs, 'depends', pop = True) + for d in wrc_depends: + if isinstance(d, CustomTargetHolder): + extra_args += get_include_args([d.outdir_include()]) + inc_dirs = extract_as_list(kwargs, 'include_directories', pop = True) + for incd in inc_dirs: + if not isinstance(incd.held_object, (str, build.IncludeDirs)): + raise MesonException('Resource include dirs should be include_directories().') + extra_args += get_include_args(inc_dirs) + + rescomp = self._find_resource_compiler(state) if 'rc' in rescomp.get_path(): # RC is used to generate .res files, a special binary resource # format, which can be passed directly to LINK (apparently LINK uses From d0acada1d5f7ef16b8ec34d5cbb924190051a310 Mon Sep 17 00:00:00 2001 From: Jon Turney Date: Sun, 30 Sep 2018 17:11:11 +0100 Subject: [PATCH 2/2] Probe Windows resource compiler type Determine the type of the Windows resource compiler by looking at its output, not its name. Also log the name and version of the resource compiler we are using. --- mesonbuild/modules/windows.py | 26 ++++++++++++++++++++++---- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/mesonbuild/modules/windows.py b/mesonbuild/modules/windows.py index 17cb87524..f0d5113f8 100644 --- a/mesonbuild/modules/windows.py +++ b/mesonbuild/modules/windows.py @@ -12,7 +12,9 @@ # See the License for the specific language governing permissions and # limitations under the License. +import enum import os +import re from .. import mlog from .. import mesonlib, build @@ -24,6 +26,10 @@ from ..interpreter import CustomTargetHolder from ..interpreterbase import permittedKwargs, FeatureNewKwargs from ..dependencies import ExternalProgram +class ResourceCompilerType(enum.Enum): + windres = 1 + rc = 2 + class WindowsModule(ExtensionModule): def detect_compiler(self, compilers): @@ -62,7 +68,19 @@ class WindowsModule(ExtensionModule): if not rescomp.found(): raise MesonException('Could not find Windows resource compiler') - self._rescomp = rescomp + for (arg, match, type) in [ + ('/?', '^.*Microsoft.*Resource Compiler.*$', ResourceCompilerType.rc), + ('--version', '^.*GNU windres.*$', ResourceCompilerType.windres), + ]: + p, o, e = mesonlib.Popen_safe(rescomp.get_command() + [arg]) + m = re.search(match, o, re.MULTILINE) + if m: + mlog.log('Windows resource compiler: %s' % m.group()) + self._rescomp = (rescomp, type) + break + else: + raise MesonException('Could not determine type of Windows resource compiler') + return self._rescomp @FeatureNewKwargs('windows.compile_resources', '0.47.0', ['depend_files', 'depends']) @@ -80,8 +98,8 @@ class WindowsModule(ExtensionModule): raise MesonException('Resource include dirs should be include_directories().') extra_args += get_include_args(inc_dirs) - rescomp = self._find_resource_compiler(state) - if 'rc' in rescomp.get_path(): + rescomp, rescomp_type = self._find_resource_compiler(state) + if rescomp_type == ResourceCompilerType.rc: # RC is used to generate .res files, a special binary resource # format, which can be passed directly to LINK (apparently LINK uses # CVTRES internally to convert this to a COFF object) @@ -137,7 +155,7 @@ class WindowsModule(ExtensionModule): } # instruct binutils windres to generate a preprocessor depfile - if 'windres' in rescomp.get_path(): + 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@']