aboutsummaryrefslogtreecommitdiff
path: root/test cases
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2019-03-06 14:41:00 +0100
committerPaolo Bonzini <pbonzini@redhat.com>2019-05-22 12:09:09 +0200
commitd894c48660a573f257f76fe075e512415fdd0f91 (patch)
treeb077999723cc6724c4ab141334af0cb00577ba91 /test cases
parente9bd7d49bdc8c630cca3bf4cc02c437841b6aaf6 (diff)
downloadmeson-d894c48660a573f257f76fe075e512415fdd0f91.zip
meson-d894c48660a573f257f76fe075e512415fdd0f91.tar.gz
meson-d894c48660a573f257f76fe075e512415fdd0f91.tar.bz2
new module "sourceset" to match source file lists against configuration data
In QEMU a single set of source files is built against many different configurations in order to generate many executable. Each executable includes a different but overlapping subset of the source files; some of the files are compiled separately for each output, others are compiled just once. Using Makefiles, this is achieved with a complicated mechanism involving a combination of non-recursive and recursive make; Meson can do better, but because there are hundreds of such conditional rules, it's important to keep meson.build files brief and easy to follow. Therefore, this commit adds a new module to satisfy this use case while preserving Meson's declarative nature. Configurations are mapped to a configuration_data object, and a new "source set" object is used to store all the rules, and then retrieve the desired set of sources together with their dependencies. The test case shows how extract_objects can be used to satisfy both cases, i.e. when the object files are shared across targets and when they have to be separate. In the real-world case, a project would use two source set objects for the two cases and then do "executable(..., sources: ... , objects: ...)". The next commit adds such an example.
Diffstat (limited to 'test cases')
-rw-r--r--test cases/common/220 source set configuration_data/a.c8
-rw-r--r--test cases/common/220 source set configuration_data/all.h7
-rw-r--r--test cases/common/220 source set configuration_data/f.c5
-rw-r--r--test cases/common/220 source set configuration_data/g.c6
-rw-r--r--test cases/common/220 source set configuration_data/meson.build54
-rw-r--r--test cases/common/220 source set configuration_data/nope.c3
-rw-r--r--test cases/common/220 source set configuration_data/subdir/b.c13
-rw-r--r--test cases/common/220 source set configuration_data/subdir/meson.build1
-rw-r--r--test cases/common/221 source set dictionary/a.c8
-rw-r--r--test cases/common/221 source set dictionary/all.h7
-rw-r--r--test cases/common/221 source set dictionary/f.c5
-rw-r--r--test cases/common/221 source set dictionary/g.c6
-rw-r--r--test cases/common/221 source set dictionary/meson.build56
-rw-r--r--test cases/common/221 source set dictionary/nope.c3
-rw-r--r--test cases/common/221 source set dictionary/subdir/b.c13
-rw-r--r--test cases/common/221 source set dictionary/subdir/meson.build1
-rw-r--r--test cases/common/222 source set custom target/a.c7
-rw-r--r--test cases/common/222 source set custom target/all.h2
-rw-r--r--test cases/common/222 source set custom target/cp.py5
-rw-r--r--test cases/common/222 source set custom target/f.c5
-rw-r--r--test cases/common/222 source set custom target/g.c5
-rw-r--r--test cases/common/222 source set custom target/meson.build28
22 files changed, 248 insertions, 0 deletions
diff --git a/test cases/common/220 source set configuration_data/a.c b/test cases/common/220 source set configuration_data/a.c
new file mode 100644
index 0000000..0570dff
--- /dev/null
+++ b/test cases/common/220 source set configuration_data/a.c
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+#include "all.h"
+
+int main(void)
+{
+ if (p) abort();
+ f();
+}
diff --git a/test cases/common/220 source set configuration_data/all.h b/test cases/common/220 source set configuration_data/all.h
new file mode 100644
index 0000000..728a7f6
--- /dev/null
+++ b/test cases/common/220 source set configuration_data/all.h
@@ -0,0 +1,7 @@
+extern void f(void);
+extern void g(void);
+extern void h(void);
+extern void undefined(void);
+
+/* No extern here to get a common symbol */
+void (*p)(void);
diff --git a/test cases/common/220 source set configuration_data/f.c b/test cases/common/220 source set configuration_data/f.c
new file mode 100644
index 0000000..a50ecda
--- /dev/null
+++ b/test cases/common/220 source set configuration_data/f.c
@@ -0,0 +1,5 @@
+#include "all.h"
+
+void f(void)
+{
+}
diff --git a/test cases/common/220 source set configuration_data/g.c b/test cases/common/220 source set configuration_data/g.c
new file mode 100644
index 0000000..4a6f253
--- /dev/null
+++ b/test cases/common/220 source set configuration_data/g.c
@@ -0,0 +1,6 @@
+#include "all.h"
+
+void g(void)
+{
+ h();
+}
diff --git a/test cases/common/220 source set configuration_data/meson.build b/test cases/common/220 source set configuration_data/meson.build
new file mode 100644
index 0000000..104f39d
--- /dev/null
+++ b/test cases/common/220 source set configuration_data/meson.build
@@ -0,0 +1,54 @@
+project('a', 'c')
+
+good = declare_dependency(link_with: static_library('good', 'g.c'))
+bad = declare_dependency(link_args: 'nonexistent.a')
+not_found = dependency('invalid', required: false)
+
+source_set = import('sourceset')
+
+sources = source_set.source_set()
+sources.add(when: 'YES', if_false: ['nope.c'])
+sources.add(when: 'YES1', if_true: files('a.c'))
+subdir('subdir')
+sources.add(when: 'NO', if_true: 'nope.c', if_false: ['f.c'])
+sources.add(when: 'NO', if_true: bad, if_false: ['f.c'])
+
+sources.add(when: 'YES2', if_true: good)
+
+# dependencies as conditions
+sources.add(when: not_found, if_true: 'nope.c')
+
+# test add_all
+sources2 = source_set.source_set()
+sources2.add(when: 'YES1', if_true: 'nope.c')
+sources.add_all(when: 'NO', if_true: sources2)
+
+# test duplicate items
+sources.add(when: 'YES1', if_true: files('a.c'))
+
+conf1 = configuration_data()
+conf1.set10('YES', true)
+conf1.set10('YES1', true)
+conf1.set10('YES2', false)
+conf1.set10('NO', false)
+result1 = sources.apply(conf1)
+
+conf2 = configuration_data()
+conf2.set10('YES', true)
+conf2.set10('YES1', false)
+conf2.set10('YES2', true)
+conf2.set10('NO', false)
+result2 = sources.apply(conf2)
+
+# Each target will recompile the objects
+executable('first', sources: result1.sources(), dependencies: result1.dependencies())
+executable('second', sources: result2.sources(), dependencies: result2.dependencies())
+
+# All target will use the same object files
+if meson.is_unity()
+ message('Skipping extraction test because this is a Unity build.')
+else
+ all_objs = static_library('all_objs', sources.all_sources())
+ executable('first_via_lib', objects: all_objs.extract_objects(result1.sources()), dependencies: result1.dependencies())
+ executable('second_via_lib', objects: all_objs.extract_objects(result2.sources()), dependencies: result2.dependencies())
+endif
diff --git a/test cases/common/220 source set configuration_data/nope.c b/test cases/common/220 source set configuration_data/nope.c
new file mode 100644
index 0000000..0ce1d3b
--- /dev/null
+++ b/test cases/common/220 source set configuration_data/nope.c
@@ -0,0 +1,3 @@
+#include "all.h"
+
+void (*p)(void) = undefined;
diff --git a/test cases/common/220 source set configuration_data/subdir/b.c b/test cases/common/220 source set configuration_data/subdir/b.c
new file mode 100644
index 0000000..31c3789
--- /dev/null
+++ b/test cases/common/220 source set configuration_data/subdir/b.c
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+#include "all.h"
+
+void h(void)
+{
+}
+
+int main(void)
+{
+ if (p) abort();
+ f();
+ g();
+}
diff --git a/test cases/common/220 source set configuration_data/subdir/meson.build b/test cases/common/220 source set configuration_data/subdir/meson.build
new file mode 100644
index 0000000..b497de5
--- /dev/null
+++ b/test cases/common/220 source set configuration_data/subdir/meson.build
@@ -0,0 +1 @@
+sources.add(when: ['YES2', good], if_true: [ files('b.c') ])
diff --git a/test cases/common/221 source set dictionary/a.c b/test cases/common/221 source set dictionary/a.c
new file mode 100644
index 0000000..0570dff
--- /dev/null
+++ b/test cases/common/221 source set dictionary/a.c
@@ -0,0 +1,8 @@
+#include <stdlib.h>
+#include "all.h"
+
+int main(void)
+{
+ if (p) abort();
+ f();
+}
diff --git a/test cases/common/221 source set dictionary/all.h b/test cases/common/221 source set dictionary/all.h
new file mode 100644
index 0000000..728a7f6
--- /dev/null
+++ b/test cases/common/221 source set dictionary/all.h
@@ -0,0 +1,7 @@
+extern void f(void);
+extern void g(void);
+extern void h(void);
+extern void undefined(void);
+
+/* No extern here to get a common symbol */
+void (*p)(void);
diff --git a/test cases/common/221 source set dictionary/f.c b/test cases/common/221 source set dictionary/f.c
new file mode 100644
index 0000000..a50ecda
--- /dev/null
+++ b/test cases/common/221 source set dictionary/f.c
@@ -0,0 +1,5 @@
+#include "all.h"
+
+void f(void)
+{
+}
diff --git a/test cases/common/221 source set dictionary/g.c b/test cases/common/221 source set dictionary/g.c
new file mode 100644
index 0000000..4a6f253
--- /dev/null
+++ b/test cases/common/221 source set dictionary/g.c
@@ -0,0 +1,6 @@
+#include "all.h"
+
+void g(void)
+{
+ h();
+}
diff --git a/test cases/common/221 source set dictionary/meson.build b/test cases/common/221 source set dictionary/meson.build
new file mode 100644
index 0000000..9a34507
--- /dev/null
+++ b/test cases/common/221 source set dictionary/meson.build
@@ -0,0 +1,56 @@
+project('a', 'c')
+
+good = declare_dependency(link_with: static_library('good', 'g.c'))
+bad = declare_dependency(link_args: 'nonexistent.a')
+not_found = dependency('invalid', required: false)
+
+source_set = import('sourceset')
+
+sources = source_set.source_set()
+sources.add(when: 'YES', if_false: ['nope.c'])
+sources.add(when: 'YES1', if_true: files('a.c'))
+subdir('subdir')
+sources.add(when: 'NO', if_true: 'nope.c', if_false: ['f.c'])
+sources.add(when: 'NO', if_true: bad, if_false: ['f.c'])
+
+sources.add(when: 'YES2', if_true: good)
+
+# dependencies as conditions
+sources.add(when: not_found, if_true: 'nope.c')
+
+# test add_all
+sources2 = source_set.source_set()
+sources2.add(when: 'YES1', if_true: 'nope.c')
+sources.add_all(when: 'NO', if_true: sources2)
+
+# test duplicate items
+sources.add(when: 'YES1', if_true: files('a.c'))
+
+conf1 = {
+ 'YES': true,
+ 'YES1': true,
+ 'YES2': false,
+ 'NO': false,
+}
+result1 = sources.apply(conf1)
+
+conf2 = {
+ 'YES': true,
+ 'YES1': false,
+ 'YES2': true,
+ 'NO': false,
+}
+result2 = sources.apply(conf2)
+
+# Each target will recompile the objects
+executable('first', sources: result1.sources(), dependencies: result1.dependencies())
+executable('second', sources: result2.sources(), dependencies: result2.dependencies())
+
+# All target will use the same object files
+if meson.is_unity()
+ message('Skipping extraction test because this is a Unity build.')
+else
+ all_objs = static_library('all_objs', sources.all_sources())
+ executable('first_via_lib', objects: all_objs.extract_objects(result1.sources()), dependencies: result1.dependencies())
+ executable('second_via_lib', objects: all_objs.extract_objects(result2.sources()), dependencies: result2.dependencies())
+endif
diff --git a/test cases/common/221 source set dictionary/nope.c b/test cases/common/221 source set dictionary/nope.c
new file mode 100644
index 0000000..0ce1d3b
--- /dev/null
+++ b/test cases/common/221 source set dictionary/nope.c
@@ -0,0 +1,3 @@
+#include "all.h"
+
+void (*p)(void) = undefined;
diff --git a/test cases/common/221 source set dictionary/subdir/b.c b/test cases/common/221 source set dictionary/subdir/b.c
new file mode 100644
index 0000000..31c3789
--- /dev/null
+++ b/test cases/common/221 source set dictionary/subdir/b.c
@@ -0,0 +1,13 @@
+#include <stdlib.h>
+#include "all.h"
+
+void h(void)
+{
+}
+
+int main(void)
+{
+ if (p) abort();
+ f();
+ g();
+}
diff --git a/test cases/common/221 source set dictionary/subdir/meson.build b/test cases/common/221 source set dictionary/subdir/meson.build
new file mode 100644
index 0000000..b497de5
--- /dev/null
+++ b/test cases/common/221 source set dictionary/subdir/meson.build
@@ -0,0 +1 @@
+sources.add(when: ['YES2', good], if_true: [ files('b.c') ])
diff --git a/test cases/common/222 source set custom target/a.c b/test cases/common/222 source set custom target/a.c
new file mode 100644
index 0000000..39a3b6b
--- /dev/null
+++ b/test cases/common/222 source set custom target/a.c
@@ -0,0 +1,7 @@
+#include "all.h"
+
+int main(void)
+{
+ f();
+ g();
+}
diff --git a/test cases/common/222 source set custom target/all.h b/test cases/common/222 source set custom target/all.h
new file mode 100644
index 0000000..5885e32
--- /dev/null
+++ b/test cases/common/222 source set custom target/all.h
@@ -0,0 +1,2 @@
+extern void f(void);
+extern void g(void);
diff --git a/test cases/common/222 source set custom target/cp.py b/test cases/common/222 source set custom target/cp.py
new file mode 100644
index 0000000..cb09cf3
--- /dev/null
+++ b/test cases/common/222 source set custom target/cp.py
@@ -0,0 +1,5 @@
+#! /usr/bin/env python3
+
+import sys
+from shutil import copyfile
+copyfile(*sys.argv[1:])
diff --git a/test cases/common/222 source set custom target/f.c b/test cases/common/222 source set custom target/f.c
new file mode 100644
index 0000000..a50ecda
--- /dev/null
+++ b/test cases/common/222 source set custom target/f.c
@@ -0,0 +1,5 @@
+#include "all.h"
+
+void f(void)
+{
+}
diff --git a/test cases/common/222 source set custom target/g.c b/test cases/common/222 source set custom target/g.c
new file mode 100644
index 0000000..7098584
--- /dev/null
+++ b/test cases/common/222 source set custom target/g.c
@@ -0,0 +1,5 @@
+#include "all.h"
+
+void g(void)
+{
+}
diff --git a/test cases/common/222 source set custom target/meson.build b/test cases/common/222 source set custom target/meson.build
new file mode 100644
index 0000000..fe6e6e1
--- /dev/null
+++ b/test cases/common/222 source set custom target/meson.build
@@ -0,0 +1,28 @@
+# Try using sourceset with various kinds of generated sources
+
+project('a', 'c')
+
+cp = find_program('cp.py')
+
+source_set = import('sourceset')
+sources = source_set.source_set()
+
+a_c = custom_target('gen-custom-target',
+ input: 'a.c', output: 'out_a.c',
+ command: [cp, '@INPUT@', '@OUTPUT@'])
+sources.add(when: 'YES', if_true: a_c)
+sources.add(when: 'YES', if_true: a_c[0])
+
+f_c = configure_file(input: 'f.c', output: 'out_f.c', copy: true)
+sources.add(when: 'YES', if_true: f_c)
+sources.add(when: 'YES', if_true: f_c)
+
+gen = generator(cp, output: 'out_@PLAINNAME@', arguments: ['@INPUT@', '@OUTPUT@'])
+g_c = gen.process(files('g.c'))
+sources.add(when: 'YES', if_true: g_c)
+sources.add(when: 'YES', if_true: g_c)
+
+conf1 = { 'YES': true, }
+result1 = sources.apply(conf1)
+
+executable('first', sources: result1.sources(), dependencies: result1.dependencies())