adding osx application bundler scripts
authorFriedrich Beckmann <friedrich.beckmann@gmx.de>
Sun, 22 May 2016 21:01:37 +0000 (23:01 +0200)
committerFriedrich Beckmann <friedrich.beckmann@gmx.de>
Sun, 22 May 2016 21:01:37 +0000 (23:01 +0200)
This adds a utility script which produces a mac application bundle
based on the macports installation of pspp. The application bundle
can then be distributed as a single file and can be installed exactly
like a usual mac application. This is easier for mac users as they
do not need to install XCode, macports, XQuartz but just this package.

utilities/osxbundler/Info-pspp.plist [new file with mode: 0644]
utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/Portfile [new file with mode: 0644]
utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-0.7.4-to-24Feb2016.diff [new file with mode: 0644]
utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-bundler_py.diff [new file with mode: 0644]
utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-gtk3-demo-bundle.diff [new file with mode: 0644]
utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-gtk3-launcher.diff [new file with mode: 0644]
utilities/osxbundler/macports-custom-packages/pspp/Portfile [new file with mode: 0644]
utilities/osxbundler/macports-custom-packages/pspp/files/PSPP [new file with mode: 0644]
utilities/osxbundler/macports-custom-packages/pspp/files/logo.png [new file with mode: 0644]
utilities/osxbundler/makeosxbundle.sh [new file with mode: 0755]
utilities/osxbundler/pspp.bundle [new file with mode: 0644]

