From 7e2edad8efea55e8df1faa695d1389ef4e326d7c Mon Sep 17 00:00:00 2001 From: Stefano Pigozzi Date: Tue, 16 Jul 2013 13:28:28 +0200 Subject: [PATCH] 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. --- .gitignore | 6 + .travis.yml | 5 +- DOCS/crosscompile-mingw.txt | 6 +- DOCS/man/docutils.conf | 1 - DOCS/waf-buildsystem.rst | 151 ++++ README.md | 38 +- TOOLS/osxbundle.py | 20 +- TOOLS/osxbundle/mpv.app/Contents/Info.plist | 2 +- bootstrap.py | 28 + configure => old-configure | 107 +-- Makefile => old-makefile | 5 +- osdep/getch2.c | 1 - video/out/x11_common.c | 6 +- waftools/__init__.py | 2 + waftools/checks/__init__.py | 0 waftools/checks/custom.py | 119 +++ waftools/checks/generic.py | 134 ++++ waftools/dependencies.py | 210 ++++++ waftools/detections/__init__.py | 0 waftools/detections/compiler.py | 57 ++ waftools/detections/cpu.py | 28 + waftools/detections/devices.py | 29 + waftools/features.py | 69 ++ waftools/fragments/cocoa.m | 11 + waftools/fragments/coreaudio.c | 15 + waftools/fragments/dvb.c | 10 + waftools/fragments/ebx.c | 12 + waftools/fragments/gl_x11.c | 9 + waftools/fragments/iconv.c | 30 + waftools/fragments/libavfilter.c | 7 + waftools/fragments/lua.c | 24 + waftools/fragments/lua_libquvi4.c | 3 + waftools/fragments/lua_libquvi9.c | 3 + waftools/fragments/mng.c | 7 + waftools/fragments/oss_audio.c | 11 + waftools/fragments/oss_audio_header.c | 13 + waftools/fragments/pthreads.c | 10 + waftools/fragments/pvr.c | 7 + waftools/fragments/vcd_windows.c | 7 + waftools/fragments/wasapi.c | 19 + waftools/fragments/xf86vm.c | 8 + waftools/fragments/xf86xk.c | 6 + waftools/generators/__init__.py | 0 waftools/generators/headers.py | 36 + waftools/generators/sources.py | 37 + waftools/inflectors.py | 26 + waftools/waf_customizations.py | 46 ++ wscript | 759 ++++++++++++++++++++ wscript_build.py | 459 ++++++++++++ 49 files changed, 2480 insertions(+), 119 deletions(-) create mode 100644 DOCS/waf-buildsystem.rst create mode 100755 bootstrap.py rename configure => old-configure (97%) rename Makefile => old-makefile (99%) create mode 100644 waftools/__init__.py create mode 100644 waftools/checks/__init__.py create mode 100644 waftools/checks/custom.py create mode 100644 waftools/checks/generic.py create mode 100644 waftools/dependencies.py create mode 100644 waftools/detections/__init__.py create mode 100644 waftools/detections/compiler.py create mode 100644 waftools/detections/cpu.py create mode 100644 waftools/detections/devices.py create mode 100644 waftools/features.py create mode 100644 waftools/fragments/cocoa.m create mode 100644 waftools/fragments/coreaudio.c create mode 100644 waftools/fragments/dvb.c create mode 100644 waftools/fragments/ebx.c create mode 100644 waftools/fragments/gl_x11.c create mode 100644 waftools/fragments/iconv.c create mode 100644 waftools/fragments/libavfilter.c create mode 100644 waftools/fragments/lua.c create mode 100644 waftools/fragments/lua_libquvi4.c create mode 100644 waftools/fragments/lua_libquvi9.c create mode 100644 waftools/fragments/mng.c create mode 100644 waftools/fragments/oss_audio.c create mode 100644 waftools/fragments/oss_audio_header.c create mode 100644 waftools/fragments/pthreads.c create mode 100644 waftools/fragments/pvr.c create mode 100644 waftools/fragments/vcd_windows.c create mode 100644 waftools/fragments/wasapi.c create mode 100644 waftools/fragments/xf86vm.c create mode 100644 waftools/fragments/xf86xk.c create mode 100644 waftools/generators/__init__.py create mode 100644 waftools/generators/headers.py create mode 100644 waftools/generators/sources.py create mode 100644 waftools/inflectors.py create mode 100644 waftools/waf_customizations.py create mode 100644 wscript create mode 100644 wscript_build.py diff --git a/.gitignore b/.gitignore index f4361056da..bf482108b7 100644 --- a/.gitignore +++ b/.gitignore @@ -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_* 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 +script: + - ./bootstrap.py + - ./waf configure + - ./waf build notifications-policy: ¬ifications-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 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 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} \makeatletter \renewcommand{\maketitle}{ \begin{center} - \includegraphics{etc/mpv-icon-8bit-64x64.png}\\ \vspace*{-1.5em} \begin{Huge} \@title 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 +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. diff --git a/README.md b/README.md index f1286bea01..2e8c1d75ff 100644 --- a/README.md +++ b/README.md @@ -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 ---------------- diff --git a/TOOLS/osxbundle.py b/TOOLS/osxbundle.py index 6cd2a227c5..66ef576efd 100755 --- a/TOOLS/osxbundle.py +++ b/TOOLS/osxbundle.py @@ -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") diff --git a/TOOLS/osxbundle/mpv.app/Contents/Info.plist b/TOOLS/osxbundle/mpv.app/Contents/Info.plist index f1e2e6f34d..0573b62e44 100644 --- a/TOOLS/osxbundle/mpv.app/Contents/Info.plist +++ b/TOOLS/osxbundle/mpv.app/Contents/Info.plist @@ -183,7 +183,7 @@ CFBundlePackageType APPL CFBundleShortVersionString - {{VERSION}} + ${VERSION} NSHighResolutionCapable CFBundleURLTypes diff --git a/bootstrap.py b/bootstrap.py new file mode 100755 index 0000000000..d855de029b --- /dev/null +++ b/bootstrap.py @@ -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) diff --git a/configure b/old-configure similarity index 97% rename from configure rename to 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" 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 < -#include -#include -#include -#include -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 diff --git a/Makefile b/old-makefile similarity index 99% rename from Makefile rename to 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/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 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; #if HAVE_TERMINFO || HAVE_TERMCAP - static char *term_rmkx = NULL; static char *term_smkx = NULL; diff --git a/video/out/x11_common.c b/video/out/x11_common.c index 09492a2294..54cd063505 100644 --- a/video/out/x11_common.c +++ b/video/out/x11_common.c @@ -50,7 +50,7 @@ #include #endif -#if HAVE_XDPMS +#if HAVE_XEXT #include #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, ¬hing, ¬hing)) { @@ -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, ¬hing, ¬hing)) { BOOL onoff; CARD16 state; diff --git a/waftools/__init__.py b/waftools/__init__.py new file mode 100644 index 0000000000..6f804bce35 --- /dev/null +++ b/waftools/__init__.py @@ -0,0 +1,2 @@ +#!/usr/bin/env python +# encoding: utf-8 diff --git a/waftools/checks/__init__.py b/waftools/checks/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/waftools/checks/custom.py b/waftools/checks/custom.py new file mode 100644 index 0000000000..d2da024037 --- /dev/null +++ b/waftools/checks/custom.py @@ -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 ' + additional_lua_test_code = load_fragment('lua_libquvi4.c') + elif 'libquvi9' in ctx.env.satisfied_deps: + additional_lua_test_header = '#include ' + 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) diff --git a/waftools/checks/generic.py b/waftools/checks/generic.py new file mode 100644 index 0000000000..46813aed01 --- /dev/null +++ b/waftools/checks/generic.py @@ -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 diff --git a/waftools/dependencies.py b/waftools/dependencies.py new file mode 100644 index 0000000000..cd85180fae --- /dev/null +++ b/waftools/dependencies.py @@ -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 diff --git a/waftools/detections/__init__.py b/waftools/detections/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/waftools/detections/compiler.py b/waftools/detections/compiler.py new file mode 100644 index 0000000000..1fee446409 --- /dev/null +++ b/waftools/detections/compiler.py @@ -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__) + diff --git a/waftools/detections/cpu.py b/waftools/detections/cpu.py new file mode 100644 index 0000000000..ce342fdd73 --- /dev/null +++ b/waftools/detections/cpu.py @@ -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) diff --git a/waftools/detections/devices.py b/waftools/detections/devices.py new file mode 100644 index 0000000000..2533788691 --- /dev/null +++ b/waftools/detections/devices.py @@ -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)) diff --git a/waftools/features.py b/waftools/features.py new file mode 100644 index 0000000000..1385d41dbf --- /dev/null +++ b/waftools/features.py @@ -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 diff --git a/waftools/fragments/cocoa.m b/waftools/fragments/cocoa.m new file mode 100644 index 0000000000..6e0e4d32b4 --- /dev/null +++ b/waftools/fragments/cocoa.m @@ -0,0 +1,11 @@ +#import +#import +#import + +int main(int argc, char **argv) { + @autoreleasepool { + NSArray *ary = @[@1, @2, @3]; + NSLog(@"test subscripting: %@", ary[0]); + NSApplicationLoad(); + } +} diff --git a/waftools/fragments/coreaudio.c b/waftools/fragments/coreaudio.c new file mode 100644 index 0000000000..c7411311a7 --- /dev/null +++ b/waftools/fragments/coreaudio.c @@ -0,0 +1,15 @@ +#include +#include +#include + +int main(int argc, char **argv) +{ + AudioComponentDescription desc = (AudioComponentDescription) { + .componentType = kAudioUnitType_Output, + .componentSubType = kAudioUnitSubType_DefaultOutput, + .componentManufacturer = kAudioUnitManufacturer_Apple, + }; + + AudioComponentFindNext(NULL, &desc); + return 0; +} diff --git a/waftools/fragments/dvb.c b/waftools/fragments/dvb.c new file mode 100644 index 0000000000..9deaa1eaab --- /dev/null +++ b/waftools/fragments/dvb.c @@ -0,0 +1,10 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +int main(void) {return 0;} diff --git a/waftools/fragments/ebx.c b/waftools/fragments/ebx.c new file mode 100644 index 0000000000..b487939c56 --- /dev/null +++ b/waftools/fragments/ebx.c @@ -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; +} diff --git a/waftools/fragments/gl_x11.c b/waftools/fragments/gl_x11.c new file mode 100644 index 0000000000..6c617d43ee --- /dev/null +++ b/waftools/fragments/gl_x11.c @@ -0,0 +1,9 @@ +#include +#include +#include + +int main(int argc, char *argv[]) { + glXCreateContext(NULL, NULL, NULL, True); + glFinish(); + return 0; +} diff --git a/waftools/fragments/iconv.c b/waftools/fragments/iconv.c new file mode 100644 index 0000000000..78c963b643 --- /dev/null +++ b/waftools/fragments/iconv.c @@ -0,0 +1,30 @@ +#include +#include +#include +#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; +} diff --git a/waftools/fragments/libavfilter.c b/waftools/fragments/libavfilter.c new file mode 100644 index 0000000000..4e1986f4a2 --- /dev/null +++ b/waftools/fragments/libavfilter.c @@ -0,0 +1,7 @@ +#include +void vf_next_query_format() {} +int main(void) { + avfilter_register_all(); + vf_next_query_format(); + return 0; +} diff --git a/waftools/fragments/lua.c b/waftools/fragments/lua.c new file mode 100644 index 0000000000..43d678b476 --- /dev/null +++ b/waftools/fragments/lua.c @@ -0,0 +1,24 @@ +#include +#include +#include +#include + +// 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; +}} diff --git a/waftools/fragments/lua_libquvi4.c b/waftools/fragments/lua_libquvi4.c new file mode 100644 index 0000000000..efcf30375a --- /dev/null +++ b/waftools/fragments/lua_libquvi4.c @@ -0,0 +1,3 @@ + quvi_t q; + if (quvi_init(&q) == QUVI_OK) + quvi_supported(q, "http://nope"); diff --git a/waftools/fragments/lua_libquvi9.c b/waftools/fragments/lua_libquvi9.c new file mode 100644 index 0000000000..e25ea1a462 --- /dev/null +++ b/waftools/fragments/lua_libquvi9.c @@ -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); diff --git a/waftools/fragments/mng.c b/waftools/fragments/mng.c new file mode 100644 index 0000000000..7befc7e895 --- /dev/null +++ b/waftools/fragments/mng.c @@ -0,0 +1,7 @@ +#include + +int main(int argc, char **argv) +{ + const char * p_ver = mng_version_text(); + return !p_ver || p_ver[0] == 0; +} diff --git a/waftools/fragments/oss_audio.c b/waftools/fragments/oss_audio.c new file mode 100644 index 0000000000..e23979da97 --- /dev/null +++ b/waftools/fragments/oss_audio.c @@ -0,0 +1,11 @@ +#if HAVE_SOUNDCARD_H +#include +#endif + +#if HAVE_SYS_SOUNDCARD_H +#include +#endif + +int main(int argc, char **argv) { + return SNDCTL_DSP_SETFRAGMENT; +} diff --git a/waftools/fragments/oss_audio_header.c b/waftools/fragments/oss_audio_header.c new file mode 100644 index 0000000000..980eb69215 --- /dev/null +++ b/waftools/fragments/oss_audio_header.c @@ -0,0 +1,13 @@ +#if HAVE_SOUNDCARD_H +#include +#endif + +#if HAVE_SYS_SOUNDCARD_H +#include +#endif + +#ifdef OPEN_SOUND_SYSTEM +int main(void) {{ return 0; }} +#else +#error Not the real thing +#endif diff --git a/waftools/fragments/pthreads.c b/waftools/fragments/pthreads.c new file mode 100644 index 0000000000..6702f36f97 --- /dev/null +++ b/waftools/fragments/pthreads.c @@ -0,0 +1,10 @@ +#include +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; +} diff --git a/waftools/fragments/pvr.c b/waftools/fragments/pvr.c new file mode 100644 index 0000000000..be301e11e5 --- /dev/null +++ b/waftools/fragments/pvr.c @@ -0,0 +1,7 @@ +#include +#include +int main(void) +{ + struct v4l2_ext_controls ext; + return ext.controls->value; +} diff --git a/waftools/fragments/vcd_windows.c b/waftools/fragments/vcd_windows.c new file mode 100644 index 0000000000..8d33127043 --- /dev/null +++ b/waftools/fragments/vcd_windows.c @@ -0,0 +1,7 @@ +#include +#include + +int main(int argc, char **argv) +{ + return 0; +} diff --git a/waftools/fragments/wasapi.c b/waftools/fragments/wasapi.c new file mode 100644 index 0000000000..ef3b3f7866 --- /dev/null +++ b/waftools/fragments/wasapi.c @@ -0,0 +1,19 @@ +#define COBJMACROS 1 +#define _WIN32_WINNT 0x600 +#include +#include +#include +#include +#include +#include +#include +#include + const GUID *check1[] = { + &IID_IAudioClient, + &IID_IAudioRenderClient, + &IID_IAudioClient, + &IID_IAudioEndpointVolume, + }; +int main(void) { + return 0; +} diff --git a/waftools/fragments/xf86vm.c b/waftools/fragments/xf86vm.c new file mode 100644 index 0000000000..195e514d6c --- /dev/null +++ b/waftools/fragments/xf86vm.c @@ -0,0 +1,8 @@ +#include +#include + +int main(int argc, char **argv) +{ + XF86VidModeQueryExtension(0, 0, 0); + return 0; +} diff --git a/waftools/fragments/xf86xk.c b/waftools/fragments/xf86xk.c new file mode 100644 index 0000000000..541e7ce3af --- /dev/null +++ b/waftools/fragments/xf86xk.c @@ -0,0 +1,6 @@ +#include + +int main(int argc, char **argv) +{ + return XF86XK_AudioPause; +} diff --git a/waftools/generators/__init__.py b/waftools/generators/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/waftools/generators/headers.py b/waftools/generators/headers.py new file mode 100644 index 0000000000..13f124a2dd --- /dev/null +++ b/waftools/generators/headers.py @@ -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) diff --git a/waftools/generators/sources.py b/waftools/generators/sources.py new file mode 100644 index 0000000000..1248ad90b4 --- /dev/null +++ b/waftools/generators/sources.py @@ -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__ diff --git a/waftools/inflectors.py b/waftools/inflectors.py new file mode 100644 index 0000000000..3641de8818 --- /dev/null +++ b/waftools/inflectors.py @@ -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() diff --git a/waftools/waf_customizations.py b/waftools/waf_customizations.py new file mode 100644 index 0000000000..b6798d4235 --- /dev/null +++ b/waftools/waf_customizations.py @@ -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) diff --git a/wscript b/wscript new file mode 100644 index 0000000000..bd86c98bb5 --- /dev/null +++ b/wscript @@ -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') diff --git a/wscript_build.py b/wscript_build.py new file mode 100644 index 0000000000..38ea141b3d --- /dev/null +++ b/wscript_build.py @@ -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')