[cig-commits] [commit] baagaard/binary-packaging: Created make_package for creating binary package. (d5dd0dc)

cig_noreply at geodynamics.org cig_noreply at geodynamics.org
Mon Oct 21 13:38:11 PDT 2013


Repository : ssh://geoshell/pylith

On branch  : baagaard/binary-packaging
Link       : https://github.com/geodynamics/pylith/compare/0000000000000000000000000000000000000000...d5dd0dcd3e7f9adf371e85dfbcd7f46d00005760

>---------------------------------------------------------------

commit d5dd0dcd3e7f9adf371e85dfbcd7f46d00005760
Author: Brad Aagaard <baagaard at usgs.gov>
Date:   Mon Oct 21 13:39:55 2013 -0700

    Created make_package for creating binary package.
    
    Refactor creating binary package from buildbot. Appears to work for
    linux. Not tested for cygwin.


>---------------------------------------------------------------

d5dd0dcd3e7f9adf371e85dfbcd7f46d00005760
 packager/cig.ico         | Bin 0 -> 1078 bytes
 packager/cygwin.py       | 343 +++++++++++++++++++++++++++++++++
 packager/make_package.py | 482 +++++++++++++++++++++++++++++++++++++++++++++++
 packager/packinglist.cfg |  91 +++++++++
 4 files changed, 916 insertions(+)

