when ($SANITIZER_TYPE || $USE_ARCADIA_PYTHON == "no" || $UDF_NO_PROBE == "yes" || $MUSL == "yes" || $TIDY == "yes") {
    YQL_UDF_LINK_CMD=$LINK_DYN_LIB
    YQL_UDF_LINK_PRG_CMD=$LINK_EXEC_DYN_LIB
}
otherwise {
    YQL_UDF_LINK_CMD=$LINK_DYN_LIB && ${tool:"yql/tools/udf_probe"} $TARGET ${kv;hide:"p UD"}
    YQL_UDF_LINK_PRG_CMD=$LINK_EXEC_DYN_LIB && ${tool:"yql/tools/udf_probe"} $TARGET ${kv;hide:"p UD"}
}

### @usage: UDF_BASE(name [EXPORTS symlist_file] [PREFIX prefix]) #internal
###
### The base logic of all UDF extension modules (User-Defined Functions).
### Processing EXPORTS and PREFIX is the same as for DLL.
###
### https://wiki.yandex-team.ru/robot/manual/kiwi/userguide/#polzovatelskiefunkciiudftriggerykwcalc
module UDF_BASE: DLL_UNIT  {
    when ($MSVC != "yes" && $DARWIN != "yes") {
        LDFLAGS+= -Wl,-Bsymbolic
    }
}

UDF_NO_PROBE="no"
### @usage: UDF_NO_PROBE()
###
### Disable UDF import check at build stage
macro UDF_NO_PROBE() {
    ENABLE(UDF_NO_PROBE)
}

### @usage: YQL_UDF_TEST([name])
###
### The module to test YQL C++ UDF.
###
### Documentation: https://yql.yandex-team.ru/docs/yt/libraries/testing/
### Documentation about the Arcadia test system: https://wiki.yandex-team.ru/yatool/test/
module YQL_UDF_TEST: PY3TEST_BIN {
    SET_APPEND(_MAKEFILE_INCLUDE_LIKE_DEPS canondata/result.json)

    PEERDIR(contrib/ydb/library/yql/tests/common/udf_test)

    DEPENDS(contrib/ydb/library/yql/tools/astdiff)
    DEPENDS(contrib/ydb/library/yql/tools/yqlrun)
    DATA(arcadia/contrib/ydb/library/yql/mount)
    DATA(arcadia/contrib/ydb/library/yql/cfg/udf_test)
    ENV(YQL_ASTDIFF_PATH="contrib/ydb/library/yql/tools/astdiff/astdiff")
    ENV(YQL_CONFIG_DIR="contrib/ydb/library/yql/cfg/udf_test")
    ENV(YQL_YQLRUN_PATH="contrib/ydb/library/yql/tools/yqlrun/yqlrun")
    ENV(YQL_SQL2YQL_PATH="contrib/ydb/library/yql/tools/sql2yql/sql2yql")
}

module YQL_UDF_YDB_TEST: PY3TEST_BIN {
    SET_APPEND(_MAKEFILE_INCLUDE_LIKE_DEPS canondata/result.json)

    PEERDIR(ydb/library/yql/tests/common/udf_test)

    DEPENDS(ydb/library/yql/tools/astdiff)
    DEPENDS(ydb/library/yql/tools/yqlrun)
    DATA(arcadia/ydb/library/yql/mount)
    DATA(arcadia/ydb/library/yql/cfg/udf_test)
}

module YQL_UDF_TEST_CONTRIB: PY3TEST_BIN {
    PEERDIR(contrib/ydb/library/yql/tests/common/udf_test)

    DEPENDS(contrib/ydb/library/yql/tools/astdiff)
    DEPENDS(contrib/ydb/library/yql/tools/yqlrun)
    DATA(arcadia/contrib/ydb/library/yql/mount)
    DATA(arcadia/contrib/ydb/library/yql/cfg/udf_test)
    ENV(YQL_ASTDIFF_PATH="contrib/ydb/library/yql/tools/astdiff/astdiff")
    ENV(YQL_CONFIG_DIR="contrib/ydb/library/yql/cfg/udf_test")
    ENV(YQL_YQLRUN_PATH="contrib/ydb/library/yql/tools/yqlrun/yqlrun")
    ENV(YQL_SQL2YQL_PATH="contrib/ydb/library/yql/tools/sql2yql/sql2yql")
}

### @usage: _ADD_YQL_UDF_DEPS()
###
### Add all needed PEERDIRs to a YQL_UDF.
###
### https://yql.yandex-team.ru/docs/yt/udf/cpp/
macro _ADD_YQL_UDF_DEPS() {
    PEERDIR(contrib/ydb/library/yql/public/udf)
    PEERDIR(contrib/ydb/library/yql/public/udf/support)
}

