load("//bazel:yr.bzl", "COPTS", "COPTS_WITH_GLOO", "LOPTS", "cc_strip")

genrule(
    name = "version",
    srcs = ["src/utils/version.h.in"],
    outs = ["src/utils/version.h"],
    cmd = """
            cat $(location :src/utils/version.h.in) > $@
            if [[ "$$(uname)" == "Darwin" ]]; then
                sed -i '' "s/@BUILD_VERSION@/$$BUILD_VERSION/g" $@
            else
                sed -i "s/@BUILD_VERSION@/$$BUILD_VERSION/g" $@
            fi
          """,
)

cc_library(
    name = "yr_api_lib",
    srcs = glob([
        "src/*.cpp",
        "src/*.h",
        "src/runtime/*.cpp",
        "src/runtime/*.h",
        "src/parallel_for/*.h",
        "src/parallel_for/*.cpp",
        "src/utils/*.h",
        "src/utils/*.cpp",
        "src/executor/*.h",
        "src/executor/*.cpp",
        "src/collective/*.h",
        "src/collective/*.cpp",
    ]) + ["src/utils/version.h"],
    hdrs = glob([
        "include/yr/*.h",
        "include/yr/api/*.h",
        "include/yr/parallel/*.h",
        "include/yr/parallel/detail/*.h",
        "include/yr/collective/*.h",
    ]),
    copts = select({
        "//conditions:default": COPTS_WITH_GLOO,
        "//:disable_gloo": COPTS,
    }) + select({
        "//:disable_datasystem": [],
        "//conditions:default": ["-DENABLE_DATASYSTEM"],
    }),
    linkopts = select({
        "//:is_macos": [],  # filesystem is part of libc++ on macOS
        "//conditions:default": ["-lstdc++fs"],
    }),
    linkstatic = True,
    strip_include_prefix = "include",
    visibility = ["//visibility:public"],
    deps = [
        ":version",
        "//:runtime_lib",
        "@com_google_absl//absl/flags:flag",
        "@com_google_absl//absl/flags:parse",
        "@securec",
        "@nlohmann_json",
        "@yaml-cpp",
    ] + select({
        "//conditions:default": ["@gloo//:gloo"],
        "//:disable_gloo": [],
    }),
    alwayslink = True,
)

cc_binary(
    name = "libyr-api.so",
    copts = COPTS,

    linkopts = LOPTS,
    linkshared = True,
    linkstatic = True,
    visibility = ["//visibility:public"],
    deps = [":yr_api_lib"],
)

cc_library(
    name = "yr_cpp_lib",
    srcs = ["libyr-api.so"],
    hdrs = glob([
        "include/yr/*.h",
        "include/yr/api/*.h",
        "include/yr/collective/*.h",
        "include/yr/parallel/*.h",
        "include/yr/parallel/detail/*.h",
    ]),
    strip_include_prefix = "include",
    visibility = ["//visibility:public"],
    deps = [
         "@nlohmann_json",
    ],
)

cc_library(
    name = "functionsdk_lib",
    srcs = glob([
        "src/faas/*.cpp",
        "src/faas/*.h",
    ]) + [
        "src/executor/executor.h",
        "src/executor/executor_holder.h",
        "src/utils/utils.h",
        "src/utils/version.h",
    ],
    hdrs = glob([
        "include/faas/*.h",
    ]),
    copts = COPTS + select({
        "//:disable_datasystem": [],
        "//conditions:default": ["-DENABLE_DATASYSTEM"],
    }),
    linkopts = select({
        "//:is_macos": [],  # filesystem is part of libc++ on macOS
        "//conditions:default": ["-lstdc++fs"],
    }),
    linkstatic = True,
    strip_include_prefix = "include/faas",
    visibility = ["//visibility:public"],
    deps = [
        "yr_cpp_lib",
        "//:runtime_lib_hdrs",
        "@msgpack",
        "@nlohmann_json",
    ],
    alwayslink = True,
)

cc_binary(
    name = "libfunctionsdk.so",
    copts = COPTS,

    linkopts = LOPTS,
    linkshared = True,
    linkstatic = True,
    visibility = ["//visibility:public"],
    deps = [":functionsdk_lib"],
)

cc_library(
    name = "yr_faas_lib",
    srcs = ["libfunctionsdk.so"],
    hdrs = glob([
        "include/faas/*.h",
    ]),
    strip_include_prefix = "include/faas",
    visibility = ["//visibility:public"],
)