diff --git a/packager/cig.ico b/packager/cig.ico
new file mode 100644
index 0000000..34896de
Binary files /dev/null and b/packager/cig.ico differ
diff --git a/packager/cygwin.py b/packager/cygwin.py
new file mode 100644
index 0000000..618a8a3
--- /dev/null
+++ b/packager/cygwin.py
@@ -0,0 +1,343 @@
+#!/usr/bin/env python
+#
+# ----------------------------------------------------------------------
+#
+# Brad T. Aagaard, U.S. Geological Survey
+# Charles A. Williams, GNS Science
+# Matthew G. Knepley, University of Chicago
+#
+# This code was developed as part of the Computational Infrastructure
+# for Geodynamics (http://geodynamics.org).
+#
+# Copyright (c) 2010-2013 University of California, Davis
+#
+# See COPYING for license information.
+#
+# ----------------------------------------------------------------------
+#
+# Functions used in creating PyLith binary with cygwin for windows.
+#
+# Usage: make_package.py
+
+import os, sys
+from os.path import basename, dirname, isabs, isdir, isfile, join
+import shutil
+
+def installCigIcon(prefix):
+    cigIco = "cig.ico"
+    os.system("cp %s %s" % (cigIco, prefix))
+    return
+
+
+def minCygwin(python):
+    # Minimal set of Cygwin binaries, as determined while preparing for CFEM 2006.
+    l = [
+        "[.exe",
+        "bash.exe",
+        "cat.exe",
+        "cp.exe",
+        "env.exe",
+        "cygattr-1.dll",
+        "cygiconv-2.dll",
+        "cygintl-8.dll",
+        "cygncurses-9.dll",
+        "cygpath.exe",
+        "cygcheck.exe",
+        "cygreadline7.dll",
+        "cyggfortran-3.dll",
+        "cyggcc_s-1.dll",
+        "cygstdc++-6.dll",
+        "cygncursesw-10.dll",
+        # This is given special treatment.
+        "cygwin1.dll",
+        "cygz.dll", # for HDF5 (used by Cigma)
+        "echo.exe",
+        "gunzip",
+        "gzip.exe",
+        "lib" + python + ".dll",
+        "ln.exe",
+        "ls.exe",
+        "ldd.exe",
+        "pwd.exe",
+        "python",
+        python + ".exe",
+        "rm.exe",
+        "sed.exe",
+        "sh.exe",
+        "tar.exe",
+        "vim-nox.exe",
+        "which.exe",
+        ]
+    l = ["/bin/" + b for b in l]
+
+    # Additional Python stuff.
+    l.extend([
+        "/lib/" + python,
+        "/usr/include/" + python,
+        ])
+
+    # Lapack libraries (used by numpy) now placed in own location.
+    l.extend([
+        "/lib/lapack",
+        ])
+
+    return l
+
+def installMungedCygwinDLL(munged):
+    # We don't require that the user has Cygwin installed.  At the
+    # same time, we need to avoid conflicts if they *do* have it
+    # installed.
+
+    # Therefore, we install a munged copy of "cygwin1.dll", performing
+    # the following transformations:
+    #     Cygnus Solutions -> Cigwin Solutions
+    #     cygwin1S4 -> cigwin1S4
+    # These are the registry key name and the shared memory object
+    # name, respectively.
+
+    # N.B.: It is significant that the replacement string is the same
+    # length as the original string.  Otherwise, the DLL would become
+    # corrupted.
+
+    # This gives us the freedom to create our own chrooted environment
+    # using Cygwin's mounts, without messing-up the Cygwin registry on
+    # systems that do have Cygwin installed.  Registry clean-up at
+    # uninstall is also made easy.
+
+    # Ugly, yes; but so much easier than building a custom Cygwin from
+    # source...
+    status = os.system("""sed -b """
+                       """-e "s/Cygnus Solutions/Cigwin Solutions/g" """
+                       """-e s/cygwin1S4/cigwin1S4/g """
+                       """/bin/cygwin1.dll > %s""" % munged)
+    if status != 0:
+        sys.exit("sed: exit %d" % status)
+    return
+
+
+def installMinimalCygwin(python, prefix):
+    cygwin = minCygwin(python)
+    copyAll(cygwin, prefix)
+    installMungedCygwinDLL("bin/cygwin1.dll")
+    return
+
+
+def rebaseDLLs(stage):
+    # Work-around "unable to remap xyz.dll to same address as parent".
+    # The base and offset were determined through trial-and-error.
+
+    print "Rebasing DLLs."
+    
+    dlls = []
+
+    for dirpath, dirnames, filenames in os.walk(stage):
+        for filename in filenames:
+            if filename.endswith(".dll"):
+                dll = join(dirpath, filename)
+                print dll
+                dlls.append(dll)
+
+    if not dlls:
+        sys.exit("no DLLs found!")
+    dlls = ' '.join(dlls)
+
+    status = os.system("""rebase -v -d -b 0x70000000 -o 0x100000 %s""" % dlls)
+    if status != 0:
+        sys.exit("rebase: exit %d" % status)
+    return
+
+
+def stageInstallation(prefix, workdir, python, pl):
+    
+    stage = join(workdir, "buildbot-win-stage")
+    shutil.rmtree(stage, ignore_errors=True)
+    os.mkdir(stage)
+    os.chdir(stage)
+
+    print "Copying packing list to %s." % stage
+    copyAll(pl.files(), prefix)
+    
+    print "Installing minimal cygwin."
+    installMinimalCygwin(python, prefix)
+    
+    rebaseDLLs(stage)
+    
+    return stage
+
+
+def generateISS(workdir, sourceDir, info, pl, bashrc, python, stage=None):
+    s = open(workdir + "/buildbot.iss", "w")
+
+
+    # [Setup]
+    s.write(
+"""; Inno Setup Script generated by BuildBot
+
+[Setup]
+AppName=%(AppName)s
+AppVerName=%(AppVerName)s
+AppPublisher=Computational Infrastructure for Geodynamics
+AppPublisherURL=http://www.geodynamics.org/
+AppSupportURL=http://www.geodynamics.org/
+AppUpdatesURL=http://www.geodynamics.org/
+DefaultDirName={pf}\\%(AppName)s
+DefaultGroupName=%(AppName)s
+SourceDir=%(SourceDir)s
+
+""" % info
+    )
+
+
+    # [Tasks]
+    s.write(
+"""
+[Tasks]
+Name: "desktopicon"; Description: "Create a &desktop icon"; GroupDescription: "Additional icons:"
+
+""")
+
+
+    # [Files]
+    #  NOTE: Don't use "Flags: ignoreversion" on any shared system files
+    s.write(
+"""
+[Files]
+"""
+    )
+    if stage:
+        for pathname in os.listdir(stage):
+            if isfile(pathname):
+                s.write("""Source: "%s"; DestDir: "{app}"; Flags: ignoreversion\n""" % pathname)
+            else:
+                s.write("""Source: "%s\\*"; DestDir: "{app}\\%s"; Flags: ignoreversion recursesubdirs\n""" % (pathname, pathname))
+    else:
+        for src, dest in itwindirs(pl.directories, sourceDir):
+            s.write("""Source: "%s\\*"; DestDir: "%s"; Flags: ignoreversion recursesubdirs\n""" % (src, dest))
+        for src, dest in itwinfiles(pl.files(), sourceDir):
+            s.write("""Source: "%s"; DestDir: "%s"; Flags: ignoreversion\n""" % (src, dest))
+        for f in [bashrc, "cig.ico"]:
+            s.write("""Source: "%s"; DestDir: "{app}"; Flags: ignoreversion\n""" % f)
+
+
+    # [Dirs]
+    s.write(
+"""
+[Dirs]
+; Cygwin demands a /tmp directory
+Name: "{app}\\tmp"
+; for our /usr mounts
+Name: "{app}\\usr"
+Name: "{app}\\usr\\bin"
+Name: "{app}\\usr\\lib"
+
+"""
+    )
+
+
+    # [Registry]
+    s.write(
+"""
+[Registry]
+Root: HKLM; Subkey: "Software\\Cigwin Solutions"; Flags: uninsdeletekey noerror
+Root: HKLM; Subkey: "Software\\Cigwin Solutions\\Cygwin"; Flags: uninsdeletekey noerror
+Root: HKLM; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2"; Flags: uninsdeletekey noerror
+Root: HKLM; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/"; Flags: uninsdeletekey noerror
+Root: HKLM; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/"; Flags: noerror; ValueType: string; ValueName: "native"; ValueData: "{app}"
+Root: HKLM; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/"; Flags: noerror; ValueType: dword; ValueName: "flags"; ValueData: "00000002"
+Root: HKLM; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/bin"; Flags: uninsdeletekey noerror
+Root: HKLM; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/bin"; Flags: noerror; ValueType: string; ValueName: "native"; ValueData: "{app}\\bin"
+Root: HKLM; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/bin"; Flags: noerror; ValueType: dword; ValueName: "flags"; ValueData: "00000002"
+Root: HKLM; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/lib"; Flags: uninsdeletekey noerror
+Root: HKLM; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/lib"; Flags: noerror; ValueType: string; ValueName: "native"; ValueData: "{app}\\lib"
+Root: HKLM; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/lib"; Flags: noerror; ValueType: dword; ValueName: "flags"; ValueData: "00000002"
+; for non-admin install
+Root: HKCU; Subkey: "Software\\Cigwin Solutions"; Flags: uninsdeletekey
+Root: HKCU; Subkey: "Software\\Cigwin Solutions\\Cygwin"; Flags: uninsdeletekey
+Root: HKCU; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2"; Flags: uninsdeletekey
+Root: HKCU; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/"; Flags: uninsdeletekey
+Root: HKCU; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/"; ValueType: string; ValueName: "native"; ValueData: "{app}"
+Root: HKCU; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/"; ValueType: dword; ValueName: "flags"; ValueData: "00000002"
+Root: HKCU; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/bin"; Flags: uninsdeletekey
+Root: HKCU; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/bin"; ValueType: string; ValueName: "native"; ValueData: "{app}\\bin"
+Root: HKCU; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/bin"; ValueType: dword; ValueName: "flags"; ValueData: "00000002"
+Root: HKCU; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/lib"; Flags: uninsdeletekey
+Root: HKCU; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/lib"; ValueType: string; ValueName: "native"; ValueData: "{app}\\lib"
+Root: HKCU; Subkey: "Software\\Cigwin Solutions\\Cygwin\\mounts v2\\/usr/lib"; ValueType: dword; ValueName: "flags"; ValueData: "00000002"
+
+"""
+    )
+
+
+    # [INI]
+    s.write("""[INI]\n""")
+    for name, filename, url in pl.urls:
+        s.write("""Filename: "{app}\\%(filename)s.url"; Section: "InternetShortcut"; Key: "URL"; String: "%(url)s"\n""" %
+                {'filename': filename, 'url': url})
+
+
+    # [Icons]
+    s.write(
+"""
+[Icons]
+Name: "{group}\\%(AppName)s"; Filename: "{app}\\bin\\bash.exe"; Parameters: "--init-file %(bashrc)s -i"; WorkingDir: "{app}"; IconFilename: "{app}\\cig.ico"
+Name: "{userdesktop}\\%(AppName)s"; Filename: "{app}\\bin\\bash.exe"; Tasks: desktopicon; Parameters: "--init-file %(bashrc)s -i"; WorkingDir: "{app}"; IconFilename: "{app}\\cig.ico"
+""" % {'AppName': info['AppName'], 'bashrc': bashrc}
+    )
+    for name, filename, url in pl.urls:
+        s.write("""Name: "{group}\\%s"; Filename: "{app}\\%s.url"\n""" % (name, filename))
+    s.write("""Name: "{group}\Uninstall %(AppName)s"; Filename: "{uninstallexe}"\n""" % info)
+
+
+    # [Run]
+    s.write(
+"""
+[Run]
+Filename: "{app}\\bin\\bash.exe"; Description: "Launch %(AppName)s"; Parameters: "--init-file %(bashrc)s -i"; WorkingDir: "{app}"; Flags: nowait postinstall skipifsilent
+
+""" % {'AppName': info['AppName'], 'bashrc': bashrc}
+    )
+
+
+    # [UninstallDelete]
+    s.write("""[UninstallDelete]\n""")
+    for name, filename, url in pl.urls:
+        s.write("""Type: files; Name: "{app}\%s.url"\n""" % filename)
+    for filename in [".bash_history"]:
+        s.write("""Type: files; Name: "{app}\%s"\n""" % filename)
+
+    s.write("\n; end of file\n")
+
+    return
+
+
+def createInstaller(python, stage, workdir, name, package, version, pl,
+                           installer):
+
+    sourceDir = cygpath("-w", stage)
+    
+    info = {
+        "AppName": name,
+        "AppVerName": name + " v" + version,
+        "SourceDir": sourceDir,
+        }
+
+    installCigIcon(stage)
+    bashrc = generateBashrc(stage, package, info)
+
+    generateISS(workdir, sourceDir, info, pl, bashrc, python, stage)
+
+    os.chdir(workdir)
+
+    os.system("unix2dos buildbot.iss")
+    
+    status = os.system("iscc buildbot.iss")
+    if status != 0:
+        sys.exit("iscc: exit %d" % status)
+
+    status = os.system("mv %s/Output/setup.exe %s.exe" % (stage, installer))
+    if status != 0:
+        sys.exit("mv: exit %d" % status)
+
+    return
+
+
diff --git a/packager/make_package.py b/packager/make_package.py
new file mode 100755
index 0000000..a1be441
--- /dev/null
+++ b/packager/make_package.py
@@ -0,0 +1,482 @@
+#!/usr/bin/env python
+#
+# ----------------------------------------------------------------------
+#
+# Brad T. Aagaard, U.S. Geological Survey
+# Charles A. Williams, GNS Science
+# Matthew G. Knepley, University of Chicago
+#
+# This code was developed as part of the Computational Infrastructure
+# for Geodynamics (http://geodynamics.org).
+#
+# Copyright (c) 2010-2013 University of California, Davis
+#
+# See COPYING for license information.
+#
+# ----------------------------------------------------------------------
+#
+# Create PyLith binary package.
+#
+# Usage: make_package.py
+
+import os, sys, platform
+from popen2 import Popen4
+from glob import glob
+from os.path import basename, dirname, isabs, isdir, isfile, join
+import shutil
+from distutils.sysconfig import parse_makefile
+from ConfigParser import ConfigParser
+import cygwin
+
+
+class Packaging(object):
+    _name = 'packaging'
+    _attrs = ['bin_dirs', 
+              'lib_dirs', 
+              'misc_dirs',
+              'files',
+              'strip_list',
+              'exclude',
+              'scripts',
+              'urls',
+              ]
+
+
+class Config(object):
+
+    sections = [Packaging]
+
+    #@classmethod
+    def readPackingList(cls):
+
+        parser = ConfigParser()
+        curdir = dirname(__file__)
+        parser.read(join(curdir, "packinglist.cfg"))
+
+        config = Config()
+
+        for sectionCls in cls.sections:
+            sectionDct = parser._sections.get(sectionCls._name, None)
+            section = None
+            if sectionDct is not None:
+                section = sectionCls()
+                for attr in section._attrs:
+                    value = sectionDct.get(attr, "")
+                    value = value.split()
+                    setattr(section, attr, value)
+            setattr(config, sectionCls._name, section)
+        
+        return config
+    readPackingList = classmethod(readPackingList)
+
+
+def getMakeInfo():
+    # NYI: This is Autotools-specific.
+    makefile = parse_makefile("Makefile")
+    info = {'package_name': makefile['PACKAGE_NAME'],
+            'package': makefile['PACKAGE'],
+            'version': makefile['VERSION'],
+            'srcdir': makefile['abs_top_srcdir'],
+            'prefix': makefile['prefix'],
+            'python_version': makefile['PYTHON_VERSION'],
+            }
+    return info
+
+
+
+def walkDirTree(dirname):
+    """
+    Get list of files in tree under dirname.
+    """
+    fullNames = []
+    for dirpath, dirs, files in os.walk(dirname):
+        for f in files:
+            fullNames.append(os.path.join(dirpath, f))
+    return fullNames
+
+
+def filterList(l, excludes):
+    try:
+        import re, functools, operator
+
+        pats = [re.compile(ex) for ex in excludes]
+        return [i for i in l if not functools.reduce(operator.or_, [bool(pat.match(i)) for pat in pats])]
+    except (ImportError, AttributeError):
+        import re, operator
+
+        pats = [re.compile(ex) for ex in excludes]
+        return [i for i in l if not reduce(operator.or_, [bool(pat.match(i)) for pat in pats])]
+
+
+class PackingList(object):
+    def __init__(self, config, opSys, python):
+        
+        binDirs = config.packaging.bin_dirs
+        libDirs = config.packaging.lib_dirs
+        miscDirs = config.packaging.misc_dirs
+        if platform.machine() == "x86_64":
+            libDirs.append("lib64")
+        self.directories = binDirs + libDirs + miscDirs
+
+        self.extraFiles = config.packaging.files
+        self.exclude = config.packaging.exclude
+
+        self.programs = []
+        for d in binDirs:
+            self.programs.extend(walkDirTree(d))
+        self.programs = filterList(self.programs, self.exclude)
+
+        self.libraries = []
+        for d in libDirs:
+            self.libraries.extend(walkDirTree(d))
+        self.libraries = filterList(self.libraries, self.exclude)
+            
+        self.misc = []
+        for d in miscDirs:
+            self.misc.extend(walkDirTree(d))
+        self.misc = filterList(self.misc, self.exclude)
+
+        # KLUDGE Explicitly add include/pythonX.X/pyconfig.h if it exists.
+        pythonConfigFile = "include/" + python + "/pyconfig.h"
+        if isfile(pythonConfigFile):
+            self.misc.append(pythonConfigFile)
+            
+        # Scripts are application specific.
+        self.scripts = []
+        for s in config.packaging.scripts:
+            s = "bin/" + s
+            self.scripts.append(s)
+
+        # Suffix for libraries that will be stripped of symbols.
+        if opSys == "linux":
+            libSuffix = ".so"
+        elif opSys == "darwin":
+            libSuffix = ".dylib"
+        elif opSys == "win":
+            libSuffix = ".dll"
+        else:
+            sys.exit("Unknown OS: " + opSys)
+
+        self.stripList = []
+        if opSys == "win":
+            for f in config.packaging.strip_list:
+                fdll = f.replace("lib/lib", "bin/cyg")+"-0"+libSuffix
+                if fdll in self.libraries:
+                    self.stripList.append(fdll)
+        else:
+            for f in config.packaging.strip_list:
+                flib = f+libSuffix
+                if flib in self.libraries:
+                    self.stripList.append(flib)
+
+        cig = [("CIG", "cig", "http://www.geodynamics.org/")]
+        self.urls = cig + tupleUp(config.packaging.urls, 3)
+
+        return
+
+
+    def addFile(self, f):
+        self.misc.append(f)
+
+    def addDirectory(self, d):
+        self.directories.append(d)
+        newFiles = walkDirTree(d)
+        newFiles = filterList(newFiles, self.exclude)
+        self.misc.extend(newFiles)
+
+
+    def files(self):
+        for f in self.programs:
+            yield f
+        for f in self.libraries:
+            yield f
+        for f in self.misc:
+            yield f
+        for f in self.extraFiles:
+            yield f
+        return
+
+
+    def all(self):
+        for d in self.directories:
+            yield d
+        for f in self.files():
+            yield f
+        return
+
+
+def tupleUp(l, n):
+    tuples = []
+    i = iter(l)
+    try:
+        while True:
+            t = []
+            for count in xrange(n):
+                t.append(i.next())
+            tuples.append(tuple(t))
+    except StopIteration:
+        pass
+    return tuples
+
+
+def spawn(*argv):
+    print ' '.join(argv)
+    status = os.spawnvp(os.P_WAIT, argv[0], argv)
+    if status != 0:
+        statusMsg = "%s: %s: exit %d" % (sys.argv[0], argv[0], status)
+        sys.exit(statusMsg)
+    return
+
+
+def ospawn(*argv):
+    print ' '.join(argv)
+    child = Popen4(argv)
+
+    child.tochild.close()
+
+    output = child.fromchild.readlines()
+    status = child.wait()
+
+    exitStatus = None
+    if (os.WIFSIGNALED(status)):
+        statusStr = "signal %d" % os.WTERMSIG(status)
+    elif (os.WIFEXITED(status)):
+        exitStatus = os.WEXITSTATUS(status)
+        statusStr = "exit %d" % exitStatus
+    else:
+        statusStr = "status %d" % status
+    if exitStatus != 0:
+        sys.exit("%s: %s: %s" % (sys.argv[0], argv[0], statusStr))
+
+    return output
+
+
+def cygpath(*args):
+    output = ospawn("cygpath", *args)
+    return output[0].rstrip()
+
+
+def getGitInfo(srcdir):
+    workdir = os.getcwd()
+    os.chdir(srcdir)
+    output = ospawn("git", "branch", "-v")
+    os.chdir(workdir)
+    revision = "unknown"
+    for line in output:
+        if line[0] == "*":
+            values = line.split()
+            revision = values[2]
+    return revision
+
+
+def itwindirs(l, sourceDir):
+    for src in l:
+        if isinstance(src, tuple):
+            src, dest = src
+        elif isabs(src):
+            dest = src[1:]
+        else:
+            dest = src
+        src = cygpath("-w", src)
+        if src.startswith(sourceDir):
+            src = src[len(sourceDir)+1:]
+        dest = "{app}\\" + dest.replace("/", "\\")
+        yield src, dest
+    return
+
+
+def itwinfiles(l, sourceDir):
+    for src in l:
+        if isinstance(src, tuple):
+            src, dest = src
+        elif isabs(src):
+            dest = dirname(src)[1:]
+        else:
+            dest = dirname(src)
+        src = cygpath("-w", src)
+        if src.startswith(sourceDir):
+            src = src[len(sourceDir)+1:]
+        dest = "{app}\\" + dest.replace("/", "\\")
+        yield src, dest
+    return
+
+
+def copyAll(srcList, prefix):
+    for src in srcList:
+        if isinstance(src, tuple):
+            src, dest = src
+        elif isabs(src):
+            dest = dirname(src)[1:]
+        else:
+            dest = dirname(src)
+        if not isabs(src):
+            src = join(prefix, src)
+        if not isdir(dest):
+            os.makedirs(dest)
+
+        if not isdir(src):
+            shutil.copy(src, dest) # faster than os.system() for small files
+        else:
+            os.system("cp -r %s %s" % (src, dest))
+    return
+
+
+def generateBashrc(prefix, package, info):
+    bashrc = "." + package.lower() + "rc"
+    s = open(prefix + "/" + bashrc, "w")
+
+    stuff = {
+        "line": "-" * len(info["AppVerName"]),
+        }
+    stuff.update(info)
+
+    s.write(
+r"""
+
+export PATH=/usr/bin:/bin:/lib:/lib/lapack:$PATH
+
+echo %(line)s
+echo %(AppVerName)s
+echo %(line)s
+
+PS1='\[\e]0;\w\a\]\n\[\e[32m\]\u@\h \[\e[33m\]\w\[\e[0m\]\n\$ '
+""" % stuff
+    )
+    
+    return bashrc
+
+
+def stripBinaries(pl, opSys):
+    strip = "strip"
+    if opSys == "darwin":
+        # Just plain "strip" renders our Python interpreter unusable
+        # by extension modules.
+        strip = "strip -S"
+    if len(pl.stripList) > 0:
+        status = os.system(strip + " " + " ".join(pl.stripList))
+        if status != 0:
+            sys.exit("strip: exit %d" % status)
+    return
+
+
+def rewriteScripts(pl, prefix, opSys):
+    # Tweak the shebang line of scripts so they are relative instead
+    # of absolute.
+    
+    if opSys == "win":
+        # chrooted environment
+        relative = "#!/bin/%s"
+    else:
+        relative = "#!/usr/bin/env %s"
+    absolute = "#!" + prefix + "/bin/"
+    
+    for script in pl.scripts:
+        s = open(script, "r")
+        lines = s.readlines()
+        s.close()
+        shebang = lines[0]
+        if shebang.startswith(absolute):
+            interpreter = shebang[len(absolute):]
+            shebang = relative % interpreter
+            s = open(script, "w")
+            s.write(shebang)
+            for line in lines[1:]:
+                s.write(line)
+            s.close()
+            
+    return
+
+
+def installSource(pl, taggedArchive):
+    src = "src"
+    shutil.rmtree(src, ignore_errors=True)
+    if not isdir(src):
+        os.makedirs(src)
+    spawn("tar", "-C", src, "-xf", taggedArchive)
+    pl.addDirectory(src)
+    return
+
+
+def mkpkg():
+    # WithProperties simply doesn't work in this case.
+    if False:
+        revision = sys.argv[2]
+        if revision:
+            revision = "r" + revision
+        else:
+            revision = "forced"
+    
+    makeinfo = getMakeInfo()
+    python = "python"+makeinfo['python_version']
+    distdir = makeinfo['package'] + "-" + makeinfo['version']
+    prefix = makeinfo['prefix']
+    package = makeinfo['package']
+    print "version:", makeinfo['version']
+    print "python:", python
+    print "prefix:", prefix
+    print "distdir:", distdir
+    
+    revision = getGitInfo(makeinfo['srcdir'])
+    opSys = platform.system().lower()
+    if opSys.startswith("cygwin"):
+        opSys = "win"
+    if opSys=="darwin":
+        arch = opSys + "-" + platform.mac_ver()[0]
+    else:
+        arch = opSys + "-" + (platform.processor() or platform.machine()) # Why does every last detail have to be painful?
+
+    config = Config.readPackingList()
+    if config.packaging is None:
+        sys.exit("ERROR: No packaging configuation.")
+
+    # Make source distribution (also extracted into binary package)
+    archive = distdir + ".tar.gz"
+    taggedArchive = revision + "-" + archive
+    status = os.system("make dist")
+    if status != 0:
+        sys.exit("make: exit %d" % status)
+    os.system("mv " + archive + " " + taggedArchive)
+
+    workdir = os.getcwd()
+    os.chdir(prefix)
+
+    pl = PackingList(config, opSys, python)
+
+    stripBinaries(pl, opSys)
+    rewriteScripts(pl, prefix, opSys)
+    installSource(pl, join(workdir, taggedArchive))
+
+    distdir_arch = distdir + "-" + arch
+    if opSys == "darwin" or opSys == "linux":
+        # No .dmg on Mac for now.
+        os.chdir(workdir)
+        os.system("rm " + distdir_arch)
+        os.system("ln -s " + prefix + " " + distdir_arch)
+
+        # Write packing list to file
+        plfile = open("tar_list", "w")
+        plfile.write('\n'.join([os.path.join(distdir_arch, m) for m in pl.files()]))
+        plfile.close()
+
+        archive = distdir_arch + ".tar.gz"
+        taggedArchive = revision + "-" + archive
+        status = os.system("tar cvzf " + archive + " -T tar_list")
+        if status != 0:
+            sys.exit("tar: exit %d" % status)
+
+        os.system("mv " + archive + " " + taggedArchive)
+        os.system("rm tar_list " + distdir_arch)
+        shutil.rmtree("src", ignore_errors=True)
+
+    elif opSys == "win":
+        stage = cygwin.stageInstallation(prefix, workdir, python, pl)
+        cygwin.createInstaller(python, stage, workdir, name, package, version, pl,
+                               revision + "-" + distdir_arch)
+    else:
+        sys.exit("unknown OS: " + opSys)
+
+    return
+
+
+if __name__ == "__main__":
+    mkpkg()
diff --git a/packager/packinglist.cfg b/packager/packinglist.cfg
new file mode 100644
index 0000000..2d84ab8
--- /dev/null
+++ b/packager/packinglist.cfg
@@ -0,0 +1,91 @@
+# -*- cfg -*-
+[packaging]
+
+bin_dirs =
+    bin
+
+lib_dirs =
+    lib
+
+misc_dirs =
+    etc
+    share
+
+files =
+    ./setup.sh
+
+
+strip_list =
+    lib/libpylith
+    lib/libspatialdata
+
+exclude =
+    bin/cpp$
+    bin/c\+\+$
+    bin/gcc$
+    bin/gccbug
+    bin/g\+\+$
+    bin/gcov
+    bin/gfortran$
+    bin/.*-.*-c\+\+.*
+    bin/.*-.*-g\+\+.*
+    bin/.*-.*-gcc.*
+    bin/.*-.*-gfortran.*
+    bin/mpicc
+    bin/mpicxx
+    bin/mpic\+\+
+    bin/mpif77
+    bin/mpif90
+    bin/TOPSGenerator\.py
+    bin/TOPSInstaller\.py
+    bin/adiforfix\.py
+    bin/adprocess\.py
+    bin/2to3
+    bin/bfort
+    bin/bib2html
+    bin/bsp_virtual
+    bin/configVars\.py
+    bin/doc2lt
+    bin/doctext
+    bin/f2py
+    bin/maint/.*
+    bin/matio\.py
+    bin/matlab/.*
+    bin/parseargs\.py
+    bin/petsc_libtool
+    bin/petscmpiexec
+    bin/petscrun
+    bin/popup
+    bin/portabilitycheck\.py
+    bin/processSummary\.py
+    bin/pstogif
+    bin/pstoxbm
+    bin/task_manager
+    bin/taucc\.py
+    bin/tohtml
+    bin/update\.py
+    bin/urlget
+    bin/urlget\.py
+    bin/win32fe/.*
+    share/man/man1/cpp\.1
+    share/man/man1/g\+\+\.1
+    share/man/man1/gcc\.1
+    share/man/man1/gfortran\.1
+    share/man/man3/.*
+    share/info/.*
+    share/doc/.*
+    lib/.*\.a
+    lib/gcc/.*-.*/.*
+
+scripts =
+    pylith
+    pylithinfo
+    pylith_genxdmf
+
+#    pyconvert.py
+#    gensimpledb.py
+#    powerlaw_gendb.py
+
+
+
+



More information about the CIG-COMMITS mailing list