Files
duplicatefinder/build.sh

273 lines
9.0 KiB
Bash

#!/usr/bin/env bash
# ============================================================================
# build.sh - Build script for filehasher (Linux)
# Usage: ./build.sh [Release|Debug] [clean]
#
# Compiler preference: gcc > clang
# Build system: Ninja (fallback to Make)
# ============================================================================
set -euo pipefail
# ---------------------------------------------------------------------------
# Colors
# ---------------------------------------------------------------------------
readonly RED='\033[0;31m'
readonly GREEN='\033[0;32m'
readonly YELLOW='\033[1;33m'
readonly CYAN='\033[0;36m'
readonly NC='\033[0m'
# ---------------------------------------------------------------------------
# Default values
# ---------------------------------------------------------------------------
BUILD_TYPE="Release"
CLEAN_BUILD=0
# ---------------------------------------------------------------------------
# Parse arguments
# ---------------------------------------------------------------------------
while [[ $# -gt 0 ]]; do
case "$1" in
Release|release)
BUILD_TYPE="Release"
shift
;;
Debug|debug)
BUILD_TYPE="Debug"
shift
;;
clean|-clean|--clean)
CLEAN_BUILD=1
shift
;;
*)
echo -e "${RED}Unknown argument: $1${NC}"
echo "Usage: $0 [Release|Debug] [clean]"
exit 1
;;
esac
done
# ---------------------------------------------------------------------------
# Setup
# ---------------------------------------------------------------------------
readonly BUILD_DIR="build/linux/${BUILD_TYPE}"
readonly SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
echo -e "${GREEN}=== Building filehasher (${BUILD_TYPE}) ===${NC}"
echo "Project: ${SCRIPT_DIR}"
# ---------------------------------------------------------------------------
# Clean if requested
# ---------------------------------------------------------------------------
if [[ $CLEAN_BUILD -eq 1 ]]; then
echo -e "${YELLOW}Cleaning build directory...${NC}"
rm -rf "${BUILD_DIR}"
echo
fi
# ---------------------------------------------------------------------------
# Create build directory
# ---------------------------------------------------------------------------
mkdir -p "${BUILD_DIR}"
cd "${BUILD_DIR}"
# ---------------------------------------------------------------------------
# Compiler selection (prefer gcc, fallback to clang)
# ---------------------------------------------------------------------------
echo -e "${YELLOW}Detecting compiler...${NC}"
CC_BINARY=""
CC_NAME=""
if command -v gcc &> /dev/null; then
CC_BINARY="gcc"
CC_VERSION=$(gcc --version | head -n1)
CC_NAME="GCC (${CC_VERSION})"
echo -e " ${GREEN}[OK]${NC} Found GCC (preferred): ${CC_VERSION}"
elif command -v clang &> /dev/null; then
CC_BINARY="clang"
CC_VERSION=$(clang --version | head -n1)
CC_NAME="Clang (${CC_VERSION})"
echo -e " ${YELLOW}[OK]${NC} Found Clang (fallback): ${CC_VERSION}"
else
echo -e "${RED}[FAIL] No suitable compiler found!${NC}"
echo "Please install gcc or clang:"
echo " Ubuntu/Debian: sudo apt install build-essential"
echo " Fedora/RHEL: sudo dnf install gcc"
echo " Arch: sudo pacman -S gcc"
exit 1
fi
# ---------------------------------------------------------------------------
# Check dependencies
# ---------------------------------------------------------------------------
echo -e "${YELLOW}Checking dependencies...${NC}"
# Check for liburing
HAVE_LIBURING=0
if ldconfig -p | grep -q liburing 2>/dev/null; then
HAVE_LIBURING=1
echo -e " ${GREEN}[OK]${NC} Found liburing"
elif pkg-config --exists liburing 2>/dev/null; then
HAVE_LIBURING=1
echo -e " ${GREEN}[OK]${NC} Found liburing (pkg-config)"
elif [[ -f /usr/lib/liburing.so ]] || [[ -f /usr/lib64/liburing.so ]] || [[ -f /usr/local/lib/liburing.so ]]; then
HAVE_LIBURING=1
echo -e " ${GREEN}[OK]${NC} Found liburing (manual detection)"
else
echo -e "${RED}[FAIL] liburing not found!${NC}"
echo "Please install liburing-dev:"
echo " Ubuntu/Debian: sudo apt install liburing-dev"
echo " Fedora/RHEL: sudo dnf install liburing-devel"
echo " Arch: sudo pacman -S liburing"
exit 1
fi
# Check for pthreads
# Check if pthreads is available (either in ldconfig or merged into libc)
if ldconfig -p | grep -q libpthread 2>/dev/null || ldd --version | grep -qP '2\.(3[4-9]|[4-9][0-9])'; then
echo -e " ${GREEN}[OK]${NC} Found pthreads (merged or standalone)"
else
echo -e " ${YELLOW}[NOTE]${NC} pthreads not found, attempting link"
fi
echo
# ---------------------------------------------------------------------------
# Generator selection (prefer ninja)
# ---------------------------------------------------------------------------
echo -e "${YELLOW}Selecting build system...${NC}"
GENERATOR=""
GENERATOR_NAME=""
if command -v ninja &> /dev/null; then
GENERATOR="Ninja"
GENERATOR_NAME="Ninja"
echo -e " ${GREEN}[OK]${NC} Using Ninja"
elif command -v make &> /dev/null; then
GENERATOR="Unix Makefiles"
GENERATOR_NAME="Make"
echo -e " ${YELLOW}[OK]${NC} Ninja not found, using Make"
else
echo -e "${RED}[FAIL] No build system found!${NC}"
echo "Please install ninja or make:"
echo " Ubuntu/Debian: sudo apt install ninja-build"
echo " Fedora/RHEL: sudo dnf install ninja-build"
echo " Arch: sudo pacman -S ninja"
exit 1
fi
echo
# ---------------------------------------------------------------------------
# Configure
# ---------------------------------------------------------------------------
echo -e "${YELLOW}Configuring CMake...${NC}"
# --------------------------------------------------------------------------
# compile_commands.json logic
# --------------------------------------------------------------------------
EXPORT_COMPILE_COMMANDS=OFF
if [[ "$BUILD_TYPE" == "Release" ]]; then
if [[ -f "${SCRIPT_DIR}/compile_commands.json" ]]; then
echo -e " compile_commands.json already exists - skipping generation"
else
echo -e " compile_commands.json will be generated"
EXPORT_COMPILE_COMMANDS=ON
fi
fi
echo -e " Build type: ${BUILD_TYPE}"
echo -e " Compiler: ${CC_NAME}"
echo -e " Generator: ${GENERATOR_NAME}"
cmake "${SCRIPT_DIR}" \
-G "${GENERATOR}" \
-DCMAKE_BUILD_TYPE="${BUILD_TYPE}" \
-DCMAKE_C_COMPILER="${CC_BINARY}" \
-DCMAKE_EXPORT_COMPILE_COMMANDS=${EXPORT_COMPILE_COMMANDS}
if [[ $? -ne 0 ]]; then
echo -e "${RED}CMake configuration failed!${NC}"
exit 1
fi
echo -e "${GREEN}Configuration successful!${NC}"
echo
# ---------------------------------------------------------------------------
# Build
# ---------------------------------------------------------------------------
echo -e "${YELLOW}Building...${NC}"
# Get number of CPU cores
if command -v nproc &> /dev/null; then
CORES=$(nproc)
else
CORES=4
fi
cmake --build . --config "${BUILD_TYPE}" --parallel "${CORES}"
if [[ $? -ne 0 ]]; then
echo -e "${RED}Build failed!${NC}"
exit 1
fi
echo -e "${GREEN}Build successful!${NC}"
echo
# ---------------------------------------------------------------------------
# Verify output
# ---------------------------------------------------------------------------
cd "${SCRIPT_DIR}"
if [[ -f "${BUILD_DIR}/filehasher" ]]; then
echo -e "${GREEN}Executable: ${BUILD_DIR}/filehasher${NC}"
if command -v file &> /dev/null; then
echo -e " Type: $(file -b ${BUILD_DIR}/filehasher)"
fi
if command -v du &> /dev/null; then
echo -e " Size: $(du -h ${BUILD_DIR}/filehasher | cut -f1)"
fi
elif [[ -f "${BUILD_DIR}/filehasher.exe" ]]; then
echo -e "${GREEN}Executable: ${BUILD_DIR}/filehasher.exe${NC}"
else
echo -e "${YELLOW}Note: Could not locate executable${NC}"
echo "Checking build directory:"
find "${BUILD_DIR}" -type f -executable 2>/dev/null || echo " No executables found"
fi
# ---------------------------------------------------------------------------
# Summary
# ---------------------------------------------------------------------------
echo
echo -e "${CYAN}=== Build Complete ===${NC}"
echo
echo -e "${YELLOW}Build Information:${NC}"
echo -e " Configuration: ${BUILD_TYPE}"
echo -e " Compiler: ${CC_NAME}"
echo -e " Generator: ${GENERATOR_NAME}"
echo -e " Output: ${BUILD_DIR}/"
# ---------------------------------------------------------------------------
# Copy compile_commands.json for clangd
# ---------------------------------------------------------------------------
if [[ "${EXPORT_COMPILE_COMMANDS}" == "ON" ]]; then
if [[ -f "${BUILD_DIR}/compile_commands.json" ]]; then
echo -e " clangd: compile_commands.json generated"
cp "${BUILD_DIR}/compile_commands.json" "${SCRIPT_DIR}/compile_commands.json"
echo -e " clangd: Copied to project root"
fi
fi
echo
echo -e "${GREEN}Ready to run: ./${BUILD_DIR}/filehasher${NC}"