cc_binary(
    name = "runtime",
    srcs = [
        "src/main/yr_runtime_main.cpp",
    ],
    copts = COPTS,
    linkopts = LOPTS + ["-pie -lpthread"],
    linkstatic = True,
    deps = [
        "yr_cpp_lib",
        "@boost",
        "@msgpack",
    ],
)

cc_strip(
    name = "cpp_strip",
    srcs = [
        "libfunctionsdk.so",
        "libyr-api.so",
        "runtime",
    ],
)

filegroup(
    name = "cpp_include",
    srcs = glob([
        "include/**/*.h",
    ]),
)

genrule(
    name = "yr_cpp_pkg",
    srcs = [
        ":cpp_strip",
        ":cpp_include",
    ] + select({
        "//:disable_observability": [],
        "//conditions:default": [
            "//src/utility/metrics:shared_exporters",
        ],
    }),
    outs = ["yr_cpp_pkg.out"],
    cmd = """
        BASE_DIR="$$(pwd)"
        CPP_SDK_DIR=$$BASE_DIR/build/output/runtime/sdk/cpp
        CPP_SERVICE_DIR=$$BASE_DIR/build/output/runtime/service/cpp
        rm -rf $$CPP_SDK_DIR $$CPP_SERVICE_DIR
        mkdir -p $$CPP_SDK_DIR/include $$CPP_SDK_DIR/include/boost $$CPP_SDK_DIR/lib $$CPP_SDK_DIR/bin $$CPP_SERVICE_DIR
        cp -rf $$BASE_DIR/external/msgpack/include $$CPP_SDK_DIR
        if [ "$$BOOST_VERSION" != "1.72.0" ];then
            cp -rf $$BASE_DIR/external/boost/boost/any $$CPP_SDK_DIR/include/boost
            cp -rf $$BASE_DIR/external/boost/boost/assert $$CPP_SDK_DIR/include/boost
        fi
        cp -rf $$BASE_DIR/external/boringssl/src/include/openssl $$CPP_SDK_DIR/include || true
        cp -rf $$BASE_DIR/external/boost/boost/asio $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/align $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/bind $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/callable_traits $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/chrono $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/config $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/container_hash $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/core $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/date_time $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/detail $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/exception $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/fiber $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/function $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/functional $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/fusion $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/integer $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/io $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/move $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/mpl $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/numeric $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/optional $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/predef $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/preprocessor $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/ratio $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/regex $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/smart_ptr $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/system $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/type_index $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/type_traits $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/utility $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/variant $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/winapi $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/*.hpp $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/boost/boost/*.h $$CPP_SDK_DIR/include/boost
        cp -rf $$BASE_DIR/external/nlohmann_json/single_include/nlohmann/json.hpp $$CPP_SDK_DIR/include
        chmod +w $(locations :cpp_strip) &&
        if [[ "$$(uname)" != "Darwin" ]]; then chrpath -d $(locations :cpp_strip) 2>/dev/null || true; fi &&
        cp -rf $(locations :cpp_strip) $$CPP_SDK_DIR/lib/ &&
        cp -rf $(locations :cpp_strip) $$CPP_SDK_DIR/bin/ &&
        rm -rf $$CPP_SDK_DIR/bin/libyr-api.so $$CPP_SDK_DIR/bin/libfunctionsdk.so &&
        if [[ "$$(uname)" == "Darwin" ]]; then
            for f in $$CPP_SDK_DIR/bin/* $$CPP_SDK_DIR/lib/*.so $$CPP_SDK_DIR/lib/*.dylib; do
                if [ -f "$$f" ]; then
                    install_name_tool -change @loader_path/../../_solib_darwin_arm64/_U_S_Sapi_Scpp_Cyr_Ucpp_Ulib___Uapi_Scpp/libyr-api.so @loader_path/../lib/libyr-api.so "$$f" 2>/dev/null || true
                    install_name_tool -change @loader_path/../../_solib_darwin_arm64/_U_S_Sapi_Scpp_Cfunctionsdk_Ulib___Uapi_Scpp/libfunctionsdk.so @loader_path/../lib/libfunctionsdk.so "$$f" 2>/dev/null || true
                    install_name_tool -change @loader_path/../../../_solib_darwin_arm64/_U_S_Sapi_Scpp_Cyr_Ucpp_Ulib___Uapi_Scpp/libyr-api.so @loader_path/../../lib/libyr-api.so "$$f" 2>/dev/null || true
                    install_name_tool -change @loader_path/../../../_solib_darwin_arm64/_U_S_Sapi_Scpp_Cfunctionsdk_Ulib___Uapi_Scpp/libfunctionsdk.so @loader_path/../../lib/libfunctionsdk.so "$$f" 2>/dev/null || true
                    install_name_tool -change @loader_path/../../_solib_darwin_x86_64/_U_S_Sapi_Scpp_Cyr_Ucpp_Ulib___Uapi_Scpp/libyr-api.so @loader_path/../lib/libyr-api.so "$$f" 2>/dev/null || true
                    install_name_tool -change @loader_path/../../_solib_darwin_x86_64/_U_S_Sapi_Scpp_Cfunctionsdk_Ulib___Uapi_Scpp/libfunctionsdk.so @loader_path/../lib/libfunctionsdk.so "$$f" 2>/dev/null || true
                    install_name_tool -change @loader_path/../../../_solib_darwin_x86_64/_U_S_Sapi_Scpp_Cyr_Ucpp_Ulib___Uapi_Scpp/libyr-api.so @loader_path/../../lib/libyr-api.so "$$f" 2>/dev/null || true
                    install_name_tool -change @loader_path/../../../_solib_darwin_x86_64/_U_S_Sapi_Scpp_Cfunctionsdk_Ulib___Uapi_Scpp/libfunctionsdk.so @loader_path/../../lib/libfunctionsdk.so "$$f" 2>/dev/null || true
                fi
            done
        fi &&
        cp -rf $$BASE_DIR/api/cpp/include $$CPP_SDK_DIR/ &&
        DATASYSTEM_DIR=$$BASE_DIR/external/datasystem_sdk &&
        if [ -d "$$DATASYSTEM_DIR/include" ]; then
            cp -rf $$DATASYSTEM_DIR/include/* $$CPP_SDK_DIR/include/ || true
        fi &&
        if [ -d "$$DATASYSTEM_DIR/lib" ]; then
            for f in "$$DATASYSTEM_DIR"/lib/*; do
                [ -e "$$f" ] || [ -L "$$f" ] || continue
                case "$$(basename "$$f")" in
                    libyr-api.so*|libfunctionsdk.so*|libcurl.so*|libssl.so|libcrypto.so)
                        continue
                        ;;
                esac
                cp -rf "$$f" $$CPP_SDK_DIR/lib/ || true
            done
        fi &&
        for f in $(SRCS); do
            case "$$(basename "$$f")" in
                libobservability-*.so|libobservability-*.dylib)
                    [ -f "$$f" ] && cp -rf "$$f" $$CPP_SDK_DIR/lib || true
                    ;;
            esac
        done &&
        for lib_name in ssl crypto; do
            link_path="$$CPP_SDK_DIR/lib/lib$${lib_name}.so"
            target_name=""
            for candidate in \
                "$$CPP_SDK_DIR/lib/lib$${lib_name}.so.3" \
                "$$CPP_SDK_DIR/lib/lib$${lib_name}.so.1.1" \
                "$$CPP_SDK_DIR/lib/lib$${lib_name}.so."*; do
                if [ -e "$$candidate" ]; then
                    target_name="$$(basename "$$candidate")"
                    break
                fi
            done
            if [ -n "$$target_name" ]; then
                rm -f "$$link_path"
                ln -s "$$target_name" "$$link_path"
            fi
        done &&
        EXAMPLE_3RD_DIR=$$BASE_DIR/api/cpp/example/3rd &&
        rm -rf $$EXAMPLE_3RD_DIR &&
        mkdir $$EXAMPLE_3RD_DIR &&
        cp -rf $$CPP_SDK_DIR/include $$EXAMPLE_3RD_DIR &&
        cp -rf $$CPP_SDK_DIR/lib $$EXAMPLE_3RD_DIR &&
        cp -rf $$CPP_SDK_DIR/bin $$CPP_SERVICE_DIR &&
        cp -rf $$CPP_SDK_DIR/lib $$CPP_SERVICE_DIR
        echo "$$BASE_DIR" > $@
    """,
    local = True,
    visibility = ["//visibility:public"],
)