273 lines
9.0 KiB
Bash
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}"
|