Repository: mesonbuild/meson

Issue:
Compilation error when using include_directories() object in subdirectory
In the setup, which uses '-Wmissing-include-dirs' together with '-Werror' treating all warnings as errors gcc compiler returns an error. Here is the simplified example:
git@bitbucket.org:adel-mamin/meson-test.git
If I compile it with gcc I get the following error:
> ninja
[1/5] Compiling c object 'subdir/liba@sha/a.c.o'
FAILED: subdir/liba@sha/a.c.o
cc  '-Isubdir/liba@sha' '-Isubdir' '-I../subdir' '-Iinclude' '-I../include' '-pipe' '-Wall' '-Winvalid-pch' '-Wmissing-include-dirs' '-Werror' '-O0' '-g' '-fPIC' '-MMD' '-MQ' 'subdir/liba@sha/a.c.o' '-MF' 'subdir/liba@sha/a.c.o.d' -o 'subdir/liba@sha/a.c.o' -c ../subdir/a.c
cc1: error: include: No such file or directory [-Werror]
cc1: all warnings being treated as errors
[2/5] Compiling c object 'mytest@exe/main.c.o'
ninja: build stopped: subcommand failed.


Discussion:
actually this is because there is no such dir in builddir: `include`
I think fix would be something to not add $builddir/dir if it's not subdir()'ed.

Resolving patch:
diff --git a/mesonbuild/backend/ninjabackend.py b/mesonbuild/backend/ninjabackend.py
--- a/mesonbuild/backend/ninjabackend.py
+++ b/mesonbuild/backend/ninjabackend.py
@@ -1782,7 +1782,16 @@ def generate_single_compile(self, target, outfile, src, is_generated=False, head
             for d in i.get_incdirs():
                 expdir =  os.path.join(basedir, d)
                 srctreedir = os.path.join(self.build_to_src, expdir)
-                bargs = compiler.get_include_args(expdir, i.is_system)
+                # There may be include dirs where a build directory has not been
+                # created for some source dir. For example if someone does this:
+                #
+                # inc = include_directories('foo/bar/baz')
+                #
+                # But never subdir()s into the actual dir.
+                if os.path.isdir(os.path.join(self.environment.get_build_dir(), expdir)):
+                    bargs = compiler.get_include_args(expdir, i.is_system)
+                else:
+                    bargs = []
                 sargs = compiler.get_include_args(srctreedir, i.is_system)
                 commands += bargs
                 commands += sargs
diff --git a/mesonbuild/compilers.py b/mesonbuild/compilers.py
--- a/mesonbuild/compilers.py
+++ b/mesonbuild/compilers.py
@@ -1923,7 +1923,7 @@ def get_include_args(self, path, is_system):
         # msvc does not have a concept of system header dirs.
         return ['-I' + path]
 
-    # Visual Studio is special. It ignores arguments it does not
+    # Visual Studio is special. It ignores some arguments it does not
     # understand and you can't tell it to error out on those.
     # http://stackoverflow.com/questions/15259720/how-can-i-make-the-microsoft-c-compiler-treat-unknown-flags-as-errors-rather-t
     def has_argument(self, arg, env):
@@ -1942,7 +1942,7 @@ def has_argument(self, arg, env):
         mlog.debug('Code:\n', code)
         p, stdo, stde = Popen_safe(commands, cwd=os.path.split(srcname)[0])
         if p.returncode != 0:
-            raise MesonException('Compiling test app failed.')
+            return False
         return not(warning_text in stde or warning_text in stdo)
 
     def get_compile_debugfile_args(self, rel_obj, pch=False):


Test patch:
diff --git a/test cases/common/130 no buildincdir/include/header.h b/test cases/common/130 no buildincdir/include/header.h
new file mode 100644
--- /dev/null
+++ b/test cases/common/130 no buildincdir/include/header.h	
@@ -0,0 +1,3 @@
+#pragma once
+
+int foobar();
diff --git a/test cases/common/130 no buildincdir/meson.build b/test cases/common/130 no buildincdir/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/common/130 no buildincdir/meson.build	
@@ -0,0 +1,14 @@
+project('nobuilddir', 'c',
+  default_options : 'werror=true')
+
+cc = meson.get_compiler('c')
+
+incwarg = '-Wmissing-include-dirs'
+
+if cc.has_argument(incwarg)
+  executable('prog', 'prog.c',
+    c_args : incwarg,
+    include_directories : include_directories('include'))
+else
+  error('MESON_SKIP_TEST compiler does not support bad inc dir argument.')
+endif
diff --git a/test cases/common/130 no buildincdir/prog.c b/test cases/common/130 no buildincdir/prog.c
new file mode 100644
--- /dev/null
+++ b/test cases/common/130 no buildincdir/prog.c	
@@ -0,0 +1,5 @@
+#include"header.h"
+
+int main(int argc, char **argv) {
+    return 0;
+}