mirror of https://github.com/mpv-player/mpv
build: use unified dependency expressions instead of weird fields
Instead of "deps", "deps_neg", and "deps_any" fields, just have a single "deps" field, which changes from an array to a string. The string is now an expression, which can contain the operators &&, ||, !, and allows grouping with ( ). It's probably overkill. If it gets a maintenance burden, we can switch to specifiying the dep expressions as ASTs (or maybe eval()-able Python expressions), and we could simplify the code that determines the reason why a dependency is not fulfilled. The latter involves a complicated conversion of the expression AST to DNF. The parser is actually pretty simple, and pretty much follows: https://en.wikipedia.org/wiki/Shunting_yard_algorithm
This commit is contained in:
parent
f4c80d4402
commit
acb28e922b
|
@ -2,6 +2,7 @@ from waflib.Errors import ConfigurationError, WafError
|
|||
from waflib.Configure import conf
|
||||
from waflib.Build import BuildContext
|
||||
from waflib.Logs import pprint
|
||||
import deps_parser
|
||||
import inflector
|
||||
|
||||
class DependencyError(Exception):
|
||||
|
@ -16,11 +17,9 @@ class Dependency(object):
|
|||
self.attributes = self.__parse_attributes__(dependency)
|
||||
|
||||
known_deps.add(self.identifier)
|
||||
for dep_key in ['deps', 'deps_any', 'deps_neg']:
|
||||
if dep_key in self.attributes:
|
||||
deps = self.attributes[dep_key]
|
||||
self.ctx.ensure_dependency_is_known(*deps)
|
||||
|
||||
if 'deps' in self.attributes:
|
||||
self.ctx.ensure_dependency_is_known(self.attributes['deps'])
|
||||
|
||||
def __parse_attributes__(self, dependency):
|
||||
if 'os_specific_checks' in dependency:
|
||||
|
@ -36,9 +35,7 @@ class Dependency(object):
|
|||
try:
|
||||
self.check_group_disabled()
|
||||
self.check_disabled()
|
||||
self.check_any_dependencies()
|
||||
self.check_dependencies()
|
||||
self.check_negative_dependencies()
|
||||
except DependencyError:
|
||||
# No check was run, since the prerequisites of the dependency are
|
||||
# not satisfied. Make sure the define is 'undefined' so that we
|
||||
|
@ -67,27 +64,12 @@ class Dependency(object):
|
|||
self.attributes['fmsg'] = "You manually enabled the feature '{0}', but \
|
||||
the autodetection check failed.".format(self.identifier)
|
||||
|
||||
def check_any_dependencies(self):
|
||||
if 'deps_any' in self.attributes:
|
||||
deps = set(self.attributes['deps_any'])
|
||||
if len(deps & self.satisfied_deps) == 0:
|
||||
self.skip("not found any of {0}".format(", ".join(deps)))
|
||||
raise DependencyError
|
||||
|
||||
def check_dependencies(self):
|
||||
if 'deps' in self.attributes:
|
||||
deps = set(self.attributes['deps'])
|
||||
if not deps <= self.satisfied_deps:
|
||||
missing_deps = deps - self.satisfied_deps
|
||||
self.skip("{0} not found".format(", ".join(missing_deps)))
|
||||
raise DependencyError
|
||||
|
||||
def check_negative_dependencies(self):
|
||||
if 'deps_neg' in self.attributes:
|
||||
deps = set(self.attributes['deps_neg'])
|
||||
conflicting_deps = deps & self.satisfied_deps
|
||||
if len(conflicting_deps) > 0:
|
||||
self.skip("{0} found".format(", ".join(conflicting_deps)), 'CYAN')
|
||||
ok, why = deps_parser.check_dependency_expr(self.attributes['deps'],
|
||||
self.satisfied_deps)
|
||||
if not ok:
|
||||
self.skip(why)
|
||||
raise DependencyError
|
||||
|
||||
def check_autodetect_func(self):
|
||||
|
@ -145,13 +127,19 @@ def configure(ctx):
|
|||
__detect_target_os_dependency__(ctx)
|
||||
|
||||
@conf
|
||||
def ensure_dependency_is_known(ctx, *depnames):
|
||||
deps = set([d for d in depnames if not d.startswith('os-')])
|
||||
if not deps <= ctx.known_deps:
|
||||
def ensure_dependency_is_known(ctx, depnames):
|
||||
def check(ast):
|
||||
if isinstance(ast, deps_parser.AstSym):
|
||||
if (not ast.name.startswith('os-')) and ast.name not in ctx.known_deps:
|
||||
raise ConfigurationError(
|
||||
"error in dependencies definition: some dependencies in"
|
||||
" {0} are unknown.".format(deps))
|
||||
|
||||
"error in dependencies definition: dependency {0} in"
|
||||
" {1} is unknown.".format(ast.name, depnames))
|
||||
elif isinstance(ast, deps_parser.AstOp):
|
||||
for sub in ast.sub:
|
||||
check(sub)
|
||||
else:
|
||||
assert False
|
||||
check(deps_parser.parse_expr(depnames))
|
||||
|
||||
@conf
|
||||
def mark_satisfied(ctx, dependency_identifier):
|
||||
|
@ -174,7 +162,9 @@ def parse_dependencies(ctx, dependencies):
|
|||
@conf
|
||||
def dependency_satisfied(ctx, dependency_identifier):
|
||||
ctx.ensure_dependency_is_known(dependency_identifier)
|
||||
return dependency_identifier in ctx.satisfied_deps
|
||||
ok, _ = deps_parser.check_dependency_expr(dependency_identifier,
|
||||
ctx.satisfied_deps)
|
||||
return ok
|
||||
|
||||
@conf
|
||||
def store_dependencies_lists(ctx):
|
||||
|
@ -194,13 +184,7 @@ def filtered_sources(ctx, sources):
|
|||
return source
|
||||
|
||||
def __check_filter__(dependency):
|
||||
if dependency.find('!') == 0:
|
||||
dependency = dependency.lstrip('!')
|
||||
ctx.ensure_dependency_is_known(dependency)
|
||||
return dependency not in ctx.satisfied_deps
|
||||
else:
|
||||
ctx.ensure_dependency_is_known(dependency)
|
||||
return dependency in ctx.satisfied_deps
|
||||
return dependency_satisfied(ctx, dependency)
|
||||
|
||||
def __unpack_and_check_filter__(source):
|
||||
try:
|
||||
|
|
|
@ -0,0 +1,218 @@
|
|||
|
||||
class ParseError(Exception):
|
||||
pass
|
||||
|
||||
class AstOp(object):
|
||||
def __init__(self, op, sub):
|
||||
self.op = op
|
||||
self.sub = sub
|
||||
|
||||
def __repr__(self):
|
||||
if len(self.sub) == 1:
|
||||
return self.op + str(self.sub[0])
|
||||
return "(" + (" " + self.op + " ").join([str(x) for x in self.sub]) + ")"
|
||||
|
||||
class AstSym(object):
|
||||
def __init__(self, name):
|
||||
assert type(name) is type("")
|
||||
self.name = name
|
||||
|
||||
def __repr__(self):
|
||||
return self.name
|
||||
|
||||
Arity = { "!": 1, "&&": 2, "||": 2 }
|
||||
Precedence = { "!": 3, "&&": 2, "||": 1 }
|
||||
Tokens = list(Arity.keys()) + ["(", ")"]
|
||||
|
||||
# return (token, rest), or (None, "") if nothing left
|
||||
def read_tok(expr):
|
||||
expr = expr.strip()
|
||||
for t in Tokens:
|
||||
if expr.startswith(t):
|
||||
return (t, expr[len(t):])
|
||||
if expr == "":
|
||||
return (None, "")
|
||||
sym = ""
|
||||
while len(expr) and ((expr[0].lower() >= 'a' and expr[0].lower() <= 'z') or
|
||||
(expr[0] >= '0' and expr[0] <= '9') or
|
||||
(expr[0] in ["_", "-", "."])):
|
||||
sym += expr[0]
|
||||
expr = expr[1:]
|
||||
if len(sym):
|
||||
return sym, expr
|
||||
raise ParseError("unknown token in '%s'" % expr)
|
||||
|
||||
def parse_expr(expr):
|
||||
opstack = []
|
||||
outstack = []
|
||||
def out(sym):
|
||||
if sym in Arity:
|
||||
sub = []
|
||||
for i in range(Arity[sym]):
|
||||
if len(outstack) == 0:
|
||||
raise ParseError("missing operator argument")
|
||||
sub.insert(0, outstack.pop())
|
||||
outstack.append(AstOp(sym, sub))
|
||||
elif sym == "(":
|
||||
raise ParseError("missing closing ')'")
|
||||
elif not isinstance(sym, AstSym):
|
||||
raise ParseError("bogus symbol '%s'" % sym)
|
||||
else:
|
||||
outstack.append(sym)
|
||||
while True:
|
||||
tok, expr = read_tok(expr)
|
||||
if tok is None:
|
||||
break
|
||||
if tok in Arity:
|
||||
while len(opstack) and opstack[-1] != '(' and \
|
||||
Precedence[opstack[-1]] > Precedence[tok]:
|
||||
out(opstack.pop())
|
||||
opstack.append(tok)
|
||||
elif tok == "(":
|
||||
opstack.append(tok)
|
||||
elif tok == ")":
|
||||
while True:
|
||||
if not len(opstack):
|
||||
raise ParseError("missing '(' for ')'")
|
||||
sym = opstack.pop()
|
||||
if sym == "(":
|
||||
break
|
||||
out(sym)
|
||||
else:
|
||||
out(AstSym(tok)) # Assume a terminal
|
||||
while len(opstack):
|
||||
out(opstack.pop())
|
||||
if len(outstack) != 1:
|
||||
raise ParseError("empty expression or extra symbols (%s)" % outstack)
|
||||
return outstack.pop()
|
||||
|
||||
def convert_dnf(ast):
|
||||
|
||||
# no nested ! (negation normal form)
|
||||
def simplify_negation(ast):
|
||||
if isinstance(ast, AstOp):
|
||||
if ast.op == "!":
|
||||
sub = ast.sub[0]
|
||||
if isinstance(sub, AstOp):
|
||||
if sub.op == "!":
|
||||
return sub.sub[0]
|
||||
elif sub.op in ["&&", "||"]:
|
||||
sub.op = "||" if sub.op == "&&" else "&&"
|
||||
sub.sub = [AstOp("!", [x]) for x in sub.sub]
|
||||
return simplify_negation(sub)
|
||||
else:
|
||||
ast.sub = [simplify_negation(x) for x in ast.sub]
|
||||
return ast
|
||||
|
||||
# a && (b && c) => a && b && c
|
||||
def flatten(ast):
|
||||
if isinstance(ast, AstOp):
|
||||
can_flatten = ast.op in ["&&", "||"]
|
||||
nsub = []
|
||||
for sub in ast.sub:
|
||||
sub = flatten(sub)
|
||||
if isinstance(sub, AstOp) and sub.op == ast.op and can_flatten:
|
||||
nsub.extend(sub.sub)
|
||||
else:
|
||||
nsub.append(sub)
|
||||
ast.sub = nsub
|
||||
if len(ast.sub) == 1 and can_flatten:
|
||||
return ast.sub[0]
|
||||
return ast
|
||||
|
||||
# a && (b || c) && d => (a && d && b) || (a && d && c)
|
||||
def redist(ast):
|
||||
def recombine(a, stuff):
|
||||
return AstOp("||", [AstOp("&&", [a, n]) for n in stuff])
|
||||
if isinstance(ast, AstOp):
|
||||
ast.sub = [flatten(redist(x)) for x in ast.sub]
|
||||
if ast.op == "&&":
|
||||
for sub in ast.sub:
|
||||
if isinstance(sub, AstOp) and sub.op == "||":
|
||||
if len(ast.sub) == 1:
|
||||
return redist(sub)
|
||||
other = None
|
||||
for n in ast.sub:
|
||||
if n is not sub:
|
||||
if other is None:
|
||||
other = n
|
||||
else:
|
||||
other = flatten(AstOp("&&", [other, n]))
|
||||
return flatten(redist(recombine(other, sub.sub)))
|
||||
return ast
|
||||
|
||||
return redist(flatten(simplify_negation(ast)))
|
||||
|
||||
# Returns (success_as_bool, failure_reason_as_string)
|
||||
def check_dependency_expr(expr, deps):
|
||||
ast = parse_expr(expr)
|
||||
def eval_ast(ast):
|
||||
if isinstance(ast, AstSym):
|
||||
return ast.name in deps
|
||||
elif isinstance(ast, AstOp):
|
||||
vals = [eval_ast(x) for x in ast.sub]
|
||||
if ast.op == "&&":
|
||||
return vals[0] and vals[1]
|
||||
elif ast.op == "||":
|
||||
return vals[0] or vals[1]
|
||||
elif ast.op == "!":
|
||||
return not vals[0]
|
||||
assert False
|
||||
if eval_ast(ast):
|
||||
return True, None
|
||||
|
||||
# Now the same thing again, but more complicated, and informing what is
|
||||
# missing.
|
||||
ast = convert_dnf(ast)
|
||||
|
||||
# ast now is a or-combined list of and-combined deps. Each dep can have a
|
||||
# negation (marking a conflict). Each case of and-combined deps is a way
|
||||
# to satisfy the deps expression. Instead of dumping full information,
|
||||
# distinguish the following cases, and only mention the one that applies,
|
||||
# in order:
|
||||
# 1. the first missing dep of a case that has missing deps only
|
||||
# 2. the first conflicting dep at all
|
||||
|
||||
def do_op(ast, op, cb):
|
||||
if isinstance(ast, AstOp) and ast.op == op:
|
||||
for sub in ast.sub:
|
||||
cb(sub)
|
||||
else:
|
||||
cb(ast)
|
||||
|
||||
def get_sub_list(node, op):
|
||||
if isinstance(node, AstOp) and node.op == op:
|
||||
return node.sub
|
||||
else:
|
||||
return [node]
|
||||
|
||||
conflict_dep = None
|
||||
missing_dep = None
|
||||
|
||||
for group in get_sub_list(ast, "||"):
|
||||
group_conflict = None
|
||||
group_missing_dep = None
|
||||
for elem in get_sub_list(group, "&&"):
|
||||
neg = False
|
||||
if isinstance(elem, AstOp) and elem.op == "!":
|
||||
neg = True
|
||||
elem = elem.sub[0]
|
||||
if not isinstance(elem, AstSym):
|
||||
continue # broken DNF?
|
||||
name = elem.name
|
||||
present = name in deps
|
||||
if (not present) and (not neg) and (group_missing_dep is None):
|
||||
group_missing_dep = name
|
||||
if present and neg and (group_conflict is None):
|
||||
group_conflict = name
|
||||
if (missing_dep is None) and (group_conflict is None):
|
||||
missing_dep = group_missing_dep
|
||||
if conflict_dep is None:
|
||||
conflict_dep = group_conflict
|
||||
|
||||
reason = "unknown"
|
||||
if missing_dep is not None:
|
||||
reason = "%s not found" % (missing_dep)
|
||||
elif conflict_dep is not None:
|
||||
reason = "%s found" % (conflict_dep)
|
||||
return False, reason
|
171
wscript
171
wscript
|
@ -40,7 +40,7 @@ build_options = [
|
|||
'name': '--libmpv-static',
|
||||
'desc': 'static library',
|
||||
'default': 'disable',
|
||||
'deps_neg': [ 'libmpv-shared' ],
|
||||
'deps': '!libmpv-shared',
|
||||
'func': check_true
|
||||
}, {
|
||||
'name': '--static-build',
|
||||
|
@ -83,8 +83,7 @@ build_options = [
|
|||
}, {
|
||||
'name': '--cplugins',
|
||||
'desc': 'C plugins',
|
||||
'deps': [ 'libdl' ],
|
||||
'deps_neg': [ 'os-win32' ],
|
||||
'deps': 'libdl && !os-win32',
|
||||
'func': check_cc(linkflags=['-rdynamic']),
|
||||
}, {
|
||||
'name': '--zsh-comp',
|
||||
|
@ -127,7 +126,7 @@ main_dependencies = [
|
|||
}, {
|
||||
'name': 'mingw',
|
||||
'desc': 'MinGW',
|
||||
'deps': [ 'os-win32' ],
|
||||
'deps': 'os-win32',
|
||||
'func': check_statement('stdlib.h', 'int x = __MINGW32__;'
|
||||
'int y = __MINGW64_VERSION_MAJOR'),
|
||||
}, {
|
||||
|
@ -143,7 +142,7 @@ main_dependencies = [
|
|||
}, {
|
||||
'name': 'posix-or-mingw',
|
||||
'desc': 'development environment',
|
||||
'deps_any': [ 'posix', 'mingw' ],
|
||||
'deps': 'posix || mingw',
|
||||
'func': check_true,
|
||||
'req': True,
|
||||
'fmsg': 'Unable to find either POSIX or MinGW-w64 environment, ' \
|
||||
|
@ -152,20 +151,17 @@ main_dependencies = [
|
|||
'name': '--uwp',
|
||||
'desc': 'Universal Windows Platform',
|
||||
'default': 'disable',
|
||||
'deps': [ 'os-win32', 'mingw' ],
|
||||
'deps_neg': [ 'cplayer' ],
|
||||
'deps': 'os-win32 && mingw && !cplayer',
|
||||
'func': check_cc(lib=['windowsapp']),
|
||||
}, {
|
||||
'name': 'win32-desktop',
|
||||
'desc': 'win32 desktop APIs',
|
||||
'deps_any': [ 'os-win32', 'os-cygwin' ],
|
||||
'deps_neg': [ 'uwp' ],
|
||||
'deps': '(os-win32 || os-cygwin) && !uwp',
|
||||
'func': check_cc(lib=['winmm', 'gdi32', 'ole32', 'uuid', 'avrt', 'dwmapi']),
|
||||
}, {
|
||||
'name': '--win32-internal-pthreads',
|
||||
'desc': 'internal pthread wrapper for win32 (Vista+)',
|
||||
'deps_neg': [ 'posix' ],
|
||||
'deps': [ 'os-win32' ],
|
||||
'deps': 'os-win32 && !posix',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': 'pthreads',
|
||||
|
@ -189,11 +185,11 @@ main_dependencies = [
|
|||
'desc': 'stdatomic.h support or slow emulation',
|
||||
'func': check_true,
|
||||
'req': True,
|
||||
'deps_any': ['stdatomic', 'gnuc'],
|
||||
'deps': 'stdatomic || gnuc',
|
||||
}, {
|
||||
'name': 'librt',
|
||||
'desc': 'linking with -lrt',
|
||||
'deps': [ 'pthreads' ],
|
||||
'deps': 'pthreads',
|
||||
'func': check_cc(lib='rt')
|
||||
}, {
|
||||
'name': '--iconv',
|
||||
|
@ -206,7 +202,7 @@ iconv support use --disable-iconv.",
|
|||
}, {
|
||||
'name': 'dos-paths',
|
||||
'desc': 'w32/dos paths',
|
||||
'deps_any': [ 'os-win32', 'os-cygwin' ],
|
||||
'deps': 'os-win32 || os-cygwin',
|
||||
'func': check_true
|
||||
}, {
|
||||
'name': '--termios',
|
||||
|
@ -226,28 +222,26 @@ iconv support use --disable-iconv.",
|
|||
'desc': 'POSIX spawnp()/kill()',
|
||||
'func': check_statement(['spawn.h', 'signal.h'],
|
||||
'posix_spawnp(0,0,0,0,0,0); kill(0,0)'),
|
||||
'deps_neg': ['mingw'],
|
||||
'deps': '!mingw',
|
||||
}, {
|
||||
'name': 'win32-pipes',
|
||||
'desc': 'Windows pipe support',
|
||||
'func': check_true,
|
||||
'deps': [ 'win32-desktop' ],
|
||||
'deps_neg': [ 'posix' ],
|
||||
'deps': 'win32-desktop && !posix',
|
||||
}, {
|
||||
'name': 'glob-posix',
|
||||
'desc': 'glob() POSIX support',
|
||||
'deps_neg': [ 'os-win32', 'os-cygwin' ],
|
||||
'deps': '!(os-win32 || os-cygwin)',
|
||||
'func': check_statement('glob.h', 'glob("filename", 0, 0, 0)'),
|
||||
}, {
|
||||
'name': 'glob-win32',
|
||||
'desc': 'glob() win32 replacement',
|
||||
'deps_neg': [ 'posix' ],
|
||||
'deps_any': [ 'os-win32', 'os-cygwin' ],
|
||||
'deps': '!posix && (os-win32 || os-cygwin)',
|
||||
'func': check_true
|
||||
}, {
|
||||
'name': 'glob',
|
||||
'desc': 'any glob() support',
|
||||
'deps_any': [ 'glob-posix', 'glob-win32' ],
|
||||
'deps': 'glob-posix || glob-win32',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': 'fchmod',
|
||||
|
@ -271,13 +265,13 @@ iconv support use --disable-iconv.",
|
|||
}, {
|
||||
'name': 'osx-thread-name',
|
||||
'desc': 'OSX API for setting thread name',
|
||||
'deps_neg': [ 'glibc-thread-name' ],
|
||||
'deps': '!glibc-thread-name',
|
||||
'func': check_statement('pthread.h',
|
||||
'pthread_setname_np("ducks")', use=['pthreads']),
|
||||
}, {
|
||||
'name': 'bsd-thread-name',
|
||||
'desc': 'BSD API for setting thread name',
|
||||
'deps_neg': [ 'glibc-thread-name', 'osx-thread-name' ],
|
||||
'deps': '!(glibc-thread-name || osx-thread-name)',
|
||||
'func': check_statement('pthread.h',
|
||||
'pthread_set_name_np(pthread_self(), "ducks")',
|
||||
use=['pthreads']),
|
||||
|
@ -289,13 +283,13 @@ iconv support use --disable-iconv.",
|
|||
}, {
|
||||
'name': 'linux-fstatfs',
|
||||
'desc': "Linux's fstatfs()",
|
||||
'deps': [ 'os-linux' ],
|
||||
'deps': 'os-linux',
|
||||
'func': check_statement('sys/vfs.h',
|
||||
'struct statfs fs; fstatfs(0, &fs); fs.f_namelen')
|
||||
}, {
|
||||
'name': '--libsmbclient',
|
||||
'desc': 'Samba support (makes mpv GPLv3)',
|
||||
'deps': [ 'libdl' ],
|
||||
'deps': 'libdl',
|
||||
'func': check_pkg_config('smbclient'),
|
||||
'default': 'disable',
|
||||
'module': 'input',
|
||||
|
@ -318,12 +312,12 @@ iconv support use --disable-iconv.",
|
|||
}, {
|
||||
'name': '--libass-osd',
|
||||
'desc': 'libass OSD support',
|
||||
'deps': [ 'libass' ],
|
||||
'deps': 'libass',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': 'dummy-osd',
|
||||
'desc': 'dummy OSD support',
|
||||
'deps_neg': [ 'libass-osd' ],
|
||||
'deps': '!libass-osd',
|
||||
'func': check_true,
|
||||
} , {
|
||||
'name': '--zlib',
|
||||
|
@ -355,7 +349,7 @@ iconv support use --disable-iconv.",
|
|||
}, {
|
||||
'name': 'dvdread-common',
|
||||
'desc': 'DVD/IFO support',
|
||||
'deps_any': [ 'dvdread', 'dvdnav' ],
|
||||
'deps': 'dvdread || dvdnav',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--cdda',
|
||||
|
@ -365,7 +359,7 @@ iconv support use --disable-iconv.",
|
|||
}, {
|
||||
'name': '--uchardet',
|
||||
'desc': 'uchardet support',
|
||||
'deps': [ 'iconv' ],
|
||||
'deps': 'iconv',
|
||||
'func': check_pkg_config('uchardet'),
|
||||
}, {
|
||||
'name': '--rubberband',
|
||||
|
@ -383,12 +377,12 @@ iconv support use --disable-iconv.",
|
|||
}, {
|
||||
'name': '--vapoursynth-lazy',
|
||||
'desc': 'VapourSynth filter bridge (Lazy Lua)',
|
||||
'deps': ['lua'],
|
||||
'deps': 'lua',
|
||||
'func': check_pkg_config('vapoursynth', '>= 24'),
|
||||
}, {
|
||||
'name': 'vapoursynth-core',
|
||||
'desc': 'VapourSynth filter bridge (core)',
|
||||
'deps_any': ['vapoursynth', 'vapoursynth-lazy'],
|
||||
'deps': 'vapoursynth || vapoursynth-lazy',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--libarchive',
|
||||
|
@ -454,7 +448,7 @@ libav_dependencies = [
|
|||
}, {
|
||||
'name': 'libav',
|
||||
'desc': 'Libav/FFmpeg library versions',
|
||||
'deps_any': [ 'is_ffmpeg', 'is_libav' ],
|
||||
'deps': 'is_ffmpeg || is_libav',
|
||||
'func': check_ffmpeg_or_libav_versions(),
|
||||
'req': True,
|
||||
'fmsg': "Unable to find development files for some of the required \
|
||||
|
@ -499,14 +493,14 @@ audio_output_features = [
|
|||
}, {
|
||||
'name': '--sdl1',
|
||||
'desc': 'SDL (1.x)',
|
||||
'deps_neg': [ 'sdl2' ],
|
||||
'deps': '!sdl2',
|
||||
'func': check_pkg_config('sdl'),
|
||||
'default': 'disable'
|
||||
}, {
|
||||
'name': '--oss-audio',
|
||||
'desc': 'OSS',
|
||||
'func': check_cc(header_name='sys/soundcard.h'),
|
||||
'deps': [ 'posix' ],
|
||||
'deps': 'posix',
|
||||
}, {
|
||||
'name': '--rsound',
|
||||
'desc': 'RSound audio output',
|
||||
|
@ -547,14 +541,14 @@ audio_output_features = [
|
|||
}, {
|
||||
'name': '--audiounit',
|
||||
'desc': 'AudioUnit output for iOS',
|
||||
'deps': ['atomics'],
|
||||
'deps': 'atomics',
|
||||
'func': check_cc(
|
||||
fragment=load_fragment('audiounit.c'),
|
||||
framework_name=['Foundation', 'AudioToolbox'])
|
||||
}, {
|
||||
'name': '--wasapi',
|
||||
'desc': 'WASAPI audio output',
|
||||
'deps_any': ['os-win32', 'os-cygwin'],
|
||||
'deps': 'os-win32 || os-cygwin',
|
||||
'func': check_cc(fragment=load_fragment('wasapi.c')),
|
||||
}
|
||||
]
|
||||
|
@ -567,12 +561,12 @@ video_output_features = [
|
|||
}, {
|
||||
'name': '--drm',
|
||||
'desc': 'DRM',
|
||||
'deps': [ 'vt.h' ],
|
||||
'deps': 'vt.h',
|
||||
'func': check_pkg_config('libdrm'),
|
||||
}, {
|
||||
'name': '--gbm',
|
||||
'desc': 'GBM',
|
||||
'deps': [ 'gbm.h' ],
|
||||
'deps': 'gbm.h',
|
||||
'func': check_pkg_config('gbm'),
|
||||
} , {
|
||||
'name': '--wayland',
|
||||
|
@ -591,12 +585,12 @@ video_output_features = [
|
|||
} , {
|
||||
'name': '--xv',
|
||||
'desc': 'Xv video output',
|
||||
'deps': [ 'x11' ],
|
||||
'deps': 'x11',
|
||||
'func': check_pkg_config('xv'),
|
||||
} , {
|
||||
'name': '--gl-cocoa',
|
||||
'desc': 'OpenGL Cocoa Backend',
|
||||
'deps': [ 'cocoa' ],
|
||||
'deps': 'cocoa',
|
||||
'groups': [ 'gl' ],
|
||||
'func': check_statement('IOSurface/IOSurface.h',
|
||||
'IOSurfaceRef surface;',
|
||||
|
@ -604,7 +598,7 @@ video_output_features = [
|
|||
} , {
|
||||
'name': '--gl-x11',
|
||||
'desc': 'OpenGL X11 Backend',
|
||||
'deps': [ 'x11' ],
|
||||
'deps': 'x11',
|
||||
'groups': [ 'gl' ],
|
||||
'func': check_libs(['GL', 'GL Xdamage'],
|
||||
check_cc(fragment=load_fragment('gl_x11.c'),
|
||||
|
@ -612,33 +606,33 @@ video_output_features = [
|
|||
} , {
|
||||
'name': '--egl-x11',
|
||||
'desc': 'OpenGL X11 EGL Backend',
|
||||
'deps': [ 'x11' ],
|
||||
'deps': 'x11',
|
||||
'groups': [ 'gl' ],
|
||||
'func': check_pkg_config('egl'),
|
||||
} , {
|
||||
'name': '--egl-drm',
|
||||
'desc': 'OpenGL DRM EGL Backend',
|
||||
'deps': [ 'drm', 'gbm' ],
|
||||
'deps': 'drm && gbm',
|
||||
'groups': [ 'gl' ],
|
||||
'func': check_pkg_config('egl'),
|
||||
} , {
|
||||
'name': '--gl-wayland',
|
||||
'desc': 'OpenGL Wayland Backend',
|
||||
'deps': [ 'wayland' ],
|
||||
'deps': 'wayland',
|
||||
'groups': [ 'gl' ],
|
||||
'func': check_pkg_config('wayland-egl', '>= 9.0.0',
|
||||
'egl', '>= 9.0.0')
|
||||
} , {
|
||||
'name': '--gl-win32',
|
||||
'desc': 'OpenGL Win32 Backend',
|
||||
'deps': [ 'win32-desktop' ],
|
||||
'deps': 'win32-desktop',
|
||||
'groups': [ 'gl' ],
|
||||
'func': check_statement('windows.h', 'wglCreateContext(0)',
|
||||
lib='opengl32')
|
||||
} , {
|
||||
'name': '--gl-dxinterop',
|
||||
'desc': 'OpenGL/DirectX Interop Backend',
|
||||
'deps': [ 'gl-win32' ],
|
||||
'deps': 'gl-win32',
|
||||
'groups': [ 'gl' ],
|
||||
'func': compose_checks(
|
||||
check_statement(['GL/gl.h', 'GL/wglext.h'], 'int i = WGL_ACCESS_WRITE_DISCARD_NV'),
|
||||
|
@ -646,14 +640,14 @@ video_output_features = [
|
|||
} , {
|
||||
'name': '--egl-angle',
|
||||
'desc': 'OpenGL ANGLE headers',
|
||||
'deps_any': [ 'os-win32', 'os-cygwin' ],
|
||||
'deps': 'os-win32 || os-cygwin',
|
||||
'groups': [ 'gl' ],
|
||||
'func': check_statement(['EGL/egl.h', 'EGL/eglext.h'],
|
||||
'int x = EGL_D3D_TEXTURE_2D_SHARE_HANDLE_ANGLE')
|
||||
} , {
|
||||
'name': '--egl-angle-lib',
|
||||
'desc': 'OpenGL Win32 ANGLE Library',
|
||||
'deps': [ 'egl-angle' ],
|
||||
'deps': 'egl-angle',
|
||||
'groups': [ 'gl' ],
|
||||
'func': check_statement(['EGL/egl.h'],
|
||||
'eglCreateWindowSurface(0, 0, 0, 0)',
|
||||
|
@ -664,54 +658,53 @@ video_output_features = [
|
|||
}, {
|
||||
'name': '--egl-angle-win32',
|
||||
'desc': 'OpenGL Win32 ANGLE Backend',
|
||||
'deps': [ 'egl-angle', 'win32-desktop' ],
|
||||
'deps': 'egl-angle && win32-desktop',
|
||||
'groups': [ 'gl' ],
|
||||
'func': check_true,
|
||||
} , {
|
||||
'name': '--vdpau',
|
||||
'desc': 'VDPAU acceleration',
|
||||
'deps': [ 'x11' ],
|
||||
'deps': 'x11',
|
||||
'func': check_pkg_config('vdpau', '>= 0.2'),
|
||||
} , {
|
||||
'name': '--vdpau-gl-x11',
|
||||
'desc': 'VDPAU with OpenGL/X11',
|
||||
'deps': [ 'vdpau', 'gl-x11' ],
|
||||
'deps': 'vdpau && gl-x11',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--vaapi',
|
||||
'desc': 'VAAPI acceleration',
|
||||
'deps': [ 'libdl' ],
|
||||
'deps_any': [ 'x11', 'wayland', 'egl-drm' ],
|
||||
'deps': 'libdl && (x11 || wayland || egl-drm)',
|
||||
'func': check_pkg_config('libva', '>= 0.36.0'),
|
||||
}, {
|
||||
'name': '--vaapi-x11',
|
||||
'desc': 'VAAPI (X11 support)',
|
||||
'deps': [ 'vaapi', 'x11' ],
|
||||
'deps': 'vaapi && x11',
|
||||
'func': check_pkg_config('libva-x11', '>= 0.36.0'),
|
||||
}, {
|
||||
'name': '--vaapi-wayland',
|
||||
'desc': 'VAAPI (Wayland support)',
|
||||
'deps': [ 'vaapi', 'gl-wayland' ],
|
||||
'deps': 'vaapi && gl-wayland',
|
||||
'func': check_pkg_config('libva-wayland', '>= 0.36.0'),
|
||||
}, {
|
||||
'name': '--vaapi-drm',
|
||||
'desc': 'VAAPI (DRM/EGL support)',
|
||||
'deps': [ 'vaapi', 'egl-drm' ],
|
||||
'deps': 'vaapi && egl-drm',
|
||||
'func': check_pkg_config('libva-drm', '>= 0.36.0'),
|
||||
}, {
|
||||
'name': '--vaapi-glx',
|
||||
'desc': 'VAAPI GLX',
|
||||
'deps': [ 'vaapi-x11', 'gl-x11' ],
|
||||
'deps': 'vaapi-x11 && gl-x11',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--vaapi-x-egl',
|
||||
'desc': 'VAAPI EGL on X11',
|
||||
'deps': [ 'vaapi-x11', 'egl-x11' ],
|
||||
'deps': 'vaapi-x11 && egl-x11',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': 'vaapi-egl',
|
||||
'desc': 'VAAPI EGL',
|
||||
'deps_any': [ 'vaapi-x-egl', 'vaapi-wayland' ],
|
||||
'deps': 'vaapi-x-egl || vaapi-wayland',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--caca',
|
||||
|
@ -725,7 +718,7 @@ video_output_features = [
|
|||
}, {
|
||||
'name': '--direct3d',
|
||||
'desc': 'Direct3D support',
|
||||
'deps': [ 'win32-desktop' ],
|
||||
'deps': 'win32-desktop',
|
||||
'func': check_cc(header_name='d3d9.h'),
|
||||
}, {
|
||||
# We need MMAL/bcm_host/dispmanx APIs. Also, most RPI distros require
|
||||
|
@ -754,12 +747,12 @@ video_output_features = [
|
|||
} , {
|
||||
'name': '--plain-gl',
|
||||
'desc': 'OpenGL without platform-specific code (e.g. for libmpv)',
|
||||
'deps_any': [ 'libmpv-shared', 'libmpv-static' ],
|
||||
'deps': 'libmpv-shared || libmpv-static',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--mali-fbdev',
|
||||
'desc': 'MALI via Linux fbdev',
|
||||
'deps': ['libdl'],
|
||||
'deps': 'libdl',
|
||||
'func': compose_checks(
|
||||
check_cc(lib="EGL"),
|
||||
check_statement('EGL/fbdev_window.h', 'struct fbdev_window test'),
|
||||
|
@ -768,9 +761,9 @@ video_output_features = [
|
|||
}, {
|
||||
'name': '--gl',
|
||||
'desc': 'OpenGL video outputs',
|
||||
'deps_any': [ 'gl-cocoa', 'gl-x11', 'egl-x11', 'egl-drm',
|
||||
'gl-win32', 'gl-wayland', 'rpi', 'mali-fbdev',
|
||||
'plain-gl' ],
|
||||
'deps': 'gl-cocoa || gl-x11 || egl-x11 || egl-drm || '
|
||||
+ 'gl-win32 || gl-wayland || rpi || mali-fbdev || '
|
||||
+ 'plain-gl',
|
||||
'func': check_true,
|
||||
'req': True,
|
||||
'fmsg': "No OpenGL video output found or enabled. " +
|
||||
|
@ -779,8 +772,8 @@ video_output_features = [
|
|||
}, {
|
||||
'name': 'egl-helpers',
|
||||
'desc': 'EGL helper functions',
|
||||
'deps_any': [ 'egl-x11', 'mali-fbdev', 'rpi', 'gl-wayland', 'egl-drm',
|
||||
'egl-angle-win32' ],
|
||||
'deps': 'egl-x11 || mali-fbdev || rpi || gl-wayland || egl-drm || ' +
|
||||
'egl-angle-win32',
|
||||
'func': check_true
|
||||
}
|
||||
]
|
||||
|
@ -789,7 +782,7 @@ hwaccel_features = [
|
|||
{
|
||||
'name': '--vaapi-hwaccel',
|
||||
'desc': 'libavcodec VAAPI hwaccel (FFmpeg 3.3 API)',
|
||||
'deps': [ 'vaapi' ],
|
||||
'deps': 'vaapi',
|
||||
'func': check_statement('libavcodec/version.h',
|
||||
'int x[(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 26, 0) && '
|
||||
' LIBAVCODEC_VERSION_MICRO < 100) ||'
|
||||
|
@ -800,7 +793,7 @@ hwaccel_features = [
|
|||
}, {
|
||||
'name': '--videotoolbox-hwaccel-new',
|
||||
'desc': 'libavcodec videotoolbox hwaccel (new API)',
|
||||
'deps_any': [ 'gl-cocoa', 'ios-gl' ],
|
||||
'deps': 'gl-cocoa || ios-gl',
|
||||
'func': check_statement('libavcodec/version.h',
|
||||
'int x[(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 96, 100) && '
|
||||
' LIBAVCODEC_VERSION_MICRO >= 100)'
|
||||
|
@ -809,8 +802,7 @@ hwaccel_features = [
|
|||
}, {
|
||||
'name': '--videotoolbox-hwaccel-old',
|
||||
'desc': 'libavcodec videotoolbox hwaccel (old API)',
|
||||
'deps_any': [ 'gl-cocoa', 'ios-gl' ],
|
||||
'deps_neg': [ 'videotoolbox-hwaccel-new' ],
|
||||
'deps': '(gl-cocoa || ios-gl) && !videotoolbox-hwaccel-new',
|
||||
'func': compose_checks(
|
||||
check_headers('VideoToolbox/VideoToolbox.h'),
|
||||
check_statement('libavcodec/videotoolbox.h',
|
||||
|
@ -819,17 +811,17 @@ hwaccel_features = [
|
|||
}, {
|
||||
'name': 'videotoolbox-hwaccel',
|
||||
'desc': 'libavcodec videotoolbox hwaccel',
|
||||
'deps_any': [ 'videotoolbox-hwaccel-new', 'videotoolbox-hwaccel-old' ],
|
||||
'deps': 'videotoolbox-hwaccel-new || videotoolbox-hwaccel-old',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--videotoolbox-gl',
|
||||
'desc': 'Videotoolbox with OpenGL',
|
||||
'deps': [ 'gl-cocoa', 'videotoolbox-hwaccel' ],
|
||||
'deps': 'gl-cocoa && videotoolbox-hwaccel',
|
||||
'func': check_true
|
||||
}, {
|
||||
'name': '--vdpau-hwaccel',
|
||||
'desc': 'libavcodec VDPAU hwaccel (FFmpeg 3.3 API)',
|
||||
'deps': [ 'vdpau' ],
|
||||
'deps': 'vdpau',
|
||||
'func': check_statement('libavcodec/version.h',
|
||||
'int x[(LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 37, 1) && '
|
||||
' LIBAVCODEC_VERSION_MICRO < 100) ||'
|
||||
|
@ -841,7 +833,7 @@ hwaccel_features = [
|
|||
# (conflated with ANGLE for easier deps)
|
||||
'name': '--d3d-hwaccel',
|
||||
'desc': 'D3D11VA hwaccel (plus ANGLE)',
|
||||
'deps': [ 'os-win32', 'egl-angle' ],
|
||||
'deps': 'os-win32 && egl-angle',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--d3d-hwaccel-new',
|
||||
|
@ -853,29 +845,28 @@ hwaccel_features = [
|
|||
' LIBAVCODEC_VERSION_MICRO >= 100)'
|
||||
' ? 1 : -1]',
|
||||
use='libav'),
|
||||
'deps': [ 'd3d-hwaccel' ],
|
||||
'deps': 'd3d-hwaccel',
|
||||
}, {
|
||||
'name': '--d3d9-hwaccel',
|
||||
'desc': 'DXVA2 hwaccel (plus ANGLE)',
|
||||
'deps': [ 'd3d-hwaccel', 'egl-angle-win32' ],
|
||||
'deps': 'd3d-hwaccel && egl-angle-win32',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--gl-dxinterop-d3d9',
|
||||
'desc': 'OpenGL/DirectX Interop Backend DXVA2 interop',
|
||||
'deps': [ 'gl-dxinterop', 'd3d9-hwaccel' ],
|
||||
'deps': 'gl-dxinterop && d3d9-hwaccel',
|
||||
'groups': [ 'gl' ],
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--cuda-hwaccel',
|
||||
'desc': 'CUDA hwaccel',
|
||||
'deps': [ 'gl' ],
|
||||
'deps': 'gl',
|
||||
'func': check_cc(fragment=load_fragment('cuda.c'),
|
||||
use='libav'),
|
||||
}, {
|
||||
'name': 'sse4-intrinsics',
|
||||
'desc': 'GCC SSE4 intrinsics for GPU memcpy',
|
||||
'deps_any': [ 'd3d-hwaccel' ],
|
||||
'deps_neg': [ 'd3d-hwaccel-new' ],
|
||||
'deps': 'd3d-hwaccel && !d3d-hwaccel-new',
|
||||
'func': check_cc(fragment=load_fragment('sse.c')),
|
||||
}
|
||||
]
|
||||
|
@ -890,28 +881,26 @@ radio_and_tv_features = [
|
|||
'name': 'sys_videoio_h',
|
||||
'desc': 'videoio.h',
|
||||
'func': check_cc(header_name=['sys/time.h', 'sys/videoio.h']),
|
||||
'deps': [ 'tv' ],
|
||||
'deps': 'tv',
|
||||
}, {
|
||||
'name': 'videodev',
|
||||
'desc': 'videodev2.h',
|
||||
'func': check_cc(header_name=['sys/time.h', 'linux/videodev2.h']),
|
||||
'deps': [ 'tv' ],
|
||||
'deps_neg': [ 'sys_videoio_h' ],
|
||||
'deps': 'tv && !sys_videoio_h',
|
||||
}, {
|
||||
'name': '--tv-v4l2',
|
||||
'desc': 'Video4Linux2 TV interface',
|
||||
'deps': [ 'tv' ],
|
||||
'deps_any': [ 'sys_videoio_h', 'videodev' ],
|
||||
'deps': 'tv && (sys_videoio_h || videodev)',
|
||||
'func': check_true,
|
||||
}, {
|
||||
'name': '--libv4l2',
|
||||
'desc': 'libv4l2 support',
|
||||
'func': check_pkg_config('libv4l2'),
|
||||
'deps': [ 'tv-v4l2' ],
|
||||
'deps': 'tv-v4l2',
|
||||
}, {
|
||||
'name': '--audio-input',
|
||||
'desc': 'audio input support',
|
||||
'deps_any': [ 'tv-v4l2' ],
|
||||
'deps': 'tv-v4l2',
|
||||
'func': check_true
|
||||
} , {
|
||||
'name': '--dvbin',
|
||||
|
@ -925,17 +914,17 @@ standalone_features = [
|
|||
{
|
||||
'name': 'win32-executable',
|
||||
'desc': 'w32 executable',
|
||||
'deps_any': [ 'os-win32', 'os-cygwin'],
|
||||
'deps': 'os-win32 || !(!(os-cygwin))',
|
||||
'func': check_ctx_vars('WINDRES')
|
||||
}, {
|
||||
'name': '--apple-remote',
|
||||
'desc': 'Apple Remote support',
|
||||
'deps': [ 'cocoa' ],
|
||||
'deps': 'cocoa',
|
||||
'func': check_true
|
||||
}, {
|
||||
'name': '--macos-touchbar',
|
||||
'desc': 'macOS Touch Bar support',
|
||||
'deps': [ 'cocoa' ],
|
||||
'deps': 'cocoa',
|
||||
'func': check_cc(
|
||||
fragment=load_fragment('touchbar.m'),
|
||||
framework_name=['AppKit'],
|
||||
|
|
Loading…
Reference in New Issue