def getExtraFiles(self, platform):
        """ Returns a list of extra files that will need to be included
        with the standalone executable in order for it to run, such as
        dependent libraries. The returned paths are full absolute paths. """

        package = self.host.getPackages(name="p3dembed", platform=platform)[0]

        if not package.downloadDescFile(self.http):
            Standalone.notify.warning("  -> %s failed for platform %s" % (package.packageName, package.platform))
            return []
        if not package.downloadPackage(self.http):
            Standalone.notify.warning("  -> %s failed for platform %s" % (package.packageName, package.platform))
            return []

        filenames = []
        vfs = VirtualFileSystem.getGlobalPtr()
        for e in package.extracts:
            if e.basename not in [
                "p3dembed",
                "p3dembed.exe",
                "p3dembed.exe.manifest",
                "p3dembedw.exe",
                "p3dembedw.exe.manifest",
            ]:
                filename = Filename(package.getPackageDir(), e.filename)
                filename.makeAbsolute()
                if vfs.exists(filename):
                    filenames.append(filename)
                else:
                    Standalone.notify.error("%s mentioned in xml, but does not exist" % e.filename)

        return filenames
    def getExtraFiles(self, platform):
        """ Returns a list of extra files that will need to be included
        with the standalone executable in order for it to run, such as
        dependent libraries. The returned paths are full absolute paths. """

        package = self.host.getPackages(name="p3dembed", platform=platform)[0]

        if not package.downloadDescFile(self.http):
            Standalone.notify.warning("  -> %s failed for platform %s" %
                                      (package.packageName, package.platform))
            return []
        if not package.downloadPackage(self.http):
            Standalone.notify.warning("  -> %s failed for platform %s" %
                                      (package.packageName, package.platform))
            return []

        filenames = []
        vfs = VirtualFileSystem.getGlobalPtr()
        for e in package.extracts:
            if e.basename not in [
                    "p3dembed", "p3dembed.exe", "p3dembed.exe.manifest",
                    "p3dembedw.exe", "p3dembedw.exe.manifest"
            ]:
                filename = Filename(package.getPackageDir(), e.filename)
                filename.makeAbsolute()
                if vfs.exists(filename):
                    filenames.append(filename)
                else:
                    Standalone.notify.error(
                        "%s mentioned in xml, but does not exist" % e.filename)

        return filenames
    def buildNSIS(self, output, platform):
        # Check if we have makensis first
        makensis = None
        if sys.platform.startswith("win"):
            syspath = os.defpath.split(";") + os.environ["PATH"].split(";")
            for p in set(syspath):
                p1 = os.path.join(p, "makensis.exe")
                p2 = os.path.join(os.path.dirname(p), "nsis", "makensis.exe")
                if os.path.isfile(p1):
                    makensis = p1
                    break
                elif os.path.isfile(p2):
                    makensis = p2
                    break
            if not makensis:
                import pandac

                makensis = os.path.dirname(os.path.dirname(pandac.__file__))
                makensis = os.path.join(makensis, "nsis", "makensis.exe")
                if not os.path.isfile(makensis):
                    makensis = None
        else:
            for p in os.defpath.split(":") + os.environ["PATH"].split(":"):
                if os.path.isfile(os.path.join(p, "makensis")):
                    makensis = os.path.join(p, "makensis")

        if makensis == None:
            Installer.notify.warning("Makensis utility not found, no Windows installer will be built!")
            return None

        output = Filename(output)
        if output.isDirectory():
            output = Filename(output, "%s %s.exe" % (self.fullname, self.version))
        Installer.notify.info("Creating %s..." % output)
        output.makeAbsolute()
        extrafiles = self.standalone.getExtraFiles(platform)

        exefile = Filename(Filename.getTempDirectory(), self.shortname + ".exe")
        exefile.unlink()
        if self.includeRequires:
            extraTokens = {"host_dir": "."}
        else:
            extraTokens = {}
        self.standalone.build(exefile, platform, extraTokens)

        # Temporary directory to store the hostdir in
        hostDir = Filename(self.tempDir, platform + "/")
        if not hostDir.exists():
            hostDir.makeDir()
            self.installPackagesInto(hostDir, platform)

        nsifile = Filename(Filename.getTempDirectory(), self.shortname + ".nsi")
        nsifile.unlink()
        nsi = open(nsifile.toOsSpecific(), "w")

        # Some global info
        nsi.write('Name "%s"\n' % self.fullname)
        nsi.write('OutFile "%s"\n' % output.toOsSpecific())
        nsi.write('InstallDir "$PROGRAMFILES\\%s"\n' % self.fullname)
        nsi.write("SetCompress auto\n")
        nsi.write("SetCompressor lzma\n")
        nsi.write("ShowInstDetails nevershow\n")
        nsi.write("ShowUninstDetails nevershow\n")
        nsi.write('InstType "Typical"\n')

        # Tell Vista that we require admin rights
        nsi.write("RequestExecutionLevel admin\n")
        nsi.write("\n")
        nsi.write("Function launch\n")
        nsi.write('  ExecShell "open" "$INSTDIR\\%s.exe"\n' % self.shortname)
        nsi.write("FunctionEnd\n")
        nsi.write("\n")
        nsi.write('!include "MUI2.nsh"\n')
        nsi.write("!define MUI_ABORTWARNING\n")
        nsi.write("!define MUI_FINISHPAGE_RUN\n")
        nsi.write("!define MUI_FINISHPAGE_RUN_FUNCTION launch\n")
        nsi.write('!define MUI_FINISHPAGE_RUN_TEXT "Run %s"\n' % self.fullname)
        nsi.write("\n")
        nsi.write("Var StartMenuFolder\n")
        nsi.write("!insertmacro MUI_PAGE_WELCOME\n")
        if not self.licensefile.empty():
            abs = Filename(self.licensefile)
            abs.makeAbsolute()
            nsi.write('!insertmacro MUI_PAGE_LICENSE "%s"\n' % abs.toOsSpecific())
        nsi.write("!insertmacro MUI_PAGE_DIRECTORY\n")
        nsi.write("!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder\n")
        nsi.write("!insertmacro MUI_PAGE_INSTFILES\n")
        nsi.write("!insertmacro MUI_PAGE_FINISH\n")
        nsi.write("!insertmacro MUI_UNPAGE_WELCOME\n")
        nsi.write("!insertmacro MUI_UNPAGE_CONFIRM\n")
        nsi.write("!insertmacro MUI_UNPAGE_INSTFILES\n")
        nsi.write("!insertmacro MUI_UNPAGE_FINISH\n")
        nsi.write('!insertmacro MUI_LANGUAGE "English"\n')

        # This section defines the installer.
        nsi.write('Section "" SecCore\n')
        nsi.write('  SetOutPath "$INSTDIR"\n')
        nsi.write('  File "%s"\n' % exefile.toOsSpecific())
        for f in extrafiles:
            nsi.write('  File "%s"\n' % f.toOsSpecific())
        curdir = ""
        for root, dirs, files in self.os_walk(hostDir.toOsSpecific()):
            for name in files:
                file = Filename.fromOsSpecific(os.path.join(root, name))
                file.makeAbsolute()
                file.makeRelativeTo(hostDir)
                outdir = file.getDirname().replace("/", "\\")
                if curdir != outdir:
                    nsi.write('  SetOutPath "$INSTDIR\\%s"\n' % outdir)
                    curdir = outdir
                nsi.write('  File "%s"\n' % os.path.join(root, name))
        nsi.write('  WriteUninstaller "$INSTDIR\\Uninstall.exe"\n')
        nsi.write("  ; Start menu items\n")
        nsi.write("  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application\n")
        nsi.write('    CreateDirectory "$SMPROGRAMS\\$StartMenuFolder"\n')
        nsi.write(
            '    CreateShortCut "$SMPROGRAMS\\$StartMenuFolder\\%s.lnk" "$INSTDIR\\%s.exe"\n'
            % (self.fullname, self.shortname)
        )
        nsi.write('    CreateShortCut "$SMPROGRAMS\\$StartMenuFolder\\Uninstall.lnk" "$INSTDIR\\Uninstall.exe"\n')
        nsi.write("  !insertmacro MUI_STARTMENU_WRITE_END\n")
        nsi.write("SectionEnd\n")

        # This section defines the uninstaller.
        nsi.write("Section Uninstall\n")
        nsi.write('  Delete "$INSTDIR\\%s.exe"\n' % self.shortname)
        for f in extrafiles:
            nsi.write('  Delete "%s"\n' % f.getBasename())
        nsi.write('  Delete "$INSTDIR\\Uninstall.exe"\n')
        nsi.write('  RMDir /r "$INSTDIR"\n')
        nsi.write("  ; Start menu items\n")
        nsi.write("  !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder\n")
        nsi.write('  Delete "$SMPROGRAMS\\$StartMenuFolder\\Uninstall.lnk"\n')
        nsi.write('  RMDir "$SMPROGRAMS\\$StartMenuFolder"\n')
        nsi.write("SectionEnd")
        nsi.close()

        cmd = [makensis]
        for o in ["V2"]:
            if sys.platform.startswith("win"):
                cmd.append("/" + o)
            else:
                cmd.append("-" + o)
        cmd.append(nsifile.toOsSpecific())
        print cmd
        try:
            retcode = subprocess.call(cmd, shell=False)
            if retcode != 0:
                self.notify.warning("Failure invoking NSIS command.")
        except OSError:
            self.notify.warning("Unable to invoke NSIS command.")

        nsifile.unlink()
        return output
    def buildPKG(self, output, platform):
        appfn = self.buildAPP(output, platform)
        appname = "/Applications/" + appfn.getBasename()
        output = Filename(output)
        if output.isDirectory():
            output = Filename(output, "%s %s.pkg" % (self.fullname, self.version))
        Installer.notify.info("Creating %s..." % output)

        Filename(output, "Contents/Resources/en.lproj/").makeDir()
        if self.licensefile:
            shutil.copyfile(
                self.licensefile.toOsSpecific(), Filename(output, "Contents/Resources/License.txt").toOsSpecific()
            )
        pkginfo = open(Filename(output, "Contents/PkgInfo").toOsSpecific(), "w")
        pkginfo.write("pkmkrpkg1")
        pkginfo.close()
        pkginfo = open(Filename(output, "Contents/Resources/package_version").toOsSpecific(), "w")
        pkginfo.write("major: 1\nminor: 9")
        pkginfo.close()

        # Although it might make more sense to use Python's plistlib here,
        # it is not available on non-OSX systems before Python 2.6.
        plist = open(Filename(output, "Contents/Info.plist").toOsSpecific(), "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write("<dict>\n")
        plist.write("\t<key>CFBundleIdentifier</key>\n")
        plist.write("\t<string>%s.pkg.%s</string>\n" % (self.authorid, self.shortname))
        plist.write("\t<key>CFBundleShortVersionString</key>\n")
        plist.write("\t<string>%s</string>\n" % self.version)
        plist.write("\t<key>IFMajorVersion</key>\n")
        plist.write("\t<integer>1</integer>\n")
        plist.write("\t<key>IFMinorVersion</key>\n")
        plist.write("\t<integer>9</integer>\n")
        plist.write("\t<key>IFPkgFlagAllowBackRev</key>\n")
        plist.write("\t<false/>\n")
        plist.write("\t<key>IFPkgFlagAuthorizationAction</key>\n")
        plist.write("\t<string>RootAuthorization</string>\n")
        plist.write("\t<key>IFPkgFlagDefaultLocation</key>\n")
        plist.write("\t<string>/</string>\n")
        plist.write("\t<key>IFPkgFlagFollowLinks</key>\n")
        plist.write("\t<true/>\n")
        plist.write("\t<key>IFPkgFlagIsRequired</key>\n")
        plist.write("\t<false/>\n")
        plist.write("\t<key>IFPkgFlagOverwritePermissions</key>\n")
        plist.write("\t<false/>\n")
        plist.write("\t<key>IFPkgFlagRelocatable</key>\n")
        plist.write("\t<false/>\n")
        plist.write("\t<key>IFPkgFlagRestartAction</key>\n")
        plist.write("\t<string>None</string>\n")
        plist.write("\t<key>IFPkgFlagRootVolumeOnly</key>\n")
        plist.write("\t<true/>\n")
        plist.write("\t<key>IFPkgFlagUpdateInstalledLanguages</key>\n")
        plist.write("\t<false/>\n")
        plist.write("\t<key>IFPkgFormatVersion</key>\n")
        plist.write("\t<real>0.10000000149011612</real>\n")
        plist.write("\t<key>IFPkgPathMappings</key>\n")
        plist.write("\t<dict>\n")
        plist.write("\t\t<key>%s</key>\n" % appname)
        plist.write("\t\t<string>{pkmk-token-2}</string>\n")
        plist.write("\t</dict>\n")
        plist.write("</dict>\n")
        plist.write("</plist>\n")
        plist.close()

        plist = open(Filename(output, "Contents/Resources/TokenDefinitions.plist").toOsSpecific(), "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write("<dict>\n")
        plist.write("\t<key>pkmk-token-2</key>\n")
        plist.write("\t<array>\n")
        plist.write("\t\t<dict>\n")
        plist.write("\t\t\t<key>identifier</key>\n")
        plist.write("\t\t\t<string>%s.%s</string>\n" % (self.authorid, self.shortname))
        plist.write("\t\t\t<key>path</key>\n")
        plist.write("\t\t\t<string>%s</string>\n" % appname)
        plist.write("\t\t\t<key>searchPlugin</key>\n")
        plist.write("\t\t\t<string>CommonAppSearch</string>\n")
        plist.write("\t\t</dict>\n")
        plist.write("\t</array>\n")
        plist.write("</dict>\n")
        plist.write("</plist>\n")
        plist.close()

        plist = open(Filename(output, "Contents/Resources/en.lproj/Description.plist").toOsSpecific(), "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write("<dict>\n")
        plist.write("\t<key>IFPkgDescriptionDescription</key>\n")
        plist.write("\t<string></string>\n")
        plist.write("\t<key>IFPkgDescriptionTitle</key>\n")
        plist.write("\t<string>%s</string>\n" % self.fullname)
        plist.write("</dict>\n")
        plist.write("</plist>\n")
        plist.close()

        if hasattr(tarfile, "PAX_FORMAT"):
            archive = tarfile.open(
                Filename(output, "Contents/Archive.pax.gz").toOsSpecific(),
                "w:gz",
                format=tarfile.PAX_FORMAT,
                tarinfo=TarInfoRootOSX,
            )
        else:
            archive = tarfile.open(
                Filename(output, "Contents/Archive.pax.gz").toOsSpecific(), "w:gz", tarinfo=TarInfoRootOSX
            )
        archive.add(appfn.toOsSpecific(), appname)
        archive.close()

        # Put the .pkg into a zipfile
        archive = Filename(output.getDirname(), "%s %s.zip" % (self.fullname, self.version))
        dir = Filename(output.getDirname())
        dir.makeAbsolute()
        zip = zipfile.ZipFile(archive.toOsSpecific(), "w")
        for root, dirs, files in self.os_walk(output.toOsSpecific()):
            for name in files:
                file = Filename.fromOsSpecific(os.path.join(root, name))
                file.makeAbsolute()
                file.makeRelativeTo(dir)
                zip.write(os.path.join(root, name), str(file))
        zip.close()

        return output
    def buildNSIS(self, output, platform):
        # Check if we have makensis first
        makensis = None
        if (sys.platform.startswith("win")):
            syspath = os.defpath.split(";") + os.environ["PATH"].split(";")
            for p in set(syspath):
                p1 = os.path.join(p, "makensis.exe")
                p2 = os.path.join(os.path.dirname(p), "nsis", "makensis.exe")
                if os.path.isfile(p1):
                    makensis = p1
                    break
                elif os.path.isfile(p2):
                    makensis = p2
                    break
            if not makensis:
                import pandac
                makensis = os.path.dirname(os.path.dirname(pandac.__file__))
                makensis = os.path.join(makensis, "nsis", "makensis.exe")
                if not os.path.isfile(makensis): makensis = None
        else:
            for p in os.defpath.split(":") + os.environ["PATH"].split(":"):
                if os.path.isfile(os.path.join(p, "makensis")):
                    makensis = os.path.join(p, "makensis")

        if makensis == None:
            Installer.notify.warning(
                "Makensis utility not found, no Windows installer will be built!"
            )
            return None

        output = Filename(output)
        if output.isDirectory():
            output = Filename(output,
                              "%s %s.exe" % (self.fullname, self.version))
        Installer.notify.info("Creating %s..." % output)
        output.makeAbsolute()
        extrafiles = self.standalone.getExtraFiles(platform)

        exefile = Filename(Filename.getTempDirectory(),
                           self.shortname + ".exe")
        exefile.unlink()
        if self.includeRequires:
            extraTokens = {"host_dir": "."}
        else:
            extraTokens = {}
        self.standalone.build(exefile, platform, extraTokens)

        # Temporary directory to store the hostdir in
        hostDir = Filename(self.tempDir, platform + "/")
        if not hostDir.exists():
            hostDir.makeDir()
            self.installPackagesInto(hostDir, platform)

        nsifile = Filename(Filename.getTempDirectory(),
                           self.shortname + ".nsi")
        nsifile.unlink()
        nsi = open(nsifile.toOsSpecific(), "w")

        # Some global info
        nsi.write('Name "%s"\n' % self.fullname)
        nsi.write('OutFile "%s"\n' % output.toOsSpecific())
        nsi.write('InstallDir "$PROGRAMFILES\\%s"\n' % self.fullname)
        nsi.write('SetCompress auto\n')
        nsi.write('SetCompressor lzma\n')
        nsi.write('ShowInstDetails nevershow\n')
        nsi.write('ShowUninstDetails nevershow\n')
        nsi.write('InstType "Typical"\n')

        # Tell Vista that we require admin rights
        nsi.write('RequestExecutionLevel admin\n')
        nsi.write('\n')
        nsi.write('Function launch\n')
        nsi.write('  ExecShell "open" "$INSTDIR\\%s.exe"\n' % self.shortname)
        nsi.write('FunctionEnd\n')
        nsi.write('\n')
        nsi.write('!include "MUI2.nsh"\n')
        nsi.write('!define MUI_ABORTWARNING\n')
        nsi.write('!define MUI_FINISHPAGE_RUN\n')
        nsi.write('!define MUI_FINISHPAGE_RUN_FUNCTION launch\n')
        nsi.write('!define MUI_FINISHPAGE_RUN_TEXT "Run %s"\n' % self.fullname)
        nsi.write('\n')
        nsi.write('Var StartMenuFolder\n')
        nsi.write('!insertmacro MUI_PAGE_WELCOME\n')
        if not self.licensefile.empty():
            abs = Filename(self.licensefile)
            abs.makeAbsolute()
            nsi.write('!insertmacro MUI_PAGE_LICENSE "%s"\n' %
                      abs.toOsSpecific())
        nsi.write('!insertmacro MUI_PAGE_DIRECTORY\n')
        nsi.write(
            '!insertmacro MUI_PAGE_STARTMENU Application $StartMenuFolder\n')
        nsi.write('!insertmacro MUI_PAGE_INSTFILES\n')
        nsi.write('!insertmacro MUI_PAGE_FINISH\n')
        nsi.write('!insertmacro MUI_UNPAGE_WELCOME\n')
        nsi.write('!insertmacro MUI_UNPAGE_CONFIRM\n')
        nsi.write('!insertmacro MUI_UNPAGE_INSTFILES\n')
        nsi.write('!insertmacro MUI_UNPAGE_FINISH\n')
        nsi.write('!insertmacro MUI_LANGUAGE "English"\n')

        # This section defines the installer.
        nsi.write('Section "" SecCore\n')
        nsi.write('  SetOutPath "$INSTDIR"\n')
        nsi.write('  File "%s"\n' % exefile.toOsSpecific())
        for f in extrafiles:
            nsi.write('  File "%s"\n' % f.toOsSpecific())
        curdir = ""
        for root, dirs, files in self.os_walk(hostDir.toOsSpecific()):
            for name in files:
                file = Filename.fromOsSpecific(os.path.join(root, name))
                file.makeAbsolute()
                file.makeRelativeTo(hostDir)
                outdir = file.getDirname().replace('/', '\\')
                if curdir != outdir:
                    nsi.write('  SetOutPath "$INSTDIR\\%s"\n' % outdir)
                    curdir = outdir
                nsi.write('  File "%s"\n' % os.path.join(root, name))
        nsi.write('  WriteUninstaller "$INSTDIR\\Uninstall.exe"\n')
        nsi.write('  ; Start menu items\n')
        nsi.write('  !insertmacro MUI_STARTMENU_WRITE_BEGIN Application\n')
        nsi.write('    CreateDirectory "$SMPROGRAMS\\$StartMenuFolder"\n')
        nsi.write(
            '    CreateShortCut "$SMPROGRAMS\\$StartMenuFolder\\%s.lnk" "$INSTDIR\\%s.exe"\n'
            % (self.fullname, self.shortname))
        nsi.write(
            '    CreateShortCut "$SMPROGRAMS\\$StartMenuFolder\\Uninstall.lnk" "$INSTDIR\\Uninstall.exe"\n'
        )
        nsi.write('  !insertmacro MUI_STARTMENU_WRITE_END\n')
        nsi.write('SectionEnd\n')

        # This section defines the uninstaller.
        nsi.write('Section Uninstall\n')
        nsi.write('  Delete "$INSTDIR\\%s.exe"\n' % self.shortname)
        for f in extrafiles:
            nsi.write('  Delete "%s"\n' % f.getBasename())
        nsi.write('  Delete "$INSTDIR\\Uninstall.exe"\n')
        nsi.write('  RMDir /r "$INSTDIR"\n')
        nsi.write('  ; Start menu items\n')
        nsi.write(
            '  !insertmacro MUI_STARTMENU_GETFOLDER Application $StartMenuFolder\n'
        )
        nsi.write('  Delete "$SMPROGRAMS\\$StartMenuFolder\\Uninstall.lnk"\n')
        nsi.write('  RMDir "$SMPROGRAMS\\$StartMenuFolder"\n')
        nsi.write('SectionEnd')
        nsi.close()

        cmd = [makensis]
        for o in ["V2"]:
            if sys.platform.startswith("win"):
                cmd.append("/" + o)
            else:
                cmd.append("-" + o)
        cmd.append(nsifile.toOsSpecific())
        print cmd
        try:
            retcode = subprocess.call(cmd, shell=False)
            if retcode != 0:
                self.notify.warning("Failure invoking NSIS command.")
        except OSError:
            self.notify.warning("Unable to invoke NSIS command.")

        nsifile.unlink()
        return output
    def buildPKG(self, output, platform):
        appfn = self.buildAPP(output, platform)
        appname = "/Applications/" + appfn.getBasename()
        output = Filename(output)
        if output.isDirectory():
            output = Filename(output,
                              "%s %s.pkg" % (self.fullname, self.version))
        Installer.notify.info("Creating %s..." % output)

        Filename(output, "Contents/Resources/en.lproj/").makeDir()
        if self.licensefile:
            shutil.copyfile(
                self.licensefile.toOsSpecific(),
                Filename(output,
                         "Contents/Resources/License.txt").toOsSpecific())
        pkginfo = open(
            Filename(output, "Contents/PkgInfo").toOsSpecific(), "w")
        pkginfo.write("pkmkrpkg1")
        pkginfo.close()
        pkginfo = open(
            Filename(output,
                     "Contents/Resources/package_version").toOsSpecific(), "w")
        pkginfo.write("major: 1\nminor: 9")
        pkginfo.close()

        # Although it might make more sense to use Python's plistlib here,
        # it is not available on non-OSX systems before Python 2.6.
        plist = open(
            Filename(output, "Contents/Info.plist").toOsSpecific(), "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write('<dict>\n')
        plist.write('\t<key>CFBundleIdentifier</key>\n')
        plist.write('\t<string>%s.pkg.%s</string>\n' %
                    (self.authorid, self.shortname))
        plist.write('\t<key>CFBundleShortVersionString</key>\n')
        plist.write('\t<string>%s</string>\n' % self.version)
        plist.write('\t<key>IFMajorVersion</key>\n')
        plist.write('\t<integer>1</integer>\n')
        plist.write('\t<key>IFMinorVersion</key>\n')
        plist.write('\t<integer>9</integer>\n')
        plist.write('\t<key>IFPkgFlagAllowBackRev</key>\n')
        plist.write('\t<false/>\n')
        plist.write('\t<key>IFPkgFlagAuthorizationAction</key>\n')
        plist.write('\t<string>RootAuthorization</string>\n')
        plist.write('\t<key>IFPkgFlagDefaultLocation</key>\n')
        plist.write('\t<string>/</string>\n')
        plist.write('\t<key>IFPkgFlagFollowLinks</key>\n')
        plist.write('\t<true/>\n')
        plist.write('\t<key>IFPkgFlagIsRequired</key>\n')
        plist.write('\t<false/>\n')
        plist.write('\t<key>IFPkgFlagOverwritePermissions</key>\n')
        plist.write('\t<false/>\n')
        plist.write('\t<key>IFPkgFlagRelocatable</key>\n')
        plist.write('\t<false/>\n')
        plist.write('\t<key>IFPkgFlagRestartAction</key>\n')
        plist.write('\t<string>None</string>\n')
        plist.write('\t<key>IFPkgFlagRootVolumeOnly</key>\n')
        plist.write('\t<true/>\n')
        plist.write('\t<key>IFPkgFlagUpdateInstalledLanguages</key>\n')
        plist.write('\t<false/>\n')
        plist.write('\t<key>IFPkgFormatVersion</key>\n')
        plist.write('\t<real>0.10000000149011612</real>\n')
        plist.write('\t<key>IFPkgPathMappings</key>\n')
        plist.write('\t<dict>\n')
        plist.write('\t\t<key>%s</key>\n' % appname)
        plist.write('\t\t<string>{pkmk-token-2}</string>\n')
        plist.write('\t</dict>\n')
        plist.write('</dict>\n')
        plist.write('</plist>\n')
        plist.close()

        plist = open(
            Filename(
                output,
                "Contents/Resources/TokenDefinitions.plist").toOsSpecific(),
            "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write('<dict>\n')
        plist.write('\t<key>pkmk-token-2</key>\n')
        plist.write('\t<array>\n')
        plist.write('\t\t<dict>\n')
        plist.write('\t\t\t<key>identifier</key>\n')
        plist.write('\t\t\t<string>%s.%s</string>\n' %
                    (self.authorid, self.shortname))
        plist.write('\t\t\t<key>path</key>\n')
        plist.write('\t\t\t<string>%s</string>\n' % appname)
        plist.write('\t\t\t<key>searchPlugin</key>\n')
        plist.write('\t\t\t<string>CommonAppSearch</string>\n')
        plist.write('\t\t</dict>\n')
        plist.write('\t</array>\n')
        plist.write('</dict>\n')
        plist.write('</plist>\n')
        plist.close()

        plist = open(
            Filename(output, "Contents/Resources/en.lproj/Description.plist").
            toOsSpecific(), "w")
        plist.write('<?xml version="1.0" encoding="UTF-8"?>\n')
        plist.write(
            '<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">\n'
        )
        plist.write('<plist version="1.0">\n')
        plist.write('<dict>\n')
        plist.write('\t<key>IFPkgDescriptionDescription</key>\n')
        plist.write('\t<string></string>\n')
        plist.write('\t<key>IFPkgDescriptionTitle</key>\n')
        plist.write('\t<string>%s</string>\n' % self.fullname)
        plist.write('</dict>\n')
        plist.write('</plist>\n')
        plist.close()

        if hasattr(tarfile, "PAX_FORMAT"):
            archive = tarfile.open(Filename(
                output, "Contents/Archive.pax.gz").toOsSpecific(),
                                   "w:gz",
                                   format=tarfile.PAX_FORMAT,
                                   tarinfo=TarInfoRootOSX)
        else:
            archive = tarfile.open(Filename(
                output, "Contents/Archive.pax.gz").toOsSpecific(),
                                   "w:gz",
                                   tarinfo=TarInfoRootOSX)
        archive.add(appfn.toOsSpecific(), appname)
        archive.close()

        # Put the .pkg into a zipfile
        archive = Filename(output.getDirname(),
                           "%s %s.zip" % (self.fullname, self.version))
        dir = Filename(output.getDirname())
        dir.makeAbsolute()
        zip = zipfile.ZipFile(archive.toOsSpecific(), 'w')
        for root, dirs, files in self.os_walk(output.toOsSpecific()):
            for name in files:
                file = Filename.fromOsSpecific(os.path.join(root, name))
                file.makeAbsolute()
                file.makeRelativeTo(dir)
                zip.write(os.path.join(root, name), str(file))
        zip.close()

        return output