From 2044bc53b3534e0e91d75b5435792e4b4d342847 Mon Sep 17 00:00:00 2001 From: Nicolas Schneider Date: Sun, 27 Jan 2019 11:03:26 +0100 Subject: [PATCH 1/2] use same compiler args for pch as for regular target Fixes #999, #1415, #2361. --- mesonbuild/backend/ninjabackend.py | 30 +++++++++++-------- .../common/13 pch/generated/gen_custom.py | 5 ++++ .../common/13 pch/generated/gen_generator.py | 7 +++++ .../13 pch/generated/generated_generator.in | 1 + .../common/13 pch/generated/meson.build | 16 ++++++++++ test cases/common/13 pch/generated/pch/prog.h | 2 ++ .../common/13 pch/generated/pch/prog_pch.c | 5 ++++ test cases/common/13 pch/generated/prog.c | 6 ++++ test cases/common/13 pch/meson.build | 2 ++ .../withIncludeDirectories/include/lib/lib.h | 1 + .../13 pch/withIncludeDirectories/meson.build | 9 ++++++ .../13 pch/withIncludeDirectories/pch/prog.h | 1 + .../withIncludeDirectories/pch/prog_pch.c | 5 ++++ .../13 pch/withIncludeDirectories/prog.c | 10 +++++++ 14 files changed, 88 insertions(+), 12 deletions(-) create mode 100644 test cases/common/13 pch/generated/gen_custom.py create mode 100644 test cases/common/13 pch/generated/gen_generator.py create mode 100644 test cases/common/13 pch/generated/generated_generator.in create mode 100644 test cases/common/13 pch/generated/meson.build create mode 100644 test cases/common/13 pch/generated/pch/prog.h create mode 100644 test cases/common/13 pch/generated/pch/prog_pch.c create mode 100644 test cases/common/13 pch/generated/prog.c create mode 100644 test cases/common/13 pch/withIncludeDirectories/include/lib/lib.h create mode 100644 test cases/common/13 pch/withIncludeDirectories/meson.build create mode 100644 test cases/common/13 pch/withIncludeDirectories/pch/prog.h create mode 100644 test cases/common/13 pch/withIncludeDirectories/pch/prog_pch.c create mode 100644 test cases/common/13 pch/withIncludeDirectories/prog.c diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index 9b215b2f1..a0b9207e0 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -428,12 +428,7 @@ int dummy; # Generate rules for building the remaining source files in this target outname = self.get_target_filename(target) obj_list = [] - use_pch = self.environment.coredata.base_options.get('b_pch', False) is_unity = self.is_unity(target) - if use_pch and target.has_pch(): - pch_objects = self.generate_pch(target, outfile) - else: - pch_objects = [] header_deps = [] unity_src = [] unity_deps = [] # Generated sources that must be built before compiling a Unity target. @@ -486,6 +481,12 @@ int dummy; header_deps=header_deps) obj_list.append(o) + use_pch = self.environment.coredata.base_options.get('b_pch', False) + if use_pch and target.has_pch(): + pch_objects = self.generate_pch(target, outfile, header_deps=header_deps) + else: + pch_objects = [] + # Generate compilation targets for C sources generated from Vala # sources. This can be extended to other $LANG->C compilers later if # necessary. This needs to be separate for at least Vala @@ -2181,12 +2182,7 @@ rule FORTRAN_DEP_HACK%s commands += compiler.get_module_outdir_args(self.get_target_private_dir(target)) element = NinjaBuildElement(self.all_outputs, rel_obj, compiler_name, rel_src) - for d in header_deps: - if isinstance(d, File): - d = d.rel_to_builddir(self.build_to_src) - elif not self.has_dir_part(d): - d = os.path.join(self.get_target_private_dir(target), d) - element.add_dep(d) + self.add_header_deps(target, element, header_deps) for d in extra_deps: element.add_dep(d) for d in order_deps: @@ -2206,6 +2202,14 @@ rule FORTRAN_DEP_HACK%s element.write(outfile) return rel_obj + def add_header_deps(self, target, ninja_element, header_deps): + for d in header_deps: + if isinstance(d, File): + d = d.rel_to_builddir(self.build_to_src) + elif not self.has_dir_part(d): + d = os.path.join(self.get_target_private_dir(target), d) + ninja_element.add_dep(d) + def has_dir_part(self, fname): # FIXME FIXME: The usage of this is a terrible and unreliable hack if isinstance(fname, File): @@ -2236,6 +2240,7 @@ rule FORTRAN_DEP_HACK%s just_name = os.path.basename(header) (objname, pch_args) = compiler.gen_pch_args(just_name, source, dst) commands += pch_args + commands += self._generate_single_compile(target, compiler) commands += self.get_compile_debugfile_args(compiler, target, objname) dep = dst + '.' + compiler.get_depfile_suffix() return commands, dep, dst, [objname] @@ -2251,7 +2256,7 @@ rule FORTRAN_DEP_HACK%s dep = dst + '.' + compiler.get_depfile_suffix() return commands, dep, dst, [] # Gcc does not create an object file during pch generation. - def generate_pch(self, target, outfile): + def generate_pch(self, target, outfile, header_deps=[]): cstr = '' pch_objects = [] if target.is_cross: @@ -2282,6 +2287,7 @@ rule FORTRAN_DEP_HACK%s elem = NinjaBuildElement(self.all_outputs, dst, rulename, src) if extradep is not None: elem.add_dep(extradep) + self.add_header_deps(target, elem, header_deps) elem.add_item('ARGS', commands) elem.add_item('DEPFILE', dep) elem.write(outfile) diff --git a/test cases/common/13 pch/generated/gen_custom.py b/test cases/common/13 pch/generated/gen_custom.py new file mode 100644 index 000000000..650e03c2b --- /dev/null +++ b/test cases/common/13 pch/generated/gen_custom.py @@ -0,0 +1,5 @@ +#!/usr/bin/env python3 +import sys + +with open(sys.argv[1], 'w') as f: + f.write("#define FOO 0") diff --git a/test cases/common/13 pch/generated/gen_generator.py b/test cases/common/13 pch/generated/gen_generator.py new file mode 100644 index 000000000..a245e7aef --- /dev/null +++ b/test cases/common/13 pch/generated/gen_generator.py @@ -0,0 +1,7 @@ +#!/usr/bin/env python3 +import sys + +with open(sys.argv[1]) as f: + content = f.read() +with open(sys.argv[2], 'w') as f: + f.write(content) diff --git a/test cases/common/13 pch/generated/generated_generator.in b/test cases/common/13 pch/generated/generated_generator.in new file mode 100644 index 000000000..1a00ebd21 --- /dev/null +++ b/test cases/common/13 pch/generated/generated_generator.in @@ -0,0 +1 @@ +#define BAR 0 diff --git a/test cases/common/13 pch/generated/meson.build b/test cases/common/13 pch/generated/meson.build new file mode 100644 index 000000000..372a00ec7 --- /dev/null +++ b/test cases/common/13 pch/generated/meson.build @@ -0,0 +1,16 @@ +cc = meson.get_compiler('c') +cc_id = cc.get_id() +if cc_id == 'lcc' + error('MESON_SKIP_TEST: Elbrus compiler does not support PCH.') +endif + +generated_customTarget = custom_target('makeheader', + output: 'generated_customTarget.h', + command : [find_program('gen_custom.py'), '@OUTPUT0@']) + +generated_generator = generator(find_program('gen_generator.py'), + output: '@BASENAME@.h', + arguments: ['@INPUT@', '@OUTPUT@']) + +exe = executable('prog', 'prog.c', generated_customTarget, generated_generator.process('generated_generator.in'), + c_pch: ['pch/prog_pch.c', 'pch/prog.h']) diff --git a/test cases/common/13 pch/generated/pch/prog.h b/test cases/common/13 pch/generated/pch/prog.h new file mode 100644 index 000000000..15fec38ce --- /dev/null +++ b/test cases/common/13 pch/generated/pch/prog.h @@ -0,0 +1,2 @@ +#include "generated_customTarget.h" +#include "generated_generator.h" diff --git a/test cases/common/13 pch/generated/pch/prog_pch.c b/test cases/common/13 pch/generated/pch/prog_pch.c new file mode 100644 index 000000000..49605057b --- /dev/null +++ b/test cases/common/13 pch/generated/pch/prog_pch.c @@ -0,0 +1,5 @@ +#if !defined(_MSC_VER) +#error "This file is only for use with MSVC." +#endif + +#include "prog.h" diff --git a/test cases/common/13 pch/generated/prog.c b/test cases/common/13 pch/generated/prog.c new file mode 100644 index 000000000..9b2e2ef22 --- /dev/null +++ b/test cases/common/13 pch/generated/prog.c @@ -0,0 +1,6 @@ +// No includes here, they need to come from the PCH + +int main(int argc, char **argv) { + return FOO + BAR; +} + diff --git a/test cases/common/13 pch/meson.build b/test cases/common/13 pch/meson.build index d39527b7b..43129c9d1 100644 --- a/test cases/common/13 pch/meson.build +++ b/test cases/common/13 pch/meson.build @@ -2,6 +2,8 @@ project('pch test', 'c', 'cpp') subdir('c') subdir('cpp') +subdir('generated') +subdir('withIncludeDirectories') if meson.backend() == 'xcode' warning('Xcode backend only supports one precompiled header per target. Skipping "mixed" which has various precompiled headers.') diff --git a/test cases/common/13 pch/withIncludeDirectories/include/lib/lib.h b/test cases/common/13 pch/withIncludeDirectories/include/lib/lib.h new file mode 100644 index 000000000..53c5fdf17 --- /dev/null +++ b/test cases/common/13 pch/withIncludeDirectories/include/lib/lib.h @@ -0,0 +1 @@ +#include diff --git a/test cases/common/13 pch/withIncludeDirectories/meson.build b/test cases/common/13 pch/withIncludeDirectories/meson.build new file mode 100644 index 000000000..2ab2cd888 --- /dev/null +++ b/test cases/common/13 pch/withIncludeDirectories/meson.build @@ -0,0 +1,9 @@ +cc = meson.get_compiler('c') +cc_id = cc.get_id() +if cc_id == 'lcc' + error('MESON_SKIP_TEST: Elbrus compiler does not support PCH.') +endif + +exe = executable('prog', 'prog.c', + include_directories: 'include', + c_pch : ['pch/prog_pch.c', 'pch/prog.h']) diff --git a/test cases/common/13 pch/withIncludeDirectories/pch/prog.h b/test cases/common/13 pch/withIncludeDirectories/pch/prog.h new file mode 100644 index 000000000..383b2c513 --- /dev/null +++ b/test cases/common/13 pch/withIncludeDirectories/pch/prog.h @@ -0,0 +1 @@ +#include diff --git a/test cases/common/13 pch/withIncludeDirectories/pch/prog_pch.c b/test cases/common/13 pch/withIncludeDirectories/pch/prog_pch.c new file mode 100644 index 000000000..49605057b --- /dev/null +++ b/test cases/common/13 pch/withIncludeDirectories/pch/prog_pch.c @@ -0,0 +1,5 @@ +#if !defined(_MSC_VER) +#error "This file is only for use with MSVC." +#endif + +#include "prog.h" diff --git a/test cases/common/13 pch/withIncludeDirectories/prog.c b/test cases/common/13 pch/withIncludeDirectories/prog.c new file mode 100644 index 000000000..0ce3d0a24 --- /dev/null +++ b/test cases/common/13 pch/withIncludeDirectories/prog.c @@ -0,0 +1,10 @@ +// No includes here, they need to come from the PCH + +void func() { + fprintf(stdout, "This is a function that fails if stdio is not #included.\n"); +} + +int main(int argc, char **argv) { + return 0; +} + From 3cbc7c7bd97a57419f2344edc919dbb2b2ef7d55 Mon Sep 17 00:00:00 2001 From: Nicolas Schneider Date: Sun, 27 Jan 2019 15:10:59 +0100 Subject: [PATCH 2/2] msvc: fix PCH staleness --- mesonbuild/backend/ninjabackend.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py index a0b9207e0..e6edf8b38 100644 --- a/mesonbuild/backend/ninjabackend.py +++ b/mesonbuild/backend/ninjabackend.py @@ -2191,7 +2191,14 @@ rule FORTRAN_DEP_HACK%s elif not self.has_dir_part(d): d = os.path.join(self.get_target_private_dir(target), d) element.add_orderdep(d) - element.add_orderdep(pch_dep) + if compiler.id == 'msvc': + # MSVC does not show includes coming from the PCH with '/showIncludes', + # thus we must add an implicit dependency to the generated PCH. + element.add_dep(pch_dep) + else: + # All other compilers properly handle includes through the PCH, so only an + # orderdep is needed to make the initial build without depfile work. + element.add_orderdep(pch_dep) # Convert from GCC-style link argument naming to the naming used by the # current compiler. commands = commands.to_native()