macro _ADD_YQL_UDF_YDB_DEPS() {
    PEERDIR(ydb/library/yql/public/udf)
    PEERDIR(ydb/library/yql/public/udf/support)
}

macro _ADD_YQL_UDF_DEPS_CONTRIB() {
    PEERDIR(contrib/ydb/library/yql/public/udf)
    PEERDIR(contrib/ydb/library/yql/public/udf/support)
}

### @usage: _MAKE_YQL_UDF()
###
### Make module definition an YQL UDF: add all needed dependencies, properties and flags
###
### https://yql.yandex-team.ru/docs/yt/udf/cpp/
macro _MAKE_YQL_UDF() {
    _ADD_YQL_UDF_DEPS()
    SET_APPEND(USER_CXXFLAGS -DBUILD_UDF)
    # For Windows using declspecs
    DEFAULT(YQL_UDF_EXPORT ${ARCADIA_ROOT}/contrib/ydb/library/yql/public/udf/udfs_exports.exports)

    when ($WINDOWS == "yes") {
        YQL_UDF_EXPORT=
    }

    SET(EXPORTS_FILE $YQL_UDF_EXPORT)
}

macro _MAKE_YQL_UDF_YDB() {
    _ADD_YQL_UDF_YDB_DEPS()
    SET_APPEND(USER_CXXFLAGS -DBUILD_UDF)
    # For Windows using declspecs
    DEFAULT(YQL_UDF_EXPORT ${ARCADIA_ROOT}/ydb/library/yql/public/udf/udfs_exports.exports)

    when ($WINDOWS == "yes") {
        YQL_UDF_EXPORT=
    }

    SET(EXPORTS_FILE $YQL_UDF_EXPORT)
}

macro _MAKE_YQL_UDF_CONTRIB() {
    _ADD_YQL_UDF_DEPS_CONTRIB()
    SET_APPEND(USER_CXXFLAGS -DBUILD_UDF)
    # For Windows using declspecs
    DEFAULT(YQL_UDF_EXPORT ${ARCADIA_ROOT}/contrib/ydb/library/yql/public/udf/udfs_exports.exports)

    when ($WINDOWS == "yes") {
        YQL_UDF_EXPORT=
    }

    SET(EXPORTS_FILE $YQL_UDF_EXPORT)
}

### @usage: YQL_UDF_MODULE(name)
###
### The extension module for YQL with C++ UDF (User Defined Function YQL)
###
### https://yql.yandex-team.ru/docs/yt/udf/cpp/
module YQL_UDF_MODULE: UDF_BASE {
    .CMD=YQL_UDF_LINK_CMD
    _MAKE_YQL_UDF()
    PROVIDES(YqlServicePolicy)
}

module YQL_UDF_YDB_MODULE: UDF_BASE {
    .CMD=YQL_UDF_LINK_CMD
    _MAKE_YQL_UDF_YDB()
    PROVIDES(YqlServicePolicy)
}

module YQL_UDF_MODULE_CONTRIB: UDF_BASE {
    .CMD=YQL_UDF_LINK_CMD
    _MAKE_YQL_UDF_CONTRIB()
    PROVIDES(YqlServicePolicy)
}

module _YQL_UDF_PROGRAM_BASE: SO_PROGRAM {
    .CMD=YQL_UDF_LINK_PRG_CMD
    _MAKE_YQL_UDF()
}

UDF_SHARED_SEM=$CPP_DYN_LIBRARY_SEM

### @usage: YQL_UDF(name)
###
### User-defined function for YQL
###
### Multimodule which is YQL_UDF_MODULE when built directly or referred by BUNDLE and DEPENDS macros.
### If used by PEERDIRs it is usual static LIBRARY with default YQL dependencies, allowing code reuse between UDFs.
###
### @see: [YQL_UDF_MODULE()](#module_YQL_UDF_MODULE)
multimodule YQL_UDF {
    module YQL_UDF_SHARED: YQL_UDF_MODULE {
        .SEM=UDF_SHARED_SEM
        CMAKE_TARGET_NAME=${REALPRJNAME}.dyn
        CMAKE_TARGET_ARTEFACT_RENAME_RULES=&& set_target_property OUTPUT_NAME $REALPRJNAME
        NO_CLANG_TIDY()
    }
    module YQL_UDF_STATIC: _DLL_COMPATIBLE_LIBRARY {
        .ALIASES=SRCS=GLOBAL_SRCS
        .SEM=CPP_LIBRARY_SEM
        .GLOBAL_SEM=CPP_OBJ_LIBRARY_SEM
        OBJ_SUF=.udfs
        _ADD_YQL_UDF_DEPS()
        # disable credits generation for static library
        SET(CREDITS_FLAGS)
        when ($MSVC == "yes" || $CYGWIN == "yes") {
            MODULE_SUFFIX=.static.lib
        }
    }
}

