#!/bin/bash

#-----------------------------------------------------------------------------------------
#    QSVEnc/NVEnc/VCEEnc by rigaya
#  -----------------------------------------------------------------------------------------
#   ソースコードについて
#   ・無保証です。
#   ・本ソースコードを使用したことによるいかなる損害・トラブルについてrigayaは責任を負いません。
#   以上に了解して頂ける場合、本ソースコードの使用、複製、改変、再頒布を行って頂いて構いません。
#  -----------------------------------------------------------------------------------------

CNF_LOG=config.log

cnf_write()
{
    echo "$*"
    echo "$*" >> ${CNF_LOG}
}
cnf_print()
{
    printf "$*"
    echo "$*" >> ${CNF_LOG}
}

write_config_mak()
{
    cnf_write $1
    echo $1 >> config.mak
}

write_enc_config()
{
    cnf_write $1
    echo $1 >> NVEncCore/rgy_config.h
}

write_app_rev()
{
    cnf_write $1
    echo $1 >> NVEncCore/rgy_rev.h
}

cxx_check()
{
    echo "" >> ${CNF_LOG}
    if [ -n "$1" ]; then
        printf "checking for $1..."
        echo "### - checking for $1... --------------" >> ${CNF_LOG}
    else 
        echo "### - test start --------------" >> ${CNF_LOG}
    fi
    echo "#include <iostream>" > cxx_check.c
    if [ -n "$3" ]; then
        echo "#include <$3>" >> cxx_check.c
    fi 
    if [ -n "$4" ]; then
        echo "extern \"C\" {" >> cxx_check.c
        echo "#include <$4>" >> cxx_check.c
        echo "}" >> cxx_check.c
    fi 
    echo "int main(void){ $5; std::cout << \"Hello World!\" << std::endl; return 0;}" >> cxx_check.c
    CXX_CMD="$CXX -w cxx_check.c $2 -o cxx_check"
    echo "------ command ------------" >> ${CNF_LOG}
    echo ${CXX_CMD} >> ${CNF_LOG}
    echo "------ test ---------------" >> ${CNF_LOG}
    cat cxx_check.c >> ${CNF_LOG}
    echo "---------------------------" >> ${CNF_LOG}
    $CXX_CMD 2>> ${CNF_LOG}
    #$CXX cxx_check.c $1 -o cxx_check
    ret=$?
    rm -f cxx_check*
    echo "### - test fin -> ${ret} ----------" >> ${CNF_LOG}
    return $ret
}

regex_check()
{
    echo "#include <iostream>" > cxx_check.c
    echo "#include <string>" >> cxx_check.c
    echo "#include <regex>" >> cxx_check.c
    echo "int main(void){ try { std::regex re(R\"(\d+)\"); std::string test(\"1234\"); return std::regex_match(test, re) ? 0 : 1; } catch (...) { return 1; } }" >> cxx_check.c
    $CXX cxx_check.c $1 -o cxx_check 2>/dev/null
    ret=$?
    if [ $ret -ne 0 ]; then
        rm -f cxx_check*
        return $ret
    fi
    ./cxx_check 2>/dev/null
    ret=$?
    rm -f cxx_check*
    return $ret
}

rm -f config.* .depend NVEncCore/rgy_config.h NVEncCore/rgy_rev.h

PKGCONFIG=${PKGCONFIG:-pkg-config}
USE_PKGCONFIG=1

ENABLE_DEBUG=0
NVCC=${NVCC:-nvcc}
CXX=${CXX:-g++}
PROGRAM=nvencc
PREFIX=${PREFIX:-/usr/local}
EXTRACXXFLAGS=""
EXTRALDFLAGS=""
SRCS=""
SRCCUS=""
X86_64=1
NO_RDTSCP_INTRIN=0

CUDA_PATH=${CUDA_PATH:-/usr/local/cuda}

ENABLE_CPP_REGEX=1

GPU_CODE_GEN=""

CHECK_LIBAV_NAMES="libswresample libavutil libavcodec libavformat libavfilter"
LIBAV_CFLAGS=""
LIBAV_LIBS=""
ENABLE_AVSW_READER=1

CHECK_VAPOURSYNTH_NAMES="vapoursynth vapoursynth-script"
ENABLE_VAPOURSYNTH=1
VAPOURSYNTH_LIBS=""
VAPOURSYNTH_CFLAGS=""

