[gtk-mac-bundler] Install gir files in the bundle and recompile typelibs from them.



commit d106f920e5fa415a5747a40d71819ed674d1e74d
Author: John Ralls <jralls ceridwen us>
Date:   Fri Sep 9 15:30:18 2016 -0700

    Install gir files in the bundle and recompile typelibs from them.
    
    GObject-introspection based projects require typelibs for connecting the
    C-based shared libraries with their language bindings. These are
    compiled from GObject-Introspection (.gir) files, in turn made by
    g-ir-scanner. g-ir-scanner embeds the install_name from the library in
    the gir file, normally an absolute path at build time. We need to change
    it to the install_name for the bundle, beginning with @executable_path.
    We do that by importing and modifying the gir files then recompiling
    them.

 bundler/bundler.py       |   42 ++++++++++++++++++++++++++++++++++++++++--
 bundler/project.py       |   16 +++++++++++++++-
 examples/gtk-demo.bundle |   16 ++++++++++++++++
 3 files changed, 71 insertions(+), 3 deletions(-)
---
diff --git a/bundler/bundler.py b/bundler/bundler.py
index fbf728c..e9d435f 100644
--- a/bundler/bundler.py
+++ b/bundler/bundler.py
@@ -523,7 +523,7 @@ class Bundler:
         for theme in themes:
             if theme.icons == IconTheme.ICONS_NONE:
                 continue
-            
+
             for root, dirs, files in os.walk(self.project.evaluate_path(theme.source)):
                 for f in files:
                     (head, tail) = os.path.splitext(f)
@@ -600,10 +600,45 @@ class Bundler:
             for root, trees, files in os.walk(source):
                 for file in filter(name_filter, files):
                     path = os.path.join(root, file)
-                    self.copy_path(Path("${prefix}" + path[len(prefix):], 
+                    self.copy_path(Path("${prefix}" + path[len(prefix):],
                                         program.dest))
 
 
+    def install_gir(self):
+        gir_files = self.project.get_gir()
+        bundle_gir_dir = self.project.get_bundle_path('Contents', 'Resources',
+                                                      'share', 'gir-1.0')
+        bundle_typelib_dir = self.project.get_bundle_path('Contents', 'Resources',
+                                                          'lib', 'girepository-1.0')
+        old_lib_path = os.path.join(self.project.get_prefix(), 'lib')
+        os.makedirs(bundle_gir_dir)
+        os.makedirs(bundle_typelib_dir)
+        import subprocess
+
+        def transform_file(filename):
+            path, fname = os.path.split(filename)
+            name, ext = os.path.splitext(fname)
+
+            with open (filename, "r") as source:
+                lines = source.readlines()
+            newpath = os.path.join(bundle_gir_dir, fname)
+            typelib = os.path.join(bundle_typelib_dir, name + '.typelib')
+            with open (newpath, "w") as target:
+                for line in lines:
+                    target.write(re.sub(old_lib_path,
+                                        '@executable_path/../Resources/lib',
+                                        line))
+            subprocess.call(['g-ir-compiler', '--output=' + typelib, newpath])
+            self.binary_paths.append(typelib)
+
+        for gir in gir_files:
+            filename = self.project.evaluate_path(gir.source)
+            for globbed_source in glob.glob(filename):
+                try:
+                    transform_file(globbed_source)
+                except Exception as err:
+                    print('Error in transformation of %s: %s' % (globbed_source, err))
+
     def run(self):
         # Remove the temp location forcefully.
         path = self.project.evaluate_path(self.bundle_path)
@@ -637,6 +672,9 @@ class Bundler:
         self.copy_binaries(self.project.get_binaries())
         self.resolve_library_dependencies()
 
+        # Gir and Typelibs
+        self.install_gir()
+
         # Data
         for path in self.project.get_data():
             self.copy_path(path)
diff --git a/bundler/project.py b/bundler/project.py
index c130f97..581f8a4 100644
--- a/bundler/project.py
+++ b/bundler/project.py
@@ -178,7 +178,14 @@ class Translation(Path):
     from_node = classmethod(from_node)
 
 
-        
+class GirFile(Path):
+    def __init__(self, sourcepath, destpath):
+        Path.__init__(self, sourcepath, destpath)
+
+    def from_node(cls, node):
+        gir = Path.from_node(node)
+        return GirFile(gir.source, gir.dest)
+    from_node = classmethod(from_node)
 
 class Data(Path):
     pass
@@ -382,6 +389,13 @@ class Project:
             translations.append(Translation.from_node(node))
         return translations
 
+    def get_gir(self):
+        gir_files = []
+        nodes = utils.node_get_elements_by_tag_name(self.root, "gir")
+        for node in nodes:
+            gir_files.append(GirFile.from_node(node))
+        return gir_files
+
     def get_main_binary(self):
         node = utils.node_get_element_by_tag_name(self.root, "main-binary")
         if not node:
diff --git a/examples/gtk-demo.bundle b/examples/gtk-demo.bundle
index fbed947..96c7bc6 100644
--- a/examples/gtk-demo.bundle
+++ b/examples/gtk-demo.bundle
@@ -88,6 +88,22 @@
   </binary>
 -->
 
+<!-- GObject-introspection based projects require typelibs for
+     connecting the C-based shared libraries with their language
+     bindings. These are compiled from GObject-Introspection (.gir)
+     files, in turn made by g-ir-scanner. g-ir-scanner embeds the
+     install_name from the library in the gir file, normally an
+     absolute path at build time. We need to change it to the
+     install_name for the bundle, beginning with @executable_path. We
+     do that by importing and modifying the gir files then recompiling
+     them. It's possible to specify only the gir files you need but in
+     most serious programs that works out to a rather long list so
+     it's better to just use a wildcard.
+     <gir>
+       ${prefix}/share/gir-1.0/*.gir
+     </gir>
+     -->
+
   <data>
     ${prefix}/etc/pango/
   </data>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]