diff options
| author | L. E. Segovia <amy@amyspark.me> | 2025-08-03 22:26:07 -0300 |
|---|---|---|
| committer | Jussi Pakkanen <jussi.pakkanen@mailbox.org> | 2025-09-06 16:58:56 +0300 |
| commit | c3ea8d5aa1b48fbc4137ef783c567a32cd596993 (patch) | |
| tree | a1c729133a5e92ad516623192fd48c742db31fa2 /mesonbuild | |
| parent | 4b7a23c047ef5139f84cf96da37d132fe5fd84bc (diff) | |
| download | meson-c3ea8d5aa1b48fbc4137ef783c567a32cd596993.tar.gz | |
compilers: Enable out-of-the-box MSVC compatibility with ccache
ccache has been for a long time compatible with MSVC (since 4.6)
but when using debug mode, the /Z7 flag must be passed instead of
/Zi.
See https://ccache.dev/releasenotes.html#_ccache_4_6
Diffstat (limited to 'mesonbuild')
| -rw-r--r-- | mesonbuild/backend/vs2010backend.py | 8 | ||||
| -rw-r--r-- | mesonbuild/cmake/interpreter.py | 4 | ||||
| -rw-r--r-- | mesonbuild/cmake/toolchain.py | 10 | ||||
| -rw-r--r-- | mesonbuild/compilers/detect.py | 21 | ||||
| -rw-r--r-- | mesonbuild/compilers/mixins/visualstudio.py | 10 | ||||
| -rw-r--r-- | mesonbuild/envconfig.py | 26 |
6 files changed, 45 insertions, 34 deletions
diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index deb3dfb23..8804b8daa 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -865,6 +865,8 @@ class Vs2010Backend(backends.Backend): # FIXME add args as needed. if entry[1:].startswith('fsanitize'): return True + if entry[1:] in frozenset(['Zi', 'Z7', 'ZI']): + return True return entry[1:].startswith('M') def add_additional_options(self, lang, parent_node, file_args): @@ -1348,11 +1350,11 @@ class Vs2010Backend(backends.Backend): if '/fsanitize=address' in build_args: ET.SubElement(type_config, 'EnableASAN').text = 'true' # Debug format - if '/ZI' in build_args: + if '/ZI' in build_args or '-ZI' in build_args: ET.SubElement(clconf, 'DebugInformationFormat').text = 'EditAndContinue' - elif '/Zi' in build_args: + elif '/Zi' in build_args or '-Zi' in build_args: ET.SubElement(clconf, 'DebugInformationFormat').text = 'ProgramDatabase' - elif '/Z7' in build_args: + elif '/Z7' in build_args or '-Z7' in build_args: ET.SubElement(clconf, 'DebugInformationFormat').text = 'OldStyle' else: ET.SubElement(clconf, 'DebugInformationFormat').text = 'None' diff --git a/mesonbuild/cmake/interpreter.py b/mesonbuild/cmake/interpreter.py index 1019246c5..54c9ae696 100644 --- a/mesonbuild/cmake/interpreter.py +++ b/mesonbuild/cmake/interpreter.py @@ -851,6 +851,10 @@ class CMakeInterpreter: trace_args = self.trace.trace_args() cmcmp_args = [f'-DCMAKE_POLICY_WARNING_{x}=OFF' for x in DISABLE_POLICY_WARNINGS] + if mesonlib.version_compare(cmake_exe.version(), '>= 3.25'): + # Enable MSVC debug information variable + cmcmp_args += ['-DCMAKE_POLICY_CMP0141=NEW'] + self.fileapi.setup_request() # Run CMake diff --git a/mesonbuild/cmake/toolchain.py b/mesonbuild/cmake/toolchain.py index 11a00be5d..902d6b088 100644 --- a/mesonbuild/cmake/toolchain.py +++ b/mesonbuild/cmake/toolchain.py @@ -174,6 +174,16 @@ class CMakeToolchain: return p # Set the compiler variables + comp_obj = self.compilers.get('c', self.compilers.get('cpp', None)) + if comp_obj and comp_obj.get_id() == 'msvc': + debug_args = comp_obj.get_debug_args(True) + if '/Z7' in debug_args: + defaults['CMAKE_MSVC_DEBUG_INFORMATION_FORMAT'] = ['Embedded'] + elif '/Zi' in debug_args: + defaults['CMAKE_MSVC_DEBUG_INFORMATION_FORMAT'] = ['ProgramDatabase'] + elif '/ZI' in debug_args: + defaults['CMAKE_MSVC_DEBUG_INFORMATION_FORMAT'] = ['EditAndContinue'] + for lang, comp_obj in self.compilers.items(): language = language_map.get(lang, None) diff --git a/mesonbuild/compilers/detect.py b/mesonbuild/compilers/detect.py index f57957f0b..a0ae8108d 100644 --- a/mesonbuild/compilers/detect.py +++ b/mesonbuild/compilers/detect.py @@ -5,8 +5,9 @@ from __future__ import annotations from ..mesonlib import ( MesonException, EnvironmentException, MachineChoice, join_args, - search_version, is_windows, Popen_safe, Popen_safe_logged, windows_proof_rm, + search_version, is_windows, Popen_safe, Popen_safe_logged, version_compare, windows_proof_rm, ) +from ..programs import ExternalProgram from ..envconfig import BinaryTable from .. import mlog @@ -118,7 +119,7 @@ def detect_compiler_for(env: 'Environment', lang: str, for_machine: MachineChoic # ======= def _get_compilers(env: 'Environment', lang: str, for_machine: MachineChoice, - allow_build_machine: bool = False) -> T.Tuple[T.List[T.List[str]], T.List[str]]: + allow_build_machine: bool = False) -> T.Tuple[T.List[T.List[str]], T.Union[None, ExternalProgram]]: ''' The list of compilers is detected in the exact same way for C, C++, ObjC, ObjC++, Fortran, CS so consolidate it here. @@ -269,7 +270,8 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin from . import c, cpp from ..linkers import linkers popen_exceptions: T.Dict[str, T.Union[Exception, str]] = {} - compilers, ccache = _get_compilers(env, lang, for_machine) + compilers, ccache_exe = _get_compilers(env, lang, for_machine) + ccache = ccache_exe.get_command() if (ccache_exe and ccache_exe.found()) else [] if override_compiler is not None: compilers = [override_compiler] is_cross = env.is_cross_build(for_machine) @@ -516,9 +518,10 @@ def _detect_c_or_cpp_compiler(env: 'Environment', lang: str, for_machine: Machin raise EnvironmentException(m) cls = c.VisualStudioCCompiler if lang == 'c' else cpp.VisualStudioCPPCompiler linker = guess_win_linker(env, ['link'], cls, version, for_machine) - # As of this writing, CCache does not support MSVC but sccache does. - if 'sccache' not in ccache: - ccache = [] + if ccache_exe and ccache_exe.found(): + if ccache_exe.get_name() == 'ccache' and version_compare(ccache_exe.get_version(), '< 4.6'): + mlog.warning('Visual Studio support requires ccache 4.6 or higher. You have ccache {}. '.format(ccache_exe.get_version()), once=True) + ccache = [] return cls( ccache, compiler, version, for_machine, is_cross, info, target, full_version=cl_signature, linker=linker) @@ -641,7 +644,8 @@ def detect_cuda_compiler(env: 'Environment', for_machine: MachineChoice) -> Comp from ..linkers.linkers import CudaLinker popen_exceptions = {} is_cross = env.is_cross_build(for_machine) - compilers, ccache = _get_compilers(env, 'cuda', for_machine) + compilers, ccache_exe = _get_compilers(env, 'cuda', for_machine) + ccache = ccache_exe.get_command() if (ccache_exe and ccache_exe.found()) else [] info = env.machines[for_machine] for compiler in compilers: arg = '--version' @@ -876,7 +880,8 @@ def detect_objcpp_compiler(env: 'Environment', for_machine: MachineChoice) -> 'C def _detect_objc_or_objcpp_compiler(env: 'Environment', lang: str, for_machine: MachineChoice) -> 'Compiler': from . import objc, objcpp popen_exceptions: T.Dict[str, T.Union[Exception, str]] = {} - compilers, ccache = _get_compilers(env, lang, for_machine) + compilers, ccache_exe = _get_compilers(env, lang, for_machine) + ccache = ccache_exe.get_command() if (ccache_exe and ccache_exe.found()) else [] is_cross = env.is_cross_build(for_machine) info = env.machines[for_machine] comp: T.Union[T.Type[objc.ObjCCompiler], T.Type[objcpp.ObjCPPCompiler]] diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index 275e7ab0a..4125ed885 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -66,11 +66,6 @@ msvc_optimization_args: T.Dict[str, T.List[str]] = { 's': ['/O1', '/Gw'], } -msvc_debug_args: T.Dict[bool, T.List[str]] = { - False: [], - True: ['/Zi'] -} - class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta): @@ -180,7 +175,10 @@ class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta): return ['/Fo' + outputname] def get_debug_args(self, is_debug: bool) -> T.List[str]: - return msvc_debug_args[is_debug] + if is_debug: + return ['/Z7'] + else: + return [] def get_optimization_args(self, optimization_level: str) -> T.List[str]: args = msvc_optimization_args[optimization_level] diff --git a/mesonbuild/envconfig.py b/mesonbuild/envconfig.py index 43fad0cd2..447639e00 100644 --- a/mesonbuild/envconfig.py +++ b/mesonbuild/envconfig.py @@ -4,12 +4,12 @@ from __future__ import annotations from dataclasses import dataclass -import subprocess import typing as T from enum import Enum from . import mesonlib from .mesonlib import EnvironmentException, HoldableObject +from .programs import ExternalProgram from . import mlog from pathlib import Path @@ -423,31 +423,23 @@ class BinaryTable: del self.binaries['pkgconfig'] @staticmethod - def detect_ccache() -> T.List[str]: - try: - subprocess.check_call(['ccache', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - except (OSError, subprocess.CalledProcessError): - return [] - return ['ccache'] + def detect_ccache() -> ExternalProgram: + return ExternalProgram('ccache') @staticmethod - def detect_sccache() -> T.List[str]: - try: - subprocess.check_call(['sccache', '--version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) - except (OSError, subprocess.CalledProcessError): - return [] - return ['sccache'] + def detect_sccache() -> ExternalProgram: + return ExternalProgram('sccache') @staticmethod - def detect_compiler_cache() -> T.List[str]: + def detect_compiler_cache() -> ExternalProgram: # Sccache is "newer" so it is assumed that people would prefer it by default. cache = BinaryTable.detect_sccache() - if cache: + if cache.found(): return cache return BinaryTable.detect_ccache() @classmethod - def parse_entry(cls, entry: T.Union[str, T.List[str]]) -> T.Tuple[T.List[str], T.List[str]]: + def parse_entry(cls, entry: T.Union[str, T.List[str]]) -> T.Tuple[T.List[str], T.Union[None, ExternalProgram]]: parts = mesonlib.stringlistify(entry) # Ensure ccache exists and remove it if it doesn't if parts[0] == 'ccache': @@ -458,7 +450,7 @@ class BinaryTable: ccache = cls.detect_sccache() else: compiler = parts - ccache = [] + ccache = None if not compiler: raise EnvironmentException(f'Compiler cache specified without compiler: {parts[0]}') # Return value has to be a list of compiler 'choices' |