CHECK_AVXSYNTH_NAMES="avxsynth"
ENABLE_AVXSYNTH=1
AVXSYNTH_CFLAGS=""

CHECK_LIBASS_NAMES="libass"
LIBASS_CFLAGS=""
LIBASS_LIBS=""
ENABLE_LIBASS=1

CHECK_LIBVMAF_NAMES="libvmaf"
LIBVMAF_CFLAGS=""
LIBVMAF_LIBS=""
ENABLE_LIBVMAF=0

DTL_CFLAGS=""
ENABLE_DTL=1

print_help()
{
cat << EOF
Usage: ./configure [options]

options:
  -h, --help               print this message

  --prefix=PREFIX          install nvencc into PREFIX/bin [${PREFIX}]

  --cxx=CXX                set C++ compiler path [${CXX}]
  --pkg-config=PKGCONFIG   set pkg-config path [${PKGCONFIG}]
  --cuda-path=CUDA_PATH    set cuda path [${CUDA_PATH}]
  --gpu-code=GPU_CODE_GEN  set gpu code gen options
      [${GPU_CODE_GEN}]
  --enable-debug           compile in debug configuration [${ENABLE_DEBUG}]

  --extra-cxxflags=XCFLAGS add XCFLAGS to CFLAGS
  --extra-ldflags=XLDFLAGS add XLDFLAGS to LDFLAGS

  --disable-vapoursynth    disable vapoursynth support [auto]
  --disable-libass         disable libass support [auto]
  --disable-dtl            disable dtl support [auto]
EOF
}

SRCDIR=$(dirname "$0")
if [ "${SRCDIR}" == "`pwd`" ]; then
    SRCDIR=.
fi

for opt; do
    optarg="${opt#*=}"
    case "$opt" in
         -h)
            print_help
            exit 0
            ;;
         --help)
            print_help
            exit 0
            ;;
        --prefix=*)
            PREFIX="$optarg"
            ;;
        --cxx=*)
            CXX="$optarg"
            ;;
        --extra-cxxflags=*)
            EXTRACXXFLAGS="$optarg"
            ;;
        --extra-ldflags=*)
            EXTRALDFLAGS="$optarg"
            ;;
        --cuda-path=*)
            CUDA_PATH="$optarg"
            ;;
        --gpu-code=*)
            GPU_CODE_GEN="$optarg"
            ;;
        --enable-debug)
            ENABLE_DEBUG=1
            ;;
        --disable-vapoursynth)
            ENABLE_VAPOURSYNTH=0
            ;;
        --disable-libass)
            ENABLE_LIBASS=0
            ;;
        --disable-libvmaf)
            ENABLE_LIBVMAF=0
            ;;
        --disable-dtl)
            ENABLE_DTL=0
            ;;
        --pkg-config=*)
            PKGCONFIG="$optarg"
            ;;
        *)
            cnf_write "unknown option $opt"
            exit 1
            ;;
    esac
done

## log
echo "" > ${CNF_LOG}
echo "CNF_LOG=${CNF_LOG}" >> ${CNF_LOG}
echo "PKGCONFIG=${PKGCONFIG}" >> ${CNF_LOG}
echo "USE_PKGCONFIG=${USE_PKGCONFIG}" >> ${CNF_LOG}
echo "ENABLE_DEBUG=${ENABLE_DEBUG}" >> ${CNF_LOG}
echo "NVCC=${NVCC}" >> ${CNF_LOG}
echo "CXX=${CXX}" >> ${CNF_LOG}
echo "PROGRAM=${PROGRAM}" >> ${CNF_LOG}
echo "PREFIX=${PREFIX}" >> ${CNF_LOG}
echo "EXTRACXXFLAGS=${EXTRACXXFLAGS}" >> ${CNF_LOG}
echo "EXTRALDFLAGS=${EXTRALDFLAGS}" >> ${CNF_LOG}
echo "X86_64=${X86_64}" >> ${CNF_LOG}
echo "CUDA_PATH=${CUDA_PATH}" >> ${CNF_LOG}
echo "ENABLE_CPP_REGEX=${ENABLE_CPP_REGEX}" >> ${CNF_LOG}
echo "CHECK_LIBAV_NAMES=${CHECK_LIBAV_NAMES}" >> ${CNF_LOG}
echo "ENABLE_AVSW_READER=${ENABLE_AVSW_READER}" >> ${CNF_LOG}
echo "ENABLE_VAPOURSYNTH=${ENABLE_VAPOURSYNTH}" >> ${CNF_LOG}
echo "ENABLE_AVXSYNTH=${ENABLE_AVXSYNTH}" >> ${CNF_LOG}
echo "ENABLE_LIBASS=${ENABLE_LIBASS}" >> ${CNF_LOG}
echo "ENABLE_LIBVMAF=${ENABLE_LIBVMAF}" >> ${CNF_LOG}
echo "ENABLE_DTL=${ENABLE_DTL}" >> ${CNF_LOG}

