From 6551ea5bd3e9781e3740e99a00c56a49917d5fc9 Mon Sep 17 00:00:00 2001 From: wm4 Date: Fri, 21 Jun 2019 02:13:48 +0200 Subject: new build system Further changes by the following people: James Ross-Gowan : win32 fixes --- DOCS/build-system.rst | 199 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100644 DOCS/build-system.rst (limited to 'DOCS/build-system.rst') diff --git a/DOCS/build-system.rst b/DOCS/build-system.rst new file mode 100644 index 0000000000..8b8f122e6d --- /dev/null +++ b/DOCS/build-system.rst @@ -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. + +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. + +Example: + + ./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. + +Big picture +=========== + +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:: + +check("-vdpau*", + desc = "VDPAU acceleration", + deps = "x11", + fn = lambda: check_pkg_config("vdpau >= 0.2"), + sources = ["video/filter/vf_vdpaupp.c", + "video/out/vo_vdpau.c", + "video/vdpau.c", + "video/vdpau_mixer.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. + +Configure tests +--------------- + +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:: + +check("-vapoursynth*", + 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.) + +Source files +------------ + +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. + +Makefile +-------- + +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. + +Variables: + + ``BUILD`` + The directory for build output. Can be a relative path, usually set to + ``build``. + ``ROOT`` + 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 ``.``. -- cgit v1.2.3