|
@@ -3,9 +3,11 @@ Generates a wheel (.whl) file from the output of makepanda.
|
|
|
|
|
|
|
|
Since the wheel requires special linking, this will only work if compiled with
|
|
Since the wheel requires special linking, this will only work if compiled with
|
|
|
the `--wheel` parameter.
|
|
the `--wheel` parameter.
|
|
|
|
|
+
|
|
|
|
|
+Please keep this file work with Panda3D 1.9 until that reaches EOL.
|
|
|
"""
|
|
"""
|
|
|
from __future__ import print_function, unicode_literals
|
|
from __future__ import print_function, unicode_literals
|
|
|
-from distutils.util import get_platform as get_dist
|
|
|
|
|
|
|
+from distutils.util import get_platform
|
|
|
import json
|
|
import json
|
|
|
|
|
|
|
|
import sys
|
|
import sys
|
|
@@ -16,20 +18,18 @@ import zipfile
|
|
|
import hashlib
|
|
import hashlib
|
|
|
import tempfile
|
|
import tempfile
|
|
|
import subprocess
|
|
import subprocess
|
|
|
-from sysconfig import get_config_var
|
|
|
|
|
|
|
+from distutils.sysconfig import get_config_var
|
|
|
from optparse import OptionParser
|
|
from optparse import OptionParser
|
|
|
from makepandacore import ColorText, LocateBinary, ParsePandaVersion, GetExtensionSuffix, SetVerbose, GetVerbose
|
|
from makepandacore import ColorText, LocateBinary, ParsePandaVersion, GetExtensionSuffix, SetVerbose, GetVerbose
|
|
|
from base64 import urlsafe_b64encode
|
|
from base64 import urlsafe_b64encode
|
|
|
|
|
|
|
|
|
|
|
|
|
-def get_platform():
|
|
|
|
|
- p = get_dist().replace('-', '_').replace('.', '_')
|
|
|
|
|
- #if "linux" in p:
|
|
|
|
|
- # print(ColorText("red", "WARNING:") +
|
|
|
|
|
- # " Linux-specific wheel files are not supported."
|
|
|
|
|
- # " We will generate this wheel as a generic package instead.")
|
|
|
|
|
- # return "any"
|
|
|
|
|
- return p
|
|
|
|
|
|
|
+default_platform = get_platform()
|
|
|
|
|
+
|
|
|
|
|
+if default_platform.startswith("linux-"):
|
|
|
|
|
+ # Is this manylinux1?
|
|
|
|
|
+ if os.path.isfile("/lib/libc-2.5.so") and os.path.isdir("/opt/python"):
|
|
|
|
|
+ default_platform = platform.replace("linux", "manylinux1")
|
|
|
|
|
|
|
|
|
|
|
|
|
def get_abi_tag():
|
|
def get_abi_tag():
|
|
@@ -71,7 +71,9 @@ def is_elf_file(path):
|
|
|
def is_mach_o_file(path):
|
|
def is_mach_o_file(path):
|
|
|
base = os.path.basename(path)
|
|
base = os.path.basename(path)
|
|
|
return os.path.isfile(path) and '.' not in base and \
|
|
return os.path.isfile(path) and '.' not in base and \
|
|
|
- open(path, 'rb').read(4) == b'\xCA\xFE\xBA\xBE'
|
|
|
|
|
|
|
+ open(path, 'rb').read(4) in (b'\xCA\xFE\xBA\xBE', b'\xBE\xBA\xFE\bCA',
|
|
|
|
|
+ b'\xFE\xED\xFA\xCE', b'\xCE\xFA\xED\xFE',
|
|
|
|
|
+ b'\xFE\xED\xFA\xCF', b'\xCF\xFA\xED\xFE')
|
|
|
|
|
|
|
|
|
|
|
|
|
if sys.platform in ('win32', 'cygwin'):
|
|
if sys.platform in ('win32', 'cygwin'):
|
|
@@ -83,18 +85,17 @@ else:
|
|
|
|
|
|
|
|
|
|
|
|
|
# Other global parameters
|
|
# Other global parameters
|
|
|
-PY_VERSION = "cp{}{}".format(sys.version_info.major, sys.version_info.minor)
|
|
|
|
|
|
|
+PY_VERSION = "cp{0}{1}".format(*sys.version_info)
|
|
|
ABI_TAG = get_abi_tag()
|
|
ABI_TAG = get_abi_tag()
|
|
|
-PLATFORM_TAG = get_platform()
|
|
|
|
|
EXCLUDE_EXT = [".pyc", ".pyo", ".N", ".prebuilt", ".xcf", ".plist", ".vcproj", ".sln"]
|
|
EXCLUDE_EXT = [".pyc", ".pyo", ".N", ".prebuilt", ".xcf", ".plist", ".vcproj", ".sln"]
|
|
|
|
|
|
|
|
# Plug-ins to install.
|
|
# Plug-ins to install.
|
|
|
-PLUGIN_LIBS = ["pandagl", "pandagles", "pandagles2", "p3ptloader", "p3assimp", "p3ffmpeg", "p3openal_audio", "p3fmod_audio"]
|
|
|
|
|
|
|
+PLUGIN_LIBS = ["pandagl", "pandagles", "pandagles2", "pandadx9", "p3tinydisplay", "p3ptloader", "p3assimp", "p3ffmpeg", "p3openal_audio", "p3fmod_audio"]
|
|
|
|
|
|
|
|
WHEEL_DATA = """Wheel-Version: 1.0
|
|
WHEEL_DATA = """Wheel-Version: 1.0
|
|
|
Generator: makepanda
|
|
Generator: makepanda
|
|
|
Root-Is-Purelib: false
|
|
Root-Is-Purelib: false
|
|
|
-Tag: {}-{}-{}
|
|
|
|
|
|
|
+Tag: {0}-{1}-{2}
|
|
|
"""
|
|
"""
|
|
|
|
|
|
|
|
METADATA = {
|
|
METADATA = {
|
|
@@ -234,7 +235,11 @@ def scan_dependencies(pathname):
|
|
|
else:
|
|
else:
|
|
|
command = ['ldd', pathname]
|
|
command = ['ldd', pathname]
|
|
|
|
|
|
|
|
- output = subprocess.check_output(command, universal_newlines=True)
|
|
|
|
|
|
|
+ process = subprocess.Popen(command, stdout=subprocess.PIPE, universal_newlines=True)
|
|
|
|
|
+ output, unused_err = process.communicate()
|
|
|
|
|
+ retcode = process.poll()
|
|
|
|
|
+ if retcode:
|
|
|
|
|
+ raise subprocess.CalledProcessError(retcode, command[0], output=output)
|
|
|
filenames = None
|
|
filenames = None
|
|
|
|
|
|
|
|
if sys.platform in ("win32", "cygwin"):
|
|
if sys.platform in ("win32", "cygwin"):
|
|
@@ -245,16 +250,21 @@ def scan_dependencies(pathname):
|
|
|
if filenames is None:
|
|
if filenames is None:
|
|
|
sys.exit("Unable to determine dependencies from %s" % (pathname))
|
|
sys.exit("Unable to determine dependencies from %s" % (pathname))
|
|
|
|
|
|
|
|
|
|
+ if sys.platform == "darwin" and len(filenames) > 0:
|
|
|
|
|
+ # Filter out the library ID.
|
|
|
|
|
+ if os.path.basename(filenames[0]).split('.', 1)[0] == os.path.basename(pathname).split('.', 1)[0]:
|
|
|
|
|
+ del filenames[0]
|
|
|
|
|
+
|
|
|
return filenames
|
|
return filenames
|
|
|
|
|
|
|
|
|
|
|
|
|
class WheelFile(object):
|
|
class WheelFile(object):
|
|
|
- def __init__(self, name, version):
|
|
|
|
|
|
|
+ def __init__(self, name, version, platform):
|
|
|
self.name = name
|
|
self.name = name
|
|
|
self.version = version
|
|
self.version = version
|
|
|
|
|
|
|
|
- wheel_name = "{}-{}-{}-{}-{}.whl".format(
|
|
|
|
|
- name, version, PY_VERSION, ABI_TAG, PLATFORM_TAG)
|
|
|
|
|
|
|
+ wheel_name = "{0}-{1}-{2}-{3}-{4}.whl".format(
|
|
|
|
|
+ name, version, PY_VERSION, ABI_TAG, platform)
|
|
|
|
|
|
|
|
print("Writing %s" % (wheel_name))
|
|
print("Writing %s" % (wheel_name))
|
|
|
self.zip_file = zipfile.ZipFile(wheel_name, 'w', zipfile.ZIP_DEFLATED)
|
|
self.zip_file = zipfile.ZipFile(wheel_name, 'w', zipfile.ZIP_DEFLATED)
|
|
@@ -279,6 +289,10 @@ class WheelFile(object):
|
|
|
# Don't include the Python library.
|
|
# Don't include the Python library.
|
|
|
return
|
|
return
|
|
|
|
|
|
|
|
|
|
+ if sys.platform == "darwin" and dep.endswith(".so"):
|
|
|
|
|
+ # Temporary hack for 1.9, which had link deps on modules.
|
|
|
|
|
+ return
|
|
|
|
|
+
|
|
|
source_path = None
|
|
source_path = None
|
|
|
|
|
|
|
|
if search_path is None:
|
|
if search_path is None:
|
|
@@ -372,7 +386,7 @@ class WheelFile(object):
|
|
|
# Save it in PEP-0376 format for writing out later.
|
|
# Save it in PEP-0376 format for writing out later.
|
|
|
digest = str(urlsafe_b64encode(sha.digest()))
|
|
digest = str(urlsafe_b64encode(sha.digest()))
|
|
|
digest = digest.rstrip('=')
|
|
digest = digest.rstrip('=')
|
|
|
- self.records.append("{},sha256={},{}\n".format(target_path, digest, size))
|
|
|
|
|
|
|
+ self.records.append("{0},sha256={1},{2}\n".format(target_path, digest, size))
|
|
|
|
|
|
|
|
if GetVerbose():
|
|
if GetVerbose():
|
|
|
print("Adding %s from %s" % (target_path, source_path))
|
|
print("Adding %s from %s" % (target_path, source_path))
|
|
@@ -388,7 +402,7 @@ class WheelFile(object):
|
|
|
sha.update(source_data.encode())
|
|
sha.update(source_data.encode())
|
|
|
digest = str(urlsafe_b64encode(sha.digest()))
|
|
digest = str(urlsafe_b64encode(sha.digest()))
|
|
|
digest = digest.rstrip('=')
|
|
digest = digest.rstrip('=')
|
|
|
- self.records.append("{},sha256={},{}\n".format(target_path, digest, len(source_data)))
|
|
|
|
|
|
|
+ self.records.append("{0},sha256={1},{2}\n".format(target_path, digest, len(source_data)))
|
|
|
|
|
|
|
|
if GetVerbose():
|
|
if GetVerbose():
|
|
|
print("Adding %s from data" % target_path)
|
|
print("Adding %s from data" % target_path)
|
|
@@ -409,18 +423,20 @@ class WheelFile(object):
|
|
|
|
|
|
|
|
def close(self):
|
|
def close(self):
|
|
|
# Write the RECORD file.
|
|
# Write the RECORD file.
|
|
|
- record_file = "{}-{}.dist-info/RECORD".format(self.name, self.version)
|
|
|
|
|
|
|
+ record_file = "{0}-{1}.dist-info/RECORD".format(self.name, self.version)
|
|
|
self.records.append(record_file + ",,\n")
|
|
self.records.append(record_file + ",,\n")
|
|
|
|
|
|
|
|
self.zip_file.writestr(record_file, "".join(self.records))
|
|
self.zip_file.writestr(record_file, "".join(self.records))
|
|
|
self.zip_file.close()
|
|
self.zip_file.close()
|
|
|
|
|
|
|
|
|
|
|
|
|
-def makewheel(version, output_dir):
|
|
|
|
|
|
|
+def makewheel(version, output_dir, platform=default_platform):
|
|
|
if sys.platform not in ("win32", "darwin") and not sys.platform.startswith("cygwin"):
|
|
if sys.platform not in ("win32", "darwin") and not sys.platform.startswith("cygwin"):
|
|
|
if not LocateBinary("patchelf"):
|
|
if not LocateBinary("patchelf"):
|
|
|
raise Exception("patchelf is required when building a Linux wheel.")
|
|
raise Exception("patchelf is required when building a Linux wheel.")
|
|
|
|
|
|
|
|
|
|
+ platform = platform.replace('-', '_').replace('.', '_')
|
|
|
|
|
+
|
|
|
# Global filepaths
|
|
# Global filepaths
|
|
|
panda3d_dir = join(output_dir, "panda3d")
|
|
panda3d_dir = join(output_dir, "panda3d")
|
|
|
pandac_dir = join(output_dir, "pandac")
|
|
pandac_dir = join(output_dir, "pandac")
|
|
@@ -438,8 +454,8 @@ def makewheel(version, output_dir):
|
|
|
# Update relevant METADATA entries
|
|
# Update relevant METADATA entries
|
|
|
METADATA['version'] = version
|
|
METADATA['version'] = version
|
|
|
version_classifiers = [
|
|
version_classifiers = [
|
|
|
- "Programming Language :: Python :: {}".format(*sys.version_info),
|
|
|
|
|
- "Programming Language :: Python :: {}.{}".format(*sys.version_info),
|
|
|
|
|
|
|
+ "Programming Language :: Python :: {0}".format(*sys.version_info),
|
|
|
|
|
+ "Programming Language :: Python :: {0}.{1}".format(*sys.version_info),
|
|
|
]
|
|
]
|
|
|
METADATA['classifiers'].extend(version_classifiers)
|
|
METADATA['classifiers'].extend(version_classifiers)
|
|
|
|
|
|
|
@@ -454,14 +470,14 @@ def makewheel(version, output_dir):
|
|
|
"Version: {version}\n" \
|
|
"Version: {version}\n" \
|
|
|
"Summary: {summary}\n" \
|
|
"Summary: {summary}\n" \
|
|
|
"License: {license}\n".format(**METADATA),
|
|
"License: {license}\n".format(**METADATA),
|
|
|
- "Home-page: {}\n".format(homepage),
|
|
|
|
|
- "Author: {}\n".format(author),
|
|
|
|
|
- "Author-email: {}\n".format(email),
|
|
|
|
|
- "Platform: {}\n".format(PLATFORM_TAG),
|
|
|
|
|
- ] + ["Classifier: {}\n".format(c) for c in METADATA['classifiers']])
|
|
|
|
|
|
|
+ "Home-page: {0}\n".format(homepage),
|
|
|
|
|
+ "Author: {0}\n".format(author),
|
|
|
|
|
+ "Author-email: {0}\n".format(email),
|
|
|
|
|
+ "Platform: {0}\n".format(platform),
|
|
|
|
|
+ ] + ["Classifier: {0}\n".format(c) for c in METADATA['classifiers']])
|
|
|
|
|
|
|
|
# Zip it up and name it the right thing
|
|
# Zip it up and name it the right thing
|
|
|
- whl = WheelFile('panda3d', version)
|
|
|
|
|
|
|
+ whl = WheelFile('panda3d', version, platform)
|
|
|
whl.lib_path = [libs_dir]
|
|
whl.lib_path = [libs_dir]
|
|
|
|
|
|
|
|
# Add the trees with Python modules.
|
|
# Add the trees with Python modules.
|
|
@@ -479,11 +495,12 @@ def makewheel(version, output_dir):
|
|
|
elif file.endswith(ext_suffix) or file.endswith('.py'):
|
|
elif file.endswith(ext_suffix) or file.endswith('.py'):
|
|
|
source_path = os.path.join(panda3d_dir, file)
|
|
source_path = os.path.join(panda3d_dir, file)
|
|
|
|
|
|
|
|
- if file.endswith('.pyd') and PLATFORM_TAG.startswith('cygwin'):
|
|
|
|
|
|
|
+ if file.endswith('.pyd') and platform.startswith('cygwin'):
|
|
|
# Rename it to .dll for cygwin Python to be able to load it.
|
|
# Rename it to .dll for cygwin Python to be able to load it.
|
|
|
target_path = 'panda3d/' + os.path.splitext(file)[0] + '.dll'
|
|
target_path = 'panda3d/' + os.path.splitext(file)[0] + '.dll'
|
|
|
else:
|
|
else:
|
|
|
target_path = 'panda3d/' + file
|
|
target_path = 'panda3d/' + file
|
|
|
|
|
+
|
|
|
whl.write_file(target_path, source_path)
|
|
whl.write_file(target_path, source_path)
|
|
|
|
|
|
|
|
# Add plug-ins.
|
|
# Add plug-ins.
|
|
@@ -499,6 +516,16 @@ def makewheel(version, output_dir):
|
|
|
if os.path.isfile(plugin_path):
|
|
if os.path.isfile(plugin_path):
|
|
|
whl.write_file('panda3d/' + plugin_name, plugin_path)
|
|
whl.write_file('panda3d/' + plugin_name, plugin_path)
|
|
|
|
|
|
|
|
|
|
+ # Add the .data directory, containing additional files.
|
|
|
|
|
+ data_dir = 'panda3d-{0}.data'.format(version)
|
|
|
|
|
+ #whl.write_directory(data_dir + '/data/etc', etc_dir)
|
|
|
|
|
+ #whl.write_directory(data_dir + '/data/models', models_dir)
|
|
|
|
|
+
|
|
|
|
|
+ # Actually, let's not. That seems to install the files to the strangest
|
|
|
|
|
+ # places in the user's filesystem. Let's instead put them in panda3d.
|
|
|
|
|
+ whl.write_directory('panda3d/etc', etc_dir)
|
|
|
|
|
+ whl.write_directory('panda3d/models', models_dir)
|
|
|
|
|
+
|
|
|
# Add the pandac tree for backward compatibility.
|
|
# Add the pandac tree for backward compatibility.
|
|
|
for file in os.listdir(pandac_dir):
|
|
for file in os.listdir(pandac_dir):
|
|
|
if file.endswith('.py'):
|
|
if file.endswith('.py'):
|
|
@@ -506,8 +533,14 @@ def makewheel(version, output_dir):
|
|
|
|
|
|
|
|
# Add a panda3d-tools directory containing the executables.
|
|
# Add a panda3d-tools directory containing the executables.
|
|
|
entry_points = '[console_scripts]\n'
|
|
entry_points = '[console_scripts]\n'
|
|
|
|
|
+ entry_points += 'eggcacher = direct.directscripts.eggcacher:main\n'
|
|
|
|
|
+ entry_points += 'packpanda = direct.directscripts.packpanda:main\n'
|
|
|
tools_init = ''
|
|
tools_init = ''
|
|
|
for file in os.listdir(bin_dir):
|
|
for file in os.listdir(bin_dir):
|
|
|
|
|
+ basename = os.path.splitext(file)[0]
|
|
|
|
|
+ if basename in ('eggcacher', 'packpanda'):
|
|
|
|
|
+ continue
|
|
|
|
|
+
|
|
|
source_path = os.path.join(bin_dir, file)
|
|
source_path = os.path.join(bin_dir, file)
|
|
|
|
|
|
|
|
if is_executable(source_path):
|
|
if is_executable(source_path):
|
|
@@ -515,29 +548,18 @@ def makewheel(version, output_dir):
|
|
|
whl.write_file('panda3d_tools/' + file, source_path)
|
|
whl.write_file('panda3d_tools/' + file, source_path)
|
|
|
|
|
|
|
|
# Tell pip to create a wrapper script.
|
|
# Tell pip to create a wrapper script.
|
|
|
- basename = os.path.splitext(file)[0]
|
|
|
|
|
funcname = basename.replace('-', '_')
|
|
funcname = basename.replace('-', '_')
|
|
|
entry_points += '{0} = panda3d_tools:{1}\n'.format(basename, funcname)
|
|
entry_points += '{0} = panda3d_tools:{1}\n'.format(basename, funcname)
|
|
|
tools_init += '{0} = lambda: _exec_tool({1!r})\n'.format(funcname, file)
|
|
tools_init += '{0} = lambda: _exec_tool({1!r})\n'.format(funcname, file)
|
|
|
|
|
|
|
|
whl.write_file_data('panda3d_tools/__init__.py', PANDA3D_TOOLS_INIT.format(tools_init))
|
|
whl.write_file_data('panda3d_tools/__init__.py', PANDA3D_TOOLS_INIT.format(tools_init))
|
|
|
|
|
|
|
|
- # Add the .data directory, containing additional files.
|
|
|
|
|
- data_dir = 'panda3d-{}.data'.format(version)
|
|
|
|
|
- #whl.write_directory(data_dir + '/data/etc', etc_dir)
|
|
|
|
|
- #whl.write_directory(data_dir + '/data/models', models_dir)
|
|
|
|
|
-
|
|
|
|
|
- # Actually, let's not. That seems to install the files to the strangest
|
|
|
|
|
- # places in the user's filesystem. Let's instead put them in panda3d.
|
|
|
|
|
- whl.write_directory('panda3d/etc', etc_dir)
|
|
|
|
|
- whl.write_directory('panda3d/models', models_dir)
|
|
|
|
|
-
|
|
|
|
|
# Add the dist-info directory last.
|
|
# Add the dist-info directory last.
|
|
|
- info_dir = 'panda3d-{}.dist-info'.format(version)
|
|
|
|
|
|
|
+ info_dir = 'panda3d-{0}.dist-info'.format(version)
|
|
|
whl.write_file_data(info_dir + '/entry_points.txt', entry_points)
|
|
whl.write_file_data(info_dir + '/entry_points.txt', entry_points)
|
|
|
whl.write_file_data(info_dir + '/metadata.json', json.dumps(METADATA, indent=4, separators=(',', ': ')))
|
|
whl.write_file_data(info_dir + '/metadata.json', json.dumps(METADATA, indent=4, separators=(',', ': ')))
|
|
|
whl.write_file_data(info_dir + '/METADATA', metadata)
|
|
whl.write_file_data(info_dir + '/METADATA', metadata)
|
|
|
- whl.write_file_data(info_dir + '/WHEEL', WHEEL_DATA.format(PY_VERSION, ABI_TAG, PLATFORM_TAG))
|
|
|
|
|
|
|
+ whl.write_file_data(info_dir + '/WHEEL', WHEEL_DATA.format(PY_VERSION, ABI_TAG, platform))
|
|
|
whl.write_file(info_dir + '/LICENSE.txt', license_src)
|
|
whl.write_file(info_dir + '/LICENSE.txt', license_src)
|
|
|
whl.write_file(info_dir + '/README.md', readme_src)
|
|
whl.write_file(info_dir + '/README.md', readme_src)
|
|
|
whl.write_file_data(info_dir + '/top_level.txt', 'direct\npanda3d\npandac\npanda3d_tools\n')
|
|
whl.write_file_data(info_dir + '/top_level.txt', 'direct\npanda3d\npandac\npanda3d_tools\n')
|
|
@@ -552,6 +574,7 @@ if __name__ == "__main__":
|
|
|
parser.add_option('', '--version', dest = 'version', help = 'Panda3D version number (default: %s)' % (version), default = version)
|
|
parser.add_option('', '--version', dest = 'version', help = 'Panda3D version number (default: %s)' % (version), default = version)
|
|
|
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')
|
|
|
parser.add_option('', '--verbose', dest = 'verbose', help = 'Enable verbose output', action = 'store_true', default = False)
|
|
parser.add_option('', '--verbose', dest = 'verbose', help = 'Enable verbose output', action = 'store_true', default = False)
|
|
|
|
|
+ parser.add_option('', '--platform', dest = 'platform', help = 'Override platform tag (default: %s)' % (default_platform), default = get_platform())
|
|
|
(options, args) = parser.parse_args()
|
|
(options, args) = parser.parse_args()
|
|
|
|
|
|
|
|
SetVerbose(options.verbose)
|
|
SetVerbose(options.verbose)
|