def buildAPP(self, output, platform): output = Filename(output) if output.isDirectory() and output.getExtension() != "app": output = Filename(output, "%s.app" % self.fullname) Installer.notify.info("Creating %s..." % output) # Create the executable for the application bundle exefile = Filename(output, "Contents/MacOS/" + self.shortname) exefile.makeDir() if self.includeRequires: extraTokens = {"host_dir": "../Resources"} else: extraTokens = {} self.standalone.build(exefile, platform, extraTokens) hostDir = Filename(output, "Contents/Resources/") hostDir.makeDir() self.installPackagesInto(hostDir, platform) # Create the application plist file. # Although it might make more sense to use Python's plistlib module here, # it is not available on non-OSX systems before Python 2.6. plist = open(Filename(output, "Contents/Info.plist").toOsSpecific(), "w") print >> plist, '<?xml version="1.0" encoding="UTF-8"?>' print >> plist, '<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">' print >> plist, '<plist version="1.0">' print >> plist, "<dict>" print >> plist, "\t<key>CFBundleDevelopmentRegion</key>" print >> plist, "\t<string>English</string>" print >> plist, "\t<key>CFBundleDisplayName</key>" print >> plist, "\t<string>%s</string>" % self.fullname print >> plist, "\t<key>CFBundleExecutable</key>" print >> plist, "\t<string>%s</string>" % exefile.getBasename() print >> plist, "\t<key>CFBundleIdentifier</key>" print >> plist, "\t<string>%s.%s</string>" % (self.authorid, self.shortname) print >> plist, "\t<key>CFBundleInfoDictionaryVersion</key>" print >> plist, "\t<string>6.0</string>" print >> plist, "\t<key>CFBundleName</key>" print >> plist, "\t<string>%s</string>" % self.shortname print >> plist, "\t<key>CFBundlePackageType</key>" print >> plist, "\t<string>APPL</string>" print >> plist, "\t<key>CFBundleShortVersionString</key>" print >> plist, "\t<string>%s</string>" % self.version print >> plist, "\t<key>CFBundleVersion</key>" print >> plist, "\t<string>%s</string>" % self.version print >> plist, "\t<key>LSHasLocalizedDisplayName</key>" print >> plist, "\t<false/>" print >> plist, "\t<key>NSAppleScriptEnabled</key>" print >> plist, "\t<false/>" print >> plist, "\t<key>NSPrincipalClass</key>" print >> plist, "\t<string>NSApplication</string>" print >> plist, "</dict>" print >> plist, "</plist>" plist.close() return output
def buildArch(self, output, platform): """ Builds an ArchLinux package and stores it in the path indicated by the 'output' argument. It will be built for the architecture specified by the 'arch' argument. If 'output' is a directory, the deb file will be stored in it. """ arch = platform.rsplit("_", 1)[-1] assert arch in ("i386", "amd64") arch = {"i386": "i686", "amd64": "x86_64"}[arch] pkgver = self.version + "-1" output = Filename(output) if output.isDirectory(): output = Filename(output, "%s-%s-%s.pkg.tar.gz" % (self.shortname.lower(), pkgver, arch)) Installer.notify.info("Creating %s..." % output) modtime = int(time.time()) # Create a temporary directory and write the launcher and dependencies to it. tempdir, totsize = self.__buildTempLinux(platform) # Create a pkginfo file in memory. pkginfo = StringIO() print >> pkginfo, "# Generated using pdeploy" print >> pkginfo, "# %s" % time.ctime(modtime) print >> pkginfo, "pkgname = %s" % self.shortname.lower() print >> pkginfo, "pkgver = %s" % pkgver print >> pkginfo, "pkgdesc = %s" % self.fullname print >> pkginfo, "builddate = %s" % modtime print >> pkginfo, "packager = %s <%s>" % (self.authorname, self.authoremail) print >> pkginfo, "size = %d" % totsize print >> pkginfo, "arch = %s" % arch if self.licensename != "": print >> pkginfo, "license = %s" % self.licensename pkginfoinfo = TarInfoRoot(".PKGINFO") pkginfoinfo.mtime = modtime pkginfoinfo.size = pkginfo.tell() pkginfo.seek(0) # Create the actual package now. pkgfile = tarfile.open(output.toOsSpecific(), "w:gz", tarinfo=TarInfoRoot) pkgfile.addfile(pkginfoinfo, pkginfo) pkgfile.add(tempdir.toOsSpecific(), "/") if not self.licensefile.empty(): pkgfile.add(self.licensefile.toOsSpecific(), "/usr/share/licenses/%s/LICENSE" % self.shortname.lower()) pkgfile.close() return output
shortname = appFilename.getBasenameWoExtension() if shortname.lower() != shortname or " " in shortname: print "\nProvided short name should be lowercase, and may not contain spaces!\n" if version == "" and deploy_mode == "installer": print '\nA version number is required in "installer" mode.\n' sys.exit(1) if not outputDir: print "\nYou must name the output directory with the -o parameter.\n" sys.exit(1) if not outputDir.exists(): print "\nThe specified output directory does not exist!\n" sys.exit(1) elif not outputDir.isDirectory(): print "\nThe specified output directory is a file!\n" sys.exit(1) if deploy_mode == "standalone": s = Standalone(appFilename, tokens) s.basename = shortname if currentPlatform: platform = PandaSystem.getPlatform() if platform.startswith("win"): s.build(Filename(outputDir, shortname + ".exe"), platform) else: s.build(Filename(outputDir, shortname), platform) elif len(platforms) == 0: s.buildAll(outputDir)
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 buildDEB(self, output, platform): """ Builds a .deb archive and stores it in the path indicated by the 'output' argument. It will be built for the architecture specified by the 'arch' argument. If 'output' is a directory, the deb file will be stored in it. """ arch = platform.rsplit("_", 1)[-1] output = Filename(output) if output.isDirectory(): output = Filename(output, "%s_%s_%s.deb" % (self.shortname.lower(), self.version, arch)) Installer.notify.info("Creating %s..." % output) modtime = int(time.time()) # Create a temporary directory and write the launcher and dependencies to it. tempdir, totsize = self.__buildTempLinux(platform) # Create a control file in memory. controlfile = StringIO() print >> controlfile, "Package: %s" % self.shortname.lower() print >> controlfile, "Version: %s" % self.version print >> controlfile, "Maintainer: %s <%s>" % (self.authorname, self.authoremail) print >> controlfile, "Section: games" print >> controlfile, "Priority: optional" print >> controlfile, "Architecture: %s" % arch print >> controlfile, "Installed-Size: %d" % -(-totsize / 1024) print >> controlfile, "Description: %s" % self.fullname print >> controlfile, "Depends: libc6, libgcc1, libstdc++6, libx11-6" controlinfo = TarInfoRoot("control") controlinfo.mtime = modtime controlinfo.size = controlfile.tell() controlfile.seek(0) # Open the deb file and write to it. It's actually # just an AR file, which is very easy to make. if output.exists(): output.unlink() debfile = open(output.toOsSpecific(), "wb") debfile.write("!<arch>\x0A") debfile.write("debian-binary %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 4)) debfile.write("2.0\x0A") # Write the control.tar.gz to the archive. debfile.write("control.tar.gz %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 0)) ctaroffs = debfile.tell() ctarfile = tarfile.open("control.tar.gz", "w:gz", debfile, tarinfo=TarInfoRoot) ctarfile.addfile(controlinfo, controlfile) ctarfile.close() ctarsize = debfile.tell() - ctaroffs if ctarsize & 1: debfile.write("\x0A") # Write the data.tar.gz to the archive. debfile.write("data.tar.gz %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 0)) dtaroffs = debfile.tell() dtarfile = tarfile.open("data.tar.gz", "w:gz", debfile, tarinfo=TarInfoRoot) dtarfile.add(Filename(tempdir, "usr").toOsSpecific(), "/usr") dtarfile.close() dtarsize = debfile.tell() - dtaroffs if dtarsize & 1: debfile.write("\x0A") # Write the correct sizes of the archives. debfile.seek(ctaroffs - 12) debfile.write("%-10ld" % ctarsize) debfile.seek(dtaroffs - 12) debfile.write("%-10ld" % dtarsize) debfile.close() return output
shortname = appFilename.getBasenameWoExtension() if shortname.lower() != shortname or ' ' in shortname: print '\nProvided short name should be lowercase, and may not contain spaces!\n' if version == '' and deploy_mode == 'installer': print '\nA version number is required in "installer" mode.\n' sys.exit(1) if not outputDir: print '\nYou must name the output directory with the -o parameter.\n' sys.exit(1) if not outputDir.exists(): print '\nThe specified output directory does not exist!\n' sys.exit(1) elif not outputDir.isDirectory(): print '\nThe specified output directory is a file!\n' sys.exit(1) if deploy_mode == 'standalone': s = Standalone(appFilename, tokens) s.basename = shortname if currentPlatform: platform = PandaSystem.getPlatform() if platform.startswith("win"): s.build(Filename(outputDir, shortname + ".exe"), platform) else: s.build(Filename(outputDir, shortname), platform) elif len(platforms) == 0: s.buildAll(outputDir)
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 buildDEB(self, output, platform): """ Builds a .deb archive and stores it in the path indicated by the 'output' argument. It will be built for the architecture specified by the 'arch' argument. If 'output' is a directory, the deb file will be stored in it. """ arch = platform.rsplit("_", 1)[-1] output = Filename(output) if output.isDirectory(): output = Filename( output, "%s_%s_%s.deb" % (self.shortname.lower(), self.version, arch)) Installer.notify.info("Creating %s..." % output) modtime = int(time.time()) # Create a temporary directory and write the launcher and dependencies to it. tempdir, totsize = self.__buildTempLinux(platform) # Create a control file in memory. controlfile = StringIO() print >> controlfile, "Package: %s" % self.shortname.lower() print >> controlfile, "Version: %s" % self.version print >> controlfile, "Maintainer: %s <%s>" % (self.authorname, self.authoremail) print >> controlfile, "Section: games" print >> controlfile, "Priority: optional" print >> controlfile, "Architecture: %s" % arch print >> controlfile, "Installed-Size: %d" % -(-totsize / 1024) print >> controlfile, "Description: %s" % self.fullname print >> controlfile, "Depends: libc6, libgcc1, libstdc++6, libx11-6" controlinfo = TarInfoRoot("control") controlinfo.mtime = modtime controlinfo.size = controlfile.tell() controlfile.seek(0) # Open the deb file and write to it. It's actually # just an AR file, which is very easy to make. if output.exists(): output.unlink() debfile = open(output.toOsSpecific(), "wb") debfile.write("!<arch>\x0A") debfile.write( "debian-binary %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 4)) debfile.write("2.0\x0A") # Write the control.tar.gz to the archive. debfile.write( "control.tar.gz %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 0)) ctaroffs = debfile.tell() ctarfile = tarfile.open("control.tar.gz", "w:gz", debfile, tarinfo=TarInfoRoot) ctarfile.addfile(controlinfo, controlfile) ctarfile.close() ctarsize = debfile.tell() - ctaroffs if (ctarsize & 1): debfile.write("\x0A") # Write the data.tar.gz to the archive. debfile.write( "data.tar.gz %-12lu0 0 100644 %-10ld\x60\x0A" % (modtime, 0)) dtaroffs = debfile.tell() dtarfile = tarfile.open("data.tar.gz", "w:gz", debfile, tarinfo=TarInfoRoot) dtarfile.add(Filename(tempdir, "usr").toOsSpecific(), "/usr") dtarfile.close() dtarsize = debfile.tell() - dtaroffs if (dtarsize & 1): debfile.write("\x0A") # Write the correct sizes of the archives. debfile.seek(ctaroffs - 12) debfile.write("%-10ld" % ctarsize) debfile.seek(dtaroffs - 12) debfile.write("%-10ld" % dtarsize) debfile.close() return output