Browse Source

Made it work on linux

rdb 17 years ago
parent
commit
cafd7c93f9
1 changed files with 162 additions and 55 deletions
  1. 162 55
      direct/src/directscripts/packpanda.py

+ 162 - 55
direct/src/directscripts/packpanda.py

@@ -1,7 +1,8 @@
 #############################################################################
 #############################################################################
 #
 #
 # packpanda - this is a tool that packages up a panda game into a
 # packpanda - this is a tool that packages up a panda game into a
-# convenient, easily-downloaded windows executable.  Packpanda relies on
+# convenient, easily-downloaded windows executable.  Packpanda runs on linux
+# and windows - on linux, it builds .debs and .rpms, on windows it relies on
 # NSIS, the nullsoft scriptable install system, to do the hard work.
 # NSIS, the nullsoft scriptable install system, to do the hard work.
 #
 #
 # This is intentionally a very simplistic game-packer with very
 # This is intentionally a very simplistic game-packer with very
@@ -12,7 +13,7 @@
 #
 #
 ##############################################################################
 ##############################################################################
 
 
-import sys, os, getopt, string, shutil, py_compile
+import sys, os, getopt, string, shutil, py_compile, subprocess
 
 
 OPTIONLIST = [
 OPTIONLIST = [
 ("dir",       1, "Name of directory containing game"),
 ("dir",       1, "Name of directory containing game"),
@@ -76,12 +77,14 @@ if (PANDA is None):
   sys.exit("Cannot locate the panda root directory in the python path (cannot locate directory containing direct and pandac).")
   sys.exit("Cannot locate the panda root directory in the python path (cannot locate directory containing direct and pandac).")
 print "PANDA located at "+PANDA
 print "PANDA located at "+PANDA
 
 
-if (os.path.exists(os.path.join(PANDA,"..","makepanda","makepanda.py"))) and (os.path.exists(os.path.join(PANDA,"..","thirdparty","win-nsis","makensis.exe"))):
+if (os.path.exists(os.path.join(PANDA,"..","makepanda","makepanda.py"))) and (sys.platform != "win32" or os.path.exists(os.path.join(PANDA,"..","thirdparty","win-nsis","makensis.exe"))):
   PSOURCE=os.path.abspath(os.path.join(PANDA,".."))
   PSOURCE=os.path.abspath(os.path.join(PANDA,".."))
-  NSIS=os.path.abspath(os.path.join(PANDA,"..","thirdparty","win-nsis"))
+  if (sys.platform == "win32"):
+    NSIS=os.path.abspath(os.path.join(PANDA,"..","thirdparty","win-nsis"))
 else:
 else:
   PSOURCE=PANDA
   PSOURCE=PANDA
-  NSIS=os.path.join(PANDA,"nsis")
+  if (sys.platform == "win32"):
+    NSIS=os.path.join(PANDA,"nsis")
 
 
 ##############################################################################
 ##############################################################################
 #
 #
@@ -95,21 +98,26 @@ if (DIR==""):
   print "You must specify the --dir option."
   print "You must specify the --dir option."
   ParseFailure()
   ParseFailure()
 DIR=os.path.abspath(DIR)
 DIR=os.path.abspath(DIR)
-NAME=os.path.basename(DIR)
+MYDIR=os.path.abspath(os.getcwd())
+BASENAME=os.path.basename(DIR)
 if (OPTIONS["name"] != ""):
 if (OPTIONS["name"] != ""):
   NAME=OPTIONS["name"]
   NAME=OPTIONS["name"]
+else:
+  NAME=BASENAME
 SMDIRECTORY=NAME
 SMDIRECTORY=NAME
 if (VER!=""): SMDIRECTORY=SMDIRECTORY+" "+VER
 if (VER!=""): SMDIRECTORY=SMDIRECTORY+" "+VER
-ICON=os.path.join(DIR, "icon.ico")
-BITMAP=os.path.join(DIR, "installer.bmp")
+PYTHONV="python"+sys.version[:3]
 LICENSE=os.path.join(DIR, "license.txt")
 LICENSE=os.path.join(DIR, "license.txt")
 OUTFILE=os.path.basename(DIR)
 OUTFILE=os.path.basename(DIR)
 if (VER!=""): OUTFILE=OUTFILE+"-"+VER
 if (VER!=""): OUTFILE=OUTFILE+"-"+VER
-OUTFILE=os.path.abspath(OUTFILE+".exe")
-INSTALLDIR='C:\\'+os.path.basename(DIR)
-if (VER!=""): INSTALLDIR=INSTALLDIR+"-"+VER
-COMPRESS="lzma"
-if (OPTIONS["fast"]): COMPRESS="zlib"
+if (sys.platform == "win32"):
+  ICON=os.path.join(DIR, "icon.ico")
+  BITMAP=os.path.join(DIR, "installer.bmp")
+  OUTFILE=os.path.abspath(OUTFILE+".exe")
+  INSTALLDIR='C:\\'+os.path.basename(DIR)
+  if (VER!=""): INSTALLDIR=INSTALLDIR+"-"+VER
+  COMPRESS="lzma"
+  if (OPTIONS["fast"]): COMPRESS="zlib"
 if (OPTIONS["pyc"]): MAIN="main.pyc"
 if (OPTIONS["pyc"]): MAIN="main.pyc"
 else: MAIN="main.py"
 else: MAIN="main.py"
 
 
@@ -123,11 +131,13 @@ PrintFileStatus("Dir", DIR)
 print "%-15s: %s"%("Name", NAME)
 print "%-15s: %s"%("Name", NAME)
 print "%-15s: %s"%("Start Menu", SMDIRECTORY)
 print "%-15s: %s"%("Start Menu", SMDIRECTORY)
 PrintFileStatus("Main", os.path.join(DIR, MAIN))
 PrintFileStatus("Main", os.path.join(DIR, MAIN))
-PrintFileStatus("Icon", ICON)
-PrintFileStatus("Bitmap", BITMAP)
+if (sys.platform == "win32"):
+  PrintFileStatus("Icon", ICON)
+  PrintFileStatus("Bitmap", BITMAP)
 PrintFileStatus("License", LICENSE)
 PrintFileStatus("License", LICENSE)
 print "%-15s: %s"%("Output", OUTFILE)
 print "%-15s: %s"%("Output", OUTFILE)
-print "%-15s: %s"%("Install Dir", INSTALLDIR)
+if (sys.platform == "win32"):
+  print "%-15s: %s"%("Install Dir", INSTALLDIR)
 
 
 if (os.path.isdir(DIR)==0):
 if (os.path.isdir(DIR)==0):
   sys.exit("Difficulty reading "+DIR+". Cannot continue.")
   sys.exit("Difficulty reading "+DIR+". Cannot continue.")
@@ -138,13 +148,14 @@ if (os.path.isfile(os.path.join(DIR, "main.py"))==0):
 if (os.path.isfile(LICENSE)==0):
 if (os.path.isfile(LICENSE)==0):
   LICENSE=os.path.join(PANDA,"LICENSE")
   LICENSE=os.path.join(PANDA,"LICENSE")
 
 
-if (os.path.isfile(BITMAP)==0):
+if (sys.platform == "win32") and (os.path.isfile(BITMAP)==0):
   BITMAP=os.path.join(NSIS,"Contrib","Graphics","Wizard","nsis.bmp")
   BITMAP=os.path.join(NSIS,"Contrib","Graphics","Wizard","nsis.bmp")
 
 
-if (os.path.isfile(ICON)==0):
-  PPICON="bin\\ppython.exe"
-else:
-  PPICON="game\\icon.ico"
+if (sys.platform == "win32"):
+  if (os.path.isfile(ICON)==0):
+    PPICON="bin\\ppython.exe"
+  else:
+    PPICON="game\\icon.ico"
 
 
 ##############################################################################
 ##############################################################################
 #
 #
@@ -156,7 +167,7 @@ def limitedCopyTree(src, dst, rmdir):
     if (os.path.isdir(src)):
     if (os.path.isdir(src)):
         if (rmdir.has_key(os.path.basename(src))):
         if (rmdir.has_key(os.path.basename(src))):
             return
             return
-        os.mkdir(dst)
+        if (not os.path.isdir(dst)): os.mkdir(dst)
         for x in os.listdir(src):
         for x in os.listdir(src):
             limitedCopyTree(os.path.join(src,x), os.path.join(dst,x), rmdir)
             limitedCopyTree(os.path.join(src,x), os.path.join(dst,x), rmdir)
     else:
     else:
@@ -164,8 +175,12 @@ def limitedCopyTree(src, dst, rmdir):
 
 
 
 
 TMPDIR=os.path.abspath("packpanda-TMP")
 TMPDIR=os.path.abspath("packpanda-TMP")
-TMPGAME=os.path.join(TMPDIR,"game")
-TMPETC=os.path.join(TMPDIR,"etc")
+if (sys.platform == "win32"):
+  TMPGAME=os.path.join(TMPDIR,"game")
+  TMPETC=os.path.join(TMPDIR,"etc")
+else:
+  TMPGAME=os.path.join(TMPDIR,"usr","share","games",BASENAME,"game")
+  TMPETC=os.path.join(TMPDIR,"usr","share","games",BASENAME,"etc")
 print ""
 print ""
 print "Copying the game to "+TMPDIR+"..."
 print "Copying the game to "+TMPDIR+"..."
 if (os.path.exists(TMPDIR)):
 if (os.path.exists(TMPDIR)):
@@ -176,12 +191,16 @@ try:
     rmdir = {}
     rmdir = {}
     for x in OPTIONS["rmdir"]:
     for x in OPTIONS["rmdir"]:
         rmdir[x] = 1
         rmdir[x] = 1
-    limitedCopyTree(DIR, TMPGAME, rmdir)
     if not os.path.isdir( TMPGAME ):
     if not os.path.isdir( TMPGAME ):
-        os.mkdir(TMPGAME)
-    limitedCopyTree(os.path.join(PANDA, "etc"), TMPETC, {})
+        os.makedirs(TMPGAME)
+    limitedCopyTree(DIR, TMPGAME, rmdir)
     if not os.path.isdir( TMPETC ):
     if not os.path.isdir( TMPETC ):
-        os.mkdir(TMPETC)
+        os.makedirs(TMPETC)
+    if sys.platform == "win32":
+      limitedCopyTree(os.path.join(PANDA, "etc"), TMPETC, {})
+    else:
+      shutil.copyfile("/etc/Config.prc", os.path.join(TMPETC, "Config.prc"))
+      shutil.copyfile("/etc/Confauto.prc", os.path.join(TMPETC, "Confauto.prc"))
 except: sys.exit("Cannot copy game to "+TMPDIR)
 except: sys.exit("Cannot copy game to "+TMPDIR)
 
 
 ##############################################################################
 ##############################################################################
@@ -219,14 +238,20 @@ if OPTIONS["bam"]:
 #
 #
 ##############################################################################
 ##############################################################################
 
 
-EGG2BAM=os.path.join(PANDA,"bin","egg2bam.exe")
+if (sys.platform == "win32"):
+  EGG2BAM=os.path.join(PANDA,"bin","egg2bam.exe")
+else:
+  EGG2BAM=os.path.join(PANDA,"bin","egg2bam")
 
 
 def egg2bam(file,bam):
 def egg2bam(file,bam):
     present = os.path.exists(bam)
     present = os.path.exists(bam)
     if (present): bam = "packpanda-TMP.bam";
     if (present): bam = "packpanda-TMP.bam";
     cmd = 'egg2bam -noabs -ps rel -pd . "'+file+'" -o "'+bam+'"'
     cmd = 'egg2bam -noabs -ps rel -pd . "'+file+'" -o "'+bam+'"'
     print "Executing: "+cmd
     print "Executing: "+cmd
-    res = os.spawnl(os.P_WAIT, EGG2BAM, cmd)
+    if (sys.platform == "win32"):
+      res = os.spawnl(os.P_WAIT, EGG2BAM, cmd)
+    else:
+      res = os.system(cmd)
     if (res != 0): sys.exit("Problem in egg file: "+file)
     if (res != 0): sys.exit("Problem in egg file: "+file)
     if (present) or (OPTIONS["bam"]==0):
     if (present) or (OPTIONS["bam"]==0):
         os.unlink(bam)
         os.unlink(bam)
@@ -283,32 +308,114 @@ DeleteFiles(".")
 
 
 ##############################################################################
 ##############################################################################
 #
 #
-# Run NSIS. Yay!
+# Now make the installer. Yay!
 #
 #
 ##############################################################################
 ##############################################################################
 
 
-CMD="\""+NSIS+"\\makensis.exe\" /V2 "
-CMD=CMD+'/DCOMPRESSOR="'+COMPRESS+'" '
-CMD=CMD+'/DNAME="'+NAME+'" '
-CMD=CMD+'/DSMDIRECTORY="'+SMDIRECTORY+'" '
-CMD=CMD+'/DINSTALLDIR="'+INSTALLDIR+'" '
-CMD=CMD+'/DOUTFILE="'+OUTFILE+'" '
-CMD=CMD+'/DLICENSE="'+LICENSE+'" '
-CMD=CMD+'/DLANGUAGE="English" '
-CMD=CMD+'/DRUNTEXT="Play '+NAME+'" '
-CMD=CMD+'/DIBITMAP="'+BITMAP+'" '
-CMD=CMD+'/DUBITMAP="'+BITMAP+'" '
-CMD=CMD+'/DPANDA="'+PANDA+'" '
-CMD=CMD+'/DPANDACONF="'+TMPETC+'" '
-CMD=CMD+'/DPSOURCE="'+PSOURCE+'" '
-CMD=CMD+'/DPPGAME="'+TMPGAME+'" '
-CMD=CMD+'/DPPMAIN="'+MAIN+'" '
-CMD=CMD+'/DPPICON="'+PPICON+'" '
-CMD=CMD+'"'+PSOURCE+'\\direct\\src\\directscripts\\packpanda.nsi"'
-
-print ""
-print CMD
-print "packing..."
-os.system(CMD)
-
+INSTALLER_DEB_FILE="""
+Package: BASENAME
+Version: VERSION
+Section: games
+Priority: optional
+Architecture: ARCH
+Essential: no
+Depends: PYTHONV
+Provides: BASENAME
+Description: NAME
+Maintainer: Unknown
+"""
+
+INSTALLER_SPEC_FILE="""
+Summary: NAME
+Name: BASENAME
+Version: VERSION
+Release: 1
+Group: Amusement/Games
+License: See license file
+BuildRoot: TMPDIR
+BuildRequires: PYTHONV
+%description
+NAME
+%files
+%defattr(-,root,root)
+/usr/bin/BASENAME
+/usr/lib/games/BASENAME
+/usr/share/games/BASENAME
+"""
+
+RUN_SCRIPT="""
+#!/bin/sh
+cd /usr/share/games/BASENAME/game
+PYTHONPATH=/usr/lib/games/BASENAME:/usr/share/games/BASENAME
+LD_LIBRARY_PATH=/usr/lib/games/BASENAME
+PYTHONV MAIN
+"""
+
+if (sys.platform == "win32"):
+    CMD="\""+NSIS+"\\makensis.exe\" /V2 "
+    CMD=CMD+'/DCOMPRESSOR="'+COMPRESS+'" '
+    CMD=CMD+'/DNAME="'+NAME+'" '
+    CMD=CMD+'/DSMDIRECTORY="'+SMDIRECTORY+'" '
+    CMD=CMD+'/DINSTALLDIR="'+INSTALLDIR+'" '
+    CMD=CMD+'/DOUTFILE="'+OUTFILE+'" '
+    CMD=CMD+'/DLICENSE="'+LICENSE+'" '
+    CMD=CMD+'/DLANGUAGE="English" '
+    CMD=CMD+'/DRUNTEXT="Play '+NAME+'" '
+    CMD=CMD+'/DIBITMAP="'+BITMAP+'" '
+    CMD=CMD+'/DUBITMAP="'+BITMAP+'" '
+    CMD=CMD+'/DPANDA="'+PANDA+'" '
+    CMD=CMD+'/DPANDACONF="'+TMPETC+'" '
+    CMD=CMD+'/DPSOURCE="'+PSOURCE+'" '
+    CMD=CMD+'/DPPGAME="'+TMPGAME+'" '
+    CMD=CMD+'/DPPMAIN="'+MAIN+'" '
+    CMD=CMD+'/DPPICON="'+PPICON+'" '
+    CMD=CMD+'"'+PSOURCE+'\\direct\\src\\directscripts\\packpanda.nsi"' 
+    
+    print ""
+    print CMD
+    print "packing..."
+    subprocess.call(CMD)
+else:
+    os.chdir(MYDIR)
+    os.system("mkdir -p %s/usr/bin" % TMPDIR)
+    os.system("mkdir -p %s/usr/share/games/%s" % (TMPDIR, BASENAME))
+    os.system("mkdir -p %s/usr/lib/games/%s" % (TMPDIR, BASENAME))
+    os.system("cp --recursive %s/direct          %s/usr/share/games/%s/direct" % (PANDA, TMPDIR, BASENAME))
+    os.system("cp --recursive %s/pandac          %s/usr/share/games/%s/pandac" % (PANDA, TMPDIR, BASENAME))
+    os.system("cp --recursive %s/models          %s/usr/share/games/%s/models" % (PANDA, TMPDIR, BASENAME))
+    os.system("cp --recursive %s/Pmw             %s/usr/share/games/%s/Pmw" % (PANDA, TMPDIR, BASENAME))
+    os.system("cp %s                             %s/usr/share/games/%s/LICENSE" % (LICENSE, TMPDIR, BASENAME))
+    os.system("cp --recursive /usr/lib/panda3d/* %s/usr/lib/games/%s/" % (TMPDIR, BASENAME))
+    
+    # Make the script to run the game
+    txt = RUN_SCRIPT[1:].replace("BASENAME",BASENAME).replace("PYTHONV",PYTHONV).replace("MAIN",MAIN)
+    WriteFile(TMPDIR+"/usr/bin/"+BASENAME, txt)
+    os.system("chmod +x "+TMPDIR+"/usr/bin/"+BASENAME)
+    
+    if (os.path.exists("/usr/bin/rpmbuild")):
+        os.system("rm -rf %s/DEBIAN" % TMPDIR)
+        os.system("rpm -E '%_target_cpu' > packpanda-TMP.txt")
+        ARCH=ReadFile("packpanda-TMP.txt").strip()
+        os.remove("packpanda-TMP.txt")
+        txt = INSTALLER_SPEC_FILE[1:].replace("VERSION",VER).replace("TMPDIR",TMPDIR)
+        txt = txt.replace("BASENAME",BASENAME).replace("NAME",NAME).replace("PYTHONV",PYTHONV)
+        WriteFile("packpanda-TMP.spec", txt)
+        os.system("rpmbuild --define '_rpmdir "+TMPDIR+"' -bb packpanda-TMP.spec")
+        os.system("mv "+ARCH+"/"+BASENAME+"-"+VER+"-1."+ARCH+".rpm .")
+        os.rmdir(ARCH)
+        os.remove("packpanda-TMP.spec")
+    
+    if (os.path.exists("/usr/bin/dpkg-deb")):
+        os.system("dpkg --print-architecture > packpanda-TMP.txt")
+        ARCH=ReadFile("packpanda-TMP.txt").strip()
+        os.remove("packpanda-TMP.txt")
+        txt = INSTALLER_DEB_FILE[1:].replace("VERSION",str(VER)).replace("PYTHONV",PYTHONV)
+        txt = txt.replace("BASENAME",BASENAME).replace("NAME",NAME).replace("ARCH",ARCH)
+        os.system("mkdir -p %s/DEBIAN" % TMPDIR)
+        os.system("cd %s ; (find usr -type f -exec md5sum {} \;) >  DEBIAN/md5sums" % TMPDIR)
+        WriteFile(TMPDIR+"/DEBIAN/control",txt)
+        os.system("dpkg-deb -b "+TMPDIR+" "+BASENAME+"_"+VER+"_"+ARCH+".deb")
+    
+    if not(os.path.exists("/usr/bin/rpmbuild") or os.path.exists("/usr/bin/dpkg-deb")):
+        exit("To build an installer, either rpmbuild or dpkg-deb must be present on your system!")