Repository: mesonbuild/meson

Issue:
build_always: false does not match the 0.46.1 behaviour
Specifying `build_always: false` and `build_by_default: true` on the same target seems to suppress the later. Targets declared as such are therefore never built unless something depends on them (but if you are using `build_by_default`, then chances are nothing does). ~~I suspect it also affects `build_always_stale: true` in the same way, but I have not tested that yet.~~ 

`build_always` must have lower priority than the other two for compatibility with older Meson releases. In addition, please don't be too trigger happy with deprecation warnings. As it stands, it is impossible to avoid the warning in meson git without also breaking compatibility with every current stable release, even if this bug is fixed.


Discussion:

Resolving patch:
diff --git a/mesonbuild/build.py b/mesonbuild/build.py
--- a/mesonbuild/build.py
+++ b/mesonbuild/build.py
@@ -1793,7 +1793,8 @@ def process_kwargs(self, kwargs):
             raise InvalidArguments('build_always and build_always_stale are mutually exclusive. Combine build_by_default and build_always_stale.')
         elif 'build_always' in kwargs:
             mlog.warning('build_always is deprecated. Combine build_by_default and build_always_stale instead.')
-            self.build_by_default = kwargs['build_always']
+            if 'build_by_default' not in kwargs:
+                self.build_by_default = kwargs['build_always']
             self.build_always_stale = kwargs['build_always']
         elif 'build_always_stale' in kwargs:
             self.build_always_stale = kwargs['build_always_stale']
diff --git a/run_unittests.py b/run_unittests.py
--- a/run_unittests.py
+++ b/run_unittests.py
@@ -1122,12 +1122,18 @@ def test_build_by_default(self):
         testdir = os.path.join(self.common_test_dir, '137 build by default')
         self.init(testdir)
         self.build()
-        genfile = os.path.join(self.builddir, 'generated.dat')
-        exe = os.path.join(self.builddir, 'fooprog' + exe_suffix)
-        self.assertPathExists(genfile)
-        self.assertPathDoesNotExist(exe)
+        genfile1 = os.path.join(self.builddir, 'generated1.dat')
+        genfile2 = os.path.join(self.builddir, 'generated2.dat')
+        exe1 = os.path.join(self.builddir, 'fooprog' + exe_suffix)
+        exe2 = os.path.join(self.builddir, 'barprog' + exe_suffix)
+        self.assertPathExists(genfile1)
+        self.assertPathExists(genfile2)
+        self.assertPathDoesNotExist(exe1)
+        self.assertPathDoesNotExist(exe2)
         self.build(target=('fooprog' + exe_suffix))
-        self.assertPathExists(exe)
+        self.assertPathExists(exe1)
+        self.build(target=('barprog' + exe_suffix))
+        self.assertPathExists(exe2)
 
     def test_internal_include_order(self):
         testdir = os.path.join(self.common_test_dir, '138 include order')


Test patch:
diff --git a/test cases/common/137 build by default/checkexists.py b/test cases/common/137 build by default/checkexists.py
new file mode 100644
--- /dev/null
+++ b/test cases/common/137 build by default/checkexists.py	
@@ -0,0 +1,10 @@
+#!/usr/bin/env python3
+
+import os.path, sys
+
+invert = False
+for path in sys.argv[1:]:
+    if path == '--not':
+        invert = True
+    elif not os.path.exists(path) ^ invert:
+        sys.exit(1)
diff --git a/test cases/common/137 build by default/meson.build b/test cases/common/137 build by default/meson.build
--- a/test cases/common/137 build by default/meson.build	
+++ b/test cases/common/137 build by default/meson.build	
@@ -3,22 +3,43 @@ project('build on all', 'c')
 py3_mod = import('python3')
 py3 = py3_mod.find_python()
 
-executable('fooprog', 'foo.c', build_by_default : false)
+executable('fooprog', 'foo.c',
+    build_by_default : false,
+)
+
+executable('barprog', 'foo.c',
+    build_by_default : false,
+    build_always : true,
+)
+
 comp = files('mygen.py')
-mytarget = custom_target('gendat',
-  output : 'generated.dat',
+checkexists = files('checkexists.py')
+
+mytarget = custom_target('gendat1',
+  output : 'generated1.dat',
+  input : 'source.txt',
+  command : [py3] + comp + ['@INPUT@', '@OUTPUT@'],
+  build_by_default : true,
+)
+
+mytarget = custom_target('gendat2',
+  output : 'generated2.dat',
   input : 'source.txt',
   command : [py3] + comp + ['@INPUT@', '@OUTPUT@'],
   build_by_default : true,
+  build_always : false,
 )
 
-ct_output = join_paths(meson.build_root(), 'generated.dat')
-exe_output = join_paths(meson.build_root(), 'fooprog')
+ct1_output = join_paths(meson.build_root(), 'generated1.dat')
+ct2_output = join_paths(meson.build_root(), 'generated2.dat')
+exe1_output = join_paths(meson.build_root(), 'fooprog')
+exe2_output = join_paths(meson.build_root(), 'barprog')
+
 if host_machine.system() == 'windows'
-  exe_output += '.exe'
+  exe1_output += '.exe'
+  exe2_output += '.exe'
 endif
 
-ct_exists_exe_nexists = 'import os.path, sys; sys.exit(not os.path.exists(sys.argv[1]) and os.path.exists(sys.argv[2]))'
-
 test('check-build-by-default', py3,
-     args : ['-c', ct_exists_exe_nexists, ct_output, exe_output])
+     args : [checkexists,
+        ct1_output, ct2_output, '--not', exe1_output, exe2_output])