diff --git a/direct/src/actor/Actor.py b/direct/src/actor/Actor.py index 6e23b0c346..8db72857e8 100644 --- a/direct/src/actor/Actor.py +++ b/direct/src/actor/Actor.py @@ -1532,8 +1532,10 @@ class Actor(DirectObject, NodePath): # actions def animPanel(self): - from direct.showbase import TkGlobal - from direct.tkpanels import AnimPanel + # Don't use a regular import, to prevent ModuleFinder from picking + # it up as a dependency when building a .p3d package. + import importlib + AnimPanel = importlib.import_module('direct.tkpanels.AnimPanel') return AnimPanel.AnimPanel(self) def stop(self, animName=None, partName=None): diff --git a/direct/src/directnotify/DirectNotify.py b/direct/src/directnotify/DirectNotify.py index d61420e3f5..2d3fb5ab19 100644 --- a/direct/src/directnotify/DirectNotify.py +++ b/direct/src/directnotify/DirectNotify.py @@ -111,10 +111,13 @@ class DirectNotify: category.setWarning(1) category.setInfo(1) category.setDebug(1) - + def popupControls(self, tl = None): - from direct.tkpanels import NotifyPanel + # Don't use a regular import, to prevent ModuleFinder from picking + # it up as a dependency when building a .p3d package. + import importlib + NotifyPanel = importlib.import_module('direct.tkpanels.NotifyPanel') NotifyPanel.NotifyPanel(self, tl) - + def giveNotify(self,cls): cls.notify = self.newCategory(cls.__name__) diff --git a/direct/src/extensions_native/CInterval_extensions.py b/direct/src/extensions_native/CInterval_extensions.py index 5a64d96c5f..eb82fc50f3 100644 --- a/direct/src/extensions_native/CInterval_extensions.py +++ b/direct/src/extensions_native/CInterval_extensions.py @@ -60,13 +60,17 @@ def popupControls(self, tl = None): """ Popup control panel for interval. """ - from direct.showbase.TkGlobal import Toplevel, Frame, Button, LEFT, X, Pmw import math - from direct.tkwidgets import EntryScale + # Don't use a regular import, to prevent ModuleFinder from picking + # it up as a dependency when building a .p3d package. + import importlib + EntryScale = importlib.import_module('direct.tkwidgets.EntryScale') + Tkinter = importlib.import_module('Tkinter') + if tl == None: - tl = Toplevel() + tl = Tkinter.Toplevel() tl.title('Interval Controls') - outerFrame = Frame(tl) + outerFrame = Tkinter.Frame(tl) def entryScaleCommand(t, s=self): s.setT(t) s.pause() @@ -75,8 +79,8 @@ def popupControls(self, tl = None): min = 0, max = math.floor(self.getDuration() * 100) / 100, command = entryScaleCommand) es.set(self.getT(), fCommand = 0) - es.pack(expand = 1, fill = X) - bf = Frame(outerFrame) + es.pack(expand = 1, fill = Tkinter.X) + bf = Tkinter.Frame(outerFrame) # Jump to start and end def toStart(s=self, es=es): s.setT(0.0) @@ -84,23 +88,23 @@ def popupControls(self, tl = None): def toEnd(s=self): s.setT(s.getDuration()) s.pause() - jumpToStart = Button(bf, text = '<<', command = toStart) + jumpToStart = Tkinter.Button(bf, text = '<<', command = toStart) # Stop/play buttons def doPlay(s=self, es=es): s.resume(es.get()) - stop = Button(bf, text = 'Stop', + stop = Tkinter.Button(bf, text = 'Stop', command = lambda s=self: s.pause()) - play = Button( + play = Tkinter.Button( bf, text = 'Play', command = doPlay) - jumpToEnd = Button(bf, text = '>>', command = toEnd) - jumpToStart.pack(side = LEFT, expand = 1, fill = X) - play.pack(side = LEFT, expand = 1, fill = X) - stop.pack(side = LEFT, expand = 1, fill = X) - jumpToEnd.pack(side = LEFT, expand = 1, fill = X) - bf.pack(expand = 1, fill = X) - outerFrame.pack(expand = 1, fill = X) + jumpToEnd = Tkinter.Button(bf, text = '>>', command = toEnd) + jumpToStart.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X) + play.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X) + stop.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X) + jumpToEnd.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X) + bf.pack(expand = 1, fill = Tkinter.X) + outerFrame.pack(expand = 1, fill = Tkinter.X) # Add function to update slider during setT calls def update(t, es=es): es.set(t, fCommand = 0) diff --git a/direct/src/extensions_native/NodePath_extensions.py b/direct/src/extensions_native/NodePath_extensions.py index 6e1920fde5..7383ae1e06 100644 --- a/direct/src/extensions_native/NodePath_extensions.py +++ b/direct/src/extensions_native/NodePath_extensions.py @@ -407,7 +407,10 @@ del iPosHprScale ##################################################################### def place(self): base.startDirect(fWantTk = 1) - from direct.tkpanels import Placer + # Don't use a regular import, to prevent ModuleFinder from picking + # it up as a dependency when building a .p3d package. + import importlib + Placer = importlib.import_module('direct.tkpanels.Placer') return Placer.place(self) Dtool_funcToMethod(place, NodePath) @@ -415,7 +418,10 @@ del place ##################################################################### def explore(self): base.startDirect(fWantTk = 1) - from direct.tkwidgets import SceneGraphExplorer + # Don't use a regular import, to prevent ModuleFinder from picking + # it up as a dependency when building a .p3d package. + import importlib + SceneGraphExplorer = importlib.import_module('direct.tkwidgets.SceneGraphExplorer') return SceneGraphExplorer.explore(self) Dtool_funcToMethod(explore, NodePath) @@ -423,7 +429,10 @@ del explore ##################################################################### def rgbPanel(self, cb = None): base.startTk() - from direct.tkwidgets import Slider + # Don't use a regular import, to prevent ModuleFinder from picking + # it up as a dependency when building a .p3d package. + import importlib + Slider = importlib.import_module('direct.tkwidgets.Slider') return Slider.rgbPanel(self, cb) Dtool_funcToMethod(rgbPanel, NodePath) diff --git a/direct/src/fsm/ClassicFSM.py b/direct/src/fsm/ClassicFSM.py index 880a249e2e..98191166ab 100644 --- a/direct/src/fsm/ClassicFSM.py +++ b/direct/src/fsm/ClassicFSM.py @@ -369,7 +369,10 @@ class ClassicFSM(DirectObject): return 0 def view(self): - from direct.tkpanels import FSMInspector + # Don't use a regular import, to prevent ModuleFinder from picking + # it up as a dependency when building a .p3d package. + import importlib + FSMInspector = importlib.import_module('direct.tkpanels.FSMInspector') FSMInspector.FSMInspector(self) def isInternalStateInFlux(self): diff --git a/direct/src/interval/Interval.py b/direct/src/interval/Interval.py index 1a677254cc..c44c63cb03 100644 --- a/direct/src/interval/Interval.py +++ b/direct/src/interval/Interval.py @@ -444,16 +444,16 @@ class Interval(DirectObject): """ Popup control panel for interval. """ - from direct.showbase import TkGlobal - import math - # I moved this here because Toontown does not ship Tk - from Tkinter import Toplevel, Frame, Button, LEFT, X - import Pmw - from direct.tkwidgets import EntryScale + # Don't use a regular import, to prevent ModuleFinder from picking + # it up as a dependency when building a .p3d package. + import importlib + EntryScale = importlib.import_module('direct.tkwidgets.EntryScale') + Tkinter = importlib.import_module('Tkinter') + if tl == None: - tl = Toplevel() + tl = Tkinter.Toplevel() tl.title('Interval Controls') - outerFrame = Frame(tl) + outerFrame = Tkinter.Frame(tl) def entryScaleCommand(t, s=self): s.setT(t) s.pause() @@ -462,8 +462,8 @@ class Interval(DirectObject): min = 0, max = math.floor(self.getDuration() * 100) / 100, command = entryScaleCommand) es.set(self.getT(), fCommand = 0) - es.pack(expand = 1, fill = X) - bf = Frame(outerFrame) + es.pack(expand = 1, fill = Tkinter.X) + bf = Tkinter.Frame(outerFrame) # Jump to start and end def toStart(s=self, es=es): s.clearToInitial() @@ -473,23 +473,23 @@ class Interval(DirectObject): s.setT(s.getDuration()) es.set(s.getDuration(), fCommand = 0) s.pause() - jumpToStart = Button(bf, text = '<<', command = toStart) + jumpToStart = Tkinter.Button(bf, text = '<<', command = toStart) # Stop/play buttons def doPlay(s=self, es=es): s.resume(es.get()) - stop = Button(bf, text = 'Stop', + stop = Tkinter.Button(bf, text = 'Stop', command = lambda s=self: s.pause()) - play = Button( + play = Tkinter.Button( bf, text = 'Play', command = doPlay) - jumpToEnd = Button(bf, text = '>>', command = toEnd) - jumpToStart.pack(side = LEFT, expand = 1, fill = X) - play.pack(side = LEFT, expand = 1, fill = X) - stop.pack(side = LEFT, expand = 1, fill = X) - jumpToEnd.pack(side = LEFT, expand = 1, fill = X) - bf.pack(expand = 1, fill = X) - outerFrame.pack(expand = 1, fill = X) + jumpToEnd = Tkinter.Button(bf, text = '>>', command = toEnd) + jumpToStart.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X) + play.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X) + stop.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X) + jumpToEnd.pack(side = Tkinter.LEFT, expand = 1, fill = Tkinter.X) + bf.pack(expand = 1, fill = Tkinter.X) + outerFrame.pack(expand = 1, fill = Tkinter.X) # Add function to update slider during setT calls def update(t, es=es): es.set(t, fCommand = 0) diff --git a/direct/src/p3d/AppRunner.py b/direct/src/p3d/AppRunner.py index 68443e4601..9c6c15631a 100644 --- a/direct/src/p3d/AppRunner.py +++ b/direct/src/p3d/AppRunner.py @@ -424,47 +424,8 @@ class AppRunner(DirectObject): it downloads a new version on-the-spot. Returns true on success, false on failure. """ - if fileSpec.quickVerify(pathname = localPathname): - # It's good, keep it. - return True - assert self.http - - # It's stale, get a new one. - doc = None - if self.superMirrorUrl: - # Use the "super mirror" first. - url = core.URLSpec(self.superMirrorUrl + fileSpec.filename) - self.notify.info("Freshening %s" % (url)) - doc = self.http.getDocument(url) - - if not doc or not doc.isValid(): - # Failing the super mirror, contact the actual host. - url = core.URLSpec(host.hostUrlPrefix + fileSpec.filename) - self.notify.info("Freshening %s" % (url)) - doc = self.http.getDocument(url) - if not doc.isValid(): - return False - - file = Filename.temporary('', 'p3d_') - if not doc.downloadToFile(file): - # Failed to download. - file.unlink() - return False - - # Successfully downloaded! - localPathname.makeDir() - if not file.renameTo(localPathname): - # Couldn't move it into place. - file.unlink() - return False - - if not fileSpec.fullVerify(pathname = localPathname, notify = self.notify): - # No good after download. - self.notify.info("%s is still no good after downloading." % (url)) - return False - - return True + return host.freshenFile(self.http, fileSpec, localPathname) def scanInstalledPackages(self): """ Scans the hosts and packages already installed locally on diff --git a/direct/src/p3d/HostInfo.py b/direct/src/p3d/HostInfo.py index ad9942c6a0..d97a39ea8e 100644 --- a/direct/src/p3d/HostInfo.py +++ b/direct/src/p3d/HostInfo.py @@ -40,8 +40,6 @@ class HostInfo: Note that perPlatform is also restricted by the individual package's specification. """ - assert appRunner or rootDir or hostDir - self.__setHostUrl(hostUrl) self.appRunner = appRunner self.rootDir = rootDir @@ -112,6 +110,52 @@ class HostInfo: # https-protected hostUrl, it will be the cleartext channel. self.downloadUrlPrefix = self.hostUrlPrefix + def freshenFile(self, http, fileSpec, localPathname): + """ Ensures that the localPathname is the most current version + of the file defined by fileSpec, as offered by host. If not, + it downloads a new version on-the-spot. Returns true on + success, false on failure. """ + + if fileSpec.quickVerify(pathname = localPathname): + # It's good, keep it. + return True + + # It's stale, get a new one. + doc = None + if self.appRunner and self.appRunner.superMirrorUrl: + # Use the "super mirror" first. + url = core.URLSpec(self.appRunner.superMirrorUrl + fileSpec.filename) + self.notify.info("Freshening %s" % (url)) + doc = http.getDocument(url) + + if not doc or not doc.isValid(): + # Failing the super mirror, contact the actual host. + url = core.URLSpec(self.hostUrlPrefix + fileSpec.filename) + self.notify.info("Freshening %s" % (url)) + doc = http.getDocument(url) + if not doc.isValid(): + return False + + file = Filename.temporary('', 'p3d_') + if not doc.downloadToFile(file): + # Failed to download. + file.unlink() + return False + + # Successfully downloaded! + localPathname.makeDir() + if not file.renameTo(localPathname): + # Couldn't move it into place. + file.unlink() + return False + + if not fileSpec.fullVerify(pathname = localPathname, notify = self.notify): + # No good after download. + self.notify.info("%s is still no good after downloading." % (url)) + return False + + return True + def downloadContentsFile(self, http, redownload = False, hashVal = None): """ Downloads the contents.xml file for this particular host, diff --git a/direct/src/p3d/Packager.py b/direct/src/p3d/Packager.py index f9ddab983f..14e8a9fa3c 100644 --- a/direct/src/p3d/Packager.py +++ b/direct/src/p3d/Packager.py @@ -13,12 +13,12 @@ import os import glob import string import types -import getpass import struct import subprocess import copy from direct.p3d.FileSpec import FileSpec from direct.p3d.SeqValue import SeqValue +from direct.p3d.HostInfo import HostInfo from direct.showbase import Loader from direct.showbase import AppRunnerGlobal from direct.showutil import FreezeTool @@ -378,7 +378,8 @@ class Packager: # This records the current list of modules we have added so # far. self.freezer = FreezeTool.Freezer(platform = self.packager.platform) - + self.freezer.storePythonSource = self.packager.storePythonSource + # Map of extensions to files to number (ignored by dir) self.ignoredDirFiles = {} @@ -1075,7 +1076,7 @@ class Packager: fpath.append(Filename("/Library/Frameworks")) fpath.append(Filename("/System/Library/Frameworks")) fpath.append(Filename("/Developer/Library/Frameworks")) - fpath.append(Filename("/Users/%s" % getpass.getuser(), "Library/Frameworks")) + fpath.append(Filename(os.path.expanduser("~"), "Library/Frameworks")) if "HOME" in os.environ: fpath.append(Filename(os.environ["HOME"], "Library/Frameworks")) ffilename = Filename(library.split('.framework/', 1)[0].split('/')[-1] + '.framework') @@ -2233,6 +2234,11 @@ class Packager: self.host = PandaSystem.getPackageHostUrl() self.addHost(self.host) + # This will be used when we're not compiling in the packaged + # environment. + self.__hostInfos = {} + self.http = HTTPClient.getGlobalPtr() + # The maximum amount of time a client should cache the # contents.xml before re-querying the server, in seconds. self.maxAge = 0 @@ -2318,6 +2324,10 @@ class Packager: # any applications. self.allowPythonDev = False + # Set this flag to store the original Python source files, + # without compiling them to .pyc or .pyo. + self.storePythonSource = False + # Fill this with a list of (certificate, chain, pkey, # password) tuples to automatically sign each p3d file # generated. @@ -3028,17 +3038,10 @@ class Packager: def __findPackageOnHost(self, packageName, platform, version, hostUrl, requires = None): appRunner = AppRunnerGlobal.appRunner - if not appRunner: - # We don't download import files from a host unless we're - # running in a packaged environment ourselves. It would - # be possible to do this, but a fair bit of work for not - # much gain--this is meant to be run in a packaged - # environment. - return None # Make sure we have a fresh version of the contents file. - host = appRunner.getHost(hostUrl) - if not host.downloadContentsFile(appRunner.http): + host = self.__getHostInfo(hostUrl) + if not host.downloadContentsFile(self.http): return None packageInfos = [] @@ -3063,23 +3066,48 @@ class Packager: # Now we've retrieved a PackageInfo. Get the import desc file # from it. - filename = Filename(host.hostDir, 'imports/' + packageInfo.importDescFile.basename) - if not appRunner.freshenFile(host, packageInfo.importDescFile, filename): + if host.hostDir: + filename = Filename(host.hostDir, 'imports/' + packageInfo.importDescFile.basename) + else: + # We're not running in the packaged environment, so download + # to a temporary file instead of the host directory. + filename = Filename.temporary('', 'import_' + packageInfo.importDescFile.basename, '.xml') + + if not host.freshenFile(self.http, packageInfo.importDescFile, filename): self.notify.error("Couldn't download import file.") continue # Now that we have the import desc file, use it to load one of # our Package objects. package = self.Package('', self) - if not package.readImportDescFile(filename): - continue + success = package.readImportDescFile(filename) - if self.__packageIsValid(package, requires, platform): + if not host.hostDir: + # Don't forget to delete the temporary file we created. + filename.unlink() + + if success and self.__packageIsValid(package, requires, platform): return package # Couldn't find a suitable package. return None + def __getHostInfo(self, hostUrl = None): + """ This shadows appRunner.getHost(), for the purpose of running + outside the packaged environment. """ + + if not hostUrl: + hostUrl = PandaSystem.getPackageHostUrl() + + if AppRunnerGlobal.appRunner: + return AppRunnerGlobal.appRunner.getHost(hostUrl) + + host = self.__hostInfos.get(hostUrl, None) + if not host: + host = HostInfo(hostUrl) + self.__hostInfos[hostUrl] = host + return host + def __sortImportPackages(self, packages): """ Given a list of Packages read from *.import.xml filenames, sorts them in reverse order by version, so that the diff --git a/direct/src/p3d/ppackage.py b/direct/src/p3d/ppackage.py index 4cb02eae80..7ca16fd4f9 100755 --- a/direct/src/p3d/ppackage.py +++ b/direct/src/p3d/ppackage.py @@ -83,6 +83,10 @@ Options: initially, but should not be set on an application intended for deployment. + -N + If this option is set, Packager will not try to compile any Python + files to .pyc or .pyo, instead storing the original source files. + -u On the Mac OSX platform, this means that Panda was built with universal binaries, and the package should be built that way as @@ -152,6 +156,7 @@ buildPatches = False installSearch = [] signParams = [] allowPythonDev = False +storePythonSource = False universalBinaries = False systemRoot = None ignoreSetHost = False @@ -160,7 +165,7 @@ p3dSuffix = '' platforms = [] try: - opts, args = getopt.getopt(sys.argv[1:], 'i:ps:S:DuP:R:Ha:hv') + opts, args = getopt.getopt(sys.argv[1:], 'i:ps:S:DNuP:R:Ha:hv') except getopt.error as msg: usage(1, msg) @@ -182,6 +187,8 @@ for opt, arg in opts: Filename.fromOsSpecific(password))) elif opt == '-D': allowPythonDev = True + elif opt == '-N': + storePythonSource = True elif opt == '-u': universalBinaries = True elif opt == '-P': @@ -236,6 +243,7 @@ for platform in platforms: packager.installSearch = [installDir] + packager.installSearch packager.signParams = signParams packager.allowPythonDev = allowPythonDev + packager.storePythonSource = storePythonSource packager.systemRoot = systemRoot packager.ignoreSetHost = ignoreSetHost packager.verbosePrint = verbosePrint diff --git a/direct/src/showbase/PythonUtil.py b/direct/src/showbase/PythonUtil.py index 51ba813cb2..9a5551d7b9 100644 --- a/direct/src/showbase/PythonUtil.py +++ b/direct/src/showbase/PythonUtil.py @@ -325,7 +325,10 @@ def adjust(command = None, dim = 1, parent = None, **kw): 10.0 """ # Make sure we enable Tk - from direct.tkwidgets import Valuator + # Don't use a regular import, to prevent ModuleFinder from picking + # it up as a dependency when building a .p3d package. + import importlib + Valuator = importlib.import_module('direct.tkwidgets.Valuator') # Set command if specified if command: kw['command'] = lambda x: apply(command, x) diff --git a/direct/src/showbase/ShowBaseGlobal.py b/direct/src/showbase/ShowBaseGlobal.py index 0722580019..451f411f15 100644 --- a/direct/src/showbase/ShowBaseGlobal.py +++ b/direct/src/showbase/ShowBaseGlobal.py @@ -14,7 +14,10 @@ assert base directNotify.setDconfigLevels() def inspect(anObject): - from direct.tkpanels import Inspector + # Don't use a regular import, to prevent ModuleFinder from picking + # it up as a dependency when building a .p3d package. + import importlib + Inspector = importlib.import_module('direct.tkpanels.Inspector') return Inspector.inspect(anObject) import __builtin__ diff --git a/direct/src/showutil/FreezeTool.py b/direct/src/showutil/FreezeTool.py index 4b186d1eeb..7b1ee6ef6b 100644 --- a/direct/src/showutil/FreezeTool.py +++ b/direct/src/showutil/FreezeTool.py @@ -1143,6 +1143,7 @@ class Freezer: elif getattr(module, '__file__', None): sourceFilename = Filename.fromOsSpecific(module.__file__) sourceFilename.setExtension("py") + sourceFilename.setText() if self.storePythonSource: if sourceFilename and sourceFilename.exists(): diff --git a/direct/src/task/Task.py b/direct/src/task/Task.py index 63ee7fd271..4a15f1d824 100644 --- a/direct/src/task/Task.py +++ b/direct/src/task/Task.py @@ -582,7 +582,10 @@ class TaskManager: return numFound def popupControls(self): - from direct.tkpanels import TaskManagerPanel + # Don't use a regular import, to prevent ModuleFinder from picking + # it up as a dependency when building a .p3d package. + import importlib + TaskManagerPanel = importlib.import_module('direct.tkpanels.TaskManagerPanel') return TaskManagerPanel.TaskManagerPanel(self) def getProfileSession(self, name=None): diff --git a/dtool/src/interrogate/interfaceMakerPythonNative.cxx b/dtool/src/interrogate/interfaceMakerPythonNative.cxx index fb6a5a6a70..4ca31e4503 100644 --- a/dtool/src/interrogate/interfaceMakerPythonNative.cxx +++ b/dtool/src/interrogate/interfaceMakerPythonNative.cxx @@ -4179,6 +4179,11 @@ bool RemapCompareLess(FunctionRemap *in1, FunctionRemap *in2) { assert(in1 != NULL); assert(in2 != NULL); + if (in1->_const_method != in2->_const_method) { + // Non-const methods should come first. + return in2->_const_method; + } + if (in1->_parameters.size() != in2->_parameters.size()) { return (in1->_parameters.size() > in2->_parameters.size()); } diff --git a/makepanda/makepanda.py b/makepanda/makepanda.py index 95b015f038..0a74c31349 100755 --- a/makepanda/makepanda.py +++ b/makepanda/makepanda.py @@ -1856,6 +1856,11 @@ def Package(target, inputs, opts): command += "direct/src/p3d/ppackage.py" + if not RTDIST: + # Don't compile Python sources, because we might not running in the same + # Python version as the selected host. + command += " -N" + if GetTarget() == "darwin": if SDK.get("MACOSX"): command += " -R \"%s\"" % SDK["MACOSX"] @@ -1868,8 +1873,31 @@ def Package(target, inputs, opts): command += " -i \"" + GetOutputDir() + "/stage\"" if (P3DSUFFIX): command += ' -a "' + P3DSUFFIX + '"' + command += " " + inputs[0] - oscmd(command) + + if GetOrigExt(target) == '.p3d': + # Build a specific .p3d file. + basename = os.path.basename(os.path.splitext(target)[0]) + command += " " + basename + oscmd(command) + + if GetTarget() == 'windows': + # Make an .exe that calls this .p3d. + objfile = FindLocation('p3dWrapper_' + basename + '.obj', []) + CompileCxx(objfile, 'direct/src/p3d/p3dWrapper.c', []) + + exefile = FindLocation(basename + '.exe', []) + CompileLink(exefile, [objfile], ['ADVAPI']) + + # Move it to the bin directory. + os.rename(GetOutputDir() + '/stage/' + basename + P3DSUFFIX + '.p3d', target) + + if sys.platform != 'win32': + oscmd('chmod +x ' + BracketNameWithQuotes(target)) + else: + # This is presumably a package or set of packages. + oscmd(command) ########################################################################################## # @@ -1970,7 +1998,10 @@ def CompileAnything(target, inputs, opts, progress = None): ProgressOutput(progress, "Compiling MIDL file", infile) return CompileMIDL(target, infile, opts) elif (infile.endswith(".pdef")): - ProgressOutput(progress, "Building package from pdef file", infile) + if origsuffix == '.p3d': + ProgressOutput(progress, "Building package", target) + else: + ProgressOutput(progress, "Building package from pdef file", infile) return Package(target, inputs, opts) elif origsuffix in SUFFIX_LIB: ProgressOutput(progress, "Linking static library", target) @@ -6234,26 +6265,17 @@ if (RTDIST): TargetAdd('_thirdparty', opts=OPTS, input='thirdparty.pdef') # -# Distribute prebuilt .p3d files as executable. +# If we have a host URL and distributor, we can make .p3d deployment tools. # -if (PkgSkip("DIRECT")==0 and not RUNTIME and not RTDIST): - if GetTarget() == 'windows': +if not PkgSkip("DIRECT") and not PkgSkip("DEPLOYTOOLS") and not RUNTIME and not RTDIST and HOST_URL and DISTRIBUTOR: OPTS=['DIR:direct/src/p3d'] - TargetAdd('p3dWrapper.obj', opts=OPTS, input='p3dWrapper.c') - TargetAdd('p3dWrapper.exe', input='p3dWrapper.obj') - TargetAdd('p3dWrapper.exe', opts=["ADVAPI"]) - for g in glob.glob("direct/src/p3d/*.p3d"): - base = os.path.basename(g) - base = base.split(".", 1)[0] - - if GetTarget() == 'windows': - TargetAdd(base+".exe", input='p3dWrapper.exe') - CopyFile(GetOutputDir()+"/bin/"+base+".p3d", g) - else: - CopyFile(GetOutputDir()+"/bin/"+base, g) - oscmd("chmod +x "+GetOutputDir()+"/bin/"+base) + TargetAdd('packp3d.p3d', opts=OPTS, input='panda3d.pdef') + TargetAdd('pdeploy.p3d', opts=OPTS, input='panda3d.pdef') + TargetAdd('pmerge.p3d', opts=OPTS, input='panda3d.pdef') + TargetAdd('ppackage.p3d', opts=OPTS, input='panda3d.pdef') + TargetAdd('ppatcher.p3d', opts=OPTS, input='panda3d.pdef') ########################################################################################## # diff --git a/makepanda/makepandacore.py b/makepanda/makepandacore.py index 4a081df235..e587cf26ef 100644 --- a/makepanda/makepandacore.py +++ b/makepanda/makepandacore.py @@ -1881,7 +1881,7 @@ def SdkLocatePython(prefer_thirdparty_python=False): sdkdir += "-x64" SDK["PYTHON"] = sdkdir - SDK["PYTHONEXEC"] = SDK["PYTHON"].replace('/', '\\') + "\\python" + SDK["PYTHONEXEC"] = SDK["PYTHON"].replace('\\', '/') + "/python" if (GetOptimize() <= 2): SDK["PYTHONEXEC"] += "_d.exe" else: @@ -2824,6 +2824,7 @@ def CalcLocation(fn, ipath): if (fn.endswith(".dle")): return OUTPUTDIR+"/plugins/"+fn[:-4]+dllext+".dle" if (fn.endswith(".plugin")):return OUTPUTDIR+"/plugins/"+fn[:-7]+dllext+".dll" if (fn.endswith(".exe")): return OUTPUTDIR+"/bin/"+fn + if (fn.endswith(".p3d")): return OUTPUTDIR+"/bin/"+fn if (fn.endswith(".lib")): return OUTPUTDIR+"/lib/"+fn[:-4]+dllext+".lib" if (fn.endswith(".ilb")): return OUTPUTDIR+"/tmp/"+fn[:-4]+dllext+".lib" elif (target == 'darwin'): @@ -2835,6 +2836,7 @@ def CalcLocation(fn, ipath): if (fn.endswith(".pyd")): return OUTPUTDIR+"/panda3d/"+fn[:-4]+".so" if (fn.endswith(".mll")): return OUTPUTDIR+"/plugins/"+fn if (fn.endswith(".exe")): return OUTPUTDIR+"/bin/"+fn[:-4] + if (fn.endswith(".p3d")): return OUTPUTDIR+"/bin/"+fn[:-4] if (fn.endswith(".lib")): return OUTPUTDIR+"/lib/"+fn[:-4]+".a" if (fn.endswith(".ilb")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".a" if (fn.endswith(".rsrc")): return OUTPUTDIR+"/tmp/"+fn @@ -2857,6 +2859,7 @@ def CalcLocation(fn, ipath): if (fn.endswith(".mll")): return OUTPUTDIR+"/plugins/"+fn if (fn.endswith(".plugin")):return OUTPUTDIR+"/plugins/"+fn[:-7]+dllext+".so" if (fn.endswith(".exe")): return OUTPUTDIR+"/bin/"+fn[:-4] + if (fn.endswith(".p3d")): return OUTPUTDIR+"/bin/"+fn[:-4] if (fn.endswith(".lib")): return OUTPUTDIR+"/lib/"+fn[:-4]+".a" if (fn.endswith(".ilb")): return OUTPUTDIR+"/tmp/"+fn[:-4]+".a" if (fn.endswith(".dat")): return OUTPUTDIR+"/tmp/"+fn