Browse Source

deploy-ng: fix failure to include libpython (particularly on macOS)

rdb 8 years ago
parent
commit
58917e6746
3 changed files with 39 additions and 20 deletions
  1. 1 3
      direct/src/showutil/FreezeTool.py
  2. 21 6
      direct/src/showutil/dist.py
  3. 17 11
      makepanda/makewheel.py

+ 1 - 3
direct/src/showutil/FreezeTool.py

@@ -1619,17 +1619,15 @@ class Freezer:
 
         return target
 
-    def generateRuntimeFromStub(self, basename, stub_file, fields={}):
+    def generateRuntimeFromStub(self, target, stub_file, fields={}):
         # We must have a __main__ module to make an exe file.
         if not self.__writingModule('__main__'):
             message = "Can't generate an executable without a __main__ module."
             raise Exception(message)
 
         if self.platform.startswith('win'):
-            target = basename + '.exe'
             modext = '.pyd'
         else:
-            target = basename
             modext = '.so'
 
         # First gather up the strings and code for all the module names, and

+ 21 - 6
direct/src/showutil/dist.py

@@ -280,11 +280,16 @@ class build_apps(distutils.core.Command):
                 freezer.excludeModule(exmod)
             freezer.done(addStartupModules=True)
 
+            target_path = os.path.join(builddir, appname)
+
             stub_name = 'deploy-stub'
             if platform.startswith('win'):
                 if not use_console:
                     stub_name = 'deploy-stubw'
+
+            if platform.startswith('win'):
                 stub_name += '.exe'
+                target_path += '.exe'
 
             if use_wheels:
                 stub_file = p3dwhl.open('panda3d_tools/{0}'.format(stub_name))
@@ -293,7 +298,7 @@ class build_apps(distutils.core.Command):
                 stub_path = os.path.join(os.path.dirname(dtool_path), '..', 'bin', stub_name)
                 stub_file = open(stub_path, 'rb')
 
-            freezer.generateRuntimeFromStub(os.path.join(builddir, appname), stub_file, {
+            freezer.generateRuntimeFromStub(target_path, stub_file, {
                 'prc_data': None,
                 'default_prc_dir': None,
                 'prc_dir_envvars': None,
@@ -306,6 +311,12 @@ class build_apps(distutils.core.Command):
             })
             stub_file.close()
 
+            # Copy the dependencies.
+            search_path = [builddir]
+            if use_wheels:
+                search_path.append(os.path.join(p3dwhlfn, 'deploy_libs'))
+            self.copy_dependencies(open(target_path, 'rb'), builddir, search_path, stub_name)
+
             freezer_extras.update(freezer.extras)
             freezer_modules.update(freezer.getAllModuleNames())
 
@@ -556,6 +567,13 @@ class build_apps(distutils.core.Command):
             shutil.copyfile(source_path, target_path)
             fp = open(target_path, 'rb')
 
+        target_dir = os.path.dirname(target_path)
+        base = os.path.basename(target_path)
+        self.copy_dependencies(fp, target_dir, search_path, base)
+
+    def copy_dependencies(self, fp, target_dir, search_path, referenced_by):
+        """ Copies the dependencies of the given open file. """
+
         # What kind of magic does the file contain?
         deps = []
         magic = fp.read(4)
@@ -589,11 +607,8 @@ class build_apps(distutils.core.Command):
             deps = self._read_dependencies_fat(fp, True)
 
         # If we discovered any dependencies, recursively add those.
-        if deps:
-            target_dir = os.path.dirname(target_path)
-            base = os.path.basename(target_path)
-            for dep in deps:
-                self.add_dependency(dep, target_dir, search_path, base)
+        for dep in deps:
+            self.add_dependency(dep, target_dir, search_path, referenced_by)
 
     def _read_dependencies_elf(self, elf, origin, search_path):
         """ Having read the first 4 bytes of the ELF file, fetches the

+ 17 - 11
makepanda/makewheel.py

@@ -350,19 +350,25 @@ class WheelFile(object):
 
             # Fix things like @loader_path/../lib references
             if sys.platform == "darwin":
+                deps_path = '@loader_path'
                 loader_path = [os.path.dirname(source_path)]
                 for dep in deps:
-                    if '@loader_path' not in dep:
-                        continue
+                    if dep.endswith('/Python'):
+                        # If this references the Python framework, change it
+                        # to reference libpython instead.
+                        new_dep = deps_path + '/libpython{0}.{1}.dylib'.format(*sys.version_info)
+                    else:
+                        if '@loader_path' not in dep:
+                            continue
+
+                        dep_path = dep.replace('@loader_path', '.')
+                        target_dep = os.path.dirname(target_path) + '/' + os.path.basename(dep)
+                        target_dep = self.consider_add_dependency(target_dep, dep_path, loader_path)
+                        if not target_dep:
+                            # It won't be included, so no use adjusting the path.
+                            continue
+                        new_dep = os.path.join(deps_path, os.path.relpath(target_dep, os.path.dirname(target_path)))
 
-                    dep_path = dep.replace('@loader_path', '.')
-                    target_dep = os.path.dirname(target_path) + '/' + os.path.basename(dep)
-                    target_dep = self.consider_add_dependency(target_dep, dep_path, loader_path)
-                    if not target_dep:
-                        # It won't be included, so no use adjusting the path.
-                        continue
-
-                    new_dep = os.path.join('@loader_path', os.path.relpath(target_dep, os.path.dirname(target_path)))
                     subprocess.call(["install_name_tool", "-change", dep, new_dep, temp.name])
             else:
                 subprocess.call(["strip", "-s", temp.name])
@@ -600,7 +606,7 @@ def makewheel(version, output_dir, platform=None):
     else:
         pylib_name = get_config_var('LDLIBRARY')
         pylib_path = os.path.join(get_config_var('LIBDIR'), pylib_name)
-    whl.write_file('/deploy_libs/' + pylib_name, pylib_path)
+    whl.write_file('deploy_libs/' + pylib_name, pylib_path)
 
     whl.close()