123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838 |
- #!/usr/bin/env python
- # @file viewer_manifest.py
- # @author Ryan Williams - Lot's of modifications by Henri Beauchamp.
- # @brief Description of all installer viewer files, and methods for packaging
- # them into installers for all supported platforms.
- #
- # $LicenseInfo:firstyear=2006&license=viewergpl$
- #
- # Copyright (c) 2006-2009, Linden Research, Inc.
- # Copyright (c) 2009-2023, Henri Beauchamp.
- #
- # Second Life Viewer Source Code
- # The source code in this file ("Source Code") is provided by Linden Lab
- # to you under the terms of the GNU General Public License, version 2.0
- # ("GPL"), unless you have obtained a separate licensing agreement
- # ("Other License"), formally executed by you and Linden Lab. Terms of
- # the GPL can be found in doc/GPL-license.txt in this distribution, or
- # online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- #
- # There are special exceptions to the terms and conditions of the GPL as
- # it is applied to this Source Code. View the full text of the exception
- # in the file doc/FLOSS-exception.txt in this software distribution, or
- # online at
- # http://secondlifegrid.net/programs/open_source/licensing/flossexception
- #
- # By copying, modifying or distributing this software, you acknowledge
- # that you have read and understood your obligations described above,
- # and agree to abide by those obligations.
- #
- # ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- # WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- # COMPLETENESS OR PERFORMANCE.
- # $/LicenseInfo$
- from __future__ import print_function
- import sys
- import os.path
- import errno
- import re
- import tarfile
- # Look for scripts/lib/python in all possible parent directories (which
- # will result in rootdir pointing at the root of the viewer sources, since
- # scripts/ is a subdirectory of that root directory.
- # Add the full path for scripts/lib/python to sys.path, so that our custom
- # modules are found.
- rootdir = os.path.realpath(__file__)
- while rootdir != os.path.sep:
- rootdir = os.path.dirname(rootdir)
- dir = os.path.join(rootdir, 'scripts', 'lib', 'python')
- if os.path.isdir(dir):
- if dir not in sys.path:
- sys.path.insert(0, dir)
- break
- else:
- print("This script is not inside a valid source tree.", file=sys.stderr)
- sys.exit(1)
- if sys.version_info[0] == 3:
- from indra.llmanifest3 import LLManifest, main, proper_windows_path, path_ancestors
- else:
- from indra.llmanifest import LLManifest, main, proper_windows_path, path_ancestors
- # Where the pre-built libraries and binaries reside:
- binreleasedir = os.path.join(rootdir, 'bin', 'release')
- libreleasedir = os.path.join(rootdir, 'lib', 'release')
- libdebugdir = os.path.join(rootdir, 'lib', 'debug')
- class ViewerManifest(LLManifest):
- def construct(self):
- super(ViewerManifest, self).construct()
- self.exclude("*.svn*")
- self.path(src=os.path.join(rootdir, 'doc', 'CoolVLViewerReadme.txt'), dst="CoolVLViewerReadme.txt")
- self.path(src=os.path.join(rootdir, 'doc', 'RestrainedLoveReadme.txt'), dst="RestrainedLoveReadme.txt")
- if self.prefix(src="app_settings"):
- self.path("*.crt")
- self.path("*.ini")
- self.path("*.xml")
- self.path("*.msg")
- self.path("gpu_table.txt")
- # Include the entire shaders directory recursively
- self.path("shaders")
- # ... and the entire windlight directory
- self.path("windlight")
- # ... and the entire meshes directory
- self.path("meshes")
- # ... and the entire dictionaries directory
- self.path("dictionaries")
- self.end_prefix("app_settings")
- if self.prefix(src="character"):
- option = self.custom_option()
- self.path("avatar_lad.xml")
- self.path("attentions.xml")
- self.path("avatar_skeleton.xml")
- if option.find('puppetry') != -1:
- self.path("avatar_constraint.llsd")
- self.path("*.llm")
- self.path("*.tga")
- # Include the entire anims directory
- self.path("anims")
- self.end_prefix("character")
- # Include our fonts
- if self.prefix(src="fonts"):
- self.path("MtB*.ttf")
- self.path("profont*")
- self.path("Roboto*")
- self.path("Twemoji*")
- self.path("Readme.txt")
- self.end_prefix("fonts")
- # Skins
- if self.prefix(src="skins"):
- self.path("paths.xml")
- # include pre-decoded sounds if any
- if self.prefix(src="default/sounds"):
- self.path("*.dsf")
- self.end_prefix("default/sounds")
- # include the entire textures directory recursively
- if self.prefix(src="*/textures"):
- self.path("*.tga")
- self.path("*.j2c")
- self.path("*.jpg")
- self.path("*.png")
- self.path("textures.xml")
- self.end_prefix("*/textures")
- self.path("*/xui/*/*.xml")
- self.path("*/*.xml")
- # Local HTML files (e.g. loading screen)
- if self.prefix(src="*/html"):
- self.path("*/*/*.html")
- self.end_prefix("*/html")
- self.end_prefix("skins")
- def buildtype(self):
- return self.args['buildtype']
- def viewer_branding_id(self):
- return self.args['branding_id']
- def installer_prefix(self):
- return "CoolVLViewer_"
- def custom_option(self):
- return self.args['custom']
- class WindowsManifest(ViewerManifest):
- def construct(self):
- super(WindowsManifest, self).construct()
- config = self.args['configuration']
- build_dir = self.args['build']
- plugins = os.path.join(build_dir, "..", "media_plugins")
- if self.prefix(src="app_settings"):
- self.path("featuretable_windows.txt", dst="featuretable.txt")
- self.end_prefix("app_settings")
- # Include fallback fonts needed by Windows for special UTF-8 characters
- if self.prefix(src="fonts"):
- self.path("DejaVu*")
- self.end_prefix("fonts")
- if self.prefix(src=config, dst=""):
- self.path("CoolVLViewer.exe")
- # The config file name needs to match the exe's name.
- #self.path("CoolVLViewer.exe.config")
- self.end_prefix()
- # Media plugins
- has_cef = 0
- has_webrtc_plugin = 0
- if self.prefix(src=os.path.join(plugins, "cef", config), dst="llplugin"):
- if (self.path("media_plugin_cef.dll")):
- has_cef = 1
- self.end_prefix()
- if self.prefix(src=os.path.join(plugins, "gstreamer", config), dst="llplugin"):
- self.path("media_plugin_gstreamer.dll")
- self.end_prefix()
- if self.prefix(src=os.path.join(plugins, "webrtc", config), dst="llplugin"):
- if (self.path("voice_plugin_webrtc.dll")):
- has_webrtc_plugin = 1
- self.end_prefix()
- # Media plugins launcher
- if self.prefix(src=os.path.join(plugins, "slplugin", config), dst=""):
- self.path("SLPlugin.exe")
- self.end_prefix()
- if self.prefix(src=libreleasedir, dst=""):
- # OpenSSL libraries (either v1.0 or v1.1, which are named differently)
- self.path("libeay32.dll")
- self.path("ssleay32.dll")
- self.path("libssl-1_1-x64.dll")
- self.path("libcrypto-1_1-x64.dll")
- # HTTP/2
- self.path("nghttp2.dll")
- # OpenAL
- self.path("alut.dll")
- self.path("OpenAL32.dll")
- # Mesh 3rd party lib
- self.path("glod.dll")
- # Lua
- self.path("lua54.dll")
- # For spellchecking
- self.path("libhunspell.dll")
- # WebRTC Voice
- if has_webrtc_plugin != 1:
- self.path("llwebrtc.dll")
- self.end_prefix()
- # For CEF plugin runtimes
- if has_cef == 1:
- if self.prefix(src=binreleasedir, dst="llplugin"):
- self.path("dullahan_host.exe")
- self.path("chrome_elf.dll")
- self.path("libcef.dll")
- self.path("libEGL.dll")
- self.path("libGLESv2.dll")
- self.path("d3dcompiler*.dll")
- self.path("*snapshot.bin")
- self.path("*_blob.bin")
- self.end_prefix()
- if self.prefix(src=os.path.join(binreleasedir, 'swiftshader'), dst=os.path.join('llplugin', 'swiftshader')):
- self.path("libEGL.dll")
- self.path("libGLESv2.dll")
- self.end_prefix()
- # CEF plugin resources
- cefresources = os.path.join(rootdir, 'Resources')
- if self.prefix(src=cefresources, dst="llplugin"):
- # CEF 89 and older: copy all but devtools_resources.pak
- self.path("cef*.pak")
- # CEF 90 and newer:
- self.path("resources.pak")
- self.path("chrome_*.pak")
- # Common to all versions
- self.path("icudtl.dat")
- self.end_prefix()
- # CEF plugin locales
- if self.prefix(src=os.path.join(cefresources, 'locales'), dst=os.path.join('llplugin', 'locales')):
- self.path("*.pak")
- self.end_prefix()
- # For WebRTC plugin runtime
- if has_webrtc_plugin == 1:
- if self.prefix(src=libreleasedir, dst="llplugin"):
- self.path("llwebrtc.dll")
- self.end_prefix()
- # SLVoice client
- if self.prefix(src=binreleasedir, dst=""):
- self.path("SLVoice.exe")
- self.end_prefix()
- # Vivox libraries
- if self.prefix(src=libreleasedir, dst=""):
- self.path("ortp_x64.dll")
- self.path("vivoxsdk_x64.dll")
- self.end_prefix()
- # Tracy, if in use
- has_tracy = 0
- if self.prefix(src=binreleasedir, dst=""):
- if (self.path("Tracy.exe")):
- # Change for this if using Tracy v0.9.1 or newer. HB
- #has_tracy = 1
- has_tracy = 0
- self.end_prefix()
- self.path(src=os.path.join(rootdir, 'doc', 'licenses-windows.txt'), dst='licenses.txt')
- self.path(src=os.path.join(rootdir, 'doc', 'VivoxAUP.txt'), dst='VivoxAUP.txt')
- # For using FMOD for sound...
- if (not self.path("fmod.dll")):
- if (not self.path("fmod64.dll")):
- print("FMOD library not found: the viewer will lack FMOD support.")
- # mimalloc overrides, if available
- has_mimalloc = 0
- if self.prefix(src=libreleasedir, dst=""):
- if (self.path("mimalloc-override.dll")):
- has_mimalloc = 1
- self.path("mimalloc-redirect.dll")
- else:
- print("Skipping mimalloc - not found (normal if built without it).")
- self.end_prefix()
- if has_mimalloc == 1 and self.prefix(src=libreleasedir, dst="llplugin"):
- self.path("mimalloc-override.dll")
- self.path("mimalloc-redirect.dll")
- self.end_prefix()
- runtime_libs = os.path.join(rootdir, 'lib', 'vc143_x64')
- if self.prefix(src=runtime_libs, dst=""):
- # For use in crash reporting (generates minidumps).
- # Actually, including dbghelp.dll is a bad idea, since it should be
- # present in any modern Windows system, and including a newer
- # version causes issues with missing DLL dependencies (such as
- # "api-ms-win-core-com-l1-1-0.dll", but not only). HB
- #self.path("dbghelp.dll")
- #self.path("api-ms-win-core-com-l1-1-0.dll")
- # VC141 runtimes
- #self.path("concrt140.dll")
- #self.path("msvcp140*.dll")
- #self.path("vccorlib140.dll")
- self.path("msvcp140.dll")
- self.path("vcruntime140*.dll")
- option = self.custom_option()
- if option.find('openmp') != -1:
- self.path("vcomp140.dll")
- if (has_tracy == 1):
- # Needed, starting with Tracy v0.9.1. HB
- self.path("msvcp140_atomic_wait.dll")
- self.end_prefix()
- # Needed by the CEF plugin wrappers
- if self.prefix(src=runtime_libs, dst="llplugin"):
- # See above about dbghelp.dll and api-ms-win-core-com-l1-1-0.dll
- #self.path("api-ms-win-core-com-l1-1-0.dll")
- #self.path("concrt140.dll")
- #self.path("msvcp140*.dll")
- #self.path("vccorlib140.dll")
- self.path("msvcp140.dll")
- self.path("vcruntime140*.dll")
- self.end_prefix()
- def package_finish(self):
- self.package_file = 'touched.bat'
- # removed: we use InstallJammer to make packages
- return
- class DarwinManifest(ViewerManifest):
- def construct(self):
- # copy over the build result (this is a no-op if run within the xcode script)
- self.path(self.args['configuration'] + "/" + self.app_name() + ".app", dst="")
- # jemalloc presence flag
- has_jemalloc = 0
- if self.prefix(src="", dst="Contents"): # everything goes in Contents
- self.path(self.info_plist_name(), dst="Info.plist")
- # Copy jemalloc, if in use
- if (self.path(os.path.join(libreleasedir, 'libjemalloc.2.dylib'), dst='Resources/libjemalloc.2.dylib')):
- has_jemalloc = 1
- else:
- print("Skipping libjemalloc.dylib - not found (normal if built without it or statically linked).")
- # Copy additional libs in <bundle>/Contents/MacOS/ and <bundle>/Contents/Resources/
- self.path(os.path.join(libreleasedir, 'libhunspell-1.3.0.dylib'), dst='Resources/libhunspell-1.3.0.dylib')
- self.path(os.path.join(libreleasedir, 'libndofdev.dylib'), dst='Resources/libndofdev.dylib')
- # Copy macOS feature table into Resources/app_settings
- self.path(os.path.join(rootdir, 'indra', 'newview', 'app_settings', 'featuretable_macos.txt'), dst='Resources/app_settings/featuretable.txt')
- # Most everything goes in the Resources directory
- if self.prefix(src="", dst="Resources"):
- super(DarwinManifest, self).construct()
- if self.prefix("cursors_mac"):
- self.path("*.tif")
- self.end_prefix("cursors_mac")
- self.path(src=os.path.join(rootdir, 'doc', 'licenses-mac.txt'), dst='licenses.txt')
- self.path(src=os.path.join(rootdir, 'doc', 'VivoxAUP.txt'), dst='VivoxAUP.txt')
- self.path("CoolVLViewer.nib")
- self.path("cool_vl_viewer.icns")
- # Translations
- self.path("English.lproj")
- # SLVoice and Vivox libs
- if self.prefix(src=binreleasedir, dst=""):
- self.path("SLVoice")
- self.end_prefix()
- if self.prefix(src=libreleasedir, dst=""):
- self.path("libortp.dylib")
- self.path("libvivoxsdk.dylib")
- self.end_prefix()
- # WebRTC library.
- if self.prefix(src=libreleasedir, dst=""):
- self.path("libllwebrtc.dylib")
- self.end_prefix("")
- # Tracy, if in use
- if self.prefix(src=binreleasedir, dst=""):
- self.path("tracy")
- self.end_prefix()
- for libfile in ("libapr-1.0.dylib",
- "libexpat.1*.dylib",
- "libglod.dylib",
- "libnghttp2.*dylib",
- "libalut.*dylib",
- "libopenal.*dylib",
- "libfmod*.dylib"):
- self.path(os.path.join(libreleasedir, libfile), libfile)
- # Plugin launcher
- self.path("../media_plugins/slplugin/" + self.args['configuration'] + "/SLPlugin.app", "SLPlugin.app")
- self.end_prefix("Resources")
- self.end_prefix("Contents")
- # Media plugins presence flags
- has_gstreamer = 0
- has_cef = 0
- has_webrtc = 0
- if self.prefix(src="", dst="Contents"): # everything goes in Contents
- # most everything goes in the Resources directory
- if self.prefix(src="", dst="Resources"):
- # Media plugins
- if self.prefix(src="", dst="llplugin"):
- if self.path("../media_plugins/gstreamer/" + self.args['configuration'] + "/media_plugin_gstreamer.dylib", "media_plugin_gstreamer.dylib"):
- has_gstreamer = 1
- if self.path("../media_plugins/cef/" + self.args['configuration'] + "/media_plugin_cef.dylib", "media_plugin_cef.dylib"):
- has_cef = 1
- if self.path("../media_plugins/webrtc/" + self.args['configuration'] + "/voice_plugin_webrtc.dylib", "voice_plugin_webrtc.dylib"):
- has_webrtc = 1
- self.end_prefix("llplugin")
- # Dullahan helper app go inside SLPlugin.app
- if has_cef == 1 and self.prefix(src="", dst="SLPlugin.app/Contents/Frameworks"):
- self.path2basename(libreleasedir, 'DullahanHelper.app')
- pluginframeworkpath = self.dst_path_of('Chromium Embedded Framework.framework');
- if self.prefix(dst=os.path.join(
- 'DullahanHelper.app', 'Contents', "Frameworks")):
- self.cmakedirs(self.get_dst_prefix());
- dullahanframeworkpath = self.dst_path_of('Chromium Embedded Framework.framework');
- self.end_prefix()
- self.end_prefix()
- # Dullahan helper (GPU) app go inside SLPlugin.app
- if has_cef == 1 and self.prefix(src="", dst="SLPlugin.app/Contents/Frameworks"):
- self.path2basename(libreleasedir, 'DullahanHelper (GPU).app')
- pluginframeworkpath = self.dst_path_of('Chromium Embedded Framework.framework');
- if self.prefix(dst=os.path.join(
- 'DullahanHelper (GPU).app', 'Contents', "Frameworks")):
- self.cmakedirs(self.get_dst_prefix());
- dullahanframeworkpath = self.dst_path_of('Chromium Embedded Framework.framework');
- self.end_prefix()
- self.end_prefix()
- # Dullahan helper (Plugin) app go inside SLPlugin.app
- if has_cef == 1 and self.prefix(src="", dst="SLPlugin.app/Contents/Frameworks"):
- self.path2basename(libreleasedir, 'DullahanHelper (Plugin).app')
- pluginframeworkpath = self.dst_path_of('Chromium Embedded Framework.framework');
- if self.prefix(dst=os.path.join(
- 'DullahanHelper (Plugin).app', 'Contents', "Frameworks")):
- self.cmakedirs(self.get_dst_prefix());
- dullahanframeworkpath = self.dst_path_of('Chromium Embedded Framework.framework');
- self.end_prefix()
- self.end_prefix()
- # Dullahan helper (Renderer) app go inside SLPlugin.app
- if has_cef == 1 and self.prefix(src="", dst="SLPlugin.app/Contents/Frameworks"):
- self.path2basename(libreleasedir, 'DullahanHelper (Renderer).app')
- pluginframeworkpath = self.dst_path_of('Chromium Embedded Framework.framework');
- if self.prefix(dst=os.path.join(
- 'DullahanHelper (Renderer).app', 'Contents', "Frameworks")):
- self.cmakedirs(self.get_dst_prefix());
- dullahanframeworkpath = self.dst_path_of('Chromium Embedded Framework.framework');
- self.end_prefix()
- self.end_prefix()
- self.end_prefix("Resources")
- # CEF framework goes inside Cool VL Viewer.app/Contents/Frameworks
- if has_cef == 1:
- if self.prefix(src="", dst="Frameworks"):
- frameworkfile="Chromium Embedded Framework.framework"
- self.path2basename(libreleasedir, frameworkfile)
- self.end_prefix("Frameworks")
- # This code constructs a relative path from the
- # target framework folder back to the location of the symlink.
- # It needs to be relative so that the symlink still works when
- # (as is normal) the user moves the app bunlde out of the DMG
- # and into the /Applications folder. Note we also call 'raise'
- # to terminate the process if we get an error since without
- # this symlink, Second Life web media can't possibly work.
- # Real Framework folder:
- # Cool VL Viewer.app/Contents/Frameworks/Chromium Embedded Framework.framework/
- # Location of symlink and why it is relative
- # Cool VL Viewer.app/Contents/Resources/SLPlugin.app/Contents/Frameworks/Chromium Embedded Framework.framework/
- frameworkpath = os.path.join(os.pardir, os.pardir, os.pardir, os.pardir, "Frameworks", "Chromium Embedded Framework.framework")
- try:
- symlinkf(frameworkpath, pluginframeworkpath)
- except OSError as err:
- print("Cannot symlink %s -> %s: %s" % (frameworkpath, pluginframeworkpath, err))
- raise
- try:
- symlinkf(frameworkpath, dullahanframeworkpath)
- except OSError as err:
- print("Cannot symlink %s -> %s: %s" % (frameworkpath, dullahanframeworkpath, err))
- raise
- self.end_prefix("Contents")
- # Fix library paths in plugins:
- self.run_command('install_name_tool -change @executable_path/../Resources/libexpat.1.dylib @executable_path/../../../libexpat.1.dylib "%(slplugin)s"' %
- { 'slplugin': self.dst_path_of('Contents/Resources/SLPlugin.app/Contents/MacOS/SLPlugin')})
- self.run_command('install_name_tool -change @executable_path/../Resources/libnghttp2.14.14.0.dylib @executable_path/../../../libnghttp2.14.14.0.dylib "%(slplugin)s"' %
- { 'slplugin': self.dst_path_of('Contents/Resources/SLPlugin.app/Contents/MacOS/SLPlugin')})
- if has_gstreamer == 1:
- self.run_command('install_name_tool -change @executable_path/../Resources/libexpat.1.dylib @executable_path/../../../libexpat.1.dylib "%(plugin)s"' %
- { 'plugin': self.dst_path_of('Contents/Resources/llplugin/media_plugin_gstreamer.dylib')})
- if has_cef == 1:
- # fix up media_plugin.dylib so it knows where to look for CEF files it needs
- self.run_command('install_name_tool -change "@rpath/Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "@executable_path/../Frameworks/Chromium Embedded Framework.framework/Chromium Embedded Framework" "../Cool VL Viewer.app/Contents/Resources/llplugin/media_plugin_cef.dylib"' %
- { 'config' : self.args['configuration'] })
- self.run_command('install_name_tool -change @executable_path/../Resources/libexpat.1.dylib @executable_path/../../../libexpat.1.dylib "%(plugin)s"' %
- { 'plugin': self.dst_path_of('Contents/Resources/llplugin/media_plugin_cef.dylib')})
- if has_webrtc == 1:
- self.run_command('install_name_tool -change @executable_path/../Resources/libllwebrtc.dylib @executable_path/../../../libllwebrtc.1.dylib "%(plugin)s"' %
- { 'plugin': self.dst_path_of('Contents/Resources/llplugin/voice_plugin_webrtc.dylib')})
- # Patch libjemalloc.dylib path in image
- if has_jemalloc == 1:
- self.run_command('install_name_tool -change libjemalloc.2.dylib @executable_path/../Resources/libjemalloc.2.dylib "%(viewer_binary)s"' %
- { 'viewer_binary': self.dst_path_of('Contents/MacOS/'+self.app_name())})
- self.run_command('install_name_tool -change libjemalloc.2.dylib @executable_path/../../../libjemalloc.2.dylib "%(slplugin)s"' %
- { 'slplugin': self.dst_path_of('Contents/Resources/SLPlugin.app/Contents/MacOS/SLPlugin')})
- if has_gstreamer == 1:
- self.run_command('install_name_tool -change libjemalloc.2.dylib @executable_path/../../../libjemalloc.2.dylib "%(plugin)s"' %
- { 'plugin': self.dst_path_of('Contents/Resources/llplugin/media_plugin_gstreamer.dylib')})
- if has_cef == 1:
- self.run_command('install_name_tool -change libjemalloc.2.dylib @executable_path/../../../libjemalloc.2.dylib "%(plugin)s"' %
- { 'plugin': self.dst_path_of('Contents/Resources/llplugin/media_plugin_cef.dylib')})
- # NOTE: the -S argument to strip causes it to keep enough info for
- # annotated backtraces (i.e. function names in the crash log). 'strip' with no
- # arguments yields a slightly smaller binary but makes crash logs mostly useless.
- # This may be desirable for the final release. Or not.
- if self.buildtype().lower() == 'release':
- if ("package" in self.args['actions'] or
- "unpacked" in self.args['actions']):
- self.run_command('strip -S "%(viewer_binary)s"' %
- { 'viewer_binary' : self.dst_path_of('Contents/MacOS/'+self.app_name())})
- # patch libfmod.dylib path in image
- self.run_command('install_name_tool -change @rpath/libfmod.dylib @executable_path/../Resources/libfmod.dylib "%(viewer_binary)s"' %
- { 'viewer_binary': self.dst_path_of('Contents/MacOS/'+self.app_name())})
- def app_name(self):
- return "Cool VL Viewer"
- def info_plist_name(self):
- return "Info-CoolVLViewer.plist"
- def package_finish(self):
- # removed, not using this anymore
- pass
- class LinuxManifest(ViewerManifest):
- def construct(self):
- super(LinuxManifest, self).construct()
- notdebug = "rel" in self.buildtype().lower()
- release = "release" in self.buildtype().lower()
- # For the Release build type (which lacks the symbols in the viewer
- # binary), save the build directory path into .buildir, so that our
- # wrapper script can find the path of the CoolVLViewer.debug file, when
- # it is still around...
- if release:
- # Save the build directory path into .buildir, so that our wrapper
- # script can find the path of the CoolVLViewer.debug file, when it
- # is still around...
- builddir_file = os.path.join(self.get_build_prefix(), '.buildir')
- ofile = open(builddir_file, "w")
- ofile.write(self.get_build_prefix())
- ofile.close()
- self.path(builddir_file, '.buildir')
- # Features table
- if self.prefix(src="app_settings"):
- self.path("featuretable_linux.txt", dst="featuretable.txt")
- self.end_prefix("app_settings")
- # Licenses and README files
- self.path(os.path.join(rootdir, 'doc', 'licenses-linux.txt'), "licenses.txt")
- self.path(os.path.join(rootdir, 'doc', 'README-linux.txt'), "README-linux.txt")
- self.path(os.path.join(rootdir, 'doc', 'VivoxAUP.txt'), 'VivoxAUP.txt')
- # Icons
- if self.prefix("res-sdl"):
- self.path("*")
- self.end_prefix("res-sdl")
- # Create a relative symlink for icon_name(); sadly, os.symlink()
- # cannot create relative links, so we call 'ln' instead.
- os.system("cd " + self.get_dst_prefix() + ";ln -s ./res-sdl/" + self.icon_name("48") + " " + self.icon_name())
- else:
- self.path("res/" + self.icon_name(), self.icon_name())
- # Various wrapper and utility scripts
- if self.prefix("linux_tools", dst=""):
- self.path("wrapper.sh", self.wrapper_name())
- self.path("viewer.conf", self.conf_name())
- self.path("handle_secondlifeprotocol.sh", "bin/handle_secondlifeprotocol.sh")
- self.path("register_secondlifeprotocol.sh", "bin/register_secondlifeprotocol.sh")
- self.path("messagebox.sh", "bin/messagebox.sh")
- self.path("launch_url.sh", "bin/launch_url.sh")
- self.path("*.tk")
- self.path("install-wine-SLVoice.sh")
- self.end_prefix("linux_tools")
- # Viewer binary, stripped or not, depending on build type
- # Note: for both the Debug and RelWithDebInfo types, we want the
- # unstripped binary.
- if release:
- self.path("CoolVLViewer-stripped", "bin/" + self.binary_name())
- else:
- self.path("CoolVLViewer", "bin/" + self.binary_name())
- # Other libraries
- if self.prefix(libreleasedir, dst="lib"):
- self.path("libapr-1.so.0.*.*", "libapr-1.so.0")
- # IMPORTANT: *never* bundle libfontconfig.so.1 with the viewer (and
- # never link the latter with a static libfontconfig.a library): the
- # version in use on the user's system might not correspond to the
- # one we use to build the viewer and the /etc/fonts/ config files
- # might not be understood by the latter. Instead, let's use the
- # system library, which matches the /etc/fonts/ config files.
- #self.path("libfontconfig.so.1.12.0", "libfontconfig.so.1")
- # This should exist on all Linux distros (part of util-linux).
- #self.path("libuuid.so.1.3.0", "libuuid.so.1")
- self.path("libalut.so.0.0.0", "libalut.so.0")
- # SDL2
- self.path("libSDL2-2.0.so.0.*.*", "libSDL2-2.0.so.0")
- # This too seemed like a good idea, but it causes issues on some
- # systems...
- #self.path("libopenal.so.1.12.854", "libopenal.so.1")
- self.path("libglod.so") # Mesh support
- self.end_prefix("lib")
- # Boost libraries, when dynamically linked. Only the Debug build uses
- # their debug version.
- if (notdebug and self.prefix(libreleasedir, dst="lib")):
- if (self.path("libboost_context-mt*.so.1.*.0")):
- self.path("libboost_fiber-mt*.so.1.*.0")
- self.path("libboost_filesystem-mt*.so.1.*.0")
- self.path("libboost_program_options-mt*.so.1.*.0")
- self.path("libboost_thread-mt*.so.1.*.0")
- self.path("libboost_atomic-mt*.so.1.*.0")
- else:
- print("Skipping boost libraries: assumed statically linked.")
- self.end_prefix("lib")
- if (not notdebug and self.prefix(libdebugdir, dst="lib")):
- if (self.path("libboost_context*.so.1.*.0")):
- self.path("libboost_fiber-mt*.so.1.*.0")
- self.path("libboost_filesystem-mt*.so.1.*.0")
- self.path("libboost_program_options-mt*.so.1.*.0")
- self.path("libboost_thread-mt*.so.1.*.0")
- self.path("libboost_atomic-mt*.so.1.*.0")
- else:
- print("Skipping boost libraries: assumed statically linked.")
- self.end_prefix("lib")
- # Shared jemalloc library, maybe...
- no_jemalloc = 1
- if (not notdebug and self.prefix(libdebugdir, dst="lib")):
- if (self.path("libjemalloc.so.2")):
- no_jemalloc = 0
- self.end_prefix("lib")
- if (no_jemalloc and self.prefix(libreleasedir, dst="lib")):
- self.path("libjemalloc.so.2")
- self.end_prefix("lib")
- # Media plugins
- has_cef = 0
- if self.prefix(src="", dst="bin/llplugin"):
- if (self.path("../media_plugins/cef/media_plugin_cef.so", "media_plugin_cef.so")):
- has_cef = 1
- self.path("../media_plugins/gstreamer/media_plugin_gstreamer.so", "media_plugin_gstreamer.so")
- self.path("../media_plugins/webrtc/voice_plugin_webrtc.so", "voice_plugin_webrtc.so")
- # SLPlugin
- self.path("../media_plugins/slplugin/SLPlugin", "SLPlugin")
- self.end_prefix("bin/llplugin")
- # For CEF3 plugin runtimes (starting with CEF 73, everything goes in
- # lib/, dullahan_host excepted).
- if has_cef == 1:
- if self.prefix(src=libreleasedir, dst="lib"):
- self.path("libcef.so")
- self.path("libEGL.so")
- self.path("libGLESv2.so")
- self.path("libvk_swiftshader.so")
- self.path("*blob.bin")
- self.path("*snapshot.bin")
- self.path("*.pak")
- self.path("icudtl.dat")
- self.end_prefix("lib")
- if self.prefix(src=os.path.join(libreleasedir, 'swiftshader'), dst="lib/swiftshader"):
- self.path("*.so")
- self.end_prefix("lib/swiftshader")
- # The locales/ directory now goes along with the libcef library,
- if self.prefix(src=os.path.join(libreleasedir, 'locales'), dst="lib/locales"):
- self.path("*.pak")
- self.end_prefix("lib/locales")
- if self.prefix(src=binreleasedir, dst="bin/llplugin"):
- self.path("dullahan_host")
- self.end_prefix("bin/llplugin")
- # 64 bits FMOD library:
- if (self.prefix(libreleasedir, dst="lib")):
- if (not self.path("libfmod.so.14.*", "libfmod.so.14")):
- print("FMOD library not found: the viewer will lack FMOD support.")
- self.end_prefix("lib")
- # Vivox runtime (they are 32 bits program and libraries)
- if self.prefix(src=binreleasedir, dst="bin"):
- self.path("SLVoice")
- self.end_prefix("bin")
- if self.prefix(src=libreleasedir, dst="lib"):
- self.path("libortp.so")
- self.path("libsndfile.so.1")
- self.path("libvivoxoal.so.1")
- self.path("libvivoxplatform.so")
- self.path("libvivoxsdk.so")
- self.end_prefix("lib")
- # WebRTC library.
- if self.prefix(src=libreleasedir, dst="lib"):
- self.path("libllwebrtc.so")
- self.end_prefix("lib")
- # Tracy, if in use
- if self.prefix(src=binreleasedir, dst="bin"):
- self.path("tracy")
- self.end_prefix()
- def wrapper_name(self):
- return "cool_vl_viewer"
- def conf_name(self):
- return "cool_vl_viewer.conf"
- def binary_name(self):
- return "cool_vl_viewer-bin"
- def icon_name(self, size = ""):
- return "cvlv_icon" + size + ".png"
- def package_finish(self):
- if 'installer_name' in self.args:
- installer_name = self.args['installer_name']
- else:
- installer_name_components = [self.installer_prefix(), 'x86_64']
- installer_name_components.extend(self.args['version'])
- installer_name = "_".join(installer_name_components)
- # Fix access permissions
- self.run_command("""
- find '%(dst)s' -type d -print0 | xargs -0 --no-run-if-empty chmod 755;
- find '%(dst)s' -type f -perm 0700 -print0 | xargs -0 --no-run-if-empty chmod 0755;
- find '%(dst)s' -type f -perm 0500 -print0 | xargs -0 --no-run-if-empty chmod 0555;
- find '%(dst)s' -type f -perm 0600 -print0 | xargs -0 --no-run-if-empty chmod 0644;
- find '%(dst)s' -type f -perm 0400 -print0 | xargs -0 --no-run-if-empty chmod 0444;
- true""" % {'dst':self.get_dst_prefix() })
- self.package_file = installer_name + '.tar.bz2'
- # Temporarily move directory tree so that it has the right name in the
- # tarfile
- self.run_command("rm -rf '%(inst)s/'" % {
- 'inst': self.build_path_of(installer_name)})
- self.run_command("mv '%(dst)s' '%(inst)s'" % {
- 'dst': self.get_dst_prefix(),
- 'inst': self.build_path_of(installer_name)})
- if "release" in self.buildtype().lower():
- # Strip the shared libraries from their debug symbols to save space
- # and speed up loading
- self.run_command("strip -s %(libs)s" % {
- 'libs': self.build_path_of(installer_name + "/lib/*.so*")})
- # --numeric-owner hides the username of the builder for security etc.
- if (self.run_command("tar -C '%(dir)s' --numeric-owner -cjf "
- "'%(inst_path)s.tar.bz2' %(inst_name)s" % {
- 'dir': self.get_build_prefix(),
- 'inst_name': installer_name,
- 'inst_path':self.build_path_of(installer_name)})):
- self.run_command("mv '%(inst)s' '%(dst)s'" % {
- 'dst': self.get_dst_prefix(),
- 'inst': self.build_path_of(installer_name)})
- ################################################################
- def symlinkf(src, dst):
- """
- Like ln -sf, but uses os.symlink() instead of running ln.
- """
- try:
- os.symlink(src, dst)
- except OSError as err:
- if err.errno != errno.EEXIST:
- raise
- # We could just blithely attempt to remove and recreate the target
- # file, but that strategy doesn't work so well if we do not have
- # permissions to remove it. Check to see if it's already the
- # symlink we want, which is the usual reason for EEXIST.
- if not (os.path.islink(dst) and os.readlink(dst) == src):
- # Here either dst is not a symlink or it is the wrong symlink.
- # Remove and recreate. Caller will just have to deal with any
- # exceptions at this stage.
- os.remove(dst)
- os.symlink(src, dst)
- if __name__ == "__main__":
- main()
|