multimodule YQL_UDF_YDB {
    module YQL_UDF_SHARED: YQL_UDF_YDB_MODULE {
        .SEM=UDF_SHARED_SEM
        CMAKE_TARGET_NAME=${REALPRJNAME}.dyn
        CMAKE_TARGET_ARTEFACT_RENAME_RULES=&& set_target_property OUTPUT_NAME $REALPRJNAME
        NO_CLANG_TIDY()
    }
    module YQL_UDF_STATIC: _DLL_COMPATIBLE_LIBRARY {
        .ALIASES=SRCS=GLOBAL_SRCS
        .SEM=CPP_LIBRARY_SEM
        .GLOBAL_SEM=CPP_OBJ_LIBRARY_SEM
        OBJ_SUF=.udfs
        _ADD_YQL_UDF_YDB_DEPS()
        # disable credits generation for static library
        SET(CREDITS_FLAGS)
        when ($MSVC == "yes" || $CYGWIN == "yes") {
            MODULE_SUFFIX=.static.lib
        }
    }
}

multimodule YQL_UDF_CONTRIB {
    module YQL_UDF_SHARED: YQL_UDF_MODULE_CONTRIB {
        .SEM=UDF_SHARED_SEM
        NO_CLANG_TIDY()
    }
    module YQL_UDF_STATIC: _DLL_COMPATIBLE_LIBRARY {
        .ALIASES=SRCS=GLOBAL_SRCS
        .SEM=CPP_LIBRARY_SEM
        .GLOBAL_SEM=CPP_OBJ_LIBRARY_SEM
        OBJ_SUF=.udfs
        _ADD_YQL_UDF_DEPS_CONTRIB()
        # disable credits generation for static library
        SET(CREDITS_FLAGS)
        when ($MSVC == "yes" || $CYGWIN == "yes") {
            MODULE_SUFFIX=.static.lib
        }
    }
}

### @usage: YQL_ABI_VERSION(major minor release))
###
### Specifying the supported ABI for YQL_UDF.
###
### @see: [YQL_UDF()](#multimodule_YQL_UDF)
macro YQL_ABI_VERSION(Major, Minor, Patch) {
    YQL_ABI_FLAGS=-DUDF_ABI_VERSION_MAJOR=$Major -DUDF_ABI_VERSION_MINOR=$Minor -DUDF_ABI_VERSION_PATCH=$Patch
    SET_APPEND(USER_CXXFLAGS $YQL_ABI_FLAGS)
}

### @usage: YQL_LAST_ABI_VERSION()
###
### Use the last ABI for YQL_UDF
###
macro YQL_LAST_ABI_VERSION() {
    YQL_ABI_FLAGS=-DUSE_CURRENT_UDF_ABI_VERSION
    SET_APPEND(USER_CXXFLAGS $YQL_ABI_FLAGS)
}

### @usage: YQL_PYTHON_UDF(name)
###
### Definition of the extension module for YQL with Python 2.x UDF (User Defined Function for YQL).
### Unlike YQL_UDF this is plain DLL module, so PEERDIRs to it are not allowed.
###
### https://yql.yandex-team.ru/docs/yt/udf/python/
module YQL_PYTHON_UDF: YQL_UDF_MODULE {
    .IGNORED=USE_PYTHON2
    .RESTRICTED=PYTHON3_ADDINCL USE_PYTHON3 PYTHON2_ADDINCL

    USE_PYTHON2()
    _ARCADIA_PYTHON_ADDINCL()
    PEERDIR(build/platform/python/ldflags)
    PEERDIR(library/python/type_info)

    DEFAULT(YQL_PYTHON_UDF_EXPORT ${ARCADIA_ROOT}/yql/udfs/common/python/python_udf/python_udfs_exports.exports)

    when ($WINDOWS == "yes") {
        YQL_PYTHON_UDF_EXPORT=
    }

    ### FIXME: XXX the statement below uncoditionally set EXPORTS_FILE (due to incorrect behaviour of old ConfReader
    ###when ($USE_ARCADIA_PYTHON == "yes") SET(EXPORTS_FILE $YQL_PYTHON_UDF_EXPORT)
    SET(EXPORTS_FILE $YQL_PYTHON_UDF_EXPORT)
}

