# ═══════════════════════════════════════════════════════════════════════════════
# file 5.46 — GNU-free CMake build for musl/LLVM (FenrirOS)
# Builds: libmagic.a (static) + file command + magic database
# ═══════════════════════════════════════════════════════════════════════════════
cmake_minimum_required(VERSION 3.20)
project(file VERSION 5.46 LANGUAGES C)

set(CMAKE_C_STANDARD 11)

# ── Generate magic.h from template ───────────────────────────────────────────
set(VERSION_NODOTS "546")
file(READ ${CMAKE_CURRENT_SOURCE_DIR}/src/magic.h.in MAGIC_H_CONTENT)
string(REPLACE "X.YY" "${VERSION_NODOTS}" MAGIC_H_CONTENT "${MAGIC_H_CONTENT}")
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/magic.h "${MAGIC_H_CONTENT}")

# ── config.h ─────────────────────────────────────────────────────────────────
include(CheckIncludeFile)
include(CheckFunctionExists)
include(CheckTypeSize)

check_include_file(stdint.h HAVE_STDINT_H)
check_include_file(inttypes.h HAVE_INTTYPES_H)
check_include_file(unistd.h HAVE_UNISTD_H)
check_include_file(fcntl.h HAVE_FCNTL_H)
check_include_file(sys/mman.h HAVE_SYS_MMAN_H)
check_include_file(sys/stat.h HAVE_SYS_STAT_H)
check_include_file(sys/types.h HAVE_SYS_TYPES_H)
check_include_file(sys/time.h HAVE_SYS_TIME_H)
check_include_file(wchar.h HAVE_WCHAR_H)
check_include_file(wctype.h HAVE_WCTYPE_H)
check_include_file(getopt.h HAVE_GETOPT_H)
check_include_file(byteswap.h HAVE_BYTESWAP_H)
check_include_file(sys/bswap.h HAVE_SYS_BSWAP_H)
check_include_file(err.h HAVE_ERR_H)
check_include_file(spawn.h HAVE_SPAWN_H)
check_include_file(sys/wait.h HAVE_SYS_WAIT_H)
check_include_file(sys/ioctl.h HAVE_SYS_IOCTL_H)

check_function_exists(mmap HAVE_MMAP)
check_function_exists(pread HAVE_PREAD)
check_function_exists(strlcpy HAVE_STRLCPY)
check_function_exists(strlcat HAVE_STRLCAT)
check_function_exists(getopt_long HAVE_GETOPT_LONG)
check_function_exists(asprintf HAVE_ASPRINTF)
check_function_exists(vasprintf HAVE_VASPRINTF)
check_function_exists(dprintf HAVE_DPRINTF)
check_function_exists(fmtcheck HAVE_FMTCHECK)
check_function_exists(ctime_r HAVE_CTIME_R)
check_function_exists(asctime_r HAVE_ASCTIME_R)
check_function_exists(gmtime_r HAVE_GMTIME_R)
check_function_exists(localtime_r HAVE_LOCALTIME_R)
check_function_exists(fork HAVE_FORK)
check_function_exists(utime HAVE_UTIME)
check_function_exists(utimes HAVE_UTIMES)
check_function_exists(wcwidth HAVE_WCWIDTH)
check_function_exists(mkstemp HAVE_MKSTEMP)
check_function_exists(posix_spawnp HAVE_POSIX_SPAWNP)
check_function_exists(strcasestr HAVE_STRCASESTR)
check_function_exists(getline HAVE_GETLINE)

check_type_size("struct stat.st_rdev" STRUCT_STAT_ST_RDEV)
if(STRUCT_STAT_ST_RDEV)
    set(HAVE_STRUCT_STAT_ST_RDEV 1)
endif()

# Find zlib (optional compression support)
find_library(ZLIB_LIBRARY z PATHS /usr/local/musl/lib /usr/local/lib)
find_path(ZLIB_INCLUDE_DIR zlib.h PATHS /usr/local/musl/include /usr/local/include)
if(ZLIB_LIBRARY AND ZLIB_INCLUDE_DIR)
    set(HAVE_ZLIB_H 1)
    set(ZLIBSUPPORT 1)
endif()

set(MAGIC "/usr/local/share/misc/magic")
set(VERSION "${PROJECT_VERSION}")
set(PACKAGE "file")
set(PACKAGE_VERSION "${PROJECT_VERSION}")

