Browse Source

Python 3 support, and a compile fix

rdb 13 years ago
parent
commit
62a4e4122c
3 changed files with 355 additions and 312 deletions
  1. 33 38
      makepanda/installpanda.py
  2. 193 187
      makepanda/makepanda.py
  3. 129 87
      makepanda/makepandacore.py

+ 33 - 38
makepanda/installpanda.py

@@ -39,59 +39,56 @@ APP_INFO_PLUGIN = (
 def WriteApplicationsFile(fname, appinfo, mimeinfo):
 def WriteApplicationsFile(fname, appinfo, mimeinfo):
     fhandle = open(fname, "w")
     fhandle = open(fname, "w")
     for app, desc, exts in appinfo:
     for app, desc, exts in appinfo:
-        print >>fhandle, app
-        print >>fhandle, "\tcommand=" + app
-        print >>fhandle, "\tname=" + desc
-        print >>fhandle, "\tcan_open_multiple_files=true"
-        print >>fhandle, "\texpects_uris=false"
-        print >>fhandle, "\trequires_terminal=false"
-        print >>fhandle, "\tmime_types=",
+        fhandle.write("%s\n" % (app))
+        fhandle.write("\tcommand=%s\n" % (app))
+        fhandle.write("\tname=%s\n" % (desc))
+        fhandle.write("\tcan_open_multiple_files=true\n")
+        fhandle.write("\texpects_uris=false\n")
+        fhandle.write("\trequires_terminal=false\n")
+        fhandle.write("\tmime_types=")
         first = True
         first = True
         for ext, mime, desc2, app2 in mimeinfo:
         for ext, mime, desc2, app2 in mimeinfo:
-            if (ext in exts):
-                if (first):
+            if ext in exts:
+                if first:
                     fhandle.write(mime)
                     fhandle.write(mime)
                     first = False
                     first = False
                 else:
                 else:
                     fhandle.write("," + mime)
                     fhandle.write("," + mime)
-        fhandle.write("\n")
-        print >>fhandle
+        fhandle.write("\n\n")
     fhandle.close()
     fhandle.close()
 
 
 def WriteMimeXMLFile(fname, info):
 def WriteMimeXMLFile(fname, info):
     fhandle = open(fname, "w")
     fhandle = open(fname, "w")
-    print >>fhandle, "<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
-    print >>fhandle
-    print >>fhandle, "<mime-info xmlns=\"http://www.freedesktop.org/standards/shared-mime-info\">"
+    fhandle.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n")
+    fhandle.write("<mime-info xmlns=\"http://www.freedesktop.org/standards/shared-mime-info\">\n")
     for ext, mime, desc, app in info:
     for ext, mime, desc, app in info:
-        print >>fhandle, "\t<mime-type type=\"" + mime + "\">"
-        print >>fhandle, "\t\t<comment xml:lang=\"en\">" + desc + "</comment>"
-        print >>fhandle, "\t\t<glob pattern=\"*." + ext + "\"/>"
-        print >>fhandle, "\t</mime-type>"
-    print >>fhandle, "</mime-info>"
-    print >>fhandle
+        fhandle.write("\t<mime-type type=\"%s\">\n" % (mime))
+        fhandle.write("\t\t<comment xml:lang=\"en\">%s</comment>\n" % (desc))
+        fhandle.write("\t\t<glob pattern=\"*.%s\"/>\n" % (ext))
+        fhandle.write("\t</mime-type>\s")
+    fhandle.write("</mime-info>\n")
     fhandle.close()
     fhandle.close()
 
 
 def WriteMimeFile(fname, info):
 def WriteMimeFile(fname, info):
     fhandle = open(fname, "w")
     fhandle = open(fname, "w")
     for ext, mime, desc, app in info:
     for ext, mime, desc, app in info:
-        print >>fhandle, mime + ":"
-        if ("." in ext):
-            print >>fhandle, "\tregex,2: " + ext.replace(".", "\\.") + "$"
-        print >>fhandle, "\text: " + ext
-        print >>fhandle
+        fhandle.write("%s:\n" % (mime))
+        if "." in ext:
+            fhandle.write("\tregex,2: %s$\n" % (ext.replace(".", "\\.")))
+        fhandle.write("\text: %s\n" % (ext))
+        fhandle.write("\n")
     fhandle.close()
     fhandle.close()
 
 
 def WriteKeysFile(fname, info):
 def WriteKeysFile(fname, info):
     fhandle = open(fname, "w")
     fhandle = open(fname, "w")
     for ext, mime, desc, app in info:
     for ext, mime, desc, app in info:
-        print >>fhandle, mime + ":"
-        print >>fhandle, "\tdescription=" + desc
-        print >>fhandle, "\tdefault_action_type=application"
-        print >>fhandle, "\tshort_list_application_ids_for_novice_user_level=" + app
-        print >>fhandle, "\topen=" + app + " %f"
-        print >>fhandle, "\tview=" + app + " %f"
-        print >>fhandle
+        fhandle.write("%s:\n" % (mime))
+        fhandle.write("\tdescription=%s\n" % (desc))
+        fhandle.write("\tdefault_action_type=application\n")
+        fhandle.write("\tshort_list_application_ids_for_novice_user_level=%s\n" % (app))
+        fhandle.write("\topen=%s %%f\n" % (app))
+        fhandle.write("\tview=%s %%f\n" % (app))
+        fhandle.write("\n")
     fhandle.close()
     fhandle.close()
 
 
 def GetLibDir():
 def GetLibDir():
@@ -229,9 +226,7 @@ if (__name__ == "__main__"):
     if (sys.platform.startswith("win") or sys.platform == "darwin"):
     if (sys.platform.startswith("win") or sys.platform == "darwin"):
         exit("This script is not supported on Windows or Mac OS X at the moment!")
         exit("This script is not supported on Windows or Mac OS X at the moment!")
 
 
-    destdir = "/"
-    if (os.environ.has_key("DESTDIR")):
-        destdir = os.environ["DESTDIR"]
+    destdir = os.environ.get("DESTDIR", "/")
 
 
     parser = OptionParser()
     parser = OptionParser()
     parser.add_option('', '--outputdir', dest = 'outputdir', help = 'Makepanda\'s output directory (default: built)', default = 'built')
     parser.add_option('', '--outputdir', dest = 'outputdir', help = 'Makepanda\'s output directory (default: built)', default = 'built')
@@ -249,10 +244,10 @@ if (__name__ == "__main__"):
         exit("Directory '%s' does not exist!" % destdir)
         exit("Directory '%s' does not exist!" % destdir)
 
 
     if (options.runtime):
     if (options.runtime):
-        print "Installing Panda3D Runtime into " + destdir + options.prefix
+        print("Installing Panda3D Runtime into " + destdir + options.prefix)
         InstallRuntime(destdir = destdir, prefix = options.prefix, outputdir = options.outputdir)
         InstallRuntime(destdir = destdir, prefix = options.prefix, outputdir = options.outputdir)
     else:
     else:
-        print "Installing Panda3D into " + destdir + options.prefix
+        print("Installing Panda3D into " + destdir + options.prefix)
         InstallPanda(destdir = destdir, prefix = options.prefix, outputdir = options.outputdir)
         InstallPanda(destdir = destdir, prefix = options.prefix, outputdir = options.outputdir)
-    print "Installation finished!"
+    print("Installation finished!")
 
 

+ 193 - 187
makepanda/makepanda.py

@@ -12,12 +12,16 @@
 #
 #
 ########################################################################
 ########################################################################
 try:
 try:
-    import sys,os,platform,time,stat,string,re,getopt,fnmatch,threading,Queue,signal,shutil
+    import sys,os,platform,time,stat,string,re,getopt,fnmatch,threading,signal,shutil
     if sys.platform == "darwin" or sys.version_info >= (2, 6):
     if sys.platform == "darwin" or sys.version_info >= (2, 6):
         import plistlib
         import plistlib
+    if sys.version_info >= (3, 0):
+        import queue
+    else:
+        import Queue as queue
 except:
 except:
-    print "You are either using an incomplete or an old version of Python!"
-    print "Please install the development package of Python 2.x and try again."
+    print("You are either using an incomplete or an old version of Python!")
+    print("Please install the development package of Python 2.x and try again.")
     exit(1)
     exit(1)
 
 
 from makepandacore import *
 from makepandacore import *
@@ -29,8 +33,7 @@ import sys
 ## jGenPyCode tries to get the directory for Direct from the sys.path. This only works if you 
 ## jGenPyCode tries to get the directory for Direct from the sys.path. This only works if you 
 ## have installed the sdk using a installer. This would not work if the installer was 
 ## have installed the sdk using a installer. This would not work if the installer was 
 ## never used and everything was grabbed into a virgin environment using cvs.
 ## never used and everything was grabbed into a virgin environment using cvs.
-sys.path.append( os.getcwd() )
-import __builtin__
+sys.path.append(os.getcwd())
 
 
 ########################################################################
 ########################################################################
 ##
 ##
@@ -115,45 +118,45 @@ signal.signal(signal.SIGINT, keyboardInterruptHandler)
 
 
 def usage(problem):
 def usage(problem):
     if (problem):
     if (problem):
-        print ""
-        print "Error parsing commandline input", problem
-
-    print ""
-    print "Makepanda generates a 'built' subdirectory containing a"
-    print "compiled copy of Panda3D.  Command-line arguments are:"
-    print ""
-    print "  --help            (print the help message you're reading now)"
-    print "  --verbose         (print out more information)"
-    print "  --runtime         (build a runtime build instead of an SDK build)"
-    print "  --installer       (build an installer)"
-    print "  --optimize X      (optimization level can be 1,2,3,4)"
-    print "  --version X       (set the panda version number)"
-    print "  --lzma            (use lzma compression when building Windows installer)"
-    print "  --distributor X   (short string identifying the distributor of the build)"
-    print "  --outputdir X     (use the specified directory instead of 'built')"
-    print "  --host URL        (set the host url (runtime build only))"
-    print "  --threads N       (use the multithreaded build system. see manual)"
-    print "  --osxtarget N     (the OSX version number to build for (OSX only))"
-    print "  --universal       (build universal binaries (OSX only))"
-    print "  --override \"O=V\"  (override dtool_config/prc option value)"
-    print "  --static          (builds libraries for static linking)"
-    print "  --target X        (experimental cross-compilation (android only))"
-    print "  --arch X          (target architecture for cross-compilation)"
-    print ""
+        print("")
+        print("Error parsing commandline input", problem)
+
+    print("")
+    print("Makepanda generates a 'built' subdirectory containing a")
+    print("compiled copy of Panda3D.  Command-line arguments are:")
+    print("")
+    print("  --help            (print the help message you're reading now)")
+    print("  --verbose         (print out more information)")
+    print("  --runtime         (build a runtime build instead of an SDK build)")
+    print("  --installer       (build an installer)")
+    print("  --optimize X      (optimization level can be 1,2,3,4)")
+    print("  --version X       (set the panda version number)")
+    print("  --lzma            (use lzma compression when building Windows installer)")
+    print("  --distributor X   (short string identifying the distributor of the build)")
+    print("  --outputdir X     (use the specified directory instead of 'built')")
+    print("  --host URL        (set the host url (runtime build only))")
+    print("  --threads N       (use the multithreaded build system. see manual)")
+    print("  --osxtarget N     (the OSX version number to build for (OSX only))")
+    print("  --universal       (build universal binaries (OSX only))")
+    print("  --override \"O=V\"  (override dtool_config/prc option value)")
+    print("  --static          (builds libraries for static linking)")
+    print("  --target X        (experimental cross-compilation (android only))")
+    print("  --arch X          (target architecture for cross-compilation)")
+    print("")
     for pkg in PkgListGet():
     for pkg in PkgListGet():
         p = pkg.lower()
         p = pkg.lower()
-        print "  --use-%-9s   --no-%-9s (enable/disable use of %s)"%(p, p, pkg)
-    print ""
-    print "  --nothing         (disable every third-party lib)"
-    print "  --everything      (enable every third-party lib)"
-    print "  --directx-sdk=X   (specify version of DX9 SDK to use: jun2010, aug2009, mar2009, aug2006)"
-    print "  --platform-sdk=X  (specify MSPlatSdk to use: win71, win61, win60A, winserver2003r2)"
-    print "  --use-icl         (experimental setting to use an intel compiler instead of MSVC on Windows)"
-    print ""
-    print "The simplest way to compile panda is to just type:"
-    print ""
-    print "  makepanda --everything"
-    print ""
+        print("  --use-%-9s   --no-%-9s (enable/disable use of %s)"%(p, p, pkg))
+    print("")
+    print("  --nothing         (disable every third-party lib)")
+    print("  --everything      (enable every third-party lib)")
+    print("  --directx-sdk=X   (specify version of DX9 SDK to use: jun2010, aug2009, mar2009, aug2006)")
+    print("  --platform-sdk=X  (specify MSPlatSdk to use: win71, win61, win60A, winserver2003r2)")
+    print("  --use-icl         (experimental setting to use an intel compiler instead of MSVC on Windows)")
+    print("")
+    print("The simplest way to compile panda is to just type:")
+    print("")
+    print("  makepanda --everything")
+    print("")
     os._exit(1)
     os._exit(1)
 
 
 def parseopts(args):
 def parseopts(args):
@@ -177,7 +180,7 @@ def parseopts(args):
     try:
     try:
         opts, extras = getopt.getopt(args, "", longopts)
         opts, extras = getopt.getopt(args, "", longopts)
         for option,value in opts:
         for option,value in opts:
-            if (option=="--help"): raise "usage"
+            if (option=="--help"): raise Exception
             elif (option=="--optimize"): optimize=value
             elif (option=="--optimize"): optimize=value
             elif (option=="--installer"): INSTALLER=1
             elif (option=="--installer"): INSTALLER=1
             elif (option=="--verbose"): SetVerbose(True)
             elif (option=="--verbose"): SetVerbose(True)
@@ -196,7 +199,7 @@ def parseopts(args):
             elif (option=="--nocolor"): DisableColors()
             elif (option=="--nocolor"): DisableColors()
             elif (option=="--version"):
             elif (option=="--version"):
                 VERSION=value
                 VERSION=value
-                if (len(VERSION.split(".")) != 3): raise "usage"
+                if (len(VERSION.split(".")) != 3): raise Exception
             elif (option=="--lzma"): COMPRESSOR="lzma"
             elif (option=="--lzma"): COMPRESSOR="lzma"
             elif (option=="--override"): AddOverride(value.strip())
             elif (option=="--override"): AddOverride(value.strip())
             elif (option=="--static"): SetLinkAllStatic(True)
             elif (option=="--static"): SetLinkAllStatic(True)
@@ -210,12 +213,12 @@ def parseopts(args):
             elif (option=="--directx-sdk"):
             elif (option=="--directx-sdk"):
                 STRDXSDKVERSION = value.strip().lower()
                 STRDXSDKVERSION = value.strip().lower()
                 if STRDXSDKVERSION == '':
                 if STRDXSDKVERSION == '':
-                    print "No DirectX SDK version specified. Using 'default' DirectX SDK search"
+                    print("No DirectX SDK version specified. Using 'default' DirectX SDK search")
                     STRDXSDKVERSION = 'default'
                     STRDXSDKVERSION = 'default'
             elif (option=="--platform-sdk"): 
             elif (option=="--platform-sdk"): 
                 STRMSPLATFORMVERSION = value.strip().lower()
                 STRMSPLATFORMVERSION = value.strip().lower()
                 if STRMSPLATFORMVERSION == '':
                 if STRMSPLATFORMVERSION == '':
-                    print "No MS Platform SDK version specified. Using 'default' MS Platform SDK search"
+                    print("No MS Platform SDK version specified. Using 'default' MS Platform SDK search")
                     STRMSPLATFORMVERSION = 'default'
                     STRMSPLATFORMVERSION = 'default'
             elif (option=="--use-icl"): BOOUSEINTELCOMPILER = True
             elif (option=="--use-icl"): BOOUSEINTELCOMPILER = True
             else:
             else:
@@ -232,7 +235,7 @@ def parseopts(args):
               anything = 1
               anything = 1
     except: 
     except: 
         usage(0)
         usage(0)
-        print "Exception while parsing commandline:", sys.exc_info()[0]
+        print("Exception while parsing commandline:", sys.exc_info()[0])
     if (anything==0): usage(0)
     if (anything==0): usage(0)
     if (RTDIST and RUNTIME):
     if (RTDIST and RUNTIME):
         usage("Options --runtime and --rtdist cannot be specified at the same time!")
         usage("Options --runtime and --rtdist cannot be specified at the same time!")
@@ -809,30 +812,30 @@ if GetTarget() == 'android':
 
 
 def printStatus(header,warnings):
 def printStatus(header,warnings):
     if GetVerbose():
     if GetVerbose():
-        print ""
-        print "-------------------------------------------------------------------"
-        print header
+        print("")
+        print("-------------------------------------------------------------------")
+        print(header)
         tkeep = ""
         tkeep = ""
         tomit = ""
         tomit = ""
         for x in PkgListGet():
         for x in PkgListGet():
             if (PkgSkip(x)==0): tkeep = tkeep + x + " "
             if (PkgSkip(x)==0): tkeep = tkeep + x + " "
             else:                  tomit = tomit + x + " "
             else:                  tomit = tomit + x + " "
-        if RTDIST:  print "Makepanda: Runtime distribution build"
-        elif RUNTIME: print "Makepanda: Runtime build"
-        else:        print "Makepanda: Regular build"
-        print "Makepanda: Compiler:",COMPILER
-        print "Makepanda: Optimize:",GetOptimize()
-        print "Makepanda: Keep Pkg:",tkeep
-        print "Makepanda: Omit Pkg:",tomit
-        if (GENMAN): print "Makepanda: Generate API reference manual"
-        else       : print "Makepanda: Don't generate API reference manual"
+        if RTDIST:  print("Makepanda: Runtime distribution build")
+        elif RUNTIME: print("Makepanda: Runtime build")
+        else:        print("Makepanda: Regular build")
+        print("Makepanda: Compiler:",COMPILER)
+        print("Makepanda: Optimize:",GetOptimize())
+        print("Makepanda: Keep Pkg:",tkeep)
+        print("Makepanda: Omit Pkg:",tomit)
+        if (GENMAN): print("Makepanda: Generate API reference manual")
+        else       : print("Makepanda: Don't generate API reference manual")
         if (sys.platform == "win32" and not RTDIST):
         if (sys.platform == "win32" and not RTDIST):
-            if INSTALLER:  print "Makepanda: Build installer, using",COMPRESSOR
-            else        :  print "Makepanda: Don't build installer"
-        print "Makepanda: Version ID: "+VERSION
-        for x in warnings: print "Makepanda: "+x
-        print "-------------------------------------------------------------------"
-        print ""
+            if INSTALLER:  print("Makepanda: Build installer, using",COMPRESSOR)
+            else        :  print("Makepanda: Don't build installer")
+        print("Makepanda: Version ID: "+VERSION)
+        for x in warnings: print("Makepanda: "+x)
+        print("-------------------------------------------------------------------")
+        print("")
         sys.stdout.flush()
         sys.stdout.flush()
 
 
 ########################################################################
 ########################################################################
@@ -1133,10 +1136,10 @@ def CompileIgate(woutd,wsrc,opts):
     library = GetValueOption(opts, "ILIB:")
     library = GetValueOption(opts, "ILIB:")
     ipath = GetListOption(opts, "DIR:")
     ipath = GetListOption(opts, "DIR:")
     if (PkgSkip("PYTHON")):
     if (PkgSkip("PYTHON")):
-        WriteFile(woutc,"")
-        WriteFile(woutd,"")
-        CompileCxx(wobj,woutc,opts)
-        ConditionalWriteFile(woutd,"")
+        WriteFile(woutc, "")
+        WriteFile(woutd, "")
+        CompileCxx(wobj, woutc, opts)
+        ConditionalWriteFile(woutd, "")
         return
         return
 
 
     if not CrossCompiling():
     if not CrossCompiling():
@@ -1202,8 +1205,8 @@ def CompileImod(wobj, wsrc, opts):
     if (COMPILER=="GCC"):
     if (COMPILER=="GCC"):
         woutc = wobj[:-2]+".cxx"
         woutc = wobj[:-2]+".cxx"
     if (PkgSkip("PYTHON")):
     if (PkgSkip("PYTHON")):
-        WriteFile(woutc,"")
-        CompileCxx(wobj,woutc,opts)
+        WriteFile(woutc, "")
+        CompileCxx(wobj, woutc, opts)
         return
         return
 
 
     if not CrossCompiling():
     if not CrossCompiling():
@@ -1709,15 +1712,15 @@ def CompileAnything(target, inputs, opts, progress = None):
 
 
         # Add version number to the dynamic library, on unix
         # Add version number to the dynamic library, on unix
         if origsuffix==".dll" and "MODULE" not in opts and not RTDIST:
         if origsuffix==".dll" and "MODULE" not in opts and not RTDIST:
-            target = GetTarget()
-            if target == "darwin":
+            tplatform = GetTarget()
+            if tplatform == "darwin":
                 # On Mac, libraries are named like libpanda.1.2.dylib
                 # On Mac, libraries are named like libpanda.1.2.dylib
-                if target.lower().endswith(".dylib"):
-                    target = target[:-5] + MAJOR_VERSION + ".dylib"
+                if tplatform.lower().endswith(".dylib"):
+                    tplatform = tplatform[:-5] + MAJOR_VERSION + ".dylib"
                     SetOrigExt(target, origsuffix)
                     SetOrigExt(target, origsuffix)
-            elif target != "windows" and target != "android":
+            elif tplatform != "windows" and tplatform != "android":
                 # On Linux, libraries are named like libpanda.so.1.2
                 # On Linux, libraries are named like libpanda.so.1.2
-                target = target + "." + MAJOR_VERSION
+                tplatform += "." + MAJOR_VERSION
                 SetOrigExt(target, origsuffix)
                 SetOrigExt(target, origsuffix)
         return CompileLink(target, inputs, opts)
         return CompileLink(target, inputs, opts)
     elif (origsuffix==".in"):
     elif (origsuffix==".in"):
@@ -2100,7 +2103,6 @@ def WriteConfigSettings():
             val = OverrideValue(key, prc_parameters[key])
             val = OverrideValue(key, prc_parameters[key])
             if (val == 'UNDEF'): conf = conf + "#undef " + key + "\n"
             if (val == 'UNDEF'): conf = conf + "#undef " + key + "\n"
             else:                conf = conf + "#define " + key + " " + val + "\n"
             else:                conf = conf + "#define " + key + " " + val + "\n"
-            del prc_parameters[key]
     ConditionalWriteFile(GetOutputDir() + '/include/prc_parameters.h', conf)
     ConditionalWriteFile(GetOutputDir() + '/include/prc_parameters.h', conf)
 
 
     conf = "/* dtool_config.h.  Generated automatically by makepanda.py */\n"
     conf = "/* dtool_config.h.  Generated automatically by makepanda.py */\n"
@@ -2108,7 +2110,6 @@ def WriteConfigSettings():
         val = OverrideValue(key, dtool_config[key])
         val = OverrideValue(key, dtool_config[key])
         if (val == 'UNDEF'): conf = conf + "#undef " + key + "\n"
         if (val == 'UNDEF'): conf = conf + "#undef " + key + "\n"
         else:                conf = conf + "#define " + key + " " + val + "\n"
         else:                conf = conf + "#define " + key + " " + val + "\n"
-        del dtool_config[key]
     ConditionalWriteFile(GetOutputDir() + '/include/dtool_config.h', conf)
     ConditionalWriteFile(GetOutputDir() + '/include/dtool_config.h', conf)
 
 
     if (RTDIST or RUNTIME):
     if (RTDIST or RUNTIME):
@@ -2117,7 +2118,6 @@ def WriteConfigSettings():
             val = plugin_config[key]
             val = plugin_config[key]
             if (val == 'UNDEF'): conf = conf + "#undef " + key + "\n"
             if (val == 'UNDEF'): conf = conf + "#undef " + key + "\n"
             else:                conf = conf + "#define " + key + " \"" + val.replace("\\", "\\\\") + "\"\n"
             else:                conf = conf + "#define " + key + " \"" + val.replace("\\", "\\\\") + "\"\n"
-            del plugin_config[key]
         ConditionalWriteFile(GetOutputDir() + '/include/p3d_plugin_config.h', conf)
         ConditionalWriteFile(GetOutputDir() + '/include/p3d_plugin_config.h', conf)
 
 
     if (PkgSkip("SPEEDTREE")==0):
     if (PkgSkip("SPEEDTREE")==0):
@@ -2126,7 +2126,6 @@ def WriteConfigSettings():
             val = OverrideValue(key, speedtree_parameters[key])
             val = OverrideValue(key, speedtree_parameters[key])
             if (val == 'UNDEF'): conf = conf + "#undef " + key + "\n"
             if (val == 'UNDEF'): conf = conf + "#undef " + key + "\n"
             else:                conf = conf + "#define " + key + " \"" + val.replace("\\", "\\\\") + "\"\n"
             else:                conf = conf + "#define " + key + " \"" + val.replace("\\", "\\\\") + "\"\n"
-            del speedtree_parameters[key]
         ConditionalWriteFile(GetOutputDir() + '/include/speedtree_parameters.h', conf)
         ConditionalWriteFile(GetOutputDir() + '/include/speedtree_parameters.h', conf)
 
 
     for x in PkgListGet():
     for x in PkgListGet():
@@ -2137,9 +2136,9 @@ WriteConfigSettings()
 
 
 MoveAwayConflictingFiles()
 MoveAwayConflictingFiles()
 if "libdtoolbase" in GetLibCache():
 if "libdtoolbase" in GetLibCache():
-    print "%sWARNING:%s Found conflicting Panda3D libraries from other ppremake build!" % (GetColor("red"), GetColor())
+    print("%sWARNING:%s Found conflicting Panda3D libraries from other ppremake build!" % (GetColor("red"), GetColor()))
 if "libp3dtoolconfig" in GetLibCache():
 if "libp3dtoolconfig" in GetLibCache():
-    print "%sWARNING:%s Found conflicting Panda3D libraries from other makepanda build!" % (GetColor("red"), GetColor())
+    print("%sWARNING:%s Found conflicting Panda3D libraries from other makepanda build!" % (GetColor("red"), GetColor()))
 
 
 ##########################################################################################
 ##########################################################################################
 #
 #
@@ -2672,7 +2671,7 @@ COMMON_EGG2X_LIBS_PYSTUB = COMMON_EGG2X_LIBS + ['libp3pystub.lib']
 #
 #
 ########################################################################
 ########################################################################
 
 
-print "Generating dependencies..."
+print("Generating dependencies...")
 sys.stdout.flush()
 sys.stdout.flush()
 
 
 #
 #
@@ -5677,7 +5676,7 @@ def BuildWorker(taskqueue, donequeue):
         sys.stdout.flush()
         sys.stdout.flush()
         if (task == 0): return
         if (task == 0): return
         try:
         try:
-            apply(task[0],task[1])
+            task[0](*task[1])
             donequeue.put(task)
             donequeue.put(task)
         except:
         except:
             donequeue.put(0)
             donequeue.put(0)
@@ -5699,8 +5698,8 @@ def AllSourcesReady(task, pending):
 
 
 def ParallelMake(tasklist):
 def ParallelMake(tasklist):
     # Create the communication queues.
     # Create the communication queues.
-    donequeue=Queue.Queue()
-    taskqueue=Queue.Queue()
+    donequeue = Queue.Queue()
+    taskqueue = Queue.Queue()
     # Build up a table listing all the pending targets
     # Build up a table listing all the pending targets
     #task = [CompileAnything, [name, inputs, opts], [name], deps, []]
     #task = [CompileAnything, [name, inputs, opts], [name], deps, []]
     # task[2] = [name]
     # task[2] = [name]
@@ -5727,12 +5726,12 @@ def ParallelMake(tasklist):
             pending[target] = 1
             pending[target] = 1
     # Create the workers
     # Create the workers
     for slave in range(THREADCOUNT):
     for slave in range(THREADCOUNT):
-        th = threading.Thread(target=BuildWorker, args=[taskqueue,donequeue])
+        th = threading.Thread(target=BuildWorker, args=[taskqueue, donequeue])
         th.setDaemon(1)
         th.setDaemon(1)
         th.start()
         th.start()
     # Feed tasks to the workers.
     # Feed tasks to the workers.
     tasksqueued = 0
     tasksqueued = 0
-    while (1):
+    while True:
         if (tasksqueued < THREADCOUNT):
         if (tasksqueued < THREADCOUNT):
             extras = []
             extras = []
             for task in tasklist:
             for task in tasklist:
@@ -5760,7 +5759,7 @@ def ParallelMake(tasklist):
     for slave in range(THREADCOUNT):
     for slave in range(THREADCOUNT):
         taskqueue.put(0)
         taskqueue.put(0)
     # Make sure there aren't any unsatisfied tasks
     # Make sure there aren't any unsatisfied tasks
-    if (len(tasklist)>0):
+    if len(tasklist) > 0:
         exit("Dependency problems: " + str(len(tasklist)) + " tasks not finished. First task unsatisfied: "+str(tasklist[0][2]))
         exit("Dependency problems: " + str(len(tasklist)) + " tasks not finished. First task unsatisfied: "+str(tasklist[0][2]))
     SequentialMake(tasklist_seq)
     SequentialMake(tasklist_seq)
 
 
@@ -5769,7 +5768,7 @@ def SequentialMake(tasklist):
     i = 0
     i = 0
     for task in tasklist:
     for task in tasklist:
         if (NeedsBuild(task[2], task[3])):
         if (NeedsBuild(task[2], task[3])):
-            apply(task[0], task[1] + [(i * 100.0) / len(tasklist)])
+            task[0](*task[1] + [(i * 100.0) / len(tasklist)])
             JustBuilt(task[2], task[3])
             JustBuilt(task[2], task[3])
         i += 1
         i += 1
 
 
@@ -5809,7 +5808,7 @@ def MakeInstallerNSIS(file, fullname, smdirectory, installdir):
         shutil.move("direct\\src\\plugin_installer\\p3d-setup.exe", file)
         shutil.move("direct\\src\\plugin_installer\\p3d-setup.exe", file)
         return
         return
 
 
-    print "Building "+fullname+" installer. This can take up to an hour."
+    print("Building "+fullname+" installer. This can take up to an hour.")
     if (COMPRESSOR != "lzma"):
     if (COMPRESSOR != "lzma"):
         print("Note: you are using zlib, which is faster, but lzma gives better compression.")
         print("Note: you are using zlib, which is faster, but lzma gives better compression.")
     if (os.path.exists("nsis-output.exe")):
     if (os.path.exists("nsis-output.exe")):
@@ -5838,11 +5837,11 @@ def MakeInstallerNSIS(file, fullname, smdirectory, installdir):
 
 
     if GetHost() == 'windows':
     if GetHost() == 'windows':
         cmd = os.path.join(GetThirdpartyBase(), 'win-nsis', 'makensis') + ' /V2'
         cmd = os.path.join(GetThirdpartyBase(), 'win-nsis', 'makensis') + ' /V2'
-        for item in nsis_defs.iteritems():
+        for item in nsis_defs.items():
             cmd += ' /D%s="%s"' % item
             cmd += ' /D%s="%s"' % item
     else:
     else:
         cmd = 'makensis -V2'
         cmd = 'makensis -V2'
-        for item in nsis_defs.iteritems():
+        for item in nsis_defs.items():
             cmd += ' -D%s="%s"' % item
             cmd += ' -D%s="%s"' % item
 
 
     cmd += ' "%s"' % (os.path.join(psource, 'direct', 'src', 'directscripts', 'packpanda.nsi'))
     cmd += ' "%s"' % (os.path.join(psource, 'direct', 'src', 'directscripts', 'packpanda.nsi'))
@@ -5969,6 +5968,41 @@ Info_plist = """<?xml version="1.0" encoding="UTF-8"?>
 </plist>
 </plist>
 """
 """
 
 
+MAC_POSTINSTALL = """#!/usr/bin/python
+import os, sys, plistlib
+home = os.environ['HOME']
+if not os.path.isdir(os.path.join(home, '.MacOSX')):
+    sys.exit()
+plist = dict()
+envfile = os.path.join(home, '.MacOSX', 'environment.plist')
+if os.path.exists(envfile):
+    try:
+        plist = plistlib.readPlist(envfile)
+    except: sys.exit(0)
+else:
+    sys.exit(0)
+paths = {'PATH' : '/Developer/Tools/Panda3D', 'DYLD_LIBRARY_PATH' : '/Developer/Panda3D/lib', 'PYTHONPATH' : '/Developer/Panda3D/lib',
+         'MAYA_SCRIPT_PATH' : '/Developer/Panda3D/plugins', 'MAYA_PLUG_IN_PATH' : '/Developer/Panda3D/plugins'}
+for env, path in dict(paths).items():
+    if env in plist:
+        paths = plist[env].split(':')
+        if '' in paths: paths.remove('')
+        if path in paths: paths.remove(path)
+        if len(paths) == 0:
+            del plist[env]
+        else:
+            plist[env] = ':'.join(paths)
+if len(plist) == 0:
+    os.remove(envfile)
+else:
+    plistlib.writePlist(plist, envfile)
+"""
+
+MAC_POSTFLIGHT = """#!/usr/bin/env bash"
+RESULT=`/usr/bin/open 'http://www.panda3d.org/wiki/index.php/Getting_Started_on_OSX'`"
+exit 0
+"""
+
 # FreeBSD pkg-descr
 # FreeBSD pkg-descr
 INSTALLER_PKG_DESCR_FILE = """
 INSTALLER_PKG_DESCR_FILE = """
 Panda3D is a game engine which includes graphics, audio, I/O, collision detection, and other abilities relevant to the creation of 3D games. Panda3D is open source and free software under the revised BSD license, and can be used for both free and commercial game development at no financial cost.
 Panda3D is a game engine which includes graphics, audio, I/O, collision detection, and other abilities relevant to the creation of 3D games. Panda3D is open source and free software under the revised BSD license, and can be used for both free and commercial game development at no financial cost.
@@ -6115,39 +6149,10 @@ def MakeInstallerOSX():
     # Temporary script that should clean up the poison that the early 1.7.0 builds injected into environment.plist
     # Temporary script that should clean up the poison that the early 1.7.0 builds injected into environment.plist
     oscmd("mkdir -p dstroot/scripts/base/")
     oscmd("mkdir -p dstroot/scripts/base/")
     postinstall = open("dstroot/scripts/base/postinstall", "w")
     postinstall = open("dstroot/scripts/base/postinstall", "w")
-    print >>postinstall, "#!/usr/bin/python"
-    print >>postinstall, "import os, sys, plistlib"
-    print >>postinstall, "home = os.environ['HOME']"
-    print >>postinstall, "if not os.path.isdir(os.path.join(home, '.MacOSX')):"
-    print >>postinstall, "    sys.exit()"
-    print >>postinstall, "plist = dict()"
-    print >>postinstall, "envfile = os.path.join(home, '.MacOSX', 'environment.plist')"
-    print >>postinstall, "if os.path.exists(envfile):"
-    print >>postinstall, "    try:"
-    print >>postinstall, "        plist = plistlib.readPlist(envfile)"
-    print >>postinstall, "    except: sys.exit(0)"
-    print >>postinstall, "else:"
-    print >>postinstall, "    sys.exit(0)"
-    print >>postinstall, "paths = {'PATH' : '/Developer/Tools/Panda3D', 'DYLD_LIBRARY_PATH' : '/Developer/Panda3D/lib', 'PYTHONPATH' : '/Developer/Panda3D/lib',"
-    print >>postinstall, "         'MAYA_SCRIPT_PATH' : '/Developer/Panda3D/plugins', 'MAYA_PLUG_IN_PATH' : '/Developer/Panda3D/plugins'}"
-    print >>postinstall, "for env, path in paths.items():"
-    print >>postinstall, "    if env in plist:"
-    print >>postinstall, "        paths = plist[env].split(':')"
-    print >>postinstall, "        if '' in paths: paths.remove('')"
-    print >>postinstall, "        if path in paths: paths.remove(path)"
-    print >>postinstall, "        if len(paths) == 0:"
-    print >>postinstall, "            del plist[env]"
-    print >>postinstall, "        else:"
-    print >>postinstall, "            plist[env] = ':'.join(paths)"
-    print >>postinstall, "if len(plist) == 0:"
-    print >>postinstall, "    os.remove(envfile)"
-    print >>postinstall, "else:"
-    print >>postinstall, "    plistlib.writePlist(plist, envfile)"
+    postinstall.write(MAC_POSTINSTALL)
     postinstall.close()
     postinstall.close()
     postflight = open("dstroot/scripts/base/postflight", "w")
     postflight = open("dstroot/scripts/base/postflight", "w")
-    print >>postflight, "#!/usr/bin/env bash\n"
-    print >>postflight, "RESULT=`/usr/bin/open 'http://www.panda3d.org/wiki/index.php/Getting_Started_on_OSX'`"
-    print >>postflight, "\nexit 0"
+    postflight.write(MAC_POSTFLIGHT)
     postflight.close()
     postflight.close()
     oscmd("chmod +x dstroot/scripts/base/postinstall")
     oscmd("chmod +x dstroot/scripts/base/postinstall")
     oscmd("chmod +x dstroot/scripts/base/postflight")
     oscmd("chmod +x dstroot/scripts/base/postflight")
@@ -6200,24 +6205,25 @@ def MakeInstallerOSX():
     # Dummy package uninstall16 which just contains a preflight script to remove /Applications/Panda3D/ .
     # Dummy package uninstall16 which just contains a preflight script to remove /Applications/Panda3D/ .
     oscmd("mkdir -p dstroot/scripts/uninstall16/")
     oscmd("mkdir -p dstroot/scripts/uninstall16/")
     preflight = open("dstroot/scripts/uninstall16/preflight", "w")
     preflight = open("dstroot/scripts/uninstall16/preflight", "w")
-    print >>preflight, "#!/usr/bin/python"
-    print >>preflight, "import os, re, sys, shutil"
-    print >>preflight, "if os.path.isdir('/Applications/Panda3D'): shutil.rmtree('/Applications/Panda3D')"
-    print >>preflight, "bash_profile = os.path.join(os.environ['HOME'], '.bash_profile')"
-    print >>preflight, "if not os.path.isfile(bash_profile): sys.exit(0)"
-    print >>preflight, "pattern = re.compile('''PANDA_VERSION=[0-9][.][0-9][.][0-9]"
-    print >>preflight, "PANDA_PATH=/Applications/Panda3D/[$A-Z.0-9_]+"
-    print >>preflight, "if \[ -d \$PANDA_PATH \]"
-    print >>preflight, "then(.+?)fi"
-    print >>preflight, "''', flags = re.DOTALL | re.MULTILINE)"
-    print >>preflight, "bpfile = open(bash_profile, 'r')"
-    print >>preflight, "bpdata = bpfile.read()"
-    print >>preflight, "bpfile.close()"
-    print >>preflight, "newbpdata = pattern.sub('', bpdata)"
-    print >>preflight, "if newbpdata == bpdata: sys.exit(0)"
-    print >>preflight, "bpfile = open(bash_profile, 'w')"
-    print >>preflight, "bpfile.write(newbpdata)"
-    print >>preflight, "bpfile.close()"
+    preflight.write(
+        "#!/usr/bin/python\n"
+        "import os, re, sys, shutil\n"
+        "if os.path.isdir('/Applications/Panda3D'): shutil.rmtree('/Applications/Panda3D')\n"
+        "bash_profile = os.path.join(os.environ['HOME'], '.bash_profile')\n"
+        "if not os.path.isfile(bash_profile): sys.exit(0)\n"
+        "pattern = re.compile('''PANDA_VERSION=[0-9][.][0-9][.][0-9]\n"
+        "PANDA_PATH=/Applications/Panda3D/[$A-Z.0-9_]+\n"
+        "if \[ -d \$PANDA_PATH \]\n"
+        "then(.+?)fi\n"
+        "''', flags = re.DOTALL | re.MULTILINE)\n"
+        "bpfile = open(bash_profile, 'r')\n"
+        "bpdata = bpfile.read()\n"
+        "bpfile.close()\n"
+        "newbpdata = pattern.sub('', bpdata)\n"
+        "if newbpdata == bpdata: sys.exit(0)\n"
+        "bpfile = open(bash_profile, 'w')\n"
+        "bpfile.write(newbpdata)\n"
+        "bpfile.close()\n")
     preflight.close()
     preflight.close()
     oscmd("chmod +x dstroot/scripts/uninstall16/preflight")
     oscmd("chmod +x dstroot/scripts/uninstall16/preflight")
 
 
@@ -6260,55 +6266,55 @@ def MakeInstallerOSX():
 
 
     # Now that we've built all of the individual packages, build the metapackage.
     # Now that we've built all of the individual packages, build the metapackage.
     dist = open("dstroot/Panda3D/Panda3D.mpkg/Contents/distribution.dist", "w")
     dist = open("dstroot/Panda3D/Panda3D.mpkg/Contents/distribution.dist", "w")
-    print >>dist, '<?xml version="1.0" encoding="utf-8"?>'
-    print >>dist, '<installer-script minSpecVersion="1.000000" authoringTool="com.apple.PackageMaker" authoringToolVersion="3.0.3" authoringToolBuild="174">'
-    print >>dist, '    <title>Panda3D</title>'
-    print >>dist, '    <options customize="always" allow-external-scripts="no" rootVolumeOnly="false"/>'
-    # The following script is to enable the "Uninstall 1.6.x" option only when Panda3D 1.6.x is actually installed.
-    print >>dist, '''    <script>
-function have16installed() {
-  return system.files.fileExistsAtPath(my.target.mountpoint + '/Applications/Panda3D');
-}</script>'''
-    print >>dist, '    <license language="en" mime-type="text/plain">%s</license>' % ReadFile("doc/LICENSE")
-    print >>dist, '    <choices-outline>'
-    print >>dist, '        <line choice="uninstall16"/>'
-    print >>dist, '        <line choice="base"/>'
-    print >>dist, '        <line choice="tools"/>'
+    dist.write('<?xml version="1.0" encoding="utf-8"?>\n')
+    dist.write('<installer-script minSpecVersion="1.000000" authoringTool="com.apple.PackageMaker" authoringToolVersion="3.0.3" authoringToolBuild="174">\n')
+    dist.write('    <title>Panda3D</title>\n')
+    dist.write('    <options customize="always" allow-external-scripts="no" rootVolumeOnly="false"/>\n')
+    dist.write('    <script>\n')
+    dist.write('    function have16installed() {\n')
+    dist.write('        return system.files.fileExistsAtPath(my.target.mountpoint + \'/Applications/Panda3D\');\n')
+    dist.write('    }\n')
+    dist.write('    </script>\n')
+    dist.write('    <license language="en" mime-type="text/plain">%s</license>\n' % ReadFile("doc/LICENSE"))
+    dist.write('    <choices-outline>\n')
+    dist.write('        <line choice="uninstall16"/>\n')
+    dist.write('        <line choice="base"/>\n')
+    dist.write('        <line choice="tools"/>\n')
     if PkgSkip("PYTHON")==0:
     if PkgSkip("PYTHON")==0:
-        print >>dist, '        <line choice="pythoncode"/>'
+        dist.write('        <line choice="pythoncode"/>\n')
     if os.path.isdir("samples"):
     if os.path.isdir("samples"):
-        print >>dist, '        <line choice="samples"/>'
-    print >>dist, '        <line choice="headers"/>'
-    print >>dist, '    </choices-outline>'
-    print >>dist, '    <choice id="uninstall16" title="Uninstall Panda3D 1.6.x" tooltip="Uninstalls Panda3D 1.6.x before installing Panda3D %s" description="If this option is checked, Panda3D 1.6.x is removed from /Applications/Panda3D/ before the new version is installed. This is recommended to avoid library conflicts. WARNING: EVERYTHING UNDER /Applications/Panda3D WILL BE DELETED. MAKE SURE YOU HAVE BACKED UP IMPORTANT DATA!" selected="have16installed()" enabled="have16installed()" visible="have16installed()">' % VERSION
-    print >>dist, '        <pkg-ref id="org.panda3d.panda3d.uninstall16.pkg"/>'
-    print >>dist, '    </choice>'
-    print >>dist, '    <choice id="base" title="Panda3D Base Installation" description="This package contains the Panda3D libraries, configuration files and models/textures that are needed to use Panda3D. Location: /Developer/Panda3D/" start_enabled="false">'
-    print >>dist, '        <pkg-ref id="org.panda3d.panda3d.base.pkg"/>'
-    print >>dist, '    </choice>'
-    print >>dist, '    <choice id="tools" title="Tools" tooltip="Useful tools and model converters to help with Panda3D development" description="This package contains the various utilities that ship with Panda3D, including packaging tools, model converters, and many more. Location: /Developer/Tools/Panda3D/">'
-    print >>dist, '        <pkg-ref id="org.panda3d.panda3d.tools.pkg"/>'
-    print >>dist, '    </choice>'
+        dist.write('        <line choice="samples"/>\n')
+    dist.write('        <line choice="headers"/>\n')
+    dist.write('    </choices-outline>\n')
+    dist.write('    <choice id="uninstall16" title="Uninstall Panda3D 1.6.x" tooltip="Uninstalls Panda3D 1.6.x before installing Panda3D %s" description="If this option is checked, Panda3D 1.6.x is removed from /Applications/Panda3D/ before the new version is installed. This is recommended to avoid library conflicts. WARNING: EVERYTHING UNDER /Applications/Panda3D WILL BE DELETED. MAKE SURE YOU HAVE BACKED UP IMPORTANT DATA!" selected="have16installed()" enabled="have16installed()" visible="have16installed()">\n' % VERSION)
+    dist.write('        <pkg-ref id="org.panda3d.panda3d.uninstall16.pkg"/>\n')
+    dist.write('    </choice>\n')
+    dist.write('    <choice id="base" title="Panda3D Base Installation" description="This package contains the Panda3D libraries, configuration files and models/textures that are needed to use Panda3D. Location: /Developer/Panda3D/" start_enabled="false">\n')
+    dist.write('        <pkg-ref id="org.panda3d.panda3d.base.pkg"/>\n')
+    dist.write('    </choice>\n')
+    dist.write('    <choice id="tools" title="Tools" tooltip="Useful tools and model converters to help with Panda3D development" description="This package contains the various utilities that ship with Panda3D, including packaging tools, model converters, and many more. Location: /Developer/Tools/Panda3D/">\n')
+    dist.write('        <pkg-ref id="org.panda3d.panda3d.tools.pkg"/>\n')
+    dist.write('    </choice>\n')
     if PkgSkip("PYTHON")==0:
     if PkgSkip("PYTHON")==0:
-        print >>dist, '    <choice id="pythoncode" title="Python Code" tooltip="Code you\'ll need for Python development" description="This package contains the \'direct\', \'pandac\' and \'panda3d\' python packages that are needed to do Python development with Panda3D. Location: /Developer/Panda3D/">'
-        print >>dist, '        <pkg-ref id="org.panda3d.panda3d.pythoncode.pkg"/>'
-        print >>dist, '    </choice>'
+        dist.write('    <choice id="pythoncode" title="Python Code" tooltip="Code you\'ll need for Python development" description="This package contains the \'direct\', \'pandac\' and \'panda3d\' python packages that are needed to do Python development with Panda3D. Location: /Developer/Panda3D/">\n')
+        dist.write('        <pkg-ref id="org.panda3d.panda3d.pythoncode.pkg"/>\n')
+        dist.write('    </choice>\n')
     if os.path.isdir("samples"):
     if os.path.isdir("samples"):
-        print >>dist, '    <choice id="samples" title="Sample Programs" tooltip="Python sample programs that use Panda3D" description="This package contains the Python sample programs that can help you with learning how to use Panda3D. Location: /Developer/Examples/Panda3D/">'
-        print >>dist, '        <pkg-ref id="org.panda3d.panda3d.samples.pkg"/>'
-        print >>dist, '    </choice>'
-    print >>dist, '    <choice id="headers" title="C++ Header Files" tooltip="Header files for C++ development with Panda3D" description="This package contains the C++ header files that are needed in order to do C++ development with Panda3D. You don\'t need this if you want to develop in Python. Location: /Developer/Panda3D/include/" start_selected="false">'
-    print >>dist, '        <pkg-ref id="org.panda3d.panda3d.headers.pkg"/>'
-    print >>dist, '    </choice>'
-    print >>dist, '    <pkg-ref id="org.panda3d.panda3d.uninstall16.pkg" installKBytes="0" version="1" auth="Root">file:./Contents/Packages/uninstall16.pkg</pkg-ref>'
-    print >>dist, '    <pkg-ref id="org.panda3d.panda3d.base.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/base.pkg</pkg-ref>' % (GetDirectorySize("dstroot/base") / 1024)
-    print >>dist, '    <pkg-ref id="org.panda3d.panda3d.tools.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/tools.pkg</pkg-ref>' % (GetDirectorySize("dstroot/tools") / 1024)
+        dist.write('    <choice id="samples" title="Sample Programs" tooltip="Python sample programs that use Panda3D" description="This package contains the Python sample programs that can help you with learning how to use Panda3D. Location: /Developer/Examples/Panda3D/">\n')
+        dist.write('        <pkg-ref id="org.panda3d.panda3d.samples.pkg"/>\n')
+        dist.write('    </choice>\n')
+    dist.write('    <choice id="headers" title="C++ Header Files" tooltip="Header files for C++ development with Panda3D" description="This package contains the C++ header files that are needed in order to do C++ development with Panda3D. You don\'t need this if you want to develop in Python. Location: /Developer/Panda3D/include/" start_selected="false">\n')
+    dist.write('        <pkg-ref id="org.panda3d.panda3d.headers.pkg"/>\n')
+    dist.write('    </choice>\n')
+    dist.write('    <pkg-ref id="org.panda3d.panda3d.uninstall16.pkg" installKBytes="0" version="1" auth="Root">file:./Contents/Packages/uninstall16.pkg</pkg-ref>\n')
+    dist.write('    <pkg-ref id="org.panda3d.panda3d.base.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/base.pkg</pkg-ref>\n' % (GetDirectorySize("dstroot/base") // 1024))
+    dist.write('    <pkg-ref id="org.panda3d.panda3d.tools.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/tools.pkg</pkg-ref>\n' % (GetDirectorySize("dstroot/tools") // 1024))
     if PkgSkip("PYTHON")==0:
     if PkgSkip("PYTHON")==0:
-        print >>dist, '    <pkg-ref id="org.panda3d.panda3d.pythoncode.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/pythoncode.pkg</pkg-ref>' % (GetDirectorySize("dstroot/pythoncode") / 1024)
+        dist.write('    <pkg-ref id="org.panda3d.panda3d.pythoncode.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/pythoncode.pkg</pkg-ref>\n' % (GetDirectorySize("dstroot/pythoncode") // 1024))
     if os.path.isdir("samples"):
     if os.path.isdir("samples"):
-        print >>dist, '    <pkg-ref id="org.panda3d.panda3d.samples.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/samples.pkg</pkg-ref>' % (GetDirectorySize("dstroot/samples") / 1024)
-    print >>dist, '    <pkg-ref id="org.panda3d.panda3d.headers.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/headers.pkg</pkg-ref>' % (GetDirectorySize("dstroot/headers") / 1024)
-    print >>dist, '</installer-script>'
+        dist.write('    <pkg-ref id="org.panda3d.panda3d.samples.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/samples.pkg</pkg-ref>\n' % (GetDirectorySize("dstroot/samples") // 1024))
+    dist.write('    <pkg-ref id="org.panda3d.panda3d.headers.pkg" installKBytes="%d" version="1" auth="Root">file:./Contents/Packages/headers.pkg</pkg-ref>\n' % (GetDirectorySize("dstroot/headers") // 1024))
+    dist.write('</installer-script>\n')
     dist.close()
     dist.close()
 
 
     oscmd('hdiutil create Panda3D-rw.dmg -srcfolder dstroot/Panda3D')
     oscmd('hdiutil create Panda3D-rw.dmg -srcfolder dstroot/Panda3D')
@@ -6410,4 +6416,4 @@ MoveBackConflictingFiles()
 WARNINGS.append("Elapsed Time: "+PrettyTime(time.time() - STARTTIME))
 WARNINGS.append("Elapsed Time: "+PrettyTime(time.time() - STARTTIME))
 
 
 printStatus("Makepanda Final Status Report", WARNINGS)
 printStatus("Makepanda Final Status Report", WARNINGS)
-print GetColor("green") + "Build successfully finished, elapsed time: " + PrettyTime(time.time() - STARTTIME) + GetColor()
+print(GetColor("green") + "Build successfully finished, elapsed time: " + PrettyTime(time.time() - STARTTIME) + GetColor())

+ 129 - 87
makepanda/makepandacore.py

@@ -9,9 +9,14 @@
 ##
 ##
 ########################################################################
 ########################################################################
 
 
-import sys,os,time,stat,string,re,getopt,cPickle,fnmatch,threading,Queue,signal,shutil,platform,glob,getpass,signal
+import sys,os,time,stat,string,re,getopt,fnmatch,threading,signal,shutil,platform,glob,getpass,signal
 from distutils import sysconfig
 from distutils import sysconfig
 
 
+if sys.version_info >= (3, 0):
+    import pickle
+else:
+    import cPickle as pickle
+
 SUFFIX_INC = [".cxx",".c",".h",".I",".yxx",".lxx",".mm",".rc",".r"]
 SUFFIX_INC = [".cxx",".c",".h",".I",".yxx",".lxx",".mm",".rc",".r"]
 SUFFIX_DLL = [".dll",".dlo",".dle",".dli",".dlm",".mll",".exe",".pyd",".ocx"]
 SUFFIX_DLL = [".dll",".dlo",".dle",".dli",".dlm",".mll",".exe",".pyd",".ocx"]
 SUFFIX_LIB = [".lib",".ilb"]
 SUFFIX_LIB = [".lib",".ilb"]
@@ -36,7 +41,10 @@ if sys.platform == 'darwin':
     # On OSX, platform.architecture reports '64bit' even if it is
     # On OSX, platform.architecture reports '64bit' even if it is
     # currently running in 32-bit mode.  But sys.maxint is a reliable
     # currently running in 32-bit mode.  But sys.maxint is a reliable
     # indicator.
     # indicator.
-    is_64 = (sys.maxint > 0x100000000L)
+    if sys.version_info >= (3, 0):
+        is_64 = (sys.maxsize > 0x100000000)
+    else:
+        is_64 = (sys.maxint > 0x100000000)
 else:
 else:
     # On Windows (and Linux?) sys.maxint reports 0x7fffffff even on a
     # On Windows (and Linux?) sys.maxint reports 0x7fffffff even on a
     # 64-bit build.  So we stick with platform.architecture in that
     # 64-bit build.  So we stick with platform.architecture in that
@@ -167,37 +175,49 @@ def GetColor(color = None):
     else:
     else:
       return curses.tparm(curses.tigetstr("sgr0"))
       return curses.tparm(curses.tigetstr("sgr0"))
 
 
+def ColorText(color, text, reset=True):
+    if reset is True:
+        return ''.join((GetColor(color), text, GetColor()))
+    else:
+        return ''.join((GetColor(color), text))
+
 def PrettyTime(t):
 def PrettyTime(t):
     t = int(t)
     t = int(t)
-    hours = t/3600
-    t -= hours*3600
-    minutes = t/60
-    t -= minutes*60
+    hours = t // 3600
+    t -= hours * 3600
+    minutes = t // 60
+    t -= minutes * 60
     seconds = t
     seconds = t
-    if (hours): return str(hours)+" hours "+str(minutes)+" min"
-    if (minutes): return str(minutes)+" min "+str(seconds)+" sec"
-    return str(seconds)+" sec"
+    if hours:
+        return "%d hours %d min" % (hours, minutes)
+    if minutes:
+        return "%d min %d sec" % (minutes, seconds)
+    return "%d sec" % (seconds)
 
 
 def ProgressOutput(progress, msg, target = None):
 def ProgressOutput(progress, msg, target = None):
-    if (threading.currentThread() == MAINTHREAD):
-        if (progress == None):
-            print msg
+    prefix = ""
+    if (threading.currentThread() is MAINTHREAD):
+        if progress is None:
+            prefix = ""
         elif (progress >= 100.0):
         elif (progress >= 100.0):
-            print "%s[%s%d%%%s] %s" % (GetColor("yellow"), GetColor("cyan"), progress, GetColor("yellow"), msg),
+            prefix = "%s[%s%d%%%s] " % (GetColor("yellow"), GetColor("cyan"), progress, GetColor("yellow"))
         elif (progress < 10.0):
         elif (progress < 10.0):
-            print "%s[%s  %d%%%s] %s" % (GetColor("yellow"), GetColor("cyan"), progress, GetColor("yellow"), msg),
+            prefix = "%s[%s  %d%%%s] " % (GetColor("yellow"), GetColor("cyan"), progress, GetColor("yellow"))
         else:
         else:
-            print "%s[%s %d%%%s] %s" % (GetColor("yellow"), GetColor("cyan"), progress, GetColor("yellow"), msg),
+            prefix = "%s[%s %d%%%s] " % (GetColor("yellow"), GetColor("cyan"), progress, GetColor("yellow"))
     else:
     else:
         global THREADS
         global THREADS
         ident = threading.currentThread().ident
         ident = threading.currentThread().ident
         if (ident not in THREADS):
         if (ident not in THREADS):
             THREADS[ident] = len(THREADS) + 1
             THREADS[ident] = len(THREADS) + 1
-        print "%s[%sT%d%s] %s" % (GetColor("yellow"), GetColor("cyan"), THREADS[ident], GetColor("yellow"), msg),
-    if (target == None):
-        print GetColor()
+        prefix = "%s[%sT%d%s] " % (GetColor("yellow"), GetColor("cyan"), THREADS[ident], GetColor("yellow"))
+
+    if target is not None:
+        suffix = ' ' + ColorText("green", target)
     else:
     else:
-        print "%s%s%s" % (GetColor("green"), target, GetColor())
+        suffix = GetColor()
+
+    print(''.join((prefix, msg, suffix)))
 
 
 def exit(msg = ""):
 def exit(msg = ""):
     sys.stdout.flush()
     sys.stdout.flush()
@@ -205,16 +225,16 @@ def exit(msg = ""):
     if (threading.currentThread() == MAINTHREAD):
     if (threading.currentThread() == MAINTHREAD):
         SaveDependencyCache()
         SaveDependencyCache()
         MoveBackConflictingFiles()
         MoveBackConflictingFiles()
-        print "Elapsed Time: "+PrettyTime(time.time() - STARTTIME)
-        print msg
-        print GetColor("red") + "Build terminated." + GetColor()
+        print("Elapsed Time: " + PrettyTime(time.time() - STARTTIME))
+        print(msg)
+        print(ColorText("red", "Build terminated."))
         sys.stdout.flush()
         sys.stdout.flush()
         sys.stderr.flush()
         sys.stderr.flush()
         ##Don't quit the interperter if I'm running this file directly (debugging)
         ##Don't quit the interperter if I'm running this file directly (debugging)
         if __name__ != '__main__':
         if __name__ != '__main__':
             os._exit(1)
             os._exit(1)
     else:
     else:
-        print msg
+        print(msg)
         raise "initiate-exit"
         raise "initiate-exit"
 
 
 ########################################################################
 ########################################################################
@@ -435,7 +455,7 @@ def LocateBinary(binary):
 
 
 def oscmd(cmd, ignoreError = False):
 def oscmd(cmd, ignoreError = False):
     if VERBOSE:
     if VERBOSE:
-        print GetColor("blue") + cmd.split(" ", 1)[0] + " " + GetColor("magenta") + cmd.split(" ", 1)[1] + GetColor()
+        print(GetColor("blue") + cmd.split(" ", 1)[0] + " " + GetColor("magenta") + cmd.split(" ", 1)[1] + GetColor())
     sys.stdout.flush()
     sys.stdout.flush()
 
 
     if sys.platform == "win32":
     if sys.platform == "win32":
@@ -448,21 +468,21 @@ def oscmd(cmd, ignoreError = False):
         res = os.system(cmd)
         res = os.system(cmd)
         sig = res & 0x7F
         sig = res & 0x7F
         if (GetVerbose() and res != 0):
         if (GetVerbose() and res != 0):
-            print GetColor("red") + "Process exited with exit status %d and signal code %d" % ((res & 0xFF00) >> 8, sig) + GetColor()
+            print(ColorText("red", "Process exited with exit status %d and signal code %d" % ((res & 0xFF00) >> 8, sig)))
         if (sig == signal.SIGINT):
         if (sig == signal.SIGINT):
             exit("keyboard interrupt")
             exit("keyboard interrupt")
         # Don't ask me where the 35584 or 34304 come from...
         # Don't ask me where the 35584 or 34304 come from...
         if (sig == signal.SIGSEGV or res == 35584 or res == 34304):
         if (sig == signal.SIGSEGV or res == 35584 or res == 34304):
             if (LocateBinary("gdb") and GetVerbose()):
             if (LocateBinary("gdb") and GetVerbose()):
-                print GetColor("red") + "Received SIGSEGV, retrieving traceback..." + GetColor()
+                print(ColorText("red", "Received SIGSEGV, retrieving traceback..."))
                 os.system("gdb -batch -ex 'handle SIG33 pass nostop noprint' -ex 'set pagination 0' -ex 'run' -ex 'bt full' -ex 'info registers' -ex 'thread apply all backtrace' -ex 'quit' --args %s < /dev/null" % cmd)
                 os.system("gdb -batch -ex 'handle SIG33 pass nostop noprint' -ex 'set pagination 0' -ex 'run' -ex 'bt full' -ex 'info registers' -ex 'thread apply all backtrace' -ex 'quit' --args %s < /dev/null" % cmd)
             else:
             else:
-                print GetColor("red") + "Received SIGSEGV" + GetColor()
+                print(ColorText("red", "Received SIGSEGV"))
             exit("")
             exit("")
 
 
     if res != 0 and not ignoreError:
     if res != 0 and not ignoreError:
         if "interrogate" in cmd.split(" ", 1)[0] and GetVerbose():
         if "interrogate" in cmd.split(" ", 1)[0] and GetVerbose():
-            print GetColor("red") + "Interrogate failed, retrieving debug output..." + GetColor()
+            print(ColorText("red", "Interrogate failed, retrieving debug output..."))
             if sys.platform == "win32":
             if sys.platform == "win32":
                 os.spawnl(os.P_WAIT, exe, cmd.split(" ", 1)[0] + " -v " + cmd.split(" ", 1)[1])
                 os.spawnl(os.P_WAIT, exe, cmd.split(" ", 1)[0] + " -v " + cmd.split(" ", 1)[1])
             else:
             else:
@@ -498,7 +518,7 @@ def GetDirectoryContents(dir, filters="*", skip=[]):
                 actual[file] = 1
                 actual[file] = 1
     if (os.path.isfile(dir + "/CVS/Entries")):
     if (os.path.isfile(dir + "/CVS/Entries")):
         cvs = {}
         cvs = {}
-        srchandle = open(dir+"/CVS/Entries", "r")
+        srchandle = open(dir + "/CVS/Entries", "r")
         files = []
         files = []
         for line in srchandle:
         for line in srchandle:
             if (line[0]=="/"):
             if (line[0]=="/"):
@@ -514,21 +534,23 @@ def GetDirectoryContents(dir, filters="*", skip=[]):
         #XXX this happens all the time, do we really need to warn about this?
         #XXX this happens all the time, do we really need to warn about this?
         #for file in actual.keys():
         #for file in actual.keys():
         #    if (file not in cvs and VERBOSE):
         #    if (file not in cvs and VERBOSE):
-        #        msg = "%sWARNING: %s is in %s, but not in CVS%s" % (GetColor("red"), GetColor("green") + file + GetColor(), GetColor("green") + dir + GetColor(), GetColor())
+        #        msg = "%sWARNING: %s is in %s, but not in CVS%s" % (GetColor("red"), ColorText("green", file), ColorText("green", dir), GetColor())
         #        print msg
         #        print msg
         #        WARNINGS.append(msg)
         #        WARNINGS.append(msg)
 
 
         for file in cvs.keys():
         for file in cvs.keys():
             if (file not in actual and VERBOSE):
             if (file not in actual and VERBOSE):
-                msg = "%sWARNING: %s is not in %s, but is in CVS%s" % (GetColor("red"), GetColor("green") + file + GetColor(), GetColor("green") + dir + GetColor(), GetColor())
-                print msg
+                msg = "%sWARNING: %s is not in %s, but is in CVS%s" % (GetColor("red"), ColorText("green", file), ColorText("green", dir), GetColor())
+                print(msg)
                 WARNINGS.append(msg)
                 WARNINGS.append(msg)
 
 
-    results = actual.keys()
+    results = list(actual.keys())
     results.sort()
     results.sort()
     return results
     return results
 
 
 def GetDirectorySize(dir):
 def GetDirectorySize(dir):
+    if not os.path.isdir(dir):
+        return 0
     size = 0
     size = 0
     for (path, dirs, files) in os.walk(dir):
     for (path, dirs, files) in os.walk(dir):
         for file in files:
         for file in files:
@@ -600,7 +622,7 @@ def NeedsBuild(files,others):
         else:
         else:
             oldothers = BUILTFROMCACHE[key][0]
             oldothers = BUILTFROMCACHE[key][0]
             if (oldothers != others and VERBOSE):
             if (oldothers != others and VERBOSE):
-                print "%sWARNING:%s file dependencies changed: %s%s%s" % (GetColor("red"), GetColor(), GetColor("green"), str(files), GetColor())
+                print("%sWARNING:%s file dependencies changed: %s%s%s" % (GetColor("red"), GetColor(), GetColor("green"), str(files), GetColor()))
     return 1
     return 1
 
 
 ########################################################################
 ########################################################################
@@ -634,7 +656,7 @@ def CxxGetIncludes(path):
     if (path in CXXINCLUDECACHE):
     if (path in CXXINCLUDECACHE):
         cached = CXXINCLUDECACHE[path]
         cached = CXXINCLUDECACHE[path]
         if (cached[0]==date): return cached[1]
         if (cached[0]==date): return cached[1]
-    try: sfile = open(path, 'rb')
+    try: sfile = open(path, 'r')
     except:
     except:
         exit("Cannot open source file \""+path+"\" for reading.")
         exit("Cannot open source file \""+path+"\" for reading.")
     include = []
     include = []
@@ -669,9 +691,9 @@ def SaveDependencyCache():
     try: icache = open(os.path.join(OUTPUTDIR, "tmp", "makepanda-dcache"),'wb')
     try: icache = open(os.path.join(OUTPUTDIR, "tmp", "makepanda-dcache"),'wb')
     except: icache = 0
     except: icache = 0
     if (icache!=0):
     if (icache!=0):
-        print "Storing dependency cache."
-        cPickle.dump(CXXINCLUDECACHE, icache, 1)
-        cPickle.dump(BUILTFROMCACHE, icache, 1)
+        print("Storing dependency cache.")
+        pickle.dump(CXXINCLUDECACHE, icache, 1)
+        pickle.dump(BUILTFROMCACHE, icache, 1)
         icache.close()
         icache.close()
 
 
 def LoadDependencyCache():
 def LoadDependencyCache():
@@ -680,8 +702,8 @@ def LoadDependencyCache():
     try: icache = open(os.path.join(OUTPUTDIR, "tmp", "makepanda-dcache"),'rb')
     try: icache = open(os.path.join(OUTPUTDIR, "tmp", "makepanda-dcache"),'rb')
     except: icache = 0
     except: icache = 0
     if (icache!=0):
     if (icache!=0):
-        CXXINCLUDECACHE = cPickle.load(icache)
-        BUILTFROMCACHE = cPickle.load(icache)
+        CXXINCLUDECACHE = pickle.load(icache)
+        BUILTFROMCACHE = pickle.load(icache)
         icache.close()
         icache.close()
 
 
 ########################################################################
 ########################################################################
@@ -759,7 +781,7 @@ def CxxCalcDependencies(srcfile, ipath, ignore):
             if (ignore.count(header)==0):
             if (ignore.count(header)==0):
                 hdeps = CxxCalcDependencies(header, ipath, [srcfile]+ignore)
                 hdeps = CxxCalcDependencies(header, ipath, [srcfile]+ignore)
                 for x in hdeps: dep[x] = 1
                 for x in hdeps: dep[x] = 1
-    result = dep.keys()
+    result = list(dep.keys())
     CxxDependencyCache[srcfile] = result
     CxxDependencyCache[srcfile] = result
     return result
     return result
 
 
@@ -775,15 +797,18 @@ def CxxCalcDependencies(srcfile, ipath, ignore):
 ########################################################################
 ########################################################################
 
 
 if sys.platform == "win32":
 if sys.platform == "win32":
-    import _winreg
+    if sys.version_info >= (3, 0):
+        import winreg
+    else:
+        import _winreg as winreg
 
 
 def TryRegistryKey(path):
 def TryRegistryKey(path):
     try:
     try:
-        key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, path, 0, _winreg.KEY_READ)
+        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path, 0, winreg.KEY_READ)
         return key
         return key
     except: pass
     except: pass
     try:
     try:
-        key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, path, 0, _winreg.KEY_READ | 256)
+        key = winreg.OpenKey(winreg.HKEY_LOCAL_MACHINE, path, 0, winreg.KEY_READ | 256)
         return key
         return key
     except: pass
     except: pass
     return 0
     return 0
@@ -795,10 +820,10 @@ def ListRegistryKeys(path):
     if (key != 0):
     if (key != 0):
         try:
         try:
             while (1):
             while (1):
-                result.append(_winreg.EnumKey(key, index))
+                result.append(winreg.EnumKey(key, index))
                 index = index + 1
                 index = index + 1
         except: pass
         except: pass
-        _winreg.CloseKey(key)
+        winreg.CloseKey(key)
     return result
     return result
 
 
 def ListRegistryValues(path):
 def ListRegistryValues(path):
@@ -808,10 +833,10 @@ def ListRegistryValues(path):
     if (key != 0):
     if (key != 0):
         try:
         try:
             while (1):
             while (1):
-                result.append(_winreg.EnumValue(key, index)[0])
+                result.append(winreg.EnumValue(key, index)[0])
                 index = index + 1
                 index = index + 1
         except: pass
         except: pass
-        _winreg.CloseKey(key)
+        winreg.CloseKey(key)
     return result
     return result
 
 
 def GetRegistryKey(path, subkey, override64=True):
 def GetRegistryKey(path, subkey, override64=True):
@@ -821,9 +846,9 @@ def GetRegistryKey(path, subkey, override64=True):
     key = TryRegistryKey(path)
     key = TryRegistryKey(path)
     if (key != 0):
     if (key != 0):
         try:
         try:
-            k1, k2 = _winreg.QueryValueEx(key, subkey)
+            k1, k2 = winreg.QueryValueEx(key, subkey)
         except: pass
         except: pass
-        _winreg.CloseKey(key)
+        winreg.CloseKey(key)
     return k1
     return k1
 
 
 def GetProgramFiles():
 def GetProgramFiles():
@@ -873,32 +898,49 @@ def MakeDirectory(path):
     os.mkdir(path)
     os.mkdir(path)
 
 
 def ReadFile(wfile):
 def ReadFile(wfile):
+    try:
+        srchandle = open(wfile, "r")
+        data = srchandle.read()
+        srchandle.close()
+        return data
+    except ex:
+        exit("Cannot read %s: %s" % (wfile, ex))
+
+def ReadBinaryFile(wfile):
     try:
     try:
         srchandle = open(wfile, "rb")
         srchandle = open(wfile, "rb")
         data = srchandle.read()
         data = srchandle.read()
         srchandle.close()
         srchandle.close()
         return data
         return data
-    except Exception, ex:
+    except ex:
         exit("Cannot read %s: %s" % (wfile, ex))
         exit("Cannot read %s: %s" % (wfile, ex))
 
 
 def WriteFile(wfile, data):
 def WriteFile(wfile, data):
+    try:
+        dsthandle = open(wfile, "w")
+        dsthandle.write(data)
+        dsthandle.close()
+    except ex:
+        exit("Cannot write to %s: %s" % (wfile, ex))
+
+def WriteBinaryFile(wfile, data):
     try:
     try:
         dsthandle = open(wfile, "wb")
         dsthandle = open(wfile, "wb")
         dsthandle.write(data)
         dsthandle.write(data)
         dsthandle.close()
         dsthandle.close()
-    except Exception, ex:
+    except ex:
         exit("Cannot write to %s: %s" % (wfile, ex))
         exit("Cannot write to %s: %s" % (wfile, ex))
 
 
-def ConditionalWriteFile(dest,desiredcontents):
+def ConditionalWriteFile(dest, desiredcontents):
     try:
     try:
-        rfile = open(dest, 'rb')
+        rfile = open(dest, 'r')
         contents = rfile.read(-1)
         contents = rfile.read(-1)
         rfile.close()
         rfile.close()
     except:
     except:
         contents=0
         contents=0
     if contents != desiredcontents:
     if contents != desiredcontents:
         sys.stdout.flush()
         sys.stdout.flush()
-        WriteFile(dest,desiredcontents)
+        WriteFile(dest, desiredcontents)
 
 
 def DeleteCVS(dir):
 def DeleteCVS(dir):
     if dir == "": dir = "."
     if dir == "": dir = "."
@@ -940,7 +982,7 @@ def DeleteEmptyDirs(dir):
 
 
 def CreateFile(file):
 def CreateFile(file):
     if (os.path.exists(file)==0):
     if (os.path.exists(file)==0):
-        WriteFile(file,"")
+        WriteFile(file, "")
 
 
 ########################################################################
 ########################################################################
 #
 #
@@ -1053,7 +1095,7 @@ def GetThirdpartyDir():
         THIRDPARTYDIR = GetThirdpartyBase()+"/android-libs-%s/" % (GetTargetArch())
         THIRDPARTYDIR = GetThirdpartyBase()+"/android-libs-%s/" % (GetTargetArch())
 
 
     else:
     else:
-        print GetColor("red") + "WARNING:" + GetColor("Unsupported platform: " + target)
+        print("%s Unsupported platform: %s" % (ColorText("red", "WARNING:"), target))
     return THIRDPARTYDIR
     return THIRDPARTYDIR
 
 
 ########################################################################
 ########################################################################
@@ -1202,7 +1244,7 @@ def AddOverride(spec):
 
 
 def OverrideValue(parameter, value):
 def OverrideValue(parameter, value):
     if parameter in OVERRIDES_LIST:
     if parameter in OVERRIDES_LIST:
-        print "Overriding value of key \"" + parameter + "\" with value \"" + OVERRIDES_LIST[parameter] + "\""
+        print("Overriding value of key \"" + parameter + "\" with value \"" + OVERRIDES_LIST[parameter] + "\"")
         return OVERRIDES_LIST[parameter]
         return OVERRIDES_LIST[parameter]
     else:
     else:
         return value
         return value
@@ -1338,7 +1380,7 @@ def GetLibCache():
     if (LD_CACHE == None):
     if (LD_CACHE == None):
         LD_CACHE = []
         LD_CACHE = []
         sysroot = SDK.get('SYSROOT', '')
         sysroot = SDK.get('SYSROOT', '')
-        print "Generating library cache..."
+        print("Generating library cache...")
 
 
         # If not cross compiling, use ldconfig to get a list of libraries in the LD cache
         # If not cross compiling, use ldconfig to get a list of libraries in the LD cache
         if (not CrossCompiling() and LocateBinary("ldconfig") != None and GetTarget() != 'freebsd'):
         if (not CrossCompiling() and LocateBinary("ldconfig") != None and GetTarget() != 'freebsd'):
@@ -1386,7 +1428,7 @@ def ChooseLib(*libs):
             return libname
             return libname
     if (len(libs) > 0):
     if (len(libs) > 0):
         if (VERBOSE):
         if (VERBOSE):
-            print GetColor("cyan") + "Couldn't find any of the libraries " + ", ".join(libs) + GetColor()
+            print(ColorText("cyan", "Couldn't find any of the libraries " + ", ".join(libs)))
         return libs[0]
         return libs[0]
 
 
 def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, framework = None, target_pkg = None, tool = "pkg-config"):
 def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None, framework = None, target_pkg = None, tool = "pkg-config"):
@@ -1462,10 +1504,10 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
             for d, v in defs.values():
             for d, v in defs.values():
                 DefSymbol(target_pkg, d, v)
                 DefSymbol(target_pkg, d, v)
         elif (pkg in PkgListGet()):
         elif (pkg in PkgListGet()):
-            print "%sWARNING:%s Could not locate framework %s, excluding from build" % (GetColor("red"), GetColor(), framework)
+            print("%sWARNING:%s Could not locate framework %s, excluding from build" % (GetColor("red"), GetColor(), framework))
             PkgDisable(pkg)
             PkgDisable(pkg)
         else:
         else:
-            print "%sERROR:%s Could not locate framework %s, aborting build" % (GetColor("red"), GetColor(), framework)
+            print("%sERROR:%s Could not locate framework %s, aborting build" % (GetColor("red"), GetColor(), framework))
             exit()
             exit()
         return
         return
     elif (LocateBinary(tool) != None and (tool != "pkg-config" or pkgconfig != None)):
     elif (LocateBinary(tool) != None and (tool != "pkg-config" or pkgconfig != None)):
@@ -1484,10 +1526,10 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
 
 
     if (pkgconfig != None and (libs == None or len(libs) == 0)):
     if (pkgconfig != None and (libs == None or len(libs) == 0)):
         if (pkg in PkgListGet()):
         if (pkg in PkgListGet()):
-            print "%sWARNING:%s Could not locate pkg-config package %s, excluding from build" % (GetColor("red"), GetColor(), pkgconfig)
+            print("%sWARNING:%s Could not locate pkg-config package %s, excluding from build" % (GetColor("red"), GetColor(), pkgconfig))
             PkgDisable(pkg)
             PkgDisable(pkg)
         else:
         else:
-            print "%sERROR:%s Could not locate pkg-config package %s, aborting build" % (GetColor("red"), GetColor(), pkgconfig)
+            print("%sERROR:%s Could not locate pkg-config package %s, aborting build" % (GetColor("red"), GetColor(), pkgconfig))
             exit()
             exit()
     else:
     else:
         # Okay, our pkg-config attempts failed. Let's try locating the libs by ourselves.
         # Okay, our pkg-config attempts failed. Let's try locating the libs by ourselves.
@@ -1500,7 +1542,7 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
                 LibName(target_pkg, "-l" + libname)
                 LibName(target_pkg, "-l" + libname)
             else:
             else:
                 if (VERBOSE):
                 if (VERBOSE):
-                    print GetColor("cyan") + "Couldn't find library lib" + libname + GetColor()
+                    print(GetColor("cyan") + "Couldn't find library lib" + libname + GetColor())
                 have_pkg = False
                 have_pkg = False
 
 
         for i in incs:
         for i in incs:
@@ -1520,7 +1562,7 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
                         incdir = sorted(glob.glob(os.path.join(pdir, i)))[-1]
                         incdir = sorted(glob.glob(os.path.join(pdir, i)))[-1]
                         have_pkg = True
                         have_pkg = True
                 if (incdir == None and VERBOSE and i.endswith(".h")):
                 if (incdir == None and VERBOSE and i.endswith(".h")):
-                    print GetColor("cyan") + "Couldn't find header file " + i + GetColor()
+                    print(GetColor("cyan") + "Couldn't find header file " + i + GetColor())
 
 
             # Note: It's possible to specify a file instead of a dir, for the sake of checking if it exists.
             # Note: It's possible to specify a file instead of a dir, for the sake of checking if it exists.
             if (incdir != None and os.path.isdir(incdir)):
             if (incdir != None and os.path.isdir(incdir)):
@@ -1528,10 +1570,10 @@ def SmartPkgEnable(pkg, pkgconfig = None, libs = None, incs = None, defs = None,
 
 
         if (not have_pkg):
         if (not have_pkg):
             if (pkg in PkgListGet()):
             if (pkg in PkgListGet()):
-                print "%sWARNING:%s Could not locate thirdparty package %s, excluding from build" % (GetColor("red"), GetColor(), pkg.lower())
+                print("%sWARNING:%s Could not locate thirdparty package %s, excluding from build" % (GetColor("red"), GetColor(), pkg.lower()))
                 PkgDisable(pkg)
                 PkgDisable(pkg)
             else:
             else:
-                print "%sERROR:%s Could not locate thirdparty package %s, aborting build" % (GetColor("red"), GetColor(), pkg.lower())
+                print("%sERROR:%s Could not locate thirdparty package %s, aborting build" % (GetColor("red"), GetColor(), pkg.lower()))
                 exit()
                 exit()
 
 
 ########################################################################
 ########################################################################
@@ -1600,32 +1642,32 @@ def SdkLocateDirectX( strMode = 'default' ):
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
             dir = GetRegistryKey("SOFTWARE\\Wow6432Node\\Microsoft\\DirectX\\Microsoft DirectX SDK (June 2010)", "InstallPath")
             dir = GetRegistryKey("SOFTWARE\\Wow6432Node\\Microsoft\\DirectX\\Microsoft DirectX SDK (June 2010)", "InstallPath")
             if (dir != 0):
             if (dir != 0):
-                print "Using DirectX SDK June 2010"
+                print("Using DirectX SDK June 2010")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (June 2010)", "InstallPath")
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (June 2010)", "InstallPath")
             if (dir != 0):
             if (dir != 0):
-                print "Using DirectX SDK June 2010"
+                print("Using DirectX SDK June 2010")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
             dir = GetRegistryKey("SOFTWARE\\Wow6432Node\\Microsoft\\DirectX\\Microsoft DirectX SDK (August 2009)", "InstallPath")
             dir = GetRegistryKey("SOFTWARE\\Wow6432Node\\Microsoft\\DirectX\\Microsoft DirectX SDK (August 2009)", "InstallPath")
             if (dir != 0):
             if (dir != 0):
-                print "Using DirectX SDK Aug 2009"
+                print("Using DirectX SDK Aug 2009")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (August 2009)", "InstallPath")
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (August 2009)", "InstallPath")
             if (dir != 0):
             if (dir != 0):
-                print "Using DirectX SDK Aug 2009"
+                print("Using DirectX SDK Aug 2009")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
             ## Try to locate the key within the "new" March 2009 location in the registry (yecch):
             ## Try to locate the key within the "new" March 2009 location in the registry (yecch):
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (March 2009)", "InstallPath")
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (March 2009)", "InstallPath")
             if (dir != 0):
             if (dir != 0):
-                print "Using DirectX SDK March 2009"
+                print("Using DirectX SDK March 2009")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
         archStr = "x86"
         archStr = "x86"
         if (is_64): archStr = "x64"
         if (is_64): archStr = "x64"
@@ -1654,13 +1696,13 @@ def SdkLocateDirectX( strMode = 'default' ):
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
             dir = GetRegistryKey("SOFTWARE\\Wow6432Node\\Microsoft\\DirectX\\Microsoft DirectX SDK (June 2010)", "InstallPath")
             dir = GetRegistryKey("SOFTWARE\\Wow6432Node\\Microsoft\\DirectX\\Microsoft DirectX SDK (June 2010)", "InstallPath")
             if (dir != 0):
             if (dir != 0):
-                print "Found DirectX SDK June 2010"
+                print("Found DirectX SDK June 2010")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (June 2010)", "InstallPath")
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (June 2010)", "InstallPath")
             if (dir != 0):
             if (dir != 0):
-                print "Found DirectX SDK June 2010"
+                print("Found DirectX SDK June 2010")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
@@ -1669,13 +1711,13 @@ def SdkLocateDirectX( strMode = 'default' ):
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
             dir = GetRegistryKey("SOFTWARE\\Wow6432Node\\Microsoft\\DirectX\\Microsoft DirectX SDK (August 2009)", "InstallPath")
             dir = GetRegistryKey("SOFTWARE\\Wow6432Node\\Microsoft\\DirectX\\Microsoft DirectX SDK (August 2009)", "InstallPath")
             if (dir != 0):
             if (dir != 0):
-                print "Found DirectX SDK Aug 2009"
+                print("Found DirectX SDK Aug 2009")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (August 2009)", "InstallPath")
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (August 2009)", "InstallPath")
             if (dir != 0):
             if (dir != 0):
-                print "Found DirectX SDK Aug 2009"
+                print("Found DirectX SDK Aug 2009")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
                 SDK["GENERIC_DXERR_LIBRARY"] = 1;
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
@@ -1685,7 +1727,7 @@ def SdkLocateDirectX( strMode = 'default' ):
             ## Try to locate the key within the "new" March 2009 location in the registry (yecch):
             ## Try to locate the key within the "new" March 2009 location in the registry (yecch):
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (March 2009)", "InstallPath")
             dir = GetRegistryKey("SOFTWARE\\Microsoft\\DirectX\\Microsoft DirectX SDK (March 2009)", "InstallPath")
             if (dir != 0):
             if (dir != 0):
-                print "Found DirectX SDK March 2009"
+                print("Found DirectX SDK March 2009")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
                 SDK["DX9"] = dir.replace("\\", "/").rstrip("/")
         if ("DX9" not in SDK):
         if ("DX9" not in SDK):
             exit("Couldn't find DirectX March 2009 SDK")
             exit("Couldn't find DirectX March 2009 SDK")
@@ -1778,7 +1820,7 @@ def SdkLocatePython(force_use_sys_executable = False):
                 exit("Could not find %s!" % SDK["PYTHONEXEC"])
                 exit("Could not find %s!" % SDK["PYTHONEXEC"])
 
 
             os.system(SDK["PYTHONEXEC"] + " -V > "+OUTPUTDIR+"/tmp/pythonversion 2>&1")
             os.system(SDK["PYTHONEXEC"] + " -V > "+OUTPUTDIR+"/tmp/pythonversion 2>&1")
-            pv=ReadFile(OUTPUTDIR+"/tmp/pythonversion")
+            pv = ReadFile(OUTPUTDIR + "/tmp/pythonversion")
             if (pv.startswith("Python ")==0):
             if (pv.startswith("Python ")==0):
                 exit("python -V did not produce the expected output")
                 exit("python -V did not produce the expected output")
             pv = pv[7:10]
             pv = pv[7:10]
@@ -1958,7 +2000,7 @@ def SdkLocateSpeedTree():
     for dirname in os.listdir(dir):
     for dirname in os.listdir(dir):
         if dirname.startswith('SpeedTree SDK v'):
         if dirname.startswith('SpeedTree SDK v'):
             version = dirname[15:].split()[0]
             version = dirname[15:].split()[0]
-            version = map(int, version.split('.'))
+            version = tuple(map(int, version.split('.')))
             speedtrees.append((version, dirname))
             speedtrees.append((version, dirname))
     if not speedtrees:
     if not speedtrees:
         # No installed SpeedTree SDK.
         # No installed SpeedTree SDK.
@@ -2142,11 +2184,11 @@ def LibName(opt, name):
         if not os.path.exists(name):
         if not os.path.exists(name):
             WARNINGS.append(name + " not found.  Skipping Package " + opt)
             WARNINGS.append(name + " not found.  Skipping Package " + opt)
             if (opt in PkgListGet()):
             if (opt in PkgListGet()):
-                print "%sWARNING:%s Could not locate thirdparty package %s, excluding from build" % (GetColor("red"), GetColor(), opt.lower())
+                print("%sWARNING:%s Could not locate thirdparty package %s, excluding from build" % (GetColor("red"), GetColor(), opt.lower()))
                 PkgDisable(opt)
                 PkgDisable(opt)
                 return
                 return
             else:
             else:
-                print "%sERROR:%s Could not locate thirdparty package %s, aborting build" % (GetColor("red"), GetColor(), opt.lower())
+                print("%sERROR:%s Could not locate thirdparty package %s, aborting build" % (GetColor("red"), GetColor(), opt.lower()))
                 exit()
                 exit()
     LIBNAMES.append((opt, name))
     LIBNAMES.append((opt, name))
 
 
@@ -2248,20 +2290,20 @@ def CopyFile(dstfile, srcfile):
         if (fnl < 0): fn = srcfile
         if (fnl < 0): fn = srcfile
         else: fn = srcfile[fnl+1:]
         else: fn = srcfile[fnl+1:]
         dstfile = dstdir + fn
         dstfile = dstdir + fn
-    if (NeedsBuild([dstfile],[srcfile])):
-        WriteFile(dstfile,ReadFile(srcfile))
+    if (NeedsBuild([dstfile], [srcfile])):
+        WriteBinaryFile(dstfile, ReadBinaryFile(srcfile))
         JustBuilt([dstfile], [srcfile])
         JustBuilt([dstfile], [srcfile])
 
 
 def CopyAllFiles(dstdir, srcdir, suffix=""):
 def CopyAllFiles(dstdir, srcdir, suffix=""):
     for x in GetDirectoryContents(srcdir, ["*"+suffix]):
     for x in GetDirectoryContents(srcdir, ["*"+suffix]):
-        CopyFile(dstdir+x, srcdir+x)
+        CopyFile(dstdir + x, srcdir + x)
 
 
 def CopyAllHeaders(dir, skip=[]):
 def CopyAllHeaders(dir, skip=[]):
     for filename in GetDirectoryContents(dir, ["*.h", "*.I", "*.T"], skip):
     for filename in GetDirectoryContents(dir, ["*.h", "*.I", "*.T"], skip):
         srcfile = dir + "/" + filename
         srcfile = dir + "/" + filename
         dstfile = OUTPUTDIR + "/include/" + filename
         dstfile = OUTPUTDIR + "/include/" + filename
         if (NeedsBuild([dstfile], [srcfile])):
         if (NeedsBuild([dstfile], [srcfile])):
-            WriteFile(dstfile, ReadFile(srcfile))
+            WriteBinaryFile(dstfile, ReadBinaryFile(srcfile))
             JustBuilt([dstfile], [srcfile])
             JustBuilt([dstfile], [srcfile])
 
 
 def CopyAllJavaSources(dir, skip=[]):
 def CopyAllJavaSources(dir, skip=[]):
@@ -2269,7 +2311,7 @@ def CopyAllJavaSources(dir, skip=[]):
         srcfile = dir + "/" + filename
         srcfile = dir + "/" + filename
         dstfile = OUTPUTDIR + "/src/org/panda3d/android/" + filename
         dstfile = OUTPUTDIR + "/src/org/panda3d/android/" + filename
         if (NeedsBuild([dstfile], [srcfile])):
         if (NeedsBuild([dstfile], [srcfile])):
-            WriteFile(dstfile, ReadFile(srcfile))
+            WriteBinaryFile(dstfile, ReadBinaryFile(srcfile))
             JustBuilt([dstfile], [srcfile])
             JustBuilt([dstfile], [srcfile])
 
 
 def CopyTree(dstdir, srcdir, omitCVS=True):
 def CopyTree(dstdir, srcdir, omitCVS=True):