Fix bug in mt_mpmc.c, in Linux mutexes are not recursive. Add arena_trim_string() to the arena API Removing arena->path, now paths are pushed to arena->metadata Replacing fe->owner[128] with char *owner; the owner is not pushed as a string to arena->metadata and trimed with arena_trim_string() Improving cache locality in arena->metadata, the memory layout is not fe; fe->path; fe->owner. Cache aligning all arenas except HasherContext->arena to sizeof(void *). Pushing elements one by one instead of snprintf() in finalize_file() and hash_worker(). Getting the full path of current directory instead of "." Fixing bug in path formating, this allow us to remove normalize_path() from the hot loop.
285 lines
9.6 KiB
CMake
285 lines
9.6 KiB
CMake
cmake_minimum_required(VERSION 3.20)
|
|
project(dfin
|
|
VERSION 1.0.0
|
|
DESCRIPTION "High-performance duplicate finder with I/O Ring/io_uring support"
|
|
LANGUAGES C
|
|
)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Force compiler search order
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# On Windows, prefer clang-cl, then GCC, then Clang
|
|
if(WIN32)
|
|
# Try to force compiler order if not already set
|
|
if(NOT CMAKE_C_COMPILER)
|
|
# Search in preferred order
|
|
find_program(CLANG_CL_COMPILER NAMES clang-cl)
|
|
find_program(GCC_COMPILER NAMES gcc)
|
|
find_program(CLANG_COMPILER NAMES clang)
|
|
|
|
if(CLANG_CL_COMPILER)
|
|
message(STATUS "Found clang-cl as preferred compiler: ${CLANG_CL_COMPILER}")
|
|
set(CMAKE_C_COMPILER "${CLANG_CL_COMPILER}" CACHE STRING "" FORCE)
|
|
elseif(GCC_COMPILER)
|
|
message(STATUS "Found GCC as fallback compiler: ${GCC_COMPILER}")
|
|
set(CMAKE_C_COMPILER "${GCC_COMPILER}" CACHE STRING "" FORCE)
|
|
elseif(CLANG_COMPILER)
|
|
message(STATUS "Found Clang as last-resort compiler: ${CLANG_COMPILER}")
|
|
set(CMAKE_C_COMPILER "${CLANG_COMPILER}" CACHE STRING "" FORCE)
|
|
endif()
|
|
endif()
|
|
else()
|
|
# On Linux, prefer GCC, then Clang
|
|
if(NOT CMAKE_C_COMPILER)
|
|
find_program(GCC_COMPILER NAMES gcc)
|
|
find_program(CLANG_COMPILER NAMES clang)
|
|
|
|
if(GCC_COMPILER)
|
|
message(STATUS "Found GCC as preferred compiler: ${GCC_COMPILER}")
|
|
set(CMAKE_C_COMPILER "${GCC_COMPILER}" CACHE STRING "" FORCE)
|
|
elseif(CLANG_COMPILER)
|
|
message(STATUS "Found Clang as fallback compiler: ${CLANG_COMPILER}")
|
|
set(CMAKE_C_COMPILER "${CLANG_COMPILER}" CACHE STRING "" FORCE)
|
|
endif()
|
|
endif()
|
|
endif()
|
|
|
|
# Now project() will use the compiler we found
|
|
# However, since we needed project() first to get C support,
|
|
# we check what we actually got
|
|
message(STATUS "Using compiler: ${CMAKE_C_COMPILER} (${CMAKE_C_COMPILER_ID})")
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Platform and Compiler Detection
|
|
# ---------------------------------------------------------------------------
|
|
|
|
if(WIN32)
|
|
set(PLATFORM_WINDOWS TRUE)
|
|
set(PLATFORM_NAME "Windows")
|
|
else()
|
|
set(PLATFORM_LINUX TRUE)
|
|
set(PLATFORM_NAME "Linux")
|
|
endif()
|
|
|
|
# Compiler type
|
|
if(CMAKE_C_COMPILER_ID STREQUAL "Clang")
|
|
# Check if it's clang-cl
|
|
if(CMAKE_C_COMPILER_FRONTEND_VARIANT STREQUAL "MSVC")
|
|
set(COMPILER_CLANG_CL TRUE)
|
|
message(STATUS "Detected clang-cl (MSVC-compatible frontend)")
|
|
else()
|
|
set(COMPILER_CLANG_GNU TRUE)
|
|
message(STATUS "Detected Clang (GNU-compatible frontend)")
|
|
endif()
|
|
elseif(CMAKE_C_COMPILER_ID STREQUAL "GNU")
|
|
set(COMPILER_GCC TRUE)
|
|
message(STATUS "Detected GCC")
|
|
elseif(CMAKE_C_COMPILER_ID STREQUAL "MSVC")
|
|
# We don't want MSVC, but if it's found, warn user
|
|
message(FATAL_ERROR
|
|
"MSVC (cl.exe) detected!\n"
|
|
"This project requires clang-cl, GCC, or Clang.\n"
|
|
"Please install one of these compilers or specify manually:\n"
|
|
" cmake .. -DCMAKE_C_COMPILER=clang-cl\n"
|
|
" cmake .. -DCMAKE_C_COMPILER=gcc\n"
|
|
" cmake .. -DCMAKE_C_COMPILER=clang\n"
|
|
)
|
|
endif()
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Build System Selection
|
|
# ---------------------------------------------------------------------------
|
|
|
|
if(NOT CMAKE_GENERATOR OR CMAKE_GENERATOR STREQUAL "")
|
|
find_program(NINJA_EXECUTABLE NAMES ninja)
|
|
if(NINJA_EXECUTABLE)
|
|
message(STATUS "Using Ninja build system")
|
|
set(CMAKE_GENERATOR "Ninja")
|
|
else()
|
|
message(STATUS "Ninja not found, using default generator: ${CMAKE_GENERATOR}")
|
|
endif()
|
|
endif()
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Source Files
|
|
# ---------------------------------------------------------------------------
|
|
|
|
set(SOURCES
|
|
duplicate_finder.c
|
|
xxhash.c
|
|
xxh_x86dispatch.c
|
|
)
|
|
|
|
# Headers for dependency tracking and IDE
|
|
set(HEADERS
|
|
arena.h
|
|
base.h
|
|
xxhash.h
|
|
mt_mpmc.h
|
|
)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Create Executable
|
|
# ---------------------------------------------------------------------------
|
|
|
|
add_executable(${PROJECT_NAME}
|
|
${SOURCES}
|
|
${HEADERS}
|
|
)
|
|
|
|
# Include directories
|
|
target_include_directories(${PROJECT_NAME} PRIVATE
|
|
${CMAKE_CURRENT_SOURCE_DIR}
|
|
)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Compiler Flags - Exact match to your commands
|
|
# ---------------------------------------------------------------------------
|
|
|
|
if(PLATFORM_WINDOWS)
|
|
if(COMPILER_CLANG_CL)
|
|
# === clang-cl flags ===
|
|
# Release: /O2
|
|
target_compile_options(${PROJECT_NAME} PRIVATE
|
|
$<$<CONFIG:Release>:/O2>
|
|
)
|
|
# Debug: /Zi /Od
|
|
target_compile_options(${PROJECT_NAME} PRIVATE
|
|
$<$<CONFIG:Debug>:/Zi /Od>
|
|
)
|
|
# Common warnings
|
|
target_compile_options(${PROJECT_NAME} PRIVATE /W4)
|
|
|
|
elseif(COMPILER_GCC)
|
|
# === GCC flags (Windows/MinGW) ===
|
|
# Release: -O3
|
|
target_compile_options(${PROJECT_NAME} PRIVATE
|
|
$<$<CONFIG:Release>:-O3>
|
|
)
|
|
# Debug: -g -O0
|
|
target_compile_options(${PROJECT_NAME} PRIVATE
|
|
$<$<CONFIG:Debug>:-g -O0>
|
|
)
|
|
# Common warnings
|
|
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra)
|
|
|
|
elseif(COMPILER_CLANG_GNU)
|
|
# === Clang flags (Windows, GNU frontend) ===
|
|
# Release: -O3
|
|
target_compile_options(${PROJECT_NAME} PRIVATE
|
|
$<$<CONFIG:Release>:-O3>
|
|
)
|
|
# Debug: -g -O0
|
|
target_compile_options(${PROJECT_NAME} PRIVATE
|
|
$<$<CONFIG:Debug>:-g -O0>
|
|
)
|
|
# Common warnings
|
|
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra)
|
|
endif()
|
|
|
|
# Windows-specific libraries
|
|
target_link_libraries(${PROJECT_NAME} PRIVATE
|
|
kernel32
|
|
)
|
|
|
|
# Windows-specific defines
|
|
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
|
WIN32_LEAN_AND_MEAN
|
|
_WIN32_WINNT=0x0A00 # Windows 10+
|
|
)
|
|
|
|
# Set output name with .exe
|
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
|
SUFFIX ".exe"
|
|
)
|
|
|
|
elseif(PLATFORM_LINUX)
|
|
# === Linux GCC/Clang flags ===
|
|
if(COMPILER_GCC OR COMPILER_CLANG_GNU)
|
|
# Release: -O3
|
|
target_compile_options(${PROJECT_NAME} PRIVATE
|
|
$<$<CONFIG:Release>:-O3>
|
|
)
|
|
# Debug: -g -O0
|
|
target_compile_options(${PROJECT_NAME} PRIVATE
|
|
$<$<CONFIG:Debug>:-g -O0>
|
|
)
|
|
# Common warnings
|
|
target_compile_options(${PROJECT_NAME} PRIVATE -Wall -Wextra)
|
|
endif()
|
|
|
|
# Linux-specific libraries
|
|
find_package(Threads REQUIRED)
|
|
find_library(LIBURING_LIBRARY NAMES uring)
|
|
|
|
if(LIBURING_LIBRARY)
|
|
message(STATUS "Found liburing: ${LIBURING_LIBRARY}")
|
|
target_link_libraries(${PROJECT_NAME} PRIVATE
|
|
Threads::Threads
|
|
${LIBURING_LIBRARY}
|
|
)
|
|
else()
|
|
message(FATAL_ERROR "liburing not found! Install liburing-dev or equivalent")
|
|
endif()
|
|
|
|
# Linux-specific defines
|
|
target_compile_definitions(${PROJECT_NAME} PRIVATE
|
|
_GNU_SOURCE
|
|
)
|
|
endif()
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# C Standard
|
|
# ---------------------------------------------------------------------------
|
|
|
|
set_target_properties(${PROJECT_NAME} PROPERTIES
|
|
C_STANDARD 11
|
|
C_STANDARD_REQUIRED ON
|
|
C_EXTENSIONS OFF
|
|
)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Build Configurations
|
|
# ---------------------------------------------------------------------------
|
|
|
|
# Set default build type if not specified (matching your Release command)
|
|
if(NOT CMAKE_BUILD_TYPE)
|
|
set(CMAKE_BUILD_TYPE "Release" CACHE STRING
|
|
"Choose the type of build: Release or Debug" FORCE)
|
|
message(STATUS "No build type specified, defaulting to Release")
|
|
endif()
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# IDE Support
|
|
# ---------------------------------------------------------------------------
|
|
|
|
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Info Target
|
|
# ---------------------------------------------------------------------------
|
|
|
|
add_custom_target(info
|
|
COMMAND ${CMAKE_COMMAND} -E echo "=== Build Configuration ==="
|
|
COMMAND ${CMAKE_COMMAND} -E echo "Project: ${PROJECT_NAME}"
|
|
COMMAND ${CMAKE_COMMAND} -E echo "Compiler: ${CMAKE_C_COMPILER} (${CMAKE_C_COMPILER_ID})"
|
|
COMMAND ${CMAKE_COMMAND} -E echo "Frontend: $<IF:$<BOOL:${COMPILER_CLANG_CL}>,clang-cl,GNU>"
|
|
COMMAND ${CMAKE_COMMAND} -E echo "Generator: ${CMAKE_GENERATOR}"
|
|
COMMAND ${CMAKE_COMMAND} -E echo "Build Type: ${CMAKE_BUILD_TYPE}"
|
|
COMMAND ${CMAKE_COMMAND} -E echo "Platform: ${PLATFORM_NAME}"
|
|
COMMAND ${CMAKE_COMMAND} -E echo "============================"
|
|
)
|
|
|
|
# ---------------------------------------------------------------------------
|
|
# Print final configuration
|
|
# ---------------------------------------------------------------------------
|
|
|
|
message(STATUS "----------------------------------------")
|
|
message(STATUS "Configuration Summary:")
|
|
message(STATUS " Compiler: ${CMAKE_C_COMPILER}")
|
|
message(STATUS " Build Type: ${CMAKE_BUILD_TYPE}")
|
|
message(STATUS " Generator: ${CMAKE_GENERATOR}")
|
|
message(STATUS " Platform: ${PLATFORM_NAME}")
|
|
message(STATUS "----------------------------------------")
|