cnf_print "checking for ${CXX}..."
if ! cxx_check "${CXX}" "" ; then
    cnf_write "${CXX} does not work"
    exit 1
fi
cnf_write "OK"

if [ `echo | ${CXX} -E -dM - | egrep "WIN32|WIN64" | wc --lines` -ne 0 ]; then
    cnf_write "This script does not support Windows platform."
    cnf_write "For Windows, use Visual Studio."
    exit 1 
fi

if [ `echo | ${CXX} -E -dM - | grep "x86_64" | wc --lines` -eq 0 ]; then
    X86_64=0
fi

CXXINC=" \
  -DLINUX -DUNIX -D_FILE_OFFSET_BITS=64 -D__USE_LARGEFILE64 -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS \
  -I${SRCDIR} -I${SRCDIR}/NVEncSDK/Common/inc -I${SRCDIR}/NVEncCore \
  -I${SRCDIR}/jitify -I${SRCDIR}/tinyxml2 -I${SRCDIR}/cppcodec -I${SRCDIR}/ttmath \
"
CXXFLAGS="-Wall -Wno-unknown-pragmas -Wno-unused -Wno-missing-braces"

LDFLAGS="-L. -ldl -lstdc++"
if [ $X86_64 -ne 0 ]; then
    CXXINC="${CXXINC} -DLINUX64 -m64"
    LDFLAGS="${LDFLAGS} -m64"
else
    CXXINC="${CXXINC} -DLINUX32 -m32"
    LDFLAGS="${LDFLAGS} -m32"
fi

CUDA_CFLAGS=""
CUDA_LIBS="-lnvrtc -lnppif -lnppig -lnppc -lcudart -lcuda"
if [ "${CUDA_PATH}" != "" ]; then
    cnf_print "checking for cuda (CUDA_PATH=${CUDA_PATH})..."
    CUDA_CFLAGS="-I${CUDA_PATH}/include"
    CUDA_LIBS="-L${CUDA_PATH}/lib64 ${CUDA_LIBS}"
    export PATH=${CUDA_PATH}/bin:${PATH}
    NVCC=`which nvcc`
    cnf_write "nvcc=${NVCC}"
fi
if ! cxx_check "cuda" "${CXXFLAGS} ${CXXINC} ${CUDA_CFLAGS} ${LDFLAGS} ${CUDA_LIBS}" "cuda.h" "" "auto result = cuInit(0);" ; then
    cnf_write "cuda not supported." 
    exit 1
fi
CUDA_VER_MAJOR=`${NVCC} --version | grep "release" | awk '{print $6}' | cut -c2- | cut -d . -f1`
CUDA_VER_MINOR=`${NVCC} --version | grep "release" | awk '{print $6}' | cut -c2- | cut -d . -f2`
if [ $CUDA_VER_MAJOR -le 8 ]; then
    cnf_write "CUDA >= 9.0 required, but CUDA ${CUDA_VER_MAJOR}.${CUDA_VER_MINOR} found." 
    exit 1
fi
if [ $CUDA_VER_MAJOR -le 10 ]; then
    GPU_CODE_GEN="--generate-code arch=compute_30,code=[compute_30,sm_30]"
fi
GPU_CODE_GEN="${GPU_CODE_GEN} --generate-code arch=compute_50,code=[compute_50,sm_50]"
GPU_CODE_GEN="${GPU_CODE_GEN} --generate-code arch=compute_61,code=[compute_61,sm_61]"
GPU_CODE_GEN="${GPU_CODE_GEN} --generate-code arch=compute_75,code=[compute_75,sm_75]"
if ( [ $CUDA_VER_MAJOR -ge 11 ] && [ $CUDA_VER_MINOR -ge 1 ] ) || [ $CUDA_VER_MAJOR -ge 12 ]; then
    GPU_CODE_GEN="${GPU_CODE_GEN} --generate-code arch=compute_86,code=[compute_86,sm_86]"