### @usage: YQL_PYTHON_UDF_PROGRAM(name)
###
### Definition of the extension module for YQL with Python 2.x UDF (User Defined Function for YQL).
### Unlike YQL_UDF this is plain DLL module, so PEERDIRs to it are not allowed.
###
### https://yql.yandex-team.ru/docs/yt/udf/python/
module YQL_PYTHON_UDF_PROGRAM: _YQL_UDF_PROGRAM_BASE {
    .IGNORED=USE_PYTHON2
    .RESTRICTED=PYTHON3_ADDINCL USE_PYTHON3 PYTHON2_ADDINCL
    USE_PYTHON2()
    _ARCADIA_PYTHON_ADDINCL()
    PEERDIR(build/platform/python/ldflags)
    PEERDIR(library/python/type_info)

    DEFAULT(YQL_PYTHON_UDF_EXPORT ${ARCADIA_ROOT}/yql/udfs/common/python/python_udf/python_udfs_exports.exports)

    when ($WINDOWS == "yes") {
        YQL_PYTHON_UDF_EXPORT=
    }

    ### FIXME: XXX the statement below uncoditionally set EXPORTS_FILE (due to incorrect behaviour of old ConfReader
    ###when ($USE_ARCADIA_PYTHON == "yes") SET(EXPORTS_FILE $YQL_PYTHON_UDF_EXPORT)
    SET(EXPORTS_FILE $YQL_PYTHON_UDF_EXPORT)
}

### @usage: YQL_PYTHON3_UDF(name)
###
### The extension module for YQL with Python 3.x UDF (User Defined Function for YQL).
### Unlike YQL_UDF this is plain DLL module, so PEERDIRs to it are not allowed.
###
### Documentation: https://yql.yandex-team.ru/docs/yt/udf/python/
module YQL_PYTHON3_UDF: YQL_UDF_MODULE {
    .RESTRICTED=PYTHON2_ADDINCL PYTHON3_ADDINCL USE_PYTHON2 USE_PYTHON3
    _ARCADIA_PYTHON3_ADDINCL()
    PEERDIR(build/platform/python/ldflags)
    PEERDIR(library/python/type_info)

    DEFAULT(YQL_PYTHON_UDF_EXPORT ${ARCADIA_ROOT}/yql/udfs/common/python/python_udf/python_udfs_exports.exports)

    when ($WINDOWS == "yes") {
        YQL_PYTHON_UDF_EXPORT=
    }

    ### FIXME: XXX the statement below uncoditionally set EXPORTS_FILE (due to incorrect behaviour of old ConfReader
    ###when ($USE_ARCADIA_PYTHON == "yes") SET(EXPORTS_FILE $YQL_PYTHON_UDF_EXPORT)
    SET(EXPORTS_FILE $YQL_PYTHON_UDF_EXPORT)
}

macro _MAKE_YQL_PYTHON_UDF_TEST() {
    PEERDIR(library/python/pytest)
    DEPENDS(yql/tools/run_python_udf)
    SETUP_PYTEST_BIN(RUNNER_BIN $(BUILD_ROOT)/yql/tools/run_python_udf/run_python_udf)
}

### @usage: YQL_PYTHON_UDF_TEST(name)
###
### The Python test for Python YQL UDF (Python User Defined Function for YQL). The code should be a proper YQL_PYTHON_UDF.
###
### This module will basically build itself as UDF and run as test using yql/tools/run_python_udf/run_python_udf tool.
###
### Documentation: https://yql.yandex-team.ru/docs/yt/udf/python/
###
### @example: https://a.yandex-team.ru/arc/trunk/arcadia/yql/udfs/test/simple/ya.make
###
### @see: [YQL_PYTHON_UDF()](#module_YQL_PYTHON_UDF)
module YQL_PYTHON_UDF_TEST: YQL_PYTHON_UDF {
    _MAKE_YQL_PYTHON_UDF_TEST()
    SET_APPEND(_MAKEFILE_INCLUDE_LIKE_DEPS canondata/result.json)
}

### @usage: YQL_PYTHON3_UDF_TEST(name)
###
### The Python test for Python 3.x YQL UDF (User Defined Function for YQL). The code should be a proper YQL_PYTHON3_UDF.
###
### This module will basically build itself as UDF and run as test using yql/tools/run_python_udf/run_python_udf tool.
###
### Documentation: https://yql.yandex-team.ru/docs/yt/udf/python/
###
### @see: [YQL_PYTHON3_UDF()](#module_YQL_PYTHON3_UDF)
module YQL_PYTHON3_UDF_TEST: YQL_PYTHON3_UDF {
    _MAKE_YQL_PYTHON_UDF_TEST()
    SET_APPEND(_MAKEFILE_INCLUDE_LIKE_DEPS canondata/result.json)
}