Add require-binaries directive to scripts (Fixes #716)

This commit is contained in:
Mathieu Comandon 2018-05-07 23:50:47 -07:00
parent 08487f12b8
commit 36ab7c01f1
2 changed files with 42 additions and 5 deletions

View file

@ -111,6 +111,18 @@ Example (setting some environment variables):
__GL_THREADED_OPTIMIZATIONS: '1'
mesa_glthread: 'true'
Requiring additional binaries
-----------------------------
If the game or the installer needs some system binaries to run, you can specify
them in the `require-binaries` directive. The value is a comma-separated list
of required binaries (acting as AND), if one of several binaries are able to
run the program, you can add them as a ``|`` separated list (acting as OR).
Example::
# This requires cmake to be installed and either ggc or clang
require-binaries: cmake, gcc | clang
Mods and add-ons
----------------
@ -118,9 +130,10 @@ Mods and add-ons require that a base game is already installed on the system.
You can let the installer know that you want to install an add-on by specifying
the ``requires`` directive. The value of ``requires`` must be the canonical
slug name of the base game, not one of its aliases. For example, to install the
add-on "The reckoning" for Quake 2, you should add:
add-on "The reckoning" for Quake 2, you should add: ``requires: quake-2``
``requires: quake-2``
You can also add complex requirements following the same syntax as the
``require-binaries`` directive described above.
Writing the installation script

View file

@ -12,7 +12,7 @@ from lutris import pga
from lutris import settings
from lutris.game import Game
from lutris.util import system
from lutris.util import strings
from lutris.util.strings import unpack_dependencies
from lutris.util.jobs import AsyncCall
from lutris.util.log import logger
from lutris.util.steam import get_app_state_log
@ -89,6 +89,7 @@ class ScriptInterpreter(CommandsMixin):
self.requires = self.script.get('requires')
self.extends = self.script.get('extends')
self._check_binary_dependencies()
self._check_dependency()
if self.creates_game_folder:
self.target_path = self.get_default_target()
@ -172,6 +173,29 @@ class ScriptInterpreter(CommandsMixin):
if bool(game) and bool(game['directory']):
return game
def _check_binary_dependencies(self):
"""Check if all required binaries are installed on the system.
This reads a `require-binaries` entry in the script, parsed the same way as
the `requires` entry.
"""
binary_dependencies = unpack_dependencies(self.script.get('require-binaries'))
for dependency in binary_dependencies:
if isinstance(dependency, tuple):
installed_binaries = {
dependency_option: bool(system.find_executable(dependency_option))
for dependency_option in dependency
}
if not any(installed_binaries.values()):
raise ScriptingError(
"This installer requires %s on your system" % ' or '.join(dependency)
)
else:
if not system.find_executable(dependency):
raise ScriptingError(
"This installer requires %s on your system" % ' or '.join(dependency)
)
def _check_dependency(self):
"""When a game is a mod or an extension of another game, check that the base
game is installed.
@ -182,7 +206,7 @@ class ScriptInterpreter(CommandsMixin):
if self.extends:
dependencies = [self.extends]
else:
dependencies = strings.unpack_dependencies(self.requires)
dependencies = unpack_dependencies(self.requires)
error_message = "You need to install {} before"
for index, dependency in enumerate(dependencies):
if isinstance(dependency, tuple):
@ -599,7 +623,7 @@ class ScriptInterpreter(CommandsMixin):
if 'game' in self.script:
config['game'].update(self.script['game'])
config['game'] = self._substitute_config(config['game'])
# steamless_binary64 can be used to specify 64 bit non-steam binaries
is_64bit = platform.machine() == "x86_64"
if is_64bit and 'steamless_binary64' in config['game']: