###############################################################################
# Copyright 2018-2025, Barcelona Supercomputing Center (BSC), Spain            #
# Copyright 2015-2025, Johannes Gutenberg Universitaet Mainz, Germany          #
#                                                                              #
# This software was partially supported by the                                 #
# EC H2020 funded project NEXTGenIO (Project ID: 671951, www.nextgenio.eu).    #
#                                                                              #
# This software was partially supported by the                                 #
# ADA-FS project under the SPPEXA project funded by the DFG.                   #
#                                                                              #
# This file is part of GekkoFS' POSIX interface.                               #
#                                                                              #
# GekkoFS' POSIX interface is free software: you can redistribute it and/or    #
# modify it under the terms of the GNU Lesser General Public License as        #
# published by the Free Software Foundation, either version 3 of the License,  #
# or (at your option) any later version.                                       #
#                                                                              #
# GekkoFS' POSIX interface is distributed in the hope that it will be useful,  #
# but WITHOUT ANY WARRANTY; without even the implied warranty of               #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                #
# GNU Lesser General Public License for more details.                          #
#                                                                              #
# You should have received a copy of the GNU Lesser General Public License     #
# along with GekkoFS' POSIX interface.  If not, see                            #
# <https://www.gnu.org/licenses/>.                                             #
#                                                                              #
# SPDX-License-Identifier: LGPL-3.0-or-later                                   #
################################################################################

# ##############################################################################
# This builds the `libgkfs_intercept.so` library: the primary GekkoFS client
# based on syscall interception.
# ##############################################################################


add_library(gkfs_common SHARED)
target_sources(gkfs_common
    PUBLIC
    path.cpp
    PRIVATE
    logging.cpp
    open_file_map.cpp
    open_dir.cpp

    rpc/forward_data.cpp
    rpc/forward_data_proxy.cpp

    rpc/forward_metadata.cpp
    rpc/forward_repairs.cpp
    rpc/forward_metadata_proxy.cpp
    rpc/forward_malleability.cpp
    cache.cpp
    syscalls/detail/syscall_info.c syscalls/util.S
    ../common/hostfile_management.cpp
    )

target_link_libraries(
    gkfs_common
    PRIVATE metadata distributor env_util arithmetic path_util rpc_utils
    PUBLIC dl
    thallium
    fmt::fmt
    Threads::Threads
    Microsoft.GSL::GSL
    ZStd::ZStd
)

add_library(gkfs_intercept SHARED)

if (GKFS_BUILD_USER_LIB)
	add_library(gkfs_user_lib SHARED)
endif()

if (GKFS_BUILD_LIBC_INTERCEPTION)
    add_library(gkfs_libc_intercept SHARED)
endif()

target_sources(gkfs_intercept
    PRIVATE gkfs_functions.cpp
    gkfs_data.cpp
    gkfs_metadata.cpp
    intercept.cpp
    hooks.cpp
    preload.cpp
    preload_context.cpp
    preload_util.cpp
)

if (GKFS_BUILD_USER_LIB)
target_sources(
    gkfs_user_lib
    PRIVATE gkfs_functions.cpp
    gkfs_data.cpp
    gkfs_metadata.cpp
    intercept.cpp
    hooks.cpp
    preload.cpp
    preload_context.cpp
    preload_util.cpp
    malleability.cpp
)
endif()

if (GKFS_BUILD_LIBC_INTERCEPTION)
target_sources(
    gkfs_libc_intercept
    PRIVATE gkfs_functions.cpp
    gkfs_data.cpp
    gkfs_metadata.cpp
    gkfs_libc.cpp
    intercept.cpp
    hooks.cpp
    preload.cpp
    preload_context.cpp
    preload_util.cpp
)
endif ()

if (GKFS_BUILD_FUSE)
add_executable(fuse_client "")
target_sources(fuse_client
    PUBLIC
    ${CMAKE_CURRENT_LIST_DIR}/fuse/fuse_client.cpp
    PRIVATE
    ${INCLUDE_DIR}/client/fuse/fuse_client.hpp
    )

target_link_libraries(fuse_client
    PRIVATE gkfs_common metadata distributor env_util arithmetic path_util rpc_utils
    ${FUSE3_LIBRARIES}
    gkfs_user_lib
    )

