switch the build system to waf

This commit adds a new build system based on waf. configure and Makefile
are deprecated effective immediately and someday in the future they will be
removed (they are still available by running ./old-configure).

You can find how the choice for waf came to be in `DOCS/waf-buildsystem.rst`.
TL;DR: we couldn't get the same level of abstraction and customization with
other build systems we tried (CMake and autotools).

For guidance on how to build the software now, take a look at README.md
and the cross compilation guide.

CREDITS:
This is a squash of ~250 commits. Some of them are not by me, so here is the
deserved attribution:

 - @wm4 contributed some Windows fixes, renamed configure to old-configure
   and contributed to the bootstrap script. Also, GNU/Linux testing.
 - @lachs0r contributed some Windows fixes and the bootstrap script.
 - @Nikoli contributed a lot of testing and discovered many bugs.
 - @CrimsonVoid contributed changes to the bootstrap script.
This commit is contained in:
Stefano Pigozzi 2013-07-16 13:28:28 +02:00
parent 0cb9227a73
commit 7e2edad8ef
49 changed files with 2480 additions and 119 deletions

6
.gitignore vendored
View File

@ -2,6 +2,7 @@
*.a
*.d
*.exe
*.pyc
.depend
/config.h
@ -25,3 +26,8 @@
/DOCS/man/*/mpv.out
/DOCS/man/*/mpv.pdf
/DOCS/man/*/mpv.toc
/waf
/build
/.waf*
/.lock-waf_*

View File

@ -13,7 +13,10 @@ branches:
- ci
before_install: ./travis-deps libass-stable $LIBAV
script: ./configure && make
script:
- ./bootstrap.py
- ./waf configure
- ./waf build
notifications-policy: &notifications-policy
on_success: change

View File

@ -3,7 +3,7 @@ produce both 32 bit and 64 bit executables. MinGW-w64 is available from
http://mingw-w64.sourceforge.net.
You have to run mpv's configure with these arguments:
./configure --enable-cross-compile --target=i686-w64-mingw32
DEST_OS=win32 TARGET=i686-w64-mingw32 ./waf configure
Using mingw-w64-cmake to setup a MinGW-w64 environment is recommended (this will
also build mpv and its dependencies): https://github.com/lachs0r/mingw-w64-cmake
@ -44,8 +44,8 @@ make pthreads
git clone https://github.com/mpv-player/mpv.git
cd mpv
export PATH=/opt/mingw/usr/bin/:$PATH
./configure --enable-cross-compile --target=i686-w64-mingw32
make
DEST_OS=win32 TARGET=i686-w64-mingw32 ./waf configure
./waf build
# This should work. Note however that MXEs ffmpeg package might be very old
# in order to avoid breaking e.g. xine-lib, so you might want to update that

View File

@ -10,7 +10,6 @@ latex-preamble: \usepackage[usenames,dvipsnames]{xcolor}
\makeatletter
\renewcommand{\maketitle}{
\begin{center}
\includegraphics{etc/mpv-icon-8bit-64x64.png}\\
\vspace*{-1.5em}
\begin{Huge}
\@title

151
DOCS/waf-buildsystem.rst Normal file
View File

@ -0,0 +1,151 @@
waf build system overview
=========================
mpv's new build system is based on waf and it should completly replace the
custom ./configure + Makefile based system inherited from MPlayer.
Goals and the choice of waf
===========================
The new system comes with some goals, which can be summed up as: be as good as
the old one at what it did well (customizability) and fix some of it's major
shortcomings:
1) The build system must be uniform in how it handles any single feature check.
Repetition and boilerplate have to be avoided.
When adding a new feature using the old configure, one had to add a fair
amount of code to the shell script to do option parsing, detection of the
feature and declaration of variables for the Makefile to pickup. The worst
part is this pieces are spread apart in the configure and copy pasted for
any single case. That brings us to..
2) --enable-feature has to override the user and help him understand that he
has libraries missing and should install them for the feature to be enabled.
3) Must be customizable, hackable, pleasant to the developer eyes and to work
with in general.
4) Must have separate configuration and build steps.
Goal 2 comes as a given on pretty much any build system, since autotools made
this behaviour very popular among users (and rightly so).
Goal 1+3 were somewhat harder to accomplish as it looks like all of the build
systems we evaluated (waf included!) had problems with them. For reference we
had proof of concept build systems with waf, CMake and autotools.
What puts waf apart from CMake and autotools, is that projects using it use
Python to program their build system. Also while the Waf Book shows really
simple API usages, you can write your own build system on top of waf that is
tailored to the project's specific needs.
mpv's custom configure step on top of waf
=========================================
To some extents mpv has a custom build system written on top of waf. This
document will not go over the standard waf behaviour as that is documented in
the ``Waf book``.
All of the configuration process is handled with a declarative approach. Lists
of dictionaries define the checks, and some custom Python code traverses these
lists and depending on the check definition it calls into the actual waf API.
A simple example using pkg-config would be::
{
'name': '--vdpau',
'desc': 'VDPAU acceleration',
'deps': [ 'x11' ],
'func': check_pkg_config('vdpau', '>= 0.2'),
}
This defines a feature called ``vdpau`` which can be enabled or disabled by
the users with configure flags (that's the meaning of ``--``). This feature
depends on another feature whose name is ``x11``, and the autodetection check
consists of running ``pkg-config`` and looking for ``vdpau`` with version
``>= 0.2``. If the check succeds a ``#define HAVE_VDPAU 1`` will be added to
``config.h``, if not ``#define HAVE_VDPAU 0`` will be added.
The defines names are automatically prepended with ``HAVE_``, capitalized and
special characters are replaced with underscores. This happens in
``waftools/inflectors.py``.
Mandatory fields:
-----------------
``name``: indicates the unique identifier used by the custom dependency code
to refer to a feature. If the unique identifier is prepended with ``--``
the build system will also generate options for ``./waf configure`` so that
the feature can be enabled and disabled.
``desc``: this is the textual representation of the feature used in the
interactions with the users.
``func``: function that will perform the check. These functions are defined in
``waftools/checks``. The reusable checks are all functions that return
functions. The return functions will then be applied using waf's configuration
context.
The source code for the reusable checks is a bit convoluted, but it should be
easy to pick up their usage from the ``wscript``. Their signature mirrors
the semantics of some of the shell functions used in mplayer.
If someone expresses some interest, I will extend this document with official
documentation for each check function.
Optional fields
---------------
``deps``: list of dependencies of this feature. It is a list of names of
other features as defined in the ``name`` field (minus the eventual leading
``--``). All of the dependencies must be satisfied. If they are not the check
will be skipped without even running ``func``.
``deps_any``: like deps but it is satisfied even if only one of the dependencies
is satisfied. You can think of ``deps`` as a 'and' condition and ``deps_any``
as a 'or' condition.
``deps_neg``: like deps but it is satisfied when none of the dependencies is
satisfied.
``req``: defaults to False. If set to True makes this feature a hard
dependency of mpv (configuration will fail if autodetection fails). If set to
True you must also provide ``fmsg``.
``fmsg``: string with the failure message in case a required dependency is not
satisfied.
``os_specific_checks``: this takes a dictionary that has ``os-`` dependencies
as keys (such as ``os-win32``), and by values has another dictionary that is
merged on top of the current feature definition only for that specific OS.
For example::
{
'name': '--pthreads',
'desc': 'POSIX threads',
'func': check_pthreads,
'os_specific_checks': {
'os-win32': {
'func': check_pthreads_w32_static.
}
}
}
will override the value of ``func`` with ``check_pthreads_w32_static`` only
if the target OS of the build is Windows.
mpv's custom build step on top of waf
=====================================
Build step is pretty much vanilla waf. The only difference being that the list
of source files can contain both strings or tuples. If a tuple is found,
the second element in the tuple will the used to match the features detected
in the configure step (the ``name`` field described above). If this feature
was not enabled during configure, the source file will not be compiled in.
All of the custom Python for this is inside the function ``filtered_sources``
contained in the file ``waftools/dependencies.py``.
Also ``dependencies_use`` and ``dependencies_includes`` collect cflags and
ldflags that were generated from the features checks in the configure step.

View File

@ -16,12 +16,22 @@ Compilation
-----------
Compiling with full features requires development files for several
external libraries. Below is a list of some important requirements. For
more information see the output of `./configure --help` for a list of options,
or look at the list of enabled and disabled features printed after running
`./configure`. If you think you have support for some feature installed
but configure fails to detect it, the file `config.log` may contain
information about the reasons for the failure.
external libraries. Below is a list of some important requirements.
The mpv build system uses *waf* but we don't store it in your source tree. The
script './bootstrap.py' will download the latest version of waf that was tested
with the build system.
For a list of the available build options use `./waf configure --help`. If
you think you have support for some feature installed but configure fails to
detect it, the file `build/config.log` may contain information about the
reasons for the failure.
To build the software you can use `./waf build`, and `./waf install` to install
it.
NOTE: Using the old build system (with `./old-configure`) should still work,
but will be removed in a future version of mpv.
Essential dependencies (incomplete list):
@ -47,22 +57,6 @@ If you are running Mac OSX and using homebrew we provide [homebrew-mpv][homebrew
to date formula that compiles mpv with sensible dependencies and defaults for
OSX.
### configure `--enable-*` parameters
The `--enable-*` parameters unconditionally force options on, completely
skipping autodetection. This behavior is unlike what you may be used to from
autoconf-based configure scripts that can decide to override you. This greater
level of control comes at a price. You may have to provide the correct compiler
and linker flags yourself.
If you used one of these options and experience a compilation or
linking failure, make sure you have passed the necessary compiler/linker flags
to configure.
mpv's configure script is greedy and automatically enables features as a result
of autodetection. The cases where you may want to use `--enable-*` are very
limited.
FFmpeg vs. Libav
----------------

View File

@ -30,24 +30,28 @@ def user_dylib_lst(input_file):
return [lib for lib in dylib_lst(input_file).split("\n") if
is_user_lib(lib, input_file)]
def bundle_name(binary_name):
def bundle_path(binary_name):
return "%s.app" % binary_name
def bundle_name(binary_name):
return os.path.basename(bundle_path(binary_name))
def target_plist(binary_name):
return os.path.join(bundle_name(binary_name), 'Contents', 'Info.plist')
return os.path.join(bundle_path(binary_name), 'Contents', 'Info.plist')
def target_directory(binary_name):
return os.path.join(bundle_name(binary_name), 'Contents', 'MacOS')
return os.path.join(bundle_path(binary_name), 'Contents', 'MacOS')
def target_binary(binary_name):
return os.path.join(target_directory(binary_name), binary_name)
return os.path.join(target_directory(binary_name),
os.path.basename(binary_name))
def copy_bundle(binary_name):
if os.path.isdir(bundle_name(binary_name)):
shutil.rmtree(bundle_name(binary_name))
if os.path.isdir(bundle_path(binary_name)):
shutil.rmtree(bundle_path(binary_name))
shutil.copytree(
os.path.join('TOOLS', 'osxbundle', bundle_name(binary_name)),
bundle_name(binary_name))
bundle_path(binary_name))
def copy_binary(binary_name):
shutil.copy(binary_name, target_binary(binary_name))
@ -91,7 +95,7 @@ def fix_dylibs_paths(target_file, dest_dir, root=True):
fix_dylibs_paths(dylib_dest_path, dest_dir, False)
def apply_plist_template(plist_file, version):
sh("sed -i -e 's/{{VERSION}}/%s/g' %s" % (version, plist_file))
sh("sed -i -e 's/${VERSION}/%s/g' %s" % (version, plist_file))
def bundle_dependencies(binary_name):
lib_bundle_directory = os.path.join(target_directory(binary_name), "lib")

View File

@ -183,7 +183,7 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>{{VERSION}}</string>
<string>${VERSION}</string>
<key>NSHighResolutionCapable</key>
<true/>
<key>CFBundleURLTypes</key>

28
bootstrap.py Executable file
View File

@ -0,0 +1,28 @@
#!/usr/bin/env python
# This script simply downloads waf to the current directory
from __future__ import print_function
import os, sys, stat, hashlib
try:
from urllib.request import urlopen
except:
from urllib2 import urlopen
WAFRELEASE = "waf-1.7.13"
SHA256HASH = "03cc750049350ee01cdbc584b70924e333fcc17ba4a2d04648dab1535538a873"
waf = urlopen("https://waf.googlecode.com/files/" + WAFRELEASE).read()
if SHA256HASH == hashlib.sha256(waf).hexdigest():
with open("waf", "wb") as wf:
wf.write(waf)
os.chmod("waf", os.stat("waf").st_mode | stat.S_IXUSR)
print("Checksum verified.")
else:
print("The checksum of the downloaded file does not match!")
print("Please download and verify the file manually.")
sys.exit(1)

View File

@ -1722,56 +1722,10 @@ fi
echores "$_wayland"
unset _wlver
echocheck "X11 headers presence"
_x11_headers="no"
res_comment="check if the dev(el) packages are installed"
for I in $(echo $extra_cflags | sed s/-I//g) /usr/include ; do
if test -f "$I/X11/Xlib.h" ; then
_x11_headers="yes"
res_comment=""
break
fi
done
if test $_cross_compile = no; then
for I in /usr/X11/include /usr/X11R7/include /usr/local/include /usr/X11R6/include \
/usr/include/X11R6 /usr/openwin/include ; do
if test -f "$I/X11/Xlib.h" ; then
extra_cflags="$extra_cflags -I$I"
_x11_headers="yes"
res_comment="using $I"
break
fi
done
fi
echores "$_x11_headers"
echocheck "X11"
if test "$_x11" = auto && test "$_x11_headers" = yes ; then
for I in "" -L/usr/X11R7/lib -L/usr/local/lib -L/usr/X11R6/lib -L/usr/lib/X11R6 \
-L/usr/X11/lib -L/usr/lib32 -L/usr/openwin/lib -L/usr/local/lib64 -L/usr/X11R6/lib64 \
-L/usr/lib ; do
if netbsd; then
_ld_tmp="$I -lXext -lX11 $_ld_pthread -Wl,-R$(echo $I | sed s/^-L//)"
else
_ld_tmp="$I -lXext -lX11 $_ld_pthread"
fi
statement_check_broken X11/Xutil.h X11/XKBlib.h 'XCreateWindow(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)' $_ld_tmp &&
_x11=yes
# Check that there aren't conflicting headers between ApplicationServices
# and X11. On versions of Mac OSX prior to 10.7 the deprecated QuickDraw API
# is included by -framework ApplicationServices and clashes with the X11
# definition of the "Cursor" type.
if darwin && depends_on_application_services && test "$_x11" = yes ; then
_x11=no
header_check_broken ApplicationServices/ApplicationServices.h \
X11/Xutil.h $_ld_tmp && _x11=yes
fi
if test "$_x11" = yes ; then
libs_mplayer="$libs_mplayer $_ld_tmp"
break
fi
done
if test "$_x11" = auto ; then
_x11="no"
pkg_config_add "x11" && _x11="yes"
fi
if test "$_x11" = yes ; then
def_x11='#define HAVE_X11 1'
@ -1797,36 +1751,19 @@ else
fi
echores "$_xss"
echocheck "DPMS"
_xdpms3=no
_xdpms4=no
echocheck "X extensions"
_xext=no
if test "$_x11" = yes ; then
cat > $TMPC <<EOF
#include <X11/Xmd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <X11/Xatom.h>
#include <X11/extensions/dpms.h>
int main(void) { DPMSQueryExtension(0, 0, 0); return 0; }
EOF
cc_check -lXdpms && _xdpms3=yes
statement_check_broken X11/Xlib.h X11/extensions/dpms.h 'DPMSQueryExtension(0, 0, 0)' -lXext && _xdpms4=yes
pkg_config_add "xext" && _xext="yes"
fi
if test "$_xdpms4" = yes ; then
def_xdpms='#define HAVE_XDPMS 1'
res_comment="using Xdpms 4"
echores "yes"
elif test "$_xdpms3" = yes ; then
def_xdpms='#define HAVE_XDPMS 1'
libs_mplayer="$libs_mplayer -lXdpms"
res_comment="using Xdpms 3"
if test "$_xext" = yes ; then
def_xext='#define HAVE_XEXT 1'
echores "yes"
else
def_xdpms='#define HAVE_XDPMS 0'
def_xext='#define HAVE_XEXT 0'
echores "no"
fi
echocheck "Xv"
if test "$_xv" = auto && test "$_x11" = yes ; then
_xv=no
@ -3232,10 +3169,22 @@ CXXFLAGS=" $CFLAGS -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMI
# DO NOT ADD ANY TESTS THAT USE LINKER FLAGS HERE (like cc_check).
# This is done so waf builds won't conflict with this. In fact, waf and old
# build system can coexist in parallel, at the same time. This is because
# waf always does out-of-tree builds, while this build system does always
# in-tree builds.
if test ! -f Makefile ; then
ln -s old-makefile Makefile
fi
rm -rf old_build
mkdir old_build
BUILDCFLAGS="-Iold_build"
#############################################################################
echo "Creating config.mak"
cat > config.mak << EOF
cat > old_build/config.mak << EOF
# -------- Generated by configure -----------
# Ensure that locale settings do not interfere with shell commands.
@ -3254,8 +3203,8 @@ CXX = $_cc
INSTALL = $_install
WINDRES = $_windres
CFLAGS = $WARNFLAGS $ERRORFLAGS $WARN_CFLAGS $CFLAGS $extra_cflags
CXXFLAGS = $WARNFLAGS $ERRORFLAGS $CXXFLAGS $extra_cflags $extra_cxxflags
CFLAGS = $BUILDCFLAGS $WARNFLAGS $ERRORFLAGS $WARN_CFLAGS $CFLAGS $extra_cflags
CXXFLAGS = $BUILDCFLAGS $WARNFLAGS $ERRORFLAGS $CXXFLAGS $extra_cflags $extra_cxxflags
DEPFLAGS = $DEPFLAGS
EXTRALIBS = $extra_ldflags $_ld_static $_ld_lm $extra_libs $libs_mplayer $end_ldflags
@ -3530,7 +3479,7 @@ $def_vaapi_hwaccel
$def_vm
$def_x11
$def_wayland
$def_xdpms
$def_xext
$def_xf86keysym
$def_xinerama
$def_xss
@ -3555,7 +3504,7 @@ $def_pthreads
EOF
# Do not overwrite an unchanged config.h to avoid superfluous rebuilds.
cmp -s "$TMPH" config.h || mv -f "$TMPH" config.h
cmp -s "$TMPH" old_build/config.h || mv -f "$TMPH" old_build/config.h
#############################################################################
@ -3601,6 +3550,10 @@ If you used one of these options and experience a compilation or
linking failure, make sure you have passed the necessary compiler/linker flags
to configure.
WARNING: The ./old-configure + make build system you are using is deprecated in
favour of waf and will be removed in a future version of mpv. Check the
README for instructions on how to build mpv with the new build system.
EOF
if test "$warn_cflags" = yes; then

View File

@ -19,7 +19,7 @@
# with MPlayer; if not, write to the Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
include config.mak
include old_build/config.mak
###### variable declarations #######
@ -535,7 +535,8 @@ clean:
-$(RM) mpvcore/player/lua/osc.inc
distclean: clean
-$(RM) config.log config.mak config.h TAGS tags
-$(RM) config.log old_build/config.h old_build/config.mak Makefile config.mak config.h TAGS tags
-rmdir old_build/
TAGS:
$(RM) $@; find . -name '*.[chS]' -o -name '*.asm' | xargs etags -a

View File

@ -73,7 +73,6 @@ static keycode_map getch2_keys;
#if HAVE_TERMINFO || HAVE_TERMCAP
static char *term_rmkx = NULL;
static char *term_smkx = NULL;

View File

@ -50,7 +50,7 @@
#include <X11/extensions/scrnsaver.h>
#endif
#if HAVE_XDPMS
#if HAVE_XEXT
#include <X11/extensions/dpms.h>
#endif
@ -1552,7 +1552,7 @@ static void saver_on(struct vo_x11_state *x11)
x11->screensaver_off = 0;
if (xss_suspend(mDisplay, False))
return;
#if HAVE_XDPMS
#if HAVE_XEXT
if (x11->dpms_disabled) {
int nothing;
if (DPMSQueryExtension(mDisplay, &nothing, &nothing)) {
@ -1587,7 +1587,7 @@ static void saver_off(struct vo_x11_state *x11)
x11->screensaver_off = 1;
if (xss_suspend(mDisplay, True))
return;
#if HAVE_XDPMS
#if HAVE_XEXT
if (DPMSQueryExtension(mDisplay, &nothing, &nothing)) {
BOOL onoff;
CARD16 state;

2
waftools/__init__.py Normal file
View File

@ -0,0 +1,2 @@
#!/usr/bin/env python
# encoding: utf-8

View File

119
waftools/checks/custom.py Normal file
View File

@ -0,0 +1,119 @@
from waftools.checks.generic import *
__all__ = ["check_pthreads", "check_iconv", "check_lua", "check_oss"]
pthreads_program = load_fragment('pthreads.c')
def check_pthreads(ctx, dependency_identifier):
platform_cflags = {
'linux': '-D_REENTRANT',
'freebsd': '-D_THREAD_SAFE',
'netbsd': '-D_THREAD_SAFE',
'openbsd': '-D_THREAD_SAFE',
'win32': '-DPTW32_STATIC_LIB',
}.get(ctx.env.DEST_OS, '')
libs = ['pthreadGC2', 'pthread']
checkfn = check_cc(fragment=pthreads_program, cflags=platform_cflags)
return check_libs(libs, checkfn)(ctx, dependency_identifier)
def check_iconv(ctx, dependency_identifier):
iconv_program = load_fragment('iconv.c')
libdliconv = " ".join(ctx.env.LIB_LIBDL + ['iconv'])
libs = ['iconv', libdliconv]
checkfn = check_cc(fragment=iconv_program)
return check_libs(libs, checkfn)(ctx, dependency_identifier)
def check_lua(ctx, dependency_identifier):
if 'libquvi4' in ctx.env.satisfied_deps:
additional_lua_test_header = '#include <quvi/quvi.h>'
additional_lua_test_code = load_fragment('lua_libquvi4.c')
elif 'libquvi9' in ctx.env.satisfied_deps:
additional_lua_test_header = '#include <quvi.h>'
additional_lua_test_code = load_fragment('lua_libquvi9.c')
else:
additional_lua_test_header = ''
additional_lua_test_code = ''
fragment = load_fragment('lua.c').format(
additional_lua_test_header='',
additional_lua_test_code='')
lua_versions = [
( '51', 'lua >= 5.1.0 lua < 5.2.0'),
( '51deb', 'lua5.1 >= 5.1.0'), # debian
( 'luajit', 'luajit >= 2.0.0' ),
# assume all our dependencies (libquvi in particular) link with 5.1
( '52', 'lua >= 5.2.0' ),
( '52deb', 'lua5.2 >= 5.2.0'), # debian
]
if ctx.options.LUA_VER:
lua_versions = \
[lv for lv in lua_versions if lv[0] == ctx.options.LUA_VER]
for lua_version, pkgconfig_query in lua_versions:
if compose_checks(
check_pkg_config(pkgconfig_query, uselib_store=lua_version),
check_cc(fragment=fragment, use=lua_version))\
(ctx, dependency_identifier):
# XXX: this is a bit of a hack, ask waf developers if I can copy
# the uselib_store to 'lua'
ctx.mark_satisfied(lua_version)
ctx.add_optional_message(dependency_identifier,
'version found: ' + lua_version)
return True
return False
# from here on there is the OSS check.. just stop reading here unless you want
# to die inside a little
def __fail_oss_check__(ctx):
ctx.define('PATH_DEV_DSP', '')
ctx.define('PATH_DEV_MIXER', '')
return False
def __get_osslibdir__():
try:
cmd = ['sh', '-c', "'source /etc/oss.conf && echo $OSSLIBDIR'"]
p = Utils.subprocess.Popen(cmd, stdin=Utils.subprocess.PIPE,
stdout=Utils.subprocess.PIPE,
stderr=Utils.subprocess.PIPE)
return p.communicate()[0]
except Exception:
return ""
def __check_oss_headers__(ctx, dependency_identifier):
import os
real_oss = ctx.check_cc(fragment=load_fragment('oss_audio_header.c'),
use='soundcard')
if real_oss:
if os.path.exists('/etc/oss.conf'):
osslibdir = __get_osslibdir__()
ossincdir = os.path.join(osslibdir, 'include')
soundcard_h = os.path.join(ossincdir, 'sys', 'soundcard.h')
if os.path.exists(soundcard_h):
ctx.env.CFLAGS.append('-I{0}'.format(ossincdir))
return True
def __check_oss_bsd__(ctxdependency_identifier):
# add the oss audio library through a check
ctx.define('PATH_DEV_DSP', '/dev/sound')
if check_cc(lib='ossaudio')(ctx, dependency_identifier):
return True
else:
return __fail_oss_check__(ctx)
def check_oss(ctx, dependency_identifier):
func = check_cc(fragment=load_fragment('oss_audio.c'), use='soundcard')
if func(ctx, dependency_identifier):
ctx.define('PATH_DEV_DSP', '/dev/dsp')
ctx.define('PATH_DEV_MIXER', '/dev/mixer')
if ctx.env.DEST_OS in ['openbsd', 'netbsd']:
return __check_oss_bsd_library__(ctx, dependency_identifier)
else:
return __check_oss_headers__(ctx, dependency_identifier)
return __fail_oss_check__(ctx)

134
waftools/checks/generic.py Normal file
View File

@ -0,0 +1,134 @@
import os
from inflectors import DependencyInflector
__all__ = [
"check_pkg_config", "check_cc", "check_statement", "check_libs",
"check_headers", "compose_checks", "check_true", "any_version",
"load_fragment", "check_stub", "check_ctx_vars"]
any_version = None
def even(n):
return n % 2 == 0
def __define_options__(dependency_identifier):
return DependencyInflector(dependency_identifier).define_dict()
def __merge_options__(dependency_identifier, *args):
options_accu = DependencyInflector(dependency_identifier).storage_dict()
options_accu['mandatory'] = False
[options_accu.update(arg) for arg in args if arg]
return options_accu
def check_libs(libs, function):
libs = [None] + libs
def fn(ctx, dependency_identifier):
for lib in libs:
kwargs = lib and {'lib': lib} or {}
if function(ctx, dependency_identifier, **kwargs):
return True
return False
return fn
def check_statement(header, statement, **kw_ext):
def fn(ctx, dependency_identifier, **kw):
fragment = """
#include <{0}>
int main(int argc, char **argv)
{{ {1}; return 0; }} """.format(header, statement)
opts = __merge_options__(dependency_identifier,
{'fragment':fragment},
__define_options__(dependency_identifier),
kw_ext, kw)
return ctx.check_cc(**opts)
return fn
def check_cc(**kw_ext):
def fn(ctx, dependency_identifier, **kw):
options = __merge_options__(dependency_identifier,
__define_options__(dependency_identifier),
kw_ext, kw)
return ctx.check_cc(**options)
return fn
def check_pkg_config(*args, **kw_ext):
def fn(ctx, dependency_identifier, **kw):
argsl = list(args)
packages = [el for (i, el) in enumerate(args) if even(i)]
sargs = [i for i in args if i] # remove None
pkgc_args = ["--libs", "--cflags"]
if ctx.dependency_satisfied('static-build'):
pkgc_args += ["--static"]
defaults = {
'path': ctx.env.PKG_CONFIG,
'package': " ".join(packages),
'args': sargs + pkgc_args }
opts = __merge_options__(dependency_identifier, defaults, kw_ext, kw)
if ctx.check_cfg(**opts):
return True
else:
defkey = DependencyInflector(dependency_identifier).define_key()
ctx.undefine(defkey)
return False
return fn
def check_headers(*headers):
def undef_others(ctx, headers, found):
not_found_hs = set(headers) - set([found])
for not_found_h in not_found_hs:
defkey = DependencyInflector(not_found_h).define_key()
ctx.undefine(defkey)
def fn(ctx, dependency_identifier):
for header in headers:
defaults = {'header_name': header, 'features': 'c cprogram'}
options = __merge_options__(dependency_identifier, defaults)
if ctx.check(**options):
undef_others(ctx, headers, header)
defkey = DependencyInflector(dependency_identifier).define_key()
ctx.define(defkey, 1)
return True
undef_others(ctx, headers, None)
return False
return fn
def check_true(ctx, dependency_identifier):
defkey = DependencyInflector(dependency_identifier).define_key()
ctx.define(defkey, 1)
return True
def check_ctx_vars(*variables):
def fn(ctx, dependency_identifier):
missing = []
for variable in variables:
if variable not in ctx.env:
missing.append(variable)
if any(missing):
ctx.add_optional_message(dependency_identifier,
'missing {0}'.format(', '.join(missing)))
return False
else:
return True
return fn
def check_stub(ctx, dependency_identifier):
defkey = DependencyInflector(dependency_identifier).define_key()
ctx.undefine(defkey)
return False
def compose_checks(*checks):
def fn(ctx, dependency_identifier):
return all([check(ctx, dependency_identifier) for check in checks])
return fn
def load_fragment(fragment):
file_path = os.path.join(os.path.dirname(__file__), '..', 'fragments',
fragment)
fp = open(file_path,"r")
fragment_code = fp.read()
fp.close()
return fragment_code

210
waftools/dependencies.py Normal file
View File

@ -0,0 +1,210 @@
from waflib.Errors import ConfigurationError, WafError
from waflib.Configure import conf
from waflib.Build import BuildContext
from waflib.Logs import pprint
from inflectors import DependencyInflector
class DependencyError(Exception):
pass
class Dependency(object):
def __init__(self, ctx, known_deps, satisfied_deps, dependency):
self.ctx = ctx
self.known_deps = known_deps
self.satisfied_deps = satisfied_deps
self.identifier, self.desc = dependency['name'], dependency['desc']
self.attributes = self.__parse_attributes__(dependency)
ctx.env.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)
def __parse_attributes__(self, dependency):
if 'os_specific_checks' in dependency:
all_chks = dependency['os_specific_checks']
chks = [check for check in all_chks if check in self.satisfied_deps]
if any(chks):
return all_chks[chks[0]]
return dependency
def check(self):
self.ctx.start_msg('Checking for {0}'.format(self.desc))
try:
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
# get a `#define YYY 0` in `config.h`.
def_key = DependencyInflector(self.identifier).define_key()
self.ctx.undefine(def_key)
self.fatal_if_needed()
return
self.check_autodetect_func()
def check_disabled(self):
if self.enabled_option() == False:
self.skip()
raise DependencyError
if self.enabled_option() == True:
self.attributes['req'] = True
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'])
if deps <= self.satisfied_deps:
conflicting_deps = deps & self.satisfied_deps
self.skip("{0} found".format(", ".join(conflicting_deps)), 'CYAN')
raise DependencyError
def check_autodetect_func(self):
if self.attributes['func'](self.ctx, self.identifier):
self.success(self.identifier)
else:
self.fail()
self.fatal_if_needed()
def enabled_option(self):
try:
return getattr(self.ctx.options, self.enabled_option_repr())
except AttributeError:
pass
return None
def enabled_option_repr(self):
return "enable_{0}".format(self.identifier)
def success(self, depname):
self.ctx.mark_satisfied(depname)
self.ctx.end_msg(self.__message__('yes'))
def fail(self, reason='no'):
self.ctx.end_msg(self.__message__(reason), 'RED')
def fatal_if_needed(self):
if self.enabled_option() == False:
return
if self.attributes.get('req', False):
raise ConfigurationError(self.attributes['fmsg'])
def skip(self, reason='disabled', color='YELLOW'):
self.ctx.end_msg(self.__message__(reason), color)
def __message__(self, message):
optional_message = self.ctx.deps_msg.get(self.identifier)
if optional_message:
return "{0} ({1})".format(message, optional_message)
else:
return message
def configure(ctx):
def __detect_target_os_dependency__(ctx):
target = "os-{0}".format(ctx.env.DEST_OS)
ctx.start_msg('Detected target OS:')
ctx.end_msg(target)
ctx.env.known_deps.add(target)
ctx.env.satisfied_deps.add(target)
ctx.deps_msg = {}
ctx.env['known_deps'] = set()
ctx.env['satisfied_deps'] = set()
__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.env.known_deps:
raise ConfigurationError(
"error in dependencies definition: some dependencies in"
" {0} are unknown.".format(deps))
@conf
def mark_satisfied(ctx, dependency_identifier):
ctx.env.satisfied_deps.add(dependency_identifier)
@conf
def add_optional_message(ctx, dependency_identifier, message):
ctx.deps_msg[dependency_identifier] = message
@conf
def parse_dependencies(ctx, dependencies):
def __check_dependency__(ctx, dependency):
Dependency(ctx,
ctx.env.known_deps,
ctx.env.satisfied_deps,
dependency).check()
[__check_dependency__(ctx, dependency) for dependency in dependencies]
@conf
def dependency_satisfied(ctx, dependency_identifier):
ctx.ensure_dependency_is_known(dependency_identifier)
return dependency_identifier in ctx.env.satisfied_deps
def filtered_sources(ctx, sources):
def __source_file__(source):
if isinstance(source, tuple):
return source[0]
else:
return source
def __check_filter__(dependency):
if dependency.find('!') == 0:
dependency = dependency.lstrip('!')
ctx.ensure_dependency_is_known(dependency)
return dependency not in ctx.env.satisfied_deps
else:
ctx.ensure_dependency_is_known(dependency)
return dependency in ctx.env.satisfied_deps
def __unpack_and_check_filter__(source):
try:
_, dependency = source
return __check_filter__(dependency)
except ValueError:
return True
return [__source_file__(source) for source in sources \
if __unpack_and_check_filter__(source)]
def env_fetch(tx):
def fn(ctx):
deps = list(ctx.env.satisfied_deps)
lists = [ctx.env[tx(dep)] for dep in deps if (tx(dep) in ctx.env)]
return [item for sublist in lists for item in sublist]
return fn
def dependencies_use(ctx):
return [DependencyInflector(dep).storage_key() for \
dep in ctx.env.satisfied_deps]
BuildContext.filtered_sources = filtered_sources
BuildContext.dependencies_use = dependencies_use
BuildContext.dependencies_includes = env_fetch(lambda x: "INCLUDES_{0}".format(x))
BuildContext.dependency_satisfied = dependency_satisfied

View File

View File

@ -0,0 +1,57 @@
from waflib import Utils
def __get_cc_env_vars__(cc):
cmd = cc + ['-dM', '-E', '-']
try:
p = Utils.subprocess.Popen(cmd, stdin=Utils.subprocess.PIPE,
stdout=Utils.subprocess.PIPE,
stderr=Utils.subprocess.PIPE)
p.stdin.write('\n'.encode())
return p.communicate()[0]
except Exception:
return ""
def __add_generic_flags__(ctx):
ctx.env.CFLAGS += ["-D_ISOC99_SOURCE", "-D_GNU_SOURCE",
"-D_LARGEFILE_SOURCE", "-D_FILE_OFFSET_BITS=64",
"-D_LARGEFILE64_SOURCE",
"-std=gnu99", "-Wall"]
if ctx.is_debug_build():
ctx.env.CFLAGS += ['-g']
def __add_gcc_flags__(ctx):
ctx.env.CFLAGS += ["-Wundef", "-Wmissing-prototypes",
"-Wno-switch", "-Wno-parentheses", "-Wpointer-arith",
"-Wredundant-decls", "-Wno-pointer-sign",
"-Werror=implicit-function-declaration",
"-Wno-error=deprecated-declarations",
"-Wno-error=unused-function" ]
def __add_clang_flags__(ctx):
ctx.env.CFLAGS += ["-Wno-logical-op-parentheses", "-fcolor-diagnostics"]
def __add_mingw_flags__(ctx):
ctx.env.CFLAGS += ['-D__USE_MINGW_ANSI_STDIO=1']
ctx.env.CFLAGS += ['-DBYTE_ORDER=1234']
ctx.env.CFLAGS += ['-DLITLE_ENDIAN=1234']
ctx.env.CFLAGS += ['-DBIG_ENDIAN=4321']
ctx.env.LAST_LINKFLAGS += ['-mconsole']
__compiler_map__ = {
'__GNUC__': __add_gcc_flags__,
'__clang__': __add_clang_flags__,
'__MINGW32__': __add_mingw_flags__,
}
def __apply_map__(ctx, fnmap):
if 'CC_ENV_VARS' not in ctx.env:
ctx.env.CC_ENV_VARS = str(__get_cc_env_vars__(ctx.env.CC))
for k, fn in fnmap.items():
if ctx.env.CC_ENV_VARS.find(k) > 0:
fn(ctx)
def configure(ctx):
__add_generic_flags__(ctx)
__apply_map__(ctx, __compiler_map__)

View File

@ -0,0 +1,28 @@
def x86(ctx):
ctx.define('ARCH_X86', 1)
ctx.define('ARCH_X86_32', 1)
def x86_64(ctx):
ctx.define('ARCH_X86', 1)
ctx.define('ARCH_X86_64', 1)
ctx.define('HAVE_FAST_64BIT', 1)
def ia64(ctx):
ctx.define('HAVE_FAST_64BIT', 1)
def default(ctx):
pass
def configure(ctx):
ctx.define('ARCH_X86', 0)
ctx.define('ARCH_X86_32', 0)
ctx.define('ARCH_X86_64', 0)
ctx.define('HAVE_FAST_64BIT', 0)
ctx.define('HAVE_MMX', 'ARCH_X86', quote=False)
ctx.define('HAVE_MMX2', 'ARCH_X86', quote=False)
ctx.define('HAVE_SSE', 'ARCH_X86', quote=False)
ctx.define('HAVE_SSE2', 'ARCH_X86', quote=False)
ctx.define('HAVE_SSSE3', 'ARCH_X86', quote=False)
globals().get(ctx.env.DEST_CPU, default)(ctx)

View File

@ -0,0 +1,29 @@
__cdrom_devices_map__ = {
'win32': 'D:',
'cygwin': 'D:',
'darwin': '/dev/disk1',
'freebsd': '/dev/cd0',
'openbsd': '/dev/rcd0r',
'default': '/dev/cdrom'
}
__dvd_devices_map__ = {
'win32': 'D:',
'cygwin': 'D:',
'darwin': '/dev/rdiskN',
'freebsd': '/dev/cd0',
'openbsd': '/dev/rcd0r',
'default': '/dev/dvd'
}
def __default_cdrom_device__(ctx):
default = __cdrom_devices_map__['default']
return __cdrom_devices_map__.get(ctx.env.DEST_OS, default)
def __default_dvd_device__(ctx):
default = __dvd_devices_map__['default']
return __dvd_devices_map__.get(ctx.env.DEST_OS, default)
def configure(ctx):
ctx.define('DEFAULT_DVD_DEVICE', __default_dvd_device__(ctx))
ctx.define('DEFAULT_CDROM_DEVICE', __default_cdrom_device__(ctx))

69
waftools/features.py Normal file
View File

@ -0,0 +1,69 @@
from waflib.Options import OptionsContext
class Feature(object):
def __init__(self, group, feature):
self.group = group
self.identifier, self.attributes = feature['name'], feature
def add_options(self):
[self.add_option(option_rule) for option_rule in self.option_rules()]
def add_option(self, rule):
self.group.add_option(self.option(rule['state']),
action=rule['action'],
default=rule['default'],
dest=self.storage(),
help=self.help(rule['state']))
# private
def option_rules(self):
return {
'autodetect': [
{'state': 'disable', 'action': 'store_false', 'default': None},
{'state': 'enable', 'action': 'store_true', 'default': None},
],
'disable': [
{'state': 'disable', 'action': 'store_false', 'default': False},
{'state': 'enable', 'action': 'store_true', 'default': False},
],
'enable': [
{'state': 'disable', 'action': 'store_false', 'default': True},
],
}[self.behaviour()]
def behaviour(self):
if 'default' in self.attributes:
return self.attributes['default']
else:
return 'autodetect'
def option(self, state):
return "--{0}-{1}".format(state, self.identifier)
def help(self, state):
return "{0} {1} [{2}]" \
.format(state, self.attributes['desc'], self.behaviour())
def storage(self):
return "enable_{0}".format(self.identifier)
def add_feature(group, feature):
Feature(group, feature).add_options()
def parse_features(opt, group_name, features):
def is_feature(dep):
return dep['name'].find('--') >= 0
def strip_feature(dep):
dep['name'] = dep['name'].lstrip('-')
return dep
features = [strip_feature(dep) for dep in features if is_feature(dep)]
group = opt.get_option_group(group_name)
if not group:
group = opt.add_option_group(group_name)
[add_feature(group, feature) for feature in features]
OptionsContext.parse_features = parse_features

View File

@ -0,0 +1,11 @@
#import <CoreServices/CoreServices.h>
#import <OpenGL/OpenGL.h>
#import <Cocoa/Cocoa.h>
int main(int argc, char **argv) {
@autoreleasepool {
NSArray *ary = @[@1, @2, @3];
NSLog(@"test subscripting: %@", ary[0]);
NSApplicationLoad();
}
}

View File

@ -0,0 +1,15 @@
#include <CoreAudio/CoreAudio.h>
#include <AudioToolbox/AudioToolbox.h>
#include <AudioUnit/AudioUnit.h>
int main(int argc, char **argv)
{
AudioComponentDescription desc = (AudioComponentDescription) {
.componentType = kAudioUnitType_Output,
.componentSubType = kAudioUnitSubType_DefaultOutput,
.componentManufacturer = kAudioUnitManufacturer_Apple,
};
AudioComponentFindNext(NULL, &desc);
return 0;
}

10
waftools/fragments/dvb.c Normal file
View File

@ -0,0 +1,10 @@
#include <poll.h>
#include <sys/ioctl.h>
#include <stdio.h>
#include <time.h>
#include <unistd.h>
#include <linux/dvb/dmx.h>
#include <linux/dvb/frontend.h>
#include <linux/dvb/video.h>
#include <linux/dvb/audio.h>
int main(void) {return 0;}

12
waftools/fragments/ebx.c Normal file
View File

@ -0,0 +1,12 @@
int main(void) {
int x;
__asm__ volatile(
"xor %0, %0"
:"=b"(x)
// just adding ebx to clobber list seems unreliable with some
// compilers, e.g. Haiku's gcc 2.95
);
// and the above check does not work for OSX 64 bit...
__asm__ volatile("":::"%ebx");
return 0;
}

View File

@ -0,0 +1,9 @@
#include <X11/Xlib.h>
#include <GL/glx.h>
#include <GL/gl.h>
int main(int argc, char *argv[]) {
glXCreateContext(NULL, NULL, NULL, True);
glFinish();
return 0;
}

View File

@ -0,0 +1,30 @@
#include <stdio.h>
#include <unistd.h>
#include <iconv.h>
#define INBUFSIZE 1024
#define OUTBUFSIZE 4096
char inbuffer[INBUFSIZE];
char outbuffer[OUTBUFSIZE];
int main(void) {
size_t numread;
iconv_t icdsc;
char *tocode="UTF-8";
char *fromcode="cp1250";
if ((icdsc = iconv_open(tocode, fromcode)) != (iconv_t)(-1)) {
while ((numread = read(0, inbuffer, INBUFSIZE))) {
char *iptr=inbuffer;
char *optr=outbuffer;
size_t inleft=numread;
size_t outleft=OUTBUFSIZE;
if (iconv(icdsc, &iptr, &inleft, &optr, &outleft)
!= (size_t)(-1)) {
write(1, outbuffer, OUTBUFSIZE - outleft);
}
}
if (iconv_close(icdsc) == -1)
;
}
return 0;
}

View File

@ -0,0 +1,7 @@
#include <libavfilter/avfilter.h>
void vf_next_query_format() {}
int main(void) {
avfilter_register_all();
vf_next_query_format();
return 0;
}

24
waftools/fragments/lua.c Normal file
View File

@ -0,0 +1,24 @@
#include <stdlib.h>
#include <lua.h>
#include <lualib.h>
#include <lauxlib.h>
// filled on the python side with .format()
{additional_lua_test_header}
void test_lua(void) {{
lua_State *L = luaL_newstate();
lua_pushstring(L, "test");
lua_setglobal(L, "test");
}}
void test_other(void) {{
// filled on the python side with .format()
{additional_lua_test_code}
}}
int main(void) {{
test_lua();
test_other();
return 0;
}}

View File

@ -0,0 +1,3 @@
quvi_t q;
if (quvi_init(&q) == QUVI_OK)
quvi_supported(q, "http://nope");

View File

@ -0,0 +1,3 @@
quvi_t q = quvi_new();
if (quvi_ok(q))
quvi_supports(q, "http://nope", QUVI_SUPPORTS_MODE_OFFLINE, QUVI_SUPPORTS_TYPE_MEDIA);

7
waftools/fragments/mng.c Normal file
View File

@ -0,0 +1,7 @@
#include <libmng.h>
int main(int argc, char **argv)
{
const char * p_ver = mng_version_text();
return !p_ver || p_ver[0] == 0;
}

View File

@ -0,0 +1,11 @@
#if HAVE_SOUNDCARD_H
#include <soundcard.h>
#endif
#if HAVE_SYS_SOUNDCARD_H
#include <sys/soundcard.h>
#endif
int main(int argc, char **argv) {
return SNDCTL_DSP_SETFRAGMENT;
}

View File

@ -0,0 +1,13 @@
#if HAVE_SOUNDCARD_H
#include <soundcard.h>
#endif
#if HAVE_SYS_SOUNDCARD_H
#include <sys/soundcard.h>
#endif
#ifdef OPEN_SOUND_SYSTEM
int main(void) {{ return 0; }}
#else
#error Not the real thing
#endif

View File

@ -0,0 +1,10 @@
#include <pthread.h>
static void *func(void *arg) { return arg; }
int main(void) {
pthread_t tid;
#ifdef PTW32_STATIC_LIB
pthread_win32_process_attach_np();
pthread_win32_thread_attach_np();
#endif
return pthread_create (&tid, 0, func, 0) != 0;
}

7
waftools/fragments/pvr.c Normal file
View File

@ -0,0 +1,7 @@
#include <sys/time.h>
#include <linux/videodev2.h>
int main(void)
{
struct v4l2_ext_controls ext;
return ext.controls->value;
}

View File

@ -0,0 +1,7 @@
#include <windows.h>
#include <ntddcdrm.h>
int main(int argc, char **argv)
{
return 0;
}

View File

@ -0,0 +1,19 @@
#define COBJMACROS 1
#define _WIN32_WINNT 0x600
#include <malloc.h>
#include <stdlib.h>
#include <process.h>
#include <initguid.h>
#include <audioclient.h>
#include <endpointvolume.h>
#include <mmdeviceapi.h>
#include <avrt.h>
const GUID *check1[] = {
&IID_IAudioClient,
&IID_IAudioRenderClient,
&IID_IAudioClient,
&IID_IAudioEndpointVolume,
};
int main(void) {
return 0;
}

View File

@ -0,0 +1,8 @@
#include <X11/Xlib.h>
#include <X11/extensions/xf86vmode.h>
int main(int argc, char **argv)
{
XF86VidModeQueryExtension(0, 0, 0);
return 0;
}

View File

@ -0,0 +1,6 @@
#include <X11/XF86keysym.h>
int main(int argc, char **argv)
{
return XF86XK_AudioPause;
}

View File

View File

@ -0,0 +1,36 @@
def __get_version__(ctx):
import subprocess
process = subprocess.Popen(["sh", "./version.sh", "--print"],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
cwd=ctx.srcnode.abspath())
process.wait()
(version, err) = process.communicate()
return version.strip()
def __get_build_date__():
import time
return time.strftime("%Y-%m-%dT%H:%M:%S", time.gmtime())
def __write_config_h__(ctx):
ctx.start_msg("Writing configuration header:")
ctx.write_config_header('config.h')
ctx.end_msg("config.h", "PINK")
def __write_version_h__(ctx):
ctx.start_msg("Writing header:")
ctx.env.VERSION = __get_version__(ctx)
ctx.define("VERSION", ctx.env.VERSION)
ctx.define("BUILDDATE", __get_build_date__())
ctx.write_config_header("version.h")
ctx.end_msg("version.h", "PINK")
def __add_mplayer_defines__(ctx):
from sys import argv
ctx.define("CONFIGURATION", " ".join(argv))
ctx.define("MPLAYER_CONFDIR", ctx.env.CONFDIR)
def configure(ctx):
__add_mplayer_defines__(ctx)
__write_config_h__(ctx)
__write_version_h__(ctx)

View File

@ -0,0 +1,37 @@
from waflib.Build import BuildContext
import os
def __file2string_cmd__(ctx):
return "${{BIN_PERL}} {0}/TOOLS/file2string.pl ${{SRC}} > ${{TGT}}" \
.format(ctx.srcnode.abspath())
def __matroska_cmd__(ctx, argument):
return "${{BIN_PERL}} {0}/TOOLS/matroska.pl {1} ${{SRC}} > ${{TGT}}" \
.format(ctx.srcnode.abspath(), argument)
def __file2string__(ctx, **kwargs):
ctx(
rule = __file2string_cmd__(ctx),
before = ("c",),
name = os.path.basename(kwargs['target']),
**kwargs
)
def __matroska_header__(ctx, **kwargs):
ctx(
rule = __matroska_cmd__(ctx, '--generate-header'),
before = ("c",),
name = os.path.basename(kwargs['target']),
**kwargs
)
def __matroska_definitions__(ctx, **kwargs):
ctx(
rule = __matroska_cmd__(ctx, '--generate-definitions'),
before = ("c",),
**kwargs
)
BuildContext.file2string = __file2string__
BuildContext.matroska_header = __matroska_header__
BuildContext.matroska_definitions = __matroska_definitions__

26
waftools/inflectors.py Normal file
View File

@ -0,0 +1,26 @@
import re
class DependencyInflector(object):
def __init__(self, dependency):
self.dep = dependency
def storage_key(self):
return self.__underscore__(self.dep)
def define_key(self):
return ("have_" + self.storage_key()).upper()
def define_dict(self):
return {'define_name': self.define_key()}
def storage_dict(self):
return {'uselib_store': self.storage_key()}
def __underscore__(self, word):
""" Converts a word "into_it_s_underscored_version"
Convert any "CamelCased" or "ordinary Word" into an
"underscored_word"."""
return re.sub('[^A-Z^a-z^0-9]+', '_', \
re.sub('([a-z\d])([A-Z])', '\\1_\\2', \
re.sub('([A-Z]+)([A-Z][a-z])', '\\1_\\2', re.sub('::', '/', word)))).lower()

View File

@ -0,0 +1,46 @@
from waflib.Configure import conf
@conf
def get_config_header(self, defines=True, headers=False, define_prefix=''):
"""
Only difference is it outputs `#define VAR 0` or `#define VAR value`
instead of `#undef VAR` or `#define VAR val`.
"""
from waflib.Tools.c_config import DEFKEYS, INCKEYS
lst = []
if headers:
for x in self.env[INCKEYS]:
lst.append('#include <%s>' % x)
if defines:
for x in self.env[DEFKEYS]:
val = self.is_defined(x) and self.get_define(x) or "0"
lst.append('#define %s %s' % (define_prefix + x, val))
return "\n".join(lst)
from waflib import TaskGen
@TaskGen.extension('.m')
def m_hook(self, node):
"""
Makes waf call the c compiler for objective-c files
"""
return self.create_compiled_task('c', node)
def build(ctx):
from waflib import Task
cls = Task.classes['cprogram']
class cprogram(cls):
run_str = cls.hcode + '${LAST_LINKFLAGS}'
cls = Task.classes['macplist']
class macplist(cls):
def run(self):
from waflib import Utils
if getattr(self, 'code', None):
txt = self.code
else:
txt = self.inputs[0].read()
txt = Utils.subst_vars(txt, self.env)
self.outputs[0].write(txt)

759
wscript Normal file
View File

@ -0,0 +1,759 @@
# vi: ft=python
import sys, os, re
sys.path.insert(0, os.path.join(os.getcwd(), 'waftools'))
from waflib.Configure import conf
from waflib import Utils
from waftools.checks.generic import *
from waftools.checks.custom import *
build_options = [
{
'name': '--static-build',
'desc': 'static build',
'default': 'disable',
'func': check_true
}, {
'name': '--build-date',
'desc': 'whether to include binary compile time',
'default': 'enable',
'func': check_true
}, {
'name': '--debug-build',
'desc': 'whether to compile-in debugging information',
'default': 'enable',
'func': check_true
}, {
'name': '--manpage-build',
'desc': 'manpage generation',
'func': check_ctx_vars('RST2MAN')
}, {
'name': '--pdf-build',
'desc': 'pdf manual generation',
'func': check_ctx_vars('RST2LATEX', 'PDFLATEX'),
'default': 'disable'
}, {
'name': 'libdl',
'desc': 'dynamic loader',
'func': check_libs(['dl'], check_statement('dlfcn.h', 'dlopen("", 0)'))
}, {
'name': 'dlopen',
'desc': 'dlopen',
'deps_any': [ 'libdl', 'os-win32', 'os-cygwin' ],
'func': check_true
}, {
'name': '--vf-dlopen-filters',
'desc': 'compilation of default filters for vf_dlopen',
'deps': [ 'dlopen' ],
'default': 'disable',
'func': check_true
}, {
'name': '--macosx-bundle',
'desc': 'compilation of a Mac OS X Application bundle',
'deps': [ 'os-darwin' ],
'default': 'disable',
'func': check_true
}, {
'name': 'win32-executable',
'desc': 'w32 executable',
'deps_any': [ 'os-win32', 'os-cygwin'],
'func': check_ctx_vars('WINDRES')
}
]
main_dependencies = [
{
'name': 'noexecstack',
'desc': 'compiler support for noexecstack',
'func': check_cc(linkflags='-Wl,-z,noexecstack')
}, {
'name': 'noexecstack',
'desc': 'linker support for --nxcompat --no-seh --dynamicbase',
'func': check_cc(linkflags=['-Wl,--nxcompat', '-Wl,--no-seh', '-Wl,--dynamicbase'])
}, {
'name': 'ebx_available',
'desc': 'ebx availability',
'func': check_cc(fragment=load_fragment('ebx.c'))
} , {
'name': 'libm',
'desc': '-lm',
'func': check_cc(lib='m')
}, {
'name': 'nanosleep',
'desc': 'nanosleep',
'func': check_statement('time.h', 'nanosleep(0,0)')
}, {
'name': 'sys-mman-h',
'desc': 'mman.h',
'func': check_statement('sys/mman.h', 'mmap(0, 0, 0, 0, 0, 0)')
}, {
'name': '--pthreads',
'desc': 'POSIX threads',
'func': check_pthreads,
}, {
'name': 'librt',
'desc': 'linking with -lrt',
'deps': [ 'pthreads' ],
'func': check_cc(lib='rt')
}, {
'name': '--iconv',
'desc': 'iconv',
'func': check_iconv,
'req': True,
'fmsg': "Unable to find iconv which should be part of a standard \
compilation environment. Aborting. If you really mean to compile without \
iconv support use --disable-iconv.",
}, {
'name': 'dos-paths',
'desc': 'w32/dos paths',
'deps_any': [ 'os-win32', 'os-cygwin' ],
'func': check_true
}, {
'name': 'priority',
'desc': 'w32 priority API',
'deps_any': [ 'os-win32', 'os-cygwin'],
'func': check_true
}, {
'name': 'stream-cache',
'desc': 'stream cache',
'deps': [ 'pthreads' ],
'func': check_true
}, {
'name': 'soundcard',
'desc': 'soundcard.h',
'func': check_headers('soundcard.h', 'sys/soundcard.h')
}, {
'name': 'videoio',
'desc': 'videoio.h',
'func': check_headers('sys/videoio.h')
}, {
'name': '--terminfo',
'desc': 'terminfo',
'func': check_libs(['ncurses', 'ncursesw'],
check_statement('term.h', 'setupterm(0, 1, 0)')),
}, {
'name': '--termcap',
'desc': 'termcap',
'deps_neg': ['terminfo'],
'func': check_libs(['ncurses', 'tinfo', 'termcap'],
check_statement('term.h', 'tgetent(0, 0)')),
}, {
'name': '--termios',
'desc': 'termios',
'func': check_headers('termios.h', 'sys/termios.h'),
}, {
'name': '--shm',
'desc': 'shm',
'func': check_statement('sys/shm.h',
'shmget(0, 0, 0); shmat(0, 0, 0); shmctl(0, 0, 0)')
}, {
'name': 'posix-select',
'desc': 'POSIX select()',
'func': check_statement('sys/select.h', """
int rc;
rc = select(0, (fd_set *)(0), (fd_set *)(0), (fd_set *)(0),
(struct timeval *)(0))""")
}, {
'name': 'glob',
'desc': 'glob()',
'func': check_statement('glob.h', 'glob("filename", 0, 0, 0)')
}, {
'name': 'glob-win32-replacement',
'desc': 'glob() win32 replacement',
'deps_neg': [ 'glob' ],
'deps_any': [ 'os-win32', 'os-cygwin' ],
'func': check_true
}, {
'name': 'setmode',
'desc': 'setmode()',
'func': check_statement('io.h', 'setmode(0, 0)')
}, {
'name': 'sys-sysinfo-h',
'desc': 'sys/sysinfo.h',
'func': check_statement('sys/sysinfo.h',
'struct sysinfo s_info; s_info.mem_unit=0; sysinfo(&s_info)')
}, {
'name': '--libguess',
'desc': 'libguess support',
'func': check_pkg_config('libguess', '>= 1.0'),
}, {
'name': '--libsmbclient',
'desc': 'Samba support',
'deps': [ 'libdl' ],
'func': check_pkg_config('smbclient', '>= 0.2.0'),
'module': 'input',
}, {
'name': '--libquvi4',
'desc': 'libquvi 0.4.x support',
'func': check_pkg_config('libquvi', '>= 0.4.1'),
}, {
'name': '--libquvi9',
'desc': 'libquvi 0.9.x support',
'deps_neg': [ 'libquvi4' ],
'func': check_pkg_config('libquvi-0.9', '>= 0.9.0'),
}, {
'name': '--libass',
'desc': 'SSA/ASS support',
'func': check_pkg_config('libass'),
'req': True,
'fmsg': "Unable to find development files for libass. Aborting. \
If you really mean to compile without libass support use --disable-libass."
}, {
'name': '--libass-osd',
'desc': 'libass OSD support',
'deps': [ 'libass' ],
'func': check_true,
}, {
'name': 'dummy-osd',
'desc': 'dummy OSD support',
'deps_neg': [ 'libass-osd' ],
'func': check_true,
} , {
'name': 'zlib',
'desc': 'zlib',
'func': check_libs(['z'],
check_statement('zlib.h', 'inflate(0, Z_NO_FLUSH)')),
'req': True,
'fmsg': 'Unable to find development files for zlib.'
} , {
'name' : '--encoding',
'desc' : 'Encoding',
'func': check_true,
}, {
'name' : '--joystick',
'desc' : 'joystick',
'func': check_cc(header_name='linux/joystick.h'),
'default': 'disable'
}, {
'name' : '--lirc',
'desc' : 'lirc',
'func': check_cc(header_name='lirc/lirc_client.h', lib='lirc_client'),
}, {
'name' : '--lircc',
'desc' : 'lircc',
'func': check_cc(header_name='lirc/lircc.h', lib='lircc'),
}, {
'name' : '--vcd',
'desc' : 'VCD support',
'deps_any': [ 'os-linux', 'os-freebsd', 'os-netbsd', 'os-openbsd', 'os-darwin' ],
'func': check_true,
'os_specific_checks': {
'os-win32': {
'func': check_cc(fragment=load_fragment('vcd_windows.c'))
}
}
}, {
'name': '--libbluray',
'desc': 'Bluray support',
'func': check_pkg_config('libbluray', '>= 0.2.1'),
}, {
'name': '--dvdread',
'desc': 'dvdread support',
'func': check_pkg_config('dvdread', '>= 4.1.0'),
}, {
'name': '--cdda',
'desc': 'cdda support (libcdio)',
'func': check_pkg_config('libcdio_paranoia'),
}, {
'name': '--enca',
'desc': 'ENCA support',
'func': check_statement('enca.h', 'enca_get_languages(NULL)', lib='enca'),
}, {
'name': '--mpg123',
'desc': 'mpg123 support',
'func': check_pkg_config('libmpg123', '>= 1.2.0'),
}, {
'name': '--ladspa',
'desc': 'LADSPA plugin support',
'func': check_statement('ladspa.h', 'LADSPA_Descriptor ld = {0}'),
}, {
'name': '--libbs2b',
'desc': 'libbs2b audio filter support',
'func': check_pkg_config('libbs2b'),
}, {
'name': '--lcms2',
'desc': 'LCMS2 support',
'func': check_pkg_config('lcms2'),
}
]
libav_pkg_config_checks = [
'libavutil', '> 51.73.0',
'libavcodec', '> 54.34.0',
'libavformat', '> 54.19.0',
'libswscale', '>= 2.0.0'
]
libav_dependencies = [
{
'name': 'libav',
'desc': 'libav/ffmpeg',
'func': check_pkg_config(*libav_pkg_config_checks),
'req': True,
'fmsg': "Unable to find development files for some of the required \
Libav libraries ({0}). Aborting.".format(" ".join(libav_pkg_config_checks))
}, {
'name': '--libavresample',
'desc': 'libavresample',
'func': check_pkg_config('libavresample', '>= 1.0.0'),
}, {
'name': 'avresample-set-channel-mapping',
'desc': 'libavresample channel mapping API',
'deps': [ 'libavresample' ],
'func': check_statement('libavresample/avresample.h',
'avresample_set_channel_mapping(NULL, NULL)',
use='libavresample'),
}, {
'name': '--libswresample',
'desc': 'libswresample',
'func': check_pkg_config('libswresample', '>= 0.17.102'),
}, {
'name': 'resampler',
'desc': 'usable resampler found',
'deps_any': [ 'libavresample', 'libswresample' ],
'func': check_true,
'req': True,
'fmsg': 'No resampler found. Install libavresample or libswresample (FFmpeg).'
}, {
'name': 'avcodec-new-vdpau-api',
'desc': 'libavcodec new vdpau API',
'func': check_statement('libavutil/pixfmt.h',
'int x = AV_PIX_FMT_VDPAU',
use='libav'),
}, {
'name': 'avcodec-chroma-pos-api',
'desc': 'libavcodec avcodec_enum_to_chroma_pos API',
'func': check_statement('libavcodec/avcodec.h', """int x, y;
avcodec_enum_to_chroma_pos(&x, &y, AVCHROMA_LOC_UNSPECIFIED)""",
use='libav')
}, {
'name': 'avutil-qp-api',
'desc': 'libavutil QP API',
'func': check_statement('libavutil/frame.h',
'av_frame_get_qp_table(NULL, NULL, NULL)',
use='libav')
}, {
'name': 'avutil-refcounting',
'desc': 'libavutil ref-counting API',
'func': check_statement('libavutil/frame.h', 'av_frame_unref(NULL)',
use='libav'),
} , {
'name': 'av-opt-set-int-list',
'desc': 'libavutil av_opt_set_int_list() API',
'func': check_statement('libavutil/opt.h',
'av_opt_set_int_list(0,0,(int*)0,0,0)',
use='libav')
}, {
'name': '--libavfilter',
'desc': 'libavfilter',
'func': compose_checks(
check_pkg_config('libavfilter'),
check_cc(fragment=load_fragment('libavfilter.c'),
use='libavfilter')),
}, {
'name': '--vf-lavfi',
'desc': 'using libavfilter through vf_lavfi',
'deps': [ 'libavfilter', 'avutil-refcounting' ],
'func': check_true
}, {
'name': '--af-lavfi',
'desc': 'using libavfilter through af_lavfi',
'deps': [ 'libavfilter', 'av-opt-set-int-list' ],
'func': check_true
}, {
'name': '--libavdevice',
'desc': 'libavdevice',
'func': check_pkg_config('libavdevice', '>= 54.0.0'),
}, {
'name': '--libpostproc',
'desc': 'libpostproc',
'func': check_pkg_config('libpostproc', '>= 52.0.0'),
}
]
audio_output_features = [
{
'name': '--sdl2',
'desc': 'SDL2',
'func': check_pkg_config('sdl2')
}, {
'name': '--sdl',
'desc': 'SDL (1.x)',
'deps_neg': [ 'sdl2' ],
'func': check_pkg_config('sdl')
}, {
'name': '--oss-audio',
'desc': 'OSS audio output',
'func': check_oss
}, {
'name': '--audio-select',
'desc': 'audio select()',
'deps': [ 'posix-select', 'oss-audio' ],
'func': check_true,
}, {
'name': '--rsound',
'desc': 'RSound audio output',
'func': check_statement('rsound.h', 'rsd_init(NULL)', lib='rsound')
}, {
'name': '--sndio',
'desc': 'sndio audio input/output',
'func': check_statement('sndio.h',
'struct sio_par par; sio_initpar(&par)', lib='sndio')
}, {
'name': '--pulse',
'desc': 'PulseAudio audio output',
'func': check_pkg_config('libpulse', '>= 0.9')
}, {
'name': '--portaudio',
'desc': 'PortAudio audio output',
'deps': [ 'pthreads' ],
'func': check_pkg_config('portaudio-2.0', '>= 19'),
}, {
'name': '--jack',
'desc': 'JACK audio output',
'func': check_pkg_config('jack'),
}, {
'name': '--openal',
'desc': 'OpenAL audio output',
'func': check_pkg_config('openal', '>= 1.13'),
'default': 'disable'
}, {
'name': '--alsa',
'desc': 'ALSA audio output',
'func': check_pkg_config('alsa'),
}, {
'name': '--coreaudio',
'desc': 'CoreAudio audio output',
'func': check_cc(
fragment=load_fragment('coreaudio.c'),
framework_name=['CoreAudio', 'AudioUnit', 'AudioToolbox'])
}, {
'name': '--dsound',
'desc': 'DirectSound audio output',
'func': check_cc(header_name='dsound.h'),
}, {
'name': '--wasapi',
'desc': 'WASAPI audio output',
'func': check_cc(fragment=load_fragment('wasapi.c'), lib='ole32'),
}
]
video_output_features = [
{
'name': '--cocoa',
'desc': 'Cocoa',
'func': check_cc(
fragment=load_fragment('cocoa.m'),
compile_filename='test.m',
framework_name=['Cocoa', 'IOKit', 'OpenGL'])
} , {
'name': '--wayland',
'desc': 'Wayland',
'func': check_pkg_config('wayland-client', '>= 1.2.0',
'wayland-cursor', '>= 1.2.0',
'xkbcommon', '>= 0.3.0'),
} , {
'name': '--x11',
'desc': 'X11',
'func': check_pkg_config('x11'),
} , {
'name': '--xss',
'desc': 'Xss screensaver extensions',
'deps': [ 'x11' ],
'func': check_statement('X11/extensions/scrnsaver.h',
'XScreenSaverSuspend(NULL, True)', use='x11', lib='Xss'),
} , {
'name': '--xext',
'desc': 'X extensions',
'deps': [ 'x11' ],
'func': check_pkg_config('xext'),
} , {
'name': '--xv',
'desc': 'Xv video output',
'deps': [ 'x11' ],
'func': check_pkg_config('xv'),
} , {
'name': '--xinerama',
'desc': 'Xinerama',
'deps': [ 'x11' ],
'func': check_pkg_config('xinerama'),
}, {
'name': '--xf86vm',
'desc': 'Xxf86vm',
'deps': [ 'x11' ],
'func': check_cc(fragment=load_fragment('xf86vm.c'),
lib='Xxf86vm', use='x11')
} , {
'name': '--xf86xk',
'desc': 'XF86keysym',
'deps': [ 'x11' ],
'func': check_cc(fragment=load_fragment('xf86xk.c'))
} , {
'name': '--gl-cocoa',
'desc': 'OpenGL Cocoa Backend',
'deps': [ 'cocoa' ],
'func': check_true
} , {
'name': '--gl-x11',
'desc': 'OpenGL X11 Backend',
'deps': [ 'x11' ],
'func': check_libs(['GL', 'GL Xdamage'],
check_cc(fragment=load_fragment('gl_x11.c'),
use=['x11', 'libdl', 'pthreads']))
} , {
'name': '--gl-wayland',
'desc': 'OpenGL Wayland Backend',
'deps': [ 'wayland' ],
'func': check_pkg_config('wayland-egl', '>= 9.0.0',
'egl', '>= 9.0.0')
} , {
'name': '--gl-win32',
'desc': 'OpenGL Win32 Backend',
'func': check_statement('windows.h', 'wglCreateContext(0)',
lib='opengl32')
} , {
'name': '--gl',
'desc': 'OpenGL video outputs',
'deps_any': [ 'gl-cocoa', 'gl-x11', 'gl-win32', 'gl-wayland' ],
'func': check_true
} , {
'name': '--corevideo',
'desc': 'CoreVideo',
'deps': [ 'gl', 'gl-cocoa' ],
'func': check_statement('QuartzCore/CoreVideo.h',
'CVOpenGLTextureCacheCreate(0, 0, 0, 0, 0, 0)',
framework_name=['QuartzCore'])
} , {
'name': '--vdpau',
'desc': 'VDPAU acceleration',
'deps': [ 'x11' ],
'func': check_pkg_config('vdpau', '>= 0.2'),
} , {
'name': '--vdpau-gl-x11',
'desc': 'VDPAU with OpenGL/X11',
'deps': [ 'vdpau', 'gl-x11' ],
'func': check_true,
}, {
'name': '--vaapi',
'desc': 'VAAPI acceleration',
'deps': [ 'x11', 'libdl' ],
'func': check_pkg_config(
'libva', '>= 0.32.0', 'libva-x11', '>= 0.32.0'),
}, {
'name': '--vaapi-vpp',
'desc': 'VAAPI VPP',
'deps': [ 'vaapi' ],
'func': check_pkg_config('libva', '>= 0.34.0'),
}, {
'name': '--vaapi-glx',
'desc': 'VAAPI GLX',
'deps': [ 'vaapi', 'gl-x11' ],
'func': check_pkg_config('libva-glx', '>= 0.32.0'),
}, {
'name': '--caca',
'desc': 'CACA',
'func': check_pkg_config('caca', '>= 0.99.beta18'),
}, {
'name': '--dvb',
'desc': 'DVB',
'func': check_cc(fragment=load_fragment('dvb.c')),
} , {
'name': '--dvbin',
'desc': 'DVB input module',
'deps': [ 'dvb' ],
'func': check_true,
}, {
'name': '--jpeg',
'desc': 'JPEG support',
'func': check_cc(header_name=['stdio.h', 'jpeglib.h'],
lib='jpeg', use='libm'),
}, {
'name': '--direct3d',
'desc': 'Direct3D support',
'func': check_cc(header_name='d3d9.h'),
}
]
hwaccel_features = [
{
'name': '--vaapi-hwaccel',
'desc': 'libavcodec VAAPI hwaccel',
'deps': [ 'vaapi' ],
'func': check_true,
} , {
'name': '--vda-hwaccel',
'desc': 'libavcodec VDA hwaccel',
'deps': [ 'corevideo', 'avutil-refcounting'],
'func': compose_checks(
check_headers('VideoDecodeAcceleration/VDADecoder.h'),
check_statement('libavcodec/vda.h',
'ff_vda_create_decoder(NULL, NULL, NULL)',
framework='IOSurface',
use='libav')),
} , {
'name': 'vda-libavcodec-refcounting',
'desc': "libavcodec VDA ref-counted CVPixelBuffers",
'deps': [ 'vda-hwaccel' ],
'func': check_statement ('libavcodec/vda.h',
"""struct vda_context a = (struct vda_context) {
.use_ref_buffer = 1 }""", use='libav')
}, {
'name': '--vdpau-decoder',
'desc': 'VDPAU decoder (old)',
'deps': [ 'vdpau' ],
'deps_neg': ['avcodec-new-vdpau-api'],
'func': check_true,
}, {
'name': '--vdpau-hwaccel',
'desc': 'libavcodec VDPAU hwaccel (new)',
'deps': [ 'vdpau', 'avcodec-new-vdpau-api' ],
'func': check_true,
}
]
radio_and_tv_features = [
{
'name': '--radio',
'desc': 'Radio interface',
'func': check_true,
'default': 'disable'
}, {
'name': '--radio-capture',
'desc': 'Radio capture (through PCI/line-in)',
'func': check_true,
'deps': [ 'radio' ],
'deps_any': [ 'alsa', 'oss-audio', 'sndio'],
}, {
'name': '--radio-v4l2',
'desc': 'Video4Linux2 radio interface',
'func': check_cc(header_name='linux/videodev2.h'),
'default': 'disable'
}, {
'name': '--tv',
'desc': 'TV interface',
'func': check_true,
}, {
'name': '--tv-v4l2',
'desc': 'Video4Linux2 TV interface',
'func': check_cc(header_name=['sys/time.h', 'linux/videodev2.h'])
## XXX: what the fuck is up with this needing: sys_videoio_h?
}, {
'name': '--libv4l2',
'desc': 'libv4l2 support',
'func': check_pkg_config('libv4l2'),
}, {
'name': '--pvr',
'desc': 'Video4Linux2 MPEG PVR interface',
'func': check_cc(fragment='pvr.c'),
}, {
'name': '--audio-input',
'desc': 'audio input support',
'deps_any': [ 'radio-capture', 'tv-v4l2' ],
'func': check_true
}
]
scripting_features = [
{
'name' : '--lua',
'desc' : 'Lua',
'func': check_lua,
}
]
_INSTALL_DIRS_LIST = [
('bindir', '${PREFIX}/bin', 'binary files'),
('libdir', '${PREFIX}/lib', 'library files'),
('confdir', '${PREFIX}/etc/mpv', 'configuration files'),
('datadir', '${PREFIX}/share', 'data files'),
('mandir', '${DATADIR}/man', 'man pages '),
('docdir', '${DATADIR}/doc/mpv', 'documentation files'),
]
def options(opt):
opt.load('compiler_c')
opt.load('waf_customizations')
opt.load('features')
group = opt.get_option_group("build and install options")
for ident, default, desc in _INSTALL_DIRS_LIST:
group.add_option('--{0}'.format(ident),
type = 'string',
dest = ident,
default = default,
help = 'directory for installing {0} [{1}]' \
.format(desc, default))
opt.parse_features('build and install options', build_options)
optional_features = main_dependencies + libav_dependencies
opt.parse_features('optional feaures', optional_features)
opt.parse_features('audio outputs', audio_output_features)
opt.parse_features('video outputs', video_output_features)
opt.parse_features('hwaccels', hwaccel_features)
opt.parse_features('radio/tv features', radio_and_tv_features)
opt.parse_features('scripting', scripting_features)
group = opt.get_option_group("scripting")
group.add_option('--lua',
type = 'string',
dest = 'LUA_VER',
help = "select Lua package which should be autodetected. Choices: 51 51deb 52 52deb luajit")
@conf
def is_debug_build(ctx):
return getattr(ctx.options, 'enable_debug-build')
def configure(ctx):
ctx.check_waf_version(mini='1.7.13')
target = os.environ.get('TARGET')
(cc, pkg_config, windres) = ('cc', 'pkg-config', 'windres')
if target:
cc = '-'.join([target, 'gcc'])
pkg_config = '-'.join([target, pkg_config])
windres = '-'.join([target, windres])
ctx.find_program(cc, var='CC')
ctx.find_program(pkg_config, var='PKG_CONFIG')
ctx.find_program('perl', var='BIN_PERL')
ctx.find_program('rst2man', var='RST2MAN', mandatory=False)
ctx.find_program('rst2latex', var='RST2LATEX', mandatory=False)
ctx.find_program('pdflatex', var='PDFLATEX', mandatory=False)
ctx.find_program(windres, var='WINDRES', mandatory=False)
for ident, _, _ in _INSTALL_DIRS_LIST:
varname = ident.upper()
ctx.env[varname] = getattr(ctx.options, ident)
# keep substituting vars, until the paths are fully expanded
while re.match('\$\{([^}]+)\}', ctx.env[varname]):
ctx.env[varname] = Utils.subst_vars(ctx.env[varname], ctx.env)
ctx.load('compiler_c')
ctx.load('waf_customizations')
ctx.load('dependencies')
ctx.load('detections.compiler')
ctx.load('detections.cpu')
ctx.load('detections.devices')
ctx.parse_dependencies(build_options)
ctx.parse_dependencies(main_dependencies)
ctx.parse_dependencies(audio_output_features)
ctx.parse_dependencies(video_output_features)
ctx.parse_dependencies(libav_dependencies)
ctx.parse_dependencies(hwaccel_features)
ctx.parse_dependencies(radio_and_tv_features)
if ctx.options.LUA_VER:
ctx.options.enable_lua = True
ctx.parse_dependencies(scripting_features)
ctx.load('generators.headers')
if not ctx.dependency_satisfied('build-date'):
ctx.env.CFLAGS += ['-DNO_BUILD_TIMESTAMPS']
def build(ctx):
ctx.load('wscript_build')

459
wscript_build.py Normal file
View File

@ -0,0 +1,459 @@
def _add_rst_manual_dependencies(ctx):
manpage_sources_basenames = """
options.rst ao.rst vo.rst af.rst vf.rst encode.rst
input.rst osc.rst lua.rst changes.rst""".split()
manpage_sources = ['DOCS/man/en/'+x for x in manpage_sources_basenames]
for manpage_source in manpage_sources:
ctx.add_manual_dependency(
ctx.path.find_node('DOCS/man/en/mpv.rst'),
ctx.path.find_node(manpage_source))
def _build_man(ctx):
ctx(
name = 'rst2man',
target = 'DOCS/man/en/mpv.1',
source = 'DOCS/man/en/mpv.rst',
rule = '${RST2MAN} ${SRC} ${TGT}',
install_path = ctx.env.MANDIR)
_add_rst_manual_dependencies(ctx)
def _build_pdf(ctx):
from waflib import TaskGen
TaskGen.declare_chain(
name = 'rst2latex',
rule = '${RST2LATEX} ${RST2LATEX_FLAGS} ${SRC} ${TGT}',
ext_in = '.rst',
ext_out = '.tex' )
TaskGen.declare_chain(
name = 'pdflatex',
rule = '${PDFLATEX} ${PDFLATEX_FLAGS} ${SRC}; ' * 2,
ext_in = '.tex',
ext_out = '.pdf',
shell = True )
ctx.env.RST2LATEX_FLAGS = [
'--config=' + ctx.srcnode.abspath() + '/DOCS/man/docutils.conf'
]
ctx.env.PDFLATEX_FLAGS = [
'--interaction=batchmode',
'--output-directory=DOCS/man/en/',
'--jobname=mpv'
]
ctx(source = 'DOCS/man/en/mpv.rst')
_add_rst_manual_dependencies(ctx)
ctx.install_files(ctx.env.DOCDIR, ['DOCS/man/en/mpv.pdf'])
def build(ctx):
ctx.load('waf_customizations')
ctx.load('generators.sources')
ctx.file2string(
source = "video/out/x11_icon.bin",
target = "video/out/x11_icon.inc")
ctx.file2string(
source = "etc/input.conf",
target = "mpvcore/input/input_conf.h")
ctx.file2string(
source = "video/out/gl_video_shaders.glsl",
target = "video/out/gl_video_shaders.h")
ctx.file2string(
source = "sub/osd_font.otf",
target = "sub/osd_font.h")
ctx.file2string(
source = "mpvcore/player/lua/defaults.lua",
target = "mpvcore/player/lua/defaults.inc")
ctx.file2string(
source = "mpvcore/player/lua/assdraw.lua",
target = "mpvcore/player/lua/assdraw.inc")
ctx.file2string(
source = "mpvcore/player/lua/osc.lua",
target = "mpvcore/player/lua/osc.inc")
ctx.matroska_header(
source = "demux/ebml.c demux/demux_mkv.c",
target = "ebml_types.h")
ctx.matroska_definitions(
source = "demux/ebml.c",
target = "ebml_defs.c")
getch2_c = {
'win32': 'osdep/getch2-win.c',
}.get(ctx.env.DEST_OS, "osdep/getch2.c")
timer_c = {
'win32': 'osdep/timer-win2.c',
'cygwin': 'osdep/timer-win2.c',
'darwin': 'osdep/timer-darwin.c',
}.get(ctx.env.DEST_OS, "osdep/timer-linux.c")
sources = [
## Audio
( "audio/audio.c" ),
( "audio/audio_buffer.c" ),
( "audio/chmap.c" ),
( "audio/chmap_sel.c" ),
( "audio/fmt-conversion.c" ),
( "audio/format.c" ),
( "audio/mixer.c" ),
( "audio/reorder_ch.c" ),
( "audio/decode/ad_lavc.c" ),
( "audio/decode/ad_mpg123.c", "mpg123" ),
( "audio/decode/ad_spdif.c" ),
( "audio/decode/dec_audio.c" ),
( "audio/filter/af.c" ),
( "audio/filter/af_bs2b.c", "libbs2b" ),
( "audio/filter/af_center.c" ),
( "audio/filter/af_channels.c" ),
( "audio/filter/af_convert24.c" ),
( "audio/filter/af_convertsignendian.c" ),
( "audio/filter/af_delay.c" ),
( "audio/filter/af_drc.c" ),
( "audio/filter/af_dummy.c" ),
( "audio/filter/af_equalizer.c" ),
( "audio/filter/af_export.c", "sys-mman-h" ),
( "audio/filter/af_extrastereo.c" ),
( "audio/filter/af_format.c" ),
( "audio/filter/af_hrtf.c" ),
( "audio/filter/af_karaoke.c" ),
( "audio/filter/af_ladspa.c", "ladspa" ),
( "audio/filter/af_lavcac3enc.c" ),
( "audio/filter/af_lavfi.c", "af-lavfi" ),
( "audio/filter/af_lavrresample.c" ),
( "audio/filter/af_pan.c" ),
( "audio/filter/af_scaletempo.c" ),
( "audio/filter/af_sinesuppress.c" ),
( "audio/filter/af_sub.c" ),
( "audio/filter/af_surround.c" ),
( "audio/filter/af_sweep.c" ),
( "audio/filter/af_volume.c" ),
( "audio/filter/filter.c" ),
( "audio/filter/tools.c" ),
( "audio/filter/window.c" ),
( "audio/out/ao.c" ),
( "audio/out/ao_alsa.c", "alsa" ),
( "audio/out/ao_coreaudio.c", "coreaudio" ),
( "audio/out/ao_coreaudio_properties.c", "coreaudio" ),
( "audio/out/ao_coreaudio_utils.c", "coreaudio" ),
( "audio/out/ao_dsound.c", "dsound" ),
( "audio/out/ao_jack.c", "jack" ),
( "audio/out/ao_lavc.c", "encoding" ),
( "audio/out/ao_null.c" ),
( "audio/out/ao_openal.c", "openal" ),
( "audio/out/ao_oss.c", "oss-audio" ),
( "audio/out/ao_pcm.c" ),
( "audio/out/ao_portaudio.c", "portaudio" ),
( "audio/out/ao_pulse.c", "pulse" ),
( "audio/out/ao_rsound.c", "rsound" ),
( "audio/out/ao_sdl.c", "sdl" ),
( "audio/out/ao_sdl.c", "sdl2" ),
( "audio/out/ao_sndio.c", "sndio" ),
( "audio/out/ao_wasapi.c", "wasapi" ),
## Core
( "mpvcore/input/input.c" ),
( "mpvcore/input/joystick.c", "joystick" ),
( "mpvcore/input/lirc.c", "lirc" ),
( "mpvcore/player/audio.c" ),
( "mpvcore/player/command.c" ),
( "mpvcore/player/configfiles.c" ),
( "mpvcore/player/loadfile.c" ),
( "mpvcore/player/main.c" ),
( "mpvcore/player/misc.c" ),
( "mpvcore/player/mp_lua.c", "lua" ),
( "mpvcore/player/osd.c" ),
( "mpvcore/player/playloop.c" ),
( "mpvcore/player/screenshot.c" ),
( "mpvcore/player/sub.c" ),
( "mpvcore/player/timeline/tl_cue.c" ),
( "mpvcore/player/timeline/tl_mpv_edl.c" ),
( "mpvcore/player/timeline/tl_matroska.c" ),
( "mpvcore/player/video.c" ),
( "mpvcore/asxparser.c" ),
( "mpvcore/av_common.c" ),
( "mpvcore/av_log.c" ),
( "mpvcore/av_opts.c" ),
( "mpvcore/bstr.c" ),
( "mpvcore/charset_conv.c" ),
( "mpvcore/codecs.c" ),
( "mpvcore/cpudetect.c" ),
( "mpvcore/encode_lavc.c", "encoding" ),
( "mpvcore/m_config.c" ),
( "mpvcore/m_option.c" ),
( "mpvcore/m_property.c" ),
( "mpvcore/mp_common.c" ),
( "mpvcore/mp_msg.c" ),
( "mpvcore/mp_ring.c" ),
( "mpvcore/options.c" ),
( "mpvcore/parser-cfg.c" ),
( "mpvcore/parser-mpcmd.c" ),
( "mpvcore/path.c" ),
( "mpvcore/playlist.c" ),
( "mpvcore/playlist_parser.c" ),
( "mpvcore/resolve_quvi.c", "libquvi4" ),
( "mpvcore/resolve_quvi9.c", "libquvi9" ),
( "mpvcore/version.c" ),
## Demuxers
( "demux/codec_tags.c" ),
( "demux/demux.c" ),
( "demux/demux_cue.c" ),
( "demux/demux_edl.c" ),
( "demux/demux_lavf.c" ),
( "demux/demux_libass.c", "libass"),
( "demux/demux_mf.c" ),
( "demux/demux_mkv.c" ),
( "demux/demux_playlist.c" ),
( "demux/demux_raw.c" ),
( "demux/demux_subreader.c" ),
( "demux/ebml.c" ),
( "demux/mf.c" ),
## Streams
( "stream/ai_alsa1x.c", "alsa" ),
( "stream/ai_oss.c", "oss-audio" ),
( "stream/ai_sndio.c", "sndio" ),
( "stream/audio_in.c", "audio-input" ),
( "stream/cache.c", "stream-cache"),
( "stream/cdinfo.c", "cdda"),
( "stream/cookies.c" ),
( "stream/dvb_tune.c", "dvbin" ),
( "stream/frequencies.c", "tv" ),
( "stream/rar.c" ),
( "stream/stream.c" ),
( "stream/stream_avdevice.c" ),
( "stream/stream_bluray.c", "libbluray" ),
( "stream/stream_cdda.c", "cdda" ),
( "stream/stream_dvb.c", "dvbin" ),
( "stream/stream_dvd.c", "dvdread" ),
( "stream/stream_dvd_common.c", "dvdread" ),
( "stream/stream_edl.c" ),
( "stream/stream_file.c" ),
( "stream/stream_lavf.c" ),
( "stream/stream_memory.c" ),
( "stream/stream_mf.c" ),
( "stream/stream_null.c" ),
( "stream/stream_pvr.c", "pvr" ),
( "stream/stream_radio.c", "radio" ),
( "stream/stream_rar.c" ),
( "stream/stream_smb.c", "libsmbclient" ),
( "stream/stream_tv.c", "tv" ),
( "stream/stream_vcd.c", "vcd" ),
( "stream/tv.c", "tv" ),
( "stream/tvi_dummy.c", "tv" ),
( "stream/tvi_v4l2.c", "tv-v4l2"),
## Subtitles
( "sub/ass_mp.c", "libass"),
( "sub/dec_sub.c" ),
( "sub/draw_bmp.c" ),
( "sub/find_subfiles.c" ),
( "sub/img_convert.c" ),
( "sub/osd_dummy.c", "dummy-osd" ),
( "sub/osd_libass.c", "libass-osd" ),
( "sub/sd_ass.c", "libass" ),
( "sub/sd_lavc.c" ),
( "sub/sd_lavc_conv.c" ),
( "sub/sd_lavf_srt.c" ),
( "sub/sd_microdvd.c" ),
( "sub/sd_movtext.c" ),
( "sub/sd_spu.c" ),
( "sub/sd_srt.c" ),
( "sub/spudec.c" ),
( "sub/sub.c" ),
## Video
( "video/csputils.c" ),
( "video/fmt-conversion.c" ),
( "video/image_writer.c" ),
( "video/img_format.c" ),
( "video/mp_image.c" ),
( "video/mp_image_pool.c" ),
( "video/sws_utils.c" ),
( "video/vaapi.c", "vaapi" ),
( "video/vdpau.c", "vdpau" ),
( "video/decode/dec_video.c"),
( "video/decode/lavc_dr1.c", "!avutil-refcounting" ),
( "video/decode/vaapi.c", "vaapi-hwaccel" ),
( "video/decode/vd.c" ),
( "video/decode/vd_lavc.c" ),
( "video/decode/vda.c", "vda-hwaccel" ),
( "video/decode/vdpau.c", "vdpau-hwaccel" ),
( "video/decode/vdpau_old.c", "vdpau-decoder" ),
( "video/filter/pullup.c" ),
( "video/filter/vf.c" ),
( "video/filter/vf_crop.c" ),
( "video/filter/vf_delogo.c" ),
( "video/filter/vf_divtc.c" ),
( "video/filter/vf_dlopen.c", "dlopen" ),
( "video/filter/vf_down3dright.c" ),
( "video/filter/vf_dsize.c" ),
( "video/filter/vf_eq.c" ),
( "video/filter/vf_expand.c" ),
( "video/filter/vf_flip.c" ),
( "video/filter/vf_format.c" ),
( "video/filter/vf_gradfun.c" ),
( "video/filter/vf_hqdn3d.c" ),
( "video/filter/vf_ilpack.c" ),
( "video/filter/vf_lavfi.c", "vf-lavfi"),
( "video/filter/vf_mirror.c" ),
( "video/filter/vf_noformat.c" ),
( "video/filter/vf_noise.c" ),
( "video/filter/vf_phase.c" ),
( "video/filter/vf_pp.c", "libpostproc" ),
( "video/filter/vf_pullup.c" ),
( "video/filter/vf_rotate.c" ),
( "video/filter/vf_scale.c" ),
( "video/filter/vf_screenshot.c" ),
( "video/filter/vf_softpulldown.c" ),
( "video/filter/vf_stereo3d.c" ),
( "video/filter/vf_sub.c" ),
( "video/filter/vf_swapuv.c" ),
( "video/filter/vf_unsharp.c" ),
( "video/filter/vf_vavpp.c", "vaapi-vpp"),
( "video/filter/vf_vo.c" ),
( "video/filter/vf_yadif.c" ),
( "video/out/aspect.c" ),
( "video/out/bitmap_packer.c" ),
( "video/out/cocoa/additions.m", "cocoa" ),
( "video/out/cocoa/view.m", "cocoa" ),
( "video/out/cocoa/window.m", "cocoa" ),
( "video/out/cocoa_common.m", "cocoa" ),
( "video/out/dither.c" ),
( "video/out/filter_kernels.c" ),
( "video/out/gl_cocoa.c", "gl-cocoa" ),
( "video/out/gl_common.c", "gl" ),
( "video/out/gl_hwdec_vaglx.c", "vaapi-glx" ),
( "video/out/gl_hwdec_vdpau.c", "vdpau-gl-x11" ),
( "video/out/gl_lcms.c", "gl" ),
( "video/out/gl_osd.c", "gl" ),
( "video/out/gl_video.c", "gl" ),
( "video/out/gl_w32.c", "gl-win32" ),
( "video/out/gl_wayland.c", "gl-wayland" ),
( "video/out/gl_x11.c", "gl-x11" ),
( "video/out/pnm_loader.c", "gl" ),
( "video/out/vo.c" ),
( "video/out/vo_caca.c", "caca" ),
( "video/out/vo_corevideo.c", "corevideo"),
( "video/out/vo_direct3d.c", "direct3d" ),
( "video/out/vo_image.c" ),
( "video/out/vo_lavc.c", "encoding" ),
( "video/out/vo_null.c" ),
( "video/out/vo_opengl.c", "gl" ),
( "video/out/vo_opengl_old.c", "gl" ),
( "video/out/vo_sdl.c", "sdl2" ),
( "video/out/vo_vaapi.c", "vaapi" ),
( "video/out/vo_vdpau.c", "vdpau" ),
( "video/out/vo_wayland.c", "wayland" ),
( "video/out/vo_x11.c" , "x11" ),
( "video/out/vo_xv.c", "xv" ),
( "video/out/w32_common.c", "os-win32" ),
( "video/out/w32_common.c", "os-cygwin" ),
( "video/out/wayland_common.c", "wayland" ),
( "video/out/x11_common.c", "x11" ),
## osdep
( getch2_c ),
( "osdep/io.c" ),
( "osdep/numcores.c"),
( "osdep/timer.c" ),
( timer_c ),
( "osdep/threads.c" ),
( "osdep/ar/HIDRemote.m", "cocoa" ),
( "osdep/macosx_application.m", "cocoa" ),
( "osdep/macosx_events.m", "cocoa" ),
( "osdep/path-macosx.m", "cocoa" ),
( "osdep/path-win.c", "os-win32" ),
( "osdep/path-win.c", "os-cygwin" ),
( "osdep/glob-win.c", "glob-win32-replacement" ),
( "osdep/priority.c", "priority" ),
( "osdep/mpv.rc", "win32-executable" ),
## tree_allocator
"ta/ta.c", "ta/ta_talloc.c", "ta/ta_utils.c"
]
if ctx.dependency_satisfied('win32-executable'):
from waflib import TaskGen
TaskGen.declare_chain(
name = 'windres',
rule = '${WINDRES} ${WINDRES_FLAGS} ${SRC} ${TGT}',
ext_in = '.rc',
ext_out = '-rc.o',
color = 'PINK')
ctx.env.WINDRES_FLAGS = [
'--include-dir={0}'.format(ctx.bldnode.abspath()),
'--include-dir={0}'.format(ctx.srcnode.abspath())
]
for node in 'osdep/mpv.exe.manifest etc/mpv-icon.ico'.split():
ctx.add_manual_dependency(
ctx.path.find_node('osdep/mpv.rc'),
ctx.path.find_node(node))
cprog_kwargs = {}
if ctx.dependency_satisfied('macosx-bundle'):
import os
basepath = 'TOOLS/osxbundle/mpv.app/Contents'
cprog_kwargs['mac_app'] = True
cprog_kwargs['mac_plist'] = os.path.join(basepath, 'Info.plist')
resources_glob = os.path.join(basepath, 'Resources', '*')
resources_nodes = ctx.srcnode.ant_glob(resources_glob)
resources = [node.srcpath() for node in resources_nodes]
cprog_kwargs['mac_resources'] = resources
ctx(
target = "mpv",
source = ctx.filtered_sources(sources),
use = ctx.dependencies_use(),
includes = [ctx.bldnode.abspath(), ctx.srcnode.abspath()] + \
ctx.dependencies_includes(),
features = "c cprogram",
install_path = ctx.env.BINDIR,
**cprog_kwargs
)
if ctx.dependency_satisfied("vf-dlopen-filters"):
dlfilters = "showqscale telecine tile rectangle framestep \
ildetect".split()
for dlfilter in dlfilters:
ctx(
target = dlfilter,
source = ['TOOLS/vf_dlopen/'+dlfilter+'.c',
'TOOLS/vf_dlopen/filterutils.c'],
includes = [ctx.srcnode.abspath() + '/video/filter'],
features = 'c cshlib',
install_path = ctx.env.LIBDIR + '/mpv' )
if ctx.dependency_satisfied('manpage-build'):
_build_man(ctx)
if ctx.dependency_satisfied('pdf-build'):
_build_pdf(ctx)
ctx.install_files(
ctx.env.DATADIR + '/applications',
['etc/mpv.desktop'] )
for size in '16x16 32x32 64x64'.split():
ctx.install_as(
ctx.env.DATADIR + '/icons/hicolor/' + size + '/apps/mpv.png',
'etc/mpv-icon-8bit-' + size + '.png')