diff options
authorStefano Pigozzi <>2013-07-16 13:28:28 +0200
committerStefano Pigozzi <>2013-11-21 21:22:36 +0100
commit7e2edad8efea55e8df1faa695d1389ef4e326d7c (patch)
parent0cb9227a73f03a6ecdf71e837c7c33c823b194b4 (diff)
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 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.
-rwxr-xr-xold-configure (renamed from configure)107
-rw-r--r--old-makefile (renamed from Makefile)5
49 files changed, 2480 insertions, 119 deletions
diff --git a/.gitignore b/.gitignore
index f4361056da..bf482108b7 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,6 +2,7 @@
@@ -25,3 +26,8 @@
diff --git a/.travis.yml b/.travis.yml
index 4e497eea82..5fc66cd2f2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -13,7 +13,10 @@ branches:
- ci
before_install: ./travis-deps libass-stable $LIBAV
-script: ./configure && make
+ - ./
+ - ./waf configure
+ - ./waf build
notifications-policy: &notifications-policy
on_success: change
diff --git a/DOCS/crosscompile-mingw.txt b/DOCS/crosscompile-mingw.txt
index 8ad59c693f..b971dffdc5 100644
--- a/DOCS/crosscompile-mingw.txt
+++ b/DOCS/crosscompile-mingw.txt
@@ -3,7 +3,7 @@ produce both 32 bit and 64 bit executables. MinGW-w64 is available from
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):
@@ -44,8 +44,8 @@ make pthreads
git clone
cd mpv
export PATH=/opt/mingw/usr/bin/:$PATH
-./configure --enable-cross-compile --target=i686-w64-mingw32
+DEST_OS=win32 TARGET=i686-w64-mingw32 ./waf configure
+./waf build
# This should work. Note however that MXE’s ffmpeg package might be very old
# in order to avoid breaking e.g. xine-lib, so you might want to update that
diff --git a/DOCS/man/docutils.conf b/DOCS/man/docutils.conf
index cd6e3acd52..2e4d0dcf43 100644
--- a/DOCS/man/docutils.conf
+++ b/DOCS/man/docutils.conf
@@ -10,7 +10,6 @@ latex-preamble: \usepackage[usenames,dvipsnames]{xcolor}
- \includegraphics{etc/mpv-icon-8bit-64x64.png}\\
diff --git a/DOCS/waf-buildsystem.rst b/DOCS/waf-buildsystem.rst
new file mode 100644
index 0000000000..ca52531501
--- /dev/null
+++ b/DOCS/waf-buildsystem.rst
@@ -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
+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
+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
+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
+``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
+``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/``.
+Also ``dependencies_use`` and ``dependencies_includes`` collect cflags and
+ldflags that were generated from the features checks in the configure step.
diff --git a/ b/
index f1286bea01..2e8c1d75ff 100644
--- a/
+++ b/
@@ -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 './' 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
+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
-### 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
FFmpeg vs. Libav
diff --git a/TOOLS/ b/TOOLS/
index 6cd2a227c5..66ef576efd 100755
--- a/TOOLS/
+++ b/TOOLS/
@@ -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 "" % 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))
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")
diff --git a/TOOLS/osxbundle/ b/TOOLS/osxbundle/
index f1e2e6f34d..0573b62e44 100644
--- a/TOOLS/osxbundle/
+++ b/TOOLS/osxbundle/
@@ -183,7 +183,7 @@
- <string>{{VERSION}}</string>
+ <string>${VERSION}</string>
diff --git a/ b/
new file mode 100755
index 0000000000..d855de029b
--- /dev/null
+++ b/
@@ -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
+ from urllib.request import urlopen
+ from urllib2 import urlopen
+WAFRELEASE = "waf-1.7.13"
+SHA256HASH = "03cc750049350ee01cdbc584b70924e333fcc17ba4a2d04648dab1535538a873"
+waf = urlopen("" + 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.")
+ print("The checksum of the downloaded file does not match!")
+ print("Please download and verify the file manually.")
+ sys.exit(1)
diff --git a/configure b/old-configure
index 0618c05594..fe77403c6b 100755
--- a/configure
+++ b/old-configure
@@ -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"
if test "$_x11" = yes ; then
def_x11='#define HAVE_X11 1'
@@ -1797,36 +1751,19 @@ else
echores "$_xss"
-echocheck "DPMS"
+echocheck "X extensions"
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; }
- 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"
-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"
- def_xdpms='#define HAVE_XDPMS 0'
+ def_xext='#define HAVE_XEXT 0'
echores "no"
echocheck "Xv"
if test "$_xv" = auto && test "$_x11" = yes ; then
+# 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
+rm -rf old_build
+mkdir old_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
-CXXFLAGS = $WARNFLAGS $ERRORFLAGS $CXXFLAGS $extra_cflags $extra_cxxflags
EXTRALIBS = $extra_ldflags $_ld_static $_ld_lm $extra_libs $libs_mplayer $end_ldflags
@@ -3530,7 +3479,7 @@ $def_vaapi_hwaccel
@@ -3555,7 +3504,7 @@ $def_pthreads
# 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.
if test "$warn_cflags" = yes; then
diff --git a/Makefile b/old-makefile
index 9323b2e72a..a6902fbb1a 100644
--- a/Makefile
+++ b/old-makefile
@@ -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/
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/
$(RM) $@; find . -name '*.[chS]' -o -name '*.asm' | xargs etags -a
diff --git a/osdep/getch2.c b/osdep/getch2.c
index ccfef64ac0..b189a678db 100644
--- a/osdep/getch2.c
+++ b/osdep/getch2.c
@@ -73,7 +73,6 @@ static keycode_map getch2_keys;