target_include_directories(fuse_client
    PRIVATE
    ${FUSE3_INCLUDE_DIRS}
    )
if (GKFS_ENABLE_CLIENT_METRICS)
    target_link_libraries(fuse_client PRIVATE msgpack_util)
    target_compile_definitions(fuse_client PUBLIC GKFS_ENABLE_CLIENT_METRICS)
endif ()
endif()

if (GKFS_BUILD_USER_LIB)
target_compile_definitions(gkfs_user_lib PUBLIC BYPASS_SYSCALL ENABLE_USER)
target_link_options(gkfs_user_lib PRIVATE -z noexecstack)
if (GKFS_ENABLE_CLIENT_METRICS)
    target_link_libraries(gkfs_user_lib PRIVATE msgpack_util)
    target_compile_definitions(gkfs_user_lib PUBLIC GKFS_ENABLE_CLIENT_METRICS)
endif ()
endif()

if (GKFS_BUILD_LIBC_INTERCEPTION)
target_compile_definitions(gkfs_libc_intercept PUBLIC BYPASS_SYSCALL)
target_link_options(gkfs_libc_intercept PRIVATE -z noexecstack)
endif ()


if (GKFS_ENABLE_AGIOS)
    target_compile_definitions(gkfs_intercept PUBLIC GKFS_ENABLE_AGIOS)
endif ()
# Enable MSGPack metrics for intercept only

target_link_libraries(
    gkfs_intercept
    PRIVATE gkfs_common metadata distributor env_util arithmetic path_util rpc_utils
    PUBLIC dl
    thallium
    fmt::fmt
    Threads::Threads
    Syscall_intercept::Syscall_intercept
    Microsoft.GSL::GSL
)
# Enable MSGPack metrics 
if (GKFS_ENABLE_CLIENT_METRICS)
    target_link_libraries(
        gkfs_intercept
        PUBLIC
        msgpack_util
    )
    target_compile_definitions(gkfs_intercept PUBLIC GKFS_ENABLE_CLIENT_METRICS)
endif ()

if (GKFS_BUILD_USER_LIB)
    target_link_libraries(
    gkfs_user_lib
    PRIVATE gkfs_common metadata distributor env_util arithmetic path_util rpc_utils
    PUBLIC dl
    thallium
    fmt::fmt
    Threads::Threads
    Microsoft.GSL::GSL
)
endif()

if (GKFS_BUILD_LIBC_INTERCEPTION)
target_link_libraries(
    gkfs_libc_intercept
    PRIVATE  gkfs_common  metadata distributor env_util arithmetic path_util rpc_utils
    PUBLIC dl
    thallium
    fmt::fmt
    Threads::Threads
    Microsoft.GSL::GSL
)
if (GKFS_ENABLE_CLIENT_METRICS)
    target_link_libraries(
        gkfs_libc_intercept
        PUBLIC
        msgpack_util
    )
    target_compile_definitions(gkfs_libc_intercept PUBLIC GKFS_ENABLE_CLIENT_METRICS)
endif ()
endif ()

install(
    TARGETS gkfs_intercept
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gkfs
)

if (GKFS_BUILD_USER_LIB)
	set_target_properties(gkfs_user_lib
 	   PROPERTIES
	    PUBLIC_HEADER "../../include/client/void_syscall_intercept.hpp"
	    PUBLIC_HEADER "../../include/client/user_functions.hpp"
	)
	install(
	    TARGETS gkfs_user_lib
	    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
	    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
	    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gkfs
	)
endif()

if (GKFS_BUILD_LIBC_INTERCEPTION)
set_target_properties(gkfs_libc_intercept
    PROPERTIES
    PUBLIC_HEADER "../../include/client/void_syscall_intercept.hpp"
    PUBLIC_HEADER "../../include/client/user_functions.hpp"
)

install(
    TARGETS gkfs_libc_intercept
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gkfs
)
endif ()

if (GKFS_BUILD_FUSE)
install(TARGETS fuse_client RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})
endif ()

install(
    TARGETS gkfs_common
    LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
    ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
    PUBLIC_HEADER DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/gkfs
)
