Diffstat (limited to 'DOCS/build-system.rst')
1 files changed, 199 insertions, 0 deletions
diff --git a/DOCS/build-system.rst b/DOCS/build-system.rst
new file mode 100644
@@ -0,0 +1,199 @@
+Build system overview
+mpv's new build system is based on Python and completely replaces the previous
+./waf build system.
+This file describes internals. See the README in the top level directory for
+User help (to be moved to README.md)
+Compiling with full features requires development files for several
+external libraries. Below is a list of some important requirements.
+For a list of the available build options use `./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.
+NOTE: To avoid cluttering the output with unreadable spam, `--help` only shows
+one of the many switches for each option. If the option is autodetected by
+default, the `--disable-***` switch is printed; if the option is disabled by
+default, the `--enable-***` switch is printed. Either way, you can use
+`--enable-***` or `--disable-***` regardless of what is printed by `--help`.
+By default, most features are auto-detected. You can use ``--with-***=option``
+to get finer control over whether auto-detection is used for a feature.
+ ./configure && make -j20
+If everything goes well, the mpv binary is created in the ``build`` directory.
+`make` alone can be used to rebuild parts of the player. On update, it's
+recommended to run `make dist-clean` and to rerun configure.
+See `./configure --help` for advanced usage.
+Motivation & Requirements
+It's unclear what the fuck the author of the new build system was thinking.
+The configure script is written in Python. It generates config.h and config.mak
+files (and possibly more). By default these are written to a newly created
+"build" directory. It also writes a build.log.
+The "actual" build system is based on GNU make (other make variants probably
+won't work). The Makefile in the project root is manually created by the build
+system "user" (i.e. the mpv developers), and is fixed and not changed by
+configure. It includes the configured-generated build/config.mak file for the
+variable parts. It also includes Header file dependencies are handled
+automatically with the ``-MD`` option (which the compiler must support).
+For out-of-tree builds, a small Makefile is generated that includes the one
+from the source directory. Simply call configure from another directory.
+(Note: this is broken, fails at generated files, and is also ugly.)
+By default, it attempts not to write any build output to the source tree, except
+to the "build" directory.
+Comparison to previous waf build system
+The new configure uses the same concept as our custom layer above waf, which
+made the checks generally declarative. In fact, most checks were ported
+straight, changing only to the new syntax.
+Some of the internal and user-visible conventions are extremely similar. For
+example, the new system creates a build dir and writes to it by default.
+The choice of Python as implementation language is unfortunate. Shell was
+considered, but discarded for being too fragile, error prone, and PITA-ish.
+Lua would be reasonable, but is too fragmented, and requires external
+dependencies to do meaningful UNIX scripting. There is nothing else left that
+is widely supported enough, does not require external dependencies, and which
+isn't something that I would not touch without gloves. Bootstrapping a system
+implemented in C was considered, but deemed too problematic.
+mpv's custom configure
+All of the configuration process is handled with a mostly-declarative approach.
+Each configure check is a call to a "check" function, which takes various named
+arguments. The check function is obviously always called, even if the
+corresponding feature is disabled.
+A simple example using pkg-config would be::
+ desc = "VDPAU acceleration",
+ deps = "x11",
+ fn = lambda: check_pkg_config("vdpau >= 0.2"),
+ sources = ["video/filter/vf_vdpaupp.c",
+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 succeeds a ``#define HAVE_VDPAU 1`` will be added to
+``config.h``, if not ``#define HAVE_VDPAU 0`` will be added (the ``*`` on the
+feature name triggers emitting of such defines).
+The defines names are automatically prepended with ``HAVE_``, capitalized, and
+some special characters are replaced with underscores.
+If the test succeeds, the listed source files are added to the build.
+Read the inline-documentation on the check function in configure_common.py for
+details. The following text only gives a crude overview.
+The check function has a ``fn`` parameter. This function is called when it's
+time to perform actual configure checks. Most check calls in configure make
+this a lambda, so the actual code to run can be passed inline as a function
+argument. (This is similar to the old waf based system, just that functions
+like check_pkg_config returned a function as result, which hid the indirection.)
+One central function is ``check_cc``. It's quite similar to the waf-native
+function with the same name. One difference is that there is no ``mandatory``
+option - instead it always returns a bool for success. On success, the passed
+build flags are appended to the check's build flags. This makes it easier to
+compose checks. For example::
+check(desc = "C11/C99",
+ fn = lambda: check_cc(flags = "-std=c11") or
+ check_cc(flags = "-std=c99"),
+ required = "No C11 or C99 support.")
+This tries to use -std=c11, but allows a fallback to -std=c99.
+If the entire check fails, none of the added build flags are added. For example,
+you could chain multiple tests like this::
+ fn = lambda: check_pkg_config("vapoursynth >= 24") and
+ check_pkg_config("vapoursynth-script >= 23"))
+If the second check fails, the final executable won't link to ``vapoursynth``.
+(Note that this test could just make a single check_pkg_config call, and pass
+each dependency as separate argument.)
+configure generates the list of source files and writes it to config.mak. You
+can add source files at any point in configure, but normally they're added with
+the ``sources`` parameter in each feature check. This is done because a larger
+number of source files depend on configure options, so having it all in the same
+place as the check is slightly nicer than having a separate conditional mess in
+the fixed Makefile.
+Configure phases, non-declarative actions
+configure was written to be as single-pass as possible. It doesn't even put the
+checks in any lists or so (except for the outcome). Handling of ``--enable-...``
+etc. options is done while running configure. If you pass e.g.
+``--enable-doesntexist``, configure will complain about an unknown
+``doesntexist`` feature only once all checks have been actually run.
+Although this is slightly weird, it is done so that the ``configure`` file
+itself can be a flat file with simple top-down execution. It enables you to add
+arbitrary non-declarative checks and such between the ``check`` calls.
+One thing you need to be aware of is that if ``--help`` was passed to configure,
+it will run in "help mode". You may have to use ``is_running()`` to check
+whether it's in a mode where checks are actually executed. Outside of this mode,
+``dep_enabled()`` will fail.
+Although most source files are added from configure, this build system still
+may require you to write some make. In particular, generated files are not
+handled by configure.
+make is bad. It's hard to use, hard to debug, and extremely fragile. It may be
+replaced by something else in the future, including the possibility of turning
+configure into waf-light.
+ The directory for build output. Can be a relative path, usually set to
+ The directory that contains ``configure``. Usually the root directory
+ of the repository. Source files need to be addressed relative to this
+ path. Can be a relative path, usually set to ``.``.