diff --git a/utilities/osxbundler/Info-pspp.plist b/utilities/osxbundler/Info-pspp.plist
new file mode 100644 (file)
index 0000000..6e6a6bf
--- /dev/null
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+    <key>CFBundleDevelopmentRegion</key>
+    <string>English</string>
+    <key>CFBundleExecutable</key>
+    <string>pspp</string>
+    <key>CFBundleGetInfoString</key>
+    <string>0.10.1, (C) 1997-2016 http://savannah.gnu.org/projects/pspp</string>
+    <key>CFBundleIconFile</key>
+    <string>pspp.icns</string>
+    <key>CFBundleIdentifier</key>
+    <string>org.gtk.pspp</string>
+    <key>CFBundleInfoDictionaryVersion</key>
+    <string>6.0</string>
+    <key>CFBundlePackageType</key>
+    <string>APPL</string>
+    <key>CFBundleShortVersionString</key>
+    <string>0.10.1</string>
+    <key>CFBundleSignature</key>
+    <string>????</string>
+    <key>CFBundleVersion</key>
+    <string>0.10.1</string>
+    <key>NSHumanReadableCopyright</key>
+    <string>Copyright 1997 - 2016 Free Software Foundation, GNU General Public License.</string>
+    <key>LSMinimumSystemVersion</key>
+    <string>10.9</string>
+</dict>
+</plist>
diff --git a/utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/Portfile b/utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/Portfile
new file mode 100644 (file)
index 0000000..cba6b35
--- /dev/null
@@ -0,0 +1,57 @@
+# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
+# $Id: Portfile 118061 2014-03-20 17:21:11Z ryandesign@macports.org $
+
+PortSystem          1.0
+PortGroup           github 1.0
+
+github.setup        jralls gtk-mac-bundler 0.7.4 bundler-
+categories          devel
+license             GPL-2
+platforms           darwin
+maintainers         gmail.com:gellule.xg \
+                    openmaintainer
+supported_archs     noarch
+
+description         Mac OS X application bundle utility
+long_description    A utility that aids in the creation of Mac OS X \
+                    application bundles. The gtk3-demo example is \
+                    patched in macports to produce a the gtk3-demo \
+                    without jhbuild environment. To test the demo run \
+                    gtk-mac-bundler <prefix>/share/gtk-mac-bundler/examples/gtk3-demo.bundle \
+                    This will create the GtkDemo bundle in ~/Desktop 
+
+#-------
+# CHECKSUM
+#---------
+checksums           rmd160  aeff015024a918ffa4e190d14a65e711ab331014 \
+                    sha256  6b67916e48e4e75e677732333060581996ed8759fa9e506a4684db2752d63eb7
+
+#---------
+# PATCHING
+#---------
+#Note: patch-0.7.4-to-24Feb2016.diff brings 0.7.4 to the commit dated 2016/02/24 - Remove after update
+patchfiles          patch-0.7.4-to-24Feb2016.diff \
+                    patch-bundler_py.diff \
+                    patch-gtk3-demo-bundle.diff \
+                    patch-gtk3-launcher.diff
+
+#---------------------------
+# CONFIGURATION AND BUILDING
+#---------------------------
+use_configure       no
+
+build {}
+
+#-----------
+# DEPLOYMENT
+#-----------
+pre-destroot {
+    reinplace "s|/usr/bin/env python|${prefix}/bin/python2.7|g" ${worksrcpath}/gtk-mac-bundler.in
+    reinplace "s|@PATH@|${frameworks_dir}/Python.framework/Version/2.7/lib/site-packages|g" ${worksrcpath}/gtk-mac-bundler.in
+    reinplace "s|\${env:JHBUILD_PREFIX}|${prefix}|g" ${worksrcpath}/examples/gtk3-demo.bundle
+    xinstall -m 755 -d ${destroot}${frameworks_dir}/Python.framework/Versions/2.7/lib/python2.7
+    copy ${worksrcpath}/bundler ${destroot}${frameworks_dir}/Python.framework/Versions/2.7/lib/python2.7/
+    file mkdir ${destroot}${prefix}/share/${name}
+    copy ${worksrcpath}/examples ${destroot}${prefix}/share/${name}
+}
+destroot.args       bindir=${destroot}${prefix}/bin
diff --git a/utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-0.7.4-to-24Feb2016.diff b/utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-0.7.4-to-24Feb2016.diff
new file mode 100644 (file)
index 0000000..511a93c
--- /dev/null
@@ -0,0 +1,707 @@
+diff --git Changelog Changelog
+index 07dfe16..47bbfef 100644
+--- Changelog
++++ Changelog
+@@ -1,5 +1,21 @@
+ Changes in version 0.7.4:
++ - Release gtk-mac-bundler 0.7.4 (John Ralls)
++ - Make sure to check for .symbolic icon extension (Jesse van den Kieboom)
++ - Fix pixbuf loader cache path (Jesse van den Kieboom)
++ - Make sure that libraries are writeable before using otool. (Julien Woillez)
++ - Update doap to reflect correct bug tracker. (John Ralls)
++ - Bug 698196: Fix typo (John Ralls)
++ - Bug #698916: Update versions, fix pixbuf (John Ralls)
++ - Update all launchers to reflect new pango environment variables (John Ralls)
++ - launcher: Update for pango changes (Dave Vasilevsky)
++ - Correct gdk-pixbuf path in the pygtk example (John Ralls)
++ - Bring example bundle files and launchers up to date (John Ralls)
++ - The *correct* fix for pango modules. (John Ralls)
++ - Fix another typo in pango module path (John Ralls)
++
++Changes in version 0.7.4:
++
+  - Make sure to check for .symbolic icon extension (Jesse van den Kieboom)
+  - Fix pixbuf loader cache path (Jesse van den Kieboom)
+  - Make sure that libraries are writeable before using otool. (Julien Woillez)
+diff --git bundler/bundler.py bundler/bundler.py
+index 8061ac1..65b8cc0 100644
+--- bundler/bundler.py
++++ bundler/bundler.py
+@@ -1,12 +1,12 @@
+ import sys
+ import os, errno, glob
+-import dircache, shutil
++import shutil
+ import re
+ from plistlib import Plist
+ from distutils import dir_util, file_util
+-from project import *
+-import utils
++from .project import *
++from . import utils
+ class Bundler:
+     def __init__(self, project):
+@@ -32,13 +32,13 @@ class Bundler:
+     def recursive_rm(self, dirname):
+         # Extra safety ;)
+         if dirname in [ "/", os.getenv("HOME"), os.path.join(os.getenv("HOME"), "Desktop"), self.meta.dest ]:
+-            print "Eek, trying to remove a bit much, eh? (%s)" % (dirname)
++            print("Eek, trying to remove a bit much, eh? (%s)" % (dirname))
+             sys.exit(1)
+         if not os.path.exists(dirname):
+             return
+         
+-        files = dircache.listdir(dirname)
++        files = os.listdir(dirname)
+         for file in files:
+             path = os.path.join (dirname, file)
+             if os.path.isdir(path):
+@@ -68,6 +68,12 @@ class Bundler:
+         self.copy_path(path)
+     def create_pango_setup(self):
++        if utils.has_pkgconfig_module("pango") and \
++                not utils.has_pkgconfig_variable("pango", "pango_module_version"):
++            # Newer pango (>= 1.38) no longer has modules, skip this
++            # step in that case.
++            return
++
+         # Create a temporary pangorc file just for creating the
+         # modules file with the right modules.
+         module_version = utils.evaluate_pkgconfig_variables("${pkg:pango:pango_module_version}")
+@@ -227,7 +233,7 @@ class Bundler:
+             # Clean out any libtool (*.la) files and static libraries
+             if os.path.isdir(dest):
+                 for root, dirs, files in os.walk(dest):
+-                    for name in filter(lambda l: l.endswith(".la") or l.endswith(".a"), files):
++                    for name in [l for l in files if l.endswith(".la") or l.endswith(".a")]:
+                         os.remove(os.path.join(root, name))
+     # Copies from Path.source to Path.dest, evaluating any variables
+@@ -247,7 +253,7 @@ class Bundler:
+                 relative_dest = self.project.evaluate_path(Path.source[m.end():])
+                 dest = self.project.get_bundle_path("Contents/Resources", relative_dest)
+             else:
+-                print "Invalid bundle file, missing or invalid 'dest' property: " + Path.dest
++                print("Invalid bundle file, missing or invalid 'dest' property: " + Path.dest)
+                 sys.exit(1)
+         (dest_parent, dest_tail) = os.path.split(dest)
+@@ -257,7 +263,7 @@ class Bundler:
+         p = re.compile("[\*\?]")
+         (source_parent, source_tail) = os.path.split(source)
+         if p.search(source_parent):
+-            print "Can't have wildcards except in the last path component: " + source
++            print("Can't have wildcards except in the last path component: " + source)
+             sys.exit(1)
+         if p.search(source_tail):
+@@ -267,7 +273,7 @@ class Bundler:
+         else:
+             source_check = source
+         if not os.path.exists(source_check):
+-            print "Cannot find source to copy: " + source
++            print("Cannot find source to copy: " + source)
+             sys.exit(1)
+         # If the destination has a wildcard as last component (copied
+@@ -285,13 +291,13 @@ class Bundler:
+                     try:
+ #                        print "Copying %s to %s" % (globbed_source, destdir)
+                         shutil.copy(globbed_source, destdir)
+-                    except EnvironmentError, e:
++                    except EnvironmentError as e:
+                         if e.errno == errno.ENOENT:
+-                            print "Warning, source file missing: " + globbed_source
++                            print("Warning, source file missing: " + globbed_source)
+                         elif e.errno == errno.EEXIST:
+-                            print "Warning, path already exits: " + dest
++                            print("Warning, path already exits: " + dest)
+                         else:
+-                            print "Error %s when copying file: %s" % ( str(e), globbed_source )
++                            print("Error %s when copying file: %s" % ( str(e), globbed_source ))
+                             sys.exit(1)
+         else:
+@@ -315,13 +321,13 @@ class Bundler:
+                                             link=None,
+                                             verbose=1,
+                                             dry_run=0)
+-                except EnvironmentError, e:
++                except EnvironmentError as e:
+                     if e.errno == errno.ENOENT:
+-                        print "Warning, source file missing: " + globbed_source
++                        print("Warning, source file missing: " + globbed_source)
+                     elif e.errno == errno.EEXIST:
+-                        print "Warning, path already exits: " + dest
++                        print("Warning, path already exits: " + dest)
+                     else:
+-                        print "Error %s when copying file: %s" %( str(e), globbed_source )
++                        print("Error %s when copying file: %s" %( str(e), globbed_source ))
+                         sys.exit(1)
+         return dest
+@@ -338,11 +344,11 @@ class Bundler:
+         for path in self.binary_paths:
+             if os.path.isdir(path):
+                 for root, dirs, files in os.walk(path):
+-                    paths.extend(map(lambda l: os.path.join(root, l), files))
++                    paths.extend([os.path.join(root, l) for l in files])
+             else:
+                 paths.append(path)
+-        paths = filter(filter_path, paths)
++        paths = list(filter(filter_path, paths))
+         return list(set(paths))
+     def resolve_library_dependencies(self):
+@@ -366,11 +372,11 @@ class Bundler:
+             def relative_path_map(line):
+                 if not os.path.isabs(line):
+-                    for prefix in prefixes.values():
++                    for prefix in list(prefixes.values()):
+                         path = os.path.join(prefix, "lib", line)
+                         if os.path.exists(path):
+                             return path
+-                    print "Cannot find a matching prefix for %s" % (line)
++                    print("Cannot find a matching prefix for %s" % (line))
+                 return line
+             def prefix_filter(line):
+@@ -378,24 +384,24 @@ class Bundler:
+                     return False
+                 if line.startswith("/usr/X11"):
+-                    print "Warning, found X11 library dependency, you most likely don't want that:", line.strip().split()[0]
++                    print("Warning, found X11 library dependency, you most likely don't want that:", line.strip().split()[0])
+                 if os.path.isabs(line):
+-                    for prefix in prefixes.values():
++                    for prefix in list(prefixes.values()):
+                         if prefix in line:
+                             return True
+                     
+                     if not line.startswith("/usr/lib") and not line.startswith("/System/Library"):
+-                        print "Warning, library not available in any prefix:", line.strip().split()[0]
++                        print("Warning, library not available in any prefix:", line.strip().split()[0])
+                     return False
+                 return True
+-            lines = filter(prefix_filter, [line.strip() for line in f])
++            lines = list(filter(prefix_filter, [line.strip() for line in f]))
+             p = re.compile("(.*\.dylib\.?.*)\s\(compatibility.*$")
+             lines = utils.filterlines(p, lines)
+-            lines = map(relative_path_map, lines)
++            lines = list(map(relative_path_map, lines))
+ #When you need to track down errors, uncomment this blocK
+ #            for path in paths:
+ #                cmd = "otool -L %s" % path
+@@ -407,7 +413,7 @@ class Bundler:
+             for library in set(lines):
+                 # Replace the real path with the right prefix so we can
+                 # create a Path object.
+-                for (key, value) in prefixes.items():
++                for (key, value) in list(prefixes.items()):
+                     if library.startswith(value):
+                         path = Path("${prefix:" + key + "}" + library[len(value):])
+                         new_libraries.append(path)
+@@ -415,14 +421,14 @@ class Bundler:
+             n_paths = len(paths)
+             n_iterations += 1
+             if n_iterations > 10:
+-                print "Too many tries to resolve library dependencies"
++                print("Too many tries to resolve library dependencies")
+                 sys.exit(1)
+             
+             self.copy_binaries(new_libraries)
+             paths = self.list_copied_binaries()
+     def run_install_name_tool(self):
+-        print "Running install name tool"
++        print("Running install name tool")
+         paths = self.list_copied_binaries()
+         prefixes = self.meta.prefixes
+@@ -430,12 +436,12 @@ class Bundler:
+         # First change all references in libraries.
+         for prefix in prefixes:
+             prefix_path = self.project.get_prefix(prefix)
+-            print "Going through prefix: " + prefix_path
++            print("Going through prefix: " + prefix_path)
+             for path in paths:
+                 cmd = os.path.join(os.path.dirname(__file__), "run-install-name-tool-change.sh") + " " + path + " " + prefix_path + " Resources" + " change"
+                 f = os.popen(cmd)
+                 for line in f:
+-                    print line
++                    print(line)
+         # Then change the id of all libraries. Skipping this part for now
+         #for path in paths:
+@@ -448,18 +454,18 @@ class Bundler:
+         for framework in self.frameworks:
+             fw_name, ext = os.path.splitext(os.path.basename(framework))
+             fwl = os.path.join(framework, fw_name)
+-            print "Importing Framework: " + fwl
++            print("Importing Framework: " + fwl)
+ # Fix the framework IDs
+             cmd = os.path.join(os.path.dirname(__file__), "run-install-name-tool-change.sh") + " " + fwl + " " + fw_name + " Frameworks" + " id"
+             f = os.popen(cmd)
+             for line in f:
+-                print line
++                print(line)
+ # Fix the dependencies in other libraries
+             for path in paths:
+                 cmd = os.path.join(os.path.dirname(__file__), "run-install-name-tool-change.sh") + " " + path + " " + fw_name + " Frameworks/" + fw_name + " change"
+                 f = os.popen(cmd)
+                 for line in f:
+-                    print line
++                    print(line)
+ #fix the dependencies in frameworks
+             for ufw in self.frameworks:
+                 ufw_name, ext = os.path.splitext(os.path.basename(ufw))
+@@ -469,20 +475,20 @@ class Bundler:
+                 cmd = os.path.join(os.path.dirname(__file__), "run-install-name-tool-change.sh") + " " + ufwl + " " + fw_name + " Frameworks/" + fw_name + " change"
+                 f = os.popen(cmd)
+                 for line in f:
+-                    print line
++                    print(line)
+     def strip_debugging(self):
+         paths = self.list_copied_binaries()
+         for path in paths:
+             if path.endswith(".dylib") or path.endswith(".so"):
+-                os.chmod(path, 0644)
++                os.chmod(path, 0o644)
+                 os.system("strip -x " + path + " 2>/dev/null")
+-                os.chmod(path, 0444)
++                os.chmod(path, 0o444)
+             else:
+-                os.chmod(path, 0755)
++                os.chmod(path, 0o755)
+                 os.system("strip -ur " + path + " 2>/dev/null")
+-                os.chmod(path, 0555)
++                os.chmod(path, 0o555)
+ #
+ # If you want to sign your application, set $APPLICATION_CERT with the
+@@ -491,7 +497,7 @@ class Bundler:
+ # bundle's id string.
+ #
+     def sign_binaries(self):
+-        if not os.environ.has_key("APPLICATION_CERT"):
++        if "APPLICATION_CERT" not in os.environ:
+             return
+         cert = os.getenv("APPLICATION_CERT")
+         paths = self.list_copied_binaries()
+@@ -501,7 +507,7 @@ class Bundler:
+             result = os.spawnvp(os.P_WAIT, 'codesign', cmdargs)
+             if result:
+-                raise OSError, '"' + " ".join(cmdargs) + '" failed %d' % result
++                raise OSError('"' + " ".join(cmdargs) + '" failed %d' % result)
+     def copy_icon_themes(self):
+         all_icons = set()
+@@ -604,7 +610,7 @@ class Bundler:
+         final_path = self.project.evaluate_path(final_path)
+         if not self.meta.overwrite and os.path.exists(final_path):
+-            print "Bundle already exists: " + final_path
++            print("Bundle already exists: " + final_path)
+             sys.exit(1)
+         self.create_skeleton()
+@@ -618,7 +624,7 @@ class Bundler:
+         path = self.project.get_main_binary()
+         source = self.project.evaluate_path(path.source)
+         if not os.path.exists(source):
+-            print "Cannot find main binary: " + source
++            print("Cannot find main binary: " + source)
+             sys.exit(1)
+         dest = self.copy_path(path)
+@@ -658,24 +664,24 @@ class Bundler:
+         launcher_script = self.project.get_launcher_script()
+         if launcher_script:
+             path = self.copy_path(launcher_script)
+-            if os.environ.has_key("APPLICATION_CERT"):
++            if "APPLICATION_CERT" in os.environ:
+                 cert = os.environ["APPLICATION_CERT"]
+                 ident = self.project.get_bundle_id()
+                 cmdargs = ['codesign', '-s', cert, '-i', ident, "-f", path]
+                 result = os.spawnvp(os.P_WAIT, 'codesign', cmdargs)
+                 if result:
+-                    raise OSError, '"'+ " ".join(cmdargs) + '" failed %d' % result
++                    raise OSError('"'+ " ".join(cmdargs) + '" failed %d' % result)
+         if self.meta.overwrite:
+             self.recursive_rm(final_path)
+         shutil.move(self.project.get_bundle_path(), final_path)
+ if __name__ == '__main__':
+     if len(sys.argv) != 2:
+-        print "Usage: %s <bundle descriptopn file>" % (sys.argv[0])
++        print("Usage: %s <bundle descriptopn file>" % (sys.argv[0]))
+         sys.exit(2)
+     if not os.path.exists(sys.argv[1]):
+-        print "File %s does not exist" % (sys.argv[1])
++        print("File %s does not exist" % (sys.argv[1]))
+         sys.exit(2)
+     project = Project(sys.argv[1])
+diff --git bundler/main.py bundler/main.py
+index bcd7dda..b9b2fc5 100644
+--- bundler/main.py
++++ bundler/main.py
+@@ -1,18 +1,20 @@
+ import sys, os
+-from project import *
+-from bundler import *
++from .project import *
++from .bundler import *
+ def main(argv):
+     if len(argv) != 1:
+-        print "Usage: %s <bundle descriptopn file>" % (sys.argv[0])
++        print("Usage: %s <bundle descriptopn file>" % (sys.argv[0]))
+         sys.exit(2)
+     if not os.path.exists(argv[0]):
+-        print "File %s does not exist" % (argv[0])
++        print("File %s does not exist" % (argv[0]))
+         sys.exit(2)
+     project = Project(argv[0])
+     bundler = Bundler(project)
+-
+-    bundler.run()
++    try:
++        bundler.run()
++    except Exception as err:
++        print("Bundler encountered an error %s" % str(err))
+diff --git bundler/project.py bundler/project.py
+index c98b65a..60f0541 100644
+--- bundler/project.py
++++ bundler/project.py
+@@ -5,7 +5,7 @@ import os
+ import xml.dom.minidom
+ from xml.dom.minidom import Node
+ from plistlib import Plist
+-import utils
++from . import utils
+ # Base class for anything that can be copied into a bundle with a
+ # source and dest.
+@@ -184,7 +184,7 @@ class Data(Path):
+     pass
+ class IconTheme:
+-    ICONS_NONE, ICONS_ALL, ICONS_AUTO = range(3)
++    ICONS_NONE, ICONS_ALL, ICONS_AUTO = list(range(3))
+     
+     def __init__(self, name, icons=ICONS_AUTO):
+         self.name = name
+@@ -221,7 +221,7 @@ class Project:
+                 # Get the first app-bundle tag and ignore any others.
+                 self.root = utils.node_get_element_by_tag_name(doc, "app-bundle")
+             except:
+-                print "Could not load project %s:" % (project_path)
++                print("Could not load project %s:" % (project_path))
+                 raise
+         # The directory the project file is in (as opposed to
+@@ -232,14 +232,14 @@ class Project:
+         plist_path = self.get_plist_path()
+         try:
+             plist = Plist.fromFile(plist_path)
+-        except EnvironmentError, e:
++        except EnvironmentError as e:
+             if e.errno == errno.ENOENT:
+-                print "Info.plist file not found: " + plist_path
++                print("Info.plist file not found: " + plist_path)
+                 sys.exit(1)
+             else:
+                 raise
+         self.name = plist.CFBundleExecutable
+-        if plist.has_key("CFBundleName"):
++        if "CFBundleName" in plist:
+             self.bundle_name = plist.CFBundleName
+         else:
+             self.bundle_name = plist.CFBundleExecutable
+@@ -340,7 +340,7 @@ class Project:
+             themes.append(IconTheme.from_node(node))
+         # The hicolor theme is mandatory.
+-        if not filter(lambda l: l.name == "hicolor", themes):
++        if not [l for l in themes if l.name == "hicolor"]:
+             themes.append(IconTheme("hicolor"))
+         return themes
+@@ -412,33 +412,33 @@ class Project:
+ if __name__ == '__main__':
+     project = Project(os.path.join(os.getcwd(), 'giggle.bundle'))
+-    print "General:"
+-    print "  Project path: %s" % (project.get_project_path())
+-    print "  Plist path: %s" % (project.get_plist_path())
+-    print "  App name: %s" % (project.name)
+-    print "  Destination: %s" % (project.get_meta().dest)
+-    print "  Overwrite: %s" % (str(project.get_meta().overwrite))
++    print("General:")
++    print("  Project path: %s" % (project.get_project_path()))
++    print("  Plist path: %s" % (project.get_plist_path()))
++    print("  App name: %s" % (project.name))
++    print("  Destination: %s" % (project.get_meta().dest))
++    print("  Overwrite: %s" % (str(project.get_meta().overwrite)))
+     environment = project.get_environment()
+-    print "Environment:"
++    print("Environment:")
+     for variable in environment.runtime_variables:
+-        print "  %s=%s" % (variable.name, variable.value)
++        print("  %s=%s" % (variable.name, variable.value))
+     for script in environment.scripts:
+-        print "  %s => %s" % (script.source, script.dest)
++        print("  %s => %s" % (script.source, script.dest))
+-    print "Frameworks:"
++    print("Frameworks:")
+     for framework in project.get_frameworks():
+-        print " ", framework
++        print(" ", framework)
+-    print "Main binary:"
++    print("Main binary:")
+     binary = project.get_main_binary()
+-    print "  %s => %s" % (binary.source, binary.dest)
++    print("  %s => %s" % (binary.source, binary.dest))
+-    print "Launcher:"
++    print("Launcher:")
+     launcher_script = project.get_launcher_script()
+-    print "  %s => %s" % (launcher_script.source, launcher_script.dest)
++    print("  %s => %s" % (launcher_script.source, launcher_script.dest))
+-    print "Binaries:"
++    print("Binaries:")
+     for binary in project.get_binaries():
+-        print "  %s => %s" % (binary.source, binary.dest)
++        print("  %s => %s" % (binary.source, binary.dest))
+diff --git bundler/project_test.py bundler/project_test.py
+index 4c3d583..0ff9179 100644
+--- bundler/project_test.py
++++ bundler/project_test.py
+@@ -5,8 +5,8 @@ import unittest
+ import xml.dom.minidom
+ from xml.dom.minidom import Node
+ from plistlib import Plist
+-from project import Project
+-import utils
++from .project import Project
++from . import utils
+ class Mock_Project(Project):
+@@ -20,9 +20,9 @@ class Mock_Project(Project):
+         try:
+             plist_path = os.path.join(self.project_dir, "test.plist")
+             plist = Plist.fromFile(plist_path)
+-        except EnvironmentError, e:
++        except EnvironmentError as e:
+             if e.errno == errno.ENOENT:
+-                print "Info.plist file not found: " + plist_path
++                print("Info.plist file not found: " + plist_path)
+                 sys.exit(1)
+             else:
+                 raise
+diff --git bundler/runtest.py bundler/runtest.py
+index 309643a..2450f2d 100755
+--- bundler/runtest.py
++++ bundler/runtest.py
+@@ -1,7 +1,7 @@
+ #!/usr/bin/python
+ import unittest
+ import os
+-from project_test import Project_Test
++from .project_test import Project_Test
+ def setProjects( goodpath, badpath):
+     if not os.path.isabs(goodpath):
+diff --git bundler/utils.py bundler/utils.py
+index 78d4c47..76c83d1 100644
+--- bundler/utils.py
++++ bundler/utils.py
+@@ -15,6 +15,21 @@ def evaluate_environment_variables(string):
+     return string
++def has_pkgconfig_module(module):
++    """Returns True if the pkg-config module exists"""
++    f = os.popen("pkg-config --exists " + module)
++    f.read().strip()
++    return f.close() is None
++
++def has_pkgconfig_variable(module, key):
++    """Returns True if the pkg-config variable exists for the given
++    module
++    """
++    f = os.popen("pkg-config --variable=" + key + " " + module)
++    status = bool(f.read().strip())
++    f.close()
++    return status
++
+ def evaluate_pkgconfig_variables(string):
+     p = re.compile("\${pkg:(.*?):(.*?)}")
+     m = p.search(string)
+@@ -24,6 +39,17 @@ def evaluate_pkgconfig_variables(string):
+         f = os.popen("pkg-config --variable=" + key + " " + module)
+         value = f.read().strip()
+         if not value:
++            # pango 1.38 removed modules, try to give a helpful
++            # message in case something tries to reference the no
++            # longer existing variable (most likely from old bundle
++            # xml files) when using a newer pango build.
++            if module == "pango" and key == "pango_module_version":
++                if has_pkgconfig_module("pango"):
++                    raise Exception(
++                        "'%s' got removed in '%s' "
++                        "1.38. Remove any reference to pango "
++                        "modules in your bundle xml." % (
++                            key, module))
+             raise Exception("pkg-config variable '%s %s' is undefined" % (key, module))
+         string = p.sub(value, string, 1)
+         m = p.search(string)
+@@ -33,7 +59,7 @@ def evaluate_pkgconfig_variables(string):
+ def makedirs(path):
+     try:
+         os.makedirs(path)
+-    except EnvironmentError, e:
++    except EnvironmentError as e:
+         if e.errno != errno.EEXIST:
+             raise
+diff --git examples/gtk-demo.bundle examples/gtk-demo.bundle
+index 4b32d6b..422126e 100644
+--- examples/gtk-demo.bundle
++++ examples/gtk-demo.bundle
+@@ -79,9 +79,11 @@
+     ${prefix}/lib/gdk-pixbuf-2.0/${pkg:${gtk}:gtk_binary_version}/loaders/*.so
+   </binary>
++<!-- No longer needed for pango >= 1.38
+    <binary>
+     ${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/
+   </binary>
++-->
+   <data>
+     ${prefix}/etc/pango/
+diff --git examples/gtk3-demo.bundle examples/gtk3-demo.bundle
+index ba15cd3..ec0eb4c 100644
+--- examples/gtk3-demo.bundle
++++ examples/gtk3-demo.bundle
+@@ -69,13 +69,11 @@
+     ${prefix}/lib/gdk-pixbuf-2.0/${pkg:gdk-pixbuf-2.0:gdk_pixbuf_binary_version}/loaders/*.so
+   </binary>
++<!-- No longer needed for pango >= 1.38
+   <binary>
+     ${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/
+   </binary>
+-
+-  <data>
+-    ${prefix}/etc/pango/
+-  </data>
++-->
+   <!-- Translation filenames, one for each program or library that you
+        want to copy in to the bundle. The "dest" attribute is
+@@ -102,6 +100,10 @@
+     ${prefix}/share/themes
+   </data>
++  <data>
++    ${prefix}/share/icons
++  </data>
++
+   <!-- Copy icons. Note that the .icns file is an Apple format which
+        contains up to 4 sizes of icon. You can use
+        /Developer/Applications/Utilities/Icon Composer.app to import
+@@ -110,25 +112,4 @@
+     ${project}/Giggle.icns
+   </data -->
+-  <!-- This is where theme commands go. You can copy them in from your
+-       theme of choice if they provide and example, or you can just
+-       change the source path. -->
+-
+-  <data dest="${bundle}/Contents/Resources/etc/${gtk}/gtkrc">
+-    ${project}/gtkrc
+-  </data>
+-
+-  <!-- Icon themes to copy. The "icons" property can be either of
+-       "auto", "all", or "none". All or none should be
+-       self-explanatory, while auto means that the script will try to
+-       figure out which icons are needed. This is done by getting all
+-       the strings from all copied binaries, and matching them against
+-       icon names. To be safe, you should use "all". "none" is useful
+-       if you want just the index.theme file but no icons, mostly
+-       needed for the "hicolor" base theme.
+-  >
+-  <icon-theme icons="auto">
+-    Tango
+-  </icon-theme -->
+-
+-</app-bundle>
++  </app-bundle>
+diff --git examples/gtk3-launcher.sh examples/gtk3-launcher.sh
+index 4aed833..9137ccb 100755
+--- examples/gtk3-launcher.sh
++++ examples/gtk3-launcher.sh
+@@ -29,11 +29,15 @@ export GTK_DATA_PREFIX="$bundle_res"
+ export GTK_EXE_PREFIX="$bundle_res"
+ export GTK_PATH="$bundle_res"
+-export GTK2_RC_FILES="$bundle_etc/gtk-3.0/gtkrc"
+-export GTK_IM_MODULE_FILE="$bundle_etc/gtk-3.0/gtk.immodules"
+-export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-3.0/gdk-pixbuf.loaders"
+-export PANGO_LIBDIR="$bundle_lib"
++# PANGO_* is no longer needed for pango >= 1.38
++export PANGO_RC_FILE="$bundle_etc/pango/pangorc"
+ export PANGO_SYSCONFDIR="$bundle_etc"
++export PANGO_LIBDIR="$bundle_lib"
++
++export GDK_PIXBUF_MODULE_FILE="$bundle_lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
++if [ `uname -r | cut -d . -f 1` -ge 10 ]; then
++    export GTK_IM_MODULE_FILE="$bundle_etc/gtk-3.0/gtk.immodules"
++fi
+ APP=name
+diff --git examples/launcher.sh examples/launcher.sh
+index a1dfd1b..11cd019 100755
+--- examples/launcher.sh
++++ examples/launcher.sh
+@@ -31,7 +31,11 @@ export GTK_PATH="$bundle_res"
+ export GTK2_RC_FILES="$bundle_etc/gtk-2.0/gtkrc"
+ export GTK_IM_MODULE_FILE="$bundle_etc/gtk-2.0/gtk.immodules"
+-export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-2.0/gdk-pixbuf.loaders"
++#N.B. When gdk-pixbuf was separated from Gtk+ the location of the
++#loaders cache changed as well. Depending on the version of Gtk+ that
++#you built with you may still need to use the old location:
++#export GDK_PIXBUF_MODULE_FILE="$bundle_etc/gtk-2.0/gdk-pixbuf.loaders"
++export GDK_PIXBUF_MODULE_FILE="$bundle_lib/gdk-pixbuf-2.0/2.10.0/loaders.cache"
+ export PANGO_LIBDIR="$bundle_lib"
+ export PANGO_SYSCONFDIR="$bundle_etc"
diff --git a/utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-bundler_py.diff b/utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-bundler_py.diff
new file mode 100644 (file)
index 0000000..1aaabd4
--- /dev/null
@@ -0,0 +1,13 @@
+diff --git bundler/bundler.py bundler/bundler.py
+index 65b8cc0..3ca931f 100644
+--- bundler/bundler.py
++++ bundler/bundler.py
+@@ -618,7 +618,7 @@ class Bundler:
+         self.copy_plist()
+         # Note: could move this to xml file...
+-        self.copy_path(Path("${prefix}/lib/charset.alias"))
++        self.copy_path(Path("/usr/lib/charset.alias", dest="${bundle}/Contents/Resources"))
+         # Main binary
+         path = self.project.get_main_binary()
diff --git a/utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-gtk3-demo-bundle.diff b/utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-gtk3-demo-bundle.diff
new file mode 100644 (file)
index 0000000..e49f499
--- /dev/null
@@ -0,0 +1,15 @@
+diff --git examples/gtk3-demo.bundle examples/gtk3-demo.bundle
+index ec0eb4c..87cbc18 100644
+--- examples/gtk3-demo.bundle
++++ examples/gtk3-demo.bundle
+@@ -104,6 +104,10 @@
+     ${prefix}/share/icons
+   </data>
++  <data>
++    ${prefix}/share/mime
++  </data>
++
+   <!-- Copy icons. Note that the .icns file is an Apple format which
+        contains up to 4 sizes of icon. You can use
+        /Developer/Applications/Utilities/Icon Composer.app to import
diff --git a/utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-gtk3-launcher.diff b/utilities/osxbundler/macports-custom-packages/gtk-mac-bundler/files/patch-gtk3-launcher.diff
new file mode 100644 (file)
index 0000000..3597b7e
--- /dev/null
@@ -0,0 +1,21 @@
+diff --git examples/gtk3-launcher.sh examples/gtk3-launcher.sh
+index 9137ccb..635ca8d 100755
+--- examples/gtk3-launcher.sh
++++ examples/gtk3-launcher.sh
+@@ -22,7 +22,6 @@ bundle_bin="$bundle_res"/bin
+ bundle_data="$bundle_res"/share
+ bundle_etc="$bundle_res"/etc
+-export DYLD_LIBRARY_PATH="$bundle_lib"
+ export XDG_CONFIG_DIRS="$bundle_etc"/xdg
+ export XDG_DATA_DIRS="$bundle_data"
+ export GTK_DATA_PREFIX="$bundle_res"
+@@ -40,7 +39,7 @@ if [ `uname -r | cut -d . -f 1` -ge 10 ]; then
+ fi
+-APP=name
++APP=$name
+ I18NDIR="$bundle_data/locale"
+ # Set the locale-related variables appropriately:
+ unset LANG LC_MESSAGES LC_MONETARY LC_COLLATE
diff --git a/utilities/osxbundler/macports-custom-packages/pspp/Portfile b/utilities/osxbundler/macports-custom-packages/pspp/Portfile
new file mode 100644 (file)
index 0000000..97aee5f
--- /dev/null
@@ -0,0 +1,167 @@
+# -*- coding: utf-8; mode: tcl; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- vim:fenc=utf-8:ft=tcl:et:sw=4:ts=4:sts=4
+# $Id: Portfile 147432 2016-04-03 16:28:15Z snc@macports.org $
+
+PortSystem              1.0
+PortGroup               app 1.0
+PortGroup               active_variants 1.1
+
+name                    pspp
+version                 0.10.1
+categories              math
+license                 GPL-3+
+maintainers             snc
+conflicts               pspp-devel
+description             Statistical analysis of sampled data (free \
+                        replacement for SPSS).
+long_description        PSPP is a program for \
+                        statistical analysis of sampled data. It is a Free \
+                        replacement for the proprietary program SPSS, and \
+                        appears very similar to it with a few exceptions.
+
+homepage                http://www.gnu.org/software/pspp/
+platforms               darwin
+master_sites            gnu
+
+checksums           rmd160  5b5aea62137b5c98a7360a42b51c86385db22f37 \
+                    sha256  44cc08864de736880bc0d7e2b1f8c8493ac0e0c2164a4f9471077608f00c8677
+
+depends_lib-append  path:lib/pkgconfig/cairo.pc:cairo \
+                    port:fontconfig \
+                    port:freetype \
+                    port:gettext \
+                    path:lib/pkgconfig/glib-2.0.pc:glib2 \
+                    port:gsl \
+                    port:libiconv \
+                    port:libxml2 \
+                    port:ncurses \
+                    path:lib/pkgconfig/pango.pc:pango \
+                    port:readline \
+                    port:zlib
+
+depends_build-append    port:pkgconfig \
+                        port:texinfo
+
+post-extract {
+    if {[variant_isset gui]} {
+        copy ${filespath}/PSPP ${worksrcpath}
+        file attributes ${worksrcpath}/PSPP -permissions ugo+rx
+    }
+}
+
+post-patch {
+    if {[variant_isset gui]} {
+        reinplace s|@@PREFIX@@|${prefix}|g ${worksrcpath}/PSPP
+    }
+}
+
+configure.args-append   --disable-rpath \
+                    --without-libpq \
+                    --without-gui \
+                    --without-perl-module \
+                    --with-packager=snc \
+                    --with-packager-version=${version} \
+                    --with-packager-bug-reports=${maintainers}
+
+set nif_compilers {macports-llvm-gcc-4.2 llvm-gcc-4.2}
+if {[lsearch -exact ${nif_compilers} ${configure.compiler}] > -1} {
+    configure.optflags-append -fno-inline-functions
+}
+
+test.run                yes
+test.target             check
+
+variant help requires gui description {Provide in-application help via yelp} {
+    depends_run-append  port:yelp
+}
+
+variant doc description {Build documentation} {
+    build.target-append  html
+}
+
+variant reloc requires quartz description {Enable relocation build for app bundle} {
+    configure.args-append --enable-relocatable
+}
+
+variant postgres description {Enables reading of postgresql databases} {
+    depends_lib-append  port:postgresql92
+    configure.args-delete   --without-libpq
+    configure.ldflags-append -L${prefix}/lib/postgresql92
+    configure.env-append    PG_CONFIG=${prefix}/lib/postgresql92/bin/pg_config
+}
+
+variant gui description {Build PSPPIRE, the graphical interface} {
+    depends_lib-append      port:atk \
+                            port:gdk-pixbuf2 \
+                            port:gtksourceview3
+    depends_run-append      port:adwaita-icon-theme
+
+    configure.args-delete   --without-gui
+}
+
+variant quartz requires gui {
+    require_active_variants gtk3 quartz
+    require_active_variants gtksourceview3 quartz
+}
+
+variant x11 requires gui {
+    require_active_variants gtk3 x11
+    depends_lib-append  port:xorg-libX11 \
+                        port:xorg-libXau \
+                        port:xorg-libXcomposite \
+                        port:xorg-libXcursor \
+                        port:xorg-libXdamage \
+                        port:xorg-libXdmcp \
+                        port:xorg-libXext \
+                        port:xorg-libXfixes \
+                        port:xorg-libXi \
+                        port:xorg-libXinerama \
+                        port:xorg-libXrandr \
+                        port:xorg-libxcb \
+                        port:xrender
+}
+
+if {![variant_isset x11] && ![variant_isset quartz] && ![variant_isset gui]} {
+    default_variants +x11
+}
+
+# check for x11-poisoned dependencies
+set x11 no
+set depspecs {gtk3}
+foreach depspec depspecs {
+    if {![catch {set result [active_variants $depspec x11]}]} {
+        if {$result} {
+            $x11 yes
+            break
+        }
+    }
+}
+
+# if x11 poison, depend on x11
+if {[string is true -strict $x11]} {
+    default_variants +x11
+}
+
+post-destroot {
+    if {[variant_isset doc]} {
+        xinstall -d -m 0755 ${destroot}${prefix}/share/doc/${name}
+        foreach fl [glob -nocomplain -directory ${worksrcpath}/doc *.pdf *.html] {
+            copy ${fl} ${destroot}${prefix}/share/doc/${name}
+        }
+    }
+}
+
+post-activate {
+    system "${prefix}/bin/gtk-update-icon-cache-3.0 --ignore-theme-index ${prefix}/share/icons/hicolor"
+
+}
+
+post-deactivate {
+    system "${prefix}/bin/gtk-update-icon-cache-3.0 --ignore-theme-index ${prefix}/share/icons/hicolor"
+}
+
+if {![variant_isset gui]} {
+    app.create      no
+}
+app.name            PSPP
+app.executable      ${worksrcpath}/PSPP
+app.icon            ${filespath}/logo.png
diff --git a/utilities/osxbundler/macports-custom-packages/pspp/files/PSPP b/utilities/osxbundler/macports-custom-packages/pspp/files/PSPP
new file mode 100644 (file)
index 0000000..9df2495
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+cd && @@PREFIX@@/bin/psppire
diff --git a/utilities/osxbundler/macports-custom-packages/pspp/files/logo.png b/utilities/osxbundler/macports-custom-packages/pspp/files/logo.png
new file mode 100644 (file)
index 0000000..d62cb75
Binary files /dev/null and b/utilities/osxbundler/macports-custom-packages/pspp/files/logo.png differ
diff --git a/utilities/osxbundler/makeosxbundle.sh b/utilities/osxbundler/makeosxbundle.sh
new file mode 100755 (executable)
index 0000000..c213a67
--- /dev/null
@@ -0,0 +1,145 @@
+#!/bin/sh -e
+
+# Create a MacOS application bundle for pspp
+# This will install all required dependencies via macports
+# With option --git it will build pspp from a source tree
+# The default is to install also pspp from macports
+# Requires XCode Commandline Tools installed and ready for macports
+
+# Copyright (C) 2016 Free Software Foundation, Inc.
+# Released under GNU General Public License, either version 3
+# or any later option
+
+# The source tree for pspp is here. This is only required if you
+# build with option --git
+psppsource=`pwd`/../..
+
+# Check if we are on MacOS
+if ! test `uname` = "Darwin"; then
+    echo "This only works on MacOS"
+    exit
+fi
+
+# Check if XCode is installed - Assume clang indicates xcode.
+if ! test -f /usr/bin/clang; then
+    echo "/usr/bin/clang not found - please install XCode CLT"
+    exit
+fi
+
+# Check the required configuration files
+if ! test -f ./pspp.bundle; then
+    echo "pspp.bundle is missing"
+    exit
+fi
+
+if ! test -f ./Info-pspp.plist; then
+    echo "Info-pspp.plist is missing"
+    exit
+fi
+
+buildfromsource=false
+if test $# = 1 && test $1 = "--git"; then
+    echo "Trying to build from source"
+    if test -f $psppsource/configure; then
+        buildfromsource=true
+    else
+        echo "Could not find pspp source in: $psppsource"
+        exit
+    fi
+fi
+
+# This is the installation directory which will be used as macports prefix
+# and as pspp configure prefix.
+bundleinstall=`pwd`/install
+
+export PATH=$bundleinstall/bin:$bundleinstall/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
+
+# Target macports install directory for the pspp bundle
+if test -d $bundleinstall; then
+    echo "Found existing macports directory $bundleinstall"
+    echo "Updating macports packages"
+    port uninstall pspp
+    port uninstall gtk-mac-bundler
+else
+    echo "Creating Macports installation in $bundleinstall"
+    mkdir $bundleinstall
+    # Install macports
+    rm -rf /tmp/macports
+    mkdir /tmp/macports
+    pushd /tmp/macports
+    curl https://distfiles.macports.org/MacPorts/MacPorts-2.3.4.tar.gz -O
+    tar xvzf Macports-2.3.4.tar.gz
+    cd Macports-2.3.4
+    ./configure --prefix=$bundleinstall \
+                --with-applications-dir=$bundleinstall/Applications \
+                --with-no-root-privileges
+    make
+    make install
+    popd
+    rm -rf /tmp/macports
+    # Modify the default variants to use quartz
+    echo "-x11 +no_x11 +quartz" > $bundleinstall/etc/macports/variants.conf
+fi
+
+# Install the packages for pspp
+port -v selfupdate
+port upgrade outdated || true
+if test $buildfromsource = "true"; then
+    # Install the build dependencies for pspp
+    port install pkgconfig texinfo makeicns cairo fontconfig freetype \
+     gettext glib2 gsl libiconv libxml2 ncurses pango readline zlib atk \
+     gdk-pixbuf2 gtksourceview3 adwaita-icon-theme
+# Configure and build pspp
+    rm -rf ./build
+    mkdir ./build
+    pushd build
+    $psppsource/configure --prefix=$bundleinstall \
+                         LDFLAGS=-L$bundleinstalll/lib \
+                         CPPFLAGS=-I$bundleinstall/include \
+                         --enable-relocatable
+    make
+    make install
+    popd
+else
+    # Install the pspp package from macports
+    # This is a custom package for the moment as this requires the relocatable variant
+    echo "Installing pspp from macports package"
+    pushd ./macports-custom-packages/pspp
+    port install +reloc
+    popd
+fi
+
+# install the mac gtk-mac-bundler
+# Custom package for the moment...
+pushd ./macports-custom-packages/gtk-mac-bundler
+port install
+popd
+
+# Create the icns file
+makeicns -256 $bundleinstall/share/icons/hicolor/256x256/apps/pspp.png \
+         -32  $bundleinstall/share/icons/hicolor/32x32/apps/pspp.png \
+         -16  $bundleinstall/share/icons/hicolor/16x16/apps/pspp.png \
+         -out pspp.icns
+
+# produce the pspp.app bundle in Desktop
+export PSPPINSTALL=$bundleinstall
+gtk-mac-bundler pspp.bundle
+
+# Fix the link issue for the relocatable binary in the app bundle
+# MacOS/pspp - the wrapper from gtk-mac-bundler calling
+# MacOS/pspp-bin - the wrapper from glibc relocatable calling pspp-bin.bin
+# but that is in the Resource directory
+pushd pspp.app/Contents/MacOS
+ln -s ../Resources/bin/psppire.bin ./pspp-bin.bin
+popd
+
+# Create the DMG for distribution
+rm -rf /tmp/psppbundle
+mkdir /tmp/psppbundle
+mv ./pspp.app /tmp/psppbundle
+rm -rf pspp.dmg
+hdiutil create -fs HFS+ -srcfolder /tmp/psppbundle -volname pspp pspp.dmg
+rm -rf /tmp/psppbundle
+
+echo "Done! Your dmg file is pspp.dmg"
+echo "You can remove the install directory: $bundleinstall"
diff --git a/utilities/osxbundler/pspp.bundle b/utilities/osxbundler/pspp.bundle
new file mode 100644 (file)
index 0000000..24452de
--- /dev/null
@@ -0,0 +1,127 @@
+<?xml version="1.0" standalone="no"?> <!--*- mode: xml -*-->
+<app-bundle>
+
+  <meta>
+    <!-- Where to pick up the GTK+ installation, icon themes,
+         etc. Note that "/opt/pspp" is evaluated to the
+         value of the environment variable JHBUILD_PREFIX. You can
+         define additional prefixes and refer to them in paths
+         throughout this file on the form "${prefix:name}". This is
+         useful for installing certain libraries or even the
+         application itself separately. Note that JHBUILD_PREFIX is
+         defined by jhbuild, so it you are not using jhbuild you can
+         either define your own or just hardcode the path here.
+    -->
+    <prefix name="default">${env:PSPPINSTALL}</prefix>
+
+    <!-- The project directory is the default location of the created
+         app. If you leave out the path, the current directory is
+         used. Note the usage of an environment variable here again.
+    -->
+    <!--destination overwrite="yes">${env:HOME}/Desktop</destination-->
+
+    <image>
+      <!-- Not implemented yet (DMG image). -->
+    </image>
+
+    <!-- Comment this out to keep the install names in binaries -->
+    <run-install-name-tool/>
+    <!-- Optionally specify a launcher script to use. If the
+         application sets up everything needed itself, like
+         environment variable, linker paths, etc, a launcher script is
+         not needed. If the source path is left out, the default
+         script will be used.
+    -->
+    <launcher-script>${project}/install/share/gtk-mac-bundler/examples/gtk3-launcher.sh</launcher-script >
+
+    <!-- Not implemented: Optional runtime, could be python or mono
+         for example.
+    -->
+    <!-- runtime copy="yes">/usr/bin/python</runtime -->
+    <!-- Indicate the active gtk version to use. This is needed only
+         for gtk+-3.0 projects. -->
+    <gtk>gtk+-3.0</gtk>
+  </meta>
+
+  <!-- The special macro "${project}" refers to the directory where
+       this bundle file is located. The application name and bundle
+       identifier are taken from the plist file.
+  -->
+  <plist>${project}/Info-pspp.plist</plist>
+
+  <main-binary>${prefix}/bin/psppire</main-binary>
+
+  <binary>${prefix}/bin/psppire.bin</binary>
+  
+
+  <!-- Copy in the input methods. Dunno if they actually work with
+       OSX. Note the ${gtkdir} macro, which expands to the correct
+       library subdirectory for the specified gtk version. -->
+  <binary>
+    ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/immodules/*.so
+  </binary>
+
+<!-- And the print backends -->
+  <binary>
+    ${prefix}/lib/${gtkdir}/${pkg:${gtk}:gtk_binary_version}/printbackends/*.so
+  </binary>
+
+<!-- Starting with 2.24, gdk-pixbuf installs into its own directory. -->
+  <binary>
+    ${prefix}/lib/gdk-pixbuf-2.0/${pkg:gdk-pixbuf-2.0:gdk_pixbuf_binary_version}/loaders/*.so
+  </binary>
+
+<!-- No longer needed for pango >= 1.38
+  <binary>
+    ${prefix}/lib/pango/${pkg:pango:pango_module_version}/modules/
+  </binary>
+-->
+
+  <!-- Translation filenames, one for each program or library that you
+       want to copy in to the bundle. The "dest" attribute is
+       optional, as usual. Bundler will find all translations of that
+       library/program under the indicated directory and copy them.-->
+  <translations  name="gtk30">
+    ${prefix}/share/locale
+  </translations>
+  <translations  name="pspp">
+    ${prefix}/share/locale
+  </translations>
+
+  <!-- Data to copy in, usually Glade/UI files, images, sounds files
+       etc. The destination inside the bundle can be specified if the
+       files should end up at a different location, by using the
+       "dest" property. The destination must then start with the macro
+       "${bundle}", which refers to the bundle root directory.
+  -->
+  <data>
+    ${prefix}/share/pspp
+  </data>
+
+  <!-- Copy in the themes data. You may want to trim this to save space
+       in your bundle. -->
+  <data>
+    ${prefix}/share/themes
+  </data>
+
+  <data>
+    ${prefix}/share/icons
+  </data>
+
+  <data>
+    ${prefix}/share/mime
+  </data>
+  <data>
+    ${prefix}/share/glib-2.0
+  </data>  
+
+  <!-- Copy icons. Note that the .icns file is an Apple format which
+       contains up to 4 sizes of icon. You can use
+       /Developer/Applications/Utilities/Icon Composer.app to import
+       artwork and create the file. -->
+  <data dest="${bundle}/Contents/Resources">
+    ${project}/pspp.icns
+  </data>
+
+  </app-bundle>