From 5e047d9c91038480bbe0d11205aa3dcc4bf7dfd0 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Wed, 17 Aug 2016 23:26:32 +0300 Subject: [PATCH 01/11] Write pdb info to a specific file. --- mesonbuild/backend/ninjabackend.py | 1 + mesonbuild/compilers.py | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 15f298b1e7cd..cb007d458fa3 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1521,6 +1521,7 @@ def generate_single_compile(self, target, outfile, src, is_generated=False, head commands+= compiler.get_include_args(i, False) if self.environment.coredata.base_options.get('b_pch', False): commands += self.get_pch_include_args(compiler, target) + commands += compiler.get_compile_debugfile_args(rel_obj) crstr = '' if target.is_cross: crstr = '_CROSS' diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index d020033c5182..5a8f48a9fbcb 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -352,6 +352,11 @@ def get_cross_extra_flags(self, environment, *, compile, link): def get_colorout_args(self, colortype): return [] + # Some compilers (msvc) write debug info to a separate file. + # These args specify where it should be written. + def get_compile_debugfile_args(self, rel_obj): + return [] + class CCompiler(Compiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None): super().__init__(exelist, version) @@ -1599,6 +1604,10 @@ def has_argument(self, arg, env): raise MesonException('Compiling test app failed.') return not(warning_text in stde or warning_text in stdo) + def get_compile_debugfile_args(self, rel_obj): + pdbarr = rel_obj.split('.')[:-1] + ['pdb'] + return ['/Fd' + '.'.join(pdbarr)] + class VisualStudioCPPCompiler(VisualStudioCCompiler): def __init__(self, exelist, version, is_cross, exe_wrap): VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap) From b08581d394d0e0102bce2e51c46f16f2102dc8c7 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Wed, 17 Aug 2016 23:50:50 +0300 Subject: [PATCH 02/11] Generate pdb files during linking. --- mesonbuild/backend/ninjabackend.py | 1 + mesonbuild/compilers.py | 11 +++++++++++ 2 files changed, 12 insertions(+) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index cb007d458fa3..7c47ef4de4f6 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1669,6 +1669,7 @@ def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[ linker) commands += linker.get_buildtype_linker_args(self.environment.coredata.get_builtin_option('buildtype')) commands += linker.get_option_link_args(self.environment.coredata.compiler_options) + commands += linker.get_link_debugfile_args(outname) if not(isinstance(target, build.StaticLibrary)): commands += self.environment.coredata.external_link_args[linker.get_language()] if isinstance(target, build.Executable): diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 5a8f48a9fbcb..744d75f8f6b9 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -357,6 +357,9 @@ def get_colorout_args(self, colortype): def get_compile_debugfile_args(self, rel_obj): return [] + def get_link_debugfile_args(self, rel_obj): + return [] + class CCompiler(Compiler): def __init__(self, exelist, version, is_cross, exe_wrapper=None): super().__init__(exelist, version) @@ -1608,6 +1611,10 @@ def get_compile_debugfile_args(self, rel_obj): pdbarr = rel_obj.split('.')[:-1] + ['pdb'] return ['/Fd' + '.'.join(pdbarr)] + def get_link_debugfile_args(self, targetfile): + pdbarr = targetfile.split('.')[:-1] + ['pdb'] + return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)] + class VisualStudioCPPCompiler(VisualStudioCCompiler): def __init__(self, exelist, version, is_cross, exe_wrap): VisualStudioCCompiler.__init__(self, exelist, version, is_cross, exe_wrap) @@ -2284,6 +2291,10 @@ def unix_link_flags_to_native(self, args): def unix_compile_flags_to_native(self, args): return args[:] + def get_link_debugfile_args(self, targetfile): + pdbarr = targetfile.split('.')[:-1] + ['pdb'] + return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)] + class ArLinker(): def __init__(self, exelist): From ccda29794b1802eba9dcd79ec2338407bb045fae Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Thu, 18 Aug 2016 00:12:54 +0300 Subject: [PATCH 03/11] Make pdb work with pch. --- mesonbuild/backend/ninjabackend.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 7c47ef4de4f6..a42db9fd5c65 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1521,7 +1521,8 @@ def generate_single_compile(self, target, outfile, src, is_generated=False, head commands+= compiler.get_include_args(i, False) if self.environment.coredata.base_options.get('b_pch', False): commands += self.get_pch_include_args(compiler, target) - commands += compiler.get_compile_debugfile_args(rel_obj) + + commands += compiler.get_compile_debugfile_args(self.get_target_filename_abs(target)) crstr = '' if target.is_cross: crstr = '_CROSS' @@ -1590,6 +1591,8 @@ def generate_msvc_pch_command(self, target, compiler, pch): just_name = os.path.split(header)[1] (objname, pch_args) = compiler.gen_pch_args(just_name, source, dst) commands += pch_args + tfilename = self.get_target_filename_abs(target) + commands += compiler.get_compile_debugfile_args(tfilename) dep = dst + '.' + compiler.get_depfile_suffix() return (commands, dep, dst, [objname]) From 402ef505fee84a3285dfb73bb723ccbf25fd46a1 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Thu, 18 Aug 2016 00:36:18 +0300 Subject: [PATCH 04/11] Fix unixy compilation. --- mesonbuild/compilers.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 744d75f8f6b9..8fd43de0e945 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -2343,3 +2343,6 @@ def unix_link_flags_to_native(self, args): def unix_compile_flags_to_native(self, args): return args[:] + + def get_link_debugfile_args(self, targetfile): + return [] From 1bed33fba2c78c95d98795405085139e3e6abc45 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Thu, 18 Aug 2016 22:56:14 +0300 Subject: [PATCH 05/11] Create pdbs that work when using pch or doing extract object (sadly not both). --- mesonbuild/backend/ninjabackend.py | 34 ++++++++++++++++++++++++++---- mesonbuild/compilers.py | 24 +++++++++++++-------- 2 files changed, 45 insertions(+), 13 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index a42db9fd5c65..94f90074bc72 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1433,6 +1433,33 @@ def get_cross_stdlib_args(self, target, compiler): return [] return compiler.get_no_stdinc_args() + + def get_pdb_name_suffix(self, target): + if isinstance(target, build.Executable): + suffix = '__exe' + elif isinstance(target, build.SharedLibrary): + suffix = '__dll' + elif isinstance(target, build.StaticLibrary): + suffix = '__lib' + else: + raise MesonException('Tried to build PDB for a non-buildtarget. Please file a bug.') + return suffix + + + def get_compile_debugfile_args(self, compiler, target, objfile): + if compiler.id != 'msvc': + return [] + suffix = self.get_pdb_name_suffix(target) + if target.has_pch(): + tfilename = self.get_target_filename_abs(target) + return compiler.get_compile_debugfile_args(tfilename, suffix) + else: + return compiler.get_compile_debugfile_args(objfile, suffix) + + def get_link_debugfile_args(self, linker, target, outname): + suffix = self.get_pdb_name_suffix(target) + return linker.get_link_debugfile_args(outname, suffix) + def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=[], order_deps=[]): if(isinstance(src, str) and src.endswith('.h')): raise RuntimeError('Fug') @@ -1522,7 +1549,7 @@ def generate_single_compile(self, target, outfile, src, is_generated=False, head if self.environment.coredata.base_options.get('b_pch', False): commands += self.get_pch_include_args(compiler, target) - commands += compiler.get_compile_debugfile_args(self.get_target_filename_abs(target)) + commands += self.get_compile_debugfile_args(compiler, target, rel_obj) crstr = '' if target.is_cross: crstr = '_CROSS' @@ -1591,8 +1618,7 @@ def generate_msvc_pch_command(self, target, compiler, pch): just_name = os.path.split(header)[1] (objname, pch_args) = compiler.gen_pch_args(just_name, source, dst) commands += pch_args - tfilename = self.get_target_filename_abs(target) - commands += compiler.get_compile_debugfile_args(tfilename) + commands += self.get_compile_debugfile_args(compiler, target, objname) dep = dst + '.' + compiler.get_depfile_suffix() return (commands, dep, dst, [objname]) @@ -1672,7 +1698,7 @@ def generate_link(self, target, outfile, outname, obj_list, linker, extra_args=[ linker) commands += linker.get_buildtype_linker_args(self.environment.coredata.get_builtin_option('buildtype')) commands += linker.get_option_link_args(self.environment.coredata.compiler_options) - commands += linker.get_link_debugfile_args(outname) + commands += self.get_link_debugfile_args(linker, target, outname) if not(isinstance(target, build.StaticLibrary)): commands += self.environment.coredata.external_link_args[linker.get_language()] if isinstance(target, build.Executable): diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 8fd43de0e945..4738abdaefc0 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -354,10 +354,10 @@ def get_colorout_args(self, colortype): # Some compilers (msvc) write debug info to a separate file. # These args specify where it should be written. - def get_compile_debugfile_args(self, rel_obj): + def get_compile_debugfile_args(self, rel_obj, fname_suffix): return [] - def get_link_debugfile_args(self, rel_obj): + def get_link_debugfile_args(self, rel_obj, fname_suffix): return [] class CCompiler(Compiler): @@ -1607,12 +1607,16 @@ def has_argument(self, arg, env): raise MesonException('Compiling test app failed.') return not(warning_text in stde or warning_text in stdo) - def get_compile_debugfile_args(self, rel_obj): - pdbarr = rel_obj.split('.')[:-1] + ['pdb'] + def get_compile_debugfile_args(self, rel_obj, name_suffix): + pdbarr = rel_obj.split('.')[:-1] + pdbarr[-1] += name_suffix + pdbarr += ['pdb'] return ['/Fd' + '.'.join(pdbarr)] - def get_link_debugfile_args(self, targetfile): - pdbarr = targetfile.split('.')[:-1] + ['pdb'] + def get_link_debugfile_args(self, targetfile, name_suffix): + pdbarr = targetfile.split('.')[:-1] + pdbarr[-1] += name_suffix + pdbarr += ['pdb'] return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)] class VisualStudioCPPCompiler(VisualStudioCCompiler): @@ -2291,8 +2295,10 @@ def unix_link_flags_to_native(self, args): def unix_compile_flags_to_native(self, args): return args[:] - def get_link_debugfile_args(self, targetfile): - pdbarr = targetfile.split('.')[:-1] + ['pdb'] + def get_link_debugfile_args(self, targetfile, name_suffix): + pdbarr = targetfile.split('.')[:-1] + pdbarr[-1] += name_suffix + pdbarr += ['pdb'] return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)] class ArLinker(): @@ -2344,5 +2350,5 @@ def unix_link_flags_to_native(self, args): def unix_compile_flags_to_native(self, args): return args[:] - def get_link_debugfile_args(self, targetfile): + def get_link_debugfile_args(self, targetfile, suffix): return [] From 36870ace0fb52ee8f2ca40c8ddb9cfb142032906 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Thu, 18 Aug 2016 23:15:54 +0300 Subject: [PATCH 06/11] Document pdb insanity a bit. --- mesonbuild/backend/ninjabackend.py | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 94f90074bc72..7a9ad445edc6 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1449,6 +1449,30 @@ def get_pdb_name_suffix(self, target): def get_compile_debugfile_args(self, compiler, target, objfile): if compiler.id != 'msvc': return [] + # The way MSVC uses PDB files is documented exactly nowhere so + # the following is what we have been able to decipher via reverse + # engineering. + # + # Each object file gets the path of its PDB file written inside it. + # This can be either the final PDB (for, say, foo.exe) or an object + # pdb (for foo.obj). If the former, then each compilation step locks + # the pdb file for writing, which is a bottleneck and object files from + # one target can not be used in a different target. The latter seems + # to be the sensible one (and what Unix does) but there is a catch. + # If you try to use precompiled headers MSVC will error out because + # both source and pch pdbs go in the same file and they must be the same. + # This means: + # + # - pch files must be compiled anew for every object file (negating + # the entire point of having them in the first place) + # - when using pch, output must go to the target pdb + # + # Since both of these are broken in some way, use the one that works + # for each target. This unfortunately means that you can't combine + # pch and object extraction in a single target. + # + # If you feel that the above is completely wrong and all of this is + # actually doable, please send patches. suffix = self.get_pdb_name_suffix(target) if target.has_pch(): tfilename = self.get_target_filename_abs(target) From a9da6c513281bd7c213d8d3d33c78c7ceed9dfd4 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Fri, 2 Sep 2016 22:52:37 +0300 Subject: [PATCH 07/11] Moved targets with same name into subdirs to make all tests pass. --- mesonbuild/backend/ninjabackend.py | 21 +++---------------- mesonbuild/compilers.py | 15 ++++++------- .../common/86 same basename/meson.build | 8 +++---- .../86 same basename/sharedsub/meson.build | 1 + .../86 same basename/staticsub/meson.build | 3 +++ 5 files changed, 16 insertions(+), 32 deletions(-) create mode 100644 test cases/common/86 same basename/sharedsub/meson.build create mode 100644 test cases/common/86 same basename/staticsub/meson.build diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 7a9ad445edc6..1f848f3d6c57 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1433,19 +1433,6 @@ def get_cross_stdlib_args(self, target, compiler): return [] return compiler.get_no_stdinc_args() - - def get_pdb_name_suffix(self, target): - if isinstance(target, build.Executable): - suffix = '__exe' - elif isinstance(target, build.SharedLibrary): - suffix = '__dll' - elif isinstance(target, build.StaticLibrary): - suffix = '__lib' - else: - raise MesonException('Tried to build PDB for a non-buildtarget. Please file a bug.') - return suffix - - def get_compile_debugfile_args(self, compiler, target, objfile): if compiler.id != 'msvc': return [] @@ -1473,16 +1460,14 @@ def get_compile_debugfile_args(self, compiler, target, objfile): # # If you feel that the above is completely wrong and all of this is # actually doable, please send patches. - suffix = self.get_pdb_name_suffix(target) if target.has_pch(): tfilename = self.get_target_filename_abs(target) - return compiler.get_compile_debugfile_args(tfilename, suffix) + return compiler.get_compile_debugfile_args(tfilename) else: - return compiler.get_compile_debugfile_args(objfile, suffix) + return compiler.get_compile_debugfile_args(objfile) def get_link_debugfile_args(self, linker, target, outname): - suffix = self.get_pdb_name_suffix(target) - return linker.get_link_debugfile_args(outname, suffix) + return linker.get_link_debugfile_args(outname) def generate_single_compile(self, target, outfile, src, is_generated=False, header_deps=[], order_deps=[]): if(isinstance(src, str) and src.endswith('.h')): diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 4738abdaefc0..8394acad226e 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -354,10 +354,10 @@ def get_colorout_args(self, colortype): # Some compilers (msvc) write debug info to a separate file. # These args specify where it should be written. - def get_compile_debugfile_args(self, rel_obj, fname_suffix): + def get_compile_debugfile_args(self, rel_obj): return [] - def get_link_debugfile_args(self, rel_obj, fname_suffix): + def get_link_debugfile_args(self, rel_obj): return [] class CCompiler(Compiler): @@ -1607,15 +1607,13 @@ def has_argument(self, arg, env): raise MesonException('Compiling test app failed.') return not(warning_text in stde or warning_text in stdo) - def get_compile_debugfile_args(self, rel_obj, name_suffix): + def get_compile_debugfile_args(self, rel_obj): pdbarr = rel_obj.split('.')[:-1] - pdbarr[-1] += name_suffix pdbarr += ['pdb'] return ['/Fd' + '.'.join(pdbarr)] - def get_link_debugfile_args(self, targetfile, name_suffix): + def get_link_debugfile_args(self, targetfile): pdbarr = targetfile.split('.')[:-1] - pdbarr[-1] += name_suffix pdbarr += ['pdb'] return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)] @@ -2295,9 +2293,8 @@ def unix_link_flags_to_native(self, args): def unix_compile_flags_to_native(self, args): return args[:] - def get_link_debugfile_args(self, targetfile, name_suffix): + def get_link_debugfile_args(self, targetfile): pdbarr = targetfile.split('.')[:-1] - pdbarr[-1] += name_suffix pdbarr += ['pdb'] return ['/DEBUG', '/PDB:' + '.'.join(pdbarr)] @@ -2350,5 +2347,5 @@ def unix_link_flags_to_native(self, args): def unix_compile_flags_to_native(self, args): return args[:] - def get_link_debugfile_args(self, targetfile, suffix): + def get_link_debugfile_args(self, targetfile): return [] diff --git a/test cases/common/86 same basename/meson.build b/test cases/common/86 same basename/meson.build index 3dc384ee7371..856c536c00a9 100644 --- a/test cases/common/86 same basename/meson.build +++ b/test cases/common/86 same basename/meson.build @@ -1,13 +1,11 @@ project('same basename', 'c') +subdir('sharedsub') +subdir('staticsub') + # Use the same source file to check that each top level target # has its own unique working directory. If they don't # then the .o files will clobber each other. -shlib = shared_library('name', 'lib.c', c_args : '-DSHAR') - -# On Windows a static lib is now libfoo.a, so it does not conflict with foo.lib -# from the shared library above -stlib = static_library('name', 'lib.c', c_args : '-DSTAT') exe1 = executable('name', 'exe1.c', link_with : stlib) exe2 = executable('name2', 'exe2.c', link_with : shlib) diff --git a/test cases/common/86 same basename/sharedsub/meson.build b/test cases/common/86 same basename/sharedsub/meson.build new file mode 100644 index 000000000000..29654a94dcab --- /dev/null +++ b/test cases/common/86 same basename/sharedsub/meson.build @@ -0,0 +1 @@ +shlib = shared_library('name', '../lib.c', c_args : '-DSHAR') diff --git a/test cases/common/86 same basename/staticsub/meson.build b/test cases/common/86 same basename/staticsub/meson.build new file mode 100644 index 000000000000..5e5242e06d58 --- /dev/null +++ b/test cases/common/86 same basename/staticsub/meson.build @@ -0,0 +1,3 @@ +# On Windows a static lib is now libfoo.a, so it does not conflict with foo.lib +# from the shared library above +stlib = static_library('name', '../lib.c', c_args : '-DSTAT') From c7e5e558f9b80c695907336f2150d097d9883ba4 Mon Sep 17 00:00:00 2001 From: Jussi Pakkanen Date: Sat, 10 Sep 2016 13:11:13 +0300 Subject: [PATCH 08/11] More PDB explanation. --- mesonbuild/backend/ninjabackend.py | 54 +++++++++++++++++++++--------- 1 file changed, 39 insertions(+), 15 deletions(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 1f848f3d6c57..28667b7953d8 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -1437,29 +1437,53 @@ def get_compile_debugfile_args(self, compiler, target, objfile): if compiler.id != 'msvc': return [] # The way MSVC uses PDB files is documented exactly nowhere so - # the following is what we have been able to decipher via reverse - # engineering. + # the following is what we have been able to decipher via + # reverse engineering. + # + # Each object file gets the path of its PDB file written + # inside it. This can be either the final PDB (for, say, + # foo.exe) or an object pdb (for foo.obj). If the former, then + # each compilation step locks the pdb file for writing, which + # is a bottleneck and object files from one target can not be + # used in a different target. The latter seems to be the + # sensible one (and what Unix does) but there is a catch. If + # you try to use precompiled headers MSVC will error out + # because both source and pch pdbs go in the same file and + # they must be the same. # - # Each object file gets the path of its PDB file written inside it. - # This can be either the final PDB (for, say, foo.exe) or an object - # pdb (for foo.obj). If the former, then each compilation step locks - # the pdb file for writing, which is a bottleneck and object files from - # one target can not be used in a different target. The latter seems - # to be the sensible one (and what Unix does) but there is a catch. - # If you try to use precompiled headers MSVC will error out because - # both source and pch pdbs go in the same file and they must be the same. # This means: # # - pch files must be compiled anew for every object file (negating # the entire point of having them in the first place) # - when using pch, output must go to the target pdb # - # Since both of these are broken in some way, use the one that works - # for each target. This unfortunately means that you can't combine - # pch and object extraction in a single target. + # Since both of these are broken in some way, use the one that + # works for each target. This unfortunately means that you + # can't combine pch and object extraction in a single target. + # + # PDB files also lead to filename collisions. A target foo.exe + # has a corresponding foo.pdb. A shared library foo.dll _also_ + # has pdb file called foo.pdb. So will a static library + # foo.lib, which clobbers both foo.pdb _and_ the dll file's + # export library called foo.lib (by default, currently we name + # them libfoo.a to avoidt this issue). You can give the files + # unique names such as foo_exe.pdb but VC also generates a + # bunch of other files which take their names from the target + # basename (i.e. "foo") and stomp on each other. # - # If you feel that the above is completely wrong and all of this is - # actually doable, please send patches. + # CMake solves this problem by doing two things. First of all + # static libraries do not generate pdb files at + # all. Presumably you don't need them and VC is smart enough + # to look up the original data when linking (speculation, not + # tested). The second solution is that you can only have + # target named "foo" as an exe, shared lib _or_ static + # lib. This makes filename collisions not happen. The downside + # is that you can't have an executable foo that uses a shared + # library libfoo.so, which is a common idiom on Unix. + # + # If you feel that the above is completely wrong and all of + # this is actually doable, please send patches. + if target.has_pch(): tfilename = self.get_target_filename_abs(target) return compiler.get_compile_debugfile_args(tfilename) From 4228a6dab6c591298b0895ce6a1ee034ba874581 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Sat, 10 Sep 2016 21:39:22 +0530 Subject: [PATCH 09/11] vs: Never serialize debug file generation with /FS /FS forces .pdb file writing to be serialized through MSPDBSRV.EXE, which is supposed to solve concurrency issues (esp. with anti-viruses), but it doesn't actually always work. It also isn't needed anymore since we don't use a shared vcXXX.pdb temporary file for pdb writing and use /Fd to explicitly set a per-target pdb filename instead. Not serializing the PDB writing will make a large difference on fast disks when linking multiple libraries and executables simultaneously. --- mesonbuild/compilers.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py index 8394acad226e..73f2416f8776 100644 --- a/mesonbuild/compilers.py +++ b/mesonbuild/compilers.py @@ -1436,16 +1436,11 @@ def can_compile(self, filename): class VisualStudioCCompiler(CCompiler): std_warn_args = ['/W3'] std_opt_args= ['/O2'] - vs2010_always_args = ['/nologo', '/showIncludes'] - vs2013_always_args = ['/nologo', '/showIncludes', '/FS'] def __init__(self, exelist, version, is_cross, exe_wrap): CCompiler.__init__(self, exelist, version, is_cross, exe_wrap) self.id = 'msvc' - if int(version.split('.')[0]) > 17: - self.always_args = VisualStudioCCompiler.vs2013_always_args - else: - self.always_args = VisualStudioCCompiler.vs2010_always_args + self.always_args = ['/nologo', '/showIncludes'] self.warn_args = {'1': ['/W2'], '2': ['/W3'], '3': ['/w4']} From 0840a908f235ac3a4df271e2cd262cad0cfc5cbd Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Mon, 9 May 2016 17:11:45 +0530 Subject: [PATCH 10/11] ninjabackend: Add support for installing .pdb files .pdb files are files created by MSVC which have debug symbols. These are created when /ZI or /Zi is passed to the compiler and /DEBUG to the linker. --- mesonbuild/backend/backends.py | 6 +++++ mesonbuild/backend/ninjabackend.py | 7 ++++++ mesonbuild/build.py | 37 ++++++++++++++++++++++++++++++ 3 files changed, 50 insertions(+) diff --git a/mesonbuild/backend/backends.py b/mesonbuild/backend/backends.py index 1f1c3ca01a47..81283dc80972 100644 --- a/mesonbuild/backend/backends.py +++ b/mesonbuild/backend/backends.py @@ -118,6 +118,12 @@ def get_target_filename_for_linking(self, target): return os.path.join(self.get_target_dir(target), target.get_filename()) raise AssertionError('BUG: Tried to link to something that\'s not a library') + def get_target_debug_filename(self, target): + fname = target.get_debug_filename() + if not fname: + raise AssertionError("BUG: Tried to generate debug filename when it doesn't exist") + return os.path.join(self.get_target_dir(target), fname) + def get_target_dir(self, target): if self.environment.coredata.get_builtin_option('layout') == 'mirror': dirname = target.get_subdir() diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 28667b7953d8..e00fe2f8f8c8 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -523,6 +523,13 @@ def generate_target_install(self, d): else: # XXX: Add BuildTarget-specific install dir cases here outdir = self.environment.get_libdir() + if isinstance(t, build.SharedLibrary) or isinstance(t, build.Executable): + if t.get_debug_filename(): + # Install the debug symbols file in the same place as + # the target itself. It has no aliases, should not be + # stripped, and doesn't have an install_rpath + i = [self.get_target_debug_filename(t), outdir, [], False, ''] + d.targets.append(i) i = [self.get_target_filename(t), outdir, t.get_aliaslist(),\ should_strip, t.install_rpath] d.targets.append(i) diff --git a/mesonbuild/build.py b/mesonbuild/build.py index 61dace7c153e..6dd2bde532b2 100644 --- a/mesonbuild/build.py +++ b/mesonbuild/build.py @@ -205,6 +205,8 @@ def __init__(self, name, subdir, subproject, is_cross, sources, objects, environ self.link_targets = [] self.link_depends = [] self.filename = 'no_name' + # The file with debugging symbols + self.debug_filename = None self.need_install = False self.pch = {} self.extra_args = {} @@ -466,6 +468,15 @@ def get_subdir(self): def get_filename(self): return self.filename + def get_debug_filename(self): + """ + The name of the file that contains debugging symbols for this target + + Returns None if there are no debugging symbols or if they are embedded + in the filename itself + """ + return self.debug_filename + def get_extra_args(self, language): return self.extra_args.get(language, []) @@ -708,6 +719,11 @@ def __init__(self, name, subdir, subproject, is_cross, sources, objects, environ self.filename = self.name if self.suffix: self.filename += '.' + self.suffix + # See determine_debug_filenames() in build.SharedLibrary + buildtype = environment.coredata.get_builtin_option('buildtype') + if compiler_is_msvc(self.sources, is_cross, environment) and \ + buildtype.startswith('debug'): + self.debug_filename = self.prefix + self.name + '.pdb' def type_suffix(self): return "@exe" @@ -733,6 +749,11 @@ def __init__(self, name, subdir, subproject, is_cross, sources, objects, environ else: self.suffix = 'a' self.filename = self.prefix + self.name + '.' + self.suffix + # See determine_debug_filenames() in build.SharedLibrary + buildtype = environment.coredata.get_builtin_option('buildtype') + if compiler_is_msvc(self.sources, is_cross, environment) and \ + buildtype.startswith('debug'): + self.debug_filename = self.prefix + self.name + '.pdb' def type_suffix(self): return "@sta" @@ -755,6 +776,7 @@ def __init__(self, name, subdir, subproject, is_cross, sources, objects, environ self.suffix = None self.basic_filename_tpl = '{0.prefix}{0.name}.{0.suffix}' self.determine_filenames(is_cross, environment) + self.determine_debug_filenames(is_cross, environment) def determine_filenames(self, is_cross, env): """ @@ -846,6 +868,21 @@ def determine_filenames(self, is_cross, env): self.suffix = suffix self.filename = self.filename_tpl.format(self) + def determine_debug_filenames(self, is_cross, env): + """ + Determine the debug filename(s) using the prefix/name/etc detected in + determine_filenames() above. + """ + buildtype = env.coredata.get_builtin_option('buildtype') + if compiler_is_msvc(self.sources, is_cross, env) and buildtype.startswith('debug'): + # Currently we only implement separate debug symbol files for MSVC + # since the toolchain does it for us. Other toolchains embed the + # debugging symbols in the file itself by default. + if self.soversion: + self.debug_filename = '{0.prefix}{0.name}-{0.soversion}.pdb'.format(self) + else: + self.debug_filename = '{0.prefix}{0.name}.pdb'.format(self) + def process_kwargs(self, kwargs, environment): super().process_kwargs(kwargs, environment) # Shared library version From 91c5f07a8efe550c4b64c72d0914108239fcc1c6 Mon Sep 17 00:00:00 2001 From: Nirbheek Chauhan Date: Fri, 24 Jun 2016 10:47:18 +0530 Subject: [PATCH 11/11] run_tests.py: Ignore .pdb files while validating install Their presence depends on build options and compiler, and we don't currently have the test infrastructure to deal with this. --- run_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/run_tests.py b/run_tests.py index 34258d8cd996..b71ab6d69af0 100755 --- a/run_tests.py +++ b/run_tests.py @@ -168,7 +168,7 @@ def validate_install(srcdir, installdir): # Check if there are any unexpected files found = get_relative_files_list_from_dir(installdir) for fname in found: - if fname not in expected: + if fname not in expected and not fname.endswith('.pdb'): ret_msg += 'Extra file {0} found.\n'.format(fname) return ret_msg