fi
cnf_write "OK, CUDA ${CUDA_VER_MAJOR}.${CUDA_VER_MINOR}"

NVCCFLAGS="${GPU_CODE_GEN} --cudart=static -std=c++14 -Xcudafe \"--display_error_number --diag_suppress=108\""

for file in "${CXX}"; do
if [ ! `which $file 2> /dev/null` ]; then
        cnf_write "$file not found"
        exit 1
    fi
done

if cxx_check "pthread" "${CXXFLAGS} ${LDFLAGS} -pthread" ; then
    CXXFLAGS="${CXXFLAGS} -pthread"
    LDFLAGS="${LDFLAGS} -pthread"
else
    cnf_write "pthread not installed." 
    exit 1
fi
cnf_write "OK"

if cxx_check "c++14" "${CXXFLAGS} -std=c++14 ${LDFLAGS}" ; then
    CXXFLAGS="$CXXFLAGS -std=c++14"
else
    cnf_write "${CXX} does not work with -std=c++14"
    exit 1
fi
cnf_write "OK"

if cxx_check "-msse4.1" "${CXXFLAGS} -msse4.1 ${LDFLAGS}" ; then
    if cxx_check "-march=native" "${CXXFLAGS} -march=native -mtune=native ${LDFLAGS}" ; then
        CXXFLAGS="$CXXFLAGS -march=native -mtune=native"
    elif cxx_check "-mpopcnt" "${CXXFLAGS} -mpopcnt ${LDFLAGS}" ; then
        CXXFLAGS="$CXXFLAGS -msse4.1 -mpopcnt"
    else
        CXXFLAGS="$CXXFLAGS -msse4.1"
    fi
else
    cnf_write "SSE4.1 not supported with this compiler." 
    exit 1
fi
cnf_write "OK"

cnf_print "checking for system SSE4.1 support..."
if [ `cat /proc/cpuinfo | grep "sse4_1" | wc --lines` -eq 0 ]; then
    cnf_write "System does not support SSE4.1."
    exit 1 
fi
cnf_write "OK"

if ! cxx_check "__rdtscp()" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LDFLAGS}" "" "x86intrin.h" "unsigned int a = 0; auto i = __rdtscp(&a);" ; then
    CXXFLAGS="${CXXFLAGS} -DNO_RDTSCP_INTRIN=1"
    cnf_write "no"
else
    cnf_write "yes"
fi

if ! cxx_check "_xgetbv()" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LDFLAGS}" "" "x86intrin.h" "unsigned int a = 0; auto i = _xgetbv(a);" ; then
    CXXFLAGS="${CXXFLAGS} -DNO_XGETBV_INTRIN=1"
    cnf_write "no"
else
    cnf_write "yes"
fi

if cxx_check "-fPIE" "${CXXFLAGS} -fPIE ${LDFLAGS}" ; then
    CXXFLAGS="$CXXFLAGS -fPIE"
fi

if [ ! $ENABLE_DEBUG -eq 0 ]; then
    cnf_write "configuring for debug..."
    CXXFLAGS="${CXXFLAGS} -O0 -g -D_DEBUG"
else
    cnf_write "configuring for speed..."
    CXXFLAGS="${CXXFLAGS} -O3 -DNDEBUG=1"
    if cxx_check "-mfpmath=sse" "${CXXFLAGS} -mfpmath=sse ${LDFLAGS}" ; then
        CXXFLAGS="$CXXFLAGS -mfpmath=sse"
        cnf_write "yes"
    else
        cnf_write "no"
    fi
    if cxx_check "-ffast-math" "${CXXFLAGS} -ffast-math ${LDFLAGS}" ; then
        CXXFLAGS="$CXXFLAGS -ffast-math"
        cnf_write "yes"
    else
        cnf_write "no"
    fi
    if cxx_check "-fomit-frame-pointer" "${CXXFLAGS} -fomit-frame-pointer ${LDFLAGS}" ; then
        CXXFLAGS="$CXXFLAGS -fomit-frame-pointer"
        cnf_write "yes"
    else
        cnf_write "no"
    fi
    #LDFLAGS="$LDFLAGS -Wl,-s"
fi

