# ════════════════════════════════════════════════════════════════════════════
# GNU-free CMake build for rsync (FenrirOS)
#
# Replaces rsync's autotools GNU-make build with CMake + Ninja so the whole
# pipeline stays GNU-free (driven by makeplus/ninja and the LLVM/musl toolchain).
#
# rsync still needs its POSIX-sh ./configure run ONCE to probe the platform and
# emit config.h. configure is an autoconf-generated /bin/sh script — not GNU
# make — so running it does not reintroduce a GNU build tool. build_rsync() in
# build-os.sh runs ./configure and generates the awk-derived headers (proto.h,
# daemon-parm.h, help-rsync.h, etc.) before invoking cmake; this file then
# compiles and links the rsync binary. The object lists mirror the rsync 3.4.1
# Makefile.in verbatim (features self-disable via config.h #ifdefs).
# ════════════════════════════════════════════════════════════════════════════
cmake_minimum_required(VERSION 3.13)
project(rsync C CXX ASM)

if(NOT EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/config.h")
    message(FATAL_ERROR
        "config.h not found in the rsync source root.\n"
        "Run ./configure (build_rsync does this) before invoking cmake.")
endif()

# musl sysroot (zlib lives here).
set(MUSL_SYSROOT "/usr/local/musl" CACHE PATH "musl sysroot prefix")

include_directories(
    "${CMAKE_CURRENT_SOURCE_DIR}"
    "${MUSL_SYSROOT}/include"
)
link_directories("${MUSL_SYSROOT}/lib")

add_compile_definitions(
    HAVE_CONFIG_H
)

if(NOT CMAKE_BUILD_TYPE)
    set(CMAKE_BUILD_TYPE "Release")
endif()
add_compile_options(
    -O2 -fPIC
    -Wno-unused-parameter -Wno-unused-result -Wno-pointer-sign
    -Wno-deprecated-non-prototype
)

# ── lib/ helper objects ────────────────────────────────────────────────────────
set(LIB_OBJS
    lib/wildmatch.c
    lib/compat.c
    lib/snprintf.c
    lib/mdfour.c
    lib/md5.c
    lib/permstring.c
    lib/pool_alloc.c
    lib/sysacls.c
    lib/sysxattrs.c
)

# ── Main rsync objects (OBJS1 + OBJS2 + OBJS3 + DAEMON_OBJ) ──────────────────
set(RSYNC_OBJS
    # OBJS1
    flist.c
    rsync.c
    generator.c
    receiver.c
    cleanup.c
    sender.c
    exclude.c
    util1.c
    util2.c
    main.c
    checksum.c
    match.c
    syscall.c
    log.c
    backup.c
    delete.c
    # OBJS2
    options.c
    io.c
    compat.c
    hlink.c
    token.c
    uidlist.c
    socket.c
    hashtable.c
    usage.c
    fileio.c
    batch.c
    clientname.c
    chmod.c
    acls.c
    xattrs.c
    # OBJS3
    progress.c
    pipe.c
    # DAEMON_OBJ
    params.c
    loadparm.c
    clientserver.c
    access.c
    connection.c
    authenticate.c
)

# ── Bundled popt (rsync ships its own, slightly modified copy) ─────────────────
set(POPT_OBJS
    popt/popt.c
    popt/poptconfig.c
    popt/popthelp.c
    popt/poptparse.c
    popt/poptint.c
)
# popt/findme.c was removed in recent rsync; add it only if present.
if(EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/popt/findme.c")
    list(APPEND POPT_OBJS popt/findme.c)
endif()

# ── Bundled zlib (used when system zlib is not available / not requested) ──────
# By default we link system zlib (-lz). Set RSYNC_USE_BUNDLED_ZLIB=ON to use
# the in-tree copy instead.
option(RSYNC_USE_BUNDLED_ZLIB "Use rsync's bundled zlib instead of system zlib" OFF)
if(RSYNC_USE_BUNDLED_ZLIB)
    set(ZLIB_OBJS
        zlib/deflate.c
        zlib/inffast.c
        zlib/inflate.c
        zlib/inftrees.c
        zlib/trees.c
        zlib/zutil.c
        zlib/adler32.c
        zlib/compress.c
        zlib/crc32.c
    )
endif()

# ── Optional SIMD/ASM acceleration (x86_64) ──────────────────────────────────
# configure enables these on x86_64 and the C code expects the symbols to exist.
# The SIMD rolling-checksum (get_checksum1) and MD5 ASM (md5_process_asm) are
# required when config.h has them enabled.
if(CMAKE_SYSTEM_PROCESSOR MATCHES "x86_64|AMD64")
    set(SIMD_SRCS
        simd-checksum-x86_64.cpp
        simd-checksum-avx2.S
    )
    set(MD5_ASM_SRCS
        lib/md5-asm-x86_64.S
    )
    # The .S files need the preprocessor to find config.h
    set_source_files_properties(
        simd-checksum-avx2.S lib/md5-asm-x86_64.S
        PROPERTIES LANGUAGE ASM
    )
endif()

# ── rsync executable ──────────────────────────────────────────────────────────
add_executable(rsync
    ${RSYNC_OBJS}
    ${LIB_OBJS}
    ${POPT_OBJS}
    ${SIMD_SRCS}
    ${MD5_ASM_SRCS}
    $<$<BOOL:${RSYNC_USE_BUNDLED_ZLIB}>:${ZLIB_OBJS}>
)

target_include_directories(rsync PRIVATE
    "${CMAKE_CURRENT_SOURCE_DIR}/popt"
)

if(RSYNC_USE_BUNDLED_ZLIB)
    target_include_directories(rsync PRIVATE "${CMAKE_CURRENT_SOURCE_DIR}/zlib")
else()
    target_link_libraries(rsync PRIVATE z)
endif()

# ── Install ───────────────────────────────────────────────────────────────────
install(TARGETS rsync RUNTIME DESTINATION bin)
