├── patches ├── vpx-sys-types.patch ├── rtmpdump-win32-make.patch └── fdk_aac-win32-make.patch ├── profiles ├── mac-x86_64.local ├── linux-x86_64.local ├── mingw-msys-x86_64.local ├── linux-x86.local ├── mingw-msys-x86.local ├── mingw-x86.local ├── mingw-x86_64.local ├── msvc-15-x86.local └── msvc-15-x86_64.local ├── libs ├── gmp.sh ├── nettle.sh ├── gnutls.sh ├── x264.sh ├── fdk_aac.sh ├── rtmp.sh ├── speex.sh ├── lame.sh ├── openssl.sh ├── ogg.sh ├── vorbis.sh ├── opus.sh ├── zlib.sh ├── vpx.sh ├── ffmpeg.sh └── x265.sh ├── windows ├── vc-32.bat └── vc-64.bat ├── README.md └── ffmpeg-builder.sh /patches/vpx-sys-types.patch: -------------------------------------------------------------------------------- 1 | --- vp8/common/threading.h 2016-03-27 16:05:21.276039443 +0200 2 | +++ vp8/common/threading.h 2016-03-27 14:43:56.983785000 +0200 3 | @@ -66,6 +66,7 @@ 4 | #include 5 | 6 | #else 7 | +#include 8 | #include 9 | #endif 10 | 11 | -------------------------------------------------------------------------------- /profiles/mac-x86_64.local: -------------------------------------------------------------------------------- 1 | # 2 | # mac-x86_64.local 3 | # 4 | 5 | ARCH="x86_64" 6 | TARGET_OS="darwin" 7 | 8 | PKG_CONFIG_PATH="$FF_PREFIX/lib/pkgconfig" 9 | CPPFLAGS="-I$FF_PREFIX/include -fPIC" 10 | LDFLAGS="-L$FF_PREFIX/lib" 11 | 12 | 13 | export CPPFLAGS LDFLAGS 14 | export PKG_CONFIG_PATH 15 | export PKG_CONFIG_LIBDIR= -------------------------------------------------------------------------------- /profiles/linux-x86_64.local: -------------------------------------------------------------------------------- 1 | # 2 | # linux-x86_64.local 3 | # 4 | 5 | ARCH="x86_64" 6 | TARGET_OS="linux64" 7 | HOST="x86_64-pc-linux-gnu" 8 | 9 | PKG_CONFIG_PATH="$FF_PREFIX/lib/pkgconfig" 10 | CPPFLAGS="-I$FF_PREFIX/include -fPIC" 11 | LDFLAGS="-L$FF_PREFIX/lib" 12 | 13 | 14 | export CPPFLAGS LDFLAGS 15 | export PKG_CONFIG_PATH 16 | export PKG_CONFIG_LIBDIR= 17 | export HOST 18 | -------------------------------------------------------------------------------- /profiles/mingw-msys-x86_64.local: -------------------------------------------------------------------------------- 1 | # 2 | # mingw-msys-x86_64.local 3 | # 4 | 5 | ARCH="x86_64" 6 | TARGET_OS="mingw64" 7 | HOST="x86_64-w64-mingw32" 8 | 9 | PKG_CONFIG_PATH="$FF_PREFIX/lib/pkgconfig" 10 | CPPFLAGS="-I$FF_PREFIX/include -fPIC" 11 | LDFLAGS="-L$FF_PREFIX/lib" 12 | 13 | 14 | export CPPFLAGS LDFLAGS 15 | export PKG_CONFIG_PATH 16 | export PKG_CONFIG_LIBDIR= 17 | export HOST 18 | -------------------------------------------------------------------------------- /profiles/linux-x86.local: -------------------------------------------------------------------------------- 1 | # 2 | # linux-x86.local 3 | # 4 | 5 | ARCH="x86" 6 | TARGET_OS="linux32" 7 | HOST="i686-pc-linux-gnu" 8 | 9 | PKG_CONFIG_PATH="$FF_PREFIX/lib/pkgconfig" 10 | CPPFLAGS="-I$FF_PREFIX/include -m32" 11 | CXXFLAGS="-m32" 12 | CFLAGS="-m32" 13 | LDFLAGS="-L$FF_PREFIX/lib -m32" 14 | 15 | 16 | export CPPFLAGS CXXFLAGS CFLAGS LDFLAGS 17 | export PKG_CONFIG_PATH 18 | export PKG_CONFIG_LIBDIR= 19 | export HOST 20 | -------------------------------------------------------------------------------- /profiles/mingw-msys-x86.local: -------------------------------------------------------------------------------- 1 | # 2 | # mingw-msys-x86.local 3 | # 4 | 5 | ARCH="x86" 6 | TARGET_OS="mingw32" 7 | HOST="i686-w64-mingw32" 8 | 9 | PKG_CONFIG_PATH="$FF_PREFIX/lib/pkgconfig" 10 | CPPFLAGS="-I$FF_PREFIX/include -m32" 11 | CXXFLAGS="-m32" 12 | CFLAGS="-m32" 13 | LDFLAGS="-L$FF_PREFIX/lib -m32" 14 | 15 | 16 | export CPPFLAGS CXXFLAGS CFLAGS LDFLAGS 17 | export PKG_CONFIG_PATH 18 | export PKG_CONFIG_LIBDIR= 19 | export HOST 20 | -------------------------------------------------------------------------------- /libs/gmp.sh: -------------------------------------------------------------------------------- 1 | gmp_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | gmp_fetch() { 6 | download_and_extract https://gmplib.org/download/gmp/gmp-6.1.1.tar.xz $1 7 | } 8 | 9 | gmp_clean() { 10 | make clean 11 | } 12 | 13 | gmp_configure() { 14 | add_host_and_prefix config "--enable-static --disable-shared --enable-pic" 15 | ./configure $config 16 | } 17 | 18 | gmp_make() { 19 | make 20 | } 21 | 22 | gmp_install() { 23 | make install 24 | } 25 | 26 | gmp_enable() { 27 | : 28 | } 29 | -------------------------------------------------------------------------------- /libs/nettle.sh: -------------------------------------------------------------------------------- 1 | nettle_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | nettle_fetch() { 6 | download_and_extract https://ftp.gnu.org/gnu/nettle/nettle-3.2.tar.gz $1 7 | } 8 | 9 | nettle_clean() { 10 | make clean 11 | } 12 | 13 | nettle_configure() { 14 | add_host_and_prefix config "--enable-static --disable-shared --enable-pic" 15 | ./configure $config 16 | } 17 | 18 | nettle_make() { 19 | make 20 | } 21 | 22 | nettle_install() { 23 | make install 24 | } 25 | 26 | nettle_enable() { 27 | : 28 | } 29 | -------------------------------------------------------------------------------- /windows/vc-32.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | :: Opens Visual Studio x86 Native Command Prompt. 4 | 5 | :: Get Visual Studio version. 6 | for /F "skip=2" %%a in ('reg query "HKLM\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /s') do ( 7 | set VS_VERSION=%%a 8 | ) 9 | 10 | :: Get Visual Studio install path. 11 | for /F "tokens=1,2*" %%a in ('reg query "HKLM\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /v "%VS_VERSION%"') do ( 12 | set VS_DIR=%%c 13 | ) 14 | 15 | TITLE VS-%VS_VERSION% x86 Native Tools 16 | 17 | cd "%VS_DIR%VC\" 18 | %comspec% /k vcvarsall.bat x86 -------------------------------------------------------------------------------- /windows/vc-64.bat: -------------------------------------------------------------------------------- 1 | @ECHO OFF 2 | 3 | :: Opens Visual Studio x64 Native Command Prompt. 4 | 5 | :: Get Visual Studio version. 6 | for /F "skip=2" %%a in ('reg query "HKLM\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /s') do ( 7 | set VS_VERSION=%%a 8 | ) 9 | 10 | :: Get Visual Studio install path. 11 | for /F "tokens=1,2*" %%a in ('reg query "HKLM\SOFTWARE\Microsoft\VisualStudio\SxS\VS7" /v "%VS_VERSION%"') do ( 12 | set VS_DIR=%%c 13 | ) 14 | 15 | TITLE VS-%VS_VERSION% x64 Native Tools 16 | 17 | cd "%VS_DIR%VC\" 18 | %comspec% /k vcvarsall.bat amd64 -------------------------------------------------------------------------------- /profiles/mingw-x86.local: -------------------------------------------------------------------------------- 1 | # 2 | # mingw-x86.local 3 | # 4 | 5 | ARCH="x86" 6 | TARGET_OS="mingw32" 7 | HOST="i686-w64-mingw32" 8 | 9 | MINGW=$(locate -n 1 i686-w64-mingw32-gcc | sed 's/\.*\/bin.*//') 10 | TOOL_CHAIN_PREFIX="$MINGW/bin/i686-w64-mingw32-" 11 | 12 | PKG_CONFIG_PATH="$FF_PREFIX/lib/pkgconfig" 13 | CPPFLAGS="-I$FF_PREFIX/include -I$MINGW/include" 14 | LDFLAGS="-L$FF_PREFIX/lib -L$MINGW/lib" 15 | PATH="$MINGW/bin:$PATH" 16 | 17 | 18 | export CPPFLAGS LDFLAGS 19 | export PKG_CONFIG_PATH 20 | export PKG_CONFIG_LIBDIR= 21 | export PATH 22 | export TOOL_CHAIN_PREFIX 23 | export HOST 24 | -------------------------------------------------------------------------------- /profiles/mingw-x86_64.local: -------------------------------------------------------------------------------- 1 | # 2 | # mingw-x86_64.local 3 | # 4 | 5 | ARCH="x86_64" 6 | TARGET_OS="mingw64" 7 | HOST="x86_64-w64-mingw32" 8 | 9 | MINGW=$(locate -n 1 x86_64-w64-mingw32-gcc | sed 's/\.*\/bin.*//') 10 | TOOL_CHAIN_PREFIX="$MINGW/bin/x86_64-w64-mingw32-" 11 | 12 | PKG_CONFIG_PATH="$FF_PREFIX/lib/pkgconfig" 13 | CPPFLAGS="-I$FF_PREFIX/include -I$MINGW/include" 14 | LDFLAGS="-L$FF_PREFIX/lib -L$MINGW/lib" 15 | PATH="$MINGW/bin:$PATH" 16 | 17 | 18 | export CPPFLAGS LDFLAGS 19 | export PKG_CONFIG_PATH 20 | export PKG_CONFIG_LIBDIR= 21 | export PATH 22 | export TOOL_CHAIN_PREFIX 23 | export HOST 24 | -------------------------------------------------------------------------------- /libs/gnutls.sh: -------------------------------------------------------------------------------- 1 | gnutls_dependencies() { 2 | eval $1="'gmp nettle'" 3 | } 4 | 5 | gnutls_fetch() { 6 | download_and_extract ftp://ftp.gnutls.org/gcrypt/gnutls/v3.4/gnutls-3.4.14.tar.xz $1 7 | } 8 | 9 | gnutls_clean() { 10 | make clean 11 | } 12 | 13 | gnutls_configure() { 14 | add_host_and_prefix config "--enable-static --disable-shared --enable-pic --disable-doc --disable-tools --with-included-libtasn1 --without-tpm --without-p11-kit --without-idn" 15 | ./configure $config 16 | } 17 | 18 | gnutls_make() { 19 | make 20 | } 21 | 22 | gnutls_install() { 23 | make install 24 | } 25 | 26 | gnutls_install_mingw() { 27 | make install 28 | 29 | sed -i '/Libs.private: / s/$/& -lcrypt32/' $PKG_CONFIG_PATH/gnutls.pc 30 | } 31 | 32 | gnutls_enable() { 33 | : 34 | } 35 | -------------------------------------------------------------------------------- /profiles/msvc-15-x86.local: -------------------------------------------------------------------------------- 1 | # 2 | # msvc-15-x86.local 3 | # 4 | 5 | ARCH="i386" 6 | TARGET_OS="win32" 7 | TOOLCHAIN="msvc" 8 | HOST="i686-w64-mingw32" 9 | 10 | VC_PATH="$VCINSTALLDIR/BIN" 11 | RC_PATH="$WindowsSdkDir/bin/x86" 12 | CMAKE_PATH="/mingw32/bin" 13 | PERL_PATH=$(reg query "HKLM\\SOFTWARE\\Perl" -ve | sed -n -e "s/^.*REG_SZ //p")bin 14 | MSBUILD_PATH=$(reg query "HKLM\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\$VisualStudioVersion" -v MSBuildToolsPath | sed -n -e "s/^.*REG_SZ //p") 15 | 16 | PKG_CONFIG_PATH="$FF_PREFIX/lib/pkgconfig" 17 | CPPFLAGS="-I$FF_PREFIX/include" 18 | LDFLAGS="-LIBPATH:$FF_PREFIX/lib" 19 | PATH="$VC_PATH:$RC_PATH:$CMAKE_PATH:$PERL_PATH:$MSBUILD_PATH:$PATH" 20 | 21 | 22 | export PATH 23 | export HOST 24 | export PKG_CONFIG_PATH 25 | export PKG_CONFIG_LIBDIR= 26 | -------------------------------------------------------------------------------- /profiles/msvc-15-x86_64.local: -------------------------------------------------------------------------------- 1 | # 2 | # msvc-15-x86_64.local 3 | # 4 | 5 | ARCH="x86_64" 6 | TARGET_OS="win64" 7 | TOOLCHAIN="msvc" 8 | HOST="x86_64-w64-mingw32" 9 | 10 | VC_PATH="$VCINSTALLDIR/BIN/amd64" 11 | RC_PATH="$WindowsSdkDir/bin/x64" 12 | CMAKE_PATH="/mingw64/bin" 13 | PERL_PATH=$(reg query "HKLM\\SOFTWARE\\Perl" -ve | sed -n -e "s/^.*REG_SZ //p")bin 14 | MSBUILD_PATH=$(reg query "HKLM\\SOFTWARE\\Microsoft\\MSBuild\\ToolsVersions\\$VisualStudioVersion" -v MSBuildToolsPath | sed -n -e "s/^.*REG_SZ //p") 15 | 16 | PKG_CONFIG_PATH="$FF_PREFIX/lib/pkgconfig" 17 | CPPFLAGS="-I$FF_PREFIX/include" 18 | LDFLAGS="-LIBPATH:$FF_PREFIX/lib" 19 | PATH="$VC_PATH:$RC_PATH:$CMAKE_PATH:$PERL_PATH:$MSBUILD_PATH:$PATH" 20 | 21 | 22 | export PATH 23 | export HOST 24 | export PKG_CONFIG_PATH 25 | export PKG_CONFIG_LIBDIR= 26 | -------------------------------------------------------------------------------- /libs/x264.sh: -------------------------------------------------------------------------------- 1 | x264_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | x264_fetch() { 6 | do_git_checkout "git://git.videolan.org/x264.git" $1 7 | } 8 | 9 | x264_clean() { 10 | make clean 11 | } 12 | 13 | x264_set_params() { 14 | local __resultvar=$1 15 | local options=$2 16 | 17 | add_host_and_prefix params "--enable-static --disable-opencl --disable-cli --enable-pic $options" 18 | 19 | eval $__resultvar='$params' 20 | } 21 | 22 | x264_configure() { 23 | x264_set_params config 24 | ./configure $config 25 | } 26 | 27 | x264_configure_mingw() { 28 | x264_set_params config "--cross-prefix=$TOOL_CHAIN_PREFIX" 29 | ./configure $config 30 | } 31 | 32 | x264_configure_win() { 33 | x264_set_params config "--extra-cflags=-DNO_PREFIX" 34 | CC=cl ./configure $config 35 | } 36 | 37 | x264_make() { 38 | make 39 | } 40 | 41 | x264_install() { 42 | make install 43 | } 44 | 45 | x264_enable() { 46 | enable_library "libx264" 47 | } 48 | -------------------------------------------------------------------------------- /libs/fdk_aac.sh: -------------------------------------------------------------------------------- 1 | fdk_aac_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | fdk_aac_fetch() { 6 | do_git_checkout "https://github.com/mstorsjo/fdk-aac.git" $1 7 | } 8 | 9 | fdk_aac_clean() { 10 | make clean 11 | } 12 | 13 | fdk_aac_clean_win() { 14 | nmake -f Makefile.vc clean 15 | } 16 | 17 | fdk_aac_configure() { 18 | ./autogen.sh 19 | 20 | if [ "$TARGET_OS" = darwin ] ; then 21 | glibtoolize 22 | fi 23 | 24 | add_host_and_prefix config "--enable-static --disable-shared" 25 | ./configure $config 26 | } 27 | 28 | fdk_aac_configure_win() { 29 | do_patch fdk_aac-win32-make.patch 30 | } 31 | 32 | fdk_aac_make() { 33 | make 34 | } 35 | 36 | fdk_aac_make_win32() { 37 | nmake -f Makefile.vc machine=Win32 38 | } 39 | 40 | fdk_aac_make_win64() { 41 | nmake -f Makefile.vc machine=Win64 42 | } 43 | 44 | fdk_aac_install() { 45 | make install 46 | } 47 | 48 | fdk_aac_install_win() { 49 | nmake -f Makefile.vc prefix=$FF_PREFIX install 50 | } 51 | 52 | fdk_aac_enable() { 53 | enable_library "nonfree libfdk-aac" 54 | } 55 | -------------------------------------------------------------------------------- /libs/rtmp.sh: -------------------------------------------------------------------------------- 1 | rtmp_dependencies() { 2 | eval $1="'zlib gnutls'" 3 | } 4 | 5 | rtmp_dependencies_win() { 6 | eval $1="'zlib openssl'" 7 | } 8 | 9 | rtmp_fetch() { 10 | do_git_checkout "git://git.ffmpeg.org/rtmpdump" $1 11 | } 12 | 13 | rtmp_clean() { 14 | make clean 15 | } 16 | 17 | rtmp_clean_win() { 18 | nmake -f Makefile.win32 clean 19 | } 20 | 21 | rtmp_configure() { 22 | : 23 | } 24 | 25 | rtmp_configure_win() { 26 | do_patch rtmpdump-win32-make.patch 27 | } 28 | 29 | rtmp_make_darwin() { 30 | make SYS=darwin CRYPTO=GNUTLS SHARED=no prefix=$FF_PREFIX XLDFLAGS="$LDFLAGS" install 31 | } 32 | 33 | rtmp_make_linux() { 34 | make SYS=posix CRYPTO=GNUTLS SHARED=no prefix=$FF_PREFIX XLDFLAGS="$LDFLAGS" install 35 | } 36 | 37 | rtmp_make_mingw() { 38 | make SYS=mingw CRYPTO=GNUTLS SHARED=no CROSS_COMPILE=$TOOL_CHAIN_PREFIX prefix=$FF_PREFIX XLDFLAGS="$LDFLAGS" LIBS_mingw="-lws2_32 -lwinmm -lgdi32 -lcrypt32" install 39 | } 40 | 41 | rtmp_make_win() { 42 | nmake -f Makefile.win32 XCFLAGS="-I$(pwd)" XCFLAGS="-I$FF_INC_DIR" XLDFLAGS="$LDFLAGS" 43 | } 44 | 45 | rtmp_install() { 46 | : 47 | } 48 | 49 | rtmp_install_win() { 50 | nmake -f Makefile.win32 prefix=$FF_PREFIX install 51 | } 52 | 53 | rtmp_enable() { 54 | enable_library "librtmp" 55 | } 56 | -------------------------------------------------------------------------------- /libs/speex.sh: -------------------------------------------------------------------------------- 1 | speex_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | speex_fetch() { 6 | download_and_extract http://downloads.xiph.org/releases/speex/speex-1.2rc2.tar.gz $1 7 | } 8 | 9 | speex_clean() { 10 | make clean 11 | } 12 | 13 | speex_clean_win32() { 14 | MSBuild.exe "$1/win32/VS2008/libspeex.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=Win32 //target:Clean 15 | } 16 | 17 | speex_clean_win64() { 18 | MSBuild.exe "$1/win32/VS2008/libspeex.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=x64 //target:Clean 19 | } 20 | 21 | speex_configure() { 22 | add_host_and_prefix config "--enable-static --disable-shared --enable-pic --enable-sse --disable-binaries" 23 | ./configure $config 24 | } 25 | 26 | speex_configure_win() { 27 | : 28 | } 29 | 30 | speex_make() { 31 | make 32 | } 33 | 34 | speex_make_win32() { 35 | MSBuild.exe "$1/win32/VS2008/libspeex.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=Win32 36 | } 37 | 38 | speex_make_win64() { 39 | MSBuild.exe "$1/win32/VS2008/libspeex.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=x64 40 | } 41 | 42 | speex_install() { 43 | make install 44 | } 45 | 46 | speex_install_win() { 47 | exit 1 48 | } 49 | 50 | speex_enable() { 51 | enable_library "libspeex" 52 | } 53 | -------------------------------------------------------------------------------- /libs/lame.sh: -------------------------------------------------------------------------------- 1 | lame_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | lame_fetch() { 6 | download_and_extract http://sourceforge.net/projects/lame/files/lame/3.99/lame-3.99.5.tar.gz $1 7 | 8 | # Patch the 32-bit build. 9 | if [ "$ARCH" = x86 ] ; then 10 | local last_dir=$(pwd) 11 | cd lame 12 | sed -i -e '/xmmintrin\.h/d' configure 13 | cd $last_dir 14 | fi 15 | } 16 | 17 | lame_clean() { 18 | make clean 19 | } 20 | 21 | lame_configure() { 22 | add_host_and_prefix config "--enable-static --disable-shared --enable-pic --disable-frontend --disable-gtktest" 23 | ./configure $config 24 | } 25 | 26 | lame_configure_win() { 27 | : 28 | } 29 | 30 | lame_make() { 31 | make 32 | } 33 | 34 | lame_make_win32() { 35 | sed -i -e "s/ \/opt:NOWIN98//" -e "s/\/GL //" Makefile.MSVC 36 | 37 | nmake -f Makefile.MSVC MSVCVER=Win32 MACHINE=/MACHINE:X86 38 | } 39 | 40 | lame_make_win64() { 41 | sed -i -e "s/ \/opt:NOWIN98//" -e "s/\/GL //" Makefile.MSVC 42 | 43 | nmake -f Makefile.MSVC MSVCVER=Win64 MACHINE=/MACHINE:X64 44 | } 45 | 46 | lame_install() { 47 | make install 48 | } 49 | 50 | lame_install_win() { 51 | mkdir -p $FF_INC_DIR/lame ; cp include/lame.h $FF_INC_DIR/lame 52 | mkdir -p $FF_LIB_DIR/ ; cp output/libmp3lame-static.lib $FF_LIB_DIR/mp3lame.lib 53 | } 54 | 55 | lame_enable() { 56 | enable_library "libmp3lame" 57 | } 58 | -------------------------------------------------------------------------------- /libs/openssl.sh: -------------------------------------------------------------------------------- 1 | openssl_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | openssl_fetch() { 6 | download_and_extract https://www.openssl.org/source/openssl-1.0.2h.tar.gz $1 7 | } 8 | 9 | openssl_clean() { 10 | make clean 11 | } 12 | 13 | openssl_clean_win() { 14 | nmake -f ms/nt.mak clean 15 | } 16 | 17 | openssl_configure() { 18 | ./config shared --prefix=$FF_PREFIX 19 | make depend 20 | } 21 | 22 | openssl_configure_linux32() { 23 | setarch i386 ./config shared -m32 --prefix=$FF_PREFIX 24 | make depend 25 | } 26 | 27 | openssl_configure_mingw32() { 28 | CROSS_COMPILE="$TOOL_CHAIN_PREFIX" ./Configure mingw shared --prefix=$FF_PREFIX 29 | make depend 30 | } 31 | 32 | openssl_configure_mingw64() { 33 | CROSS_COMPILE="$TOOL_CHAIN_PREFIX" ./Configure mingw64 shared --prefix=$FF_PREFIX 34 | make depend 35 | } 36 | 37 | openssl_configure_win32() { 38 | perl Configure VC-WIN32 --prefix=$FF_PREFIX 39 | } 40 | 41 | openssl_configure_win64() { 42 | perl Configure VC-WIN64A --prefix=$FF_PREFIX 43 | } 44 | 45 | openssl_make() { 46 | make 47 | } 48 | 49 | openssl_make_win32() { 50 | ms/do_nasm.bat 51 | nmake -f ms/nt.mak 52 | } 53 | 54 | openssl_make_win64() { 55 | ms/do_win64a.bat 56 | nmake -f ms/nt.mak 57 | } 58 | 59 | openssl_install() { 60 | make install 61 | } 62 | 63 | openssl_install_win() { 64 | nmake -f ms/nt.mak install 65 | } 66 | 67 | openssl_enable() { 68 | : 69 | } 70 | -------------------------------------------------------------------------------- /libs/ogg.sh: -------------------------------------------------------------------------------- 1 | ogg_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | ogg_fetch() { 6 | download_and_extract http://downloads.xiph.org/releases/ogg/libogg-1.3.2.tar.gz $1 7 | } 8 | 9 | ogg_clean() { 10 | make clean 11 | } 12 | 13 | ogg_clean_win32() { 14 | MSBuild.exe "win32/VS2010/libogg_static.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=Win32 //target:Clean 15 | } 16 | 17 | ogg_clean_win64() { 18 | MSBuild.exe "win32/VS2010/libogg_static.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=x64 //target:Clean 19 | } 20 | 21 | ogg_configure() { 22 | add_host_and_prefix config "--enable-static --disable-shared --enable-pic" 23 | ./configure $config 24 | } 25 | 26 | ogg_configure_win() { 27 | : 28 | } 29 | 30 | ogg_make() { 31 | make 32 | } 33 | 34 | ogg_make_win32() { 35 | MSBuild.exe "win32/VS2010/libogg_static.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=Win32 36 | } 37 | 38 | ogg_make_win64() { 39 | MSBuild.exe "win32/VS2010/libogg_static.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=x64 40 | } 41 | 42 | ogg_install() { 43 | make install 44 | } 45 | 46 | ogg_install_win() { 47 | local target= 48 | 49 | case $TARGET_OS in 50 | win32) target="Win32" ;; 51 | win64) target="x64" ;; 52 | *) exit ;; 53 | esac 54 | 55 | mkdir -p $FF_INC_DIR/ogg ; cp include/ogg/*.h $FF_INC_DIR/ogg 56 | mkdir -p $FF_LIB_DIR/ ; cp win32/VS2010/$target/Release/libogg_static.lib $FF_LIB_DIR/ogg.lib 57 | } 58 | 59 | ogg_enable() { 60 | : 61 | } 62 | -------------------------------------------------------------------------------- /libs/vorbis.sh: -------------------------------------------------------------------------------- 1 | vorbis_dependencies() { 2 | eval $1="'ogg'" 3 | } 4 | 5 | vorbis_fetch() { 6 | download_and_extract http://downloads.xiph.org/releases/vorbis/libvorbis-1.3.5.tar.gz $1 7 | } 8 | 9 | vorbis_clean() { 10 | make clean 11 | } 12 | 13 | vorbis_clean_win32() { 14 | MSBuild.exe "win32/VS2010/vorbis_static.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=Win32 //target:Clean 15 | } 16 | 17 | vorbis_clean_win64() { 18 | MSBuild.exe "win32/VS2010/vorbis_static.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=x64 //target:Clean 19 | } 20 | 21 | vorbis_configure() { 22 | add_host_and_prefix config "--enable-static --disable-shared --enable-pic" 23 | ./configure $config 24 | } 25 | 26 | vorbis_configure_win() { 27 | # Change /MD to /MT 28 | sed -i 's/MultiThreadedDLL/MultiThreaded/' win32/VS2010/libvorbis/libvorbis_static.vcxproj 29 | } 30 | 31 | vorbis_make() { 32 | make 33 | } 34 | 35 | vorbis_make_win32() { 36 | MSBuild.exe "win32/VS2010/vorbis_static.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=Win32 37 | } 38 | 39 | vorbis_make_win64() { 40 | MSBuild.exe "win32/VS2010/vorbis_static.sln" //p:PlatformToolset=v140 //p:Configuration=Release //p:Platform=x64 41 | } 42 | 43 | vorbis_install() { 44 | make install 45 | } 46 | 47 | vorbis_install_win() { 48 | local target= 49 | 50 | case $TARGET_OS in 51 | win32) target="Win32" ;; 52 | win64) target="x64" ;; 53 | *) exit ;; 54 | esac 55 | 56 | mkdir -p $FF_INC_DIR/vorbis ; cp include/vorbis/*.h $FF_INC_DIR/vorbis 57 | mkdir -p $FF_LIB_DIR/ ; cp win32/VS2010/$target/Release/libvorbis_static.lib $FF_LIB_DIR/vorbis.lib 58 | cp win32/VS2010/$target/Release/libvorbis_static.lib $FF_LIB_DIR/vorbisenc.lib 59 | cp win32/VS2010/$target/Release/libvorbisfile_static.lib $FF_LIB_DIR/vorbisfile.lib 60 | } 61 | 62 | vorbis_enable() { 63 | enable_library "libvorbis" 64 | } 65 | -------------------------------------------------------------------------------- /libs/opus.sh: -------------------------------------------------------------------------------- 1 | opus_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | opus_fetch() { 6 | download_and_extract http://downloads.xiph.org/releases/opus/opus-1.1.3.tar.gz $1 7 | } 8 | 9 | opus_clean() { 10 | make clean 11 | } 12 | 13 | opus_clean_win32() { 14 | MSBuild.exe "win32/VS2015/opus.sln" //p:Configuration=Release //p:Platform=Win32 //target:Clean 15 | } 16 | 17 | opus_clean_win64() { 18 | MSBuild.exe "win32/VS2015/opus.sln" //p:Configuration=Release //p:Platform=x64 //target:Clean 19 | } 20 | 21 | opus_configure() { 22 | add_host_and_prefix config "--enable-static --disable-shared --enable-pic --disable-doc --disable-extra-programs" 23 | ./configure $config 24 | } 25 | 26 | opus_configure_win() { 27 | # Create version header file. 28 | IFS='=' read var version <<< $(grep -v '^#' "version.mk") 29 | echo "#define $var $version" > win32/version.h 30 | } 31 | 32 | opus_make() { 33 | make 34 | } 35 | 36 | opus_make_win32() { 37 | MSBuild.exe "win32/VS2015/opus.sln" //p:Configuration=Release //p:Platform=Win32 38 | } 39 | 40 | opus_make_win64() { 41 | MSBuild.exe "win32/VS2015/opus.sln" //p:Configuration=Release //p:Platform=x64 42 | } 43 | 44 | opus_install() { 45 | make install 46 | } 47 | 48 | opus_install_win() { 49 | local target= 50 | 51 | case $TARGET_OS in 52 | win32) target="Win32" ;; 53 | win64) target="x64" ;; 54 | *) exit ;; 55 | esac 56 | 57 | mkdir -p $FF_INC_DIR/opus ; cp include/* $FF_INC_DIR/opus 58 | mkdir -p $FF_LIB_DIR/ ; cp win32/VS2015/$target/Release/*.lib $FF_LIB_DIR/ 59 | mkdir -p $PKG_CONFIG_PATH 60 | 61 | cp opus.pc.in $PKG_CONFIG_PATH/opus.pc 62 | 63 | sed -i -e "s|@prefix@|$FF_PREFIX|" \ 64 | -e "s|@exec_prefix@|\${prefix}|" \ 65 | -e "s|@libdir@|\${exec_prefix}/lib|" \ 66 | -e "s|@includedir@|\${prefix}/include|" \ 67 | -e "s|@PC_BUILD@|floating-point|" \ 68 | -e "s|@VERSION@|1.1.3|" \ 69 | -e "s|@LIBM@|\-lcelt -lsilk_common -lsilk_float|" \ 70 | $PKG_CONFIG_PATH/opus.pc 71 | } 72 | 73 | opus_enable() { 74 | enable_library "libopus" 75 | } 76 | -------------------------------------------------------------------------------- /libs/zlib.sh: -------------------------------------------------------------------------------- 1 | zlib_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | zlib_fetch() { 6 | download_and_extract http://zlib.net/zlib-1.2.8.tar.gz $1 7 | } 8 | 9 | zlib_clean() { 10 | case "$(uname -s)" in 11 | MINGW*) 12 | make clean -f win32/Makefile.gcc 13 | ;; 14 | *) 15 | make clean 16 | ;; 17 | esac 18 | } 19 | 20 | zlib_clean_win() { 21 | nmake -f win32/Makefile.msc clean 22 | } 23 | 24 | zlib_configure() { 25 | case "$(uname -s)" in 26 | MINGW*) 27 | ;; 28 | *) 29 | ./configure --static --prefix=$FF_PREFIX 30 | ;; 31 | esac 32 | } 33 | 34 | zlib_configure_win() { 35 | # Use -MT instead of -MD, since this is how FFmpeg is built as well. 36 | sed -i 's/-nologo -MD/-nologo -MT/' win32/Makefile.msc 37 | # Remove the inclusion of unistd.h. 38 | sed -i 's/include //' zconf.h 39 | } 40 | 41 | zlib_make() { 42 | case "$(uname -s)" in 43 | MINGW*) 44 | make -f win32/Makefile.gcc 45 | ;; 46 | *) 47 | make CC="$(echo $TOOL_CHAIN_PREFIX)gcc" AR="$(echo $TOOL_CHAIN_PREFIX)ar" RANLIB="$(echo $TOOL_CHAIN_PREFIX)ranlib" 48 | ;; 49 | esac 50 | } 51 | 52 | zlib_make_win32() { 53 | nmake -f win32/Makefile.msc LOC="-DASMV -DASMINF" OBJA="inffas32.obj match686.obj" 54 | } 55 | 56 | zlib_make_win64() { 57 | nmake -f win32/Makefile.msc AS=ml64 LOC="-DASMV -DASMINF -I." OBJA="inffasx64.obj gvmat64.obj inffas8664.obj" 58 | } 59 | 60 | zlib_install() { 61 | case "$(uname -s)" in 62 | MINGW*) 63 | make install -f win32/Makefile.gcc prefix=$FF_PREFIX BINARY_PATH=$FF_BIN_DIR INCLUDE_PATH=$FF_INC_DIR LIBRARY_PATH=$FF_LIB_DIR 64 | ;; 65 | *) 66 | make CC="$(echo $TOOL_CHAIN_PREFIX)gcc" AR="$(echo $TOOL_CHAIN_PREFIX)ar" RANLIB="$(echo $TOOL_CHAIN_PREFIX)ranlib" install 67 | ;; 68 | esac 69 | } 70 | 71 | zlib_install_win() { 72 | mkdir -p $FF_INC_DIR/ ; cp zconf.h zlib.h $FF_INC_DIR/ 73 | mkdir -p $FF_LIB_DIR/ ; cp zlib.lib $FF_LIB_DIR/ 74 | mkdir -p $FF_BIN_DIR/ ; cp zlib1.dll $FF_BIN_DIR/ 75 | } 76 | 77 | zlib_enable() { 78 | enable_library "zlib" 79 | } 80 | -------------------------------------------------------------------------------- /libs/vpx.sh: -------------------------------------------------------------------------------- 1 | vpx_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | vpx_fetch() { 6 | do_git_checkout "https://chromium.googlesource.com/webm/libvpx" $1 7 | } 8 | 9 | vpx_clean() { 10 | make clean 11 | } 12 | 13 | vpx_set_params() { 14 | local __resultvar=$1 15 | local options=$2 16 | 17 | add_prefix params "--enable-vp8 --enable-vp9 --enable-static --enable-pic --disable-examples --disable-unit-tests --disable-docs $options" 18 | 19 | eval $__resultvar='$params' 20 | } 21 | 22 | vpx_configure_darwin() { 23 | vpx_set_params config "--target=$ARCH-darwin15-gcc" 24 | ./configure $config 25 | } 26 | 27 | vpx_configure_linux() { 28 | vpx_set_params config "--target=$ARCH-linux-gcc" 29 | ./configure $config 30 | } 31 | 32 | vpx_configure_mingw32() { 33 | do_patch vpx-sys-types.patch 34 | 35 | vpx_set_params config "--target=$ARCH-win32-gcc" 36 | 37 | # Need to set CROSS to allow clean stripping with MinGWs tool chain. 38 | CROSS="$TOOL_CHAIN_PREFIX" ./configure $config 39 | } 40 | 41 | vpx_configure_mingw64() { 42 | do_patch vpx-sys-types.patch 43 | 44 | vpx_set_params config "--target=$ARCH-win64-gcc" 45 | 46 | # Need to set CROSS to allow clean stripping with MinGWs tool chain. 47 | CROSS="$TOOL_CHAIN_PREFIX" ./configure $config 48 | } 49 | 50 | vpx_configure_win32() { 51 | # Use /MT instead of /MD. 52 | vpx_set_params config "--target=x86-win32-vs14 --enable-static-msvcrt" 53 | ./configure $config 54 | } 55 | 56 | vpx_configure_win64() { 57 | # Use /MT instead of /MD. 58 | vpx_set_params config "--target=x86_64-win64-vs14 --enable-static-msvcrt" 59 | ./configure $config 60 | } 61 | 62 | vpx_make() { 63 | make 64 | } 65 | 66 | vpx_install() { 67 | make install 68 | } 69 | 70 | vpx_install_win() { 71 | make install 72 | 73 | local target_dir= 74 | 75 | case $TARGET_OS in 76 | win32) target_dir="Win32" ;; 77 | win64) target_dir="x64" ;; 78 | *) exit ;; 79 | esac 80 | 81 | mv $FF_LIB_DIR/$target_dir/vpxmt.lib $FF_LIB_DIR/vpx.lib 82 | rm -R $FF_LIB_DIR/$target_dir 83 | } 84 | 85 | vpx_enable() { 86 | enable_library "libvpx" 87 | } 88 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Modular FFmpeg builder 2 | This builder will create a shared [FFmpeg](http://ffmpeg.org) build with statically linked libraries. It's a multi-file build script, where each library is responsible for its compilation process and its dependencies. The compilation process of a library is defined in its own file. This makes the builder easy to maintain. 3 | 4 | ### Options 5 | ``` 6 | -h, --help print this help. 7 | -i, --prefix installation directory. 8 | -p, --profile target os profile, see below. 9 | -l, --libs space separated list of libraries to include into FFmpeg [optional]. 10 | ``` 11 | 12 | ### Profiles 13 | 14 | | Profile | Toolchain | 15 | | :------------------------------------ | :---------------------------------- | 16 | | linux-x86
linux-x86_64 | Linux native | 17 | | mac-x86_64 | OS X native | 18 | | mingw-msys-x86
mingw-msys-x86_64 | MSYS MinGW on Windows | 19 | | mingw-x86
mingw-x86_64 | MinGW, e.g. on Linux | 20 | | msvc-15-x86
msvc-15-x86_64 | MSYS using Visual Studio on Windows | 21 | 22 | For `mingw-msys` and `msvc-15` profiles refer to the [Initial setup of MSYS2](https://github.com/opcodevoid/ffmpeg-builder/wiki/Initial-setup-of-MSYS2) wiki. 23 | 24 | ### Examples 25 | OS X 64-bit build 26 | ``` 27 | $ ./ffmpeg-builder -p mac-x86_64 -i /usr/local/ffmpeg -l "opus vpx x264 x265" 28 | ``` 29 | 30 | Windows 64-bit build with [MSYS2](http://msys2.github.io) and [Visual Studio](https://www.visualstudio.com) toolchain. 31 | ``` 32 | $ ./ffmpeg-builder -p msvc-15-x86_64 -i /usr/local/ffmpeg-win-64 -l "opus vpx" 33 | ``` 34 | 35 | Windows 32-bit build with [Mingw-w64](http://mingw-w64.org) cross compiler on a Unix host. 36 | ``` 37 | $ ./ffmpeg-builder -p mingw-x86 -i /usr/local/ffmpeg-win-32 -l "opus vpx" 38 | ``` 39 | 40 | ### Todos 41 | - [ ] ARM support 42 | - [ ] Add option to create a static build 43 | -------------------------------------------------------------------------------- /libs/ffmpeg.sh: -------------------------------------------------------------------------------- 1 | ffmpeg_dependencies() { 2 | eval $1="'$FF_LIBS'" 3 | } 4 | 5 | ffmpeg_fetch() { 6 | #do_git_checkout https://github.com/FFmpeg/FFmpeg.git $1 7 | download_and_extract http://ffmpeg.org/releases/ffmpeg-3.1.2.tar.bz2 $1 8 | } 9 | 10 | ffmpeg_clean() { 11 | make distclean 12 | } 13 | 14 | ffmpeg_set_params() { 15 | local __resultvar=$1 16 | local options=$2 17 | 18 | # Make enabled libraries unique. 19 | FF_ENABLED_LIBS=$(echo "$FF_ENABLED_LIBS" | tr ' ' '\n' | sort -u) 20 | 21 | add_prefix params "--arch=$ARCH \ 22 | --pkg-config=pkg-config \ 23 | --pkg-config-flags=--static \ 24 | --disable-ffprobe \ 25 | --disable-ffserver \ 26 | --disable-debug \ 27 | --disable-doc \ 28 | --disable-static \ 29 | --enable-shared \ 30 | --enable-gpl \ 31 | --enable-version3 \ 32 | --enable-postproc \ 33 | --enable-runtime-cpudetect \ 34 | --enable-memalign-hack \ 35 | --enable-pic \ 36 | $options \ 37 | $FF_ENABLED_LIBS" 38 | 39 | eval $__resultvar='$params' 40 | } 41 | 42 | ffmpeg_set_pthreads() { 43 | eval $1='"$2 --disable-w32threads --enable-pthreads"' 44 | } 45 | 46 | ffmpeg_configure_darwin() { 47 | ffmpeg_set_params config "--target-os=darwin" 48 | ffmpeg_set_pthreads config "$config" 49 | 50 | ./configure $config 51 | } 52 | 53 | ffmpeg_configure_linux32() { 54 | ffmpeg_set_params config "--target-os=linux --enable-cross-compile --extra-ldflags=-ldl" 55 | ffmpeg_set_pthreads config "$config" 56 | 57 | ./configure $config 58 | } 59 | 60 | ffmpeg_configure_linux64() { 61 | ffmpeg_set_params config "--target-os=linux" 62 | ffmpeg_set_pthreads config "$config" 63 | 64 | ./configure $config 65 | } 66 | 67 | ffmpeg_configure_mingw() { 68 | ffmpeg_set_params config "--target-os=mingw32 --cross-prefix=$TOOL_CHAIN_PREFIX --enable-dxva2" 69 | ffmpeg_set_pthreads config "$config" 70 | 71 | LDFLAGS="$LDFLAGS -static -static-libgcc -static-libstdc++" ./configure $config 72 | } 73 | 74 | ffmpeg_configure_win() { 75 | ffmpeg_set_params config "--toolchain=$TOOLCHAIN --extra-cflags=$CPPFLAGS --extra-ldflags=$LDFLAGS" 76 | 77 | ./configure $config 78 | } 79 | 80 | ffmpeg_make() { 81 | make 82 | } 83 | 84 | ffmpeg_install() { 85 | make install 86 | } 87 | 88 | ffmpeg_enable() { 89 | : 90 | } 91 | -------------------------------------------------------------------------------- /libs/x265.sh: -------------------------------------------------------------------------------- 1 | x265_dependencies() { 2 | eval $1="''" 3 | } 4 | 5 | x265_fetch() { 6 | download_and_extract https://bitbucket.org/multicoreware/x265/downloads/x265_2.0.tar.gz $1 7 | } 8 | 9 | x265_clean() { 10 | rm -R build/* 11 | } 12 | 13 | x265_set_params() { 14 | eval $1='"-DCMAKE_BUILD_TYPE=Release -DCMAKE_CXX_IMPLICIT_LINK_LIBRARIES=stdc++"' 15 | } 16 | 17 | x265_configure_darwin() { 18 | x265_set_params config 19 | exec_in_dir "build" do_cmake "Unix Makefiles" "../source" "Darwin" "$config" 20 | } 21 | 22 | x265_configure_linux() { 23 | x265_set_params config 24 | exec_in_dir "build" do_cmake "Unix Makefiles" "../source" "Linux" "$config" 25 | } 26 | 27 | x265_configure_mingw() { 28 | x265_set_params config 29 | 30 | case "$(uname -s)" in 31 | MINGW*) 32 | exec_in_dir "build" do_cmake "MSYS Makefiles" "../source" "Windows" "$config" 33 | ;; 34 | *) 35 | exec_in_dir "build" do_cmake "MinGW Makefiles" "../source" "Windows" "-DCMAKE_RANLIB=${TOOL_CHAIN_PREFIX}ranlib -DCMAKE_C_COMPILER=${TOOL_CHAIN_PREFIX}gcc -DCMAKE_CXX_COMPILER=${TOOL_CHAIN_PREFIX}g++ -DCMAKE_RC_COMPILER=${TOOL_CHAIN_PREFIX}windres $config" 36 | ;; 37 | esac 38 | } 39 | 40 | x265_configure_win32() { 41 | x265_set_params config 42 | exec_in_dir "build" do_cmake "Visual Studio 14 2015" "../source" "Windows" "-DSTATIC_LINK_CRT=On $config" 43 | } 44 | 45 | x265_configure_win64() { 46 | x265_set_params config 47 | exec_in_dir "build" do_cmake "Visual Studio 14 2015 Win64" "../source" "Windows" "-DSTATIC_LINK_CRT=On $config" 48 | } 49 | 50 | x265_make() { 51 | exec_in_dir "build" make 52 | } 53 | 54 | x265_make_win() { 55 | MSBuild.exe "build/x265.sln" //p:Configuration=Release 56 | } 57 | 58 | x265_install() { 59 | exec_in_dir "build" make install 60 | } 61 | 62 | x265_install_win() { 63 | mkdir -p $FF_INC_DIR/ ; cp source/x265.h build/x265_config.h $FF_INC_DIR/ 64 | mkdir -p $FF_BIN_DIR/ ; cp build/Release/libx265.dll build/Release/x265.exe $FF_BIN_DIR/ 65 | mkdir -p $FF_LIB_DIR/ ; cp build/x265.def build/Release/x265-static.lib $FF_LIB_DIR/ 66 | mkdir -p $PKG_CONFIG_PATH ; cp build/x265.pc $PKG_CONFIG_PATH 67 | 68 | sed -i 's/-lx265/-lx265-static/' $PKG_CONFIG_PATH/x265.pc 69 | } 70 | 71 | x265_enable() { 72 | enable_library "libx265" 73 | } 74 | -------------------------------------------------------------------------------- /ffmpeg-builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | FF_TIME=$(date +%s%N) 4 | FF_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" 5 | FF_LIBS_DIR=$FF_DIR/libs 6 | FF_PATCH_DIR=$FF_DIR/patches 7 | FF_PROFILE_DIR=$FF_DIR/profiles 8 | FF_LOG_NAME="build.log" 9 | FF_LOG_PATH="" 10 | FF_PREFIX="" 11 | FF_PROFILE="" 12 | FF_LIBS="" 13 | FF_ENABLED_LIBS="" 14 | FF_BIN_DIR="" 15 | FF_INC_DIR="" 16 | FF_LIB_DIR="" 17 | FF_SRC_DIR="" 18 | FF_FUNCTIONS=( dependencies fetch configure make install enable ) 19 | 20 | 21 | log_enable() { 22 | exec 3>&1 4>&2 &>> $FF_LOG_PATH 23 | } 24 | 25 | log_disable() { 26 | exec 1>&3 2>&4 27 | } 28 | 29 | log_clear() { 30 | > $FF_LOG_PATH 31 | } 32 | 33 | do_notify() { 34 | local message="$1" 35 | 36 | echo -e "\e[1;34m>>> $message\e[00m" 37 | } 38 | 39 | do_notify_error() { 40 | local message="$1" 41 | 42 | echo -e "\e[1;31m!!! $message\e[00m" 43 | } 44 | 45 | error() { 46 | local message="$1" 47 | 48 | log_disable 49 | do_notify_error "$message" 50 | log_enable 51 | 52 | exit 1 53 | } 54 | 55 | add_prefix() { 56 | local __resultvar=$1 57 | local options=$2 58 | local myresult="$options --prefix=$FF_PREFIX" 59 | 60 | eval $__resultvar='$myresult' 61 | } 62 | 63 | add_host() { 64 | local __resultvar=$1 65 | local options=$2 66 | local myresult="$options --host=$HOST" 67 | 68 | eval $__resultvar='$myresult' 69 | } 70 | 71 | add_host_and_prefix() { 72 | local __resultvar=$1 73 | local options=$2 74 | local myresult="$options --host=$HOST --prefix=$FF_PREFIX" 75 | 76 | eval $__resultvar='$myresult' 77 | } 78 | 79 | download_and_extract() { 80 | local file_url="$1" 81 | local dest_url="$2" 82 | local file_name=$(basename "$file_url") 83 | local src_dir="${file_name%.*}" 84 | src_dir="${src_dir%.tar}" 85 | 86 | if [ ! -d $dest_url ]; then 87 | do_notify "Downloading $file_name ..." 88 | 89 | wget -c $file_url || return 1 90 | 91 | if [[ -z "$dest_url" ]]; then 92 | tar xf $file_name || return 1 93 | else 94 | tar xf $file_name || return 1 95 | mv $src_dir $dest_url 96 | fi 97 | 98 | rm $file_name 99 | fi 100 | } 101 | 102 | do_git_checkout() { 103 | local repo_url="$1" 104 | local src_dir="$2" 105 | local last_dir=$(pwd) 106 | 107 | if [ ! -d $src_dir ]; then 108 | do_notify "Git clone $repo_url to $src_dir" 109 | # Prevent partial checkouts by renaming it only after success. 110 | git clone $repo_url $src_dir.tmp || return 1 111 | mv $src_dir.tmp $src_dir 112 | do_notify "Git clone to $src_dir finished." 113 | else 114 | do_notify "Updating $repo_url to latest version..." 115 | cd $src_dir 116 | git pull 117 | cd $last_dir 118 | fi 119 | } 120 | 121 | do_svn_checkout() { 122 | local repo_url="$1" 123 | local src_dir="$2" 124 | local last_dir=$(pwd) 125 | 126 | if [ ! -d $src_dir ]; then 127 | do_notify "Svn checkout $repo_url to $src_dir" 128 | rm -rf $src_dir 129 | # Prevent partial checkouts by renaming it only after success. 130 | svn co $repo_url $src_dir.tmp || return 1 131 | mv $src_dir.tmp $src_dir 132 | do_notify "Svn checkout to $src_dir finished." 133 | else 134 | do_notify "Updating $repo_url to latest version..." 135 | cd $src_dir 136 | svn up 137 | cd $last_dir 138 | fi 139 | } 140 | 141 | do_patch() { 142 | local patch_name="$1" 143 | 144 | patch -p0 -N -s --dry-run < $FF_PATCH_DIR/$patch_name 2>/dev/null 145 | 146 | if [ $? -eq 0 ]; then 147 | do_notify "Patching $(pwd) ..." 148 | 149 | patch -p0 -N < $FF_PATCH_DIR/$patch_name 150 | fi 151 | } 152 | 153 | do_cmake() { 154 | local generator="$1" 155 | local dst_dir="$2" 156 | local system="$3" 157 | local args="$4" 158 | 159 | cmake -G "$generator" "$dst_dir" \ 160 | -DCMAKE_SYSTEM_NAME="$system" \ 161 | -DCMAKE_INSTALL_PREFIX="$FF_PREFIX" \ 162 | $args 163 | } 164 | 165 | exec_in_dir() { 166 | local dir="$1"; shift 167 | local last_dir=$(pwd) 168 | 169 | cd $dir 170 | 171 | "$@" || return 1 172 | 173 | cd $last_dir 174 | } 175 | 176 | import_sources() { 177 | source $FF_PROFILE_DIR/$FF_PROFILE.local 178 | 179 | . $FF_LIBS_DIR/ffmpeg.sh 180 | } 181 | 182 | import_installers() { 183 | if [[ -d $FF_LIBS_DIR ]]; then 184 | for file in $FF_LIBS_DIR/*; do 185 | if [[ -f $file ]] && [[ "$file" != *~ ]]; then 186 | . $file 187 | fi 188 | done 189 | fi 190 | } 191 | 192 | contains() { 193 | declare -a list=("${!1}") 194 | 195 | [[ "${list[@]}" =~ (^|[[:space:]])"$2"($|[[:space:]]) ]] 196 | return $? 197 | } 198 | 199 | function_exists() { 200 | declare -f -F $1 > /dev/null 201 | return $? 202 | } 203 | 204 | execute_function() { 205 | local lib_name=$1 206 | local func_name=$2 207 | local params=$3 208 | local t_prefix=${TARGET_OS//[0-9]/} 209 | local functions=( "$func_name"_"$t_prefix" "$func_name"_"$TARGET_OS" "$func_name" ) 210 | local functions_no_cd=( "$lib_name""_dependencies" "$lib_name""_fetch" "$lib_name""_enable" ) 211 | local last_dir=$(pwd) 212 | local do_cd=false 213 | 214 | contains functions_no_cd[@] "$func_name" || do_cd=true 215 | 216 | if $do_cd ; then 217 | cd $lib_name || return 1 218 | fi 219 | 220 | for function in ${functions[@]}; do 221 | if function_exists "$function"; then 222 | "$function" "$params" 223 | 224 | if (( $? != 0 )); then 225 | # Exit properly. 226 | if $do_cd ; then 227 | cd $last_dir 228 | fi 229 | 230 | return 1 231 | fi 232 | 233 | break 234 | fi 235 | done 236 | 237 | if $do_cd ; then 238 | cd $last_dir 239 | fi 240 | 241 | return 0 242 | } 243 | 244 | install_library() { 245 | local name=$1 246 | local func= 247 | 248 | # Check if all required functions exist. 249 | for function in ${FF_FUNCTIONS[@]}; do 250 | func="$name"_"$function" 251 | 252 | if ! function_exists "$func" ; then 253 | local t_prefix=${TARGET_OS//[0-9]/} 254 | local sub_functions=( "$func"_"$t_prefix" "$func"_"$TARGET_OS" ) 255 | local found=false 256 | 257 | for sub_function in ${sub_functions[@]}; do 258 | if function_exists "$sub_function" ; then 259 | found=true 260 | break 261 | fi 262 | done 263 | 264 | if ! $found ; then 265 | do_notify_error "Package $name is missing [$function] function. Aborting..." 266 | exit 1 267 | fi 268 | fi 269 | done 270 | 271 | # Execute package functions. 272 | execute_function $name "$name"_dependencies deps 273 | 274 | # Resolve all dependencies recursively. 275 | if [[ ! -z "$deps" ]]; then 276 | for dep in ${deps[@]}; do 277 | install_library $dep 278 | done 279 | fi 280 | 281 | log_disable 282 | do_notify "Building $name" 283 | log_enable 284 | 285 | # Critical functions will exit on error. 286 | 287 | do_notify "Fetching $name ..." 288 | execute_function $name "$name"_fetch $name || error "Fetching $name failed!" 289 | 290 | do_notify "Cleaning $name ..." 291 | execute_function $name "$name"_clean 292 | 293 | do_notify "Configuring $name ..." 294 | execute_function $name "$name"_configure || error "Configuring $name failed!" 295 | 296 | do_notify "Making $name ..." 297 | execute_function $name "$name"_make || error "Making $name failed!" 298 | 299 | do_notify "Installing $name ..." 300 | execute_function $name "$name"_install || error "Installing $name failed!" 301 | 302 | execute_function $name "$name"_enable 303 | } 304 | 305 | enable_library() { 306 | local libs=("$@") 307 | 308 | for lib in ${libs[@]}; do 309 | FF_ENABLED_LIBS="$FF_ENABLED_LIBS --enable-$lib" 310 | done 311 | } 312 | 313 | create_build_dir() { 314 | mkdir -p $FF_SRC_DIR 315 | cd $FF_SRC_DIR 316 | } 317 | 318 | usage() { 319 | local profiles="" 320 | local my_name=$(basename -- "$0") 321 | my_name="${my_name%.*}" 322 | 323 | # List all available profiles. 324 | if [[ -d $FF_PROFILE_DIR ]]; then 325 | for file in $FF_PROFILE_DIR/*; do 326 | if [[ -f $file ]] && [[ "$file" != *~ ]]; then 327 | local name=$(basename -- "$file") 328 | name="${name%.*}" 329 | profiles="$profiles $name\n" 330 | fi 331 | done 332 | fi 333 | 334 | 335 | cat <<- _EOF_ 336 | Usage: $my_name [options] 337 | 338 | Example: ./$my_name -p mac-x86_64 -i /usr/local/ffmpeg -l "opus lame vorbis vpx x264 x265 rtmp" 339 | 340 | Options: 341 | -h, --help print this help. 342 | -i, --prefix installation directory. 343 | -p, --profile target os profile, see below. 344 | -l, --libs space separated list of libraries to include into FFmpeg [optional]. 345 | 346 | Profiles: 347 | $(echo -e "$profiles") 348 | 349 | _EOF_ 350 | } 351 | 352 | check_input() { 353 | if [ ! -f $FF_PROFILE_DIR/$FF_PROFILE.local ]; then 354 | usage 355 | do_notify_error "Profile [$FF_PROFILE] not found." 356 | exit 1 357 | fi 358 | 359 | if [ "$FF_PREFIX" = "" ]; then 360 | usage 361 | do_notify_error "No prefix specified." 362 | exit 1 363 | fi 364 | } 365 | 366 | set_vars() { 367 | FF_BIN_DIR="$FF_PREFIX/bin" 368 | FF_INC_DIR="$FF_PREFIX/include" 369 | FF_LIB_DIR="$FF_PREFIX/lib" 370 | FF_SRC_DIR="$FF_PREFIX/src" 371 | FF_LOG_PATH="$FF_PREFIX/$FF_LOG_NAME" 372 | } 373 | 374 | show_total_time() { 375 | # Time interval in nanoseconds 376 | local N=$(($(date +%s%N)-FF_TIME)) 377 | # Seconds 378 | local S=$((N/1000000000)) 379 | # Milliseconds 380 | local M=$((N/1000000)) 381 | 382 | log_disable 383 | 384 | printf "Total time: %02d:%02d:%02d.%03d\n" $((S/3600%24)) $((S/60%60)) $((S%60)) ${M} 385 | } 386 | 387 | ##### Entry Point 388 | 389 | if [ "$#" -lt 2 ] 390 | then 391 | usage 392 | exit 1 393 | fi 394 | 395 | while [ "$1" != "" ]; do 396 | case $1 in 397 | -p | --profile ) shift 398 | FF_PROFILE=$1 399 | ;; 400 | -i | --prefix ) shift 401 | FF_PREFIX=$1 402 | ;; 403 | -l | --libs ) shift 404 | FF_LIBS=$1 405 | ;; 406 | -h | --help ) usage 407 | exit 408 | ;; 409 | * ) usage 410 | exit 1 411 | esac 412 | shift 413 | done 414 | 415 | check_input 416 | set_vars 417 | import_sources 418 | import_installers 419 | create_build_dir 420 | log_clear 421 | log_enable 422 | install_library ffmpeg 423 | show_total_time 424 | -------------------------------------------------------------------------------- /patches/rtmpdump-win32-make.patch: -------------------------------------------------------------------------------- 1 | diff -ruN getopt.h getopt.h 2 | --- getopt.h 1970-01-01 01:00:00.000000000 +0100 3 | +++ getopt.h 2016-08-21 08:48:00.099452100 +0200 4 | @@ -0,0 +1,653 @@ 5 | +#ifndef __GETOPT_H__ 6 | +/** 7 | + * DISCLAIMER 8 | + * This file is part of the mingw-w64 runtime package. 9 | + * 10 | + * The mingw-w64 runtime package and its code is distributed in the hope that it 11 | + * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR 12 | + * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to 13 | + * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 14 | + */ 15 | + /* 16 | + * Copyright (c) 2002 Todd C. Miller 17 | + * 18 | + * Permission to use, copy, modify, and distribute this software for any 19 | + * purpose with or without fee is hereby granted, provided that the above 20 | + * copyright notice and this permission notice appear in all copies. 21 | + * 22 | + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 23 | + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 24 | + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 25 | + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 26 | + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 27 | + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 28 | + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 29 | + * 30 | + * Sponsored in part by the Defense Advanced Research Projects 31 | + * Agency (DARPA) and Air Force Research Laboratory, Air Force 32 | + * Materiel Command, USAF, under agreement number F39502-99-1-0512. 33 | + */ 34 | +/*- 35 | + * Copyright (c) 2000 The NetBSD Foundation, Inc. 36 | + * All rights reserved. 37 | + * 38 | + * This code is derived from software contributed to The NetBSD Foundation 39 | + * by Dieter Baron and Thomas Klausner. 40 | + * 41 | + * Redistribution and use in source and binary forms, with or without 42 | + * modification, are permitted provided that the following conditions 43 | + * are met: 44 | + * 1. Redistributions of source code must retain the above copyright 45 | + * notice, this list of conditions and the following disclaimer. 46 | + * 2. Redistributions in binary form must reproduce the above copyright 47 | + * notice, this list of conditions and the following disclaimer in the 48 | + * documentation and/or other materials provided with the distribution. 49 | + * 50 | + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 51 | + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 52 | + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 53 | + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 54 | + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 55 | + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 56 | + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 57 | + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 58 | + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 59 | + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 60 | + * POSSIBILITY OF SUCH DAMAGE. 61 | + */ 62 | + 63 | +#pragma warning(disable:4996); 64 | + 65 | +#define __GETOPT_H__ 66 | + 67 | +/* All the headers include this file. */ 68 | +#include 69 | +#include 70 | +#include 71 | +#include 72 | +#include 73 | +#include 74 | +//#include 75 | + 76 | +#ifdef __cplusplus 77 | +extern "C" { 78 | +#endif 79 | + 80 | +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ 81 | + 82 | +#ifdef REPLACE_GETOPT 83 | +int opterr = 1; /* if error message should be printed */ 84 | +int optind = 1; /* index into parent argv vector */ 85 | +int optopt = '?'; /* character checked for validity */ 86 | +#undef optreset /* see getopt.h */ 87 | +#define optreset __mingw_optreset 88 | +int optreset; /* reset getopt */ 89 | +char *optarg; /* argument associated with option */ 90 | +#endif 91 | + 92 | +//extern int optind; /* index of first non-option in argv */ 93 | +//extern int optopt; /* single option character, as parsed */ 94 | +//extern int opterr; /* flag to enable built-in diagnostics... */ 95 | +// /* (user may set to zero, to suppress) */ 96 | +// 97 | +//extern char *optarg; /* pointer to argument of current option */ 98 | + 99 | +#define PRINT_ERROR ((opterr) && (*options != ':')) 100 | + 101 | +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ 102 | +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ 103 | +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ 104 | + 105 | +/* return values */ 106 | +#define BADCH (int)'?' 107 | +#define BADARG ((*options == ':') ? (int)':' : (int)'?') 108 | +#define INORDER (int)1 109 | + 110 | +#ifndef __CYGWIN__ 111 | +#define __progname __argv[0] 112 | +#else 113 | +extern char __declspec(dllimport) *__progname; 114 | +#endif 115 | + 116 | +#ifdef __CYGWIN__ 117 | +static char EMSG[] = ""; 118 | +#else 119 | +#define EMSG "" 120 | +#endif 121 | + 122 | +static int getopt_internal(int, char * const *, const char *, 123 | + const struct option *, int *, int); 124 | +static int parse_long_options(char * const *, const char *, 125 | + const struct option *, int *, int); 126 | +static int gcd(int, int); 127 | +static void permute_args(int, int, int, char * const *); 128 | + 129 | +static char *place = EMSG; /* option letter processing */ 130 | + 131 | +/* XXX: set optreset to 1 rather than these two */ 132 | +static int nonopt_start = -1; /* first non option argument (for permute) */ 133 | +static int nonopt_end = -1; /* first option after non options (for permute) */ 134 | + 135 | +/* Error messages */ 136 | +static const char recargchar[] = "option requires an argument -- %c"; 137 | +static const char recargstring[] = "option requires an argument -- %s"; 138 | +static const char ambig[] = "ambiguous option -- %.*s"; 139 | +static const char noarg[] = "option doesn't take an argument -- %.*s"; 140 | +static const char illoptchar[] = "unknown option -- %c"; 141 | +static const char illoptstring[] = "unknown option -- %s"; 142 | + 143 | +static void 144 | +_vwarnx(const char *fmt,va_list ap) 145 | +{ 146 | + (void)fprintf(stderr,"%s: ",__progname); 147 | + if (fmt != NULL) 148 | + (void)vfprintf(stderr,fmt,ap); 149 | + (void)fprintf(stderr,"\n"); 150 | +} 151 | + 152 | +static void 153 | +warnx(const char *fmt,...) 154 | +{ 155 | + va_list ap; 156 | + va_start(ap,fmt); 157 | + _vwarnx(fmt,ap); 158 | + va_end(ap); 159 | +} 160 | + 161 | +/* 162 | + * Compute the greatest common divisor of a and b. 163 | + */ 164 | +static int 165 | +gcd(int a, int b) 166 | +{ 167 | + int c; 168 | + 169 | + c = a % b; 170 | + while (c != 0) { 171 | + a = b; 172 | + b = c; 173 | + c = a % b; 174 | + } 175 | + 176 | + return (b); 177 | +} 178 | + 179 | +/* 180 | + * Exchange the block from nonopt_start to nonopt_end with the block 181 | + * from nonopt_end to opt_end (keeping the same order of arguments 182 | + * in each block). 183 | + */ 184 | +static void 185 | +permute_args(int panonopt_start, int panonopt_end, int opt_end, 186 | + char * const *nargv) 187 | +{ 188 | + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; 189 | + char *swap; 190 | + 191 | + /* 192 | + * compute lengths of blocks and number and size of cycles 193 | + */ 194 | + nnonopts = panonopt_end - panonopt_start; 195 | + nopts = opt_end - panonopt_end; 196 | + ncycle = gcd(nnonopts, nopts); 197 | + cyclelen = (opt_end - panonopt_start) / ncycle; 198 | + 199 | + for (i = 0; i < ncycle; i++) { 200 | + cstart = panonopt_end+i; 201 | + pos = cstart; 202 | + for (j = 0; j < cyclelen; j++) { 203 | + if (pos >= panonopt_end) 204 | + pos -= nnonopts; 205 | + else 206 | + pos += nopts; 207 | + swap = nargv[pos]; 208 | + /* LINTED const cast */ 209 | + ((char **) nargv)[pos] = nargv[cstart]; 210 | + /* LINTED const cast */ 211 | + ((char **)nargv)[cstart] = swap; 212 | + } 213 | + } 214 | +} 215 | + 216 | +#ifdef REPLACE_GETOPT 217 | +/* 218 | + * getopt -- 219 | + * Parse argc/argv argument vector. 220 | + * 221 | + * [eventually this will replace the BSD getopt] 222 | + */ 223 | +int 224 | +getopt(int nargc, char * const *nargv, const char *options) 225 | +{ 226 | + 227 | + /* 228 | + * We don't pass FLAG_PERMUTE to getopt_internal() since 229 | + * the BSD getopt(3) (unlike GNU) has never done this. 230 | + * 231 | + * Furthermore, since many privileged programs call getopt() 232 | + * before dropping privileges it makes sense to keep things 233 | + * as simple (and bug-free) as possible. 234 | + */ 235 | + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); 236 | +} 237 | +#endif /* REPLACE_GETOPT */ 238 | + 239 | +//extern int getopt(int nargc, char * const *nargv, const char *options); 240 | + 241 | +#ifdef _BSD_SOURCE 242 | +/* 243 | + * BSD adds the non-standard `optreset' feature, for reinitialisation 244 | + * of `getopt' parsing. We support this feature, for applications which 245 | + * proclaim their BSD heritage, before including this header; however, 246 | + * to maintain portability, developers are advised to avoid it. 247 | + */ 248 | +# define optreset __mingw_optreset 249 | +extern int optreset; 250 | +#endif 251 | +#ifdef __cplusplus 252 | +} 253 | +#endif 254 | +/* 255 | + * POSIX requires the `getopt' API to be specified in `unistd.h'; 256 | + * thus, `unistd.h' includes this header. However, we do not want 257 | + * to expose the `getopt_long' or `getopt_long_only' APIs, when 258 | + * included in this manner. Thus, close the standard __GETOPT_H__ 259 | + * declarations block, and open an additional __GETOPT_LONG_H__ 260 | + * specific block, only when *not* __UNISTD_H_SOURCED__, in which 261 | + * to declare the extended API. 262 | + */ 263 | +#endif /* !defined(__GETOPT_H__) */ 264 | + 265 | +#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) 266 | +#define __GETOPT_LONG_H__ 267 | + 268 | +#ifdef __cplusplus 269 | +extern "C" { 270 | +#endif 271 | + 272 | +struct option /* specification for a long form option... */ 273 | +{ 274 | + const char *name; /* option name, without leading hyphens */ 275 | + int has_arg; /* does it take an argument? */ 276 | + int *flag; /* where to save its status, or NULL */ 277 | + int val; /* its associated status value */ 278 | +}; 279 | + 280 | +enum /* permitted values for its `has_arg' field... */ 281 | +{ 282 | + no_argument = 0, /* option never takes an argument */ 283 | + required_argument, /* option always requires an argument */ 284 | + optional_argument /* option may take an argument */ 285 | +}; 286 | + 287 | +/* 288 | + * parse_long_options -- 289 | + * Parse long options in argc/argv argument vector. 290 | + * Returns -1 if short_too is set and the option does not match long_options. 291 | + */ 292 | +static int 293 | +parse_long_options(char * const *nargv, const char *options, 294 | + const struct option *long_options, int *idx, int short_too) 295 | +{ 296 | + char *current_argv, *has_equal; 297 | + size_t current_argv_len; 298 | + int i, ambiguous, match; 299 | + 300 | +#define IDENTICAL_INTERPRETATION(_x, _y) \ 301 | + (long_options[(_x)].has_arg == long_options[(_y)].has_arg && \ 302 | + long_options[(_x)].flag == long_options[(_y)].flag && \ 303 | + long_options[(_x)].val == long_options[(_y)].val) 304 | + 305 | + current_argv = place; 306 | + match = -1; 307 | + ambiguous = 0; 308 | + 309 | + optind++; 310 | + 311 | + if ((has_equal = strchr(current_argv, '=')) != NULL) { 312 | + /* argument found (--option=arg) */ 313 | + current_argv_len = has_equal - current_argv; 314 | + has_equal++; 315 | + } else 316 | + current_argv_len = strlen(current_argv); 317 | + 318 | + for (i = 0; long_options[i].name; i++) { 319 | + /* find matching long option */ 320 | + if (strncmp(current_argv, long_options[i].name, 321 | + current_argv_len)) 322 | + continue; 323 | + 324 | + if (strlen(long_options[i].name) == current_argv_len) { 325 | + /* exact match */ 326 | + match = i; 327 | + ambiguous = 0; 328 | + break; 329 | + } 330 | + /* 331 | + * If this is a known short option, don't allow 332 | + * a partial match of a single character. 333 | + */ 334 | + if (short_too && current_argv_len == 1) 335 | + continue; 336 | + 337 | + if (match == -1) /* partial match */ 338 | + match = i; 339 | + else if (!IDENTICAL_INTERPRETATION(i, match)) 340 | + ambiguous = 1; 341 | + } 342 | + if (ambiguous) { 343 | + /* ambiguous abbreviation */ 344 | + if (PRINT_ERROR) 345 | + warnx(ambig, (int)current_argv_len, 346 | + current_argv); 347 | + optopt = 0; 348 | + return (BADCH); 349 | + } 350 | + if (match != -1) { /* option found */ 351 | + if (long_options[match].has_arg == no_argument 352 | + && has_equal) { 353 | + if (PRINT_ERROR) 354 | + warnx(noarg, (int)current_argv_len, 355 | + current_argv); 356 | + /* 357 | + * XXX: GNU sets optopt to val regardless of flag 358 | + */ 359 | + if (long_options[match].flag == NULL) 360 | + optopt = long_options[match].val; 361 | + else 362 | + optopt = 0; 363 | + return (BADARG); 364 | + } 365 | + if (long_options[match].has_arg == required_argument || 366 | + long_options[match].has_arg == optional_argument) { 367 | + if (has_equal) 368 | + optarg = has_equal; 369 | + else if (long_options[match].has_arg == 370 | + required_argument) { 371 | + /* 372 | + * optional argument doesn't use next nargv 373 | + */ 374 | + optarg = nargv[optind++]; 375 | + } 376 | + } 377 | + if ((long_options[match].has_arg == required_argument) 378 | + && (optarg == NULL)) { 379 | + /* 380 | + * Missing argument; leading ':' indicates no error 381 | + * should be generated. 382 | + */ 383 | + if (PRINT_ERROR) 384 | + warnx(recargstring, 385 | + current_argv); 386 | + /* 387 | + * XXX: GNU sets optopt to val regardless of flag 388 | + */ 389 | + if (long_options[match].flag == NULL) 390 | + optopt = long_options[match].val; 391 | + else 392 | + optopt = 0; 393 | + --optind; 394 | + return (BADARG); 395 | + } 396 | + } else { /* unknown option */ 397 | + if (short_too) { 398 | + --optind; 399 | + return (-1); 400 | + } 401 | + if (PRINT_ERROR) 402 | + warnx(illoptstring, current_argv); 403 | + optopt = 0; 404 | + return (BADCH); 405 | + } 406 | + if (idx) 407 | + *idx = match; 408 | + if (long_options[match].flag) { 409 | + *long_options[match].flag = long_options[match].val; 410 | + return (0); 411 | + } else 412 | + return (long_options[match].val); 413 | +#undef IDENTICAL_INTERPRETATION 414 | +} 415 | + 416 | +/* 417 | + * getopt_internal -- 418 | + * Parse argc/argv argument vector. Called by user level routines. 419 | + */ 420 | +static int 421 | +getopt_internal(int nargc, char * const *nargv, const char *options, 422 | + const struct option *long_options, int *idx, int flags) 423 | +{ 424 | + char *oli; /* option letter list index */ 425 | + int optchar, short_too; 426 | + static int posixly_correct = -1; 427 | + 428 | + if (options == NULL) 429 | + return (-1); 430 | + 431 | + /* 432 | + * XXX Some GNU programs (like cvs) set optind to 0 instead of 433 | + * XXX using optreset. Work around this braindamage. 434 | + */ 435 | + if (optind == 0) 436 | + optind = optreset = 1; 437 | + 438 | + /* 439 | + * Disable GNU extensions if POSIXLY_CORRECT is set or options 440 | + * string begins with a '+'. 441 | + * 442 | + * CV, 2009-12-14: Check POSIXLY_CORRECT anew if optind == 0 or 443 | + * optreset != 0 for GNU compatibility. 444 | + */ 445 | + if (posixly_correct == -1 || optreset != 0) 446 | + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); 447 | + if (*options == '-') 448 | + flags |= FLAG_ALLARGS; 449 | + else if (posixly_correct || *options == '+') 450 | + flags &= ~FLAG_PERMUTE; 451 | + if (*options == '+' || *options == '-') 452 | + options++; 453 | + 454 | + optarg = NULL; 455 | + if (optreset) 456 | + nonopt_start = nonopt_end = -1; 457 | +start: 458 | + if (optreset || !*place) { /* update scanning pointer */ 459 | + optreset = 0; 460 | + if (optind >= nargc) { /* end of argument vector */ 461 | + place = EMSG; 462 | + if (nonopt_end != -1) { 463 | + /* do permutation, if we have to */ 464 | + permute_args(nonopt_start, nonopt_end, 465 | + optind, nargv); 466 | + optind -= nonopt_end - nonopt_start; 467 | + } 468 | + else if (nonopt_start != -1) { 469 | + /* 470 | + * If we skipped non-options, set optind 471 | + * to the first of them. 472 | + */ 473 | + optind = nonopt_start; 474 | + } 475 | + nonopt_start = nonopt_end = -1; 476 | + return (-1); 477 | + } 478 | + if (*(place = nargv[optind]) != '-' || 479 | + (place[1] == '\0' && strchr(options, '-') == NULL)) { 480 | + place = EMSG; /* found non-option */ 481 | + if (flags & FLAG_ALLARGS) { 482 | + /* 483 | + * GNU extension: 484 | + * return non-option as argument to option 1 485 | + */ 486 | + optarg = nargv[optind++]; 487 | + return (INORDER); 488 | + } 489 | + if (!(flags & FLAG_PERMUTE)) { 490 | + /* 491 | + * If no permutation wanted, stop parsing 492 | + * at first non-option. 493 | + */ 494 | + return (-1); 495 | + } 496 | + /* do permutation */ 497 | + if (nonopt_start == -1) 498 | + nonopt_start = optind; 499 | + else if (nonopt_end != -1) { 500 | + permute_args(nonopt_start, nonopt_end, 501 | + optind, nargv); 502 | + nonopt_start = optind - 503 | + (nonopt_end - nonopt_start); 504 | + nonopt_end = -1; 505 | + } 506 | + optind++; 507 | + /* process next argument */ 508 | + goto start; 509 | + } 510 | + if (nonopt_start != -1 && nonopt_end == -1) 511 | + nonopt_end = optind; 512 | + 513 | + /* 514 | + * If we have "-" do nothing, if "--" we are done. 515 | + */ 516 | + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { 517 | + optind++; 518 | + place = EMSG; 519 | + /* 520 | + * We found an option (--), so if we skipped 521 | + * non-options, we have to permute. 522 | + */ 523 | + if (nonopt_end != -1) { 524 | + permute_args(nonopt_start, nonopt_end, 525 | + optind, nargv); 526 | + optind -= nonopt_end - nonopt_start; 527 | + } 528 | + nonopt_start = nonopt_end = -1; 529 | + return (-1); 530 | + } 531 | + } 532 | + 533 | + /* 534 | + * Check long options if: 535 | + * 1) we were passed some 536 | + * 2) the arg is not just "-" 537 | + * 3) either the arg starts with -- we are getopt_long_only() 538 | + */ 539 | + if (long_options != NULL && place != nargv[optind] && 540 | + (*place == '-' || (flags & FLAG_LONGONLY))) { 541 | + short_too = 0; 542 | + if (*place == '-') 543 | + place++; /* --foo long option */ 544 | + else if (*place != ':' && strchr(options, *place) != NULL) 545 | + short_too = 1; /* could be short option too */ 546 | + 547 | + optchar = parse_long_options(nargv, options, long_options, 548 | + idx, short_too); 549 | + if (optchar != -1) { 550 | + place = EMSG; 551 | + return (optchar); 552 | + } 553 | + } 554 | + 555 | + if ((optchar = (int)*place++) == (int)':' || 556 | + (optchar == (int)'-' && *place != '\0') || 557 | + (oli = (char*)strchr(options, optchar)) == NULL) { 558 | + /* 559 | + * If the user specified "-" and '-' isn't listed in 560 | + * options, return -1 (non-option) as per POSIX. 561 | + * Otherwise, it is an unknown option character (or ':'). 562 | + */ 563 | + if (optchar == (int)'-' && *place == '\0') 564 | + return (-1); 565 | + if (!*place) 566 | + ++optind; 567 | + if (PRINT_ERROR) 568 | + warnx(illoptchar, optchar); 569 | + optopt = optchar; 570 | + return (BADCH); 571 | + } 572 | + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { 573 | + /* -W long-option */ 574 | + if (*place) /* no space */ 575 | + /* NOTHING */; 576 | + else if (++optind >= nargc) { /* no arg */ 577 | + place = EMSG; 578 | + if (PRINT_ERROR) 579 | + warnx(recargchar, optchar); 580 | + optopt = optchar; 581 | + return (BADARG); 582 | + } else /* white space */ 583 | + place = nargv[optind]; 584 | + optchar = parse_long_options(nargv, options, long_options, 585 | + idx, 0); 586 | + place = EMSG; 587 | + return (optchar); 588 | + } 589 | + if (*++oli != ':') { /* doesn't take argument */ 590 | + if (!*place) 591 | + ++optind; 592 | + } else { /* takes (optional) argument */ 593 | + optarg = NULL; 594 | + if (*place) /* no white space */ 595 | + optarg = place; 596 | + else if (oli[1] != ':') { /* arg not optional */ 597 | + if (++optind >= nargc) { /* no arg */ 598 | + place = EMSG; 599 | + if (PRINT_ERROR) 600 | + warnx(recargchar, optchar); 601 | + optopt = optchar; 602 | + return (BADARG); 603 | + } else 604 | + optarg = nargv[optind]; 605 | + } 606 | + place = EMSG; 607 | + ++optind; 608 | + } 609 | + /* dump back option letter */ 610 | + return (optchar); 611 | +} 612 | + 613 | +/* 614 | + * getopt_long -- 615 | + * Parse argc/argv argument vector. 616 | + */ 617 | +int 618 | +getopt_long(int nargc, char * const *nargv, const char *options, 619 | + const struct option *long_options, int *idx) 620 | +{ 621 | + 622 | + return (getopt_internal(nargc, nargv, options, long_options, idx, 623 | + FLAG_PERMUTE)); 624 | +} 625 | + 626 | +/* 627 | + * getopt_long_only -- 628 | + * Parse argc/argv argument vector. 629 | + */ 630 | +int 631 | +getopt_long_only(int nargc, char * const *nargv, const char *options, 632 | + const struct option *long_options, int *idx) 633 | +{ 634 | + 635 | + return (getopt_internal(nargc, nargv, options, long_options, idx, 636 | + FLAG_PERMUTE|FLAG_LONGONLY)); 637 | +} 638 | + 639 | +//extern int getopt_long(int nargc, char * const *nargv, const char *options, 640 | +// const struct option *long_options, int *idx); 641 | +//extern int getopt_long_only(int nargc, char * const *nargv, const char *options, 642 | +// const struct option *long_options, int *idx); 643 | +/* 644 | + * Previous MinGW implementation had... 645 | + */ 646 | +#ifndef HAVE_DECL_GETOPT 647 | +/* 648 | + * ...for the long form API only; keep this for compatibility. 649 | + */ 650 | +# define HAVE_DECL_GETOPT 1 651 | +#endif 652 | + 653 | +#ifdef __cplusplus 654 | +} 655 | +#endif 656 | + 657 | +#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */ 658 | diff -ruN librtmp/librtmp.def librtmp/librtmp.def 659 | --- librtmp/librtmp.def 1970-01-01 01:00:00.000000000 +0100 660 | +++ librtmp/librtmp.def 2016-08-21 08:48:00.103955900 +0200 661 | @@ -0,0 +1,149 @@ 662 | +EXPORTS 663 | + AMF3CD_AddProp 664 | + AMF3CD_GetProp 665 | + AMF3Prop_Decode 666 | + AMF3ReadInteger 667 | + AMF3ReadString 668 | + AMF3_Decode 669 | + AMFProp_Decode 670 | + AMFProp_Dump 671 | + AMFProp_Encode 672 | + AMFProp_GetBoolean 673 | + AMFProp_GetName 674 | + AMFProp_GetNumber 675 | + AMFProp_GetObject 676 | + AMFProp_GetString 677 | + AMFProp_GetType 678 | + AMFProp_IsValid 679 | + AMFProp_Reset 680 | + AMFProp_SetName 681 | + AMF_AddProp 682 | + AMF_CountProp 683 | + AMF_Decode 684 | + AMF_DecodeArray 685 | + AMF_DecodeBoolean 686 | + AMF_DecodeInt16 687 | + AMF_DecodeInt24 688 | + AMF_DecodeInt32 689 | + AMF_DecodeLongString 690 | + AMF_DecodeNumber 691 | + AMF_DecodeString 692 | + AMF_Dump 693 | + AMF_Encode 694 | + AMF_EncodeArray 695 | + AMF_EncodeBoolean 696 | + AMF_EncodeEcmaArray 697 | + AMF_EncodeInt16 698 | + AMF_EncodeInt24 699 | + AMF_EncodeInt32 700 | + AMF_EncodeNamedBoolean 701 | + AMF_EncodeNamedNumber 702 | + AMF_EncodeNamedString 703 | + AMF_EncodeNumber 704 | + AMF_EncodeString 705 | + AMF_GetProp 706 | + AMF_Reset 707 | + HTTP_get 708 | + RTMPPacket_Alloc 709 | + RTMPPacket_Dump 710 | + RTMPPacket_Free 711 | + RTMPPacket_Reset 712 | + RTMPProtocolStrings 713 | + RTMPProtocolStringsLower 714 | + RTMPSockBuf_Close 715 | + RTMPSockBuf_Fill 716 | + RTMPSockBuf_Send 717 | + RTMP_Alloc 718 | + RTMP_ClientPacket 719 | + RTMP_Close 720 | + RTMP_Connect 721 | + RTMP_Connect0 722 | + RTMP_Connect1 723 | + RTMP_ConnectStream 724 | + RTMP_DefaultFlashVer 725 | + RTMP_DeleteStream 726 | + RTMP_DropRequest 727 | + RTMP_EnableWrite 728 | + RTMP_FindFirstMatchingProperty 729 | + RTMP_FindPrefixProperty 730 | + RTMP_Free 731 | + RTMP_GetDuration 732 | + RTMP_GetNextMediaPacket 733 | + RTMP_GetTime 734 | + RTMP_HashSWF 735 | + RTMP_Init 736 | + RTMP_IsConnected 737 | + RTMP_IsTimedout 738 | + RTMP_LibVersion 739 | + RTMP_Log 740 | + RTMP_LogGetLevel 741 | + RTMP_LogHex 742 | + RTMP_LogHexString 743 | + RTMP_LogPrintf 744 | + RTMP_LogSetCallback 745 | + RTMP_LogSetLevel 746 | + RTMP_LogSetOutput 747 | + RTMP_LogStatus 748 | + RTMP_ParsePlaypath 749 | + RTMP_ParseURL 750 | + RTMP_Pause 751 | + RTMP_Read 752 | + RTMP_ReadPacket 753 | + RTMP_ReconnectStream 754 | + RTMP_SendChunk 755 | + RTMP_SendClientBW 756 | + RTMP_SendCreateStream 757 | + RTMP_SendCtrl 758 | + RTMP_SendPacket 759 | + RTMP_SendPause 760 | + RTMP_SendSeek 761 | + RTMP_SendServerBW 762 | + RTMP_Serve 763 | + RTMP_SetBufferMS 764 | + RTMP_SetOpt 765 | + RTMP_SetupStream 766 | + RTMP_SetupURL 767 | + RTMP_Socket 768 | + RTMP_TLS_Accept 769 | + RTMP_TLS_AllocServerContext 770 | + RTMP_TLS_FreeServerContext 771 | + RTMP_TLS_Init 772 | + RTMP_TLS_ctx 773 | + RTMP_ToggleStream 774 | + RTMP_UpdateBufferMS 775 | + RTMP_UserInterrupt 776 | + RTMP_Write 777 | + RTMP_ctrlC 778 | + RTMP_debuglevel 779 | + adler32 780 | + adler32_combine 781 | + adler32_combine64 782 | + crc32 783 | + crc32_combine 784 | + crc32_combine64 785 | + get_crc_table 786 | + inflate 787 | + inflateCopy 788 | + inflateEnd 789 | + inflateGetDictionary 790 | + inflateGetHeader 791 | + inflateInit2_ 792 | + inflateInit_ 793 | + inflateMark 794 | + inflatePrime 795 | + inflateReset 796 | + inflateReset2 797 | + inflateResetKeep 798 | + inflateSetDictionary 799 | + inflateSync 800 | + inflateSyncPoint 801 | + inflateUndermine 802 | + inflate_copyright 803 | + inflate_fast 804 | + inflate_table 805 | + zError 806 | + z_errmsg 807 | + zcalloc 808 | + zcfree 809 | + zlibCompileFlags 810 | + zlibVersion 811 | diff -ruN librtmp/Makefile.win32 librtmp/Makefile.win32 812 | --- librtmp/Makefile.win32 1970-01-01 01:00:00.000000000 +0100 813 | +++ librtmp/Makefile.win32 2016-08-21 11:21:40.599080100 +0200 814 | @@ -0,0 +1,64 @@ 815 | +VERSION=v2.4 816 | + 817 | +# Compiler, linker, librarian, and other tools 818 | +CC = cl 819 | +LD = link 820 | +AR = lib 821 | +RM = del 822 | + 823 | +prefix=/usr/local 824 | + 825 | +CRYPTO_DEF=-DUSE_OPENSSL 826 | +DEF=-DRTMPDUMP_VERSION=\"$(VERSION)\" $(CRYPTO_DEF) $(XDEF) 827 | + 828 | +CFLAGS = -nologo -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE -W3 -O2 -sdl- -MT $(DEF) $(XCFLAGS) 829 | +LDFLAGS = -nologo $(XLDFLAGS) 830 | +ARFLAGS = -nologo 831 | + 832 | +incdir=$(prefix)/include/librtmp 833 | +bindir=$(prefix)/bin 834 | +libdir=$(prefix)/lib 835 | +mandir=$(prefix)/man 836 | + 837 | +DLL_LIBS=ws2_32.lib winmm.lib gdi32.lib crypt32.lib User32.lib advapi32.lib libeay32.lib ssleay32.lib zlib.lib 838 | +PRIVATE_LIBS=-lws2_32 -lwinmm -lgdi32 -luser32 -lcrypt32 -llibeay32 -lssleay32 -lzlib 839 | +CRYPTO_REQ= 840 | +PUBLIC_LIBS= 841 | + 842 | +LIB_DEF = librtmp.def 843 | +STATIC_LIB = librtmp.lib 844 | +SHARED_LIB = librtmp.1.dll 845 | +IMP_LIB = librtmp.1.lib 846 | + 847 | +C_SOURCE=rtmp.c log.c amf.c hashswf.c parseurl.c 848 | +OBJS=$(C_SOURCE:.c=.obj) 849 | + 850 | + 851 | +all: $(STATIC_LIB) $(SHARED_LIB) $(IMP_LIB) 852 | + 853 | +clean: 854 | + rm -f *.obj *.lib *.obj *.dll *.pdb *.exp librtmp.pc 855 | + 856 | +install: librtmp.pc 857 | + @mkdir -p $(incdir) $(libdir)/pkgconfig $(mandir)/man3 $(bindir) 858 | + cp amf.h http.h log.h rtmp.h $(incdir) 859 | + cp librtmp.lib $(libdir)/rtmp.lib 860 | + cp librtmp.1.dll $(bindir)/rtmp.1.dll 861 | + cp librtmp.def $(libdir)/rtmp.def 862 | + cp librtmp.pc $(libdir)/pkgconfig 863 | + cp librtmp.3 $(mandir)/man3 864 | + 865 | +$(STATIC_LIB): $(OBJS) 866 | + $(AR) $(ARFLAGS) -out:$@ $(OBJS) 867 | + 868 | +$(IMP_LIB): $(SHARED_LIB) 869 | + 870 | +$(SHARED_LIB): $(OBJS) 871 | + $(LD) $(LDFLAGS) -OUT:$@ -DEF:$(LIB_DEF) -implib:$(IMP_LIB) -DLL $(DLL_LIBS) $(OBJS) 872 | + 873 | +librtmp.pc: 874 | + @sed -e "s;@prefix@;$(prefix);" -e "s;@libdir@;$(libdir);" \ 875 | + -e "s;@VERSION@;$(VERSION);" \ 876 | + -e "s;@CRYPTO_REQ@;$(CRYPTO_REQ);" \ 877 | + -e "s;@PUBLIC_LIBS@;$(PUBLIC_LIBS);" \ 878 | + -e "s;@PRIVATE_LIBS@;$(PRIVATE_LIBS);" librtmp.pc.in > $@ 879 | \ Kein Zeilenumbruch am Dateiende. 880 | diff -ruN librtmp/rtmp_sys.h librtmp/rtmp_sys.h 881 | --- librtmp/rtmp_sys.h 2016-08-21 11:27:45.623484200 +0200 882 | +++ librtmp/rtmp_sys.h 2016-08-21 08:48:00.110690800 +0200 883 | @@ -28,10 +28,14 @@ 884 | #include 885 | 886 | #ifdef _MSC_VER /* MSVC */ 887 | -#define snprintf _snprintf 888 | #define strcasecmp stricmp 889 | #define strncasecmp strnicmp 890 | + 891 | +#if _MSC_VER<1900 892 | #define vsnprintf _vsnprintf 893 | +#define snprintf _snprintf 894 | +#endif 895 | + 896 | #endif 897 | 898 | #define GetSockError() WSAGetLastError() 899 | diff -ruN Makefile.win32 Makefile.win32 900 | --- Makefile.win32 1970-01-01 01:00:00.000000000 +0100 901 | +++ Makefile.win32 2016-08-21 11:23:32.208446300 +0200 902 | @@ -0,0 +1,68 @@ 903 | +VERSION=v2.4 904 | + 905 | +# Compiler, linker, librarian, and other tools 906 | +CC = cl 907 | +LD = link 908 | +AR = lib 909 | +RM = del 910 | + 911 | +prefix=/usr/local 912 | + 913 | +DEF=-DRTMPDUMP_VERSION=\"$(VERSION)\" -DUSE_OPENSSL $(XDEF) 914 | + 915 | +CFLAGS = -nologo -DWIN32 -D_CRT_SECURE_NO_DEPRECATE -DHAVE_STRUCT_TIMESPEC -MT -O2 -W3 $(DEF) $(XCFLAGS) 916 | +LDFLAGS = -nologo $(XLDFLAGS) 917 | +ARFLAGS = -nologo 918 | + 919 | +bindir=$(prefix)/bin 920 | +sbindir=$(prefix)/sbin 921 | +mandir=$(prefix)/man 922 | + 923 | +BINDIR=$(DESTDIR)$(bindir) 924 | +SBINDIR=$(DESTDIR)$(sbindir) 925 | +MANDIR=$(DESTDIR)$(mandir) 926 | + 927 | +CRYPTO_LIB=libeay32.lib ssleay32.lib 928 | +LIBS_SYS=ws2_32.lib winmm.lib gdi32.lib crypt32.lib User32.lib zlib.lib 929 | +LIBRTMP=librtmp/librtmp.lib 930 | +LIBS=$(LIBRTMP) $(CRYPTO_LIB) $(LIBS_SYS) $(XLIBS) 931 | + 932 | +INCRTMP=librtmp/rtmp_sys.h librtmp/rtmp.h librtmp/log.h librtmp/amf.h 933 | + 934 | +PROGS=rtmpdump rtmpgw rtmpsrv rtmpsuck 935 | + 936 | + 937 | + 938 | +all: $(LIBRTMP) $(PROGS) 939 | + 940 | +install: 941 | + @mkdir -p $(BINDIR) $(SBINDIR) $(MANDIR)/man1 $(MANDIR)/man8 942 | + cp rtmpdump.exe $(BINDIR) 943 | + cp rtmpgw.exe rtmpsrv.exe rtmpsuck.exe $(SBINDIR) 944 | + cp rtmpdump.1 $(MANDIR)/man1 945 | + cp rtmpgw.8 $(MANDIR)/man8 946 | + @cd librtmp 947 | + @$(MAKE) -f Makefile.win32 prefix="$(prefix)" install 948 | + @cd .. 949 | + 950 | +clean: 951 | + rm -f *.obj *.exe 952 | + @cd librtmp 953 | + @$(MAKE) -f Makefile.win32 clean 954 | + 955 | +$(LIBRTMP): 956 | + @cd librtmp 957 | + @$(MAKE) -f Makefile.win32 all 958 | + @cd .. 959 | + 960 | +rtmpdump: rtmpdump.obj 961 | + $(LD) $(LDFLAGS) -out:$@.exe rtmpdump.obj $(LIBS) 962 | + 963 | +rtmpsrv: rtmpsrv.obj thread.obj 964 | + $(LD) $(LDFLAGS) -out:$@.exe rtmpsrv.obj thread.obj $(LIBS) 965 | + 966 | +rtmpsuck: rtmpsuck.obj thread.obj 967 | + $(LD) $(LDFLAGS) -out:$@.exe rtmpsuck.obj thread.obj $(LIBS) 968 | + 969 | +rtmpgw: rtmpgw.obj thread.obj 970 | + $(LD) $(LDFLAGS) -out:$@.exe rtmpgw.obj thread.obj $(LIBS) 971 | \ Kein Zeilenumbruch am Dateiende. 972 | diff -ruN rtmpdump.c rtmpdump.c 973 | --- rtmpdump.c 2016-08-21 11:27:45.633472500 +0200 974 | +++ rtmpdump.c 2016-08-21 08:48:00.118199000 +0200 975 | @@ -34,8 +34,9 @@ 976 | #include "librtmp/log.h" 977 | 978 | #ifdef WIN32 979 | -#define fseeko fseeko64 980 | -#define ftello ftello64 981 | +#define off_t long int 982 | +#define fseeko _fseeki64 983 | +#define ftello _ftelli64 984 | #include 985 | #include 986 | #define SET_BINMODE(f) setmode(fileno(f), O_BINARY) 987 | @@ -279,7 +280,7 @@ 988 | uint32_t * nInitialFrameSize) // length of initialFrame [out] 989 | { 990 | const size_t bufferSize = 16; 991 | - char buffer[bufferSize]; 992 | + char buffer[16]; 993 | uint8_t dataType; 994 | int bAudioOnly; 995 | off_t size; 996 | -------------------------------------------------------------------------------- /patches/fdk_aac-win32-make.patch: -------------------------------------------------------------------------------- 1 | diff -ruN aac-enc.c aac-enc.c 2 | --- aac-enc.c 2016-08-25 12:20:08.000000000 +0200 3 | +++ aac-enc.c 2016-08-27 16:09:27.581437700 +0200 4 | @@ -18,11 +18,35 @@ 5 | 6 | #include 7 | #include 8 | + 9 | +#if defined(_MSC_VER) 10 | +#include 11 | +#include 12 | + 13 | +double get_time() { 14 | + LARGE_INTEGER t, f; 15 | + QueryPerformanceCounter(&t); 16 | + QueryPerformanceFrequency(&f); 17 | + return (double)t.QuadPart/(double)f.QuadPart; 18 | +} 19 | + 20 | +#else 21 | #include 22 | +#include 23 | + 24 | +double get_time() { 25 | + struct timeval t; 26 | + struct timezone tzp; 27 | + gettimeofday(&t, &tzp); 28 | + return t.tv_sec + t.tv_usec*1e-6; 29 | +} 30 | +#endif 31 | + 32 | #include 33 | #include "libAACenc/include/aacenc_lib.h" 34 | #include "wavreader.h" 35 | 36 | + 37 | void usage(const char* name) { 38 | fprintf(stderr, "%s [-r bitrate] [-t aot] [-a afterburner] [-s sbr] [-v vbr] in.wav out.aac\n", name); 39 | fprintf(stderr, "Supported AOTs:\n"); 40 | @@ -80,6 +104,8 @@ 41 | infile = argv[optind]; 42 | outfile = argv[optind + 1]; 43 | 44 | + double start = get_time(); 45 | + 46 | wav = wav_read_open(infile); 47 | if (!wav) { 48 | fprintf(stderr, "Unable to open wav file %s\n", infile); 49 | @@ -228,6 +254,10 @@ 50 | fclose(out); 51 | wav_read_close(wav); 52 | aacEncClose(&handle); 53 | + 54 | + double end = get_time(); 55 | + 56 | + printf("Encoding took %lf seconds.\n", (end - start)); 57 | 58 | return 0; 59 | } 60 | diff -ruN Makefile.vc Makefile.vc 61 | --- Makefile.vc 1970-01-01 01:00:00.000000000 +0100 62 | +++ Makefile.vc 2016-08-28 20:24:56.286907100 +0200 63 | @@ -0,0 +1,279 @@ 64 | +# 65 | +# Options: 66 | +# machine=Win32|Win64 67 | +# prefix=\path\to\install 68 | +# 69 | +# If no machine is specified, the makefile uses the systems 70 | +# PROCESSOR_ARCHITECTURE. 71 | +# 72 | +# Compiling: nmake -f Makefile.win32 73 | +# Installing: nmake -f Makefile.win32 prefix=\path\to\x install 74 | +# 75 | + 76 | +VERSION=0.1.5 77 | + 78 | +# Compiler, linker, librarian, and other tools 79 | +CC = cl 80 | +CXX = cl 81 | +LD = link 82 | +AR = lib 83 | + 84 | +!IFDEF MACHINE 85 | +!IF "$(MACHINE)" == "Win64" 86 | +TARGET_FLAGS = /D__x86_64__ 87 | +!ENDIF 88 | +!ELSE 89 | +!IF "$(PROCESSOR_ARCHITECTURE)" == "AMD64" 90 | +TARGET_FLAGS = /D__x86_64__ 91 | +!ENDIF 92 | +!ENDIF 93 | + 94 | +!IFDEF HOME 95 | +# In case we are using a cross compiler shell. 96 | +MKDIR_FLAGS = -p 97 | +!ENDIF 98 | + 99 | +AM_CPPFLAGS = \ 100 | + -Iwin32 \ 101 | + -IlibAACdec/include \ 102 | + -IlibAACenc/include \ 103 | + -IlibSBRdec/include \ 104 | + -IlibSBRenc/include \ 105 | + -IlibMpegTPDec/include \ 106 | + -IlibMpegTPEnc/include \ 107 | + -IlibSYS/include \ 108 | + -IlibFDK/include \ 109 | + -IlibPCMutils/include 110 | + 111 | +AACDEC_SRC = \ 112 | + libAACdec/src/aacdec_drc.cpp \ 113 | + libAACdec/src/aacdec_hcr.cpp \ 114 | + libAACdec/src/aacdecoder.cpp \ 115 | + libAACdec/src/aacdec_pns.cpp \ 116 | + libAACdec/src/aac_ram.cpp \ 117 | + libAACdec/src/block.cpp \ 118 | + libAACdec/src/channelinfo.cpp \ 119 | + libAACdec/src/ldfiltbank.cpp \ 120 | + libAACdec/src/rvlcbit.cpp \ 121 | + libAACdec/src/rvlc.cpp \ 122 | + libAACdec/src/aacdec_hcr_bit.cpp \ 123 | + libAACdec/src/aacdec_hcrs.cpp \ 124 | + libAACdec/src/aacdecoder_lib.cpp \ 125 | + libAACdec/src/aacdec_tns.cpp \ 126 | + libAACdec/src/aac_rom.cpp \ 127 | + libAACdec/src/channel.cpp \ 128 | + libAACdec/src/conceal.cpp \ 129 | + libAACdec/src/pulsedata.cpp \ 130 | + libAACdec/src/rvlcconceal.cpp \ 131 | + libAACdec/src/stereo.cpp 132 | + 133 | +AACENC_SRC = \ 134 | + libAACenc/src/aacenc.cpp \ 135 | + libAACenc/src/aacEnc_ram.cpp \ 136 | + libAACenc/src/band_nrg.cpp \ 137 | + libAACenc/src/block_switch.cpp \ 138 | + libAACenc/src/grp_data.cpp \ 139 | + libAACenc/src/metadata_main.cpp \ 140 | + libAACenc/src/pre_echo_control.cpp \ 141 | + libAACenc/src/quantize.cpp \ 142 | + libAACenc/src/tonality.cpp \ 143 | + libAACenc/src/aacEnc_rom.cpp \ 144 | + libAACenc/src/bandwidth.cpp \ 145 | + libAACenc/src/channel_map.cpp \ 146 | + libAACenc/src/intensity.cpp \ 147 | + libAACenc/src/ms_stereo.cpp \ 148 | + libAACenc/src/psy_configuration.cpp \ 149 | + libAACenc/src/sf_estim.cpp \ 150 | + libAACenc/src/transform.cpp \ 151 | + libAACenc/src/aacenc_lib.cpp \ 152 | + libAACenc/src/aacenc_tns.cpp \ 153 | + libAACenc/src/bit_cnt.cpp \ 154 | + libAACenc/src/chaosmeasure.cpp \ 155 | + libAACenc/src/line_pe.cpp \ 156 | + libAACenc/src/noisedet.cpp \ 157 | + libAACenc/src/psy_main.cpp \ 158 | + libAACenc/src/spreading.cpp \ 159 | + libAACenc/src/aacenc_pns.cpp \ 160 | + libAACenc/src/adj_thr.cpp \ 161 | + libAACenc/src/bitenc.cpp \ 162 | + libAACenc/src/dyn_bits.cpp \ 163 | + libAACenc/src/metadata_compressor.cpp \ 164 | + libAACenc/src/pnsparam.cpp \ 165 | + libAACenc/src/qc_main.cpp 166 | + 167 | +FDK_SRC = \ 168 | + libFDK/src/autocorr2nd.cpp \ 169 | + libFDK/src/dct.cpp \ 170 | + libFDK/src/FDK_bitbuffer.cpp \ 171 | + libFDK/src/FDK_core.cpp \ 172 | + libFDK/src/FDK_crc.cpp \ 173 | + libFDK/src/FDK_hybrid.cpp \ 174 | + libFDK/src/FDK_tools_rom.cpp \ 175 | + libFDK/src/FDK_trigFcts.cpp \ 176 | + libFDK/src/fft.cpp \ 177 | + libFDK/src/fft_rad2.cpp \ 178 | + libFDK/src/fixpoint_math.cpp \ 179 | + libFDK/src/mdct.cpp \ 180 | + libFDK/src/qmf.cpp \ 181 | + libFDK/src/scale.cpp \ 182 | + 183 | +MPEGTPDEC_SRC = \ 184 | + libMpegTPDec/src/tpdec_adif.cpp \ 185 | + libMpegTPDec/src/tpdec_adts.cpp \ 186 | + libMpegTPDec/src/tpdec_asc.cpp \ 187 | + libMpegTPDec/src/tpdec_drm.cpp \ 188 | + libMpegTPDec/src/tpdec_latm.cpp \ 189 | + libMpegTPDec/src/tpdec_lib.cpp 190 | + 191 | +MPEGTPENC_SRC = \ 192 | + libMpegTPEnc/src/tpenc_adif.cpp \ 193 | + libMpegTPEnc/src/tpenc_adts.cpp \ 194 | + libMpegTPEnc/src/tpenc_asc.cpp \ 195 | + libMpegTPEnc/src/tpenc_latm.cpp \ 196 | + libMpegTPEnc/src/tpenc_lib.cpp 197 | + 198 | +PCMUTILS_SRC = \ 199 | + libPCMutils/src/limiter.cpp \ 200 | + libPCMutils/src/pcmutils_lib.cpp 201 | + 202 | +SBRDEC_SRC = \ 203 | + libSBRdec/src/env_calc.cpp \ 204 | + libSBRdec/src/env_dec.cpp \ 205 | + libSBRdec/src/env_extr.cpp \ 206 | + libSBRdec/src/huff_dec.cpp \ 207 | + libSBRdec/src/lpp_tran.cpp \ 208 | + libSBRdec/src/psbitdec.cpp \ 209 | + libSBRdec/src/psdec.cpp \ 210 | + libSBRdec/src/psdec_hybrid.cpp \ 211 | + libSBRdec/src/sbr_crc.cpp \ 212 | + libSBRdec/src/sbr_deb.cpp \ 213 | + libSBRdec/src/sbr_dec.cpp \ 214 | + libSBRdec/src/sbrdec_drc.cpp \ 215 | + libSBRdec/src/sbrdec_freq_sca.cpp \ 216 | + libSBRdec/src/sbrdecoder.cpp \ 217 | + libSBRdec/src/sbr_ram.cpp \ 218 | + libSBRdec/src/sbr_rom.cpp 219 | + 220 | +SBRENC_SRC = \ 221 | + libSBRenc/src/bit_sbr.cpp \ 222 | + libSBRenc/src/env_bit.cpp \ 223 | + libSBRenc/src/fram_gen.cpp \ 224 | + libSBRenc/src/mh_det.cpp \ 225 | + libSBRenc/src/ps_bitenc.cpp \ 226 | + libSBRenc/src/ps_encode.cpp \ 227 | + libSBRenc/src/resampler.cpp \ 228 | + libSBRenc/src/sbr_encoder.cpp \ 229 | + libSBRenc/src/sbr_ram.cpp \ 230 | + libSBRenc/src/ton_corr.cpp \ 231 | + libSBRenc/src/code_env.cpp \ 232 | + libSBRenc/src/env_est.cpp \ 233 | + libSBRenc/src/invf_est.cpp \ 234 | + libSBRenc/src/nf_est.cpp \ 235 | + libSBRenc/src/ps_main.cpp \ 236 | + libSBRenc/src/sbrenc_freq_sca.cpp \ 237 | + libSBRenc/src/sbr_misc.cpp \ 238 | + libSBRenc/src/sbr_rom.cpp \ 239 | + libSBRenc/src/tran_det.cpp 240 | + 241 | +SYS_SRC = \ 242 | + libSYS/src/cmdl_parser.cpp \ 243 | + libSYS/src/conv_string.cpp \ 244 | + libSYS/src/genericStds.cpp \ 245 | + libSYS/src/wav_file.cpp 246 | + 247 | +libfdk_aac_SOURCES = \ 248 | + $(AACDEC_SRC) $(AACENC_SRC) \ 249 | + $(MPEGTPDEC_SRC) $(MPEGTPENC_SRC) \ 250 | + $(SBRDEC_SRC) $(SBRENC_SRC) \ 251 | + $(PCMUTILS_SRC) $(FDK_SRC) $(SYS_SRC) 252 | + 253 | + 254 | +aac_enc_SOURCES = aac-enc.c wavreader.c 255 | + 256 | +prefix = \usr\local 257 | +prefix_win = $(prefix:/=\) # In case we are using MSYS or MinGW. 258 | + 259 | +CFLAGS = /nologo /W3 /Ox /MT /EHsc $(TARGET_FLAGS) $(AM_CPPFLAGS) $(XCFLAGS) 260 | +CXXFLAGS = $(CFLAGS) 261 | +CPPFLAGS = $(CFLAGS) 262 | +LDFLAGS = -nologo $(XLDFLAGS) 263 | +ARFLAGS = -nologo 264 | + 265 | +incdir = $(prefix_win)\include\fdk-aac 266 | +bindir = $(prefix_win)\bin 267 | +libdir = $(prefix_win)\lib 268 | + 269 | +INST_DIRS = $(bindir) $(incdir) $(libdir)\pkgconfig 270 | + 271 | +DLL_LIBS = 272 | +PRIVATE_LIBS = 273 | +PUBLIC_LIBS = 274 | + 275 | +LIB_DEF = fdk-aac.def 276 | +STATIC_LIB = fdk-aac.lib 277 | +SHARED_LIB = fdk-aac-1.dll 278 | +IMP_LIB = fdk-aac.dll.lib 279 | + 280 | +AAC_ENC_OBJS = $(aac_enc_SOURCES:.c=.obj) 281 | +FDK_OBJS = $(libfdk_aac_SOURCES:.cpp=.obj) 282 | + 283 | +PROGS = aac-enc.exe 284 | + 285 | + 286 | +all: $(LIB_DEF) $(STATIC_LIB) $(SHARED_LIB) $(IMP_LIB) $(PROGS) 287 | + 288 | +clean: 289 | + del /f $(LIB_DEF) $(STATIC_LIB) $(SHARED_LIB) $(IMP_LIB) $(PROGS) libfdk-aac.pc 2>NUL 290 | + del /f *.obj *.exp 2>NUL 291 | + del /f libAACdec\src\*.obj 2>NUL 292 | + del /f libAACenc\src\*.obj 2>NUL 293 | + del /f libFDK\src\*.obj 2>NUL 294 | + del /f libMpegTPDec\src\*.obj 2>NUL 295 | + del /f libMpegTPEnc\src\*.obj 2>NUL 296 | + del /f libPCMutils\src\*.obj 2>NUL 297 | + del /f libSBRdec\src\*.obj 2>NUL 298 | + del /f libSBRenc\src\*.obj 2>NUL 299 | + del /f libSYS\src\*.obj 2>NUL 300 | + 301 | +install: $(INST_DIRS) libfdk-aac.pc 302 | + copy libAACdec\include\aacdecoder_lib.h $(incdir) 303 | + copy libAACenc\include\aacenc_lib.h $(incdir) 304 | + copy libSYS\include\FDK_audio.h $(incdir) 305 | + copy libSYS\include\genericStds.h $(incdir) 306 | + copy libSYS\include\machine_type.h $(incdir) 307 | + copy $(STATIC_LIB) $(libdir) 308 | + copy $(IMP_LIB) $(libdir) 309 | + copy $(SHARED_LIB) $(bindir) 310 | + copy $(PROGS) $(bindir) 311 | + copy $(LIB_DEF) $(libdir) 312 | + copy libfdk-aac.pc $(libdir)\pkgconfig 313 | + 314 | +$(INST_DIRS): 315 | + @mkdir $(MKDIR_FLAGS) $@ 316 | + 317 | +$(STATIC_LIB): $(FDK_OBJS) 318 | + $(AR) $(ARFLAGS) -out:$@ $(FDK_OBJS) 319 | + 320 | +$(IMP_LIB): $(SHARED_LIB) 321 | + 322 | +$(SHARED_LIB): $(FDK_OBJS) 323 | + $(LD) $(LDFLAGS) -OUT:$@ -DEF:$(LIB_DEF) -implib:$(IMP_LIB) -DLL $(DLL_LIBS) $(FDK_OBJS) 324 | + 325 | +$(PROGS): $(AAC_ENC_OBJS) 326 | + $(LD) $(LDFLAGS) -out:$@ $(AAC_ENC_OBJS) $(STATIC_LIB) 327 | + 328 | +.cpp.obj: 329 | + $(CXX) $(CXXFLAGS) -c -Fo:$@ $< 330 | + 331 | +$(LIB_DEF): 332 | + @echo EXPORTS > $(LIB_DEF) 333 | + @type fdk-aac.sym >> $(LIB_DEF) 334 | + 335 | +libfdk-aac.pc: 336 | + @sed -e "s;@prefix@;$(prefix);" \ 337 | + -e 's;@exec_prefix@;$(prefix);' \ 338 | + -e "s;@libdir@;$(prefix)/lib;" \ 339 | + -e "s;@includedir@;$(prefix)/include;" \ 340 | + -e "s;@PACKAGE_VERSION@;$(VERSION);" \ 341 | + -e "s;@LIBS_PUBLIC@;$(PUBLIC_LIBS);" \ 342 | + -e "s;@LIBS_PRIVATE@;$(PRIVATE_LIBS);" fdk-aac.pc.in > $@ 343 | \ Kein Zeilenumbruch am Dateiende. 344 | diff -ruN win32/getopt.h win32/getopt.h 345 | --- win32/getopt.h 1970-01-01 01:00:00.000000000 +0100 346 | +++ win32/getopt.h 2016-08-27 20:50:46.779964800 +0200 347 | @@ -0,0 +1,902 @@ 348 | +#ifndef __GETOPT_H__ 349 | +/** 350 | + * DISCLAIMER 351 | + * This file has no copyright assigned and is placed in the Public Domain. 352 | + * This file is part of the mingw-w64 runtime package. 353 | + * 354 | + * The mingw-w64 runtime package and its code is distributed in the hope that it 355 | + * will be useful but WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESSED OR 356 | + * IMPLIED ARE HEREBY DISCLAIMED. This includes but is not limited to 357 | + * warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 358 | + */ 359 | +/* 360 | + * Implementation of the `getopt', `getopt_long' and `getopt_long_only' 361 | + * APIs, for inclusion in the MinGW runtime library. 362 | + * 363 | + * This file is part of the MinGW32 package set. 364 | + * 365 | + * Written by Keith Marshall 366 | + * Copyright (C) 2008, 2009, 2011, 2012, MinGW.org Project. 367 | + * 368 | + * --------------------------------------------------------------------------- 369 | + * 370 | + * Permission is hereby granted, free of charge, to any person obtaining a 371 | + * copy of this software and associated documentation files (the "Software"), 372 | + * to deal in the Software without restriction, including without limitation 373 | + * the rights to use, copy, modify, merge, publish, distribute, sublicense, 374 | + * and/or sell copies of the Software, and to permit persons to whom the 375 | + * Software is furnished to do so, subject to the following conditions: 376 | + * 377 | + * The above copyright notice, this permission notice, and the following 378 | + * disclaimer shall be included in all copies or substantial portions of 379 | + * the Software. 380 | + * 381 | + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 382 | + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 383 | + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 384 | + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 385 | + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 386 | + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 387 | + * DEALINGS IN THE SOFTWARE. 388 | + * 389 | + * --------------------------------------------------------------------------- 390 | + * 391 | + */ 392 | + 393 | +#define __GETOPT_H__ 394 | + 395 | +/* All the headers include this file. */ 396 | +#include 397 | +#include 398 | +#include 399 | +#include 400 | + 401 | +#ifdef __cplusplus 402 | +extern "C" { 403 | +#endif 404 | + 405 | +extern int optind; /* index of first non-option in argv */ 406 | +extern int optopt; /* single option character, as parsed */ 407 | +extern int opterr; /* flag to enable built-in diagnostics... */ 408 | + /* (user may set to zero, to suppress) */ 409 | + 410 | +extern char *optarg; /* pointer to argument of current option */ 411 | + 412 | +/* Identify how to get the calling program name, for use in messages... 413 | + */ 414 | +#ifdef __CYGWIN__ 415 | +/* 416 | + * CYGWIN uses this DLL reference... 417 | + */ 418 | +# define PROGNAME __progname 419 | +extern char __declspec(dllimport) *__progname; 420 | +#else 421 | +/* 422 | + * ...while elsewhere, we simply use the first argument passed. 423 | + */ 424 | +# define PROGNAME *argv 425 | +#endif 426 | + 427 | +extern int getopt(int nargc, char * const *nargv, const char *options); 428 | + 429 | +#ifdef _BSD_SOURCE 430 | +/* 431 | + * BSD adds the non-standard `optreset' feature, for reinitialisation 432 | + * of `getopt' parsing. We support this feature, for applications which 433 | + * proclaim their BSD heritage, before including this header; however, 434 | + * to maintain portability, developers are advised to avoid it. 435 | + */ 436 | +# define optreset __mingw_optreset 437 | +extern int optreset; 438 | +#endif 439 | +#ifdef __cplusplus 440 | +} 441 | +#endif 442 | +/* 443 | + * POSIX requires the `getopt' API to be specified in `unistd.h'; 444 | + * thus, `unistd.h' includes this header. However, we do not want 445 | + * to expose the `getopt_long' or `getopt_long_only' APIs, when 446 | + * included in this manner. Thus, close the standard __GETOPT_H__ 447 | + * declarations block, and open an additional __GETOPT_LONG_H__ 448 | + * specific block, only when *not* __UNISTD_H_SOURCED__, in which 449 | + * to declare the extended API. 450 | + */ 451 | +#endif /* !defined(__GETOPT_H__) */ 452 | + 453 | +#if !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) 454 | +#define __GETOPT_LONG_H__ 455 | + 456 | +#ifdef __cplusplus 457 | +extern "C" { 458 | +#endif 459 | + 460 | +struct option /* specification for a long form option... */ 461 | +{ 462 | + const char *name; /* option name, without leading hyphens */ 463 | + int has_arg; /* does it take an argument? */ 464 | + int *flag; /* where to save its status, or NULL */ 465 | + int val; /* its associated status value */ 466 | +}; 467 | + 468 | +enum /* permitted values for its `has_arg' field... */ 469 | +{ 470 | + no_argument = 0, /* option never takes an argument */ 471 | + required_argument, /* option always requires an argument */ 472 | + optional_argument /* option may take an argument */ 473 | +}; 474 | + 475 | +extern int getopt_long(int nargc, char * const *nargv, const char *options, 476 | + const struct option *long_options, int *idx); 477 | +extern int getopt_long_only(int nargc, char * const *nargv, const char *options, 478 | + const struct option *long_options, int *idx); 479 | +/* 480 | + * Previous MinGW implementation had... 481 | + */ 482 | +#ifndef HAVE_DECL_GETOPT 483 | +/* 484 | + * ...for the long form API only; keep this for compatibility. 485 | + */ 486 | +# define HAVE_DECL_GETOPT 1 487 | +#endif 488 | + 489 | + 490 | + 491 | +/* Identify how to get the calling program name, for use in messages... 492 | + */ 493 | +#ifdef __CYGWIN__ 494 | +/* 495 | + * CYGWIN uses this DLL reference... 496 | + */ 497 | +# define PROGNAME __progname 498 | +extern char __declspec(dllimport) *__progname; 499 | +#else 500 | +/* 501 | + * ...while elsewhere, we simply use the first argument passed. 502 | + */ 503 | +# define PROGNAME *argv 504 | +#endif 505 | + 506 | +/* Initialise the public variables. */ 507 | + 508 | +int optind = 1; /* index for first non-option arg */ 509 | +int opterr = 1; /* enable built-in error messages */ 510 | + 511 | +char *optarg = NULL; /* pointer to current option argument */ 512 | + 513 | +#define CHAR char /* argument type selector */ 514 | + 515 | +#define getopt_switchar '-' /* option prefix character in argv */ 516 | +#define getopt_pluschar '+' /* prefix for POSIX mode in optstring */ 517 | +#define getopt_takes_argument ':' /* marker for optarg in optstring */ 518 | +#define getopt_arg_assign '=' /* longopt argument field separator */ 519 | +#define getopt_unknown '?' /* return code for unmatched option */ 520 | +#define getopt_ordered 1 /* return code for ordered non-option */ 521 | + 522 | +#define getopt_all_done -1 /* return code to indicate completion */ 523 | + 524 | +enum 525 | +{ /* All `getopt' API functions are implemented via calls to the 526 | + * common static function `getopt_parse()'; these `mode' selectors 527 | + * determine the behaviour of `getopt_parse()', to deliver the 528 | + * appropriate result in each case. 529 | + */ 530 | + getopt_mode_standard = 0, /* getopt() */ 531 | + getopt_mode_long, /* getopt_long() */ 532 | + getopt_mode_long_only /* getopt_long_only() */ 533 | +}; 534 | + 535 | +enum 536 | +{ /* When attempting to match a command line argument to a long form option, 537 | + * these indicate the status of the match. 538 | + */ 539 | + getopt_no_match = 0, /* no successful match */ 540 | + getopt_abbreviated_match, /* argument is an abbreviation for an option */ 541 | + getopt_exact_match /* argument matches the full option name */ 542 | +}; 543 | + 544 | +int optopt = getopt_unknown; /* return value for option being evaluated */ 545 | + 546 | +/* Some BSD applications expect to be able to reinitialise `getopt' parsing 547 | + * by setting a global variable called `optreset'. We provide an obfuscated 548 | + * API, which allows applications to emulate this brain damage; however, any 549 | + * use of this is non-portable, and is strongly discouraged. 550 | + */ 551 | +#define optreset __mingw_optreset 552 | +int optreset = 0; 553 | + 554 | +static 555 | +int getopt_missing_arg( const CHAR *optstring ) 556 | +{ 557 | + /* Helper function to determine the appropriate return value, 558 | + * for the case where a required option argument is missing. 559 | + */ 560 | + if( (*optstring == getopt_pluschar) || (*optstring == getopt_switchar) ) 561 | + ++optstring; 562 | + return (*optstring == getopt_takes_argument) 563 | + ? getopt_takes_argument 564 | + : getopt_unknown; 565 | +} 566 | + 567 | +/* `complain' macro facilitates the generation of simple built-in 568 | + * error messages, displayed on various fault conditions, provided 569 | + * `opterr' is non-zero. 570 | + */ 571 | +#define complain( MSG, ARG ) if( opterr ) \ 572 | + fprintf( stderr, "%s: "MSG"\n", PROGNAME, ARG ) 573 | + 574 | +static 575 | +int getopt_argerror( int mode, char *fmt, CHAR *prog, struct option *opt, int retval ) 576 | +{ 577 | + /* Helper function, to generate more complex built-in error 578 | + * messages, for invalid arguments to long form options ... 579 | + */ 580 | + if( opterr ) 581 | + { 582 | + /* ... but, displayed only if `opterr' is non-zero. 583 | + */ 584 | + char flag[] = "--"; 585 | + if( mode != getopt_mode_long ) 586 | + /* 587 | + * only display one hyphen, for implicit long form options, 588 | + * improperly resolved by `getopt_long_only()'. 589 | + */ 590 | + flag[1] = 0; 591 | + /* 592 | + * always preface the program name ... 593 | + */ 594 | + fprintf( stderr, "%s: ", prog ); 595 | + /* 596 | + * to the appropriate, option specific message. 597 | + */ 598 | + fprintf( stderr, fmt, flag, opt->name ); 599 | + } 600 | + /* Whether displaying the message, or not, always set `optopt' 601 | + * to identify the faulty option ... 602 | + */ 603 | + optopt = opt->val; 604 | + /* 605 | + * and return the `invalid option' indicator. 606 | + */ 607 | + return retval; 608 | +} 609 | + 610 | +/* `getopt_conventions' establish behavioural options, to control 611 | + * the operation of `getopt_parse()', e.g. to select between POSIX 612 | + * and GNU style argument parsing behaviour. 613 | + */ 614 | +#define getopt_set_conventions 0x1000 615 | +#define getopt_posixly_correct 0x0010 616 | + 617 | +static 618 | +int getopt_conventions( int flags ) 619 | +{ 620 | + static int conventions = 0; 621 | + 622 | + if( (conventions == 0) && ((flags & getopt_set_conventions) == 0) ) 623 | + { 624 | + /* default conventions have not yet been established; 625 | + * initialise them now! 626 | + */ 627 | + conventions = getopt_set_conventions; 628 | + if( flags == getopt_pluschar ) 629 | + conventions |= getopt_posixly_correct; 630 | + } 631 | + 632 | + else if( flags & getopt_set_conventions ) 633 | + /* 634 | + * default conventions may have already been established, 635 | + * but this is a specific request to augment them. 636 | + */ 637 | + conventions |= flags; 638 | + 639 | + /* in any event, return the currently established conventions. 640 | + */ 641 | + return conventions; 642 | +} 643 | + 644 | +static 645 | +int is_switchar( CHAR flag ) 646 | +{ 647 | + /* A simple helper function, used to identify the switch character 648 | + * introducing an optional command line argument. 649 | + */ 650 | + return flag == getopt_switchar; 651 | +} 652 | + 653 | +static 654 | +const CHAR *getopt_match( CHAR lookup, const CHAR *opt_string ) 655 | +{ 656 | + /* Helper function, used to identify short form options. 657 | + */ 658 | + if( (*opt_string == getopt_pluschar) || (*opt_string == getopt_switchar) ) 659 | + ++opt_string; 660 | + if( *opt_string == getopt_takes_argument ) 661 | + ++opt_string; 662 | + do if( lookup == *opt_string ) return opt_string; 663 | + while( *++opt_string ); 664 | + return NULL; 665 | +} 666 | + 667 | +static 668 | +int getopt_match_long( const CHAR *nextchar, const CHAR *optname ) 669 | +{ 670 | + /* Helper function, used to identify potential matches for 671 | + * long form options. 672 | + */ 673 | + CHAR matchchar; 674 | + while( (matchchar = *nextchar++) && (matchchar == *optname) ) 675 | + /* 676 | + * skip over initial substring which DOES match. 677 | + */ 678 | + ++optname; 679 | + 680 | + if( matchchar ) 681 | + { 682 | + /* did NOT match the entire argument to an initial substring 683 | + * of a defined option name ... 684 | + */ 685 | + if( matchchar != getopt_arg_assign ) 686 | + /* 687 | + * ... and didn't stop at an `=' internal field separator, 688 | + * so this is NOT a possible match. 689 | + */ 690 | + return getopt_no_match; 691 | + 692 | + /* DID stop at an `=' internal field separator, 693 | + * so this IS a possible match, and what follows is an 694 | + * argument to the possibly matched option. 695 | + */ 696 | + optarg = (char *)(nextchar); 697 | + } 698 | + return *optname 699 | + /* 700 | + * if we DIDN'T match the ENTIRE text of the option name, 701 | + * then it's a possible abbreviated match ... 702 | + */ 703 | + ? getopt_abbreviated_match 704 | + /* 705 | + * but if we DID match the entire option name, 706 | + * then it's a DEFINITE EXACT match. 707 | + */ 708 | + : getopt_exact_match; 709 | +} 710 | + 711 | +static 712 | +int getopt_resolved( int mode, int argc, CHAR *const *argv, int *argind, 713 | +struct option *opt, int index, int *retindex, const CHAR *optstring ) 714 | +{ 715 | + /* Helper function to establish appropriate return conditions, 716 | + * on resolution of a long form option. 717 | + */ 718 | + if( retindex != NULL ) 719 | + *retindex = index; 720 | + 721 | + /* On return, `optind' should normally refer to the argument, if any, 722 | + * which follows the current one; it is convenient to set this, before 723 | + * checking for the presence of any `optarg'. 724 | + */ 725 | + optind = *argind + 1; 726 | + 727 | + if( optarg && (opt[index].has_arg == no_argument) ) 728 | + /* 729 | + * it is an error for the user to specify an option specific argument 730 | + * with an option which doesn't expect one! 731 | + */ 732 | + return getopt_argerror( mode, "option `%s%s' doesn't accept an argument\n", 733 | + PROGNAME, opt + index, getopt_unknown ); 734 | + 735 | + else if( (optarg == NULL) && (opt[index].has_arg == required_argument) ) 736 | + { 737 | + /* similarly, it is an error if no argument is specified 738 | + * with an option which requires one ... 739 | + */ 740 | + if( optind < argc ) 741 | + /* 742 | + * ... except that the requirement may be satisfied from 743 | + * the following command line argument, if any ... 744 | + */ 745 | + optarg = argv[*argind = optind++]; 746 | + 747 | + else 748 | + /* so fail this case, only if no such argument exists! 749 | + */ 750 | + return getopt_argerror( mode, "option `%s%s' requires an argument\n", 751 | + PROGNAME, opt + index, getopt_missing_arg( optstring ) ); 752 | + } 753 | + 754 | + /* when the caller has provided a return buffer ... 755 | + */ 756 | + if( opt[index].flag != NULL ) 757 | + { 758 | + /* ... then we place the proper return value there, 759 | + * and return a status code of zero ... 760 | + */ 761 | + *(opt[index].flag) = opt[index].val; 762 | + return 0; 763 | + } 764 | + /* ... otherwise, the return value becomes the status code. 765 | + */ 766 | + return opt[index].val; 767 | +} 768 | + 769 | +static 770 | +int getopt_verify( const CHAR *nextchar, const CHAR *optstring ) 771 | +{ 772 | + /* Helper function, called by getopt_parse() when invoked 773 | + * by getopt_long_only(), to verify when an unmatched or an 774 | + * ambiguously matched long form option string is valid as 775 | + * a short form option specification. 776 | + */ 777 | + if( ! (nextchar && *nextchar && optstring && *optstring) ) 778 | + /* 779 | + * There are no characters to be matched, or there are no 780 | + * valid short form option characters to which they can be 781 | + * matched, so this can never be valid. 782 | + */ 783 | + return 0; 784 | + 785 | + while( *nextchar ) 786 | + { 787 | + /* For each command line character in turn ... 788 | + */ 789 | + const CHAR *test; 790 | + if( (test = getopt_match( *nextchar++, optstring )) == NULL ) 791 | + /* 792 | + * ... there is no short form option to match the current 793 | + * candidate, so the entire argument fails. 794 | + */ 795 | + return 0; 796 | + 797 | + if( test[1] == getopt_takes_argument ) 798 | + /* 799 | + * The current candidate is valid, and it matches an option 800 | + * which takes an argument, so this command line argument is 801 | + * a valid short form option specification; accept it. 802 | + */ 803 | + return 1; 804 | + } 805 | + /* If we get to here, then every character in the command line 806 | + * argument was valid as a short form option; accept it. 807 | + */ 808 | + return 1; 809 | +} 810 | + 811 | +static 812 | +#define getopt_std_args int argc, CHAR *const argv[], const CHAR *optstring 813 | +int getopt_parse( int mode, getopt_std_args, ... ) 814 | +{ 815 | + /* Common core implementation for ALL `getopt' functions. 816 | + */ 817 | + static int argind = 0; 818 | + static int optbase = 0; 819 | + static const CHAR *nextchar = NULL; 820 | + static int optmark = 0; 821 | + 822 | + if( (optreset |= (optind < 1)) || (optind < optbase) ) 823 | + { 824 | + /* POSIX does not prescribe any definitive mechanism for restarting 825 | + * a `getopt' scan, but some applications may require such capability. 826 | + * We will support it, by allowing the caller to adjust the value of 827 | + * `optind' downwards, (nominally setting it to zero). Since POSIX 828 | + * wants `optind' to have an initial value of one, but we want all 829 | + * of our internal place holders to be initialised to zero, when we 830 | + * are called for the first time, we will handle such a reset by 831 | + * adjusting all of the internal place holders to one less than 832 | + * the adjusted `optind' value, (but never to less than zero). 833 | + */ 834 | + if( optreset ) 835 | + { 836 | + /* User has explicitly requested reinitialisation... 837 | + * We need to reset `optind' to it's normal initial value of 1, 838 | + * to avoid a potential infinitely recursive loop; by doing this 839 | + * up front, we also ensure that the remaining place holders 840 | + * will be correctly reinitialised to no less than zero. 841 | + */ 842 | + optind = 1; 843 | + 844 | + /* We also need to clear the `optreset' request... 845 | + */ 846 | + optreset = 0; 847 | + } 848 | + 849 | + /* Now, we may safely reinitialise the internal place holders, to 850 | + * one less than `optind', without fear of making them negative. 851 | + */ 852 | + optmark = optbase = argind = optind - 1; 853 | + nextchar = NULL; 854 | + } 855 | + 856 | + /* From a POSIX perspective, the following is `undefined behaviour'; 857 | + * we implement it thus, for compatibility with GNU and BSD getopt. 858 | + */ 859 | + else if( optind > (argind + 1) ) 860 | + { 861 | + /* Some applications expect to be able to manipulate `optind', 862 | + * causing `getopt' to skip over one or more elements of `argv'; 863 | + * POSIX doesn't require us to support this brain-damaged concept; 864 | + * (indeed, POSIX defines no particular behaviour, in the event of 865 | + * such usage, so it must be considered a bug for an application 866 | + * to rely on any particular outcome); nonetheless, Mac-OS-X and 867 | + * BSD actually provide *documented* support for this capability, 868 | + * so we ensure that our internal place holders keep track of 869 | + * external `optind' increments; (`argind' must lag by one). 870 | + */ 871 | + argind = optind - 1; 872 | + 873 | + /* When `optind' is misused, in this fashion, we also abandon any 874 | + * residual text in the argument we had been parsing; this is done 875 | + * without any further processing of such abandoned text, assuming 876 | + * that the caller is equipped to handle it appropriately. 877 | + */ 878 | + nextchar = NULL; 879 | + } 880 | + 881 | + if( nextchar && *nextchar ) 882 | + { 883 | + /* we are parsing a standard, or short format, option argument ... 884 | + */ 885 | + const CHAR *optchar; 886 | + if( (optchar = getopt_match( optopt = *nextchar++, optstring )) != NULL ) 887 | + { 888 | + /* we have identified it as valid ... 889 | + */ 890 | + if( optchar[1] == getopt_takes_argument ) 891 | + { 892 | + /* and determined that it requires an associated argument ... 893 | + */ 894 | + if( ! *(optarg = (char *)(nextchar)) ) 895 | + { 896 | + /* the argument is NOT attached ... 897 | + */ 898 | + if( optchar[2] == getopt_takes_argument ) 899 | + /* 900 | + * but this GNU extension marks it as optional, 901 | + * so we don't provide one on this occasion. 902 | + */ 903 | + optarg = NULL; 904 | + 905 | + /* otherwise this option takes a mandatory argument, 906 | + * so, provided there is one available ... 907 | + */ 908 | + else if( (argc - argind) > 1 ) 909 | + /* 910 | + * we take the following command line argument, 911 | + * as the appropriate option argument. 912 | + */ 913 | + optarg = argv[++argind]; 914 | + 915 | + /* but if no further argument is available, 916 | + * then there is nothing we can do, except for 917 | + * issuing the requisite diagnostic message. 918 | + */ 919 | + else 920 | + { 921 | + complain( "option requires an argument -- %c", optopt ); 922 | + return getopt_missing_arg( optstring ); 923 | + } 924 | + } 925 | + optind = argind + 1; 926 | + nextchar = NULL; 927 | + } 928 | + else 929 | + optarg = NULL; 930 | + optind = (nextchar && *nextchar) ? argind : argind + 1; 931 | + return optopt; 932 | + } 933 | + /* if we didn't find a valid match for the specified option character, 934 | + * then we fall through to here, so take appropriate diagnostic action. 935 | + */ 936 | + if( mode == getopt_mode_long_only ) 937 | + { 938 | + complain( "unrecognised option `-%s'", --nextchar ); 939 | + nextchar = NULL; 940 | + optopt = 0; 941 | + } 942 | + else 943 | + complain( "invalid option -- %c", optopt ); 944 | + optind = (nextchar && *nextchar) ? argind : argind + 1; 945 | + return getopt_unknown; 946 | + } 947 | + 948 | + if( optmark > optbase ) 949 | + { 950 | + /* This can happen, in GNU parsing mode ONLY, when we have 951 | + * skipped over non-option arguments, and found a subsequent 952 | + * option argument; in this case we permute the arguments. 953 | + */ 954 | + int index; 955 | + /* 956 | + * `optspan' specifies the number of contiguous arguments 957 | + * which are spanned by the current option, and so must be 958 | + * moved together during permutation. 959 | + */ 960 | + const int optspan = argind - optmark + 1; 961 | + /* 962 | + * we use `this_arg' to store these temporarily. 963 | + */ 964 | + CHAR *this_arg = malloc(sizeof(CHAR) * optspan); 965 | + /* 966 | + * we cannot manipulate `argv' directly, since the `getopt' 967 | + * API prototypes it as `read-only'; this cast to `arglist' 968 | + * allows us to work around that restriction. 969 | + */ 970 | + CHAR **arglist = (char **)(argv); 971 | + 972 | + /* save temporary copies of the arguments which are associated 973 | + * with the current option ... 974 | + */ 975 | + for( index = 0; index < optspan; ++index ) 976 | + this_arg[index] = arglist[optmark + index]; 977 | + 978 | + /* move all preceding non-option arguments to the right, 979 | + * overwriting these saved arguments, while making space 980 | + * to replace them in their permuted location. 981 | + */ 982 | + for( --optmark; optmark >= optbase; --optmark ) 983 | + arglist[optmark + optspan] = arglist[optmark]; 984 | + 985 | + /* restore the temporarily saved option arguments to 986 | + * their permuted location. 987 | + */ 988 | + for( index = 0; index < optspan; ++index ) 989 | + arglist[optbase + index] = this_arg[index]; 990 | + 991 | + /* adjust `optbase', to account for the relocated option. 992 | + */ 993 | + optbase += optspan; 994 | + 995 | + free(this_arg); 996 | + } 997 | + 998 | + else 999 | + /* no permutation occurred ... 1000 | + * simply adjust `optbase' for all options parsed so far. 1001 | + */ 1002 | + optbase = argind + 1; 1003 | + 1004 | + /* enter main parsing loop ... 1005 | + */ 1006 | + while( argc > ++argind ) 1007 | + { 1008 | + /* inspect each argument in turn, identifying possible options ... 1009 | + */ 1010 | + if( is_switchar( *(nextchar = argv[optmark = argind]) ) && *++nextchar ) 1011 | + { 1012 | + /* we've found a candidate option argument ... */ 1013 | + 1014 | + if( is_switchar( *nextchar ) ) 1015 | + { 1016 | + /* it's a double hyphen argument ... */ 1017 | + 1018 | + const CHAR *refchar = nextchar; 1019 | + if( *++refchar ) 1020 | + { 1021 | + /* and it looks like a long format option ... 1022 | + * `getopt_long' mode must be active to accept it as such, 1023 | + * `getopt_long_only' also qualifies, but we must downgrade 1024 | + * it to force explicit handling as a long format option. 1025 | + */ 1026 | + if( mode >= getopt_mode_long ) 1027 | + { 1028 | + nextchar = refchar; 1029 | + mode = getopt_mode_long; 1030 | + } 1031 | + } 1032 | + else 1033 | + { 1034 | + /* this is an explicit `--' end of options marker, so wrap up now! 1035 | + */ 1036 | + if( optmark > optbase ) 1037 | + { 1038 | + /* permuting the argument list as necessary ... 1039 | + * (note use of `this_arg' and `arglist', as above). 1040 | + */ 1041 | + CHAR *this_arg = argv[optmark]; 1042 | + CHAR **arglist = (CHAR **)(argv); 1043 | + 1044 | + /* move all preceding non-option arguments to the right ... 1045 | + */ 1046 | + do arglist[optmark] = arglist[optmark - 1]; 1047 | + while( optmark-- > optbase ); 1048 | + 1049 | + /* reinstate the `--' marker, in its permuted location. 1050 | + */ 1051 | + arglist[optbase] = this_arg; 1052 | + } 1053 | + /* ... before finally bumping `optbase' past the `--' marker, 1054 | + * and returning the `all done' completion indicator. 1055 | + */ 1056 | + optind = ++optbase; 1057 | + return getopt_all_done; 1058 | + } 1059 | + } 1060 | + else if( mode < getopt_mode_long_only ) 1061 | + { 1062 | + /* it's not an explicit long option, and `getopt_long_only' isn't active, 1063 | + * so we must explicitly try to match it as a short option. 1064 | + */ 1065 | + mode = getopt_mode_standard; 1066 | + } 1067 | + 1068 | + if( mode >= getopt_mode_long ) 1069 | + { 1070 | + /* the current argument is a long form option, (either explicitly, 1071 | + * introduced by a double hyphen, or implicitly because we were called 1072 | + * by `getopt_long_only'); this is where we parse it. 1073 | + */ 1074 | + int lookup; 1075 | + int matched = -1; 1076 | + 1077 | + /* we need to fetch the `extra' function arguments, which are 1078 | + * specified for the `getopt_long' APIs. 1079 | + */ 1080 | + va_list refptr; 1081 | + va_start( refptr, optstring ); 1082 | + struct option *longopts = va_arg( refptr, struct option * ); 1083 | + int *optindex = va_arg( refptr, int * ); 1084 | + va_end( refptr ); 1085 | + 1086 | + /* ensuring that `optarg' does not inherit any junk, from parsing 1087 | + * preceding arguments ... 1088 | + */ 1089 | + optarg = NULL; 1090 | + for( lookup = 0; longopts && longopts[lookup].name; ++lookup ) 1091 | + { 1092 | + /* scan the list of defined long form options ... 1093 | + */ 1094 | + switch( getopt_match_long( nextchar, longopts[lookup].name ) ) 1095 | + { 1096 | + /* looking for possible matches for the current argument. 1097 | + */ 1098 | + case getopt_exact_match: 1099 | + /* 1100 | + * when an exact match is found, 1101 | + * return it immediately, setting `nextchar' to NULL, 1102 | + * to ensure we don't mistakenly try to match any 1103 | + * subsequent characters as short form options. 1104 | + */ 1105 | + nextchar = NULL; 1106 | + return getopt_resolved( mode, argc, argv, &argind, 1107 | + longopts, lookup, optindex, optstring ); 1108 | + 1109 | + case getopt_abbreviated_match: 1110 | + /* 1111 | + * but, for a partial (initial substring) match ... 1112 | + */ 1113 | + if( matched >= 0 ) 1114 | + { 1115 | + /* if this is not the first, then we have an ambiguity ... 1116 | + */ 1117 | + if( (mode == getopt_mode_long_only) 1118 | + /* 1119 | + * However, in the case of getopt_long_only(), if 1120 | + * the entire ambiguously matched string represents 1121 | + * a valid short option specification, then we may 1122 | + * proceed to interpret it as such. 1123 | + */ 1124 | + && getopt_verify( nextchar, optstring ) ) 1125 | + return getopt_parse( mode, argc, argv, optstring ); 1126 | + 1127 | + /* If we get to here, then the ambiguously matched 1128 | + * partial long option isn't valid for short option 1129 | + * evaluation; reset parser context to resume with 1130 | + * the following command line argument, diagnose 1131 | + * ambiguity, and bail out. 1132 | + */ 1133 | + optopt = 0; 1134 | + nextchar = NULL; 1135 | + optind = argind + 1; 1136 | + complain( "option `%s' is ambiguous", argv[argind] ); 1137 | + return getopt_unknown; 1138 | + } 1139 | + /* otherwise just note that we've found a possible match ... 1140 | + */ 1141 | + matched = lookup; 1142 | + } 1143 | + } 1144 | + if( matched >= 0 ) 1145 | + { 1146 | + /* if we get to here, then we found exactly one partial match, 1147 | + * so return it, as for an exact match. 1148 | + */ 1149 | + nextchar = NULL; 1150 | + return getopt_resolved( mode, argc, argv, &argind, 1151 | + longopts, matched, optindex, optstring ); 1152 | + } 1153 | + /* if here, then we had what SHOULD have been a long form option, 1154 | + * but it is unmatched ... 1155 | + */ 1156 | + if( (mode < getopt_mode_long_only) 1157 | + /* 1158 | + * ... although paradoxically, `mode == getopt_mode_long_only' 1159 | + * allows us to still try to match it as a short form option. 1160 | + */ 1161 | + || (getopt_verify( nextchar, optstring ) == 0) ) 1162 | + { 1163 | + /* When it cannot be matched, reset the parsing context to 1164 | + * resume from the next argument, diagnose the failed match, 1165 | + * and bail out. 1166 | + */ 1167 | + optopt = 0; 1168 | + nextchar = NULL; 1169 | + optind = argind + 1; 1170 | + complain( "unrecognised option `%s'", argv[argind] ); 1171 | + return getopt_unknown; 1172 | + } 1173 | + } 1174 | + /* fall through to handle standard short form options... 1175 | + * when the option argument format is neither explictly identified 1176 | + * as long, nor implicitly matched as such, and the argument isn't 1177 | + * just a bare hyphen, (which isn't an option), then we make one 1178 | + * recursive call to explicitly interpret it as short format. 1179 | + */ 1180 | + if( *nextchar ) 1181 | + return getopt_parse( mode, argc, argv, optstring ); 1182 | + } 1183 | + /* if we get to here, then we've parsed a non-option argument ... 1184 | + * in GNU compatibility mode, we step over it, so we can permute 1185 | + * any subsequent option arguments, but ... 1186 | + */ 1187 | + if( *optstring == getopt_switchar ) 1188 | + { 1189 | + /* if `optstring' begins with a `-' character, this special 1190 | + * GNU specific behaviour requires us to return the non-option 1191 | + * arguments in strict order, as pseudo-arguments to a special 1192 | + * option, with return value defined as `getopt_ordered'. 1193 | + */ 1194 | + nextchar = NULL; 1195 | + optind = argind + 1; 1196 | + optarg = argv[argind]; 1197 | + return getopt_ordered; 1198 | + } 1199 | + if( getopt_conventions( *optstring ) & getopt_posixly_correct ) 1200 | + /* 1201 | + * otherwise ... 1202 | + * for POSIXLY_CORRECT behaviour, or if `optstring' begins with 1203 | + * a `+' character, then we break out of the parsing loop, so that 1204 | + * the scan ends at the current argument, with no permutation. 1205 | + */ 1206 | + break; 1207 | + } 1208 | + /* fall through when all arguments have been evaluated, 1209 | + */ 1210 | + optind = optbase; 1211 | + return getopt_all_done; 1212 | +} 1213 | + 1214 | +/* All three public API entry points are trivially defined, 1215 | + * in terms of the internal `getopt_parse' function. 1216 | + */ 1217 | +int getopt( getopt_std_args ) 1218 | +{ 1219 | + return getopt_parse( getopt_mode_standard, argc, argv, optstring ); 1220 | +} 1221 | + 1222 | +int getopt_long( getopt_std_args, const struct option *opts, int *index ) 1223 | +{ 1224 | + return getopt_parse( getopt_mode_long, argc, argv, optstring, opts, index ); 1225 | +} 1226 | + 1227 | +int getopt_long_only( getopt_std_args, const struct option *opts, int *index ) 1228 | +{ 1229 | + return getopt_parse( getopt_mode_long_only, argc, argv, optstring, opts, index ); 1230 | +} 1231 | + 1232 | +#ifdef __weak_alias 1233 | +/* 1234 | + * These Microsnot style uglified aliases are provided for compatibility 1235 | + * with the previous MinGW implementation of the getopt API. 1236 | + */ 1237 | +__weak_alias( getopt, _getopt ) 1238 | +__weak_alias( getopt_long, _getopt_long ) 1239 | +__weak_alias( getopt_long_only, _getopt_long_only ) 1240 | +#endif 1241 | + 1242 | + 1243 | + 1244 | + 1245 | +#ifdef __cplusplus 1246 | +} 1247 | +#endif 1248 | + 1249 | +#endif /* !defined(__UNISTD_H_SOURCED__) && !defined(__GETOPT_LONG_H__) */ 1250 | --------------------------------------------------------------------------------