Repository: mesonbuild/meson

Issue:
combining multiple static libraries into one
it's not uncommon to create a static library that is a combination of multiple static libraries.
Meaning i have my project dir:
-proj
-- a
-- b
-- c

they result in liba.a, libb.a, libc.a. I want to create a libproj.a that contains all other static libraries.
In autotools it's possible to define a Makefile.am that accomplishes the same task:

liba_la_SOURCES = \ 
a/a.cxx \ 
a/a.h \ 
$(NULL) 

libb_la_SOURCES = \ 
b/b.cxx \ 
b/b.h \ 
$(NULL) 

libc_la_SOURCES = \ 
c/c.h \ 
c/c.cxx \ 
$(NULL) 

libcombo_la_LIBADD = \ 
liba.la \ 
libb.la \ 
libc.la \ 
$(NULL)

I think that an API should be implemented for this target.



Discussion:
You can do the same already like this:

```
a = static_library('a', ...)
b = static_library('b', ...)
c = static_library('c', ...)
```

   combined = [a, b, c]

   exe('foo', ..., link_with : combined)

It's not what I'm trying to achieve.
I want to be able to combine libraries into a combined library.
What you offer is a way to link them into an executable.
I want define this combination once, and every project that consumes my project will be able to use the combined library and have access to all symbols of the underlying libraries.

@jpakkane it's like static_library('lib', objects : combined), but extract_objects() is hell here


Resolving patch:
diff --git a/build.py b/build.py
--- a/build.py
+++ b/build.py
@@ -159,7 +159,9 @@ def __init__(self, name, subdir, is_cross, sources, objects, environment, kwargs
         self.process_objectlist(objects)
         self.process_kwargs(kwargs, environment)
         self.check_unknown_kwargs(kwargs)
-        if len(self.sources) == 0 and len(self.generated) == 0:
+        if len(self.sources) == 0 and \
+            len(self.generated) == 0 and \
+            len(self.objects) == 0:
             raise InvalidArguments('Build target %s has no sources.' % name)
         self.validate_sources()
 
@@ -255,6 +257,9 @@ def extract_objects(self, srcargs):
                 obj_src.append(src)
         return ExtractedObjects(self, obj_src)
 
+    def extract_all_objects(self):
+        return ExtractedObjects(self, self.sources)
+
     def get_rpaths(self):
         return self.get_transitive_rpaths()
 
diff --git a/interpreter.py b/interpreter.py
--- a/interpreter.py
+++ b/interpreter.py
@@ -429,7 +429,8 @@ class BuildTargetHolder(InterpreterObject):
     def __init__(self, target):
         super().__init__()
         self.held_object = target
-        self.methods.update({'extract_objects' : self.extract_objects_method})
+        self.methods.update({'extract_objects' : self.extract_objects_method,
+                             'extract_all_objects' : self.extract_all_objects_method})
 
     def is_cross(self):
         return self.held_object.is_cross()
@@ -438,6 +439,10 @@ def extract_objects_method(self, args, kwargs):
         gobjs = self.held_object.extract_objects(args)
         return GeneratedObjectsHolder(gobjs)
 
+    def extract_all_objects_method(self, args, kwargs):
+        gobjs = self.held_object.extract_all_objects()
+        return GeneratedObjectsHolder(gobjs)
+
 class ExecutableHolder(BuildTargetHolder):
     def __init__(self, target):
         super().__init__(target)


Test patch:
diff --git a/test cases/common/88 extract all/extractor.h b/test cases/common/88 extract all/extractor.h
new file mode 100644
--- /dev/null
+++ b/test cases/common/88 extract all/extractor.h	
@@ -0,0 +1,6 @@
+#pragma once
+
+int func1();
+int func2();
+int func3();
+int func4();
diff --git a/test cases/common/88 extract all/four.c b/test cases/common/88 extract all/four.c
new file mode 100644
--- /dev/null
+++ b/test cases/common/88 extract all/four.c	
@@ -0,0 +1,5 @@
+#include"extractor.h"
+
+int func4() {
+    return 4;
+}
diff --git a/test cases/common/88 extract all/meson.build b/test cases/common/88 extract all/meson.build
new file mode 100644
--- /dev/null
+++ b/test cases/common/88 extract all/meson.build	
@@ -0,0 +1,9 @@
+project('extract all', 'c')
+
+a = static_library('a', 'one.c', 'two.c')
+b = static_library('b', 'three.c', 'four.c')
+c = static_library('c', 
+  objects : [a.extract_all_objects(), b.extract_all_objects()])
+
+e = executable('proggie', 'prog.c', link_with : c)
+test('extall', e)
diff --git a/test cases/common/88 extract all/one.c b/test cases/common/88 extract all/one.c
new file mode 100644
--- /dev/null
+++ b/test cases/common/88 extract all/one.c	
@@ -0,0 +1,5 @@
+#include"extractor.h"
+
+int func1() {
+    return 1;
+}
diff --git a/test cases/common/88 extract all/prog.c b/test cases/common/88 extract all/prog.c
new file mode 100644
--- /dev/null
+++ b/test cases/common/88 extract all/prog.c	
@@ -0,0 +1,10 @@
+#include"extractor.h"
+#include<stdio.h>
+
+int main(int argc, char **argv) {
+    if((1+2+3+4) != (func1() + func2() + func3() + func4())) {
+        printf("Arithmetic is fail.\n");
+        return 1;
+    }
+    return 0;
+}
diff --git a/test cases/common/88 extract all/three.c b/test cases/common/88 extract all/three.c
new file mode 100644
--- /dev/null
+++ b/test cases/common/88 extract all/three.c	
@@ -0,0 +1,5 @@
+#include"extractor.h"
+
+int func3() {
+    return 3;
+}
diff --git a/test cases/common/88 extract all/two.c b/test cases/common/88 extract all/two.c
new file mode 100644
--- /dev/null
+++ b/test cases/common/88 extract all/two.c	
@@ -0,0 +1,5 @@
+#include"extractor.h"
+
+int func2() {
+    return 2;
+}