From d1638a4fde5be879fe7778200b6ae6d59106a25e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Vili=20V=C3=A4in=C3=B6l=C3=A4?= Date: Sun, 27 Sep 2020 14:12:46 +0300 Subject: [PATCH] compilers/VS: fix build to use optimization and debug flags - Fixed using debug and optimization built-in options in MSVC. - Fixed that VS backend does not create pdb files in release mode. VS implicitly adds the debug fields if left out. - Fix that it is possible to add debug info with ninja backend with optimizations. --- mesonbuild/backend/backends.py | 4 +++ mesonbuild/backend/vs2010backend.py | 30 ++++++++++++------ mesonbuild/compilers/mixins/visualstudio.py | 34 ++++++++++----------- 3 files changed, 41 insertions(+), 27 deletions(-) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 85d5eb6c8..a8b6df985 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -685,6 +685,10 @@ class Backend: commands += compiler.get_buildtype_args(self.get_option_for_target('buildtype', target)) commands += compiler.get_optimization_args(self.get_option_for_target('optimization', target)) commands += compiler.get_debug_args(self.get_option_for_target('debug', target)) + # MSVC debug builds have /ZI argument by default and /Zi is added with debug flag + # /ZI needs to be removed in that case to avoid cl's warning to that effect (D9025 : overriding '/ZI' with '/Zi') + if ('/ZI' in commands) and ('/Zi' in commands): + commands.remove('/Zi') # Add compile args added using add_project_arguments() commands += self.build.get_project_args(compiler, target.subproject, target.for_machine) # Add compile args added using add_global_arguments() diff --git a/mesonbuild/backend/vs2010backend.py b/mesonbuild/backend/vs2010backend.py index 3b0f84246..ab2cafd9b 100644 --- a/mesonbuild/backend/vs2010backend.py +++ b/mesonbuild/backend/vs2010backend.py @@ -182,6 +182,8 @@ class Vs2010Backend(backends.Backend): else: raise MesonException('Unsupported Visual Studio platform: ' + target_machine) self.buildtype = self.environment.coredata.get_builtin_option('buildtype') + self.optimization = self.environment.coredata.get_builtin_option('optimization') + self.debug = self.environment.coredata.get_builtin_option('debug') sln_filename = os.path.join(self.environment.get_build_dir(), self.build.project_name + '.sln') projlist = self.generate_projects() self.gen_testproj('RUN_TESTS', os.path.join(self.environment.get_build_dir(), 'RUN_TESTS.vcxproj')) @@ -774,7 +776,9 @@ class Vs2010Backend(backends.Backend): if self.is_unity(target): sources = self.generate_unity_files(target, sources) compiler = self._get_cl_compiler(target) - buildtype_args = compiler.get_buildtype_args(self.buildtype) + build_args = compiler.get_buildtype_args(self.buildtype) + build_args += compiler.get_optimization_args(self.optimization) + build_args += compiler.get_debug_args(self.debug) buildtype_link_args = compiler.get_buildtype_linker_args(self.buildtype) vscrt_type = self.environment.coredata.base_options['b_vscrt'] project_name = target.name @@ -844,18 +848,20 @@ class Vs2010Backend(backends.Backend): ET.SubElement(type_config, 'UseDebugLibraries').text = 'false' ET.SubElement(clconf, 'RuntimeLibrary').text = 'MultiThreadedDLL' # Debug format - if '/ZI' in buildtype_args: + if '/ZI' in build_args: ET.SubElement(clconf, 'DebugInformationFormat').text = 'EditAndContinue' - elif '/Zi' in buildtype_args: + elif '/Zi' in build_args: ET.SubElement(clconf, 'DebugInformationFormat').text = 'ProgramDatabase' - elif '/Z7' in buildtype_args: + elif '/Z7' in build_args: ET.SubElement(clconf, 'DebugInformationFormat').text = 'OldStyle' + else: + ET.SubElement(clconf, 'DebugInformationFormat').text = 'None' # Runtime checks - if '/RTC1' in buildtype_args: + if '/RTC1' in build_args: ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'EnableFastChecks' - elif '/RTCu' in buildtype_args: + elif '/RTCu' in build_args: ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'UninitializedLocalUsageCheck' - elif '/RTCs' in buildtype_args: + elif '/RTCs' in build_args: ET.SubElement(clconf, 'BasicRuntimeChecks').text = 'StackFrameRuntimeCheck' # Exception handling has to be set in the xml in addition to the "AdditionalOptions" because otherwise # cl will give warning D9025: overriding '/Ehs' with cpp_eh value @@ -1022,6 +1028,8 @@ class Vs2010Backend(backends.Backend): target_args.append(arg) languages += gen_langs + if '/Gw' in build_args: + target_args.append('/Gw') if len(target_args) > 0: target_args.append('%(AdditionalOptions)') ET.SubElement(clconf, "AdditionalOptions").text = ' '.join(target_args) @@ -1035,7 +1043,7 @@ class Vs2010Backend(backends.Backend): if self.get_option_for_target('werror', target): ET.SubElement(clconf, 'TreatWarningAsError').text = 'true' # Optimization flags - o_flags = split_o_flags_args(buildtype_args) + o_flags = split_o_flags_args(build_args) if '/Ox' in o_flags: ET.SubElement(clconf, 'Optimization').text = 'Full' elif '/O2' in o_flags: @@ -1087,8 +1095,10 @@ class Vs2010Backend(backends.Backend): # AdditionalOptions? extra_link_args += compiler.get_buildtype_linker_args(self.buildtype) # Generate Debug info - if self.buildtype.startswith('debug'): + if self.debug: self.generate_debug_information(link) + else: + ET.SubElement(link, 'GenerateDebugInformation').text = 'false' if not isinstance(target, build.StaticLibrary): if isinstance(target, build.SharedModule): options = self.environment.coredata.base_options @@ -1186,7 +1196,7 @@ class Vs2010Backend(backends.Backend): if target.vs_module_defs: relpath = os.path.join(down, target.vs_module_defs.rel_to_builddir(self.build_to_src)) ET.SubElement(link, 'ModuleDefinitionFile').text = relpath - if '/ZI' in buildtype_args or '/Zi' in buildtype_args: + if self.debug: pdb = ET.SubElement(link, 'ProgramDataBaseFileName') pdb.text = '$(OutDir}%s.pdb' % target_name targetmachine = ET.SubElement(link, 'TargetMachine') diff --git a/mesonbuild/compilers/mixins/visualstudio.py b/mesonbuild/compilers/mixins/visualstudio.py index d9abb9540..77f8dfc13 100644 --- a/mesonbuild/compilers/mixins/visualstudio.py +++ b/mesonbuild/compilers/mixins/visualstudio.py @@ -62,10 +62,10 @@ vs64_instruction_set_args = { msvc_buildtype_args = { 'plain': [], - 'debug': ["/ZI", "/Ob0", "/Od", "/RTC1"], - 'debugoptimized': ["/Zi", "/Ob1"], - 'release': ["/Ob2", "/Gw"], - 'minsize': ["/Zi", "/Gw"], + 'debug': ["/ZI", "/RTC1"], + 'debugoptimized': [], + 'release': [], + 'minsize': [], 'custom': [], } # type: T.Dict[str, T.List[str]] @@ -79,17 +79,17 @@ clangcl_buildtype_args = msvc_buildtype_args.copy() clangcl_buildtype_args['debug'] = ['/Zi', '/Ob0', '/Od', '/RTC1'] msvc_optimization_args = { - '0': [], + '0': ['/Od', '/Ob0'], 'g': ['/O0'], '1': ['/O1'], - '2': ['/O2'], - '3': ['/O2'], - 's': ['/O1'], # Implies /Os. + '2': ['/O2', '/Ob1'], + '3': ['/O2', '/Ob2', '/Gw'], + 's': ['/O1', '/Gw'], # Implies /Os. } # type: T.Dict[str, T.List[str]] msvc_debug_args = { False: [], - True: [] # Fixme! + True: ['/Zi'] } # type: T.Dict[bool, T.List[str]] @@ -182,12 +182,18 @@ class VisualStudioLikeCompiler(Compiler, metaclass=abc.ABCMeta): return ['/Fe' + target] return ['/Fo' + target] - def get_optimization_args(self, optimization_level: str) -> T.List[str]: - return msvc_optimization_args[optimization_level] + def get_buildtype_args(self, buildtype: str) -> T.List[str]: + return msvc_buildtype_args[buildtype] def get_debug_args(self, is_debug: bool) -> T.List[str]: return msvc_debug_args[is_debug] + def get_optimization_args(self, optimization_level: str) -> T.List[str]: + args = msvc_optimization_args[optimization_level] + if mesonlib.version_compare(self.version, '<18.0'): + args = [arg for arg in args if arg != '/Gw'] + return args + def get_dependency_gen_args(self, outtarget: str, outfile: str) -> T.List[str]: return [] @@ -409,12 +415,6 @@ class MSVCCompiler(VisualStudioLikeCompiler): return None return super().get_instruction_set_args(instruction_set) - def get_buildtype_args(self, buildtype: str) -> T.List[str]: - args = msvc_buildtype_args[buildtype] - if mesonlib.version_compare(self.version, '<18.0'): - args = [arg for arg in args if arg != '/Gw'] - return args - def get_pch_base_name(self, header: str) -> str: return os.path.basename(header)