if [ -n $EXTRACXXFLAGS ]; then
    if ! cxx_check "--extra-cflags" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LDFLAGS}" ; then
        cnf_write "--extra-cflags=${EXTRACXXFLAGS} does not work"
        exit 1
    fi
    cnf_write "OK"
fi

if [ -n $EXTRALDFLAGS ]; then
    if ! cxx_check "--extra-ldflags" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LDFLAGS} ${EXTRALDFLAGS}" ; then
        cnf_write "--extra-ldflags=${EXTRALDFLAGS} does not work"
        exit 1
    fi
    cnf_write "OK"
fi

cnf_print "checking for pkg-config..."
export PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$PREFIX/lib/pkgconfig
which $PKGCONFIG 2>/dev/null 1>/dev/null
if [ $? -ne 0 ]; then
    cnf_write "${PKGCONFIG} does not exist."
    USE_PKGCONFIG=0
fi
cnf_write "OK"

if [ $ENABLE_AVSW_READER -ne 0 ]; then
    if [ $USE_PKGCONFIG -ne 0 ]; then
        cnf_print "checking libavcodec with pkg-config..."
        if ! ${PKGCONFIG} --exists $CHECK_LIBAV_NAMES ; then
            cnf_write "libs could not be detected by ${PKGCONFIG}. [ PKG_CONFIG_PATH=${PKG_CONFIG_PATH} ]"
        else
            cnf_write "OK"
            LIBAV_LIBS=`${PKGCONFIG} --libs ${CHECK_LIBAV_NAMES}`
            LIBAV_CFLAGS=`${PKGCONFIG} --cflags ${CHECK_LIBAV_NAMES}`
        fi
    fi
    
    if [ -z "$LIBAV_LIBS" ]; then
        LIBAV_LIBS=""
        for lib in $CHECK_LIB_NAMES; do
            LIBAV_LIBS="${LIBAV_LIBS} -l${lib#lib}"
        done
        cnf_write "lib settings might be inaqurate."
    fi

    if ! cxx_check "libavutil" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LIBAV_CFLAGS} ${LDFLAGS} ${EXTRALDFLAGS} ${LIBAV_LIBS}" "" "libavutil/avutil.h" "avutil_version();" ; then
        cnf_write "no"
        ENABLE_AVSW_READER=0
    else
        cnf_write "yes"
    fi
    
    if ! cxx_check "libavcodec" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LIBAV_CFLAGS} ${LDFLAGS} ${EXTRALDFLAGS} ${LIBAV_LIBS}" "" "libavcodec/avcodec.h" "avcodec_find_decoder((AVCodecID)0);" ; then
        cnf_write "no"
        ENABLE_AVSW_READER=0
    else
        cnf_write "yes"
    fi
    
    if ! cxx_check "libavformat" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LIBAV_CFLAGS} ${LDFLAGS} ${EXTRALDFLAGS} ${LIBAV_LIBS}" "" "libavformat/avformat.h" "avformat_find_stream_info(0,0);" ; then
        cnf_write "no"
        ENABLE_AVSW_READER=0
    else
        cnf_write "yes"
    fi
    
    if ! cxx_check "libavfilter" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LIBAV_CFLAGS} ${LDFLAGS} ${EXTRALDFLAGS} ${LIBAV_LIBS}" "" "libavfilter/avfilter.h" "avfilter_register_all();" ; then
        cnf_write "no"
        ENABLE_AVSW_READER=0
    else
        cnf_write "yes"
    fi
    
    if ! cxx_check "libswresample" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LIBAV_CFLAGS} ${LDFLAGS} ${EXTRALDFLAGS} ${LIBAV_LIBS}" "" "libswresample/swresample.h" "swr_alloc();" ; then
        cnf_write "no"
        ENABLE_AVSW_READER=0
    else
        cnf_write "yes"
    fi
    if [ $ENABLE_AVSW_READER -eq 0 ]; then
        cnf_write "libavutil, libavcodec, libavformat, libavfilter, libswresample are required to build nvencc."
        exit 1
    fi
fi

