mirror of
https://github.com/jellyfin/jellyfin-media-player.git
synced 2024-11-30 09:40:52 +00:00
Download dependencies from CMake and fix install names
This makes it easier to deploy new versions of Qt and other deps.
This commit is contained in:
parent
9fc95e77d8
commit
4b93840a32
@ -1,4 +1,4 @@
|
||||
set(app "@EXE@")
|
||||
set(app "${CMAKE_INSTALL_PREFIX}/@EXE@")
|
||||
|
||||
list(APPEND BINS "Contents/Resources/updater")
|
||||
list(APPEND BINS "Contents/Resources/@HELPER_NAME@")
|
||||
@ -10,9 +10,18 @@ foreach(BIN ${BINS})
|
||||
list(APPEND args "-executable=${app}/${BIN}")
|
||||
endforeach(BIN ${BINS})
|
||||
|
||||
set(ENV{DYLD_LIBRARY_PATH} @QTROOT@/lib:@DEPENDENCY_ROOT@/lib)
|
||||
set(ENV{DYLD_FRAMEWORK_PATH} @QTROOT@/lib:@DEPENDENCY_ROOT@/lib)
|
||||
|
||||
set(QTCONFCONTENT "[Paths]
|
||||
Prefix=@QTROOT@
|
||||
")
|
||||
|
||||
file(WRITE @QTROOT@/bin/qt.conf ${QTCONFCONTENT})
|
||||
|
||||
execute_process(
|
||||
COMMAND @QTROOT@/bin/macdeployqt ${args}
|
||||
WORKING_DIRECTORY ${CMAKE_INSTALL_PREFIX}
|
||||
WORKING_DIRECTORY @QTROOT@/bin
|
||||
)
|
||||
|
||||
#set(ENTITLEMENTS --entitlements @SOURCE_ROOT@/bundle/osx/Konvergo.entitlements)
|
||||
|
@ -1,8 +1,12 @@
|
||||
find_package(PkgConfig)
|
||||
option(DISABLE_BUNDLED_DEPS "Disable the bundled deps on certain platforms" OFF)
|
||||
|
||||
if(APPLE AND NOT DISABLE_BUNDLED_DEPS)
|
||||
set(DEFAULT_ROOT "${CMAKE_SOURCE_DIR}/dependencies/konvergo-depends-darwin-x86_64-release")
|
||||
include(FetchDependencies)
|
||||
|
||||
if(APPLE AND NOT DISABLE_BUNDLED_DEPS)
|
||||
download_deps("plexmediaplayer-dependencies" dir)
|
||||
message("dependencies are: ${dir}")
|
||||
set(DEFAULT_ROOT ${dir})
|
||||
endif(APPLE AND NOT DISABLE_BUNDLED_DEPS)
|
||||
|
||||
if(WIN32)
|
||||
|
89
CMakeModules/FetchDependencies.cmake
Normal file
89
CMakeModules/FetchDependencies.cmake
Normal file
@ -0,0 +1,89 @@
|
||||
set(DEP_DIR ${CMAKE_BINARY_DIR}/dependencies)
|
||||
|
||||
if(APPLE)
|
||||
set(OS "darwin")
|
||||
elseif(WIN32)
|
||||
set(OS "windows")
|
||||
elseif(UNIX)
|
||||
set(OS "linux")
|
||||
endif()
|
||||
|
||||
# note that hardcoding the ARCH here is not correct.
|
||||
set(ARCHSTR "${OS}-x86_64")
|
||||
|
||||
function(download_deps depname dirpath)
|
||||
file(MAKE_DIRECTORY ${DEP_DIR})
|
||||
|
||||
message(STATUS "Downloading ${depname}.hash.txt...")
|
||||
file(
|
||||
DOWNLOAD "https://nightlies.plex.tv/directdl/plex-dependencies/${depname}/latest/hash.txt" ${DEP_DIR}/${depname}-hash.txt
|
||||
STATUS HASH_STATUS
|
||||
)
|
||||
list(GET HASH_STATUS 0 SUCCESS)
|
||||
|
||||
if(SUCCESS EQUAL 0)
|
||||
file(STRINGS ${DEP_DIR}/${depname}-hash.txt DEP_HASH LIMIT_COUNT 1)
|
||||
|
||||
if(depname STREQUAL plexmediaplayer-qt)
|
||||
set(DEP_DIRNAME "konvergo-qt-${ARCHSTR}-release-${DEP_HASH}")
|
||||
elseif(depname STREQUAL plexmediaplayer-dependencies)
|
||||
set(DEP_DIRNAME "konvergo-depends-${ARCHSTR}-release-${DEP_HASH}")
|
||||
else()
|
||||
set(DEP_DIRNAME "${depname}-${ARCHSTR}-release-${DEP_HASH}")
|
||||
endif()
|
||||
|
||||
set(DEP_FILENAME ${DEP_DIRNAME}.tbz2)
|
||||
set(DEP_URL "https://nightlies.plex.tv/directdl/plex-dependencies/${depname}/latest/${DEP_FILENAME}")
|
||||
|
||||
set(${dirpath} ${DEP_DIR}/${DEP_DIRNAME} PARENT_SCOPE)
|
||||
|
||||
if(NOT EXISTS ${DEP_DIR}/${DEP_DIRNAME})
|
||||
message(STATUS "Downloading ${DEP_FILENAME}.sha.txt...")
|
||||
file(DOWNLOAD ${DEP_URL}.sha.txt ${DEP_DIR}/${DEP_FILENAME}.sha.txt STATUS SHA_STATUS)
|
||||
|
||||
list(GET SHA_STATUS 0 SHASUCCESS)
|
||||
|
||||
if(SHASUCCESS EQUAL 0)
|
||||
file(STRINGS ${DEP_DIR}/${DEP_FILENAME}.sha.txt CONTENT_HASH LIMIT_COUNT 1)
|
||||
|
||||
message(STATUS "Downloading ${DEP_FILENAME}...")
|
||||
|
||||
file(
|
||||
DOWNLOAD ${DEP_URL} ${DEP_DIR}/${DEP_FILENAME}
|
||||
EXPECTED_HASH SHA1=${CONTENT_HASH}
|
||||
SHOW_PROGRESS
|
||||
STATUS DEP_STATUS
|
||||
)
|
||||
|
||||
list(GET DEP_STATUS 0 DEP_SUCCESS)
|
||||
|
||||
if(NOT DEP_SUCCESS EQUAL 0)
|
||||
message(FATAL_ERROR "Failed to download ${DEP_URL}")
|
||||
endif()
|
||||
|
||||
if(NOT EXISTS ${DEP_DIR}/${DEP_DIRNAME})
|
||||
message(STATUS "Unpacking ${DEP_FILENAME}...")
|
||||
execute_process(
|
||||
COMMAND ${CMAKE_COMMAND} -E tar xjf ${DEP_DIR}/${DEP_FILENAME}
|
||||
WORKING_DIRECTORY ${DEP_DIR}
|
||||
)
|
||||
message(STATUS "Fixing install library names...")
|
||||
execute_process(
|
||||
COMMAND ${PROJECT_SOURCE_DIR}/scripts/fix-install-names.py ${DEP_DIR}/${DEP_DIRNAME}
|
||||
WORKING_DIRECTORY ${DEP_DIR}
|
||||
)
|
||||
message(STATUS "Done")
|
||||
endif()
|
||||
else(SHASUCCESS EQUAL 0)
|
||||
list(GET SHA_STATUS 1 SHAERROR)
|
||||
message(FATAL_ERROR "Failed to download ${DEP_FILENAME}.sha.txt error: ${SHAERROR}")
|
||||
endif(SHASUCCESS EQUAL 0)
|
||||
else(NOT EXISTS ${DEP_DIR}/${DEP_DIRNAME})
|
||||
message(STATUS "Directory ${DEP_DIR}/${DEP_DIRNAME} already exists, remove it to redownload")
|
||||
endif(NOT EXISTS ${DEP_DIR}/${DEP_DIRNAME})
|
||||
|
||||
else(SUCCESS EQUAL 0)
|
||||
list(GET HASH_STATUS 1 HASHERROR)
|
||||
message(FATAL_ERROR "Failed to download ${depname}.hash.txt error: ${HASHERROR}")
|
||||
endif(SUCCESS EQUAL 0)
|
||||
endfunction(download_deps depname)
|
@ -1,6 +1,15 @@
|
||||
set(QTROOT "/usr/local/Qt/Qt5.5" CACHE PATH "Root of the QT binaries.")
|
||||
|
||||
include(FetchDependencies)
|
||||
if(APPLE)
|
||||
download_deps("plexmediaplayer-qt" dir)
|
||||
set(QTROOT ${dir})
|
||||
else()
|
||||
set(QTROOT "/usr/local/Qt/Qt5.5" CACHE PATH "Root of the QT binaries.")
|
||||
endif()
|
||||
set(REQUIRED_QT_VERSION "5.5.0")
|
||||
|
||||
message(STATUS ${QTROOT})
|
||||
|
||||
set(QTCONFIGROOT ${QTROOT}/lib/cmake/Qt5)
|
||||
set(components Core Network WebChannel Qml Quick Xml WebEngine)
|
||||
|
||||
|
@ -1,278 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Sample CI usage: scripts\common\fetch-binaries.py -p windows -b release -t abc123 -n 33
|
||||
# Sample desktop usage: scripts\common\fetch-binaries.py -i ..\plex-dependency-builder\output\Packages\pms-depends-windows-i386-debug-dev.bz2
|
||||
|
||||
import hashlib
|
||||
import optparse
|
||||
import ConfigParser
|
||||
import os, re
|
||||
import platform
|
||||
import subprocess
|
||||
import sys
|
||||
import shutil
|
||||
import urllib2
|
||||
import base64
|
||||
import glob
|
||||
|
||||
# Edit these to set a new default dependencies build
|
||||
default_tag = "auto"
|
||||
default_release_build_number = "107"
|
||||
default_release_dir = "plexmediaplayer-dependencies"
|
||||
default_branch = "master"
|
||||
|
||||
def sha1_for_file(path):
|
||||
hash=hashlib.sha1()
|
||||
fp=file(path, "rb")
|
||||
while True:
|
||||
data=fp.read(4096)
|
||||
if not data:
|
||||
break
|
||||
hash.update(data)
|
||||
return hash.hexdigest()
|
||||
|
||||
def exec_cmd(args, env={}, supress_output=False):
|
||||
""" main exec_cmd function """
|
||||
|
||||
# forward SSH_AUTH_SOCK, so that ssh-agent works
|
||||
if os.name != "nt" and "SSH_AUTH_SOCK" in os.environ:
|
||||
env = os.environ
|
||||
extra_env={"SSH_AUTH_SOCK":os.environ["SSH_AUTH_SOCK"]}
|
||||
env.update(extra_env)
|
||||
else:
|
||||
env = os.environ
|
||||
|
||||
cmd = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, env = env)
|
||||
output = ''
|
||||
while True:
|
||||
out = cmd.stdout.read(1)
|
||||
if out == '' and cmd.poll() != None:
|
||||
break
|
||||
if out != '':
|
||||
if not supress_output:
|
||||
sys.stdout.write(out)
|
||||
output += out
|
||||
if cmd.wait() != 0:
|
||||
raise Exception("Command failed: \"%s\"" % " ".join(args), output)
|
||||
return output
|
||||
|
||||
|
||||
platform_map={"linux-synology-i386":"synology-i686",
|
||||
"linux-readynas-arm":"ubuntu-arm",
|
||||
"linux-debian-4-i386":"debian-i686",
|
||||
"linux-control4-arm":"control4-arm",
|
||||
"linux-apm-ppc":"apm-ppc",
|
||||
"linux-armada-arm7":"armada-arm7",
|
||||
"linux-synology-arm":"synology-arm"}
|
||||
|
||||
def platform_str():
|
||||
if "BUILD_TAG" in os.environ:
|
||||
for (k, v) in platform_map.iteritems():
|
||||
if k in os.environ["BUILD_TAG"]:
|
||||
return "linux-"+v
|
||||
|
||||
return "linux-%s-%s"%(platform.linux_distribution()[0].strip().lower(), platform.machine())
|
||||
|
||||
def merge_directories(src, dest, move = False):
|
||||
for src_dir, dirs, files in os.walk(src):
|
||||
dst_dir = src_dir.replace(src, dest)
|
||||
if not os.path.exists(dst_dir):
|
||||
os.mkdir(dst_dir)
|
||||
for file_ in files:
|
||||
src_file = os.path.join(src_dir, file_)
|
||||
dst_file = os.path.join(dst_dir, file_)
|
||||
if os.path.exists(dst_file):
|
||||
os.remove(dst_file)
|
||||
if move:
|
||||
shutil.move(src_file, dst_dir)
|
||||
else:
|
||||
shutil.copy(src_file, dst_dir)
|
||||
if move and os.path.exists(src):
|
||||
shutil.rmtree(src)
|
||||
|
||||
def unpack_and_install(download, inputfile, installed_filepath):
|
||||
# Make paths absolute before changing directories
|
||||
inputfile = os.path.abspath(inputfile)
|
||||
if not os.path.exists(inputfile):
|
||||
print "Input file %s does not exist" % inputfile
|
||||
sys.exit(1)
|
||||
shafile = "%s.sha.txt" % inputfile
|
||||
|
||||
installed_filepath = os.path.abspath(installed_filepath)
|
||||
|
||||
# Go to directory.
|
||||
old_cwd = os.getcwd()
|
||||
os.chdir(options.output)
|
||||
|
||||
# Check the SHA
|
||||
if options.nochecksha:
|
||||
print "-- Skipping SHA verification"
|
||||
elif os.path.exists(shafile):
|
||||
f = open(shafile, "r")
|
||||
sha = f.readline().strip()
|
||||
computed = sha1_for_file(inputfile)
|
||||
if not computed == sha:
|
||||
print "-- SHA didn't match: %s != %s" % (sha, computed)
|
||||
sys.exit(1)
|
||||
else:
|
||||
print "-- SHA %s matches" % sha
|
||||
|
||||
f.close()
|
||||
else:
|
||||
print "-- ERROR - No SHA file is available to verify the file's integrity"
|
||||
sys.exit(1)
|
||||
|
||||
# Untar the package file
|
||||
inputfile_tarfriendly = inputfile
|
||||
if os.name == "nt":
|
||||
pattern = re.compile(r'([a-z]):\\', re.IGNORECASE)
|
||||
inputfile_tarfriendly = pattern.sub('/\\1/', inputfile).replace('\\','/')
|
||||
|
||||
# The final destination directory is the filename without a version number
|
||||
# The version number is the last element in the filename (by convention)
|
||||
packagename = os.path.splitext(os.path.basename(inputfile))[0]
|
||||
packagename_elements = packagename.split("-")
|
||||
del packagename_elements[-1]
|
||||
packagename_noversion = "-".join(packagename_elements)
|
||||
|
||||
if os.path.exists(packagename_noversion):
|
||||
shutil.rmtree(packagename_noversion, ignore_errors=True)
|
||||
|
||||
os.makedirs(packagename_noversion)
|
||||
|
||||
print "-- Unpacking %s... to %s" % (os.path.basename(inputfile), packagename_noversion)
|
||||
if os.name == "nt":
|
||||
# Touch files from the package, which often arrive from the future when freshly built on our Windows build machine
|
||||
exec_cmd(["tar", "xjf", inputfile_tarfriendly, "-C", packagename_noversion, "--touch", "--strip-components", "1", "--no-same-owner"])
|
||||
else:
|
||||
exec_cmd(["tar", "xjf", inputfile_tarfriendly, "-C", packagename_noversion, "--strip-components", "1", "--no-same-owner"])
|
||||
|
||||
if download and installed_filepath:
|
||||
# Create the installed stamp file to note our success
|
||||
open(installed_filepath, "wb")
|
||||
|
||||
# Restore directory.
|
||||
os.chdir(old_cwd)
|
||||
|
||||
return packagename
|
||||
|
||||
if __name__=='__main__':
|
||||
parser=optparse.OptionParser()
|
||||
|
||||
parser.add_option("-p", "--platform", action="store", type="string",
|
||||
dest="platform", help="Platform identifier (e.g. windows-i386)", default=None)
|
||||
|
||||
parser.add_option("-b", "--buildconfig", action="store", type="string",
|
||||
dest="buildconfig", help="Build configuration (release or debug). Default is release", default="release")
|
||||
|
||||
parser.add_option("-t", "--tag", action="store", type="string",
|
||||
dest="tag", help="Build tag. Default is %s" % default_tag, default=default_tag)
|
||||
|
||||
parser.add_option("-n", "--buildnumber", action="store", type="string",
|
||||
dest="buildnumber", help="Build number. Default is %s for release builds" % (default_release_build_number), default=None)
|
||||
|
||||
parser.add_option("-d", "--dir", action="store", type="string",
|
||||
dest="dir", help="CI build dir. Default is %s for release builds" % (default_release_dir), default=None)
|
||||
|
||||
parser.add_option("-i", "--inputfile", action="store", type="string",
|
||||
dest="inputfile", help="Dependencies package filename, can be supplied instead of platform, buildconfig, tag and buildnumber", default=None)
|
||||
|
||||
parser.add_option("-o", "--output", action="store", type="string",
|
||||
dest="output", help="Output directory. Default is Dependencies",
|
||||
default="Dependencies")
|
||||
|
||||
parser.add_option("-x", "--nochecksha", action="store_true",
|
||||
dest="nochecksha", help="Don't check the SHA. Default is false",
|
||||
default=False)
|
||||
|
||||
parser.add_option("-r", "--branch", action="store", type="string",
|
||||
dest="branch", help="Git branch", default=None)
|
||||
|
||||
(options, args)=parser.parse_args(sys.argv)
|
||||
|
||||
if not os.path.exists(options.output):
|
||||
os.makedirs(options.output)
|
||||
|
||||
# Fail early if platform is not known
|
||||
download = not options.inputfile
|
||||
if download and not options.platform:
|
||||
print "ERROR - A platform must be specified"
|
||||
sys.exit(1)
|
||||
|
||||
installed_filepath = None
|
||||
if download:
|
||||
|
||||
if not options.buildnumber:
|
||||
if options.buildconfig == "release":
|
||||
options.buildnumber = default_release_build_number
|
||||
else:
|
||||
options.buildnumber = default_debug_build_number
|
||||
|
||||
if not options.dir:
|
||||
if options.buildconfig == "release":
|
||||
options.dir = default_release_dir
|
||||
else:
|
||||
options.dir = default_debug_dir
|
||||
|
||||
installed_filepath = os.path.join(options.output, "konvergo-depends-%s-%s-%s.installed" % (options.platform, options.buildconfig, options.buildnumber))
|
||||
if os.path.exists(installed_filepath) and options.buildnumber != "latest":
|
||||
print "The required deps bundle was already downloaded and installed."
|
||||
print "You can delete %s to force a reinstall." % installed_filepath
|
||||
sys.exit(0)
|
||||
|
||||
# Delete previous installed stamps
|
||||
cont = ["-c"]
|
||||
for path in glob.iglob(os.path.join(options.output, "konvergo-depends-%s-%s-*.installed") % (options.platform, options.buildconfig)):
|
||||
match = re.search("-(\d+)\.installed", path, re.DOTALL)
|
||||
if match:
|
||||
if not match.group(1) == options.buildnumber:
|
||||
cont = []
|
||||
os.remove(path)
|
||||
|
||||
if options.tag == "auto":
|
||||
req = urllib2.Request("https://nightlies.plex.tv/directdl/plex-dependencies/%s/%s/hash.txt" % (options.dir, options.buildnumber))
|
||||
try:
|
||||
match = urllib2.urlopen(req).read().rstrip()
|
||||
except urllib2.URLError, err:
|
||||
print err
|
||||
print "ERROR - Download failed"
|
||||
sys.exit(1)
|
||||
|
||||
options.tag = match
|
||||
|
||||
base_filename = "konvergo-depends-%s-%s-%s" % (options.platform, options.buildconfig, options.tag)
|
||||
filename = "%s.tbz2" % base_filename
|
||||
|
||||
installed_filepath = os.path.join(options.output, "konvergo-depends-%s-%s-%s.installed" % (options.platform, options.buildconfig, options.buildnumber))
|
||||
if os.path.exists(installed_filepath):
|
||||
print "%s was already downloaded and installed." % filename
|
||||
print "You can delete %s to force a reinstall." % installed_filepath
|
||||
sys.exit(0)
|
||||
|
||||
url = "https://nightlies.plex.tv/directdl/plex-dependencies/%s/%s/%s" % (options.dir, options.buildnumber, filename)
|
||||
inputfile = os.path.join(options.output, filename)
|
||||
|
||||
print "-- Downloading %s ..." % url
|
||||
exec_cmd(["wget", "--no-check-certificate"] + cont + ["-O", inputfile, url])
|
||||
|
||||
shaurl = "%s.sha.txt" % url
|
||||
shafile = "%s.sha.txt" % inputfile
|
||||
|
||||
print "-- Downloading %s ..." % shaurl
|
||||
exec_cmd(["wget", "--no-check-certificate"] + ["-O", shafile, shaurl])
|
||||
|
||||
else:
|
||||
inputfile = options.inputfile
|
||||
|
||||
# Unpack and install
|
||||
packagename = unpack_and_install(download, inputfile, installed_filepath)
|
||||
|
||||
# On OS X, we need to postprocess the dependencies.
|
||||
if platform.system() == 'Darwin':
|
||||
root = os.path.realpath(os.path.join(os.getcwd()))
|
||||
script = os.path.join(root, "scripts", "fix-install-names.py")
|
||||
for p in ("lib", "bin", "update_installer"):
|
||||
path = os.path.join(root, "Dependencies", "konvergo-depends-" + options.platform + "-" + options.buildconfig, p)
|
||||
exec_cmd([script, path])
|
||||
|
||||
# Done!
|
||||
print "-- Done with %s" % packagename
|
@ -9,6 +9,9 @@ import subprocess
|
||||
import sys
|
||||
import shutil
|
||||
|
||||
exts = (".dylib", ".so")
|
||||
exes = ("fc-cache", "macdeployqt", "qmake", "moc", "rcc", "qmlimportscanner")
|
||||
|
||||
def exec_cmd(args, env={}, supress_output=False):
|
||||
cmd = subprocess.Popen(args, stdout = subprocess.PIPE, stderr = subprocess.STDOUT, env = env)
|
||||
output = ''
|
||||
@ -28,8 +31,8 @@ def fix_install_name(path):
|
||||
for root, dirs, files in os.walk(path):
|
||||
for f in files:
|
||||
fpath = os.path.join(root, f)
|
||||
if (f.endswith(".dylib") or f in ['fc-cache'] or f.endswith(".so")) and not os.path.islink(fpath) and os.path.exists(fpath):
|
||||
|
||||
if (f.endswith(exts) or os.path.basename(f) in exes or (".framework/Versions/" in root and os.access(fpath, os.X_OK))) and not os.path.islink(fpath) and os.path.exists(fpath):
|
||||
# Fix permissions
|
||||
if not os.access(fpath, os.W_OK) or not os.access(fpath, os.R_OK) or not os.access(fpath, os.X_OK):
|
||||
os.chmod(fpath, 0o644)
|
||||
@ -51,6 +54,8 @@ def fix_install_name(path):
|
||||
# look for it further up, like in the root path:
|
||||
if os.path.exists(os.path.join(path, "lib", current_basename)):
|
||||
correct_lib = os.path.join(path, "lib", current_basename)
|
||||
elif os.path.exists(os.path.join(path, "lib", current_lib)):
|
||||
correct_lib = os.path.join(path, "lib", current_lib)
|
||||
else:
|
||||
print "Can't link %s" % current_lib
|
||||
continue
|
||||
|
Loading…
Reference in New Issue
Block a user