configure_file(${CMAKE_CURRENT_SOURCE_DIR}/cmake_config.h.in
    ${CMAKE_CURRENT_BINARY_DIR}/config.h @ONLY)

# ── libmagic sources ─────────────────────────────────────────────────────────
set(LIBMAGIC_SOURCES
    src/buffer.c
    src/magic.c
    src/apprentice.c
    src/softmagic.c
    src/ascmagic.c
    src/encoding.c
    src/compress.c
    src/is_csv.c
    src/is_json.c
    src/is_simh.c
    src/is_tar.c
    src/readelf.c
    src/print.c
    src/fsmagic.c
    src/funcs.c
    src/apptype.c
    src/der.c
    src/cdf.c
    src/cdf_time.c
    src/readcdf.c
)

# Add compat sources if musl doesn't provide them
if(NOT HAVE_STRLCPY)
    list(APPEND LIBMAGIC_SOURCES src/strlcpy.c)
endif()
if(NOT HAVE_STRLCAT)
    list(APPEND LIBMAGIC_SOURCES src/strlcat.c)
endif()
if(NOT HAVE_GETOPT_LONG)
    list(APPEND LIBMAGIC_SOURCES src/getopt_long.c)
endif()
if(NOT HAVE_ASPRINTF)
    list(APPEND LIBMAGIC_SOURCES src/asprintf.c)
endif()
if(NOT HAVE_VASPRINTF)
    list(APPEND LIBMAGIC_SOURCES src/vasprintf.c)
endif()
if(NOT HAVE_DPRINTF)
    list(APPEND LIBMAGIC_SOURCES src/dprintf.c)
endif()
if(NOT HAVE_FMTCHECK)
    list(APPEND LIBMAGIC_SOURCES src/fmtcheck.c)
endif()
if(NOT HAVE_CTIME_R)
    list(APPEND LIBMAGIC_SOURCES src/ctime_r.c)
endif()
if(NOT HAVE_ASCTIME_R)
    list(APPEND LIBMAGIC_SOURCES src/asctime_r.c)
endif()
if(NOT HAVE_GMTIME_R)
    list(APPEND LIBMAGIC_SOURCES src/gmtime_r.c)
endif()
if(NOT HAVE_LOCALTIME_R)
    list(APPEND LIBMAGIC_SOURCES src/localtime_r.c)
endif()
if(NOT HAVE_PREAD)
    list(APPEND LIBMAGIC_SOURCES src/pread.c)
endif()
if(NOT HAVE_STRCASESTR)
    list(APPEND LIBMAGIC_SOURCES src/strcasestr.c)
endif()
if(NOT HAVE_GETLINE)
    list(APPEND LIBMAGIC_SOURCES src/getline.c)
endif()

add_library(magic STATIC ${LIBMAGIC_SOURCES})
target_include_directories(magic
    PUBLIC ${CMAKE_CURRENT_BINARY_DIR}
    PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src
)
target_compile_definitions(magic PRIVATE
    HAVE_CONFIG_H
    _GNU_SOURCE
    MAGIC="${MAGIC}"
    VERSION="${VERSION}"
)
if(ZLIBSUPPORT)
    target_include_directories(magic PRIVATE ${ZLIB_INCLUDE_DIR})
    target_link_libraries(magic PRIVATE ${ZLIB_LIBRARY})
endif()

# ── file command ──────────────────────────────────────────────────────────────
add_executable(file_cmd src/file.c)
set_target_properties(file_cmd PROPERTIES OUTPUT_NAME file)
target_include_directories(file_cmd PRIVATE
    ${CMAKE_CURRENT_BINARY_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/src
)
target_compile_definitions(file_cmd PRIVATE HAVE_CONFIG_H VERSION="${VERSION}")
target_link_libraries(file_cmd PRIVATE magic m)
if(ZLIBSUPPORT)
    target_link_libraries(file_cmd PRIVATE ${ZLIB_LIBRARY})
endif()

# ── Install ───────────────────────────────────────────────────────────────────
install(TARGETS magic ARCHIVE DESTINATION lib)
install(TARGETS file_cmd RUNTIME DESTINATION bin)
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/magic.h DESTINATION include)

# Install magic database files
install(DIRECTORY magic/Magdir/ DESTINATION share/misc/magic
    FILES_MATCHING PATTERN "*")