if [ $ENABLE_VAPOURSYNTH -ne 0 ]; then
    cnf_print "checking vapoursynth with pkg-config..."
    if ! ${PKGCONFIG} --exists ${CHECK_VAPOURSYNTH_NAMES} ; then
        cnf_write "libs could not be detected by ${PKGCONFIG}. [ PKG_CONFIG_PATH=${PKG_CONFIG_PATH} ]"
    else
        cnf_write "OK"
        VAPOURSYNTH_LIBS=`${PKGCONFIG} --libs ${CHECK_VAPOURSYNTH_NAMES}`
        VAPOURSYNTH_CFLAGS=`${PKGCONFIG} --cflags ${CHECK_VAPOURSYNTH_NAMES}`
    fi
    if ! cxx_check "VapourSynth.h" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LIBAV_CFLAGS} ${VAPOURSYNTH_CFLAGS} ${LDFLAGS} ${EXTRALDFLAGS} ${LIBAV_LIBS} ${VAPOURSYNTH_LIBS}" "VapourSynth.h" "" "" ; then
        cnf_write "no"
        ENABLE_VAPOURSYNTH=0
    else
        cnf_write "yes"
    fi
    if ! cxx_check "VSScript.h" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LIBAV_CFLAGS} ${VAPOURSYNTH_CFLAGS} ${LDFLAGS} ${EXTRALDFLAGS} ${LIBAV_LIBS} ${VAPOURSYNTH_LIBS}" "VSScript.h" "" "vsscript_init();" ; then
        cnf_write "no"
        ENABLE_VAPOURSYNTH=0
    else
        cnf_write "yes"
    fi
    if [ $ENABLE_VAPOURSYNTH -eq 0 ]; then
        VAPOURSYNTH_CFLAGS=""
        VAPOURSYNTH_LIBS=""
    fi
fi

if [ $ENABLE_AVXSYNTH -ne 0 ]; then
    cnf_print "checking avxsynth with pkg-config..."
    if ! ${PKGCONFIG} --exists ${CHECK_AVXSYNTH_NAMES} ; then
        cnf_write "libs could not be detected by ${PKGCONFIG}. [ PKG_CONFIG_PATH=${PKG_CONFIG_PATH} ]"
    else
        cnf_write "OK"
        AVXSYNTH_LIBS=`${PKGCONFIG} --libs ${CHECK_AVXSYNTH_NAMES}`
        AVXSYNTH_CFLAGS=`${PKGCONFIG} --cflags ${CHECK_AVXSYNTH_NAMES}`
    fi
    if ! cxx_check "avxsynth_c.h" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LIBAV_CFLAGS} ${AVXSYNTH_CFLAGS} ${LDFLAGS} ${EXTRALDFLAGS} ${AVXSYNTH_LIBS}" "" "avxsynth_c.h" "" ; then
        cnf_write "no"
        ENABLE_AVXSYNTH=0
    else
        cnf_write "yes"
    fi
    if [ $ENABLE_AVXSYNTH -eq 0 ]; then
        AVXSYNTH_CFLAGS=""
        AVXSYNTH_LIBS=""
    fi
fi

if [ $ENABLE_LIBASS -ne 0 ]; then
    cnf_print "checking libass with pkg-config..."
    if ! ${PKGCONFIG} --exists ${CHECK_LIBASS_NAMES} ; then
        cnf_write "libs could not be detected by ${PKGCONFIG}. [ PKG_CONFIG_PATH=${PKG_CONFIG_PATH} ]"
    else
        cnf_write "OK"
        LIBASS_LIBS=`${PKGCONFIG} --libs ${CHECK_LIBASS_NAMES}`
        LIBASS_CFLAGS=`${PKGCONFIG} --cflags ${CHECK_LIBASS_NAMES}`
    fi
    if ! cxx_check "ass/ass.h" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LDFLAGS} ${EXTRALDFLAGS}" "" "ass/ass.h" "" ; then
        cnf_write "no"
        ENABLE_LIBASS=0
    else
        cnf_write "yes"
    fi
    if [ $ENABLE_LIBASS -eq 0 ]; then
        LIBASS_CFLAGS=""
        LIBASS_LIBS=""
    fi
fi

