aboutsummaryrefslogtreecommitdiff
path: root/mesonbuild/backend/ninjabackend.py
diff options
context:
space:
mode:
Diffstat (limited to 'mesonbuild/backend/ninjabackend.py')
-rw-r--r--mesonbuild/backend/ninjabackend.py71
1 files changed, 71 insertions, 0 deletions
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
index 0b2b304..db9e1b0 100644
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -544,6 +544,13 @@ int dummy;
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)
@@ -1482,6 +1489,66 @@ rule FORTRAN_DEP_HACK
return []
return compiler.get_no_stdinc_args()
+ 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.
+ #
+ # 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.
+ #
+ # 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)
+ else:
+ return compiler.get_compile_debugfile_args(objfile)
+
+ def get_link_debugfile_args(self, linker, target, outname):
+ 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')):
raise RuntimeError('Fug')
@@ -1568,6 +1635,8 @@ rule FORTRAN_DEP_HACK
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 += self.get_compile_debugfile_args(compiler, target, rel_obj)
crstr = ''
if target.is_cross:
crstr = '_CROSS'
@@ -1636,6 +1705,7 @@ rule FORTRAN_DEP_HACK
just_name = os.path.split(header)[1]
(objname, pch_args) = compiler.gen_pch_args(just_name, source, dst)
commands += pch_args
+ commands += self.get_compile_debugfile_args(compiler, target, objname)
dep = dst + '.' + compiler.get_depfile_suffix()
return (commands, dep, dst, [objname])
@@ -1715,6 +1785,7 @@ rule FORTRAN_DEP_HACK
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 += 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):