if [ $ENABLE_LIBVMAF -ne 0 ]; then
    cnf_print "checking libvmaf with pkg-config..."
    if ! ${PKGCONFIG} --exists ${CHECK_LIBVMAF_NAMES} ; then
        cnf_write "libs could not be detected by ${PKGCONFIG}. [ PKG_CONFIG_PATH=${PKG_CONFIG_PATH} ]"
    else
        cnf_write "OK"
        LIBVMAF_LIBS=`${PKGCONFIG} --libs ${CHECK_LIBVMAF_NAMES}`
        LIBVMAF_CFLAGS=`${PKGCONFIG} --cflags ${CHECK_LIBVMAF_NAMES}`
    fi
    if ! cxx_check "libvmaf/vmaf.h" "${CXXFLAGS} ${EXTRACXXFLAGS} ${LDFLAGS} ${EXTRALDFLAGS}" "" "libvmaf/libvmaf.h" "" ; then
        cnf_write "no"
        ENABLE_LIBASS=0
    else
        cnf_write "yes"
    fi
    if [ $ENABLE_LIBVMAF -eq 0 ]; then
        LIBVMAF_CFLAGS=""
        LIBVMAF_LIBS=""
    fi
fi

if [ $ENABLE_DTL -ne 0 ]; then
    if ! cxx_check "dtl/dtl.hpp" "${CXXFLAGS} ${CXXINC} ${EXTRACXXFLAGS} ${LDFLAGS} ${EXTRALDFLAGS}" "dtl/dtl/dtl.hpp" "" "" ; then
        if ! cxx_check "dtl/dtl.hpp" "${CXXFLAGS} ${CXXINC} ${EXTRACXXFLAGS} ${LDFLAGS} ${EXTRALDFLAGS}" "dtl/dtl.hpp" "" "" ; then
            cnf_write "no"
            ENABLE_DTL=0
        else
            cnf_write "yes"
        fi
    else
        DTL_CFLAGS="-I./dtl"
        cnf_write "yes"
    fi
fi

SRC_NVENCSDK=" \
dynlink_nvcuvid.cpp
"

SRC_NVENCCORE=" \
CuvidDecode.cpp        FrameQueue.cpp              NVEncCmd.cpp                 NVEncCore.cpp \
NVEncDevice.cpp        NVEncFilter.cpp             NVEncFilterAfs.cpp           NVEncFilterColorspace.cpp \
NVEncFilterCustom.cpp  NVEncFilterDelogo.cpp       NVEncFilterDenoiseGauss.cpp  NVEncFilterPad.cpp \
NVEncFilterRff.cpp     NVEncFilterSelectEvery.cpp  NVEncFilterSsim.cpp          NVEncFilterSubburn.cpp \
NVEncFrameInfo.cpp     NVEncParam.cpp              NVEncUtil.cpp                cl_func.cpp \
convert_csp.cpp        convert_csp_avx.cpp         convert_csp_avx2.cpp         convert_csp_sse2.cpp \
convert_csp_sse41.cpp  convert_csp_ssse3.cpp       cpu_info.cpp                 gpu_info.cpp \
gpuz_info.cpp          h264_level.cpp              hevc_level.cpp               logo.cpp \
rgy_avlog.cpp          rgy_avutil.cpp              rgy_bitstream.cpp            rgy_caption.cpp \
rgy_chapter.cpp        rgy_cmd.cpp                 rgy_codepage.cpp             rgy_def.cpp \
rgy_err.cpp            rgy_event.cpp               rgy_frame.cpp                rgy_hdr10plus.cpp \
rgy_ini.cpp            rgy_input.cpp               rgy_input_avcodec.cpp        rgy_input_avi.cpp \
rgy_input_avs.cpp      rgy_input_raw.cpp           rgy_input_sm.cpp             rgy_input_vpy.cpp            rgy_language.cpp \
rgy_log.cpp            rgy_output.cpp              rgy_output_avcodec.cpp       rgy_perf_counter.cpp \
rgy_perf_monitor.cpp   rgy_pipe.cpp                rgy_pipe_linux.cpp           rgy_prm.cpp \
rgy_simd.cpp           rgy_status.cpp              rgy_timecode.cpp             rgy_util.cpp                 rgy_version.cpp \
"

CU_NVENCCORE=" \
NVEncFilterAfsAnalyze.cu  NVEncFilterAfsFilter.cu   NVEncFilterAfsMerge.cu   NVEncFilterAfsSynthesize.cu \
NVEncFilterCrop.cu        NVEncFilterDeband.cu      NVEncFilterDecimate.cu   NVEncFilterDelogo.cu \
NVEncFilterDenoiseKnn.cu  NVEncFilterDenoisePmd.cu  NVEncFilterEdgelevel.cu  NVEncFilterMpdecimate.cu            NVEncFilterNnedi.cu \
NVEncFilterResize.cu      NVEncFilterSmooth.cu      NVEncFilterSsim.cu       NVEncFilterSubburn.cu \
NVEncFilterTransform.cu   NVEncFilterTweak.cu       NVEncFilterUnsharp.cu    NVEncFilterWarpsharp.cu             NVEncFilterYadif.cu \
"

SRC_TINYXML2="tinyxml2.cpp"

SRC_NVENCC="NVEncC.cpp"

PYW_PERF_MONITOR="perf_monitor.pyw"

BINS="resource/nnedi3_weights.bin"

BINHS="NVEncCore/NVEncFilterColorspaceFunc.h"

for src in $SRC_NVENCSDK; do
    SRCS="$SRCS NVEncSDK/Common/src/$src"
done

for src in $SRC_NVENCCORE; do
    SRCS="$SRCS NVEncCore/$src"
done

for src in $CU_NVENCCORE; do
    SRCCUS="$SRCCUS NVEncCore/$src"
done

for pyw in $PYW_PERF_MONITOR; do
    PYWS="$PYWS PerfMonitor/$pyw"
done

for src in $SRC_TINYXML2; do
    SRCS="$SRCS tinyxml2/$src"
done

for src in $SRC_NVENCC; do
    SRCS="$SRCS NVEncC/$src"
done

ENCODER_REV=`git rev-list HEAD | wc --lines`

cnf_write ""
cnf_write "Creating config.mak, rgy_config.h..."
echo "SRCS = $SRCS" >> config.mak
echo "SRCCUS = $SRCCUS" >> config.mak
echo "BINS = $BINS" >> config.mak
echo "BINHS = $BINHS" >> config.mak
echo "PYWS = $PYWS" >> config.mak
write_config_mak "SRCDIR = $SRCDIR"
write_config_mak "CXX  = $CXX"
write_config_mak "NVCC = $NVCC"
write_config_mak "LD   = $CXX"
write_config_mak "PROGRAM = $PROGRAM"
write_config_mak "ENABLE_DEBUG = $ENABLE_DEBUG"
write_config_mak "CXXFLAGS = $CXXFLAGS $CXXINC $EXTRACXXFLAGS $CUDA_CFLAGS $LIBAV_CFLAGS $VAPOURSYNTH_CFLAGS $AVXSYNTH_CFLAGS $LIBASS_CFLAGS $LIBVMAF_CFLAGS $DTL_CFLAGS"
write_config_mak "NVCCFLAGS = $NVCCFLAGS -ccbin $CXX $CUDA_CFLAGS $CXXINC -Xcompiler \"${CXXFLAGS} ${EXTRACXXFLAGS}\" $LIBAV_CFLAGS $VAPOURSYNTH_CFLAGS $AVXSYNTH_CFLAGS $LIBASS_CFLAGS $LIBVMAF_CFLAGS $DTL_CFLAGS"
write_config_mak "LDFLAGS = $LDFLAGS $CUDA_LIBS $EXTRALDFLAGS $LIBAV_LIBS $LIBASS_LIBS $LIBVMAF_LIBS"
write_config_mak "PREFIX = $PREFIX"
echo "X86_64 = ${X86_64}"
write_app_rev    "#define ENCODER_REV                  \"$ENCODER_REV\""
write_enc_config "#define ENABLE_AVI_READER             0"
write_enc_config "#define ENABLE_AVISYNTH_READER        $ENABLE_AVXSYNTH"
write_enc_config "#define ENABLE_VAPOURSYNTH_READER     $ENABLE_VAPOURSYNTH"
write_enc_config "#define ENABLE_AVSW_READER            $ENABLE_AVSW_READER"     
write_enc_config "#define ENABLE_SM_READER              0"
write_enc_config "#define ENABLE_LIBASS_SUBBURN         $ENABLE_LIBASS"
write_enc_config "#define ENABLE_VMAF                   $ENABLE_LIBVMAF"
write_enc_config "#define ENABLE_AVCODEC_OUT_THREAD     1"
write_enc_config "#define ENABLE_CPP_REGEX              $ENABLE_CPP_REGEX"
write_enc_config "#define ENABLE_DTL                    $ENABLE_DTL"
write_enc_config "#define ENABLE_PERF_COUNTER           0"

cnf_write "successfully generated config.mak, rgy_config.h"


